_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,
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,
{
/* Compare the two devices up to their size */
if (RtlEqualMemory(&Device1->Local,
- &Device2->Local,
- DeviceSize - FIELD_OFFSET(BL_DEVICE_DESCRIPTOR, Local)))
+ &Device2->Local,
+ DeviceSize - FIELD_OFFSET(BL_DEVICE_DESCRIPTOR, Local)))
{
/* They match! */
DeviceMatch = TRUE;
return DeviceMatch;
}
-BOOLEAN
-DeviceTableCompare (
- _In_ PVOID Entry,
- _In_ PVOID Argument1,
- _In_ PVOID Argument2,
- _Inout_ PVOID Argument3,
- _Inout_ PVOID Argument4
+NTSTATUS
+BlockIopFreeAllocations (
+ _In_ PBL_BLOCK_DEVICE BlockDevice
)
{
- 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))
+ /* If a block device was passed in, free it */
+ if (BlockDevice)
{
- /* 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;
- }
- }
- }
+ BlMmFreeHeap(BlockDevice);
}
- /* Return matching state */
- return Found;
+ /* Nothing else to do */
+ return STATUS_SUCCESS;
}
NTSTATUS
-DeviceTableDestroyEntry (
- _In_ PVOID Entry,
- _In_ ULONG DeviceId
+BlockIoEfiGetBlockIoInformation (
+ _In_ PBL_BLOCK_DEVICE BlockDevice
)
{
- PBL_DEVICE_ENTRY DeviceEntry = (PBL_DEVICE_ENTRY)Entry;
NTSTATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
- /* Call the close routine for this entry */
- Status = DeviceEntry->Callbacks.Close(DmDeviceTable[DeviceId]);
+ /* Open the Block I/O protocol on this device */
+ Status = EfiOpenProtocol(BlockDevice->Handle,
+ &EfiBlockIoProtocol,
+ (PVOID*)&BlockDevice->Protocol);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
- /* Free the descriptor, and the device itself */
- BlMmFreeHeap(DeviceEntry->DeviceDescriptor);
- BlMmFreeHeap(DeviceEntry);
+ /* Get information on the block media */
+ Media = BlockDevice->Protocol->Media;
- /* 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;
+ EfiPrintf(L"Block I/O Info for Device 0x%p, 0x%lX\r\n", BlockDevice, BlockDevice->Handle);
+ EfiPrintf(L"Removable: %d Present: %d Last Block: %I64d BlockSize: %d IoAlign: %d MediaId: %d ReadOnly: %d\r\n",
+ Media->RemovableMedia, Media->MediaPresent, Media->LastBlock, Media->BlockSize, Media->IoAlign,
+ Media->MediaId, Media->ReadOnly);
/* Set the appropriate device flags */
BlockDevice->DeviceFlags = 0;
if (Media->RemovableMedia)
{
- BlockDevice->DeviceFlags = 1;
+ BlockDevice->DeviceFlags = BL_BLOCK_DEVICE_REMOVABLE_FLAG;
}
if (Media->MediaPresent)
{
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;
+ /* Extract the identifier, and the block device object */
Device = DeviceEntry->DeviceDescriptor;
BlockDevice = (PBL_BLOCK_DEVICE)DeviceEntry->DeviceSpecificData;
- Found = FALSE;
-
- Handle = BlockDevice->Handle;
-
- Protocol[0].Handle = Handle;
+ /* Initialize protocol handles */
+ Protocol[0].Handle = BlockDevice->Handle;
Protocol[1].Handle = 0;
- Status = EfiOpenProtocol(Handle,
+ /* Open this device */
+ Status = EfiOpenProtocol(Protocol[0].Handle,
&EfiDevicePathProtocol,
&Protocol[0].Interface);
- if (Status < 0)
+ if (!NT_SUCCESS(Status))
{
+ /* Fail */
return Status;
}
+ /* Iteratate twice -- once for the top level, once for the bottom */
for (i = 0, Found = FALSE; Found == FALSE && Protocol[i].Handle; i++)
{
LeafNode = EfiGetLeafNode(Protocol[i].Interface);
+ EfiPrintf(L"Pass %d, Leaf node: %p Type: %d\r\n", i, LeafNode, LeafNode->Type);
if (LeafNode->Type == ACPI_DEVICE_PATH)
{
/* We only support floppy drives */
{
/* Extract the disk path and check if it's a physical disk */
DiskPath = (HARDDRIVE_DEVICE_PATH*)LeafNode;
+ EfiPrintf(L"Disk path: %p Type: %lx\r\n", DiskPath, LeafNode->SubType);
if (LeafNode->SubType == MEDIA_HARDDRIVE_DP)
{
+ /* Set this as a local device */
Device->Local.Type = LocalDevice;
/* Check if this is an MBR partition */
Device->DeviceType = LegacyPartitionDevice;
Device->Partition.Disk.Type = LocalDevice;
+ /* Write the MBR partition signature */
BlockDevice->PartitionType = MbrPartition;
BlockDevice->Disk.Mbr.Signature = *(PULONG)&DiskPath->Signature[0];
Found = TRUE;
}
else if (DiskPath->SignatureType == SIGNATURE_TYPE_GUID)
{
- BlockDevice->PartitionType = 0;
+ /* Set this as a GPT partition */
+ BlockDevice->PartitionType = GptPartition;
Device->Local.HardDisk.PartitionType = GptPartition;
+ /* Get the GPT signature */
Status = BlockIoGetGPTDiskSignature(DeviceEntry,
&Device->Local.HardDisk.Gpt.PartitionSignature);
if (NT_SUCCESS(Status))
{
+ /* Copy it */
RtlCopyMemory(&BlockDevice->Disk.Gpt.Signature,
&Device->Local.HardDisk.Gpt.PartitionSignature,
sizeof(&BlockDevice->Disk.Gpt.Signature));
}
}
- /* Otherwise, raw boot is not supported */
+ /* Otherwise, this is a raw disk */
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 */
+ EfiPrintf(L"Found CD-ROM\r\n");
BlockDevice->PartitionType = RawPartition;
BlockDevice->Type = CdRomDevice;
}
}
else if ((LeafNode->Type != MEDIA_DEVICE_PATH) &&
- (LeafNode->Type == ACPI_DEVICE_PATH) &&
+ (LeafNode->Type != ACPI_DEVICE_PATH) &&
(i == 0))
{
- Status = BlockIoEfiGetChildHandle(Protocol, &Protocol[i]);
+ /* 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);
if (!NT_SUCCESS(Status))
{
+ /* We're not. So this must be a raw device */
Device->DeviceType = LocalDevice;
- Found = 1;
- if (BlockDevice->DeviceFlags & 1)
+ Found = TRUE;
+
+ /* Is it a removable raw device? */
+ if (BlockDevice->DeviceFlags & BL_BLOCK_DEVICE_REMOVABLE_FLAG)
{
+ /* This is a removable (CD or Floppy or USB) device */
BlockDevice->Type = FloppyDevice;
- Device->Local.HardDisk.PartitionType = BlockIoFirmwareRemovableDiskCount++;
Device->Local.Type = FloppyDevice;
+ Device->Local.FloppyDisk.DriveNumber = BlockIoFirmwareRemovableDiskCount++;
+ EfiPrintf(L"Found Floppy\r\n");
}
else
{
+ /* It's a fixed device */
BlockDevice->Type = DiskDevice;
Device->Local.Type = DiskDevice;
+
+ /* Set it as a raw partition */
Device->Local.HardDisk.PartitionType = RawPartition;
- BlockDevice->PartitionType = RawPartition;
Device->Local.HardDisk.Mbr.PartitionSignature = BlockIoFirmwareRawDiskCount++;
+ EfiPrintf(L"Found raw disk\r\n");
}
}
}
}
+ /* Close any protocols that we opened for each handle */
while (i)
{
EfiCloseProtocol(Protocol[--i].Handle, &EfiDevicePathProtocol);
}
- if (Found)
- {
- Status = 0;
- }
- else
- {
- Status = STATUS_NOT_SUPPORTED;
- }
- return Status;
+ /* Return appropriate status */
+ return Found ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
}
NTSTATUS
/* Free the device entry itself and return the failure code */
BlMmFreeHeap(IoDeviceEntry);
+ EfiPrintf(L"Failed: %lx\r\n", Status);
return Status;
}
if (NT_SUCCESS(Status))
{
/* We already know about this device */
+ EfiPrintf(L"Device is known\r\n");
continue;
}
Status = BlockIoEfiCreateDeviceEntry(&DeviceEntry, DeviceHandles[i]);
if (!NT_SUCCESS(Status))
{
+ EfiPrintf(L"EFI create failed: %lx\n", Status);
break;
}
/* Does this device match what we're looking for? */
DeviceMatch = BlpDeviceCompare(DeviceEntry->DeviceDescriptor, Device);
+ EfiPrintf(L"Device match: %d\r\n", DeviceMatch);
if (DeviceMatch)
{
/* Yep, return the data back */
return Status;
}
+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;
+ 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;
+}
+
+
BOOLEAN
BlockIoDeviceTableCompare (
_In_ PVOID Entry,
if (!NT_SUCCESS(Status))
{
/* Failed to initialize block I/O */
+ EfiPrintf(L"Block I/O Init failed\r\n");
return Status;
}
}
if (FoundDeviceEntry)
{
/* We already found a device, so copy its device data and callbacks */
+ EfiPrintf(L"Device entry found: %p\r\n", FoundDeviceEntry);
RtlCopyMemory(BlockDevice, FoundDeviceEntry->DeviceSpecificData, sizeof(*BlockDevice));
RtlCopyMemory(&DeviceEntry->Callbacks,
&FoundDeviceEntry->Callbacks,
if (DeviceEntry)
{
/* Return it, taking a reference on it */
+ EfiPrintf(L"Device found: %p\r\n", DeviceEntry);
*DeviceId = DeviceEntry->DeviceId;
++DeviceEntry->ReferenceCount;
DeviceEntry->Flags |= 1;
if (NT_SUCCESS(Status))
{
/* It worked -- return the ID in the table to the caller */
+ EfiPrintf(L"Device ID: %lx\r\n", *DeviceId);
DeviceEntry->DeviceId = *DeviceId;
return STATUS_SUCCESS;
}
Quickie:
/* Failure path -- did we allocate a device entry? */
+ EfiPrintf(L"Block failure: %lx\r\n", Status);
if (DeviceEntry)
{
/* Yep -- did it have a descriptor? */