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.
34 // Include common header file for this module.
36 #include "CommonHeader.h"
40 EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding
= {
41 DiskIoDriverBindingSupported
,
42 DiskIoDriverBindingStart
,
43 DiskIoDriverBindingStop
,
49 DISK_IO_PRIVATE_DATA gDiskIoPrivateDataTemplate
= {
50 DISK_IO_PRIVATE_DATA_SIGNATURE
,
52 EFI_DISK_IO_PROTOCOL_REVISION
,
61 DiskIoDriverBindingSupported (
62 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
63 IN EFI_HANDLE ControllerHandle
,
64 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
69 Test to see if this driver supports ControllerHandle. Any ControllerHandle
70 than contains a BlockIo protocol can be supported.
73 This - Protocol instance pointer.
74 ControllerHandle - Handle of device to test.
75 RemainingDevicePath - Not used.
78 EFI_SUCCESS - This driver supports this device.
79 EFI_ALREADY_STARTED - This driver is already running on this device.
80 other - This driver does not support this device.
85 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
88 // Open the IO Abstraction(s) needed to perform the supported test.
90 Status
= gBS
->OpenProtocol (
92 &gEfiBlockIoProtocolGuid
,
94 This
->DriverBindingHandle
,
96 EFI_OPEN_PROTOCOL_BY_DRIVER
98 if (EFI_ERROR (Status
)) {
102 // Close the I/O Abstraction(s) used to perform the supported test.
106 &gEfiBlockIoProtocolGuid
,
107 This
->DriverBindingHandle
,
115 DiskIoDriverBindingStart (
116 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
117 IN EFI_HANDLE ControllerHandle
,
118 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
123 Start this driver on ControllerHandle by opening a Block IO protocol and
124 installing a Disk IO protocol on ControllerHandle.
127 This - Protocol instance pointer.
128 ControllerHandle - Handle of device to bind driver to.
129 RemainingDevicePath - Not used, always produce all possible children.
132 EFI_SUCCESS - This driver is added to ControllerHandle.
133 EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
134 other - This driver does not support this device.
139 DISK_IO_PRIVATE_DATA
*Private
;
144 // Connect to the Block IO interface on ControllerHandle.
146 Status
= gBS
->OpenProtocol (
148 &gEfiBlockIoProtocolGuid
,
149 (VOID
**) &gDiskIoPrivateDataTemplate
.BlockIo
,
150 This
->DriverBindingHandle
,
152 EFI_OPEN_PROTOCOL_BY_DRIVER
154 if (EFI_ERROR (Status
)) {
158 // Initialize the Disk IO device instance.
160 Private
= AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA
), &gDiskIoPrivateDataTemplate
);
161 if (Private
== NULL
) {
162 Status
= EFI_OUT_OF_RESOURCES
;
166 // Install protocol interfaces for the Disk IO device.
168 Status
= gBS
->InstallProtocolInterface (
170 &gEfiDiskIoProtocolGuid
,
171 EFI_NATIVE_INTERFACE
,
176 if (EFI_ERROR (Status
)) {
178 if (Private
!= NULL
) {
184 &gEfiBlockIoProtocolGuid
,
185 This
->DriverBindingHandle
,
195 DiskIoDriverBindingStop (
196 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
197 IN EFI_HANDLE ControllerHandle
,
198 IN UINTN NumberOfChildren
,
199 IN EFI_HANDLE
*ChildHandleBuffer
204 Stop this driver on ControllerHandle by removing Disk IO protocol and closing
205 the Block IO protocol on ControllerHandle.
208 This - Protocol instance pointer.
209 ControllerHandle - Handle of device to stop driver on.
210 NumberOfChildren - Not used.
211 ChildHandleBuffer - Not used.
214 EFI_SUCCESS - This driver is removed ControllerHandle.
215 other - This driver was not removed from this device.
221 EFI_DISK_IO_PROTOCOL
*DiskIo
;
222 DISK_IO_PRIVATE_DATA
*Private
;
225 // Get our context back.
227 Status
= gBS
->OpenProtocol (
229 &gEfiDiskIoProtocolGuid
,
231 This
->DriverBindingHandle
,
233 EFI_OPEN_PROTOCOL_GET_PROTOCOL
235 if (EFI_ERROR (Status
)) {
236 return EFI_UNSUPPORTED
;
239 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (DiskIo
);
241 Status
= gBS
->UninstallProtocolInterface (
243 &gEfiDiskIoProtocolGuid
,
246 if (!EFI_ERROR (Status
)) {
248 Status
= gBS
->CloseProtocol (
250 &gEfiBlockIoProtocolGuid
,
251 This
->DriverBindingHandle
,
256 if (!EFI_ERROR (Status
)) {
266 IN EFI_DISK_IO_PROTOCOL
*This
,
275 Read BufferSize bytes from Offset into Buffer.
277 Reads may support reads that are not aligned on
278 sector boundaries. There are three cases:
280 UnderRun - The first byte is not on a sector boundary or the read request is
281 less than a sector in length.
283 Aligned - A read of N contiguous sectors.
285 OverRun - The last byte is not on a sector boundary.
289 This - Protocol instance pointer.
290 MediaId - Id of the media, changes every time the media is replaced.
291 Offset - The starting byte offset to read from.
292 BufferSize - Size of Buffer.
293 Buffer - Buffer containing read data.
296 EFI_SUCCESS - The data was read correctly from the device.
297 EFI_DEVICE_ERROR - The device reported an error while performing the read.
298 EFI_NO_MEDIA - There is no media in the device.
299 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
300 EFI_INVALID_PARAMETER - The read request contains device addresses that are not
301 valid for the device.
307 DISK_IO_PRIVATE_DATA
*Private
;
308 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
309 EFI_BLOCK_IO_MEDIA
*Media
;
315 BOOLEAN TransactionComplete
;
316 UINTN WorkingBufferSize
;
317 UINT8
*WorkingBuffer
;
321 UINTN IsBufferAligned
;
322 UINTN DataBufferSize
;
325 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (This
);
327 BlockIo
= Private
->BlockIo
;
328 Media
= BlockIo
->Media
;
329 BlockSize
= Media
->BlockSize
;
331 if (Media
->MediaId
!= MediaId
) {
332 return EFI_MEDIA_CHANGED
;
335 WorkingBuffer
= Buffer
;
336 WorkingBufferSize
= BufferSize
;
339 // Allocate a temporary buffer for operation
341 DataBufferSize
= BlockSize
* DATA_BUFFER_BLOCK_NUM
;
343 if (Media
->IoAlign
> 1) {
344 PreData
= AllocatePool (DataBufferSize
+ Media
->IoAlign
);
345 Data
= PreData
- ((UINTN
) PreData
& (Media
->IoAlign
- 1)) + Media
->IoAlign
;
347 PreData
= AllocatePool (DataBufferSize
);
351 if (PreData
== NULL
) {
352 return EFI_OUT_OF_RESOURCES
;
355 Lba
= DivU64x32Remainder (Offset
, BlockSize
, &UnderRun
);
357 Length
= BlockSize
- UnderRun
;
358 TransactionComplete
= FALSE
;
360 Status
= EFI_SUCCESS
;
363 // Offset starts in the middle of an Lba, so read the entire block.
365 Status
= BlockIo
->ReadBlocks (
373 if (EFI_ERROR (Status
)) {
377 if (Length
> BufferSize
) {
379 TransactionComplete
= TRUE
;
382 CopyMem (WorkingBuffer
, Data
+ UnderRun
, Length
);
384 WorkingBuffer
+= Length
;
386 WorkingBufferSize
-= Length
;
387 if (WorkingBufferSize
== 0) {
394 OverRunLba
= Lba
+ DivU64x32Remainder (WorkingBufferSize
, BlockSize
, &OverRun
);
396 if (!TransactionComplete
&& WorkingBufferSize
>= BlockSize
) {
398 // If the DiskIo maps directly to a BlockIo device do the read.
401 WorkingBufferSize
-= OverRun
;
404 // Check buffer alignment
406 IsBufferAligned
= (UINTN
) WorkingBuffer
& (UINTN
) (Media
->IoAlign
- 1);
408 if (Media
->IoAlign
<= 1 || IsBufferAligned
== 0) {
410 // Alignment is satisfied, so read them together
412 Status
= BlockIo
->ReadBlocks (
420 if (EFI_ERROR (Status
)) {
424 WorkingBuffer
+= WorkingBufferSize
;
428 // Use the allocated buffer instead of the original buffer
429 // to avoid alignment issue.
430 // Here, the allocated buffer (8-byte align) can satisfy the alignment
434 if (WorkingBufferSize
<= DataBufferSize
) {
436 // It is the last calling to readblocks in this loop
438 DataBufferSize
= WorkingBufferSize
;
442 Status
= BlockIo
->ReadBlocks (
449 if (EFI_ERROR (Status
)) {
453 CopyMem (WorkingBuffer
, Data
, DataBufferSize
);
454 WorkingBufferSize
-= DataBufferSize
;
455 WorkingBuffer
+= DataBufferSize
;
456 Lba
+= DATA_BUFFER_BLOCK_NUM
;
461 if (!TransactionComplete
&& OverRun
!= 0) {
463 // Last read is not a complete block.
465 Status
= BlockIo
->ReadBlocks (
473 if (EFI_ERROR (Status
)) {
477 CopyMem (WorkingBuffer
, Data
, OverRun
);
481 if (PreData
!= NULL
) {
491 IN EFI_DISK_IO_PROTOCOL
*This
,
500 Read BufferSize bytes from Offset into Buffer.
502 Writes may require a read modify write to support writes that are not
503 aligned on sector boundaries. There are three cases:
505 UnderRun - The first byte is not on a sector boundary or the write request
506 is less than a sector in length. Read modify write is required.
508 Aligned - A write of N contiguous sectors.
510 OverRun - The last byte is not on a sector boundary. Read modified write
514 This - Protocol instance pointer.
515 MediaId - Id of the media, changes every time the media is replaced.
516 Offset - The starting byte offset to read from.
517 BufferSize - Size of Buffer.
518 Buffer - Buffer containing read data.
521 EFI_SUCCESS - The data was written correctly to the device.
522 EFI_WRITE_PROTECTED - The device can not be written to.
523 EFI_DEVICE_ERROR - The device reported an error while performing the write.
524 EFI_NO_MEDIA - There is no media in the device.
525 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
526 EFI_INVALID_PARAMETER - The write request contains device addresses that are not
527 valid for the device.
533 DISK_IO_PRIVATE_DATA
*Private
;
534 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
535 EFI_BLOCK_IO_MEDIA
*Media
;
541 BOOLEAN TransactionComplete
;
542 UINTN WorkingBufferSize
;
543 UINT8
*WorkingBuffer
;
547 UINTN IsBufferAligned
;
548 UINTN DataBufferSize
;
551 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (This
);
553 BlockIo
= Private
->BlockIo
;
554 Media
= BlockIo
->Media
;
555 BlockSize
= Media
->BlockSize
;
557 if (Media
->ReadOnly
) {
558 return EFI_WRITE_PROTECTED
;
561 if (Media
->MediaId
!= MediaId
) {
562 return EFI_MEDIA_CHANGED
;
565 DataBufferSize
= BlockSize
* DATA_BUFFER_BLOCK_NUM
;
567 if (Media
->IoAlign
> 1) {
568 PreData
= AllocatePool (DataBufferSize
+ Media
->IoAlign
);
569 Data
= PreData
- ((UINTN
) PreData
& (Media
->IoAlign
- 1)) + Media
->IoAlign
;
571 PreData
= AllocatePool (DataBufferSize
);
575 if (PreData
== NULL
) {
576 return EFI_OUT_OF_RESOURCES
;
579 WorkingBuffer
= Buffer
;
580 WorkingBufferSize
= BufferSize
;
582 Lba
= DivU64x32Remainder (Offset
, BlockSize
, &UnderRun
);
584 Length
= BlockSize
- UnderRun
;
585 TransactionComplete
= FALSE
;
587 Status
= EFI_SUCCESS
;
590 // Offset starts in the middle of an Lba, so do read modify write.
592 Status
= BlockIo
->ReadBlocks (
600 if (EFI_ERROR (Status
)) {
604 if (Length
> BufferSize
) {
606 TransactionComplete
= TRUE
;
609 CopyMem (Data
+ UnderRun
, WorkingBuffer
, Length
);
611 Status
= BlockIo
->WriteBlocks (
618 if (EFI_ERROR (Status
)) {
622 WorkingBuffer
+= Length
;
623 WorkingBufferSize
-= Length
;
624 if (WorkingBufferSize
== 0) {
631 OverRunLba
= Lba
+ DivU64x32Remainder (WorkingBufferSize
, BlockSize
, &OverRun
);
633 if (!TransactionComplete
&& WorkingBufferSize
>= BlockSize
) {
635 // If the DiskIo maps directly to a BlockIo device do the write.
638 WorkingBufferSize
-= OverRun
;
641 // Check buffer alignment
643 IsBufferAligned
= (UINTN
) WorkingBuffer
& (UINTN
) (Media
->IoAlign
- 1);
645 if (Media
->IoAlign
<= 1 || IsBufferAligned
== 0) {
647 // Alignment is satisfied, so write them together
649 Status
= BlockIo
->WriteBlocks (
657 if (EFI_ERROR (Status
)) {
661 WorkingBuffer
+= WorkingBufferSize
;
665 // The buffer parameter is not aligned with the request
666 // So use the allocated instead.
667 // It can fit almost all the cases.
671 if (WorkingBufferSize
<= DataBufferSize
) {
673 // It is the last calling to writeblocks in this loop
675 DataBufferSize
= WorkingBufferSize
;
679 CopyMem (Data
, WorkingBuffer
, DataBufferSize
);
680 Status
= BlockIo
->WriteBlocks (
687 if (EFI_ERROR (Status
)) {
691 WorkingBufferSize
-= DataBufferSize
;
692 WorkingBuffer
+= DataBufferSize
;
693 Lba
+= DATA_BUFFER_BLOCK_NUM
;
694 } while (!LastWrite
);
698 if (!TransactionComplete
&& OverRun
!= 0) {
700 // Last bit is not a complete block, so do a read modify write.
702 Status
= BlockIo
->ReadBlocks (
710 if (EFI_ERROR (Status
)) {
714 CopyMem (Data
, WorkingBuffer
, OverRun
);
716 Status
= BlockIo
->WriteBlocks (
723 if (EFI_ERROR (Status
)) {
729 if (PreData
!= NULL
) {