- 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
This commit is contained in:
Alex Ionescu 2015-09-09 18:09:04 +00:00
parent de917295f6
commit be0ecbd74e
5 changed files with 367 additions and 15 deletions

View file

@ -12,7 +12,6 @@
/* DATA VARIABLES ************************************************************/
#include <initguid.h>
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))
{

View file

@ -17,6 +17,7 @@
#include <wchar.h>
/* NT Base Headers */
#include <initguid.h>
#include <ntifs.h>
/* UEFI Headers */
@ -25,6 +26,9 @@
/* Boot Library Headers */
#include <bl.h>
/* BCD Headers */
#include <bcd.h>
/* FUNCTIONS *****************************************************************/
NTSTATUS

View file

@ -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;

View file

@ -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;

View file

@ -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
*