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