mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 00:03:22 +00:00
[BOOTMGFW]
- 1.5KLOC code dump of current device block I/O handling. Totally untested and broken, just a checkpoint for now. - Implement most of Hash Table Utility Functions. - Implement parts of Block Allocator. - Finish Implementation of Generic Table Utility Functions. - Fix some EFI device emulation code. - Temporarily disable freeing from heap while I figure out what's corrupting it. svn path=/trunk/; revision=69142
This commit is contained in:
parent
ba76268519
commit
85de1f5f6a
14 changed files with 2825 additions and 49 deletions
|
@ -22,43 +22,42 @@ DEFINE_GUID(GUID_WINDOWS_BOOTMGR,
|
|||
ULONGLONG ApplicationStartTime;
|
||||
ULONGLONG PostTime;
|
||||
GUID BmApplicationIdentifier;
|
||||
PWCHAR BootDirectory;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
PGUID
|
||||
BlGetApplicationIdentifier (
|
||||
NTSTATUS
|
||||
BmFwInitializeBootDirectoryPath (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PWCHAR BootDirectory;
|
||||
|
||||
NTSTATUS
|
||||
BmFwInitializeBootDirectoryPath()
|
||||
{
|
||||
#if 0
|
||||
PWCHAR FinalPath;
|
||||
NTSTATUS Status;
|
||||
PWCHAR BcdDirectory;
|
||||
UNICODE_STRING BcdPath;
|
||||
ULONG FinalSize, FileHandle, DeviceHandle;
|
||||
|
||||
BcdPath.MaximumLength = 0;
|
||||
BcdPath.Buffer = NULL;
|
||||
// UNICODE_STRING BcdPath;
|
||||
//ULONG FinalSize;
|
||||
ULONG FileHandle, DeviceHandle;
|
||||
|
||||
/* Initialize everything for failure */
|
||||
// BcdPath.MaximumLength = 0;
|
||||
// BcdPath.Buffer = NULL;
|
||||
BcdDirectory = NULL;
|
||||
FinalPath = NULL;
|
||||
|
||||
FileHandle = -1;
|
||||
DeviceHandle = -1;
|
||||
|
||||
/* Try to open the boot device */
|
||||
Status = BlpDeviceOpen(BlpBootDevice, 1u, 0, &DeviceHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* For now, do nothing */
|
||||
EfiPrintf(L"Successfully opened boot device: %lx\r\n", DeviceHandle);
|
||||
EfiStall(2000000);
|
||||
|
||||
#if 0
|
||||
Status = BmpFwGetApplicationDirectoryPath(&BcdPath);
|
||||
BcdDirectory = BcdPath.Buffer;
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -91,8 +90,10 @@ BmFwInitializeBootDirectoryPath()
|
|||
}
|
||||
|
||||
BootDirectory = L"\\EFI\\Microsoft\\Boot";
|
||||
#endif
|
||||
|
||||
Quickie:
|
||||
/* Free all the allocations we made */
|
||||
if (BcdDirectory)
|
||||
{
|
||||
Status = BlMmFreeHeap(BcdDirectory);
|
||||
|
@ -101,18 +102,21 @@ Quickie:
|
|||
{
|
||||
Status = BlMmFreeHeap(FinalPath);
|
||||
}
|
||||
|
||||
/* Close the BCD file */
|
||||
if (FileHandle != -1)
|
||||
{
|
||||
Status = BlFileClose(FileHandle);
|
||||
//Status = BlFileClose(FileHandle);
|
||||
}
|
||||
|
||||
/* Close the boot device */
|
||||
if (DeviceHandle != -1)
|
||||
{
|
||||
Status = BlDeviceClose(DeviceHandle);
|
||||
}
|
||||
|
||||
/* Return back to the caller */
|
||||
return Status;
|
||||
#else
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -172,6 +176,9 @@ BmMain (
|
|||
goto Quickie;
|
||||
}
|
||||
|
||||
EfiPrintf(L"We are A-OK!\n");
|
||||
EfiStall(10000000);
|
||||
|
||||
/* Get the application identifier */
|
||||
AppIdentifier = BlGetApplicationIdentifier();
|
||||
if (!AppIdentifier)
|
||||
|
|
|
@ -253,7 +253,10 @@ EfiInitpConvertEfiFilePath (
|
|||
FilePath->PathName,
|
||||
StringLength,
|
||||
&BytesAppended);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Increase the size of the data, consume buffer space */
|
||||
DataSize += BytesAppended;
|
||||
|
@ -345,7 +348,7 @@ EfiInitpGetDeviceNode (
|
|||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
EfiInitTranslateDevicePath(
|
||||
EfiInitTranslateDevicePath (
|
||||
_In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||
_In_ PBL_DEVICE_DESCRIPTOR DeviceEntry
|
||||
)
|
||||
|
@ -418,7 +421,7 @@ EfiInitTranslateDevicePath(
|
|||
}
|
||||
|
||||
/* Other types should come in as MEDIA_DEVICE_PATH -- Windows assumes this is a floppy */
|
||||
DeviceEntry->DeviceType = LocalDevice;
|
||||
DeviceEntry->DeviceType = DiskDevice;
|
||||
DeviceEntry->Local.Type = FloppyDevice;
|
||||
DeviceEntry->Local.FloppyDisk.DriveNumber = 0;
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -434,7 +437,7 @@ EfiInitTranslateDevicePath(
|
|||
if (DiskPath->SignatureType == SIGNATURE_TYPE_MBR)
|
||||
{
|
||||
/* Set that this is a local partition */
|
||||
DeviceEntry->DeviceType = PartitionDevice;
|
||||
DeviceEntry->DeviceType = LegacyPartitionDevice;
|
||||
DeviceEntry->Partition.Disk.Type = LocalDevice;
|
||||
|
||||
DeviceEntry->Partition.Disk.HardDisk.PartitionType = MbrPartition;
|
||||
|
@ -448,7 +451,7 @@ EfiInitTranslateDevicePath(
|
|||
if (DiskPath->SignatureType == SIGNATURE_TYPE_GUID)
|
||||
{
|
||||
/* Set that this is a local disk */
|
||||
DeviceEntry->DeviceType = HardDiskDevice;
|
||||
DeviceEntry->DeviceType = PartitionDevice;
|
||||
DeviceEntry->Partition.Disk.Type = LocalDevice;
|
||||
|
||||
/* Set GPT partition ID */
|
||||
|
@ -463,15 +466,16 @@ EfiInitTranslateDevicePath(
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Othertwise, raw boot is not supported */
|
||||
DeviceEntry->DeviceType = HardDiskDevice;
|
||||
/* Otherwise, raw boot is not supported */
|
||||
DeviceEntry->DeviceType = PartitionDevice;
|
||||
DeviceEntry->Partition.Disk.Type = LocalDevice;
|
||||
DeviceEntry->Partition.Disk.HardDisk.PartitionType = RawPartition;
|
||||
DeviceEntry->Partition.Disk.HardDisk.Raw.DiskNumber = 0;
|
||||
}
|
||||
else if (DeviceNode->SubType == MEDIA_CDROM_DP)
|
||||
{
|
||||
/* Set the right type for a CDROM */
|
||||
DeviceEntry->DeviceType = LocalDevice;
|
||||
DeviceEntry->DeviceType = DiskDevice;
|
||||
DeviceEntry->Local.Type = CdRomDevice;
|
||||
|
||||
/* Set the drive number to zero */
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <LoadedImage.h>
|
||||
#include <GraphicsOutput.h>
|
||||
#include <UgaDraw.h>
|
||||
#include <BlockIo.h>
|
||||
|
||||
/* DEFINES *******************************************************************/
|
||||
|
||||
|
@ -76,6 +77,8 @@
|
|||
#define BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG 0x01
|
||||
#define BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG 0x02
|
||||
|
||||
#define BL_HT_VALUE_IS_INLINE 0x01
|
||||
|
||||
#define BL_FS_REGISTER_AT_HEAD_FLAG 1
|
||||
|
||||
#define BL_MEMORY_CLASS_SHIFT 28
|
||||
|
@ -127,10 +130,13 @@ typedef enum _BL_ARCH_MODE
|
|||
//
|
||||
typedef enum _BL_DEVICE_TYPE
|
||||
{
|
||||
LocalDevice = 0,
|
||||
PartitionDevice = 2,
|
||||
DiskDevice = 0,
|
||||
LegacyPartitionDevice = 2,
|
||||
SerialDevice = 3,
|
||||
UdpDevice = 4,
|
||||
HardDiskDevice = 6
|
||||
BootDevice = 5,
|
||||
PartitionDevice = 6,
|
||||
LocateDevice = 8,
|
||||
} BL_DEVICE_TYPE;
|
||||
|
||||
//
|
||||
|
@ -138,9 +144,12 @@ typedef enum _BL_DEVICE_TYPE
|
|||
//
|
||||
typedef enum _BL_LOCAL_DEVICE_TYPE
|
||||
{
|
||||
LocalDevice = 0,
|
||||
FloppyDevice = 1,
|
||||
CdRomDevice = 2,
|
||||
RamDiskDevice = 3,
|
||||
FileDevice = 5,
|
||||
VirtualDiskDevice = 6
|
||||
} BL_LOCAL_DEVICE_TYPE;
|
||||
|
||||
//
|
||||
|
@ -180,11 +189,13 @@ typedef enum _BL_MEMORY_TYPE
|
|||
// Loader Memory
|
||||
//
|
||||
BlLoaderMemory = 0xD0000002,
|
||||
BlLoaderDeviceMemory = 0xD0000004,
|
||||
BlLoaderHeap = 0xD0000005,
|
||||
BlLoaderPageDirectory = 0xD0000006,
|
||||
BlLoaderReferencePage = 0xD0000007,
|
||||
BlLoaderRamDisk = 0xD0000008,
|
||||
BlLoaderData = 0xD000000A,
|
||||
BlLoaderBlockMemory = 0xD000000C,
|
||||
BlLoaderSelfMap = 0xD000000F,
|
||||
|
||||
//
|
||||
|
@ -341,6 +352,50 @@ NTSTATUS
|
|||
_In_ ULONG Attribute
|
||||
);
|
||||
|
||||
typedef
|
||||
BOOLEAN
|
||||
(*PBL_TBL_LOOKUP_ROUTINE) (
|
||||
_In_ PVOID Entry,
|
||||
_In_ PVOID Argument1,
|
||||
_In_ PVOID Argument2,
|
||||
_In_ PVOID Argument3,
|
||||
_In_ PVOID Argument4
|
||||
);
|
||||
|
||||
typedef
|
||||
NTSTATUS
|
||||
(*PBL_TBL_MAP_ROUTINE) (
|
||||
_In_ PVOID Entry,
|
||||
_In_ ULONG EntryIndex
|
||||
);
|
||||
|
||||
typedef
|
||||
NTSTATUS
|
||||
(*PBL_TBL_SET_ROUTINE) (
|
||||
_In_ PVOID Entry
|
||||
);
|
||||
|
||||
typedef
|
||||
NTSTATUS
|
||||
(*PBL_IO_DESTROY_ROUTINE) (
|
||||
VOID
|
||||
);
|
||||
|
||||
struct _BL_HASH_ENTRY;
|
||||
typedef
|
||||
BOOLEAN
|
||||
(*PBL_HASH_TABLE_COMPARE_FUNCTION) (
|
||||
_In_ struct _BL_HASH_ENTRY* Entry1,
|
||||
_In_ struct _BL_HASH_ENTRY* Entry2
|
||||
);
|
||||
|
||||
typedef
|
||||
ULONG
|
||||
(*PBL_HASH_TABLE_HASH_FUNCTION) (
|
||||
_In_ struct _BL_HASH_ENTRY* Entry,
|
||||
_In_ ULONG TableSize
|
||||
);
|
||||
|
||||
/* DATA STRUCTURES ***********************************************************/
|
||||
|
||||
typedef struct _BL_LIBRARY_PARAMETERS
|
||||
|
@ -568,11 +623,6 @@ typedef struct _BL_FILE_ENTRY
|
|||
PBL_FILE_DESTROY_CALLBACK DestroyCallback;
|
||||
} BL_FILE_ENTRY, *PBL_FILE_ENTRY;
|
||||
|
||||
typedef struct _BL_DEVICE_ENTRY
|
||||
{
|
||||
ULONG ReferenceCount;
|
||||
} BL_DEVICE_ENTRY, *PBL_DEVICE_ENTRY;
|
||||
|
||||
typedef struct _BL_FILE_SYSTEM_ENTRY
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
|
@ -665,6 +715,67 @@ typedef struct _BL_REMOTE_CONSOLE
|
|||
BL_TEXT_CONSOLE TextConsole;
|
||||
} BL_REMOTE_CONSOLE, *PBL_REMOTE_CONSOLE;
|
||||
|
||||
typedef struct _BL_HASH_TABLE
|
||||
{
|
||||
PLIST_ENTRY HashLinks;
|
||||
ULONG Size;
|
||||
PBL_HASH_TABLE_COMPARE_FUNCTION CompareFunction;
|
||||
PBL_HASH_TABLE_HASH_FUNCTION HashFunction;
|
||||
} BL_HASH_TABLE, *PBL_HASH_TABLE;
|
||||
|
||||
typedef struct _BL_HASH_ENTRY
|
||||
{
|
||||
ULONG Size;
|
||||
ULONG Flags;
|
||||
PVOID Value;
|
||||
} BL_HASH_ENTRY, *PBL_HASH_ENTRY;
|
||||
|
||||
typedef struct _BL_HASH_VALUE
|
||||
{
|
||||
ULONG DataSize;
|
||||
PVOID Data;
|
||||
} BL_HASH_VALUE, *PBL_HASH_VALUE;
|
||||
|
||||
typedef struct _BL_HASH_NODE
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
BL_HASH_ENTRY Entry;
|
||||
BL_HASH_VALUE Value;
|
||||
} BL_HASH_NODE, *PBL_HASH_NODE;
|
||||
|
||||
typedef struct _BL_BLOCK_DEVICE
|
||||
{
|
||||
BL_LOCAL_DEVICE_TYPE Type;
|
||||
ULONG DeviceFlags;
|
||||
ULONG Unknown;
|
||||
BL_PARTITION_TYPE PartitionType;
|
||||
ULONG BlockSize;
|
||||
ULONG Alignment;
|
||||
struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG Signature;
|
||||
} Mbr;
|
||||
struct
|
||||
{
|
||||
GUID Signature;
|
||||
} Gpt;
|
||||
};
|
||||
} Disk;
|
||||
ULONGLONG LastBlock;
|
||||
EFI_BLOCK_IO* Protocol;
|
||||
EFI_HANDLE Handle;
|
||||
} BL_BLOCK_DEVICE, *PBL_BLOCK_DEVICE;
|
||||
|
||||
typedef struct _BL_PROTOCOL_HANDLE
|
||||
{
|
||||
EFI_HANDLE Handle;
|
||||
PVOID Interface;
|
||||
} BL_PROTOCOL_HANDLE, *PBL_PROTOCOL_HANDLE;
|
||||
|
||||
/* INLINE ROUTINES ***********************************************************/
|
||||
|
||||
FORCEINLINE
|
||||
|
@ -893,6 +1004,17 @@ EfiResetSystem (
|
|||
_In_ EFI_RESET_TYPE ResetType
|
||||
);
|
||||
|
||||
EFI_DEVICE_PATH*
|
||||
EfiGetLeafNode (
|
||||
_In_ EFI_DEVICE_PATH *DevicePath
|
||||
);
|
||||
|
||||
EFI_DEVICE_PATH *
|
||||
EfiIsDevicePathParent (
|
||||
_In_ EFI_DEVICE_PATH *DevicePath1,
|
||||
_In_ EFI_DEVICE_PATH *DevicePath2
|
||||
);
|
||||
|
||||
/* PLATFORM TIMER ROUTINES ***************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
@ -922,6 +1044,71 @@ BlFwReboot (
|
|||
VOID
|
||||
);
|
||||
|
||||
PGUID
|
||||
BlGetApplicationIdentifier (
|
||||
VOID
|
||||
);
|
||||
|
||||
/* TABLE ROUTINES ************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
BlTblMap (
|
||||
_In_ PVOID *Table,
|
||||
_In_ ULONG Count,
|
||||
_In_ PBL_TBL_MAP_ROUTINE MapCallback
|
||||
);
|
||||
|
||||
PVOID
|
||||
BlTblFindEntry (
|
||||
_In_ PVOID *Table,
|
||||
_In_ ULONG Count,
|
||||
_Out_ PULONG EntryIndex,
|
||||
_In_ PBL_TBL_LOOKUP_ROUTINE Callback,
|
||||
_In_ PVOID Argument1,
|
||||
_In_ PVOID Argument2,
|
||||
_In_ PVOID Argument3,
|
||||
_In_ PVOID Argument4
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
BlTblSetEntry (
|
||||
_Inout_ PVOID** Table,
|
||||
_Inout_ PULONG Count,
|
||||
_In_ PVOID Entry,
|
||||
_Out_ PULONG EntryIndex,
|
||||
_In_ PBL_TBL_SET_ROUTINE Callback
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
TblDoNotPurgeEntry (
|
||||
_In_ PVOID Entry
|
||||
);
|
||||
|
||||
/* HASH TABLE ROUTINES *******************************************************/
|
||||
|
||||
NTSTATUS
|
||||
BlHtStore (
|
||||
_In_ ULONG TableId,
|
||||
_In_ PBL_HASH_ENTRY Entry,
|
||||
_In_ PVOID Data,
|
||||
_In_ ULONG DataSize
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
BlHtLookup (
|
||||
_In_ ULONG TableId,
|
||||
_In_ PBL_HASH_ENTRY Entry,
|
||||
_Out_ PBL_HASH_VALUE *Value
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
BlHtCreate (
|
||||
_In_ ULONG Size,
|
||||
_In_ PBL_HASH_TABLE_HASH_FUNCTION HashFunction,
|
||||
_In_ PBL_HASH_TABLE_COMPARE_FUNCTION CompareFunction,
|
||||
_Out_ PULONG Id
|
||||
);
|
||||
|
||||
/* BCD ROUTINES **************************************************************/
|
||||
|
||||
ULONG
|
||||
|
@ -1001,7 +1188,7 @@ MmMdFreeDescriptor (
|
|||
|
||||
NTSTATUS
|
||||
MmPapAllocatePagesInRange (
|
||||
_Inout_ PULONG PhysicalAddress,
|
||||
_Inout_ PVOID* PhysicalAddress,
|
||||
_In_ BL_MEMORY_TYPE MemoryType,
|
||||
_In_ ULONGLONG Pages,
|
||||
_In_ ULONG Attributes,
|
||||
|
@ -1026,6 +1213,13 @@ BlMmMapPhysicalAddressEx (
|
|||
_In_ PHYSICAL_ADDRESS PhysicalAddress
|
||||
);
|
||||
|
||||
/* BLOCK ALLOCATOR ROUTINES **************************************************/
|
||||
|
||||
NTSTATUS
|
||||
BlpMmCreateBlockAllocator (
|
||||
VOID
|
||||
);
|
||||
|
||||
/* HEAP ALLOCATOR ROUTINES ***************************************************/
|
||||
|
||||
PVOID
|
||||
|
@ -1046,7 +1240,27 @@ BlDisplayGetTextCellResolution (
|
|||
_Out_ PULONG TextHeight
|
||||
);
|
||||
|
||||
/* TExT CONSOLE ROUTINES *****************************************************/
|
||||
/* I/O ROUTINES **************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
BlpIoRegisterDestroyRoutine (
|
||||
_In_ PBL_IO_DESTROY_ROUTINE DestroyRoutine
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
BlDeviceClose (
|
||||
_In_ ULONG DeviceId
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
BlpDeviceOpen (
|
||||
_In_ PBL_DEVICE_DESCRIPTOR Device,
|
||||
_In_ ULONG Flags,
|
||||
_In_ ULONG Unknown,
|
||||
_Out_ PULONG DeviceId
|
||||
);
|
||||
|
||||
/* TEXT CONSOLE ROUTINES *****************************************************/
|
||||
|
||||
NTSTATUS
|
||||
ConsoleTextLocalDestruct (
|
||||
|
@ -1197,6 +1411,7 @@ extern EFI_GUID EfiGraphicsOutputProtocol;
|
|||
extern EFI_GUID EfiUgaDrawProtocol;
|
||||
extern EFI_GUID EfiLoadedImageProtocol;
|
||||
extern EFI_GUID EfiDevicePathProtocol;
|
||||
extern EFI_GUID EfiBlockIoProtocol;
|
||||
extern EFI_GUID EfiSimpleTextInputExProtocol;
|
||||
extern ULONG ConsoleGraphicalResolutionListFlags;
|
||||
extern BL_DISPLAY_MODE ConsoleGraphicalResolutionList[];
|
||||
|
|
241
reactos/boot/environ/include/efi/BlockIo.h
Normal file
241
reactos/boot/environ/include/efi/BlockIo.h
Normal file
|
@ -0,0 +1,241 @@
|
|||
/** @file
|
||||
Block IO protocol as defined in the UEFI 2.0 specification.
|
||||
|
||||
The Block IO protocol is used to abstract block devices like hard drives,
|
||||
DVD-ROMs and floppy drives.
|
||||
|
||||
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __BLOCK_IO_H__
|
||||
#define __BLOCK_IO_H__
|
||||
|
||||
#define EFI_BLOCK_IO_PROTOCOL_GUID \
|
||||
{ \
|
||||
0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
|
||||
}
|
||||
|
||||
typedef struct _EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL;
|
||||
|
||||
///
|
||||
/// Protocol GUID name defined in EFI1.1.
|
||||
///
|
||||
#define BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL_GUID
|
||||
|
||||
///
|
||||
/// Protocol defined in EFI1.1.
|
||||
///
|
||||
typedef EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO;
|
||||
|
||||
/**
|
||||
Reset the Block Device.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
|
||||
not be reset.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_BLOCK_RESET)(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
/**
|
||||
Read BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId Id of the media, changes every time the media is replaced.
|
||||
@param Lba The starting Logical Block Address to read from
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer A pointer to the destination buffer for the data. The caller is
|
||||
responsible for either having implicit or explicit ownership of the buffer.
|
||||
|
||||
@retval EFI_SUCCESS The data was read correctly from the device.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing the read.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_BLOCK_READ)(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Write BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId The media ID that the write request is for.
|
||||
@param Lba The starting logical block address to be written. The caller is
|
||||
responsible for writing to only legitimate locations.
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer A pointer to the source buffer for the data.
|
||||
|
||||
@retval EFI_SUCCESS The data was written correctly to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be written to.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing the write.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_BLOCK_WRITE)(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Flush the Block Device.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
|
||||
@retval EFI_SUCCESS All outstanding data was written to the device
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while writting back the data
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_BLOCK_FLUSH)(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
);
|
||||
|
||||
/**
|
||||
Block IO read only mode data and updated only via members of BlockIO
|
||||
**/
|
||||
typedef struct {
|
||||
///
|
||||
/// The curent media Id. If the media changes, this value is changed.
|
||||
///
|
||||
UINT32 MediaId;
|
||||
|
||||
///
|
||||
/// TRUE if the media is removable; otherwise, FALSE.
|
||||
///
|
||||
BOOLEAN RemovableMedia;
|
||||
|
||||
///
|
||||
/// TRUE if there is a media currently present in the device;
|
||||
/// othersise, FALSE. THis field shows the media present status
|
||||
/// as of the most recent ReadBlocks() or WriteBlocks() call.
|
||||
///
|
||||
BOOLEAN MediaPresent;
|
||||
|
||||
///
|
||||
/// TRUE if LBA 0 is the first block of a partition; otherwise
|
||||
/// FALSE. For media with only one partition this would be TRUE.
|
||||
///
|
||||
BOOLEAN LogicalPartition;
|
||||
|
||||
///
|
||||
/// TRUE if the media is marked read-only otherwise, FALSE.
|
||||
/// This field shows the read-only status as of the most recent WriteBlocks () call.
|
||||
///
|
||||
BOOLEAN ReadOnly;
|
||||
|
||||
///
|
||||
/// TRUE if the WriteBlock () function caches write data.
|
||||
///
|
||||
BOOLEAN WriteCaching;
|
||||
|
||||
///
|
||||
/// The intrinsic block size of the device. If the media changes, then
|
||||
/// this field is updated.
|
||||
///
|
||||
UINT32 BlockSize;
|
||||
|
||||
///
|
||||
/// Supplies the alignment requirement for any buffer to read or write block(s).
|
||||
///
|
||||
UINT32 IoAlign;
|
||||
|
||||
///
|
||||
/// The last logical block address on the device.
|
||||
/// If the media changes, then this field is updated.
|
||||
///
|
||||
EFI_LBA LastBlock;
|
||||
|
||||
///
|
||||
/// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to
|
||||
/// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the first LBA is aligned to
|
||||
/// a physical block boundary.
|
||||
///
|
||||
EFI_LBA LowestAlignedLba;
|
||||
|
||||
///
|
||||
/// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to
|
||||
/// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the number of logical blocks
|
||||
/// per physical block.
|
||||
///
|
||||
UINT32 LogicalBlocksPerPhysicalBlock;
|
||||
|
||||
///
|
||||
/// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to
|
||||
/// EFI_BLOCK_IO_PROTOCOL_REVISION3. Returns the optimal transfer length
|
||||
/// granularity as a number of logical blocks.
|
||||
///
|
||||
UINT32 OptimalTransferLengthGranularity;
|
||||
} EFI_BLOCK_IO_MEDIA;
|
||||
|
||||
#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000
|
||||
#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001
|
||||
#define EFI_BLOCK_IO_PROTOCOL_REVISION3 0x00020031
|
||||
|
||||
///
|
||||
/// Revision defined in EFI1.1.
|
||||
///
|
||||
#define EFI_BLOCK_IO_INTERFACE_REVISION EFI_BLOCK_IO_PROTOCOL_REVISION
|
||||
|
||||
///
|
||||
/// This protocol provides control over block devices.
|
||||
///
|
||||
struct _EFI_BLOCK_IO_PROTOCOL {
|
||||
///
|
||||
/// The revision to which the block IO interface adheres. All future
|
||||
/// revisions must be backwards compatible. If a future version is not
|
||||
/// back wards compatible, it is not the same GUID.
|
||||
///
|
||||
UINT64 Revision;
|
||||
///
|
||||
/// Pointer to the EFI_BLOCK_IO_MEDIA data for this device.
|
||||
///
|
||||
EFI_BLOCK_IO_MEDIA *Media;
|
||||
|
||||
EFI_BLOCK_RESET Reset;
|
||||
EFI_BLOCK_READ ReadBlocks;
|
||||
EFI_BLOCK_WRITE WriteBlocks;
|
||||
EFI_BLOCK_FLUSH FlushBlocks;
|
||||
|
||||
};
|
||||
|
||||
extern EFI_GUID gEfiBlockIoProtocolGuid;
|
||||
|
||||
#endif
|
|
@ -393,3 +393,13 @@ BlDestroyLibrary (
|
|||
EfiPrintf(L"Destroy not yet implemented\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
PGUID
|
||||
BlGetApplicationIdentifier (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
/* Return the GUID, if one was present */
|
||||
return (BlpApplicationEntry.Flags & BL_APPLICATION_ENTRY_FLAG_NO_GUID) ?
|
||||
NULL : &BlpApplicationEntry.Guid;
|
||||
}
|
||||
|
|
|
@ -29,11 +29,84 @@ EFI_GUID EfiUgaDrawProtocol = EFI_UGA_DRAW_PROTOCOL_GUID;
|
|||
EFI_GUID EfiLoadedImageProtocol = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
||||
EFI_GUID EfiDevicePathProtocol = EFI_DEVICE_PATH_PROTOCOL_GUID;
|
||||
EFI_GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
|
||||
EFI_GUID EfiBlockIoProtocol = EFI_BLOCK_IO_PROTOCOL_GUID;
|
||||
|
||||
WCHAR BlScratchBuffer[8192];
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
EFI_DEVICE_PATH *
|
||||
EfiIsDevicePathParent (
|
||||
_In_ EFI_DEVICE_PATH *DevicePath1,
|
||||
_In_ EFI_DEVICE_PATH *DevicePath2
|
||||
)
|
||||
{
|
||||
USHORT Length1, Length2;
|
||||
|
||||
/* Loop each element of the device path */
|
||||
while (!IsDevicePathEndType(DevicePath1) && !IsDevicePathEndType(DevicePath2))
|
||||
{
|
||||
/* Check if the element has a different length */
|
||||
Length1 = DevicePathNodeLength(DevicePath1);
|
||||
Length2 = DevicePathNodeLength(DevicePath2);
|
||||
if (Length1 != Length2)
|
||||
{
|
||||
/* Then they're not related */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if the rest of the element data matches */
|
||||
if (RtlCompareMemory(DevicePath1, DevicePath2, Length1) != Length1)
|
||||
{
|
||||
/* Nope, not related */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Move to the next element */
|
||||
DevicePath1 = NextDevicePathNode(DevicePath1);
|
||||
DevicePath2 = NextDevicePathNode(DevicePath2);
|
||||
}
|
||||
|
||||
/* If the last element in path 1 is empty, then path 2 is the child (deeper) */
|
||||
if (!IsDevicePathEndType(DevicePath1))
|
||||
{
|
||||
return DevicePath2;
|
||||
}
|
||||
|
||||
/* If the last element in path 2 is empty, then path 1 is the child (deeper) */
|
||||
if (!IsDevicePathEndType(DevicePath2))
|
||||
{
|
||||
return DevicePath1;
|
||||
}
|
||||
|
||||
/* They're both the end, so they're identical, so there's no parent */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EFI_DEVICE_PATH*
|
||||
EfiGetLeafNode (
|
||||
_In_ EFI_DEVICE_PATH *DevicePath
|
||||
)
|
||||
{
|
||||
EFI_DEVICE_PATH *NextDevicePath;
|
||||
|
||||
/* Make sure we're not already at the end */
|
||||
if (!IsDevicePathEndType(DevicePath))
|
||||
{
|
||||
/* Grab the next node element, and keep going until the end */
|
||||
for (NextDevicePath = NextDevicePathNode(DevicePath);
|
||||
!IsDevicePathEndType(NextDevicePath);
|
||||
NextDevicePath = NextDevicePathNode(NextDevicePath))
|
||||
{
|
||||
/* Save the current node we're at */
|
||||
DevicePath = NextDevicePath;
|
||||
}
|
||||
}
|
||||
|
||||
/* This now contains the deepeest (leaf) node */
|
||||
return DevicePath;
|
||||
}
|
||||
|
||||
VOID
|
||||
EfiPrintf (
|
||||
_In_ PWCHAR Format,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -66,7 +66,7 @@ DsppInitialize (
|
|||
InitializeListHead(&BfiFontFileListHead);
|
||||
|
||||
/* Allocate the font rectangle */
|
||||
BfiGraphicsRectangle = BlMmAllocateHeap(0x5A);
|
||||
BfiGraphicsRectangle = BlMmAllocateHeap(90);
|
||||
if (!BfiGraphicsRectangle)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
|
|
|
@ -44,7 +44,7 @@ ConsoleCreateRemoteConsole (
|
|||
|
||||
/* Construct it */
|
||||
Status = ConsoleRemoteConstruct(RemoteConsole);
|
||||
if (Status < 0)
|
||||
if (!NT_SUCCESS(Status));
|
||||
{
|
||||
/* Failed to construct it, delete it */
|
||||
BlMmFreeHeap(RemoteConsole);
|
||||
|
|
|
@ -17,6 +17,20 @@ PVOID* IoMgrDestroyRoutineTable;
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
BlpIoRegisterDestroyRoutine (
|
||||
_In_ PBL_IO_DESTROY_ROUTINE DestroyRoutine
|
||||
)
|
||||
{
|
||||
ULONG Id;
|
||||
|
||||
return BlTblSetEntry(&IoMgrDestroyRoutineTable,
|
||||
&IoMgrRoutineEntries,
|
||||
DestroyRoutine,
|
||||
&Id,
|
||||
TblDoNotPurgeEntry);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlpIoInitialize (
|
||||
VOID
|
||||
|
|
|
@ -188,6 +188,455 @@ BlUtlInitialize (
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PVOID
|
||||
BlTblFindEntry (
|
||||
_In_ PVOID *Table,
|
||||
_In_ ULONG Count,
|
||||
_Out_ PULONG EntryIndex,
|
||||
_In_ PBL_TBL_LOOKUP_ROUTINE Callback,
|
||||
_In_ PVOID Argument1,
|
||||
_In_ PVOID Argument2,
|
||||
_In_ PVOID Argument3,
|
||||
_In_ PVOID Argument4
|
||||
)
|
||||
{
|
||||
PVOID Entry = NULL;
|
||||
ULONG Index = 0;
|
||||
BOOLEAN Result;
|
||||
|
||||
/* Check for invalid parameters */
|
||||
if (!(Table) || !(EntryIndex) || !(Count))
|
||||
{
|
||||
return Entry;
|
||||
}
|
||||
|
||||
/* Loop each entry in the table */
|
||||
while (Index < Count)
|
||||
{
|
||||
/* Check if this entry is filled out */
|
||||
if (Table[Index])
|
||||
{
|
||||
/* Call the comparison function */
|
||||
Result = Callback(Table[Index],
|
||||
Argument1,
|
||||
Argument2,
|
||||
Argument3,
|
||||
Argument4);
|
||||
if (Result)
|
||||
{
|
||||
/* Entry fouund return it */
|
||||
*EntryIndex = Index;
|
||||
Entry = Table[Index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the entry that was (or wasn't) found */
|
||||
return Entry;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlTblSetEntry (
|
||||
_Inout_ PVOID** Table,
|
||||
_Inout_ PULONG Count,
|
||||
_In_ PVOID Entry,
|
||||
_Out_ PULONG EntryIndex,
|
||||
_In_ PBL_TBL_SET_ROUTINE Callback
|
||||
)
|
||||
{
|
||||
ULONG NewCount;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
ULONG Index = 0;
|
||||
PVOID* NewTable;
|
||||
|
||||
/* Make sure all the parameters were specified */
|
||||
if (!(Table) || !(*Table) || !(Count) || !(Callback))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Read the current table */
|
||||
NewTable = *Table;
|
||||
NewCount = *Count;
|
||||
|
||||
/* Iterate over it */
|
||||
while (Index < NewCount)
|
||||
{
|
||||
/* Look for a free index */
|
||||
if (!NewTable[Index])
|
||||
{
|
||||
goto SetIndex;
|
||||
}
|
||||
|
||||
/* No free index yet, keep going */
|
||||
++Index;
|
||||
}
|
||||
|
||||
/* No free index was found, try to purge some entries */
|
||||
Index = 0;
|
||||
while (Index < NewCount)
|
||||
{
|
||||
/* Call each purge callback, trying to make space */
|
||||
Status = Callback(NewTable[Index]);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* We should have this slot available now */
|
||||
goto SetIndex;
|
||||
}
|
||||
|
||||
/* Keep trying to purge more */
|
||||
++Index;
|
||||
}
|
||||
|
||||
/* Double the table */
|
||||
NewTable = BlMmAllocateHeap(2 * sizeof(PVOID) * NewCount);
|
||||
if (!NewTable)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Clear the new table, and copy the old entries */
|
||||
RtlZeroMemory(&NewTable[NewCount], sizeof(PVOID) * NewCount);
|
||||
RtlCopyMemory(NewTable, *Table, sizeof(PVOID) * NewCount);
|
||||
|
||||
/* Free the old table */
|
||||
BlMmFreeHeap(*Table);
|
||||
|
||||
/* Return the new table and count */
|
||||
*Count = 2 * NewCount;
|
||||
*Table = NewTable;
|
||||
|
||||
SetIndex:
|
||||
/* Set the index and return */
|
||||
NewTable[Index] = Entry;
|
||||
*EntryIndex = Index;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlTblMap (
|
||||
_In_ PVOID *Table,
|
||||
_In_ ULONG Count,
|
||||
_In_ PBL_TBL_MAP_ROUTINE MapCallback
|
||||
)
|
||||
{
|
||||
NTSTATUS Status, LocalStatus;
|
||||
PVOID Entry;
|
||||
ULONG Index;
|
||||
|
||||
/* Bail out if there's no table */
|
||||
if (!Table)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Assume success and loop each index */
|
||||
Status = STATUS_SUCCESS;
|
||||
for (Index = 0; Index < Count; Index++)
|
||||
{
|
||||
/* See if an entry exists at this index */
|
||||
Entry = Table[Index];
|
||||
if (Entry)
|
||||
{
|
||||
/* Call the map routine for this entry */
|
||||
LocalStatus = MapCallback(Entry, Index);
|
||||
if (!NT_SUCCESS(LocalStatus))
|
||||
{
|
||||
/* Propagate failure only */
|
||||
Status = LocalStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return status to caller */
|
||||
return Status;
|
||||
}
|
||||
|
||||
ULONG HtTableSize;
|
||||
PBL_HASH_TABLE* HtTableArray;
|
||||
ULONG HtTableEntries;
|
||||
|
||||
ULONG
|
||||
DefaultHashFunction (
|
||||
_In_ PBL_HASH_ENTRY Entry,
|
||||
_In_ ULONG TableSize
|
||||
)
|
||||
{
|
||||
PUCHAR Value;
|
||||
ULONG KeyHash, i;
|
||||
|
||||
/* Check if the value is a pointer, or embedded inline */
|
||||
Value = (Entry->Flags & BL_HT_VALUE_IS_INLINE) ? Entry->Value : (PUCHAR)&Entry->Value;
|
||||
|
||||
/* Iterate over each byte, and sum it */
|
||||
for (i = 0, KeyHash = 0; i < Entry->Size; i++)
|
||||
{
|
||||
KeyHash += Value[i++];
|
||||
}
|
||||
|
||||
/* Modulo the number of buckets */
|
||||
return KeyHash % TableSize;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
HtpCompareKeys (
|
||||
_In_ PBL_HASH_ENTRY Entry1,
|
||||
_In_ PBL_HASH_ENTRY Entry2
|
||||
)
|
||||
{
|
||||
ULONG Flags;
|
||||
BOOLEAN ValueMatch;
|
||||
|
||||
/* Check if the flags or sizes are not matching */
|
||||
Flags = Entry1->Flags;
|
||||
if ((Entry1->Size != Entry2->Size) || (Flags != Entry2->Flags))
|
||||
{
|
||||
ValueMatch = FALSE;
|
||||
}
|
||||
else if (Flags & BL_HT_VALUE_IS_INLINE)
|
||||
{
|
||||
/* Check if this is an in-line value, compare it */
|
||||
ValueMatch = Entry1->Value == Entry2->Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a pointer value, compare it */
|
||||
ValueMatch = (RtlCompareMemory(Entry1->Value, Entry2->Value, Entry1->Size) ==
|
||||
Entry1->Size);
|
||||
}
|
||||
|
||||
/* Return if it matched */
|
||||
return ValueMatch;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
TblDoNotPurgeEntry (
|
||||
_In_ PVOID Entry
|
||||
)
|
||||
{
|
||||
/* Never purge this entry */
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlHtCreate (
|
||||
_In_ ULONG Size,
|
||||
_In_ PBL_HASH_TABLE_HASH_FUNCTION HashFunction,
|
||||
_In_ PBL_HASH_TABLE_COMPARE_FUNCTION CompareFunction,
|
||||
_Out_ PULONG Id
|
||||
)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PBL_HASH_TABLE HashTable;
|
||||
ULONG i;
|
||||
|
||||
/* Assume failure */
|
||||
HashTable = NULL;
|
||||
|
||||
/* Can't create a table with no ID */
|
||||
if (!Id)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Check if we don't already have a hash table table */
|
||||
if (!HtTableSize)
|
||||
{
|
||||
/* Allocate it and zero it out */
|
||||
HtTableSize = 4;
|
||||
HtTableArray = BlMmAllocateHeap(HtTableSize * sizeof(PVOID));
|
||||
if (!HtTableArray)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quickie;
|
||||
}
|
||||
RtlZeroMemory(HtTableArray, HtTableSize * sizeof(PVOID));
|
||||
HtTableEntries = 0;
|
||||
}
|
||||
|
||||
/* Allocate the hash table */
|
||||
HashTable = BlMmAllocateHeap(sizeof(*HashTable));
|
||||
if (!HashTable)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Fill it out */
|
||||
HashTable->HashFunction = HashFunction ? HashFunction : DefaultHashFunction;
|
||||
HashTable->CompareFunction = CompareFunction ? CompareFunction : HtpCompareKeys;
|
||||
HashTable->Size = Size ? Size : 13;
|
||||
|
||||
/* Allocate the hash links, one for each bucket */
|
||||
HashTable->HashLinks = BlMmAllocateHeap(sizeof(LIST_ENTRY) * HashTable->Size);
|
||||
if (!HashTable->HashLinks)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Initialize the hash links */
|
||||
for (i = 0; i < HashTable->Size; i++)
|
||||
{
|
||||
InitializeListHead(&HashTable->HashLinks[i]);
|
||||
}
|
||||
|
||||
/* Save us in the table of hash tables */
|
||||
Status = BlTblSetEntry((PVOID**)&HtTableArray,
|
||||
&Size,
|
||||
HashTable,
|
||||
Id,
|
||||
TblDoNotPurgeEntry);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* One more -- we're done */
|
||||
++HtTableEntries;
|
||||
return Status;
|
||||
}
|
||||
|
||||
Quickie:
|
||||
/* Check if we just allocated the table array now */
|
||||
if (!(HtTableEntries) && (HtTableArray))
|
||||
{
|
||||
/* Free it */
|
||||
BlMmFreeHeap(HtTableArray);
|
||||
HtTableArray = NULL;
|
||||
HtTableSize = 0;
|
||||
}
|
||||
|
||||
/* Check if we allocated a hash table*/
|
||||
if (HashTable)
|
||||
{
|
||||
/* With links? */
|
||||
if (HashTable->HashLinks)
|
||||
{
|
||||
/* Free them */
|
||||
BlMmFreeHeap(HashTable->HashLinks);
|
||||
}
|
||||
|
||||
/* Free the table*/
|
||||
BlMmFreeHeap(HashTable);
|
||||
}
|
||||
|
||||
/* We're done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlHtLookup (
|
||||
_In_ ULONG TableId,
|
||||
_In_ PBL_HASH_ENTRY Entry,
|
||||
_Out_opt_ PBL_HASH_VALUE *Value
|
||||
)
|
||||
{
|
||||
PBL_HASH_TABLE HashTable;
|
||||
ULONG HashValue;
|
||||
NTSTATUS Status;
|
||||
PLIST_ENTRY HashLinkHead, HashLink;
|
||||
PBL_HASH_NODE HashNode;
|
||||
|
||||
/* Check if the table ID is invalid, or we have no entry, or it's malformed */
|
||||
if ((HtTableSize <= TableId) ||
|
||||
!(Entry) ||
|
||||
((Entry->Flags & BL_HT_VALUE_IS_INLINE) && (Entry->Size != sizeof(ULONG))))
|
||||
{
|
||||
/* Fail */
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, get the hash table for this index */
|
||||
HashTable = HtTableArray[TableId];
|
||||
|
||||
/* Get the hash bucket */
|
||||
HashValue = HashTable->HashFunction(Entry, HashTable->Size);
|
||||
|
||||
/* Start iterating each entry in the bucket, assuming failure */
|
||||
Status = STATUS_NOT_FOUND;
|
||||
HashLinkHead = &HashTable->HashLinks[HashValue];
|
||||
HashLink = HashLinkHead->Flink;
|
||||
while (HashLink != HashLinkHead)
|
||||
{
|
||||
/* Get a node in this bucket, and compare the value */
|
||||
HashNode = CONTAINING_RECORD(HashLink, BL_HASH_NODE, ListEntry);
|
||||
if (HashTable->CompareFunction(&HashNode->Entry, Entry))
|
||||
{
|
||||
/* Does the caller want the value? */
|
||||
if (Value)
|
||||
{
|
||||
/* Return it */
|
||||
*Value = &HashNode->Value;
|
||||
}
|
||||
|
||||
/* Return success and stop scanning */
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try the next node */
|
||||
HashLink = HashLink->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return back to the caller */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlHtStore (
|
||||
_In_ ULONG TableId,
|
||||
_In_ PBL_HASH_ENTRY Entry,
|
||||
_In_ PVOID Data,
|
||||
_In_ ULONG DataSize
|
||||
)
|
||||
{
|
||||
PBL_HASH_NODE HashNode;
|
||||
NTSTATUS Status;
|
||||
PLIST_ENTRY HashLinkHead;
|
||||
PBL_HASH_TABLE HashTable;
|
||||
|
||||
/* Check for invalid tablle ID, missing arguments, or malformed entry */
|
||||
if ((HtTableSize <= TableId) ||
|
||||
!(Entry) ||
|
||||
!(Data) ||
|
||||
!(Entry->Size) ||
|
||||
!(Entry->Value) ||
|
||||
!(DataSize) ||
|
||||
((Entry->Flags & BL_HT_VALUE_IS_INLINE) && (Entry->Size != sizeof(ULONG))))
|
||||
{
|
||||
/* Fail the call */
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Get the hash table for this ID */
|
||||
HashTable = HtTableArray[TableId];
|
||||
|
||||
/* Allocate a hash node */
|
||||
HashNode = BlMmAllocateHeap(sizeof(*HashNode));
|
||||
if (!HashNode)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Capture all the data*/
|
||||
HashNode->Entry.Size = Entry->Size;
|
||||
HashNode->Entry.Flags = Entry->Flags;
|
||||
HashNode->Entry.Value = Entry->Value;
|
||||
HashNode->Value.DataSize = DataSize;
|
||||
HashNode->Value.Data = Data;
|
||||
|
||||
/* Insert it into the bucket list and return success */
|
||||
HashLinkHead = &HashTable->HashLinks[HashTable->HashFunction(Entry, HashTable->Size)];
|
||||
InsertTailList(HashLinkHead, &HashNode->ListEntry);
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
Quickie:
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
BlFwReboot (
|
||||
VOID
|
||||
|
|
|
@ -12,18 +12,261 @@
|
|||
|
||||
/* DATA VARIABLES ************************************************************/
|
||||
|
||||
PVOID MmBlockAllocatorTable;
|
||||
PVOID* MmBlockAllocatorTable;
|
||||
ULONG MmBlockAllocatorTableEntries;
|
||||
BOOLEAN MmBlockAllocatorInitialized;
|
||||
|
||||
typedef struct _BL_BLOCK_DESCRIPTOR
|
||||
{
|
||||
LIST_ENTRY NextEntry;
|
||||
UCHAR Unknown[0x50 - sizeof(LIST_ENTRY)];
|
||||
LIST_ENTRY ListHead;
|
||||
ULONG Unknown;
|
||||
BL_MEMORY_TYPE Type;
|
||||
ULONG Attributes;
|
||||
ULONG Unknown2;
|
||||
ULONG Count;
|
||||
ULONG Count2;
|
||||
ULONG Size;
|
||||
ULONG BlockId;
|
||||
ULONG ReferenceCount;
|
||||
} BL_BLOCK_DESCRIPTOR, *PBL_BLOCK_DESCRIPTOR;
|
||||
|
||||
typedef struct _BL_BLOCK_ENTRY
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
ULONG Todo;
|
||||
} BL_BLOCK_ENTRY, *PBL_BLOCK_ENTRY;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
BOOLEAN
|
||||
MmBapCompareBlockAllocatorTableEntry (
|
||||
_In_ PVOID Entry,
|
||||
_In_ PVOID Argument1,
|
||||
_In_ PVOID Argument2,
|
||||
_In_ PVOID Argument3,
|
||||
_In_ PVOID Argument4
|
||||
)
|
||||
{
|
||||
PBL_BLOCK_DESCRIPTOR BlockInfo = (PBL_BLOCK_DESCRIPTOR)Entry;
|
||||
ULONG BlockId = (ULONG)Argument1;
|
||||
|
||||
/* Check if the block ID matches */
|
||||
return BlockInfo->BlockId == BlockId;
|
||||
}
|
||||
|
||||
PBL_BLOCK_DESCRIPTOR
|
||||
MmBapFindBlockInformation (
|
||||
ULONG BlockId
|
||||
)
|
||||
{
|
||||
ULONG EntryId;
|
||||
|
||||
/* Find the block that matches */
|
||||
EntryId = BlockId;
|
||||
return BlTblFindEntry(MmBlockAllocatorTable,
|
||||
MmBlockAllocatorTableEntries,
|
||||
&EntryId,
|
||||
MmBapCompareBlockAllocatorTableEntry,
|
||||
(PVOID)EntryId,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmBapFreeBlockAllocatorDescriptor (
|
||||
_In_ PBL_BLOCK_DESCRIPTOR BlockInfo,
|
||||
_In_ PBL_BLOCK_ENTRY BlockEntry
|
||||
)
|
||||
{
|
||||
/* @TODO FIXME: Later */
|
||||
EfiPrintf(L"Block free not yet implemented\r\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlpMmDeleteBlockAllocator (
|
||||
_In_ ULONG BlockId
|
||||
)
|
||||
{
|
||||
NTSTATUS Status, LocalStatus;
|
||||
PBL_BLOCK_DESCRIPTOR BlockInfo;
|
||||
PLIST_ENTRY ListHead, NextEntry;
|
||||
PBL_BLOCK_ENTRY BlockEntry;
|
||||
|
||||
/* Nothing to delete if we're not initialized */
|
||||
if (!MmBlockAllocatorInitialized)
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Find the block descriptor */
|
||||
BlockInfo = MmBapFindBlockInformation(BlockId);
|
||||
if (BlockInfo)
|
||||
{
|
||||
/* Assume success for now */
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
/* Do we have at least one reference? */
|
||||
if (BlockInfo->ReferenceCount)
|
||||
{
|
||||
/* Iterate over the allocated blocks */
|
||||
ListHead = &BlockInfo->ListHead;
|
||||
NextEntry = ListHead->Flink;
|
||||
while (NextEntry != ListHead)
|
||||
{
|
||||
/* Free each one */
|
||||
BlockEntry = CONTAINING_RECORD(NextEntry,
|
||||
BL_BLOCK_ENTRY,
|
||||
ListEntry);
|
||||
LocalStatus = MmBapFreeBlockAllocatorDescriptor(BlockInfo,
|
||||
BlockEntry);
|
||||
if (!NT_SUCCESS(LocalStatus))
|
||||
{
|
||||
/* Remember status on failure only */
|
||||
Status = LocalStatus;
|
||||
}
|
||||
}
|
||||
|
||||
/* Drop a reference */
|
||||
BlockInfo->ReferenceCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There aren't any references, so why are we being called? */
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No block exists with this ID */
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Return back */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmBapFreeBlockAllocatorTableEntry (
|
||||
_In_ PVOID Entry,
|
||||
_In_ ULONG Index
|
||||
)
|
||||
{
|
||||
PBL_BLOCK_DESCRIPTOR BlockInfo = (PBL_BLOCK_DESCRIPTOR)Entry;
|
||||
NTSTATUS Status, LocalStatus;
|
||||
|
||||
/* Assume success */
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
/* Check if there was at least one reference */
|
||||
if (BlockInfo->ReferenceCount > 1)
|
||||
{
|
||||
/* Try to delete the allocator */
|
||||
LocalStatus = BlpMmDeleteBlockAllocator(BlockInfo->BlockId);
|
||||
if (!NT_SUCCESS(LocalStatus))
|
||||
{
|
||||
/* Remember status on failure only */
|
||||
Status = LocalStatus;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now destroy the allocator's descriptor */
|
||||
LocalStatus = BlMmFreeHeap(BlockInfo);
|
||||
if (!NT_SUCCESS(LocalStatus))
|
||||
{
|
||||
/* Remember status on failure only */
|
||||
Status = LocalStatus;
|
||||
}
|
||||
|
||||
/* Free the entry, and return failure, if any */
|
||||
MmBlockAllocatorTable[Index] = NULL;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmBapPurgeBlockAlloctorTableEntry (
|
||||
_In_ PVOID Entry
|
||||
)
|
||||
{
|
||||
PBL_BLOCK_DESCRIPTOR BlockInfo = (PBL_BLOCK_DESCRIPTOR)Entry;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Check if there's a reference on the block descriptor */
|
||||
if (BlockInfo->ReferenceCount)
|
||||
{
|
||||
/* Don't allow purging */
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free the entry */
|
||||
Status = MmBapFreeBlockAllocatorTableEntry(BlockInfo,
|
||||
BlockInfo->BlockId);
|
||||
}
|
||||
|
||||
/* Return purge status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlpMmCreateBlockAllocator (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
PBL_BLOCK_DESCRIPTOR BlockInfo;
|
||||
ULONG BlockId;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* If the block allocator isn't initialized, bail out */
|
||||
BlockId = -1;
|
||||
if (!MmBlockAllocatorInitialized)
|
||||
{
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Allocate a block descriptor and zero it out */
|
||||
BlockInfo = BlMmAllocateHeap(sizeof(*BlockInfo));
|
||||
if (!BlockInfo)
|
||||
{
|
||||
goto Quickie;
|
||||
}
|
||||
RtlZeroMemory(BlockInfo, sizeof(*BlockInfo));
|
||||
|
||||
/* Setup the block descriptor */
|
||||
BlockInfo->Attributes = 0;
|
||||
BlockInfo->Type = BlLoaderBlockMemory;
|
||||
BlockInfo->Unknown = 1;
|
||||
BlockInfo->Unknown2 = 1;
|
||||
BlockInfo->Size = PAGE_SIZE;
|
||||
BlockInfo->Count = 128;
|
||||
BlockInfo->Count2 = 128;
|
||||
InitializeListHead(&BlockInfo->ListHead);
|
||||
|
||||
/* Add it to the list of block descriptors */
|
||||
Status = BlTblSetEntry(&MmBlockAllocatorTable,
|
||||
&MmBlockAllocatorTableEntries,
|
||||
BlockInfo,
|
||||
&BlockId,
|
||||
MmBapPurgeBlockAlloctorTableEntry);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Add the initial reference and store the block ID */
|
||||
BlockInfo->ReferenceCount = 1;
|
||||
BlockInfo->BlockId = BlockId;
|
||||
}
|
||||
|
||||
Quickie:
|
||||
/* On failure, free the block descriptor */
|
||||
if (BlockId == -1)
|
||||
{
|
||||
BlMmFreeHeap(BlockInfo);
|
||||
}
|
||||
|
||||
/* Return the block descriptor ID, or -1 on failure */
|
||||
return BlockId;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmBaInitialize (
|
||||
VOID
|
||||
|
|
|
@ -146,7 +146,7 @@ MmHapHeapAllocatorExtend (
|
|||
}
|
||||
|
||||
/* We do not -- allocate one */
|
||||
Status = MmPapAllocatePagesInRange((PULONG)&HeapBase,
|
||||
Status = MmPapAllocatePagesInRange((PVOID*)&HeapBase,
|
||||
BlLoaderHeap,
|
||||
AlignedSize >> PAGE_SHIFT,
|
||||
HapAllocationAttributes,
|
||||
|
@ -673,6 +673,13 @@ BlMmFreeHeap (
|
|||
}
|
||||
|
||||
/* Get the heap header */
|
||||
EfiPrintf(L"Freeing entry at: %p\r\n", Buffer);
|
||||
if (Buffer)
|
||||
{
|
||||
/* Don't free heap until we discover the corruption */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BusyEntry = CONTAINING_RECORD(Buffer, BL_BUSY_HEAP_ENTRY, Buffer);
|
||||
|
||||
/* Loop all the heaps */
|
||||
|
|
|
@ -391,7 +391,7 @@ Quickie:
|
|||
|
||||
NTSTATUS
|
||||
MmPapAllocatePagesInRange (
|
||||
_Inout_ PULONG PhysicalAddress,
|
||||
_Inout_ PVOID* PhysicalAddress,
|
||||
_In_ BL_MEMORY_TYPE MemoryType,
|
||||
_In_ ULONGLONG Pages,
|
||||
_In_ ULONG Attributes,
|
||||
|
@ -425,7 +425,7 @@ MmPapAllocatePagesInRange (
|
|||
else
|
||||
{
|
||||
/* Check if this is a fixed allocation */
|
||||
BaseAddress.QuadPart = (Attributes & BlMemoryFixed) ? *PhysicalAddress : 0;
|
||||
BaseAddress.QuadPart = (Attributes & BlMemoryFixed) ? (ULONG_PTR)*PhysicalAddress : 0;
|
||||
|
||||
/* Allocate the pages */
|
||||
Status = MmPapAllocatePhysicalPagesInRange(&BaseAddress,
|
||||
|
@ -441,7 +441,7 @@ MmPapAllocatePagesInRange (
|
|||
Type);
|
||||
|
||||
/* Return the allocated address */
|
||||
*PhysicalAddress = BaseAddress.LowPart;
|
||||
*PhysicalAddress = (PVOID)BaseAddress.LowPart;
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue