Author: ion
Date: Wed Sep 9 05:48:50 2015
New Revision: 69142
URL:
http://svn.reactos.org/svn/reactos?rev=69142&view=rev
Log:
[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.
Added:
trunk/reactos/boot/environ/include/efi/BlockIo.h (with props)
Modified:
trunk/reactos/boot/environ/app/bootmgr/bootmgr.c
trunk/reactos/boot/environ/app/bootmgr/efiemu.c
trunk/reactos/boot/environ/include/bl.h
trunk/reactos/boot/environ/lib/bootlib.c
trunk/reactos/boot/environ/lib/firmware/efi/firmware.c
trunk/reactos/boot/environ/lib/io/device.c
trunk/reactos/boot/environ/lib/io/display/display.c
trunk/reactos/boot/environ/lib/io/display/emscons.c
trunk/reactos/boot/environ/lib/io/io.c
trunk/reactos/boot/environ/lib/misc/util.c
trunk/reactos/boot/environ/lib/mm/blkalloc.c
trunk/reactos/boot/environ/lib/mm/heapalloc.c
trunk/reactos/boot/environ/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/b…
==============================================================================
--- trunk/reactos/boot/environ/app/bootmgr/bootmgr.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/app/bootmgr/bootmgr.c [iso-8859-1] Wed Sep 9 05:48:50
2015
@@ -22,43 +22,42 @@
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 @@
}
BootDirectory = L"\\EFI\\Microsoft\\Boot";
+#endif
Quickie:
+ /* Free all the allocations we made */
if (BcdDirectory)
{
Status = BlMmFreeHeap(BcdDirectory);
@@ -101,18 +102,21 @@
{
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 @@
goto Quickie;
}
+ EfiPrintf(L"We are A-OK!\n");
+ EfiStall(10000000);
+
/* Get the application identifier */
AppIdentifier = BlGetApplicationIdentifier();
if (!AppIdentifier)
Modified: trunk/reactos/boot/environ/app/bootmgr/efiemu.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/app/bootmgr/e…
==============================================================================
--- trunk/reactos/boot/environ/app/bootmgr/efiemu.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/app/bootmgr/efiemu.c [iso-8859-1] Wed Sep 9 05:48:50 2015
@@ -253,7 +253,10 @@
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 @@
*
*--*/
NTSTATUS
-EfiInitTranslateDevicePath(
+EfiInitTranslateDevicePath (
_In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
_In_ PBL_DEVICE_DESCRIPTOR DeviceEntry
)
@@ -418,7 +421,7 @@
}
/* 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 @@
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 @@
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 @@
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 */
Modified: trunk/reactos/boot/environ/include/bl.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/include/bl.h?…
==============================================================================
--- trunk/reactos/boot/environ/include/bl.h [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/include/bl.h [iso-8859-1] Wed Sep 9 05:48:50 2015
@@ -28,6 +28,7 @@
#include <LoadedImage.h>
#include <GraphicsOutput.h>
#include <UgaDraw.h>
+#include <BlockIo.h>
/* DEFINES *******************************************************************/
@@ -75,6 +76,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
@@ -127,10 +130,13 @@
//
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_LOCAL_DEVICE_TYPE
{
+ LocalDevice = 0,
FloppyDevice = 1,
CdRomDevice = 2,
RamDiskDevice = 3,
+ FileDevice = 5,
+ VirtualDiskDevice = 6
} BL_LOCAL_DEVICE_TYPE;
//
@@ -180,11 +189,13 @@
// Loader Memory
//
BlLoaderMemory = 0xD0000002,
+ BlLoaderDeviceMemory = 0xD0000004,
BlLoaderHeap = 0xD0000005,
BlLoaderPageDirectory = 0xD0000006,
BlLoaderReferencePage = 0xD0000007,
BlLoaderRamDisk = 0xD0000008,
BlLoaderData = 0xD000000A,
+ BlLoaderBlockMemory = 0xD000000C,
BlLoaderSelfMap = 0xD000000F,
//
@@ -339,6 +350,50 @@
_In_ struct _BL_TEXT_CONSOLE* Console,
_In_ PCHAR Text,
_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 ***********************************************************/
@@ -568,11 +623,6 @@
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 @@
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 @@
_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
@@ -920,6 +1042,71 @@
VOID
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 **************************************************************/
@@ -1001,7 +1188,7 @@
NTSTATUS
MmPapAllocatePagesInRange (
- _Inout_ PULONG PhysicalAddress,
+ _Inout_ PVOID* PhysicalAddress,
_In_ BL_MEMORY_TYPE MemoryType,
_In_ ULONGLONG Pages,
_In_ ULONG Attributes,
@@ -1026,6 +1213,13 @@
_In_ PHYSICAL_ADDRESS PhysicalAddress
);
+/* BLOCK ALLOCATOR ROUTINES **************************************************/
+
+NTSTATUS
+BlpMmCreateBlockAllocator (
+ VOID
+ );
+
/* HEAP ALLOCATOR ROUTINES ***************************************************/
PVOID
@@ -1046,7 +1240,27 @@
_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 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[];
Added: trunk/reactos/boot/environ/include/efi/BlockIo.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/include/efi/B…
==============================================================================
--- trunk/reactos/boot/environ/include/efi/BlockIo.h (added)
+++ trunk/reactos/boot/environ/include/efi/BlockIo.h [iso-8859-1] Wed Sep 9 05:48:50
2015
@@ -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
Propchange: trunk/reactos/boot/environ/include/efi/BlockIo.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/boot/environ/lib/bootlib.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/bootlib.c…
==============================================================================
--- trunk/reactos/boot/environ/lib/bootlib.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/bootlib.c [iso-8859-1] Wed Sep 9 05:48:50 2015
@@ -393,3 +393,13 @@
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;
+}
Modified: trunk/reactos/boot/environ/lib/firmware/efi/firmware.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/firmware/…
==============================================================================
--- trunk/reactos/boot/environ/lib/firmware/efi/firmware.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/firmware/efi/firmware.c [iso-8859-1] Wed Sep 9
05:48:50 2015
@@ -29,10 +29,83 @@
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 (
Modified: trunk/reactos/boot/environ/lib/io/device.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/io/device…
==============================================================================
--- trunk/reactos/boot/environ/lib/io/device.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/io/device.c [iso-8859-1] Wed Sep 9 05:48:50 2015
@@ -29,6 +29,1520 @@
/* FUNCTIONS *****************************************************************/
+struct _BL_DEVICE_ENTRY;
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_ENUMERATE_DEVICE_CLASS) (
+ VOID
+ );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_OPEN) (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ struct _BL_DEVICE_ENTRY* DeviceEntry
+ );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_CLOSE) (
+ _In_ struct _BL_DEVICE_ENTRY* DeviceEntry
+ );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_READ) (
+ VOID
+ );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_WRITE) (
+ VOID
+ );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_GET_INFORMATION) (
+ VOID
+ );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_SET_INFORMATION) (
+ VOID
+ );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_RESET) (
+ VOID
+ );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_FLUSH) (
+ VOID
+ );
+
+typedef
+NTSTATUS
+(*PBL_DEVICE_CREATE) (
+ VOID
+ );
+
+typedef struct _BL_DEVICE_CALLBACKS
+{
+ PBL_DEVICE_ENUMERATE_DEVICE_CLASS EnumerateDeviceClass;
+ PBL_DEVICE_OPEN Open;
+ PBL_DEVICE_CLOSE Close;
+ PBL_DEVICE_READ Read;
+ PBL_DEVICE_WRITE Write;
+ PBL_DEVICE_GET_INFORMATION GetInformation;
+ PBL_DEVICE_SET_INFORMATION SetInformation;
+ PBL_DEVICE_RESET Reset;
+ PBL_DEVICE_FLUSH Flush;
+ PBL_DEVICE_CREATE Create;
+} BL_DEVICE_CALLBACKS, *PBL_DEVICE_CALLBACKS;
+
+typedef struct _BL_DEVICE_ENTRY
+{
+ ULONG DeviceId;
+ ULONG Flags;
+ ULONG Unknown;
+ ULONG ReferenceCount;
+ BL_DEVICE_CALLBACKS Callbacks;
+ PVOID DeviceSpecificData;
+ PBL_DEVICE_DESCRIPTOR DeviceDescriptor;
+} BL_DEVICE_ENTRY, *PBL_DEVICE_ENTRY;
+
+typedef struct _BL_REGISTERED_DEVICE
+{
+ LIST_ENTRY ListEntry;
+ BL_DEVICE_CALLBACKS Callbacks;
+} BL_REGISTERED_DEVICE, *PBL_REGISTERED_DEVICE;
+
+PVOID* BlockIoDeviceTable;
+ULONG BlockIoDeviceTableEntries;
+
+ULONG BlockIoFirmwareRemovableDiskCount;
+ULONG BlockIoFirmwareRawDiskCount;
+ULONG BlockIoFirmwareCdromCount;
+
+PVOID BlockIopAlignedBuffer;
+ULONG BlockIopAlignedBufferSize;
+
+PVOID BlockIopPartialBlockBuffer;
+ULONG BlockIopPartialBlockBufferSize;
+
+PVOID BlockIopPrefetchBuffer;
+
+PVOID BlockIopReadBlockBuffer;
+ULONG BlockIopReadBlockBufferSize;
+
+ULONG HashTableId;
+
+BOOLEAN BlockIoInitialized;
+
+NTSTATUS
+BlockIoOpen (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ PBL_DEVICE_ENTRY DeviceEntry
+ );
+
+NTSTATUS
+PartitionOpen (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ PBL_DEVICE_ENTRY DeviceEntry
+ )
+{
+ EfiPrintf(L"Not implemented!\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+VhdFileDeviceOpen (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ PBL_DEVICE_ENTRY DeviceEntry
+ )
+{
+ EfiPrintf(L"Not implemented!\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+DiskOpen (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ PBL_DEVICE_ENTRY DeviceEntry
+ )
+{
+ EfiPrintf(L"Not implemented!\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+RdDeviceOpen (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ PBL_DEVICE_ENTRY DeviceEntry
+ )
+{
+ EfiPrintf(L"Not implemented!\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+FileDeviceOpen (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ PBL_DEVICE_ENTRY DeviceEntry
+ )
+{
+ EfiPrintf(L"Not implemented!\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+SpOpen (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ PBL_DEVICE_ENTRY DeviceEntry
+ )
+{
+ EfiPrintf(L"Not implemented!\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+UdpOpen (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ PBL_DEVICE_ENTRY DeviceEntry
+ )
+{
+ EfiPrintf(L"Not implemented!\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+BL_DEVICE_CALLBACKS FileDeviceFunctionTable =
+{
+ NULL,
+ FileDeviceOpen,
+ NULL,
+};
+
+BL_DEVICE_CALLBACKS PartitionDeviceFunctionTable =
+{
+ NULL,
+ PartitionOpen,
+ NULL,
+};
+
+BL_DEVICE_CALLBACKS RamDiskDeviceFunctionTable =
+{
+ NULL,
+ RdDeviceOpen,
+ NULL,
+};
+
+BL_DEVICE_CALLBACKS DiskDeviceFunctionTable =
+{
+ NULL,
+ DiskOpen,
+ NULL,
+};
+
+BL_DEVICE_CALLBACKS VirtualDiskDeviceFunctionTable =
+{
+ NULL,
+ VhdFileDeviceOpen,
+ NULL,
+};
+
+BL_DEVICE_CALLBACKS BlockIoDeviceFunctionTable =
+{
+ NULL,
+ BlockIoOpen,
+ NULL,
+};
+
+BL_DEVICE_CALLBACKS UdpFunctionTable =
+{
+ NULL,
+ UdpOpen,
+ NULL,
+};
+
+BL_DEVICE_CALLBACKS SerialPortFunctionTable =
+{
+ NULL,
+ SpOpen,
+ NULL,
+};
+
+
+ULONG BcpBlockAllocatorHandle;
+ULONG BcpHashTableId;
+
+NTSTATUS
+BcpDestroy (
+ VOID
+ )
+{
+ //BcpPurgeCacheEntries();
+ //return BlpMmDeleteBlockAllocator(BcpBlockAllocatorHandle);
+ EfiPrintf(L"Destructor for block cache not yet implemented\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+BOOLEAN
+BcpCompareKey (
+ _In_ PBL_HASH_ENTRY Entry1,
+ _In_ PBL_HASH_ENTRY Entry2
+ )
+{
+ PULONG Value1, Value2;
+
+ Value1 = Entry1->Value;
+ Value2 = Entry2->Value;
+ return Entry1->Size == Entry2->Size && Entry1->Flags ==
Entry2->Flags && *Value1 == *Value2 && Value1[1] == Value2[1]
&& Value1[2] == Value2[2];
+}
+
+ULONG
+BcpHashFunction (
+ _In_ PBL_HASH_ENTRY Entry,
+ _In_ ULONG TableSize
+ )
+{
+ ULONG i, j, ValueHash;
+ PUCHAR ValueBuffer;
+
+ j = 0;
+ ValueHash = 0;
+ i = 0;
+
+ ValueBuffer = Entry->Value;
+
+ do
+ {
+ ValueHash += ValueBuffer[i++];
+ }
+ while (i < 8);
+
+ do
+ {
+ ValueHash += ValueBuffer[j++ + 8];
+ }
+ while (j < 4);
+
+ return ValueHash % TableSize;
+}
+
+NTSTATUS
+BcInitialize (
+ VOID
+ )
+{
+ NTSTATUS Status;
+
+ Status = BlHtCreate(50, BcpHashFunction, BcpCompareKey, &BcpHashTableId);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Quickie;
+ }
+
+ BcpBlockAllocatorHandle = BlpMmCreateBlockAllocator();
+ if (BcpBlockAllocatorHandle == -1)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ goto Quickie;
+ }
+
+ Status = BlpIoRegisterDestroyRoutine(BcpDestroy);
+ if (Status >= 0)
+ {
+ return Status;
+ }
+
+Quickie:
+ EfiPrintf(L"Failure path not yet implemented\n");
+#if 0
+ if (BcpHashTableId != -1)
+ {
+ BlHtDestroy(BcpHashTableId);
+ }
+ if (BcpBlockAllocatorHandle != -1)
+ {
+ BlpMmDeleteBlockAllocator(BcpBlockAllocatorHandle);
+ }
+#endif
+ return Status;
+}
+
+BOOLEAN
+BlpDeviceCompare (
+ _In_ PBL_DEVICE_DESCRIPTOR Device1,
+ _In_ PBL_DEVICE_DESCRIPTOR Device2
+ )
+{
+ BOOLEAN DeviceMatch;
+ ULONG DeviceSize;
+
+ /* Assume failure */
+ DeviceMatch = FALSE;
+
+ /* Check if the two devices exist and are identical in typ */
+ if ((Device1) && (Device2) && (Device1->DeviceType ==
Device2->DeviceType))
+ {
+ /* Take the bigger of the two sizes */
+ DeviceSize = max(Device1->Size, Device2->Size);
+ if (DeviceSize >= (ULONG)FIELD_OFFSET(BL_DEVICE_DESCRIPTOR, Local))
+ {
+ /* Compare the two devices up to their size */
+ if (RtlEqualMemory(&Device1->Local,
+ &Device2->Local,
+ DeviceSize - FIELD_OFFSET(BL_DEVICE_DESCRIPTOR, Local)))
+ {
+ /* They match! */
+ DeviceMatch = TRUE;
+ }
+ }
+ }
+
+ /* Return matching state */
+ return DeviceMatch;
+}
+
+BOOLEAN
+DeviceTableCompare (
+ _In_ PVOID Entry,
+ _In_ PVOID Argument1,
+ _In_ PVOID Argument2,
+ _Inout_ PVOID Argument3,
+ _Inout_ PVOID Argument4
+ )
+{
+ BOOLEAN Found;
+ PBL_DEVICE_DESCRIPTOR Device = (PBL_DEVICE_DESCRIPTOR)Entry;
+ PBL_DEVICE_ENTRY DeviceEntry = (PBL_DEVICE_ENTRY)Argument1;
+ ULONG Flags = *(PULONG)Argument2;
+ ULONG Unknown = *(PULONG)Argument3;
+
+ /* Assume failure */
+ Found = FALSE;
+
+ /* Compare the device descriptor */
+ if (BlpDeviceCompare(DeviceEntry->DeviceDescriptor, Device))
+ {
+ /* Compare something */
+ if (DeviceEntry->Unknown == Unknown)
+ {
+ /* Compare flags */
+ if ((!(Flags & 1) || (DeviceEntry->Flags & 2)) &&
+ (!(Flags & 2) || (DeviceEntry->Flags & 4)))
+ {
+ /* And more flags */
+ if (((Flags & 8) || !(DeviceEntry->Flags & 8)) &&
+ (!(Flags & 8) || (DeviceEntry->Flags & 8)))
+ {
+ /* Found a match! */
+ Found = TRUE;
+ }
+ }
+ }
+ }
+
+ /* Return matching state */
+ return Found;
+}
+
+NTSTATUS
+DeviceTableDestroyEntry (
+ _In_ PVOID Entry,
+ _In_ ULONG DeviceId
+ )
+{
+ PBL_DEVICE_ENTRY DeviceEntry = (PBL_DEVICE_ENTRY)Entry;
+ NTSTATUS Status;
+
+ /* Call the close routine for this entry */
+ Status = DeviceEntry->Callbacks.Close(DmDeviceTable[DeviceId]);
+
+ /* Free the descriptor, and the device itself */
+ BlMmFreeHeap(DeviceEntry->DeviceDescriptor);
+ BlMmFreeHeap(DeviceEntry);
+
+ /* Clear out the netry, and return */
+ DmDeviceTable[DeviceId] = NULL;
+ return Status;
+}
+
+NTSTATUS
+DeviceTablePurge (
+ _In_ PVOID Entry
+ )
+{
+ PBL_DEVICE_ENTRY DeviceEntry = (PBL_DEVICE_ENTRY)Entry;
+ NTSTATUS Status;
+
+ /* Check if the device is opened */
+ if (DeviceEntry->Flags & 1)
+ {
+ /* It is, so can't purge it */
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ /* It isn't, so destroy the entry */
+ Status = DeviceTableDestroyEntry(DeviceEntry, DeviceEntry->DeviceId);
+ }
+
+ /* Return back to caller */
+ return Status;
+}
+
+NTSTATUS
+BlockIoDeviceTableDestroyEntry (
+ _In_ PVOID Entry,
+ _In_ ULONG DeviceId
+ )
+{
+ PBL_DEVICE_ENTRY DeviceEntry = (PBL_DEVICE_ENTRY)Entry;
+ NTSTATUS Status;
+
+ /* Call the close routine for this entry */
+ Status = DeviceEntry->Callbacks.Close(DeviceEntry);
+
+ /* Free the descriptor, and the device itself */
+ BlMmFreeHeap(DeviceEntry->DeviceDescriptor);
+ BlMmFreeHeap(DeviceEntry);
+
+ /* Clear out the netry, and return */
+ BlockIoDeviceTable[DeviceId] = NULL;
+ return Status;
+}
+
+NTSTATUS
+BlockIoDeviceTableDestroy (
+ VOID
+ )
+{
+ NTSTATUS Status;
+
+ /* Call the entry destructor on each entry in the table */
+ Status = BlTblMap(BlockIoDeviceTable,
+ BlockIoDeviceTableEntries,
+ BlockIoDeviceTableDestroyEntry);
+
+ /* Free the table and return */
+ BlMmFreeHeap(BlockIoDeviceTable);
+ return Status;
+}
+
+NTSTATUS
+BlockIopDestroy (
+ VOID
+ )
+{
+ /* Free the prefetch buffer */
+ BlMmFreeHeap(BlockIopPrefetchBuffer);
+
+ /* Set state to non initialized */
+ BlockIoInitialized = FALSE;
+
+ /* Return back */
+ return STATUS_SUCCESS;
+}
+
+ULONG
+BlockIoEfiHashFunction (
+ _In_ PBL_HASH_ENTRY Entry,
+ _In_ ULONG TableSize
+ )
+{
+ /* Get rid of the alignment bits to have a more unique number */
+ return ((ULONG)Entry->Value >> 3) % TableSize;
+}
+
+NTSTATUS
+BlockIopInitialize (
+ VOID
+ )
+{
+ NTSTATUS Status;
+
+ /* Allocate the block device table and zero it out */
+ BlockIoDeviceTableEntries = 8;
+ BlockIoDeviceTable = BlMmAllocateHeap(sizeof(PVOID) *
+ BlockIoDeviceTableEntries);
+ if (!BlockIoDeviceTableEntries)
+ {
+ return STATUS_NO_MEMORY;
+ }
+ RtlZeroMemory(BlockIoDeviceTable, sizeof(PVOID) * BlockIoDeviceTableEntries);
+
+ /* Register our destructor */
+ Status = BlpIoRegisterDestroyRoutine(BlockIoDeviceTableDestroy);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Initialize all counters */
+ BlockIoFirmwareRemovableDiskCount = 0;
+ BlockIoFirmwareRawDiskCount = 0;
+ BlockIoFirmwareCdromCount = 0;
+
+ /* Initialize the buffers and their sizes */
+ BlockIopAlignedBuffer = NULL;
+ BlockIopAlignedBufferSize = 0;
+ BlockIopPartialBlockBuffer = NULL;
+ BlockIopPartialBlockBufferSize = 0;
+ BlockIopPrefetchBuffer = NULL;
+ BlockIopReadBlockBuffer = NULL;
+ BlockIopReadBlockBufferSize = 0;
+
+ /* Allocate the prefetch buffer */
+ Status = MmPapAllocatePagesInRange(&BlockIopPrefetchBuffer,
+ BlLoaderDeviceMemory,
+ 0x100,
+ 0,
+ 0,
+ NULL,
+ 0);
+ if (NT_SUCCESS(Status))
+ {
+ /* Initialize the block cache */
+ Status = BcInitialize();
+ if (NT_SUCCESS(Status))
+ {
+ /* Initialize the block device hash table */
+ Status = BlHtCreate(29, BlockIoEfiHashFunction, NULL, &HashTableId);
+ if (NT_SUCCESS(Status))
+ {
+ /* Register our destructor */
+ Status = BlpIoRegisterDestroyRoutine(BlockIopDestroy);
+ if (NT_SUCCESS(Status))
+ {
+ /* We're good */
+ BlockIoInitialized = TRUE;
+ }
+ }
+ }
+ }
+
+ /* Check if this is the failure path */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Free the prefetch buffer is one was allocated */
+ if (BlockIopPrefetchBuffer)
+ {
+ EfiPrintf(L"Failure path not implemented %lx\r\n", Status);
+ //MmPapFreePages(BlockIopPrefetchBuffer, 1);
+ }
+ }
+
+ /* Return back to the caller */
+ return Status;
+}
+
+NTSTATUS
+BlockIopFreeAllocations (
+ _In_ PBL_BLOCK_DEVICE BlockDevice
+ )
+{
+ /* If a block device was passed in, free it */
+ if (BlockDevice)
+ {
+ BlMmFreeHeap(BlockDevice);
+ }
+
+ /* Nothing else to do */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+BlockIoEfiGetBlockIoInformation (
+ _In_ PBL_BLOCK_DEVICE BlockDevice
+ )
+{
+ NTSTATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+
+ /* Open the Block I/O protocol on this device */
+ Status = EfiOpenProtocol(BlockDevice->Handle,
+ &EfiBlockIoProtocol,
+ (PVOID*)&BlockDevice->Protocol);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Get information on the block media */
+ Media = BlockDevice->Protocol->Media;
+
+ /* Set the appropriate device flags */
+ BlockDevice->DeviceFlags = 0;
+ if (Media->RemovableMedia)
+ {
+ BlockDevice->DeviceFlags = 1;
+ }
+ if (Media->MediaPresent)
+ {
+ BlockDevice->DeviceFlags |= 2;
+ }
+
+ /* No clue */
+ BlockDevice->Unknown = 0;
+
+ /* Set the block size */
+ BlockDevice->BlockSize = Media->BlockSize;
+
+ /* Make sure there's a last block value */
+ if (!Media->LastBlock)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Don't let it be too high */
+ if (Media->LastBlock > 0xFFFFFFFFFFE)
+ {
+ BlockDevice->LastBlock = 0xFFFFFFFFFFE;
+ }
+ else
+ {
+ BlockDevice->LastBlock = Media->LastBlock;
+ }
+
+ /* Make the alignment the smaller of the I/O alignment or the block size */
+ if (Media->IoAlign >= Media->BlockSize)
+ {
+ BlockDevice->Alignment = Media->IoAlign;
+ }
+ else
+ {
+ BlockDevice->Alignment = Media->BlockSize;
+ }
+
+ /* All good */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+BlockIoEfiGetChildHandle (
+ _In_ PBL_PROTOCOL_HANDLE ProtocolInterface,
+ _In_ PBL_PROTOCOL_HANDLE ChildProtocolInterface)
+{
+ NTSTATUS Status;
+ ULONG i, DeviceCount;
+ EFI_DEVICE_PATH *DevicePath, *ParentDevicePath;
+ EFI_HANDLE *DeviceHandles;
+ EFI_HANDLE Handle;
+
+ /* Find all the Block I/O device handles on the system */
+ DeviceCount = 0;
+ DeviceHandles = 0;
+ Status = EfiLocateHandleBuffer(ByProtocol,
+ &EfiBlockIoProtocol,
+ &DeviceCount,
+ &DeviceHandles);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed to enumerate, bail out */
+ return Status;
+ }
+
+ /* Loop all the handles */
+ for (i = 0; i < DeviceCount; i++)
+ {
+ /* Check if this is the device itself */
+ Handle = DeviceHandles[i];
+ if (Handle == ProtocolInterface->Handle)
+ {
+ /* Skip it */
+ continue;
+ }
+
+ /* Get the device path of this device */
+ Status = EfiOpenProtocol(Handle,
+ &EfiDevicePathProtocol,
+ (PVOID*)&DevicePath);
+ if (!NT_SUCCESS(Status))
+ {
+ /* We failed, skip it */
+ continue;
+ }
+
+ /* See if we are its parent */
+ ParentDevicePath = EfiIsDevicePathParent(ProtocolInterface->Interface,
+ DevicePath);
+ if (ParentDevicePath == ProtocolInterface->Interface)
+ {
+ /* Yup, return back to caller */
+ ChildProtocolInterface->Handle = Handle;
+ ChildProtocolInterface->Interface = DevicePath;
+ break;
+ }
+
+ /* Close the device path */
+ EfiCloseProtocol(Handle, &EfiDevicePathProtocol);
+ }
+
+ /* If we got here, nothing was found */
+ Status = STATUS_NO_SUCH_DEVICE;
+
+ /* Free the handle array buffer */
+ BlMmFreeHeap(DeviceHandles);
+ return Status;
+}
+
+NTSTATUS
+BlockIoGetGPTDiskSignature (
+ _In_ PBL_DEVICE_ENTRY DeviceEntry,
+ _Out_ PGUID DiskSignature
+ )
+{
+ EfiPrintf(L"GPT not supported\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+BlockIoEfiGetDeviceInformation (
+ _In_ PBL_DEVICE_ENTRY DeviceEntry
+ )
+{
+ NTSTATUS Status;
+ PBL_DEVICE_DESCRIPTOR Device;
+ PBL_BLOCK_DEVICE BlockDevice;
+ EFI_DEVICE_PATH *LeafNode;
+ EFI_HANDLE Handle;
+ BL_PROTOCOL_HANDLE Protocol[2];
+ ACPI_HID_DEVICE_PATH *AcpiPath;
+ HARDDRIVE_DEVICE_PATH *DiskPath;
+ BOOLEAN Found;
+ ULONG i;
+
+ Device = DeviceEntry->DeviceDescriptor;
+ BlockDevice = (PBL_BLOCK_DEVICE)DeviceEntry->DeviceSpecificData;
+
+ Found = FALSE;
+
+ Handle = BlockDevice->Handle;
+
+ Protocol[0].Handle = Handle;
+ Protocol[1].Handle = 0;
+
+ Status = EfiOpenProtocol(Handle,
+ &EfiDevicePathProtocol,
+ &Protocol[0].Interface);
+ if (Status < 0)
+ {
+ return Status;
+ }
+
+ for (i = 0, Found = FALSE; Found == FALSE && Protocol[i].Handle; i++)
+ {
+ LeafNode = EfiGetLeafNode(Protocol[i].Interface);
+ if (LeafNode->Type == ACPI_DEVICE_PATH)
+ {
+ /* We only support floppy drives */
+ AcpiPath = (ACPI_HID_DEVICE_PATH*)LeafNode;
+ if ((AcpiPath->HID == EISA_PNP_ID(0x604)) &&
+ (AcpiPath->HID == EISA_PNP_ID(0x700)))
+ {
+ /* Set the boot library specific device types */
+ Device->DeviceType = LocalDevice;
+ Device->Local.Type = FloppyDevice;
+
+ /* The ACPI UID is the drive number */
+ Device->Local.FloppyDisk.DriveNumber = AcpiPath->UID;
+
+ /* We found a match */
+ Found = TRUE;
+ }
+ }
+ else if ((LeafNode->Type == MEDIA_DEVICE_PATH) && (i == 1))
+ {
+ /* Extract the disk path and check if it's a physical disk */
+ DiskPath = (HARDDRIVE_DEVICE_PATH*)LeafNode;
+ if (LeafNode->SubType == MEDIA_HARDDRIVE_DP)
+ {
+ Device->Local.Type = LocalDevice;
+
+ /* Check if this is an MBR partition */
+ if (DiskPath->SignatureType == SIGNATURE_TYPE_MBR)
+ {
+ /* Set that this is a local partition */
+ Device->DeviceType = LegacyPartitionDevice;
+ Device->Partition.Disk.Type = LocalDevice;
+
+ BlockDevice->PartitionType = MbrPartition;
+ BlockDevice->Disk.Mbr.Signature =
*(PULONG)&DiskPath->Signature[0];
+ Found = TRUE;
+ }
+ else if (DiskPath->SignatureType == SIGNATURE_TYPE_GUID)
+ {
+ BlockDevice->PartitionType = 0;
+ Device->Local.HardDisk.PartitionType = GptPartition;
+
+ Status = BlockIoGetGPTDiskSignature(DeviceEntry,
+
&Device->Local.HardDisk.Gpt.PartitionSignature);
+ if (NT_SUCCESS(Status))
+ {
+ RtlCopyMemory(&BlockDevice->Disk.Gpt.Signature,
+
&Device->Local.HardDisk.Gpt.PartitionSignature,
+ sizeof(&BlockDevice->Disk.Gpt.Signature));
+ Found = TRUE;
+ }
+ }
+
+ /* Otherwise, raw boot is not supported */
+ BlockDevice->PartitionType = RawPartition;
+ Device->Local.HardDisk.PartitionType = RawPartition;
+ Device->Local.HardDisk.Raw.DiskNumber =
BlockIoFirmwareRawDiskCount++;;
+ }
+ else if (LeafNode->SubType == MEDIA_CDROM_DP)
+ {
+ /* Set block device information */
+ BlockDevice->PartitionType = RawPartition;
+ BlockDevice->Type = CdRomDevice;
+
+ /* Set CDROM data */
+ Device->Local.Type = CdRomDevice;
+ Device->Local.FloppyDisk.DriveNumber = 0;
+ Found = TRUE;
+ }
+ }
+ else if ((LeafNode->Type != MEDIA_DEVICE_PATH) &&
+ (LeafNode->Type == ACPI_DEVICE_PATH) &&
+ (i == 0))
+ {
+ Status = BlockIoEfiGetChildHandle(Protocol, &Protocol[i]);
+ if (!NT_SUCCESS(Status))
+ {
+ Device->DeviceType = LocalDevice;
+ Found = 1;
+ if (BlockDevice->DeviceFlags & 1)
+ {
+ BlockDevice->Type = FloppyDevice;
+ Device->Local.HardDisk.PartitionType =
BlockIoFirmwareRemovableDiskCount++;
+ Device->Local.Type = FloppyDevice;
+ }
+ else
+ {
+ BlockDevice->Type = DiskDevice;
+ Device->Local.Type = DiskDevice;
+ Device->Local.HardDisk.PartitionType = RawPartition;
+ BlockDevice->PartitionType = RawPartition;
+ Device->Local.HardDisk.Mbr.PartitionSignature =
BlockIoFirmwareRawDiskCount++;
+ }
+ }
+ }
+ }
+
+ while (i)
+ {
+ EfiCloseProtocol(Protocol[--i].Handle, &EfiDevicePathProtocol);
+ }
+
+ if (Found)
+ {
+ Status = 0;
+ }
+ else
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ return Status;
+}
+
+NTSTATUS
+BlockIoEfiReset (
+ VOID
+ )
+{
+ EfiPrintf(L"not implemented\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+BlockIoEfiFlush (
+ VOID
+ )
+{
+ EfiPrintf(L"not implemented\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+BlockIoEfiCreateDeviceEntry (
+ _In_ PBL_DEVICE_ENTRY *DeviceEntry,
+ _Out_ PVOID Handle
+ )
+{
+ PBL_DEVICE_ENTRY IoDeviceEntry;
+ PBL_BLOCK_DEVICE BlockDevice;
+ NTSTATUS Status;
+ PBL_DEVICE_DESCRIPTOR Device;
+
+ /* Allocate the entry for this device and zero it out */
+ IoDeviceEntry = BlMmAllocateHeap(sizeof(*IoDeviceEntry));
+ if (!IoDeviceEntry)
+ {
+ return STATUS_NO_MEMORY;
+ }
+ RtlZeroMemory(IoDeviceEntry, sizeof(*IoDeviceEntry));
+
+ /* Allocate the device descriptor for this device and zero it out */
+ Device = BlMmAllocateHeap(sizeof(*Device));
+ if (!Device)
+ {
+ return STATUS_NO_MEMORY;
+ }
+ RtlZeroMemory(Device, sizeof(*Device));
+
+ /* Allocate the block device specific data, and zero it out */
+ BlockDevice = BlMmAllocateHeap(sizeof(*BlockDevice));
+ if (!BlockDevice)
+ {
+ return STATUS_NO_MEMORY;
+ }
+ RtlZeroMemory(BlockDevice, sizeof(*BlockDevice));
+
+ /* Save the descriptor and block device specific data */
+ IoDeviceEntry->DeviceSpecificData = BlockDevice;
+ IoDeviceEntry->DeviceDescriptor = Device;
+
+ /* Set the size of the descriptor */
+ Device->Size = sizeof(*Device);
+
+ /* Copy the standard I/O callbacks */
+ RtlCopyMemory(&IoDeviceEntry->Callbacks,
+ &BlockIoDeviceFunctionTable,
+ sizeof(IoDeviceEntry->Callbacks));
+
+ /* Add the two that are firmware specific */
+ IoDeviceEntry->Callbacks.Reset = BlockIoEfiReset;
+ IoDeviceEntry->Callbacks.Flush = BlockIoEfiFlush;
+
+ /* Save the EFI handle */
+ BlockDevice->Handle = Handle;
+
+ /* Get information on this device from EFI, caching it in the device */
+ Status = BlockIoEfiGetBlockIoInformation(BlockDevice);
+ if (NT_SUCCESS(Status))
+ {
+ /* Build the descriptor structure for this device */
+ Status = BlockIoEfiGetDeviceInformation(IoDeviceEntry);
+ if (NT_SUCCESS(Status))
+ {
+ /* We have a fully constructed device, reuturn it */
+ *DeviceEntry = IoDeviceEntry;
+ return STATUS_SUCCESS;
+ }
+ }
+
+ /* Failure path, free the descriptor if we allocated one */
+ if (IoDeviceEntry->DeviceDescriptor)
+ {
+ BlMmFreeHeap(IoDeviceEntry->DeviceDescriptor);
+ }
+
+ /* Free any other specific allocations */
+ BlockIopFreeAllocations(IoDeviceEntry->DeviceSpecificData);
+
+ /* Free the device entry itself and return the failure code */
+ BlMmFreeHeap(IoDeviceEntry);
+ return Status;
+}
+
+NTSTATUS
+BlockIoFirmwareOpen (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ PBL_BLOCK_DEVICE BlockIoDevice
+ )
+{
+ NTSTATUS Status;
+ BOOLEAN DeviceMatch;
+ BL_HASH_ENTRY HashEntry;
+ ULONG i, Id, DeviceCount;
+ PBL_DEVICE_ENTRY DeviceEntry;
+ EFI_HANDLE* DeviceHandles;
+
+ /* Initialize everything */
+ DeviceEntry = NULL;
+ DeviceCount = 0;
+ DeviceHandles = 0;
+ DeviceEntry = NULL;
+
+ /* Ask EFI for handles to all block devices */
+ Status = EfiLocateHandleBuffer(ByProtocol,
+ &EfiBlockIoProtocol,
+ &DeviceCount,
+ &DeviceHandles);
+ if (!NT_SUCCESS(Status))
+ {
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ /* Build a hash entry, with the value inline */
+ HashEntry.Flags = 1;
+ HashEntry.Size = sizeof(EFI_HANDLE);
+
+ /* Loop each device we got */
+ DeviceMatch = FALSE;
+ Status = STATUS_NO_SUCH_DEVICE;
+ for (i = 0; i < DeviceCount; i++)
+ {
+ /* Check if we have a match in the device hash table */
+ HashEntry.Value = DeviceHandles[i];
+ Status = BlHtLookup(HashTableId, &HashEntry, 0);
+ if (NT_SUCCESS(Status))
+ {
+ /* We already know about this device */
+ continue;
+ }
+
+ /* New device, store it in the hash table */
+ Status = BlHtStore(HashTableId,
+ &HashEntry,
+ DeviceHandles[i],
+ sizeof(DeviceHandles[i]));
+ if (!NT_SUCCESS(Status))
+ {
+ /* Free the array and fail */
+ BlMmFreeHeap(DeviceHandles);
+ break;
+ }
+
+ /* Create an entry for this device*/
+ Status = BlockIoEfiCreateDeviceEntry(&DeviceEntry, DeviceHandles[i]);
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+
+ /* Add the device entry to the device table */
+ Status = BlTblSetEntry(&BlockIoDeviceTable,
+ &BlockIoDeviceTableEntries,
+ DeviceEntry,
+ &Id,
+ TblDoNotPurgeEntry);
+ if (!NT_SUCCESS(Status))
+ {
+ EfiPrintf(L"Failure path not implemented: %lx\r\n", Status);
+#if 0
+ BlHtDelete(HashTableId, &HashKey);
+#endif
+ /* Free the block I/O device data */
+ BlockIopFreeAllocations(DeviceEntry->DeviceSpecificData);
+
+ /* Free the descriptor */
+ BlMmFreeHeap(DeviceEntry->DeviceDescriptor);
+
+ /* Free the entry */
+ BlMmFreeHeap(DeviceEntry);
+ break;
+ }
+
+ /* Does this device match what we're looking for? */
+ DeviceMatch = BlpDeviceCompare(DeviceEntry->DeviceDescriptor, Device);
+ if (DeviceMatch)
+ {
+ /* Yep, return the data back */
+ RtlCopyMemory(BlockIoDevice,
+ DeviceEntry->DeviceSpecificData,
+ sizeof(*BlockIoDevice));
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ }
+
+ /* Free the device handle buffer array */
+ BlMmFreeHeap(DeviceHandles);
+
+ /* Return status */
+ return Status;
+}
+
+BOOLEAN
+BlockIoDeviceTableCompare (
+ _In_ PVOID Entry,
+ _In_ PVOID Argument1,
+ _In_ PVOID Argument2,
+ _In_ PVOID Argument3,
+ _In_ PVOID Argument4
+ )
+{
+ PBL_DEVICE_ENTRY DeviceEntry = (PBL_DEVICE_ENTRY)Entry;
+ PBL_DEVICE_DESCRIPTOR Device = (PBL_DEVICE_DESCRIPTOR)Argument1;
+
+ /* Compare the two devices */
+ return BlpDeviceCompare(DeviceEntry->DeviceDescriptor, Device);
+}
+
+NTSTATUS
+BlockIoOpen (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ PBL_DEVICE_ENTRY DeviceEntry
+ )
+{
+ NTSTATUS Status;
+ PBL_BLOCK_DEVICE BlockDevice;
+ PBL_DEVICE_ENTRY FoundDeviceEntry;
+ ULONG Dummy;
+
+ /* Check if the block I/O manager is initialized */
+ if (!BlockIoInitialized)
+ {
+ /* First call, initialize it now */
+ Status = BlockIopInitialize();
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed to initialize block I/O */
+ return Status;
+ }
+ }
+
+ /* Copy a function table for block I/O devices */
+ RtlCopyMemory(&DeviceEntry->Callbacks,
+ &BlockIoDeviceFunctionTable,
+ sizeof(DeviceEntry->Callbacks));
+
+ /* Allocate a block I/O device */
+ BlockDevice = BlMmAllocateHeap(sizeof(*BlockDevice));
+ if (!BlockDevice)
+ {
+ return STATUS_NO_MEMORY;
+ }
+
+ /* Set this as the device-specific data for this device entry */
+ Status = STATUS_SUCCESS;
+ DeviceEntry->DeviceSpecificData = BlockDevice;
+
+ /* Check if we already have this device in our device table */
+ FoundDeviceEntry = BlTblFindEntry(BlockIoDeviceTable,
+ BlockIoDeviceTableEntries,
+ &Dummy,
+ BlockIoDeviceTableCompare,
+ Device,
+ NULL,
+ NULL,
+ NULL);
+ if (FoundDeviceEntry)
+ {
+ /* We already found a device, so copy its device data and callbacks */
+ RtlCopyMemory(BlockDevice, FoundDeviceEntry->DeviceSpecificData,
sizeof(*BlockDevice));
+ RtlCopyMemory(&DeviceEntry->Callbacks,
+ &FoundDeviceEntry->Callbacks,
+ sizeof(DeviceEntry->Callbacks));
+ return Status;
+ }
+
+ /* Zero out the device for now */
+ RtlZeroMemory(BlockDevice, sizeof(*BlockDevice));
+
+ /* Is this a disk? */
+ if (Device->DeviceType == DiskDevice)
+ {
+ /* What type of disk is it? */
+ switch (Device->Local.Type)
+ {
+ /* Is it a raw physical disk? */
+ case LocalDevice:
+ case FloppyDevice:
+ case CdRomDevice:
+ /* Open a disk device */
+ Status = DiskDeviceFunctionTable.Open(Device, DeviceEntry);
+ break;
+
+ /* Is it a RAM disk? */
+ case RamDiskDevice:
+ /* Open a RAM disk */
+ Status = RamDiskDeviceFunctionTable.Open(Device, DeviceEntry);
+ break;
+
+ /* Is it a file? */
+ case FileDevice:
+ /* Open a file */
+ Status = FileDeviceFunctionTable.Open(Device, DeviceEntry);
+ break;
+
+ /* Is it a VHD? */
+ case VirtualDiskDevice:
+ /* Open a virtual disk */
+ Status = VirtualDiskDeviceFunctionTable.Open(Device, DeviceEntry);
+ break;
+
+ /* Is it something else? */
+ default:
+ /* Not supported */
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ }
+ else if ((Device->DeviceType == LegacyPartitionDevice) ||
+ (Device->DeviceType == PartitionDevice))
+ {
+ /* This is a partition on a disk, open it as such */
+ Status = PartitionDeviceFunctionTable.Open(Device, DeviceEntry);
+ }
+ else
+ {
+ /* Other devices are not supported */
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ /* Check for failure */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Free any allocations for this device */
+ BlockIopFreeAllocations(BlockDevice);
+ }
+
+ /* Return back to the caller */
+ return Status;
+}
+
+NTSTATUS
+BlpDeviceResolveLocate (
+ _In_ PBL_DEVICE_DESCRIPTOR InputDevice,
+ _Out_ PBL_DEVICE_DESCRIPTOR* LocateDevice
+ )
+{
+ EfiPrintf(L"Not implemented!\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+BlDeviceClose (
+ _In_ ULONG DeviceId
+ )
+{
+ PBL_DEVICE_ENTRY DeviceEntry;
+
+ /* Validate the device ID */
+ if (DmTableEntries <= DeviceId)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Make sure there's a device there */
+ DeviceEntry = DmDeviceTable[DeviceId];
+ if (DeviceEntry == NULL)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Make sure the device is active */
+ if (!(DeviceEntry->Flags & 1))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Drop a reference and check if it's the last one */
+ DeviceEntry->ReferenceCount--;
+ if (!DeviceEntry->ReferenceCount)
+ {
+ /* Mark the device as inactive */
+ DeviceEntry->Flags = ~1;
+ }
+
+ /* We're good */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+BlpDeviceOpen (
+ _In_ PBL_DEVICE_DESCRIPTOR Device,
+ _In_ ULONG Flags,
+ _In_ ULONG Unknown,
+ _Out_ PULONG DeviceId
+ )
+{
+ NTSTATUS Status;
+ PBL_DEVICE_ENTRY DeviceEntry;
+ PBL_DEVICE_DESCRIPTOR LocateDeviceDescriptor;
+ PBL_REGISTERED_DEVICE RegisteredDevice;
+ PLIST_ENTRY NextEntry, ListHead;
+
+ DeviceEntry = NULL;
+
+ /* Check for missing parameters */
+ if (!(Device) || !(DeviceId) || !(Device->Size))
+ {
+ /* Bail out */
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quickie;
+ }
+
+ /* Check for unsupported flags */
+ if (!(Flags & 3))
+ {
+ /* Bail out */
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quickie;
+ }
+
+ /* Check if the boot device is being opened */
+ if (Device->DeviceType == BootDevice)
+ {
+ /* Select it */
+ Device = BlpBootDevice;
+ }
+
+ /* Check if the 'locate' device is being opened */
+ if (Device->DeviceType == LocateDevice)
+ {
+ /* Go find it */
+ Status = BlpDeviceResolveLocate(Device, &LocateDeviceDescriptor);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Not found, bail out */
+ goto Quickie;
+ }
+
+ /* Select it */
+ Device = LocateDeviceDescriptor;
+ }
+
+ /* Check if the device isn't ready yet */
+ if (Device->Flags & 1)
+ {
+ /* Return a failure */
+ Status = STATUS_DEVICE_NOT_READY;
+ goto Quickie;
+ }
+
+ /* Check if we already have an entry for the device */
+ DeviceEntry = BlTblFindEntry(DmDeviceTable,
+ DmTableEntries,
+ DeviceId,
+ DeviceTableCompare,
+ Device,
+ &Flags,
+ &Unknown,
+ NULL);
+ if (DeviceEntry)
+ {
+ /* Return it, taking a reference on it */
+ *DeviceId = DeviceEntry->DeviceId;
+ ++DeviceEntry->ReferenceCount;
+ DeviceEntry->Flags |= 1;
+ return STATUS_SUCCESS;
+ }
+
+ /* We don't, allocate one */
+ DeviceEntry = BlMmAllocateHeap(sizeof(*DeviceEntry));
+ if (!DeviceEntry)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Quickie;
+ }
+
+ /* Fill it out */
+ RtlZeroMemory(DeviceEntry, sizeof(*DeviceEntry));
+ DeviceEntry->ReferenceCount = 1;
+ DeviceEntry->Flags |= 7;
+ DeviceEntry->Unknown = Unknown;
+
+ /* Save flag 8 if needed */
+ if (Flags & 8)
+ {
+ DeviceEntry->Flags |= 8;
+ }
+
+ /* Allocate a device descriptor for the device */
+ DeviceEntry->DeviceDescriptor = BlMmAllocateHeap(Device->Size);
+ if (!DeviceEntry->DeviceDescriptor)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Quickie;
+ }
+
+ /* Copy the descriptor that was passed in */
+ RtlCopyMemory(DeviceEntry->DeviceDescriptor, Device, Device->Size);
+
+ /* Now loop the list of dynamically registered devices */
+ ListHead = &DmRegisteredDevices;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the device */
+ RegisteredDevice = CONTAINING_RECORD(NextEntry,
+ BL_REGISTERED_DEVICE,
+ ListEntry);
+
+ /* Open the device */
+ Status = RegisteredDevice->Callbacks.Open(Device, DeviceEntry);
+ if (NT_SUCCESS(Status))
+ {
+ /* The device was opened, so we have the right one */
+ goto DeviceOpened;
+ }
+
+ /* Nope, keep trying */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Well, it wasn't a dynamic device. Is it a block device? */
+ if ((Device->DeviceType == PartitionDevice) ||
+ (Device->DeviceType == DiskDevice) ||
+ (Device->DeviceType == LegacyPartitionDevice))
+ {
+ /* Call the Block I/O handler */
+ Status = BlockIoDeviceFunctionTable.Open(Device, DeviceEntry);
+ }
+ else if (Device->DeviceType == SerialDevice)
+ {
+ /* It's a serial device, call the serial device handler */
+ Status = SerialPortFunctionTable.Open(Device, DeviceEntry);
+ }
+ else if (Device->DeviceType == UdpDevice)
+ {
+ /* It's a network device, call the UDP device handler */
+ Status = UdpFunctionTable.Open(Device, DeviceEntry);
+ }
+ else
+ {
+ /* Unsupported type of device */
+ Status = STATUS_NOT_IMPLEMENTED;
+ }
+
+ /* Check if the device was opened successfuly */
+ if (NT_SUCCESS(Status))
+ {
+DeviceOpened:
+ /* Save the entry in the device table */
+ Status = BlTblSetEntry(&DmDeviceTable,
+ &DmTableEntries,
+ DeviceEntry,
+ DeviceId,
+ DeviceTablePurge);
+ if (NT_SUCCESS(Status))
+ {
+ /* It worked -- return the ID in the table to the caller */
+ DeviceEntry->DeviceId = *DeviceId;
+ return STATUS_SUCCESS;
+ }
+ }
+
+Quickie:
+ /* Failure path -- did we allocate a device entry? */
+ if (DeviceEntry)
+ {
+ /* Yep -- did it have a descriptor? */
+ if (DeviceEntry->DeviceDescriptor)
+ {
+ /* Free it */
+ BlMmFreeHeap(DeviceEntry->DeviceDescriptor);
+ }
+
+ /* Free the entry */
+ BlMmFreeHeap(DeviceEntry);
+ }
+
+ /* Return the failure */
+ return Status;
+}
+
NTSTATUS
BlpDeviceInitialize (
VOID
@@ -52,7 +1566,6 @@
{
/* Clear it */
RtlZeroMemory(DmDeviceTable, DmTableEntries * sizeof(PVOID));
-
#if 0
/* Initialize BitLocker support */
Status = FvebInitialize();
Modified: trunk/reactos/boot/environ/lib/io/display/display.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/io/displa…
==============================================================================
--- trunk/reactos/boot/environ/lib/io/display/display.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/io/display/display.c [iso-8859-1] Wed Sep 9 05:48:50
2015
@@ -66,7 +66,7 @@
InitializeListHead(&BfiFontFileListHead);
/* Allocate the font rectangle */
- BfiGraphicsRectangle = BlMmAllocateHeap(0x5A);
+ BfiGraphicsRectangle = BlMmAllocateHeap(90);
if (!BfiGraphicsRectangle)
{
return STATUS_NO_MEMORY;
Modified: trunk/reactos/boot/environ/lib/io/display/emscons.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/io/displa…
==============================================================================
--- trunk/reactos/boot/environ/lib/io/display/emscons.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/io/display/emscons.c [iso-8859-1] Wed Sep 9 05:48:50
2015
@@ -44,7 +44,7 @@
/* Construct it */
Status = ConsoleRemoteConstruct(RemoteConsole);
- if (Status < 0)
+ if (!NT_SUCCESS(Status));
{
/* Failed to construct it, delete it */
BlMmFreeHeap(RemoteConsole);
Modified: trunk/reactos/boot/environ/lib/io/io.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/io/io.c?r…
==============================================================================
--- trunk/reactos/boot/environ/lib/io/io.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/io/io.c [iso-8859-1] Wed Sep 9 05:48:50 2015
@@ -16,6 +16,20 @@
PVOID* IoMgrDestroyRoutineTable;
/* FUNCTIONS *****************************************************************/
+
+NTSTATUS
+BlpIoRegisterDestroyRoutine (
+ _In_ PBL_IO_DESTROY_ROUTINE DestroyRoutine
+ )
+{
+ ULONG Id;
+
+ return BlTblSetEntry(&IoMgrDestroyRoutineTable,
+ &IoMgrRoutineEntries,
+ DestroyRoutine,
+ &Id,
+ TblDoNotPurgeEntry);
+}
NTSTATUS
BlpIoInitialize (
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] Wed Sep 9 05:48:50 2015
@@ -188,6 +188,455 @@
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
Modified: trunk/reactos/boot/environ/lib/mm/blkalloc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/mm/blkall…
==============================================================================
--- trunk/reactos/boot/environ/lib/mm/blkalloc.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/mm/blkalloc.c [iso-8859-1] Wed Sep 9 05:48:50 2015
@@ -12,17 +12,260 @@
/* 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 (
Modified: trunk/reactos/boot/environ/lib/mm/heapalloc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/mm/heapal…
==============================================================================
--- trunk/reactos/boot/environ/lib/mm/heapalloc.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/mm/heapalloc.c [iso-8859-1] Wed Sep 9 05:48:50 2015
@@ -146,7 +146,7 @@
}
/* We do not -- allocate one */
- Status = MmPapAllocatePagesInRange((PULONG)&HeapBase,
+ Status = MmPapAllocatePagesInRange((PVOID*)&HeapBase,
BlLoaderHeap,
AlignedSize >> PAGE_SHIFT,
HapAllocationAttributes,
@@ -673,6 +673,13 @@
}
/* 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 */
Modified: trunk/reactos/boot/environ/lib/mm/pagealloc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/mm/pageal…
==============================================================================
--- trunk/reactos/boot/environ/lib/mm/pagealloc.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/mm/pagealloc.c [iso-8859-1] Wed Sep 9 05:48:50 2015
@@ -391,7 +391,7 @@
NTSTATUS
MmPapAllocatePagesInRange (
- _Inout_ PULONG PhysicalAddress,
+ _Inout_ PVOID* PhysicalAddress,
_In_ BL_MEMORY_TYPE MemoryType,
_In_ ULONGLONG Pages,
_In_ ULONG Attributes,
@@ -425,7 +425,7 @@
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 @@
Type);
/* Return the allocated address */
- *PhysicalAddress = BaseAddress.LowPart;
+ *PhysicalAddress = (PVOID)BaseAddress.LowPart;
}
Exit: