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 } 481