2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Manager
4 * FILE: boot/environ/app/bootmgr/bootmgr.c
5 * PURPOSE: Boot Manager Entrypoint
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
13 /* DATA VARIABLES ************************************************************/
15 DEFINE_GUID(GUID_WINDOWS_BOOTMGR
,
19 0xAC, 0xC1, 0xF3, 0x2B, 0x34, 0x4D, 0x47, 0x95);
21 ULONGLONG ApplicationStartTime
;
23 GUID BmApplicationIdentifier
;
26 BL_BOOT_ERROR BmpErrorBuffer
;
27 PBL_BOOT_ERROR BmpInternalBootError
;
28 BL_PACKED_BOOT_ERROR BmpPackedBootError
;
30 BOOLEAN BmBootIniUsed
;
31 WCHAR BmpFileNameBuffer
[128];
32 PWCHAR ParentFileName
= L
"";
34 BOOLEAN BmDisplayStateCached
;
36 /* FUNCTIONS *****************************************************************/
40 _In_ HANDLE BcdHandle
,
42 _In_ PBL_BCD_OPTION
*OptionList
47 ULONG ElementSize
, ElementCount
, i
, OptionsSize
;
49 PBCD_ELEMENT_HEADER Header
;
50 PBCD_ELEMENT BcdElements
;
51 PBL_BCD_OPTION Options
, Option
, PreviousOption
, DeviceOptions
;
52 PBCD_DEVICE_OPTION DeviceOption
;
56 /* Open the BCD object requested */
59 Status
= BcdOpenObject(BcdHandle
, ObjectId
, &ObjectHandle
);
60 if (!NT_SUCCESS(Status
))
65 /* Do the initial enumeration to get the size needed */
67 Status
= BcdEnumerateAndUnpackElements(BcdHandle
,
72 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
74 /* If we got success, that doesn't make any sense */
75 if (NT_SUCCESS(Status
))
77 Status
= STATUS_INVALID_PARAMETER
;
84 /* Allocate a large-enough buffer */
85 BcdElements
= BlMmAllocateHeap(ElementSize
);
88 Status
= STATUS_NO_MEMORY
;
92 /* Now do the real enumeration to fill out the elements buffer */
93 Status
= BcdEnumerateAndUnpackElements(BcdHandle
,
98 if (!NT_SUCCESS(Status
))
103 /* Go through each BCD option to add the sizes up */
105 for (i
= 0; i
< ElementCount
; i
++)
107 OptionsSize
+= BcdElements
[i
].Header
->Size
+ sizeof(BL_BCD_OPTION
);
110 /* Allocate the required BCD option list */
111 Options
= BlMmAllocateHeap(OptionsSize
);
114 Status
= STATUS_NO_MEMORY
;
119 RtlZeroMemory(Options
, OptionsSize
);
121 /* Start going through each option */
122 PreviousOption
= NULL
;
124 EfiPrintf(L
"BCD Options found: %d\r\n", ElementCount
);
125 for (i
= 0; i
< ElementCount
; i
++)
127 /* Read the header and type */
128 Header
= BcdElements
[i
].Header
;
129 Type
.PackedValue
= Header
->Type
;
131 /* Check if this option isn't already present */
132 if (!MiscGetBootOption(Options
, Type
.PackedValue
))
134 /* It's a new option. Did we have an existing one? */
137 /* Link it to this new one */
138 PreviousOption
->NextEntryOffset
= (ULONG_PTR
)Option
-
142 /* Capture the type, size, data, and offset */
143 Option
->Type
= Type
.PackedValue
;
144 Option
->DataSize
= Header
->Size
;
145 RtlCopyMemory(Option
+ 1, BcdElements
[i
].Body
, Header
->Size
);
146 Option
->DataOffset
= sizeof(BL_BCD_OPTION
);
148 /* Check if this was a device */
149 if (Type
.Format
== BCD_TYPE_DEVICE
)
152 DeviceOption
= (PBCD_DEVICE_OPTION
)(Option
+ 1);
153 DeviceId
= DeviceOption
->AssociatedEntry
;
155 /* Look up the options for that GUID */
156 Status
= BmGetOptionList(BcdHandle
, &DeviceId
, &DeviceOptions
);
157 if (NT_SUCCESS(Status
))
159 /* Device data is after the device option */
160 DeviceData
= (PVOID
)((ULONG_PTR
)DeviceOption
+ Header
->Size
);
163 RtlCopyMemory(DeviceData
,
165 BlGetBootOptionListSize(DeviceOptions
));
167 /* Don't need this anymore */
168 BlMmFreeHeap(DeviceOptions
);
170 /* Write the offset of the device options */
171 Option
->ListOffset
= (ULONG_PTR
)DeviceData
-
176 /* Save the previous option and go to the next one */
177 PreviousOption
= Option
;
178 Option
= (PBL_BCD_OPTION
)((ULONG_PTR
)Option
+
179 BlGetBootOptionSize(Option
));
183 /* Return the pointer back, we've made it! */
184 *OptionList
= Options
;
185 Status
= STATUS_SUCCESS
;
188 /* Did we allocate a local buffer? Free it if so */
191 BlMmFreeHeap(BcdElements
);
194 /* Was the key open? Close it if so */
197 BiCloseKey(ObjectHandle
);
200 /* Return the option list parsing status */
205 BmpUpdateApplicationOptions (
206 _In_ HANDLE BcdHandle
210 PBL_BCD_OPTION Options
;
212 /* Get the boot option list */
213 Status
= BmGetOptionList(BcdHandle
, &BmApplicationIdentifier
, &Options
);
214 if (!NT_SUCCESS(Status
))
219 /* Append the options, free the local buffer, and return success */
220 BlAppendBootOptions(&BlpApplicationEntry
, Options
);
221 BlMmFreeHeap(Options
);
222 return STATUS_SUCCESS
;
226 BmpFwGetApplicationDirectoryPath (
227 _In_ PUNICODE_STRING ApplicationDirectoryPath
231 ULONG i
, AppPathLength
;
232 PWCHAR ApplicationPath
, PathCopy
;
234 /* Clear the incoming string */
235 ApplicationDirectoryPath
->Length
= 0;
236 ApplicationDirectoryPath
->MaximumLength
= 0;
237 ApplicationDirectoryPath
->Buffer
= 0;
239 /* Get the boot application path */
240 ApplicationPath
= NULL
;
241 Status
= BlGetBootOptionString(BlpApplicationEntry
.BcdData
,
242 BcdLibraryString_ApplicationPath
,
244 if (NT_SUCCESS(Status
))
246 /* Calculate the length of the application path */
247 for (i
= wcslen(ApplicationPath
) - 1; i
> 0; i
--)
249 /* Keep going until the path separator */
250 if (ApplicationPath
[i
] == OBJ_NAME_PATH_SEPARATOR
)
256 /* Check if we have space for one more character */
257 Status
= RtlULongAdd(i
, 1, &AppPathLength
);
258 if (NT_SUCCESS(Status
))
260 /* Check if it's safe to multiply by two */
261 Status
= RtlULongMult(AppPathLength
, sizeof(WCHAR
), &AppPathLength
);
262 if (NT_SUCCESS(Status
))
264 /* Allocate a copy for the string */
265 PathCopy
= BlMmAllocateHeap(AppPathLength
);
268 /* NULL-terminate it */
269 RtlCopyMemory(PathCopy
,
271 AppPathLength
- sizeof(UNICODE_NULL
));
272 PathCopy
[AppPathLength
] = UNICODE_NULL
;
274 /* Finally, initialize the outoing string */
275 RtlInitUnicodeString(ApplicationDirectoryPath
, PathCopy
);
279 /* No memory, fail */
280 Status
= STATUS_NO_MEMORY
;
286 /* Check if we had an application path */
289 /* No longer need this, free it */
290 BlMmFreeHeap(ApplicationPath
);
298 BmFwInitializeBootDirectoryPath (
305 UNICODE_STRING BcdPath
;
307 ULONG FileHandle
, DeviceHandle
;
309 /* Initialize everything for failure */
310 BcdPath
.MaximumLength
= 0;
311 BcdPath
.Buffer
= NULL
;
317 /* Try to open the boot device */
318 Status
= BlpDeviceOpen(BlpBootDevice
,
319 BL_DEVICE_READ_ACCESS
,
322 if (!NT_SUCCESS(Status
))
324 EfiPrintf(L
"Device open failed: %lx\r\n", Status
);
328 /* Get the directory path */
329 Status
= BmpFwGetApplicationDirectoryPath(&BcdPath
);
330 BcdDirectory
= BcdPath
.Buffer
;
331 if (!NT_SUCCESS(Status
))
336 /* Add the BCD file name to it */
337 FinalSize
= BcdPath
.MaximumLength
+ sizeof(L
"\\BCD") - sizeof(UNICODE_NULL
);
338 if (FinalSize
< BcdPath
.MaximumLength
)
343 /* Allocate space for the final path */
344 FinalPath
= BlMmAllocateHeap(FinalSize
);
351 RtlZeroMemory(FinalPath
, FinalSize
);
352 RtlCopyMemory(FinalPath
, BcdDirectory
, BcdPath
.MaximumLength
);
353 wcsncat(FinalPath
, L
"\\BCD", FinalSize
/ sizeof(WCHAR
));
355 /* Try to open the file */
356 Status
= BlFileOpen(DeviceHandle
,
360 if (!NT_SUCCESS(Status
))
362 BootDirectory
= BcdDirectory
;
366 /* Save the boot directory */
367 BootDirectory
= L
"\\EFI\\Boot"; /* Should be EFI\\ReactOS\\Boot */
370 /* Free all the allocations we made */
373 Status
= BlMmFreeHeap(BcdDirectory
);
377 Status
= BlMmFreeHeap(FinalPath
);
380 /* Close the BCD file */
381 if (FileHandle
!= -1)
383 Status
= BlFileClose(FileHandle
);
386 /* Close the boot device */
387 if (DeviceHandle
!= -1)
389 Status
= BlDeviceClose(DeviceHandle
);
392 /* Return back to the caller */
401 /* Don't yet handled boot.ini */
402 return STATUS_NOT_FOUND
;
406 BmpFatalErrorMessageFilter (
407 _In_ NTSTATUS ErrorStatus
,
408 _Out_ PULONG ErrorResourceId
413 /* Assume no message for now, check for known status message */
417 /* Convert each status to a resource ID */
418 case STATUS_UNEXPECTED_IO_ERROR
:
419 *ErrorResourceId
= 9017;
422 case STATUS_IMAGE_CHECKSUM_MISMATCH
:
423 *ErrorResourceId
= 9018;
425 case STATUS_INVALID_IMAGE_WIN_64
:
426 *ErrorResourceId
= 9016;
429 *ErrorResourceId
= 9019;
433 *ErrorResourceId
= 9013;
437 /* Return the type of message */
446 /* Check if a boot error is present */
447 if (BmpPackedBootError
.BootError
)
450 BlMmFreeHeap(BmpPackedBootError
.BootError
);
451 BmpPackedBootError
.BootError
= NULL
;
454 /* Zero out the packed buffer */
455 BmpPackedBootError
.Size
= 0;
456 BmpInternalBootError
= NULL
;
457 RtlZeroMemory(&BmpErrorBuffer
, sizeof(BmpErrorBuffer
));
462 _In_ ULONG ErrorCode
,
463 _In_ NTSTATUS ErrorStatus
,
464 _In_ ULONG ErrorMsgId
,
465 _In_ PWCHAR FileName
,
469 PWCHAR ErrorMsgString
;
471 /* Check if we already had an error */
472 if (BmpInternalBootError
)
478 /* Find the string for this error ID */
479 ErrorMsgString
= BlResourceFindMessage(ErrorMsgId
);
482 /* Fill out the error buffer */
483 BmpErrorBuffer
.Unknown1
= 0;
484 BmpErrorBuffer
.Unknown2
= 0;
485 BmpErrorBuffer
.ErrorString
= ErrorMsgString
;
486 BmpErrorBuffer
.FileName
= FileName
;
487 BmpErrorBuffer
.ErrorCode
= ErrorCode
;
488 BmpErrorBuffer
.ErrorStatus
= ErrorStatus
;
489 BmpErrorBuffer
.HelpMsgId
= HelpMsgId
;
490 BmpInternalBootError
= &BmpErrorBuffer
;
496 _In_ ULONG ErrorCode
,
497 _In_ ULONG_PTR Parameter1
,
498 _In_ ULONG_PTR Parameter2
,
499 _In_ ULONG_PTR Parameter3
,
500 _In_ ULONG_PTR Parameter4
503 PWCHAR FileName
, Buffer
;
504 NTSTATUS ErrorStatus
;
505 WCHAR FormatString
[256];
506 ULONG ErrorResourceId
, ErrorHelpId
;
507 BOOLEAN Restart
, NoError
;
509 /* Assume no buffer for now */
512 /* Check what error code is being raised */
515 /* Error reading the BCD */
516 case BL_FATAL_ERROR_BCD_READ
:
518 /* Check if we have a name for the BCD file */
521 /* Check if the name fits into our buffer */
522 FileName
= (PWCHAR
)Parameter1
;
523 if (wcslen(FileName
) < sizeof(BmpFileNameBuffer
))
525 /* Copy it in there */
526 Buffer
= BmpFileNameBuffer
;
527 wcsncpy(BmpFileNameBuffer
,
529 RTL_NUMBER_OF(BmpFileNameBuffer
));
533 /* If we don't have a buffer, use an empty one */
536 Buffer
= ParentFileName
;
539 /* The NTSTATUS code is in parameter 2*/
540 ErrorStatus
= (NTSTATUS
)Parameter2
;
542 /* Build the error string */
543 swprintf(FormatString
,
544 L
"\nAn error occurred (%08x) while attempting "
545 L
"to read the boot configuration data file %s\n",
549 /* Select the resource ID message */
550 ErrorResourceId
= 9002;
553 case BL_FATAL_ERROR_BCD_ENTRIES
:
555 /* File name is in parameter 1 */
556 FileName
= (PWCHAR
)Parameter1
;
558 /* The NTSTATUS code is in parameter 2*/
559 ErrorStatus
= (NTSTATUS
)Parameter2
;
561 /* Build the error string */
562 swprintf(FormatString
,
563 L
"\nNo valid entries found in the boot configuration data file %s\n",
566 /* Select the resource ID message */
567 ErrorResourceId
= 9007;
570 case BL_FATAL_ERROR_BCD_PARSE
:
572 /* File name isin parameter 1 */
573 FileName
= (PWCHAR
)Parameter1
;
575 /* The NTSTATUS code is in parameter 2*/
576 ErrorStatus
= (NTSTATUS
)Parameter2
;
578 /* Build the error string */
579 swprintf(FormatString
,
580 L
"\nThe boot configuration file %s is invalid (%08x).\n",
584 /* Select the resource ID message */
585 ErrorResourceId
= 9015;
588 case BL_FATAL_ERROR_GENERIC
:
590 /* The NTSTATUS code is in parameter 1*/
591 ErrorStatus
= (NTSTATUS
)Parameter1
;
593 /* Build the error string */
594 swprintf(FormatString
,
595 L
"\nThe boot manager experienced an error (%08x).\n",
598 /* Select the resource ID message */
599 ErrorResourceId
= 9005;
604 /* The rest is not yet handled */
605 EfiPrintf(L
"Unexpected fatal error: %lx\r\n", ErrorCode
);
610 /* Check if the BCD option for restart is set */
611 BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
612 BcdLibraryBoolean_RestartOnFailure
,
616 /* Yes, so no error should be shown since we'll auto-restart */
621 /* Check if the option for not showing errors is set in the BCD */
622 BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
623 BcdBootMgrBoolean_NoErrorDisplay
,
627 /* Do we want an error? */
630 /* Yep, print it and then raise an error */
631 BlStatusPrint(FormatString
);
632 BlStatusError(1, ErrorCode
, Parameter1
, Parameter2
, Parameter3
);
635 /* Get the help message ID */
636 ErrorHelpId
= BmpFatalErrorMessageFilter(ErrorStatus
, &ErrorResourceId
);
637 BmpErrorLog(ErrorCode
, ErrorStatus
, ErrorResourceId
, Buffer
, ErrorHelpId
);
642 _In_ PWCHAR FileName
,
643 _Out_ PWCHAR
* FullPath
647 ULONG BootDirLength
, PathLength
;
649 /* Compute the length of the directory, and add a NUL */
650 BootDirLength
= wcslen(BootDirectory
);
651 Status
= RtlULongAdd(BootDirLength
, 1, &BootDirLength
);
652 if (!NT_SUCCESS(Status
))
657 /* Add the length of the file, make sure it fits */
658 PathLength
= wcslen(FileName
);
659 Status
= RtlULongAdd(PathLength
, BootDirLength
, &PathLength
);
660 if (!NT_SUCCESS(Status
))
665 /* Convert to bytes */
666 Status
= RtlULongLongToULong(PathLength
* sizeof(WCHAR
), &PathLength
);
667 if (!NT_SUCCESS(Status
))
672 /* Allocate the full path */
673 *FullPath
= BlMmAllocateHeap(PathLength
);
676 /* Copy the directory followed by the file name */
677 wcsncpy(*FullPath
, BootDirectory
, PathLength
/ sizeof(WCHAR
));
678 wcsncat(*FullPath
, FileName
, PathLength
/ sizeof(WCHAR
));
682 /* Bail out since we have no memory */
683 Status
= STATUS_NO_MEMORY
;
687 /* Return to caller */
696 /* Check if boot.ini data needs to be freed */
699 EfiPrintf(L
"Boot.ini not handled\r\n");
702 /* Dereference the hive and close the key */
703 BiDereferenceHive(Handle
);
713 PBL_DEVICE_DESCRIPTOR BcdDevice
;
714 PWCHAR BcdPath
, FullPath
, PathBuffer
;
716 ULONG PathLength
, FullSize
;
718 UNICODE_STRING BcdString
;
720 /* Initialize variables */
726 /* Check if a boot.ini file exists */
727 Status
= BmOpenBootIni();
728 if (NT_SUCCESS(Status
))
730 BmBootIniUsed
= TRUE
;
733 /* Check on which device the BCD is */
734 Status
= BlGetBootOptionDevice(BlpApplicationEntry
.BcdData
,
735 BcdBootMgrDevice_BcdDevice
,
738 if (!NT_SUCCESS(Status
))
740 /* It's not on a custom device, so it must be where we are */
741 Status
= BlGetBootOptionDevice(BlpApplicationEntry
.BcdData
,
742 BcdLibraryDevice_ApplicationDevice
,
745 if (!NT_SUCCESS(Status
))
747 /* This BCD option is required */
752 /* Next, check what file contains the BCD */
753 Status
= BlGetBootOptionString(BlpApplicationEntry
.BcdData
,
754 BcdBootMgrString_BcdFilePath
,
756 if (NT_SUCCESS(Status
))
758 /* We don't handle custom BCDs yet */
759 EfiPrintf(L
"Custom BCD Not handled: %s\r\n", BcdPath
);
760 Status
= STATUS_NOT_IMPLEMENTED
;
764 /* Now check if the BCD is on a remote share */
765 if (BcdDevice
->DeviceType
== UdpDevice
)
767 /* Nope. Nope. Nope */
768 EfiPrintf(L
"UDP device Not handled\r\n");
769 Status
= STATUS_NOT_IMPLEMENTED
;
773 /* Otherwise, compute the hardcoded path of the BCD */
774 Status
= BmpFwGetFullPath(L
"\\BCD", &FullPath
);
775 if (!NT_SUCCESS(Status
))
777 /* User the raw path */
778 PathBuffer
= BcdPath
;
782 /* Use the path we got */
783 PathBuffer
= FullPath
;
787 /* Check if we failed to get the BCD path */
788 if (!NT_SUCCESS(Status
))
793 /* Add a NUL to the path, make sure it'll fit */
794 PathLength
= wcslen(PathBuffer
);
795 Status
= RtlULongAdd(PathLength
, 1, &PathLength
);
796 if (!NT_SUCCESS(Status
))
801 /* Convert to bytes */
802 Status
= RtlULongLongToULong(PathLength
* sizeof(WCHAR
), &PathLength
);
803 if (!NT_SUCCESS(Status
))
808 /* Now add the size of the path to the device path, check if it fits */
809 Status
= RtlULongAdd(PathLength
, BcdDevice
->Size
, &FullSize
);
810 if (!NT_SUCCESS(Status
))
815 /* Allocate a final structure to hold both entities */
816 FinalBuffer
= BlMmAllocateHeap(FullSize
);
819 Status
= STATUS_NO_MEMORY
;
823 /* Copy the device path and file path into the final buffer */
824 RtlCopyMemory(FinalBuffer
, BcdDevice
, BcdDevice
->Size
);
825 RtlCopyMemory((PVOID
)((ULONG_PTR
)FinalBuffer
+ BcdDevice
->Size
),
829 /* Now tell the BCD engine to open the store */
830 BcdString
.Length
= FullSize
;
831 BcdString
.MaximumLength
= FullSize
;
832 BcdString
.Buffer
= FinalBuffer
;
833 Status
= BcdOpenStoreFromFile(&BcdString
, Handle
);
835 /* Free our final buffer */
836 BlMmFreeHeap(FinalBuffer
);
839 /* Did we allocate a device? */
843 BlMmFreeHeap(BcdDevice
);
846 /* Is this the failure path? */
847 if (!NT_SUCCESS(Status
))
849 /* Raise a fatal error */
850 BmFatalErrorEx(BL_FATAL_ERROR_BCD_READ
,
851 (ULONG_PTR
)PathBuffer
,
857 /* Did we get an allocated path? */
858 if ((PathBuffer
) && (HavePath
))
861 BlMmFreeHeap(PathBuffer
);
864 /* Return back to the caller */
868 typedef struct _BL_BSD_LOG_OBJECT
875 } BL_BSD_LOG_OBJECT
, *PBL_BSD_LOG_OBJECT
;
877 BL_BSD_LOG_OBJECT BsdpLogObject
;
878 BOOLEAN BsdpLogObjectInitialized
;
882 _In_ PBL_DEVICE_DESCRIPTOR LogDevice
,
889 /* Don't initialize twice */
890 if (BsdpLogObjectInitialized
)
895 /* Set invalid IDs for now */
896 BsdpLogObject
.DeviceId
= -1;
897 BsdpLogObject
.FileId
= -1;
899 /* Open the BSD device */
900 Status
= BlpDeviceOpen(LogDevice
,
901 BL_DEVICE_READ_ACCESS
| BL_DEVICE_WRITE_ACCESS
,
903 &BsdpLogObject
.DeviceId
);
904 if (!NT_SUCCESS(Status
))
906 /* Welp that didn't work */
910 /* Now open the BSD itself */
911 Status
= BlFileOpen(BsdpLogObject
.DeviceId
,
913 BL_FILE_READ_ACCESS
| BL_FILE_WRITE_ACCESS
,
914 &BsdpLogObject
.FileId
);
915 if (!NT_SUCCESS(Status
))
921 /* The BSD is open. Start doing stuff to it */
922 EfiPrintf(L
"Unimplemented BSD path\r\n");
923 Status
= STATUS_NOT_IMPLEMENTED
;
926 /* Close the BSD if we had it open */
927 if (BsdpLogObject
.FileId
!= -1)
929 BlFileClose(BsdpLogObject
.FileId
);
932 /* Close the device if we had it open */
933 if (BsdpLogObject
.DeviceId
!= -1)
935 BlDeviceClose(BsdpLogObject
.DeviceId
);
938 /* Set BSD object to its uninitialized state */
939 BsdpLogObjectInitialized
= FALSE
;
940 BsdpLogObject
.FileId
= 0;
941 BsdpLogObject
.DeviceId
= 0;
942 BsdpLogObject
.Flags
= 0;
943 BsdpLogObject
.Unknown
= 0;
944 BsdpLogObject
.Size
= 0;
948 BmpInitializeBootStatusDataLog (
953 PBL_DEVICE_DESCRIPTOR BsdDevice
;
958 /* Initialize locals */
963 /* Check if the BSD is stored in a custom device */
964 Status
= BlGetBootOptionDevice(BlpApplicationEntry
.BcdData
,
965 BcdLibraryDevice_BsdLogDevice
,
968 if (!NT_SUCCESS(Status
))
970 /* Nope, use the boot device */
971 BsdDevice
= BlpBootDevice
;
974 /* Check if the path is custom as well */
975 Status
= BlGetBootOptionString(BlpApplicationEntry
.BcdData
,
976 BcdLibraryString_BsdLogPath
,
978 if (!NT_SUCCESS(Status
))
980 /* Nope, use our default path */
981 Status
= BmpFwGetFullPath(L
"\\bootstat.dat", &BsdPath
);
982 if (!NT_SUCCESS(Status
))
987 /* Set preserve flag */
992 /* Set preserve flag */
996 /* Finally, check if the BSD should be preserved */
997 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
998 BcdLibraryBoolean_PreserveBsdLog
,
1000 if (!(NT_SUCCESS(Status
)) || !(PreserveBsd
))
1002 /* We failed to read, or we were asked not to preserve it */
1006 /* Initialize the log */
1007 BlBsdInitializeLog(BsdDevice
, BsdPath
, Flags
);
1009 /* Free the BSD device descriptor if we had one */
1012 BlMmFreeHeap(BsdDevice
);
1015 /* Free the BSD path if we had one */
1016 if ((Flags
) && (BsdPath
))
1018 BlMmFreeHeap(BsdPath
);
1023 BmFwMemoryInitialize (
1028 PHYSICAL_ADDRESS PhysicalAddress
;
1029 BL_ADDRESS_RANGE AddressRange
;
1031 /* Select the range below 1MB */
1032 AddressRange
.Maximum
= 0xFFFFF;
1033 AddressRange
.Minimum
= 0;
1035 /* Allocate one reserved page with the "reserved" attribute */
1036 Status
= MmPapAllocatePhysicalPagesInRange(&PhysicalAddress
,
1037 BlApplicationReserved
,
1041 &MmMdlUnmappedAllocated
,
1043 BL_MM_REQUEST_DEFAULT_TYPE
);
1044 if (!NT_SUCCESS(Status
))
1046 /* Print a message on error, but keep going */
1047 BlStatusPrint(L
"BmFwMemoryInitialize: Failed to allocate a page below 1MB. Status: 0x%08x\r\n",
1053 BmpBgDisplayClearScreen (
1057 /* Not yet supported */
1058 return STATUS_NOT_IMPLEMENTED
;
1067 EfiPrintf(L
"XML: %s\r\n", XmlTag
);
1068 return STATUS_NOT_IMPLEMENTED
;
1073 _In_ PWCHAR Stylesheet
1076 /* Reset the cursor type */
1077 BlDisplaySetCursorType(0);
1079 /* Nope, not doing any XML stuff */
1080 return STATUS_SUCCESS
;
1084 BlImgQueryCodeIntegrityBootOptions (
1085 _In_ PBL_LOADED_APPLICATION_ENTRY ApplicationEntry
,
1086 _Out_ PBOOLEAN IntegrityChecksDisabled
,
1087 _Out_ PBOOLEAN TestSigningEnabled
1094 /* Check if /DISABLEINTEGRITYCHECKS is on */
1095 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
1096 BcdLibraryBoolean_DisableIntegrityChecks
,
1098 *IntegrityChecksDisabled
= NT_SUCCESS(Status
) && (Value
);
1100 /* Check if /TESTSIGNING is on */
1101 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
1102 BcdLibraryBoolean_AllowPrereleaseSignatures
,
1104 *TestSigningEnabled
= NT_SUCCESS(Status
) && (Value
);
1108 BmFwVerifySelfIntegrity (
1112 /* Check if we're booted by UEFI off the DVD directlry */
1113 if ((BlpBootDevice
->DeviceType
== LocalDevice
) &&
1114 (BlpBootDevice
->Local
.Type
== CdRomDevice
) &&
1115 (BlpApplicationFlags
& BL_APPLICATION_FLAG_CONVERTED_FROM_EFI
))
1117 /* Windows actually bypasses integrity checks in this case. Works for us */
1118 return STATUS_SUCCESS
;
1121 /* Our binaries aren't signed, so always return failure */
1126 BmFwRegisterRevocationList (
1131 BOOLEAN SecureBootEnabled
;
1133 /* Is SecureBoot enabled? */
1134 Status
= BlSecureBootIsEnabled(&SecureBootEnabled
);
1135 if ((NT_SUCCESS(Status
)) && (SecureBootEnabled
))
1137 EfiPrintf(L
"SB not implemented revok\r\n");
1138 return STATUS_NOT_IMPLEMENTED
;
1142 /* Nothing to do without SecureBoot */
1143 Status
= STATUS_SUCCESS
;
1146 /* Return revocation result back to caller */
1151 BmResumeFromHibernate (
1152 _Out_ PHANDLE BcdResumeHandle
1156 BOOLEAN AttemptResume
;
1158 /* Should we attempt to resume from hibernation? */
1159 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
1160 BcdBootMgrBoolean_AttemptResume
,
1162 if (!NT_SUCCESS(Status
))
1164 /* Nope. Is automatic restart on crash enabled? */
1165 AttemptResume
= FALSE
;
1166 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
1167 BcdOSLoaderBoolean_DisableCrashAutoReboot
,
1169 AttemptResume
= (NT_SUCCESS(Status
) && (AttemptResume
));
1172 /* Don't do anything if there's no need to resume anything */
1175 return STATUS_SUCCESS
;
1178 /* Not yet implemented */
1179 EfiPrintf(L
"Resume not supported\r\n");
1180 return STATUS_NOT_IMPLEMENTED
;
1184 BmpProcessBadMemory (
1188 BL_PD_DATA_BLOB BadMemoryData
;
1191 /* Try to get the memory data from the memtest application */
1192 BadMemoryData
.BlobSize
= 0;
1193 BadMemoryData
.Data
= NULL
;
1194 BadMemoryData
.DataSize
= 0;
1195 Status
= BlPdQueryData(&BadMemoryGuid
, NULL
, &BadMemoryData
);
1196 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1198 /* No results, or some other error */
1202 /* Not yet implemented */
1203 EfiPrintf(L
"Bad page list persistence not implemented\r\n");
1204 return STATUS_NOT_IMPLEMENTED
;
1209 _In_ HANDLE BcdHandle
,
1210 _In_ PGUID ObjectId
,
1214 HANDLE ObjectHandle
;
1217 /* Open the object */
1218 Status
= BcdOpenObject(BcdHandle
, ObjectId
, &ObjectHandle
);
1219 if (NT_SUCCESS(Status
))
1221 /* Delete the element */
1222 BcdDeleteElement(ObjectHandle
, Type
);
1224 /* Close the object and set success */
1225 BiCloseKey(ObjectHandle
);
1226 Status
= STATUS_SUCCESS
;
1229 /* Return the result */
1234 BmpPopulateBootEntryList (
1235 _In_ HANDLE BcdHandle
,
1236 _In_ PGUID SequenceList
,
1238 _Out_ PBL_LOADED_APPLICATION_ENTRY
* BootSequence
,
1239 _Out_ PULONG SequenceCount
1242 EfiPrintf(L
"Boot population not yet supported\r\n");
1244 *BootSequence
= NULL
;
1245 return STATUS_NOT_IMPLEMENTED
;
1250 _In_ HANDLE BcdHandle
,
1251 _In_ PGUID SequenceList
,
1252 _In_ ULONG SequenceListCount
,
1254 _Out_ PBL_LOADED_APPLICATION_ENTRY
** BootSequence
,
1255 _Out_ PULONG SequenceCount
1258 PBL_LOADED_APPLICATION_ENTRY
* Sequence
;
1262 /* Allocate the sequence list */
1263 Sequence
= BlMmAllocateHeap(SequenceListCount
* sizeof(*Sequence
));
1266 return STATUS_NO_MEMORY
;
1269 /* Populate the sequence list */
1270 Status
= BmpPopulateBootEntryList(BcdHandle
,
1275 if (!NT_SUCCESS(Status
))
1277 /* Free the list on failure */
1278 BlMmFreeHeap(Sequence
);
1282 /* Otherwise, set success and return the list and count */
1283 Status
= STATUS_SUCCESS
;
1284 *BootSequence
= Sequence
;
1285 *SequenceCount
= Count
;
1293 BmEnumerateBootEntries (
1294 _In_ HANDLE BcdHandle
,
1295 _Out_ PBL_LOADED_APPLICATION_ENTRY
**BootSequence
,
1296 _Out_ PULONG SequenceCount
1300 ULONG BootIndex
, BootIniCount
, BootEntryCount
, BcdCount
;
1301 PBL_LOADED_APPLICATION_ENTRY
* Sequence
;
1304 BOOLEAN UseDisplayList
;
1306 /* Initialize locals */
1309 /* First try to get the display list, if any */
1310 UseDisplayList
= TRUE
;
1311 Status
= BlGetBootOptionGuidList(BlpApplicationEntry
.BcdData
,
1312 BcdBootMgrObjectList_DisplayOrder
,
1315 if (!NT_SUCCESS(Status
))
1317 /* No list, get the default entry instead */
1318 Status
= BlGetBootOptionGuid(BlpApplicationEntry
.BcdData
,
1319 BcdBootMgrObject_DefaultObject
,
1321 if (NT_SUCCESS(Status
))
1323 /* Set the array to just our entry */
1324 UseDisplayList
= FALSE
;
1326 DisplayOrder
= &DefaultObject
;
1330 /* No default list either, return success but no entries */
1331 *BootSequence
= NULL
;
1333 Status
= STATUS_SUCCESS
;
1334 DisplayOrder
= NULL
;
1339 /* Check if boot.ini was used */
1343 /* Get the entries from it */
1344 EfiPrintf(L
"Boot.ini not supported\r\n");
1345 BootIniCount
= 0;//BmBootIniGetEntryCount();
1348 /* Allocate an array large enough for the combined boot entries */
1349 BootEntryCount
= BootIniCount
+ BcdCount
;
1350 Sequence
= BlMmAllocateHeap(BootEntryCount
* sizeof(*Sequence
));
1353 Status
= STATUS_NO_MEMORY
;
1358 RtlZeroMemory(Sequence
, BootEntryCount
* sizeof(*Sequence
));
1360 /* Check if we had BCD entries */
1363 /* Populate the list of bootable entries */
1364 Status
= BmpPopulateBootEntryList(BcdHandle
,
1369 if (!NT_SUCCESS(Status
))
1376 /* Check if we had boot.ini entries */
1380 EfiPrintf(L
"Boot.ini not supported\r\n");
1383 /* Return success and the sequence + count populated */
1384 Status
= STATUS_SUCCESS
;
1385 *BootSequence
= Sequence
;
1386 *SequenceCount
= BootIniCount
+ BcdCount
;
1389 /* Check if we had allocated a GUID list */
1390 if ((UseDisplayList
) && (DisplayOrder
))
1393 BlMmFreeHeap(DisplayOrder
);
1396 /* Check if this is the failure path */
1397 if (!(NT_SUCCESS(Status
)) && (Sequence
))
1399 /* Loop the remaining boot entries */
1400 while (BootIndex
< BootEntryCount
)
1402 /* Check if it had been allocated */
1403 if (Sequence
[BootIndex
])
1406 BlMmFreeHeap(Sequence
[BootIndex
]);
1413 /* Free the whole sequence now */
1414 BlMmFreeHeap(Sequence
);
1417 /* All done, return the result */
1422 BmpGetSelectedBootEntry (
1423 _In_ HANDLE BcdHandle
,
1424 _Out_ PBL_LOADED_APPLICATION_ENTRY
*SelectedBootEntry
,
1425 _Out_ PULONG EntryIndex
,
1426 _Out_ PBOOLEAN ExitBootManager
1430 PBL_LOADED_APPLICATION_ENTRY
* Sequence
;
1431 PBL_LOADED_APPLICATION_ENTRY Entry
, SelectedEntry
;
1432 ULONG Count
, BootIndex
;
1434 /* Initialize locals */
1438 SelectedEntry
= NULL
;
1440 /* Enumerate all the boot entries */
1441 Status
= BmEnumerateBootEntries(BcdHandle
, &Sequence
, &Count
);
1442 if (!NT_SUCCESS(Status
))
1444 /* Bail out if we failed */
1448 /* Check if there are no entries */
1451 /* This is fatal -- kill the system */
1452 Status
= STATUS_FILE_INVALID
;
1453 BmFatalErrorEx(BL_FATAL_ERROR_BCD_ENTRIES
, (ULONG_PTR
)L
"\\BCD", Status
, 0, 0);
1457 EfiPrintf(L
"Boot selection not yet implemented\r\n");
1458 *SelectedBootEntry
= NULL
;
1461 /* We are done -- did we have a sequence? */
1464 /* Do we have any boot entries we parsed? */
1465 while (BootIndex
< Count
)
1467 /* Get the current boot entry */
1468 Entry
= Sequence
[BootIndex
];
1470 /* Did we fail, or is is not the selected one? */
1471 if ((Entry
) && ((Entry
!= SelectedEntry
) || !(NT_SUCCESS(Status
))))
1473 /* Destroy it, as it won't be needed */
1474 BlDestroyBootEntry(Entry
);
1476 else if (Entry
== SelectedEntry
)
1478 /* It's the selected one, return its index */
1479 *EntryIndex
= BootIndex
;
1482 /* Move to the next entry */
1486 /* Free the sequence of entries */
1487 BlMmFreeHeap(Sequence
);
1490 /* Return the selection result */
1495 BmpLaunchBootEntry (
1496 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
,
1497 _Out_ PULONG EntryIndex
,
1499 _In_ BOOLEAN LaunchWinRe
1502 EfiPrintf(L
"Boot launch not yet implemented\r\n");
1503 return STATUS_NOT_IMPLEMENTED
;
1509 * The BmMain function implements the Windows Boot Application entrypoint for
1512 * @param BootParameters
1513 * Pointer to the Boot Application Parameter Block.
1515 * @return NT_SUCCESS if the image was loaded correctly, relevant error code
1521 _In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters
1524 NTSTATUS Status
, LibraryStatus
;
1525 BL_LIBRARY_PARAMETERS LibraryParameters
;
1526 PBL_RETURN_ARGUMENTS ReturnArguments
;
1527 PGUID AppIdentifier
;
1528 HANDLE BcdHandle
, ResumeBcdHandle
;
1529 PBL_BCD_OPTION EarlyOptions
;
1531 BOOLEAN XmlLoaded
, DisableIntegrity
, TestSigning
, PersistBootSequence
;
1532 BOOLEAN RebootOnError
, CustomActions
;
1534 PBL_LOADED_APPLICATION_ENTRY BootEntry
;
1536 ULONG SequenceListCount
;
1537 PBL_LOADED_APPLICATION_ENTRY
* BootSequence
;
1539 BOOLEAN ExitBootManager
;
1542 ULONG SequenceCount
;
1544 EfiPrintf(L
"ReactOS UEFI Boot Manager Initializing...\r\n");
1546 /* Reading the BCD can change this later on */
1547 RebootOnError
= FALSE
;
1549 /* Save the start/end-of-POST time */
1550 ApplicationStartTime
= __rdtsc();
1551 PostTime
= ApplicationStartTime
;
1553 /* Setup the boot library parameters for this application */
1554 BlSetupDefaultParameters(&LibraryParameters
);
1555 LibraryParameters
.TranslationType
= BlNone
;
1556 LibraryParameters
.LibraryFlags
= 0x400 | 0x8;
1557 LibraryParameters
.MinimumAllocationCount
= 16;
1558 LibraryParameters
.MinimumHeapSize
= 512 * 1024;
1560 /* Initialize the boot library */
1561 Status
= BlInitializeLibrary(BootParameters
, &LibraryParameters
);
1562 if (!NT_SUCCESS(Status
))
1564 /* Check for failure due to invalid application entry */
1565 if (Status
!= STATUS_INVALID_PARAMETER_9
)
1567 /* Specifically print out what happened */
1568 EfiPrintf(L
"BlInitializeLibrary failed 0x%x\r\n", Status
);
1571 /* Go to exit path */
1575 /* Get the application identifier */
1576 AppIdentifier
= BlGetApplicationIdentifier();
1579 /* None was given, so set our default one */
1580 AppIdentifier
= (PGUID
)&GUID_WINDOWS_BOOTMGR
;
1583 /* Save our identifier */
1584 BmApplicationIdentifier
= *AppIdentifier
;
1586 /* Initialize the file system to open a handle to our root boot directory */
1587 BmFwInitializeBootDirectoryPath();
1589 /* Load and initialize the boot configuration database (BCD) */
1590 Status
= BmOpenDataStore(&BcdHandle
);
1591 if (NT_SUCCESS(Status
))
1593 /* Copy the boot options */
1594 Status
= BlCopyBootOptions(BlpApplicationEntry
.BcdData
, &EarlyOptions
);
1595 if (NT_SUCCESS(Status
))
1598 Status
= BmpUpdateApplicationOptions(BcdHandle
);
1599 if (!NT_SUCCESS(Status
))
1601 /* Log a fatal error */
1602 BmFatalErrorEx(BL_FATAL_ERROR_BCD_PARSE
,
1603 (ULONG_PTR
)L
"\\BCD",
1612 /* Initialize the secure boot machine policy */
1613 Status
= BmSecureBootInitializeMachinePolicy();
1614 if (!NT_SUCCESS(Status
))
1616 BmFatalErrorEx(BL_FATAL_ERROR_SECURE_BOOT
, Status
, 0, 0, 0);
1620 /* Copy the library parameters and add the re-initialization flag */
1621 RtlCopyMemory(&LibraryParameters
,
1622 &BlpLibraryParameters
,
1623 sizeof(LibraryParameters
));
1624 LibraryParameters
.LibraryFlags
|= (BL_LIBRARY_FLAG_REINITIALIZE_ALL
|
1625 BL_LIBRARY_FLAG_REINITIALIZE
);
1627 /* Now that we've parsed the BCD, re-initialize the library */
1628 LibraryStatus
= BlInitializeLibrary(BootParameters
, &LibraryParameters
);
1629 if (!NT_SUCCESS(LibraryStatus
) && (NT_SUCCESS(Status
)))
1631 Status
= LibraryStatus
;
1634 /* Initialize firmware-specific memory regions */
1635 BmFwMemoryInitialize();
1637 /* Initialize the boot status data log (BSD) */
1638 BmpInitializeBootStatusDataLog();
1640 /* Find our XSL stylesheet */
1641 Stylesheet
= BlResourceFindHtml();
1644 /* Awe, no XML. This is actually fatal lol. Can't boot without XML. */
1645 Status
= STATUS_NOT_FOUND
;
1646 EfiPrintf(L
"BlResourceFindMessage failed 0x%x\r\n", STATUS_NOT_FOUND
);
1650 /* Initialize the XML Engine (as a side-effect, resets cursor) */
1651 Status
= BlXmiInitialize(Stylesheet
);
1652 if (!NT_SUCCESS(Status
))
1654 EfiPrintf(L
"\r\nBlXmiInitialize failed 0x%x\r\n", Status
);
1659 /* Check if there's an active bitmap visible */
1660 if (!BlDisplayValidOemBitmap())
1662 /* Nope, make the screen black using BGFX */
1663 if (!NT_SUCCESS(BmpBgDisplayClearScreen(0xFF000000)))
1665 /* BGFX isn't active, use standard display */
1666 BlDisplayClearScreen();
1671 /* Bitlocker will take over screen UI if enabled */
1672 FveDisplayScreen
= BmFveDisplayScreen
;
1675 /* Check if any bypass options are enabled */
1676 BlImgQueryCodeIntegrityBootOptions(&BlpApplicationEntry
,
1679 if (!DisableIntegrity
)
1681 /* Integrity checks are enabled, so validate our signature */
1682 Status
= BmFwVerifySelfIntegrity();
1683 if (!NT_SUCCESS(Status
))
1685 /* Signature invalid, fail boot */
1690 /* Write out the first XML tag */
1691 BlXmiWrite(L
"<bootmgr/>");
1693 /* Check for factory resset */
1694 BlSecureBootCheckForFactoryReset();
1696 /* Load the revocation list */
1697 Status
= BmFwRegisterRevocationList();
1698 if (!NT_SUCCESS(Status
))
1703 /* Register our custom progress routine */
1704 BlUtlRegisterProgressRoutine();
1706 /* Display state is not currently cached */
1707 BmDisplayStateCached
= FALSE
;
1709 /* Check if we need to resume from hibernate */
1710 Status
= BmResumeFromHibernate(&ResumeBcdHandle
);
1711 if (!NT_SUCCESS(Status
))
1716 #ifdef BL_NET_SUPPORT
1717 /* Register multicast printing routine */
1718 BlUtlRegisterMulticastRoutine();
1721 /* Check if restart on failure is enabled */
1722 BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
1723 BcdLibraryBoolean_RestartOnFailure
,
1726 /* Check if the boot sequence is persisted */
1727 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
1728 BcdBootMgrBoolean_PersistBootSequence
,
1729 &PersistBootSequence
);
1730 if (!NT_SUCCESS(Status
))
1733 PersistBootSequence
= TRUE
;
1736 /* Check if there's custom actions to take */
1737 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
1738 BcdBootMgrBoolean_ProcessCustomActionsFirst
,
1740 if ((NT_SUCCESS(Status
)) && (CustomActions
))
1742 /* We don't suppport this yet */
1743 EfiPrintf(L
"Not implemented\r\n");
1744 Status
= STATUS_NOT_IMPLEMENTED
;
1748 /* At last, enter the boot selection stage */
1752 SequenceList
= NULL
;
1753 BootSequence
= NULL
;
1757 /* We don't have a boot entry nor a sequence ID */
1761 /* Do we have a hardcoded boot sequence set? */
1762 if (!(BootSequence
) && !(GetEntry
))
1764 /* Not yet, read the BCD to see if one is there */
1765 Status
= BlGetBootOptionGuidList(BlpApplicationEntry
.BcdData
,
1766 BcdBootMgrObjectList_BootSequence
,
1768 &SequenceListCount
);
1769 if (NT_SUCCESS(Status
))
1771 /* A GUID list for the boot sequence is set. Extract it */
1772 Status
= BmGetBootSequence(BcdHandle
,
1778 if (NT_SUCCESS(Status
))
1780 /* Don't get stuck in a loop repeating this sequence */
1781 BlRemoveBootOption(BlpApplicationEntry
.BcdData
,
1782 BcdBootMgrObjectList_BootSequence
);
1784 /* But do check if we should persist it */
1785 if (PersistBootSequence
)
1787 /* Yes -- so go select an entry now */
1792 /* We shouldn't, so wipe it from the BCD too */
1793 Status
= BmPurgeOption(BcdHandle
,
1794 &BmApplicationIdentifier
,
1795 BcdBootMgrObjectList_BootSequence
);
1796 if (!NT_SUCCESS(Status
))
1798 /* Well that failed */
1806 /* No boot entry sequence for us */
1807 BootSequence
= NULL
;
1811 /* Do we have a sequence active, and are we still processing it? */
1812 if ((BootSequence
) && ((GetEntry
) || (SequenceId
< SequenceCount
)))
1814 /* Extract the next entry in the sequence */
1815 BootEntry
= BootSequence
[SequenceId
];
1816 BootSequence
[SequenceId
] = NULL
;
1818 /* Move to the next entry for next time */
1821 /* Unless there won't be a a next time? */
1822 if (SequenceId
== SequenceCount
)
1824 /* Clean up, it's the last entry */
1825 BlMmFreeHeap(BootSequence
);
1826 BootSequence
= NULL
;
1831 /* Get the selected boot entry from the user */
1832 ExitBootManager
= FALSE
;
1833 Status
= BmpGetSelectedBootEntry(BcdHandle
,
1837 if (!(NT_SUCCESS(Status
)) || (ExitBootManager
))
1839 /* Selection failed, or user wants to exit */
1844 /* Did we have a BCD open? */
1847 /* Close it, we'll be opening a new one */
1848 BmCloseDataStore(BcdHandle
);
1852 /* Launch the selected entry */
1853 Status
= BmpLaunchBootEntry(BootEntry
, &BootIndex
, 0, TRUE
);
1854 if (NT_SUCCESS(Status
))
1856 /* Boot worked, uncache display and process the bad memory list */
1857 BmDisplayStateCached
= FALSE
;
1858 BmpProcessBadMemory();
1862 /* Boot failed -- was it user driven? */
1863 if (Status
!= STATUS_CANCELLED
)
1865 /* Nope, remember that booting failed */
1870 /* Yes -- the display is still valid */
1871 BmDisplayStateCached
= TRUE
;
1874 /* Reopen the BCD */
1875 Status
= BmOpenDataStore(&BcdHandle
);
1876 if (!NT_SUCCESS(Status
))
1881 /* Put the BCD options back into our entry */
1882 BlReplaceBootOptions(&BlpApplicationEntry
, EarlyOptions
);
1884 /* Update our options one more time */
1885 Status
= BmpUpdateApplicationOptions(BcdHandle
);
1886 if (NT_SUCCESS(Status
))
1888 /* Boot was 100% OK */
1893 /* Did we have a boot entry? */
1896 /* We can destroy it now */
1897 BlDestroyBootEntry(BootEntry
);
1900 /* Is this the success path? */
1901 if (NT_SUCCESS(Status
))
1903 /* Did we actually boot something? */
1906 /* Bope, fail out */
1911 /* This is the failure path... should we reboot? */
1921 /* Check if we got here due to an internal error */
1922 if (BmpInternalBootError
)
1924 /* If XML is available, display the error */
1927 //BmDisplayDumpError(0, 0);
1931 /* Don't do a fatal error -- return back to firmware */
1936 /* Log a general fatal error once we're here */
1937 BmFatalErrorEx(BL_FATAL_ERROR_GENERIC
, Status
, 0, 0, 0);
1940 /* Check if we should reboot */
1941 if ((RebootOnError
) ||
1942 (BlpApplicationEntry
.Flags
& BL_APPLICATION_ENTRY_REBOOT_ON_ERROR
))
1944 /* Reboot the box */
1946 Status
= STATUS_SUCCESS
;
1950 /* Return back to the caller with the error argument encoded */
1951 ReturnArguments
= (PVOID
)((ULONG_PTR
)BootParameters
+ BootParameters
->ReturnArgumentsOffset
);
1952 ReturnArguments
->Version
= BL_RETURN_ARGUMENTS_VERSION
;
1953 ReturnArguments
->Status
= Status
;
1955 /* Tear down the boot library */
1959 /* Return back status */