xref: /reactos/boot/environ/lib/bootlib.c (revision 9393fc32)
1 /*
2  * COPYRIGHT:       See COPYING.ARM in the top level directory
3  * PROJECT:         ReactOS UEFI Boot Library
4  * FILE:            boot/environ/lib/bootlib.c
5  * PURPOSE:         Boot Library Initialization
6  * PROGRAMMER:      Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include "bl.h"
12 
13 /* DATA VARIABLES ************************************************************/
14 
15 BL_LIBRARY_PARAMETERS BlpLibraryParameters;
16 PBL_DEVICE_DESCRIPTOR BlpBootDevice;
17 PWCHAR BlpApplicationBaseDirectory;
18 PBOOT_APPLICATION_PARAMETER_BLOCK BlpApplicationParameters;
19 BL_LOADED_APPLICATION_ENTRY BlpApplicationEntry;
20 BOOLEAN BlpLibraryParametersInitialized;
21 ULONG BlpApplicationFlags;
22 
23 ULONG PdPersistAllocations;
24 LIST_ENTRY BlpPdListHead;
25 
26 /* FUNCTIONS *****************************************************************/
27 
28 /*++
29  * @name InitializeLibrary
30  *
31  *     The InitializeLibrary function initializes the Boot Library.
32  *
33  * @param  BootParameters
34  *         Pointer to the Boot Application Parameter Block.
35  *
36  * @param  LibraryParameters
37  *         Pointer to the Boot Library Parameters.
38  *
39  * @return NT_SUCCESS if the boot library was loaded correctly, relevant error
40  *         otherwise.
41  *
42  *--*/
43 NTSTATUS
InitializeLibrary(_In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootAppParameters,_In_ PBL_LIBRARY_PARAMETERS LibraryParameters)44 InitializeLibrary (
45     _In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootAppParameters,
46     _In_ PBL_LIBRARY_PARAMETERS LibraryParameters
47     )
48 {
49     NTSTATUS Status;
50     PBL_MEMORY_DATA MemoryData;
51     PBL_APPLICATION_ENTRY AppEntry;
52     PBL_FIRMWARE_DESCRIPTOR FirmwareDescriptor;
53     LARGE_INTEGER BootFrequency;
54     ULONG_PTR ParamPointer;
55 
56     /* Validate correct Boot Application data */
57     ParamPointer = (ULONG_PTR)BootAppParameters;
58     if (!(BootAppParameters) ||
59         (BootAppParameters->Signature[0] != BOOT_APPLICATION_SIGNATURE_1) ||
60         (BootAppParameters->Signature[1] != BOOT_APPLICATION_SIGNATURE_2) ||
61         (BootAppParameters->Size < sizeof(*BootAppParameters)))
62     {
63         Status = STATUS_INVALID_PARAMETER;
64         goto Quickie;
65     }
66 
67     /* Get sub-structures */
68     MemoryData = (PBL_MEMORY_DATA)(ParamPointer + BootAppParameters->MemoryDataOffset);
69     FirmwareDescriptor = (PBL_FIRMWARE_DESCRIPTOR)(ParamPointer + BootAppParameters->FirmwareParametersOffset);
70     AppEntry = (PBL_APPLICATION_ENTRY)(ParamPointer + BootAppParameters->AppEntryOffset);
71     BlpBootDevice = (PBL_DEVICE_DESCRIPTOR)(ParamPointer + BootAppParameters->BootDeviceOffset);
72     BlpApplicationBaseDirectory = LibraryParameters->ApplicationBaseDirectory;
73 
74     /* Initialize the firmware table */
75     Status = BlpFwInitialize(0, FirmwareDescriptor);
76     if (!NT_SUCCESS(Status))
77     {
78         goto Quickie;
79     }
80 
81     /* Find boot application entry */
82     if (strncmp(AppEntry->Signature, BL_APP_ENTRY_SIGNATURE, 7))
83     {
84         Status = STATUS_INVALID_PARAMETER_9;
85         goto Quickie;
86     }
87 
88     /* Read parameters */
89     BlpApplicationParameters = BootAppParameters;
90     BlpLibraryParameters = *LibraryParameters;
91 
92     /* Check if the caller sent us their internal BCD options */
93     if (AppEntry->Flags & BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL)
94     {
95         /* These are external to us now, as far as we are concerned */
96         AppEntry->Flags &= ~BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL;
97         AppEntry->Flags |= BL_APPLICATION_ENTRY_BCD_OPTIONS_EXTERNAL;
98     }
99 
100     /* Save the application entry flags */
101     BlpApplicationEntry.Flags = AppEntry->Flags;
102 
103     /* Copy the GUID and point to the options */
104     BlpApplicationEntry.Guid = AppEntry->Guid;
105     BlpApplicationEntry.BcdData = &AppEntry->BcdData;
106 
107     /* Everything has been captured */
108     BlpLibraryParametersInitialized = TRUE;
109 
110     /* Initialize the architecture (PM or RM) switching */
111     Status = BlpArchInitialize(0);
112     if (!NT_SUCCESS(Status))
113     {
114         goto Quickie;
115     }
116 
117     /* Initialize the memory manager */
118     Status = BlpMmInitialize(MemoryData,
119                              BootAppParameters->MemoryTranslationType,
120                              LibraryParameters);
121     if (!NT_SUCCESS(Status))
122     {
123         EfiPrintf(L"MM init failed!\r\n");
124         goto Quickie;
125     }
126 
127     /* Initialize firmware now that the heap, etc works */
128     Status = BlpFwInitialize(1, FirmwareDescriptor);
129     if (!NT_SUCCESS(Status))
130     {
131         /* Destroy memory manager in phase 1 */
132         //BlpMmDestroy(1);
133         EfiPrintf(L"Firmware2 init failed!\r\n");
134         return Status;
135     }
136 
137     /* Modern systems have an undocumented BCD system for the boot frequency */
138     Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
139                                     0x15000075,
140                                     (PULONGLONG)&BootFrequency.QuadPart);
141     if (NT_SUCCESS(Status) && (BootFrequency.QuadPart))
142     {
143         /* Use it if present */
144         BlpTimePerformanceFrequency = BootFrequency.QuadPart;
145     }
146     else
147     {
148         /* Use the TSC for calibration */
149         Status = BlpTimeCalibratePerformanceCounter();
150         if (!NT_SUCCESS(Status))
151         {
152             /* Destroy memory manager in phase 1 */
153             EfiPrintf(L"TSC calibration failed\r\n");
154             //BlpMmDestroy(1);
155             return Status;
156         }
157     }
158 
159     /* Now setup the rest of the architecture (IDT, etc) */
160     Status = BlpArchInitialize(1);
161     if (!NT_SUCCESS(Status))
162     {
163         /* Destroy memory manager in phase 1 */
164         EfiPrintf(L"Arch2 init failed\r\n");
165         //BlpMmDestroy(1);
166         return Status;
167     }
168 
169 #ifdef BL_TPM_SUPPORT
170     /* Initialize support for Trusted Platform Module v1.2 */
171     BlpTpmInitialize();
172 #endif
173 
174 #ifdef BL_TPM_SUPPORT
175     /* Initialize the event manager */
176     EnSubsystemInitialized = 1;
177     InitializeListHead(&EnEventNotificationList);
178 #endif
179 
180     /* Initialize the I/O Manager */
181     Status = BlpIoInitialize();
182     if (!NT_SUCCESS(Status))
183     {
184         /* Destroy memory manager in phase 1 and the event manager */
185         EfiPrintf(L"IO init failed\r\n");
186 #ifdef BL_TPM_SUPPORT
187         if (EnSubsystemInitialized)
188         {
189             BlpEnDestroy();
190         }
191 #endif
192         //BlpMmDestroy(1);
193         return Status;
194     }
195 
196 #ifdef BL_NET_SUPPORT
197     /* Initialize the network stack */
198     Status = BlNetInitialize();
199     if (!NT_SUCCESS(Status))
200     {
201         /* Destroy the I/O, event, and memory managers in phase 1 */
202         BlpIoDestroy();
203 #ifdef BL_TPM_SUPPORT
204         if (EnSubsystemInitialized)
205         {
206             BlpEnDestroy();
207         }
208 #endif
209         BlpMmDestroy(1);
210         return Status;
211     }
212 #endif
213 
214     /* Initialize the utility library */
215     Status = BlUtlInitialize();
216     if (!NT_SUCCESS(Status))
217     {
218         /* Destroy the network, I/O, event, and memory managers in phase 1 */
219 #ifdef BL_NET_SUPPORT
220         BlNetDestroy();
221 #endif
222         //BlpIoDestroy();
223 #ifdef BL_TPM_SUPPORT
224         if (EnSubsystemInitialized)
225         {
226             BlpEnDestroy();
227         }
228 #endif
229         //BlpMmDestroy(1);
230         EfiPrintf(L"Util init failed\r\n");
231         return Status;
232     }
233 
234 #ifdef BL_KD_SUPPORT
235     /* Initialize PCI Platform Support */
236     PltInitializePciConfiguration();
237 #endif
238 
239 #ifdef BL_SECURE_BOOT_SUPPORT
240     /* Read the current SecureBoot Policy*/
241     Status = BlSecureBootSetActivePolicyFromPersistedData();
242     if (!NT_SUCCESS(Status))
243     {
244         /* Destroy everything that we've currently set up */
245 #ifdef BL_KD_SUPPORT
246         PltDestroyPciConfiguration();
247 #endif
248 #ifdef BL_NET_SUPPORT
249         BlNetDestroy();
250 #endif
251         BlpIoDestroy();
252 #ifdef BL_TPM_SUPPORT
253         if (EnSubsystemInitialized)
254         {
255             BlpEnDestroy();
256         }
257 #endif
258         BlpMmDestroy(1);
259         return Status;
260     }
261 #endif
262 
263 #ifdef BL_TPM_SUPPORT
264     /* Initialize phase 0 of the security subsystem */
265     SipInitializePhase0();
266 #endif
267 
268 #ifdef BL_KD_SUPPORT
269     /* Bring up the boot debugger, now that SecureBoot has been processed */
270     BlBdInitialize();
271 #endif
272 
273 #ifdef BL_ETW_SUPPORT
274     /* Initialize internal logging */
275     BlpLogInitialize();
276 #endif
277 
278     /* Are graphics enabled? */
279     if (!(LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_NO_DISPLAY))
280     {
281         /* Initialize the graphics library */
282         BlpDisplayInitialize(LibraryParameters->LibraryFlags);
283     }
284 
285     /* Initialize the boot application persistent data */
286     PdPersistAllocations = 0;
287     InitializeListHead(&BlpPdListHead);
288 
289 #ifdef BL_TPM_SUPPORT
290     /* Now setup the security subsystem in phase 1 */
291     BlpSiInitialize(1);
292 #endif
293 
294     /* Setup the text, UI and font resources */
295     Status = BlpResourceInitialize();
296     if (!NT_SUCCESS(Status))
297     {
298         /* Tear down everything if this failed */
299         if (!(LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_NO_DISPLAY))
300         {
301 //            BlpDisplayDestroy();
302         }
303 #ifdef BL_KD_SUPPORT
304         BlpBdDestroy();
305         PltDestroyPciConfiguration();
306 #endif
307 #ifdef BL_NET_SUPPORT
308         BlNetDestroy();
309 #endif
310         //BlpIoDestroy();
311 #ifdef BL_TPM_SUPPORT
312         if (EnSubsystemInitialized)
313         {
314             BlpEnDestroy();
315         }
316 #endif
317         //BlpMmDestroy(1);
318         return Status;
319     }
320 
321 #if BL_BITLOCKER_SUPPORT
322     /* Setup the boot cryptography library */
323     g_pEnvironmentData = &SymCryptEnvironmentWindowsBootLibrary;
324     if (SymCryptEnvWindowsBootLibInit)
325     {
326         SymCryptEnvWindowsBootLibInit();
327     }
328 #endif
329 
330     /* We are fully initialized, remember this and exit with success */
331     BlpLibraryParameters.LibraryFlags |= BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED;
332     Status = STATUS_SUCCESS;
333 
334 Quickie:
335     return Status;
336 }
337 
338 /*++
339  * @name BlInitializeLibrary
340  *
341  *     The BlInitializeLibrary function initializes, or re-initializes, the
342  *     Boot Library.
343  *
344  * @param  BootParameters
345  *         Pointer to the Boot Application Parameter Block.
346  *
347  * @param  LibraryParameters
348  *         Pointer to the Boot Library Parameters.
349  *
350  * @return NT_SUCCESS if the boot library was loaded correctly, relevant error
351  *         otherwise.
352  *
353  *--*/
354 NTSTATUS
BlInitializeLibrary(_In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootAppParameters,_In_ PBL_LIBRARY_PARAMETERS LibraryParameters)355 BlInitializeLibrary(
356     _In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootAppParameters,
357     _In_ PBL_LIBRARY_PARAMETERS LibraryParameters
358     )
359 {
360     NTSTATUS Status;
361 
362     /* Are we re-initializing the library? */
363     if (LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_REINITIALIZE)
364     {
365         /* From scratch? */
366         BlpLibraryParameters = *LibraryParameters;
367         if (LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_REINITIALIZE_ALL)
368         {
369 #ifdef BL_TPM_SUPPORT
370             /* Reinitialize the TPM security enclave as BCD hash changed */
371             BlpSiInitialize(1);
372 #endif
373 #ifdef BL_KD_SUPPORT
374             /* Reinitialize the boot debugger as BCD debug options changed */
375             BlBdInitialize();
376 #endif
377 
378             /* Reparse the bad page list now that the BCD has been reloaded */
379             BlMmRemoveBadMemory();
380 
381             /* Reparse the low/high physical address limits as well */
382             BlpMmInitializeConstraints();
383 
384             /* Redraw the graphics console as needed */
385             BlpDisplayInitialize(LibraryParameters->LibraryFlags);
386 
387             /* Reinitialize resources (language may have changed) */
388             BlpResourceInitialize();
389         }
390 
391         /* Nothing to do, we're done */
392         Status = STATUS_SUCCESS;
393     }
394     else
395     {
396         /* Nope, this is first time initialization */
397         Status = InitializeLibrary(BootAppParameters, LibraryParameters);
398     }
399 
400     /* Return initialization status */
401     return Status;
402 }
403 
404 VOID
BlDestroyLibrary(VOID)405 BlDestroyLibrary (
406     VOID
407     )
408 {
409     EfiPrintf(L"Destroy not yet implemented\r\n");
410     return;
411 }
412 
413 PGUID
BlGetApplicationIdentifier(VOID)414 BlGetApplicationIdentifier (
415     VOID
416     )
417 {
418     /* Return the GUID, if one was present */
419     return (BlpApplicationEntry.Flags & BL_APPLICATION_ENTRY_FLAG_NO_GUID) ?
420             NULL : &BlpApplicationEntry.Guid;
421 }
422 
423 NTSTATUS
BlGetApplicationBaseAndSize(_Out_ PVOID * ImageBase,_Out_ PULONG ImageSize)424 BlGetApplicationBaseAndSize (
425     _Out_ PVOID* ImageBase,
426     _Out_ PULONG ImageSize
427     )
428 {
429     /* Fail if output parameters are missing */
430     if (!ImageBase || !ImageSize)
431     {
432         return STATUS_INVALID_PARAMETER;
433     }
434 
435     /* Return the requested data */
436     *ImageBase = (PVOID)(ULONG_PTR)BlpApplicationParameters->ImageBase;
437     *ImageSize = BlpApplicationParameters->ImageSize;
438     return STATUS_SUCCESS;
439 }
440 
441 VOID
BlDestroyBootEntry(_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry)442 BlDestroyBootEntry (
443     _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry
444     )
445 {
446     /* Check if we had allocated BCD options */
447     if (AppEntry->Flags & BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL)
448     {
449         BlMmFreeHeap(AppEntry->BcdData);
450     }
451 
452     /* Free the entry itself */
453     BlMmFreeHeap(AppEntry);
454 }
455 
456 NTSTATUS
BlPdQueryData(_In_ const GUID * DataGuid,_In_ PVOID Unknown,_Inout_ PBL_PD_DATA_BLOB DataBlob)457 BlPdQueryData (
458     _In_ const GUID* DataGuid,
459     _In_ PVOID Unknown,
460     _Inout_ PBL_PD_DATA_BLOB DataBlob
461     )
462 {
463     /* Check for invalid or missing parameters */
464     if (!(DataBlob) ||
465         !(DataGuid) ||
466         ((DataBlob->BlobSize) && !(DataBlob->Data)))
467     {
468         return STATUS_INVALID_PARAMETER;
469     }
470 
471     /* Check if there's no persistent data blobs */
472     if (IsListEmpty(&BlpPdListHead))
473     {
474         return STATUS_NOT_FOUND;
475     }
476 
477     /* Not yet handled, TODO */
478     EfiPrintf(L"Boot persistent data not yet implemented\r\n");
479     return STATUS_NOT_IMPLEMENTED;
480 }
481