Author: ion Date: Sun Oct 4 21:07:12 2015 New Revision: 69447
URL: http://svn.reactos.org/svn/reactos?rev=69447&view=rev Log: [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
Added: trunk/reactos/boot/environ/lib/misc/debug.c (with props) trunk/reactos/boot/environ/lib/misc/image.c (with props) Modified: trunk/reactos/boot/environ/CMakeLists.txt trunk/reactos/boot/environ/app/bootmgr/bootmgr.c trunk/reactos/boot/environ/app/bootmgr/bootmgr.h trunk/reactos/boot/environ/app/bootmgr/efiemu.c trunk/reactos/boot/environ/include/bcd.h trunk/reactos/boot/environ/include/bl.h trunk/reactos/boot/environ/lib/io/file.c trunk/reactos/boot/environ/lib/misc/bcd.c trunk/reactos/boot/environ/lib/misc/util.c trunk/reactos/boot/environ/lib/mm/mm.c trunk/reactos/boot/environ/lib/mm/pagealloc.c
Modified: trunk/reactos/boot/environ/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/CMakeLists.txt... ============================================================================== --- trunk/reactos/boot/environ/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/boot/environ/CMakeLists.txt [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -10,8 +10,10 @@ 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
Modified: trunk/reactos/boot/environ/app/bootmgr/bootmgr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/app/bootmgr/bo... ============================================================================== --- trunk/reactos/boot/environ/app/bootmgr/bootmgr.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/app/bootmgr/bootmgr.c [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -22,6 +22,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 *****************************************************************/
@@ -120,8 +128,8 @@
/* All done! */ return Status; - -} +} + NTSTATUS BmFwInitializeBootDirectoryPath ( VOID @@ -187,6 +195,7 @@ goto Quickie; }
+ /* Save the boot directory */ BootDirectory = L"\EFI\Microsoft\Boot";
Quickie: @@ -216,6 +225,441 @@ 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 @@ PBL_RETURN_ARGUMENTS ReturnArguments; BOOLEAN RebootOnError; PGUID AppIdentifier; -// HANDLE BcdHandle; + HANDLE BcdHandle;
EfiPrintf(L"ReactOS UEFI Boot Manager Initializing...\n");
@@ -280,15 +724,18 @@ /* 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);
Modified: trunk/reactos/boot/environ/app/bootmgr/bootmgr.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/app/bootmgr/bo... ============================================================================== --- trunk/reactos/boot/environ/app/bootmgr/bootmgr.h [iso-8859-1] (original) +++ trunk/reactos/boot/environ/app/bootmgr/bootmgr.h [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -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
Modified: trunk/reactos/boot/environ/app/bootmgr/efiemu.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/app/bootmgr/ef... ============================================================================== --- trunk/reactos/boot/environ/app/bootmgr/efiemu.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/app/bootmgr/efiemu.c [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -9,7 +9,6 @@ /* INCLUDES ******************************************************************/
#include "bootmgr.h" -#include <bcd.h>
/* DATA STRUCTURES ***********************************************************/
@@ -206,8 +205,7 @@ ) { ULONG BytesAppended, DataSize, StringLength; - PBCDE_STRING StringEntry; - PWCHAR PathString; + PWCHAR StringEntry, PathString; FILEPATH_DEVICE_PATH *FilePath; NTSTATUS Status;
@@ -227,8 +225,8 @@ 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 @@ 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 @@ _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 @@ 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 @@ /* 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 @@ 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 @@
/* 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);
Modified: trunk/reactos/boot/environ/include/bcd.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/include/bcd.h?... ============================================================================== --- trunk/reactos/boot/environ/include/bcd.h [iso-8859-1] (original) +++ trunk/reactos/boot/environ/include/bcd.h [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -137,17 +137,39 @@ 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
Modified: trunk/reactos/boot/environ/include/bl.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/include/bl.h?r... ============================================================================== --- trunk/reactos/boot/environ/include/bl.h [iso-8859-1] (original) +++ trunk/reactos/boot/environ/include/bl.h [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -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 @@ -84,6 +88,30 @@ #define BL_BLOCK_DEVICE_REMOVABLE_FLAG 0x01
#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 **************************************************************/
@@ -169,6 +197,7 @@ // typedef enum _BL_PATH_TYPE { + InternalPath = 3, EfiPath = 4 } BL_PATH_TYPE;
@@ -266,6 +295,7 @@ /* CALLBACKS *****************************************************************/
struct _BL_FILE_ENTRY; +struct _BL_FILE_INFORMATION; typedef NTSTATUS (*PBL_FILE_OPEN) ( @@ -284,7 +314,10 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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,7 +1290,43 @@ _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( @@ -1263,6 +1351,11 @@ PGUID BlGetApplicationIdentifier ( VOID + ); + +PWCHAR +BlResourceFindMessage ( + _In_ ULONG MsgId );
/* TABLE ROUTINES ************************************************************/ @@ -1351,6 +1444,14 @@ _In_ PBL_BCD_OPTION List, _In_ ULONG Type, _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 **********************************************************/ @@ -1424,6 +1525,20 @@ /* 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, _In_ BL_MEMORY_TYPE MemoryType, @@ -1450,6 +1565,12 @@ _In_ PHYSICAL_ADDRESS PhysicalAddress );
+NTSTATUS +BlMmUnmapVirtualAddressEx ( + _In_ PVOID VirtualAddress, + _In_ ULONGLONG Size + ); + /* BLOCK ALLOCATOR ROUTINES **************************************************/
NTSTATUS @@ -1526,10 +1647,26 @@ );
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 ConsoleTextResolutionList[]; extern ULONG ConsoleGraphicalResolutionListSize; extern PVOID DspRemoteInputConsole; +extern WCHAR BlScratchBuffer[8192]; #endif
Modified: trunk/reactos/boot/environ/lib/io/file.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/io/file.c?... ============================================================================== --- trunk/reactos/boot/environ/lib/io/file.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/io/file.c [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -31,7 +31,6 @@ NULL };
- extern ULONG DmTableEntries; extern PVOID* DmDeviceTable;
@@ -120,7 +119,9 @@
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 @@
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 @@ 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)) - { - Status = STATUS_UNSUCCESSFUL; - } - else - { - Status = FileTableDestroyEntry(FileEntry, FileEntry->FileId); - } - - return Status; + + /* 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)) + { + return STATUS_UNSUCCESSFUL; + } + + /* Purge the entry othwrwise */ + return FileTableDestroyEntry(FileEntry, FileEntry->FileId); }
NTSTATUS @@ -219,28 +223,34 @@ { 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)) - { - return STATUS_INVALID_PARAMETER; - } - + /* 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 @@ _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 @@ 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) - { - goto FileOpenEnd; - } - + &DirectoryEntry); + if (NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Now get the the file name itself */ FileNameCopy = FileIoCopyFileName(FileName); if (!FileNameCopy) { Status = STATUS_NO_MEMORY; - goto FileOpenEnd; - } - - Status = ParentDirectoryEntry->Callbacks.Open(ParentDirectoryEntry, - FileNameCopy, - Flags, - &FileEntry); + goto Quickie; + } + + /* 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) - { - FileEntry->Flags |= 2u; - } - - if (Flags & 2) - { - FileEntry->Flags |= 4u; - } - + /* Convert open flags into entry flags */ + if (Flags & BL_FILE_READ_ACCESS) + { + FileEntry->Flags |= BL_FILE_ENTRY_READ_ACCESS; + } + if (Flags & BL_FILE_WRITE_ACCESS) + { + FileEntry->Flags |= BL_FILE_ENTRY_WRITE_ACCESS; + } + + /* Save the file into the file table */ Status = BlTblSetEntry(&FileTable, &FileEntries, (PVOID)FileEntry, @@ -386,48 +417,62 @@ 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; + FileEntry->FileId = FileId;
EfiPrintf(L"File %s opened with ID: %lx\r\n", FileEntry->FilePath, FileId); - FileEntry->FileId = 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) - { - FileEntry->Flags |= 0x10; - } - - if (ReturnFileEntry) - { - *ReturnFileEntry = FileEntry; - } - -FileOpenEnd: - if (ParentDirectoryEntry) - { - BlFileClose(ParentDirectoryEntry->FileId); - } + /* Set the file as opened */ + FileEntry->Flags |= BL_FILE_ENTRY_OPENED; + + /* Not sure what this flag does */ + if (Flags & BL_UNKNOWN_ACCESS) + { + FileEntry->Flags |= BL_FILE_ENTRY_UNKNOWN_ACCESS; + } + + /* If the caller wanted the entry back, return it */ + if (NewFileEntry) + { + *NewFileEntry = FileEntry; + } + +Quickie: + /* Close the parent */ + if (DirectoryEntry) + { + 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 @@ 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 @@ 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 @@ return STATUS_INVALID_PARAMETER; }
+ /* Open a file on this device, creating one if needed */ Status = FileIoOpen(DeviceId, FileName, Flags, @@ -475,10 +524,339 @@ &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; }
Modified: trunk/reactos/boot/environ/lib/misc/bcd.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/misc/bcd.c... ============================================================================== --- trunk/reactos/boot/environ/lib/misc/bcd.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/misc/bcd.c [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -59,6 +59,86 @@
/* We found the option, return it */ 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 @@ -162,6 +242,151 @@ }
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, _In_ ULONG Type, @@ -231,80 +456,342 @@ 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 - ) -{ - 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; +#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 + ) +{ + UNREFERENCED_PARAMETER(Paged); + UNREFERENCED_PARAMETER(Tag); + + /* Call the heap allocator */ + return BlMmAllocateHeap(Size); +} + +VOID +NTAPI +CmpFree ( + _In_ PVOID Ptr, + _In_ ULONG Quota + ) +{ + UNREFERENCED_PARAMETER(Quota); + + /* Call the heap allocator */ + BlMmFreeHeap(Ptr); +} + +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)) + { + /* 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); - } - - /* 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; -} + /* Failure, drop a reference on the hive and close the key */ + BiDereferenceHive(HiveHandle); + BiCloseKey(HiveHandle); + } + + /* 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; +} +
Added: trunk/reactos/boot/environ/lib/misc/debug.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/misc/debug... ============================================================================== --- trunk/reactos/boot/environ/lib/misc/debug.c (added) +++ trunk/reactos/boot/environ/lib/misc/debug.c [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -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(); + } +} +
Propchange: trunk/reactos/boot/environ/lib/misc/debug.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/boot/environ/lib/misc/image.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/misc/image... ============================================================================== --- trunk/reactos/boot/environ/lib/misc/image.c (added) +++ trunk/reactos/boot/environ/lib/misc/image.c [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -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; +} +
Propchange: trunk/reactos/boot/environ/lib/misc/image.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/boot/environ/lib/misc/util.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/misc/util.... ============================================================================== --- trunk/reactos/boot/environ/lib/misc/util.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/misc/util.c [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -28,7 +28,46 @@ 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
Modified: trunk/reactos/boot/environ/lib/mm/mm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/mm/mm.c?re... ============================================================================== --- trunk/reactos/boot/environ/lib/mm/mm.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/mm/mm.c [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -205,6 +205,72 @@ }
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, _In_ BL_TRANSLATION_TYPE TranslationType,
Modified: trunk/reactos/boot/environ/lib/mm/pagealloc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/mm/pageall... ============================================================================== --- trunk/reactos/boot/environ/lib/mm/pagealloc.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/mm/pagealloc.c [iso-8859-1] Sun Oct 4 21:07:12 2015 @@ -568,4 +568,33 @@ 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); +}