mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 20:03:12 +00:00
[BOOTLIB]: Separate out bcd.c into bcdopt.c, bootreg.c and bcd.c
[BOOTLIB]: Implement routines to enumerate subkeys and to read a key value. [BOOTLIB]: Implement routines to parse, enumerate, and convert registry data into BCD elements, and to convert BCD elements into boot library BCD options. [BOOTLIB/BOOTMGFW]: Lots of cleanups, mainly around the fact we now use ntintsafe.h instead of the manually self-inlined code from before, and from documenting additional flag values, and from using our newfound BCD powers. [BOOTMGFW]: Implement BmGetOptionList, BmpUpdateApplicationOptions. [BOOTMGFW]: Prepare for post-BCD library reinitialization. We correctly read the 3 BCD options so far in the hive. svn path=/trunk/; revision=70492
This commit is contained in:
parent
bdc681e191
commit
6e87f8eab7
12 changed files with 3204 additions and 1113 deletions
|
@ -12,6 +12,8 @@ list(APPEND BOOTLIB_SOURCE
|
||||||
lib/bootlib.c
|
lib/bootlib.c
|
||||||
lib/misc/debug.c
|
lib/misc/debug.c
|
||||||
lib/misc/bcd.c
|
lib/misc/bcd.c
|
||||||
|
lib/misc/bcdopt.c
|
||||||
|
lib/misc/bootreg.c
|
||||||
lib/misc/util.c
|
lib/misc/util.c
|
||||||
lib/misc/image.c
|
lib/misc/image.c
|
||||||
lib/firmware/efi/firmware.c
|
lib/firmware/efi/firmware.c
|
||||||
|
|
|
@ -31,8 +31,197 @@ BOOLEAN BmBootIniUsed;
|
||||||
WCHAR BmpFileNameBuffer[128];
|
WCHAR BmpFileNameBuffer[128];
|
||||||
PWCHAR ParentFileName = L"";
|
PWCHAR ParentFileName = L"";
|
||||||
|
|
||||||
|
BOOLEAN BmDisplayStateCached;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BmGetOptionList (
|
||||||
|
_In_ HANDLE BcdHandle,
|
||||||
|
_In_ PGUID ObjectId,
|
||||||
|
_In_ PBL_BCD_OPTION *OptionList
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE ObjectHandle;
|
||||||
|
ULONG ElementSize, ElementCount, i, OptionsSize;
|
||||||
|
BcdElementType Type;
|
||||||
|
PBCD_ELEMENT_HEADER Header;
|
||||||
|
PBCD_ELEMENT BcdElements;
|
||||||
|
PBL_BCD_OPTION Options, Option, PreviousOption, DeviceOptions;
|
||||||
|
PBCD_DEVICE_OPTION DeviceOption;
|
||||||
|
GUID DeviceId;
|
||||||
|
PVOID DeviceData;
|
||||||
|
|
||||||
|
/* Open the BCD object requested */
|
||||||
|
ObjectHandle = NULL;
|
||||||
|
BcdElements = NULL;
|
||||||
|
Status = BcdOpenObject(BcdHandle, ObjectId, &ObjectHandle);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the initial enumeration to get the size needed */
|
||||||
|
ElementSize = 0;
|
||||||
|
Status = BcdEnumerateAndUnpackElements(BcdHandle,
|
||||||
|
ObjectHandle,
|
||||||
|
NULL,
|
||||||
|
&ElementSize,
|
||||||
|
&ElementCount);
|
||||||
|
if (Status != STATUS_BUFFER_TOO_SMALL)
|
||||||
|
{
|
||||||
|
/* If we got success, that doesn't make any sense */
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bail out */
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a large-enough buffer */
|
||||||
|
BcdElements = BlMmAllocateHeap(ElementSize);
|
||||||
|
if (!BcdElements)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now do the real enumeration to fill out the elements buffer */
|
||||||
|
Status = BcdEnumerateAndUnpackElements(BcdHandle,
|
||||||
|
ObjectHandle,
|
||||||
|
BcdElements,
|
||||||
|
&ElementSize,
|
||||||
|
&ElementCount);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go through each BCD option to add the sizes up */
|
||||||
|
OptionsSize = 0;
|
||||||
|
for (i = 0; i < ElementCount; i++)
|
||||||
|
{
|
||||||
|
OptionsSize += BcdElements[i].Header->Size + sizeof(BL_BCD_OPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate the required BCD option list */
|
||||||
|
Options = BlMmAllocateHeap(OptionsSize);
|
||||||
|
if (!Options)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zero it out */
|
||||||
|
RtlZeroMemory(Options, OptionsSize);
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
Header = BcdElements[i].Header;
|
||||||
|
Type.PackedValue = Header->Type;
|
||||||
|
|
||||||
|
/* Check if this option isn't already present */
|
||||||
|
if (!MiscGetBootOption(Options, Type.PackedValue))
|
||||||
|
{
|
||||||
|
/* It's a new option. Did we have an existing one? */
|
||||||
|
if (PreviousOption)
|
||||||
|
{
|
||||||
|
/* Link it to this new one */
|
||||||
|
PreviousOption->NextEntryOffset = (ULONG_PTR)Option -
|
||||||
|
(ULONG_PTR)Options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Capture the type, size, data, and offset */
|
||||||
|
Option->Type = Type.PackedValue;
|
||||||
|
Option->DataSize = Header->Size;
|
||||||
|
RtlCopyMemory(Option + 1, BcdElements[i].Body, Header->Size);
|
||||||
|
Option->DataOffset = sizeof(BL_BCD_OPTION);
|
||||||
|
|
||||||
|
/* Check if this was a device */
|
||||||
|
if (Type.Format == BCD_TYPE_DEVICE)
|
||||||
|
{
|
||||||
|
/* Grab its GUID */
|
||||||
|
DeviceOption = (PBCD_DEVICE_OPTION)(Option + 1);
|
||||||
|
DeviceId = DeviceOption->AssociatedEntry;
|
||||||
|
|
||||||
|
/* Look up the options for that GUID */
|
||||||
|
Status = BmGetOptionList(BcdHandle, &DeviceId, &DeviceOptions);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Device data is after the device option */
|
||||||
|
DeviceData = (PVOID)((ULONG_PTR)DeviceOption + Header->Size);
|
||||||
|
|
||||||
|
/* Copy it */
|
||||||
|
RtlCopyMemory(DeviceData,
|
||||||
|
DeviceOptions,
|
||||||
|
BlGetBootOptionListSize(DeviceOptions));
|
||||||
|
|
||||||
|
/* Don't need this anymore */
|
||||||
|
BlMmFreeHeap(DeviceOptions);
|
||||||
|
|
||||||
|
/* Write the offset of the device options */
|
||||||
|
Option->ListOffset = (ULONG_PTR)DeviceData -
|
||||||
|
(ULONG_PTR)Option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save the previous option and go to the next one */
|
||||||
|
PreviousOption = Option;
|
||||||
|
Option = (PBL_BCD_OPTION)((ULONG_PTR)Option +
|
||||||
|
BlGetBootOptionSize(Option));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the pointer back, we've made it! */
|
||||||
|
*OptionList = Options;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* Did we allocate a local buffer? Free it if so */
|
||||||
|
if (BcdElements)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(BcdElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Was the key open? Close it if so */
|
||||||
|
if (ObjectHandle)
|
||||||
|
{
|
||||||
|
BiCloseKey(ObjectHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the option list parsing status */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BmpUpdateApplicationOptions (
|
||||||
|
_In_ HANDLE BcdHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PBL_BCD_OPTION Options;
|
||||||
|
|
||||||
|
/* Get the boot option list */
|
||||||
|
Status = BmGetOptionList(BcdHandle, &BmApplicationIdentifier, &Options);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the options, free the local buffer, and return success */
|
||||||
|
BlAppendBootOptions(&BlpApplicationEntry, Options);
|
||||||
|
BlMmFreeHeap(Options);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
BmpFwGetApplicationDirectoryPath (
|
BmpFwGetApplicationDirectoryPath (
|
||||||
_In_ PUNICODE_STRING ApplicationDirectoryPath
|
_In_ PUNICODE_STRING ApplicationDirectoryPath
|
||||||
|
@ -65,39 +254,14 @@ BmpFwGetApplicationDirectoryPath (
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we have space for one more character */
|
/* Check if we have space for one more character */
|
||||||
AppPathLength = i + 1;
|
Status = RtlULongAdd(i, 1, &AppPathLength);
|
||||||
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))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Check if it's safe to multiply by two */
|
/* Check if it's safe to multiply by two */
|
||||||
if ((AppPathLength * sizeof(WCHAR)) > 0xFFFFFFFF)
|
Status = RtlULongMult(AppPathLength, sizeof(WCHAR), &AppPathLength);
|
||||||
{
|
|
||||||
/* 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))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
/* Allocate a copy for the string */
|
||||||
PathCopy = BlMmAllocateHeap(AppPathLength);
|
PathCopy = BlMmAllocateHeap(AppPathLength);
|
||||||
if (PathCopy)
|
if (PathCopy)
|
||||||
{
|
{
|
||||||
|
@ -382,6 +546,38 @@ BmFatalErrorEx (
|
||||||
ErrorResourceId = 9002;
|
ErrorResourceId = 9002;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BL_FATAL_ERROR_BCD_PARSE:
|
||||||
|
|
||||||
|
/* File name isin parameter 1 */
|
||||||
|
FileName = (PWCHAR)Parameter1;
|
||||||
|
|
||||||
|
/* The NTSTATUS code is in parameter 2*/
|
||||||
|
ErrorStatus = (NTSTATUS)Parameter2;
|
||||||
|
|
||||||
|
/* Build the error string */
|
||||||
|
swprintf(FormatString,
|
||||||
|
L"\nThe boot configuration file %s is invalid (%08x).\n",
|
||||||
|
FileName,
|
||||||
|
ErrorStatus);
|
||||||
|
|
||||||
|
/* Select the resource ID message */
|
||||||
|
ErrorResourceId = 9015;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BL_FATAL_ERROR_GENERIC:
|
||||||
|
|
||||||
|
/* The NTSTATUS code is in parameter 1*/
|
||||||
|
ErrorStatus = (NTSTATUS)Parameter1;
|
||||||
|
|
||||||
|
/* Build the error string */
|
||||||
|
swprintf(FormatString,
|
||||||
|
L"\nThe boot manager experienced an error (%08x).\n",
|
||||||
|
ErrorStatus);
|
||||||
|
|
||||||
|
/* Select the resource ID message */
|
||||||
|
ErrorResourceId = 9005;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/* The rest is not yet handled */
|
/* The rest is not yet handled */
|
||||||
|
@ -427,25 +623,11 @@ BmpFwGetFullPath (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG BootDirLength, BootDirLengthWithNul;
|
ULONG BootDirLength, PathLength;
|
||||||
ULONG PathLength, FullPathLength;
|
|
||||||
|
|
||||||
/* Compute the length of the directory, and add a NUL */
|
/* Compute the length of the directory, and add a NUL */
|
||||||
BootDirLength = wcslen(BootDirectory);
|
BootDirLength = wcslen(BootDirectory);
|
||||||
BootDirLengthWithNul = BootDirLength + 1;
|
Status = RtlULongAdd(BootDirLength, 1, &BootDirLength);
|
||||||
if (BootDirLengthWithNul < BootDirLength)
|
|
||||||
{
|
|
||||||
/* This would overflow */
|
|
||||||
BootDirLengthWithNul = -1;
|
|
||||||
Status = STATUS_INTEGER_OVERFLOW;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* We have space */
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fail on overflow */
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
goto Quickie;
|
goto Quickie;
|
||||||
|
@ -453,33 +635,26 @@ BmpFwGetFullPath (
|
||||||
|
|
||||||
/* Add the length of the file, make sure it fits */
|
/* Add the length of the file, make sure it fits */
|
||||||
PathLength = wcslen(FileName);
|
PathLength = wcslen(FileName);
|
||||||
FullPathLength = PathLength + BootDirLength;
|
Status = RtlULongAdd(PathLength, BootDirLength, &PathLength);
|
||||||
if (FullPathLength < PathLength)
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Nope */
|
goto Quickie;
|
||||||
FullPathLength = -1;
|
|
||||||
Status = STATUS_INTEGER_OVERFLOW;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* All good */
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fail on overflow */
|
/* Convert to bytes */
|
||||||
|
Status = RtlULongLongToULong(PathLength * sizeof(WCHAR), &PathLength);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
goto Quickie;
|
goto Quickie;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the full path */
|
/* Allocate the full path */
|
||||||
FullPathLength = FullPathLength * sizeof(WCHAR);
|
*FullPath = BlMmAllocateHeap(PathLength);
|
||||||
*FullPath = BlMmAllocateHeap(FullPathLength);
|
|
||||||
if (*FullPath)
|
if (*FullPath)
|
||||||
{
|
{
|
||||||
/* Copy the directory followed by the file name */
|
/* Copy the directory followed by the file name */
|
||||||
wcsncpy(*FullPath, BootDirectory, FullPathLength / sizeof(WCHAR));
|
wcsncpy(*FullPath, BootDirectory, PathLength / sizeof(WCHAR));
|
||||||
wcsncat(*FullPath, FileName, FullPathLength / sizeof(WCHAR));
|
wcsncat(*FullPath, FileName, PathLength / sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -492,6 +667,22 @@ Quickie:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BmCloseDataStore (
|
||||||
|
_In_ HANDLE Handle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Check if boot.ini data needs to be freed */
|
||||||
|
if (BmBootIniUsed)
|
||||||
|
{
|
||||||
|
EfiPrintf(L"Not handled\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dereference the hive and close the key */
|
||||||
|
BiDereferenceHive(Handle);
|
||||||
|
BiCloseKey(Handle);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
BmOpenDataStore (
|
BmOpenDataStore (
|
||||||
_Out_ PHANDLE Handle
|
_Out_ PHANDLE Handle
|
||||||
|
@ -501,7 +692,7 @@ BmOpenDataStore (
|
||||||
PBL_DEVICE_DESCRIPTOR BcdDevice;
|
PBL_DEVICE_DESCRIPTOR BcdDevice;
|
||||||
PWCHAR BcdPath, FullPath, PathBuffer;
|
PWCHAR BcdPath, FullPath, PathBuffer;
|
||||||
BOOLEAN HavePath;
|
BOOLEAN HavePath;
|
||||||
ULONG PathLength, PathLengthWithNul, FullSize;
|
ULONG PathLength, FullSize;
|
||||||
PVOID FinalBuffer;
|
PVOID FinalBuffer;
|
||||||
UNICODE_STRING BcdString;
|
UNICODE_STRING BcdString;
|
||||||
|
|
||||||
|
@ -544,7 +735,7 @@ BmOpenDataStore (
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* We don't handle custom BCDs yet */
|
/* We don't handle custom BCDs yet */
|
||||||
EfiPrintf(L"Not handled\n");
|
EfiPrintf(L"Not handled: %s\r\n", BcdPath);
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
goto Quickie;
|
goto Quickie;
|
||||||
}
|
}
|
||||||
|
@ -579,35 +770,22 @@ BmOpenDataStore (
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a NUL to the path, make sure it'll fit */
|
/* Add a NUL to the path, make sure it'll fit */
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
PathLength = wcslen(PathBuffer);
|
PathLength = wcslen(PathBuffer);
|
||||||
PathLengthWithNul = PathLength + 1;
|
Status = RtlULongAdd(PathLength, 1, &PathLength);
|
||||||
if (PathLengthWithNul < PathLength)
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
PathLengthWithNul = -1;
|
goto Quickie;
|
||||||
Status = STATUS_INTEGER_OVERFLOW;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bail out if it doesn't fit */
|
/* Convert to bytes */
|
||||||
|
Status = RtlULongLongToULong(PathLength * sizeof(WCHAR), &PathLength);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
goto Quickie;
|
goto Quickie;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now add the size of the path to the device path, check if it fits */
|
/* Now add the size of the path to the device path, check if it fits */
|
||||||
PathLengthWithNul = PathLengthWithNul * sizeof(WCHAR);
|
Status = RtlULongAdd(PathLength, BcdDevice->Size, &FullSize);
|
||||||
FullSize = PathLengthWithNul + BcdDevice->Size;
|
|
||||||
if (FullSize < BcdDevice->Size)
|
|
||||||
{
|
|
||||||
FullSize = -1;
|
|
||||||
Status = STATUS_INTEGER_OVERFLOW;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bail out if it doesn't fit */
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
goto Quickie;
|
goto Quickie;
|
||||||
|
@ -625,7 +803,7 @@ BmOpenDataStore (
|
||||||
RtlCopyMemory(FinalBuffer, BcdDevice, BcdDevice->Size);
|
RtlCopyMemory(FinalBuffer, BcdDevice, BcdDevice->Size);
|
||||||
RtlCopyMemory((PVOID)((ULONG_PTR)FinalBuffer + BcdDevice->Size),
|
RtlCopyMemory((PVOID)((ULONG_PTR)FinalBuffer + BcdDevice->Size),
|
||||||
PathBuffer,
|
PathBuffer,
|
||||||
PathLengthWithNul);
|
PathLength);
|
||||||
|
|
||||||
/* Now tell the BCD engine to open the store */
|
/* Now tell the BCD engine to open the store */
|
||||||
BcdString.Length = FullSize;
|
BcdString.Length = FullSize;
|
||||||
|
@ -648,7 +826,11 @@ Quickie:
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Raise a fatal error */
|
/* Raise a fatal error */
|
||||||
BmFatalErrorEx(1, (ULONG_PTR)PathBuffer, Status, 0, 0);
|
BmFatalErrorEx(BL_FATAL_ERROR_BCD_READ,
|
||||||
|
(ULONG_PTR)PathBuffer,
|
||||||
|
Status,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Did we get an allocated path? */
|
/* Did we get an allocated path? */
|
||||||
|
@ -680,12 +862,13 @@ BmMain (
|
||||||
_In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters
|
_In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status, LibraryStatus;
|
||||||
BL_LIBRARY_PARAMETERS LibraryParameters;
|
BL_LIBRARY_PARAMETERS LibraryParameters;
|
||||||
PBL_RETURN_ARGUMENTS ReturnArguments;
|
PBL_RETURN_ARGUMENTS ReturnArguments;
|
||||||
BOOLEAN RebootOnError;
|
BOOLEAN RebootOnError;
|
||||||
PGUID AppIdentifier;
|
PGUID AppIdentifier;
|
||||||
HANDLE BcdHandle;
|
HANDLE BcdHandle;
|
||||||
|
PBL_BCD_OPTION EarlyOptions;
|
||||||
|
|
||||||
EfiPrintf(L"ReactOS UEFI Boot Manager Initializing...\n");
|
EfiPrintf(L"ReactOS UEFI Boot Manager Initializing...\n");
|
||||||
|
|
||||||
|
@ -734,12 +917,73 @@ BmMain (
|
||||||
|
|
||||||
/* Load and initialize the boot configuration database (BCD) */
|
/* Load and initialize the boot configuration database (BCD) */
|
||||||
Status = BmOpenDataStore(&BcdHandle);
|
Status = BmOpenDataStore(&BcdHandle);
|
||||||
EfiPrintf(L"BCD Open: %lx\r\n", Status);
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Copy the boot options */
|
||||||
|
Status = BlCopyBootOptions(BlpApplicationEntry.BcdData, &EarlyOptions);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Update them */
|
||||||
|
Status = BmpUpdateApplicationOptions(BcdHandle);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Log a fatal error */
|
||||||
|
BmFatalErrorEx(BL_FATAL_ERROR_BCD_PARSE,
|
||||||
|
(ULONG_PTR)L"\\BCD",
|
||||||
|
Status,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _SECURE_BOOT
|
||||||
|
/* Initialize the secure boot machine policy */
|
||||||
|
Status = BmSecureBootInitializeMachinePolicy();
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
BmFatalErrorEx(BL_FATAL_ERROR_SECURE_BOOT, Status, 0, 0, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Copy the library parameters and add the re-initialization flag */
|
||||||
|
RtlCopyMemory(&LibraryParameters,
|
||||||
|
&BlpLibraryParameters,
|
||||||
|
sizeof(LibraryParameters));
|
||||||
|
LibraryParameters.LibraryFlags |= (BL_LIBRARY_FLAG_REINITIALIZE_ALL |
|
||||||
|
BL_LIBRARY_FLAG_REINITIALIZE);
|
||||||
|
|
||||||
|
/* Now that we've parsed the BCD, re-initialize the library */
|
||||||
|
LibraryStatus = BlInitializeLibrary(BootParameters, &LibraryParameters);
|
||||||
|
if (!NT_SUCCESS(LibraryStatus) && (NT_SUCCESS(Status)))
|
||||||
|
{
|
||||||
|
Status = LibraryStatus;
|
||||||
|
}
|
||||||
|
|
||||||
/* do more stuff!! */
|
/* do more stuff!! */
|
||||||
EfiPrintf(L"We are A-OK!\r\n");
|
EfiPrintf(L"We are A-OKer!\r\n");
|
||||||
EfiStall(10000000);
|
EfiStall(10000000);
|
||||||
|
|
||||||
|
//Failure:
|
||||||
|
/* Check if we got here due to an internal error */
|
||||||
|
if (BmpInternalBootError)
|
||||||
|
{
|
||||||
|
/* If XML is available, display the error */
|
||||||
|
#if 0
|
||||||
|
if (XmlLoaded)
|
||||||
|
{
|
||||||
|
BmDisplayDumpError(0, 0);
|
||||||
|
BmErrorPurge();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Don't do a fatal error -- return back to firmware */
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Log a general fatal error once we're here */
|
||||||
|
BmFatalErrorEx(BL_FATAL_ERROR_GENERIC, Status, 0, 0, 0);
|
||||||
|
|
||||||
Quickie:
|
Quickie:
|
||||||
/* Check if we should reboot */
|
/* Check if we should reboot */
|
||||||
if ((RebootOnError) ||
|
if ((RebootOnError) ||
|
||||||
|
|
|
@ -49,7 +49,9 @@ typedef struct _BL_PACKED_BOOT_ERROR
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
} BL_PACKED_BOOT_ERROR, *PBL_PACKED_BOOT_ERROR;
|
} BL_PACKED_BOOT_ERROR, *PBL_PACKED_BOOT_ERROR;
|
||||||
|
|
||||||
#define BL_FATAL_ERROR_BCD_READ 0x01
|
#define BL_FATAL_ERROR_BCD_READ 0x01
|
||||||
|
#define BL_FATAL_ERROR_GENERIC 0x04
|
||||||
|
#define BL_FATAL_ERROR_BCD_PARSE 0x07
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,21 @@
|
||||||
|
|
||||||
/* ENUMERATIONS **************************************************************/
|
/* ENUMERATIONS **************************************************************/
|
||||||
|
|
||||||
|
/* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa964229(v=vs.85).aspx */
|
||||||
|
|
||||||
|
#define BCD_CLASS_LIBRARY 0x01
|
||||||
|
#define BCD_CLASS_APPLICATION 0x02
|
||||||
|
#define BCD_CLASS_DEVICE 0x03
|
||||||
|
#define BCD_CLASS_OEM 0x05
|
||||||
|
|
||||||
|
#define BCD_TYPE_DEVICE 0x01
|
||||||
|
#define BCD_TYPE_STRING 0x02
|
||||||
|
#define BCD_TYPE_OBJECT 0x03
|
||||||
|
#define BCD_TYPE_OBJECT_LIST 0x04
|
||||||
|
#define BCD_TYPE_INTEGER 0x05
|
||||||
|
#define BCD_TYPE_BOOLEAN 0x06
|
||||||
|
#define BCD_TYPE_INTEGER_LIST 0x07
|
||||||
|
|
||||||
typedef enum BcdLibraryElementTypes
|
typedef enum BcdLibraryElementTypes
|
||||||
{
|
{
|
||||||
BcdLibraryDevice_ApplicationDevice = 0x11000001,
|
BcdLibraryDevice_ApplicationDevice = 0x11000001,
|
||||||
|
@ -155,9 +170,43 @@ typedef enum BcdBootMgrElementTypes
|
||||||
BcdBootMgrBoolean_PersistBootSequence = 0x26000031
|
BcdBootMgrBoolean_PersistBootSequence = 0x26000031
|
||||||
} BcdBootMgrElementTypes;
|
} BcdBootMgrElementTypes;
|
||||||
|
|
||||||
|
|
||||||
/* DATA STRUCTURES ***********************************************************/
|
/* DATA STRUCTURES ***********************************************************/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
ULONG PackedValue;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
ULONG SubType : 24;
|
||||||
|
ULONG Format : 4;
|
||||||
|
ULONG Class : 4;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} BcdElementType;
|
||||||
|
|
||||||
|
typedef struct _BCD_ELEMENT_HEADER
|
||||||
|
{
|
||||||
|
ULONG Version;
|
||||||
|
ULONG Type;
|
||||||
|
ULONG Size;
|
||||||
|
} BCD_ELEMENT_HEADER, *PBCD_ELEMENT_HEADER;
|
||||||
|
|
||||||
|
typedef struct _BCD_PACKED_ELEMENT
|
||||||
|
{
|
||||||
|
struct _BCD_PACKED_ELEMENT* NextEntry;
|
||||||
|
BcdElementType RootType;
|
||||||
|
BCD_ELEMENT_HEADER;
|
||||||
|
UCHAR Data[ANYSIZE_ARRAY];
|
||||||
|
} BCD_PACKED_ELEMENT, *PBCD_PACKED_ELEMENT;
|
||||||
|
|
||||||
|
typedef struct _BCD_ELEMENT
|
||||||
|
{
|
||||||
|
PBCD_ELEMENT_HEADER Header;
|
||||||
|
PUCHAR Body;
|
||||||
|
} BCD_ELEMENT, *PBCD_ELEMENT;
|
||||||
|
|
||||||
typedef struct _BCD_DEVICE_OPTION
|
typedef struct _BCD_DEVICE_OPTION
|
||||||
{
|
{
|
||||||
GUID AssociatedEntry;
|
GUID AssociatedEntry;
|
||||||
|
@ -172,4 +221,35 @@ BcdOpenStoreFromFile (
|
||||||
_In_ PHANDLE StoreHandle
|
_In_ PHANDLE StoreHandle
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#define BCD_ENUMERATE_FLAG_DEEP 0x04
|
||||||
|
#define BCD_ENUMERATE_FLAG_DEVICES 0x08
|
||||||
|
#define BCD_ENUMERATE_FLAG_IN_ORDER 0x10
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BiEnumerateElements (
|
||||||
|
_In_ HANDLE BcdHandle,
|
||||||
|
_In_ HANDLE ObjectHandle,
|
||||||
|
_In_ ULONG RootElementType,
|
||||||
|
_In_ ULONG Flags,
|
||||||
|
_Out_opt_ PBCD_PACKED_ELEMENT Elements,
|
||||||
|
_Inout_ PULONG ElementSize,
|
||||||
|
_Out_ PULONG ElementCountNe
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BcdOpenObject (
|
||||||
|
_In_ HANDLE BcdHandle,
|
||||||
|
_In_ PGUID ObjectId,
|
||||||
|
_Out_ PHANDLE ObjectHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BcdEnumerateAndUnpackElements (
|
||||||
|
_In_ HANDLE BcdHandle,
|
||||||
|
_In_ HANDLE ObjectHandle,
|
||||||
|
_Out_opt_ PBCD_ELEMENT Elements,
|
||||||
|
_Inout_ PULONG ElementSize,
|
||||||
|
_Out_ PULONG ElementCount
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
/* NDK Headers */
|
/* NDK Headers */
|
||||||
#include <ntndk.h>
|
#include <ntndk.h>
|
||||||
|
|
||||||
|
/* NT SafeInt Header */
|
||||||
|
#include <ntintsafe.h>
|
||||||
|
|
||||||
/* UEFI Headers */
|
/* UEFI Headers */
|
||||||
#include <Uefi.h>
|
#include <Uefi.h>
|
||||||
#include <DevicePath.h>
|
#include <DevicePath.h>
|
||||||
|
@ -52,7 +55,9 @@
|
||||||
#define BL_FIRMWARE_DESCRIPTOR_VERSION 2
|
#define BL_FIRMWARE_DESCRIPTOR_VERSION 2
|
||||||
|
|
||||||
#define BL_APPLICATION_ENTRY_FLAG_NO_GUID 0x01
|
#define BL_APPLICATION_ENTRY_FLAG_NO_GUID 0x01
|
||||||
|
#define BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL 0x02
|
||||||
#define BL_APPLICATION_ENTRY_REBOOT_ON_ERROR 0x20
|
#define BL_APPLICATION_ENTRY_REBOOT_ON_ERROR 0x20
|
||||||
|
#define BL_APPLICATION_ENTRY_BCD_OPTIONS_EXTERNAL 0x80
|
||||||
|
|
||||||
#define BL_CONTEXT_PAGING_ON 1
|
#define BL_CONTEXT_PAGING_ON 1
|
||||||
#define BL_CONTEXT_INTERRUPTS_ON 2
|
#define BL_CONTEXT_INTERRUPTS_ON 2
|
||||||
|
@ -716,9 +721,9 @@ typedef struct _BL_LOCAL_DEVICE
|
||||||
|
|
||||||
typedef struct _BL_DEVICE_DESCRIPTOR
|
typedef struct _BL_DEVICE_DESCRIPTOR
|
||||||
{
|
{
|
||||||
ULONG Size;
|
|
||||||
ULONG Flags;
|
|
||||||
DEVICE_TYPE DeviceType;
|
DEVICE_TYPE DeviceType;
|
||||||
|
ULONG Flags;
|
||||||
|
ULONG Size;
|
||||||
ULONG Unknown;
|
ULONG Unknown;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
@ -1424,7 +1429,18 @@ BlHtCreate (
|
||||||
_Out_ PULONG Id
|
_Out_ PULONG Id
|
||||||
);
|
);
|
||||||
|
|
||||||
/* BCD ROUTINES **************************************************************/
|
/* BCD OPTION ROUTINES *******************************************************/
|
||||||
|
|
||||||
|
PBL_BCD_OPTION
|
||||||
|
MiscGetBootOption (
|
||||||
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
_In_ ULONG Type
|
||||||
|
);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
BlGetBootOptionListSize (
|
||||||
|
_In_ PBL_BCD_OPTION BcdOption
|
||||||
|
);
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
BlGetBootOptionSize (
|
BlGetBootOptionSize (
|
||||||
|
@ -1452,6 +1468,15 @@ BlGetBootOptionBoolean (
|
||||||
_Out_ PBOOLEAN Value
|
_Out_ PBOOLEAN Value
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlpGetBootOptionIntegerList (
|
||||||
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
_In_ ULONG Type,
|
||||||
|
_Out_ PULONGLONG* Value,
|
||||||
|
_Out_ PULONGLONG Count,
|
||||||
|
_In_ BOOLEAN NoCopy
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
BlGetBootOptionDevice (
|
BlGetBootOptionDevice (
|
||||||
_In_ PBL_BCD_OPTION List,
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
@ -1460,6 +1485,68 @@ BlGetBootOptionDevice (
|
||||||
_In_opt_ PBL_BCD_OPTION* ExtraOptions
|
_In_opt_ PBL_BCD_OPTION* ExtraOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlGetBootOptionGuidList (
|
||||||
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
_In_ ULONG Type,
|
||||||
|
_Out_ PGUID *Value,
|
||||||
|
_In_ PULONG Count
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlCopyBootOptions (
|
||||||
|
_In_ PBL_BCD_OPTION OptionList,
|
||||||
|
_Out_ PBL_BCD_OPTION *CopiedOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlAppendBootOptions (
|
||||||
|
_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,
|
||||||
|
_In_ PBL_BCD_OPTION Options
|
||||||
|
);
|
||||||
|
|
||||||
|
/* BOOT REGISTRY ROUTINES ****************************************************/
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BiCloseKey (
|
||||||
|
_In_ HANDLE KeyHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BiOpenKey(
|
||||||
|
_In_ HANDLE ParentHandle,
|
||||||
|
_In_ PWCHAR KeyName,
|
||||||
|
_Out_ PHANDLE Handle
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BiLoadHive (
|
||||||
|
_In_ PBL_FILE_PATH_DESCRIPTOR FilePath,
|
||||||
|
_Out_ PHANDLE HiveHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BiGetRegistryValue (
|
||||||
|
_In_ HANDLE KeyHandle,
|
||||||
|
_In_ PWCHAR ValueName,
|
||||||
|
_In_ PWCHAR KeyName,
|
||||||
|
_In_ ULONG Type,
|
||||||
|
_Out_ PVOID* Buffer,
|
||||||
|
_Out_ PULONG ValueLength
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BiEnumerateSubKeys (
|
||||||
|
_In_ HANDLE KeyHandle,
|
||||||
|
_Out_ PWCHAR** SubKeyList,
|
||||||
|
_Out_ PULONG SubKeyCount
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BiDereferenceHive (
|
||||||
|
_In_ HANDLE KeyHandle
|
||||||
|
);
|
||||||
|
|
||||||
/* CONTEXT ROUTINES **********************************************************/
|
/* CONTEXT ROUTINES **********************************************************/
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -1561,6 +1648,16 @@ MmFwGetMemoryMap (
|
||||||
_In_ ULONG Flags
|
_In_ ULONG Flags
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlpMmInitializeConstraints (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlMmRemoveBadMemory (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
/* VIRTUAL MEMORY ROUTINES ***************************************************/
|
/* VIRTUAL MEMORY ROUTINES ***************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -86,11 +86,15 @@ InitializeLibrary (
|
||||||
BlpApplicationParameters = BootAppParameters;
|
BlpApplicationParameters = BootAppParameters;
|
||||||
BlpLibraryParameters = *LibraryParameters;
|
BlpLibraryParameters = *LibraryParameters;
|
||||||
|
|
||||||
/* Save the application entry flags */
|
/* Check if the caller sent us their internal BCD options */
|
||||||
if (AppEntry->Flags & 2)
|
if (AppEntry->Flags & BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL)
|
||||||
{
|
{
|
||||||
AppEntry->Flags = (AppEntry->Flags & ~0x2) | 0x80;
|
/* These are external to us now, as far as we are concerned */
|
||||||
|
AppEntry->Flags &= ~BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL;
|
||||||
|
AppEntry->Flags |= BL_APPLICATION_ENTRY_BCD_OPTIONS_EXTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save the application entry flags */
|
||||||
BlpApplicationEntry.Flags = AppEntry->Flags;
|
BlpApplicationEntry.Flags = AppEntry->Flags;
|
||||||
|
|
||||||
/* Copy the GUID and point to the options */
|
/* Copy the GUID and point to the options */
|
||||||
|
@ -363,15 +367,24 @@ BlInitializeLibrary(
|
||||||
BlpLibraryParameters = *LibraryParameters;
|
BlpLibraryParameters = *LibraryParameters;
|
||||||
if (LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_REINITIALIZE_ALL)
|
if (LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_REINITIALIZE_ALL)
|
||||||
{
|
{
|
||||||
#if 0
|
#ifdef BL_TPM_SUPPORT
|
||||||
/* Initialize all the core modules again */
|
/* Reinitialize the TPM security enclave as BCD hash changed */
|
||||||
BlpSiInitialize(1);
|
BlpSiInitialize(1);
|
||||||
|
#endif
|
||||||
|
#ifdef BL_KD_SUPPORT
|
||||||
|
/* Reinitialize the boot debugger as BCD debug options changed */
|
||||||
BlBdInitialize();
|
BlBdInitialize();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Reparse the bad page list now that the BCD has been reloaded */
|
||||||
BlMmRemoveBadMemory();
|
BlMmRemoveBadMemory();
|
||||||
|
|
||||||
|
/* Reparse the low/high physical address limits as well */
|
||||||
BlpMmInitializeConstraints();
|
BlpMmInitializeConstraints();
|
||||||
|
|
||||||
/* Redraw the graphics console as needed */
|
/* Redraw the graphics console as needed */
|
||||||
BlpDisplayInitialize(LibraryParameters->LibraryFlags);
|
BlpDisplayInitialize(LibraryParameters->LibraryFlags);
|
||||||
|
#if 0
|
||||||
BlpResourceInitialize();
|
BlpResourceInitialize();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ DsppGraphicsDisabledByBcd (
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
//EarlyPrint(L"Disabling graphics\r\n");
|
EfiPrintf(L"Disabling graphics\r\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,10 +53,10 @@ DsppInitialize (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BL_LIBRARY_PARAMETERS LibraryParameters = BlpLibraryParameters;
|
BL_LIBRARY_PARAMETERS LibraryParameters = BlpLibraryParameters;
|
||||||
BOOLEAN NoGraphics;// , HighestMode;
|
BOOLEAN NoGraphics, HighestMode;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PBL_DISPLAY_MODE DisplayMode;
|
PBL_DISPLAY_MODE DisplayMode;
|
||||||
//ULONG GraphicsResolution;
|
ULONGLONG GraphicsResolution;
|
||||||
PBL_GRAPHICS_CONSOLE GraphicsConsole;
|
PBL_GRAPHICS_CONSOLE GraphicsConsole;
|
||||||
PBL_TEXT_CONSOLE TextConsole, RemoteConsole;
|
PBL_TEXT_CONSOLE TextConsole, RemoteConsole;
|
||||||
|
|
||||||
|
@ -100,14 +100,9 @@ DsppInitialize (
|
||||||
DisplayMode = &ConsoleGraphicalResolutionList[0];
|
DisplayMode = &ConsoleGraphicalResolutionList[0];
|
||||||
|
|
||||||
/* Check what resolution to use*/
|
/* Check what resolution to use*/
|
||||||
#if 0
|
|
||||||
Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
|
Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
|
||||||
BcdLibraryInteger_GraphicsResolution,
|
BcdLibraryInteger_GraphicsResolution,
|
||||||
&GraphicsResolution);
|
&GraphicsResolution);
|
||||||
#else
|
|
||||||
//GraphicsResolution = 0;
|
|
||||||
Status = STATUS_NOT_FOUND;
|
|
||||||
#endif
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG;
|
ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG;
|
||||||
|
@ -116,14 +111,9 @@ DsppInitialize (
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the highest mode should be forced */
|
/* Check if the highest mode should be forced */
|
||||||
#if 0
|
|
||||||
Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
|
Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
|
||||||
BcdLibraryBoolean_GraphicsForceHighestMode,
|
BcdLibraryBoolean_GraphicsForceHighestMode,
|
||||||
&HighestMode);
|
&HighestMode);
|
||||||
#else
|
|
||||||
//HighestMode = 0;
|
|
||||||
Status = STATUS_NOT_FOUND;
|
|
||||||
#endif
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG;
|
ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG;
|
||||||
|
@ -233,6 +223,7 @@ BlpDisplayInitialize (
|
||||||
{
|
{
|
||||||
/* This is a reset */
|
/* This is a reset */
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
EfiPrintf(L"Display reset not yet implemented\r\n");
|
||||||
#if 0
|
#if 0
|
||||||
Status = DsppReinitialize(Flags);
|
Status = DsppReinitialize(Flags);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
|
|
File diff suppressed because it is too large
Load diff
647
reactos/boot/environ/lib/misc/bcdopt.c
Normal file
647
reactos/boot/environ/lib/misc/bcdopt.c
Normal file
|
@ -0,0 +1,647 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING.ARM in the top level directory
|
||||||
|
* PROJECT: ReactOS UEFI Boot Library
|
||||||
|
* FILE: boot/environ/lib/misc/bcdopt.c
|
||||||
|
* PURPOSE: Boot Library BCD Option Parsing Routines
|
||||||
|
* PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include "bl.h"
|
||||||
|
#include <bcd.h>
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
PBL_BCD_OPTION
|
||||||
|
MiscGetBootOption (
|
||||||
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
_In_ ULONG Type
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG_PTR NextOption = 0, ListOption;
|
||||||
|
PBL_BCD_OPTION Option, FoundOption;
|
||||||
|
|
||||||
|
/* No options, bail out */
|
||||||
|
if (!List)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop while we find an option */
|
||||||
|
FoundOption = NULL;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* 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))
|
||||||
|
{
|
||||||
|
FoundOption = Option;
|
||||||
|
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);
|
||||||
|
if (Option)
|
||||||
|
{
|
||||||
|
/* Return it */
|
||||||
|
FoundOption = Option;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (NextOption);
|
||||||
|
|
||||||
|
/* Return the option that was found, if any */
|
||||||
|
return FoundOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*++
|
||||||
|
* @name BlGetBootOptionListSize
|
||||||
|
*
|
||||||
|
* The BlGetBootOptionListSize routine
|
||||||
|
*
|
||||||
|
* @param BcdOption
|
||||||
|
* UEFI Image Handle for the current loaded application.
|
||||||
|
*
|
||||||
|
* @return Size of the BCD option
|
||||||
|
*
|
||||||
|
*--*/
|
||||||
|
ULONG
|
||||||
|
BlGetBootOptionListSize (
|
||||||
|
_In_ PBL_BCD_OPTION BcdOption
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG Size = 0, NextOffset = 0;
|
||||||
|
PBL_BCD_OPTION NextOption;
|
||||||
|
|
||||||
|
/* Loop all the options*/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Move to the next one */
|
||||||
|
NextOption = (PBL_BCD_OPTION)((ULONG_PTR)BcdOption + NextOffset);
|
||||||
|
|
||||||
|
/* Compute the size of the next one */
|
||||||
|
Size += BlGetBootOptionSize(NextOption);
|
||||||
|
|
||||||
|
/* Update the offset */
|
||||||
|
NextOffset = NextOption->NextEntryOffset;
|
||||||
|
} while (NextOffset);
|
||||||
|
|
||||||
|
/* Return final computed size */
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*++
|
||||||
|
* @name BlGetBootOptionSize
|
||||||
|
*
|
||||||
|
* The BlGetBootOptionSize routine
|
||||||
|
*
|
||||||
|
* @param BcdOption
|
||||||
|
* UEFI Image Handle for the current loaded application.
|
||||||
|
*
|
||||||
|
* @return Size of the BCD option
|
||||||
|
*
|
||||||
|
*--*/
|
||||||
|
ULONG
|
||||||
|
BlGetBootOptionSize (
|
||||||
|
_In_ PBL_BCD_OPTION BcdOption
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG Size, Offset;
|
||||||
|
|
||||||
|
/* Check if there's any data */
|
||||||
|
if (BcdOption->DataOffset)
|
||||||
|
{
|
||||||
|
/* Add the size of the data */
|
||||||
|
Size = BcdOption->DataOffset + BcdOption->DataSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No data, just the structure itself */
|
||||||
|
Size = sizeof(*BcdOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Any associated options? */
|
||||||
|
Offset = BcdOption->ListOffset;
|
||||||
|
if (Offset)
|
||||||
|
{
|
||||||
|
/* Go get those too */
|
||||||
|
Size += BlGetBootOptionListSize((PVOID)((ULONG_PTR)BcdOption + Offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the final size */
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlGetBootOptionString (
|
||||||
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
_In_ ULONG Type,
|
||||||
|
_Out_ PWCHAR* Value
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PBL_BCD_OPTION Option;
|
||||||
|
PWCHAR String, StringCopy;
|
||||||
|
ULONG StringLength;
|
||||||
|
BcdElementType ElementType;
|
||||||
|
//PGUID AppIdentifier;
|
||||||
|
|
||||||
|
/* Make sure this is a BCD_STRING */
|
||||||
|
ElementType.PackedValue = Type;
|
||||||
|
if (ElementType.Format != BCD_TYPE_STRING)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the data */
|
||||||
|
Option = MiscGetBootOption(List, Type);
|
||||||
|
if (Option)
|
||||||
|
{
|
||||||
|
/* Extract the string */
|
||||||
|
String = (PWCHAR)((ULONG_PTR)Option + Option->DataOffset);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No string is present */
|
||||||
|
String = NULL;
|
||||||
|
Status = STATUS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Make sure we have a valid, non-filtered string */
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Check if we have space for one more character */
|
||||||
|
Status = RtlULongAdd(StringLength, 1, &StringLength);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Check if it's safe to multiply by two */
|
||||||
|
Status = RtlULongMult(StringLength, sizeof(WCHAR), &StringLength);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Allocate a copy for the string */
|
||||||
|
StringCopy = BlMmAllocateHeap(StringLength);
|
||||||
|
if (StringCopy)
|
||||||
|
{
|
||||||
|
/* NULL-terminate it */
|
||||||
|
RtlCopyMemory(StringCopy,
|
||||||
|
String,
|
||||||
|
StringLength - sizeof(UNICODE_NULL));
|
||||||
|
StringCopy[StringLength] = UNICODE_NULL;
|
||||||
|
*Value = StringCopy;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No memory, fail */
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All done */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlGetBootOptionGuidList (
|
||||||
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
_In_ ULONG Type,
|
||||||
|
_Out_ PGUID *Value,
|
||||||
|
_In_ PULONG Count
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PBL_BCD_OPTION Option;
|
||||||
|
PGUID GuidCopy, Guid;
|
||||||
|
ULONG GuidCount;
|
||||||
|
BcdElementType ElementType;
|
||||||
|
|
||||||
|
/* Make sure this is a BCD_TYPE_OBJECT_LIST */
|
||||||
|
ElementType.PackedValue = Type;
|
||||||
|
if (ElementType.Format != BCD_TYPE_OBJECT_LIST)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the data */
|
||||||
|
Option = MiscGetBootOption(List, Type);
|
||||||
|
if (!Option)
|
||||||
|
{
|
||||||
|
/* Set failure if no data exists */
|
||||||
|
Status = STATUS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Get the GUIDs and allocate a copy for them */
|
||||||
|
Guid = (PGUID)((ULONG_PTR)Option + Option->DataOffset);
|
||||||
|
GuidCopy = BlMmAllocateHeap(Option->DataSize);
|
||||||
|
if (GuidCopy)
|
||||||
|
{
|
||||||
|
/* Copy the GUIDs */
|
||||||
|
RtlCopyMemory(GuidCopy, Guid, Option->DataSize);
|
||||||
|
|
||||||
|
/* Return the number of GUIDs and the start of the array */
|
||||||
|
GuidCount = Option->DataSize / sizeof(GUID);
|
||||||
|
*Value = GuidCopy;
|
||||||
|
*Count = GuidCount;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No memory for the copy */
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All good */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlGetBootOptionDevice (
|
||||||
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
_In_ ULONG Type,
|
||||||
|
_Out_ PBL_DEVICE_DESCRIPTOR* Value,
|
||||||
|
_In_opt_ PBL_BCD_OPTION* ExtraOptions
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PBL_BCD_OPTION Option, ListData, ListCopy, SecureListData;
|
||||||
|
PBCD_DEVICE_OPTION BcdDevice;
|
||||||
|
ULONG DeviceSize, ListOffset, ListSize;
|
||||||
|
PBL_DEVICE_DESCRIPTOR DeviceDescriptor, SecureDescriptor;
|
||||||
|
//PGUID AppIdentifier;
|
||||||
|
BcdElementType ElementType;
|
||||||
|
|
||||||
|
/* Make sure this is a BCD_TYPE_DEVICE */
|
||||||
|
ElementType.PackedValue = Type;
|
||||||
|
if (ElementType.Format != BCD_TYPE_DEVICE)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the data */
|
||||||
|
Option = MiscGetBootOption(List, Type);
|
||||||
|
if (!Option)
|
||||||
|
{
|
||||||
|
/* Set failure if no data exists */
|
||||||
|
Status = STATUS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise, read the size of the BCD device encoded */
|
||||||
|
BcdDevice = (PBCD_DEVICE_OPTION)((ULONG_PTR)Option + Option->DataOffset);
|
||||||
|
DeviceSize = BcdDevice->DeviceDescriptor.Size;
|
||||||
|
|
||||||
|
/* Allocate a buffer to copy it into */
|
||||||
|
DeviceDescriptor = BlMmAllocateHeap(DeviceSize);
|
||||||
|
if (!DeviceDescriptor)
|
||||||
|
{
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy it into that buffer */
|
||||||
|
RtlCopyMemory(DeviceDescriptor, &BcdDevice->DeviceDescriptor, DeviceSize);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if extra options were requested */
|
||||||
|
if (ExtraOptions)
|
||||||
|
{
|
||||||
|
/* See where they are */
|
||||||
|
ListOffset = Option->ListOffset;
|
||||||
|
if (ListOffset)
|
||||||
|
{
|
||||||
|
/* See how big they are */
|
||||||
|
ListData = (PBL_BCD_OPTION)((ULONG_PTR)Option + ListOffset);
|
||||||
|
ListSize = BlGetBootOptionListSize(ListData);
|
||||||
|
|
||||||
|
/* Allocate a buffer to hold them into */
|
||||||
|
ListCopy = BlMmAllocateHeap(ListSize);
|
||||||
|
if (!ListCopy)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy them in there */
|
||||||
|
RtlCopyMemory(ListCopy, ListData, ListSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _SECURE_BOOT_
|
||||||
|
/* Filter out SecureBoot Options */
|
||||||
|
AppIdentifier = BlGetApplicationIdentifier();
|
||||||
|
if (BlpBootOptionCallbacks)
|
||||||
|
{
|
||||||
|
DeviceCallback = BlpBootOptionCallbacks->Device;
|
||||||
|
if (DeviceCallback)
|
||||||
|
{
|
||||||
|
Status = DeviceCallback(BlpBootOptionCallbackCookie,
|
||||||
|
Status,
|
||||||
|
0,
|
||||||
|
AppIdentifier,
|
||||||
|
Type,
|
||||||
|
&SecureDescriptor,
|
||||||
|
PtrOptionData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* No secure boot, so the secure descriptors are the standard ones */
|
||||||
|
SecureDescriptor = DeviceDescriptor;
|
||||||
|
SecureListData = ListCopy;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check if the data was read correctly */
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Check if we had a new descriptor after filtering */
|
||||||
|
if (SecureDescriptor != DeviceDescriptor)
|
||||||
|
{
|
||||||
|
/* Yep -- if we had an old one, free it */
|
||||||
|
if (DeviceDescriptor)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(DeviceDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we had a new list after filtering */
|
||||||
|
if (SecureListData != ListCopy)
|
||||||
|
{
|
||||||
|
/* Yep -- if we had an old list, free it */
|
||||||
|
if (ListCopy)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(ListCopy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, check if the caller wanted extra options */
|
||||||
|
if (ExtraOptions)
|
||||||
|
{
|
||||||
|
/* Yep -- so pass the caller our copy */
|
||||||
|
*ExtraOptions = ListCopy;
|
||||||
|
ListCopy = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Caller always wants data back, so pass them our copy */
|
||||||
|
*Value = DeviceDescriptor;
|
||||||
|
DeviceDescriptor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* On the failure path, if these buffers are active, we should free them */
|
||||||
|
if (ListCopy)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(ListCopy);
|
||||||
|
}
|
||||||
|
if (DeviceDescriptor)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(DeviceDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
BcdElementType ElementType;
|
||||||
|
|
||||||
|
/* Make sure this is a BCD_TYPE_INTEGER */
|
||||||
|
ElementType.PackedValue = Type;
|
||||||
|
if (ElementType.Format != BCD_TYPE_INTEGER)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
BcdElementType ElementType;
|
||||||
|
|
||||||
|
/* Make sure this is a BCD_TYPE_BOOLEAN */
|
||||||
|
ElementType.PackedValue = Type;
|
||||||
|
if (ElementType.Format != BCD_TYPE_BOOLEAN)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlpGetBootOptionIntegerList (
|
||||||
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
_In_ ULONG Type,
|
||||||
|
_Out_ PULONGLONG* Value,
|
||||||
|
_Out_ PULONGLONG Count,
|
||||||
|
_In_ BOOLEAN NoCopy
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PBL_BCD_OPTION Option;
|
||||||
|
BcdElementType ElementType;
|
||||||
|
PULONGLONG ValueCopy;
|
||||||
|
|
||||||
|
/* Make sure this is a BCD_TYPE_INTEGER_LIST */
|
||||||
|
ElementType.PackedValue = Type;
|
||||||
|
if (ElementType.Format != BCD_TYPE_INTEGER_LIST)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the data */
|
||||||
|
Option = MiscGetBootOption(List, Type);
|
||||||
|
if (!Option)
|
||||||
|
{
|
||||||
|
return STATUS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if a copy should be made of it */
|
||||||
|
if (NoCopy)
|
||||||
|
{
|
||||||
|
/* Nope, return the raw value */
|
||||||
|
*Value = (PULONGLONG)((ULONG_PTR)Option + Option->DataOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Allocate a buffer for the copy */
|
||||||
|
ValueCopy = BlMmAllocateHeap(Option->DataSize);
|
||||||
|
if (!ValueCopy)
|
||||||
|
{
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the data in */
|
||||||
|
RtlCopyMemory(ValueCopy,
|
||||||
|
(PVOID)((ULONG_PTR)Option + Option->DataOffset),
|
||||||
|
Option->DataSize);
|
||||||
|
|
||||||
|
/* Return our copy */
|
||||||
|
*Value = ValueCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return count and success */
|
||||||
|
*Count = Option->DataSize / sizeof(ULONGLONG);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlCopyBootOptions (
|
||||||
|
_In_ PBL_BCD_OPTION OptionList,
|
||||||
|
_Out_ PBL_BCD_OPTION *CopiedOptions
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG OptionSize;
|
||||||
|
PBL_BCD_OPTION Options;
|
||||||
|
|
||||||
|
/* Assume no options */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
*CopiedOptions = NULL;
|
||||||
|
|
||||||
|
/* Get the size of the list and allocate a copy for it */
|
||||||
|
OptionSize = BlGetBootOptionListSize(OptionList);
|
||||||
|
Options = BlMmAllocateHeap(OptionSize);
|
||||||
|
if (!Options)
|
||||||
|
{
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make the copy and return it to the caller */
|
||||||
|
RtlCopyMemory(Options, OptionList, OptionSize);
|
||||||
|
*CopiedOptions = Options;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlAppendBootOptions (
|
||||||
|
_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,
|
||||||
|
_In_ PBL_BCD_OPTION Options
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG OptionsSize, CurrentSize;
|
||||||
|
PBL_BCD_OPTION NewOptions, CurrentOptions, NextOption;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG CurrentOffset;
|
||||||
|
|
||||||
|
/* Get the current options */
|
||||||
|
CurrentOptions = AppEntry->BcdData;
|
||||||
|
|
||||||
|
/* Calculate the size of the current, and the appended options */
|
||||||
|
CurrentSize = BlGetBootOptionListSize(CurrentOptions);
|
||||||
|
OptionsSize = BlGetBootOptionListSize(Options);
|
||||||
|
|
||||||
|
/* Allocate a buffer for the concatenated (new) options */
|
||||||
|
NewOptions = BlMmAllocateHeap(CurrentSize + OptionsSize);
|
||||||
|
if (!NewOptions)
|
||||||
|
{
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the old options, and the ones to be added */
|
||||||
|
RtlCopyMemory(NewOptions, CurrentOptions, CurrentSize);
|
||||||
|
RtlCopyMemory(&NewOptions[OptionsSize], Options, OptionsSize);
|
||||||
|
|
||||||
|
/* We made it! */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
/* Scan through to the last option in the list */
|
||||||
|
CurrentOffset = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
NextOption = (PBL_BCD_OPTION)((ULONG_PTR)NewOptions + CurrentOffset);
|
||||||
|
CurrentOffset = NextOption->NextEntryOffset;
|
||||||
|
} while (CurrentOffset);
|
||||||
|
|
||||||
|
/* Every other option now has to have its offset adjusted */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
NextOption->NextEntryOffset += OptionsSize;
|
||||||
|
NextOption = (PBL_BCD_OPTION)((ULONG_PTR)NewOptions + NextOption->NextEntryOffset);
|
||||||
|
} while (NextOption->NextEntryOffset);
|
||||||
|
|
||||||
|
/* If we already had internal options, free them */
|
||||||
|
if (AppEntry->Flags & BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(AppEntry->BcdData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the new pointer */
|
||||||
|
AppEntry->BcdData = NewOptions;
|
||||||
|
|
||||||
|
/* Options are now internal, not external */
|
||||||
|
AppEntry->Flags &= ~BL_APPLICATION_ENTRY_BCD_OPTIONS_EXTERNAL;
|
||||||
|
AppEntry->Flags |= BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
889
reactos/boot/environ/lib/misc/bootreg.c
Normal file
889
reactos/boot/environ/lib/misc/bootreg.c
Normal file
|
@ -0,0 +1,889 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING.ARM in the top level directory
|
||||||
|
* PROJECT: ReactOS UEFI Boot Library
|
||||||
|
* FILE: boot/environ/lib/misc/bootreg.c
|
||||||
|
* PURPOSE: Boot Library Boot Registry Wrapper for CMLIB
|
||||||
|
* PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include "bl.h"
|
||||||
|
#include <bcd.h>
|
||||||
|
|
||||||
|
/* DEFINITIONS ***************************************************************/
|
||||||
|
|
||||||
|
#define BI_FLUSH_HIVE 0x01
|
||||||
|
#define BI_HIVE_WRITEABLE 0x02
|
||||||
|
|
||||||
|
/* DATA STRUCTURES ***********************************************************/
|
||||||
|
|
||||||
|
typedef struct _BI_KEY_HIVE
|
||||||
|
{
|
||||||
|
PHBASE_BLOCK BaseBlock;
|
||||||
|
ULONG HiveSize;
|
||||||
|
PBL_FILE_PATH_DESCRIPTOR FilePath;
|
||||||
|
CMHIVE Hive;
|
||||||
|
LONG ReferenceCount;
|
||||||
|
ULONG Flags;
|
||||||
|
PCM_KEY_NODE RootNode;
|
||||||
|
} BI_KEY_HIVE, *PBI_KEY_HIVE;
|
||||||
|
|
||||||
|
typedef struct _BI_KEY_OBJECT
|
||||||
|
{
|
||||||
|
PBI_KEY_HIVE KeyHive;
|
||||||
|
PCM_KEY_NODE KeyNode;
|
||||||
|
HCELL_INDEX KeyCell;
|
||||||
|
PWCHAR KeyName;
|
||||||
|
} BI_KEY_OBJECT, *PBI_KEY_OBJECT;
|
||||||
|
|
||||||
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
|
BOOLEAN BiHiveHashLibraryInitialized;
|
||||||
|
ULONGLONG HvSymcryptSeed;
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
HvIsInPlaceBaseBlockValid (
|
||||||
|
_In_ PHBASE_BLOCK BaseBlock
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG HiveLength, HeaderSum;
|
||||||
|
BOOLEAN Valid;
|
||||||
|
|
||||||
|
/* Assume failure */
|
||||||
|
Valid = FALSE;
|
||||||
|
|
||||||
|
/* Check for incorrect signature, type, version, or format */
|
||||||
|
if ((BaseBlock->Signature == 'fger') &&
|
||||||
|
(BaseBlock->Type == 0) &&
|
||||||
|
(BaseBlock->Major <= 1) &&
|
||||||
|
(BaseBlock->Minor <= 5) &&
|
||||||
|
(BaseBlock->Minor >= 3) &&
|
||||||
|
(BaseBlock->Format == 1))
|
||||||
|
{
|
||||||
|
/* Check for invalid hive size */
|
||||||
|
HiveLength = BaseBlock->Length;
|
||||||
|
if (HiveLength)
|
||||||
|
{
|
||||||
|
/* Check for misaligned or too large hive size */
|
||||||
|
if (!(HiveLength & 0xFFF) && HiveLength <= 0x7FFFE000)
|
||||||
|
{
|
||||||
|
/* Check for invalid header checksum */
|
||||||
|
HeaderSum = HvpHiveHeaderChecksum(BaseBlock);
|
||||||
|
if (HeaderSum == BaseBlock->CheckSum)
|
||||||
|
{
|
||||||
|
/* All good */
|
||||||
|
Valid = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return validity */
|
||||||
|
return Valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
NTAPI
|
||||||
|
CmpAllocate (
|
||||||
|
_In_ SIZE_T Size,
|
||||||
|
_In_ BOOLEAN Paged,
|
||||||
|
_In_ ULONG Tag
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UNREFERENCED_PARAMETER(Paged);
|
||||||
|
UNREFERENCED_PARAMETER(Tag);
|
||||||
|
|
||||||
|
/* Call the heap allocator */
|
||||||
|
return BlMmAllocateHeap(Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CmpFree (
|
||||||
|
_In_ PVOID Ptr,
|
||||||
|
_In_ ULONG Quota
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UNREFERENCED_PARAMETER(Quota);
|
||||||
|
|
||||||
|
/* Call the heap allocator */
|
||||||
|
BlMmFreeHeap(Ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BiDereferenceHive (
|
||||||
|
_In_ HANDLE KeyHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PBI_KEY_OBJECT KeyObject;
|
||||||
|
|
||||||
|
/* Get the key object */
|
||||||
|
KeyObject = (PBI_KEY_OBJECT)KeyHandle;
|
||||||
|
|
||||||
|
/* Drop a reference on the parent hive */
|
||||||
|
--KeyObject->KeyHive->ReferenceCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BiFlushHive (
|
||||||
|
_In_ HANDLE KeyHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Not yet implemented */
|
||||||
|
EfiPrintf(L"NO reg flush\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BiCloseKey (
|
||||||
|
_In_ HANDLE KeyHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PBI_KEY_HIVE KeyHive;
|
||||||
|
PBI_KEY_OBJECT KeyObject;
|
||||||
|
|
||||||
|
/* Get the key object and hive */
|
||||||
|
KeyObject = (PBI_KEY_OBJECT)KeyHandle;
|
||||||
|
KeyHive = KeyObject->KeyHive;
|
||||||
|
|
||||||
|
/* Check if we have a hive, or name, or key node */
|
||||||
|
if ((KeyHive) || (KeyObject->KeyNode) || (KeyObject->KeyName))
|
||||||
|
{
|
||||||
|
/* Drop a reference, see if it's the last one */
|
||||||
|
BiDereferenceHive(KeyHandle);
|
||||||
|
if (!KeyHive->ReferenceCount)
|
||||||
|
{
|
||||||
|
/* Check if we should flush it */
|
||||||
|
if (KeyHive->Flags & BI_FLUSH_HIVE)
|
||||||
|
{
|
||||||
|
BiFlushHive(KeyHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unmap the hive */
|
||||||
|
//MmPapFreePages(KeyHive->ImageBase, 1);
|
||||||
|
EfiPrintf(L"Leaking hive memory\r\n");
|
||||||
|
|
||||||
|
/* Free the hive and hive path */
|
||||||
|
BlMmFreeHeap(KeyHive->FilePath);
|
||||||
|
BlMmFreeHeap(KeyHive);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if a key name is present */
|
||||||
|
if (KeyObject->KeyName)
|
||||||
|
{
|
||||||
|
/* Free it */
|
||||||
|
BlMmFreeHeap(KeyObject->KeyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the object */
|
||||||
|
BlMmFreeHeap(KeyObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BiOpenKey(
|
||||||
|
_In_ HANDLE ParentHandle,
|
||||||
|
_In_ PWCHAR KeyName,
|
||||||
|
_Out_ PHANDLE Handle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PBI_KEY_OBJECT ParentKey, NewKey;
|
||||||
|
PBI_KEY_HIVE ParentHive;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG NameLength, SubNameLength, NameBytes;
|
||||||
|
PWCHAR NameStart, NameBuffer;
|
||||||
|
UNICODE_STRING KeyString;
|
||||||
|
HCELL_INDEX KeyCell;
|
||||||
|
PHHIVE Hive;
|
||||||
|
PCM_KEY_NODE ParentNode;
|
||||||
|
|
||||||
|
/* Convert from a handle to our key object */
|
||||||
|
ParentKey = (PBI_KEY_OBJECT)ParentHandle;
|
||||||
|
|
||||||
|
/* Extract the hive and node information */
|
||||||
|
ParentHive = ParentKey->KeyHive;
|
||||||
|
ParentNode = ParentKey->KeyNode;
|
||||||
|
Hive = &ParentKey->KeyHive->Hive.Hive;
|
||||||
|
|
||||||
|
/* Initialize variables */
|
||||||
|
KeyCell = HCELL_NIL;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
NameBuffer = NULL;
|
||||||
|
|
||||||
|
/* Loop as long as there's still portions of the key name in play */
|
||||||
|
NameLength = wcslen(KeyName);
|
||||||
|
while (NameLength)
|
||||||
|
{
|
||||||
|
/* Find the first path separator */
|
||||||
|
NameStart = wcschr(KeyName, OBJ_NAME_PATH_SEPARATOR);
|
||||||
|
if (NameStart)
|
||||||
|
{
|
||||||
|
/* Look only at the key before the separator */
|
||||||
|
SubNameLength = NameStart - KeyName;
|
||||||
|
++NameStart;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No path separator, this is the final leaf key */
|
||||||
|
SubNameLength = NameLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the name buffer from the previous pass if needed */
|
||||||
|
if (NameBuffer)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(NameBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a buffer to hold the name of this specific subkey only */
|
||||||
|
NameBytes = SubNameLength * sizeof(WCHAR);
|
||||||
|
NameBuffer = BlMmAllocateHeap(NameBytes + sizeof(UNICODE_NULL));
|
||||||
|
if (!NameBuffer)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy and null-terminate the name of the subkey */
|
||||||
|
RtlCopyMemory(NameBuffer, KeyName, NameBytes);
|
||||||
|
NameBuffer[SubNameLength] = UNICODE_NULL;
|
||||||
|
|
||||||
|
/* Convert it into a UNICODE_STRING and try to find it */
|
||||||
|
RtlInitUnicodeString(&KeyString, NameBuffer);
|
||||||
|
KeyCell = CmpFindSubKeyByName(Hive, ParentNode, &KeyString);
|
||||||
|
if (KeyCell == HCELL_NIL)
|
||||||
|
{
|
||||||
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We found it -- get the key node out of it */
|
||||||
|
ParentNode = (PCM_KEY_NODE)HvGetCell(Hive, KeyCell);
|
||||||
|
if (!ParentNode)
|
||||||
|
{
|
||||||
|
Status = STATUS_REGISTRY_CORRUPT;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the key name to the next remaining path element */
|
||||||
|
KeyName = NameStart;
|
||||||
|
if (NameStart)
|
||||||
|
{
|
||||||
|
/* Update the length to the remainder of the path */
|
||||||
|
NameLength += -1 - SubNameLength;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* There's nothing left, this was the leaf key */
|
||||||
|
NameLength = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a key object */
|
||||||
|
NewKey = BlMmAllocateHeap(sizeof(*NewKey));
|
||||||
|
if (!NewKey)
|
||||||
|
{
|
||||||
|
/* Bail out if we had no memory for it */
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill out the key object data */
|
||||||
|
NewKey->KeyNode = ParentNode;
|
||||||
|
NewKey->KeyHive = ParentHive;
|
||||||
|
NewKey->KeyName = NameBuffer;
|
||||||
|
NewKey->KeyCell = KeyCell;
|
||||||
|
|
||||||
|
/* Add a reference to the hive */
|
||||||
|
++ParentHive->ReferenceCount;
|
||||||
|
|
||||||
|
/* Return the object back to the caller */
|
||||||
|
*Handle = NewKey;
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* If we had a name buffer, free it */
|
||||||
|
if (NameBuffer)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(NameBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return status of the open operation */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BiInitializeAndValidateHive (
|
||||||
|
_In_ PBI_KEY_HIVE Hive
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG HiveSize;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Make sure the hive is at least the size of a base block */
|
||||||
|
if (Hive->HiveSize < sizeof(HBASE_BLOCK))
|
||||||
|
{
|
||||||
|
return STATUS_REGISTRY_CORRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure that the base block accurately describes the size of the hive */
|
||||||
|
HiveSize = Hive->BaseBlock->Length + sizeof(HBASE_BLOCK);
|
||||||
|
if ((HiveSize < sizeof(HBASE_BLOCK)) || (HiveSize > Hive->HiveSize))
|
||||||
|
{
|
||||||
|
return STATUS_REGISTRY_CORRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize a flat memory hive */
|
||||||
|
RtlZeroMemory(&Hive->Hive, sizeof(Hive->Hive));
|
||||||
|
Status = HvInitialize(&Hive->Hive.Hive,
|
||||||
|
HINIT_FLAT,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
Hive->BaseBlock,
|
||||||
|
CmpAllocate,
|
||||||
|
CmpFree,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Cleanup volatile/old data */
|
||||||
|
CmPrepareHive(&Hive->Hive.Hive); // CmCheckRegistry
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the final status */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BiLoadHive (
|
||||||
|
_In_ PBL_FILE_PATH_DESCRIPTOR FilePath,
|
||||||
|
_Out_ PHANDLE HiveHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG DeviceId;
|
||||||
|
PHBASE_BLOCK BaseBlock, NewBaseBlock;
|
||||||
|
PBI_KEY_OBJECT KeyObject;
|
||||||
|
PBI_KEY_HIVE BcdHive;
|
||||||
|
PBL_DEVICE_DESCRIPTOR BcdDevice;
|
||||||
|
ULONG PathLength, DeviceLength, HiveSize, HiveLength, NewHiveSize;
|
||||||
|
PWCHAR HiveName, LogName;
|
||||||
|
BOOLEAN HaveWriteAccess;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PVOID LogData;
|
||||||
|
PHHIVE Hive;
|
||||||
|
UNICODE_STRING KeyString;
|
||||||
|
PCM_KEY_NODE RootNode;
|
||||||
|
HCELL_INDEX CellIndex;
|
||||||
|
|
||||||
|
/* Initialize variables */
|
||||||
|
DeviceId = -1;
|
||||||
|
BaseBlock = NULL;
|
||||||
|
BcdHive = NULL;
|
||||||
|
KeyObject = NULL;
|
||||||
|
LogData = NULL;
|
||||||
|
LogName = NULL;
|
||||||
|
|
||||||
|
/* Initialize the crypto seed */
|
||||||
|
if (!BiHiveHashLibraryInitialized)
|
||||||
|
{
|
||||||
|
HvSymcryptSeed = 0x82EF4D887A4E55C5;
|
||||||
|
BiHiveHashLibraryInitialized = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract and validate the input path */
|
||||||
|
BcdDevice = (PBL_DEVICE_DESCRIPTOR)&FilePath->Path;
|
||||||
|
PathLength = FilePath->Length;
|
||||||
|
DeviceLength = BcdDevice->Size;
|
||||||
|
HiveName = (PWCHAR)((ULONG_PTR)BcdDevice + BcdDevice->Size);
|
||||||
|
if (PathLength <= DeviceLength)
|
||||||
|
{
|
||||||
|
/* Doesn't make sense, bail out */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to open the underlying device for RW access */
|
||||||
|
HaveWriteAccess = TRUE;
|
||||||
|
Status = BlpDeviceOpen(BcdDevice,
|
||||||
|
BL_DEVICE_READ_ACCESS | BL_DEVICE_WRITE_ACCESS,
|
||||||
|
0,
|
||||||
|
&DeviceId);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Try for RO access instead */
|
||||||
|
HaveWriteAccess = FALSE;
|
||||||
|
Status = BlpDeviceOpen(BcdDevice, BL_DEVICE_READ_ACCESS, 0, &DeviceId);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* No access at all -- bail out */
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now try to load the hive on disk */
|
||||||
|
Status = BlImgLoadImageWithProgress2(DeviceId,
|
||||||
|
BlLoaderRegistry,
|
||||||
|
HiveName,
|
||||||
|
(PVOID*)&BaseBlock,
|
||||||
|
&HiveSize,
|
||||||
|
0,
|
||||||
|
FALSE,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
EfiPrintf(L"Hive read failure: % lx\r\n", Status);
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a hive structure */
|
||||||
|
BcdHive = BlMmAllocateHeap(sizeof(*BcdHive));
|
||||||
|
if (!BcdHive)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize it */
|
||||||
|
RtlZeroMemory(BcdHive, sizeof(*BcdHive));
|
||||||
|
BcdHive->BaseBlock = BaseBlock;
|
||||||
|
BcdHive->HiveSize = HiveSize;
|
||||||
|
if (HaveWriteAccess)
|
||||||
|
{
|
||||||
|
BcdHive->Flags |= BI_HIVE_WRITEABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the hive was at least one bin long */
|
||||||
|
if (HiveSize < sizeof(*BaseBlock))
|
||||||
|
{
|
||||||
|
Status = STATUS_REGISTRY_CORRUPT;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the hive contents are at least one bin long */
|
||||||
|
HiveLength = BaseBlock->Length;
|
||||||
|
if (BaseBlock->Length < sizeof(*BaseBlock))
|
||||||
|
{
|
||||||
|
Status = STATUS_REGISTRY_CORRUPT;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate the initial bin (the base block) */
|
||||||
|
if (!HvIsInPlaceBaseBlockValid(BaseBlock))
|
||||||
|
{
|
||||||
|
EfiPrintf(L"Recovery not implemented\r\n");
|
||||||
|
Status = STATUS_REGISTRY_CORRUPT;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there's log recovery that needs to happen */
|
||||||
|
if (BaseBlock->Sequence1 != BaseBlock->Sequence2)
|
||||||
|
{
|
||||||
|
EfiPrintf(L"Log fix not implemented: %lx %lx\r\n");
|
||||||
|
Status = STATUS_REGISTRY_CORRUPT;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the whole hive doesn't fit in the buffer.
|
||||||
|
* Note: HiveLength does not include the size of the baseblock itself
|
||||||
|
*/
|
||||||
|
if (HiveSize < (HiveLength + sizeof(*BaseBlock)))
|
||||||
|
{
|
||||||
|
EfiPrintf(L"Need bigger hive buffer path\r\n");
|
||||||
|
|
||||||
|
/* Allocate a slightly bigger buffer */
|
||||||
|
NewHiveSize = HiveLength + sizeof(*BaseBlock);
|
||||||
|
Status = MmPapAllocatePagesInRange((PVOID*)&NewBaseBlock,
|
||||||
|
BlLoaderRegistry,
|
||||||
|
NewHiveSize >> PAGE_SHIFT,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the current data in there */
|
||||||
|
RtlCopyMemory(NewBaseBlock, BaseBlock, HiveSize);
|
||||||
|
|
||||||
|
/* Free the old data */
|
||||||
|
EfiPrintf(L"Leaking old hive buffer\r\n");
|
||||||
|
//MmPapFreePages(BaseBlock, 1);
|
||||||
|
|
||||||
|
/* Update our pointers */
|
||||||
|
BaseBlock = NewBaseBlock;
|
||||||
|
HiveSize = NewHiveSize;
|
||||||
|
BcdHive->BaseBlock = BaseBlock;
|
||||||
|
BcdHive->HiveSize = HiveSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if any log stuff needs to happen */
|
||||||
|
if (LogData)
|
||||||
|
{
|
||||||
|
EfiPrintf(L"Log fix not implemented: %lx %lx\r\n");
|
||||||
|
Status = STATUS_REGISTRY_CORRUPT;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call Hv to setup the hive library */
|
||||||
|
Status = BiInitializeAndValidateHive(BcdHive);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now get the root node */
|
||||||
|
Hive = &BcdHive->Hive.Hive;
|
||||||
|
RootNode = (PCM_KEY_NODE)HvGetCell(Hive, Hive->BaseBlock->RootCell);
|
||||||
|
if (!RootNode)
|
||||||
|
{
|
||||||
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the Objects subkey under it to see if it's a real BCD hive */
|
||||||
|
RtlInitUnicodeString(&KeyString, L"Objects");
|
||||||
|
CellIndex = CmpFindSubKeyByName(Hive, RootNode, &KeyString);
|
||||||
|
if (CellIndex == HCELL_NIL)
|
||||||
|
{
|
||||||
|
EfiPrintf(L"No OBJECTS subkey found!\r\n");
|
||||||
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a valid BCD hive, store its root node here */
|
||||||
|
BcdHive->RootNode = RootNode;
|
||||||
|
|
||||||
|
/* Allocate a copy of the file path */
|
||||||
|
BcdHive->FilePath = BlMmAllocateHeap(FilePath->Length);
|
||||||
|
if (!BcdHive->FilePath)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make a copy of it */
|
||||||
|
RtlCopyMemory(BcdHive->FilePath, FilePath, FilePath->Length);
|
||||||
|
|
||||||
|
/* Create a key object to describe the rot */
|
||||||
|
KeyObject = BlMmAllocateHeap(sizeof(*KeyObject));
|
||||||
|
if (!KeyObject)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill out the details */
|
||||||
|
KeyObject->KeyNode = RootNode;
|
||||||
|
KeyObject->KeyHive = BcdHive;
|
||||||
|
KeyObject->KeyName = NULL;
|
||||||
|
KeyObject->KeyCell = Hive->BaseBlock->RootCell;
|
||||||
|
|
||||||
|
/* One reference for the key object, plus one lifetime reference */
|
||||||
|
BcdHive->ReferenceCount = 2;
|
||||||
|
|
||||||
|
/* This is the hive handle */
|
||||||
|
*HiveHandle = KeyObject;
|
||||||
|
|
||||||
|
/* We're all good */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* If we had a log name, free it */
|
||||||
|
if (LogName)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(LogName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we had logging data, free it */
|
||||||
|
if (LogData)
|
||||||
|
{
|
||||||
|
EfiPrintf(L"Leaking log buffer\r\n");
|
||||||
|
//MmPapFreePages(LogData, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if this is the failure path */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* If we mapped the hive, free it */
|
||||||
|
if (BaseBlock)
|
||||||
|
{
|
||||||
|
EfiPrintf(L"Leaking base block on failure\r\n");
|
||||||
|
//MmPapFreePages(BaseBlock, 1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we opened the device, close it */
|
||||||
|
if (DeviceId != -1)
|
||||||
|
{
|
||||||
|
BlDeviceClose(DeviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Did we create a hive object? */
|
||||||
|
if (BcdHive)
|
||||||
|
{
|
||||||
|
/* Free the file path if we made a copy of it */
|
||||||
|
if (BcdHive->FilePath)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(BcdHive->FilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the hive itself */
|
||||||
|
BlMmFreeHeap(BcdHive);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, free the root key object if we created one */
|
||||||
|
if (KeyObject)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(KeyObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the final status */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BiGetRegistryValue (
|
||||||
|
_In_ HANDLE KeyHandle,
|
||||||
|
_In_ PWCHAR ValueName,
|
||||||
|
_In_ PWCHAR KeyName,
|
||||||
|
_In_ ULONG Type,
|
||||||
|
_Out_ PVOID* Buffer,
|
||||||
|
_Out_ PULONG ValueLength
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCM_KEY_NODE KeyNode;
|
||||||
|
PHHIVE KeyHive;
|
||||||
|
UNICODE_STRING ValueString;
|
||||||
|
PBI_KEY_OBJECT KeyObject;
|
||||||
|
PCM_KEY_VALUE KeyValue;
|
||||||
|
PVOID ValueCopy;
|
||||||
|
ULONG Size;
|
||||||
|
HCELL_INDEX CellIndex;
|
||||||
|
PCELL_DATA ValueData;
|
||||||
|
|
||||||
|
/* Get the key object, node,and hive */
|
||||||
|
KeyObject = (PBI_KEY_OBJECT)KeyHandle;
|
||||||
|
KeyNode = KeyObject->KeyNode;
|
||||||
|
KeyHive = &KeyObject->KeyHive->Hive.Hive;
|
||||||
|
|
||||||
|
/* Find the value cell index in the list of values */
|
||||||
|
RtlInitUnicodeString(&ValueString, ValueName);
|
||||||
|
CmpFindNameInList(KeyHive,
|
||||||
|
&KeyNode->ValueList,
|
||||||
|
&ValueString,
|
||||||
|
NULL,
|
||||||
|
&CellIndex);
|
||||||
|
if (CellIndex == HCELL_NIL)
|
||||||
|
{
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the cell data for it */
|
||||||
|
KeyValue = (PCM_KEY_VALUE)HvGetCell(KeyHive, CellIndex);
|
||||||
|
if (!KeyValue)
|
||||||
|
{
|
||||||
|
return STATUS_REGISTRY_CORRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the type matches */
|
||||||
|
if (KeyValue->Type != Type)
|
||||||
|
{
|
||||||
|
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now get the data cell */
|
||||||
|
ValueData = CmpValueToData(KeyHive, KeyValue, &Size);
|
||||||
|
|
||||||
|
/* Make a copy of it */
|
||||||
|
ValueCopy = BlMmAllocateHeap(Size);
|
||||||
|
if (!ValueCopy)
|
||||||
|
{
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy it in the buffer, and return it and its size */
|
||||||
|
RtlCopyMemory(ValueCopy, ValueData, Size);
|
||||||
|
*Buffer = ValueCopy;
|
||||||
|
*ValueLength = Size;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BiEnumerateSubKeys (
|
||||||
|
_In_ HANDLE KeyHandle,
|
||||||
|
_Out_ PWCHAR** SubKeyList,
|
||||||
|
_Out_ PULONG SubKeyCount
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCM_KEY_NODE KeyNode, Node;
|
||||||
|
PBI_KEY_OBJECT KeyObject;
|
||||||
|
ULONG KeyCount;
|
||||||
|
ULONG NameLength, NewTotalNameLength, FinalLength, TotalNameLength;
|
||||||
|
PHHIVE Hive;
|
||||||
|
PWCHAR KeyName, NameEnd;
|
||||||
|
HCELL_INDEX CellIndex;
|
||||||
|
PWCHAR* SubKeys;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
/* Get the key object, node, and hive */
|
||||||
|
KeyObject = (PBI_KEY_OBJECT)KeyHandle;
|
||||||
|
KeyNode = KeyObject->KeyNode;
|
||||||
|
Hive = &KeyObject->KeyHive->Hive.Hive;
|
||||||
|
|
||||||
|
/* Assume it's empty */
|
||||||
|
*SubKeyList = 0;
|
||||||
|
*SubKeyCount = 0;
|
||||||
|
|
||||||
|
/* Initialize locals */
|
||||||
|
KeyCount = 0;
|
||||||
|
SubKeys = 0;
|
||||||
|
TotalNameLength = 0;
|
||||||
|
|
||||||
|
/* Find the first subkey cell index */
|
||||||
|
CellIndex = CmpFindSubKeyByNumber(Hive, KeyNode, KeyCount);
|
||||||
|
while (CellIndex != HCELL_NIL)
|
||||||
|
{
|
||||||
|
/* Move to the next one */
|
||||||
|
KeyCount++;
|
||||||
|
|
||||||
|
/* Get the cell data for it */
|
||||||
|
Node = (PCM_KEY_NODE)HvGetCell(Hive, CellIndex);
|
||||||
|
if (!Node)
|
||||||
|
{
|
||||||
|
return STATUS_REGISTRY_CORRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the value is compressed */
|
||||||
|
if (Node->Flags & KEY_COMP_NAME)
|
||||||
|
{
|
||||||
|
/* Get the compressed name size */
|
||||||
|
NameLength = CmpCompressedNameSize(Node->Name, Node->NameLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Get the real size */
|
||||||
|
NameLength = Node->NameLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add up the new length, protecting against overflow */
|
||||||
|
NewTotalNameLength = TotalNameLength + NameLength + sizeof(UNICODE_NULL);
|
||||||
|
if (NewTotalNameLength < TotalNameLength)
|
||||||
|
{
|
||||||
|
Status = STATUS_NAME_TOO_LONG;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We're good, use the new length */
|
||||||
|
TotalNameLength = NewTotalNameLength;
|
||||||
|
|
||||||
|
/* Find the next subkey cell index */
|
||||||
|
CellIndex = CmpFindSubKeyByNumber(Hive, KeyNode, KeyCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Were there no keys? We're done, if so */
|
||||||
|
if (!KeyCount)
|
||||||
|
{
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Safely compute the size of the array needed */
|
||||||
|
Status = RtlULongLongToULong(sizeof(PWCHAR) * KeyCount, &FinalLength);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Safely add that to the name length */
|
||||||
|
Status = RtlULongAdd(TotalNameLength, FinalLength, &FinalLength);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate an array big enough for the names and pointers */
|
||||||
|
SubKeys = BlMmAllocateHeap(FinalLength);
|
||||||
|
if (!SubKeys)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go over each key again */
|
||||||
|
NameEnd = (PWCHAR)&SubKeys[KeyCount];
|
||||||
|
for (i = 0; i < KeyCount; i++)
|
||||||
|
{
|
||||||
|
/* Get the cell index for this subkey */
|
||||||
|
CellIndex = CmpFindSubKeyByNumber(Hive, KeyNode, i);
|
||||||
|
if (CellIndex == HCELL_NIL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the cell data for it */
|
||||||
|
Node = HvGetCell(Hive, CellIndex);
|
||||||
|
if (!Node)
|
||||||
|
{
|
||||||
|
Status = STATUS_REGISTRY_CORRUPT;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the value is compressed */
|
||||||
|
KeyName = Node->Name;
|
||||||
|
if (Node->Flags & KEY_COMP_NAME)
|
||||||
|
{
|
||||||
|
/* Get the compressed name size */
|
||||||
|
NameLength = CmpCompressedNameSize(KeyName, Node->NameLength);
|
||||||
|
CmpCopyCompressedName(NameEnd, NameLength, KeyName, Node->NameLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Get the real size */
|
||||||
|
NameLength = Node->NameLength;
|
||||||
|
RtlCopyMemory(NameEnd, KeyName, NameLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move the name buffer to the next spot, and NULL-terminate */
|
||||||
|
SubKeys[i] = NameEnd;
|
||||||
|
NameEnd += (NameLength / sizeof(WCHAR));
|
||||||
|
*NameEnd = UNICODE_NULL;
|
||||||
|
|
||||||
|
/* Keep going */
|
||||||
|
NameEnd++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the subkeys were empty */
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
/* They disappeared in the middle of enumeration */
|
||||||
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the count and the array of names */
|
||||||
|
*SubKeyList = SubKeys;
|
||||||
|
*SubKeyCount = i;
|
||||||
|
SubKeys = NULL;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* On the failure path, free the subkeys if any exist */
|
||||||
|
if (SubKeys)
|
||||||
|
{
|
||||||
|
BlMmFreeHeap(SubKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All done, return the result */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "bl.h"
|
#include "bl.h"
|
||||||
|
#include "bcd.h"
|
||||||
|
|
||||||
/* DATA VARIABLES ************************************************************/
|
/* DATA VARIABLES ************************************************************/
|
||||||
|
|
||||||
|
@ -38,7 +39,35 @@ BlMmRemoveBadMemory (
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* FIXME: Read BCD option to see what bad memory to remove */
|
BOOLEAN AllowBad;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PULONGLONG BadPages;
|
||||||
|
ULONGLONG BadPageCount;
|
||||||
|
|
||||||
|
/* First check if bad memory access is allowed */
|
||||||
|
AllowBad = FALSE;
|
||||||
|
Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
|
||||||
|
BcdLibraryBoolean_AllowBadMemoryAccess,
|
||||||
|
&AllowBad);
|
||||||
|
if ((NT_SUCCESS(Status)) && (AllowBad))
|
||||||
|
{
|
||||||
|
/* No point checking the list if it is */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, check if there's a persisted bad page list */
|
||||||
|
Status = BlpGetBootOptionIntegerList(BlpApplicationEntry.BcdData,
|
||||||
|
BcdLibraryIntegerList_BadMemoryList,
|
||||||
|
&BadPages,
|
||||||
|
&BadPageCount,
|
||||||
|
TRUE);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
EfiPrintf(L"Persistent bad page list not supported\r\n");
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All done here */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "bl.h"
|
#include "bl.h"
|
||||||
|
#include "bcd.h"
|
||||||
|
|
||||||
typedef struct _BL_PA_REQUEST
|
typedef struct _BL_PA_REQUEST
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,30 @@ BlpMmInitializeConstraints (
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* FIXME: Read BCD option 'avoidlowmemory' and 'truncatememory' */
|
NTSTATUS Status;
|
||||||
|
ULONGLONG LowestAddressValid, HighestAddressValid;
|
||||||
|
|
||||||
|
/* Check for LOWMEM */
|
||||||
|
Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
|
||||||
|
BcdLibraryInteger_AvoidLowPhysicalMemory,
|
||||||
|
&LowestAddressValid);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
EfiPrintf(L"/LOWMEM not supported\r\n");
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for MAXMEM */
|
||||||
|
Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
|
||||||
|
BcdLibraryInteger_TruncatePhysicalMemory,
|
||||||
|
&HighestAddressValid);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
EfiPrintf(L"/MAXMEM not supported\r\n");
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return back to the caller */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue