From: Alex Ionescu Date: Wed, 9 Sep 2015 18:09:04 +0000 (+0000) Subject: - Implement BmpFwGetApplicationDirectoryPath and most of BmFwInitializeBootDirectoryPath. X-Git-Tag: ReactOS-0.4.0~892 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=be0ecbd74e1476ed9f3599d8316f07e3f9c1e13b - Implement BmpFwGetApplicationDirectoryPath and most of BmFwInitializeBootDirectoryPath. - Implement boolean, integer, and string BCD reading. - Fix a more bugs. - We are now ready to open the BCD hive! svn path=/trunk/; revision=69155 --- diff --git a/reactos/boot/environ/app/bootmgr/bootmgr.c b/reactos/boot/environ/app/bootmgr/bootmgr.c index 7afd6f205a0..ab84d034124 100644 --- a/reactos/boot/environ/app/bootmgr/bootmgr.c +++ b/reactos/boot/environ/app/bootmgr/bootmgr.c @@ -12,7 +12,6 @@ /* DATA VARIABLES ************************************************************/ -#include DEFINE_GUID(GUID_WINDOWS_BOOTMGR, 0x9DEA862C, 0x5CDD, @@ -26,6 +25,103 @@ PWCHAR BootDirectory; /* FUNCTIONS *****************************************************************/ +NTSTATUS +BmpFwGetApplicationDirectoryPath ( + _In_ PUNICODE_STRING ApplicationDirectoryPath + ) +{ + NTSTATUS Status; + ULONG i, AppPathLength; + PWCHAR ApplicationPath, PathCopy; + + /* Clear the incoming string */ + ApplicationDirectoryPath->Length = 0; + ApplicationDirectoryPath->MaximumLength = 0; + ApplicationDirectoryPath->Buffer = 0; + + /* Get the boot application path */ + ApplicationPath = NULL; + Status = BlGetBootOptionString(BlpApplicationEntry.BcdData, + BcdLibraryString_ApplicationPath, + &ApplicationPath); + if (NT_SUCCESS(Status)) + { + /* Calculate the length of the application path */ + for (i = wcslen(ApplicationPath) - 1; i > 0; i--) + { + /* Keep going until the path separator */ + if (ApplicationPath[i] == OBJ_NAME_PATH_SEPARATOR) + { + break; + } + } + + /* Check if we have space for one more character */ + AppPathLength = i + 1; + if (AppPathLength < i) + { + /* Nope, we'll overflow */ + AppPathLength = -1; + Status = STATUS_INTEGER_OVERFLOW; + } + else + { + /* Go ahead */ + Status = STATUS_SUCCESS; + } + + /* No overflow? */ + if (NT_SUCCESS(Status)) + { + /* Check if it's safe to multiply by two */ + if ((AppPathLength * sizeof(WCHAR)) > 0xFFFFFFFF) + { + /* Nope */ + AppPathLength = -1; + Status = STATUS_INTEGER_OVERFLOW; + } + else + { + /* We're good, do the multiplication */ + Status = STATUS_SUCCESS; + AppPathLength *= sizeof(WCHAR); + } + + /* Allocate a copy for the string */ + if (NT_SUCCESS(Status)) + { + PathCopy = BlMmAllocateHeap(AppPathLength); + if (PathCopy) + { + /* NULL-terminate it */ + RtlCopyMemory(PathCopy, + ApplicationPath, + AppPathLength - sizeof(UNICODE_NULL)); + PathCopy[AppPathLength] = UNICODE_NULL; + + /* Finally, initialize the outoing string */ + RtlInitUnicodeString(ApplicationDirectoryPath, PathCopy); + } + else + { + /* No memory, fail */ + Status = STATUS_NO_MEMORY; + } + } + } + } + + /* Check if we had an application path */ + if (ApplicationPath) + { + /* No longer need this, free it */ + BlMmFreeHeap(ApplicationPath); + } + + /* All done! */ + return Status; + +} NTSTATUS BmFwInitializeBootDirectoryPath ( VOID @@ -34,13 +130,13 @@ BmFwInitializeBootDirectoryPath ( PWCHAR FinalPath; NTSTATUS Status; PWCHAR BcdDirectory; - // UNICODE_STRING BcdPath; - //ULONG FinalSize; + UNICODE_STRING BcdPath; + ULONG FinalSize; ULONG FileHandle, DeviceHandle; /* Initialize everything for failure */ - // BcdPath.MaximumLength = 0; - // BcdPath.Buffer = NULL; + BcdPath.MaximumLength = 0; + BcdPath.Buffer = NULL; BcdDirectory = NULL; FinalPath = NULL; FileHandle = -1; @@ -51,39 +147,40 @@ BmFwInitializeBootDirectoryPath ( if (!NT_SUCCESS(Status)) { EfiPrintf(L"Device open failed: %lx\r\n", Status); - EfiStall(2000000); goto Quickie; } - /* For now, do nothing */ - EfiPrintf(L"Successfully opened boot device: %lx\r\n", DeviceHandle); - EfiStall(2000000); - -#if 0 + /* Get the directory path */ Status = BmpFwGetApplicationDirectoryPath(&BcdPath); BcdDirectory = BcdPath.Buffer; if (!NT_SUCCESS(Status)) { + EfiPrintf(L"path failed: %lx\n", Status); goto Quickie; } + /* Add the BCD file name to it */ FinalSize = BcdPath.MaximumLength + sizeof(L"\\BCD") - sizeof(UNICODE_NULL); if (FinalSize < BcdPath.MaximumLength) { goto Quickie; } + /* Allocate space for the final path */ FinalPath = BlMmAllocateHeap(FinalSize); if (!FinalPath) { goto Quickie; } + /* Build it */ RtlZeroMemory(FinalPath, FinalSize); RtlCopyMemory(FinalPath, BcdDirectory, BcdPath.MaximumLength); wcsncat(FinalPath, L"\\BCD", FinalSize / sizeof(WCHAR)); + /* Try to open the file */ EfiPrintf(L"Opening: %s\r\n", FinalPath); +#if 0 Status = BlFileOpen(DeviceHandle, FinalPath, 1u, &FileHandle); if (!NT_SUCCESS(Status)) { diff --git a/reactos/boot/environ/app/bootmgr/bootmgr.h b/reactos/boot/environ/app/bootmgr/bootmgr.h index 13d5bcd06a6..de39b772939 100644 --- a/reactos/boot/environ/app/bootmgr/bootmgr.h +++ b/reactos/boot/environ/app/bootmgr/bootmgr.h @@ -17,6 +17,7 @@ #include /* NT Base Headers */ +#include #include /* UEFI Headers */ @@ -25,6 +26,9 @@ /* Boot Library Headers */ #include +/* BCD Headers */ +#include + /* FUNCTIONS *****************************************************************/ NTSTATUS diff --git a/reactos/boot/environ/include/bl.h b/reactos/boot/environ/include/bl.h index 093867a37d2..2bf8a181cb2 100644 --- a/reactos/boot/environ/include/bl.h +++ b/reactos/boot/environ/include/bl.h @@ -506,6 +506,13 @@ typedef struct _BL_APPLICATION_ENTRY BL_BCD_OPTION BcdData; } BL_APPLICATION_ENTRY, *PBL_APPLICATION_ENTRY; +typedef struct _BL_LOADED_APPLICATION_ENTRY +{ + ULONG Flags; + GUID Guid; + PBL_BCD_OPTION BcdData; +} BL_LOADED_APPLICATION_ENTRY, *PBL_LOADED_APPLICATION_ENTRY; + typedef struct _BL_HARDDISK_DEVICE { ULONG PartitionType; @@ -1123,6 +1130,27 @@ BlGetBootOptionSize ( _In_ PBL_BCD_OPTION BcdOption ); +NTSTATUS +BlGetBootOptionString ( + _In_ PBL_BCD_OPTION List, + _In_ ULONG Type, + _Out_ PWCHAR* Value + ); + +NTSTATUS +BlGetBootOptionInteger ( + _In_ PBL_BCD_OPTION List, + _In_ ULONG Type, + _Out_ PULONGLONG Value + ); + +NTSTATUS +BlGetBootOptionBoolean ( + _In_ PBL_BCD_OPTION List, + _In_ ULONG Type, + _Out_ PBOOLEAN Value + ); + /* CONTEXT ROUTINES **********************************************************/ VOID @@ -1412,7 +1440,7 @@ extern BL_LIBRARY_PARAMETERS BlpLibraryParameters; extern BL_TRANSLATION_TYPE MmTranslationType; extern PBL_ARCH_CONTEXT CurrentExecutionContext; extern PBL_DEVICE_DESCRIPTOR BlpBootDevice; -extern BL_APPLICATION_ENTRY BlpApplicationEntry; +extern BL_LOADED_APPLICATION_ENTRY BlpApplicationEntry; extern SIMPLE_TEXT_OUTPUT_INTERFACE *EfiConOut; extern EFI_GUID EfiGraphicsOutputProtocol; extern EFI_GUID EfiUgaDrawProtocol; diff --git a/reactos/boot/environ/lib/bootlib.c b/reactos/boot/environ/lib/bootlib.c index fbbb946680a..43ef21361b8 100644 --- a/reactos/boot/environ/lib/bootlib.c +++ b/reactos/boot/environ/lib/bootlib.c @@ -16,7 +16,7 @@ BL_LIBRARY_PARAMETERS BlpLibraryParameters; PBL_DEVICE_DESCRIPTOR BlpBootDevice; PWCHAR BlpApplicationBaseDirectory; PBOOT_APPLICATION_PARAMETER_BLOCK BlpApplicationParameters; -BL_APPLICATION_ENTRY BlpApplicationEntry; +BL_LOADED_APPLICATION_ENTRY BlpApplicationEntry; BOOLEAN BlpLibraryParametersInitialized; ULONG PdPersistAllocations; @@ -86,12 +86,16 @@ InitializeLibrary ( BlpApplicationParameters = BootAppParameters; BlpLibraryParameters = *LibraryParameters; - /* Save the application entry */ + /* Save the application entry flags */ if (AppEntry->Flags & 2) { AppEntry->Flags = (AppEntry->Flags & ~0x2) | 0x80; } - BlpApplicationEntry = *AppEntry; + BlpApplicationEntry.Flags = AppEntry->Flags; + + /* Copy the GUID and point to the options */ + BlpApplicationEntry.Guid = AppEntry->Guid; + BlpApplicationEntry.BcdData = &AppEntry->BcdData; /* Everything has been captured */ BlpLibraryParametersInitialized = TRUE; diff --git a/reactos/boot/environ/lib/misc/bcd.c b/reactos/boot/environ/lib/misc/bcd.c index 903f1f17ee9..58eed43173d 100644 --- a/reactos/boot/environ/lib/misc/bcd.c +++ b/reactos/boot/environ/lib/misc/bcd.c @@ -12,6 +12,225 @@ /* FUNCTIONS *****************************************************************/ +PBL_BCD_OPTION +MiscGetBootOption ( + _In_ PBL_BCD_OPTION List, + _In_ ULONG Type + ) +{ + ULONG_PTR NextOption = 0, ListOption; + PBL_BCD_OPTION Option; + + /* No options, bail out */ + if (!List) + { + return NULL; + } + + /* Loop while we find an option */ + while (TRUE) + { + /* Get the next option and see if it matches the type */ + Option = (PBL_BCD_OPTION)((ULONG_PTR)List + NextOption); + if ((Option->Type == Type) && !(Option->Empty)) + { + break; + } + + /* Store the offset of the next option */ + NextOption = Option->NextEntryOffset; + + /* Failed to match. Check for list options */ + ListOption = Option->ListOffset; + if (ListOption) + { + /* Try to get a match in the associated option */ + Option = MiscGetBootOption((PBL_BCD_OPTION)((ULONG_PTR)Option + + ListOption), + Type); + + /* Found one, return it */ + if (Option) + { + return Option; + } + } + } + + /* We found the option, return it */ + return Option; +} + +NTSTATUS +BlGetBootOptionString ( + _In_ PBL_BCD_OPTION List, + _In_ ULONG Type, + _Out_ PWCHAR* Value + ) +{ + NTSTATUS Status; + PBL_BCD_OPTION Option; + PWCHAR String, StringCopy; + ULONG StringLength, CopyLength; + //PGUID AppIdentifier; + + /* Make sure this is a BCD_STRING */ + if ((Type & 0xF000000) != 0x2000000) + { + return STATUS_INVALID_PARAMETER; + } + + /* Return the data */ + Option = MiscGetBootOption(List, Type); + if (Option) + { + /* Extract the string */ + String = (PWCHAR)((ULONG_PTR)Option + Option->DataOffset); + } + else + { + /* No string is present */ + String = NULL; + } + + /* Compute the data size */ + StringLength = Option->DataSize / sizeof(WCHAR); + +#ifdef _SECURE_BOOT_ + /* Filter out SecureBoot Options */ + AppIdentifier = BlGetApplicationIdentifier(); + Status = BlpBootOptionCallbackString(AppIdentifier, Type, String, StringLength, &String, &StringLength); +#else + Status = STATUS_SUCCESS; +#endif + + /* Check if we have space for one more character */ + CopyLength = StringLength + 1; + if (CopyLength < StringLength) + { + /* Nope, we'll overflow */ + CopyLength = -1; + Status = STATUS_INTEGER_OVERFLOW; + } + else + { + /* Go ahead */ + Status = STATUS_SUCCESS; + } + + /* No overflow? */ + if (NT_SUCCESS(Status)) + { + /* Check if it's safe to multiply by two */ + if ((CopyLength * sizeof(WCHAR)) > 0xFFFFFFFF) + { + /* Nope */ + CopyLength = -1; + Status = STATUS_INTEGER_OVERFLOW; + } + else + { + /* We're good, do the multiplication */ + Status = STATUS_SUCCESS; + CopyLength *= sizeof(WCHAR); + } + + /* Allocate a copy for the string */ + if (NT_SUCCESS(Status)) + { + StringCopy = BlMmAllocateHeap(CopyLength); + if (StringCopy) + { + /* NULL-terminate it */ + RtlCopyMemory(StringCopy, + String, + CopyLength - sizeof(UNICODE_NULL)); + StringCopy[CopyLength] = UNICODE_NULL; + *Value = StringCopy; + Status = STATUS_SUCCESS; + } + else + { + /* No memory, fail */ + Status = STATUS_NO_MEMORY; + } + } + } + + /* All done */ + return Status; +} + +NTSTATUS +BlGetBootOptionInteger ( + _In_ PBL_BCD_OPTION List, + _In_ ULONG Type, + _Out_ PULONGLONG Value + ) +{ + NTSTATUS Status; + PBL_BCD_OPTION Option; + //PGUID AppIdentifier; + + /* Make sure this is a BCD_INTEGER */ + if ((Type & 0xF000000) != 0x5000000) + { + return STATUS_INVALID_PARAMETER; + } + + /* Return the data */ + Option = MiscGetBootOption(List, Type); + if (Option) + { + *Value = *(PULONGLONG)((ULONG_PTR)Option + Option->DataOffset); + } + +#ifdef _SECURE_BOOT_ + /* Filter out SecureBoot Options */ + AppIdentifier = BlGetApplicationIdentifier(); + Status = BlpBootOptionCallbackULongLong(AppIdentifier, Type, Value); +#else + /* Option found */ + Status = Option ? STATUS_SUCCESS : STATUS_NOT_FOUND; +#endif + return Status; +} + +NTSTATUS +BlGetBootOptionBoolean ( + _In_ PBL_BCD_OPTION List, + _In_ ULONG Type, + _Out_ PBOOLEAN Value + ) +{ + NTSTATUS Status; + PBL_BCD_OPTION Option; + //PGUID AppIdentifier; + + /* Make sure this is a BCD_BOOLEAN */ + if ((Type & 0xF000000) != 0x6000000) + { + return STATUS_INVALID_PARAMETER; + } + + /* Return the data */ + Option = MiscGetBootOption(List, Type); + if (Option) + { + *Value = *(PBOOLEAN)((ULONG_PTR)Option + Option->DataOffset); + } + +#ifdef _SECURE_BOOT_ + /* Filter out SecureBoot Options */ + AppIdentifier = BlGetApplicationIdentifier(); + Status = BlpBootOptionCallbackBoolean(AppIdentifier, Type, Value); +#else + /* Option found */ + Status = Option ? STATUS_SUCCESS : STATUS_NOT_FOUND; +#endif + return Status; +} + /*++ * @name BlGetBootOptionListSize *