diff --git a/reactos/boot/environ/app/bootmgr/bootmgr.c b/reactos/boot/environ/app/bootmgr/bootmgr.c index 69f09021145..dc938d60ea8 100644 --- a/reactos/boot/environ/app/bootmgr/bootmgr.c +++ b/reactos/boot/environ/app/bootmgr/bootmgr.c @@ -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) diff --git a/reactos/boot/environ/app/bootmgr/efiemu.c b/reactos/boot/environ/app/bootmgr/efiemu.c index a249c663f71..40b94872b08 100644 --- a/reactos/boot/environ/app/bootmgr/efiemu.c +++ b/reactos/boot/environ/app/bootmgr/efiemu.c @@ -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 */ diff --git a/reactos/boot/environ/include/bl.h b/reactos/boot/environ/include/bl.h index 41f94a09585..33fda87418b 100644 --- a/reactos/boot/environ/include/bl.h +++ b/reactos/boot/environ/include/bl.h @@ -28,6 +28,7 @@ #include #include #include +#include /* 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[]; diff --git a/reactos/boot/environ/include/efi/BlockIo.h b/reactos/boot/environ/include/efi/BlockIo.h new file mode 100644 index 00000000000..4bc2109db12 --- /dev/null +++ b/reactos/boot/environ/include/efi/BlockIo.h @@ -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.
+ 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 diff --git a/reactos/boot/environ/lib/bootlib.c b/reactos/boot/environ/lib/bootlib.c index 512385dc999..fbbb946680a 100644 --- a/reactos/boot/environ/lib/bootlib.c +++ b/reactos/boot/environ/lib/bootlib.c @@ -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; +} diff --git a/reactos/boot/environ/lib/firmware/efi/firmware.c b/reactos/boot/environ/lib/firmware/efi/firmware.c index a1ce37956e3..6bf33597d2a 100644 --- a/reactos/boot/environ/lib/firmware/efi/firmware.c +++ b/reactos/boot/environ/lib/firmware/efi/firmware.c @@ -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, diff --git a/reactos/boot/environ/lib/io/device.c b/reactos/boot/environ/lib/io/device.c index 31b84283432..1687c5a1a2b 100644 --- a/reactos/boot/environ/lib/io/device.c +++ b/reactos/boot/environ/lib/io/device.c @@ -29,6 +29,1520 @@ BL_DEVICE_INFORMATION DmDeviceIoInformation; /* 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 @@ BlpDeviceInitialize ( { /* Clear it */ RtlZeroMemory(DmDeviceTable, DmTableEntries * sizeof(PVOID)); - #if 0 /* Initialize BitLocker support */ Status = FvebInitialize(); diff --git a/reactos/boot/environ/lib/io/display/display.c b/reactos/boot/environ/lib/io/display/display.c index 82f77bffba8..21e80fc169d 100644 --- a/reactos/boot/environ/lib/io/display/display.c +++ b/reactos/boot/environ/lib/io/display/display.c @@ -66,7 +66,7 @@ DsppInitialize ( InitializeListHead(&BfiFontFileListHead); /* Allocate the font rectangle */ - BfiGraphicsRectangle = BlMmAllocateHeap(0x5A); + BfiGraphicsRectangle = BlMmAllocateHeap(90); if (!BfiGraphicsRectangle) { return STATUS_NO_MEMORY; diff --git a/reactos/boot/environ/lib/io/display/emscons.c b/reactos/boot/environ/lib/io/display/emscons.c index 6610324b463..96607dd333d 100644 --- a/reactos/boot/environ/lib/io/display/emscons.c +++ b/reactos/boot/environ/lib/io/display/emscons.c @@ -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); diff --git a/reactos/boot/environ/lib/io/io.c b/reactos/boot/environ/lib/io/io.c index 83c90f71ac3..4138b498c52 100644 --- a/reactos/boot/environ/lib/io/io.c +++ b/reactos/boot/environ/lib/io/io.c @@ -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 diff --git a/reactos/boot/environ/lib/misc/util.c b/reactos/boot/environ/lib/misc/util.c index 3b67fb35b1d..2bd951a3ae6 100644 --- a/reactos/boot/environ/lib/misc/util.c +++ b/reactos/boot/environ/lib/misc/util.c @@ -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 diff --git a/reactos/boot/environ/lib/mm/blkalloc.c b/reactos/boot/environ/lib/mm/blkalloc.c index 15496388322..bbf996d5d70 100644 --- a/reactos/boot/environ/lib/mm/blkalloc.c +++ b/reactos/boot/environ/lib/mm/blkalloc.c @@ -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 diff --git a/reactos/boot/environ/lib/mm/heapalloc.c b/reactos/boot/environ/lib/mm/heapalloc.c index 28889d41116..9bdc92c9851 100644 --- a/reactos/boot/environ/lib/mm/heapalloc.c +++ b/reactos/boot/environ/lib/mm/heapalloc.c @@ -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 */ diff --git a/reactos/boot/environ/lib/mm/pagealloc.c b/reactos/boot/environ/lib/mm/pagealloc.c index 00697b766cd..120f5014e84 100644 --- a/reactos/boot/environ/lib/mm/pagealloc.c +++ b/reactos/boot/environ/lib/mm/pagealloc.c @@ -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: