2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/io/device.c
5 * PURPOSE: Boot Library Device Management Routines
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
13 /* DATA VARIABLES ************************************************************/
15 typedef struct _BL_DEVICE_IO_INFORMATION
19 } BL_DEVICE_IO_INFORMATION
, *PBL_DEVICE_IO_INFORMATION
;
21 LIST_ENTRY DmRegisteredDevices
;
23 LIST_ENTRY DmRegisteredDevices
;
26 BL_DEVICE_IO_INFORMATION DmDeviceIoInformation
;
28 /* FUNCTIONS *****************************************************************/
30 typedef struct _BL_REGISTERED_DEVICE
33 BL_DEVICE_CALLBACKS Callbacks
;
34 } BL_REGISTERED_DEVICE
, *PBL_REGISTERED_DEVICE
;
36 PVOID
* BlockIoDeviceTable
;
37 ULONG BlockIoDeviceTableEntries
;
39 ULONG BlockIoFirmwareRemovableDiskCount
;
40 ULONG BlockIoFirmwareRawDiskCount
;
41 ULONG BlockIoFirmwareCdromCount
;
43 PVOID BlockIopAlignedBuffer
;
44 ULONG BlockIopAlignedBufferSize
;
46 PVOID BlockIopPartialBlockBuffer
;
47 ULONG BlockIopPartialBlockBufferSize
;
49 PVOID BlockIopPrefetchBuffer
;
51 PVOID BlockIopReadBlockBuffer
;
52 ULONG BlockIopReadBlockBufferSize
;
56 BOOLEAN BlockIoInitialized
;
60 _In_ PBL_DEVICE_DESCRIPTOR Device
,
61 _In_ PBL_DEVICE_ENTRY DeviceEntry
65 BlockIoGetInformation (
66 _In_ PBL_DEVICE_ENTRY DeviceEntry
,
67 _Out_ PBL_DEVICE_INFORMATION DeviceInformation
71 BlockIoSetInformation (
72 _In_ PBL_DEVICE_ENTRY DeviceEntry
,
73 _Out_ PBL_DEVICE_INFORMATION DeviceInformation
78 _In_ PBL_DEVICE_ENTRY DeviceEntry
,
81 _Out_ PULONG BytesRead
84 BL_DEVICE_CALLBACKS BlockIoDeviceFunctionTable
=
91 BlockIoGetInformation
,
96 BlockIoFirmwareWrite (
97 _In_ PBL_BLOCK_DEVICE BlockDevice
,
100 _In_ ULONGLONG BlockCount
103 return STATUS_NOT_IMPLEMENTED
;
107 BlockIoFirmwareRead (
108 _In_ PBL_BLOCK_DEVICE BlockDevice
,
110 _In_ ULONGLONG Block
,
111 _In_ ULONGLONG BlockCount
115 EFI_BLOCK_IO
*BlockProtocol
;
116 BL_ARCH_MODE OldMode
;
117 EFI_STATUS EfiStatus
;
120 for (FailureCount
= 0, Status
= STATUS_SUCCESS
;
121 FailureCount
< 2 && NT_SUCCESS(Status
);
124 BlockProtocol
= BlockDevice
->Protocol
;
126 OldMode
= CurrentExecutionContext
->Mode
;
127 if (CurrentExecutionContext
->Mode
!= 1)
129 Status
= STATUS_NOT_IMPLEMENTED
;
133 //EfiPrintf(L"EFI Reading BLOCK %d off media %lx (%d blocks)\r\n",
134 //Block, BlockProtocol->Media->MediaId, BlockCount);
135 EfiStatus
= BlockProtocol
->ReadBlocks(BlockProtocol
,
136 BlockProtocol
->Media
->MediaId
,
138 BlockProtocol
->Media
->BlockSize
* BlockCount
,
140 if (EfiStatus
== EFI_SUCCESS
)
142 //EfiPrintf(L"EFI Read complete into buffer\r\n");
143 //EfiPrintf(L"Buffer data: %lx %lx %lx %lx\r\n", *(PULONG)Buffer, *((PULONG)Buffer + 1), *((PULONG)Buffer + 2), *((PULONG)Buffer + 3));
148 BlpArchSwitchContext(OldMode
);
151 Status
= EfiGetNtStatusCode(EfiStatus
);
152 if (Status
!= STATUS_MEDIA_CHANGED
)
157 EfiCloseProtocol(BlockDevice
->Handle
, &EfiBlockIoProtocol
);
159 Status
= EfiOpenProtocol(BlockDevice
->Handle
,
161 (PVOID
*)BlockDevice
->Protocol
);
168 BlockIopFirmwareOperation (
169 PBL_DEVICE_ENTRY DeviceEntry
,
171 _In_ ULONGLONG Block
,
172 _In_ ULONGLONG BlockCount
,
173 _In_ ULONG OperationType
177 PBL_BLOCK_DEVICE BlockDevice
;
180 BlockDevice
= DeviceEntry
->DeviceSpecificData
;
182 if (OperationType
== 1)
184 for (FailureCount
= 0; FailureCount
< 3; FailureCount
++)
186 Status
= BlockIoFirmwareWrite(BlockDevice
, Buffer
, Block
, BlockCount
);
195 for (FailureCount
= 0; FailureCount
< 3; FailureCount
++)
197 Status
= BlockIoFirmwareRead(BlockDevice
, Buffer
, Block
, BlockCount
);
208 BlockIopFreeAlignedBuffer (
209 _Inout_ PVOID
* Buffer
,
210 _Inout_ PULONG BufferSize
217 EfiPrintf(L
"Aligned free not yet implemented\r\n");
218 Status
= STATUS_NOT_IMPLEMENTED
;
219 //Status = MmPapFreePages(*Buffer, 1);
226 Status
= STATUS_SUCCESS
;
233 BlockIopAllocateAlignedBuffer (
234 _Inout_ PVOID
* Buffer
,
235 _Inout_ PULONG BufferSize
,
247 Status
= STATUS_SUCCESS
;
248 if ((Size
> *BufferSize
) || ((Alignment
- 1) & (ULONG_PTR
)*Buffer
))
250 BlockIopFreeAlignedBuffer(Buffer
, BufferSize
);
252 *BufferSize
= ROUND_TO_PAGES(Size
);
254 Status
= MmPapAllocatePagesInRange(Buffer
,
255 BlLoaderDeviceMemory
,
256 *BufferSize
>> PAGE_SHIFT
,
258 Alignment
>> PAGE_SHIFT
,
261 if (!NT_SUCCESS(Status
))
271 BlockIopReadUsingPrefetch (
272 _In_ PBL_DEVICE_ENTRY DeviceEntry
,
274 _In_ ULONG BlockCount
277 EfiPrintf(L
"No prefetch support\r\n");
278 return STATUS_NOT_IMPLEMENTED
;
283 _In_ PBL_DEVICE_ENTRY DeviceEntry
,
285 _In_ ULONG BlockCount
,
286 _In_ ULONG OperationType
289 PBL_BLOCK_DEVICE BlockDevice
;
290 ULONG BufferSize
, Alignment
;
294 BlockDevice
= DeviceEntry
->DeviceSpecificData
;
295 BufferSize
= BlockDevice
->BlockSize
* BlockCount
;
296 Offset
= BlockDevice
->Block
+ BlockDevice
->StartOffset
;
297 if ((BlockDevice
->LastBlock
+ 1) < (BlockDevice
->Block
+ BlockCount
))
299 EfiPrintf(L
"Read past end of device\r\n");
300 return STATUS_INVALID_PARAMETER
;
303 Alignment
= BlockDevice
->Alignment
;
304 if (!Alignment
|| !((Alignment
- 1) & (ULONG_PTR
)Buffer
))
306 Status
= BlockIopFirmwareOperation(DeviceEntry
,
311 if (!NT_SUCCESS(Status
))
313 EfiPrintf(L
"EFI op failed: %lx\r\n", Status
);
317 return STATUS_SUCCESS
;
320 EfiPrintf(L
"Firmware alignment fixup required\r\n");
321 Status
= BlockIopAllocateAlignedBuffer(&BlockIopAlignedBuffer
,
322 &BlockIopAlignedBufferSize
,
324 BlockDevice
->Alignment
);
325 if (!NT_SUCCESS(Status
))
327 EfiPrintf(L
"No memory for align\r\n");
328 return STATUS_NO_MEMORY
;
331 if (OperationType
== 1)
333 RtlCopyMemory(BlockIopAlignedBuffer
, Buffer
, BufferSize
);
336 Status
= BlockIopFirmwareOperation(DeviceEntry
,
337 BlockIopAlignedBuffer
,
341 if (!NT_SUCCESS(Status
))
348 RtlCopyMemory(Buffer
, BlockIopAlignedBuffer
, BufferSize
);
351 return STATUS_SUCCESS
;
355 BlockIopReadWriteVirtualDevice (
356 _In_ PBL_DEVICE_ENTRY DeviceEntry
,
359 _In_ ULONG Operation
,
360 _Out_ PULONG BytesRead
363 return STATUS_NOT_IMPLEMENTED
;
367 BlockIopReadPhysicalDevice (
368 _In_ PBL_DEVICE_ENTRY DeviceEntry
,
371 _Out_ PULONG BytesRead
374 PBL_BLOCK_DEVICE BlockDevice
;
375 PVOID ReadBuffer
; // edi@1
376 ULONGLONG OffsetEnd
, AlignedOffsetEnd
, Offset
;
379 BlockDevice
= DeviceEntry
->DeviceSpecificData
;
381 OffsetEnd
= Size
+ BlockDevice
->Offset
;
382 if (OffsetEnd
< Size
)
385 return STATUS_INTEGER_OVERFLOW
;
388 AlignedOffsetEnd
= ~(BlockDevice
->BlockSize
- 1) & (OffsetEnd
+ BlockDevice
->BlockSize
- 1);
389 if (AlignedOffsetEnd
< OffsetEnd
)
391 return STATUS_INTEGER_OVERFLOW
;
394 if ((BlockDevice
->Offset
) || (Size
!= AlignedOffsetEnd
))
396 Status
= BlockIopAllocateAlignedBuffer(&BlockIopReadBlockBuffer
,
397 &BlockIopReadBlockBufferSize
,
399 BlockDevice
->Alignment
);
400 if (!NT_SUCCESS(Status
))
402 EfiPrintf(L
"Failed to allocate buffer: %lx\r\n", Status
);
406 ReadBuffer
= BlockIopReadBlockBuffer
;
409 Offset
= AlignedOffsetEnd
/ BlockDevice
->BlockSize
;
411 if (BlockDevice
->Unknown
& 2)
413 Status
= BlockIopReadUsingPrefetch(DeviceEntry
,
415 AlignedOffsetEnd
/ BlockDevice
->BlockSize
);
416 if (NT_SUCCESS(Status
))
422 Status
= BlockIopOperation(DeviceEntry
, ReadBuffer
, Offset
, 0);
423 if (!NT_SUCCESS(Status
))
425 EfiPrintf(L
"Block I/O failed:%lx\r\n", Status
);
429 BlockDevice
->Block
+= Offset
;
432 if (ReadBuffer
!= Buffer
)
434 RtlCopyMemory(Buffer
,
435 (PVOID
)((ULONG_PTR
)ReadBuffer
+
436 (ULONG_PTR
)BlockDevice
->Offset
),
445 return STATUS_SUCCESS
;
449 BlockIopBlockInformationCheck (
450 _In_ PBL_BLOCK_DEVICE BlockDevice
,
451 _In_opt_ PULONG DesiredSize
,
452 _Out_opt_ PULONG Size
,
453 _Out_opt_ PULONG OutputAdjustedSize
457 ULONGLONG Offset
, LastOffset
, RemainingOffset
, MaxOffset
;
462 Offset
= (BlockDevice
->Offset
* BlockDevice
->BlockSize
) + BlockDevice
->Block
;
464 if (Offset
> ((BlockDevice
->LastBlock
+ 1) * BlockDevice
->BlockSize
))
466 Status
= STATUS_INVALID_PARAMETER
;
470 LastOffset
= (BlockDevice
->LastBlock
* BlockDevice
->BlockSize
) + BlockDevice
->BlockSize
- 1;
472 MaxOffset
= BlockDevice
->LastBlock
;
473 if (MaxOffset
< BlockDevice
->BlockSize
)
475 MaxOffset
= BlockDevice
->BlockSize
;
478 if (LastOffset
< MaxOffset
)
481 Status
= STATUS_INVALID_PARAMETER
;
485 if (Offset
> LastOffset
)
487 Status
= STATUS_INVALID_PARAMETER
;
491 RemainingOffset
= LastOffset
- Offset
+ 1;
493 if (DesiredSize
!= FALSE
)
495 RealSize
= *DesiredSize
;
499 RealSize
= ULONG_MAX
;
502 if (RemainingOffset
< RealSize
)
507 Status
= STATUS_INVALID_PARAMETER
;
511 RealSize
= RemainingOffset
;
514 Status
= STATUS_SUCCESS
;
527 _In_ PBL_DEVICE_ENTRY DeviceEntry
,
530 _Out_ PULONG BytesRead
533 PBL_BLOCK_DEVICE BlockDevice
;
536 BlockDevice
= DeviceEntry
->DeviceSpecificData
;
538 Status
= BlockIopBlockInformationCheck(BlockDevice
, &Size
, BytesRead
, &Size
);
539 if (NT_SUCCESS(Status
))
541 if (BlockDevice
->DeviceFlags
& 4)
543 Status
= BlockIopReadWriteVirtualDevice(DeviceEntry
, Buffer
, Size
, 0, BytesRead
);
547 Status
= BlockIopReadPhysicalDevice(DeviceEntry
, Buffer
, Size
, BytesRead
);
558 BlockIoSetInformation (
559 _In_ PBL_DEVICE_ENTRY DeviceEntry
,
560 _Out_ PBL_DEVICE_INFORMATION DeviceInformation
563 PBL_BLOCK_DEVICE BlockDevice
;
566 BlockDevice
= DeviceEntry
->DeviceSpecificData
;
568 Offset
= DeviceInformation
->BlockDeviceInfo
.Block
* BlockDevice
->BlockSize
+ DeviceInformation
->BlockDeviceInfo
.Offset
;
569 if (Offset
> ((BlockDevice
->LastBlock
+ 1) * BlockDevice
->BlockSize
- 1))
571 EfiPrintf(L
"Invalid offset\r\n");
572 return STATUS_INVALID_PARAMETER
;
575 BlockDevice
->Block
= Offset
/ BlockDevice
->BlockSize
;
576 BlockDevice
->Offset
= Offset
% BlockDevice
->BlockSize
;
577 BlockDevice
->Unknown
= DeviceInformation
->BlockDeviceInfo
.Unknown
;
578 return STATUS_SUCCESS
;
582 BlockIoGetInformation (
583 _In_ PBL_DEVICE_ENTRY DeviceEntry
,
584 _Out_ PBL_DEVICE_INFORMATION DeviceInformation
587 PBL_BLOCK_DEVICE BlockDevice
;
589 BlockDevice
= DeviceEntry
->DeviceSpecificData
;
591 RtlCopyMemory(&DeviceInformation
->BlockDeviceInfo
,
593 sizeof(DeviceInformation
->BlockDeviceInfo
));
594 DeviceInformation
->DeviceType
= DiskDevice
;
595 return STATUS_SUCCESS
;
599 BlDeviceSetInformation (
601 _Out_ PBL_DEVICE_INFORMATION DeviceInformation
604 PBL_DEVICE_ENTRY DeviceEntry
;
606 if (!(DeviceInformation
))
608 return STATUS_INVALID_PARAMETER
;
611 if (DmTableEntries
<= DeviceId
)
613 return STATUS_INVALID_PARAMETER
;
616 DeviceEntry
= DmDeviceTable
[DeviceId
];
619 return STATUS_INVALID_PARAMETER
;
622 if (!(DeviceEntry
->Flags
& 1))
624 return STATUS_INVALID_PARAMETER
;
627 DeviceInformation
->DeviceType
= DeviceEntry
->DeviceDescriptor
->DeviceType
;
628 return DeviceEntry
->Callbacks
.SetInformation(DeviceEntry
, DeviceInformation
);
632 BlDeviceGetInformation (
634 _Out_ PBL_DEVICE_INFORMATION DeviceInformation
637 PBL_DEVICE_ENTRY DeviceEntry
;
639 if (!(DeviceInformation
))
641 return STATUS_INVALID_PARAMETER
;
644 if (DmTableEntries
<= DeviceId
)
646 return STATUS_INVALID_PARAMETER
;
649 DeviceEntry
= DmDeviceTable
[DeviceId
];
652 return STATUS_INVALID_PARAMETER
;
655 if (!(DeviceEntry
->Flags
& 1))
657 return STATUS_INVALID_PARAMETER
;
660 DeviceInformation
->DeviceType
= DeviceEntry
->DeviceDescriptor
->DeviceType
;
661 return DeviceEntry
->Callbacks
.GetInformation(DeviceEntry
, DeviceInformation
);
669 _Out_ PULONG BytesRead
672 PBL_DEVICE_ENTRY DeviceEntry
;
674 ULONG BytesTransferred
;
676 if (!(Buffer
) || (DmTableEntries
<= DeviceId
))
678 return STATUS_INVALID_PARAMETER
;
681 DeviceEntry
= DmDeviceTable
[DeviceId
];
684 return STATUS_INVALID_PARAMETER
;
687 if (!(DeviceEntry
->Flags
& 1) || !(DeviceEntry
->Flags
& 2))
689 return STATUS_INVALID_PARAMETER
;
692 Status
= DeviceEntry
->Callbacks
.Read(DeviceEntry
, Buffer
, Size
, &BytesTransferred
);
693 if (!DeviceEntry
->Unknown
)
695 DmDeviceIoInformation
.ReadCount
+= BytesTransferred
;
700 *BytesRead
= BytesTransferred
;
707 BlDeviceReadAtOffset (
710 _In_ ULONGLONG Offset
,
712 _Out_ PULONG BytesRead
716 BL_DEVICE_INFORMATION DeviceInformation
;
718 Status
= BlDeviceGetInformation(DeviceId
, &DeviceInformation
);
719 if (!NT_SUCCESS(Status
))
724 DeviceInformation
.BlockDeviceInfo
.Block
= Offset
/ DeviceInformation
.BlockDeviceInfo
.BlockSize
;
725 DeviceInformation
.BlockDeviceInfo
.Offset
= Offset
% DeviceInformation
.BlockDeviceInfo
.BlockSize
;
726 Status
= BlDeviceSetInformation(DeviceId
, &DeviceInformation
);
727 if (NT_SUCCESS(Status
))
729 Status
= BlDeviceRead(DeviceId
, Buffer
, Size
, BytesRead
);
737 _In_ PBL_DEVICE_DESCRIPTOR Device1
,
738 _In_ PBL_DEVICE_DESCRIPTOR Device2
747 /* Check if the two devices exist and are identical in typ */
748 if ((Device1
) && (Device2
) && (Device1
->DeviceType
== Device2
->DeviceType
))
750 /* Take the bigger of the two sizes */
751 DeviceSize
= max(Device1
->Size
, Device2
->Size
);
752 if (DeviceSize
>= (ULONG
)FIELD_OFFSET(BL_DEVICE_DESCRIPTOR
, Local
))
754 /* Compare the two devices up to their size */
755 if (RtlEqualMemory(&Device1
->Local
,
757 DeviceSize
- FIELD_OFFSET(BL_DEVICE_DESCRIPTOR
, Local
)))
765 /* Return matching state */
770 BlockIopFreeAllocations (
771 _In_ PBL_BLOCK_DEVICE BlockDevice
774 /* If a block device was passed in, free it */
777 BlMmFreeHeap(BlockDevice
);
780 /* Nothing else to do */
781 return STATUS_SUCCESS
;
785 BlockIoEfiGetBlockIoInformation (
786 _In_ PBL_BLOCK_DEVICE BlockDevice
790 EFI_BLOCK_IO_MEDIA
*Media
;
792 /* Open the Block I/O protocol on this device */
793 Status
= EfiOpenProtocol(BlockDevice
->Handle
,
795 (PVOID
*)&BlockDevice
->Protocol
);
796 if (!NT_SUCCESS(Status
))
801 /* Get information on the block media */
802 Media
= BlockDevice
->Protocol
->Media
;
804 EfiPrintf(L
"Block I/O Info for Device 0x%p, 0x%lX\r\n", BlockDevice
, BlockDevice
->Handle
);
805 EfiPrintf(L
"Removable: %d Present: %d Last Block: %I64d BlockSize: %d IoAlign: %d MediaId: %d ReadOnly: %d\r\n",
806 Media
->RemovableMedia
, Media
->MediaPresent
, Media
->LastBlock
, Media
->BlockSize
, Media
->IoAlign
,
807 Media
->MediaId
, Media
->ReadOnly
);
809 /* Set the appropriate device flags */
810 BlockDevice
->DeviceFlags
= 0;
811 if (Media
->RemovableMedia
)
813 BlockDevice
->DeviceFlags
= BL_BLOCK_DEVICE_REMOVABLE_FLAG
;
815 if (Media
->MediaPresent
)
817 BlockDevice
->DeviceFlags
|= 2;
821 BlockDevice
->Unknown
= 0;
823 /* Set the block size */
824 BlockDevice
->BlockSize
= Media
->BlockSize
;
826 /* Make sure there's a last block value */
827 if (!Media
->LastBlock
)
829 return STATUS_INVALID_PARAMETER
;
832 /* Don't let it be too high */
833 if (Media
->LastBlock
> 0xFFFFFFFFFFE)
835 BlockDevice
->LastBlock
= 0xFFFFFFFFFFE;
839 BlockDevice
->LastBlock
= Media
->LastBlock
;
842 /* Make the alignment the smaller of the I/O alignment or the block size */
843 if (Media
->IoAlign
>= Media
->BlockSize
)
845 BlockDevice
->Alignment
= Media
->IoAlign
;
849 BlockDevice
->Alignment
= Media
->BlockSize
;
853 return STATUS_SUCCESS
;
857 BlockIoEfiGetChildHandle (
858 _In_ PBL_PROTOCOL_HANDLE ProtocolInterface
,
859 _In_ PBL_PROTOCOL_HANDLE ChildProtocolInterface
)
862 ULONG i
, DeviceCount
;
863 EFI_DEVICE_PATH
*DevicePath
, *ParentDevicePath
;
864 EFI_HANDLE
*DeviceHandles
;
867 /* Find all the Block I/O device handles on the system */
870 Status
= EfiLocateHandleBuffer(ByProtocol
,
874 if (!NT_SUCCESS(Status
))
876 /* Failed to enumerate, bail out */
880 /* Loop all the handles */
881 for (i
= 0; i
< DeviceCount
; i
++)
883 /* Check if this is the device itself */
884 Handle
= DeviceHandles
[i
];
885 if (Handle
== ProtocolInterface
->Handle
)
891 /* Get the device path of this device */
892 Status
= EfiOpenProtocol(Handle
,
893 &EfiDevicePathProtocol
,
894 (PVOID
*)&DevicePath
);
895 if (!NT_SUCCESS(Status
))
897 /* We failed, skip it */
901 /* See if we are its parent */
902 ParentDevicePath
= EfiIsDevicePathParent(ProtocolInterface
->Interface
,
904 if (ParentDevicePath
== ProtocolInterface
->Interface
)
906 /* Yup, return back to caller */
907 ChildProtocolInterface
->Handle
= Handle
;
908 ChildProtocolInterface
->Interface
= DevicePath
;
912 /* Close the device path */
913 EfiCloseProtocol(Handle
, &EfiDevicePathProtocol
);
916 /* If we got here, nothing was found */
917 Status
= STATUS_NO_SUCH_DEVICE
;
919 /* Free the handle array buffer */
920 BlMmFreeHeap(DeviceHandles
);
925 BlockIoGetGPTDiskSignature (
926 _In_ PBL_DEVICE_ENTRY DeviceEntry
,
927 _Out_ PGUID DiskSignature
930 EfiPrintf(L
"GPT not supported\r\n");
931 return STATUS_NOT_IMPLEMENTED
;
935 BlockIoEfiGetDeviceInformation (
936 _In_ PBL_DEVICE_ENTRY DeviceEntry
940 PBL_DEVICE_DESCRIPTOR Device
;
941 PBL_BLOCK_DEVICE BlockDevice
;
942 EFI_DEVICE_PATH
*LeafNode
;
943 BL_PROTOCOL_HANDLE Protocol
[2];
944 ACPI_HID_DEVICE_PATH
*AcpiPath
;
945 HARDDRIVE_DEVICE_PATH
*DiskPath
;
949 /* Extract the identifier, and the block device object */
950 Device
= DeviceEntry
->DeviceDescriptor
;
951 BlockDevice
= (PBL_BLOCK_DEVICE
)DeviceEntry
->DeviceSpecificData
;
953 /* Initialize protocol handles */
954 Protocol
[0].Handle
= BlockDevice
->Handle
;
955 Protocol
[1].Handle
= 0;
957 /* Open this device */
958 Status
= EfiOpenProtocol(Protocol
[0].Handle
,
959 &EfiDevicePathProtocol
,
960 &Protocol
[0].Interface
);
961 if (!NT_SUCCESS(Status
))
967 /* Iteratate twice -- once for the top level, once for the bottom */
968 for (i
= 0, Found
= FALSE
; Found
== FALSE
&& Protocol
[i
].Handle
; i
++)
970 LeafNode
= EfiGetLeafNode(Protocol
[i
].Interface
);
971 EfiPrintf(L
"Pass %d, Leaf node: %p Type: %d\r\n", i
, LeafNode
, LeafNode
->Type
);
972 if (LeafNode
->Type
== ACPI_DEVICE_PATH
)
974 /* We only support floppy drives */
975 AcpiPath
= (ACPI_HID_DEVICE_PATH
*)LeafNode
;
976 if ((AcpiPath
->HID
== EISA_PNP_ID(0x604)) &&
977 (AcpiPath
->HID
== EISA_PNP_ID(0x700)))
979 /* Set the boot library specific device types */
980 Device
->DeviceType
= LocalDevice
;
981 Device
->Local
.Type
= FloppyDevice
;
983 /* The ACPI UID is the drive number */
984 Device
->Local
.FloppyDisk
.DriveNumber
= AcpiPath
->UID
;
986 /* We found a match */
990 else if ((LeafNode
->Type
== MEDIA_DEVICE_PATH
) && (i
== 1))
992 /* Extract the disk path and check if it's a physical disk */
993 DiskPath
= (HARDDRIVE_DEVICE_PATH
*)LeafNode
;
994 EfiPrintf(L
"Disk path: %p Type: %lx\r\n", DiskPath
, LeafNode
->SubType
);
995 if (LeafNode
->SubType
== MEDIA_HARDDRIVE_DP
)
997 /* Set this as a local device */
998 Device
->Local
.Type
= LocalDevice
;
1000 /* Check if this is an MBR partition */
1001 if (DiskPath
->SignatureType
== SIGNATURE_TYPE_MBR
)
1003 /* Set that this is a local partition */
1004 Device
->DeviceType
= LegacyPartitionDevice
;
1005 Device
->Partition
.Disk
.Type
= LocalDevice
;
1007 /* Write the MBR partition signature */
1008 BlockDevice
->PartitionType
= MbrPartition
;
1009 BlockDevice
->Disk
.Mbr
.Signature
= *(PULONG
)&DiskPath
->Signature
[0];
1012 else if (DiskPath
->SignatureType
== SIGNATURE_TYPE_GUID
)
1014 /* Set this as a GPT partition */
1015 BlockDevice
->PartitionType
= GptPartition
;
1016 Device
->Local
.HardDisk
.PartitionType
= GptPartition
;
1018 /* Get the GPT signature */
1019 Status
= BlockIoGetGPTDiskSignature(DeviceEntry
,
1020 &Device
->Local
.HardDisk
.Gpt
.PartitionSignature
);
1021 if (NT_SUCCESS(Status
))
1024 RtlCopyMemory(&BlockDevice
->Disk
.Gpt
.Signature
,
1025 &Device
->Local
.HardDisk
.Gpt
.PartitionSignature
,
1026 sizeof(BlockDevice
->Disk
.Gpt
.Signature
));
1031 /* Otherwise, this is a raw disk */
1032 BlockDevice
->PartitionType
= RawPartition
;
1033 Device
->Local
.HardDisk
.PartitionType
= RawPartition
;
1034 Device
->Local
.HardDisk
.Raw
.DiskNumber
= BlockIoFirmwareRawDiskCount
++;;
1036 else if (LeafNode
->SubType
== MEDIA_CDROM_DP
)
1038 /* Set block device information */
1039 EfiPrintf(L
"Found CD-ROM\r\n");
1040 BlockDevice
->PartitionType
= RawPartition
;
1041 BlockDevice
->Type
= CdRomDevice
;
1043 /* Set CDROM data */
1044 Device
->Local
.Type
= CdRomDevice
;
1045 Device
->Local
.FloppyDisk
.DriveNumber
= 0;
1049 else if ((LeafNode
->Type
!= MEDIA_DEVICE_PATH
) &&
1050 (LeafNode
->Type
!= ACPI_DEVICE_PATH
) &&
1053 /* This is probably a messaging device node. Are we under it? */
1054 Status
= BlockIoEfiGetChildHandle(Protocol
, &Protocol
[1]);
1055 EfiPrintf(L
"Pass 0, non DP/ACPI path. Child handle obtained: %lx\r\n", Protocol
[1].Handle
);
1056 if (!NT_SUCCESS(Status
))
1058 /* We're not. So this must be a raw device */
1059 Device
->DeviceType
= LocalDevice
;
1062 /* Is it a removable raw device? */
1063 if (BlockDevice
->DeviceFlags
& BL_BLOCK_DEVICE_REMOVABLE_FLAG
)
1065 /* This is a removable (CD or Floppy or USB) device */
1066 BlockDevice
->Type
= FloppyDevice
;
1067 Device
->Local
.Type
= FloppyDevice
;
1068 Device
->Local
.FloppyDisk
.DriveNumber
= BlockIoFirmwareRemovableDiskCount
++;
1069 EfiPrintf(L
"Found Floppy\r\n");
1073 /* It's a fixed device */
1074 BlockDevice
->Type
= DiskDevice
;
1075 Device
->Local
.Type
= DiskDevice
;
1077 /* Set it as a raw partition */
1078 Device
->Local
.HardDisk
.PartitionType
= RawPartition
;
1079 Device
->Local
.HardDisk
.Mbr
.PartitionSignature
= BlockIoFirmwareRawDiskCount
++;
1080 EfiPrintf(L
"Found raw disk\r\n");
1086 /* Close any protocols that we opened for each handle */
1089 EfiCloseProtocol(Protocol
[--i
].Handle
, &EfiDevicePathProtocol
);
1092 /* Return appropriate status */
1093 return Found
? STATUS_SUCCESS
: STATUS_NOT_SUPPORTED
;
1101 EfiPrintf(L
"not implemented\r\n");
1102 return STATUS_NOT_IMPLEMENTED
;
1110 EfiPrintf(L
"not implemented\r\n");
1111 return STATUS_NOT_IMPLEMENTED
;
1115 BlockIoEfiCreateDeviceEntry (
1116 _In_ PBL_DEVICE_ENTRY
*DeviceEntry
,
1120 PBL_DEVICE_ENTRY IoDeviceEntry
;
1121 PBL_BLOCK_DEVICE BlockDevice
;
1123 PBL_DEVICE_DESCRIPTOR Device
;
1125 /* Allocate the entry for this device and zero it out */
1126 IoDeviceEntry
= BlMmAllocateHeap(sizeof(*IoDeviceEntry
));
1129 return STATUS_NO_MEMORY
;
1131 RtlZeroMemory(IoDeviceEntry
, sizeof(*IoDeviceEntry
));
1133 /* Allocate the device descriptor for this device and zero it out */
1134 Device
= BlMmAllocateHeap(sizeof(*Device
));
1137 return STATUS_NO_MEMORY
;
1139 RtlZeroMemory(Device
, sizeof(*Device
));
1141 /* Allocate the block device specific data, and zero it out */
1142 BlockDevice
= BlMmAllocateHeap(sizeof(*BlockDevice
));
1145 return STATUS_NO_MEMORY
;
1147 RtlZeroMemory(BlockDevice
, sizeof(*BlockDevice
));
1149 /* Save the descriptor and block device specific data */
1150 IoDeviceEntry
->DeviceSpecificData
= BlockDevice
;
1151 IoDeviceEntry
->DeviceDescriptor
= Device
;
1153 /* Set the size of the descriptor */
1154 Device
->Size
= sizeof(*Device
);
1156 /* Copy the standard I/O callbacks */
1157 RtlCopyMemory(&IoDeviceEntry
->Callbacks
,
1158 &BlockIoDeviceFunctionTable
,
1159 sizeof(IoDeviceEntry
->Callbacks
));
1161 /* Add the two that are firmware specific */
1162 IoDeviceEntry
->Callbacks
.Reset
= BlockIoEfiReset
;
1163 IoDeviceEntry
->Callbacks
.Flush
= BlockIoEfiFlush
;
1165 /* Save the EFI handle */
1166 BlockDevice
->Handle
= Handle
;
1168 /* Get information on this device from EFI, caching it in the device */
1169 Status
= BlockIoEfiGetBlockIoInformation(BlockDevice
);
1170 if (NT_SUCCESS(Status
))
1172 /* Build the descriptor structure for this device */
1173 Status
= BlockIoEfiGetDeviceInformation(IoDeviceEntry
);
1174 if (NT_SUCCESS(Status
))
1176 /* We have a fully constructed device, reuturn it */
1177 *DeviceEntry
= IoDeviceEntry
;
1178 return STATUS_SUCCESS
;
1182 /* Failure path, free the descriptor if we allocated one */
1183 if (IoDeviceEntry
->DeviceDescriptor
)
1185 BlMmFreeHeap(IoDeviceEntry
->DeviceDescriptor
);
1188 /* Free any other specific allocations */
1189 BlockIopFreeAllocations(IoDeviceEntry
->DeviceSpecificData
);
1191 /* Free the device entry itself and return the failure code */
1192 BlMmFreeHeap(IoDeviceEntry
);
1193 EfiPrintf(L
"Failed: %lx\r\n", Status
);
1198 BlockIoFirmwareOpen (
1199 _In_ PBL_DEVICE_DESCRIPTOR Device
,
1200 _In_ PBL_BLOCK_DEVICE BlockIoDevice
1204 BOOLEAN DeviceMatch
;
1205 BL_HASH_ENTRY HashEntry
;
1206 ULONG i
, Id
, DeviceCount
;
1207 PBL_DEVICE_ENTRY DeviceEntry
;
1208 EFI_HANDLE
* DeviceHandles
;
1210 /* Initialize everything */
1216 /* Ask EFI for handles to all block devices */
1217 Status
= EfiLocateHandleBuffer(ByProtocol
,
1218 &EfiBlockIoProtocol
,
1221 if (!NT_SUCCESS(Status
))
1223 return STATUS_NO_SUCH_DEVICE
;
1226 /* Build a hash entry, with the value inline */
1227 HashEntry
.Flags
= 1;
1228 HashEntry
.Size
= sizeof(EFI_HANDLE
);
1230 /* Loop each device we got */
1231 DeviceMatch
= FALSE
;
1232 Status
= STATUS_NO_SUCH_DEVICE
;
1233 for (i
= 0; i
< DeviceCount
; i
++)
1235 /* Check if we have a match in the device hash table */
1236 HashEntry
.Value
= DeviceHandles
[i
];
1237 Status
= BlHtLookup(HashTableId
, &HashEntry
, 0);
1238 if (NT_SUCCESS(Status
))
1240 /* We already know about this device */
1241 EfiPrintf(L
"Device is known\r\n");
1245 /* New device, store it in the hash table */
1246 Status
= BlHtStore(HashTableId
,
1249 sizeof(DeviceHandles
[i
]));
1250 if (!NT_SUCCESS(Status
))
1252 /* Free the array and fail */
1253 BlMmFreeHeap(DeviceHandles
);
1257 /* Create an entry for this device*/
1258 Status
= BlockIoEfiCreateDeviceEntry(&DeviceEntry
, DeviceHandles
[i
]);
1259 if (!NT_SUCCESS(Status
))
1261 EfiPrintf(L
"EFI create failed: %lx\n", Status
);
1265 /* Add the device entry to the device table */
1266 Status
= BlTblSetEntry(&BlockIoDeviceTable
,
1267 &BlockIoDeviceTableEntries
,
1270 TblDoNotPurgeEntry
);
1271 if (!NT_SUCCESS(Status
))
1273 EfiPrintf(L
"Failure path not implemented: %lx\r\n", Status
);
1275 BlHtDelete(HashTableId
, &HashKey
);
1277 /* Free the block I/O device data */
1278 BlockIopFreeAllocations(DeviceEntry
->DeviceSpecificData
);
1280 /* Free the descriptor */
1281 BlMmFreeHeap(DeviceEntry
->DeviceDescriptor
);
1283 /* Free the entry */
1284 BlMmFreeHeap(DeviceEntry
);
1288 /* Does this device match what we're looking for? */
1289 DeviceMatch
= BlpDeviceCompare(DeviceEntry
->DeviceDescriptor
, Device
);
1290 EfiPrintf(L
"Device match: %d\r\n", DeviceMatch
);
1293 /* Yep, return the data back */
1294 RtlCopyMemory(BlockIoDevice
,
1295 DeviceEntry
->DeviceSpecificData
,
1296 sizeof(*BlockIoDevice
));
1297 Status
= STATUS_SUCCESS
;
1302 /* Free the device handle buffer array */
1303 BlMmFreeHeap(DeviceHandles
);
1311 _In_ PBL_DEVICE_DESCRIPTOR Device
,
1312 _In_ PBL_DEVICE_ENTRY DeviceEntry
1315 EfiPrintf(L
"Not implemented!\r\n");
1316 return STATUS_NOT_IMPLEMENTED
;
1321 _In_ PBL_DEVICE_DESCRIPTOR Device
,
1322 _In_ PBL_DEVICE_ENTRY DeviceEntry
1325 EfiPrintf(L
"Not implemented!\r\n");
1326 return STATUS_NOT_IMPLEMENTED
;
1331 _In_ PBL_DEVICE_ENTRY DeviceEntry
1334 NTSTATUS Status
, LocalStatus
;
1335 PBL_BLOCK_DEVICE BlockDevice
;
1337 /* Assume success */
1338 Status
= STATUS_SUCCESS
;
1339 BlockDevice
= DeviceEntry
->DeviceSpecificData
;
1341 /* Close the protocol */
1342 LocalStatus
= EfiCloseProtocol(BlockDevice
->Handle
, &EfiBlockIoProtocol
);
1343 if (!NT_SUCCESS(LocalStatus
))
1345 /* Only inherit failures */
1346 Status
= LocalStatus
;
1349 /* Free the block device allocations */
1350 LocalStatus
= BlockIopFreeAllocations(BlockDevice
);
1351 if (!NT_SUCCESS(LocalStatus
))
1353 /* Only inherit failures */
1354 Status
= LocalStatus
;
1357 /* Return back to caller */
1363 _In_ PBL_DEVICE_DESCRIPTOR Device
,
1364 _In_ PBL_DEVICE_ENTRY DeviceEntry
1369 /* Use firmware-specific functions to open the disk */
1370 Status
= BlockIoFirmwareOpen(Device
, DeviceEntry
->DeviceSpecificData
);
1371 if (NT_SUCCESS(Status
))
1373 /* Overwrite with our own close routine */
1374 DeviceEntry
->Callbacks
.Close
= DiskClose
;
1377 /* Return back to caller */
1383 _In_ PBL_DEVICE_DESCRIPTOR Device
,
1384 _In_ PBL_DEVICE_ENTRY DeviceEntry
1387 EfiPrintf(L
"Not implemented!\r\n");
1388 return STATUS_NOT_IMPLEMENTED
;
1393 _In_ PBL_DEVICE_DESCRIPTOR Device
,
1394 _In_ PBL_DEVICE_ENTRY DeviceEntry
1397 EfiPrintf(L
"Not implemented!\r\n");
1398 return STATUS_NOT_IMPLEMENTED
;
1403 _In_ PBL_DEVICE_DESCRIPTOR Device
,
1404 _In_ PBL_DEVICE_ENTRY DeviceEntry
1407 EfiPrintf(L
"Not implemented!\r\n");
1408 return STATUS_NOT_IMPLEMENTED
;
1413 _In_ PBL_DEVICE_DESCRIPTOR Device
,
1414 _In_ PBL_DEVICE_ENTRY DeviceEntry
1417 EfiPrintf(L
"Not implemented!\r\n");
1418 return STATUS_NOT_IMPLEMENTED
;
1421 BL_DEVICE_CALLBACKS FileDeviceFunctionTable
=
1428 BL_DEVICE_CALLBACKS PartitionDeviceFunctionTable
=
1435 BL_DEVICE_CALLBACKS RamDiskDeviceFunctionTable
=
1442 BL_DEVICE_CALLBACKS DiskDeviceFunctionTable
=
1449 BL_DEVICE_CALLBACKS VirtualDiskDeviceFunctionTable
=
1456 BL_DEVICE_CALLBACKS UdpFunctionTable
=
1463 BL_DEVICE_CALLBACKS SerialPortFunctionTable
=
1471 DeviceTableCompare (
1473 _In_ PVOID Argument1
,
1474 _In_ PVOID Argument2
,
1475 _Inout_ PVOID Argument3
,
1476 _Inout_ PVOID Argument4
1480 PBL_DEVICE_DESCRIPTOR Device
= (PBL_DEVICE_DESCRIPTOR
)Entry
;
1481 PBL_DEVICE_ENTRY DeviceEntry
= (PBL_DEVICE_ENTRY
)Argument1
;
1482 ULONG Flags
= *(PULONG
)Argument2
;
1483 ULONG Unknown
= *(PULONG
)Argument3
;
1485 /* Assume failure */
1488 /* Compare the device descriptor */
1489 if (BlpDeviceCompare(DeviceEntry
->DeviceDescriptor
, Device
))
1491 /* Compare something */
1492 if (DeviceEntry
->Unknown
== Unknown
)
1495 if ((!(Flags
& 1) || (DeviceEntry
->Flags
& 2)) &&
1496 (!(Flags
& 2) || (DeviceEntry
->Flags
& 4)))
1498 /* And more flags */
1499 if (((Flags
& 8) || !(DeviceEntry
->Flags
& 8)) &&
1500 (!(Flags
& 8) || (DeviceEntry
->Flags
& 8)))
1502 /* Found a match! */
1509 /* Return matching state */
1514 DeviceTableDestroyEntry (
1519 PBL_DEVICE_ENTRY DeviceEntry
= (PBL_DEVICE_ENTRY
)Entry
;
1522 /* Call the close routine for this entry */
1523 Status
= DeviceEntry
->Callbacks
.Close(DmDeviceTable
[DeviceId
]);
1525 /* Free the descriptor, and the device itself */
1526 BlMmFreeHeap(DeviceEntry
->DeviceDescriptor
);
1527 BlMmFreeHeap(DeviceEntry
);
1529 /* Clear out the netry, and return */
1530 DmDeviceTable
[DeviceId
] = NULL
;
1539 PBL_DEVICE_ENTRY DeviceEntry
= (PBL_DEVICE_ENTRY
)Entry
;
1542 /* Check if the device is opened */
1543 if (DeviceEntry
->Flags
& 1)
1545 /* It is, so can't purge it */
1546 Status
= STATUS_UNSUCCESSFUL
;
1550 /* It isn't, so destroy the entry */
1551 Status
= DeviceTableDestroyEntry(DeviceEntry
, DeviceEntry
->DeviceId
);
1554 /* Return back to caller */
1559 BlockIoDeviceTableDestroyEntry (
1564 PBL_DEVICE_ENTRY DeviceEntry
= (PBL_DEVICE_ENTRY
)Entry
;
1567 /* Call the close routine for this entry */
1568 Status
= DeviceEntry
->Callbacks
.Close(DeviceEntry
);
1570 /* Free the descriptor, and the device itself */
1571 BlMmFreeHeap(DeviceEntry
->DeviceDescriptor
);
1572 BlMmFreeHeap(DeviceEntry
);
1574 /* Clear out the netry, and return */
1575 BlockIoDeviceTable
[DeviceId
] = NULL
;
1580 BlockIoDeviceTableDestroy (
1586 /* Call the entry destructor on each entry in the table */
1587 Status
= BlTblMap(BlockIoDeviceTable
,
1588 BlockIoDeviceTableEntries
,
1589 BlockIoDeviceTableDestroyEntry
);
1591 /* Free the table and return */
1592 BlMmFreeHeap(BlockIoDeviceTable
);
1601 /* Free the prefetch buffer */
1602 BlMmFreeHeap(BlockIopPrefetchBuffer
);
1604 /* Set state to non initialized */
1605 BlockIoInitialized
= FALSE
;
1608 return STATUS_SUCCESS
;
1612 BlockIoEfiHashFunction (
1613 _In_ PBL_HASH_ENTRY Entry
,
1614 _In_ ULONG TableSize
1617 /* Get rid of the alignment bits to have a more unique number */
1618 return ((ULONG
)Entry
->Value
>> 3) % TableSize
;
1622 BlockIopInitialize (
1628 /* Allocate the block device table and zero it out */
1629 BlockIoDeviceTableEntries
= 8;
1630 BlockIoDeviceTable
= BlMmAllocateHeap(sizeof(PVOID
) *
1631 BlockIoDeviceTableEntries
);
1632 if (!BlockIoDeviceTableEntries
)
1634 return STATUS_NO_MEMORY
;
1636 RtlZeroMemory(BlockIoDeviceTable
, sizeof(PVOID
) * BlockIoDeviceTableEntries
);
1638 /* Register our destructor */
1639 Status
= BlpIoRegisterDestroyRoutine(BlockIoDeviceTableDestroy
);
1640 if (!NT_SUCCESS(Status
))
1645 /* Initialize all counters */
1646 BlockIoFirmwareRemovableDiskCount
= 0;
1647 BlockIoFirmwareRawDiskCount
= 0;
1648 BlockIoFirmwareCdromCount
= 0;
1650 /* Initialize the buffers and their sizes */
1651 BlockIopAlignedBuffer
= NULL
;
1652 BlockIopAlignedBufferSize
= 0;
1653 BlockIopPartialBlockBuffer
= NULL
;
1654 BlockIopPartialBlockBufferSize
= 0;
1655 BlockIopPrefetchBuffer
= NULL
;
1656 BlockIopReadBlockBuffer
= NULL
;
1657 BlockIopReadBlockBufferSize
= 0;
1659 /* Allocate the prefetch buffer */
1660 Status
= MmPapAllocatePagesInRange(&BlockIopPrefetchBuffer
,
1661 BlLoaderDeviceMemory
,
1667 if (NT_SUCCESS(Status
))
1669 /* Initialize the block cache */
1670 Status
= BcInitialize();
1671 if (NT_SUCCESS(Status
))
1673 /* Initialize the block device hash table */
1674 Status
= BlHtCreate(29, BlockIoEfiHashFunction
, NULL
, &HashTableId
);
1675 if (NT_SUCCESS(Status
))
1677 /* Register our destructor */
1678 Status
= BlpIoRegisterDestroyRoutine(BlockIopDestroy
);
1679 if (NT_SUCCESS(Status
))
1682 BlockIoInitialized
= TRUE
;
1688 /* Check if this is the failure path */
1689 if (!NT_SUCCESS(Status
))
1691 /* Free the prefetch buffer is one was allocated */
1692 if (BlockIopPrefetchBuffer
)
1694 EfiPrintf(L
"Failure path not implemented %lx\r\n", Status
);
1695 //MmPapFreePages(BlockIopPrefetchBuffer, 1);
1699 /* Return back to the caller */
1705 BlockIoDeviceTableCompare (
1707 _In_ PVOID Argument1
,
1708 _In_ PVOID Argument2
,
1709 _In_ PVOID Argument3
,
1710 _In_ PVOID Argument4
1713 PBL_DEVICE_ENTRY DeviceEntry
= (PBL_DEVICE_ENTRY
)Entry
;
1714 PBL_DEVICE_DESCRIPTOR Device
= (PBL_DEVICE_DESCRIPTOR
)Argument1
;
1716 /* Compare the two devices */
1717 return BlpDeviceCompare(DeviceEntry
->DeviceDescriptor
, Device
);
1722 _In_ PBL_DEVICE_DESCRIPTOR Device
,
1723 _In_ PBL_DEVICE_ENTRY DeviceEntry
1727 PBL_BLOCK_DEVICE BlockDevice
;
1728 PBL_DEVICE_ENTRY FoundDeviceEntry
;
1731 /* Check if the block I/O manager is initialized */
1732 if (!BlockIoInitialized
)
1734 /* First call, initialize it now */
1735 Status
= BlockIopInitialize();
1736 if (!NT_SUCCESS(Status
))
1738 /* Failed to initialize block I/O */
1739 EfiPrintf(L
"Block I/O Init failed\r\n");
1744 /* Copy a function table for block I/O devices */
1745 RtlCopyMemory(&DeviceEntry
->Callbacks
,
1746 &BlockIoDeviceFunctionTable
,
1747 sizeof(DeviceEntry
->Callbacks
));
1749 /* Allocate a block I/O device */
1750 BlockDevice
= BlMmAllocateHeap(sizeof(*BlockDevice
));
1753 return STATUS_NO_MEMORY
;
1756 /* Set this as the device-specific data for this device entry */
1757 Status
= STATUS_SUCCESS
;
1758 DeviceEntry
->DeviceSpecificData
= BlockDevice
;
1760 /* Check if we already have this device in our device table */
1761 FoundDeviceEntry
= BlTblFindEntry(BlockIoDeviceTable
,
1762 BlockIoDeviceTableEntries
,
1764 BlockIoDeviceTableCompare
,
1769 if (FoundDeviceEntry
)
1771 /* We already found a device, so copy its device data and callbacks */
1772 EfiPrintf(L
"Device entry found: %p\r\n", FoundDeviceEntry
);
1773 RtlCopyMemory(BlockDevice
, FoundDeviceEntry
->DeviceSpecificData
, sizeof(*BlockDevice
));
1774 RtlCopyMemory(&DeviceEntry
->Callbacks
,
1775 &FoundDeviceEntry
->Callbacks
,
1776 sizeof(DeviceEntry
->Callbacks
));
1780 /* Zero out the device for now */
1781 RtlZeroMemory(BlockDevice
, sizeof(*BlockDevice
));
1783 /* Is this a disk? */
1784 if (Device
->DeviceType
== DiskDevice
)
1786 /* What type of disk is it? */
1787 switch (Device
->Local
.Type
)
1789 /* Is it a raw physical disk? */
1793 /* Open a disk device */
1794 Status
= DiskDeviceFunctionTable
.Open(Device
, DeviceEntry
);
1797 /* Is it a RAM disk? */
1799 /* Open a RAM disk */
1800 Status
= RamDiskDeviceFunctionTable
.Open(Device
, DeviceEntry
);
1806 Status
= FileDeviceFunctionTable
.Open(Device
, DeviceEntry
);
1810 case VirtualDiskDevice
:
1811 /* Open a virtual disk */
1812 Status
= VirtualDiskDeviceFunctionTable
.Open(Device
, DeviceEntry
);
1815 /* Is it something else? */
1818 Status
= STATUS_INVALID_PARAMETER
;
1822 else if ((Device
->DeviceType
== LegacyPartitionDevice
) ||
1823 (Device
->DeviceType
== PartitionDevice
))
1825 /* This is a partition on a disk, open it as such */
1826 Status
= PartitionDeviceFunctionTable
.Open(Device
, DeviceEntry
);
1830 /* Other devices are not supported */
1831 Status
= STATUS_INVALID_PARAMETER
;
1834 /* Check for failure */
1835 if (!NT_SUCCESS(Status
))
1837 /* Free any allocations for this device */
1838 BlockIopFreeAllocations(BlockDevice
);
1841 /* Return back to the caller */
1846 BlpDeviceResolveLocate (
1847 _In_ PBL_DEVICE_DESCRIPTOR InputDevice
,
1848 _Out_ PBL_DEVICE_DESCRIPTOR
* LocateDevice
1851 EfiPrintf(L
"Not implemented!\r\n");
1852 return STATUS_NOT_IMPLEMENTED
;
1860 PBL_DEVICE_ENTRY DeviceEntry
;
1862 /* Validate the device ID */
1863 if (DmTableEntries
<= DeviceId
)
1865 return STATUS_INVALID_PARAMETER
;
1868 /* Make sure there's a device there */
1869 DeviceEntry
= DmDeviceTable
[DeviceId
];
1870 if (DeviceEntry
== NULL
)
1872 return STATUS_INVALID_PARAMETER
;
1875 /* Make sure the device is active */
1876 if (!(DeviceEntry
->Flags
& 1))
1878 return STATUS_INVALID_PARAMETER
;
1881 /* Drop a reference and check if it's the last one */
1882 DeviceEntry
->ReferenceCount
--;
1883 if (!DeviceEntry
->ReferenceCount
)
1885 /* Mark the device as inactive */
1886 DeviceEntry
->Flags
= ~1;
1890 return STATUS_SUCCESS
;
1895 _In_ PBL_DEVICE_DESCRIPTOR Device
,
1898 _Out_ PULONG DeviceId
1902 PBL_DEVICE_ENTRY DeviceEntry
;
1903 PBL_DEVICE_DESCRIPTOR LocateDeviceDescriptor
;
1904 PBL_REGISTERED_DEVICE RegisteredDevice
;
1905 PLIST_ENTRY NextEntry
, ListHead
;
1909 /* Check for missing parameters */
1910 if (!(Device
) || !(DeviceId
) || !(Device
->Size
))
1913 Status
= STATUS_INVALID_PARAMETER
;
1917 /* Make sure both read and write access are set */
1918 if (!(Flags
& (BL_DEVICE_READ_ACCESS
| BL_DEVICE_WRITE_ACCESS
)))
1921 Status
= STATUS_INVALID_PARAMETER
;
1925 /* Check if the boot device is being opened */
1926 if (Device
->DeviceType
== BootDevice
)
1929 Device
= BlpBootDevice
;
1932 /* Check if the 'locate' device is being opened */
1933 if (Device
->DeviceType
== LocateDevice
)
1936 Status
= BlpDeviceResolveLocate(Device
, &LocateDeviceDescriptor
);
1937 if (!NT_SUCCESS(Status
))
1939 /* Not found, bail out */
1944 Device
= LocateDeviceDescriptor
;
1947 /* Check if the device isn't ready yet */
1948 if (Device
->Flags
& 1)
1950 /* Return a failure */
1951 Status
= STATUS_DEVICE_NOT_READY
;
1955 /* Check if we already have an entry for the device */
1956 DeviceEntry
= BlTblFindEntry(DmDeviceTable
,
1966 /* Return it, taking a reference on it */
1967 EfiPrintf(L
"Device found: %p\r\n", DeviceEntry
);
1968 *DeviceId
= DeviceEntry
->DeviceId
;
1969 ++DeviceEntry
->ReferenceCount
;
1970 DeviceEntry
->Flags
|= 1;
1971 return STATUS_SUCCESS
;
1974 /* We don't, allocate one */
1975 DeviceEntry
= BlMmAllocateHeap(sizeof(*DeviceEntry
));
1978 Status
= STATUS_NO_MEMORY
;
1983 RtlZeroMemory(DeviceEntry
, sizeof(*DeviceEntry
));
1984 DeviceEntry
->ReferenceCount
= 1;
1985 DeviceEntry
->Flags
|= (BL_DEVICE_ENTRY_OPENED
|
1986 BL_DEVICE_ENTRY_READ_ACCESS
|
1987 BL_DEVICE_ENTRY_WRITE_ACCESS
);
1988 DeviceEntry
->Unknown
= Unknown
;
1990 /* Save flag 8 if needed */
1993 DeviceEntry
->Flags
|= 8;
1996 /* Allocate a device descriptor for the device */
1997 DeviceEntry
->DeviceDescriptor
= BlMmAllocateHeap(Device
->Size
);
1998 if (!DeviceEntry
->DeviceDescriptor
)
2000 Status
= STATUS_NO_MEMORY
;
2004 /* Copy the descriptor that was passed in */
2005 RtlCopyMemory(DeviceEntry
->DeviceDescriptor
, Device
, Device
->Size
);
2007 /* Now loop the list of dynamically registered devices */
2008 ListHead
= &DmRegisteredDevices
;
2009 NextEntry
= ListHead
->Flink
;
2010 while (NextEntry
!= ListHead
)
2012 /* Get the device */
2013 RegisteredDevice
= CONTAINING_RECORD(NextEntry
,
2014 BL_REGISTERED_DEVICE
,
2017 /* Open the device */
2018 Status
= RegisteredDevice
->Callbacks
.Open(Device
, DeviceEntry
);
2019 if (NT_SUCCESS(Status
))
2021 /* The device was opened, so we have the right one */
2025 /* Nope, keep trying */
2026 NextEntry
= NextEntry
->Flink
;
2029 /* Well, it wasn't a dynamic device. Is it a block device? */
2030 if ((Device
->DeviceType
== PartitionDevice
) ||
2031 (Device
->DeviceType
== DiskDevice
) ||
2032 (Device
->DeviceType
== LegacyPartitionDevice
))
2034 /* Call the Block I/O handler */
2035 Status
= BlockIoDeviceFunctionTable
.Open(Device
, DeviceEntry
);
2037 else if (Device
->DeviceType
== SerialDevice
)
2039 /* It's a serial device, call the serial device handler */
2040 Status
= SerialPortFunctionTable
.Open(Device
, DeviceEntry
);
2042 else if (Device
->DeviceType
== UdpDevice
)
2044 /* It's a network device, call the UDP device handler */
2045 Status
= UdpFunctionTable
.Open(Device
, DeviceEntry
);
2049 /* Unsupported type of device */
2050 Status
= STATUS_NOT_IMPLEMENTED
;
2053 /* Check if the device was opened successfuly */
2054 if (NT_SUCCESS(Status
))
2057 /* Save the entry in the device table */
2058 Status
= BlTblSetEntry(&DmDeviceTable
,
2063 if (NT_SUCCESS(Status
))
2065 /* It worked -- return the ID in the table to the caller */
2066 EfiPrintf(L
"Device ID: %lx\r\n", *DeviceId
);
2067 DeviceEntry
->DeviceId
= *DeviceId
;
2068 return STATUS_SUCCESS
;
2073 /* Failure path -- did we allocate a device entry? */
2074 EfiPrintf(L
"Block failure: %lx\r\n", Status
);
2077 /* Yep -- did it have a descriptor? */
2078 if (DeviceEntry
->DeviceDescriptor
)
2081 BlMmFreeHeap(DeviceEntry
->DeviceDescriptor
);
2084 /* Free the entry */
2085 BlMmFreeHeap(DeviceEntry
);
2088 /* Return the failure */
2093 BlpDeviceInitialize (
2099 /* Initialize the table count and list of devices */
2101 InitializeListHead(&DmRegisteredDevices
);
2103 /* Initialize device information */
2104 DmDeviceIoInformation
.ReadCount
= 0;
2105 DmDeviceIoInformation
.WriteCount
= 0;
2107 /* Allocate the device table */
2108 DmDeviceTable
= BlMmAllocateHeap(DmTableEntries
* sizeof(PVOID
));
2112 RtlZeroMemory(DmDeviceTable
, DmTableEntries
* sizeof(PVOID
));
2113 #if BL_BITLOCKER_SUPPORT
2114 /* Initialize BitLocker support */
2115 Status
= FvebInitialize();
2117 Status
= STATUS_SUCCESS
;
2122 /* No memory, we'll fail */
2123 Status
= STATUS_NO_MEMORY
;
2126 /* Return initialization state */