2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Manager
4 * FILE: boot/environ/app/bootmgr/bootmgr.cla
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
;
35 PBL_LOADED_APPLICATION_ENTRY
* BmpFailedBootEntries
;
36 PBL_LOADED_APPLICATION_ENTRY BmpSelectedBootEntry
;
37 BOOLEAN BmBootEntryOverridePresent
;
38 BOOLEAN BmpDisplayBootMenu
;
40 /* FUNCTIONS *****************************************************************/
44 _In_ HANDLE BcdHandle
,
46 _In_ PBL_BCD_OPTION
*OptionList
51 ULONG ElementSize
, ElementCount
, i
, OptionsSize
;
53 PBCD_ELEMENT_HEADER Header
;
54 PBCD_ELEMENT BcdElements
;
55 PBL_BCD_OPTION Options
, Option
, PreviousOption
, DeviceOptions
;
56 PBCD_DEVICE_OPTION DeviceOption
;
60 /* Open the BCD object requested */
63 Status
= BcdOpenObject(BcdHandle
, ObjectId
, &ObjectHandle
);
64 if (!NT_SUCCESS(Status
))
69 /* Do the initial enumeration to get the size needed */
71 Status
= BcdEnumerateAndUnpackElements(BcdHandle
,
76 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
78 /* If we got success, that doesn't make any sense */
79 if (NT_SUCCESS(Status
))
81 Status
= STATUS_INVALID_PARAMETER
;
88 /* Allocate a large-enough buffer */
89 BcdElements
= BlMmAllocateHeap(ElementSize
);
92 Status
= STATUS_NO_MEMORY
;
96 /* Now do the real enumeration to fill out the elements buffer */
97 Status
= BcdEnumerateAndUnpackElements(BcdHandle
,
102 if (!NT_SUCCESS(Status
))
107 /* Go through each BCD option to add the sizes up */
109 for (i
= 0; i
< ElementCount
; i
++)
111 OptionsSize
+= BcdElements
[i
].Header
->Size
+ sizeof(BL_BCD_OPTION
);
114 /* Allocate the required BCD option list */
115 Options
= BlMmAllocateHeap(OptionsSize
);
118 Status
= STATUS_NO_MEMORY
;
123 RtlZeroMemory(Options
, OptionsSize
);
125 /* Start going through each option */
126 PreviousOption
= NULL
;
128 for (i
= 0; i
< ElementCount
; i
++)
130 /* Read the header and type */
131 Header
= BcdElements
[i
].Header
;
132 Type
.PackedValue
= Header
->Type
;
134 /* Check if this option isn't already present */
135 if (!MiscGetBootOption(Options
, Type
.PackedValue
))
137 /* It's a new option. Did we have an existing one? */
140 /* Link it to this new one */
141 PreviousOption
->NextEntryOffset
= (ULONG_PTR
)Option
-
145 /* Capture the type, size, data, and offset */
146 Option
->Type
= Type
.PackedValue
;
147 Option
->DataSize
= Header
->Size
;
148 RtlCopyMemory(Option
+ 1, BcdElements
[i
].Body
, Header
->Size
);
149 Option
->DataOffset
= sizeof(BL_BCD_OPTION
);
151 /* Check if this was a device */
152 if (Type
.Format
== BCD_TYPE_DEVICE
)
155 DeviceOption
= (PBCD_DEVICE_OPTION
)(Option
+ 1);
156 DeviceId
= DeviceOption
->AssociatedEntry
;
158 /* Look up the options for that GUID */
159 Status
= BmGetOptionList(BcdHandle
, &DeviceId
, &DeviceOptions
);
160 if (NT_SUCCESS(Status
))
162 /* Device data is after the device option */
163 DeviceData
= (PVOID
)((ULONG_PTR
)DeviceOption
+ Header
->Size
);
166 RtlCopyMemory(DeviceData
,
168 BlGetBootOptionListSize(DeviceOptions
));
170 /* Don't need this anymore */
171 BlMmFreeHeap(DeviceOptions
);
173 /* Write the offset of the device options */
174 Option
->ListOffset
= (ULONG_PTR
)DeviceData
-
179 /* Save the previous option and go to the next one */
180 PreviousOption
= Option
;
181 Option
= (PBL_BCD_OPTION
)((ULONG_PTR
)Option
+
182 BlGetBootOptionSize(Option
));
186 /* Return the pointer back, we've made it! */
187 *OptionList
= Options
;
188 Status
= STATUS_SUCCESS
;
191 /* Did we allocate a local buffer? Free it if so */
194 BlMmFreeHeap(BcdElements
);
197 /* Was the key open? Close it if so */
200 BiCloseKey(ObjectHandle
);
203 /* Return the option list parsing status */
208 BmpUpdateApplicationOptions (
209 _In_ HANDLE BcdHandle
213 PBL_BCD_OPTION Options
;
215 /* Get the boot option list */
216 Status
= BmGetOptionList(BcdHandle
, &BmApplicationIdentifier
, &Options
);
217 if (!NT_SUCCESS(Status
))
222 /* Append the options, free the local buffer, and return success */
223 BlAppendBootOptions(&BlpApplicationEntry
, Options
);
224 BlMmFreeHeap(Options
);
225 return STATUS_SUCCESS
;
229 BmpFwGetApplicationDirectoryPath (
230 _In_ PUNICODE_STRING ApplicationDirectoryPath
234 ULONG i
, AppPathLength
;
235 PWCHAR ApplicationPath
, PathCopy
;
237 /* Clear the incoming string */
238 ApplicationDirectoryPath
->Length
= 0;
239 ApplicationDirectoryPath
->MaximumLength
= 0;
240 ApplicationDirectoryPath
->Buffer
= 0;
242 /* Get the boot application path */
243 ApplicationPath
= NULL
;
244 Status
= BlGetBootOptionString(BlpApplicationEntry
.BcdData
,
245 BcdLibraryString_ApplicationPath
,
247 if (NT_SUCCESS(Status
))
249 /* Calculate the length of the application path */
250 for (i
= wcslen(ApplicationPath
) - 1; i
> 0; i
--)
252 /* Keep going until the path separator */
253 if (ApplicationPath
[i
] == OBJ_NAME_PATH_SEPARATOR
)
259 /* Check if we have space for one more character */
260 Status
= RtlULongAdd(i
, 1, &AppPathLength
);
261 if (NT_SUCCESS(Status
))
263 /* Check if it's safe to multiply by two */
264 Status
= RtlULongMult(AppPathLength
, sizeof(WCHAR
), &AppPathLength
);
265 if (NT_SUCCESS(Status
))
267 /* Allocate a copy for the string */
268 PathCopy
= BlMmAllocateHeap(AppPathLength
);
271 /* NULL-terminate it */
272 RtlCopyMemory(PathCopy
,
274 AppPathLength
- sizeof(UNICODE_NULL
));
275 PathCopy
[AppPathLength
] = UNICODE_NULL
;
277 /* Finally, initialize the outoing string */
278 RtlInitUnicodeString(ApplicationDirectoryPath
, PathCopy
);
282 /* No memory, fail */
283 Status
= STATUS_NO_MEMORY
;
289 /* Check if we had an application path */
292 /* No longer need this, free it */
293 BlMmFreeHeap(ApplicationPath
);
301 BmFwInitializeBootDirectoryPath (
308 UNICODE_STRING BcdPath
;
310 ULONG FileHandle
, DeviceHandle
;
312 /* Initialize everything for failure */
313 BcdPath
.MaximumLength
= 0;
314 BcdPath
.Buffer
= NULL
;
320 /* Try to open the boot device */
321 Status
= BlpDeviceOpen(BlpBootDevice
,
322 BL_DEVICE_READ_ACCESS
,
325 if (!NT_SUCCESS(Status
))
327 EfiPrintf(L
"Device open failed: %lx\r\n", Status
);
331 /* Get the directory path */
332 Status
= BmpFwGetApplicationDirectoryPath(&BcdPath
);
333 BcdDirectory
= BcdPath
.Buffer
;
334 if (!NT_SUCCESS(Status
))
339 /* Add the BCD file name to it */
340 FinalSize
= BcdPath
.MaximumLength
+ sizeof(L
"\\BCD") - sizeof(UNICODE_NULL
);
341 if (FinalSize
< BcdPath
.MaximumLength
)
346 /* Allocate space for the final path */
347 FinalPath
= BlMmAllocateHeap(FinalSize
);
354 RtlZeroMemory(FinalPath
, FinalSize
);
355 RtlCopyMemory(FinalPath
, BcdDirectory
, BcdPath
.MaximumLength
);
356 wcsncat(FinalPath
, L
"\\BCD", FinalSize
/ sizeof(WCHAR
));
358 /* Try to open the file */
359 Status
= BlFileOpen(DeviceHandle
,
363 if (!NT_SUCCESS(Status
))
365 BootDirectory
= BcdDirectory
;
369 /* Save the boot directory */
370 BootDirectory
= L
"\\EFI\\Boot"; /* Should be EFI\\ReactOS\\Boot */
373 /* Free all the allocations we made */
376 Status
= BlMmFreeHeap(BcdDirectory
);
380 Status
= BlMmFreeHeap(FinalPath
);
383 /* Close the BCD file */
384 if (FileHandle
!= -1)
386 Status
= BlFileClose(FileHandle
);
389 /* Close the boot device */
390 if (DeviceHandle
!= -1)
392 Status
= BlDeviceClose(DeviceHandle
);
395 /* Return back to the caller */
404 /* Don't yet handled boot.ini */
405 return STATUS_NOT_FOUND
;
409 BmpFatalErrorMessageFilter (
410 _In_ NTSTATUS ErrorStatus
,
411 _Out_ PULONG ErrorResourceId
416 /* Assume no message for now, check for known status message */
420 /* Convert each status to a resource ID */
421 case STATUS_UNEXPECTED_IO_ERROR
:
422 *ErrorResourceId
= 9017;
425 case STATUS_IMAGE_CHECKSUM_MISMATCH
:
426 *ErrorResourceId
= 9018;
428 case STATUS_INVALID_IMAGE_WIN_64
:
429 *ErrorResourceId
= 9016;
432 *ErrorResourceId
= 9019;
436 *ErrorResourceId
= 9013;
440 /* Return the type of message */
449 /* Check if a boot error is present */
450 if (BmpPackedBootError
.BootError
)
453 BlMmFreeHeap(BmpPackedBootError
.BootError
);
454 BmpPackedBootError
.BootError
= NULL
;
457 /* Zero out the packed buffer */
458 BmpPackedBootError
.Size
= 0;
459 BmpInternalBootError
= NULL
;
460 RtlZeroMemory(&BmpErrorBuffer
, sizeof(BmpErrorBuffer
));
465 _In_ ULONG ErrorCode
,
466 _In_ NTSTATUS ErrorStatus
,
467 _In_ ULONG ErrorMsgId
,
468 _In_ PWCHAR FileName
,
472 PWCHAR ErrorMsgString
;
474 /* Check if we already had an error */
475 if (BmpInternalBootError
)
481 /* Find the string for this error ID */
482 ErrorMsgString
= BlResourceFindMessage(ErrorMsgId
);
485 /* Fill out the error buffer */
486 BmpErrorBuffer
.Unknown1
= 0;
487 BmpErrorBuffer
.Unknown2
= 0;
488 BmpErrorBuffer
.ErrorString
= ErrorMsgString
;
489 BmpErrorBuffer
.FileName
= FileName
;
490 BmpErrorBuffer
.ErrorCode
= ErrorCode
;
491 BmpErrorBuffer
.ErrorStatus
= ErrorStatus
;
492 BmpErrorBuffer
.HelpMsgId
= HelpMsgId
;
493 BmpInternalBootError
= &BmpErrorBuffer
;
499 _In_ ULONG ErrorCode
,
500 _In_ ULONG_PTR Parameter1
,
501 _In_ ULONG_PTR Parameter2
,
502 _In_ ULONG_PTR Parameter3
,
503 _In_ ULONG_PTR Parameter4
506 PWCHAR FileName
, Buffer
;
507 NTSTATUS ErrorStatus
;
508 WCHAR FormatString
[256];
509 ULONG ErrorResourceId
, ErrorHelpId
;
510 BOOLEAN Restart
, NoError
;
512 /* Assume no buffer for now */
515 /* Check what error code is being raised */
518 /* Error reading the BCD */
519 case BL_FATAL_ERROR_BCD_READ
:
521 /* Check if we have a name for the BCD file */
524 /* Check if the name fits into our buffer */
525 FileName
= (PWCHAR
)Parameter1
;
526 if (wcslen(FileName
) < sizeof(BmpFileNameBuffer
))
528 /* Copy it in there */
529 Buffer
= BmpFileNameBuffer
;
530 wcsncpy(BmpFileNameBuffer
,
532 RTL_NUMBER_OF(BmpFileNameBuffer
));
536 /* If we don't have a buffer, use an empty one */
539 Buffer
= ParentFileName
;
542 /* The NTSTATUS code is in parameter 2*/
543 ErrorStatus
= (NTSTATUS
)Parameter2
;
545 /* Build the error string */
546 swprintf(FormatString
,
547 L
"\nAn error occurred (%08x) while attempting "
548 L
"to read the boot configuration data file %s\n",
552 /* Select the resource ID message */
553 ErrorResourceId
= 9002;
556 case BL_FATAL_ERROR_BCD_ENTRIES
:
558 /* File name is in parameter 1 */
559 FileName
= (PWCHAR
)Parameter1
;
561 /* The NTSTATUS code is in parameter 2*/
562 ErrorStatus
= (NTSTATUS
)Parameter2
;
564 /* Build the error string */
565 swprintf(FormatString
,
566 L
"\nNo valid entries found in the boot configuration data file %s\n",
569 /* Select the resource ID message */
570 ErrorResourceId
= 9007;
573 case BL_FATAL_ERROR_BCD_PARSE
:
575 /* File name isin parameter 1 */
576 FileName
= (PWCHAR
)Parameter1
;
578 /* The NTSTATUS code is in parameter 2*/
579 ErrorStatus
= (NTSTATUS
)Parameter2
;
581 /* Build the error string */
582 swprintf(FormatString
,
583 L
"\nThe boot configuration file %s is invalid (%08x).\n",
587 /* Select the resource ID message */
588 ErrorResourceId
= 9015;
591 case BL_FATAL_ERROR_GENERIC
:
593 /* The NTSTATUS code is in parameter 1*/
594 ErrorStatus
= (NTSTATUS
)Parameter1
;
596 /* Build the error string */
597 swprintf(FormatString
,
598 L
"\nThe boot manager experienced an error (%08x).\n",
601 /* Select the resource ID message */
602 ErrorResourceId
= 9005;
607 /* The rest is not yet handled */
608 EfiPrintf(L
"Unexpected fatal error: %lx\r\n", ErrorCode
);
613 /* Check if the BCD option for restart is set */
614 BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
615 BcdLibraryBoolean_RestartOnFailure
,
619 /* Yes, so no error should be shown since we'll auto-restart */
624 /* Check if the option for not showing errors is set in the BCD */
625 BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
626 BcdBootMgrBoolean_NoErrorDisplay
,
630 /* Do we want an error? */
633 /* Yep, print it and then raise an error */
634 BlStatusPrint(FormatString
);
635 BlStatusError(1, ErrorCode
, Parameter1
, Parameter2
, Parameter3
);
638 /* Get the help message ID */
639 ErrorHelpId
= BmpFatalErrorMessageFilter(ErrorStatus
, &ErrorResourceId
);
640 BmpErrorLog(ErrorCode
, ErrorStatus
, ErrorResourceId
, Buffer
, ErrorHelpId
);
645 _In_ PWCHAR FileName
,
646 _Out_ PWCHAR
* FullPath
650 ULONG BootDirLength
, PathLength
;
652 /* Compute the length of the directory, and add a NUL */
653 BootDirLength
= wcslen(BootDirectory
);
654 Status
= RtlULongAdd(BootDirLength
, 1, &BootDirLength
);
655 if (!NT_SUCCESS(Status
))
660 /* Add the length of the file, make sure it fits */
661 PathLength
= wcslen(FileName
);
662 Status
= RtlULongAdd(PathLength
, BootDirLength
, &PathLength
);
663 if (!NT_SUCCESS(Status
))
668 /* Convert to bytes */
669 Status
= RtlULongLongToULong(PathLength
* sizeof(WCHAR
), &PathLength
);
670 if (!NT_SUCCESS(Status
))
675 /* Allocate the full path */
676 *FullPath
= BlMmAllocateHeap(PathLength
);
679 /* Copy the directory followed by the file name */
680 wcsncpy(*FullPath
, BootDirectory
, PathLength
/ sizeof(WCHAR
));
681 wcsncat(*FullPath
, FileName
, PathLength
/ sizeof(WCHAR
));
685 /* Bail out since we have no memory */
686 Status
= STATUS_NO_MEMORY
;
690 /* Return to caller */
699 /* Check if boot.ini data needs to be freed */
702 EfiPrintf(L
"Boot.ini not handled\r\n");
705 /* Dereference the hive and close the key */
706 BiDereferenceHive(Handle
);
716 PBL_DEVICE_DESCRIPTOR BcdDevice
;
717 PWCHAR BcdPath
, FullPath
, PathBuffer
;
719 ULONG PathLength
, FullSize
;
721 UNICODE_STRING BcdString
;
723 /* Initialize variables */
729 /* Check if a boot.ini file exists */
730 Status
= BmOpenBootIni();
731 if (NT_SUCCESS(Status
))
733 BmBootIniUsed
= TRUE
;
736 /* Check on which device the BCD is */
737 Status
= BlGetBootOptionDevice(BlpApplicationEntry
.BcdData
,
738 BcdBootMgrDevice_BcdDevice
,
741 if (!NT_SUCCESS(Status
))
743 /* It's not on a custom device, so it must be where we are */
744 Status
= BlGetBootOptionDevice(BlpApplicationEntry
.BcdData
,
745 BcdLibraryDevice_ApplicationDevice
,
748 if (!NT_SUCCESS(Status
))
750 /* This BCD option is required */
755 /* Next, check what file contains the BCD */
756 Status
= BlGetBootOptionString(BlpApplicationEntry
.BcdData
,
757 BcdBootMgrString_BcdFilePath
,
759 if (NT_SUCCESS(Status
))
761 /* We don't handle custom BCDs yet */
762 EfiPrintf(L
"Custom BCD Not handled: %s\r\n", BcdPath
);
763 Status
= STATUS_NOT_IMPLEMENTED
;
767 /* Now check if the BCD is on a remote share */
768 if (BcdDevice
->DeviceType
== UdpDevice
)
770 /* Nope. Nope. Nope */
771 EfiPrintf(L
"UDP device Not handled\r\n");
772 Status
= STATUS_NOT_IMPLEMENTED
;
776 /* Otherwise, compute the hardcoded path of the BCD */
777 Status
= BmpFwGetFullPath(L
"\\BCD", &FullPath
);
778 if (!NT_SUCCESS(Status
))
780 /* User the raw path */
781 PathBuffer
= BcdPath
;
785 /* Use the path we got */
786 PathBuffer
= FullPath
;
790 /* Check if we failed to get the BCD path */
791 if (!NT_SUCCESS(Status
))
796 /* Add a NUL to the path, make sure it'll fit */
797 PathLength
= wcslen(PathBuffer
);
798 Status
= RtlULongAdd(PathLength
, 1, &PathLength
);
799 if (!NT_SUCCESS(Status
))
804 /* Convert to bytes */
805 Status
= RtlULongLongToULong(PathLength
* sizeof(WCHAR
), &PathLength
);
806 if (!NT_SUCCESS(Status
))
811 /* Now add the size of the path to the device path, check if it fits */
812 Status
= RtlULongAdd(PathLength
, BcdDevice
->Size
, &FullSize
);
813 if (!NT_SUCCESS(Status
))
818 /* Allocate a final structure to hold both entities */
819 FinalBuffer
= BlMmAllocateHeap(FullSize
);
822 Status
= STATUS_NO_MEMORY
;
826 /* Copy the device path and file path into the final buffer */
827 RtlCopyMemory(FinalBuffer
, BcdDevice
, BcdDevice
->Size
);
828 RtlCopyMemory((PVOID
)((ULONG_PTR
)FinalBuffer
+ BcdDevice
->Size
),
832 /* Now tell the BCD engine to open the store */
833 BcdString
.Length
= FullSize
;
834 BcdString
.MaximumLength
= FullSize
;
835 BcdString
.Buffer
= FinalBuffer
;
836 Status
= BcdOpenStoreFromFile(&BcdString
, Handle
);
838 /* Free our final buffer */
839 BlMmFreeHeap(FinalBuffer
);
842 /* Did we allocate a device? */
846 BlMmFreeHeap(BcdDevice
);
849 /* Is this the failure path? */
850 if (!NT_SUCCESS(Status
))
852 /* Raise a fatal error */
853 BmFatalErrorEx(BL_FATAL_ERROR_BCD_READ
,
854 (ULONG_PTR
)PathBuffer
,
860 /* Did we get an allocated path? */
861 if ((PathBuffer
) && (HavePath
))
864 BlMmFreeHeap(PathBuffer
);
867 /* Return back to the caller */
871 typedef struct _BL_BSD_LOG_OBJECT
878 } BL_BSD_LOG_OBJECT
, *PBL_BSD_LOG_OBJECT
;
880 BL_BSD_LOG_OBJECT BsdpLogObject
;
881 BOOLEAN BsdpLogObjectInitialized
;
885 _In_ PBL_DEVICE_DESCRIPTOR LogDevice
,
892 /* Don't initialize twice */
893 if (BsdpLogObjectInitialized
)
898 /* Set invalid IDs for now */
899 BsdpLogObject
.DeviceId
= -1;
900 BsdpLogObject
.FileId
= -1;
902 /* Open the BSD device */
903 Status
= BlpDeviceOpen(LogDevice
,
904 BL_DEVICE_READ_ACCESS
| BL_DEVICE_WRITE_ACCESS
,
906 &BsdpLogObject
.DeviceId
);
907 if (!NT_SUCCESS(Status
))
909 /* Welp that didn't work */
913 /* Now open the BSD itself */
914 Status
= BlFileOpen(BsdpLogObject
.DeviceId
,
916 BL_FILE_READ_ACCESS
| BL_FILE_WRITE_ACCESS
,
917 &BsdpLogObject
.FileId
);
918 if (!NT_SUCCESS(Status
))
924 /* The BSD is open. Start doing stuff to it */
925 EfiPrintf(L
"Unimplemented BSD path\r\n");
926 Status
= STATUS_NOT_IMPLEMENTED
;
929 /* Close the BSD if we had it open */
930 if (BsdpLogObject
.FileId
!= -1)
932 BlFileClose(BsdpLogObject
.FileId
);
935 /* Close the device if we had it open */
936 if (BsdpLogObject
.DeviceId
!= -1)
938 BlDeviceClose(BsdpLogObject
.DeviceId
);
941 /* Set BSD object to its uninitialized state */
942 BsdpLogObjectInitialized
= FALSE
;
943 BsdpLogObject
.FileId
= 0;
944 BsdpLogObject
.DeviceId
= 0;
945 BsdpLogObject
.Flags
= 0;
946 BsdpLogObject
.Unknown
= 0;
947 BsdpLogObject
.Size
= 0;
951 BmpInitializeBootStatusDataLog (
956 PBL_DEVICE_DESCRIPTOR BsdDevice
;
961 /* Initialize locals */
966 /* Check if the BSD is stored in a custom device */
967 Status
= BlGetBootOptionDevice(BlpApplicationEntry
.BcdData
,
968 BcdLibraryDevice_BsdLogDevice
,
971 if (!NT_SUCCESS(Status
))
973 /* Nope, use the boot device */
974 BsdDevice
= BlpBootDevice
;
977 /* Check if the path is custom as well */
978 Status
= BlGetBootOptionString(BlpApplicationEntry
.BcdData
,
979 BcdLibraryString_BsdLogPath
,
981 if (!NT_SUCCESS(Status
))
983 /* Nope, use our default path */
984 Status
= BmpFwGetFullPath(L
"\\bootstat.dat", &BsdPath
);
985 if (!NT_SUCCESS(Status
))
990 /* Set preserve flag */
995 /* Set preserve flag */
999 /* Finally, check if the BSD should be preserved */
1000 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
1001 BcdLibraryBoolean_PreserveBsdLog
,
1003 if (!(NT_SUCCESS(Status
)) || !(PreserveBsd
))
1005 /* We failed to read, or we were asked not to preserve it */
1009 /* Initialize the log */
1010 BlBsdInitializeLog(BsdDevice
, BsdPath
, Flags
);
1012 /* Free the BSD device descriptor if we had one */
1015 BlMmFreeHeap(BsdDevice
);
1018 /* Free the BSD path if we had one */
1019 if ((Flags
) && (BsdPath
))
1021 BlMmFreeHeap(BsdPath
);
1026 BmFwMemoryInitialize (
1031 PHYSICAL_ADDRESS PhysicalAddress
;
1032 BL_ADDRESS_RANGE AddressRange
;
1034 /* Select the range below 1MB */
1035 AddressRange
.Maximum
= 0xFFFFF;
1036 AddressRange
.Minimum
= 0;
1038 /* Allocate one reserved page with the "reserved" attribute */
1039 Status
= MmPapAllocatePhysicalPagesInRange(&PhysicalAddress
,
1040 BlApplicationReserved
,
1044 &MmMdlUnmappedAllocated
,
1046 BL_MM_REQUEST_DEFAULT_TYPE
);
1047 if (!NT_SUCCESS(Status
))
1049 /* Print a message on error, but keep going */
1050 BlStatusPrint(L
"BmFwMemoryInitialize: Failed to allocate a page below 1MB. Status: 0x%08x\r\n",
1056 BmpBgDisplayClearScreen (
1060 /* Not yet supported */
1061 return STATUS_NOT_IMPLEMENTED
;
1070 EfiPrintf(L
"XML: %s\r\n", XmlTag
);
1071 return STATUS_NOT_IMPLEMENTED
;
1076 _In_ PWCHAR Stylesheet
1079 /* Reset the cursor type */
1080 BlDisplaySetCursorType(0);
1082 /* Nope, not doing any XML stuff */
1083 return STATUS_SUCCESS
;
1087 BlImgQueryCodeIntegrityBootOptions (
1088 _In_ PBL_LOADED_APPLICATION_ENTRY ApplicationEntry
,
1089 _Out_ PBOOLEAN IntegrityChecksDisabled
,
1090 _Out_ PBOOLEAN TestSigningEnabled
1097 /* Check if /DISABLEINTEGRITYCHECKS is on */
1098 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
1099 BcdLibraryBoolean_DisableIntegrityChecks
,
1101 *IntegrityChecksDisabled
= NT_SUCCESS(Status
) && (Value
);
1103 /* Check if /TESTSIGNING is on */
1104 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
1105 BcdLibraryBoolean_AllowPrereleaseSignatures
,
1107 *TestSigningEnabled
= NT_SUCCESS(Status
) && (Value
);
1111 BmFwVerifySelfIntegrity (
1115 /* Check if we're booted by UEFI off the DVD directlry */
1116 if ((BlpBootDevice
->DeviceType
== LocalDevice
) &&
1117 (BlpBootDevice
->Local
.Type
== CdRomDevice
) &&
1118 (BlpApplicationFlags
& BL_APPLICATION_FLAG_CONVERTED_FROM_EFI
))
1120 /* Windows actually bypasses integrity checks in this case. Works for us */
1121 return STATUS_SUCCESS
;
1124 /* Our binaries aren't signed, so always return failure */
1129 BmFwRegisterRevocationList (
1134 BOOLEAN SecureBootEnabled
;
1136 /* Is SecureBoot enabled? */
1137 Status
= BlSecureBootIsEnabled(&SecureBootEnabled
);
1138 if ((NT_SUCCESS(Status
)) && (SecureBootEnabled
))
1140 EfiPrintf(L
"SB not implemented revok\r\n");
1141 return STATUS_NOT_IMPLEMENTED
;
1145 /* Nothing to do without SecureBoot */
1146 Status
= STATUS_SUCCESS
;
1149 /* Return revocation result back to caller */
1154 BmResumeFromHibernate (
1155 _Out_ PHANDLE BcdResumeHandle
1159 BOOLEAN AttemptResume
;
1161 /* Should we attempt to resume from hibernation? */
1162 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
1163 BcdBootMgrBoolean_AttemptResume
,
1165 if (!NT_SUCCESS(Status
))
1167 /* Nope. Is automatic restart on crash enabled? */
1168 AttemptResume
= FALSE
;
1169 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
1170 BcdOSLoaderBoolean_DisableCrashAutoReboot
,
1172 AttemptResume
= (NT_SUCCESS(Status
) && (AttemptResume
));
1175 /* Don't do anything if there's no need to resume anything */
1178 return STATUS_SUCCESS
;
1181 /* Not yet implemented */
1182 EfiPrintf(L
"Resume not supported\r\n");
1183 return STATUS_NOT_IMPLEMENTED
;
1187 BmpProcessBadMemory (
1191 BL_PD_DATA_BLOB BadMemoryData
;
1194 /* Try to get the memory data from the memtest application */
1195 BadMemoryData
.BlobSize
= 0;
1196 BadMemoryData
.Data
= NULL
;
1197 BadMemoryData
.DataSize
= 0;
1198 Status
= BlPdQueryData(&BadMemoryGuid
, NULL
, &BadMemoryData
);
1199 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1201 /* No results, or some other error */
1205 /* Not yet implemented */
1206 EfiPrintf(L
"Bad page list persistence not implemented\r\n");
1207 return STATUS_NOT_IMPLEMENTED
;
1212 _In_ HANDLE BcdHandle
,
1213 _In_ PGUID ObjectId
,
1217 HANDLE ObjectHandle
;
1220 /* Open the object */
1221 Status
= BcdOpenObject(BcdHandle
, ObjectId
, &ObjectHandle
);
1222 if (NT_SUCCESS(Status
))
1224 /* Delete the element */
1225 BcdDeleteElement(ObjectHandle
, Type
);
1227 /* Close the object and set success */
1228 BiCloseKey(ObjectHandle
);
1229 Status
= STATUS_SUCCESS
;
1232 /* Return the result */
1237 BmGetEntryDescription (
1238 _In_ HANDLE BcdHandle
,
1239 _In_ PGUID ObjectId
,
1240 _Out_ PBCD_OBJECT_DESCRIPTION Description
1244 HANDLE ObjectHandle
;
1246 /* Open the BCD object */
1247 Status
= BcdOpenObject(BcdHandle
, ObjectId
, &ObjectHandle
);
1248 if (NT_SUCCESS(Status
))
1250 /* Make sure the caller passed this argument in */
1253 /* Fail otherwise */
1254 Status
= STATUS_INVALID_PARAMETER
;
1258 /* Query the description from the BCD interface */
1259 Status
= BiGetObjectDescription(ObjectHandle
, Description
);
1262 /* Close the object key */
1263 BiCloseKey(ObjectHandle
);
1266 /* Return the result back */
1271 BmpPopulateBootEntryList (
1272 _In_ HANDLE BcdHandle
,
1273 _In_ PGUID SequenceList
,
1275 _Out_ PBL_LOADED_APPLICATION_ENTRY
* BootSequence
,
1276 _Out_ PULONG SequenceCount
1280 ULONG BootIndex
, i
, OptionSize
;
1281 PBL_LOADED_APPLICATION_ENTRY BootEntry
;
1282 PBL_BCD_OPTION Options
;
1283 BCD_OBJECT_DESCRIPTION Description
;
1284 BcdObjectType ObjectType
;
1285 BOOLEAN HavePath
, IsWinPe
, SoftReboot
;
1288 /* Initialize locals */
1291 Status
= STATUS_NOT_FOUND
;
1293 /* Loop through every element in the sequence */
1294 for (i
= 0; i
< *SequenceCount
; i
++)
1296 /* Assume failure */
1299 /* Get the options for the sequence element */
1300 Status
= BmGetOptionList(BcdHandle
, SequenceList
, &Options
);
1301 if (!NT_SUCCESS(Status
))
1303 EfiPrintf(L
"option list failed: %lx\r\n", Status
);
1307 /* Make sure there's at least a path and description */
1308 if (!(MiscGetBootOption(Options
, BcdLibraryDevice_ApplicationDevice
)) ||
1309 !(MiscGetBootOption(Options
, BcdLibraryString_Description
)))
1311 Status
= STATUS_UNSUCCESSFUL
;
1312 EfiPrintf(L
"missing list failed: %lx\r\n", Status
);
1316 /* Get the size of the BCD options and allocate a large enough entry */
1317 OptionSize
= BlGetBootOptionListSize(Options
);
1318 BootEntry
= BlMmAllocateHeap(sizeof(*BootEntry
) + OptionSize
);
1321 Status
= STATUS_NO_MEMORY
;
1325 /* Save it as part of the sequence */
1326 BootSequence
[BootIndex
] = BootEntry
;
1328 /* Initialize it, and copy the BCD data */
1329 RtlZeroMemory(BootEntry
, sizeof(*BootEntry
));
1330 BootEntry
->Guid
= *SequenceList
;
1331 BootEntry
->BcdData
= (PBL_BCD_OPTION
)(BootEntry
+ 1);
1332 BootEntry
->Flags
= Flags
;
1333 RtlCopyMemory(BootEntry
->BcdData
, Options
, OptionSize
);
1335 /* Get the object descriptor to find out what kind of entry it is */
1336 Status
= BmGetEntryDescription(BcdHandle
,
1339 if (!NT_SUCCESS(Status
))
1341 EfiPrintf(L
"missing desc failed: %lx\r\n", Status
);
1345 /* Check if a path was given or not */
1346 HavePath
= MiscGetBootOption(Options
, BcdLibraryString_ApplicationPath
) ?
1349 /* Now select based on what type of object this is -- must be an app */
1350 ObjectType
.PackedValue
= Description
.Type
;
1351 if (ObjectType
.Application
.ObjectCode
== BCD_OBJECT_TYPE_APPLICATION
)
1353 /* Then select based on what kind of app it is */
1354 switch (ObjectType
.Application
.ApplicationCode
)
1356 /* Another boot manager */
1357 case BCD_APPLICATION_TYPE_BOOTMGR
:
1358 BootEntry
->Flags
|= BCD_APPLICATION_TYPE_BOOTMGR
;
1362 case BCD_APPLICATION_TYPE_OSLOADER
:
1363 BootEntry
->Flags
|= BL_APPLICATION_ENTRY_WINLOAD
;
1365 /* Do we have a path for it? */
1368 /* We'll try to make one up. Is this WinPE? */
1370 Status
= BlGetBootOptionBoolean(Options
,
1371 BcdOSLoaderBoolean_WinPEMode
,
1373 if (!(NT_SUCCESS(Status
)) && (Status
!= STATUS_NOT_FOUND
))
1378 /* Use the appropriate path for WinPE or local install */
1379 LoaderPath
= IsWinPe
?
1380 L
"\\Windows\\System32\\boot\\winload.efi" :
1381 L
"\\Windows\\System32\\winload.efi";
1383 /* Add the path to the boot entry */
1384 Status
= BlAppendBootOptionString(BootEntry
, LoaderPath
);
1385 if (!NT_SUCCESS(Status
))
1390 /* We have a path now */
1395 /* A hibernate-resume application */
1396 case BCD_APPLICATION_TYPE_RESUME
:
1397 BootEntry
->Flags
|= BL_APPLICATION_ENTRY_WINRESUME
;
1400 /* An older OS NTLDR */
1401 case BCD_APPLICATION_TYPE_NTLDR
:
1402 BootEntry
->Flags
|= BL_APPLICATION_ENTRY_NTLDR
;
1405 /* An older OS SETUPLDR */
1406 case BCD_APPLICATION_TYPE_SETUPLDR
:
1407 BootEntry
->Flags
|= BL_APPLICATION_ENTRY_SETUPLDR
;
1410 /* A 3rd party/Win9x boot sector */
1411 case BCD_APPLICATION_TYPE_BOOTSECTOR
:
1412 BootEntry
->Flags
|= BL_APPLICATION_ENTRY_BOOTSECTOR
;
1415 /* Something else entirely */
1421 /* We better have a path by now */
1424 Status
= STATUS_UNSUCCESSFUL
;
1428 /* Check if this is a real mode startup.com */
1429 if ((ObjectType
.Application
.ObjectCode
== BCD_OBJECT_TYPE_APPLICATION
) &&
1430 (ObjectType
.Application
.ImageCode
= BCD_IMAGE_TYPE_REAL_MODE
) &&
1431 (ObjectType
.Application
.ApplicationCode
== BCD_APPLICATION_TYPE_STARTUPCOM
))
1433 /* Check if PXE soft reboot will occur */
1434 Status
= BlGetBootOptionBoolean(Options
,
1435 BcdStartupBoolean_PxeSoftReboot
,
1437 if ((NT_SUCCESS(Status
)) && (SoftReboot
))
1439 /* Then it's a valid startup.com entry */
1440 BootEntry
->Flags
|= BL_APPLICATION_ENTRY_STARTUP
;
1445 /* All done with this entry -- did we have BCD options? */
1448 /* Free them, they're part of the entry now */
1449 BlMmFreeHeap(Options
);
1453 /* Did we fail anywhere? */
1454 if (!NT_SUCCESS(Status
))
1456 /* Yep -- did we fail with an active boot entry? */
1460 BlDestroyBootEntry(BootEntry
);
1461 BootSequence
[BootIndex
] = NULL
;
1466 /* It worked, so populate the next index now */
1470 /* And move to the next GUID in the sequence list */
1475 /* All done now -- did we have any BCD options? */
1479 BlMmFreeHeap(Options
);
1482 /* Return the status */
1488 _In_ HANDLE BcdHandle
,
1489 _In_ PGUID SequenceList
,
1490 _In_ ULONG SequenceListCount
,
1492 _Out_ PBL_LOADED_APPLICATION_ENTRY
** BootSequence
,
1493 _Out_ PULONG SequenceCount
1496 PBL_LOADED_APPLICATION_ENTRY
* Sequence
;
1500 /* Allocate the sequence list */
1501 Sequence
= BlMmAllocateHeap(SequenceListCount
* sizeof(*Sequence
));
1504 return STATUS_NO_MEMORY
;
1507 /* Populate the sequence list */
1508 Status
= BmpPopulateBootEntryList(BcdHandle
,
1513 if (!NT_SUCCESS(Status
))
1515 /* Free the list on failure */
1516 BlMmFreeHeap(Sequence
);
1520 /* Otherwise, set success and return the list and count */
1521 Status
= STATUS_SUCCESS
;
1522 *BootSequence
= Sequence
;
1523 *SequenceCount
= Count
;
1531 BmEnumerateBootEntries (
1532 _In_ HANDLE BcdHandle
,
1533 _Out_ PBL_LOADED_APPLICATION_ENTRY
**BootSequence
,
1534 _Out_ PULONG SequenceCount
1538 ULONG BootIndex
, BootIniCount
, BootEntryCount
, BcdCount
;
1539 PBL_LOADED_APPLICATION_ENTRY
* Sequence
;
1542 BOOLEAN UseDisplayList
;
1544 /* Initialize locals */
1547 /* First try to get the display list, if any */
1548 UseDisplayList
= TRUE
;
1549 Status
= BlGetBootOptionGuidList(BlpApplicationEntry
.BcdData
,
1550 BcdBootMgrObjectList_DisplayOrder
,
1553 if (!NT_SUCCESS(Status
))
1555 /* No list, get the default entry instead */
1556 Status
= BlGetBootOptionGuid(BlpApplicationEntry
.BcdData
,
1557 BcdBootMgrObject_DefaultObject
,
1559 if (NT_SUCCESS(Status
))
1561 /* Set the array to just our entry */
1562 UseDisplayList
= FALSE
;
1564 DisplayOrder
= &DefaultObject
;
1568 /* No default list either, return success but no entries */
1569 *BootSequence
= NULL
;
1571 Status
= STATUS_SUCCESS
;
1572 DisplayOrder
= NULL
;
1577 /* Check if boot.ini was used */
1581 /* Get the entries from it */
1582 EfiPrintf(L
"Boot.ini not supported\r\n");
1583 BootIniCount
= 0;//BmBootIniGetEntryCount();
1586 /* Allocate an array large enough for the combined boot entries */
1587 BootEntryCount
= BootIniCount
+ BcdCount
;
1588 Sequence
= BlMmAllocateHeap(BootEntryCount
* sizeof(*Sequence
));
1591 Status
= STATUS_NO_MEMORY
;
1596 RtlZeroMemory(Sequence
, BootEntryCount
* sizeof(*Sequence
));
1598 /* Check if we had BCD entries */
1601 /* Populate the list of bootable entries */
1602 Status
= BmpPopulateBootEntryList(BcdHandle
,
1604 BL_APPLICATION_ENTRY_DISPLAY_ORDER
,
1607 if (!NT_SUCCESS(Status
))
1614 /* Check if we had boot.ini entries */
1618 EfiPrintf(L
"Boot.ini not supported\r\n");
1621 /* Return success and the sequence + count populated */
1622 Status
= STATUS_SUCCESS
;
1623 *BootSequence
= Sequence
;
1624 *SequenceCount
= BootIniCount
+ BcdCount
;
1627 /* Check if we had allocated a GUID list */
1628 if ((UseDisplayList
) && (DisplayOrder
))
1631 BlMmFreeHeap(DisplayOrder
);
1634 /* Check if this is the failure path */
1635 if (!(NT_SUCCESS(Status
)) && (Sequence
))
1637 /* Loop the remaining boot entries */
1638 while (BootIndex
< BootEntryCount
)
1640 /* Check if it had been allocated */
1641 if (Sequence
[BootIndex
])
1644 BlMmFreeHeap(Sequence
[BootIndex
]);
1651 /* Free the whole sequence now */
1652 BlMmFreeHeap(Sequence
);
1655 /* All done, return the result */
1660 BmpGetDefaultBootEntry (
1661 _In_ PBL_LOADED_APPLICATION_ENTRY
* Sequence
,
1663 _Out_ PBL_LOADED_APPLICATION_ENTRY
* DefaultEntry
,
1664 _Out_ PULONG DefaultIndex
1671 /* Assume no default */
1672 *DefaultEntry
= *Sequence
;
1675 /* Nothing to do if there's just one entry */
1681 /* Get the default object, bail out if there isn't one */
1682 Status
= BlGetBootOptionGuid(BlpApplicationEntry
.BcdData
,
1683 BcdBootMgrObject_DefaultObject
,
1685 if (!(NT_SUCCESS(Status
)) || !(Count
))
1690 /* Scan the boot sequence */
1691 for (BootIndex
= 0; BootIndex
< Count
; BootIndex
++)
1693 /* Find one that matches the default */
1694 if (RtlEqualMemory(&Sequence
[BootIndex
]->Guid
,
1699 *DefaultEntry
= Sequence
[BootIndex
];
1700 *DefaultIndex
= BootIndex
;
1707 BmGetBootMenuPolicy (
1708 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
1713 ULONGLONG BootMenuPolicy
;
1716 /* Check if EMS is enabled */
1717 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
1718 BcdOSLoaderBoolean_EmsEnabled
,
1720 if ((NT_SUCCESS(Status
)) && (EmsEnabled
))
1723 return MenuPolicyLegacy
;
1726 /* Check what entry we are looking at */
1729 /* No entry, pick the selected one */
1730 BootEntry
= BmpSelectedBootEntry
;
1733 /* Do we still not have an entry? */
1737 return MenuPolicyStandard
;
1740 /* Check if this is an OS loader */
1742 if (BootEntry
->Flags
& BL_APPLICATION_ENTRY_WINLOAD
)
1744 /* Use the correct option ID */
1745 OptionId
= BcdOSLoaderInteger_BootMenuPolicy
;
1749 /* Check if this is an OS resumer */
1750 if (!(BootEntry
->Flags
& BL_APPLICATION_ENTRY_WINRESUME
))
1752 /* Nope, so no reason for a menu */
1753 return MenuPolicyLegacy
;
1756 /* Use the correct opetion ID */
1757 OptionId
= BcdResumeInteger_BootMenuPolicy
;
1760 /* Check the option ID for the boot menu policy */
1761 Status
= BlGetBootOptionInteger(BootEntry
->BcdData
,
1764 if (NT_SUCCESS(Status
))
1766 /* We have one, return it */
1767 return BootMenuPolicy
;
1770 /* No policy, so assume no menu */
1771 return MenuPolicyLegacy
;
1775 BmDisplayGetBootMenuStatus (
1776 _Out_ PL_MENU_STATUS MenuStatus
1779 /* For now, don't support key input at all */
1780 MenuStatus
->AsULong
= 0;
1781 MenuStatus
->OemKey
= UNICODE_NULL
;
1782 MenuStatus
->BootIndex
= -1;
1786 BmProcessCustomAction (
1787 _In_ HANDLE BcdHandle
,
1788 _In_ PWCHAR ActionKey
1791 EfiPrintf(L
"Custom actions not yet handled\r\n");
1792 return STATUS_NOT_IMPLEMENTED
;
1796 BmpProcessBootEntry (
1797 _In_ HANDLE BcdHandle
,
1798 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
,
1799 _Out_ PBOOLEAN ExitBootManager
1802 BL_MENU_STATUS MenuStatus
;
1805 *ExitBootManager
= FALSE
;
1807 /* If the legacy menu must be shown, or if we have a boot entry */
1808 if ((BmGetBootMenuPolicy(BootEntry
) != MenuPolicyStandard
) || (BootEntry
))
1810 /* Check if any key has been presseed */
1811 BmDisplayGetBootMenuStatus(&MenuStatus
);
1812 if (MenuStatus
.AnyKey
)
1814 /* Was the exit key pressed? */
1815 if (MenuStatus
.Exit
)
1817 /* Don't display a menu, and exit */
1818 *ExitBootManager
= TRUE
;
1819 BmpDisplayBootMenu
= FALSE
;
1821 else if (MenuStatus
.OemKey
)
1823 /* Process the OEM key action */
1824 BmProcessCustomAction(BcdHandle
, &MenuStatus
.KeyValue
);
1828 /* Process other keys */
1829 EfiPrintf(L
"TODO\r\n");
1836 BmpGetSelectedBootEntry (
1837 _In_ HANDLE BcdHandle
,
1838 _Out_ PBL_LOADED_APPLICATION_ENTRY
* SelectedBootEntry
,
1839 _Out_ PULONG EntryIndex
,
1840 _Out_ PBOOLEAN ExitBootManager
1844 PBL_LOADED_APPLICATION_ENTRY
* Sequence
;
1845 PBL_LOADED_APPLICATION_ENTRY Entry
, SelectedEntry
;
1846 ULONG Count
, BootIndex
, SelectedIndex
;
1847 // BOOLEAN FoundFailedEntry;
1850 /* Initialize locals */
1854 SelectedEntry
= NULL
;
1856 /* Enumerate all the boot entries */
1857 Status
= BmEnumerateBootEntries(BcdHandle
, &Sequence
, &Count
);
1858 if (!NT_SUCCESS(Status
))
1860 /* Bail out if we failed */
1864 /* Check if there are no entries */
1867 /* This is fatal -- kill the system */
1868 Status
= STATUS_FILE_INVALID
;
1869 BmFatalErrorEx(BL_FATAL_ERROR_BCD_ENTRIES
, (ULONG_PTR
)L
"\\BCD", Status
, 0, 0);
1873 /* Check if we don't yet have an array of failed boot entries */
1874 if (!BmpFailedBootEntries
)
1877 BmpFailedBootEntries
= BlMmAllocateHeap(Count
);
1878 if (BmpFailedBootEntries
)
1881 RtlZeroMemory(BmpFailedBootEntries
, Count
);
1885 /* Check if we have a hardcoded boot override */
1886 if (BmBootEntryOverridePresent
)
1888 EfiPrintf(L
"Hard-coded boot override mode not supported\r\n");
1891 /* Log the OS count */
1892 //BlLogEtwWrite(BOOT_BOOTMGR_MULTI_OS_COUNT);
1894 /* Check if the display is already active and cached */
1895 if (!BmDisplayStateCached
)
1897 /* Check if we should display a boot menu */
1898 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
1899 BcdBootMgrBoolean_DisplayBootMenu
,
1900 &BmpDisplayBootMenu
);
1901 if (!NT_SUCCESS(Status
))
1904 BmpDisplayBootMenu
= FALSE
;
1908 /* Check if there's only one entry to boot anyway */
1912 SelectedEntry
= *Sequence
;
1915 BmpProcessBootEntry(BcdHandle
, SelectedEntry
, ExitBootManager
);
1917 /* Check if we're not displaying a boot menu */
1918 if (!BmpDisplayBootMenu
)
1921 BmpDisplayBootMenu
= TRUE
;
1923 /* Return the entry and its index back */
1925 *SelectedBootEntry
= SelectedEntry
;
1926 Status
= STATUS_SUCCESS
;
1932 /* Get the default boot entry */
1933 BmpGetDefaultBootEntry(Sequence
, Count
, &SelectedEntry
, &SelectedIndex
);
1935 /* Check if we have a failed boot entry array allocated */
1936 //FoundFailedEntry = FALSE;
1937 if (BmpFailedBootEntries
)
1939 /* Check if the default entry failed to boot */
1940 if (BmpFailedBootEntries
[SelectedIndex
])
1942 /* Loop through the current boot sequence */
1943 for (SelectedIndex
= 0; SelectedIndex
< Count
; SelectedIndex
++)
1945 /* Check if there's no sequence for this index, or it failed */
1946 while (!(Sequence
[SelectedIndex
]) ||
1947 (BmpFailedBootEntries
[SelectedIndex
]))
1949 /* Remember that this is a failed entry */
1950 SelectedEntry
= Sequence
[SelectedIndex
];
1951 //FoundFailedEntry = TRUE;
1952 BmpDisplayBootMenu
= FALSE
;
1958 /* Check if the entry is an OS loader */
1959 if (SelectedEntry
->Flags
& BL_APPLICATION_ENTRY_WINLOAD
)
1962 EfiPrintf(L
"todo path\r\n");
1965 /* Check if there's no timeout */
1966 Status
= BlGetBootOptionInteger(BlpApplicationEntry
.BcdData
,
1967 BcdBootMgrInteger_Timeout
,
1969 if ((NT_SUCCESS(Status
) && !(Timeout
)))
1971 /* There isn't, so just process the default entry right away */
1972 BmpProcessBootEntry(BcdHandle
, SelectedEntry
, ExitBootManager
);
1974 /* Check if we're not displaying a boot menu */
1975 if (!BmpDisplayBootMenu
)
1978 BmpDisplayBootMenu
= TRUE
;
1980 /* Return the entry and its index back */
1982 *SelectedBootEntry
= SelectedEntry
;
1983 Status
= STATUS_SUCCESS
;
1987 /* Remove the timeout for this boot instance */
1988 BlRemoveBootOption(BlpApplicationEntry
.BcdData
,
1989 BcdBootMgrInteger_Timeout
);
1993 /* Here is where we display the menu and list of tools */
1994 EfiPrintf(L
"Tool selection not yet implemented\r\n");
1996 *SelectedBootEntry
= NULL
;
1999 /* We are done -- did we have a sequence? */
2002 /* Do we have any boot entries we parsed? */
2003 while (BootIndex
< Count
)
2005 /* Get the current boot entry */
2006 Entry
= Sequence
[BootIndex
];
2008 /* Did we fail, or is is not the selected one? */
2009 if ((Entry
) && ((Entry
!= SelectedEntry
) || !(NT_SUCCESS(Status
))))
2011 /* Destroy it, as it won't be needed */
2012 BlDestroyBootEntry(Entry
);
2014 else if (Entry
== SelectedEntry
)
2016 /* It's the selected one, return its index */
2017 *EntryIndex
= BootIndex
;
2020 /* Move to the next entry */
2024 /* Free the sequence of entries */
2025 BlMmFreeHeap(Sequence
);
2028 /* Return the selection result */
2033 BmpLaunchBootEntry (
2034 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
,
2035 _Out_ PULONG EntryIndex
,
2036 _In_ ULONG LaunchCode
,
2037 _In_ BOOLEAN LaunchWinRe
2041 BmLaunchRecoverySequence (
2042 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
,
2043 _In_ ULONG LaunchCode
2047 PBL_LOADED_APPLICATION_ENTRY RecoveryEntry
;
2049 PGUID RecoverySequence
;
2050 ULONG Count
, i
, RecoveryIndex
, SequenceCount
;
2051 PBL_LOADED_APPLICATION_ENTRY
* Sequence
;
2055 RecoverySequence
= NULL
;
2059 Status
= BmOpenDataStore(&BcdHandle
);
2060 if (NT_SUCCESS(Status
))
2062 Status
= BlGetBootOptionGuidList(BootEntry
->BcdData
,
2063 BcdLibraryObjectList_RecoverySequence
,
2066 if (NT_SUCCESS(Status
))
2068 Status
= BmGetBootSequence(BcdHandle
,
2071 BL_APPLICATION_ENTRY_RECOVERY
,
2074 if (NT_SUCCESS(Status
))
2078 BmCloseDataStore(BcdHandle
);
2081 for (i
= 0; i
< Count
; ++i
)
2083 if (LaunchCode
== 2 || LaunchCode
== 5)
2085 BlRemoveBootOption(Sequence
[i
]->BcdData
, BcdLibraryInteger_DisplayMessageOverride
);
2086 BlAppendBootOptionInteger(Sequence
[i
],
2087 BcdLibraryInteger_DisplayMessageOverride
,
2090 else if (LaunchCode
== 3)
2092 BlRemoveBootOption(Sequence
[i
]->BcdData
, BcdLibraryInteger_DisplayMessageOverride
);
2093 BlAppendBootOptionInteger(Sequence
[i
],
2094 BcdLibraryInteger_DisplayMessageOverride
,
2098 Status
= BmpLaunchBootEntry(Sequence
[i
], NULL
, LaunchCode
, FALSE
);
2099 if (!NT_SUCCESS(Status
))
2108 for (RecoveryIndex
= 0; RecoveryIndex
< Count
; RecoveryIndex
++)
2110 RecoveryEntry
= Sequence
[RecoveryIndex
];
2113 BlDestroyBootEntry(RecoveryEntry
);
2116 BlMmFreeHeap(Sequence
);
2120 if (RecoverySequence
)
2122 BlMmFreeHeap(RecoverySequence
);
2130 BmDisplayDumpError (
2131 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
,
2132 _In_ ULONG LaunchCode
2137 BOOLEAN Restart
, NoError
;
2141 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
2142 BcdLibraryBoolean_RestartOnFailure
,
2144 if ((NT_SUCCESS(Status
)) && (Restart
))
2149 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
2150 BcdBootMgrBoolean_NoErrorDisplay
,
2152 if ((NT_SUCCESS(Status
)) && (NoError
))
2157 if (BmpInternalBootError
)
2159 return (ULONG
)BmpInternalBootError
; // ???
2162 EfiPrintf(L
"Error menu not yet implemented\r\n");
2168 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
2171 ULONG NextOffset
, DataOffset
, ListOffset
;
2172 PBL_BCD_OPTION Option
, ListOption
;
2173 BcdElementType ElementType
;
2174 PBCD_DEVICE_OPTION BcdDevice
;
2179 Option
= (PBL_BCD_OPTION
)((ULONG_PTR
)BootEntry
->BcdData
+ NextOffset
);
2180 NextOffset
= Option
->NextEntryOffset
;
2187 ElementType
.PackedValue
= Option
->Type
;
2188 if (ElementType
.Format
!= BCD_TYPE_DEVICE
)
2193 DataOffset
= Option
->DataOffset
;
2195 BcdDevice
= (PBCD_DEVICE_OPTION
)((ULONG_PTR
)BootEntry
->BcdData
+ DataOffset
);
2196 if (!(BcdDevice
->DeviceDescriptor
.Flags
& 1))
2202 ListOffset
= Option
->ListOffset
;
2203 if (Option
->ListOffset
)
2205 ListOption
= (PBL_BCD_OPTION
)((ULONG_PTR
)BootEntry
->BcdData
+ ListOffset
);
2208 EfiPrintf(L
"Unspecified devices not yet supported: %p\r\n", ListOption
);
2209 return STATUS_NOT_SUPPORTED
;
2210 } while (NextOffset
!= 0);
2212 return STATUS_SUCCESS
;
2215 /* MOVE TO IMAGe.C */
2217 BlImgLoadBootApplication (
2218 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
,
2219 _Out_ PHANDLE AppHandle
2222 EfiPrintf(L
"Loading application %p\r\n", BootEntry
);
2224 return STATUS_NOT_IMPLEMENTED
;
2228 BlImgStartBootApplication (
2229 _In_ HANDLE AppHandle
,
2230 _Inout_ PBL_RETURN_ARGUMENTS ReturnArguments
2233 EfiPrintf(L
"Starting application %p\r\n", AppHandle
);
2235 return STATUS_NOT_IMPLEMENTED
;
2239 BlImgUnloadBootApplication (
2240 _In_ HANDLE AppHandle
2243 EfiPrintf(L
"Unloading application %p\r\n", AppHandle
);
2245 return STATUS_NOT_IMPLEMENTED
;
2249 BmpTransferExecution (
2250 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
,
2251 _Out_ PULONG LaunchCode
,
2252 _Out_ PBOOLEAN Recover
2257 PBL_DEVICE_DESCRIPTOR AppDevice
;
2258 BL_RETURN_ARGUMENTS ReturnArgs
;
2259 BOOLEAN AdvancedOptions
;
2262 Status
= BlGetBootOptionString(BootEntry
->BcdData
,
2263 BcdLibraryString_ApplicationPath
,
2265 if (!NT_SUCCESS(Status
))
2270 if (BootEntry
->Flags
& BL_APPLICATION_ENTRY_STARTUP
)
2273 Status
= BlNetSoftReboot(BootEntry
);
2275 EfiPrintf(L
"Net boot not supported\r\n");
2276 Status
= STATUS_NOT_SUPPORTED
;
2283 Status
= BlImgLoadBootApplication(BootEntry
, &AppHandle
);
2284 if (Status
== STATUS_NOT_FOUND
)
2286 Status
= BlGetBootOptionDevice(BootEntry
->BcdData
,
2287 BcdLibraryDevice_ApplicationDevice
,
2290 if (NT_SUCCESS(Status
))
2292 Status
= BlFwEnumerateDevice(AppDevice
);
2295 if (!NT_SUCCESS(Status
))
2297 BmFatalErrorEx(2, (ULONG_PTR
)AppPath
, Status
, 0, 0);
2301 Status
= BlImgLoadBootApplication(BootEntry
, &AppHandle
);
2304 if (Status
== STATUS_CANCELLED
)
2306 if ((BmGetBootMenuPolicy(BootEntry
) != MenuPolicyStandard
) ||
2307 !(MiscGetBootOption(BootEntry
->BcdData
,
2308 BcdLibraryObjectList_RecoverySequence
)))
2318 if (Status
== 0xC0210000)
2325 if (!NT_SUCCESS(Status
))
2327 BmFatalErrorEx(2, (ULONG_PTR
)AppPath
, Status
, 0, 0);
2331 RtlZeroMemory(&ReturnArgs
, sizeof(ReturnArgs
));
2332 //BmpLogApplicationLaunchEvent(&BootEntry->Guid, AppPath);
2334 Status
= BlImgStartBootApplication(AppHandle
, &ReturnArgs
);
2336 #if BL_BITLOCKER_SUPPORT
2337 BlFveSecureBootCheckpointAppReturn(BootEntry
, &ReturnArgs
);
2340 //BlBsdLogEntry(1, 0x12, &BootEntry->Guid, 0x14);
2342 BlImgUnloadBootApplication(AppHandle
);
2344 } while (Status
!= 0xC0000453);
2347 if (ReturnArgs
.Flags
& 1)
2349 Status
= BlGetBootOptionBoolean(BootEntry
->BcdData
,
2350 BcdLibraryBoolean_DisplayAdvancedOptions
,
2352 if ((NT_SUCCESS(Status
)) && (AdvancedOptions
))
2361 else if (ReturnArgs
.Flags
& 4)
2365 else if (ReturnArgs
.Flags
& 8)
2369 else if (ReturnArgs
.Flags
& 0x10)
2373 else if (ReturnArgs
.Flags
& 0x20)
2377 else if (ReturnArgs
.Flags
& 0x40)
2380 BmFatalErrorEx(11, Status
, 0, 0, 0);
2386 BlMmFreeHeap(AppPath
);
2393 BmpLaunchBootEntry (
2394 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
,
2395 _Out_ PULONG EntryIndex
,
2396 _In_ ULONG LaunchCode
,
2397 _In_ BOOLEAN LaunchWinRe
2403 BOOLEAN DoRecovery
, AutoRecovery
, DoRestart
, RestartOnFailure
;
2405 BOOLEAN AdvancedOneTime
, EditOneTime
, Recover
;
2407 if (BootEntry
->Flags
& BL_APPLICATION_ENTRY_WINLOAD
)
2409 if (MiscGetBootOption(BootEntry
->BcdData
, BcdOSLoaderBoolean_AdvancedOptionsOneTime
))
2412 Status
= BmOpenDataStore(BcdHandle
);
2413 if (NT_SUCCESS(Status
))
2415 ObjectId
= BootEntry
->Guid
;
2416 BmPurgeOption(BcdHandle
, &ObjectId
, BcdOSLoaderBoolean_AdvancedOptionsOneTime
);
2417 BmCloseDataStore(BcdHandle
);
2420 if (MiscGetBootOption(BootEntry
->BcdData
, BcdOSLoaderBoolean_OptionsEditOneTime
))
2423 Status
= BmOpenDataStore(BcdHandle
);
2424 if (NT_SUCCESS(Status
))
2426 ObjectId
= BootEntry
->Guid
;
2427 BmPurgeOption(BcdHandle
, &ObjectId
, BcdOSLoaderBoolean_OptionsEditOneTime
);
2428 BmCloseDataStore(BcdHandle
);
2436 BmpSelectedBootEntry
= BootEntry
;
2438 Status
= BmpCreateDevices(BootEntry
);
2439 if (!NT_SUCCESS(Status
))
2450 if (BootEntry
->Flags
& BL_APPLICATION_ENTRY_WINLOAD
)
2452 Status
= BlGetBootOptionBoolean(BootEntry
->BcdData
, BcdOSLoaderBoolean_AdvancedOptionsOneTime
, &AdvancedOneTime
);
2453 if (NT_SUCCESS(Status
))
2455 if (AdvancedOneTime
)
2457 BlAppendBootOptionBoolean(BootEntry
, BcdLibraryBoolean_DisplayAdvancedOptions
);
2461 BlRemoveBootOption(BootEntry
->BcdData
, BcdLibraryBoolean_DisplayAdvancedOptions
);
2464 BlRemoveBootOption(BootEntry
->BcdData
, BcdOSLoaderBoolean_AdvancedOptionsOneTime
);
2467 Status
= BlGetBootOptionBoolean(BootEntry
->BcdData
, BcdOSLoaderBoolean_OptionsEditOneTime
, &EditOneTime
);
2468 if (NT_SUCCESS(Status
))
2470 if (AdvancedOneTime
)
2472 BlAppendBootOptionBoolean(BootEntry
, BcdLibraryBoolean_DisplayOptionsEdit
);
2476 BlRemoveBootOption(BootEntry
->BcdData
, BcdLibraryBoolean_DisplayOptionsEdit
);
2479 BlRemoveBootOption(BootEntry
->BcdData
, BcdOSLoaderBoolean_OptionsEditOneTime
);
2483 Status
= BmpTransferExecution(BootEntry
, &LaunchCode
, &Recover
);
2489 DoRecovery
= Recover
;
2491 if (((NT_SUCCESS(Status
)) || (Status
== STATUS_CANCELLED
)) && !(Recover
))
2503 if (MiscGetBootOption(BootEntry
->BcdData
, BcdLibraryObjectList_RecoverySequence
))
2505 if ((LaunchCode
== 3) || (LaunchCode
== 5) || (LaunchCode
== 6))
2507 Status
= BlGetBootOptionBoolean(BootEntry
->BcdData
, BcdLibraryBoolean_AutoRecoveryEnabled
, &AutoRecovery
);
2508 if (NT_SUCCESS(Status
))
2510 DoRecovery
= AutoRecovery
;
2519 RestartOnFailure
= FALSE
;
2520 BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
, BcdLibraryBoolean_RestartOnFailure
, &RestartOnFailure
);
2521 DoRestart
= RestartOnFailure
? FALSE
: DoRecovery
;
2528 //BlFveRegisterBootEntryForTrustedWimBoot(BootEntry, TRUE);
2531 Status
= BmLaunchRecoverySequence(BootEntry
, LaunchCode
);
2535 //BlFveRegisterBootEntryForTrustedWimBoot(BootEntry, FALSE);
2536 AutoRecovery
= FALSE
;
2539 if (NT_SUCCESS(Status
))
2541 return STATUS_SUCCESS
;
2544 BlRemoveBootOption(BootEntry
->BcdData
, BcdLibraryObjectList_RecoverySequence
);
2547 if (!BmpInternalBootError
)
2549 BmFatalErrorEx(4, Status
, 0, 0, 0);
2552 ErrorCode
= BmDisplayDumpError(BootEntry
, LaunchCode
);
2562 return STATUS_CANCELLED
;
2564 Status
= BmOpenDataStore(BcdHandle
);
2565 if (NT_SUCCESS(Status
))
2567 Status
= BmProcessCustomAction(BcdHandle
, NULL
);
2571 BmCloseDataStore(BcdHandle
);
2575 BlAppendBootOptionBoolean(BootEntry
, BcdOSLoaderBoolean_AdvancedOptionsOneTime
);
2578 BlAppendBootOptionBoolean(BootEntry
, BcdOSLoaderBoolean_OptionsEditOneTime
);
2585 return STATUS_CANCELLED
;
2591 return STATUS_SUCCESS
;
2597 * The BmMain function implements the Windows Boot Application entrypoint for
2600 * @param BootParameters
2601 * Pointer to the Boot Application Parameter Block.
2603 * @return NT_SUCCESS if the image was loaded correctly, relevant error code
2609 _In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters
2612 NTSTATUS Status
, LibraryStatus
;
2613 BL_LIBRARY_PARAMETERS LibraryParameters
;
2614 PBL_RETURN_ARGUMENTS ReturnArguments
;
2615 PGUID AppIdentifier
;
2616 HANDLE BcdHandle
, ResumeBcdHandle
;
2617 PBL_BCD_OPTION EarlyOptions
;
2619 BOOLEAN XmlLoaded
, DisableIntegrity
, TestSigning
, PersistBootSequence
;
2620 BOOLEAN RebootOnError
, CustomActions
;
2622 PBL_LOADED_APPLICATION_ENTRY BootEntry
;
2624 ULONG SequenceListCount
;
2625 PBL_LOADED_APPLICATION_ENTRY
* BootSequence
;
2627 BOOLEAN ExitBootManager
;
2630 ULONG SequenceCount
;
2632 EfiPrintf(L
"ReactOS UEFI Boot Manager Initializing...\r\n");
2634 /* Reading the BCD can change this later on */
2635 RebootOnError
= FALSE
;
2637 /* Save the start/end-of-POST time */
2638 ApplicationStartTime
= __rdtsc();
2639 PostTime
= ApplicationStartTime
;
2641 /* Setup the boot library parameters for this application */
2642 BlSetupDefaultParameters(&LibraryParameters
);
2643 LibraryParameters
.TranslationType
= BlNone
;
2644 LibraryParameters
.LibraryFlags
= 0x400 | 0x8;
2645 LibraryParameters
.MinimumAllocationCount
= 16;
2646 LibraryParameters
.MinimumHeapSize
= 512 * 1024;
2648 /* Initialize the boot library */
2649 Status
= BlInitializeLibrary(BootParameters
, &LibraryParameters
);
2650 if (!NT_SUCCESS(Status
))
2652 /* Check for failure due to invalid application entry */
2653 if (Status
!= STATUS_INVALID_PARAMETER_9
)
2655 /* Specifically print out what happened */
2656 EfiPrintf(L
"BlInitializeLibrary failed 0x%x\r\n", Status
);
2659 /* Go to exit path */
2663 /* Get the application identifier */
2664 AppIdentifier
= BlGetApplicationIdentifier();
2667 /* None was given, so set our default one */
2668 AppIdentifier
= (PGUID
)&GUID_WINDOWS_BOOTMGR
;
2671 /* Save our identifier */
2672 BmApplicationIdentifier
= *AppIdentifier
;
2674 /* Initialize the file system to open a handle to our root boot directory */
2675 BmFwInitializeBootDirectoryPath();
2677 /* Load and initialize the boot configuration database (BCD) */
2678 Status
= BmOpenDataStore(&BcdHandle
);
2679 if (NT_SUCCESS(Status
))
2681 /* Copy the boot options */
2682 Status
= BlCopyBootOptions(BlpApplicationEntry
.BcdData
, &EarlyOptions
);
2683 if (NT_SUCCESS(Status
))
2686 Status
= BmpUpdateApplicationOptions(BcdHandle
);
2687 if (!NT_SUCCESS(Status
))
2689 /* Log a fatal error */
2690 BmFatalErrorEx(BL_FATAL_ERROR_BCD_PARSE
,
2691 (ULONG_PTR
)L
"\\BCD",
2700 /* Initialize the secure boot machine policy */
2701 Status
= BmSecureBootInitializeMachinePolicy();
2702 if (!NT_SUCCESS(Status
))
2704 BmFatalErrorEx(BL_FATAL_ERROR_SECURE_BOOT
, Status
, 0, 0, 0);
2708 /* Copy the library parameters and add the re-initialization flag */
2709 RtlCopyMemory(&LibraryParameters
,
2710 &BlpLibraryParameters
,
2711 sizeof(LibraryParameters
));
2712 LibraryParameters
.LibraryFlags
|= (BL_LIBRARY_FLAG_REINITIALIZE_ALL
|
2713 BL_LIBRARY_FLAG_REINITIALIZE
);
2715 /* Now that we've parsed the BCD, re-initialize the library */
2716 LibraryStatus
= BlInitializeLibrary(BootParameters
, &LibraryParameters
);
2717 if (!NT_SUCCESS(LibraryStatus
) && (NT_SUCCESS(Status
)))
2719 Status
= LibraryStatus
;
2722 /* Initialize firmware-specific memory regions */
2723 BmFwMemoryInitialize();
2725 /* Initialize the boot status data log (BSD) */
2726 BmpInitializeBootStatusDataLog();
2728 /* Find our XSL stylesheet */
2729 Stylesheet
= BlResourceFindHtml();
2732 /* Awe, no XML. This is actually fatal lol. Can't boot without XML. */
2733 Status
= STATUS_NOT_FOUND
;
2734 EfiPrintf(L
"BlResourceFindMessage failed 0x%x\r\n", STATUS_NOT_FOUND
);
2738 /* Initialize the XML Engine (as a side-effect, resets cursor) */
2739 Status
= BlXmiInitialize(Stylesheet
);
2740 if (!NT_SUCCESS(Status
))
2742 EfiPrintf(L
"\r\nBlXmiInitialize failed 0x%x\r\n", Status
);
2747 /* Check if there's an active bitmap visible */
2748 if (!BlDisplayValidOemBitmap())
2750 /* Nope, make the screen black using BGFX */
2751 if (!NT_SUCCESS(BmpBgDisplayClearScreen(0xFF000000)))
2753 /* BGFX isn't active, use standard display */
2754 BlDisplayClearScreen();
2759 /* Bitlocker will take over screen UI if enabled */
2760 FveDisplayScreen
= BmFveDisplayScreen
;
2763 /* Check if any bypass options are enabled */
2764 BlImgQueryCodeIntegrityBootOptions(&BlpApplicationEntry
,
2767 if (!DisableIntegrity
)
2769 /* Integrity checks are enabled, so validate our signature */
2770 Status
= BmFwVerifySelfIntegrity();
2771 if (!NT_SUCCESS(Status
))
2773 /* Signature invalid, fail boot */
2778 /* Write out the first XML tag */
2779 BlXmiWrite(L
"<bootmgr/>");
2781 /* Check for factory resset */
2782 BlSecureBootCheckForFactoryReset();
2784 /* Load the revocation list */
2785 Status
= BmFwRegisterRevocationList();
2786 if (!NT_SUCCESS(Status
))
2791 /* Register our custom progress routine */
2792 BlUtlRegisterProgressRoutine();
2794 /* Display state is not currently cached */
2795 BmDisplayStateCached
= FALSE
;
2797 /* Check if we need to resume from hibernate */
2798 Status
= BmResumeFromHibernate(&ResumeBcdHandle
);
2799 if (!NT_SUCCESS(Status
))
2804 #ifdef BL_NET_SUPPORT
2805 /* Register multicast printing routine */
2806 BlUtlRegisterMulticastRoutine();
2809 /* Check if restart on failure is enabled */
2810 BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
2811 BcdLibraryBoolean_RestartOnFailure
,
2814 /* Check if the boot sequence is persisted */
2815 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
2816 BcdBootMgrBoolean_PersistBootSequence
,
2817 &PersistBootSequence
);
2818 if (!NT_SUCCESS(Status
))
2821 PersistBootSequence
= TRUE
;
2824 /* Check if there's custom actions to take */
2825 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
2826 BcdBootMgrBoolean_ProcessCustomActionsFirst
,
2828 if ((NT_SUCCESS(Status
)) && (CustomActions
))
2830 /* We don't suppport this yet */
2831 EfiPrintf(L
"Not implemented\r\n");
2832 Status
= STATUS_NOT_IMPLEMENTED
;
2836 /* At last, enter the boot selection stage */
2840 SequenceList
= NULL
;
2841 BootSequence
= NULL
;
2845 /* We don't have a boot entry nor a sequence ID */
2849 /* Do we have a hardcoded boot sequence set? */
2850 if (!(BootSequence
) && !(GetEntry
))
2852 /* Not yet, read the BCD to see if one is there */
2853 Status
= BlGetBootOptionGuidList(BlpApplicationEntry
.BcdData
,
2854 BcdBootMgrObjectList_BootSequence
,
2856 &SequenceListCount
);
2857 if (NT_SUCCESS(Status
))
2859 /* A GUID list for the boot sequence is set. Extract it */
2860 Status
= BmGetBootSequence(BcdHandle
,
2863 BL_APPLICATION_ENTRY_FIXED_SEQUENCE
,
2866 if (NT_SUCCESS(Status
))
2868 /* Don't get stuck in a loop repeating this sequence */
2869 BlRemoveBootOption(BlpApplicationEntry
.BcdData
,
2870 BcdBootMgrObjectList_BootSequence
);
2872 /* But do check if we should persist it */
2873 if (PersistBootSequence
)
2875 /* Yes -- so go select an entry now */
2880 /* We shouldn't, so wipe it from the BCD too */
2881 Status
= BmPurgeOption(BcdHandle
,
2882 &BmApplicationIdentifier
,
2883 BcdBootMgrObjectList_BootSequence
);
2884 if (!NT_SUCCESS(Status
))
2886 /* Well that failed */
2894 /* No boot entry sequence for us */
2895 BootSequence
= NULL
;
2899 /* Do we have a sequence active, and are we still processing it? */
2900 if ((BootSequence
) && ((GetEntry
) || (SequenceId
< SequenceCount
)))
2902 /* Extract the next entry in the sequence */
2903 BootEntry
= BootSequence
[SequenceId
];
2904 BootSequence
[SequenceId
] = NULL
;
2906 /* Move to the next entry for next time */
2909 /* Unless there won't be a a next time? */
2910 if (SequenceId
== SequenceCount
)
2912 /* Clean up, it's the last entry */
2913 BlMmFreeHeap(BootSequence
);
2914 BootSequence
= NULL
;
2919 /* Get the selected boot entry from the user */
2920 ExitBootManager
= FALSE
;
2921 Status
= BmpGetSelectedBootEntry(BcdHandle
,
2925 if (!(NT_SUCCESS(Status
)) || (ExitBootManager
))
2927 /* Selection failed, or user wants to exit */
2932 /* Did we have a BCD open? */
2935 /* Close it, we'll be opening a new one */
2936 BmCloseDataStore(BcdHandle
);
2940 /* Launch the selected entry */
2941 Status
= BmpLaunchBootEntry(BootEntry
, &BootIndex
, 0, TRUE
);
2942 if (NT_SUCCESS(Status
))
2944 /* Boot worked, uncache display and process the bad memory list */
2945 BmDisplayStateCached
= FALSE
;
2946 BmpProcessBadMemory();
2950 /* Boot failed -- was it user driven? */
2951 if (Status
!= STATUS_CANCELLED
)
2953 /* Nope, remember that booting failed */
2958 /* Yes -- the display is still valid */
2959 BmDisplayStateCached
= TRUE
;
2962 /* Reopen the BCD */
2963 Status
= BmOpenDataStore(&BcdHandle
);
2964 if (!NT_SUCCESS(Status
))
2969 /* Put the BCD options back into our entry */
2970 BlReplaceBootOptions(&BlpApplicationEntry
, EarlyOptions
);
2972 /* Update our options one more time */
2973 Status
= BmpUpdateApplicationOptions(BcdHandle
);
2974 if (NT_SUCCESS(Status
))
2976 /* Boot was 100% OK */
2981 /* Did we have a boot entry? */
2984 /* We can destroy it now */
2985 BlDestroyBootEntry(BootEntry
);
2988 /* Is this the success path? */
2989 if (NT_SUCCESS(Status
))
2991 /* Did we actually boot something? */
2994 /* Bope, fail out */
2999 /* This is the failure path... should we reboot? */
3009 /* Check if we got here due to an internal error */
3010 if (BmpInternalBootError
)
3012 /* If XML is available, display the error */
3015 //BmDisplayDumpError(0, 0);
3019 /* Don't do a fatal error -- return back to firmware */
3024 /* Log a general fatal error once we're here */
3025 BmFatalErrorEx(BL_FATAL_ERROR_GENERIC
, Status
, 0, 0, 0);
3028 /* Check if we should reboot */
3029 if ((RebootOnError
) ||
3030 (BlpApplicationEntry
.Flags
& BL_APPLICATION_ENTRY_REBOOT_ON_ERROR
))
3032 /* Reboot the box */
3034 Status
= STATUS_SUCCESS
;
3038 /* Return back to the caller with the error argument encoded */
3039 ReturnArguments
= (PVOID
)((ULONG_PTR
)BootParameters
+ BootParameters
->ReturnArgumentsOffset
);
3040 ReturnArguments
->Version
= BL_RETURN_ARGUMENTS_VERSION
;
3041 ReturnArguments
->Status
= Status
;
3043 /* Tear down the boot library */
3047 /* Return back status */