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.
35 EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding
= {
36 DiskIoDriverBindingSupported
,
37 DiskIoDriverBindingStart
,
38 DiskIoDriverBindingStop
,
44 DISK_IO_PRIVATE_DATA gDiskIoPrivateDataTemplate
= {
45 DISK_IO_PRIVATE_DATA_SIGNATURE
,
47 EFI_DISK_IO_PROTOCOL_REVISION
,
56 DiskIoDriverBindingSupported (
57 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
58 IN EFI_HANDLE ControllerHandle
,
59 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
64 Test to see if this driver supports ControllerHandle. Any ControllerHandle
65 than contains a BlockIo protocol can be supported.
68 This - Protocol instance pointer.
69 ControllerHandle - Handle of device to test.
70 RemainingDevicePath - Not used.
73 EFI_SUCCESS - This driver supports this device.
74 EFI_ALREADY_STARTED - This driver is already running on this device.
75 other - This driver does not support this device.
80 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
83 // Open the IO Abstraction(s) needed to perform the supported test.
85 Status
= gBS
->OpenProtocol (
87 &gEfiBlockIoProtocolGuid
,
89 This
->DriverBindingHandle
,
91 EFI_OPEN_PROTOCOL_BY_DRIVER
93 if (EFI_ERROR (Status
)) {
97 // Close the I/O Abstraction(s) used to perform the supported test.
101 &gEfiBlockIoProtocolGuid
,
102 This
->DriverBindingHandle
,
110 DiskIoDriverBindingStart (
111 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
112 IN EFI_HANDLE ControllerHandle
,
113 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
118 Start this driver on ControllerHandle by opening a Block IO protocol and
119 installing a Disk IO protocol on ControllerHandle.
122 This - Protocol instance pointer.
123 ControllerHandle - Handle of device to bind driver to.
124 RemainingDevicePath - Not used, always produce all possible children.
127 EFI_SUCCESS - This driver is added to ControllerHandle.
128 EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
129 other - This driver does not support this device.
134 DISK_IO_PRIVATE_DATA
*Private
;
139 // Connect to the Block IO interface on ControllerHandle.
141 Status
= gBS
->OpenProtocol (
143 &gEfiBlockIoProtocolGuid
,
144 (VOID
**) &gDiskIoPrivateDataTemplate
.BlockIo
,
145 This
->DriverBindingHandle
,
147 EFI_OPEN_PROTOCOL_BY_DRIVER
149 if (EFI_ERROR (Status
)) {
153 // Initialize the Disk IO device instance.
155 Private
= AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA
), &gDiskIoPrivateDataTemplate
);
156 if (Private
== NULL
) {
157 Status
= EFI_OUT_OF_RESOURCES
;
161 // Install protocol interfaces for the Disk IO device.
163 Status
= gBS
->InstallProtocolInterface (
165 &gEfiDiskIoProtocolGuid
,
166 EFI_NATIVE_INTERFACE
,
171 if (EFI_ERROR (Status
)) {
173 if (Private
!= NULL
) {
179 &gEfiBlockIoProtocolGuid
,
180 This
->DriverBindingHandle
,
190 DiskIoDriverBindingStop (
191 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
192 IN EFI_HANDLE ControllerHandle
,
193 IN UINTN NumberOfChildren
,
194 IN EFI_HANDLE
*ChildHandleBuffer
199 Stop this driver on ControllerHandle by removing Disk IO protocol and closing
200 the Block IO protocol on ControllerHandle.
203 This - Protocol instance pointer.
204 ControllerHandle - Handle of device to stop driver on.
205 NumberOfChildren - Not used.
206 ChildHandleBuffer - Not used.
209 EFI_SUCCESS - This driver is removed ControllerHandle.
210 other - This driver was not removed from this device.
216 EFI_DISK_IO_PROTOCOL
*DiskIo
;
217 DISK_IO_PRIVATE_DATA
*Private
;
220 // Get our context back.
222 Status
= gBS
->OpenProtocol (
224 &gEfiDiskIoProtocolGuid
,
226 This
->DriverBindingHandle
,
228 EFI_OPEN_PROTOCOL_GET_PROTOCOL
230 if (EFI_ERROR (Status
)) {
231 return EFI_UNSUPPORTED
;
234 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (DiskIo
);
236 Status
= gBS
->UninstallProtocolInterface (
238 &gEfiDiskIoProtocolGuid
,
241 if (!EFI_ERROR (Status
)) {
243 Status
= gBS
->CloseProtocol (
245 &gEfiBlockIoProtocolGuid
,
246 This
->DriverBindingHandle
,
251 if (!EFI_ERROR (Status
)) {
261 IN EFI_DISK_IO_PROTOCOL
*This
,
270 Read BufferSize bytes from Offset into Buffer.
272 Reads may support reads that are not aligned on
273 sector boundaries. There are three cases:
275 UnderRun - The first byte is not on a sector boundary or the read request is
276 less than a sector in length.
278 Aligned - A read of N contiguous sectors.
280 OverRun - The last byte is not on a sector boundary.
284 This - Protocol instance pointer.
285 MediaId - Id of the media, changes every time the media is replaced.
286 Offset - The starting byte offset to read from.
287 BufferSize - Size of Buffer.
288 Buffer - Buffer containing read data.
291 EFI_SUCCESS - The data was read correctly from the device.
292 EFI_DEVICE_ERROR - The device reported an error while performing the read.
293 EFI_NO_MEDIA - There is no media in the device.
294 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
295 EFI_INVALID_PARAMETER - The read request contains device addresses that are not
296 valid for the device.
302 DISK_IO_PRIVATE_DATA
*Private
;
303 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
304 EFI_BLOCK_IO_MEDIA
*Media
;
310 BOOLEAN TransactionComplete
;
311 UINTN WorkingBufferSize
;
312 UINT8
*WorkingBuffer
;
316 UINTN IsBufferAligned
;
317 UINTN DataBufferSize
;
320 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (This
);
322 BlockIo
= Private
->BlockIo
;
323 Media
= BlockIo
->Media
;
324 BlockSize
= Media
->BlockSize
;
326 if (Media
->MediaId
!= MediaId
) {
327 return EFI_MEDIA_CHANGED
;
330 WorkingBuffer
= Buffer
;
331 WorkingBufferSize
= BufferSize
;
334 // Allocate a temporary buffer for operation
336 DataBufferSize
= BlockSize
* DATA_BUFFER_BLOCK_NUM
;
338 if (Media
->IoAlign
> 1) {
339 PreData
= AllocatePool (DataBufferSize
+ Media
->IoAlign
);
340 Data
= PreData
- ((UINTN
) PreData
& (Media
->IoAlign
- 1)) + Media
->IoAlign
;
342 PreData
= AllocatePool (DataBufferSize
);
346 if (PreData
== NULL
) {
347 return EFI_OUT_OF_RESOURCES
;
350 Lba
= DivU64x32Remainder (Offset
, BlockSize
, &UnderRun
);
352 Length
= BlockSize
- UnderRun
;
353 TransactionComplete
= FALSE
;
355 Status
= EFI_SUCCESS
;
358 // Offset starts in the middle of an Lba, so read the entire block.
360 Status
= BlockIo
->ReadBlocks (
368 if (EFI_ERROR (Status
)) {
372 if (Length
> BufferSize
) {
374 TransactionComplete
= TRUE
;
377 CopyMem (WorkingBuffer
, Data
+ UnderRun
, Length
);
379 WorkingBuffer
+= Length
;
381 WorkingBufferSize
-= Length
;
382 if (WorkingBufferSize
== 0) {
389 OverRunLba
= Lba
+ DivU64x32Remainder (WorkingBufferSize
, BlockSize
, &OverRun
);
391 if (!TransactionComplete
&& WorkingBufferSize
>= BlockSize
) {
393 // If the DiskIo maps directly to a BlockIo device do the read.
396 WorkingBufferSize
-= OverRun
;
399 // Check buffer alignment
401 IsBufferAligned
= (UINTN
) WorkingBuffer
& (UINTN
) (Media
->IoAlign
- 1);
403 if (Media
->IoAlign
<= 1 || IsBufferAligned
== 0) {
405 // Alignment is satisfied, so read them together
407 Status
= BlockIo
->ReadBlocks (
415 if (EFI_ERROR (Status
)) {
419 WorkingBuffer
+= WorkingBufferSize
;
423 // Use the allocated buffer instead of the original buffer
424 // to avoid alignment issue.
425 // Here, the allocated buffer (8-byte align) can satisfy the alignment
429 if (WorkingBufferSize
<= DataBufferSize
) {
431 // It is the last calling to readblocks in this loop
433 DataBufferSize
= WorkingBufferSize
;
437 Status
= BlockIo
->ReadBlocks (
444 if (EFI_ERROR (Status
)) {
448 CopyMem (WorkingBuffer
, Data
, DataBufferSize
);
449 WorkingBufferSize
-= DataBufferSize
;
450 WorkingBuffer
+= DataBufferSize
;
451 Lba
+= DATA_BUFFER_BLOCK_NUM
;
456 if (!TransactionComplete
&& OverRun
!= 0) {
458 // Last read is not a complete block.
460 Status
= BlockIo
->ReadBlocks (
468 if (EFI_ERROR (Status
)) {
472 CopyMem (WorkingBuffer
, Data
, OverRun
);
476 if (PreData
!= NULL
) {
486 IN EFI_DISK_IO_PROTOCOL
*This
,
495 Read BufferSize bytes from Offset into Buffer.
497 Writes may require a read modify write to support writes that are not
498 aligned on sector boundaries. There are three cases:
500 UnderRun - The first byte is not on a sector boundary or the write request
501 is less than a sector in length. Read modify write is required.
503 Aligned - A write of N contiguous sectors.
505 OverRun - The last byte is not on a sector boundary. Read modified write
509 This - Protocol instance pointer.
510 MediaId - Id of the media, changes every time the media is replaced.
511 Offset - The starting byte offset to read from.
512 BufferSize - Size of Buffer.
513 Buffer - Buffer containing read data.
516 EFI_SUCCESS - The data was written correctly to the device.
517 EFI_WRITE_PROTECTED - The device can not be written to.
518 EFI_DEVICE_ERROR - The device reported an error while performing the write.
519 EFI_NO_MEDIA - There is no media in the device.
520 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
521 EFI_INVALID_PARAMETER - The write request contains device addresses that are not
522 valid for the device.
528 DISK_IO_PRIVATE_DATA
*Private
;
529 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
530 EFI_BLOCK_IO_MEDIA
*Media
;
536 BOOLEAN TransactionComplete
;
537 UINTN WorkingBufferSize
;
538 UINT8
*WorkingBuffer
;
542 UINTN IsBufferAligned
;
543 UINTN DataBufferSize
;
546 Private
= DISK_IO_PRIVATE_DATA_FROM_THIS (This
);
548 BlockIo
= Private
->BlockIo
;
549 Media
= BlockIo
->Media
;
550 BlockSize
= Media
->BlockSize
;
552 if (Media
->ReadOnly
) {
553 return EFI_WRITE_PROTECTED
;
556 if (Media
->MediaId
!= MediaId
) {
557 return EFI_MEDIA_CHANGED
;
560 DataBufferSize
= BlockSize
* DATA_BUFFER_BLOCK_NUM
;
562 if (Media
->IoAlign
> 1) {
563 PreData
= AllocatePool (DataBufferSize
+ Media
->IoAlign
);
564 Data
= PreData
- ((UINTN
) PreData
& (Media
->IoAlign
- 1)) + Media
->IoAlign
;
566 PreData
= AllocatePool (DataBufferSize
);
570 if (PreData
== NULL
) {
571 return EFI_OUT_OF_RESOURCES
;
574 WorkingBuffer
= Buffer
;
575 WorkingBufferSize
= BufferSize
;
577 Lba
= DivU64x32Remainder (Offset
, BlockSize
, &UnderRun
);
579 Length
= BlockSize
- UnderRun
;
580 TransactionComplete
= FALSE
;
582 Status
= EFI_SUCCESS
;
585 // Offset starts in the middle of an Lba, so do read modify write.
587 Status
= BlockIo
->ReadBlocks (
595 if (EFI_ERROR (Status
)) {
599 if (Length
> BufferSize
) {
601 TransactionComplete
= TRUE
;
604 CopyMem (Data
+ UnderRun
, WorkingBuffer
, Length
);
606 Status
= BlockIo
->WriteBlocks (
613 if (EFI_ERROR (Status
)) {
617 WorkingBuffer
+= Length
;
618 WorkingBufferSize
-= Length
;
619 if (WorkingBufferSize
== 0) {
626 OverRunLba
= Lba
+ DivU64x32Remainder (WorkingBufferSize
, BlockSize
, &OverRun
);
628 if (!TransactionComplete
&& WorkingBufferSize
>= BlockSize
) {
630 // If the DiskIo maps directly to a BlockIo device do the write.
633 WorkingBufferSize
-= OverRun
;
636 // Check buffer alignment
638 IsBufferAligned
= (UINTN
) WorkingBuffer
& (UINTN
) (Media
->IoAlign
- 1);
640 if (Media
->IoAlign
<= 1 || IsBufferAligned
== 0) {
642 // Alignment is satisfied, so write them together
644 Status
= BlockIo
->WriteBlocks (
652 if (EFI_ERROR (Status
)) {
656 WorkingBuffer
+= WorkingBufferSize
;
660 // The buffer parameter is not aligned with the request
661 // So use the allocated instead.
662 // It can fit almost all the cases.
666 if (WorkingBufferSize
<= DataBufferSize
) {
668 // It is the last calling to writeblocks in this loop
670 DataBufferSize
= WorkingBufferSize
;
674 CopyMem (Data
, WorkingBuffer
, DataBufferSize
);
675 Status
= BlockIo
->WriteBlocks (
682 if (EFI_ERROR (Status
)) {
686 WorkingBufferSize
-= DataBufferSize
;
687 WorkingBuffer
+= DataBufferSize
;
688 Lba
+= DATA_BUFFER_BLOCK_NUM
;
689 } while (!LastWrite
);
693 if (!TransactionComplete
&& OverRun
!= 0) {
695 // Last bit is not a complete block, so do a read modify write.
697 Status
= BlockIo
->ReadBlocks (
705 if (EFI_ERROR (Status
)) {
709 CopyMem (Data
, WorkingBuffer
, OverRun
);
711 Status
= BlockIo
->WriteBlocks (
718 if (EFI_ERROR (Status
)) {
724 if (PreData
!= NULL
) {