Create the AHCI branch for Aman's work
[reactos.git] / 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 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
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
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
405 BlDestroyLibrary (
406 VOID
407 )
408 {
409 EfiPrintf(L"Destroy not yet implemented\r\n");
410 return;
411 }
412
413 PGUID
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
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
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
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 }