mirror of
https://github.com/reactos/reactos.git
synced 2025-06-01 07:28:19 +00:00
[BOOTLIB]:
- WIP work to begin reading, parsing, mounting and loading the BCD hive into a data store. Untested, has missing pieces. - Implement BlFileSet/GetInformation, BlFileReadEx, BlFileReadAtOffsetEx and helper structures/functions. Document multiple previously unknown/magic flags. - Implement BlMmAllocatePhysicalPages. Stub BlMmFreePhysicalPages. - Implement MmUnmapVirtualAddress, BlMmUnmapVirtualAddressEx when operating in real mode. - Implement ImgpGetFileSize, ImgpReadFileAtOffset, ImgpOpenFile, ImgpCloseFile, BlImgAllocateImageBuffer, BlImgLoadImageWithProgress2. - Implement BdDebuggerInitialized, BlBdDebuggerEnabled, BlStatusPrint, BlStatuserror. Stub BlBdPullRemoteFile. - Implement BlGetBootOptionDevice. - Implement BiReferenceHive, BiDereferenceHive, BiCloseKey, BiOpenKey. Stub BiFlushKey, BiLoadHive. - Implement BiAddStoreFromFile, BcdOpenStoreFromFile. - Stub BlUtlUpdateProcess and BlResourceFindMessage. - Other misc. cleanups. [BOOTMGR]: - Implement BmpFatalErrorMessageFilter, BmErrorPurge, BmpErrorLog, BmFatalErrorEx. - Implement BmpFwGetFullPath. - Implement BmOpenDataStore. - Stub BmOpenBootIni svn path=/trunk/; revision=69447
This commit is contained in:
parent
e17f8bc3e7
commit
e7dee1f989
13 changed files with 2465 additions and 147 deletions
|
@ -10,8 +10,10 @@ add_definitions(-D_NTHAL_ -D_BLDR_ -D_NTSYSTEM_)
|
||||||
list(APPEND BOOTLIB_SOURCE
|
list(APPEND BOOTLIB_SOURCE
|
||||||
app/bootmgr/bootmgr.h
|
app/bootmgr/bootmgr.h
|
||||||
lib/bootlib.c
|
lib/bootlib.c
|
||||||
|
lib/misc/debug.c
|
||||||
lib/misc/bcd.c
|
lib/misc/bcd.c
|
||||||
lib/misc/util.c
|
lib/misc/util.c
|
||||||
|
lib/misc/image.c
|
||||||
lib/firmware/efi/firmware.c
|
lib/firmware/efi/firmware.c
|
||||||
lib/mm/mm.c
|
lib/mm/mm.c
|
||||||
lib/mm/pagealloc.c
|
lib/mm/pagealloc.c
|
||||||
|
|
|
@ -23,6 +23,14 @@ ULONGLONG PostTime;
|
||||||
GUID BmApplicationIdentifier;
|
GUID BmApplicationIdentifier;
|
||||||
PWCHAR BootDirectory;
|
PWCHAR BootDirectory;
|
||||||
|
|
||||||
|
BL_BOOT_ERROR BmpErrorBuffer;
|
||||||
|
PBL_BOOT_ERROR BmpInternalBootError;
|
||||||
|
BL_PACKED_BOOT_ERROR BmpPackedBootError;
|
||||||
|
|
||||||
|
BOOLEAN BmBootIniUsed;
|
||||||
|
WCHAR BmpFileNameBuffer[128];
|
||||||
|
PWCHAR ParentFileName = L"";
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -120,8 +128,8 @@ BmpFwGetApplicationDirectoryPath (
|
||||||
|
|
||||||
/* All done! */
|
/* All done! */
|
||||||
return Status;
|
return Status;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
BmFwInitializeBootDirectoryPath (
|
BmFwInitializeBootDirectoryPath (
|
||||||
VOID
|
VOID
|
||||||
|
@ -187,6 +195,7 @@ BmFwInitializeBootDirectoryPath (
|
||||||
goto Quickie;
|
goto Quickie;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save the boot directory */
|
||||||
BootDirectory = L"\\EFI\\Microsoft\\Boot";
|
BootDirectory = L"\\EFI\\Microsoft\\Boot";
|
||||||
|
|
||||||
Quickie:
|
Quickie:
|
||||||
|
@ -216,6 +225,441 @@ Quickie:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BmOpenBootIni (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Don't yet handled boot.ini */
|
||||||
|
return STATUS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
BmpFatalErrorMessageFilter (
|
||||||
|
_In_ NTSTATUS ErrorStatus,
|
||||||
|
_Out_ PULONG ErrorResourceId
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG Result;
|
||||||
|
|
||||||
|
/* Assume no message for now, check for known status message */
|
||||||
|
Result = 0;
|
||||||
|
switch (ErrorStatus)
|
||||||
|
{
|
||||||
|
/* Convert each status to a resource ID */
|
||||||
|
case STATUS_UNEXPECTED_IO_ERROR:
|
||||||
|
*ErrorResourceId = 9017;
|
||||||
|
Result = 1;
|
||||||
|
break;
|
||||||
|
case STATUS_IMAGE_CHECKSUM_MISMATCH:
|
||||||
|
*ErrorResourceId = 9018;
|
||||||
|
break;
|
||||||
|
case STATUS_INVALID_IMAGE_WIN_64:
|
||||||
|
*ErrorResourceId = 9016;
|
||||||
|
break;
|
||||||
|
case 0xC0000428:
|
||||||
|
*ErrorResourceId = 9019;
|
||||||
|
Result = 2;
|
||||||
|
break;
|
||||||
|
case 0xC0210000:
|
||||||
|
*ErrorResourceId = 9013;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the type of message */
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BmErrorPurge (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Check if a boot error is present */
|
||||||
|
if (BmpPackedBootError.BootError)
|
||||||
|
{
|
||||||
|
/* Purge it */
|
||||||
|
BlMmFreeHeap(BmpPackedBootError.BootError);
|
||||||
|
BmpPackedBootError.BootError = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zero out the packed buffer */
|
||||||
|
BmpPackedBootError.Size = 0;
|
||||||
|
BmpInternalBootError = NULL;
|
||||||
|
RtlZeroMemory(&BmpErrorBuffer, sizeof(BmpErrorBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BmpErrorLog (
|
||||||
|
_In_ ULONG ErrorCode,
|
||||||
|
_In_ NTSTATUS ErrorStatus,
|
||||||
|
_In_ ULONG ErrorMsgId,
|
||||||
|
_In_ PWCHAR FileName,
|
||||||
|
_In_ ULONG HelpMsgId
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PWCHAR ErrorMsgString;
|
||||||
|
|
||||||
|
/* Check if we already had an error */
|
||||||
|
if (BmpInternalBootError)
|
||||||
|
{
|
||||||
|
/* Purge it */
|
||||||
|
BmErrorPurge();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the string for this error ID */
|
||||||
|
ErrorMsgString = BlResourceFindMessage(ErrorMsgId);
|
||||||
|
if (ErrorMsgString)
|
||||||
|
{
|
||||||
|
/* Fill out the error buffer */
|
||||||
|
BmpErrorBuffer.Unknown1 = 0;
|
||||||
|
BmpErrorBuffer.Unknown2 = 0;
|
||||||
|
BmpErrorBuffer.ErrorString = ErrorMsgString;
|
||||||
|
BmpErrorBuffer.FileName = FileName;
|
||||||
|
BmpErrorBuffer.ErrorCode = ErrorCode;
|
||||||
|
BmpErrorBuffer.ErrorStatus = ErrorStatus;
|
||||||
|
BmpErrorBuffer.HelpMsgId = HelpMsgId;
|
||||||
|
BmpInternalBootError = &BmpErrorBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BmFatalErrorEx (
|
||||||
|
_In_ ULONG ErrorCode,
|
||||||
|
_In_ ULONG_PTR Parameter1,
|
||||||
|
_In_ ULONG_PTR Parameter2,
|
||||||
|
_In_ ULONG_PTR Parameter3,
|
||||||
|
_In_ ULONG_PTR Parameter4
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PWCHAR FileName, Buffer;
|
||||||
|
NTSTATUS ErrorStatus;
|
||||||
|
WCHAR FormatString[256];
|
||||||
|
ULONG ErrorResourceId, ErrorHelpId;
|
||||||
|
BOOLEAN Restart, NoError;
|
||||||
|
|
||||||
|
/* Assume no buffer for now */
|
||||||
|
Buffer = NULL;
|
||||||
|
|
||||||
|
/* Check what error code is being raised */
|
||||||
|
switch (ErrorCode)
|
||||||
|
{
|
||||||
|
/* Error reading the BCD */
|
||||||
|
case BL_FATAL_ERROR_BCD_READ:
|
||||||
|
|
||||||
|
/* Check if we have a name for the BCD file */
|
||||||
|
if (Parameter1)
|
||||||
|
{
|
||||||
|
/* Check if the name fits into our buffer */
|
||||||
|
FileName = (PWCHAR)Parameter1;
|
||||||
|
if (wcslen(FileName) < sizeof(BmpFileNameBuffer))
|
||||||
|
{
|
||||||
|
/* Copy it in there */
|
||||||
|
Buffer = BmpFileNameBuffer;
|
||||||
|
wcsncpy(BmpFileNameBuffer,
|
||||||
|
FileName,
|
||||||
|
RTL_NUMBER_OF(BmpFileNameBuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we don't have a buffer, use an empty one */
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
Buffer = ParentFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The NTSTATUS code is in parameter 2*/
|
||||||
|
ErrorStatus = (NTSTATUS)Parameter2;
|
||||||
|
|
||||||
|
/* Build the error string */
|
||||||
|
swprintf(FormatString,
|
||||||
|
L"\nAn error occurred (%08x) while attempting"
|
||||||
|
L"to read the boot configuration data file %s\n",
|
||||||
|
ErrorStatus,
|
||||||
|
Buffer);
|
||||||
|
|
||||||
|
/* Select the resource ID message */
|
||||||
|
ErrorResourceId = 9002;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
/* The rest is not yet handled */
|
||||||
|
EfiPrintf(L"Unexpected fatal error: %lx\n", ErrorCode);
|
||||||
|
while (1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the BCD option for restart is set */
|
||||||
|
BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
|
||||||
|
BcdLibraryBoolean_RestartOnFailure,
|
||||||
|
&Restart);
|
||||||
|
if (Restart)
|
||||||
|
{
|
||||||
|
/* Yes, so no error should be shown since we'll auto-restart */
|
||||||
|
NoError = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Check if the option for not showing errors is set in the BCD */
|
||||||
|
BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
|
||||||
|
BcdBootMgrBoolean_NoErrorDisplay,
|
||||||
|
&NoError);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do we want an error? */
|
||||||
|
if (!NoError)
|
||||||
|
{
|
||||||
|
/* Yep, print it and then raise an error */
|
||||||
|
BlStatusPrint(FormatString);
|
||||||
|
BlStatusError(1, ErrorCode, Parameter1, Parameter2, Parameter3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the help message ID */
|
||||||
|
ErrorHelpId = BmpFatalErrorMessageFilter(ErrorStatus, &ErrorResourceId);
|
||||||
|
BmpErrorLog(ErrorCode, ErrorStatus, ErrorResourceId, Buffer, ErrorHelpId);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BmpFwGetFullPath (
|
||||||
|
_In_ PWCHAR FileName,
|
||||||
|
_Out_ PWCHAR* FullPath
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG BootDirLength, BootDirLengthWithNul;
|
||||||
|
ULONG PathLength, FullPathLength;
|
||||||
|
|
||||||
|
/* Compute the length of the directory, and add a NUL */
|
||||||
|
BootDirLength = wcslen(BootDirectory);
|
||||||
|
BootDirLengthWithNul = BootDirLength + 1;
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the length of the file, make sure it fits */
|
||||||
|
PathLength = wcslen(FileName);
|
||||||
|
FullPathLength = PathLength + BootDirLength;
|
||||||
|
if (FullPathLength < PathLength)
|
||||||
|
{
|
||||||
|
/* Nope */
|
||||||
|
FullPathLength = -1;
|
||||||
|
Status = STATUS_INTEGER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* All good */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fail on overflow */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate the full path */
|
||||||
|
FullPathLength = FullPathLength * sizeof(WCHAR);
|
||||||
|
*FullPath = BlMmAllocateHeap(FullPathLength);
|
||||||
|
if (*FullPath)
|
||||||
|
{
|
||||||
|
/* Copy the directory followed by the file name */
|
||||||
|
wcsncpy(*FullPath, BootDirectory, FullPathLength / sizeof(WCHAR));
|
||||||
|
wcsncat(*FullPath, FileName, FullPathLength / sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Bail out since we have no memory */
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* Return to caller */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BmOpenDataStore (
|
||||||
|
_Out_ PHANDLE Handle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PBL_DEVICE_DESCRIPTOR BcdDevice;
|
||||||
|
PWCHAR BcdPath, FullPath, PathBuffer;
|
||||||
|
BOOLEAN HavePath;
|
||||||
|
ULONG PathLength, PathLengthWithNul, FullSize;
|
||||||
|
PVOID FinalBuffer;
|
||||||
|
UNICODE_STRING BcdString;
|
||||||
|
|
||||||
|
PathBuffer = NULL;
|
||||||
|
BcdDevice = NULL;
|
||||||
|
BcdPath = NULL;
|
||||||
|
HavePath = FALSE;
|
||||||
|
|
||||||
|
/* Check if a boot.ini file exists */
|
||||||
|
Status = BmOpenBootIni();
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
BmBootIniUsed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check on which device the BCD is */
|
||||||
|
Status = BlGetBootOptionDevice(BlpApplicationEntry.BcdData,
|
||||||
|
BcdBootMgrDevice_BcdDevice,
|
||||||
|
&BcdDevice,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* It's not on a custom device, so it must be where we are */
|
||||||
|
Status = BlGetBootOptionDevice(BlpApplicationEntry.BcdData,
|
||||||
|
BcdLibraryDevice_ApplicationDevice,
|
||||||
|
&BcdDevice,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* This BCD option is required */
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next, check what file contains the BCD */
|
||||||
|
Status = BlGetBootOptionString(BlpApplicationEntry.BcdData,
|
||||||
|
BcdBootMgrString_BcdFilePath,
|
||||||
|
&BcdPath);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* We don't handle custom BCDs yet */
|
||||||
|
EfiPrintf(L"Not handled\n");
|
||||||
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now check if the BCD is on a remote share */
|
||||||
|
if (BcdDevice->DeviceType == UdpDevice)
|
||||||
|
{
|
||||||
|
/* Nope. Nope. Nope */
|
||||||
|
EfiPrintf(L"Not handled\n");
|
||||||
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, compute the hardcoded path of the BCD */
|
||||||
|
Status = BmpFwGetFullPath(L"\\BCD", &FullPath);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* User the raw path */
|
||||||
|
PathBuffer = BcdPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Use the path we got */
|
||||||
|
PathBuffer = FullPath;
|
||||||
|
HavePath = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we failed to get the BCD path */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a NUL to the path, make sure it'll fit */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
PathLength = wcslen(PathBuffer);
|
||||||
|
PathLengthWithNul = PathLength + 1;
|
||||||
|
if (PathLengthWithNul < PathLength)
|
||||||
|
{
|
||||||
|
PathLengthWithNul = -1;
|
||||||
|
Status = STATUS_INTEGER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bail out if it doesn't fit */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now add the size of the path to the device path, check if it fits */
|
||||||
|
PathLengthWithNul = PathLengthWithNul * sizeof(WCHAR);
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a final structure to hold both entities */
|
||||||
|
FinalBuffer = BlMmAllocateHeap(FullSize);
|
||||||
|
if (!FinalBuffer)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the device path and file path into the final buffer */
|
||||||
|
RtlCopyMemory(FinalBuffer, BcdDevice, BcdDevice->Size);
|
||||||
|
RtlCopyMemory((PVOID)((ULONG_PTR)FinalBuffer + BcdDevice->Size),
|
||||||
|
PathBuffer,
|
||||||
|
PathLengthWithNul);
|
||||||
|
|
||||||
|
/* Now tell the BCD engine to open the store */
|
||||||
|
BcdString.Length = FullSize;
|
||||||
|
BcdString.MaximumLength = FullSize;
|
||||||
|
BcdString.Buffer = FinalBuffer;
|
||||||
|
Status = BcdOpenStoreFromFile(&BcdString, Handle);
|
||||||
|
|
||||||
|
/* Free our final buffer */
|
||||||
|
BlMmFreeHeap(FinalBuffer);
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* Did we allocate a device? */
|
||||||
|
if (BcdDevice)
|
||||||
|
{
|
||||||
|
/* Free it */
|
||||||
|
BlMmFreeHeap(BcdDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is this the failure path? */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Raise a fatal error */
|
||||||
|
BmFatalErrorEx(1, (ULONG_PTR)PathBuffer, Status, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Did we get an allocated path? */
|
||||||
|
if ((PathBuffer) && (HavePath))
|
||||||
|
{
|
||||||
|
/* Free it */
|
||||||
|
BlMmFreeHeap(PathBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return back to the caller */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
* @name BmMain
|
* @name BmMain
|
||||||
|
@ -240,7 +684,7 @@ BmMain (
|
||||||
PBL_RETURN_ARGUMENTS ReturnArguments;
|
PBL_RETURN_ARGUMENTS ReturnArguments;
|
||||||
BOOLEAN RebootOnError;
|
BOOLEAN RebootOnError;
|
||||||
PGUID AppIdentifier;
|
PGUID AppIdentifier;
|
||||||
// HANDLE BcdHandle;
|
HANDLE BcdHandle;
|
||||||
|
|
||||||
EfiPrintf(L"ReactOS UEFI Boot Manager Initializing...\n");
|
EfiPrintf(L"ReactOS UEFI Boot Manager Initializing...\n");
|
||||||
|
|
||||||
|
@ -280,15 +724,18 @@ BmMain (
|
||||||
/* None was given, so set our default one */
|
/* None was given, so set our default one */
|
||||||
AppIdentifier = (PGUID)&GUID_WINDOWS_BOOTMGR;
|
AppIdentifier = (PGUID)&GUID_WINDOWS_BOOTMGR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save our identifier */
|
/* Save our identifier */
|
||||||
BmApplicationIdentifier = *AppIdentifier;
|
BmApplicationIdentifier = *AppIdentifier;
|
||||||
|
|
||||||
/* Initialize the file system to open a handle to our root boot directory */
|
/* Initialize the file system to open a handle to our root boot directory */
|
||||||
BmFwInitializeBootDirectoryPath();
|
BmFwInitializeBootDirectoryPath();
|
||||||
|
|
||||||
//Status = BmOpenDataStore(&BcdHandle);
|
/* Load and initialize the boot configuration database (BCD) */
|
||||||
|
Status = BmOpenDataStore(&BcdHandle);
|
||||||
|
EfiPrintf(L"BCD Open: %lx\r\n", Status);
|
||||||
|
|
||||||
|
/* do more stuff!! */
|
||||||
EfiPrintf(L"We are A-OK!\r\n");
|
EfiPrintf(L"We are A-OK!\r\n");
|
||||||
EfiStall(10000000);
|
EfiStall(10000000);
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,28 @@
|
||||||
/* BCD Headers */
|
/* BCD Headers */
|
||||||
#include <bcd.h>
|
#include <bcd.h>
|
||||||
|
|
||||||
|
/* STRUCTURES ****************************************************************/
|
||||||
|
|
||||||
|
typedef struct _BL_BOOT_ERROR
|
||||||
|
{
|
||||||
|
ULONG ErrorCode;
|
||||||
|
NTSTATUS ErrorStatus;
|
||||||
|
ULONG Unknown1;
|
||||||
|
PWCHAR ErrorString;
|
||||||
|
PWCHAR FileName;
|
||||||
|
ULONG HelpMsgId;
|
||||||
|
ULONG Unknown2;
|
||||||
|
} BL_BOOT_ERROR, *PBL_BOOT_ERROR;
|
||||||
|
|
||||||
|
typedef struct _BL_PACKED_BOOT_ERROR
|
||||||
|
{
|
||||||
|
PBL_BOOT_ERROR BootError;
|
||||||
|
ULONG Unknown;
|
||||||
|
ULONG Size;
|
||||||
|
} BL_PACKED_BOOT_ERROR, *PBL_PACKED_BOOT_ERROR;
|
||||||
|
|
||||||
|
#define BL_FATAL_ERROR_BCD_READ 0x02
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "bootmgr.h"
|
#include "bootmgr.h"
|
||||||
#include <bcd.h>
|
|
||||||
|
|
||||||
/* DATA STRUCTURES ***********************************************************/
|
/* DATA STRUCTURES ***********************************************************/
|
||||||
|
|
||||||
|
@ -206,8 +205,7 @@ EfiInitpConvertEfiFilePath (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ULONG BytesAppended, DataSize, StringLength;
|
ULONG BytesAppended, DataSize, StringLength;
|
||||||
PBCDE_STRING StringEntry;
|
PWCHAR StringEntry, PathString;
|
||||||
PWCHAR PathString;
|
|
||||||
FILEPATH_DEVICE_PATH *FilePath;
|
FILEPATH_DEVICE_PATH *FilePath;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
@ -227,8 +225,8 @@ EfiInitpConvertEfiFilePath (
|
||||||
Option->DataOffset = sizeof(*Option);
|
Option->DataOffset = sizeof(*Option);
|
||||||
|
|
||||||
/* Extract the string option */
|
/* Extract the string option */
|
||||||
StringEntry = (PBCDE_STRING)(Option + 1);
|
StringEntry = (PWCHAR)(Option + 1);
|
||||||
PathString = StringEntry->String;
|
PathString = StringEntry;
|
||||||
|
|
||||||
/* Start parsing the device path */
|
/* Start parsing the device path */
|
||||||
FilePath = (FILEPATH_DEVICE_PATH*)DevicePath;
|
FilePath = (FILEPATH_DEVICE_PATH*)DevicePath;
|
||||||
|
@ -282,7 +280,7 @@ EfiInitpConvertEfiFilePath (
|
||||||
DataSize += sizeof(UNICODE_NULL);
|
DataSize += sizeof(UNICODE_NULL);
|
||||||
|
|
||||||
/* Check if all of this has amounted to a single NULL-char */
|
/* Check if all of this has amounted to a single NULL-char */
|
||||||
if (PathString == StringEntry->String)
|
if (PathString == StringEntry)
|
||||||
{
|
{
|
||||||
/* Then this option is empty */
|
/* Then this option is empty */
|
||||||
Option->Empty = TRUE;
|
Option->Empty = TRUE;
|
||||||
|
@ -520,7 +518,7 @@ EfiInitpConvertEfiDevicePath (
|
||||||
_In_ ULONG MaximumLength
|
_In_ ULONG MaximumLength
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PBCDE_DEVICE DeviceEntry;
|
PBCD_DEVICE_OPTION BcdDevice;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
/* Make sure we have enough space for the option */
|
/* Make sure we have enough space for the option */
|
||||||
|
@ -534,15 +532,17 @@ EfiInitpConvertEfiDevicePath (
|
||||||
RtlZeroMemory(Option, sizeof(*Option));
|
RtlZeroMemory(Option, sizeof(*Option));
|
||||||
|
|
||||||
/* Make sure we have enough space for the device entry */
|
/* Make sure we have enough space for the device entry */
|
||||||
if ((MaximumLength - sizeof(*Option)) < (ULONG)FIELD_OFFSET(BCDE_DEVICE, Device))
|
if ((MaximumLength - sizeof(*Option)) <
|
||||||
|
(ULONG)FIELD_OFFSET(BCD_DEVICE_OPTION, DeviceDescriptor))
|
||||||
{
|
{
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
goto Quickie;
|
goto Quickie;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill it out */
|
/* Fill it out */
|
||||||
DeviceEntry = (PBCDE_DEVICE)(Option + 1);
|
BcdDevice = (PBCD_DEVICE_OPTION)(Option + 1);
|
||||||
Status = EfiInitTranslateDevicePath(DevicePath, &DeviceEntry->Device);
|
Status = EfiInitTranslateDevicePath(DevicePath,
|
||||||
|
&BcdDevice->DeviceDescriptor);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
goto Quickie;
|
goto Quickie;
|
||||||
|
@ -551,8 +551,8 @@ EfiInitpConvertEfiDevicePath (
|
||||||
/* Fill out the rest of the option structure */
|
/* Fill out the rest of the option structure */
|
||||||
Option->DataOffset = sizeof(*Option);
|
Option->DataOffset = sizeof(*Option);
|
||||||
Option->Type = DeviceType;
|
Option->Type = DeviceType;
|
||||||
Option->DataSize = FIELD_OFFSET(BCDE_DEVICE, Device) +
|
Option->DataSize = FIELD_OFFSET(BCD_DEVICE_OPTION, DeviceDescriptor) +
|
||||||
DeviceEntry->Device.Size;
|
BcdDevice->DeviceDescriptor.Size;
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
Quickie:
|
Quickie:
|
||||||
|
@ -618,7 +618,7 @@ EfiInitpCreateApplicationEntry (
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
UNICODE_STRING GuidString;
|
UNICODE_STRING GuidString;
|
||||||
GUID ObjectGuid;
|
GUID ObjectGuid;
|
||||||
PBCDE_DEVICE BcdDevice;
|
PBCD_DEVICE_OPTION BcdDevice;
|
||||||
BOOLEAN HaveBinaryOptions, HaveGuid;
|
BOOLEAN HaveBinaryOptions, HaveGuid;
|
||||||
PBL_FILE_PATH_DESCRIPTOR OsPath;
|
PBL_FILE_PATH_DESCRIPTOR OsPath;
|
||||||
EFI_DEVICE_PATH *OsDevicePath;
|
EFI_DEVICE_PATH *OsDevicePath;
|
||||||
|
@ -719,7 +719,7 @@ EfiInitpCreateApplicationEntry (
|
||||||
|
|
||||||
/* Extract the device descriptor and return it */
|
/* Extract the device descriptor and return it */
|
||||||
BcdDevice = (PVOID)((ULONG_PTR)&Entry->BcdData + Entry->BcdData.DataOffset);
|
BcdDevice = (PVOID)((ULONG_PTR)&Entry->BcdData + Entry->BcdData.DataOffset);
|
||||||
*AppEntryDevice = &BcdDevice->Device;
|
*AppEntryDevice = &BcdDevice->DeviceDescriptor;
|
||||||
|
|
||||||
/* Calculate how big this option was and consume that from the buffer */
|
/* Calculate how big this option was and consume that from the buffer */
|
||||||
TotalOptionSize = BlGetBootOptionSize(&Entry->BcdData);
|
TotalOptionSize = BlGetBootOptionSize(&Entry->BcdData);
|
||||||
|
|
|
@ -137,17 +137,39 @@ typedef enum BcdOSLoaderElementTypes
|
||||||
BcdOSLoaderInteger_XSaveDisable = 0x2500012b
|
BcdOSLoaderInteger_XSaveDisable = 0x2500012b
|
||||||
} BcdOSLoaderElementTypes;
|
} BcdOSLoaderElementTypes;
|
||||||
|
|
||||||
|
typedef enum BcdBootMgrElementTypes
|
||||||
|
{
|
||||||
|
BcdBootMgrObjectList_DisplayOrder = 0x24000001,
|
||||||
|
BcdBootMgrObjectList_BootSequence = 0x24000002,
|
||||||
|
BcdBootMgrObject_DefaultObject = 0x23000003,
|
||||||
|
BcdBootMgrInteger_Timeout = 0x25000004,
|
||||||
|
BcdBootMgrBoolean_AttemptResume = 0x26000005,
|
||||||
|
BcdBootMgrObject_ResumeObject = 0x23000006,
|
||||||
|
BcdBootMgrObjectList_ToolsDisplayOrder = 0x24000010,
|
||||||
|
BcdBootMgrBoolean_DisplayBootMenu = 0x26000020,
|
||||||
|
BcdBootMgrBoolean_NoErrorDisplay = 0x26000021,
|
||||||
|
BcdBootMgrDevice_BcdDevice = 0x21000022,
|
||||||
|
BcdBootMgrString_BcdFilePath = 0x22000023,
|
||||||
|
BcdBootMgrBoolean_ProcessCustomActionsFirst = 0x26000028,
|
||||||
|
BcdBootMgrIntegerList_CustomActionsList = 0x27000030,
|
||||||
|
BcdBootMgrBoolean_PersistBootSequence = 0x26000031
|
||||||
|
} BcdBootMgrElementTypes;
|
||||||
|
|
||||||
|
|
||||||
/* DATA STRUCTURES ***********************************************************/
|
/* DATA STRUCTURES ***********************************************************/
|
||||||
|
|
||||||
typedef struct _BCDE_DEVICE
|
typedef struct _BCD_DEVICE_OPTION
|
||||||
{
|
{
|
||||||
GUID AdditionalOptions;
|
GUID AssociatedEntry;
|
||||||
BL_DEVICE_DESCRIPTOR Device;
|
BL_DEVICE_DESCRIPTOR DeviceDescriptor;
|
||||||
} BCDE_DEVICE, *PBCDE_DEVICE;
|
} BCD_DEVICE_OPTION, *PBCD_DEVICE_OPTION;
|
||||||
|
|
||||||
typedef struct _BCDE_STRING
|
/* FUNCTIONS ******************************************************************/
|
||||||
{
|
|
||||||
WCHAR String[ANYSIZE_ARRAY];
|
NTSTATUS
|
||||||
} BCDE_STRING, *PBCDE_STRING;
|
BcdOpenStoreFromFile (
|
||||||
|
_In_ PUNICODE_STRING FileName,
|
||||||
|
_In_ PHANDLE StoreHandle
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*b
|
||||||
* COPYRIGHT: See COPYING.ARM in the top level directory
|
* COPYRIGHT: See COPYING.ARM in the top level directory
|
||||||
* PROJECT: ReactOS UEFI Boot Library
|
* PROJECT: ReactOS UEFI Boot Library
|
||||||
* FILE: boot/environ/include/bl.h
|
* FILE: boot/environ/include/bl.h
|
||||||
|
@ -30,6 +30,10 @@
|
||||||
#include <UgaDraw.h>
|
#include <UgaDraw.h>
|
||||||
#include <BlockIo.h>
|
#include <BlockIo.h>
|
||||||
|
|
||||||
|
/* Registry Headers */
|
||||||
|
#define __FREELDR_H
|
||||||
|
#include <cmlib.h>
|
||||||
|
|
||||||
/* DEFINES *******************************************************************/
|
/* DEFINES *******************************************************************/
|
||||||
|
|
||||||
#define BL_APPLICATION_FLAG_CONVERTED_FROM_EFI 0x01
|
#define BL_APPLICATION_FLAG_CONVERTED_FROM_EFI 0x01
|
||||||
|
@ -85,6 +89,30 @@
|
||||||
|
|
||||||
#define BL_MEMORY_CLASS_SHIFT 28
|
#define BL_MEMORY_CLASS_SHIFT 28
|
||||||
|
|
||||||
|
#define BL_FILE_READ_ACCESS 0x01
|
||||||
|
#define BL_FILE_WRITE_ACCESS 0x02
|
||||||
|
#define BL_DIRECTORY_ACCESS 0x04
|
||||||
|
#define BL_UNKNOWN_ACCESS 0x10
|
||||||
|
|
||||||
|
#define BL_DEVICE_ENTRY_OPENED 0x01
|
||||||
|
#define BL_DEVICE_ENTRY_READ_ACCESS 0x02
|
||||||
|
#define BL_DEVICE_ENTRY_WRITE_ACCESS 0x04
|
||||||
|
|
||||||
|
#define BL_FILE_ENTRY_OPENED 0x01
|
||||||
|
#define BL_FILE_ENTRY_READ_ACCESS 0x02
|
||||||
|
#define BL_FILE_ENTRY_WRITE_ACCESS 0x04
|
||||||
|
#define BL_FILE_ENTRY_UNKNOWN_ACCESS 0x10
|
||||||
|
|
||||||
|
#define BL_IMG_VALID_FILE 0x01
|
||||||
|
#define BL_IMG_MEMORY_FILE 0x02
|
||||||
|
#define BL_IMG_REMOTE_FILE 0x04
|
||||||
|
|
||||||
|
#define BL_LOAD_IMG_VIRTUAL_BUFFER 0x01
|
||||||
|
#define BL_LOAD_IMG_EXISTING_BUFFER 0x04
|
||||||
|
#define BL_LOAD_IMG_UNKNOWN_BUFFER_FLAG 0x08
|
||||||
|
#define BL_LOAD_IMG_COMPUTE_SIGNATURE 0x10
|
||||||
|
#define BL_LOAD_IMG_COMPUTE_HASH 0x40000
|
||||||
|
|
||||||
/* ENUMERATIONS **************************************************************/
|
/* ENUMERATIONS **************************************************************/
|
||||||
|
|
||||||
typedef enum _BL_COLOR
|
typedef enum _BL_COLOR
|
||||||
|
@ -169,6 +197,7 @@ typedef enum _BL_PARTITION_TYPE
|
||||||
//
|
//
|
||||||
typedef enum _BL_PATH_TYPE
|
typedef enum _BL_PATH_TYPE
|
||||||
{
|
{
|
||||||
|
InternalPath = 3,
|
||||||
EfiPath = 4
|
EfiPath = 4
|
||||||
} BL_PATH_TYPE;
|
} BL_PATH_TYPE;
|
||||||
|
|
||||||
|
@ -266,6 +295,7 @@ typedef enum _BL_MEMORY_ATTR
|
||||||
/* CALLBACKS *****************************************************************/
|
/* CALLBACKS *****************************************************************/
|
||||||
|
|
||||||
struct _BL_FILE_ENTRY;
|
struct _BL_FILE_ENTRY;
|
||||||
|
struct _BL_FILE_INFORMATION;
|
||||||
typedef
|
typedef
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
(*PBL_FILE_OPEN) (
|
(*PBL_FILE_OPEN) (
|
||||||
|
@ -284,7 +314,10 @@ NTSTATUS
|
||||||
typedef
|
typedef
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
(*PBL_FILE_READ) (
|
(*PBL_FILE_READ) (
|
||||||
VOID
|
_In_ struct _BL_FILE_ENTRY* FileEntry,
|
||||||
|
_In_ PVOID Buffer,
|
||||||
|
_In_ ULONG Size,
|
||||||
|
_Out_ PULONG BytesRead
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
|
@ -302,13 +335,15 @@ NTSTATUS
|
||||||
typedef
|
typedef
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
(*PBL_FILE_GET_INFO) (
|
(*PBL_FILE_GET_INFO) (
|
||||||
VOID
|
_In_ struct _BL_FILE_ENTRY* FileEntry,
|
||||||
|
_Out_ struct _BL_FILE_INFORMATION* FileInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
(*PBL_FILE_SET_INFO) (
|
(*PBL_FILE_SET_INFO) (
|
||||||
VOID
|
_In_ struct _BL_FILE_ENTRY* FileEntry,
|
||||||
|
_In_ struct _BL_FILE_INFORMATION* FileInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
|
@ -745,6 +780,12 @@ typedef struct _BL_ADDRESS_RANGE
|
||||||
ULONGLONG Maximum;
|
ULONGLONG Maximum;
|
||||||
} BL_ADDRESS_RANGE, *PBL_ADDRESS_RANGE;
|
} BL_ADDRESS_RANGE, *PBL_ADDRESS_RANGE;
|
||||||
|
|
||||||
|
typedef struct _BL_FILE_INFORMATION
|
||||||
|
{
|
||||||
|
ULONGLONG FileSize;
|
||||||
|
ULONGLONG CurrentOffset;
|
||||||
|
} BL_FILE_INFORMATION, *PBL_FILE_INFORMATION;
|
||||||
|
|
||||||
typedef struct _BL_FILE_CALLBACKS
|
typedef struct _BL_FILE_CALLBACKS
|
||||||
{
|
{
|
||||||
PBL_FILE_OPEN Open;
|
PBL_FILE_OPEN Open;
|
||||||
|
@ -767,7 +808,6 @@ typedef struct _BL_FILE_ENTRY
|
||||||
ULONGLONG Unknown1;
|
ULONGLONG Unknown1;
|
||||||
ULONGLONG Unknown2;
|
ULONGLONG Unknown2;
|
||||||
BL_FILE_CALLBACKS Callbacks;
|
BL_FILE_CALLBACKS Callbacks;
|
||||||
//PBL_FILE_DESTROY_CALLBACK DestroyCallback;
|
|
||||||
PVOID FsSpecificData;
|
PVOID FsSpecificData;
|
||||||
} BL_FILE_ENTRY, *PBL_FILE_ENTRY;
|
} BL_FILE_ENTRY, *PBL_FILE_ENTRY;
|
||||||
|
|
||||||
|
@ -966,6 +1006,18 @@ typedef struct _BL_DEVICE_ENTRY
|
||||||
PBL_DEVICE_DESCRIPTOR DeviceDescriptor;
|
PBL_DEVICE_DESCRIPTOR DeviceDescriptor;
|
||||||
} BL_DEVICE_ENTRY, *PBL_DEVICE_ENTRY;
|
} BL_DEVICE_ENTRY, *PBL_DEVICE_ENTRY;
|
||||||
|
|
||||||
|
typedef struct _BL_IMG_FILE
|
||||||
|
{
|
||||||
|
UCHAR Flags;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
PVOID BaseAddress;
|
||||||
|
ULONG FileId;
|
||||||
|
};
|
||||||
|
ULONG FileSize;
|
||||||
|
PWCHAR FileName;
|
||||||
|
} BL_IMG_FILE, *PBL_IMG_FILE;
|
||||||
|
|
||||||
/* INLINE ROUTINES ***********************************************************/
|
/* INLINE ROUTINES ***********************************************************/
|
||||||
|
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
|
@ -1238,8 +1290,44 @@ EtfsMount (
|
||||||
_Out_ PBL_FILE_ENTRY* FileEntry
|
_Out_ PBL_FILE_ENTRY* FileEntry
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* DEBUG ROUTINES ************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
BlBdDebuggerEnabled (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlBdPullRemoteFile (
|
||||||
|
_In_ PWCHAR FilePath,
|
||||||
|
_Out_ PVOID BaseAddress,
|
||||||
|
_Out_ PULONGLONG FileSize
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BlStatusPrint (
|
||||||
|
_In_ PCWCH Format,
|
||||||
|
...
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BlStatusError (
|
||||||
|
_In_ ULONG ErrorCode,
|
||||||
|
_In_ ULONG Parameter1,
|
||||||
|
_In_ ULONG_PTR Parameter2,
|
||||||
|
_In_ ULONG_PTR Parameter3,
|
||||||
|
_In_ ULONG_PTR Parameter4
|
||||||
|
);
|
||||||
|
|
||||||
/* UTILITY ROUTINES **********************************************************/
|
/* UTILITY ROUTINES **********************************************************/
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BlUtlUpdateProgress (
|
||||||
|
_In_ ULONG Percentage,
|
||||||
|
_Out_opt_ PBOOLEAN Completed
|
||||||
|
);
|
||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
EfiGetEfiStatusCode(
|
EfiGetEfiStatusCode(
|
||||||
_In_ NTSTATUS Status
|
_In_ NTSTATUS Status
|
||||||
|
@ -1265,6 +1353,11 @@ BlGetApplicationIdentifier (
|
||||||
VOID
|
VOID
|
||||||
);
|
);
|
||||||
|
|
||||||
|
PWCHAR
|
||||||
|
BlResourceFindMessage (
|
||||||
|
_In_ ULONG MsgId
|
||||||
|
);
|
||||||
|
|
||||||
/* TABLE ROUTINES ************************************************************/
|
/* TABLE ROUTINES ************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -1353,6 +1446,14 @@ BlGetBootOptionBoolean (
|
||||||
_Out_ PBOOLEAN Value
|
_Out_ PBOOLEAN Value
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlGetBootOptionDevice (
|
||||||
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
_In_ ULONG Type,
|
||||||
|
_Out_ PBL_DEVICE_DESCRIPTOR* Value,
|
||||||
|
_In_opt_ PBL_BCD_OPTION* ExtraOptions
|
||||||
|
);
|
||||||
|
|
||||||
/* CONTEXT ROUTINES **********************************************************/
|
/* CONTEXT ROUTINES **********************************************************/
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -1423,6 +1524,20 @@ MmMdFreeDescriptor (
|
||||||
|
|
||||||
/* PAGE ALLOCATOR ROUTINES ***************************************************/
|
/* PAGE ALLOCATOR ROUTINES ***************************************************/
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlMmAllocatePhysicalPages(
|
||||||
|
_Inout_ PPHYSICAL_ADDRESS Address,
|
||||||
|
_In_ BL_MEMORY_TYPE MemoryType,
|
||||||
|
_In_ ULONGLONG PageCount,
|
||||||
|
_In_ ULONG Attributes,
|
||||||
|
_In_ ULONG Alignment
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlMmFreePhysicalPages (
|
||||||
|
_In_ PHYSICAL_ADDRESS Address
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
MmPapAllocatePagesInRange (
|
MmPapAllocatePagesInRange (
|
||||||
_Inout_ PVOID* PhysicalAddress,
|
_Inout_ PVOID* PhysicalAddress,
|
||||||
|
@ -1450,6 +1565,12 @@ BlMmMapPhysicalAddressEx (
|
||||||
_In_ PHYSICAL_ADDRESS PhysicalAddress
|
_In_ PHYSICAL_ADDRESS PhysicalAddress
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlMmUnmapVirtualAddressEx (
|
||||||
|
_In_ PVOID VirtualAddress,
|
||||||
|
_In_ ULONGLONG Size
|
||||||
|
);
|
||||||
|
|
||||||
/* BLOCK ALLOCATOR ROUTINES **************************************************/
|
/* BLOCK ALLOCATOR ROUTINES **************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -1525,11 +1646,27 @@ BlFileClose (
|
||||||
_In_ ULONG FileId
|
_In_ ULONG FileId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlFileReadAtOffsetEx (
|
||||||
|
_In_ ULONG FileId,
|
||||||
|
_In_ ULONG Size,
|
||||||
|
_In_ ULONGLONG ByteOffset,
|
||||||
|
_In_ PVOID Buffer,
|
||||||
|
_Out_ PULONG BytesReturned,
|
||||||
|
_In_ ULONG Flags
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlFileGetInformation (
|
||||||
|
_In_ ULONG FileId,
|
||||||
|
_In_ PBL_FILE_INFORMATION FileInfo
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
BlFileOpen (
|
BlFileOpen (
|
||||||
_In_ ULONG DeviceId,
|
_In_ ULONG DeviceId,
|
||||||
_In_ PWCHAR FileName,
|
_In_ PWCHAR FileName,
|
||||||
_In_ ULONG OpenFlags,
|
_In_ ULONG Flags,
|
||||||
_Out_ PULONG FileId
|
_Out_ PULONG FileId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1691,4 +1828,5 @@ extern BL_DISPLAY_MODE ConsoleGraphicalResolutionList[];
|
||||||
extern BL_DISPLAY_MODE ConsoleTextResolutionList[];
|
extern BL_DISPLAY_MODE ConsoleTextResolutionList[];
|
||||||
extern ULONG ConsoleGraphicalResolutionListSize;
|
extern ULONG ConsoleGraphicalResolutionListSize;
|
||||||
extern PVOID DspRemoteInputConsole;
|
extern PVOID DspRemoteInputConsole;
|
||||||
|
extern WCHAR BlScratchBuffer[8192];
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,7 +31,6 @@ BL_FILE_SYSTEM_REGISTRATION_TABLE EtfsRegisterFunctionTable =
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern ULONG DmTableEntries;
|
extern ULONG DmTableEntries;
|
||||||
extern PVOID* DmDeviceTable;
|
extern PVOID* DmDeviceTable;
|
||||||
|
|
||||||
|
@ -120,7 +119,9 @@ FileTableCompareWithSubsetAttributes (
|
||||||
|
|
||||||
Found = FALSE;
|
Found = FALSE;
|
||||||
|
|
||||||
if ((FileEntry->DeviceId == DeviceId) && !(_wcsicmp(FileEntry->FilePath, FilePath)) && (FileEntry->Unknown == Unknown))
|
if ((FileEntry->DeviceId == DeviceId) &&
|
||||||
|
!(_wcsicmp(FileEntry->FilePath, FilePath)) &&
|
||||||
|
(FileEntry->Unknown == Unknown))
|
||||||
{
|
{
|
||||||
if ((!(Flags & 1) || (FileEntry->Flags & 2)) && (!(Flags & 2) || (FileEntry->Flags & 4)))
|
if ((!(Flags & 1) || (FileEntry->Flags & 2)) && (!(Flags & 2) || (FileEntry->Flags & 4)))
|
||||||
{
|
{
|
||||||
|
@ -151,7 +152,9 @@ FileTableCompareWithSameAttributes (
|
||||||
|
|
||||||
Found = FALSE;
|
Found = FALSE;
|
||||||
|
|
||||||
if ((FileEntry->DeviceId == DeviceId) && !(_wcsicmp(FileEntry->FilePath, FilePath)) && (FileEntry->Unknown == Unknown))
|
if ((FileEntry->DeviceId == DeviceId) &&
|
||||||
|
!(_wcsicmp(FileEntry->FilePath, FilePath)) &&
|
||||||
|
(FileEntry->Unknown == Unknown))
|
||||||
{
|
{
|
||||||
if ((!(Flags & 1) || (FileEntry->Flags & 2)) && ((Flags & 1) || !(FileEntry->Flags & 2)) && (!(Flags & 2) || (FileEntry->Flags & 4)) && ((Flags & 2) || !(FileEntry->Flags & 4)))
|
if ((!(Flags & 1) || (FileEntry->Flags & 2)) && ((Flags & 1) || !(FileEntry->Flags & 2)) && (!(Flags & 2) || (FileEntry->Flags & 4)) && ((Flags & 2) || !(FileEntry->Flags & 4)))
|
||||||
{
|
{
|
||||||
|
@ -192,24 +195,25 @@ FileTableDestroyEntry (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BL_FILE_PURGE_LIMIT 512
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
FileTablePurgeEntry (
|
FileTablePurgeEntry (
|
||||||
_In_ PVOID Entry
|
_In_ PVOID Entry
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PBL_FILE_ENTRY FileEntry = (PBL_FILE_ENTRY)Entry;
|
PBL_FILE_ENTRY FileEntry = (PBL_FILE_ENTRY)Entry;
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
if (((FileEntry->Flags & 1) || (FileEntry->Flags & 0x10000)) && (FileEntries < 0x200))
|
/* Don't purge opened files, or if there's less than 512 files cached */
|
||||||
|
if (((FileEntry->Flags & BL_FILE_ENTRY_OPENED) ||
|
||||||
|
(FileEntry->Flags & 0x10000)) &&
|
||||||
|
(FileEntries < BL_FILE_PURGE_LIMIT))
|
||||||
{
|
{
|
||||||
Status = STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Status = FileTableDestroyEntry(FileEntry, FileEntry->FileId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
/* Purge the entry othwrwise */
|
||||||
|
return FileTableDestroyEntry(FileEntry, FileEntry->FileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -219,28 +223,34 @@ BlFileClose (
|
||||||
{
|
{
|
||||||
PBL_FILE_ENTRY FileEntry;
|
PBL_FILE_ENTRY FileEntry;
|
||||||
|
|
||||||
|
/* Validate the file ID */
|
||||||
if (FileEntries <= FileId)
|
if (FileEntries <= FileId)
|
||||||
{
|
{
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure a file entry actually exists */
|
||||||
FileEntry = FileTable[FileId];
|
FileEntry = FileTable[FileId];
|
||||||
if (!FileEntry)
|
if (!FileEntry)
|
||||||
{
|
{
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(FileEntry->Flags & 1))
|
/* And that it's actually open */
|
||||||
|
if (!(FileEntry->Flags & BL_FILE_ENTRY_OPENED))
|
||||||
{
|
{
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Drop a reference, check if this was the last one */
|
||||||
--FileEntry->ReferenceCount;
|
--FileEntry->ReferenceCount;
|
||||||
if (!FileEntry->ReferenceCount)
|
if (!FileEntry->ReferenceCount)
|
||||||
{
|
{
|
||||||
FileEntry->Flags &= ~1;
|
/* File is no longer open */
|
||||||
|
FileEntry->Flags &= ~BL_FILE_ENTRY_OPENED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* All good */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,46 +261,58 @@ FileIoOpen (
|
||||||
_In_ ULONG Flags,
|
_In_ ULONG Flags,
|
||||||
_In_ ULONG Unknown,
|
_In_ ULONG Unknown,
|
||||||
_In_ PBL_TBL_LOOKUP_ROUTINE CompareRoutine,
|
_In_ PBL_TBL_LOOKUP_ROUTINE CompareRoutine,
|
||||||
_Out_ PBL_FILE_ENTRY *ReturnFileEntry
|
_Out_opt_ PBL_FILE_ENTRY *NewFileEntry
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PWCHAR FileNameCopy, ParentFileName;
|
PWCHAR FileNameCopy, ParentFileName;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PBL_DEVICE_ENTRY DeviceEntry;
|
PBL_DEVICE_ENTRY DeviceEntry;
|
||||||
PBL_FILE_SYSTEM_ENTRY FileSystem;
|
PBL_FILE_SYSTEM_ENTRY FileSystem;
|
||||||
ULONG FileId;
|
ULONG FileId, CheckFlags;
|
||||||
PBL_FILE_ENTRY ParentDirectoryEntry, FileEntry;
|
PBL_FILE_ENTRY DirectoryEntry, FileEntry;
|
||||||
PLIST_ENTRY NextEntry, ListHead;
|
PLIST_ENTRY NextEntry, ListHead;
|
||||||
|
|
||||||
ParentDirectoryEntry = NULL;
|
/* Preinitialize variables for failure */
|
||||||
|
DirectoryEntry = NULL;
|
||||||
FileNameCopy = NULL;
|
FileNameCopy = NULL;
|
||||||
Flags |= 1;
|
|
||||||
ParentFileName = NULL;
|
ParentFileName = NULL;
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
/* Bail out if the device ID is invalid */
|
||||||
if (DmTableEntries <= DeviceId)
|
if (DmTableEntries <= DeviceId)
|
||||||
{
|
{
|
||||||
return STATUS_ACCESS_DENIED;
|
return STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bail out if there's no device entry */
|
||||||
DeviceEntry = DmDeviceTable[DeviceId];
|
DeviceEntry = DmDeviceTable[DeviceId];
|
||||||
if (!DeviceEntry)
|
if (!DeviceEntry)
|
||||||
{
|
{
|
||||||
return STATUS_ACCESS_DENIED;
|
return STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Flags & 1) && (!(DeviceEntry->Flags & 1) || !(DeviceEntry->Flags & 2)))
|
/* Read access is always required for touching the device */
|
||||||
|
CheckFlags = Flags | BL_FILE_READ_ACCESS;
|
||||||
|
|
||||||
|
/* Check if the device is granting us read access */
|
||||||
|
if ((CheckFlags & BL_FILE_READ_ACCESS) &&
|
||||||
|
(!(DeviceEntry->Flags & BL_DEVICE_ENTRY_OPENED) ||
|
||||||
|
!(DeviceEntry->Flags & BL_DEVICE_ENTRY_READ_ACCESS)))
|
||||||
{
|
{
|
||||||
EfiPrintf(L"Access denied\r\n");
|
EfiPrintf(L"Access denied\r\n");
|
||||||
return STATUS_ACCESS_DENIED;
|
return STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Flags & 2) && (!(DeviceEntry->Flags & 1) || !(DeviceEntry->Flags & 4)))
|
/* Check if the device is granting us write access */
|
||||||
|
if ((CheckFlags & BL_FILE_WRITE_ACCESS) &&
|
||||||
|
(!(DeviceEntry->Flags & BL_DEVICE_ENTRY_OPENED) ||
|
||||||
|
!(DeviceEntry->Flags & BL_DEVICE_ENTRY_WRITE_ACCESS)))
|
||||||
{
|
{
|
||||||
EfiPrintf(L"Access denied2\r\n");
|
EfiPrintf(L"Access denied2\r\n");
|
||||||
return STATUS_ACCESS_DENIED;
|
return STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if we already have this file open */
|
||||||
FileEntry = (PBL_FILE_ENTRY )BlTblFindEntry(FileTable,
|
FileEntry = (PBL_FILE_ENTRY )BlTblFindEntry(FileTable,
|
||||||
FileEntries,
|
FileEntries,
|
||||||
&FileId,
|
&FileId,
|
||||||
|
@ -305,80 +327,89 @@ FileIoOpen (
|
||||||
goto FileOpened;
|
goto FileOpened;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if we are opening the root drive or an actual file/directory */
|
||||||
if ((*FileName != OBJ_NAME_PATH_SEPARATOR) || (FileName[1]))
|
if ((*FileName != OBJ_NAME_PATH_SEPARATOR) || (FileName[1]))
|
||||||
{
|
{
|
||||||
|
/* Get the name of the directory */
|
||||||
ParentFileName = FileIoCopyParentDirectoryPath(FileName);
|
ParentFileName = FileIoCopyParentDirectoryPath(FileName);
|
||||||
if (!ParentFileName)
|
if (!ParentFileName)
|
||||||
{
|
{
|
||||||
Status = STATUS_NO_MEMORY;
|
Status = STATUS_NO_MEMORY;
|
||||||
goto FileOpenEnd;
|
goto Quickie;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open it */
|
||||||
Status = FileIoOpen(DeviceId,
|
Status = FileIoOpen(DeviceId,
|
||||||
ParentFileName,
|
ParentFileName,
|
||||||
5,
|
BL_FILE_READ_ACCESS | BL_DIRECTORY_ACCESS,
|
||||||
Unknown,
|
Unknown,
|
||||||
FileTableCompareWithSubsetAttributes,
|
FileTableCompareWithSubsetAttributes,
|
||||||
&ParentDirectoryEntry);
|
&DirectoryEntry);
|
||||||
if (Status < 0)
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
goto FileOpenEnd;
|
goto Quickie;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now get the the file name itself */
|
||||||
FileNameCopy = FileIoCopyFileName(FileName);
|
FileNameCopy = FileIoCopyFileName(FileName);
|
||||||
if (!FileNameCopy)
|
if (!FileNameCopy)
|
||||||
{
|
{
|
||||||
Status = STATUS_NO_MEMORY;
|
Status = STATUS_NO_MEMORY;
|
||||||
goto FileOpenEnd;
|
goto Quickie;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = ParentDirectoryEntry->Callbacks.Open(ParentDirectoryEntry,
|
/* Open it */
|
||||||
FileNameCopy,
|
Status = DirectoryEntry->Callbacks.Open(DirectoryEntry,
|
||||||
Flags,
|
FileNameCopy,
|
||||||
&FileEntry);
|
Flags,
|
||||||
|
&FileEntry);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EfiPrintf(L"Opening root drive\r\n");
|
/* We're opening the root, scan through all the file systems */
|
||||||
Status = STATUS_UNSUCCESSFUL;
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
ListHead = &RegisteredFileSystems;
|
ListHead = &RegisteredFileSystems;
|
||||||
NextEntry = ListHead->Flink;
|
NextEntry = ListHead->Flink;
|
||||||
while (NextEntry != ListHead)
|
while (NextEntry != ListHead)
|
||||||
{
|
{
|
||||||
|
/* Try to mount this one */
|
||||||
FileSystem = CONTAINING_RECORD(NextEntry, BL_FILE_SYSTEM_ENTRY, ListEntry);
|
FileSystem = CONTAINING_RECORD(NextEntry, BL_FILE_SYSTEM_ENTRY, ListEntry);
|
||||||
|
|
||||||
EfiPrintf(L"Calling filesystem %p mount routine: %p\r\n", FileSystem, FileSystem->MountCallback);
|
|
||||||
Status = FileSystem->MountCallback(DeviceId, Unknown, &FileEntry);
|
Status = FileSystem->MountCallback(DeviceId, Unknown, &FileEntry);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
/* Mount successful */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try the next file system */
|
||||||
NextEntry = NextEntry->Flink;
|
NextEntry = NextEntry->Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Nothing to free on this path */
|
||||||
FileNameCopy = NULL;
|
FileNameCopy = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle failure */
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
EfiPrintf(L"Could not open file!: %lx\r\n", Status);
|
EfiPrintf(L"Could not open file!: %lx\r\n", Status);
|
||||||
goto FileOpenEnd;
|
goto Quickie;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save the unknown */
|
||||||
FileEntry->Unknown = Unknown;
|
FileEntry->Unknown = Unknown;
|
||||||
|
|
||||||
if (Flags & 1)
|
/* Convert open flags into entry flags */
|
||||||
|
if (Flags & BL_FILE_READ_ACCESS)
|
||||||
{
|
{
|
||||||
FileEntry->Flags |= 2u;
|
FileEntry->Flags |= BL_FILE_ENTRY_READ_ACCESS;
|
||||||
}
|
}
|
||||||
|
if (Flags & BL_FILE_WRITE_ACCESS)
|
||||||
if (Flags & 2)
|
|
||||||
{
|
{
|
||||||
FileEntry->Flags |= 4u;
|
FileEntry->Flags |= BL_FILE_ENTRY_WRITE_ACCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save the file into the file table */
|
||||||
Status = BlTblSetEntry(&FileTable,
|
Status = BlTblSetEntry(&FileTable,
|
||||||
&FileEntries,
|
&FileEntries,
|
||||||
(PVOID)FileEntry,
|
(PVOID)FileEntry,
|
||||||
|
@ -386,48 +417,62 @@ FileIoOpen (
|
||||||
FileTablePurgeEntry);
|
FileTablePurgeEntry);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
/* Close it if that failed */
|
||||||
FileEntry->Callbacks.Close(FileEntry);
|
FileEntry->Callbacks.Close(FileEntry);
|
||||||
goto FileOpenEnd;
|
goto Quickie;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add a reference on the device, and save our file ID */
|
||||||
++DeviceEntry->ReferenceCount;
|
++DeviceEntry->ReferenceCount;
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
EfiPrintf(L"File %s opened with ID: %lx\r\n", FileEntry->FilePath, FileId);
|
|
||||||
FileEntry->FileId = FileId;
|
FileEntry->FileId = FileId;
|
||||||
|
|
||||||
|
EfiPrintf(L"File %s opened with ID: %lx\r\n", FileEntry->FilePath, FileId);
|
||||||
|
|
||||||
FileOpened:
|
FileOpened:
|
||||||
|
/* Add a reference to the file entry, and see if this is the first one */
|
||||||
if (++FileEntry->ReferenceCount == 1)
|
if (++FileEntry->ReferenceCount == 1)
|
||||||
{
|
{
|
||||||
|
/* Reset unknowns */
|
||||||
FileEntry->Unknown1 = 0;
|
FileEntry->Unknown1 = 0;
|
||||||
FileEntry->Unknown2 = 0;
|
FileEntry->Unknown2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileEntry->Flags |= 1;
|
/* Set the file as opened */
|
||||||
|
FileEntry->Flags |= BL_FILE_ENTRY_OPENED;
|
||||||
if (Flags & 0x10)
|
|
||||||
|
/* Not sure what this flag does */
|
||||||
|
if (Flags & BL_UNKNOWN_ACCESS)
|
||||||
{
|
{
|
||||||
FileEntry->Flags |= 0x10;
|
FileEntry->Flags |= BL_FILE_ENTRY_UNKNOWN_ACCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ReturnFileEntry)
|
/* If the caller wanted the entry back, return it */
|
||||||
|
if (NewFileEntry)
|
||||||
{
|
{
|
||||||
*ReturnFileEntry = FileEntry;
|
*NewFileEntry = FileEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileOpenEnd:
|
Quickie:
|
||||||
if (ParentDirectoryEntry)
|
/* Close the parent */
|
||||||
|
if (DirectoryEntry)
|
||||||
{
|
{
|
||||||
BlFileClose(ParentDirectoryEntry->FileId);
|
BlFileClose(DirectoryEntry->FileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free the parent name copy */
|
||||||
if (ParentFileName)
|
if (ParentFileName)
|
||||||
{
|
{
|
||||||
BlMmFreeHeap(ParentFileName);
|
BlMmFreeHeap(ParentFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free the file name copy */
|
||||||
if (FileNameCopy)
|
if (FileNameCopy)
|
||||||
{
|
{
|
||||||
BlMmFreeHeap(FileNameCopy);
|
BlMmFreeHeap(FileNameCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return back to caller */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,15 +488,17 @@ BlFileOpen (
|
||||||
PBL_FILE_ENTRY FileEntry;
|
PBL_FILE_ENTRY FileEntry;
|
||||||
BL_DEVICE_INFORMATION DeviceInformation;
|
BL_DEVICE_INFORMATION DeviceInformation;
|
||||||
|
|
||||||
|
/* Make sure we have a valid file name, access flags and parameters */
|
||||||
if (!(FileName) ||
|
if (!(FileName) ||
|
||||||
(*FileName != OBJ_NAME_PATH_SEPARATOR) ||
|
(*FileName != OBJ_NAME_PATH_SEPARATOR) ||
|
||||||
!(FileId) ||
|
!(FileId) ||
|
||||||
!(Flags & 3))
|
!(Flags & (BL_FILE_READ_ACCESS | BL_FILE_WRITE_ACCESS)))
|
||||||
{
|
{
|
||||||
EfiPrintf(L"Invalid file options\r\n");
|
EfiPrintf(L"Invalid file options\r\n");
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get information on the underlying device */
|
||||||
Status = BlDeviceGetInformation(DeviceId, &DeviceInformation);
|
Status = BlDeviceGetInformation(DeviceId, &DeviceInformation);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -459,6 +506,7 @@ BlFileOpen (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure it's a device that can host files */
|
||||||
if ((DeviceInformation.DeviceType != DiskDevice) &&
|
if ((DeviceInformation.DeviceType != DiskDevice) &&
|
||||||
(DeviceInformation.DeviceType != LegacyPartitionDevice) &&
|
(DeviceInformation.DeviceType != LegacyPartitionDevice) &&
|
||||||
(DeviceInformation.DeviceType != UdpDevice))
|
(DeviceInformation.DeviceType != UdpDevice))
|
||||||
|
@ -467,6 +515,7 @@ BlFileOpen (
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open a file on this device, creating one if needed */
|
||||||
Status = FileIoOpen(DeviceId,
|
Status = FileIoOpen(DeviceId,
|
||||||
FileName,
|
FileName,
|
||||||
Flags,
|
Flags,
|
||||||
|
@ -475,10 +524,339 @@ BlFileOpen (
|
||||||
&FileEntry);
|
&FileEntry);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
/* Return the file ID back to the caller */
|
||||||
EfiPrintf(L"File opened: %lx\r\n", FileEntry->FileId);
|
EfiPrintf(L"File opened: %lx\r\n", FileEntry->FileId);
|
||||||
*FileId = FileEntry->FileId;
|
*FileId = FileEntry->FileId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* All good */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlFileSetInformation (
|
||||||
|
_In_ ULONG FileId,
|
||||||
|
_Out_ PBL_FILE_INFORMATION FileInfo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PBL_FILE_ENTRY FileEntry;
|
||||||
|
|
||||||
|
/* Make sure caller passed this in */
|
||||||
|
if (!FileInfo)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate file ID */
|
||||||
|
if (FileEntries > FileId)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure an opened file exits with this ID */
|
||||||
|
FileEntry = FileTable[FileId];
|
||||||
|
if (!(FileEntry) || !(FileEntry->Flags & BL_FILE_ENTRY_OPENED))
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the I/O operation */
|
||||||
|
return FileEntry->Callbacks.SetInfo(FileEntry, FileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlFileGetInformation (
|
||||||
|
_In_ ULONG FileId,
|
||||||
|
_In_ PBL_FILE_INFORMATION FileInfo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PBL_FILE_ENTRY FileEntry;
|
||||||
|
|
||||||
|
/* Make sure caller passed this in */
|
||||||
|
if (!FileInfo)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate file ID */
|
||||||
|
if (FileEntries > FileId)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure an opened file exits with this ID */
|
||||||
|
FileEntry = FileTable[FileId];
|
||||||
|
if (!(FileEntry) || !(FileEntry->Flags & BL_FILE_ENTRY_OPENED))
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the I/O operation */
|
||||||
|
return FileEntry->Callbacks.GetInfo(FileEntry, FileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
FileInformationCheck (
|
||||||
|
_In_ PBL_FILE_INFORMATION FileInformation,
|
||||||
|
_In_ BOOLEAN Write,
|
||||||
|
_In_opt_ PULONG InputSize,
|
||||||
|
_In_opt_ PULONG BytesReturned,
|
||||||
|
_Out_opt_ PULONG RequiredSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG Size;
|
||||||
|
|
||||||
|
/* Initialize variables */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
Size = 0;
|
||||||
|
|
||||||
|
/* Make sure we didn't overshoot */
|
||||||
|
if (FileInformation->CurrentOffset > FileInformation->FileSize)
|
||||||
|
{
|
||||||
|
/* Bail out */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the appropriate 32-bit size of this read, based on file size */
|
||||||
|
Size = ULONG_MAX;
|
||||||
|
if ((FileInformation->FileSize - FileInformation->CurrentOffset) <= ULONG_MAX)
|
||||||
|
{
|
||||||
|
Size = (ULONG)(FileInformation->FileSize) - (ULONG)(FileInformation->CurrentOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the caller has an input buffer */
|
||||||
|
if (InputSize)
|
||||||
|
{
|
||||||
|
/* Is the size bigger than what the caller can handle? */
|
||||||
|
if (Size >= *InputSize)
|
||||||
|
{
|
||||||
|
/* Yes, so cap it at the size of the caller's buffer */
|
||||||
|
Size = *InputSize;
|
||||||
|
}
|
||||||
|
else if (!(BytesReturned) || (Write))
|
||||||
|
{
|
||||||
|
/* Caller's input buffer is too smaller is fatal for writes */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* Does the caller want to know how big to make their buffer? */
|
||||||
|
if (RequiredSize)
|
||||||
|
{
|
||||||
|
/* Let them know*/
|
||||||
|
*RequiredSize = Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return final status */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlFileReadEx (
|
||||||
|
_In_ ULONG FileId,
|
||||||
|
_Out_ PVOID Buffer,
|
||||||
|
_In_ ULONG Size,
|
||||||
|
_Out_ PULONG BytesReturned,
|
||||||
|
_In_ ULONG Flags
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PBL_FILE_ENTRY FileEntry;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG OldUnknown, RequiredSize;
|
||||||
|
BOOLEAN ChangedUnknown;
|
||||||
|
BL_DEVICE_INFORMATION DeviceInfo;
|
||||||
|
BL_FILE_INFORMATION fileInfo;
|
||||||
|
|
||||||
|
/* Initialize variables */
|
||||||
|
RtlZeroMemory(&DeviceInfo, sizeof(DeviceInfo));
|
||||||
|
OldUnknown = 0;
|
||||||
|
ChangedUnknown = FALSE;
|
||||||
|
|
||||||
|
/* Bail out if there's no buffer */
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bail out of the file ID is invalid */
|
||||||
|
if (FileEntries > FileId)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bail out if there's no file opened for read access */
|
||||||
|
FileEntry = FileTable[FileId];
|
||||||
|
if (!(FileEntry) ||
|
||||||
|
!(FileEntry->Flags & (BL_FILE_ENTRY_OPENED | BL_FILE_ENTRY_READ_ACCESS)))
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bail out if we can't read the file's information */
|
||||||
|
Status = BlFileGetInformation(FileId, &fileInfo);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the read attempt is valid, and fix up the size if needed */
|
||||||
|
RequiredSize = Size;
|
||||||
|
Status = FileInformationCheck(&fileInfo,
|
||||||
|
FALSE,
|
||||||
|
&RequiredSize,
|
||||||
|
BytesReturned,
|
||||||
|
&RequiredSize);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Invalid or illegal read attempt */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is there anything left to read after all? */
|
||||||
|
if (RequiredSize)
|
||||||
|
{
|
||||||
|
/* Check if flags 2 or 4 are set */
|
||||||
|
if ((Flags & 2) || (Flags & 4))
|
||||||
|
{
|
||||||
|
/* Check if this is a disk or partition device */
|
||||||
|
BlDeviceGetInformation(FileEntry->DeviceId, &DeviceInfo);
|
||||||
|
if ((DeviceInfo.DeviceType == DiskDevice) ||
|
||||||
|
(DeviceInfo.DeviceType == LegacyPartitionDevice))
|
||||||
|
{
|
||||||
|
/* Check if request flags are incompatible with device flags */
|
||||||
|
if ((!(DeviceInfo.BlockDeviceInfo.Unknown & 1) && (Flags & 2)) ||
|
||||||
|
(!(DeviceInfo.BlockDeviceInfo.Unknown & 2) && (Flags & 4)))
|
||||||
|
{
|
||||||
|
/* We're going to change the device flags */
|
||||||
|
ChangedUnknown = TRUE;
|
||||||
|
|
||||||
|
/* Set unknown flag 1 for request flag 2 */
|
||||||
|
if (Flags & 2)
|
||||||
|
{
|
||||||
|
DeviceInfo.BlockDeviceInfo.Unknown |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set unknown flag 2 for request flag 4 */
|
||||||
|
if (Flags & 4)
|
||||||
|
{
|
||||||
|
DeviceInfo.BlockDeviceInfo.Unknown |= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save the new device flags */
|
||||||
|
BlDeviceSetInformation(FileEntry->DeviceId, &DeviceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Issue the read to the underlying file system */
|
||||||
|
Status = FileEntry->Callbacks.Read(FileEntry,
|
||||||
|
Buffer,
|
||||||
|
RequiredSize,
|
||||||
|
BytesReturned);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Don't update the bytes read on failure */
|
||||||
|
RequiredSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* There's nothing to do, return success and 0 bytes */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
if (BytesReturned)
|
||||||
|
{
|
||||||
|
*BytesReturned = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increment the number of bytes read */
|
||||||
|
FileEntry->Unknown1 += RequiredSize;
|
||||||
|
|
||||||
|
/* Check if the unknown flag on the device was changed during this routine */
|
||||||
|
if (ChangedUnknown)
|
||||||
|
{
|
||||||
|
/* Reset it back to its original value */
|
||||||
|
DeviceInfo.BlockDeviceInfo.Unknown = OldUnknown;
|
||||||
|
BlDeviceSetInformation(FileEntry->DeviceId, &DeviceInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the final status */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlFileReadAtOffsetEx (
|
||||||
|
_In_ ULONG FileId,
|
||||||
|
_In_ ULONG Size,
|
||||||
|
_In_ ULONGLONG ByteOffset,
|
||||||
|
_In_ PVOID Buffer,
|
||||||
|
_Out_ PULONG BytesReturned,
|
||||||
|
_In_ ULONG Flags
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
BL_FILE_INFORMATION FileInfo;
|
||||||
|
ULONG RequiredSize;
|
||||||
|
ULONGLONG FileOffset;
|
||||||
|
|
||||||
|
/* Get information on the specified file */
|
||||||
|
Status = BlFileGetInformation(FileId, &FileInfo);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save the current offset, and overwrite it with the one we want */
|
||||||
|
FileOffset = FileInfo.CurrentOffset;
|
||||||
|
FileInfo.CurrentOffset = ByteOffset;
|
||||||
|
|
||||||
|
/* Check the validity of the read and the actual size to read */
|
||||||
|
RequiredSize = Size;
|
||||||
|
Status = FileInformationCheck(&FileInfo,
|
||||||
|
FALSE,
|
||||||
|
&RequiredSize,
|
||||||
|
BytesReturned,
|
||||||
|
&RequiredSize);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Bail out if the read is invalid */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the offset we're requesting is not the current offset */
|
||||||
|
if (FileInfo.CurrentOffset != FileOffset)
|
||||||
|
{
|
||||||
|
/* Set the new offset to use */
|
||||||
|
Status = BlFileSetInformation(FileId, &FileInfo);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Can't do much if that failed */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the read at the required offset now */
|
||||||
|
Status = BlFileReadEx(FileId,
|
||||||
|
Buffer,
|
||||||
|
RequiredSize,
|
||||||
|
BytesReturned,
|
||||||
|
Flags);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* The read failed -- had we modified the offset? */
|
||||||
|
if (FileInfo.CurrentOffset != FileOffset)
|
||||||
|
{
|
||||||
|
/* Restore the offset back to its original value */
|
||||||
|
FileInfo.CurrentOffset = FileOffset;
|
||||||
|
BlFileSetInformation(FileId, &FileInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the status of the read */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,86 @@ MiscGetBootOption (
|
||||||
return Option;
|
return Option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*++
|
||||||
|
* @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 != 0);
|
||||||
|
|
||||||
|
/* 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 != 0)
|
||||||
|
{
|
||||||
|
/* 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 != 0)
|
||||||
|
{
|
||||||
|
/* Go get those too */
|
||||||
|
Size += BlGetBootOptionListSize((PVOID)((ULONG_PTR)BcdOption + Offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the final size */
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
BlGetBootOptionString (
|
BlGetBootOptionString (
|
||||||
_In_ PBL_BCD_OPTION List,
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
@ -161,6 +241,151 @@ BlGetBootOptionString (
|
||||||
return Status;
|
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;
|
||||||
|
|
||||||
|
/* Make sure this is a BCD_DEVICE */
|
||||||
|
if ((Type & 0xF000000) != 0x1000000)
|
||||||
|
{
|
||||||
|
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 */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
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
|
NTSTATUS
|
||||||
BlGetBootOptionInteger (
|
BlGetBootOptionInteger (
|
||||||
_In_ PBL_BCD_OPTION List,
|
_In_ PBL_BCD_OPTION List,
|
||||||
|
@ -231,80 +456,342 @@ BlGetBootOptionBoolean (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*++
|
#define BI_FLUSH_HIVE 0x01
|
||||||
* @name BlGetBootOptionListSize
|
|
||||||
*
|
typedef struct _BI_KEY_HIVE
|
||||||
* The BlGetBootOptionListSize routine
|
{
|
||||||
*
|
PVOID ImageBase;
|
||||||
* @param BcdOption
|
PBL_FILE_PATH_DESCRIPTOR FilePath;
|
||||||
* UEFI Image Handle for the current loaded application.
|
CMHIVE Hive;
|
||||||
*
|
LONG ReferenceCount;
|
||||||
* @return Size of the BCD option
|
ULONG Flags;
|
||||||
*
|
} BI_KEY_HIVE, *PBI_KEY_HIVE;
|
||||||
*--*/
|
|
||||||
ULONG
|
typedef struct _BI_KEY_OBJECT
|
||||||
BlGetBootOptionListSize (
|
{
|
||||||
_In_ PBL_BCD_OPTION BcdOption
|
PBI_KEY_HIVE KeyHive;
|
||||||
|
PCM_KEY_NODE KeyNode;
|
||||||
|
HCELL_INDEX KeyCell;
|
||||||
|
PWCHAR KeyName;
|
||||||
|
} BI_KEY_OBJECT, *PBI_KEY_OBJECT;
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
NTAPI
|
||||||
|
CmpAllocate (
|
||||||
|
_In_ SIZE_T Size,
|
||||||
|
_In_ BOOLEAN Paged,
|
||||||
|
_In_ ULONG Tag
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ULONG Size = 0, NextOffset = 0;
|
UNREFERENCED_PARAMETER(Paged);
|
||||||
PBL_BCD_OPTION NextOption;
|
UNREFERENCED_PARAMETER(Tag);
|
||||||
|
|
||||||
/* Loop all the options*/
|
/* Call the heap allocator */
|
||||||
do
|
return BlMmAllocateHeap(Size);
|
||||||
{
|
|
||||||
/* 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 != 0);
|
|
||||||
|
|
||||||
/* Return final computed size */
|
|
||||||
return Size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*++
|
VOID
|
||||||
* @name BlGetBootOptionSize
|
NTAPI
|
||||||
*
|
CmpFree (
|
||||||
* The BlGetBootOptionSize routine
|
_In_ PVOID Ptr,
|
||||||
*
|
_In_ ULONG Quota
|
||||||
* @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;
|
UNREFERENCED_PARAMETER(Quota);
|
||||||
|
|
||||||
/* Check if there's any data */
|
/* Call the heap allocator */
|
||||||
if (BcdOption->DataOffset != 0)
|
BlMmFreeHeap(Ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
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))
|
||||||
{
|
{
|
||||||
/* Add the size of the data */
|
/* Drop a reference, see if it's the last one */
|
||||||
Size = BcdOption->DataOffset + BcdOption->DataSize;
|
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)Hive->GetCellRoutine(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
|
||||||
|
BiLoadHive (
|
||||||
|
_In_ PBL_FILE_PATH_DESCRIPTOR FilePath,
|
||||||
|
_Out_ PHANDLE HiveHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* This is TODO */
|
||||||
|
EfiPrintf(L"Loading a hive is not yet implemented\r\n");
|
||||||
|
*HiveHandle = NULL;
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BiAddStoreFromFile (
|
||||||
|
_In_ PBL_FILE_PATH_DESCRIPTOR FilePath,
|
||||||
|
_Out_ PHANDLE StoreHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE HiveHandle, KeyHandle;
|
||||||
|
|
||||||
|
/* Load the specified hive */
|
||||||
|
Status = BiLoadHive(FilePath, &HiveHandle);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the description key to make sure this is really a BCD */
|
||||||
|
Status = BiOpenKey(HiveHandle, L"Description", &KeyHandle);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* It is -- close the key as we don't need it */
|
||||||
|
BiCloseKey(KeyHandle);
|
||||||
|
*StoreHandle = HiveHandle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No data, just the structure itself */
|
/* Failure, drop a reference on the hive and close the key */
|
||||||
Size = sizeof(*BcdOption);
|
BiDereferenceHive(HiveHandle);
|
||||||
|
BiCloseKey(HiveHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Any associated options? */
|
/* Return the status */
|
||||||
Offset = BcdOption->ListOffset;
|
return Status;
|
||||||
if (Offset != 0)
|
|
||||||
{
|
|
||||||
/* Go get those too */
|
|
||||||
Size += BlGetBootOptionListSize((PVOID)((ULONG_PTR)BcdOption + Offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the final size */
|
|
||||||
return Size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BcdOpenStoreFromFile (
|
||||||
|
_In_ PUNICODE_STRING FileName,
|
||||||
|
_In_ PHANDLE StoreHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG Length;
|
||||||
|
PBL_FILE_PATH_DESCRIPTOR FilePath;
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE LocalHandle;
|
||||||
|
|
||||||
|
/* Assume failure */
|
||||||
|
LocalHandle = NULL;
|
||||||
|
|
||||||
|
/* Allocate a path descriptor */
|
||||||
|
Length = FileName->Length + sizeof(*FilePath);
|
||||||
|
FilePath = BlMmAllocateHeap(Length);
|
||||||
|
if (!FilePath)
|
||||||
|
{
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize it */
|
||||||
|
FilePath->Version = 1;
|
||||||
|
FilePath->PathType = InternalPath;
|
||||||
|
FilePath->Length = Length;
|
||||||
|
|
||||||
|
/* Copy the name and NULL-terminate it */
|
||||||
|
RtlCopyMemory(FilePath->Path, FileName->Buffer, Length);
|
||||||
|
FilePath->Path[Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
|
|
||||||
|
/* Open the BCD */
|
||||||
|
Status = BiAddStoreFromFile(FilePath, &LocalHandle);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Return the handle on success */
|
||||||
|
*StoreHandle = LocalHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the descriptor and return the status */
|
||||||
|
BlMmFreeHeap(FilePath);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
137
reactos/boot/environ/lib/misc/debug.c
Normal file
137
reactos/boot/environ/lib/misc/debug.c
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING.ARM in the top level directory
|
||||||
|
* PROJECT: ReactOS UEFI Boot Library
|
||||||
|
* FILE: boot/environ/lib/misc/debug.c
|
||||||
|
* PURPOSE: Boot Library Debug Routines
|
||||||
|
* PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include "bl.h"
|
||||||
|
|
||||||
|
/* DATA VARIABLES ************************************************************/
|
||||||
|
|
||||||
|
CHAR AnsiBuffer[1024];
|
||||||
|
BOOLEAN BdDebuggerNotPresent;
|
||||||
|
BOOLEAN BdSubsystemInitialized;
|
||||||
|
BOOLEAN BdArchBlockDebuggerOperation;
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
BdDebuggerInitialized (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Check if BD was initialized, and is currently usable */
|
||||||
|
return BdSubsystemInitialized && !BdArchBlockDebuggerOperation;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlBdPullRemoteFile (
|
||||||
|
_In_ PWCHAR FilePath,
|
||||||
|
_Out_ PVOID BaseAddress,
|
||||||
|
_Out_ PULONGLONG FileSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Is the boot debugger enabled? */
|
||||||
|
if (!BlBdDebuggerEnabled())
|
||||||
|
{
|
||||||
|
/* Nothing to pull */
|
||||||
|
return STATUS_DEBUGGER_INACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
EfiPrintf(L"Todo\r\n");
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
BlBdDebuggerEnabled (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
BOOLEAN Initialized, Enabled;
|
||||||
|
|
||||||
|
/* Check if the debugger is initialized */
|
||||||
|
Initialized = BdDebuggerInitialized();
|
||||||
|
|
||||||
|
/* Check if it's currently active */
|
||||||
|
Enabled = FALSE;
|
||||||
|
if ((Initialized) && !(BdDebuggerNotPresent))
|
||||||
|
{
|
||||||
|
/* Yep! */
|
||||||
|
Enabled = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return enabled state */
|
||||||
|
return Enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BlStatusPrint (
|
||||||
|
_In_ PCWCH Format,
|
||||||
|
...
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ANSI_STRING AnsiString;
|
||||||
|
UNICODE_STRING UnicodeString;
|
||||||
|
va_list va;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
va_start(va, Format);
|
||||||
|
|
||||||
|
/* Check if the boot debugger is enabled */
|
||||||
|
if (BlBdDebuggerEnabled())
|
||||||
|
{
|
||||||
|
/* Print the string out into a buffer */
|
||||||
|
if (vswprintf(BlScratchBuffer, Format, va) > 0)
|
||||||
|
{
|
||||||
|
/* Make it a UNICODE_STRING */
|
||||||
|
RtlInitUnicodeString(&UnicodeString, BlScratchBuffer);
|
||||||
|
|
||||||
|
/* Then convert it into an ANSI_STRING */
|
||||||
|
AnsiString.Length = 0;
|
||||||
|
AnsiString.MaximumLength = sizeof(AnsiBuffer);
|
||||||
|
AnsiString.Buffer = AnsiBuffer;
|
||||||
|
Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Print it out to the debugger if that worked */
|
||||||
|
DbgPrint(AnsiString.Buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BlStatusError (
|
||||||
|
_In_ ULONG ErrorCode,
|
||||||
|
_In_ ULONG Parameter1,
|
||||||
|
_In_ ULONG_PTR Parameter2,
|
||||||
|
_In_ ULONG_PTR Parameter3,
|
||||||
|
_In_ ULONG_PTR Parameter4
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Check if the boot debugger is enabled */
|
||||||
|
if (BlBdDebuggerEnabled())
|
||||||
|
{
|
||||||
|
/* Print out the fatal error */
|
||||||
|
BlStatusPrint(L"\n"
|
||||||
|
L"*** Fatal Error 0x%08x :\n"
|
||||||
|
L" (0x%p, 0x%p, 0x%p, 0x%p)\n"
|
||||||
|
L"\n",
|
||||||
|
ErrorCode,
|
||||||
|
Parameter1,
|
||||||
|
Parameter2,
|
||||||
|
Parameter3,
|
||||||
|
Parameter4);
|
||||||
|
|
||||||
|
/* Issue a breakpoint */
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
551
reactos/boot/environ/lib/misc/image.c
Normal file
551
reactos/boot/environ/lib/misc/image.c
Normal file
|
@ -0,0 +1,551 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING.ARM in the top level directory
|
||||||
|
* PROJECT: ReactOS UEFI Boot Library
|
||||||
|
* FILE: boot/environ/lib/misc/image.c
|
||||||
|
* PURPOSE: Boot Library Image Routines
|
||||||
|
* PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include "bl.h"
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ImgpGetFileSize (
|
||||||
|
_In_ PBL_IMG_FILE File,
|
||||||
|
_Out_ PULONG FileSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG Size;
|
||||||
|
BL_FILE_INFORMATION FileInformation;
|
||||||
|
|
||||||
|
/* Check if the file was memory mapped */
|
||||||
|
if (File->Flags & BL_IMG_MEMORY_FILE)
|
||||||
|
{
|
||||||
|
/* Just read the size of the mapping */
|
||||||
|
Size = File->FileSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Do file I/O to get the file size */
|
||||||
|
Status = BlFileGetInformation(File->FileId,
|
||||||
|
&FileInformation);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We only support files less than 4GB in the Image Mapped */
|
||||||
|
Size = FileInformation.FileSize;
|
||||||
|
if (FileInformation.FileSize > ULONG_MAX)
|
||||||
|
{
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the size and success */
|
||||||
|
*FileSize = Size;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ImgpReadAtFileOffset (
|
||||||
|
_In_ PBL_IMG_FILE File,
|
||||||
|
_In_ ULONG Size,
|
||||||
|
_In_ ULONGLONG ByteOffset,
|
||||||
|
_In_ PVOID Buffer,
|
||||||
|
_Out_ PULONG BytesReturned
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Check what if this is a mapped file or not */
|
||||||
|
if (File->Flags & BL_IMG_MEMORY_FILE)
|
||||||
|
{
|
||||||
|
/* Check if the boundaries are within the file size */
|
||||||
|
if ((ByteOffset + Size) <= File->FileSize)
|
||||||
|
{
|
||||||
|
/* Yep, copy into the caller-supplied buffer */
|
||||||
|
RtlCopyMemory(Buffer,
|
||||||
|
(PVOID)((ULONG_PTR)File->BaseAddress + (ULONG_PTR)ByteOffset),
|
||||||
|
Size);
|
||||||
|
|
||||||
|
/* If caller wanted to know, return the size copied */
|
||||||
|
if (BytesReturned)
|
||||||
|
{
|
||||||
|
*BytesReturned = Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All good */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Doesn't fit */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Issue the file I/O instead */
|
||||||
|
Status = BlFileReadAtOffsetEx(File->FileId,
|
||||||
|
Size,
|
||||||
|
ByteOffset,
|
||||||
|
Buffer,
|
||||||
|
BytesReturned,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the final status */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ImgpOpenFile (
|
||||||
|
_In_ ULONG DeviceId,
|
||||||
|
_In_ PWCHAR FileName,
|
||||||
|
_In_ ULONG Flags,
|
||||||
|
_Out_ PBL_IMG_FILE NewFile
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG FileSize;
|
||||||
|
ULONGLONG RemoteFileSize;
|
||||||
|
PVOID RemoteFileAddress;
|
||||||
|
ULONG FileId;
|
||||||
|
|
||||||
|
/* First, try to see if BD has this file remotely */
|
||||||
|
Status = BlBdPullRemoteFile(FileName,
|
||||||
|
&RemoteFileAddress,
|
||||||
|
&RemoteFileSize);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Yep, get the file size and make sure it's < 4GB */
|
||||||
|
FileSize = RemoteFileSize;
|
||||||
|
if (RemoteFileSize <= ULONG_MAX)
|
||||||
|
{
|
||||||
|
/* Remember this is a memory mapped remote file */
|
||||||
|
NewFile->Flags |= (BL_IMG_MEMORY_FILE | BL_IMG_REMOTE_FILE);
|
||||||
|
NewFile->FileSize = FileSize;
|
||||||
|
NewFile->BaseAddress = RemoteFileAddress;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use File I/O instead */
|
||||||
|
Status = BlFileOpen(DeviceId,
|
||||||
|
FileName,
|
||||||
|
BL_FILE_READ_ACCESS,
|
||||||
|
&FileId);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Bail out on failure */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure nobody thinks this is a memory file */
|
||||||
|
NewFile->Flags &= ~BL_IMG_MEMORY_FILE;
|
||||||
|
NewFile->FileId = FileId;
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* Set common data for both memory and I/O based file */
|
||||||
|
NewFile->Flags |= BL_IMG_VALID_FILE;
|
||||||
|
NewFile->FileName = FileName;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ImgpCloseFile (
|
||||||
|
_In_ PBL_IMG_FILE File
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Make sure this is a valid file, otherwise no-op */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
if (File->Flags & BL_IMG_VALID_FILE)
|
||||||
|
{
|
||||||
|
/* Is this a memory mapped file? */
|
||||||
|
if (!(File->Flags & BL_IMG_MEMORY_FILE))
|
||||||
|
{
|
||||||
|
/* Nope, close the file handle */
|
||||||
|
return BlFileClose(File->FileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is this a remote file? */
|
||||||
|
if (File->Flags & BL_IMG_REMOTE_FILE)
|
||||||
|
{
|
||||||
|
/* Then only free the memory in that scenario */
|
||||||
|
EfiPrintf(L"TODO\r\n");
|
||||||
|
//return MmPapFreePages(File->BaseAddress, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the final status */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlImgAllocateImageBuffer (
|
||||||
|
_Inout_ PVOID* ImageBuffer,
|
||||||
|
_In_ ULONG MemoryType,
|
||||||
|
_In_ ULONGLONG ImageSize,
|
||||||
|
_In_ ULONG Flags
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG Attributes;
|
||||||
|
ULONGLONG Pages, Size;
|
||||||
|
PVOID MappedBase, CurrentBuffer;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PHYSICAL_ADDRESS PhysicalAddress;
|
||||||
|
|
||||||
|
/* Read and reset the current buffer address */
|
||||||
|
CurrentBuffer = *ImageBuffer;
|
||||||
|
*ImageBuffer = NULL;
|
||||||
|
|
||||||
|
/* Align the image size to page */
|
||||||
|
Size = ROUND_TO_PAGES(ImageSize);
|
||||||
|
|
||||||
|
/* Not sure what this attribute does yet */
|
||||||
|
Attributes = 0;
|
||||||
|
if (Flags & BL_LOAD_IMG_UNKNOWN_BUFFER_FLAG)
|
||||||
|
{
|
||||||
|
Attributes = 0x10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the caller wants a virtual buffer */
|
||||||
|
if (Flags & BL_LOAD_IMG_VIRTUAL_BUFFER)
|
||||||
|
{
|
||||||
|
/* Set the physical address to the current buffer */
|
||||||
|
PhysicalAddress.QuadPart = (ULONG_PTR)CurrentBuffer;
|
||||||
|
Pages = Size >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
/* Allocate the physical pages */
|
||||||
|
Status = BlMmAllocatePhysicalPages(&PhysicalAddress,
|
||||||
|
Pages,
|
||||||
|
MemoryType,
|
||||||
|
Attributes,
|
||||||
|
0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* If that failed, remove allocation attributes */
|
||||||
|
PhysicalAddress.QuadPart = 0;
|
||||||
|
Attributes &= ~BlMemoryValidAllocationAttributeMask,
|
||||||
|
Status = BlMmAllocatePhysicalPages(&PhysicalAddress,
|
||||||
|
Pages,
|
||||||
|
MemoryType,
|
||||||
|
Attributes,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if either attempts succeeded */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now map the physical buffer at the address requested */
|
||||||
|
MappedBase = (PVOID)PhysicalAddress.LowPart;
|
||||||
|
Status = BlMmMapPhysicalAddressEx(&MappedBase,
|
||||||
|
BlMemoryFixed,
|
||||||
|
Size,
|
||||||
|
PhysicalAddress);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Free on failure if needed */
|
||||||
|
BlMmFreePhysicalPages(PhysicalAddress);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise, allocate raw physical pages */
|
||||||
|
MappedBase = CurrentBuffer;
|
||||||
|
Pages = Size >> PAGE_SHIFT;
|
||||||
|
Status = MmPapAllocatePagesInRange(&MappedBase,
|
||||||
|
MemoryType,
|
||||||
|
Pages,
|
||||||
|
Attributes,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* If that failed, try without allocation attributes */
|
||||||
|
MappedBase = NULL;
|
||||||
|
Attributes &= ~BlMemoryValidAllocationAttributeMask,
|
||||||
|
Status = MmPapAllocatePagesInRange(&MappedBase,
|
||||||
|
MemoryType,
|
||||||
|
Pages,
|
||||||
|
Attributes,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if either attempts succeeded */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success path, returned allocated address */
|
||||||
|
*ImageBuffer = MappedBase;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlImgLoadImageWithProgress2 (
|
||||||
|
_In_ ULONG DeviceId,
|
||||||
|
_In_ BL_MEMORY_TYPE MemoryType,
|
||||||
|
_In_ PWCHAR FileName,
|
||||||
|
_Inout_ PVOID* MappedBase,
|
||||||
|
_Inout_ PULONG MappedSize,
|
||||||
|
_In_ ULONG ImageFlags,
|
||||||
|
_In_ BOOLEAN ShowProgress,
|
||||||
|
_Out_opt_ PUCHAR* HashBuffer,
|
||||||
|
_Out_opt_ PULONG HashSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PVOID BaseAddress, Buffer;
|
||||||
|
ULONG RemainingLength, CurrentSize, ImageSize, ReadSize;
|
||||||
|
BOOLEAN ComputeSignature, ComputeHash, Completed;
|
||||||
|
BL_IMG_FILE FileHandle;
|
||||||
|
ULONGLONG ByteOffset;
|
||||||
|
PHYSICAL_ADDRESS PhysicalAddress;
|
||||||
|
|
||||||
|
/* Initialize variables */
|
||||||
|
BaseAddress = 0;
|
||||||
|
ImageSize = 0;
|
||||||
|
Completed = FALSE;
|
||||||
|
RtlZeroMemory(&FileHandle, sizeof(FileHandle));
|
||||||
|
|
||||||
|
/* Check for missing parameters */
|
||||||
|
if (!MappedBase)
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
if (!FileName)
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
if (!MappedSize)
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the image buffer is being provided */
|
||||||
|
if (ImageFlags & BL_LOAD_IMG_EXISTING_BUFFER)
|
||||||
|
{
|
||||||
|
/* An existing base must already exist */
|
||||||
|
if (!(*MappedBase))
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check of a hash is being requested */
|
||||||
|
if (ImageFlags & BL_LOAD_IMG_COMPUTE_HASH)
|
||||||
|
{
|
||||||
|
/* Make sure we can return the hash */
|
||||||
|
if (!HashBuffer)
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
if (!HashSize)
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for invalid combination of parameters */
|
||||||
|
if ((ImageFlags & BL_LOAD_IMG_COMPUTE_HASH) && (ImageFlags & 0x270))
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize hash if requested by caller */
|
||||||
|
if (HashBuffer)
|
||||||
|
{
|
||||||
|
*HashBuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the same for the hash size */
|
||||||
|
if (HashSize)
|
||||||
|
{
|
||||||
|
*HashSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the image file */
|
||||||
|
Status = ImgpOpenFile(DeviceId, FileName, DeviceId, &FileHandle);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the size of the image */
|
||||||
|
Status = ImgpGetFileSize(&FileHandle, &ImageSize);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the current base address */
|
||||||
|
BaseAddress = *MappedBase;
|
||||||
|
if (ImageFlags & BL_LOAD_IMG_EXISTING_BUFFER)
|
||||||
|
{
|
||||||
|
/* Check if the current buffer is too small */
|
||||||
|
if (*MappedSize < ImageSize)
|
||||||
|
{
|
||||||
|
/* Return the required size of the buffer */
|
||||||
|
*MappedSize = ImageSize;
|
||||||
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* A buffer was not provided, allocate one ourselves */
|
||||||
|
Status = BlImgAllocateImageBuffer(&BaseAddress,
|
||||||
|
MemoryType,
|
||||||
|
ImageSize,
|
||||||
|
ImageFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bail out if allocation failed */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the initial byte offset and length to read */
|
||||||
|
RemainingLength = ImageSize;
|
||||||
|
ByteOffset = 0;
|
||||||
|
Buffer = BaseAddress;
|
||||||
|
|
||||||
|
/* Update the initial progress */
|
||||||
|
Completed = FALSE;
|
||||||
|
if (ShowProgress)
|
||||||
|
{
|
||||||
|
BlUtlUpdateProgress(0, &Completed);
|
||||||
|
ShowProgress &= (Completed != 0) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the chunk size for each read */
|
||||||
|
ReadSize = 0x100000;
|
||||||
|
if (ReadSize > ImageSize)
|
||||||
|
{
|
||||||
|
ReadSize = ImageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we should compute hash and/or signatures */
|
||||||
|
ComputeSignature = ImageFlags & BL_LOAD_IMG_COMPUTE_SIGNATURE;
|
||||||
|
if ((ComputeSignature) || (ImageFlags & BL_LOAD_IMG_COMPUTE_HASH))
|
||||||
|
{
|
||||||
|
ComputeHash = TRUE;
|
||||||
|
// todo: crypto is hard
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Begin the read loop */
|
||||||
|
while (RemainingLength)
|
||||||
|
{
|
||||||
|
/* Check if we've got more than a chunk left to read */
|
||||||
|
if (RemainingLength > ReadSize)
|
||||||
|
{
|
||||||
|
/* Read a chunk*/
|
||||||
|
CurrentSize = ReadSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Read only what's left */
|
||||||
|
CurrentSize = RemainingLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the chunk */
|
||||||
|
Status = ImgpReadAtFileOffset(&FileHandle,
|
||||||
|
CurrentSize,
|
||||||
|
ByteOffset,
|
||||||
|
Buffer,
|
||||||
|
0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we need to compute the hash of this chunk */
|
||||||
|
if (ComputeHash)
|
||||||
|
{
|
||||||
|
// todo: crypto is hard
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update our position and read information */
|
||||||
|
Buffer = (PVOID)((ULONG_PTR)Buffer + CurrentSize);
|
||||||
|
RemainingLength -= CurrentSize;
|
||||||
|
ByteOffset += CurrentSize;
|
||||||
|
|
||||||
|
/* Check if we should update the progress bar */
|
||||||
|
if (ShowProgress)
|
||||||
|
{
|
||||||
|
/* Compute new percentage completed, check if we're done */
|
||||||
|
BlUtlUpdateProgress(100 - 100 * RemainingLength / ImageSize,
|
||||||
|
&Completed);
|
||||||
|
ShowProgress &= (Completed != 0) - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is the read fully complete? We need to finalize the hash if requested */
|
||||||
|
if (ComputeHash != RemainingLength)
|
||||||
|
{
|
||||||
|
// todo: CRYPTO IS HARD
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success path, return back the buffer and the size of the image */
|
||||||
|
*MappedBase = BaseAddress;
|
||||||
|
*MappedSize = ImageSize;
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* Close the file handle */
|
||||||
|
ImgpCloseFile(&FileHandle);
|
||||||
|
|
||||||
|
/* Check if we failed and had allocated a buffer */
|
||||||
|
if (!(NT_SUCCESS(Status)) &&
|
||||||
|
(BaseAddress) &&
|
||||||
|
!(ImageFlags & BL_LOAD_IMG_EXISTING_BUFFER))
|
||||||
|
{
|
||||||
|
/* Check what kind of buffer we had allocated */
|
||||||
|
if (ImageFlags & BL_LOAD_IMG_VIRTUAL_BUFFER)
|
||||||
|
{
|
||||||
|
/* Unmap and free the virtual buffer */
|
||||||
|
PhysicalAddress.QuadPart = (ULONG_PTR)BaseAddress;
|
||||||
|
BlMmUnmapVirtualAddressEx(BaseAddress, ImageSize);
|
||||||
|
BlMmFreePhysicalPages(PhysicalAddress);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Free the physical buffer */
|
||||||
|
//MmPapFreePages(VirtualAddress, 1);
|
||||||
|
EfiPrintf(L"Leaking memory\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we hadn't gotten to 100% yet, do it now */
|
||||||
|
if (ShowProgress)
|
||||||
|
{
|
||||||
|
BlUtlUpdateProgress(100, &Completed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the final status */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
|
@ -28,8 +28,47 @@ ULONG UtlNextUpdatePercentage;
|
||||||
BOOLEAN UtlProgressNeedsInfoUpdate;
|
BOOLEAN UtlProgressNeedsInfoUpdate;
|
||||||
PVOID UtlProgressInfo;
|
PVOID UtlProgressInfo;
|
||||||
|
|
||||||
|
PVOID ResRootDirectory;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
VOID
|
||||||
|
BlUtlUpdateProgress (
|
||||||
|
_In_ ULONG Percentage,
|
||||||
|
_Out_opt_ PBOOLEAN Completed
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (UtlProgressRoutine)
|
||||||
|
{
|
||||||
|
EfiPrintf(L"Unimplemented\r\n");
|
||||||
|
}
|
||||||
|
else if (*Completed)
|
||||||
|
{
|
||||||
|
*Completed = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PWCHAR
|
||||||
|
BlResourceFindMessage (
|
||||||
|
_In_ ULONG MsgId
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PWCHAR Message;
|
||||||
|
|
||||||
|
/* Assume failure */
|
||||||
|
Message = NULL;
|
||||||
|
|
||||||
|
/* Check if we've loaded resources */
|
||||||
|
if (ResRootDirectory)
|
||||||
|
{
|
||||||
|
/* Not yet handled */
|
||||||
|
EfiPrintf(L"Not implemented\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the message for this ID */
|
||||||
|
return Message;
|
||||||
|
}
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
* @name EfiGetEfiStatusCode
|
* @name EfiGetEfiStatusCode
|
||||||
*
|
*
|
||||||
|
|
|
@ -204,6 +204,72 @@ Quickie:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
MmUnmapVirtualAddress (
|
||||||
|
_Inout_ PVOID* VirtualAddress,
|
||||||
|
_Inout_ PULONGLONG Size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Make sure parameters were passed in and are valid */
|
||||||
|
if ((VirtualAddress) && (Size) && (*Size <= 0xFFFFFFFF))
|
||||||
|
{
|
||||||
|
/* Nothing to do if translation isn't active */
|
||||||
|
if (MmTranslationType == BlNone)
|
||||||
|
{
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All done */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlMmUnmapVirtualAddressEx (
|
||||||
|
_In_ PVOID VirtualAddress,
|
||||||
|
_In_ ULONGLONG Size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Increment call depth */
|
||||||
|
++MmDescriptorCallTreeCount;
|
||||||
|
|
||||||
|
/* Make sure all parameters are tehre */
|
||||||
|
if ((VirtualAddress) && (Size))
|
||||||
|
{
|
||||||
|
/* Unmap the virtual address */
|
||||||
|
Status = MmUnmapVirtualAddress(&VirtualAddress, &Size);
|
||||||
|
|
||||||
|
/* Check if we actually had a virtual mapping active */
|
||||||
|
if ((NT_SUCCESS(Status)) && (MmTranslationType != BlNone))
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup descriptors and reduce depth */
|
||||||
|
MmMdFreeGlobalDescriptors();
|
||||||
|
--MmDescriptorCallTreeCount;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
BlpMmInitialize (
|
BlpMmInitialize (
|
||||||
_In_ PBL_MEMORY_DATA MemoryData,
|
_In_ PBL_MEMORY_DATA MemoryData,
|
||||||
|
|
|
@ -568,4 +568,33 @@ MmPaInitialize (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlMmAllocatePhysicalPages(
|
||||||
|
_In_ PPHYSICAL_ADDRESS Address,
|
||||||
|
_In_ BL_MEMORY_TYPE MemoryType,
|
||||||
|
_In_ ULONGLONG PageCount,
|
||||||
|
_In_ ULONG Attributes,
|
||||||
|
_In_ ULONG Alignment
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Call the physical allocator */
|
||||||
|
return MmPapAllocatePhysicalPagesInRange(Address,
|
||||||
|
MemoryType,
|
||||||
|
PageCount,
|
||||||
|
Attributes,
|
||||||
|
Alignment,
|
||||||
|
&MmMdlUnmappedAllocated,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlMmFreePhysicalPages (
|
||||||
|
_In_ PHYSICAL_ADDRESS Address
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Call the physical allocator */
|
||||||
|
EfiPrintf(L"Leaking memory!\r\n");
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
//return MmPapFreePhysicalPages(4, 0, Address);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue