2 Partition driver that produces logical BlockIo devices from a physical
3 BlockIo device. The logical BlockIo devices are based on the format
4 of the raw block devices media. Currently "El Torito CD-ROM", Legacy
5 MBR, and GPT partition schemes are supported.
7 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include "Partition.h"
22 // Partition Driver Global Variables.
24 EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding
= {
25 PartitionDriverBindingSupported
,
26 PartitionDriverBindingStart
,
27 PartitionDriverBindingStop
,
29 // Grub4Dos copies the BPB of the first partition to the MBR. If the
30 // DriverBindingStart() of the Fat driver gets run before that of Partition
31 // driver only the first partition can be recognized.
32 // Let the driver binding version of Partition driver be higher than that of
33 // Fat driver to make sure the DriverBindingStart() of the Partition driver
34 // gets run before that of Fat driver so that all the partitions can be recognized.
42 // Prioritized function list to detect partition table.
44 PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable
[] = {
45 PartitionInstallGptChildHandles
,
46 PartitionInstallElToritoChildHandles
,
47 PartitionInstallMbrChildHandles
,
52 Test to see if this driver supports ControllerHandle. Any ControllerHandle
53 than contains a BlockIo and DiskIo protocol or a BlockIo2 protocol can be
56 @param[in] This Protocol instance pointer.
57 @param[in] ControllerHandle Handle of device to test.
58 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
61 @retval EFI_SUCCESS This driver supports this device
62 @retval EFI_ALREADY_STARTED This driver is already running on this device
63 @retval other This driver does not support this device
68 PartitionDriverBindingSupported (
69 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
70 IN EFI_HANDLE ControllerHandle
,
71 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
75 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
76 EFI_DISK_IO_PROTOCOL
*DiskIo
;
80 // Check RemainingDevicePath validation
82 if (RemainingDevicePath
!= NULL
) {
84 // Check if RemainingDevicePath is the End of Device Path Node,
85 // if yes, go on checking other conditions
87 if (!IsDevicePathEnd (RemainingDevicePath
)) {
89 // If RemainingDevicePath isn't the End of Device Path Node,
90 // check its validation
92 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
93 if (Node
->DevPath
.Type
!= MEDIA_DEVICE_PATH
||
94 Node
->DevPath
.SubType
!= MEDIA_HARDDRIVE_DP
||
95 DevicePathNodeLength (&Node
->DevPath
) != sizeof (HARDDRIVE_DEVICE_PATH
)) {
96 return EFI_UNSUPPORTED
;
102 // Open the IO Abstraction(s) needed to perform the supported test
104 Status
= gBS
->OpenProtocol (
106 &gEfiDiskIoProtocolGuid
,
108 This
->DriverBindingHandle
,
110 EFI_OPEN_PROTOCOL_BY_DRIVER
112 if (Status
== EFI_ALREADY_STARTED
) {
115 if (EFI_ERROR (Status
)) {
119 // Close the I/O Abstraction(s) used to perform the supported test
123 &gEfiDiskIoProtocolGuid
,
124 This
->DriverBindingHandle
,
129 // Open the EFI Device Path protocol needed to perform the supported test
131 Status
= gBS
->OpenProtocol (
133 &gEfiDevicePathProtocolGuid
,
134 (VOID
**) &ParentDevicePath
,
135 This
->DriverBindingHandle
,
137 EFI_OPEN_PROTOCOL_BY_DRIVER
139 if (Status
== EFI_ALREADY_STARTED
) {
143 if (EFI_ERROR (Status
)) {
148 // Close protocol, don't use device path protocol in the Support() function
152 &gEfiDevicePathProtocolGuid
,
153 This
->DriverBindingHandle
,
158 // Open the IO Abstraction(s) needed to perform the supported test
160 Status
= gBS
->OpenProtocol (
162 &gEfiBlockIoProtocolGuid
,
164 This
->DriverBindingHandle
,
166 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
168 if (EFI_ERROR (Status
)) {
176 Start this driver on ControllerHandle by opening a Block IO or a Block IO2
177 or both, and Disk IO protocol, reading Device Path, and creating a child
178 handle with a Disk IO and device path protocol.
180 @param[in] This Protocol instance pointer.
181 @param[in] ControllerHandle Handle of device to bind driver to
182 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
185 @retval EFI_SUCCESS This driver is added to ControllerHandle
186 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
187 @retval other This driver does not support this device
192 PartitionDriverBindingStart (
193 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
194 IN EFI_HANDLE ControllerHandle
,
195 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
199 EFI_STATUS OpenStatus
;
200 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
201 EFI_BLOCK_IO2_PROTOCOL
*BlockIo2
;
202 EFI_DISK_IO_PROTOCOL
*DiskIo
;
203 EFI_DISK_IO2_PROTOCOL
*DiskIo2
;
204 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
205 PARTITION_DETECT_ROUTINE
*Routine
;
206 BOOLEAN MediaPresent
;
210 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
212 // Check RemainingDevicePath validation
214 if (RemainingDevicePath
!= NULL
) {
216 // Check if RemainingDevicePath is the End of Device Path Node,
217 // if yes, return EFI_SUCCESS
219 if (IsDevicePathEnd (RemainingDevicePath
)) {
220 Status
= EFI_SUCCESS
;
226 // Try to open BlockIO and BlockIO2. If BlockIO would be opened, continue,
227 // otherwise, return error.
229 Status
= gBS
->OpenProtocol (
231 &gEfiBlockIoProtocolGuid
,
233 This
->DriverBindingHandle
,
235 EFI_OPEN_PROTOCOL_GET_PROTOCOL
237 if (EFI_ERROR (Status
)) {
241 Status
= gBS
->OpenProtocol (
243 &gEfiBlockIo2ProtocolGuid
,
245 This
->DriverBindingHandle
,
247 EFI_OPEN_PROTOCOL_GET_PROTOCOL
249 if (EFI_ERROR (Status
)) {
254 // Get the Device Path Protocol on ControllerHandle's handle.
256 Status
= gBS
->OpenProtocol (
258 &gEfiDevicePathProtocolGuid
,
259 (VOID
**) &ParentDevicePath
,
260 This
->DriverBindingHandle
,
262 EFI_OPEN_PROTOCOL_BY_DRIVER
264 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
269 // Get the DiskIo and DiskIo2.
271 Status
= gBS
->OpenProtocol (
273 &gEfiDiskIoProtocolGuid
,
275 This
->DriverBindingHandle
,
277 EFI_OPEN_PROTOCOL_BY_DRIVER
279 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
282 &gEfiDevicePathProtocolGuid
,
283 This
->DriverBindingHandle
,
291 Status
= gBS
->OpenProtocol (
293 &gEfiDiskIo2ProtocolGuid
,
295 This
->DriverBindingHandle
,
297 EFI_OPEN_PROTOCOL_BY_DRIVER
299 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
304 // Try to read blocks when there's media or it is removable physical partition.
306 Status
= EFI_UNSUPPORTED
;
307 MediaPresent
= BlockIo
->Media
->MediaPresent
;
308 if (BlockIo
->Media
->MediaPresent
||
309 (BlockIo
->Media
->RemovableMedia
&& !BlockIo
->Media
->LogicalPartition
)) {
311 // Try for GPT, then El Torito, and then legacy MBR partition types. If the
312 // media supports a given partition type install child handles to represent
313 // the partitions described by the media.
315 Routine
= &mPartitionDetectRoutineTable
[0];
316 while (*Routine
!= NULL
) {
317 Status
= (*Routine
) (
326 if (!EFI_ERROR (Status
) || Status
== EFI_MEDIA_CHANGED
|| Status
== EFI_NO_MEDIA
) {
333 // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),
334 // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the
335 // driver. So don't try to close them. Otherwise, we will break the dependency
336 // between the controller and the driver set up before.
338 // In the case that when the media changes on a device it will Reinstall the
339 // BlockIo interaface. This will cause a call to our Stop(), and a subsequent
340 // reentrant call to our Start() successfully. We should leave the device open
341 // when this happen. The "media change" case includes either the status is
342 // EFI_MEDIA_CHANGED or it is a "media" to "no media" change.
344 if (EFI_ERROR (Status
) &&
345 !EFI_ERROR (OpenStatus
) &&
346 Status
!= EFI_MEDIA_CHANGED
&&
347 !(MediaPresent
&& Status
== EFI_NO_MEDIA
)) {
350 &gEfiDiskIoProtocolGuid
,
351 This
->DriverBindingHandle
,
355 // Close Parent BlockIO2 if has.
359 &gEfiBlockIo2ProtocolGuid
,
360 This
->DriverBindingHandle
,
366 &gEfiDevicePathProtocolGuid
,
367 This
->DriverBindingHandle
,
373 gBS
->RestoreTPL (OldTpl
);
378 Stop this driver on ControllerHandle. Support stopping any child handles
379 created by this driver.
381 @param This Protocol instance pointer.
382 @param ControllerHandle Handle of device to stop driver on
383 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
384 children is zero stop the entire bus driver.
385 @param ChildHandleBuffer List of Child Handles to Stop.
387 @retval EFI_SUCCESS This driver is removed ControllerHandle
388 @retval other This driver was not removed from this device
393 PartitionDriverBindingStop (
394 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
395 IN EFI_HANDLE ControllerHandle
,
396 IN UINTN NumberOfChildren
,
397 IN EFI_HANDLE
*ChildHandleBuffer
402 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
403 EFI_BLOCK_IO2_PROTOCOL
*BlockIo2
;
404 BOOLEAN AllChildrenStopped
;
405 PARTITION_PRIVATE_DATA
*Private
;
406 EFI_DISK_IO_PROTOCOL
*DiskIo
;
412 if (NumberOfChildren
== 0) {
414 // Close the bus driver
418 &gEfiDiskIoProtocolGuid
,
419 This
->DriverBindingHandle
,
423 // Close Parent BlockIO2 if has.
427 &gEfiDiskIo2ProtocolGuid
,
428 This
->DriverBindingHandle
,
434 &gEfiDevicePathProtocolGuid
,
435 This
->DriverBindingHandle
,
441 AllChildrenStopped
= TRUE
;
442 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
444 ChildHandleBuffer
[Index
],
445 &gEfiBlockIoProtocolGuid
,
447 This
->DriverBindingHandle
,
449 EFI_OPEN_PROTOCOL_GET_PROTOCOL
452 // Try to locate BlockIo2.
455 ChildHandleBuffer
[Index
],
456 &gEfiBlockIo2ProtocolGuid
,
458 This
->DriverBindingHandle
,
460 EFI_OPEN_PROTOCOL_GET_PROTOCOL
464 Private
= PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo
);
466 Status
= gBS
->CloseProtocol (
468 &gEfiDiskIoProtocolGuid
,
469 This
->DriverBindingHandle
,
470 ChildHandleBuffer
[Index
]
473 // All Software protocols have be freed from the handle so remove it.
474 // Remove the BlockIo Protocol if has.
475 // Remove the BlockIo2 Protocol if has.
477 if (BlockIo2
!= NULL
) {
478 BlockIo
->FlushBlocks (BlockIo
);
479 BlockIo2
->FlushBlocksEx (BlockIo2
, NULL
);
480 Status
= gBS
->UninstallMultipleProtocolInterfaces (
481 ChildHandleBuffer
[Index
],
482 &gEfiDevicePathProtocolGuid
,
484 &gEfiBlockIoProtocolGuid
,
486 &gEfiBlockIo2ProtocolGuid
,
493 BlockIo
->FlushBlocks (BlockIo
);
494 Status
= gBS
->UninstallMultipleProtocolInterfaces (
495 ChildHandleBuffer
[Index
],
496 &gEfiDevicePathProtocolGuid
,
498 &gEfiBlockIoProtocolGuid
,
506 if (EFI_ERROR (Status
)) {
509 &gEfiDiskIoProtocolGuid
,
511 This
->DriverBindingHandle
,
512 ChildHandleBuffer
[Index
],
513 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
516 FreePool (Private
->DevicePath
);
520 if (EFI_ERROR (Status
)) {
521 AllChildrenStopped
= FALSE
;
525 if (!AllChildrenStopped
) {
526 return EFI_DEVICE_ERROR
;
534 Reset the Block Device.
536 @param This Protocol instance pointer.
537 @param ExtendedVerification Driver may perform diagnostics on reset.
539 @retval EFI_SUCCESS The device was reset.
540 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
547 IN EFI_BLOCK_IO_PROTOCOL
*This
,
548 IN BOOLEAN ExtendedVerification
551 PARTITION_PRIVATE_DATA
*Private
;
553 Private
= PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This
);
555 return Private
->ParentBlockIo
->Reset (
556 Private
->ParentBlockIo
,
562 Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
563 for no media or media change case. Otherwise DefaultStatus is returned.
565 @param DiskIo Pointer to the DiskIo instance.
566 @param MediaId Id of the media, changes every time the media is replaced.
567 @param DefaultStatus The default status to return when it's not the no media
568 or media change case.
570 @retval EFI_NO_MEDIA There is no media.
571 @retval EFI_MEDIA_CHANGED The media was changed.
572 @retval others The default status to return.
576 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
578 IN EFI_STATUS DefaultStatus
584 // Read 1 byte from offset 0 but passing NULL as buffer pointer
586 Status
= DiskIo
->ReadDisk (DiskIo
, MediaId
, 0, 1, NULL
);
587 if ((Status
== EFI_NO_MEDIA
) || (Status
== EFI_MEDIA_CHANGED
)) {
590 return DefaultStatus
;
594 Read by using the Disk IO protocol on the parent device. Lba addresses
595 must be converted to byte offsets.
597 @param This Protocol instance pointer.
598 @param MediaId Id of the media, changes every time the media is replaced.
599 @param Lba The starting Logical Block Address to read from
600 @param BufferSize Size of Buffer, must be a multiple of device block size.
601 @param Buffer Buffer containing read data
603 @retval EFI_SUCCESS The data was read correctly from the device.
604 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
605 @retval EFI_NO_MEDIA There is no media in the device.
606 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
607 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
608 @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
609 valid for the device.
614 PartitionReadBlocks (
615 IN EFI_BLOCK_IO_PROTOCOL
*This
,
622 PARTITION_PRIVATE_DATA
*Private
;
625 Private
= PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This
);
627 if (BufferSize
% Private
->BlockSize
!= 0) {
628 return ProbeMediaStatus (Private
->DiskIo
, MediaId
, EFI_BAD_BUFFER_SIZE
);
631 Offset
= MultU64x32 (Lba
, Private
->BlockSize
) + Private
->Start
;
632 if (Offset
+ BufferSize
> Private
->End
) {
633 return ProbeMediaStatus (Private
->DiskIo
, MediaId
, EFI_INVALID_PARAMETER
);
636 // Because some kinds of partition have different block size from their parent
637 // device, we call the Disk IO protocol on the parent device, not the Block IO
640 return Private
->DiskIo
->ReadDisk (Private
->DiskIo
, MediaId
, Offset
, BufferSize
, Buffer
);
644 Write by using the Disk IO protocol on the parent device. Lba addresses
645 must be converted to byte offsets.
647 @param[in] This Protocol instance pointer.
648 @param[in] MediaId Id of the media, changes every time the media is replaced.
649 @param[in] Lba The starting Logical Block Address to read from
650 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
651 @param[in] Buffer Buffer containing data to be written to device.
653 @retval EFI_SUCCESS The data was written correctly to the device.
654 @retval EFI_WRITE_PROTECTED The device can not be written to.
655 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
656 @retval EFI_NO_MEDIA There is no media in the device.
657 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
658 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
659 @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not
660 valid for the device.
665 PartitionWriteBlocks (
666 IN EFI_BLOCK_IO_PROTOCOL
*This
,
673 PARTITION_PRIVATE_DATA
*Private
;
676 Private
= PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This
);
678 if (BufferSize
% Private
->BlockSize
!= 0) {
679 return ProbeMediaStatus (Private
->DiskIo
, MediaId
, EFI_BAD_BUFFER_SIZE
);
682 Offset
= MultU64x32 (Lba
, Private
->BlockSize
) + Private
->Start
;
683 if (Offset
+ BufferSize
> Private
->End
) {
684 return ProbeMediaStatus (Private
->DiskIo
, MediaId
, EFI_INVALID_PARAMETER
);
687 // Because some kinds of partition have different block size from their parent
688 // device, we call the Disk IO protocol on the parent device, not the Block IO
691 return Private
->DiskIo
->WriteDisk (Private
->DiskIo
, MediaId
, Offset
, BufferSize
, Buffer
);
696 Flush the parent Block Device.
698 @param This Protocol instance pointer.
700 @retval EFI_SUCCESS All outstanding data was written to the device
701 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
702 @retval EFI_NO_MEDIA There is no media in the device.
707 PartitionFlushBlocks (
708 IN EFI_BLOCK_IO_PROTOCOL
*This
711 PARTITION_PRIVATE_DATA
*Private
;
713 Private
= PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This
);
715 return Private
->ParentBlockIo
->FlushBlocks (Private
->ParentBlockIo
);
719 Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
720 for no media or media change case. Otherwise DefaultStatus is returned.
722 @param DiskIo2 Pointer to the DiskIo2 instance.
723 @param MediaId Id of the media, changes every time the media is replaced.
724 @param DefaultStatus The default status to return when it's not the no media
725 or media change case.
727 @retval EFI_NO_MEDIA There is no media.
728 @retval EFI_MEDIA_CHANGED The media was changed.
729 @retval others The default status to return.
733 IN EFI_DISK_IO2_PROTOCOL
*DiskIo2
,
735 IN EFI_STATUS DefaultStatus
741 // Read 1 byte from offset 0 but passing NULL as buffer pointer
743 Status
= DiskIo2
->ReadDiskEx (DiskIo2
, MediaId
, 0, NULL
, 1, NULL
);
744 if ((Status
== EFI_NO_MEDIA
) || (Status
== EFI_MEDIA_CHANGED
)) {
747 return DefaultStatus
;
751 Reset the Block Device throught Block I/O2 protocol.
753 @param This Protocol instance pointer.
754 @param ExtendedVerification Driver may perform diagnostics on reset.
756 @retval EFI_SUCCESS The device was reset.
757 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
764 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
765 IN BOOLEAN ExtendedVerification
768 PARTITION_PRIVATE_DATA
*Private
;
770 Private
= PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This
);
772 return Private
->ParentBlockIo2
->Reset (
773 Private
->ParentBlockIo2
,
779 The general callback for the DiskIo2 interfaces.
780 @param Event Event whose notification function is being invoked.
781 @param Context The pointer to the notification function's context,
782 which points to the PARTITION_ACCESS_TASK instance.
786 PartitionOnAccessComplete (
791 PARTITION_ACCESS_TASK
*Task
;
793 Task
= (PARTITION_ACCESS_TASK
*) Context
;
795 gBS
->CloseEvent (Event
);
797 Task
->BlockIo2Token
->TransactionStatus
= Task
->DiskIo2Token
.TransactionStatus
;
798 gBS
->SignalEvent (Task
->BlockIo2Token
->Event
);
804 Create a new PARTITION_ACCESS_TASK instance.
806 @param Token Pointer to the EFI_BLOCK_IO2_TOKEN.
808 @return Pointer to the created PARTITION_ACCESS_TASK instance or NULL upon failure.
810 PARTITION_ACCESS_TASK
*
811 PartitionCreateAccessTask (
812 IN EFI_BLOCK_IO2_TOKEN
*Token
816 PARTITION_ACCESS_TASK
*Task
;
818 Task
= AllocatePool (sizeof (*Task
));
823 Status
= gBS
->CreateEvent (
826 PartitionOnAccessComplete
,
828 &Task
->DiskIo2Token
.Event
830 if (EFI_ERROR (Status
)) {
835 Task
->BlockIo2Token
= Token
;
841 Read BufferSize bytes from Lba into Buffer.
843 This function reads the requested number of blocks from the device. All the
844 blocks are read, or an error is returned.
845 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
846 non-blocking I/O is being used, the Event associated with this request will
849 @param[in] This Indicates a pointer to the calling context.
850 @param[in] MediaId Id of the media, changes every time the media is
852 @param[in] Lba The starting Logical Block Address to read from.
853 @param[in, out] Token A pointer to the token associated with the transaction.
854 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
855 @param[out] Buffer A pointer to the destination buffer for the data. The
856 caller is responsible for either having implicit or
857 explicit ownership of the buffer.
859 @retval EFI_SUCCESS The read request was queued if Token->Event is
860 not NULL.The data was read correctly from the
861 device if the Token->Event is NULL.
862 @retval EFI_DEVICE_ERROR The device reported an error while performing
864 @retval EFI_NO_MEDIA There is no media in the device.
865 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
866 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
867 intrinsic block size of the device.
868 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
869 or the buffer is not on proper alignment.
870 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
875 PartitionReadBlocksEx (
876 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
879 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
885 PARTITION_PRIVATE_DATA
*Private
;
887 PARTITION_ACCESS_TASK
*Task
;
889 Private
= PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This
);
891 if (BufferSize
% Private
->BlockSize
!= 0) {
892 return ProbeMediaStatusEx (Private
->DiskIo2
, MediaId
, EFI_BAD_BUFFER_SIZE
);
895 Offset
= MultU64x32 (Lba
, Private
->BlockSize
) + Private
->Start
;
896 if (Offset
+ BufferSize
> Private
->End
) {
897 return ProbeMediaStatusEx (Private
->DiskIo2
, MediaId
, EFI_INVALID_PARAMETER
);
900 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
901 Task
= PartitionCreateAccessTask (Token
);
903 return EFI_OUT_OF_RESOURCES
;
906 Status
= Private
->DiskIo2
->ReadDiskEx (Private
->DiskIo2
, MediaId
, Offset
, &Task
->DiskIo2Token
, BufferSize
, Buffer
);
907 if (EFI_ERROR (Status
)) {
908 gBS
->CloseEvent (Task
->DiskIo2Token
.Event
);
912 Status
= Private
->DiskIo2
->ReadDiskEx (Private
->DiskIo2
, MediaId
, Offset
, NULL
, BufferSize
, Buffer
);
919 Write BufferSize bytes from Lba into Buffer.
921 This function writes the requested number of blocks to the device. All blocks
922 are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
923 EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
924 being used, the Event associated with this request will not be signaled.
926 @param[in] This Indicates a pointer to the calling context.
927 @param[in] MediaId The media ID that the write request is for.
928 @param[in] Lba The starting logical block address to be written. The
929 caller is responsible for writing to only legitimate
931 @param[in, out] Token A pointer to the token associated with the transaction.
932 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
933 @param[in] Buffer A pointer to the source buffer for the data.
935 @retval EFI_SUCCESS The write request was queued if Event is not NULL.
936 The data was written correctly to the device if
938 @retval EFI_WRITE_PROTECTED The device can not be written to.
939 @retval EFI_NO_MEDIA There is no media in the device.
940 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
941 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
942 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
943 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
944 or the buffer is not on proper alignment.
945 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
951 PartitionWriteBlocksEx (
952 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
955 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
961 PARTITION_PRIVATE_DATA
*Private
;
963 PARTITION_ACCESS_TASK
*Task
;
965 Private
= PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This
);
967 if (BufferSize
% Private
->BlockSize
!= 0) {
968 return ProbeMediaStatusEx (Private
->DiskIo2
, MediaId
, EFI_BAD_BUFFER_SIZE
);
971 Offset
= MultU64x32 (Lba
, Private
->BlockSize
) + Private
->Start
;
972 if (Offset
+ BufferSize
> Private
->End
) {
973 return ProbeMediaStatusEx (Private
->DiskIo2
, MediaId
, EFI_INVALID_PARAMETER
);
976 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
977 Task
= PartitionCreateAccessTask (Token
);
979 return EFI_OUT_OF_RESOURCES
;
982 Status
= Private
->DiskIo2
->WriteDiskEx (Private
->DiskIo2
, MediaId
, Offset
, &Task
->DiskIo2Token
, BufferSize
, Buffer
);
983 if (EFI_ERROR (Status
)) {
984 gBS
->CloseEvent (Task
->DiskIo2Token
.Event
);
988 Status
= Private
->DiskIo2
->WriteDiskEx (Private
->DiskIo2
, MediaId
, Offset
, NULL
, BufferSize
, Buffer
);
994 Flush the Block Device.
996 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
997 is returned and non-blocking I/O is being used, the Event associated with
998 this request will not be signaled.
1000 @param[in] This Indicates a pointer to the calling context.
1001 @param[in, out] Token A pointer to the token associated with the transaction
1003 @retval EFI_SUCCESS The flush request was queued if Event is not NULL.
1004 All outstanding data was written correctly to the
1005 device if the Event is NULL.
1006 @retval EFI_DEVICE_ERROR The device reported an error while writting back
1008 @retval EFI_WRITE_PROTECTED The device cannot be written to.
1009 @retval EFI_NO_MEDIA There is no media in the device.
1010 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1011 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
1017 PartitionFlushBlocksEx (
1018 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1019 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
1023 PARTITION_PRIVATE_DATA
*Private
;
1024 PARTITION_ACCESS_TASK
*Task
;
1026 Private
= PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This
);
1028 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1029 Task
= PartitionCreateAccessTask (Token
);
1031 return EFI_OUT_OF_RESOURCES
;
1034 Status
= Private
->DiskIo2
->FlushDiskEx (Private
->DiskIo2
, &Task
->DiskIo2Token
);
1035 if (EFI_ERROR (Status
)) {
1036 gBS
->CloseEvent (Task
->DiskIo2Token
.Event
);
1040 Status
= Private
->DiskIo2
->FlushDiskEx (Private
->DiskIo2
, NULL
);
1047 Create a child handle for a logical block device that represents the
1048 bytes Start to End of the Parent Block IO device.
1050 @param[in] This Protocol instance pointer.
1051 @param[in] ParentHandle Parent Handle for new child.
1052 @param[in] ParentDiskIo Parent DiskIo interface.
1053 @param[in] ParentDiskIo2 Parent DiskIo2 interface.
1054 @param[in] ParentBlockIo Parent BlockIo interface.
1055 @param[in] ParentBlockIo2 Parent BlockIo2 interface.
1056 @param[in] ParentDevicePath Parent Device Path.
1057 @param[in] DevicePathNode Child Device Path node.
1058 @param[in] Start Start Block.
1059 @param[in] End End Block.
1060 @param[in] BlockSize Child block size.
1061 @param[in] InstallEspGuid Flag to install EFI System Partition GUID on handle.
1063 @retval EFI_SUCCESS A child handle was added.
1064 @retval other A child handle was not added.
1068 PartitionInstallChildHandle (
1069 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1070 IN EFI_HANDLE ParentHandle
,
1071 IN EFI_DISK_IO_PROTOCOL
*ParentDiskIo
,
1072 IN EFI_DISK_IO2_PROTOCOL
*ParentDiskIo2
,
1073 IN EFI_BLOCK_IO_PROTOCOL
*ParentBlockIo
,
1074 IN EFI_BLOCK_IO2_PROTOCOL
*ParentBlockIo2
,
1075 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1076 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
,
1079 IN UINT32 BlockSize
,
1080 IN BOOLEAN InstallEspGuid
1084 PARTITION_PRIVATE_DATA
*Private
;
1086 Status
= EFI_SUCCESS
;
1087 Private
= AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA
));
1088 if (Private
== NULL
) {
1089 return EFI_OUT_OF_RESOURCES
;
1092 Private
->Signature
= PARTITION_PRIVATE_DATA_SIGNATURE
;
1094 Private
->Start
= MultU64x32 (Start
, ParentBlockIo
->Media
->BlockSize
);
1095 Private
->End
= MultU64x32 (End
+ 1, ParentBlockIo
->Media
->BlockSize
);
1097 Private
->BlockSize
= BlockSize
;
1098 Private
->ParentBlockIo
= ParentBlockIo
;
1099 Private
->ParentBlockIo2
= ParentBlockIo2
;
1100 Private
->DiskIo
= ParentDiskIo
;
1101 Private
->DiskIo2
= ParentDiskIo2
;
1104 // Set the BlockIO into Private Data.
1106 Private
->BlockIo
.Revision
= ParentBlockIo
->Revision
;
1108 Private
->BlockIo
.Media
= &Private
->Media
;
1109 CopyMem (Private
->BlockIo
.Media
, ParentBlockIo
->Media
, sizeof (EFI_BLOCK_IO_MEDIA
));
1111 Private
->BlockIo
.Reset
= PartitionReset
;
1112 Private
->BlockIo
.ReadBlocks
= PartitionReadBlocks
;
1113 Private
->BlockIo
.WriteBlocks
= PartitionWriteBlocks
;
1114 Private
->BlockIo
.FlushBlocks
= PartitionFlushBlocks
;
1117 // Set the BlockIO2 into Private Data.
1119 if (Private
->DiskIo2
!= NULL
) {
1120 ASSERT (Private
->ParentBlockIo2
!= NULL
);
1121 Private
->BlockIo2
.Media
= &Private
->Media2
;
1122 CopyMem (Private
->BlockIo2
.Media
, ParentBlockIo2
->Media
, sizeof (EFI_BLOCK_IO_MEDIA
));
1124 Private
->BlockIo2
.Reset
= PartitionResetEx
;
1125 Private
->BlockIo2
.ReadBlocksEx
= PartitionReadBlocksEx
;
1126 Private
->BlockIo2
.WriteBlocksEx
= PartitionWriteBlocksEx
;
1127 Private
->BlockIo2
.FlushBlocksEx
= PartitionFlushBlocksEx
;
1130 Private
->Media
.IoAlign
= 0;
1131 Private
->Media
.LogicalPartition
= TRUE
;
1132 Private
->Media
.LastBlock
= DivU64x32 (
1135 ParentBlockIo
->Media
->BlockSize
1140 Private
->Media
.BlockSize
= (UINT32
) BlockSize
;
1142 Private
->Media2
.IoAlign
= 0;
1143 Private
->Media2
.LogicalPartition
= TRUE
;
1144 Private
->Media2
.LastBlock
= Private
->Media
.LastBlock
;
1145 Private
->Media2
.BlockSize
= (UINT32
) BlockSize
;
1148 // Per UEFI Spec, LowestAlignedLba, LogicalBlocksPerPhysicalBlock and OptimalTransferLengthGranularity must be 0
1149 // for logical partitions.
1151 if (Private
->BlockIo
.Revision
>= EFI_BLOCK_IO_PROTOCOL_REVISION2
) {
1152 Private
->Media
.LowestAlignedLba
= 0;
1153 Private
->Media
.LogicalBlocksPerPhysicalBlock
= 0;
1154 Private
->Media2
.LowestAlignedLba
= 0;
1155 Private
->Media2
.LogicalBlocksPerPhysicalBlock
= 0;
1156 if (Private
->BlockIo
.Revision
>= EFI_BLOCK_IO_PROTOCOL_REVISION3
) {
1157 Private
->Media
.OptimalTransferLengthGranularity
= 0;
1158 Private
->Media2
.OptimalTransferLengthGranularity
= 0;
1162 Private
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, DevicePathNode
);
1164 if (Private
->DevicePath
== NULL
) {
1166 return EFI_OUT_OF_RESOURCES
;
1169 if (InstallEspGuid
) {
1170 Private
->EspGuid
= &gEfiPartTypeSystemPartGuid
;
1173 // If NULL InstallMultipleProtocolInterfaces will ignore it.
1175 Private
->EspGuid
= NULL
;
1179 // Create the new handle.
1181 Private
->Handle
= NULL
;
1182 if (Private
->DiskIo2
!= NULL
) {
1183 Status
= gBS
->InstallMultipleProtocolInterfaces (
1185 &gEfiDevicePathProtocolGuid
,
1186 Private
->DevicePath
,
1187 &gEfiBlockIoProtocolGuid
,
1189 &gEfiBlockIo2ProtocolGuid
,
1196 Status
= gBS
->InstallMultipleProtocolInterfaces (
1198 &gEfiDevicePathProtocolGuid
,
1199 Private
->DevicePath
,
1200 &gEfiBlockIoProtocolGuid
,
1208 if (!EFI_ERROR (Status
)) {
1210 // Open the Parent Handle for the child
1212 Status
= gBS
->OpenProtocol (
1214 &gEfiDiskIoProtocolGuid
,
1215 (VOID
**) &ParentDiskIo
,
1216 This
->DriverBindingHandle
,
1218 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1221 FreePool (Private
->DevicePath
);
1230 The user Entry Point for module Partition. The user code starts with this function.
1232 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1233 @param[in] SystemTable A pointer to the EFI System Table.
1235 @retval EFI_SUCCESS The entry point is executed successfully.
1236 @retval other Some error occurs when executing this entry point.
1241 InitializePartition (
1242 IN EFI_HANDLE ImageHandle
,
1243 IN EFI_SYSTEM_TABLE
*SystemTable
1249 // Install driver model protocol(s).
1251 Status
= EfiLibInstallDriverBindingComponentName2 (
1254 &gPartitionDriverBinding
,
1256 &gPartitionComponentName
,
1257 &gPartitionComponentName2
1259 ASSERT_EFI_ERROR (Status
);