]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
Set the BlockIo.Media.IoAlign to 0 because the BlockIo produced by Partition driver...
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / PartitionDxe / Partition.c
index 401facf4759a9bfd1f664c2fba82f061d72431c6..0a5d3d28f0cc7a580574661a7bbf83c625c064dc 100644 (file)
@@ -4,8 +4,8 @@
   of the raw block devices media. Currently "El Torito CD-ROM", Legacy\r
   MBR, and GPT partition schemes are supported.\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+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
@@ -69,22 +69,35 @@ PartitionDriverBindingSupported (
   EFI_DISK_IO_PROTOCOL      *DiskIo;\r
   EFI_DEV_PATH              *Node;\r
 \r
+  //\r
+  // Check RemainingDevicePath validation\r
+  //\r
   if (RemainingDevicePath != NULL) {\r
-    Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
-    if (Node->DevPath.Type != MEDIA_DEVICE_PATH ||\r
+    //\r
+    // Check if RemainingDevicePath is the End of Device Path Node, \r
+    // if yes, go on checking other conditions\r
+    //\r
+    if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+      //\r
+      // If RemainingDevicePath isn't the End of Device Path Node,\r
+      // check its validation\r
+      //\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
+        DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)) {\r
       return EFI_UNSUPPORTED;\r
+      }\r
     }\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
+                  &gEfiDiskIoProtocolGuid,\r
+                  (VOID **) &DiskIo,\r
                   This->DriverBindingHandle,\r
                   ControllerHandle,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
@@ -101,18 +114,18 @@ PartitionDriverBindingSupported (
   //\r
   gBS->CloseProtocol (\r
          ControllerHandle,\r
-         &gEfiDevicePathProtocolGuid,\r
+         &gEfiDiskIoProtocolGuid,\r
          This->DriverBindingHandle,\r
          ControllerHandle\r
          );\r
 \r
   //\r
-  // Open the IO Abstraction(s) needed to perform the supported test\r
+  // Open the EFI Device Path protocol needed to perform the supported test\r
   //\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
-                  &gEfiDiskIoProtocolGuid,\r
-                  (VOID **) &DiskIo,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
                   This->DriverBindingHandle,\r
                   ControllerHandle,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
@@ -124,12 +137,13 @@ PartitionDriverBindingSupported (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
   //\r
-  // Close the I/O Abstraction(s) used to perform the supported test\r
+  // Close protocol, don't use device path protocol in the Support() function\r
   //\r
   gBS->CloseProtocol (\r
         ControllerHandle,\r
-        &gEfiDiskIoProtocolGuid,\r
+        &gEfiDevicePathProtocolGuid,\r
         This->DriverBindingHandle,\r
         ControllerHandle\r
         );\r
@@ -179,6 +193,23 @@ PartitionDriverBindingStart (
   EFI_DISK_IO_PROTOCOL      *DiskIo;\r
   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;\r
   PARTITION_DETECT_ROUTINE  *Routine;\r
+  BOOLEAN                   MediaPresent;\r
+  EFI_TPL                   OldTpl;\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK); \r
+  //\r
+  // Check RemainingDevicePath validation\r
+  //\r
+  if (RemainingDevicePath != NULL) {\r
+    //\r
+    // Check if RemainingDevicePath is the End of Device Path Node, \r
+    // if yes, return EFI_SUCCESS\r
+    //\r
+    if (IsDevicePathEnd (RemainingDevicePath)) {\r
+      Status = EFI_SUCCESS;\r
+      goto Exit;\r
+    }\r
+  }\r
 \r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
@@ -189,7 +220,7 @@ PartitionDriverBindingStart (
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto Exit;\r
   }\r
   //\r
   // Get the Device Path Protocol on ControllerHandle's handle\r
@@ -203,7 +234,7 @@ PartitionDriverBindingStart (
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
-    return Status;\r
+    goto Exit;\r
   }\r
 \r
   Status = gBS->OpenProtocol (\r
@@ -221,16 +252,18 @@ PartitionDriverBindingStart (
           This->DriverBindingHandle,\r
           ControllerHandle\r
           );\r
-    return Status;\r
+    goto Exit;\r
   }\r
 \r
   OpenStatus = Status;\r
 \r
   //\r
-  // If no media is present, do nothing here.\r
+  // Try to read blocks when there's media or it is removable physical partition.\r
   //\r
-  Status = EFI_UNSUPPORTED;\r
-  if (BlockIo->Media->MediaPresent) {\r
+  Status       = EFI_UNSUPPORTED;\r
+  MediaPresent = BlockIo->Media->MediaPresent;\r
+  if (BlockIo->Media->MediaPresent ||\r
+      (BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition)) {\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
@@ -245,7 +278,7 @@ PartitionDriverBindingStart (
                    BlockIo,\r
                    ParentDevicePath\r
                    );\r
-      if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED) {\r
+      if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED || Status == EFI_NO_MEDIA) {\r
         break;\r
       }\r
       Routine++;\r
@@ -257,7 +290,16 @@ PartitionDriverBindingStart (
   // 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
+  // In the case that when the media changes on a device it will Reinstall the \r
+  // BlockIo interaface. This will cause a call to our Stop(), and a subsequent\r
+  // reentrant call to our Start() successfully. We should leave the device open\r
+  // when this happen. The "media change" case includes either the status is\r
+  // EFI_MEDIA_CHANGED or it is a "media" to "no media" change. \r
+  //  \r
+  if (EFI_ERROR (Status)          &&\r
+      !EFI_ERROR (OpenStatus)     &&\r
+      Status != EFI_MEDIA_CHANGED &&\r
+      !(MediaPresent && Status == EFI_NO_MEDIA)) {\r
     gBS->CloseProtocol (\r
           ControllerHandle,\r
           &gEfiDiskIoProtocolGuid,\r
@@ -273,6 +315,8 @@ PartitionDriverBindingStart (
           );\r
   }\r
 \r
+Exit:\r
+  gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
 \r
@@ -602,8 +646,13 @@ PartitionInstallChildHandle (
   Private->BlockIo.Revision = ParentBlockIo->Revision;\r
 \r
   Private->BlockIo.Media    = &Private->Media;\r
-  CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, SIZE_OF_EFI_BLOCK_IO_MEDIA_REV1);\r
+  CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
   Private->Media.LogicalPartition = TRUE;\r
+\r
+  //\r
+  // Logical BlockIo instance doesn't have IoAlign restriction because it implements block io operation based on DiskIo\r
+  //\r
+  Private->Media.IoAlign   = 0;\r
   Private->Media.LastBlock = DivU64x32 (\r
                                MultU64x32 (\r
                                  End - Start + 1,\r
@@ -612,7 +661,16 @@ PartitionInstallChildHandle (
                                BlockSize\r
                                ) - 1;\r
 \r
-  Private->Media.BlockSize      = (UINT32) BlockSize;\r
+  Private->Media.BlockSize = (UINT32) BlockSize;\r
+\r
+  //\r
+  // Per UEFI Spec, LowestAlignedLba and LogicalBlocksPerPhysicalBlock must be 0\r
+  //  for logical partitions.\r
+  //\r
+  if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION2) {\r
+    Private->BlockIo.Media->LowestAlignedLba              = 0;\r
+    Private->BlockIo.Media->LogicalBlocksPerPhysicalBlock = 0;\r
+  }\r
 \r
   Private->BlockIo.Reset        = PartitionReset;\r
   Private->BlockIo.ReadBlocks   = PartitionReadBlocks;\r