]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Disk/Partition/Dxe/Partition.c
add modules DiskIo, Partition and SecurityStub.
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / Partition / Dxe / Partition.c
diff --git a/MdeModulePkg/Universal/Disk/Partition/Dxe/Partition.c b/MdeModulePkg/Universal/Disk/Partition/Dxe/Partition.c
new file mode 100644 (file)
index 0000000..63e771e
--- /dev/null
@@ -0,0 +1,706 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  Partition.c\r
+\r
+Abstract:\r
+\r
+  Partition driver that produces logical BlockIo devices from a physical\r
+  BlockIo device. The logical BlockIo devices are based on the format\r
+  of the raw block devices media. Currently "El Torito CD-ROM", Legacy\r
+  MBR, and GPT partition schemes are supported.\r
+\r
+--*/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "Partition.h"\r
+\r
+//\r
+// Partition Driver Global Variables\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {\r
+  PartitionDriverBindingSupported,\r
+  PartitionDriverBindingStart,\r
+  PartitionDriverBindingStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+STATIC \r
+PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {\r
+  PartitionInstallGptChildHandles,\r
+  PartitionInstallElToritoChildHandles,\r
+  PartitionInstallMbrChildHandles,\r
+  NULL\r
+};\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PartitionDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
+    than contains a BlockIo and DiskIo protocol can be supported.\r
+\r
+  Arguments:\r
+    This                - Protocol instance pointer.\r
+    ControllerHandle    - Handle of device to test\r
+    RemainingDevicePath - Not used\r
+\r
+  Returns:\r
+    EFI_SUCCESS         - This driver supports this device\r
+    EFI_ALREADY_STARTED - This driver is already running on this device\r
+    EFI_UNSUPPORTED     - This driver does not support this device\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;\r
+  EFI_DISK_IO_PROTOCOL      *DiskIo;\r
+  EFI_DEV_PATH              *Node;\r
+\r
+  if (RemainingDevicePath != NULL) {\r
+    Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
+    if (Node->DevPath.Type != MEDIA_DEVICE_PATH ||\r
+        Node->DevPath.SubType != MEDIA_HARDDRIVE_DP ||\r
+        DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)\r
+        ) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+  //\r
+  // Open the IO Abstraction(s) needed to perform the supported test\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Close the I/O Abstraction(s) used to perform the supported test\r
+  //\r
+  gBS->CloseProtocol (\r
+        ControllerHandle,\r
+        &gEfiDevicePathProtocolGuid,\r
+        This->DriverBindingHandle,\r
+        ControllerHandle\r
+        );\r
+\r
+  //\r
+  // Open the IO Abstraction(s) needed to perform the supported test\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiDiskIoProtocolGuid,\r
+                  (VOID **) &DiskIo,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Close the I/O Abstraction(s) used to perform the supported test\r
+  //\r
+  gBS->CloseProtocol (\r
+        ControllerHandle,\r
+        &gEfiDiskIoProtocolGuid,\r
+        This->DriverBindingHandle,\r
+        ControllerHandle\r
+        );\r
+\r
+  //\r
+  // Open the IO Abstraction(s) needed to perform the supported test\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiBlockIoProtocolGuid,\r
+                  NULL,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PartitionDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Start this driver on ControllerHandle by opening a Block IO and Disk IO\r
+    protocol, reading Device Path, and creating a child handle with a\r
+    Disk IO and device path protocol.\r
+\r
+  Arguments:\r
+    This                - Protocol instance pointer.\r
+    ControllerHandle    - Handle of device to bind driver to\r
+    RemainingDevicePath - Not used\r
+\r
+  Returns:\r
+    EFI_SUCCESS         - This driver is added to DeviceHandle\r
+    EFI_ALREADY_STARTED - This driver is already running on DeviceHandle\r
+    other               - This driver does not support this device\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_STATUS                OpenStatus;\r
+  EFI_BLOCK_IO_PROTOCOL     *BlockIo;\r
+  EFI_DISK_IO_PROTOCOL      *DiskIo;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;\r
+  PARTITION_DETECT_ROUTINE  *Routine;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiBlockIoProtocolGuid,\r
+                  (VOID **) &BlockIo,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Get the Device Path Protocol on ControllerHandle's handle\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiDiskIoProtocolGuid,\r
+                  (VOID **) &DiskIo,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    gBS->CloseProtocol (\r
+          ControllerHandle,\r
+          &gEfiDevicePathProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+    return Status;\r
+  }\r
+\r
+  OpenStatus = Status;\r
+\r
+  //\r
+  // If no media is present, do nothing here.\r
+  //\r
+  Status = EFI_UNSUPPORTED;\r
+  if (BlockIo->Media->MediaPresent) {\r
+    //\r
+    // Try for GPT, then El Torito, and then legacy MBR partition types. If the\r
+    // media supports a given partition type install child handles to represent\r
+    // the partitions described by the media.\r
+    //\r
+    Routine = &mPartitionDetectRoutineTable[0];\r
+    while (*Routine != NULL) {\r
+      Status = (*Routine) (\r
+                   This,\r
+                   ControllerHandle,\r
+                   DiskIo,\r
+                   BlockIo,\r
+                   ParentDevicePath\r
+                   );\r
+      if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED) {\r
+        break;\r
+      }\r
+      Routine++;\r
+    }\r
+  }\r
+  //\r
+  // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),\r
+  // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the\r
+  // driver. So don't try to close them. Otherwise, we will break the dependency\r
+  // between the controller and the driver set up before.\r
+  //\r
+  if (EFI_ERROR (Status) && !EFI_ERROR (OpenStatus) && Status != EFI_MEDIA_CHANGED) {\r
+    gBS->CloseProtocol (\r
+          ControllerHandle,\r
+          &gEfiDiskIoProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+\r
+    gBS->CloseProtocol (\r
+          ControllerHandle,\r
+          &gEfiDevicePathProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PartitionDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
+  IN  EFI_HANDLE                    ControllerHandle,\r
+  IN  UINTN                         NumberOfChildren,\r
+  IN  EFI_HANDLE                    *ChildHandleBuffer\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Stop this driver on ControllerHandle. Support stoping any child handles\r
+    created by this driver.\r
+\r
+  Arguments:\r
+    This              - Protocol instance pointer.\r
+    ControllerHandle  - Handle of device to stop driver on\r
+    NumberOfChildren  - Number of Children in the ChildHandleBuffer\r
+    ChildHandleBuffer - List of handles for the children we need to stop.\r
+\r
+  Returns:\r
+    EFI_SUCCESS         - This driver is removed DeviceHandle\r
+    EFI_DEVICE_ERROR    - This driver was not removed from this device\r
+\r
+--*/\r
+{\r
+  EFI_STATUS              Status;\r
+  UINTN                   Index;\r
+  EFI_BLOCK_IO_PROTOCOL   *BlockIo;\r
+  BOOLEAN                 AllChildrenStopped;\r
+  PARTITION_PRIVATE_DATA  *Private;\r
+  EFI_DISK_IO_PROTOCOL    *DiskIo;\r
+\r
+  if (NumberOfChildren == 0) {\r
+    //\r
+    // Close the bus driver\r
+    //\r
+    gBS->CloseProtocol (\r
+          ControllerHandle,\r
+          &gEfiDiskIoProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+\r
+    gBS->CloseProtocol (\r
+          ControllerHandle,\r
+          &gEfiDevicePathProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  AllChildrenStopped = TRUE;\r
+  for (Index = 0; Index < NumberOfChildren; Index++) {\r
+    Status = gBS->OpenProtocol (\r
+                    ChildHandleBuffer[Index],\r
+                    &gEfiBlockIoProtocolGuid,\r
+                    (VOID **) &BlockIo,\r
+                    This->DriverBindingHandle,\r
+                    ControllerHandle,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+\r
+      Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);\r
+\r
+      //\r
+      // All Software protocols have be freed from the handle so remove it.\r
+      //\r
+      BlockIo->FlushBlocks (BlockIo);\r
+\r
+      Status = gBS->CloseProtocol (\r
+                      ControllerHandle,\r
+                      &gEfiDiskIoProtocolGuid,\r
+                      This->DriverBindingHandle,\r
+                      ChildHandleBuffer[Index]\r
+                      );\r
+\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      ChildHandleBuffer[Index],\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      Private->DevicePath,\r
+                      &gEfiBlockIoProtocolGuid,\r
+                      &Private->BlockIo,\r
+                      Private->EspGuid,\r
+                      NULL,\r
+                      NULL\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        gBS->OpenProtocol (\r
+              ControllerHandle,\r
+              &gEfiDiskIoProtocolGuid,\r
+              (VOID **) &DiskIo,\r
+              This->DriverBindingHandle,\r
+              ChildHandleBuffer[Index],\r
+              EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+              );\r
+      } else {\r
+        FreePool (Private->DevicePath);\r
+        FreePool (Private);\r
+      }\r
+\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      AllChildrenStopped = FALSE;\r
+    }\r
+  }\r
+\r
+  if (!AllChildrenStopped) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+PartitionReset (\r
+  IN EFI_BLOCK_IO_PROTOCOL  *This,\r
+  IN BOOLEAN                ExtendedVerification\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reset the parent Block Device.\r
+\r
+  Arguments:\r
+    This                 - Protocol instance pointer.\r
+    ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The device was reset.\r
+    EFI_DEVICE_ERROR      - The device is not functioning properly and could\r
+                            not be reset.\r
+\r
+--*/\r
+{\r
+  PARTITION_PRIVATE_DATA  *Private;\r
+\r
+  Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
+\r
+  return Private->ParentBlockIo->Reset (\r
+                                  Private->ParentBlockIo,\r
+                                  ExtendedVerification\r
+                                  );\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+PartitionReadBlocks (\r
+  IN EFI_BLOCK_IO_PROTOCOL  *This,\r
+  IN UINT32                 MediaId,\r
+  IN EFI_LBA                Lba,\r
+  IN UINTN                  BufferSize,\r
+  OUT VOID                  *Buffer\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Read by using the Disk IO protocol on the parent device. Lba addresses\r
+    must be converted to byte offsets.\r
+\r
+  Arguments:\r
+    This       - Protocol instance pointer.\r
+    MediaId    - Id of the media, changes every time the media is replaced.\r
+    Lba        - The starting Logical Block Address to read from\r
+    BufferSize - Size of Buffer, must be a multiple of device block size.\r
+    Buffer     - Buffer containing read data\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The data was read correctly from the device.\r
+    EFI_DEVICE_ERROR      - The device reported an error while performing the read.\r
+    EFI_NO_MEDIA          - There is no media in the device.\r
+    EFI_MEDIA_CHANGED     - The MediaId does not matched the current device.\r
+    EFI_BAD_BUFFER_SIZE   - The Buffer was not a multiple of the block size of the\r
+                            device.\r
+    EFI_INVALID_PARAMETER - The read request contains device addresses that are not\r
+                            valid for the device.\r
+\r
+--*/\r
+{\r
+  PARTITION_PRIVATE_DATA  *Private;\r
+  UINT64                  Offset;\r
+\r
+  Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
+\r
+  if (BufferSize % Private->BlockSize != 0) {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
+  if (Offset + BufferSize > Private->End) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Because some kinds of partition have different block size from their parent\r
+  // device, we call the Disk IO protocol on the parent device, not the Block IO\r
+  // protocol\r
+  //\r
+  return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+PartitionWriteBlocks (\r
+  IN EFI_BLOCK_IO_PROTOCOL  *This,\r
+  IN UINT32                 MediaId,\r
+  IN EFI_LBA                Lba,\r
+  IN UINTN                  BufferSize,\r
+  OUT VOID                  *Buffer\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Write by using the Disk IO protocol on the parent device. Lba addresses\r
+    must be converted to byte offsets.\r
+\r
+  Arguments:\r
+    This       - Protocol instance pointer.\r
+    MediaId    - Id of the media, changes every time the media is replaced.\r
+    Lba        - The starting Logical Block Address to read from\r
+    BufferSize - Size of Buffer, must be a multiple of device block size.\r
+    Buffer     - Buffer containing read data\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The data was written correctly to the device.\r
+    EFI_WRITE_PROTECTED   - The device can not be written to.\r
+    EFI_DEVICE_ERROR      - The device reported an error while performing the write.\r
+    EFI_NO_MEDIA          - There is no media in the device.\r
+    EFI_MEDIA_CHNAGED     - The MediaId does not matched the current device.\r
+    EFI_BAD_BUFFER_SIZE   - The Buffer was not a multiple of the block size of the\r
+                            device.\r
+    EFI_INVALID_PARAMETER - The write request contains a LBA that is not\r
+                            valid for the device.\r
+\r
+--*/\r
+{\r
+  PARTITION_PRIVATE_DATA  *Private;\r
+  UINT64                  Offset;\r
+\r
+  Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
+\r
+  if (BufferSize % Private->BlockSize != 0) {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
+  if (Offset + BufferSize > Private->End) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Because some kinds of partition have different block size from their parent\r
+  // device, we call the Disk IO protocol on the parent device, not the Block IO\r
+  // protocol\r
+  //\r
+  return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+PartitionFlushBlocks (\r
+  IN EFI_BLOCK_IO_PROTOCOL  *This\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Flush the parent Block Device.\r
+\r
+  Arguments:\r
+    This             - Protocol instance pointer.\r
+\r
+  Returns:\r
+    EFI_SUCCESS      - All outstanding data was written to the device\r
+    EFI_DEVICE_ERROR - The device reported an error while writing back the data\r
+    EFI_NO_MEDIA     - There is no media in the device.\r
+\r
+--*/\r
+{\r
+  PARTITION_PRIVATE_DATA  *Private;\r
+\r
+  Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
+\r
+  return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);\r
+}\r
+\r
+EFI_STATUS\r
+PartitionInstallChildHandle (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   ParentHandle,\r
+  IN  EFI_DISK_IO_PROTOCOL         *ParentDiskIo,\r
+  IN  EFI_BLOCK_IO_PROTOCOL        *ParentBlockIo,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,\r
+  IN  EFI_LBA                      Start,\r
+  IN  EFI_LBA                      End,\r
+  IN  UINT32                       BlockSize,\r
+  IN  BOOLEAN                      InstallEspGuid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Create a child handle for a logical block device that represents the\r
+  bytes Start to End of the Parent Block IO device.\r
+\r
+Arguments:\r
+  This             - Calling context.\r
+  ParentHandle     - Parent Handle for new child\r
+  ParentDiskIo     - Parent DiskIo interface\r
+  ParentBlockIo    - Parent BlockIo interface\r
+  ParentDevicePath - Parent Device Path\r
+  DevicePathNode   - Child Device Path node\r
+  Start            - Start Block\r
+  End              - End Block\r
+  BlockSize        - Child block size\r
+  InstallEspGuid   - Flag to install EFI System Partition GUID on handle\r
+\r
+Returns:\r
+  EFI_SUCCESS - If a child handle was added\r
+  EFI_OUT_OF_RESOURCES  - A child handle was not added\r
+\r
+--*/\r
+{\r
+  EFI_STATUS              Status;\r
+  PARTITION_PRIVATE_DATA  *Private;\r
+\r
+  Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));\r
+  if (Private == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Private->Signature        = PARTITION_PRIVATE_DATA_SIGNATURE;\r
+\r
+  Private->Start            = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);\r
+  Private->End              = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);\r
+\r
+  Private->BlockSize        = BlockSize;\r
+  Private->ParentBlockIo    = ParentBlockIo;\r
+  Private->DiskIo           = ParentDiskIo;\r
+\r
+  Private->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
+\r
+  Private->BlockIo.Media    = &Private->Media;\r
+  CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
+  Private->Media.LogicalPartition = TRUE;\r
+  Private->Media.LastBlock = DivU64x32 (\r
+                               MultU64x32 (\r
+                                 End - Start + 1,\r
+                                 ParentBlockIo->Media->BlockSize\r
+                                 ),\r
+                               BlockSize\r
+                               ) - 1;\r
+\r
+  Private->Media.BlockSize      = (UINT32) BlockSize;\r
+\r
+  Private->BlockIo.Reset        = PartitionReset;\r
+  Private->BlockIo.ReadBlocks   = PartitionReadBlocks;\r
+  Private->BlockIo.WriteBlocks  = PartitionWriteBlocks;\r
+  Private->BlockIo.FlushBlocks  = PartitionFlushBlocks;\r
+\r
+  Private->DevicePath           = AppendDevicePathNode (ParentDevicePath, DevicePathNode);\r
+\r
+  if (Private->DevicePath == NULL) {\r
+    FreePool (Private);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (InstallEspGuid) {\r
+    Private->EspGuid = &gEfiPartTypeSystemPartGuid;\r
+  } else {\r
+    //\r
+    // If NULL InstallMultipleProtocolInterfaces will ignore it.\r
+    //\r
+    Private->EspGuid = NULL;\r
+  }\r
+  //\r
+  // Create the new handle\r
+  //\r
+  Private->Handle = NULL;\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &Private->Handle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  Private->DevicePath,\r
+                  &gEfiBlockIoProtocolGuid,\r
+                  &Private->BlockIo,\r
+                  Private->EspGuid,\r
+                  NULL,\r
+                  NULL\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Open the Parent Handle for the child\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    ParentHandle,\r
+                    &gEfiDiskIoProtocolGuid,\r
+                    (VOID **) &ParentDiskIo,\r
+                    This->DriverBindingHandle,\r
+                    Private->Handle,\r
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                    );\r
+  } else {\r
+    FreePool (Private->DevicePath);\r
+    FreePool (Private);\r
+  }\r
+\r
+  return Status;\r
+}\r