Author: ion Date: Mon Jan 18 16:54:44 2016 New Revision: 70614
URL: http://svn.reactos.org/svn/reactos?rev=70614&view=rev Log: [HIVEBCD]: Fix wrong element type for application device element. [BOOTMGR]: Implement boot sequence population. We correctly detect our winload.efi entry in the BCD hive. [BOOTMGR]: Document more application entry flags. [BOOTLIB]: Document and implement BCD object description parsing. Based off BCD Reference Guide / Geoff Chappel's website. [BOOTLIB]: Add support for appending a boot option to an entry.
Modified: trunk/reactos/boot/bootdata/hivebcd.inf trunk/reactos/boot/environ/app/bootmgr/bootmgr.c trunk/reactos/boot/environ/include/bcd.h trunk/reactos/boot/environ/include/bl.h trunk/reactos/boot/environ/lib/misc/bcd.c trunk/reactos/boot/environ/lib/misc/bcdopt.c trunk/reactos/boot/environ/lib/misc/bootreg.c
Modified: trunk/reactos/boot/bootdata/hivebcd.inf URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/hivebcd.inf?r... ============================================================================== --- trunk/reactos/boot/bootdata/hivebcd.inf [iso-8859-1] (original) +++ trunk/reactos/boot/bootdata/hivebcd.inf [iso-8859-1] Mon Jan 18 16:54:44 2016 @@ -22,7 +22,7 @@ ; ReactOS Boot Loader ; BCD,"BCD00000000\Objects{7619dcc9-fafe-11d9-b411-000476eba25f}\Description","Type",0x00010001,0x10200003 ; identifier={winload} -BCD,"BCD00000000\Objects{7619dcc9-fafe-11d9-b411-000476eba25f}\Elements\11000011","Element",0x1,\ ; device=boot +BCD,"BCD00000000\Objects{7619dcc9-fafe-11d9-b411-000476eba25f}\Elements\11000001","Element",0x1,\ ; device=boot 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\ 05,00,00,00,\ 00,00,00,00,\ @@ -45,7 +45,7 @@ ; ReactOS Memory Tester ; BCD,"BCD00000000\Objects{b2721d73-1db4-4c62-bf78-c548a880142d}\Description","Type",0x00010001,0x10200005 ; identifier={memdiag} -BCD,"BCD00000000\Objects{b2721d73-1db4-4c62-bf78-c548a880142d}\Elements\11000011","Element",0x1,\ ; device=boot +BCD,"BCD00000000\Objects{b2721d73-1db4-4c62-bf78-c548a880142d}\Elements\11000001","Element",0x1,\ ; device=boot 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\ 05,00,00,00,\ 00,00,00,00,\
Modified: trunk/reactos/boot/environ/app/bootmgr/bootmgr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/app/bootmgr/bo... ============================================================================== --- trunk/reactos/boot/environ/app/bootmgr/bootmgr.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/app/bootmgr/bootmgr.c [iso-8859-1] Mon Jan 18 16:54:44 2016 @@ -121,7 +121,6 @@ /* Start going through each option */ PreviousOption = NULL; Option = Options; - EfiPrintf(L"BCD Options found: %d\r\n", ElementCount); for (i = 0; i < ElementCount; i++) { /* Read the header and type */ @@ -1231,6 +1230,40 @@ }
NTSTATUS +BmGetEntryDescription ( + _In_ HANDLE BcdHandle, + _In_ PGUID ObjectId, + _Out_ PBCD_OBJECT_DESCRIPTION Description + ) +{ + NTSTATUS Status; + HANDLE ObjectHandle; + + /* Open the BCD object */ + Status = BcdOpenObject(BcdHandle, ObjectId, &ObjectHandle); + if (NT_SUCCESS(Status)) + { + /* Make sure the caller passed this argument in */ + if (!Description) + { + /* Fail otherwise */ + Status = STATUS_INVALID_PARAMETER; + } + else + { + /* Query the description from the BCD interface */ + Status = BiGetObjectDescription(ObjectHandle, Description); + } + + /* Close the object key */ + BiCloseKey(ObjectHandle); + } + + /* Return the result back */ + return Status; +} + +NTSTATUS BmpPopulateBootEntryList ( _In_ HANDLE BcdHandle, _In_ PGUID SequenceList, @@ -1239,10 +1272,211 @@ _Out_ PULONG SequenceCount ) { - EfiPrintf(L"Boot population not yet supported\r\n"); - *SequenceCount = 0; - *BootSequence = NULL; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + ULONG BootIndex, i, OptionSize; + PBL_LOADED_APPLICATION_ENTRY BootEntry; + PBL_BCD_OPTION Options; + BCD_OBJECT_DESCRIPTION Description; + BcdObjectType ObjectType; + BOOLEAN HavePath, IsWinPe, SoftReboot; + PWCHAR LoaderPath; + + /* Initialize locals */ + Options = NULL; + BootIndex = 0; + Status = STATUS_NOT_FOUND; + + /* Loop through every element in the sequence */ + for (i = 0; i < *SequenceCount; i++) + { + /* Assume failure */ + BootEntry = NULL; + + /* Get the options for the sequence element */ + Status = BmGetOptionList(BcdHandle, SequenceList, &Options); + if (!NT_SUCCESS(Status)) + { + EfiPrintf(L"option list failed: %lx\r\n", Status); + goto LoopQuickie; + } + + /* Make sure there's at least a path and description */ + if (!(MiscGetBootOption(Options, BcdLibraryDevice_ApplicationDevice)) || + !(MiscGetBootOption(Options, BcdLibraryString_Description))) + { + Status = STATUS_UNSUCCESSFUL; + EfiPrintf(L"missing list failed: %lx\r\n", Status); + goto LoopQuickie; + } + + /* Get the size of the BCD options and allocate a large enough entry */ + OptionSize = BlGetBootOptionListSize(Options); + BootEntry = BlMmAllocateHeap(sizeof(*BootEntry) + OptionSize); + if (!BootEntry) + { + Status = STATUS_NO_MEMORY; + goto Quickie; + } + + /* Save it as part of the sequence */ + BootSequence[BootIndex] = BootEntry; + + /* Initialize it, and copy the BCD data */ + RtlZeroMemory(BootEntry, sizeof(*BootEntry)); + BootEntry->Guid = *SequenceList; + BootEntry->BcdData = (PBL_BCD_OPTION)(BootEntry + 1); + BootEntry->Flags = Flags; + RtlCopyMemory(BootEntry->BcdData, Options, OptionSize); + + /* Get the object descriptor to find out what kind of entry it is */ + Status = BmGetEntryDescription(BcdHandle, + &BootEntry->Guid, + &Description); + if (!NT_SUCCESS(Status)) + { + EfiPrintf(L"missing desc failed: %lx\r\n", Status); + goto LoopQuickie; + } + + /* Check if a path was given or not */ + HavePath = MiscGetBootOption(Options, BcdLibraryString_ApplicationPath) ? + TRUE : FALSE; + + /* Now select based on what type of object this is -- must be an app */ + ObjectType.PackedValue = Description.Type; + if (ObjectType.Application.ObjectCode == BCD_OBJECT_TYPE_APPLICATION) + { + /* Then select based on what kind of app it is */ + switch (ObjectType.Application.ApplicationCode) + { + /* Another boot manager */ + case BCD_APPLICATION_TYPE_BOOTMGR: + BootEntry->Flags |= BCD_APPLICATION_TYPE_BOOTMGR; + break; + + /* An OS loader */ + case BCD_APPLICATION_TYPE_OSLOADER: + BootEntry->Flags |= BL_APPLICATION_ENTRY_WINLOAD; + + /* Do we have a path for it? */ + if (!HavePath) + { + /* We'll try to make one up. Is this WinPE? */ + IsWinPe = FALSE; + Status = BlGetBootOptionBoolean(Options, + BcdOSLoaderBoolean_WinPEMode, + &IsWinPe); + if (!(NT_SUCCESS(Status)) && (Status != STATUS_NOT_FOUND)) + { + goto Quickie; + } + + /* Use the appropriate path for WinPE or local install */ + LoaderPath = IsWinPe ? + L"\Windows\System32\boot\winload.efi" : + L"\Windows\System32\winload.efi"; + + /* Add the path to the boot entry */ + Status = BlAppendBootOptionString(BootEntry, LoaderPath); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* We have a path now */ + HavePath = TRUE; + } + break; + + /* A hibernate-resume application */ + case BCD_APPLICATION_TYPE_RESUME: + BootEntry->Flags |= BL_APPLICATION_ENTRY_WINRESUME; + break; + + /* An older OS NTLDR */ + case BCD_APPLICATION_TYPE_NTLDR: + BootEntry->Flags |= BL_APPLICATION_ENTRY_NTLDR; + break; + + /* An older OS SETUPLDR */ + case BCD_APPLICATION_TYPE_SETUPLDR: + BootEntry->Flags |= BL_APPLICATION_ENTRY_SETUPLDR; + break; + + /* A 3rd party/Win9x boot sector */ + case BCD_APPLICATION_TYPE_BOOTSECTOR: + BootEntry->Flags |= BL_APPLICATION_ENTRY_BOOTSECTOR; + break; + + /* Something else entirely */ + default: + break; + } + } + + /* We better have a path by now */ + if (!HavePath) + { + Status = STATUS_UNSUCCESSFUL; + goto LoopQuickie; + } + + /* Check if this is a real mode startup.com */ + if ((ObjectType.Application.ObjectCode == BCD_OBJECT_TYPE_APPLICATION) && + (ObjectType.Application.ImageCode = BCD_IMAGE_TYPE_REAL_MODE) && + (ObjectType.Application.ApplicationCode == BCD_APPLICATION_TYPE_STARTUPCOM)) + { + /* Check if PXE soft reboot will occur */ + Status = BlGetBootOptionBoolean(Options, + BcdStartupBoolean_PxeSoftReboot, + &SoftReboot); + if ((NT_SUCCESS(Status)) && (SoftReboot)) + { + /* Then it's a valid startup.com entry */ + BootEntry->Flags |= BL_APPLICATION_ENTRY_STARTUP; + } + } + +LoopQuickie: + /* All done with this entry -- did we have BCD options? */ + if (Options) + { + /* Free them, they're part of the entry now */ + BlMmFreeHeap(Options); + Options = NULL; + } + + /* Did we fail anywhere? */ + if (!NT_SUCCESS(Status)) + { + /* Yep -- did we fail with an active boot entry? */ + if (BootEntry) + { + /* Destroy it */ + BlDestroyBootEntry(BootEntry); + BootSequence[BootIndex] = NULL; + } + } + else + { + /* It worked, so populate the next index now */ + BootIndex++; + } + + /* And move to the next GUID in the sequence list */ + SequenceList++; + } + +Quickie: + /* All done now -- did we have any BCD options? */ + if (Options) + { + /* Free them */ + BlMmFreeHeap(Options); + } + + /* Return the status */ + return Status; }
NTSTATUS @@ -1363,7 +1597,7 @@ /* Populate the list of bootable entries */ Status = BmpPopulateBootEntryList(BcdHandle, DisplayOrder, - 0x800000, + BL_APPLICATION_ENTRY_DISPLAY_ORDER, Sequence, &BcdCount); if (!NT_SUCCESS(Status)) @@ -1454,7 +1688,8 @@ goto Quickie; }
- EfiPrintf(L"Boot selection not yet implemented\r\n"); + EfiPrintf(L"Boot selection not yet implemented. %d entries found\r\n", Count); + EfiStall(10000000); *SelectedBootEntry = NULL;
Quickie: @@ -1772,7 +2007,7 @@ Status = BmGetBootSequence(BcdHandle, SequenceList, SequenceListCount, - 0x20000000, + BL_APPLICATION_ENTRY_FIXED_SEQUENCE, &BootSequence, &SequenceCount); if (NT_SUCCESS(Status))
Modified: trunk/reactos/boot/environ/include/bcd.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/include/bcd.h?... ============================================================================== --- trunk/reactos/boot/environ/include/bcd.h [iso-8859-1] (original) +++ trunk/reactos/boot/environ/include/bcd.h [iso-8859-1] Mon Jan 18 16:54:44 2016 @@ -25,6 +25,25 @@ #define BCD_TYPE_INTEGER 0x05 #define BCD_TYPE_BOOLEAN 0x06 #define BCD_TYPE_INTEGER_LIST 0x07 + +#define BCD_IMAGE_TYPE_FIRMWARE 0x01 +#define BCD_IMAGE_TYPE_BOOT_APP 0x02 +#define BCD_IMAGE_TYPE_NTLDR 0x03 +#define BCD_IMAGE_TYPE_REAL_MODE 0x04 + +#define BCD_APPLICATION_TYPE_FWBOOTMGR 0x01 +#define BCD_APPLICATION_TYPE_BOOTMGR 0x02 +#define BCD_APPLICATION_TYPE_OSLOADER 0x03 +#define BCD_APPLICATION_TYPE_RESUME 0x04 +#define BCD_APPLICATION_TYPE_MEMDIAG 0x05 +#define BCD_APPLICATION_TYPE_NTLDR 0x06 +#define BCD_APPLICATION_TYPE_SETUPLDR 0x07 +#define BCD_APPLICATION_TYPE_BOOTSECTOR 0x08 +#define BCD_APPLICATION_TYPE_STARTUPCOM 0x09 + +#define BCD_OBJECT_TYPE_APPLICATION 0x01 +#define BCD_OBJECT_TYPE_INHEREIT 0x02 +#define BCD_OBJECT_TYPE_DEVICE 0x03
typedef enum BcdLibraryElementTypes { @@ -172,13 +191,20 @@ BcdBootMgrBoolean_PersistBootSequence = 0x26000031 } BcdBootMgrElementTypes;
+/* Undocumented */ +typedef enum BcdStartupElementTypes +{ + BcdStartupBoolean_PxeSoftReboot = 0x26000001, + BcdStartupString_PxeApplicationName = 0x22000002, +} BcdStartupElementTypes; + /* DATA STRUCTURES ***********************************************************/
typedef struct { union { - ULONG PackedValue; + ULONG PackedValue; struct { ULONG SubType : 24; @@ -188,6 +214,36 @@ }; } BcdElementType;
+typedef struct +{ + union + { + ULONG PackedValue; + union + { + struct + { + ULONG ApplicationCode : 20; + ULONG ImageCode : 4; + ULONG Reserved : 4; + ULONG ObjectCode : 4; + } Application; + struct + { + ULONG Value : 20; + ULONG ClassCode : 4; + ULONG Reserved : 4; + ULONG ObjectCode : 4; + } Inherit; + struct + { + ULONG Reserved:28; + ULONG ObjectCode : 4; + } Device; + }; + }; +} BcdObjectType; + typedef struct _BCD_ELEMENT_HEADER { ULONG Version; @@ -214,6 +270,12 @@ GUID AssociatedEntry; BL_DEVICE_DESCRIPTOR DeviceDescriptor; } BCD_DEVICE_OPTION, *PBCD_DEVICE_OPTION; + +typedef struct _BCD_OBJECT_DESCRIPTION +{ + ULONG Valid; + ULONG Type; +} BCD_OBJECT_DESCRIPTION, *PBCD_OBJECT_DESCRIPTION;;
/* FUNCTIONS ******************************************************************/
@@ -260,4 +322,10 @@ _Out_ PULONG ElementCount );
+NTSTATUS +BiGetObjectDescription ( + _In_ HANDLE ObjectHandle, + _Out_ PBCD_OBJECT_DESCRIPTION Description + ); + #endif
Modified: trunk/reactos/boot/environ/include/bl.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/include/bl.h?r... ============================================================================== --- trunk/reactos/boot/environ/include/bl.h [iso-8859-1] (original) +++ trunk/reactos/boot/environ/include/bl.h [iso-8859-1] Mon Jan 18 16:54:44 2016 @@ -66,8 +66,17 @@
#define BL_APPLICATION_ENTRY_FLAG_NO_GUID 0x01 #define BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL 0x02 +#define BL_APPLICATION_ENTRY_WINLOAD 0x04 +#define BL_APPLICATION_ENTRY_STARTUP 0x08 #define BL_APPLICATION_ENTRY_REBOOT_ON_ERROR 0x20 +#define BL_APPLICATION_ENTRY_NTLDR 0x40 #define BL_APPLICATION_ENTRY_BCD_OPTIONS_EXTERNAL 0x80 +#define BL_APPLICATION_ENTRY_WINRESUME 0x100 +#define BL_APPLICATION_ENTRY_SETUPLDR 0x200 +#define BL_APPLICATION_ENTRY_BOOTSECTOR 0x400 +#define BL_APPLICATION_ENTRY_BOOTMGR 0x1000 +#define BL_APPLICATION_ENTRY_DISPLAY_ORDER 0x800000 +#define BL_APPLICATION_ENTRY_FIXED_SEQUENCE 0x20000000
#define BL_CONTEXT_PAGING_ON 1 #define BL_CONTEXT_INTERRUPTS_ON 2 @@ -1743,6 +1752,12 @@ );
NTSTATUS +BlAppendBootOptionString ( + _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, + _In_ PWCHAR OptionString + ); + +NTSTATUS BlAppendBootOptions ( _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, _In_ PBL_BCD_OPTION Options @@ -1784,7 +1799,6 @@ BiGetRegistryValue ( _In_ HANDLE KeyHandle, _In_ PWCHAR ValueName, - _In_ PWCHAR KeyName, _In_ ULONG Type, _Out_ PVOID* Buffer, _Out_ PULONG ValueLength
Modified: trunk/reactos/boot/environ/lib/misc/bcd.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/misc/bcd.c... ============================================================================== --- trunk/reactos/boot/environ/lib/misc/bcd.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/misc/bcd.c [iso-8859-1] Mon Jan 18 16:54:44 2016 @@ -881,7 +881,6 @@ /* Read the appropriate registry value type for this element */ Status = BiGetRegistryValue(ElementHandle, L"Element", - NULL, BiConvertElementFormatToValueType( ElementType.Format), &RegistryElementData, @@ -1177,6 +1176,69 @@ }
NTSTATUS +BiGetObjectDescription ( + _In_ HANDLE ObjectHandle, + _Out_ PBCD_OBJECT_DESCRIPTION Description + ) +{ + NTSTATUS Status; + HANDLE DescriptionHandle; + PULONG Data; + ULONG Length; + + /* Initialize locals */ + Data = NULL; + DescriptionHandle = NULL; + + /* Open the description key */ + Status = BiOpenKey(ObjectHandle, L"Description", &DescriptionHandle); + if (NT_SUCCESS(Status)) + { + /* It exists */ + Description->Valid = TRUE; + + /* Read the type */ + Length = 0; + Status = BiGetRegistryValue(DescriptionHandle, + L"Type", + REG_DWORD, + (PVOID*)&Data, + &Length); + if (NT_SUCCESS(Status)) + { + /* Make sure it's the length we expected it to be */ + if (Length == sizeof(Data)) + { + /* Return the type that is stored there */ + Description->Type = *Data; + } + else + { + /* Invalid type value */ + Status = STATUS_OBJECT_TYPE_MISMATCH; + } + } + } + + /* Did we have a handle open? */ + if (DescriptionHandle) + { + /* Close it */ + BiCloseKey(DescriptionHandle); + } + + /* Did we have data allocated? */ + if (Data) + { + /* Free it */ + BlMmFreeHeap(Data); + } + + /* Return back to caller */ + return Status; +} + +NTSTATUS BcdEnumerateAndUnpackElements ( _In_ HANDLE BcdHandle, _In_ HANDLE ObjectHandle,
Modified: trunk/reactos/boot/environ/lib/misc/bcdopt.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/misc/bcdop... ============================================================================== --- trunk/reactos/boot/environ/lib/misc/bcdopt.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/misc/bcdopt.c [iso-8859-1] Mon Jan 18 16:54:44 2016 @@ -622,6 +622,53 @@ }
NTSTATUS +BlAppendBootOptionString ( + _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, + _In_ PWCHAR OptionString + ) +{ + NTSTATUS Status; + ULONG StringSize; + PBL_BCD_OPTION Option; + + /* Get the length in bytes */ + Status = RtlULongLongToULong(wcslen(OptionString) * sizeof(WCHAR), + &StringSize); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Add a NULL-terminator */ + Status = RtlULongAdd(StringSize, sizeof(UNICODE_NULL), &StringSize); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Allocate space for the entry */ + Option = BlMmAllocateHeap(sizeof(*Option) + StringSize); + if (!Option) + { + return STATUS_NO_MEMORY; + } + + /* Initialize it and copy the string value */ + RtlZeroMemory(Option, sizeof(*Option) + StringSize); + Option->DataSize = StringSize; + Option->Type = BcdLibraryString_ApplicationPath; + Option->DataOffset = sizeof(*Option); + wcsncpy((PWCHAR)Option + 1, OptionString, StringSize / sizeof(WCHAR)); + + /* Append it */ + Status = BlAppendBootOptions(AppEntry, Option); + + /* We're all done, free our initial option */ + BlMmFreeHeap(Option); + return Status; +} + +NTSTATUS BlAppendBootOptions ( _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, _In_ PBL_BCD_OPTION Options
Modified: trunk/reactos/boot/environ/lib/misc/bootreg.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/misc/bootr... ============================================================================== --- trunk/reactos/boot/environ/lib/misc/bootreg.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/misc/bootreg.c [iso-8859-1] Mon Jan 18 16:54:44 2016 @@ -655,7 +655,6 @@ BiGetRegistryValue ( _In_ HANDLE KeyHandle, _In_ PWCHAR ValueName, - _In_ PWCHAR KeyName, _In_ ULONG Type, _Out_ PVOID* Buffer, _Out_ PULONG ValueLength