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
;
135 // Open the IO Abstraction(s) needed to perform the supported test.
137 Status
= gBS
->OpenProtocol (
139 &gEfiBlockIoProtocolGuid
,
141 This
->DriverBindingHandle
,
143 EFI_OPEN_PROTOCOL_BY_DRIVER
145 if (EFI_ERROR (Status
)) {
149 // Close the I/O Abstraction(s) used to perform the supported test.
153 &gEfiBlockIoProtocolGuid
,
154 This
->DriverBindingHandle
,
162 DiskIoDriverBindingStart (
163 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
164 IN EFI_HANDLE ControllerHandle
,
165 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
170 Start this driver on ControllerHandle by opening a Block IO protocol and
171 installing a Disk IO protocol on ControllerHandle.
174 This - Protocol instance pointer.
175 ControllerHandle - Handle of device to bind driver to.
176 RemainingDevicePath - Not used, always produce all possible children.
179 EFI_SUCCESS - This driver is added to ControllerHandle.
180 EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
181 other - This driver does not support this device.
186 DISK_IO_PRIVATE_DATA
*Private
;
191 // Connect to the Block IO interface on ControllerHandle.
193 Status
= gBS
->OpenProtocol (
195 &gEfiBlockIoProtocolGuid
,
196 (VOID
**) &gDiskIoPrivateDataTemplate
.BlockIo
,
197 This
->DriverBindingHandle
,
199 EFI_OPEN_PROTOCOL_BY_DRIVER
201 if (EFI_ERROR (Status
)) {
205 // Initialize the Disk IO device instance.
207 Private
= AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA
), &gDiskIoPrivateDataTemplate
);
208 if (Private
== NULL
) {
209 Status
= EFI_OUT_OF_RESOURCES
;
213 // Install protocol interfaces for the Disk IO device.
215 Status
= gBS
->InstallProtocolInterface (
217 &gEfiDiskIoProtocolGuid
,
218 EFI_NATIVE_INTERFACE
,
223 if (EFI_ERROR (Status
)) {
225 if (Private
!= NULL
) {
226 gBS
->FreePool (Private
);
231 &gEfiBlockIoProtocolGuid
,
232 This
->DriverBindingHandle
,
242 DiskIoDriverBindingStop (
243 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
244 IN EFI_HANDLE ControllerHandle
,
245 IN UINTN NumberOfChildren
,
246 IN EFI_HANDLE
*ChildHandleBuffer
251 Stop this driver on ControllerHandle by removing Disk IO protocol and closing
252 the Block IO protocol on ControllerHandle.
255 This - Protocol instance pointer.
256 ControllerHandle - Handle of device to stop driver on.
257 NumberOfChildren - Not used.
258 ChildHandleBuffer - Not used.
261 EFI_SUCCESS - This driver is removed ControllerHandle.
262 other - This driver was not removed from this device.
268 EFI_DISK_IO_PROTOCOL
*DiskIo
;
269 DISK_IO_PRIVATE_DATA
*Private
;
272 // Get our context back.
274 Status
= gBS
->OpenProtocol (
276 &gEfiDiskIoProtocolGuid
,
278 This
->DriverBindingHandle
,
280 EFI_OPEN_PROTOCOL_GET_PROTOCOL
282 if (EFI_ERROR (Status
)) {
283 return EFI_UNSUPPORTED
;
286 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (DiskIo
);
288 Status
= gBS
->UninstallProtocolInterface (
290 &gEfiDiskIoProtocolGuid
,
293 if (!EFI_ERROR (Status
)) {
295 Status
= gBS
->CloseProtocol (
297 &gEfiBlockIoProtocolGuid
,
298 This
->DriverBindingHandle
,
303 if (!EFI_ERROR (Status
)) {
304 gBS
->FreePool (Private
);
313 IN EFI_DISK_IO_PROTOCOL
*This
,
322 Read BufferSize bytes from Offset into Buffer.
324 Reads may support reads that are not aligned on
325 sector boundaries. There are three cases:
327 UnderRun - The first byte is not on a sector boundary or the read request is
328 less than a sector in length.
330 Aligned - A read of N contiguous sectors.
332 OverRun - The last byte is not on a sector boundary.
336 This - Protocol instance pointer.
337 MediaId - Id of the media, changes every time the media is replaced.
338 Offset - The starting byte offset to read from.
339 BufferSize - Size of Buffer.
340 Buffer - Buffer containing read data.
343 EFI_SUCCESS - The data was read correctly from the device.
344 EFI_DEVICE_ERROR - The device reported an error while performing the read.
345 EFI_NO_MEDIA - There is no media in the device.
346 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
347 EFI_INVALID_PARAMETER - The read request contains device addresses that are not
348 valid for the device.
354 DISK_IO_PRIVATE_DATA
*Private
;
355 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
356 EFI_BLOCK_IO_MEDIA
*Media
;
362 BOOLEAN TransactionComplete
;
363 UINTN WorkingBufferSize
;
364 UINT8
*WorkingBuffer
;
368 UINTN IsBufferAligned
;
369 UINTN DataBufferSize
;
372 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (This
);
374 BlockIo
= Private
->BlockIo
;
375 Media
= BlockIo
->Media
;
376 BlockSize
= Media
->BlockSize
;
378 if (Media
->MediaId
!= MediaId
) {
379 return EFI_MEDIA_CHANGED
;
382 WorkingBuffer
= Buffer
;
383 WorkingBufferSize
= BufferSize
;
386 // Allocate a temporary buffer for operation
388 DataBufferSize
= BlockSize
* DATA_BUFFER_BLOCK_NUM
;
390 if (Media
->IoAlign
> 1) {
391 PreData
= AllocatePool (DataBufferSize
+ Media
->IoAlign
);
392 Data
= PreData
- ((UINTN
) PreData
& (Media
->IoAlign
- 1)) + Media
->IoAlign
;
394 PreData
= AllocatePool (DataBufferSize
);
398 if (PreData
== NULL
) {
399 return EFI_OUT_OF_RESOURCES
;
402 Lba
= DivU64x32Remainder (Offset
, BlockSize
, &UnderRun
);
404 Length
= BlockSize
- UnderRun
;
405 TransactionComplete
= FALSE
;
407 Status
= EFI_SUCCESS
;
410 // Offset starts in the middle of an Lba, so read the entire block.
412 Status
= BlockIo
->ReadBlocks (
420 if (EFI_ERROR (Status
)) {
424 if (Length
> BufferSize
) {
426 TransactionComplete
= TRUE
;
429 CopyMem (WorkingBuffer
, Data
+ UnderRun
, Length
);
431 WorkingBuffer
+= Length
;
433 WorkingBufferSize
-= Length
;
434 if (WorkingBufferSize
== 0) {
441 OverRunLba
= Lba
+ DivU64x32Remainder (WorkingBufferSize
, BlockSize
, &OverRun
);
443 if (!TransactionComplete
&& WorkingBufferSize
>= BlockSize
) {
445 // If the DiskIo maps directly to a BlockIo device do the read.
448 WorkingBufferSize
-= OverRun
;
451 // Check buffer alignment
453 IsBufferAligned
= (UINTN
) WorkingBuffer
& (UINTN
) (Media
->IoAlign
- 1);
455 if (Media
->IoAlign
<= 1 || IsBufferAligned
== 0) {
457 // Alignment is satisfied, so read them together
459 Status
= BlockIo
->ReadBlocks (
467 if (EFI_ERROR (Status
)) {
471 WorkingBuffer
+= WorkingBufferSize
;
475 // Use the allocated buffer instead of the original buffer
476 // to avoid alignment issue.
477 // Here, the allocated buffer (8-byte align) can satisfy the alignment
481 if (WorkingBufferSize
<= DataBufferSize
) {
483 // It is the last calling to readblocks in this loop
485 DataBufferSize
= WorkingBufferSize
;
489 Status
= BlockIo
->ReadBlocks (
496 if (EFI_ERROR (Status
)) {
500 CopyMem (WorkingBuffer
, Data
, DataBufferSize
);
501 WorkingBufferSize
-= DataBufferSize
;
502 WorkingBuffer
+= DataBufferSize
;
503 Lba
+= DATA_BUFFER_BLOCK_NUM
;
508 if (!TransactionComplete
&& OverRun
!= 0) {
510 // Last read is not a complete block.
512 Status
= BlockIo
->ReadBlocks (
520 if (EFI_ERROR (Status
)) {
524 CopyMem (WorkingBuffer
, Data
, OverRun
);
528 if (PreData
!= NULL
) {
529 gBS
->FreePool (PreData
);
538 IN EFI_DISK_IO_PROTOCOL
*This
,
547 Read BufferSize bytes from Offset into Buffer.
549 Writes may require a read modify write to support writes that are not
550 aligned on sector boundaries. There are three cases:
552 UnderRun - The first byte is not on a sector boundary or the write request
553 is less than a sector in length. Read modify write is required.
555 Aligned - A write of N contiguous sectors.
557 OverRun - The last byte is not on a sector boundary. Read modified write
561 This - Protocol instance pointer.
562 MediaId - Id of the media, changes every time the media is replaced.
563 Offset - The starting byte offset to read from.
564 BufferSize - Size of Buffer.
565 Buffer - Buffer containing read data.
568 EFI_SUCCESS - The data was written correctly to the device.
569 EFI_WRITE_PROTECTED - The device can not be written to.
570 EFI_DEVICE_ERROR - The device reported an error while performing the write.
571 EFI_NO_MEDIA - There is no media in the device.
572 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
573 EFI_INVALID_PARAMETER - The write request contains device addresses that are not
574 valid for the device.
580 DISK_IO_PRIVATE_DATA
*Private
;
581 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
582 EFI_BLOCK_IO_MEDIA
*Media
;
588 BOOLEAN TransactionComplete
;
589 UINTN WorkingBufferSize
;
590 UINT8
*WorkingBuffer
;
594 UINTN IsBufferAligned
;
595 UINTN DataBufferSize
;
598 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (This
);
600 BlockIo
= Private
->BlockIo
;
601 Media
= BlockIo
->Media
;
602 BlockSize
= Media
->BlockSize
;
604 if (Media
->ReadOnly
) {
605 return EFI_WRITE_PROTECTED
;
608 if (Media
->MediaId
!= MediaId
) {
609 return EFI_MEDIA_CHANGED
;
612 DataBufferSize
= BlockSize
* DATA_BUFFER_BLOCK_NUM
;
614 if (Media
->IoAlign
> 1) {
615 PreData
= AllocatePool (DataBufferSize
+ Media
->IoAlign
);
616 Data
= PreData
- ((UINTN
) PreData
& (Media
->IoAlign
- 1)) + Media
->IoAlign
;
618 PreData
= AllocatePool (DataBufferSize
);
622 if (PreData
== NULL
) {
623 return EFI_OUT_OF_RESOURCES
;
626 WorkingBuffer
= Buffer
;
627 WorkingBufferSize
= BufferSize
;
629 Lba
= DivU64x32Remainder (Offset
, BlockSize
, &UnderRun
);
631 Length
= BlockSize
- UnderRun
;
632 TransactionComplete
= FALSE
;
634 Status
= EFI_SUCCESS
;
637 // Offset starts in the middle of an Lba, so do read modify write.
639 Status
= BlockIo
->ReadBlocks (
647 if (EFI_ERROR (Status
)) {
651 if (Length
> BufferSize
) {
653 TransactionComplete
= TRUE
;
656 CopyMem (Data
+ UnderRun
, WorkingBuffer
, Length
);
658 Status
= BlockIo
->WriteBlocks (
665 if (EFI_ERROR (Status
)) {
669 WorkingBuffer
+= Length
;
670 WorkingBufferSize
-= Length
;
671 if (WorkingBufferSize
== 0) {
678 OverRunLba
= Lba
+ DivU64x32Remainder (WorkingBufferSize
, BlockSize
, &OverRun
);
680 if (!TransactionComplete
&& WorkingBufferSize
>= BlockSize
) {
682 // If the DiskIo maps directly to a BlockIo device do the write.
685 WorkingBufferSize
-= OverRun
;
688 // Check buffer alignment
690 IsBufferAligned
= (UINTN
) WorkingBuffer
& (UINTN
) (Media
->IoAlign
- 1);
692 if (Media
->IoAlign
<= 1 || IsBufferAligned
== 0) {
694 // Alignment is satisfied, so write them together
696 Status
= BlockIo
->WriteBlocks (
704 if (EFI_ERROR (Status
)) {
708 WorkingBuffer
+= WorkingBufferSize
;
712 // The buffer parameter is not aligned with the request
713 // So use the allocated instead.
714 // It can fit almost all the cases.
718 if (WorkingBufferSize
<= DataBufferSize
) {
720 // It is the last calling to writeblocks in this loop
722 DataBufferSize
= WorkingBufferSize
;
726 CopyMem (Data
, WorkingBuffer
, DataBufferSize
);
727 Status
= BlockIo
->WriteBlocks (
734 if (EFI_ERROR (Status
)) {
738 WorkingBufferSize
-= DataBufferSize
;
739 WorkingBuffer
+= DataBufferSize
;
740 Lba
+= DATA_BUFFER_BLOCK_NUM
;
741 } while (!LastWrite
);
745 if (!TransactionComplete
&& OverRun
!= 0) {
747 // Last bit is not a complete block, so do a read modify write.
749 Status
= BlockIo
->ReadBlocks (
757 if (EFI_ERROR (Status
)) {
761 CopyMem (Data
, WorkingBuffer
, OverRun
);
763 Status
= BlockIo
->WriteBlocks (
770 if (EFI_ERROR (Status
)) {
776 if (PreData
!= NULL
) {
777 gBS
->FreePool (PreData
);