Home | History | Annotate | Download | only in PartitionDxe
      1 /** @file
      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.
      6 
      7 Copyright (c) 2006 - 2014, 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
     12 
     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.
     15 
     16 **/
     17 
     18 
     19 #include "Partition.h"
     20 
     21 //
     22 // Partition Driver Global Variables.
     23 //
     24 EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {
     25   PartitionDriverBindingSupported,
     26   PartitionDriverBindingStart,
     27   PartitionDriverBindingStop,
     28   //
     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.
     35   //
     36   0xb,
     37   NULL,
     38   NULL
     39 };
     40 
     41 //
     42 // Prioritized function list to detect partition table.
     43 //
     44 PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
     45   PartitionInstallGptChildHandles,
     46   PartitionInstallElToritoChildHandles,
     47   PartitionInstallMbrChildHandles,
     48   NULL
     49 };
     50 
     51 /**
     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
     54   supported.
     55 
     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
     59                                   device to start.
     60 
     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
     64 
     65 **/
     66 EFI_STATUS
     67 EFIAPI
     68 PartitionDriverBindingSupported (
     69   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
     70   IN EFI_HANDLE                   ControllerHandle,
     71   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
     72   )
     73 {
     74   EFI_STATUS                Status;
     75   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
     76   EFI_DISK_IO_PROTOCOL      *DiskIo;
     77   EFI_DEV_PATH              *Node;
     78 
     79   //
     80   // Check RemainingDevicePath validation
     81   //
     82   if (RemainingDevicePath != NULL) {
     83     //
     84     // Check if RemainingDevicePath is the End of Device Path Node,
     85     // if yes, go on checking other conditions
     86     //
     87     if (!IsDevicePathEnd (RemainingDevicePath)) {
     88       //
     89       // If RemainingDevicePath isn't the End of Device Path Node,
     90       // check its validation
     91       //
     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;
     97       }
     98     }
     99   }
    100 
    101   //
    102   // Open the IO Abstraction(s) needed to perform the supported test
    103   //
    104   Status = gBS->OpenProtocol (
    105                   ControllerHandle,
    106                   &gEfiDiskIoProtocolGuid,
    107                   (VOID **) &DiskIo,
    108                   This->DriverBindingHandle,
    109                   ControllerHandle,
    110                   EFI_OPEN_PROTOCOL_BY_DRIVER
    111                   );
    112   if (Status == EFI_ALREADY_STARTED) {
    113     return EFI_SUCCESS;
    114   }
    115   if (EFI_ERROR (Status)) {
    116     return Status;
    117   }
    118   //
    119   // Close the I/O Abstraction(s) used to perform the supported test
    120   //
    121   gBS->CloseProtocol (
    122          ControllerHandle,
    123          &gEfiDiskIoProtocolGuid,
    124          This->DriverBindingHandle,
    125          ControllerHandle
    126          );
    127 
    128   //
    129   // Open the EFI Device Path protocol needed to perform the supported test
    130   //
    131   Status = gBS->OpenProtocol (
    132                   ControllerHandle,
    133                   &gEfiDevicePathProtocolGuid,
    134                   (VOID **) &ParentDevicePath,
    135                   This->DriverBindingHandle,
    136                   ControllerHandle,
    137                   EFI_OPEN_PROTOCOL_BY_DRIVER
    138                   );
    139   if (Status == EFI_ALREADY_STARTED) {
    140     return EFI_SUCCESS;
    141   }
    142 
    143   if (EFI_ERROR (Status)) {
    144     return Status;
    145   }
    146 
    147   //
    148   // Close protocol, don't use device path protocol in the Support() function
    149   //
    150   gBS->CloseProtocol (
    151         ControllerHandle,
    152         &gEfiDevicePathProtocolGuid,
    153         This->DriverBindingHandle,
    154         ControllerHandle
    155         );
    156 
    157   //
    158   // Open the IO Abstraction(s) needed to perform the supported test
    159   //
    160   Status = gBS->OpenProtocol (
    161                   ControllerHandle,
    162                   &gEfiBlockIoProtocolGuid,
    163                   NULL,
    164                   This->DriverBindingHandle,
    165                   ControllerHandle,
    166                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    167                   );
    168 
    169   return Status;
    170 }
    171 
    172 /**
    173   Start this driver on ControllerHandle by opening a Block IO or a Block IO2
    174   or both, and Disk IO protocol, reading Device Path, and creating a child
    175   handle with a Disk IO and device path protocol.
    176 
    177   @param[in]  This                 Protocol instance pointer.
    178   @param[in]  ControllerHandle     Handle of device to bind driver to
    179   @param[in]  RemainingDevicePath  Optional parameter use to pick a specific child
    180                                    device to start.
    181 
    182   @retval EFI_SUCCESS          This driver is added to ControllerHandle
    183   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
    184   @retval other                This driver does not support this device
    185 
    186 **/
    187 EFI_STATUS
    188 EFIAPI
    189 PartitionDriverBindingStart (
    190   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    191   IN EFI_HANDLE                   ControllerHandle,
    192   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    193   )
    194 {
    195   EFI_STATUS                Status;
    196   EFI_STATUS                OpenStatus;
    197   EFI_BLOCK_IO_PROTOCOL     *BlockIo;
    198   EFI_BLOCK_IO2_PROTOCOL    *BlockIo2;
    199   EFI_DISK_IO_PROTOCOL      *DiskIo;
    200   EFI_DISK_IO2_PROTOCOL     *DiskIo2;
    201   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
    202   PARTITION_DETECT_ROUTINE  *Routine;
    203   BOOLEAN                   MediaPresent;
    204   EFI_TPL                   OldTpl;
    205 
    206   BlockIo2 = NULL;
    207   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    208   //
    209   // Check RemainingDevicePath validation
    210   //
    211   if (RemainingDevicePath != NULL) {
    212     //
    213     // Check if RemainingDevicePath is the End of Device Path Node,
    214     // if yes, return EFI_SUCCESS
    215     //
    216     if (IsDevicePathEnd (RemainingDevicePath)) {
    217       Status = EFI_SUCCESS;
    218       goto Exit;
    219     }
    220   }
    221 
    222   //
    223   // Try to open BlockIO and BlockIO2. If BlockIO would be opened, continue,
    224   // otherwise, return error.
    225   //
    226   Status = gBS->OpenProtocol (
    227                   ControllerHandle,
    228                   &gEfiBlockIoProtocolGuid,
    229                   (VOID **) &BlockIo,
    230                   This->DriverBindingHandle,
    231                   ControllerHandle,
    232                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    233                   );
    234   if (EFI_ERROR (Status)) {
    235     goto Exit;
    236   }
    237 
    238   Status = gBS->OpenProtocol (
    239                   ControllerHandle,
    240                   &gEfiBlockIo2ProtocolGuid,
    241                   (VOID **) &BlockIo2,
    242                   This->DriverBindingHandle,
    243                   ControllerHandle,
    244                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    245                   );
    246   if (EFI_ERROR (Status)) {
    247     BlockIo2 = NULL;
    248   }
    249 
    250   //
    251   // Get the Device Path Protocol on ControllerHandle's handle.
    252   //
    253   Status = gBS->OpenProtocol (
    254                   ControllerHandle,
    255                   &gEfiDevicePathProtocolGuid,
    256                   (VOID **) &ParentDevicePath,
    257                   This->DriverBindingHandle,
    258                   ControllerHandle,
    259                   EFI_OPEN_PROTOCOL_BY_DRIVER
    260                   );
    261   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
    262     goto Exit;
    263   }
    264 
    265   //
    266   // Get the DiskIo and DiskIo2.
    267   //
    268   Status = gBS->OpenProtocol (
    269                   ControllerHandle,
    270                   &gEfiDiskIoProtocolGuid,
    271                   (VOID **) &DiskIo,
    272                   This->DriverBindingHandle,
    273                   ControllerHandle,
    274                   EFI_OPEN_PROTOCOL_BY_DRIVER
    275                   );
    276   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
    277     gBS->CloseProtocol (
    278           ControllerHandle,
    279           &gEfiDevicePathProtocolGuid,
    280           This->DriverBindingHandle,
    281           ControllerHandle
    282           );
    283     goto Exit;
    284   }
    285 
    286   OpenStatus = Status;
    287 
    288   Status = gBS->OpenProtocol (
    289                   ControllerHandle,
    290                   &gEfiDiskIo2ProtocolGuid,
    291                   (VOID **) &DiskIo2,
    292                   This->DriverBindingHandle,
    293                   ControllerHandle,
    294                   EFI_OPEN_PROTOCOL_BY_DRIVER
    295                   );
    296   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
    297     DiskIo2 = NULL;
    298   }
    299 
    300   //
    301   // Try to read blocks when there's media or it is removable physical partition.
    302   //
    303   Status       = EFI_UNSUPPORTED;
    304   MediaPresent = BlockIo->Media->MediaPresent;
    305   if (BlockIo->Media->MediaPresent ||
    306       (BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition)) {
    307     //
    308     // Try for GPT, then El Torito, and then legacy MBR partition types. If the
    309     // media supports a given partition type install child handles to represent
    310     // the partitions described by the media.
    311     //
    312     Routine = &mPartitionDetectRoutineTable[0];
    313     while (*Routine != NULL) {
    314       Status = (*Routine) (
    315                    This,
    316                    ControllerHandle,
    317                    DiskIo,
    318                    DiskIo2,
    319                    BlockIo,
    320                    BlockIo2,
    321                    ParentDevicePath
    322                    );
    323       if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED || Status == EFI_NO_MEDIA) {
    324         break;
    325       }
    326       Routine++;
    327     }
    328   }
    329   //
    330   // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),
    331   // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the
    332   // driver. So don't try to close them. Otherwise, we will break the dependency
    333   // between the controller and the driver set up before.
    334   //
    335   // In the case that when the media changes on a device it will Reinstall the
    336   // BlockIo interaface. This will cause a call to our Stop(), and a subsequent
    337   // reentrant call to our Start() successfully. We should leave the device open
    338   // when this happen. The "media change" case includes either the status is
    339   // EFI_MEDIA_CHANGED or it is a "media" to "no media" change.
    340   //
    341   if (EFI_ERROR (Status)          &&
    342       !EFI_ERROR (OpenStatus)     &&
    343       Status != EFI_MEDIA_CHANGED &&
    344       !(MediaPresent && Status == EFI_NO_MEDIA)) {
    345     gBS->CloseProtocol (
    346           ControllerHandle,
    347           &gEfiDiskIoProtocolGuid,
    348           This->DriverBindingHandle,
    349           ControllerHandle
    350           );
    351     //
    352     // Close Parent DiskIo2 if has.
    353     //
    354     gBS->CloseProtocol (
    355            ControllerHandle,
    356            &gEfiDiskIo2ProtocolGuid,
    357            This->DriverBindingHandle,
    358            ControllerHandle
    359            );
    360 
    361     gBS->CloseProtocol (
    362           ControllerHandle,
    363           &gEfiDevicePathProtocolGuid,
    364           This->DriverBindingHandle,
    365           ControllerHandle
    366           );
    367   }
    368 
    369 Exit:
    370   gBS->RestoreTPL (OldTpl);
    371   return Status;
    372 }
    373 
    374 /**
    375   Stop this driver on ControllerHandle. Support stopping any child handles
    376   created by this driver.
    377 
    378   @param  This              Protocol instance pointer.
    379   @param  ControllerHandle  Handle of device to stop driver on
    380   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
    381                             children is zero stop the entire bus driver.
    382   @param  ChildHandleBuffer List of Child Handles to Stop.
    383 
    384   @retval EFI_SUCCESS       This driver is removed ControllerHandle
    385   @retval other             This driver was not removed from this device
    386 
    387 **/
    388 EFI_STATUS
    389 EFIAPI
    390 PartitionDriverBindingStop (
    391   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
    392   IN  EFI_HANDLE                    ControllerHandle,
    393   IN  UINTN                         NumberOfChildren,
    394   IN  EFI_HANDLE                    *ChildHandleBuffer
    395   )
    396 {
    397   EFI_STATUS              Status;
    398   UINTN                   Index;
    399   EFI_BLOCK_IO_PROTOCOL   *BlockIo;
    400   EFI_BLOCK_IO2_PROTOCOL  *BlockIo2;
    401   BOOLEAN                 AllChildrenStopped;
    402   PARTITION_PRIVATE_DATA  *Private;
    403   EFI_DISK_IO_PROTOCOL    *DiskIo;
    404 
    405   BlockIo  = NULL;
    406   BlockIo2 = NULL;
    407   Private = NULL;
    408 
    409   if (NumberOfChildren == 0) {
    410     //
    411     // In the case of re-entry of the PartitionDriverBindingStop, the
    412     // NumberOfChildren may not reflect the actual number of children on the
    413     // bus driver. Hence, additional check is needed here.
    414     //
    415     if (HasChildren (ControllerHandle)) {
    416       DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: Still has child.\n"));
    417       return EFI_DEVICE_ERROR;
    418     }
    419 
    420     //
    421     // Close the bus driver
    422     //
    423     gBS->CloseProtocol (
    424           ControllerHandle,
    425           &gEfiDiskIoProtocolGuid,
    426           This->DriverBindingHandle,
    427           ControllerHandle
    428           );
    429     //
    430     // Close Parent BlockIO2 if has.
    431     //
    432     gBS->CloseProtocol (
    433            ControllerHandle,
    434            &gEfiDiskIo2ProtocolGuid,
    435            This->DriverBindingHandle,
    436            ControllerHandle
    437            );
    438 
    439     gBS->CloseProtocol (
    440           ControllerHandle,
    441           &gEfiDevicePathProtocolGuid,
    442           This->DriverBindingHandle,
    443           ControllerHandle
    444           );
    445     return EFI_SUCCESS;
    446   }
    447 
    448   AllChildrenStopped = TRUE;
    449   for (Index = 0; Index < NumberOfChildren; Index++) {
    450     gBS->OpenProtocol (
    451            ChildHandleBuffer[Index],
    452            &gEfiBlockIoProtocolGuid,
    453            (VOID **) &BlockIo,
    454            This->DriverBindingHandle,
    455            ControllerHandle,
    456            EFI_OPEN_PROTOCOL_GET_PROTOCOL
    457            );
    458     //
    459     // Try to locate BlockIo2.
    460     //
    461     gBS->OpenProtocol (
    462            ChildHandleBuffer[Index],
    463            &gEfiBlockIo2ProtocolGuid,
    464            (VOID **) &BlockIo2,
    465            This->DriverBindingHandle,
    466            ControllerHandle,
    467            EFI_OPEN_PROTOCOL_GET_PROTOCOL
    468            );
    469 
    470 
    471     Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);
    472     if (Private->InStop) {
    473       //
    474       // If the child handle is going to be stopped again during the re-entry
    475       // of DriverBindingStop, just do nothing.
    476       //
    477       break;
    478     }
    479     Private->InStop = TRUE;
    480 
    481     BlockIo->FlushBlocks (BlockIo);
    482 
    483     if (BlockIo2 != NULL) {
    484       Status = BlockIo2->FlushBlocksEx (BlockIo2, NULL);
    485       DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: FlushBlocksEx returned with %r\n", Status));
    486     } else {
    487       Status = EFI_SUCCESS;
    488     }
    489 
    490     gBS->CloseProtocol (
    491            ControllerHandle,
    492            &gEfiDiskIoProtocolGuid,
    493            This->DriverBindingHandle,
    494            ChildHandleBuffer[Index]
    495            );
    496     //
    497     // All Software protocols have be freed from the handle so remove it.
    498     // Remove the BlockIo Protocol if has.
    499     // Remove the BlockIo2 Protocol if has.
    500     //
    501     if (BlockIo2 != NULL) {
    502       //
    503       // Some device drivers might re-install the BlockIO(2) protocols for a
    504       // media change condition. Therefore, if the FlushBlocksEx returned with
    505       // EFI_MEDIA_CHANGED, just let the BindingStop fail to avoid potential
    506       // reference of already stopped child handle.
    507       //
    508       if (Status != EFI_MEDIA_CHANGED) {
    509         Status = gBS->UninstallMultipleProtocolInterfaces (
    510                          ChildHandleBuffer[Index],
    511                          &gEfiDevicePathProtocolGuid,
    512                          Private->DevicePath,
    513                          &gEfiBlockIoProtocolGuid,
    514                          &Private->BlockIo,
    515                          &gEfiBlockIo2ProtocolGuid,
    516                          &Private->BlockIo2,
    517                          Private->EspGuid,
    518                          NULL,
    519                          NULL
    520                          );
    521       }
    522     } else {
    523       Status = gBS->UninstallMultipleProtocolInterfaces (
    524                        ChildHandleBuffer[Index],
    525                        &gEfiDevicePathProtocolGuid,
    526                        Private->DevicePath,
    527                        &gEfiBlockIoProtocolGuid,
    528                        &Private->BlockIo,
    529                        Private->EspGuid,
    530                        NULL,
    531                        NULL
    532                        );
    533     }
    534 
    535     if (EFI_ERROR (Status)) {
    536       Private->InStop = FALSE;
    537       gBS->OpenProtocol (
    538              ControllerHandle,
    539              &gEfiDiskIoProtocolGuid,
    540              (VOID **) &DiskIo,
    541              This->DriverBindingHandle,
    542              ChildHandleBuffer[Index],
    543              EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    544              );
    545     } else {
    546       FreePool (Private->DevicePath);
    547       FreePool (Private);
    548     }
    549 
    550     if (EFI_ERROR (Status)) {
    551       AllChildrenStopped = FALSE;
    552       if (Status == EFI_MEDIA_CHANGED) {
    553         break;
    554       }
    555     }
    556   }
    557 
    558   if (!AllChildrenStopped) {
    559     return EFI_DEVICE_ERROR;
    560   }
    561 
    562   return EFI_SUCCESS;
    563 }
    564 
    565 
    566 /**
    567   Reset the Block Device.
    568 
    569   @param  This                 Protocol instance pointer.
    570   @param  ExtendedVerification Driver may perform diagnostics on reset.
    571 
    572   @retval EFI_SUCCESS          The device was reset.
    573   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
    574                                not be reset.
    575 
    576 **/
    577 EFI_STATUS
    578 EFIAPI
    579 PartitionReset (
    580   IN EFI_BLOCK_IO_PROTOCOL  *This,
    581   IN BOOLEAN                ExtendedVerification
    582   )
    583 {
    584   PARTITION_PRIVATE_DATA  *Private;
    585 
    586   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
    587 
    588   return Private->ParentBlockIo->Reset (
    589                                   Private->ParentBlockIo,
    590                                   ExtendedVerification
    591                                   );
    592 }
    593 
    594 /**
    595   Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
    596   for no media or media change case. Otherwise DefaultStatus is returned.
    597 
    598   @param DiskIo             Pointer to the DiskIo instance.
    599   @param MediaId            Id of the media, changes every time the media is replaced.
    600   @param DefaultStatus      The default status to return when it's not the no media
    601                             or media change case.
    602 
    603   @retval EFI_NO_MEDIA      There is no media.
    604   @retval EFI_MEDIA_CHANGED The media was changed.
    605   @retval others            The default status to return.
    606 **/
    607 EFI_STATUS
    608 ProbeMediaStatus (
    609   IN EFI_DISK_IO_PROTOCOL    *DiskIo,
    610   IN UINT32                  MediaId,
    611   IN EFI_STATUS              DefaultStatus
    612   )
    613 {
    614   EFI_STATUS                 Status;
    615   UINT8                      Buffer[1];
    616 
    617   //
    618   // Read 1 byte from offset 0 to check if the MediaId is still valid.
    619   // The reading operation is synchronious thus it is not worth it to
    620   // allocate a buffer from the pool. The destination buffer for the
    621   // data is in the stack.
    622   //
    623   Status = DiskIo->ReadDisk (DiskIo, MediaId, 0, 1, (VOID*)Buffer);
    624   if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
    625     return Status;
    626   }
    627   return DefaultStatus;
    628 }
    629 
    630 /**
    631   Read by using the Disk IO protocol on the parent device. Lba addresses
    632   must be converted to byte offsets.
    633 
    634   @param  This       Protocol instance pointer.
    635   @param  MediaId    Id of the media, changes every time the media is replaced.
    636   @param  Lba        The starting Logical Block Address to read from
    637   @param  BufferSize Size of Buffer, must be a multiple of device block size.
    638   @param  Buffer     Buffer containing read data
    639 
    640   @retval EFI_SUCCESS           The data was read correctly from the device.
    641   @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.
    642   @retval EFI_NO_MEDIA          There is no media in the device.
    643   @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.
    644   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
    645   @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
    646                                 valid for the device.
    647 
    648 **/
    649 EFI_STATUS
    650 EFIAPI
    651 PartitionReadBlocks (
    652   IN EFI_BLOCK_IO_PROTOCOL  *This,
    653   IN UINT32                 MediaId,
    654   IN EFI_LBA                Lba,
    655   IN UINTN                  BufferSize,
    656   OUT VOID                  *Buffer
    657   )
    658 {
    659   PARTITION_PRIVATE_DATA  *Private;
    660   UINT64                  Offset;
    661 
    662   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
    663 
    664   if (BufferSize % Private->BlockSize != 0) {
    665     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
    666   }
    667 
    668   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
    669   if (Offset + BufferSize > Private->End) {
    670     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
    671   }
    672   //
    673   // Because some kinds of partition have different block size from their parent
    674   // device, we call the Disk IO protocol on the parent device, not the Block IO
    675   // protocol
    676   //
    677   return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
    678 }
    679 
    680 /**
    681   Write by using the Disk IO protocol on the parent device. Lba addresses
    682   must be converted to byte offsets.
    683 
    684   @param[in]  This       Protocol instance pointer.
    685   @param[in]  MediaId    Id of the media, changes every time the media is replaced.
    686   @param[in]  Lba        The starting Logical Block Address to read from
    687   @param[in]  BufferSize Size of Buffer, must be a multiple of device block size.
    688   @param[in]  Buffer     Buffer containing data to be written to device.
    689 
    690   @retval EFI_SUCCESS           The data was written correctly to the device.
    691   @retval EFI_WRITE_PROTECTED   The device can not be written to.
    692   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
    693   @retval EFI_NO_MEDIA          There is no media in the device.
    694   @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
    695   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
    696   @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not
    697                                 valid for the device.
    698 
    699 **/
    700 EFI_STATUS
    701 EFIAPI
    702 PartitionWriteBlocks (
    703   IN EFI_BLOCK_IO_PROTOCOL  *This,
    704   IN UINT32                 MediaId,
    705   IN EFI_LBA                Lba,
    706   IN UINTN                  BufferSize,
    707   IN VOID                  *Buffer
    708   )
    709 {
    710   PARTITION_PRIVATE_DATA  *Private;
    711   UINT64                  Offset;
    712 
    713   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
    714 
    715   if (BufferSize % Private->BlockSize != 0) {
    716     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
    717   }
    718 
    719   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
    720   if (Offset + BufferSize > Private->End) {
    721     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
    722   }
    723   //
    724   // Because some kinds of partition have different block size from their parent
    725   // device, we call the Disk IO protocol on the parent device, not the Block IO
    726   // protocol
    727   //
    728   return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
    729 }
    730 
    731 
    732 /**
    733   Flush the parent Block Device.
    734 
    735   @param  This              Protocol instance pointer.
    736 
    737   @retval EFI_SUCCESS       All outstanding data was written to the device
    738   @retval EFI_DEVICE_ERROR  The device reported an error while writting back the data
    739   @retval EFI_NO_MEDIA      There is no media in the device.
    740 
    741 **/
    742 EFI_STATUS
    743 EFIAPI
    744 PartitionFlushBlocks (
    745   IN EFI_BLOCK_IO_PROTOCOL  *This
    746   )
    747 {
    748   PARTITION_PRIVATE_DATA  *Private;
    749 
    750   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
    751 
    752   return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);
    753 }
    754 
    755 /**
    756   Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
    757   for no media or media change case. Otherwise DefaultStatus is returned.
    758 
    759   @param DiskIo2            Pointer to the DiskIo2 instance.
    760   @param MediaId            Id of the media, changes every time the media is replaced.
    761   @param DefaultStatus      The default status to return when it's not the no media
    762                             or media change case.
    763 
    764   @retval EFI_NO_MEDIA      There is no media.
    765   @retval EFI_MEDIA_CHANGED The media was changed.
    766   @retval others            The default status to return.
    767 **/
    768 EFI_STATUS
    769 ProbeMediaStatusEx (
    770   IN EFI_DISK_IO2_PROTOCOL   *DiskIo2,
    771   IN UINT32                  MediaId,
    772   IN EFI_STATUS              DefaultStatus
    773   )
    774 {
    775   EFI_STATUS                 Status;
    776 
    777   //
    778   // Read 1 byte from offset 0 but passing NULL as buffer pointer
    779   //
    780   Status = DiskIo2->ReadDiskEx (DiskIo2, MediaId, 0, NULL, 1, NULL);
    781   if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
    782     return Status;
    783   }
    784   return DefaultStatus;
    785 }
    786 
    787 /**
    788   Reset the Block Device throught Block I/O2 protocol.
    789 
    790   @param  This                 Protocol instance pointer.
    791   @param  ExtendedVerification Driver may perform diagnostics on reset.
    792 
    793   @retval EFI_SUCCESS          The device was reset.
    794   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
    795                                not be reset.
    796 
    797 **/
    798 EFI_STATUS
    799 EFIAPI
    800 PartitionResetEx (
    801   IN EFI_BLOCK_IO2_PROTOCOL *This,
    802   IN BOOLEAN                ExtendedVerification
    803   )
    804 {
    805   PARTITION_PRIVATE_DATA  *Private;
    806 
    807   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
    808 
    809   return Private->ParentBlockIo2->Reset (
    810                                     Private->ParentBlockIo2,
    811                                     ExtendedVerification
    812                                     );
    813 }
    814 
    815 /**
    816   The general callback for the DiskIo2 interfaces.
    817   @param  Event                 Event whose notification function is being invoked.
    818   @param  Context               The pointer to the notification function's context,
    819                                 which points to the PARTITION_ACCESS_TASK instance.
    820 **/
    821 VOID
    822 EFIAPI
    823 PartitionOnAccessComplete (
    824   IN EFI_EVENT                 Event,
    825   IN VOID                      *Context
    826   )
    827 {
    828   PARTITION_ACCESS_TASK   *Task;
    829 
    830   Task = (PARTITION_ACCESS_TASK *) Context;
    831 
    832   gBS->CloseEvent (Event);
    833 
    834   Task->BlockIo2Token->TransactionStatus = Task->DiskIo2Token.TransactionStatus;
    835   gBS->SignalEvent (Task->BlockIo2Token->Event);
    836 
    837   FreePool (Task);
    838 }
    839 
    840 /**
    841   Create a new PARTITION_ACCESS_TASK instance.
    842 
    843   @param  Token  Pointer to the EFI_BLOCK_IO2_TOKEN.
    844 
    845   @return Pointer to the created PARTITION_ACCESS_TASK instance or NULL upon failure.
    846 **/
    847 PARTITION_ACCESS_TASK *
    848 PartitionCreateAccessTask (
    849   IN EFI_BLOCK_IO2_TOKEN    *Token
    850   )
    851 {
    852   EFI_STATUS                Status;
    853   PARTITION_ACCESS_TASK     *Task;
    854 
    855   Task = AllocatePool (sizeof (*Task));
    856   if (Task == NULL) {
    857     return NULL;
    858   }
    859 
    860   Status = gBS->CreateEvent (
    861                   EVT_NOTIFY_SIGNAL,
    862                   TPL_NOTIFY,
    863                   PartitionOnAccessComplete,
    864                   Task,
    865                   &Task->DiskIo2Token.Event
    866                   );
    867   if (EFI_ERROR (Status)) {
    868     FreePool (Task);
    869     return NULL;
    870   }
    871 
    872   Task->BlockIo2Token = Token;
    873 
    874   return Task;
    875 }
    876 
    877 /**
    878   Read BufferSize bytes from Lba into Buffer.
    879 
    880   This function reads the requested number of blocks from the device. All the
    881   blocks are read, or an error is returned.
    882   If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
    883   non-blocking I/O is being used, the Event associated with this request will
    884   not be signaled.
    885 
    886   @param[in]       This       Indicates a pointer to the calling context.
    887   @param[in]       MediaId    Id of the media, changes every time the media is
    888                               replaced.
    889   @param[in]       Lba        The starting Logical Block Address to read from.
    890   @param[in, out]  Token	    A pointer to the token associated with the transaction.
    891   @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.
    892   @param[out]      Buffer     A pointer to the destination buffer for the data. The
    893                               caller is responsible for either having implicit or
    894                               explicit ownership of the buffer.
    895 
    896   @retval EFI_SUCCESS           The read request was queued if Token->Event is
    897                                 not NULL.The data was read correctly from the
    898                                 device if the Token->Event is NULL.
    899   @retval EFI_DEVICE_ERROR      The device reported an error while performing
    900                                 the read.
    901   @retval EFI_NO_MEDIA          There is no media in the device.
    902   @retval EFI_MEDIA_CHANGED     The MediaId is not for the current media.
    903   @retval EFI_BAD_BUFFER_SIZE   The BufferSize parameter is not a multiple of the
    904                                 intrinsic block size of the device.
    905   @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
    906                                 or the buffer is not on proper alignment.
    907   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack
    908                                 of resources.
    909 **/
    910 EFI_STATUS
    911 EFIAPI
    912 PartitionReadBlocksEx (
    913   IN     EFI_BLOCK_IO2_PROTOCOL *This,
    914   IN     UINT32                 MediaId,
    915   IN     EFI_LBA                Lba,
    916   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
    917   IN     UINTN                  BufferSize,
    918   OUT    VOID                   *Buffer
    919   )
    920 {
    921   EFI_STATUS              Status;
    922   PARTITION_PRIVATE_DATA  *Private;
    923   UINT64                  Offset;
    924   PARTITION_ACCESS_TASK   *Task;
    925 
    926   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
    927 
    928   if (BufferSize % Private->BlockSize != 0) {
    929     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
    930   }
    931 
    932   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
    933   if (Offset + BufferSize > Private->End) {
    934     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
    935   }
    936 
    937   if ((Token != NULL) && (Token->Event != NULL)) {
    938     Task = PartitionCreateAccessTask (Token);
    939     if (Task == NULL) {
    940       return EFI_OUT_OF_RESOURCES;
    941     }
    942 
    943     Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
    944     if (EFI_ERROR (Status)) {
    945       gBS->CloseEvent (Task->DiskIo2Token.Event);
    946       FreePool (Task);
    947     }
    948   } else {
    949     Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
    950   }
    951 
    952   return Status;
    953 }
    954 
    955 /**
    956   Write BufferSize bytes from Lba into Buffer.
    957 
    958   This function writes the requested number of blocks to the device. All blocks
    959   are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
    960   EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
    961   being used, the Event associated with this request will not be signaled.
    962 
    963   @param[in]       This       Indicates a pointer to the calling context.
    964   @param[in]       MediaId    The media ID that the write request is for.
    965   @param[in]       Lba        The starting logical block address to be written. The
    966                               caller is responsible for writing to only legitimate
    967                               locations.
    968   @param[in, out]  Token      A pointer to the token associated with the transaction.
    969   @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.
    970   @param[in]       Buffer     A pointer to the source buffer for the data.
    971 
    972   @retval EFI_SUCCESS           The write request was queued if Event is not NULL.
    973                                 The data was written correctly to the device if
    974                                 the Event is NULL.
    975   @retval EFI_WRITE_PROTECTED   The device can not be written to.
    976   @retval EFI_NO_MEDIA          There is no media in the device.
    977   @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
    978   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
    979   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
    980   @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
    981                                 or the buffer is not on proper alignment.
    982   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack
    983                                 of resources.
    984 
    985 **/
    986 EFI_STATUS
    987 EFIAPI
    988 PartitionWriteBlocksEx (
    989   IN     EFI_BLOCK_IO2_PROTOCOL *This,
    990   IN     UINT32                 MediaId,
    991   IN     EFI_LBA                Lba,
    992   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
    993   IN     UINTN                  BufferSize,
    994   IN     VOID                   *Buffer
    995   )
    996 {
    997   EFI_STATUS              Status;
    998   PARTITION_PRIVATE_DATA  *Private;
    999   UINT64                  Offset;
   1000   PARTITION_ACCESS_TASK   *Task;
   1001 
   1002   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
   1003 
   1004   if (BufferSize % Private->BlockSize != 0) {
   1005     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
   1006   }
   1007 
   1008   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
   1009   if (Offset + BufferSize > Private->End) {
   1010     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
   1011   }
   1012 
   1013   if ((Token != NULL) && (Token->Event != NULL)) {
   1014     Task = PartitionCreateAccessTask (Token);
   1015     if (Task == NULL) {
   1016       return EFI_OUT_OF_RESOURCES;
   1017     }
   1018 
   1019     Status =  Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
   1020     if (EFI_ERROR (Status)) {
   1021       gBS->CloseEvent (Task->DiskIo2Token.Event);
   1022       FreePool (Task);
   1023     }
   1024   } else {
   1025     Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
   1026   }
   1027   return Status;
   1028 }
   1029 
   1030 /**
   1031   Flush the Block Device.
   1032 
   1033   If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
   1034   is returned and non-blocking I/O is being used, the Event associated with
   1035   this request will not be signaled.
   1036 
   1037   @param[in]      This     Indicates a pointer to the calling context.
   1038   @param[in, out] Token    A pointer to the token associated with the transaction
   1039 
   1040   @retval EFI_SUCCESS          The flush request was queued if Event is not NULL.
   1041                                All outstanding data was written correctly to the
   1042                                device if the Event is NULL.
   1043   @retval EFI_DEVICE_ERROR     The device reported an error while writting back
   1044                                the data.
   1045   @retval EFI_WRITE_PROTECTED  The device cannot be written to.
   1046   @retval EFI_NO_MEDIA         There is no media in the device.
   1047   @retval EFI_MEDIA_CHANGED    The MediaId is not for the current media.
   1048   @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
   1049                                of resources.
   1050 
   1051 **/
   1052 EFI_STATUS
   1053 EFIAPI
   1054 PartitionFlushBlocksEx (
   1055   IN     EFI_BLOCK_IO2_PROTOCOL *This,
   1056   IN OUT EFI_BLOCK_IO2_TOKEN    *Token
   1057   )
   1058 {
   1059   EFI_STATUS              Status;
   1060   PARTITION_PRIVATE_DATA  *Private;
   1061   PARTITION_ACCESS_TASK   *Task;
   1062 
   1063   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
   1064 
   1065   if ((Token != NULL) && (Token->Event != NULL)) {
   1066     Task = PartitionCreateAccessTask (Token);
   1067     if (Task == NULL) {
   1068       return EFI_OUT_OF_RESOURCES;
   1069     }
   1070 
   1071     Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, &Task->DiskIo2Token);
   1072     if (EFI_ERROR (Status)) {
   1073       gBS->CloseEvent (Task->DiskIo2Token.Event);
   1074       FreePool (Task);
   1075     }
   1076   } else {
   1077     Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, NULL);
   1078   }
   1079   return Status;
   1080 }
   1081 
   1082 
   1083 /**
   1084   Create a child handle for a logical block device that represents the
   1085   bytes Start to End of the Parent Block IO device.
   1086 
   1087   @param[in]  This              Protocol instance pointer.
   1088   @param[in]  ParentHandle      Parent Handle for new child.
   1089   @param[in]  ParentDiskIo      Parent DiskIo interface.
   1090   @param[in]  ParentDiskIo2     Parent DiskIo2 interface.
   1091   @param[in]  ParentBlockIo     Parent BlockIo interface.
   1092   @param[in]  ParentBlockIo2    Parent BlockIo2 interface.
   1093   @param[in]  ParentDevicePath  Parent Device Path.
   1094   @param[in]  DevicePathNode    Child Device Path node.
   1095   @param[in]  Start             Start Block.
   1096   @param[in]  End               End Block.
   1097   @param[in]  BlockSize         Child block size.
   1098   @param[in]  InstallEspGuid    Flag to install EFI System Partition GUID on handle.
   1099 
   1100   @retval EFI_SUCCESS       A child handle was added.
   1101   @retval other             A child handle was not added.
   1102 
   1103 **/
   1104 EFI_STATUS
   1105 PartitionInstallChildHandle (
   1106   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
   1107   IN  EFI_HANDLE                   ParentHandle,
   1108   IN  EFI_DISK_IO_PROTOCOL         *ParentDiskIo,
   1109   IN  EFI_DISK_IO2_PROTOCOL        *ParentDiskIo2,
   1110   IN  EFI_BLOCK_IO_PROTOCOL        *ParentBlockIo,
   1111   IN  EFI_BLOCK_IO2_PROTOCOL       *ParentBlockIo2,
   1112   IN  EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,
   1113   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
   1114   IN  EFI_LBA                      Start,
   1115   IN  EFI_LBA                      End,
   1116   IN  UINT32                       BlockSize,
   1117   IN  BOOLEAN                      InstallEspGuid
   1118   )
   1119 {
   1120   EFI_STATUS              Status;
   1121   PARTITION_PRIVATE_DATA  *Private;
   1122 
   1123   Status  = EFI_SUCCESS;
   1124   Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));
   1125   if (Private == NULL) {
   1126     return EFI_OUT_OF_RESOURCES;
   1127   }
   1128 
   1129   Private->Signature        = PARTITION_PRIVATE_DATA_SIGNATURE;
   1130 
   1131   Private->Start            = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);
   1132   Private->End              = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);
   1133 
   1134   Private->BlockSize        = BlockSize;
   1135   Private->ParentBlockIo    = ParentBlockIo;
   1136   Private->ParentBlockIo2   = ParentBlockIo2;
   1137   Private->DiskIo           = ParentDiskIo;
   1138   Private->DiskIo2          = ParentDiskIo2;
   1139 
   1140   //
   1141   // Set the BlockIO into Private Data.
   1142   //
   1143   Private->BlockIo.Revision = ParentBlockIo->Revision;
   1144 
   1145   Private->BlockIo.Media    = &Private->Media;
   1146   CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));
   1147 
   1148   Private->BlockIo.Reset        = PartitionReset;
   1149   Private->BlockIo.ReadBlocks   = PartitionReadBlocks;
   1150   Private->BlockIo.WriteBlocks  = PartitionWriteBlocks;
   1151   Private->BlockIo.FlushBlocks  = PartitionFlushBlocks;
   1152 
   1153   //
   1154   // Set the BlockIO2 into Private Data.
   1155   //
   1156   if (Private->DiskIo2 != NULL) {
   1157     ASSERT (Private->ParentBlockIo2 != NULL);
   1158     Private->BlockIo2.Media    = &Private->Media2;
   1159     CopyMem (Private->BlockIo2.Media, ParentBlockIo2->Media, sizeof (EFI_BLOCK_IO_MEDIA));
   1160 
   1161     Private->BlockIo2.Reset          = PartitionResetEx;
   1162     Private->BlockIo2.ReadBlocksEx   = PartitionReadBlocksEx;
   1163     Private->BlockIo2.WriteBlocksEx  = PartitionWriteBlocksEx;
   1164     Private->BlockIo2.FlushBlocksEx  = PartitionFlushBlocksEx;
   1165   }
   1166 
   1167   Private->Media.IoAlign   = 0;
   1168   Private->Media.LogicalPartition = TRUE;
   1169   Private->Media.LastBlock = DivU64x32 (
   1170                                MultU64x32 (
   1171                                  End - Start + 1,
   1172                                  ParentBlockIo->Media->BlockSize
   1173                                  ),
   1174                                 BlockSize
   1175                                ) - 1;
   1176 
   1177   Private->Media.BlockSize = (UINT32) BlockSize;
   1178 
   1179   Private->Media2.IoAlign   = 0;
   1180   Private->Media2.LogicalPartition = TRUE;
   1181   Private->Media2.LastBlock = Private->Media.LastBlock;
   1182   Private->Media2.BlockSize = (UINT32) BlockSize;
   1183 
   1184   //
   1185   // Per UEFI Spec, LowestAlignedLba, LogicalBlocksPerPhysicalBlock and OptimalTransferLengthGranularity must be 0
   1186   //  for logical partitions.
   1187   //
   1188   if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION2) {
   1189     Private->Media.LowestAlignedLba               = 0;
   1190     Private->Media.LogicalBlocksPerPhysicalBlock  = 0;
   1191     Private->Media2.LowestAlignedLba              = 0;
   1192     Private->Media2.LogicalBlocksPerPhysicalBlock = 0;
   1193     if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION3) {
   1194       Private->Media.OptimalTransferLengthGranularity  = 0;
   1195       Private->Media2.OptimalTransferLengthGranularity = 0;
   1196     }
   1197   }
   1198 
   1199   Private->DevicePath     = AppendDevicePathNode (ParentDevicePath, DevicePathNode);
   1200 
   1201   if (Private->DevicePath == NULL) {
   1202     FreePool (Private);
   1203     return EFI_OUT_OF_RESOURCES;
   1204   }
   1205 
   1206   if (InstallEspGuid) {
   1207     Private->EspGuid = &gEfiPartTypeSystemPartGuid;
   1208   } else {
   1209     //
   1210     // If NULL InstallMultipleProtocolInterfaces will ignore it.
   1211     //
   1212     Private->EspGuid = NULL;
   1213   }
   1214 
   1215   //
   1216   // Create the new handle.
   1217   //
   1218   Private->Handle = NULL;
   1219   if (Private->DiskIo2 != NULL) {
   1220     Status = gBS->InstallMultipleProtocolInterfaces (
   1221                     &Private->Handle,
   1222                     &gEfiDevicePathProtocolGuid,
   1223                     Private->DevicePath,
   1224                     &gEfiBlockIoProtocolGuid,
   1225                     &Private->BlockIo,
   1226                     &gEfiBlockIo2ProtocolGuid,
   1227                     &Private->BlockIo2,
   1228                     Private->EspGuid,
   1229                     NULL,
   1230                     NULL
   1231                     );
   1232   } else {
   1233     Status = gBS->InstallMultipleProtocolInterfaces (
   1234                     &Private->Handle,
   1235                     &gEfiDevicePathProtocolGuid,
   1236                     Private->DevicePath,
   1237                     &gEfiBlockIoProtocolGuid,
   1238                     &Private->BlockIo,
   1239                     Private->EspGuid,
   1240                     NULL,
   1241                     NULL
   1242                     );
   1243   }
   1244 
   1245   if (!EFI_ERROR (Status)) {
   1246     //
   1247     // Open the Parent Handle for the child
   1248     //
   1249     Status = gBS->OpenProtocol (
   1250                     ParentHandle,
   1251                     &gEfiDiskIoProtocolGuid,
   1252                     (VOID **) &ParentDiskIo,
   1253                     This->DriverBindingHandle,
   1254                     Private->Handle,
   1255                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
   1256                     );
   1257   } else {
   1258     FreePool (Private->DevicePath);
   1259     FreePool (Private);
   1260   }
   1261 
   1262   return Status;
   1263 }
   1264 
   1265 
   1266 /**
   1267   The user Entry Point for module Partition. The user code starts with this function.
   1268 
   1269   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
   1270   @param[in] SystemTable    A pointer to the EFI System Table.
   1271 
   1272   @retval EFI_SUCCESS       The entry point is executed successfully.
   1273   @retval other             Some error occurs when executing this entry point.
   1274 
   1275 **/
   1276 EFI_STATUS
   1277 EFIAPI
   1278 InitializePartition (
   1279   IN EFI_HANDLE           ImageHandle,
   1280   IN EFI_SYSTEM_TABLE     *SystemTable
   1281   )
   1282 {
   1283   EFI_STATUS              Status;
   1284 
   1285   //
   1286   // Install driver model protocol(s).
   1287   //
   1288   Status = EfiLibInstallDriverBindingComponentName2 (
   1289              ImageHandle,
   1290              SystemTable,
   1291              &gPartitionDriverBinding,
   1292              ImageHandle,
   1293              &gPartitionComponentName,
   1294              &gPartitionComponentName2
   1295              );
   1296   ASSERT_EFI_ERROR (Status);
   1297 
   1298 
   1299   return Status;
   1300 }
   1301 
   1302 
   1303 /**
   1304   Test to see if there is any child on ControllerHandle.
   1305 
   1306   @param[in]  ControllerHandle    Handle of device to test.
   1307 
   1308   @retval TRUE                    There are children on the ControllerHandle.
   1309   @retval FALSE                   No child is on the ControllerHandle.
   1310 
   1311 **/
   1312 BOOLEAN
   1313 HasChildren (
   1314   IN EFI_HANDLE           ControllerHandle
   1315   )
   1316 {
   1317   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY  *OpenInfoBuffer;
   1318   UINTN                                EntryCount;
   1319   EFI_STATUS                           Status;
   1320   UINTN                                Index;
   1321 
   1322   Status = gBS->OpenProtocolInformation (
   1323                   ControllerHandle,
   1324                   &gEfiDiskIoProtocolGuid,
   1325                   &OpenInfoBuffer,
   1326                   &EntryCount
   1327                   );
   1328   ASSERT_EFI_ERROR (Status);
   1329 
   1330   for (Index = 0; Index < EntryCount; Index++) {
   1331     if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
   1332       break;
   1333     }
   1334   }
   1335   FreePool (OpenInfoBuffer);
   1336 
   1337   return (BOOLEAN) (Index < EntryCount);
   1338 }
   1339 
   1340