mirror of
https://github.com/reactos/reactos.git
synced 2025-05-30 22:49:12 +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
|
||||
app/bootmgr/bootmgr.h
|
||||
lib/bootlib.c
|
||||
lib/misc/debug.c
|
||||
lib/misc/bcd.c
|
||||
lib/misc/util.c
|
||||
lib/misc/image.c
|
||||
lib/firmware/efi/firmware.c
|
||||
lib/mm/mm.c
|
||||
lib/mm/pagealloc.c
|
||||
|
|
|
@ -23,6 +23,14 @@ ULONGLONG PostTime;
|
|||
GUID BmApplicationIdentifier;
|
||||
PWCHAR BootDirectory;
|
||||
|
||||
BL_BOOT_ERROR BmpErrorBuffer;
|
||||
PBL_BOOT_ERROR BmpInternalBootError;
|
||||
BL_PACKED_BOOT_ERROR BmpPackedBootError;
|
||||
|
||||
BOOLEAN BmBootIniUsed;
|
||||
WCHAR BmpFileNameBuffer[128];
|
||||
PWCHAR ParentFileName = L"";
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
@ -120,8 +128,8 @@ BmpFwGetApplicationDirectoryPath (
|
|||
|
||||
/* All done! */
|
||||
return Status;
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BmFwInitializeBootDirectoryPath (
|
||||
VOID
|
||||
|
@ -187,6 +195,7 @@ BmFwInitializeBootDirectoryPath (
|
|||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Save the boot directory */
|
||||
BootDirectory = L"\\EFI\\Microsoft\\Boot";
|
||||
|
||||
Quickie:
|
||||
|
@ -216,6 +225,441 @@ Quickie:
|
|||
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
|
||||
|
@ -240,7 +684,7 @@ BmMain (
|
|||
PBL_RETURN_ARGUMENTS ReturnArguments;
|
||||
BOOLEAN RebootOnError;
|
||||
PGUID AppIdentifier;
|
||||
// HANDLE BcdHandle;
|
||||
HANDLE BcdHandle;
|
||||
|
||||
EfiPrintf(L"ReactOS UEFI Boot Manager Initializing...\n");
|
||||
|
||||
|
@ -280,15 +724,18 @@ BmMain (
|
|||
/* None was given, so set our default one */
|
||||
AppIdentifier = (PGUID)&GUID_WINDOWS_BOOTMGR;
|
||||
}
|
||||
|
||||
|
||||
/* Save our identifier */
|
||||
BmApplicationIdentifier = *AppIdentifier;
|
||||
|
||||
/* Initialize the file system to open a handle to our root boot directory */
|
||||
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");
|
||||
EfiStall(10000000);
|
||||
|
||||
|
|
|
@ -29,6 +29,28 @@
|
|||
/* BCD Headers */
|
||||
#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 *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "bootmgr.h"
|
||||
#include <bcd.h>
|
||||
|
||||
/* DATA STRUCTURES ***********************************************************/
|
||||
|
||||
|
@ -206,8 +205,7 @@ EfiInitpConvertEfiFilePath (
|
|||
)
|
||||
{
|
||||
ULONG BytesAppended, DataSize, StringLength;
|
||||
PBCDE_STRING StringEntry;
|
||||
PWCHAR PathString;
|
||||
PWCHAR StringEntry, PathString;
|
||||
FILEPATH_DEVICE_PATH *FilePath;
|
||||
NTSTATUS Status;
|
||||
|
||||
|
@ -227,8 +225,8 @@ EfiInitpConvertEfiFilePath (
|
|||
Option->DataOffset = sizeof(*Option);
|
||||
|
||||
/* Extract the string option */
|
||||
StringEntry = (PBCDE_STRING)(Option + 1);
|
||||
PathString = StringEntry->String;
|
||||
StringEntry = (PWCHAR)(Option + 1);
|
||||
PathString = StringEntry;
|
||||
|
||||
/* Start parsing the device path */
|
||||
FilePath = (FILEPATH_DEVICE_PATH*)DevicePath;
|
||||
|
@ -282,7 +280,7 @@ EfiInitpConvertEfiFilePath (
|
|||
DataSize += sizeof(UNICODE_NULL);
|
||||
|
||||
/* Check if all of this has amounted to a single NULL-char */
|
||||
if (PathString == StringEntry->String)
|
||||
if (PathString == StringEntry)
|
||||
{
|
||||
/* Then this option is empty */
|
||||
Option->Empty = TRUE;
|
||||
|
@ -520,7 +518,7 @@ EfiInitpConvertEfiDevicePath (
|
|||
_In_ ULONG MaximumLength
|
||||
)
|
||||
{
|
||||
PBCDE_DEVICE DeviceEntry;
|
||||
PBCD_DEVICE_OPTION BcdDevice;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Make sure we have enough space for the option */
|
||||
|
@ -534,15 +532,17 @@ EfiInitpConvertEfiDevicePath (
|
|||
RtlZeroMemory(Option, sizeof(*Option));
|
||||
|
||||
/* 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;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Fill it out */
|
||||
DeviceEntry = (PBCDE_DEVICE)(Option + 1);
|
||||
Status = EfiInitTranslateDevicePath(DevicePath, &DeviceEntry->Device);
|
||||
BcdDevice = (PBCD_DEVICE_OPTION)(Option + 1);
|
||||
Status = EfiInitTranslateDevicePath(DevicePath,
|
||||
&BcdDevice->DeviceDescriptor);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
goto Quickie;
|
||||
|
@ -551,8 +551,8 @@ EfiInitpConvertEfiDevicePath (
|
|||
/* Fill out the rest of the option structure */
|
||||
Option->DataOffset = sizeof(*Option);
|
||||
Option->Type = DeviceType;
|
||||
Option->DataSize = FIELD_OFFSET(BCDE_DEVICE, Device) +
|
||||
DeviceEntry->Device.Size;
|
||||
Option->DataSize = FIELD_OFFSET(BCD_DEVICE_OPTION, DeviceDescriptor) +
|
||||
BcdDevice->DeviceDescriptor.Size;
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
Quickie:
|
||||
|
@ -618,7 +618,7 @@ EfiInitpCreateApplicationEntry (
|
|||
NTSTATUS Status;
|
||||
UNICODE_STRING GuidString;
|
||||
GUID ObjectGuid;
|
||||
PBCDE_DEVICE BcdDevice;
|
||||
PBCD_DEVICE_OPTION BcdDevice;
|
||||
BOOLEAN HaveBinaryOptions, HaveGuid;
|
||||
PBL_FILE_PATH_DESCRIPTOR OsPath;
|
||||
EFI_DEVICE_PATH *OsDevicePath;
|
||||
|
@ -719,7 +719,7 @@ EfiInitpCreateApplicationEntry (
|
|||
|
||||
/* Extract the device descriptor and return it */
|
||||
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 */
|
||||
TotalOptionSize = BlGetBootOptionSize(&Entry->BcdData);
|
||||
|
|
|
@ -137,17 +137,39 @@ typedef enum BcdOSLoaderElementTypes
|
|||
BcdOSLoaderInteger_XSaveDisable = 0x2500012b
|
||||
} 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 ***********************************************************/
|
||||
|
||||
typedef struct _BCDE_DEVICE
|
||||
typedef struct _BCD_DEVICE_OPTION
|
||||
{
|
||||
GUID AdditionalOptions;
|
||||
BL_DEVICE_DESCRIPTOR Device;
|
||||
} BCDE_DEVICE, *PBCDE_DEVICE;
|
||||
GUID AssociatedEntry;
|
||||
BL_DEVICE_DESCRIPTOR DeviceDescriptor;
|
||||
} BCD_DEVICE_OPTION, *PBCD_DEVICE_OPTION;
|
||||
|
||||
typedef struct _BCDE_STRING
|
||||
{
|
||||
WCHAR String[ANYSIZE_ARRAY];
|
||||
} BCDE_STRING, *PBCDE_STRING;
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
BcdOpenStoreFromFile (
|
||||
_In_ PUNICODE_STRING FileName,
|
||||
_In_ PHANDLE StoreHandle
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*b
|
||||
* COPYRIGHT: See COPYING.ARM in the top level directory
|
||||
* PROJECT: ReactOS UEFI Boot Library
|
||||
* FILE: boot/environ/include/bl.h
|
||||
|
@ -30,6 +30,10 @@
|
|||
#include <UgaDraw.h>
|
||||
#include <BlockIo.h>
|
||||
|
||||
/* Registry Headers */
|
||||
#define __FREELDR_H
|
||||
#include <cmlib.h>
|
||||
|
||||
/* DEFINES *******************************************************************/
|
||||
|
||||
#define BL_APPLICATION_FLAG_CONVERTED_FROM_EFI 0x01
|
||||
|
@ -85,6 +89,30 @@
|
|||
|
||||
#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 **************************************************************/
|
||||
|
||||
typedef enum _BL_COLOR
|
||||
|
@ -169,6 +197,7 @@ typedef enum _BL_PARTITION_TYPE
|
|||
//
|
||||
typedef enum _BL_PATH_TYPE
|
||||
{
|
||||
InternalPath = 3,
|
||||
EfiPath = 4
|
||||
} BL_PATH_TYPE;
|
||||
|
||||
|
@ -266,6 +295,7 @@ typedef enum _BL_MEMORY_ATTR
|
|||
/* CALLBACKS *****************************************************************/
|
||||
|
||||
struct _BL_FILE_ENTRY;
|
||||
struct _BL_FILE_INFORMATION;
|
||||
typedef
|
||||
NTSTATUS
|
||||
(*PBL_FILE_OPEN) (
|
||||
|
@ -284,7 +314,10 @@ NTSTATUS
|
|||
typedef
|
||||
NTSTATUS
|
||||
(*PBL_FILE_READ) (
|
||||
VOID
|
||||
_In_ struct _BL_FILE_ENTRY* FileEntry,
|
||||
_In_ PVOID Buffer,
|
||||
_In_ ULONG Size,
|
||||
_Out_ PULONG BytesRead
|
||||
);
|
||||
|
||||
typedef
|
||||
|
@ -302,13 +335,15 @@ NTSTATUS
|
|||
typedef
|
||||
NTSTATUS
|
||||
(*PBL_FILE_GET_INFO) (
|
||||
VOID
|
||||
_In_ struct _BL_FILE_ENTRY* FileEntry,
|
||||
_Out_ struct _BL_FILE_INFORMATION* FileInfo
|
||||
);
|
||||
|
||||
typedef
|
||||
NTSTATUS
|
||||
(*PBL_FILE_SET_INFO) (
|
||||
VOID
|
||||
_In_ struct _BL_FILE_ENTRY* FileEntry,
|
||||
_In_ struct _BL_FILE_INFORMATION* FileInfo
|
||||
);
|
||||
|
||||
typedef
|
||||
|
@ -745,6 +780,12 @@ typedef struct _BL_ADDRESS_RANGE
|
|||
ULONGLONG Maximum;
|
||||
} 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
|
||||
{
|
||||
PBL_FILE_OPEN Open;
|
||||
|
@ -767,7 +808,6 @@ typedef struct _BL_FILE_ENTRY
|
|||
ULONGLONG Unknown1;
|
||||
ULONGLONG Unknown2;
|
||||
BL_FILE_CALLBACKS Callbacks;
|
||||
//PBL_FILE_DESTROY_CALLBACK DestroyCallback;
|
||||
PVOID FsSpecificData;
|
||||
} BL_FILE_ENTRY, *PBL_FILE_ENTRY;
|
||||
|
||||
|
@ -966,6 +1006,18 @@ typedef struct _BL_DEVICE_ENTRY
|
|||
PBL_DEVICE_DESCRIPTOR DeviceDescriptor;
|
||||
} 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 ***********************************************************/
|
||||
|
||||
FORCEINLINE
|
||||
|
@ -1238,8 +1290,44 @@ EtfsMount (
|
|||
_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 **********************************************************/
|
||||
|
||||
VOID
|
||||
BlUtlUpdateProgress (
|
||||
_In_ ULONG Percentage,
|
||||
_Out_opt_ PBOOLEAN Completed
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EfiGetEfiStatusCode(
|
||||
_In_ NTSTATUS Status
|
||||
|
@ -1265,6 +1353,11 @@ BlGetApplicationIdentifier (
|
|||
VOID
|
||||
);
|
||||
|
||||
PWCHAR
|
||||
BlResourceFindMessage (
|
||||
_In_ ULONG MsgId
|
||||
);
|
||||
|
||||
/* TABLE ROUTINES ************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
@ -1353,6 +1446,14 @@ BlGetBootOptionBoolean (
|
|||
_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 **********************************************************/
|
||||
|
||||
VOID
|
||||
|
@ -1423,6 +1524,20 @@ MmMdFreeDescriptor (
|
|||
|
||||
/* 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
|
||||
MmPapAllocatePagesInRange (
|
||||
_Inout_ PVOID* PhysicalAddress,
|
||||
|
@ -1450,6 +1565,12 @@ BlMmMapPhysicalAddressEx (
|
|||
_In_ PHYSICAL_ADDRESS PhysicalAddress
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
BlMmUnmapVirtualAddressEx (
|
||||
_In_ PVOID VirtualAddress,
|
||||
_In_ ULONGLONG Size
|
||||
);
|
||||
|
||||
/* BLOCK ALLOCATOR ROUTINES **************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
@ -1525,11 +1646,27 @@ BlFileClose (
|
|||
_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
|
||||
BlFileOpen (
|
||||
_In_ ULONG DeviceId,
|
||||
_In_ PWCHAR FileName,
|
||||
_In_ ULONG OpenFlags,
|
||||
_In_ ULONG Flags,
|
||||
_Out_ PULONG FileId
|
||||
);
|
||||
|
||||
|
@ -1691,4 +1828,5 @@ extern BL_DISPLAY_MODE ConsoleGraphicalResolutionList[];
|
|||
extern BL_DISPLAY_MODE ConsoleTextResolutionList[];
|
||||
extern ULONG ConsoleGraphicalResolutionListSize;
|
||||
extern PVOID DspRemoteInputConsole;
|
||||
extern WCHAR BlScratchBuffer[8192];
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,6 @@ BL_FILE_SYSTEM_REGISTRATION_TABLE EtfsRegisterFunctionTable =
|
|||
NULL
|
||||
};
|
||||
|
||||
|
||||
extern ULONG DmTableEntries;
|
||||
extern PVOID* DmDeviceTable;
|
||||
|
||||
|
@ -120,7 +119,9 @@ FileTableCompareWithSubsetAttributes (
|
|||
|
||||
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)))
|
||||
{
|
||||
|
@ -151,7 +152,9 @@ FileTableCompareWithSameAttributes (
|
|||
|
||||
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)))
|
||||
{
|
||||
|
@ -192,24 +195,25 @@ FileTableDestroyEntry (
|
|||
return Status;
|
||||
}
|
||||
|
||||
#define BL_FILE_PURGE_LIMIT 512
|
||||
|
||||
NTSTATUS
|
||||
FileTablePurgeEntry (
|
||||
_In_ PVOID 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = FileTableDestroyEntry(FileEntry, FileEntry->FileId);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return Status;
|
||||
/* Purge the entry othwrwise */
|
||||
return FileTableDestroyEntry(FileEntry, FileEntry->FileId);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -219,28 +223,34 @@ BlFileClose (
|
|||
{
|
||||
PBL_FILE_ENTRY FileEntry;
|
||||
|
||||
/* Validate the file ID */
|
||||
if (FileEntries <= FileId)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Make sure a file entry actually exists */
|
||||
FileEntry = FileTable[FileId];
|
||||
if (!FileEntry)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* Drop a reference, check if this was the last one */
|
||||
--FileEntry->ReferenceCount;
|
||||
if (!FileEntry->ReferenceCount)
|
||||
{
|
||||
FileEntry->Flags &= ~1;
|
||||
/* File is no longer open */
|
||||
FileEntry->Flags &= ~BL_FILE_ENTRY_OPENED;
|
||||
}
|
||||
|
||||
/* All good */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -251,46 +261,58 @@ FileIoOpen (
|
|||
_In_ ULONG Flags,
|
||||
_In_ ULONG Unknown,
|
||||
_In_ PBL_TBL_LOOKUP_ROUTINE CompareRoutine,
|
||||
_Out_ PBL_FILE_ENTRY *ReturnFileEntry
|
||||
_Out_opt_ PBL_FILE_ENTRY *NewFileEntry
|
||||
)
|
||||
{
|
||||
PWCHAR FileNameCopy, ParentFileName;
|
||||
NTSTATUS Status;
|
||||
PBL_DEVICE_ENTRY DeviceEntry;
|
||||
PBL_FILE_SYSTEM_ENTRY FileSystem;
|
||||
ULONG FileId;
|
||||
PBL_FILE_ENTRY ParentDirectoryEntry, FileEntry;
|
||||
ULONG FileId, CheckFlags;
|
||||
PBL_FILE_ENTRY DirectoryEntry, FileEntry;
|
||||
PLIST_ENTRY NextEntry, ListHead;
|
||||
|
||||
ParentDirectoryEntry = NULL;
|
||||
/* Preinitialize variables for failure */
|
||||
DirectoryEntry = NULL;
|
||||
FileNameCopy = NULL;
|
||||
Flags |= 1;
|
||||
ParentFileName = NULL;
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
/* Bail out if the device ID is invalid */
|
||||
if (DmTableEntries <= DeviceId)
|
||||
{
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* Bail out if there's no device entry */
|
||||
DeviceEntry = DmDeviceTable[DeviceId];
|
||||
if (!DeviceEntry)
|
||||
{
|
||||
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");
|
||||
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");
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* Check if we already have this file open */
|
||||
FileEntry = (PBL_FILE_ENTRY )BlTblFindEntry(FileTable,
|
||||
FileEntries,
|
||||
&FileId,
|
||||
|
@ -305,80 +327,89 @@ FileIoOpen (
|
|||
goto FileOpened;
|
||||
}
|
||||
|
||||
/* Check if we are opening the root drive or an actual file/directory */
|
||||
if ((*FileName != OBJ_NAME_PATH_SEPARATOR) || (FileName[1]))
|
||||
{
|
||||
/* Get the name of the directory */
|
||||
ParentFileName = FileIoCopyParentDirectoryPath(FileName);
|
||||
if (!ParentFileName)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto FileOpenEnd;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Open it */
|
||||
Status = FileIoOpen(DeviceId,
|
||||
ParentFileName,
|
||||
5,
|
||||
BL_FILE_READ_ACCESS | BL_DIRECTORY_ACCESS,
|
||||
Unknown,
|
||||
FileTableCompareWithSubsetAttributes,
|
||||
&ParentDirectoryEntry);
|
||||
if (Status < 0)
|
||||
&DirectoryEntry);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
goto FileOpenEnd;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Now get the the file name itself */
|
||||
FileNameCopy = FileIoCopyFileName(FileName);
|
||||
if (!FileNameCopy)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto FileOpenEnd;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
Status = ParentDirectoryEntry->Callbacks.Open(ParentDirectoryEntry,
|
||||
FileNameCopy,
|
||||
Flags,
|
||||
&FileEntry);
|
||||
/* Open it */
|
||||
Status = DirectoryEntry->Callbacks.Open(DirectoryEntry,
|
||||
FileNameCopy,
|
||||
Flags,
|
||||
&FileEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
EfiPrintf(L"Opening root drive\r\n");
|
||||
/* We're opening the root, scan through all the file systems */
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
ListHead = &RegisteredFileSystems;
|
||||
NextEntry = ListHead->Flink;
|
||||
while (NextEntry != ListHead)
|
||||
{
|
||||
/* Try to mount this one */
|
||||
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);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Mount successful */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try the next file system */
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
/* Nothing to free on this path */
|
||||
FileNameCopy = NULL;
|
||||
}
|
||||
|
||||
/* Handle failure */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
EfiPrintf(L"Could not open file!: %lx\r\n", Status);
|
||||
goto FileOpenEnd;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Save the 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 & 2)
|
||||
if (Flags & BL_FILE_WRITE_ACCESS)
|
||||
{
|
||||
FileEntry->Flags |= 4u;
|
||||
FileEntry->Flags |= BL_FILE_ENTRY_WRITE_ACCESS;
|
||||
}
|
||||
|
||||
/* Save the file into the file table */
|
||||
Status = BlTblSetEntry(&FileTable,
|
||||
&FileEntries,
|
||||
(PVOID)FileEntry,
|
||||
|
@ -386,48 +417,62 @@ FileIoOpen (
|
|||
FileTablePurgeEntry);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Close it if that failed */
|
||||
FileEntry->Callbacks.Close(FileEntry);
|
||||
goto FileOpenEnd;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Add a reference on the device, and save our file ID */
|
||||
++DeviceEntry->ReferenceCount;
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
EfiPrintf(L"File %s opened with ID: %lx\r\n", FileEntry->FilePath, FileId);
|
||||
FileEntry->FileId = FileId;
|
||||
|
||||
EfiPrintf(L"File %s opened with ID: %lx\r\n", FileEntry->FilePath, FileId);
|
||||
|
||||
FileOpened:
|
||||
/* Add a reference to the file entry, and see if this is the first one */
|
||||
if (++FileEntry->ReferenceCount == 1)
|
||||
{
|
||||
/* Reset unknowns */
|
||||
FileEntry->Unknown1 = 0;
|
||||
FileEntry->Unknown2 = 0;
|
||||
}
|
||||
|
||||
FileEntry->Flags |= 1;
|
||||
|
||||
if (Flags & 0x10)
|
||||
/* Set the file as opened */
|
||||
FileEntry->Flags |= BL_FILE_ENTRY_OPENED;
|
||||
|
||||
/* 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:
|
||||
if (ParentDirectoryEntry)
|
||||
Quickie:
|
||||
/* Close the parent */
|
||||
if (DirectoryEntry)
|
||||
{
|
||||
BlFileClose(ParentDirectoryEntry->FileId);
|
||||
BlFileClose(DirectoryEntry->FileId);
|
||||
}
|
||||
|
||||
/* Free the parent name copy */
|
||||
if (ParentFileName)
|
||||
{
|
||||
BlMmFreeHeap(ParentFileName);
|
||||
}
|
||||
|
||||
/* Free the file name copy */
|
||||
if (FileNameCopy)
|
||||
{
|
||||
BlMmFreeHeap(FileNameCopy);
|
||||
}
|
||||
|
||||
/* Return back to caller */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -443,15 +488,17 @@ BlFileOpen (
|
|||
PBL_FILE_ENTRY FileEntry;
|
||||
BL_DEVICE_INFORMATION DeviceInformation;
|
||||
|
||||
/* Make sure we have a valid file name, access flags and parameters */
|
||||
if (!(FileName) ||
|
||||
(*FileName != OBJ_NAME_PATH_SEPARATOR) ||
|
||||
!(FileId) ||
|
||||
!(Flags & 3))
|
||||
!(Flags & (BL_FILE_READ_ACCESS | BL_FILE_WRITE_ACCESS)))
|
||||
{
|
||||
EfiPrintf(L"Invalid file options\r\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Get information on the underlying device */
|
||||
Status = BlDeviceGetInformation(DeviceId, &DeviceInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -459,6 +506,7 @@ BlFileOpen (
|
|||
return Status;
|
||||
}
|
||||
|
||||
/* Make sure it's a device that can host files */
|
||||
if ((DeviceInformation.DeviceType != DiskDevice) &&
|
||||
(DeviceInformation.DeviceType != LegacyPartitionDevice) &&
|
||||
(DeviceInformation.DeviceType != UdpDevice))
|
||||
|
@ -467,6 +515,7 @@ BlFileOpen (
|
|||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Open a file on this device, creating one if needed */
|
||||
Status = FileIoOpen(DeviceId,
|
||||
FileName,
|
||||
Flags,
|
||||
|
@ -475,10 +524,339 @@ BlFileOpen (
|
|||
&FileEntry);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Return the file ID back to the caller */
|
||||
EfiPrintf(L"File opened: %lx\r\n", 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,86 @@ MiscGetBootOption (
|
|||
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
|
||||
BlGetBootOptionString (
|
||||
_In_ PBL_BCD_OPTION List,
|
||||
|
@ -161,6 +241,151 @@ BlGetBootOptionString (
|
|||
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
|
||||
BlGetBootOptionInteger (
|
||||
_In_ PBL_BCD_OPTION List,
|
||||
|
@ -231,80 +456,342 @@ BlGetBootOptionBoolean (
|
|||
return Status;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @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
|
||||
#define BI_FLUSH_HIVE 0x01
|
||||
|
||||
typedef struct _BI_KEY_HIVE
|
||||
{
|
||||
PVOID ImageBase;
|
||||
PBL_FILE_PATH_DESCRIPTOR FilePath;
|
||||
CMHIVE Hive;
|
||||
LONG ReferenceCount;
|
||||
ULONG Flags;
|
||||
} BI_KEY_HIVE, *PBI_KEY_HIVE;
|
||||
|
||||
typedef struct _BI_KEY_OBJECT
|
||||
{
|
||||
PBI_KEY_HIVE KeyHive;
|
||||
PCM_KEY_NODE KeyNode;
|
||||
HCELL_INDEX KeyCell;
|
||||
PWCHAR KeyName;
|
||||
} BI_KEY_OBJECT, *PBI_KEY_OBJECT;
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
CmpAllocate (
|
||||
_In_ SIZE_T Size,
|
||||
_In_ BOOLEAN Paged,
|
||||
_In_ ULONG Tag
|
||||
)
|
||||
{
|
||||
ULONG Size = 0, NextOffset = 0;
|
||||
PBL_BCD_OPTION NextOption;
|
||||
UNREFERENCED_PARAMETER(Paged);
|
||||
UNREFERENCED_PARAMETER(Tag);
|
||||
|
||||
/* 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;
|
||||
/* Call the heap allocator */
|
||||
return BlMmAllocateHeap(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
|
||||
VOID
|
||||
NTAPI
|
||||
CmpFree (
|
||||
_In_ PVOID Ptr,
|
||||
_In_ ULONG Quota
|
||||
)
|
||||
{
|
||||
ULONG Size, Offset;
|
||||
UNREFERENCED_PARAMETER(Quota);
|
||||
|
||||
/* Check if there's any data */
|
||||
if (BcdOption->DataOffset != 0)
|
||||
/* Call the heap allocator */
|
||||
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 */
|
||||
Size = BcdOption->DataOffset + BcdOption->DataSize;
|
||||
/* Drop a reference, see if it's the last one */
|
||||
BiDereferenceHive(KeyHandle);
|
||||
if (!KeyHive->ReferenceCount)
|
||||
{
|
||||
/* Check if we should flush it */
|
||||
if (KeyHive->Flags & BI_FLUSH_HIVE)
|
||||
{
|
||||
BiFlushHive(KeyHandle);
|
||||
}
|
||||
|
||||
/* Unmap the hive */
|
||||
//MmPapFreePages(KeyHive->ImageBase, 1);
|
||||
EfiPrintf(L"Leaking hive memory\r\n");
|
||||
|
||||
/* Free the hive and hive path */
|
||||
BlMmFreeHeap(KeyHive->FilePath);
|
||||
BlMmFreeHeap(KeyHive);
|
||||
}
|
||||
|
||||
/* Check if a key name is present */
|
||||
if (KeyObject->KeyName)
|
||||
{
|
||||
/* Free it */
|
||||
BlMmFreeHeap(KeyObject->KeyName);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the object */
|
||||
BlMmFreeHeap(KeyObject);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BiOpenKey(
|
||||
_In_ HANDLE ParentHandle,
|
||||
_In_ PWCHAR KeyName,
|
||||
_Out_ PHANDLE Handle
|
||||
)
|
||||
{
|
||||
PBI_KEY_OBJECT ParentKey, NewKey;
|
||||
PBI_KEY_HIVE ParentHive;
|
||||
NTSTATUS Status;
|
||||
ULONG NameLength, SubNameLength, NameBytes;
|
||||
PWCHAR NameStart, NameBuffer;
|
||||
UNICODE_STRING KeyString;
|
||||
HCELL_INDEX KeyCell;
|
||||
PHHIVE Hive;
|
||||
PCM_KEY_NODE ParentNode;
|
||||
|
||||
/* Convert from a handle to our key object */
|
||||
ParentKey = (PBI_KEY_OBJECT)ParentHandle;
|
||||
|
||||
/* Extract the hive and node information */
|
||||
ParentHive = ParentKey->KeyHive;
|
||||
ParentNode = ParentKey->KeyNode;
|
||||
Hive = &ParentKey->KeyHive->Hive.Hive;
|
||||
|
||||
/* Initialize variables */
|
||||
KeyCell = HCELL_NIL;
|
||||
Status = STATUS_SUCCESS;
|
||||
NameBuffer = NULL;
|
||||
|
||||
/* Loop as long as there's still portions of the key name in play */
|
||||
NameLength = wcslen(KeyName);
|
||||
while (NameLength)
|
||||
{
|
||||
/* Find the first path separator */
|
||||
NameStart = wcschr(KeyName, OBJ_NAME_PATH_SEPARATOR);
|
||||
if (NameStart)
|
||||
{
|
||||
/* Look only at the key before the separator */
|
||||
SubNameLength = NameStart - KeyName;
|
||||
++NameStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No path separator, this is the final leaf key */
|
||||
SubNameLength = NameLength;
|
||||
}
|
||||
|
||||
/* Free the name buffer from the previous pass if needed */
|
||||
if (NameBuffer)
|
||||
{
|
||||
BlMmFreeHeap(NameBuffer);
|
||||
}
|
||||
|
||||
/* Allocate a buffer to hold the name of this specific subkey only */
|
||||
NameBytes = SubNameLength * sizeof(WCHAR);
|
||||
NameBuffer = BlMmAllocateHeap(NameBytes + sizeof(UNICODE_NULL));
|
||||
if (!NameBuffer)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Copy and null-terminate the name of the subkey */
|
||||
RtlCopyMemory(NameBuffer, KeyName, NameBytes);
|
||||
NameBuffer[SubNameLength] = UNICODE_NULL;
|
||||
|
||||
/* Convert it into a UNICODE_STRING and try to find it */
|
||||
RtlInitUnicodeString(&KeyString, NameBuffer);
|
||||
KeyCell = CmpFindSubKeyByName(Hive, ParentNode, &KeyString);
|
||||
if (KeyCell == HCELL_NIL)
|
||||
{
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* We found it -- get the key node out of it */
|
||||
ParentNode = (PCM_KEY_NODE)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
|
||||
{
|
||||
/* No data, just the structure itself */
|
||||
Size = sizeof(*BcdOption);
|
||||
/* Failure, drop a reference on the hive and close the key */
|
||||
BiDereferenceHive(HiveHandle);
|
||||
BiCloseKey(HiveHandle);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* Return the status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
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;
|
||||
PVOID UtlProgressInfo;
|
||||
|
||||
PVOID ResRootDirectory;
|
||||
|
||||
/* 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
|
||||
*
|
||||
|
|
|
@ -204,6 +204,72 @@ Quickie:
|
|||
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
|
||||
BlpMmInitialize (
|
||||
_In_ PBL_MEMORY_DATA MemoryData,
|
||||
|
|
|
@ -568,4 +568,33 @@ MmPaInitialize (
|
|||
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