1 /* 2 * COPYRIGHT: See COPYING.ARM in the top level directory 3 * PROJECT: ReactOS UEFI OS Loader 4 * FILE: boot/environ/app/rosload/rosload.c 5 * PURPOSE: OS Loader Entrypoint 6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include "rosload.h" 12 13 NTSTATUS 14 OslArchTransferToKernel ( 15 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock, 16 _In_ PVOID KernelEntrypoint 17 ); 18 19 /* DATA VARIABLES ************************************************************/ 20 21 PLOADER_PARAMETER_BLOCK OslLoaderBlock; 22 PVOID OslEntryPoint; 23 PVOID UserSharedAddress; 24 ULONGLONG ArchXCr0BitsToClear; 25 ULONGLONG ArchCr4BitsToClear; 26 BOOLEAN BdDebugAfterExitBootServices; 27 KDESCRIPTOR OslKernelGdt; 28 KDESCRIPTOR OslKernelIdt; 29 30 ULONG_PTR OslImcHiveHandle; 31 ULONG_PTR OslMachineHiveHandle; 32 ULONG_PTR OslElamHiveHandle; 33 ULONG_PTR OslSystemHiveHandle; 34 35 PBL_DEVICE_DESCRIPTOR OslLoadDevice; 36 PCHAR OslLoadOptions; 37 PWCHAR OslSystemRoot; 38 39 LIST_ENTRY OslFreeMemoryDesctiptorsList; 40 LIST_ENTRY OslFinalMemoryMap; 41 LIST_ENTRY OslCoreExtensionSubGroups[2]; 42 LIST_ENTRY OslLoadedFirmwareDriverList; 43 44 BL_BUFFER_DESCRIPTOR OslFinalMemoryMapDescriptorsBuffer; 45 46 GUID OslApplicationIdentifier; 47 48 ULONG OslResetBootStatus; 49 BOOLEAN OslImcProcessingValid; 50 ULONG OslFreeMemoryDesctiptorsListSize; 51 PVOID OslMemoryDescriptorBuffer; 52 53 BcdObjectType BlpSbdiCurrentApplicationType; 54 55 PRTL_BSD_DATA BsdBootStatusData; 56 57 OSL_BSD_ITEM_TABLE_ENTRY OslpBootStatusFields[RtlBsdItemMax] = 58 { 59 { 60 FIELD_OFFSET(RTL_BSD_DATA, Version), 61 sizeof(&BsdBootStatusData->Version) 62 }, // RtlBsdItemVersionNumber 63 { 64 FIELD_OFFSET(RTL_BSD_DATA, ProductType), 65 sizeof(&BsdBootStatusData->ProductType) 66 }, // RtlBsdItemProductType 67 { 68 FIELD_OFFSET(RTL_BSD_DATA, AabEnabled), 69 sizeof(&BsdBootStatusData->AabEnabled) 70 }, // RtlBsdItemAabEnabled 71 { 72 FIELD_OFFSET(RTL_BSD_DATA, AabTimeout), 73 sizeof(&BsdBootStatusData->AabTimeout) 74 }, // RtlBsdItemAabTimeout 75 { 76 FIELD_OFFSET(RTL_BSD_DATA, LastBootSucceeded), 77 sizeof(&BsdBootStatusData->LastBootSucceeded) 78 }, // RtlBsdItemBootGood 79 { 80 FIELD_OFFSET(RTL_BSD_DATA, LastBootShutdown), 81 sizeof(&BsdBootStatusData->LastBootShutdown) 82 }, // RtlBsdItemBootShutdown 83 { 84 FIELD_OFFSET(RTL_BSD_DATA, SleepInProgress), 85 sizeof(&BsdBootStatusData->SleepInProgress) 86 }, // RtlBsdSleepInProgress 87 { 88 FIELD_OFFSET(RTL_BSD_DATA, PowerTransition), 89 sizeof(&BsdBootStatusData->PowerTransition) 90 }, // RtlBsdPowerTransition 91 { 92 FIELD_OFFSET(RTL_BSD_DATA, BootAttemptCount), 93 sizeof(&BsdBootStatusData->BootAttemptCount) 94 }, // RtlBsdItemBootAttemptCount 95 { 96 FIELD_OFFSET(RTL_BSD_DATA, LastBootCheckpoint), 97 sizeof(&BsdBootStatusData->LastBootCheckpoint) 98 }, // RtlBsdItemBootCheckpoint 99 { 100 FIELD_OFFSET(RTL_BSD_DATA, LastBootId), 101 sizeof(&BsdBootStatusData->LastBootId) 102 }, // RtlBsdItemBootId 103 { 104 FIELD_OFFSET(RTL_BSD_DATA, LastSuccessfulShutdownBootId), 105 sizeof(&BsdBootStatusData->LastSuccessfulShutdownBootId) 106 }, // RtlBsdItemShutdownBootId 107 { 108 FIELD_OFFSET(RTL_BSD_DATA, LastReportedAbnormalShutdownBootId), 109 sizeof(&BsdBootStatusData->LastReportedAbnormalShutdownBootId) 110 }, // RtlBsdItemReportedAbnormalShutdownBootId 111 { 112 FIELD_OFFSET(RTL_BSD_DATA, ErrorInfo), 113 sizeof(&BsdBootStatusData->ErrorInfo) 114 }, // RtlBsdItemErrorInfo 115 { 116 FIELD_OFFSET(RTL_BSD_DATA, PowerButtonPressInfo), 117 sizeof(&BsdBootStatusData->PowerButtonPressInfo) 118 }, // RtlBsdItemPowerButtonPressInfo 119 { 120 FIELD_OFFSET(RTL_BSD_DATA, Checksum), 121 sizeof(&BsdBootStatusData->Checksum) 122 }, // RtlBsdItemChecksum 123 }; 124 125 ULONG OslBootAttemptCount; 126 ULONG OslBootCountUpdateRequestForAbort; 127 ULONG OslBootAttemptMaximum; 128 129 ULONG OslBootCountUpdateIncrement; 130 131 BOOLEAN OslCurrentBootCheckpoint; 132 BOOLEAN OslCurrentBootSucceeded; 133 BOOLEAN OslCurrentBootShutdown; 134 135 /* FUNCTIONS *****************************************************************/ 136 137 VOID 138 OslFatalErrorEx ( 139 _In_ ULONG ErrorCode, 140 _In_ ULONG Parameter1, 141 _In_ ULONG_PTR Parameter2, 142 _In_ ULONG_PTR Parameter3 143 ) 144 { 145 /* For now just do this */ 146 BlStatusPrint(L"FATAL ERROR IN ROSLOAD: %lx\n", ErrorCode); 147 } 148 149 VOID 150 OslAbortBoot ( 151 _In_ NTSTATUS Status 152 ) 153 { 154 /* For now just do this */ 155 BlStatusPrint(L"BOOT ABORTED: %lx\n", Status); 156 } 157 158 NTSTATUS 159 OslBlStatusErrorHandler ( 160 _In_ ULONG ErrorCode, 161 _In_ ULONG Parameter1, 162 _In_ ULONG_PTR Parameter2, 163 _In_ ULONG_PTR Parameter3, 164 _In_ ULONG_PTR Parameter4 165 ) 166 { 167 /* We only filter error code 4 */ 168 if (ErrorCode != 4) 169 { 170 return STATUS_NOT_IMPLEMENTED; 171 } 172 173 /* Handle error 4 as a fatal error 3 internally */ 174 OslFatalErrorEx(3, Parameter1, Parameter2, Parameter3); 175 return STATUS_SUCCESS; 176 } 177 178 VOID 179 OslpSanitizeLoadOptionsString ( 180 _In_ PWCHAR OptionString, 181 _In_ PWCHAR SanitizeString 182 ) 183 { 184 /* TODO */ 185 return; 186 } 187 188 VOID 189 OslpSanitizeStringOptions ( 190 _In_ PBL_BCD_OPTION BcdOptions 191 ) 192 { 193 /* TODO */ 194 return; 195 } 196 197 NTSTATUS 198 OslpRemoveInternalApplicationOptions ( 199 VOID 200 ) 201 { 202 PWCHAR LoadString; 203 NTSTATUS Status; 204 205 /* Assume success */ 206 Status = STATUS_SUCCESS; 207 208 /* Remove attempts to disable integrity checks or ELAM driver load */ 209 BlRemoveBootOption(BlpApplicationEntry.BcdData, 210 BcdLibraryBoolean_DisableIntegrityChecks); 211 BlRemoveBootOption(BlpApplicationEntry.BcdData, 212 BcdOSLoaderBoolean_DisableElamDrivers); 213 214 /* Get the command-line parameters, if any */ 215 Status = BlGetBootOptionString(BlpApplicationEntry.BcdData, 216 BcdLibraryString_LoadOptionsString, 217 &LoadString); 218 if (NT_SUCCESS(Status)) 219 { 220 /* Conver to upper case */ 221 _wcsupr(LoadString); 222 223 /* Remove the existing one */ 224 BlRemoveBootOption(BlpApplicationEntry.BcdData, 225 BcdLibraryString_LoadOptionsString); 226 227 /* Sanitize strings we don't want */ 228 OslpSanitizeLoadOptionsString(LoadString, L"DISABLE_INTEGRITY_CHECKS"); 229 OslpSanitizeLoadOptionsString(LoadString, L"NOINTEGRITYCHECKS"); 230 OslpSanitizeLoadOptionsString(LoadString, L"DISABLEELAMDRIVERS"); 231 232 /* Add the sanitized one back */ 233 Status = BlAppendBootOptionString(&BlpApplicationEntry, 234 BcdLibraryString_LoadOptionsString, 235 LoadString); 236 237 /* Free the original BCD one */ 238 BlMmFreeHeap(LoadString); 239 } 240 241 /* One more pass for secure-boot options */ 242 OslpSanitizeStringOptions(BlpApplicationEntry.BcdData); 243 244 /* All good */ 245 return Status; 246 } 247 248 NTSTATUS 249 OslpCheckForcedFailure ( 250 VOID 251 ) 252 { 253 ULONG64 ForceReason; 254 NTSTATUS Status; 255 256 /* Read the option */ 257 Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData, 258 BcdOSLoaderInteger_ForceFailure, 259 &ForceReason); 260 if (NT_SUCCESS(Status) && (ForceReason < 4)) 261 { 262 /* For reasons above 3, don't actually do anything */ 263 if (ForceReason > 3) 264 { 265 return STATUS_SUCCESS; 266 } 267 } 268 269 /* If the option isn't there or invalid, always return success */ 270 return STATUS_SUCCESS; 271 } 272 273 VOID 274 OslpInitializeBootStatusDataLog ( 275 VOID 276 ) 277 { 278 /* TODO */ 279 return; 280 } 281 282 NTSTATUS 283 OslpReadWriteBootStatusData ( 284 _In_ BOOLEAN WriteAccess 285 ) 286 { 287 /* Are you trying to write? */ 288 if (WriteAccess) 289 { 290 /* Have we already read? */ 291 if (!BsdBootStatusData) 292 { 293 /* No -- fail */ 294 return STATUS_UNSUCCESSFUL; 295 } 296 } 297 else if (BsdBootStatusData) 298 { 299 /* No -- you're trying to read and we already have the data: no-op */ 300 return STATUS_SUCCESS; 301 } 302 303 /* TODO */ 304 return STATUS_NOT_IMPLEMENTED; 305 } 306 307 NTSTATUS 308 OslpGetSetBootStatusData ( 309 _In_ BOOLEAN Read, 310 _In_ RTL_BSD_ITEM_TYPE DataClass, 311 _Out_ PVOID Buffer, 312 _Inout_ PULONG Size 313 ) 314 { 315 NTSTATUS Status; 316 ULONG Length, Offset; 317 318 /* No data has been read yet, fail */ 319 if (!BsdBootStatusData) 320 { 321 return STATUS_UNSUCCESSFUL; 322 } 323 324 /* Invalid data item, fail */ 325 if (DataClass >= RtlBsdItemMax) 326 { 327 return STATUS_INVALID_PARAMETER; 328 } 329 330 /* Capture the length and offset */ 331 Length = OslpBootStatusFields[DataClass].Size; 332 Offset = OslpBootStatusFields[DataClass].Offset; 333 334 /* Make sure it doesn't overflow past the structure we've read */ 335 if ((Length + Offset) > BsdBootStatusData->Version) 336 { 337 return STATUS_REVISION_MISMATCH; 338 } 339 340 /* Make sure we have enough space */ 341 if (*Size >= Length) 342 { 343 /* We do -- is this a read? */ 344 if (Read) 345 { 346 /* Yes, copy into the caller's buffer */ 347 RtlCopyMemory(Buffer, 348 (PVOID)((ULONG_PTR)BsdBootStatusData + Offset), 349 Length); 350 } 351 else 352 { 353 /* It's a write, copy from caller's buffer */ 354 RtlCopyMemory((PVOID)((ULONG_PTR)BsdBootStatusData + Offset), 355 Buffer, 356 Length); 357 } 358 359 /* Set success */ 360 Status = STATUS_SUCCESS; 361 } 362 else 363 { 364 /* Return size needed and failure code */ 365 *Size = Length; 366 Status = STATUS_BUFFER_TOO_SMALL; 367 } 368 369 /* All good */ 370 return Status; 371 } 372 373 NTSTATUS 374 OslSetBootStatusData ( 375 _In_ BOOLEAN LastBootGood, 376 _In_ BOOLEAN LastBootShutdown, 377 _In_ BOOLEAN LastBootCheckpoint, 378 _In_ ULONG UpdateIncrement, 379 _In_ ULONG BootAttemptCount 380 ) 381 { 382 NTSTATUS Status; 383 ULONG Size; 384 385 /* Capture the BSD data in our globals, if needed */ 386 Status = OslpReadWriteBootStatusData(FALSE); 387 if (!NT_SUCCESS(Status)) 388 { 389 goto Quickie; 390 } 391 392 /* Write last boot shutdown */ 393 Size = sizeof(LastBootShutdown); 394 Status = OslpGetSetBootStatusData(FALSE, 395 RtlBsdItemBootShutdown, 396 &LastBootShutdown, 397 &Size); 398 if (!NT_SUCCESS(Status)) 399 { 400 goto Quickie; 401 } 402 403 /* Write last boot good */ 404 Size = sizeof(LastBootGood); 405 Status = OslpGetSetBootStatusData(FALSE, 406 RtlBsdItemBootGood, 407 &LastBootGood, 408 &Size); 409 if (!NT_SUCCESS(Status)) 410 { 411 goto Quickie; 412 } 413 414 /* Write last boot checkpoint */ 415 Size = sizeof(LastBootCheckpoint); 416 Status = OslpGetSetBootStatusData(FALSE, 417 RtlBsdItemBootCheckpoint, 418 &LastBootCheckpoint, 419 &Size); 420 if (!NT_SUCCESS(Status)) 421 { 422 goto Quickie; 423 } 424 425 /* Write boot attempt count */ 426 Size = sizeof(BootAttemptCount); 427 Status = OslpGetSetBootStatusData(FALSE, 428 RtlBsdItemBootAttemptCount, 429 &BootAttemptCount, 430 &Size); 431 if (!NT_SUCCESS(Status)) 432 { 433 goto Quickie; 434 } 435 436 /* TODO: Update Boot ID*/ 437 438 /* Now write the data */ 439 Status = OslpReadWriteBootStatusData(TRUE); 440 441 Quickie: 442 return Status; 443 } 444 445 NTSTATUS 446 OslGetBootStatusData ( 447 _Out_ PBOOLEAN LastBootGood, 448 _Out_ PBOOLEAN LastBootShutdown, 449 _Out_ PBOOLEAN LastBootCheckpoint, 450 _Out_ PULONG LastBootId, 451 _Out_ PBOOLEAN BootGood, 452 _Out_ PBOOLEAN BootShutdown 453 ) 454 { 455 NTSTATUS Status; 456 ULONG Size; 457 ULONG64 BootStatusPolicy; 458 BOOLEAN localBootShutdown, localBootGood; 459 460 /* Capture the BSD data in our globals, if needed */ 461 Status = OslpReadWriteBootStatusData(FALSE); 462 if (!NT_SUCCESS(Status)) 463 { 464 goto Quickie; 465 } 466 467 /* Read the last boot ID */ 468 Size = sizeof(*LastBootId); 469 Status = OslpGetSetBootStatusData(TRUE, RtlBsdItemBootId, LastBootId, &Size); 470 if (!NT_SUCCESS(Status)) 471 { 472 /* Set to zero if we couldn't find it */ 473 *LastBootId = 0; 474 } 475 476 /* Get the boot status policy */ 477 Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData, 478 BcdOSLoaderInteger_BootStatusPolicy, 479 &BootStatusPolicy); 480 if (!NT_SUCCESS(Status)) 481 { 482 /* Apply a default if none exists */ 483 BootStatusPolicy = IgnoreShutdownFailures; 484 } 485 486 /* Check if this was a good shutdown */ 487 Size = sizeof(localBootShutdown); 488 Status = OslpGetSetBootStatusData(TRUE, 489 RtlBsdItemBootShutdown, 490 &localBootShutdown, 491 &Size); 492 if (!NT_SUCCESS(Status)) 493 { 494 goto Quickie; 495 } 496 497 /* Tell the caller */ 498 *BootShutdown = localBootShutdown; 499 500 /* Check if this was a good boot */ 501 Size = sizeof(localBootGood); 502 Status = OslpGetSetBootStatusData(TRUE, 503 RtlBsdItemBootGood, 504 &localBootGood, 505 &Size); 506 if (!NT_SUCCESS(Status)) 507 { 508 goto Quickie; 509 } 510 511 /* Tell the caller*/ 512 *BootGood = localBootGood; 513 514 /* TODO: Additional logic for checkpoints and such */ 515 Status = STATUS_NOT_IMPLEMENTED; 516 517 Quickie: 518 return Status; 519 } 520 521 BOOLEAN 522 OslpAdvancedOptionsRequested ( 523 VOID 524 ) 525 { 526 /* TODO */ 527 return FALSE; 528 } 529 530 NTSTATUS 531 OslPrepareTarget ( 532 _Out_ PULONG ReturnFlags, 533 _Out_ PBOOLEAN Jump 534 ) 535 { 536 PGUID AppId; 537 NTSTATUS Status; 538 PBL_DEVICE_DESCRIPTOR OsDevice; 539 PWCHAR SystemRoot; 540 SIZE_T RootLength, RootLengthWithSep; 541 ULONG i; 542 ULONG64 StartPerf, EndPerf; 543 RTL_BSD_DATA_POWER_TRANSITION PowerTransitionData; 544 PRTL_BSD_DATA_POWER_TRANSITION PowerBuffer; 545 ULONG OsDeviceHandle; 546 BOOLEAN LastBootGood, LastBootShutdown, LastBootCheckpoint; 547 ULONG BootId; 548 BOOLEAN BootGood, BootShutdown; 549 ULONG BsdSize; 550 551 /* Initialize locals */ 552 PowerBuffer = NULL; 553 554 /* Assume no flags */ 555 *ReturnFlags = 0; 556 557 /* Make all registry handles invalid */ 558 OslImcHiveHandle = -1; 559 OslMachineHiveHandle = -1; 560 OslElamHiveHandle = -1; 561 OslSystemHiveHandle = -1; 562 563 /* Initialize memory lists */ 564 InitializeListHead(&OslFreeMemoryDesctiptorsList); 565 InitializeListHead(&OslFinalMemoryMap); 566 InitializeListHead(&OslLoadedFirmwareDriverList); 567 for (i = 0; i < RTL_NUMBER_OF(OslCoreExtensionSubGroups); i++) 568 { 569 InitializeListHead(&OslCoreExtensionSubGroups[i]); 570 } 571 572 /* Initialize the memory map descriptor buffer */ 573 RtlZeroMemory(&OslFinalMemoryMapDescriptorsBuffer, 574 sizeof(OslFinalMemoryMapDescriptorsBuffer)); 575 576 /* Initialize general pointers */ 577 OslLoadDevice = NULL; 578 OslLoadOptions = NULL; 579 OslSystemRoot = NULL; 580 OslLoaderBlock = NULL; 581 OslMemoryDescriptorBuffer = NULL; 582 583 /* Initialize general variables */ 584 OslResetBootStatus = 0; 585 OslImcProcessingValid = FALSE; 586 OslFreeMemoryDesctiptorsListSize = 0; 587 588 /* Capture the current TSC */ 589 StartPerf = BlArchGetPerformanceCounter(); 590 591 /* Set our application type for SecureBoot/TPM purposes */ 592 BlpSbdiCurrentApplicationType.Application.ObjectCode = 593 BCD_OBJECT_TYPE_APPLICATION; 594 BlpSbdiCurrentApplicationType.Application.ImageCode = 595 BCD_IMAGE_TYPE_BOOT_APP; 596 BlpSbdiCurrentApplicationType.Application.ApplicationCode = 597 BCD_APPLICATION_TYPE_OSLOADER; 598 BlpSbdiCurrentApplicationType.Application.Reserved = 0; 599 600 /* Register an error handler */ 601 BlpStatusErrorHandler = OslBlStatusErrorHandler; 602 603 /* Get the application identifier and save it */ 604 AppId = BlGetApplicationIdentifier(); 605 if (AppId) 606 { 607 OslApplicationIdentifier = *AppId; 608 } 609 610 /* Enable tracing */ 611 #ifdef BL_ETW_SUPPORT 612 TraceLoggingRegister(&TlgOslBootProviderProv); 613 #endif 614 615 /* Remove dangerous BCD options */ 616 Status = OslpRemoveInternalApplicationOptions(); 617 if (!NT_SUCCESS(Status)) 618 { 619 EfiPrintf(L"Fail here: %d\r\n", __LINE__); 620 goto Quickie; 621 } 622 623 /* Get the OS device */ 624 Status = BlGetBootOptionDevice(BlpApplicationEntry.BcdData, 625 BcdOSLoaderDevice_OSDevice, 626 &OsDevice, 627 0); 628 if (!NT_SUCCESS(Status)) 629 { 630 EfiPrintf(L"Fail here: %d\r\n", __LINE__); 631 goto Quickie; 632 } 633 634 /* If the OS device is the boot device, use the one provided by bootlib */ 635 if (OsDevice->DeviceType == BootDevice) 636 { 637 OsDevice = BlpBootDevice; 638 } 639 640 /* Save it as a global for later */ 641 OslLoadDevice = OsDevice; 642 643 /* Get the system root */ 644 Status = BlGetBootOptionString(BlpApplicationEntry.BcdData, 645 BcdOSLoaderString_SystemRoot, 646 &SystemRoot); 647 if (!NT_SUCCESS(Status)) 648 { 649 EfiPrintf(L"Fail here: %d\r\n", __LINE__); 650 goto Quickie; 651 } 652 653 EfiPrintf(L"System root: %s\r\n", SystemRoot); 654 655 /* Get the system root length and make sure it's slash-terminated */ 656 RootLength = wcslen(SystemRoot); 657 if (SystemRoot[RootLength - 1] == OBJ_NAME_PATH_SEPARATOR) 658 { 659 /* Perfect, set it */ 660 OslSystemRoot = SystemRoot; 661 } 662 else 663 { 664 /* Allocate a new buffer large enough to contain the slash */ 665 RootLengthWithSep = RootLength + sizeof(OBJ_NAME_PATH_SEPARATOR); 666 OslSystemRoot = BlMmAllocateHeap(RootLengthWithSep * sizeof(WCHAR)); 667 if (!OslSystemRoot) 668 { 669 /* Bail out if we're out of memory */ 670 Status = STATUS_NO_MEMORY; 671 EfiPrintf(L"Fail here: %d\r\n", __LINE__); 672 goto Quickie; 673 } 674 675 /* Make a copy of the path, adding the separator */ 676 wcscpy(OslSystemRoot, SystemRoot); 677 wcscat(OslSystemRoot, L"\\"); 678 679 /* Free the original one from the BCD library */ 680 BlMmFreeHeap(SystemRoot); 681 } 682 683 /* Initialize access to the BSD */ 684 OslpInitializeBootStatusDataLog(); 685 686 /* Check if we're supposed to fail on purpose */ 687 Status = OslpCheckForcedFailure(); 688 if (!NT_SUCCESS(Status)) 689 { 690 EfiPrintf(L"Fail here: %d\r\n", __LINE__); 691 goto Quickie; 692 } 693 694 /* Always disable VGA mode */ 695 Status = BlAppendBootOptionBoolean(&BlpApplicationEntry, 696 BcdOSLoaderBoolean_DisableVgaMode, 697 TRUE); 698 if (!NT_SUCCESS(Status)) 699 { 700 EfiPrintf(L"Fail here: %d\r\n", __LINE__); 701 goto Quickie; 702 } 703 704 /* Get telemetry data from the last boot */ 705 Status = OslGetBootStatusData(&LastBootGood, 706 &LastBootShutdown, 707 &LastBootCheckpoint, 708 &BootId, 709 &BootGood, 710 &BootShutdown); 711 if (!NT_SUCCESS(Status)) 712 { 713 /* Assume this is the very first boot and everything went well */ 714 BootId = 0; 715 LastBootGood = TRUE; 716 LastBootShutdown = TRUE; 717 LastBootCheckpoint = TRUE; 718 BootGood = TRUE; 719 BootShutdown = TRUE; 720 721 /* Set 0 boot attempts */ 722 OslBootAttemptCount = 0; 723 } 724 725 /* Set more attempt variables to their initial state */ 726 OslResetBootStatus = TRUE; 727 OslBootCountUpdateRequestForAbort = 0; 728 729 /* Read the current BSD data into the global buffer */ 730 Status = OslpReadWriteBootStatusData(FALSE); 731 if (NT_SUCCESS(Status)) 732 { 733 /* Get the power transition buffer from the BSD */ 734 BsdSize = sizeof(PowerTransitionData); 735 Status = OslpGetSetBootStatusData(TRUE, 736 RtlBsdPowerTransition, 737 &PowerTransitionData, 738 &BsdSize); 739 if (NT_SUCCESS(Status)) 740 { 741 /* Save the buffer */ 742 PowerBuffer = &PowerTransitionData; 743 } 744 } 745 746 /* Check if this is VHD boot, which gets 3 boot attempts instead of 2 */ 747 OslBootAttemptMaximum = 2; 748 OslBootAttemptMaximum += BlDeviceIsVirtualPartitionDevice(OslLoadDevice, NULL); 749 750 /* Check if the user wants to see the advanced menu */ 751 if (!OslpAdvancedOptionsRequested()) 752 { 753 /* The last boot failed more than the maximum */ 754 if (!(LastBootGood) && 755 (OslBootAttemptCount >= OslBootAttemptMaximum)) 756 { 757 /* Return failure due to boot -- launch recovery */ 758 *ReturnFlags |= 8; 759 760 /* Update the attempt count and status variables */ 761 OslBootAttemptCount = OslBootAttemptMaximum - 1; 762 OslCurrentBootCheckpoint = LastBootCheckpoint; 763 OslCurrentBootSucceeded = FALSE; 764 OslCurrentBootShutdown = LastBootShutdown; 765 766 /* Crash with code 15 and abort boot */ 767 OslFatalErrorEx(15, 0, 0, 0); 768 Status = STATUS_UNSUCCESSFUL; 769 EfiPrintf(L"Fail here: %d\r\n", __LINE__); 770 goto Quickie; 771 } 772 773 /* We never made it far enough, more than the maximum */ 774 if (!(LastBootCheckpoint) && 775 (OslBootAttemptCount >= OslBootAttemptMaximum)) 776 { 777 /* Return crash/dirty shutdown during boot attempt */ 778 *ReturnFlags |= 0x10; 779 780 /* Update the attempt count and status variables */ 781 OslBootAttemptCount = OslBootAttemptMaximum - 1; 782 OslCurrentBootSucceeded = LastBootGood; 783 OslCurrentBootShutdown = LastBootShutdown; 784 OslCurrentBootCheckpoint = FALSE; 785 786 /* Crash with code 16 and abort boot */ 787 OslFatalErrorEx(16, 0, 0, 0); 788 Status = STATUS_UNSUCCESSFUL; 789 EfiPrintf(L"Fail here: %d\r\n", __LINE__); 790 goto Quickie; 791 } 792 793 /* We failed to shutdown cleanly, and haven't booted yet */ 794 if (!(LastBootShutdown) && !(OslBootAttemptCount)) 795 { 796 /* Return crash/dirty shutdown */ 797 *ReturnFlags |= 0x10; 798 799 /* There's no boot attempt, so only update shutdown variables */ 800 OslCurrentBootSucceeded = LastBootGood; 801 OslCurrentBootShutdown = TRUE; 802 OslCurrentBootCheckpoint = LastBootCheckpoint; 803 804 /* Crash with code 16 and abort boot */ 805 OslFatalErrorEx(16, 0, 0, 0); 806 Status = STATUS_UNSUCCESSFUL; 807 EfiPrintf(L"Fail here: %d\r\n", __LINE__); 808 goto Quickie; 809 } 810 } 811 812 /* Officially increment the number of boot attempts */ 813 OslBootAttemptCount++; 814 815 /* No success yet, write to boot status file */ 816 OslCurrentBootCheckpoint = FALSE; 817 OslCurrentBootSucceeded = FALSE; 818 OslCurrentBootShutdown = FALSE; 819 OslSetBootStatusData(FALSE, 820 FALSE, 821 FALSE, 822 OslBootCountUpdateIncrement, 823 OslBootAttemptCount); 824 825 /* Open the OS Loader Device for Read/Write access */ 826 Status = BlpDeviceOpen(OslLoadDevice, 827 BL_DEVICE_READ_ACCESS | BL_DEVICE_WRITE_ACCESS, 828 0, 829 &OsDeviceHandle); 830 if (!NT_SUCCESS(Status)) 831 { 832 EfiPrintf(L"Fail here: %d\r\n", __LINE__); 833 goto Quickie; 834 } 835 836 /* That's all for now, folks */ 837 Status = STATUS_NOT_IMPLEMENTED; 838 DBG_UNREFERENCED_LOCAL_VARIABLE(PowerBuffer); 839 840 /* Printf perf */ 841 EndPerf = BlArchGetPerformanceCounter(); 842 EfiPrintf(L"Delta: %lld\r\n", EndPerf - StartPerf); 843 844 Quickie: 845 #if BL_BITLOCKER_SUPPORT 846 /* Destroy the RNG/AES library for BitLocker */ 847 SymCryptRngAesUninstantiate(); 848 #endif 849 850 /* Abort the boot */ 851 OslAbortBoot(Status); 852 853 /* This is a failure path, so never do the jump */ 854 *Jump = FALSE; 855 856 /* Return error code */ 857 return Status; 858 } 859 860 NTSTATUS 861 OslFwpKernelSetupPhase1 ( 862 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock 863 ) 864 { 865 return STATUS_NOT_IMPLEMENTED; 866 } 867 868 NTSTATUS 869 OslArchpKernelSetupPhase0 ( 870 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock 871 ) 872 { 873 return STATUS_NOT_IMPLEMENTED; 874 } 875 876 VOID 877 ArchRestoreProcessorFeatures ( 878 VOID 879 ) 880 { 881 /* Any XCR0 bits to clear? */ 882 if (ArchXCr0BitsToClear) 883 { 884 /* Clear them */ 885 #if defined(_MSC_VER) && !defined(__clang__) && !defined(_M_ARM) 886 __xsetbv(0, __xgetbv(0) & ~ArchXCr0BitsToClear); 887 #endif 888 ArchXCr0BitsToClear = 0; 889 } 890 891 /* Any CR4 bits to clear? */ 892 if (ArchCr4BitsToClear) 893 { 894 /* Clear them */ 895 #if !defined(_M_ARM) 896 __writecr4(__readcr4() & ~ArchCr4BitsToClear); 897 #endif 898 ArchCr4BitsToClear = 0; 899 } 900 } 901 902 NTSTATUS 903 OslArchKernelSetup ( 904 _In_ ULONG Phase, 905 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock 906 ) 907 { 908 /* For phase 0, do architectural setup */ 909 if (Phase == 0) 910 { 911 return OslArchpKernelSetupPhase0(LoaderBlock); 912 } 913 914 /* Nothing to do for Phase 1 */ 915 if (Phase == 1) 916 { 917 return STATUS_SUCCESS; 918 } 919 920 /* Relocate the self map */ 921 BlMmRelocateSelfMap(); 922 923 /* Zero out the HAL Heap */ 924 BlMmZeroVirtualAddressRange((PVOID)MM_HAL_VA_START, 925 MM_HAL_VA_END - MM_HAL_VA_START + 1); 926 927 /* Move shared user data in its place */ 928 BlMmMoveVirtualAddressRange((PVOID)KI_USER_SHARED_DATA, 929 UserSharedAddress, 930 PAGE_SIZE); 931 932 /* Clear XCR0/CR4 CPU features that should be disabled before boot */ 933 ArchRestoreProcessorFeatures(); 934 935 /* Good to go */ 936 return STATUS_SUCCESS; 937 } 938 939 NTSTATUS 940 OslExecuteTransition ( 941 VOID 942 ) 943 { 944 NTSTATUS Status; 945 946 /* Is the debugger meant to be kept enabled throughout the boot phase? */ 947 if (!BdDebugAfterExitBootServices) 948 { 949 #ifdef BL_KD_SUPPORT 950 /* No -- disable it */ 951 BlBdStop(); 952 #endif 953 } 954 955 /* Setup Firmware for Phase 1 */ 956 Status = OslFwpKernelSetupPhase1(OslLoaderBlock); 957 if (NT_SUCCESS(Status)) 958 { 959 /* Setup kernel for Phase 2 */ 960 Status = OslArchKernelSetup(2, OslLoaderBlock); 961 if (NT_SUCCESS(Status)) 962 { 963 #ifdef BL_KD_SUPPORT 964 /* Stop the boot debugger */ 965 BlBdStop(); 966 #endif 967 /* Jump to the kernel entrypoint */ 968 OslArchTransferToKernel(OslLoaderBlock, OslEntryPoint); 969 970 /* Infinite loop if we got here */ 971 for (;;); 972 } 973 } 974 975 /* Return back with the failure code */ 976 return Status; 977 } 978 979 NTSTATUS 980 OslpMain ( 981 _Out_ PULONG ReturnFlags 982 ) 983 { 984 NTSTATUS Status; 985 BOOLEAN ExecuteJump; 986 #if !defined(_M_ARM) 987 CPU_INFO CpuInfo; 988 BOOLEAN NxEnabled; 989 LARGE_INTEGER MiscMsr; 990 991 /* Check if the CPU supports NX */ 992 BlArchCpuId(0x80000001, 0, &CpuInfo); 993 if (!(CpuInfo.Edx & 0x10000)) 994 { 995 /* It doesn't, check if this is Intel */ 996 EfiPrintf(L"NX disabled: %lx\r\n", CpuInfo.Edx); 997 if (BlArchGetCpuVendor() == CPU_INTEL) 998 { 999 /* Then turn off the MSR disable feature for it, enabling NX */ 1000 MiscMsr.QuadPart = __readmsr(MSR_IA32_MISC_ENABLE); 1001 EfiPrintf(L"NX being turned on: %llx\r\n", MiscMsr.QuadPart); 1002 MiscMsr.HighPart &= MSR_XD_ENABLE_MASK; 1003 MiscMsr.QuadPart = __readmsr(MSR_IA32_MISC_ENABLE); 1004 __writemsr(MSR_IA32_MISC_ENABLE, MiscMsr.QuadPart); 1005 NxEnabled = TRUE; 1006 } 1007 } 1008 1009 /* Turn on NX support with the CPU-generic MSR */ 1010 __writemsr(MSR_EFER, __readmsr(MSR_EFER) | MSR_NXE); 1011 1012 #endif 1013 1014 /* Load the kernel */ 1015 Status = OslPrepareTarget(ReturnFlags, &ExecuteJump); 1016 if (NT_SUCCESS(Status) && (ExecuteJump)) 1017 { 1018 /* Jump to the kernel */ 1019 Status = OslExecuteTransition(); 1020 } 1021 1022 #if !defined(_M_ARM) 1023 /* Retore NX support */ 1024 __writemsr(MSR_EFER, __readmsr(MSR_EFER) ^ MSR_NXE); 1025 1026 /* Did we manually enable NX? */ 1027 if (NxEnabled) 1028 { 1029 /* Turn it back off */ 1030 MiscMsr.QuadPart = __readmsr(MSR_IA32_MISC_ENABLE); 1031 MiscMsr.HighPart |= ~MSR_XD_ENABLE_MASK; 1032 __writemsr(MSR_IA32_MISC_ENABLE, MiscMsr.QuadPart); 1033 } 1034 1035 #endif 1036 /* Go back */ 1037 return Status; 1038 } 1039 1040 /*++ 1041 * @name OslMain 1042 * 1043 * The OslMain function implements the Windows Boot Application entrypoint for 1044 * the OS Loader. 1045 * 1046 * @param BootParameters 1047 * Pointer to the Boot Application Parameter Block. 1048 * 1049 * @return NT_SUCCESS if the image was loaded correctly, relevant error code 1050 * otherwise. 1051 * 1052 *--*/ 1053 NTSTATUS 1054 NTAPI 1055 OslMain ( 1056 _In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters 1057 ) 1058 { 1059 BL_LIBRARY_PARAMETERS LibraryParameters; 1060 NTSTATUS Status; 1061 PBL_RETURN_ARGUMENTS ReturnArguments; 1062 PBL_APPLICATION_ENTRY AppEntry; 1063 CPU_INFO CpuInfo; 1064 ULONG Flags; 1065 1066 /* Get the return arguments structure, and set our version */ 1067 ReturnArguments = (PBL_RETURN_ARGUMENTS)((ULONG_PTR)BootParameters + 1068 BootParameters->ReturnArgumentsOffset); 1069 ReturnArguments->Version = BL_RETURN_ARGUMENTS_VERSION; 1070 1071 /* Get the application entry, and validate it */ 1072 AppEntry = (PBL_APPLICATION_ENTRY)((ULONG_PTR)BootParameters + 1073 BootParameters->AppEntryOffset); 1074 if (!RtlEqualMemory(AppEntry->Signature, 1075 BL_APP_ENTRY_SIGNATURE, 1076 sizeof(AppEntry->Signature))) 1077 { 1078 /* Unrecognized, bail out */ 1079 Status = STATUS_INVALID_PARAMETER_9; 1080 goto Quickie; 1081 } 1082 1083 #if !defined(_M_ARM) 1084 /* Check if CPUID 01h is supported */ 1085 if (BlArchIsCpuIdFunctionSupported(1)) 1086 { 1087 /* Query CPU features */ 1088 BlArchCpuId(1, 0, &CpuInfo); 1089 1090 /* Check if PAE is supported */ 1091 if (CpuInfo.Edx & 0x40) 1092 { 1093 EfiPrintf(L"PAE Supported, but won't be used\r\n"); 1094 } 1095 } 1096 #endif 1097 1098 /* Setup the boot library parameters for this application */ 1099 BlSetupDefaultParameters(&LibraryParameters); 1100 LibraryParameters.TranslationType = BlVirtual; 1101 LibraryParameters.LibraryFlags = BL_LIBRARY_FLAG_ZERO_HEAP_ALLOCATIONS_ON_FREE | 1102 BL_LIBRARY_FLAG_REINITIALIZE_ALL; 1103 LibraryParameters.MinimumAllocationCount = 1024; 1104 LibraryParameters.MinimumHeapSize = 2 * 1024 * 1024; 1105 LibraryParameters.HeapAllocationAttributes = BlMemoryKernelRange; 1106 LibraryParameters.FontBaseDirectory = L"\\Reactos\\Boot\\Fonts"; 1107 LibraryParameters.DescriptorCount = 512; 1108 1109 /* Initialize the boot library */ 1110 Status = BlInitializeLibrary(BootParameters, &LibraryParameters); 1111 if (NT_SUCCESS(Status)) 1112 { 1113 /* For testing, draw the logo */ 1114 OslDrawLogo(); 1115 1116 /* Call the main routine */ 1117 Status = OslpMain(&Flags); 1118 1119 /* Return the flags, and destroy the boot library */ 1120 ReturnArguments->Flags = Flags; 1121 BlDestroyLibrary(); 1122 } 1123 1124 Quickie: 1125 /* Return back to boot manager */ 1126 ReturnArguments->Status = Status; 1127 return Status; 1128 } 1129 1130