3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 DiskIo driver that layers it's self on every Block IO protocol in the system.
19 DiskIo converts a block oriented device to a byte oriented device.
21 ReadDisk may have to do reads that are not aligned on sector boundaries.
22 There are three cases:
24 UnderRun - The first byte is not on a sector boundary or the read request is
25 less than a sector in length.
27 Aligned - A read of N contiguous sectors.
29 OverRun - The last byte is not on a sector boundary.
37 // Driver model protocol interface
41 DiskIoDriverBindingSupported (
42 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
43 IN EFI_HANDLE ControllerHandle
,
44 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
49 DiskIoDriverBindingStart (
50 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
51 IN EFI_HANDLE ControllerHandle
,
52 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
57 DiskIoDriverBindingStop (
58 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
59 IN EFI_HANDLE ControllerHandle
,
60 IN UINTN NumberOfChildren
,
61 IN EFI_HANDLE
*ChildHandleBuffer
65 // Disk I/O Protocol Interface
70 IN EFI_DISK_IO_PROTOCOL
*This
,
80 IN EFI_DISK_IO_PROTOCOL
*This
,
87 EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding
= {
88 DiskIoDriverBindingSupported
,
89 DiskIoDriverBindingStart
,
90 DiskIoDriverBindingStop
,
96 DISK_IO_PRIVATE_DATA gDiskIoPrivateDataTemplate
= {
97 DISK_IO_PRIVATE_DATA_SIGNATURE
,
99 EFI_DISK_IO_PROTOCOL_REVISION
,
108 DiskIoDriverBindingSupported (
109 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
110 IN EFI_HANDLE ControllerHandle
,
111 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
116 Test to see if this driver supports ControllerHandle. Any ControllerHandle
117 than contains a BlockIo protocol can be supported.
120 This - Protocol instance pointer.
121 ControllerHandle - Handle of device to test.
122 RemainingDevicePath - Not used.
125 EFI_SUCCESS - This driver supports this device.
126 EFI_ALREADY_STARTED - This driver is already running on this device.
127 other - This driver does not support this device.
132 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
142 Bar = PcdGet32 (PciExpressBaseVersion);
143 DEBUG ((EFI_D_ERROR, "PciExpressBaseVersion = %08x\n", Bar));
148 Foo = PcdGet32 (PciExpressBaseAddress);
149 DEBUG ((EFI_D_ERROR, "PciExpressBaseAddress = %08x\n", Foo));
154 PcdSet32 (PciExpressBaseAddress, Foo + 1);
159 Foo = PcdGet32 (PciExpressBaseAddress);
160 DEBUG ((EFI_D_ERROR, "PciExpressBaseAddress = %08x\n", Foo));
165 HotPlug = PcdGet32 (PciExpressBaseHotPlug);
166 DEBUG ((EFI_D_ERROR, "PciExpressHotPlug = %08x\n", HotPlug));
171 PcdSet32 (PciExpressBaseHotPlug, HotPlug + 1);
176 HotPlug = PcdGet32 (PciExpressBaseHotPlug);
177 DEBUG ((EFI_D_ERROR, "PciExpressHotPlug = %08x\n", HotPlug));
184 if (ControllerHandle == NULL) {
185 MyVariable = 32 * (UINTN)This;
186 ControllerHandle = (EFI_HANDLE)MyVariable;
187 DEBUG ((EFI_D_ERROR, "DiskIoSupported-DebugCode. MyVariable = %08x\n", MyVariable));
188 ASSERT (MyVariable != 32);
192 DEBUG ((EFI_D_ERROR
, "DiskIoSupported\n"));
195 // Io8And (0x400, 1);
196 // Io8AndThenOr (0x400, 1, 2);
198 // Mmio8Or (0xa0000000, 1);
199 // Mmio8And (0xa0000000, 1);
200 // Mmio8AndThenOr (0xa0000000, 1, 2);
203 PciRead8 (PCI_LIB_ADDRESS (1,2,3,4));
204 PciRead16 (PCI_LIB_ADDRESS (1,2,3,4));
205 PciRead32 (PCI_LIB_ADDRESS (1,2,3,4));
207 PciWrite8 (PCI_LIB_ADDRESS (1,2,3,4), 0xAA);
208 PciWrite16 (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55);
209 PciWrite32 (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55A55A);
211 Pci8Or (PCI_LIB_ADDRESS (1,2,3,4), 0xAA);
212 Pci8And (PCI_LIB_ADDRESS (1,2,3,4), 0x55);
213 Pci8AndThenOr (PCI_LIB_ADDRESS (1,2,3,4), 0xAA, 0x55);
215 Pci16Or (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55);
216 Pci16And (PCI_LIB_ADDRESS (1,2,3,4), 0x55AA);
217 Pci16AndThenOr (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55, 0x55AA);
219 Pci32Or (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55A55A);
220 Pci32And (PCI_LIB_ADDRESS (1,2,3,4), 0x55AA5AA5);
221 Pci32AndThenOr (PCI_LIB_ADDRESS (1,2,3,4), 0xAA555AA5, 0x55AAA55A);
224 // Open the IO Abstraction(s) needed to perform the supported test.
226 Status
= gBS
->OpenProtocol (
228 &gEfiBlockIoProtocolGuid
,
230 This
->DriverBindingHandle
,
232 EFI_OPEN_PROTOCOL_BY_DRIVER
234 if (EFI_ERROR (Status
)) {
238 // Close the I/O Abstraction(s) used to perform the supported test.
242 &gEfiBlockIoProtocolGuid
,
243 This
->DriverBindingHandle
,
251 DiskIoDriverBindingStart (
252 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
253 IN EFI_HANDLE ControllerHandle
,
254 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
259 Start this driver on ControllerHandle by opening a Block IO protocol and
260 installing a Disk IO protocol on ControllerHandle.
263 This - Protocol instance pointer.
264 ControllerHandle - Handle of device to bind driver to.
265 RemainingDevicePath - Not used, always produce all possible children.
268 EFI_SUCCESS - This driver is added to ControllerHandle.
269 EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
270 other - This driver does not support this device.
275 DISK_IO_PRIVATE_DATA
*Private
;
279 DEBUG ((EFI_D_ERROR
, "DiskIoStart\n"));
281 // Connect to the Block IO interface on ControllerHandle.
283 Status
= gBS
->OpenProtocol (
285 &gEfiBlockIoProtocolGuid
,
286 (VOID
**) &gDiskIoPrivateDataTemplate
.BlockIo
,
287 This
->DriverBindingHandle
,
289 EFI_OPEN_PROTOCOL_BY_DRIVER
291 if (EFI_ERROR (Status
)) {
295 // Initialize the Disk IO device instance.
297 Private
= AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA
), &gDiskIoPrivateDataTemplate
);
298 if (Private
== NULL
) {
299 Status
= EFI_OUT_OF_RESOURCES
;
303 // Install protocol interfaces for the Disk IO device.
305 Status
= gBS
->InstallProtocolInterface (
307 &gEfiDiskIoProtocolGuid
,
308 EFI_NATIVE_INTERFACE
,
313 if (EFI_ERROR (Status
)) {
315 if (Private
!= NULL
) {
316 gBS
->FreePool (Private
);
321 &gEfiBlockIoProtocolGuid
,
322 This
->DriverBindingHandle
,
332 DiskIoDriverBindingStop (
333 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
334 IN EFI_HANDLE ControllerHandle
,
335 IN UINTN NumberOfChildren
,
336 IN EFI_HANDLE
*ChildHandleBuffer
341 Stop this driver on ControllerHandle by removing Disk IO protocol and closing
342 the Block IO protocol on ControllerHandle.
345 This - Protocol instance pointer.
346 ControllerHandle - Handle of device to stop driver on.
347 NumberOfChildren - Not used.
348 ChildHandleBuffer - Not used.
351 EFI_SUCCESS - This driver is removed ControllerHandle.
352 other - This driver was not removed from this device.
358 EFI_DISK_IO_PROTOCOL
*DiskIo
;
359 DISK_IO_PRIVATE_DATA
*Private
;
361 DEBUG ((EFI_D_ERROR
, "DiskIoStop\n"));
363 // Get our context back.
365 Status
= gBS
->OpenProtocol (
367 &gEfiDiskIoProtocolGuid
,
369 This
->DriverBindingHandle
,
371 EFI_OPEN_PROTOCOL_GET_PROTOCOL
373 if (EFI_ERROR (Status
)) {
374 return EFI_UNSUPPORTED
;
377 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (DiskIo
);
379 Status
= gBS
->UninstallProtocolInterface (
381 &gEfiDiskIoProtocolGuid
,
384 if (!EFI_ERROR (Status
)) {
386 Status
= gBS
->CloseProtocol (
388 &gEfiBlockIoProtocolGuid
,
389 This
->DriverBindingHandle
,
394 if (!EFI_ERROR (Status
)) {
395 gBS
->FreePool (Private
);
404 IN EFI_DISK_IO_PROTOCOL
*This
,
413 Read BufferSize bytes from Offset into Buffer.
415 Reads may support reads that are not aligned on
416 sector boundaries. There are three cases:
418 UnderRun - The first byte is not on a sector boundary or the read request is
419 less than a sector in length.
421 Aligned - A read of N contiguous sectors.
423 OverRun - The last byte is not on a sector boundary.
427 This - Protocol instance pointer.
428 MediaId - Id of the media, changes every time the media is replaced.
429 Offset - The starting byte offset to read from.
430 BufferSize - Size of Buffer.
431 Buffer - Buffer containing read data.
434 EFI_SUCCESS - The data was read correctly from the device.
435 EFI_DEVICE_ERROR - The device reported an error while performing the read.
436 EFI_NO_MEDIA - There is no media in the device.
437 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
438 EFI_INVALID_PARAMETER - The read request contains device addresses that are not
439 valid for the device.
445 DISK_IO_PRIVATE_DATA
*Private
;
446 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
447 EFI_BLOCK_IO_MEDIA
*Media
;
453 BOOLEAN TransactionComplete
;
454 UINTN WorkingBufferSize
;
455 UINT8
*WorkingBuffer
;
459 UINTN IsBufferAligned
;
460 UINTN DataBufferSize
;
463 DEBUG ((EFI_D_ERROR
, "DiskIoReadDisk\n"));
465 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (This
);
467 BlockIo
= Private
->BlockIo
;
468 Media
= BlockIo
->Media
;
469 BlockSize
= Media
->BlockSize
;
471 if (Media
->MediaId
!= MediaId
) {
472 return EFI_MEDIA_CHANGED
;
475 WorkingBuffer
= Buffer
;
476 WorkingBufferSize
= BufferSize
;
479 // Allocate a temporary buffer for operation
481 DataBufferSize
= BlockSize
* DATA_BUFFER_BLOCK_NUM
;
483 if (Media
->IoAlign
> 1) {
484 PreData
= AllocatePool (DataBufferSize
+ Media
->IoAlign
);
485 Data
= PreData
- ((UINTN
) PreData
& (Media
->IoAlign
- 1)) + Media
->IoAlign
;
487 PreData
= AllocatePool (DataBufferSize
);
491 if (PreData
== NULL
) {
492 return EFI_OUT_OF_RESOURCES
;
495 Lba
= DivU64x32Remainder (Offset
, BlockSize
, &UnderRun
);
497 Length
= BlockSize
- UnderRun
;
498 TransactionComplete
= FALSE
;
500 Status
= EFI_SUCCESS
;
503 // Offset starts in the middle of an Lba, so read the entire block.
505 Status
= BlockIo
->ReadBlocks (
513 if (EFI_ERROR (Status
)) {
517 if (Length
> BufferSize
) {
519 TransactionComplete
= TRUE
;
522 CopyMem (WorkingBuffer
, Data
+ UnderRun
, Length
);
524 WorkingBuffer
+= Length
;
526 WorkingBufferSize
-= Length
;
527 if (WorkingBufferSize
== 0) {
534 OverRunLba
= Lba
+ DivU64x32Remainder (WorkingBufferSize
, BlockSize
, &OverRun
);
536 if (!TransactionComplete
&& WorkingBufferSize
>= BlockSize
) {
538 // If the DiskIo maps directly to a BlockIo device do the read.
541 WorkingBufferSize
-= OverRun
;
544 // Check buffer alignment
546 IsBufferAligned
= (UINTN
) WorkingBuffer
& (UINTN
) (Media
->IoAlign
- 1);
548 if (Media
->IoAlign
<= 1 || IsBufferAligned
== 0) {
550 // Alignment is satisfied, so read them together
552 Status
= BlockIo
->ReadBlocks (
560 if (EFI_ERROR (Status
)) {
564 WorkingBuffer
+= WorkingBufferSize
;
568 // Use the allocated buffer instead of the original buffer
569 // to avoid alignment issue.
570 // Here, the allocated buffer (8-byte align) can satisfy the alignment
574 if (WorkingBufferSize
<= DataBufferSize
) {
576 // It is the last calling to readblocks in this loop
578 DataBufferSize
= WorkingBufferSize
;
582 Status
= BlockIo
->ReadBlocks (
589 if (EFI_ERROR (Status
)) {
593 CopyMem (WorkingBuffer
, Data
, DataBufferSize
);
594 WorkingBufferSize
-= DataBufferSize
;
595 WorkingBuffer
+= DataBufferSize
;
596 Lba
+= DATA_BUFFER_BLOCK_NUM
;
601 if (!TransactionComplete
&& OverRun
!= 0) {
603 // Last read is not a complete block.
605 Status
= BlockIo
->ReadBlocks (
613 if (EFI_ERROR (Status
)) {
617 CopyMem (WorkingBuffer
, Data
, OverRun
);
621 if (PreData
!= NULL
) {
622 gBS
->FreePool (PreData
);
631 IN EFI_DISK_IO_PROTOCOL
*This
,
640 Read BufferSize bytes from Offset into Buffer.
642 Writes may require a read modify write to support writes that are not
643 aligned on sector boundaries. There are three cases:
645 UnderRun - The first byte is not on a sector boundary or the write request
646 is less than a sector in length. Read modify write is required.
648 Aligned - A write of N contiguous sectors.
650 OverRun - The last byte is not on a sector boundary. Read modified write
654 This - Protocol instance pointer.
655 MediaId - Id of the media, changes every time the media is replaced.
656 Offset - The starting byte offset to read from.
657 BufferSize - Size of Buffer.
658 Buffer - Buffer containing read data.
661 EFI_SUCCESS - The data was written correctly to the device.
662 EFI_WRITE_PROTECTED - The device can not be written to.
663 EFI_DEVICE_ERROR - The device reported an error while performing the write.
664 EFI_NO_MEDIA - There is no media in the device.
665 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
666 EFI_INVALID_PARAMETER - The write request contains device addresses that are not
667 valid for the device.
673 DISK_IO_PRIVATE_DATA
*Private
;
674 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
675 EFI_BLOCK_IO_MEDIA
*Media
;
681 BOOLEAN TransactionComplete
;
682 UINTN WorkingBufferSize
;
683 UINT8
*WorkingBuffer
;
687 UINTN IsBufferAligned
;
688 UINTN DataBufferSize
;
691 DEBUG ((EFI_D_ERROR
, "DiskIoWriteDisk\n"));
693 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (This
);
695 BlockIo
= Private
->BlockIo
;
696 Media
= BlockIo
->Media
;
697 BlockSize
= Media
->BlockSize
;
699 if (Media
->ReadOnly
) {
700 return EFI_WRITE_PROTECTED
;
703 if (Media
->MediaId
!= MediaId
) {
704 return EFI_MEDIA_CHANGED
;
707 DataBufferSize
= BlockSize
* DATA_BUFFER_BLOCK_NUM
;
709 if (Media
->IoAlign
> 1) {
710 PreData
= AllocatePool (DataBufferSize
+ Media
->IoAlign
);
711 Data
= PreData
- ((UINTN
) PreData
& (Media
->IoAlign
- 1)) + Media
->IoAlign
;
713 PreData
= AllocatePool (DataBufferSize
);
717 if (PreData
== NULL
) {
718 return EFI_OUT_OF_RESOURCES
;
721 WorkingBuffer
= Buffer
;
722 WorkingBufferSize
= BufferSize
;
724 Lba
= DivU64x32Remainder (Offset
, BlockSize
, &UnderRun
);
726 Length
= BlockSize
- UnderRun
;
727 TransactionComplete
= FALSE
;
729 Status
= EFI_SUCCESS
;
732 // Offset starts in the middle of an Lba, so do read modify write.
734 Status
= BlockIo
->ReadBlocks (
742 if (EFI_ERROR (Status
)) {
746 if (Length
> BufferSize
) {
748 TransactionComplete
= TRUE
;
751 CopyMem (Data
+ UnderRun
, WorkingBuffer
, Length
);
753 Status
= BlockIo
->WriteBlocks (
760 if (EFI_ERROR (Status
)) {
764 WorkingBuffer
+= Length
;
765 WorkingBufferSize
-= Length
;
766 if (WorkingBufferSize
== 0) {
773 OverRunLba
= Lba
+ DivU64x32Remainder (WorkingBufferSize
, BlockSize
, &OverRun
);
775 if (!TransactionComplete
&& WorkingBufferSize
>= BlockSize
) {
777 // If the DiskIo maps directly to a BlockIo device do the write.
780 WorkingBufferSize
-= OverRun
;
783 // Check buffer alignment
785 IsBufferAligned
= (UINTN
) WorkingBuffer
& (UINTN
) (Media
->IoAlign
- 1);
787 if (Media
->IoAlign
<= 1 || IsBufferAligned
== 0) {
789 // Alignment is satisfied, so write them together
791 Status
= BlockIo
->WriteBlocks (
799 if (EFI_ERROR (Status
)) {
803 WorkingBuffer
+= WorkingBufferSize
;
807 // The buffer parameter is not aligned with the request
808 // So use the allocated instead.
809 // It can fit almost all the cases.
813 if (WorkingBufferSize
<= DataBufferSize
) {
815 // It is the last calling to writeblocks in this loop
817 DataBufferSize
= WorkingBufferSize
;
821 CopyMem (Data
, WorkingBuffer
, DataBufferSize
);
822 Status
= BlockIo
->WriteBlocks (
829 if (EFI_ERROR (Status
)) {
833 WorkingBufferSize
-= DataBufferSize
;
834 WorkingBuffer
+= DataBufferSize
;
835 Lba
+= DATA_BUFFER_BLOCK_NUM
;
836 } while (!LastWrite
);
840 if (!TransactionComplete
&& OverRun
!= 0) {
842 // Last bit is not a complete block, so do a read modify write.
844 Status
= BlockIo
->ReadBlocks (
852 if (EFI_ERROR (Status
)) {
856 CopyMem (Data
, WorkingBuffer
, OverRun
);
858 Status
= BlockIo
->WriteBlocks (
865 if (EFI_ERROR (Status
)) {
871 if (PreData
!= NULL
) {
872 gBS
->FreePool (PreData
);