2015-09-06 21:29:41 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING.ARM in the top level directory
|
|
|
|
* PROJECT: ReactOS UEFI Boot Library
|
|
|
|
* FILE: boot/environ/lib/io/device.c
|
|
|
|
* PURPOSE: Boot Library Device Management Routines
|
|
|
|
* PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
|
|
|
#include "bl.h"
|
|
|
|
|
|
|
|
/* DATA VARIABLES ************************************************************/
|
|
|
|
|
2015-09-10 04:01:41 +00:00
|
|
|
typedef struct _BL_DEVICE_IO_INFORMATION
|
2015-09-06 21:29:41 +00:00
|
|
|
{
|
2015-09-10 05:19:50 +00:00
|
|
|
ULONGLONG ReadCount;
|
|
|
|
ULONGLONG WriteCount;
|
2015-09-10 04:01:41 +00:00
|
|
|
} BL_DEVICE_IO_INFORMATION, *PBL_DEVICE_IO_INFORMATION;
|
2015-09-06 21:29:41 +00:00
|
|
|
|
|
|
|
LIST_ENTRY DmRegisteredDevices;
|
|
|
|
ULONG DmTableEntries;
|
|
|
|
LIST_ENTRY DmRegisteredDevices;
|
|
|
|
PVOID* DmDeviceTable;
|
|
|
|
|
2015-09-10 04:01:41 +00:00
|
|
|
BL_DEVICE_IO_INFORMATION DmDeviceIoInformation;
|
2015-09-06 21:29:41 +00:00
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2015-09-09 05:48:50 +00:00
|
|
|
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
|
|
|
|
);
|
|
|
|
|
2015-09-10 04:01:41 +00:00
|
|
|
NTSTATUS
|
|
|
|
BlockIoGetInformation (
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry,
|
|
|
|
_Out_ PBL_DEVICE_INFORMATION DeviceInformation
|
|
|
|
);
|
|
|
|
|
2015-09-10 05:19:50 +00:00
|
|
|
NTSTATUS
|
|
|
|
BlockIoSetInformation (
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry,
|
|
|
|
_Out_ PBL_DEVICE_INFORMATION DeviceInformation
|
|
|
|
);
|
|
|
|
|
2015-09-10 23:13:31 +00:00
|
|
|
NTSTATUS
|
|
|
|
BlockIoRead (
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry,
|
|
|
|
_In_ PVOID Buffer,
|
|
|
|
_In_ ULONG Size,
|
|
|
|
_Out_ PULONG BytesRead
|
|
|
|
);
|
|
|
|
|
2015-09-09 05:48:50 +00:00
|
|
|
BL_DEVICE_CALLBACKS BlockIoDeviceFunctionTable =
|
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
BlockIoOpen,
|
|
|
|
NULL,
|
2015-09-10 23:13:31 +00:00
|
|
|
BlockIoRead,
|
2015-09-10 04:01:41 +00:00
|
|
|
NULL,
|
2015-09-10 05:19:50 +00:00
|
|
|
BlockIoGetInformation,
|
|
|
|
BlockIoSetInformation
|
2015-09-09 05:48:50 +00:00
|
|
|
};
|
|
|
|
|
2015-09-10 23:13:31 +00:00
|
|
|
NTSTATUS
|
|
|
|
BlockIoFirmwareWrite (
|
|
|
|
_In_ PBL_BLOCK_DEVICE BlockDevice,
|
|
|
|
_In_ PVOID Buffer,
|
|
|
|
_In_ ULONGLONG Block,
|
|
|
|
_In_ ULONGLONG BlockCount
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
BlockIoFirmwareRead (
|
|
|
|
_In_ PBL_BLOCK_DEVICE BlockDevice,
|
|
|
|
_In_ PVOID Buffer,
|
|
|
|
_In_ ULONGLONG Block,
|
|
|
|
_In_ ULONGLONG BlockCount
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
EFI_BLOCK_IO *BlockProtocol;
|
|
|
|
BL_ARCH_MODE OldMode;
|
|
|
|
EFI_STATUS EfiStatus;
|
|
|
|
ULONG FailureCount;
|
|
|
|
|
|
|
|
for (FailureCount = 0, Status = STATUS_SUCCESS;
|
|
|
|
FailureCount < 2 && NT_SUCCESS(Status);
|
|
|
|
FailureCount++)
|
|
|
|
{
|
|
|
|
BlockProtocol = BlockDevice->Protocol;
|
|
|
|
|
|
|
|
OldMode = CurrentExecutionContext->Mode;
|
|
|
|
if (CurrentExecutionContext->Mode != 1)
|
|
|
|
{
|
|
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-09-11 04:33:24 +00:00
|
|
|
//EfiPrintf(L"EFI Reading BLOCK %d off media %lx (%d blocks)\r\n",
|
|
|
|
//Block, BlockProtocol->Media->MediaId, BlockCount);
|
2015-09-10 23:13:31 +00:00
|
|
|
EfiStatus = BlockProtocol->ReadBlocks(BlockProtocol,
|
|
|
|
BlockProtocol->Media->MediaId,
|
|
|
|
Block,
|
|
|
|
BlockProtocol->Media->BlockSize * BlockCount,
|
|
|
|
Buffer);
|
|
|
|
if (EfiStatus == EFI_SUCCESS)
|
|
|
|
{
|
2015-09-11 04:33:24 +00:00
|
|
|
//EfiPrintf(L"EFI Read complete into buffer\r\n");
|
|
|
|
//EfiPrintf(L"Buffer data: %lx %lx %lx %lx\r\n", *(PULONG)Buffer, *((PULONG)Buffer + 1), *((PULONG)Buffer + 2), *((PULONG)Buffer + 3));
|
2015-09-10 23:13:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (OldMode != 1)
|
|
|
|
{
|
|
|
|
BlpArchSwitchContext(OldMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = EfiGetNtStatusCode(EfiStatus);
|
|
|
|
if (Status != STATUS_MEDIA_CHANGED)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
EfiCloseProtocol(BlockDevice->Handle, &EfiBlockIoProtocol);
|
|
|
|
|
|
|
|
Status = EfiOpenProtocol(BlockDevice->Handle,
|
|
|
|
&EfiBlockIoProtocol,
|
|
|
|
(PVOID*)BlockDevice->Protocol);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
BlockIopFirmwareOperation (
|
|
|
|
PBL_DEVICE_ENTRY DeviceEntry,
|
|
|
|
_In_ PVOID Buffer,
|
|
|
|
_In_ ULONGLONG Block,
|
|
|
|
_In_ ULONGLONG BlockCount,
|
|
|
|
_In_ ULONG OperationType
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ULONG FailureCount;
|
|
|
|
PBL_BLOCK_DEVICE BlockDevice;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
BlockDevice = DeviceEntry->DeviceSpecificData;
|
|
|
|
|
|
|
|
if (OperationType == 1)
|
|
|
|
{
|
|
|
|
for (FailureCount = 0; FailureCount < 3; FailureCount++)
|
|
|
|
{
|
|
|
|
Status = BlockIoFirmwareWrite(BlockDevice, Buffer, Block, BlockCount);
|
|
|
|
if (Status >= 0)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (FailureCount = 0; FailureCount < 3; FailureCount++)
|
|
|
|
{
|
|
|
|
Status = BlockIoFirmwareRead(BlockDevice, Buffer, Block, BlockCount);
|
|
|
|
if (Status >= 0)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
BlockIopFreeAlignedBuffer (
|
|
|
|
_Inout_ PVOID* Buffer,
|
|
|
|
_Inout_ PULONG BufferSize
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
if (*BufferSize)
|
|
|
|
{
|
|
|
|
EfiPrintf(L"Aligned free not yet implemented\r\n");
|
|
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
//Status = MmPapFreePages(*Buffer, 1);
|
|
|
|
|
|
|
|
*Buffer = NULL;
|
|
|
|
*BufferSize = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
BlockIopAllocateAlignedBuffer (
|
|
|
|
_Inout_ PVOID* Buffer,
|
|
|
|
_Inout_ PULONG BufferSize,
|
|
|
|
_In_ ULONG Size,
|
|
|
|
_In_ ULONG Alignment
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
if (!Alignment)
|
|
|
|
{
|
|
|
|
++Alignment;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
if ((Size > *BufferSize) || ((Alignment - 1) & (ULONG_PTR)*Buffer))
|
|
|
|
{
|
|
|
|
BlockIopFreeAlignedBuffer(Buffer, BufferSize);
|
|
|
|
|
|
|
|
*BufferSize = ROUND_TO_PAGES(Size);
|
|
|
|
|
|
|
|
Status = MmPapAllocatePagesInRange(Buffer,
|
|
|
|
BlLoaderDeviceMemory,
|
|
|
|
*BufferSize >> PAGE_SHIFT,
|
|
|
|
0,
|
|
|
|
Alignment >> PAGE_SHIFT,
|
|
|
|
NULL,
|
|
|
|
0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
*BufferSize = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
BlockIopReadUsingPrefetch (
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry,
|
|
|
|
_In_ PVOID Buffer,
|
|
|
|
_In_ ULONG BlockCount
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EfiPrintf(L"No prefetch support\r\n");
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
BlockIopOperation (
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry,
|
|
|
|
_In_ PVOID Buffer,
|
|
|
|
_In_ ULONG BlockCount,
|
|
|
|
_In_ ULONG OperationType
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PBL_BLOCK_DEVICE BlockDevice;
|
|
|
|
ULONG BufferSize, Alignment;
|
|
|
|
ULONGLONG Offset;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
BlockDevice = DeviceEntry->DeviceSpecificData;
|
|
|
|
BufferSize = BlockDevice->BlockSize * BlockCount;
|
|
|
|
Offset = BlockDevice->Block + BlockDevice->StartOffset;
|
|
|
|
if ((BlockDevice->LastBlock + 1) < (BlockDevice->Block + BlockCount))
|
|
|
|
{
|
|
|
|
EfiPrintf(L"Read past end of device\r\n");
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
Alignment = BlockDevice->Alignment;
|
2016-01-07 05:30:18 +00:00
|
|
|
if (!(Alignment) || !((Alignment - 1) & (ULONG_PTR)Buffer))
|
2015-09-10 23:13:31 +00:00
|
|
|
{
|
|
|
|
Status = BlockIopFirmwareOperation(DeviceEntry,
|
|
|
|
Buffer,
|
|
|
|
Offset,
|
|
|
|
BlockCount,
|
|
|
|
OperationType);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
EfiPrintf(L"EFI op failed: %lx\r\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = BlockIopAllocateAlignedBuffer(&BlockIopAlignedBuffer,
|
|
|
|
&BlockIopAlignedBufferSize,
|
|
|
|
BufferSize,
|
|
|
|
BlockDevice->Alignment);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
EfiPrintf(L"No memory for align\r\n");
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OperationType == 1)
|
|
|
|
{
|
|
|
|
RtlCopyMemory(BlockIopAlignedBuffer, Buffer, BufferSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = BlockIopFirmwareOperation(DeviceEntry,
|
|
|
|
BlockIopAlignedBuffer,
|
|
|
|
Offset,
|
|
|
|
BlockCount,
|
|
|
|
OperationType);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!OperationType)
|
|
|
|
{
|
|
|
|
RtlCopyMemory(Buffer, BlockIopAlignedBuffer, BufferSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
BlockIopReadWriteVirtualDevice (
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry,
|
|
|
|
_In_ PVOID Buffer,
|
|
|
|
_In_ ULONG Size,
|
|
|
|
_In_ ULONG Operation,
|
|
|
|
_Out_ PULONG BytesRead
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
BlockIopReadPhysicalDevice (
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry,
|
|
|
|
_In_ PVOID Buffer,
|
|
|
|
_In_ ULONG Size,
|
|
|
|
_Out_ PULONG BytesRead
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PBL_BLOCK_DEVICE BlockDevice;
|
|
|
|
PVOID ReadBuffer; // edi@1
|
|
|
|
ULONGLONG OffsetEnd, AlignedOffsetEnd, Offset;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
BlockDevice = DeviceEntry->DeviceSpecificData;
|
|
|
|
ReadBuffer = Buffer;
|
|
|
|
OffsetEnd = Size + BlockDevice->Offset;
|
|
|
|
if (OffsetEnd < Size)
|
|
|
|
{
|
|
|
|
OffsetEnd = -1;
|
|
|
|
return STATUS_INTEGER_OVERFLOW;
|
|
|
|
}
|
|
|
|
|
|
|
|
AlignedOffsetEnd = ~(BlockDevice->BlockSize - 1) & (OffsetEnd + BlockDevice->BlockSize - 1);
|
|
|
|
if (AlignedOffsetEnd < OffsetEnd)
|
|
|
|
{
|
|
|
|
return STATUS_INTEGER_OVERFLOW;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((BlockDevice->Offset) || (Size != AlignedOffsetEnd))
|
|
|
|
{
|
|
|
|
Status = BlockIopAllocateAlignedBuffer(&BlockIopReadBlockBuffer,
|
|
|
|
&BlockIopReadBlockBufferSize,
|
|
|
|
AlignedOffsetEnd,
|
|
|
|
BlockDevice->Alignment);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
EfiPrintf(L"Failed to allocate buffer: %lx\r\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReadBuffer = BlockIopReadBlockBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
Offset = AlignedOffsetEnd / BlockDevice->BlockSize;
|
|
|
|
|
|
|
|
if (BlockDevice->Unknown & 2)
|
|
|
|
{
|
|
|
|
Status = BlockIopReadUsingPrefetch(DeviceEntry,
|
|
|
|
ReadBuffer,
|
|
|
|
AlignedOffsetEnd / BlockDevice->BlockSize);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
goto ReadComplete;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = BlockIopOperation(DeviceEntry, ReadBuffer, Offset, 0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
EfiPrintf(L"Block I/O failed:%lx\r\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockDevice->Block += Offset;
|
|
|
|
|
|
|
|
ReadComplete:
|
|
|
|
if (ReadBuffer != Buffer)
|
|
|
|
{
|
|
|
|
RtlCopyMemory(Buffer,
|
|
|
|
(PVOID)((ULONG_PTR)ReadBuffer +
|
|
|
|
(ULONG_PTR)BlockDevice->Offset),
|
|
|
|
Size);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BytesRead)
|
|
|
|
{
|
|
|
|
*BytesRead = Size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
BlockIopBlockInformationCheck (
|
|
|
|
_In_ PBL_BLOCK_DEVICE BlockDevice,
|
|
|
|
_In_opt_ PULONG DesiredSize,
|
|
|
|
_Out_opt_ PULONG Size,
|
|
|
|
_Out_opt_ PULONG OutputAdjustedSize
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ULONG RealSize;
|
|
|
|
ULONGLONG Offset, LastOffset, RemainingOffset, MaxOffset;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
RealSize = 0;
|
|
|
|
|
|
|
|
Offset = (BlockDevice->Offset * BlockDevice->BlockSize) + BlockDevice->Block;
|
|
|
|
|
|
|
|
if (Offset > ((BlockDevice->LastBlock + 1) * BlockDevice->BlockSize))
|
|
|
|
{
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
goto Quickie;
|
|
|
|
}
|
|
|
|
|
|
|
|
LastOffset = (BlockDevice->LastBlock * BlockDevice->BlockSize) + BlockDevice->BlockSize - 1;
|
|
|
|
|
|
|
|
MaxOffset = BlockDevice->LastBlock;
|
|
|
|
if (MaxOffset < BlockDevice->BlockSize)
|
|
|
|
{
|
|
|
|
MaxOffset = BlockDevice->BlockSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LastOffset < MaxOffset)
|
|
|
|
{
|
|
|
|
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
goto Quickie;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Offset > LastOffset)
|
|
|
|
{
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
goto Quickie;
|
|
|
|
}
|
|
|
|
|
|
|
|
RemainingOffset = LastOffset - Offset + 1;
|
|
|
|
|
|
|
|
if (DesiredSize != FALSE)
|
|
|
|
{
|
|
|
|
RealSize = *DesiredSize;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RealSize = ULONG_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (RemainingOffset < RealSize)
|
|
|
|
{
|
|
|
|
if (Size == FALSE)
|
|
|
|
{
|
|
|
|
RealSize = 0;
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
goto Quickie;
|
|
|
|
}
|
|
|
|
|
|
|
|
RealSize = RemainingOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
Quickie:
|
|
|
|
if (Size)
|
|
|
|
{
|
|
|
|
*Size = RealSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
BlockIoRead (
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry,
|
|
|
|
_In_ PVOID Buffer,
|
|
|
|
_In_ ULONG Size,
|
|
|
|
_Out_ PULONG BytesRead
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PBL_BLOCK_DEVICE BlockDevice;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
BlockDevice = DeviceEntry->DeviceSpecificData;
|
|
|
|
|
|
|
|
Status = BlockIopBlockInformationCheck(BlockDevice, &Size, BytesRead, &Size);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
if (BlockDevice->DeviceFlags & 4)
|
|
|
|
{
|
|
|
|
Status = BlockIopReadWriteVirtualDevice(DeviceEntry, Buffer, Size, 0, BytesRead);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = BlockIopReadPhysicalDevice(DeviceEntry, Buffer, Size, BytesRead);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (BytesRead)
|
|
|
|
{
|
|
|
|
*BytesRead = 0;
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2015-09-10 05:19:50 +00:00
|
|
|
NTSTATUS
|
|
|
|
BlockIoSetInformation (
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry,
|
|
|
|
_Out_ PBL_DEVICE_INFORMATION DeviceInformation
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PBL_BLOCK_DEVICE BlockDevice;
|
|
|
|
ULONGLONG Offset;
|
|
|
|
|
|
|
|
BlockDevice = DeviceEntry->DeviceSpecificData;
|
|
|
|
|
|
|
|
Offset = DeviceInformation->BlockDeviceInfo.Block * BlockDevice->BlockSize + DeviceInformation->BlockDeviceInfo.Offset;
|
2015-09-10 23:13:31 +00:00
|
|
|
if (Offset > ((BlockDevice->LastBlock + 1) * BlockDevice->BlockSize - 1))
|
2015-09-10 05:19:50 +00:00
|
|
|
{
|
2015-09-10 23:13:31 +00:00
|
|
|
EfiPrintf(L"Invalid offset\r\n");
|
2015-09-10 05:19:50 +00:00
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockDevice->Block = Offset / BlockDevice->BlockSize;
|
|
|
|
BlockDevice->Offset = Offset % BlockDevice->BlockSize;
|
|
|
|
BlockDevice->Unknown = DeviceInformation->BlockDeviceInfo.Unknown;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2015-09-10 04:01:41 +00:00
|
|
|
NTSTATUS
|
|
|
|
BlockIoGetInformation (
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry,
|
|
|
|
_Out_ PBL_DEVICE_INFORMATION DeviceInformation
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PBL_BLOCK_DEVICE BlockDevice;
|
|
|
|
|
|
|
|
BlockDevice = DeviceEntry->DeviceSpecificData;
|
|
|
|
|
|
|
|
RtlCopyMemory(&DeviceInformation->BlockDeviceInfo,
|
|
|
|
BlockDevice,
|
|
|
|
sizeof(DeviceInformation->BlockDeviceInfo));
|
|
|
|
DeviceInformation->DeviceType = DiskDevice;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2015-09-10 05:19:50 +00:00
|
|
|
NTSTATUS
|
|
|
|
BlDeviceSetInformation (
|
|
|
|
_In_ ULONG DeviceId,
|
|
|
|
_Out_ PBL_DEVICE_INFORMATION DeviceInformation
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PBL_DEVICE_ENTRY DeviceEntry;
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* This parameter is not optional */
|
|
|
|
if (!DeviceInformation)
|
2015-09-10 05:19:50 +00:00
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Make sure the device ID is valid */
|
2015-09-10 05:19:50 +00:00
|
|
|
if (DmTableEntries <= DeviceId)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Get the device entry */
|
2015-09-10 05:19:50 +00:00
|
|
|
DeviceEntry = DmDeviceTable[DeviceId];
|
|
|
|
if (!DeviceEntry)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Make sure the device is open */
|
|
|
|
if (!(DeviceEntry->Flags & BL_DEVICE_ENTRY_OPENED))
|
2015-09-10 05:19:50 +00:00
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Set the device information */
|
2015-09-10 05:19:50 +00:00
|
|
|
return DeviceEntry->Callbacks.SetInformation(DeviceEntry, DeviceInformation);
|
|
|
|
}
|
|
|
|
|
2015-09-10 04:01:41 +00:00
|
|
|
NTSTATUS
|
|
|
|
BlDeviceGetInformation (
|
2015-09-10 23:13:31 +00:00
|
|
|
_In_ ULONG DeviceId,
|
2015-09-10 04:01:41 +00:00
|
|
|
_Out_ PBL_DEVICE_INFORMATION DeviceInformation
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PBL_DEVICE_ENTRY DeviceEntry;
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* This parameter is not optional */
|
|
|
|
if (!DeviceInformation)
|
2015-09-10 04:01:41 +00:00
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Make sure the device ID is valid */
|
2015-09-10 04:01:41 +00:00
|
|
|
if (DmTableEntries <= DeviceId)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Get the device entry */
|
2015-09-10 04:01:41 +00:00
|
|
|
DeviceEntry = DmDeviceTable[DeviceId];
|
|
|
|
if (!DeviceEntry)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Make sure the device is open */
|
|
|
|
if (!(DeviceEntry->Flags & BL_DEVICE_ENTRY_OPENED))
|
2015-09-10 04:01:41 +00:00
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Return the device information */
|
2015-09-10 04:01:41 +00:00
|
|
|
DeviceInformation->DeviceType = DeviceEntry->DeviceDescriptor->DeviceType;
|
|
|
|
return DeviceEntry->Callbacks.GetInformation(DeviceEntry, DeviceInformation);
|
|
|
|
}
|
|
|
|
|
2015-09-10 05:19:50 +00:00
|
|
|
NTSTATUS
|
|
|
|
BlDeviceRead (
|
|
|
|
_In_ ULONG DeviceId,
|
|
|
|
_In_ PVOID Buffer,
|
|
|
|
_In_ ULONG Size,
|
2016-01-07 05:14:26 +00:00
|
|
|
_Out_opt_ PULONG BytesRead
|
2015-09-10 05:19:50 +00:00
|
|
|
)
|
|
|
|
{
|
2015-09-10 23:13:31 +00:00
|
|
|
PBL_DEVICE_ENTRY DeviceEntry;
|
2015-09-10 05:19:50 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG BytesTransferred;
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Make sure we have a buffer, and the device ID is valid */
|
2015-09-10 23:13:31 +00:00
|
|
|
if (!(Buffer) || (DmTableEntries <= DeviceId))
|
2015-09-10 05:19:50 +00:00
|
|
|
{
|
2015-09-10 23:13:31 +00:00
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2015-09-10 05:19:50 +00:00
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Get the device entry for it */
|
2015-09-10 23:13:31 +00:00
|
|
|
DeviceEntry = DmDeviceTable[DeviceId];
|
|
|
|
if (!DeviceEntry)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2015-09-10 05:19:50 +00:00
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Make sure this is a device opened for read access */
|
|
|
|
if (!(DeviceEntry->Flags & BL_DEVICE_ENTRY_OPENED) ||
|
|
|
|
!(DeviceEntry->Flags & BL_DEVICE_ENTRY_READ_ACCESS))
|
2015-09-10 23:13:31 +00:00
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
2015-09-10 05:19:50 +00:00
|
|
|
}
|
2015-09-10 23:13:31 +00:00
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Issue the read */
|
|
|
|
Status = DeviceEntry->Callbacks.Read(DeviceEntry,
|
|
|
|
Buffer,
|
|
|
|
Size,
|
|
|
|
&BytesTransferred);
|
2015-09-10 23:13:31 +00:00
|
|
|
if (!DeviceEntry->Unknown)
|
2015-09-10 05:19:50 +00:00
|
|
|
{
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Update performance counters */
|
2015-09-10 23:13:31 +00:00
|
|
|
DmDeviceIoInformation.ReadCount += BytesTransferred;
|
2015-09-10 05:19:50 +00:00
|
|
|
}
|
2015-09-10 23:13:31 +00:00
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Return back how many bytes were read, if caller wants to know */
|
2015-09-10 23:13:31 +00:00
|
|
|
if (BytesRead)
|
|
|
|
{
|
|
|
|
*BytesRead = BytesTransferred;
|
|
|
|
}
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Return read result */
|
2015-09-10 05:19:50 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
BlDeviceReadAtOffset (
|
|
|
|
_In_ ULONG DeviceId,
|
|
|
|
_In_ ULONG Size,
|
|
|
|
_In_ ULONGLONG Offset,
|
|
|
|
_In_ PVOID Buffer,
|
|
|
|
_Out_ PULONG BytesRead
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
BL_DEVICE_INFORMATION DeviceInformation;
|
|
|
|
|
|
|
|
Status = BlDeviceGetInformation(DeviceId, &DeviceInformation);
|
2015-09-10 23:13:31 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2015-09-10 05:19:50 +00:00
|
|
|
{
|
2015-09-10 23:13:31 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2015-09-10 05:19:50 +00:00
|
|
|
|
2015-09-10 23:13:31 +00:00
|
|
|
DeviceInformation.BlockDeviceInfo.Block = Offset / DeviceInformation.BlockDeviceInfo.BlockSize;
|
|
|
|
DeviceInformation.BlockDeviceInfo.Offset = Offset % DeviceInformation.BlockDeviceInfo.BlockSize;
|
|
|
|
Status = BlDeviceSetInformation(DeviceId, &DeviceInformation);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Status = BlDeviceRead(DeviceId, Buffer, Size, BytesRead);
|
2015-09-10 05:19:50 +00:00
|
|
|
}
|
2015-09-10 23:13:31 +00:00
|
|
|
|
2015-09-10 05:19:50 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2015-09-09 05:48:50 +00:00
|
|
|
BOOLEAN
|
|
|
|
BlpDeviceCompare (
|
|
|
|
_In_ PBL_DEVICE_DESCRIPTOR Device1,
|
|
|
|
_In_ PBL_DEVICE_DESCRIPTOR Device2
|
|
|
|
)
|
|
|
|
{
|
|
|
|
BOOLEAN DeviceMatch;
|
|
|
|
ULONG DeviceSize;
|
|
|
|
|
|
|
|
/* Assume failure */
|
|
|
|
DeviceMatch = FALSE;
|
|
|
|
|
2016-01-07 05:14:26 +00:00
|
|
|
/* Check if the two devices exist and are identical in type */
|
2015-09-09 05:48:50 +00:00
|
|
|
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,
|
2016-01-07 05:14:26 +00:00
|
|
|
&Device2->Local,
|
|
|
|
DeviceSize - FIELD_OFFSET(BL_DEVICE_DESCRIPTOR, Local)))
|
2015-09-09 05:48:50 +00:00
|
|
|
{
|
|
|
|
/* They match! */
|
|
|
|
DeviceMatch = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return matching state */
|
|
|
|
return DeviceMatch;
|
|
|
|
}
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
NTSTATUS
|
|
|
|
BlockIopFreeAllocations (
|
|
|
|
_In_ PBL_BLOCK_DEVICE BlockDevice
|
2015-09-09 05:48:50 +00:00
|
|
|
)
|
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
/* If a block device was passed in, free it */
|
|
|
|
if (BlockDevice)
|
2015-09-09 05:48:50 +00:00
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
BlMmFreeHeap(BlockDevice);
|
2015-09-09 05:48:50 +00:00
|
|
|
}
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Nothing else to do */
|
|
|
|
return STATUS_SUCCESS;
|
2015-09-09 05:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
2015-09-09 16:50:05 +00:00
|
|
|
BlockIoEfiGetBlockIoInformation (
|
|
|
|
_In_ PBL_BLOCK_DEVICE BlockDevice
|
2015-09-09 05:48:50 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
2015-09-09 16:50:05 +00:00
|
|
|
EFI_BLOCK_IO_MEDIA *Media;
|
2015-09-09 05:48:50 +00:00
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Open the Block I/O protocol on this device */
|
|
|
|
Status = EfiOpenProtocol(BlockDevice->Handle,
|
|
|
|
&EfiBlockIoProtocol,
|
|
|
|
(PVOID*)&BlockDevice->Protocol);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
2015-09-09 05:48:50 +00:00
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Get information on the block media */
|
|
|
|
Media = BlockDevice->Protocol->Media;
|
2015-09-09 05:48:50 +00:00
|
|
|
|
|
|
|
/* Set the appropriate device flags */
|
|
|
|
BlockDevice->DeviceFlags = 0;
|
|
|
|
if (Media->RemovableMedia)
|
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
BlockDevice->DeviceFlags = BL_BLOCK_DEVICE_REMOVABLE_FLAG;
|
2015-09-09 05:48:50 +00:00
|
|
|
}
|
|
|
|
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;
|
2016-01-08 00:15:00 +00:00
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
goto Quickie;
|
2015-09-09 05:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Close the device path */
|
|
|
|
EfiCloseProtocol(Handle, &EfiDevicePathProtocol);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we got here, nothing was found */
|
|
|
|
Status = STATUS_NO_SUCH_DEVICE;
|
|
|
|
|
2016-01-08 00:15:00 +00:00
|
|
|
Quickie:
|
2015-09-09 05:48:50 +00:00
|
|
|
/* 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;
|
|
|
|
BL_PROTOCOL_HANDLE Protocol[2];
|
|
|
|
ACPI_HID_DEVICE_PATH *AcpiPath;
|
|
|
|
HARDDRIVE_DEVICE_PATH *DiskPath;
|
|
|
|
BOOLEAN Found;
|
|
|
|
ULONG i;
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Extract the identifier, and the block device object */
|
2015-09-09 05:48:50 +00:00
|
|
|
Device = DeviceEntry->DeviceDescriptor;
|
|
|
|
BlockDevice = (PBL_BLOCK_DEVICE)DeviceEntry->DeviceSpecificData;
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Initialize protocol handles */
|
|
|
|
Protocol[0].Handle = BlockDevice->Handle;
|
2015-09-09 05:48:50 +00:00
|
|
|
Protocol[1].Handle = 0;
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Open this device */
|
|
|
|
Status = EfiOpenProtocol(Protocol[0].Handle,
|
2015-09-09 05:48:50 +00:00
|
|
|
&EfiDevicePathProtocol,
|
|
|
|
&Protocol[0].Interface);
|
2015-09-09 16:50:05 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2015-09-09 05:48:50 +00:00
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Fail */
|
2015-09-09 05:48:50 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Iteratate twice -- once for the top level, once for the bottom */
|
2015-09-09 05:48:50 +00:00
|
|
|
for (i = 0, Found = FALSE; Found == FALSE && Protocol[i].Handle; i++)
|
|
|
|
{
|
2016-01-08 00:15:00 +00:00
|
|
|
/* Check what kind of leaf node device this is */
|
2015-09-09 05:48:50 +00:00
|
|
|
LeafNode = EfiGetLeafNode(Protocol[i].Interface);
|
2015-09-09 16:50:05 +00:00
|
|
|
EfiPrintf(L"Pass %d, Leaf node: %p Type: %d\r\n", i, LeafNode, LeafNode->Type);
|
2015-09-09 05:48:50 +00:00
|
|
|
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;
|
2015-09-09 16:50:05 +00:00
|
|
|
EfiPrintf(L"Disk path: %p Type: %lx\r\n", DiskPath, LeafNode->SubType);
|
2015-09-09 05:48:50 +00:00
|
|
|
if (LeafNode->SubType == MEDIA_HARDDRIVE_DP)
|
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Set this as a local device */
|
2015-09-09 05:48:50 +00:00
|
|
|
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;
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Write the MBR partition signature */
|
2015-09-09 05:48:50 +00:00
|
|
|
BlockDevice->PartitionType = MbrPartition;
|
|
|
|
BlockDevice->Disk.Mbr.Signature = *(PULONG)&DiskPath->Signature[0];
|
|
|
|
Found = TRUE;
|
|
|
|
}
|
|
|
|
else if (DiskPath->SignatureType == SIGNATURE_TYPE_GUID)
|
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Set this as a GPT partition */
|
|
|
|
BlockDevice->PartitionType = GptPartition;
|
2015-09-09 05:48:50 +00:00
|
|
|
Device->Local.HardDisk.PartitionType = GptPartition;
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Get the GPT signature */
|
2015-09-09 05:48:50 +00:00
|
|
|
Status = BlockIoGetGPTDiskSignature(DeviceEntry,
|
|
|
|
&Device->Local.HardDisk.Gpt.PartitionSignature);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Copy it */
|
2015-09-09 05:48:50 +00:00
|
|
|
RtlCopyMemory(&BlockDevice->Disk.Gpt.Signature,
|
|
|
|
&Device->Local.HardDisk.Gpt.PartitionSignature,
|
2015-11-20 09:51:23 +00:00
|
|
|
sizeof(BlockDevice->Disk.Gpt.Signature));
|
2015-09-09 05:48:50 +00:00
|
|
|
Found = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Otherwise, this is a raw disk */
|
2015-09-09 05:48:50 +00:00
|
|
|
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 */
|
2015-09-09 16:50:05 +00:00
|
|
|
EfiPrintf(L"Found CD-ROM\r\n");
|
2015-09-09 05:48:50 +00:00
|
|
|
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) &&
|
2015-09-09 16:50:05 +00:00
|
|
|
(LeafNode->Type != ACPI_DEVICE_PATH) &&
|
2015-09-09 05:48:50 +00:00
|
|
|
(i == 0))
|
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
/* This is probably a messaging device node. Are we under it? */
|
|
|
|
Status = BlockIoEfiGetChildHandle(Protocol, &Protocol[1]);
|
|
|
|
EfiPrintf(L"Pass 0, non DP/ACPI path. Child handle obtained: %lx\r\n", Protocol[1].Handle);
|
2015-09-09 05:48:50 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
/* We're not. So this must be a raw device */
|
2015-09-09 05:48:50 +00:00
|
|
|
Device->DeviceType = LocalDevice;
|
2015-09-09 16:50:05 +00:00
|
|
|
Found = TRUE;
|
|
|
|
|
|
|
|
/* Is it a removable raw device? */
|
|
|
|
if (BlockDevice->DeviceFlags & BL_BLOCK_DEVICE_REMOVABLE_FLAG)
|
2015-09-09 05:48:50 +00:00
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
/* This is a removable (CD or Floppy or USB) device */
|
2015-09-09 05:48:50 +00:00
|
|
|
BlockDevice->Type = FloppyDevice;
|
|
|
|
Device->Local.Type = FloppyDevice;
|
2015-09-09 16:50:05 +00:00
|
|
|
Device->Local.FloppyDisk.DriveNumber = BlockIoFirmwareRemovableDiskCount++;
|
|
|
|
EfiPrintf(L"Found Floppy\r\n");
|
2015-09-09 05:48:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
/* It's a fixed device */
|
2015-09-09 05:48:50 +00:00
|
|
|
BlockDevice->Type = DiskDevice;
|
|
|
|
Device->Local.Type = DiskDevice;
|
2015-09-09 16:50:05 +00:00
|
|
|
|
|
|
|
/* Set it as a raw partition */
|
2015-09-09 05:48:50 +00:00
|
|
|
Device->Local.HardDisk.PartitionType = RawPartition;
|
|
|
|
Device->Local.HardDisk.Mbr.PartitionSignature = BlockIoFirmwareRawDiskCount++;
|
2015-09-09 16:50:05 +00:00
|
|
|
EfiPrintf(L"Found raw disk\r\n");
|
2015-09-09 05:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Close any protocols that we opened for each handle */
|
2015-09-09 05:48:50 +00:00
|
|
|
while (i)
|
|
|
|
{
|
|
|
|
EfiCloseProtocol(Protocol[--i].Handle, &EfiDevicePathProtocol);
|
|
|
|
}
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
/* Return appropriate status */
|
|
|
|
return Found ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
|
2015-09-09 05:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
{
|
2016-01-07 05:14:26 +00:00
|
|
|
/* We have a fully constructed device, return it */
|
2015-09-09 05:48:50 +00:00
|
|
|
*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);
|
2015-09-09 16:50:05 +00:00
|
|
|
EfiPrintf(L"Failed: %lx\r\n", Status);
|
2015-09-09 05:48:50 +00:00
|
|
|
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 */
|
2015-09-09 16:50:05 +00:00
|
|
|
EfiPrintf(L"Device is known\r\n");
|
2015-09-09 05:48:50 +00:00
|
|
|
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))
|
|
|
|
{
|
2015-09-09 16:50:05 +00:00
|
|
|
EfiPrintf(L"EFI create failed: %lx\n", Status);
|
Three tiny squirmy subtle bugs combined themselves with the bug that was just fixed to make bootmgfw believe it was being booted from a raw removable disk (floppy). Because bootmgfw now correctly enumerates boot devices and detects the DVD/CDROM media, it could no longer 'find itself', believing it was on a floppy.
[BOOTLIB]: When failing to find a block device, keep going searching for more, instead of giving up (critical, because the CDROM FAT12 image is now device path #1, not #0).
[BOOTMGR]: Correctly use the right logical operator in EfiInitpGetDeviceNode to get the deepest-level media device node. We now get the CDROM node, not the raw node.
[CDMAKE]: Don't actually create an EFI/BOOT directory on the CDROM itself, but rather in the FAT12 image. Otherwise, this can confuse UEFI implementations to boot the boot manager off the raw CDROM, instead of the FAT12 image on the CDROM.
svn path=/trunk/; revision=70542
2016-01-08 01:18:08 +00:00
|
|
|
continue;
|
2015-09-09 05:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2015-09-09 16:50:05 +00:00
|
|
|
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
|
|
|
|
DiskClose (
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status, LocalStatus;
|
|
|
|
PBL_BLOCK_DEVICE BlockDevice;
|
|
|
|
|
|
|
|
/* Assume success */
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
BlockDevice = DeviceEntry->DeviceSpecificData;
|
|
|
|
|
|
|
|
/* Close the protocol */
|
|
|
|
LocalStatus = EfiCloseProtocol(BlockDevice->Handle, &EfiBlockIoProtocol);
|
|
|
|
if (!NT_SUCCESS(LocalStatus))
|
|
|
|
{
|
|
|
|
/* Only inherit failures */
|
|
|
|
Status = LocalStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the block device allocations */
|
|
|
|
LocalStatus = BlockIopFreeAllocations(BlockDevice);
|
|
|
|
if (!NT_SUCCESS(LocalStatus))
|
|
|
|
{
|
|
|
|
/* Only inherit failures */
|
|
|
|
Status = LocalStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return back to caller */
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
DiskOpen (
|
|
|
|
_In_ PBL_DEVICE_DESCRIPTOR Device,
|
|
|
|
_In_ PBL_DEVICE_ENTRY DeviceEntry
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
/* Use firmware-specific functions to open the disk */
|
|
|
|
Status = BlockIoFirmwareOpen(Device, DeviceEntry->DeviceSpecificData);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Overwrite with our own close routine */
|
|
|
|
DeviceEntry->Callbacks.Close = DiskClose;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return back to caller */
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 UdpFunctionTable =
|
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
UdpOpen,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
BL_DEVICE_CALLBACKS SerialPortFunctionTable =
|
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
SpOpen,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
DeviceTableCompare (
|
|
|
|
_In_ PVOID Entry,
|
|
|
|
_In_ PVOID Argument1,
|
|
|
|
_In_ PVOID Argument2,
|
|
|
|
_Inout_ PVOID Argument3,
|
|
|
|
_Inout_ PVOID Argument4
|
|
|
|
)
|
|
|
|
{
|
|
|
|
BOOLEAN Found;
|
2016-01-07 05:14:26 +00:00
|
|
|
PBL_DEVICE_DESCRIPTOR Device = (PBL_DEVICE_DESCRIPTOR)Argument1;
|
|
|
|
PBL_DEVICE_ENTRY DeviceEntry = (PBL_DEVICE_ENTRY)Entry;
|
2015-09-09 16:50:05 +00:00
|
|
|
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 */
|
2016-01-07 05:14:26 +00:00
|
|
|
if ((!(Flags & BL_DEVICE_READ_ACCESS) || (DeviceEntry->Flags & BL_DEVICE_ENTRY_READ_ACCESS)) &&
|
|
|
|
(!(Flags & BL_DEVICE_WRITE_ACCESS) || (DeviceEntry->Flags & BL_DEVICE_ENTRY_WRITE_ACCESS)))
|
2015-09-09 16:50:05 +00:00
|
|
|
{
|
|
|
|
/* 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 */
|
2016-01-07 05:14:26 +00:00
|
|
|
if (DeviceEntry->Flags & BL_DEVICE_ENTRY_OPENED)
|
2015-09-09 16:50:05 +00:00
|
|
|
{
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2015-09-09 05:48:50 +00:00
|
|
|
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 */
|
2016-01-07 05:14:26 +00:00
|
|
|
//EfiPrintf(L"Block I/O Device entry found: %p\r\n", FoundDeviceEntry);
|
2015-09-09 05:48:50 +00:00
|
|
|
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 */
|
2016-01-07 05:14:26 +00:00
|
|
|
if (!(DeviceEntry->Flags & BL_DEVICE_ENTRY_OPENED))
|
2015-09-09 05:48:50 +00:00
|
|
|
{
|
|
|
|
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 */
|
2016-01-07 05:14:26 +00:00
|
|
|
DeviceEntry->Flags = ~BL_DEVICE_ENTRY_OPENED;
|
2015-09-09 05:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2015-10-05 04:51:32 +00:00
|
|
|
/* Make sure both read and write access are set */
|
|
|
|
if (!(Flags & (BL_DEVICE_READ_ACCESS | BL_DEVICE_WRITE_ACCESS)))
|
2015-09-09 05:48:50 +00:00
|
|
|
{
|
|
|
|
/* 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;
|
2016-01-07 05:14:26 +00:00
|
|
|
DeviceEntry->Flags |= BL_DEVICE_ENTRY_OPENED;
|
2015-09-09 05:48:50 +00:00
|
|
|
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;
|
2015-10-05 04:51:32 +00:00
|
|
|
DeviceEntry->Flags |= (BL_DEVICE_ENTRY_OPENED |
|
|
|
|
BL_DEVICE_ENTRY_READ_ACCESS |
|
|
|
|
BL_DEVICE_ENTRY_WRITE_ACCESS);
|
2015-09-09 05:48:50 +00:00
|
|
|
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 */
|
2015-09-09 16:50:05 +00:00
|
|
|
EfiPrintf(L"Device ID: %lx\r\n", *DeviceId);
|
2015-09-09 05:48:50 +00:00
|
|
|
DeviceEntry->DeviceId = *DeviceId;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Quickie:
|
|
|
|
/* Failure path -- did we allocate a device entry? */
|
2015-09-09 16:50:05 +00:00
|
|
|
EfiPrintf(L"Block failure: %lx\r\n", Status);
|
2015-09-09 05:48:50 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-09-06 21:29:41 +00:00
|
|
|
NTSTATUS
|
|
|
|
BlpDeviceInitialize (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
/* Initialize the table count and list of devices */
|
|
|
|
DmTableEntries = 8;
|
|
|
|
InitializeListHead(&DmRegisteredDevices);
|
|
|
|
|
|
|
|
/* Initialize device information */
|
2015-09-10 05:19:50 +00:00
|
|
|
DmDeviceIoInformation.ReadCount = 0;
|
|
|
|
DmDeviceIoInformation.WriteCount = 0;
|
2015-09-06 21:29:41 +00:00
|
|
|
|
|
|
|
/* Allocate the device table */
|
|
|
|
DmDeviceTable = BlMmAllocateHeap(DmTableEntries * sizeof(PVOID));
|
|
|
|
if (DmDeviceTable)
|
|
|
|
{
|
|
|
|
/* Clear it */
|
|
|
|
RtlZeroMemory(DmDeviceTable, DmTableEntries * sizeof(PVOID));
|
2015-09-10 23:13:31 +00:00
|
|
|
#if BL_BITLOCKER_SUPPORT
|
2015-09-06 21:29:41 +00:00
|
|
|
/* Initialize BitLocker support */
|
|
|
|
Status = FvebInitialize();
|
|
|
|
#else
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* No memory, we'll fail */
|
|
|
|
Status = STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return initialization state */
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|