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     // Close the bus driver
    412     //
    413     gBS->CloseProtocol (
    414           ControllerHandle,
    415           &gEfiDiskIoProtocolGuid,
    416           This->DriverBindingHandle,
    417           ControllerHandle
    418           );
    419     //
    420     // Close Parent BlockIO2 if has.
    421     //
    422     gBS->CloseProtocol (
    423            ControllerHandle,
    424            &gEfiDiskIo2ProtocolGuid,
    425            This->DriverBindingHandle,
    426            ControllerHandle
    427            );
    428 
    429     gBS->CloseProtocol (
    430           ControllerHandle,
    431           &gEfiDevicePathProtocolGuid,
    432           This->DriverBindingHandle,
    433           ControllerHandle
    434           );
    435     return EFI_SUCCESS;
    436   }
    437 
    438   AllChildrenStopped = TRUE;
    439   for (Index = 0; Index < NumberOfChildren; Index++) {
    440     gBS->OpenProtocol (
    441            ChildHandleBuffer[Index],
    442            &gEfiBlockIoProtocolGuid,
    443            (VOID **) &BlockIo,
    444            This->DriverBindingHandle,
    445            ControllerHandle,
    446            EFI_OPEN_PROTOCOL_GET_PROTOCOL
    447            );
    448     //
    449     // Try to locate BlockIo2.
    450     //
    451     gBS->OpenProtocol (
    452            ChildHandleBuffer[Index],
    453            &gEfiBlockIo2ProtocolGuid,
    454            (VOID **) &BlockIo2,
    455            This->DriverBindingHandle,
    456            ControllerHandle,
    457            EFI_OPEN_PROTOCOL_GET_PROTOCOL
    458            );
    459 
    460 
    461     Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);
    462 
    463     Status = gBS->CloseProtocol (
    464                     ControllerHandle,
    465                     &gEfiDiskIoProtocolGuid,
    466                     This->DriverBindingHandle,
    467                     ChildHandleBuffer[Index]
    468                     );
    469     //
    470     // All Software protocols have be freed from the handle so remove it.
    471     // Remove the BlockIo Protocol if has.
    472     // Remove the BlockIo2 Protocol if has.
    473     //
    474     if (BlockIo2 != NULL) {
    475       BlockIo->FlushBlocks (BlockIo);
    476       BlockIo2->FlushBlocksEx (BlockIo2, NULL);
    477       Status = gBS->UninstallMultipleProtocolInterfaces (
    478                        ChildHandleBuffer[Index],
    479                        &gEfiDevicePathProtocolGuid,
    480                        Private->DevicePath,
    481                        &gEfiBlockIoProtocolGuid,
    482                        &Private->BlockIo,
    483                        &gEfiBlockIo2ProtocolGuid,
    484                        &Private->BlockIo2,
    485                        Private->EspGuid,
    486                        NULL,
    487                        NULL
    488                        );
    489     } else {
    490       BlockIo->FlushBlocks (BlockIo);
    491       Status = gBS->UninstallMultipleProtocolInterfaces (
    492                        ChildHandleBuffer[Index],
    493                        &gEfiDevicePathProtocolGuid,
    494                        Private->DevicePath,
    495                        &gEfiBlockIoProtocolGuid,
    496                        &Private->BlockIo,
    497                        Private->EspGuid,
    498                        NULL,
    499                        NULL
    500                        );
    501     }
    502 
    503     if (EFI_ERROR (Status)) {
    504       gBS->OpenProtocol (
    505              ControllerHandle,
    506              &gEfiDiskIoProtocolGuid,
    507              (VOID **) &DiskIo,
    508              This->DriverBindingHandle,
    509              ChildHandleBuffer[Index],
    510              EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    511              );
    512     } else {
    513       FreePool (Private->DevicePath);
    514       FreePool (Private);
    515     }
    516 
    517     if (EFI_ERROR (Status)) {
    518       AllChildrenStopped = FALSE;
    519     }
    520   }
    521 
    522   if (!AllChildrenStopped) {
    523     return EFI_DEVICE_ERROR;
    524   }
    525 
    526   return EFI_SUCCESS;
    527 }
    528 
    529 
    530 /**
    531   Reset the Block Device.
    532 
    533   @param  This                 Protocol instance pointer.
    534   @param  ExtendedVerification Driver may perform diagnostics on reset.
    535 
    536   @retval EFI_SUCCESS          The device was reset.
    537   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
    538                                not be reset.
    539 
    540 **/
    541 EFI_STATUS
    542 EFIAPI
    543 PartitionReset (
    544   IN EFI_BLOCK_IO_PROTOCOL  *This,
    545   IN BOOLEAN                ExtendedVerification
    546   )
    547 {
    548   PARTITION_PRIVATE_DATA  *Private;
    549 
    550   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
    551 
    552   return Private->ParentBlockIo->Reset (
    553                                   Private->ParentBlockIo,
    554                                   ExtendedVerification
    555                                   );
    556 }
    557 
    558 /**
    559   Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
    560   for no media or media change case. Otherwise DefaultStatus is returned.
    561 
    562   @param DiskIo             Pointer to the DiskIo instance.
    563   @param MediaId            Id of the media, changes every time the media is replaced.
    564   @param DefaultStatus      The default status to return when it's not the no media
    565                             or media change case.
    566 
    567   @retval EFI_NO_MEDIA      There is no media.
    568   @retval EFI_MEDIA_CHANGED The media was changed.
    569   @retval others            The default status to return.
    570 **/
    571 EFI_STATUS
    572 ProbeMediaStatus (
    573   IN EFI_DISK_IO_PROTOCOL    *DiskIo,
    574   IN UINT32                  MediaId,
    575   IN EFI_STATUS              DefaultStatus
    576   )
    577 {
    578   EFI_STATUS                 Status;
    579   UINT8                      Buffer[1];
    580 
    581   //
    582   // Read 1 byte from offset 0 to check if the MediaId is still valid.
    583   // The reading operation is synchronious thus it is not worth it to
    584   // allocate a buffer from the pool. The destination buffer for the
    585   // data is in the stack.
    586   //
    587   Status = DiskIo->ReadDisk (DiskIo, MediaId, 0, 1, (VOID*)Buffer);
    588   if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
    589     return Status;
    590   }
    591   return DefaultStatus;
    592 }
    593 
    594 /**
    595   Read by using the Disk IO protocol on the parent device. Lba addresses
    596   must be converted to byte offsets.
    597 
    598   @param  This       Protocol instance pointer.
    599   @param  MediaId    Id of the media, changes every time the media is replaced.
    600   @param  Lba        The starting Logical Block Address to read from
    601   @param  BufferSize Size of Buffer, must be a multiple of device block size.
    602   @param  Buffer     Buffer containing read data
    603 
    604   @retval EFI_SUCCESS           The data was read correctly from the device.
    605   @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.
    606   @retval EFI_NO_MEDIA          There is no media in the device.
    607   @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.
    608   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
    609   @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
    610                                 valid for the device.
    611 
    612 **/
    613 EFI_STATUS
    614 EFIAPI
    615 PartitionReadBlocks (
    616   IN EFI_BLOCK_IO_PROTOCOL  *This,
    617   IN UINT32                 MediaId,
    618   IN EFI_LBA                Lba,
    619   IN UINTN                  BufferSize,
    620   OUT VOID                  *Buffer
    621   )
    622 {
    623   PARTITION_PRIVATE_DATA  *Private;
    624   UINT64                  Offset;
    625 
    626   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
    627 
    628   if (BufferSize % Private->BlockSize != 0) {
    629     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
    630   }
    631 
    632   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
    633   if (Offset + BufferSize > Private->End) {
    634     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
    635   }
    636   //
    637   // Because some kinds of partition have different block size from their parent
    638   // device, we call the Disk IO protocol on the parent device, not the Block IO
    639   // protocol
    640   //
    641   return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
    642 }
    643 
    644 /**
    645   Write by using the Disk IO protocol on the parent device. Lba addresses
    646   must be converted to byte offsets.
    647 
    648   @param[in]  This       Protocol instance pointer.
    649   @param[in]  MediaId    Id of the media, changes every time the media is replaced.
    650   @param[in]  Lba        The starting Logical Block Address to read from
    651   @param[in]  BufferSize Size of Buffer, must be a multiple of device block size.
    652   @param[in]  Buffer     Buffer containing data to be written to device.
    653 
    654   @retval EFI_SUCCESS           The data was written correctly to the device.
    655   @retval EFI_WRITE_PROTECTED   The device can not be written to.
    656   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
    657   @retval EFI_NO_MEDIA          There is no media in the device.
    658   @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
    659   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
    660   @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not
    661                                 valid for the device.
    662 
    663 **/
    664 EFI_STATUS
    665 EFIAPI
    666 PartitionWriteBlocks (
    667   IN EFI_BLOCK_IO_PROTOCOL  *This,
    668   IN UINT32                 MediaId,
    669   IN EFI_LBA                Lba,
    670   IN UINTN                  BufferSize,
    671   IN VOID                  *Buffer
    672   )
    673 {
    674   PARTITION_PRIVATE_DATA  *Private;
    675   UINT64                  Offset;
    676 
    677   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
    678 
    679   if (BufferSize % Private->BlockSize != 0) {
    680     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
    681   }
    682 
    683   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
    684   if (Offset + BufferSize > Private->End) {
    685     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
    686   }
    687   //
    688   // Because some kinds of partition have different block size from their parent
    689   // device, we call the Disk IO protocol on the parent device, not the Block IO
    690   // protocol
    691   //
    692   return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
    693 }
    694 
    695 
    696 /**
    697   Flush the parent Block Device.
    698 
    699   @param  This              Protocol instance pointer.
    700 
    701   @retval EFI_SUCCESS       All outstanding data was written to the device
    702   @retval EFI_DEVICE_ERROR  The device reported an error while writting back the data
    703   @retval EFI_NO_MEDIA      There is no media in the device.
    704 
    705 **/
    706 EFI_STATUS
    707 EFIAPI
    708 PartitionFlushBlocks (
    709   IN EFI_BLOCK_IO_PROTOCOL  *This
    710   )
    711 {
    712   PARTITION_PRIVATE_DATA  *Private;
    713 
    714   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
    715 
    716   return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);
    717 }
    718 
    719 /**
    720   Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
    721   for no media or media change case. Otherwise DefaultStatus is returned.
    722 
    723   @param DiskIo2            Pointer to the DiskIo2 instance.
    724   @param MediaId            Id of the media, changes every time the media is replaced.
    725   @param DefaultStatus      The default status to return when it's not the no media
    726                             or media change case.
    727 
    728   @retval EFI_NO_MEDIA      There is no media.
    729   @retval EFI_MEDIA_CHANGED The media was changed.
    730   @retval others            The default status to return.
    731 **/
    732 EFI_STATUS
    733 ProbeMediaStatusEx (
    734   IN EFI_DISK_IO2_PROTOCOL   *DiskIo2,
    735   IN UINT32                  MediaId,
    736   IN EFI_STATUS              DefaultStatus
    737   )
    738 {
    739   EFI_STATUS                 Status;
    740 
    741   //
    742   // Read 1 byte from offset 0 but passing NULL as buffer pointer
    743   //
    744   Status = DiskIo2->ReadDiskEx (DiskIo2, MediaId, 0, NULL, 1, NULL);
    745   if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
    746     return Status;
    747   }
    748   return DefaultStatus;
    749 }
    750 
    751 /**
    752   Reset the Block Device throught Block I/O2 protocol.
    753 
    754   @param  This                 Protocol instance pointer.
    755   @param  ExtendedVerification Driver may perform diagnostics on reset.
    756 
    757   @retval EFI_SUCCESS          The device was reset.
    758   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
    759                                not be reset.
    760 
    761 **/
    762 EFI_STATUS
    763 EFIAPI
    764 PartitionResetEx (
    765   IN EFI_BLOCK_IO2_PROTOCOL *This,
    766   IN BOOLEAN                ExtendedVerification
    767   )
    768 {
    769   PARTITION_PRIVATE_DATA  *Private;
    770 
    771   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
    772 
    773   return Private->ParentBlockIo2->Reset (
    774                                     Private->ParentBlockIo2,
    775                                     ExtendedVerification
    776                                     );
    777 }
    778 
    779 /**
    780   The general callback for the DiskIo2 interfaces.
    781   @param  Event                 Event whose notification function is being invoked.
    782   @param  Context               The pointer to the notification function's context,
    783                                 which points to the PARTITION_ACCESS_TASK instance.
    784 **/
    785 VOID
    786 EFIAPI
    787 PartitionOnAccessComplete (
    788   IN EFI_EVENT                 Event,
    789   IN VOID                      *Context
    790   )
    791 {
    792   PARTITION_ACCESS_TASK   *Task;
    793 
    794   Task = (PARTITION_ACCESS_TASK *) Context;
    795 
    796   gBS->CloseEvent (Event);
    797 
    798   Task->BlockIo2Token->TransactionStatus = Task->DiskIo2Token.TransactionStatus;
    799   gBS->SignalEvent (Task->BlockIo2Token->Event);
    800 
    801   FreePool (Task);
    802 }
    803 
    804 /**
    805   Create a new PARTITION_ACCESS_TASK instance.
    806 
    807   @param  Token  Pointer to the EFI_BLOCK_IO2_TOKEN.
    808 
    809   @return Pointer to the created PARTITION_ACCESS_TASK instance or NULL upon failure.
    810 **/
    811 PARTITION_ACCESS_TASK *
    812 PartitionCreateAccessTask (
    813   IN EFI_BLOCK_IO2_TOKEN    *Token
    814   )
    815 {
    816   EFI_STATUS                Status;
    817   PARTITION_ACCESS_TASK     *Task;
    818 
    819   Task = AllocatePool (sizeof (*Task));
    820   if (Task == NULL) {
    821     return NULL;
    822   }
    823 
    824   Status = gBS->CreateEvent (
    825                   EVT_NOTIFY_SIGNAL,
    826                   TPL_NOTIFY,
    827                   PartitionOnAccessComplete,
    828                   Task,
    829                   &Task->DiskIo2Token.Event
    830                   );
    831   if (EFI_ERROR (Status)) {
    832     FreePool (Task);
    833     return NULL;
    834   }
    835 
    836   Task->BlockIo2Token = Token;
    837 
    838   return Task;
    839 }
    840 
    841 /**
    842   Read BufferSize bytes from Lba into Buffer.
    843 
    844   This function reads the requested number of blocks from the device. All the
    845   blocks are read, or an error is returned.
    846   If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
    847   non-blocking I/O is being used, the Event associated with this request will
    848   not be signaled.
    849 
    850   @param[in]       This       Indicates a pointer to the calling context.
    851   @param[in]       MediaId    Id of the media, changes every time the media is
    852                               replaced.
    853   @param[in]       Lba        The starting Logical Block Address to read from.
    854   @param[in, out]  Token	    A pointer to the token associated with the transaction.
    855   @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.
    856   @param[out]      Buffer     A pointer to the destination buffer for the data. The
    857                               caller is responsible for either having implicit or
    858                               explicit ownership of the buffer.
    859 
    860   @retval EFI_SUCCESS           The read request was queued if Token->Event is
    861                                 not NULL.The data was read correctly from the
    862                                 device if the Token->Event is NULL.
    863   @retval EFI_DEVICE_ERROR      The device reported an error while performing
    864                                 the read.
    865   @retval EFI_NO_MEDIA          There is no media in the device.
    866   @retval EFI_MEDIA_CHANGED     The MediaId is not for the current media.
    867   @retval EFI_BAD_BUFFER_SIZE   The BufferSize parameter is not a multiple of the
    868                                 intrinsic block size of the device.
    869   @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
    870                                 or the buffer is not on proper alignment.
    871   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack
    872                                 of resources.
    873 **/
    874 EFI_STATUS
    875 EFIAPI
    876 PartitionReadBlocksEx (
    877   IN     EFI_BLOCK_IO2_PROTOCOL *This,
    878   IN     UINT32                 MediaId,
    879   IN     EFI_LBA                Lba,
    880   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
    881   IN     UINTN                  BufferSize,
    882   OUT    VOID                   *Buffer
    883   )
    884 {
    885   EFI_STATUS              Status;
    886   PARTITION_PRIVATE_DATA  *Private;
    887   UINT64                  Offset;
    888   PARTITION_ACCESS_TASK   *Task;
    889 
    890   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
    891 
    892   if (BufferSize % Private->BlockSize != 0) {
    893     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
    894   }
    895 
    896   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
    897   if (Offset + BufferSize > Private->End) {
    898     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
    899   }
    900 
    901   if ((Token != NULL) && (Token->Event != NULL)) {
    902     Task = PartitionCreateAccessTask (Token);
    903     if (Task == NULL) {
    904       return EFI_OUT_OF_RESOURCES;
    905     }
    906 
    907     Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
    908     if (EFI_ERROR (Status)) {
    909       gBS->CloseEvent (Task->DiskIo2Token.Event);
    910       FreePool (Task);
    911     }
    912   } else {
    913     Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
    914   }
    915 
    916   return Status;
    917 }
    918 
    919 /**
    920   Write BufferSize bytes from Lba into Buffer.
    921 
    922   This function writes the requested number of blocks to the device. All blocks
    923   are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
    924   EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
    925   being used, the Event associated with this request will not be signaled.
    926 
    927   @param[in]       This       Indicates a pointer to the calling context.
    928   @param[in]       MediaId    The media ID that the write request is for.
    929   @param[in]       Lba        The starting logical block address to be written. The
    930                               caller is responsible for writing to only legitimate
    931                               locations.
    932   @param[in, out]  Token      A pointer to the token associated with the transaction.
    933   @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.
    934   @param[in]       Buffer     A pointer to the source buffer for the data.
    935 
    936   @retval EFI_SUCCESS           The write request was queued if Event is not NULL.
    937                                 The data was written correctly to the device if
    938                                 the Event is NULL.
    939   @retval EFI_WRITE_PROTECTED   The device can not be written to.
    940   @retval EFI_NO_MEDIA          There is no media in the device.
    941   @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
    942   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
    943   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
    944   @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
    945                                 or the buffer is not on proper alignment.
    946   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack
    947                                 of resources.
    948 
    949 **/
    950 EFI_STATUS
    951 EFIAPI
    952 PartitionWriteBlocksEx (
    953   IN     EFI_BLOCK_IO2_PROTOCOL *This,
    954   IN     UINT32                 MediaId,
    955   IN     EFI_LBA                Lba,
    956   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
    957   IN     UINTN                  BufferSize,
    958   IN     VOID                   *Buffer
    959   )
    960 {
    961   EFI_STATUS              Status;
    962   PARTITION_PRIVATE_DATA  *Private;
    963   UINT64                  Offset;
    964   PARTITION_ACCESS_TASK   *Task;
    965 
    966   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
    967 
    968   if (BufferSize % Private->BlockSize != 0) {
    969     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
    970   }
    971 
    972   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
    973   if (Offset + BufferSize > Private->End) {
    974     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
    975   }
    976 
    977   if ((Token != NULL) && (Token->Event != NULL)) {
    978     Task = PartitionCreateAccessTask (Token);
    979     if (Task == NULL) {
    980       return EFI_OUT_OF_RESOURCES;
    981     }
    982 
    983     Status =  Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
    984     if (EFI_ERROR (Status)) {
    985       gBS->CloseEvent (Task->DiskIo2Token.Event);
    986       FreePool (Task);
    987     }
    988   } else {
    989     Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
    990   }
    991   return Status;
    992 }
    993 
    994 /**
    995   Flush the Block Device.
    996 
    997   If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
    998   is returned and non-blocking I/O is being used, the Event associated with
    999   this request will not be signaled.
   1000 
   1001   @param[in]      This     Indicates a pointer to the calling context.
   1002   @param[in, out] Token    A pointer to the token associated with the transaction
   1003 
   1004   @retval EFI_SUCCESS          The flush request was queued if Event is not NULL.
   1005                                All outstanding data was written correctly to the
   1006                                device if the Event is NULL.
   1007   @retval EFI_DEVICE_ERROR     The device reported an error while writting back
   1008                                the data.
   1009   @retval EFI_WRITE_PROTECTED  The device cannot be written to.
   1010   @retval EFI_NO_MEDIA         There is no media in the device.
   1011   @retval EFI_MEDIA_CHANGED    The MediaId is not for the current media.
   1012   @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
   1013                                of resources.
   1014 
   1015 **/
   1016 EFI_STATUS
   1017 EFIAPI
   1018 PartitionFlushBlocksEx (
   1019   IN     EFI_BLOCK_IO2_PROTOCOL *This,
   1020   IN OUT EFI_BLOCK_IO2_TOKEN    *Token
   1021   )
   1022 {
   1023   EFI_STATUS              Status;
   1024   PARTITION_PRIVATE_DATA  *Private;
   1025   PARTITION_ACCESS_TASK   *Task;
   1026 
   1027   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
   1028 
   1029   if ((Token != NULL) && (Token->Event != NULL)) {
   1030     Task = PartitionCreateAccessTask (Token);
   1031     if (Task == NULL) {
   1032       return EFI_OUT_OF_RESOURCES;
   1033     }
   1034 
   1035     Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, &Task->DiskIo2Token);
   1036     if (EFI_ERROR (Status)) {
   1037       gBS->CloseEvent (Task->DiskIo2Token.Event);
   1038       FreePool (Task);
   1039     }
   1040   } else {
   1041     Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, NULL);
   1042   }
   1043   return Status;
   1044 }
   1045 
   1046 
   1047 /**
   1048   Create a child handle for a logical block device that represents the
   1049   bytes Start to End of the Parent Block IO device.
   1050 
   1051   @param[in]  This              Protocol instance pointer.
   1052   @param[in]  ParentHandle      Parent Handle for new child.
   1053   @param[in]  ParentDiskIo      Parent DiskIo interface.
   1054   @param[in]  ParentDiskIo2     Parent DiskIo2 interface.
   1055   @param[in]  ParentBlockIo     Parent BlockIo interface.
   1056   @param[in]  ParentBlockIo2    Parent BlockIo2 interface.
   1057   @param[in]  ParentDevicePath  Parent Device Path.
   1058   @param[in]  DevicePathNode    Child Device Path node.
   1059   @param[in]  Start             Start Block.
   1060   @param[in]  End               End Block.
   1061   @param[in]  BlockSize         Child block size.
   1062   @param[in]  InstallEspGuid    Flag to install EFI System Partition GUID on handle.
   1063 
   1064   @retval EFI_SUCCESS       A child handle was added.
   1065   @retval other             A child handle was not added.
   1066 
   1067 **/
   1068 EFI_STATUS
   1069 PartitionInstallChildHandle (
   1070   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
   1071   IN  EFI_HANDLE                   ParentHandle,
   1072   IN  EFI_DISK_IO_PROTOCOL         *ParentDiskIo,
   1073   IN  EFI_DISK_IO2_PROTOCOL        *ParentDiskIo2,
   1074   IN  EFI_BLOCK_IO_PROTOCOL        *ParentBlockIo,
   1075   IN  EFI_BLOCK_IO2_PROTOCOL       *ParentBlockIo2,
   1076   IN  EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,
   1077   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
   1078   IN  EFI_LBA                      Start,
   1079   IN  EFI_LBA                      End,
   1080   IN  UINT32                       BlockSize,
   1081   IN  BOOLEAN                      InstallEspGuid
   1082   )
   1083 {
   1084   EFI_STATUS              Status;
   1085   PARTITION_PRIVATE_DATA  *Private;
   1086 
   1087   Status  = EFI_SUCCESS;
   1088   Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));
   1089   if (Private == NULL) {
   1090     return EFI_OUT_OF_RESOURCES;
   1091   }
   1092 
   1093   Private->Signature        = PARTITION_PRIVATE_DATA_SIGNATURE;
   1094 
   1095   Private->Start            = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);
   1096   Private->End              = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);
   1097 
   1098   Private->BlockSize        = BlockSize;
   1099   Private->ParentBlockIo    = ParentBlockIo;
   1100   Private->ParentBlockIo2   = ParentBlockIo2;
   1101   Private->DiskIo           = ParentDiskIo;
   1102   Private->DiskIo2          = ParentDiskIo2;
   1103 
   1104   //
   1105   // Set the BlockIO into Private Data.
   1106   //
   1107   Private->BlockIo.Revision = ParentBlockIo->Revision;
   1108 
   1109   Private->BlockIo.Media    = &Private->Media;
   1110   CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));
   1111 
   1112   Private->BlockIo.Reset        = PartitionReset;
   1113   Private->BlockIo.ReadBlocks   = PartitionReadBlocks;
   1114   Private->BlockIo.WriteBlocks  = PartitionWriteBlocks;
   1115   Private->BlockIo.FlushBlocks  = PartitionFlushBlocks;
   1116 
   1117   //
   1118   // Set the BlockIO2 into Private Data.
   1119   //
   1120   if (Private->DiskIo2 != NULL) {
   1121     ASSERT (Private->ParentBlockIo2 != NULL);
   1122     Private->BlockIo2.Media    = &Private->Media2;
   1123     CopyMem (Private->BlockIo2.Media, ParentBlockIo2->Media, sizeof (EFI_BLOCK_IO_MEDIA));
   1124 
   1125     Private->BlockIo2.Reset          = PartitionResetEx;
   1126     Private->BlockIo2.ReadBlocksEx   = PartitionReadBlocksEx;
   1127     Private->BlockIo2.WriteBlocksEx  = PartitionWriteBlocksEx;
   1128     Private->BlockIo2.FlushBlocksEx  = PartitionFlushBlocksEx;
   1129   }
   1130 
   1131   Private->Media.IoAlign   = 0;
   1132   Private->Media.LogicalPartition = TRUE;
   1133   Private->Media.LastBlock = DivU64x32 (
   1134                                MultU64x32 (
   1135                                  End - Start + 1,
   1136                                  ParentBlockIo->Media->BlockSize
   1137                                  ),
   1138                                 BlockSize
   1139                                ) - 1;
   1140 
   1141   Private->Media.BlockSize = (UINT32) BlockSize;
   1142 
   1143   Private->Media2.IoAlign   = 0;
   1144   Private->Media2.LogicalPartition = TRUE;
   1145   Private->Media2.LastBlock = Private->Media.LastBlock;
   1146   Private->Media2.BlockSize = (UINT32) BlockSize;
   1147 
   1148   //
   1149   // Per UEFI Spec, LowestAlignedLba, LogicalBlocksPerPhysicalBlock and OptimalTransferLengthGranularity must be 0
   1150   //  for logical partitions.
   1151   //
   1152   if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION2) {
   1153     Private->Media.LowestAlignedLba               = 0;
   1154     Private->Media.LogicalBlocksPerPhysicalBlock  = 0;
   1155     Private->Media2.LowestAlignedLba              = 0;
   1156     Private->Media2.LogicalBlocksPerPhysicalBlock = 0;
   1157     if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION3) {
   1158       Private->Media.OptimalTransferLengthGranularity  = 0;
   1159       Private->Media2.OptimalTransferLengthGranularity = 0;
   1160     }
   1161   }
   1162 
   1163   Private->DevicePath     = AppendDevicePathNode (ParentDevicePath, DevicePathNode);
   1164 
   1165   if (Private->DevicePath == NULL) {
   1166     FreePool (Private);
   1167     return EFI_OUT_OF_RESOURCES;
   1168   }
   1169 
   1170   if (InstallEspGuid) {
   1171     Private->EspGuid = &gEfiPartTypeSystemPartGuid;
   1172   } else {
   1173     //
   1174     // If NULL InstallMultipleProtocolInterfaces will ignore it.
   1175     //
   1176     Private->EspGuid = NULL;
   1177   }
   1178 
   1179   //
   1180   // Create the new handle.
   1181   //
   1182   Private->Handle = NULL;
   1183   if (Private->DiskIo2 != NULL) {
   1184     Status = gBS->InstallMultipleProtocolInterfaces (
   1185                     &Private->Handle,
   1186                     &gEfiDevicePathProtocolGuid,
   1187                     Private->DevicePath,
   1188                     &gEfiBlockIoProtocolGuid,
   1189                     &Private->BlockIo,
   1190                     &gEfiBlockIo2ProtocolGuid,
   1191                     &Private->BlockIo2,
   1192                     Private->EspGuid,
   1193                     NULL,
   1194                     NULL
   1195                     );
   1196   } else {
   1197     Status = gBS->InstallMultipleProtocolInterfaces (
   1198                     &Private->Handle,
   1199                     &gEfiDevicePathProtocolGuid,
   1200                     Private->DevicePath,
   1201                     &gEfiBlockIoProtocolGuid,
   1202                     &Private->BlockIo,
   1203                     Private->EspGuid,
   1204                     NULL,
   1205                     NULL
   1206                     );
   1207   }
   1208 
   1209   if (!EFI_ERROR (Status)) {
   1210     //
   1211     // Open the Parent Handle for the child
   1212     //
   1213     Status = gBS->OpenProtocol (
   1214                     ParentHandle,
   1215                     &gEfiDiskIoProtocolGuid,
   1216                     (VOID **) &ParentDiskIo,
   1217                     This->DriverBindingHandle,
   1218                     Private->Handle,
   1219                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
   1220                     );
   1221   } else {
   1222     FreePool (Private->DevicePath);
   1223     FreePool (Private);
   1224   }
   1225 
   1226   return Status;
   1227 }
   1228 
   1229 
   1230 /**
   1231   The user Entry Point for module Partition. The user code starts with this function.
   1232 
   1233   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
   1234   @param[in] SystemTable    A pointer to the EFI System Table.
   1235 
   1236   @retval EFI_SUCCESS       The entry point is executed successfully.
   1237   @retval other             Some error occurs when executing this entry point.
   1238 
   1239 **/
   1240 EFI_STATUS
   1241 EFIAPI
   1242 InitializePartition (
   1243   IN EFI_HANDLE           ImageHandle,
   1244   IN EFI_SYSTEM_TABLE     *SystemTable
   1245   )
   1246 {
   1247   EFI_STATUS              Status;
   1248 
   1249   //
   1250   // Install driver model protocol(s).
   1251   //
   1252   Status = EfiLibInstallDriverBindingComponentName2 (
   1253              ImageHandle,
   1254              SystemTable,
   1255              &gPartitionDriverBinding,
   1256              ImageHandle,
   1257              &gPartitionComponentName,
   1258              &gPartitionComponentName2
   1259              );
   1260   ASSERT_EFI_ERROR (Status);
   1261 
   1262 
   1263   return Status;
   1264 }
   1265 
   1266