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_PARSE
:
555 /* File name isin 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
"\nThe boot configuration file %s is invalid (%08x).\n",
567 /* Select the resource ID message */
568 ErrorResourceId
= 9015;
571 case BL_FATAL_ERROR_GENERIC
:
573 /* The NTSTATUS code is in parameter 1*/
574 ErrorStatus
= (NTSTATUS
)Parameter1
;
576 /* Build the error string */
577 swprintf(FormatString
,
578 L
"\nThe boot manager experienced an error (%08x).\n",
581 /* Select the resource ID message */
582 ErrorResourceId
= 9005;
587 /* The rest is not yet handled */
588 EfiPrintf(L
"Unexpected fatal error: %lx\n", ErrorCode
);
593 /* Check if the BCD option for restart is set */
594 BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
595 BcdLibraryBoolean_RestartOnFailure
,
599 /* Yes, so no error should be shown since we'll auto-restart */
604 /* Check if the option for not showing errors is set in the BCD */
605 BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
606 BcdBootMgrBoolean_NoErrorDisplay
,
610 /* Do we want an error? */
613 /* Yep, print it and then raise an error */
614 BlStatusPrint(FormatString
);
615 BlStatusError(1, ErrorCode
, Parameter1
, Parameter2
, Parameter3
);
618 /* Get the help message ID */
619 ErrorHelpId
= BmpFatalErrorMessageFilter(ErrorStatus
, &ErrorResourceId
);
620 BmpErrorLog(ErrorCode
, ErrorStatus
, ErrorResourceId
, Buffer
, ErrorHelpId
);
625 _In_ PWCHAR FileName
,
626 _Out_ PWCHAR
* FullPath
630 ULONG BootDirLength
, PathLength
;
632 /* Compute the length of the directory, and add a NUL */
633 BootDirLength
= wcslen(BootDirectory
);
634 Status
= RtlULongAdd(BootDirLength
, 1, &BootDirLength
);
635 if (!NT_SUCCESS(Status
))
640 /* Add the length of the file, make sure it fits */
641 PathLength
= wcslen(FileName
);
642 Status
= RtlULongAdd(PathLength
, BootDirLength
, &PathLength
);
643 if (!NT_SUCCESS(Status
))
648 /* Convert to bytes */
649 Status
= RtlULongLongToULong(PathLength
* sizeof(WCHAR
), &PathLength
);
650 if (!NT_SUCCESS(Status
))
655 /* Allocate the full path */
656 *FullPath
= BlMmAllocateHeap(PathLength
);
659 /* Copy the directory followed by the file name */
660 wcsncpy(*FullPath
, BootDirectory
, PathLength
/ sizeof(WCHAR
));
661 wcsncat(*FullPath
, FileName
, PathLength
/ sizeof(WCHAR
));
665 /* Bail out since we have no memory */
666 Status
= STATUS_NO_MEMORY
;
670 /* Return to caller */
679 /* Check if boot.ini data needs to be freed */
682 EfiPrintf(L
"Not handled\r\n");
685 /* Dereference the hive and close the key */
686 BiDereferenceHive(Handle
);
696 PBL_DEVICE_DESCRIPTOR BcdDevice
;
697 PWCHAR BcdPath
, FullPath
, PathBuffer
;
699 ULONG PathLength
, FullSize
;
701 UNICODE_STRING BcdString
;
703 /* Initialize variables */
709 /* Check if a boot.ini file exists */
710 Status
= BmOpenBootIni();
711 if (NT_SUCCESS(Status
))
713 BmBootIniUsed
= TRUE
;
716 /* Check on which device the BCD is */
717 Status
= BlGetBootOptionDevice(BlpApplicationEntry
.BcdData
,
718 BcdBootMgrDevice_BcdDevice
,
721 if (!NT_SUCCESS(Status
))
723 /* It's not on a custom device, so it must be where we are */
724 Status
= BlGetBootOptionDevice(BlpApplicationEntry
.BcdData
,
725 BcdLibraryDevice_ApplicationDevice
,
728 if (!NT_SUCCESS(Status
))
730 /* This BCD option is required */
735 /* Next, check what file contains the BCD */
736 Status
= BlGetBootOptionString(BlpApplicationEntry
.BcdData
,
737 BcdBootMgrString_BcdFilePath
,
739 if (NT_SUCCESS(Status
))
741 /* We don't handle custom BCDs yet */
742 EfiPrintf(L
"Not handled: %s\r\n", BcdPath
);
743 Status
= STATUS_NOT_IMPLEMENTED
;
747 /* Now check if the BCD is on a remote share */
748 if (BcdDevice
->DeviceType
== UdpDevice
)
750 /* Nope. Nope. Nope */
751 EfiPrintf(L
"Not handled\n");
752 Status
= STATUS_NOT_IMPLEMENTED
;
756 /* Otherwise, compute the hardcoded path of the BCD */
757 Status
= BmpFwGetFullPath(L
"\\BCD", &FullPath
);
758 if (!NT_SUCCESS(Status
))
760 /* User the raw path */
761 PathBuffer
= BcdPath
;
765 /* Use the path we got */
766 PathBuffer
= FullPath
;
770 /* Check if we failed to get the BCD path */
771 if (!NT_SUCCESS(Status
))
776 /* Add a NUL to the path, make sure it'll fit */
777 PathLength
= wcslen(PathBuffer
);
778 Status
= RtlULongAdd(PathLength
, 1, &PathLength
);
779 if (!NT_SUCCESS(Status
))
784 /* Convert to bytes */
785 Status
= RtlULongLongToULong(PathLength
* sizeof(WCHAR
), &PathLength
);
786 if (!NT_SUCCESS(Status
))
791 /* Now add the size of the path to the device path, check if it fits */
792 Status
= RtlULongAdd(PathLength
, BcdDevice
->Size
, &FullSize
);
793 if (!NT_SUCCESS(Status
))
798 /* Allocate a final structure to hold both entities */
799 FinalBuffer
= BlMmAllocateHeap(FullSize
);
802 Status
= STATUS_NO_MEMORY
;
806 /* Copy the device path and file path into the final buffer */
807 RtlCopyMemory(FinalBuffer
, BcdDevice
, BcdDevice
->Size
);
808 RtlCopyMemory((PVOID
)((ULONG_PTR
)FinalBuffer
+ BcdDevice
->Size
),
812 /* Now tell the BCD engine to open the store */
813 BcdString
.Length
= FullSize
;
814 BcdString
.MaximumLength
= FullSize
;
815 BcdString
.Buffer
= FinalBuffer
;
816 Status
= BcdOpenStoreFromFile(&BcdString
, Handle
);
818 /* Free our final buffer */
819 BlMmFreeHeap(FinalBuffer
);
822 /* Did we allocate a device? */
826 BlMmFreeHeap(BcdDevice
);
829 /* Is this the failure path? */
830 if (!NT_SUCCESS(Status
))
832 /* Raise a fatal error */
833 BmFatalErrorEx(BL_FATAL_ERROR_BCD_READ
,
834 (ULONG_PTR
)PathBuffer
,
840 /* Did we get an allocated path? */
841 if ((PathBuffer
) && (HavePath
))
844 BlMmFreeHeap(PathBuffer
);
847 /* Return back to the caller */
851 typedef struct _BL_BSD_LOG_OBJECT
858 } BL_BSD_LOG_OBJECT
, *PBL_BSD_LOG_OBJECT
;
860 BL_BSD_LOG_OBJECT BsdpLogObject
;
861 BOOLEAN BsdpLogObjectInitialized
;
865 _In_ PBL_DEVICE_DESCRIPTOR LogDevice
,
872 /* Don't initialize twice */
873 if (BsdpLogObjectInitialized
)
878 /* Set invalid IDs for now */
879 BsdpLogObject
.DeviceId
= -1;
880 BsdpLogObject
.FileId
= -1;
882 /* Open the BSD device */
883 Status
= BlpDeviceOpen(LogDevice
,
884 BL_DEVICE_READ_ACCESS
| BL_DEVICE_WRITE_ACCESS
,
886 &BsdpLogObject
.DeviceId
);
887 if (!NT_SUCCESS(Status
))
889 /* Welp that didn't work */
893 /* Now open the BSD itself */
894 Status
= BlFileOpen(BsdpLogObject
.DeviceId
,
896 BL_FILE_READ_ACCESS
| BL_FILE_WRITE_ACCESS
,
897 &BsdpLogObject
.FileId
);
898 if (!NT_SUCCESS(Status
))
904 /* The BSD is open. Start doing stuff to it */
905 EfiPrintf(L
"Unimplemented BSD path\r\n");
906 Status
= STATUS_NOT_IMPLEMENTED
;
909 /* Close the BSD if we had it open */
910 if (BsdpLogObject
.FileId
!= -1)
912 BlFileClose(BsdpLogObject
.FileId
);
915 /* Close the device if we had it open */
916 if (BsdpLogObject
.DeviceId
!= -1)
918 BlDeviceClose(BsdpLogObject
.DeviceId
);
921 /* Set BSD object to its uninitialized state */
922 BsdpLogObjectInitialized
= FALSE
;
923 BsdpLogObject
.FileId
= 0;
924 BsdpLogObject
.DeviceId
= 0;
925 BsdpLogObject
.Flags
= 0;
926 BsdpLogObject
.Unknown
= 0;
927 BsdpLogObject
.Size
= 0;
931 BmpInitializeBootStatusDataLog (
936 PBL_DEVICE_DESCRIPTOR BsdDevice
;
941 /* Initialize locals */
946 /* Check if the BSD is stored in a custom device */
947 Status
= BlGetBootOptionDevice(BlpApplicationEntry
.BcdData
,
948 BcdLibraryDevice_BsdLogDevice
,
951 if (!NT_SUCCESS(Status
))
953 /* Nope, use the boot device */
954 BsdDevice
= BlpBootDevice
;
957 /* Check if the path is custom as well */
958 Status
= BlGetBootOptionString(BlpApplicationEntry
.BcdData
,
959 BcdLibraryString_BsdLogPath
,
961 if (!NT_SUCCESS(Status
))
963 /* Nope, use our default path */
964 Status
= BmpFwGetFullPath(L
"\\bootstat.dat", &BsdPath
);
965 if (!NT_SUCCESS(Status
))
970 /* Set preserve flag */
975 /* Set preserve flag */
979 /* Finally, check if the BSD should be preserved */
980 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
981 BcdLibraryBoolean_PreserveBsdLog
,
983 if (!(NT_SUCCESS(Status
)) || !(PreserveBsd
))
985 /* We failed to read, or we were asked not to preserve it */
989 /* Initialize the log */
990 BlBsdInitializeLog(BsdDevice
, BsdPath
, Flags
);
992 /* Free the BSD device descriptor if we had one */
995 BlMmFreeHeap(BsdDevice
);
998 /* Free the BSD path if we had one */
999 if ((Flags
) && (BsdPath
))
1001 BlMmFreeHeap(BsdPath
);
1006 BmFwMemoryInitialize (
1011 PHYSICAL_ADDRESS PhysicalAddress
;
1012 BL_ADDRESS_RANGE AddressRange
;
1014 /* Select the range below 1MB */
1015 AddressRange
.Maximum
= 0xFFFFF;
1016 AddressRange
.Minimum
= 0;
1018 /* Allocate one reserved page with the "reserved" attribute */
1019 Status
= MmPapAllocatePhysicalPagesInRange(&PhysicalAddress
,
1020 BlApplicationReserved
,
1024 &MmMdlUnmappedAllocated
,
1026 BL_MM_REQUEST_DEFAULT_TYPE
);
1027 if (!NT_SUCCESS(Status
))
1029 /* Print a message on error, but keep going */
1030 BlStatusPrint(L
"BmFwMemoryInitialize: Failed to allocate a page below 1MB. Status: 0x%08x\r\n",
1036 BmpBgDisplayClearScreen (
1040 /* Not yet supported */
1041 return STATUS_NOT_IMPLEMENTED
;
1046 _In_ PWCHAR Stylesheet
1049 /* Reset the cursor type */
1050 BlDisplaySetCursorType(0);
1052 /* Nope, not doing any XML stuff */
1053 return STATUS_SUCCESS
;
1057 BlImgQueryCodeIntegrityBootOptions (
1058 _In_ PBL_LOADED_APPLICATION_ENTRY ApplicationEntry
,
1059 _Out_ PBOOLEAN IntegrityChecksDisabled
,
1060 _Out_ PBOOLEAN TestSigningEnabled
1067 /* Check if /DISABLEINTEGRITYCHECKS is on */
1068 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
1069 BcdLibraryBoolean_DisableIntegrityChecks
,
1071 *IntegrityChecksDisabled
= NT_SUCCESS(Status
) && (Value
);
1073 /* Check if /TESTSIGNING is on */
1074 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
1075 BcdLibraryBoolean_AllowPrereleaseSignatures
,
1077 *TestSigningEnabled
= NT_SUCCESS(Status
) && (Value
);
1081 BmFwVerifySelfIntegrity (
1085 EfiPrintf(L
"Device Type %d Local Type %d\r\n", BlpBootDevice
->DeviceType
, BlpBootDevice
->Local
.Type
);
1086 if ((BlpBootDevice
->DeviceType
== LocalDevice
) &&
1087 (BlpBootDevice
->Local
.Type
== CdRomDevice
) &&
1088 (BlpApplicationFlags
& BL_APPLICATION_FLAG_CONVERTED_FROM_EFI
))
1090 return STATUS_SUCCESS
;
1099 * The BmMain function implements the Windows Boot Application entrypoint for
1102 * @param BootParameters
1103 * Pointer to the Boot Application Parameter Block.
1105 * @return NT_SUCCESS if the image was loaded correctly, relevant error code
1111 _In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters
1114 NTSTATUS Status
, LibraryStatus
;
1115 BL_LIBRARY_PARAMETERS LibraryParameters
;
1116 PBL_RETURN_ARGUMENTS ReturnArguments
;
1117 BOOLEAN RebootOnError
;
1118 PGUID AppIdentifier
;
1120 PBL_BCD_OPTION EarlyOptions
;
1122 BOOLEAN XmlLoaded
, DisableIntegrity
, TestSigning
;
1124 EfiPrintf(L
"ReactOS UEFI Boot Manager Initializing...\n");
1126 /* Reading the BCD can change this later on */
1127 RebootOnError
= FALSE
;
1129 /* Save the start/end-of-POST time */
1130 ApplicationStartTime
= __rdtsc();
1131 PostTime
= ApplicationStartTime
;
1133 /* Setup the boot library parameters for this application */
1134 BlSetupDefaultParameters(&LibraryParameters
);
1135 LibraryParameters
.TranslationType
= BlNone
;
1136 LibraryParameters
.LibraryFlags
= 0x400 | 0x8;
1137 LibraryParameters
.MinimumAllocationCount
= 16;
1138 LibraryParameters
.MinimumHeapSize
= 512 * 1024;
1140 /* Initialize the boot library */
1141 Status
= BlInitializeLibrary(BootParameters
, &LibraryParameters
);
1142 if (!NT_SUCCESS(Status
))
1144 /* Check for failure due to invalid application entry */
1145 if (Status
!= STATUS_INVALID_PARAMETER_9
)
1147 /* Specifically print out what happened */
1148 EfiPrintf(L
"BlInitializeLibrary failed 0x%x\r\n", Status
);
1151 /* Go to exit path */
1155 /* Get the application identifier */
1156 AppIdentifier
= BlGetApplicationIdentifier();
1159 /* None was given, so set our default one */
1160 AppIdentifier
= (PGUID
)&GUID_WINDOWS_BOOTMGR
;
1163 /* Save our identifier */
1164 BmApplicationIdentifier
= *AppIdentifier
;
1166 /* Initialize the file system to open a handle to our root boot directory */
1167 BmFwInitializeBootDirectoryPath();
1169 /* Load and initialize the boot configuration database (BCD) */
1170 Status
= BmOpenDataStore(&BcdHandle
);
1171 if (NT_SUCCESS(Status
))
1173 /* Copy the boot options */
1174 Status
= BlCopyBootOptions(BlpApplicationEntry
.BcdData
, &EarlyOptions
);
1175 if (NT_SUCCESS(Status
))
1178 Status
= BmpUpdateApplicationOptions(BcdHandle
);
1179 if (!NT_SUCCESS(Status
))
1181 /* Log a fatal error */
1182 BmFatalErrorEx(BL_FATAL_ERROR_BCD_PARSE
,
1183 (ULONG_PTR
)L
"\\BCD",
1192 /* Initialize the secure boot machine policy */
1193 Status
= BmSecureBootInitializeMachinePolicy();
1194 if (!NT_SUCCESS(Status
))
1196 BmFatalErrorEx(BL_FATAL_ERROR_SECURE_BOOT
, Status
, 0, 0, 0);
1200 /* Copy the library parameters and add the re-initialization flag */
1201 RtlCopyMemory(&LibraryParameters
,
1202 &BlpLibraryParameters
,
1203 sizeof(LibraryParameters
));
1204 LibraryParameters
.LibraryFlags
|= (BL_LIBRARY_FLAG_REINITIALIZE_ALL
|
1205 BL_LIBRARY_FLAG_REINITIALIZE
);
1207 /* Now that we've parsed the BCD, re-initialize the library */
1208 LibraryStatus
= BlInitializeLibrary(BootParameters
, &LibraryParameters
);
1209 if (!NT_SUCCESS(LibraryStatus
) && (NT_SUCCESS(Status
)))
1211 Status
= LibraryStatus
;
1214 /* Initialize firmware-specific memory regions */
1215 BmFwMemoryInitialize();
1217 /* Initialize the boot status data log (BSD) */
1218 BmpInitializeBootStatusDataLog();
1220 /* Find our XSL stylesheet */
1221 Stylesheet
= BlResourceFindHtml();
1224 /* Awe, no XML. This is actually fatal lol. Can't boot without XML. */
1225 Status
= STATUS_NOT_FOUND
;
1226 EfiPrintf(L
"BlResourceFindMessage failed 0x%x\r\n", STATUS_NOT_FOUND
);
1230 /* Initialize the XML Engine (as a side-effect, resets cursor) */
1231 Status
= BlXmiInitialize(Stylesheet
);
1232 if (!NT_SUCCESS(Status
))
1234 EfiPrintf(L
"\r\nBlXmiInitialize failed 0x%x\r\n", Status
);
1239 /* Check if there's an active bitmap visible */
1240 if (!BlDisplayValidOemBitmap())
1242 /* Nope, make the screen black using BGFX */
1243 if (!NT_SUCCESS(BmpBgDisplayClearScreen(0xFF000000)))
1245 /* BGFX isn't active, use standard display */
1246 BlDisplayClearScreen();
1251 /* Bitlocker will take over screen UI if enabled */
1252 FveDisplayScreen
= BmFveDisplayScreen
;
1255 /* Check if any bypass options are enabled */
1256 BlImgQueryCodeIntegrityBootOptions(&BlpApplicationEntry
,
1259 if (!DisableIntegrity
)
1261 /* Integrity checks are enabled, so validate our signature */
1262 Status
= BmFwVerifySelfIntegrity();
1263 if (!NT_SUCCESS(Status
))
1265 /* Signature invalid, fail boot */
1270 // BlXmiWrite(L"<bootmgr/>");
1272 //BlSecureBootCheckForFactoryReset();
1275 /* do more stuff!! */
1276 EfiPrintf(BlResourceFindMessage(BM_MSG_TEST
));
1277 EfiPrintf(Stylesheet
);
1281 /* Check if we got here due to an internal error */
1282 if (BmpInternalBootError
)
1284 /* If XML is available, display the error */
1287 //BmDisplayDumpError(0, 0);
1291 /* Don't do a fatal error -- return back to firmware */
1295 /* Log a general fatal error once we're here */
1296 BmFatalErrorEx(BL_FATAL_ERROR_GENERIC
, Status
, 0, 0, 0);
1299 /* Check if we should reboot */
1300 if ((RebootOnError
) ||
1301 (BlpApplicationEntry
.Flags
& BL_APPLICATION_ENTRY_REBOOT_ON_ERROR
))
1303 /* Reboot the box */
1305 Status
= STATUS_SUCCESS
;
1309 /* Return back to the caller with the error argument encoded */
1310 ReturnArguments
= (PVOID
)((ULONG_PTR
)BootParameters
+ BootParameters
->ReturnArgumentsOffset
);
1311 ReturnArguments
->Version
= BL_RETURN_ARGUMENTS_VERSION
;
1312 ReturnArguments
->Status
= Status
;
1314 /* Tear down the boot library*/
1318 /* Return back status */