]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/CapsulePei: Optimize the CapsulePei
authorBret Barkelew <Bret.Barkelew@microsoft.com>
Tue, 4 Jun 2019 02:24:02 +0000 (10:24 +0800)
committerHao A Wu <hao.a.wu@intel.com>
Mon, 24 Jun 2019 01:18:31 +0000 (09:18 +0800)
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1853

Code change form Mu project:
https://github.com/microsoft/mu_basecore/blob/release/201903/
MdeModulePkg/Universal/CapsulePei/UefiCapsule.c#L801

Separate the capsule check function from GetCapsuleDescriptors
to AreCapsulesStaged. The original one is unclear.

Avoid querying the capsule variable twice. Use a fixed array
to cache the SG list during count the number of SG list. Then
allocate memory buffer to save the SG list from array.

Using MemoryAllocationLib instead of memory function in Pei
services.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Michael Turner <Michael.Turner@microsoft.com>
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Signed-off-by: Zhichao gao <zhichao.gao@intel.com>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
MdeModulePkg/Universal/CapsulePei/Capsule.h
MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
MdeModulePkg/Universal/CapsulePei/UefiCapsule.c

index baf40423afb7b302e8df55fd49768f2cd202503e..3d9cab02c48500eaca5f7f967eb69ea0471ef532 100644 (file)
@@ -30,6 +30,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/PcdLib.h>\r
 #include <Library/ReportStatusCodeLib.h>\r
 #include <Library/DebugAgentLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
 #include <IndustryStandard/PeImage.h>\r
 #include "Common/CommonHeader.h"\r
 \r
index 5d43df30751a30c541bbd5563282e8da9e1ed773..786c41163304c01544fa2f0f782103df6a298f27 100644 (file)
@@ -43,6 +43,7 @@
   BaseLib\r
   HobLib\r
   BaseMemoryLib\r
+  MemoryAllocationLib\r
   PeiServicesLib\r
   PeimEntryPoint\r
   DebugLib\r
index e967599e96a9321b37403bb7db4fdfee8c6a6278..7c8c7a0f451ec2b193b1f8fd5867e448480ed132 100644 (file)
@@ -791,18 +791,84 @@ BuildMemoryResourceDescriptor (
 }\r
 \r
 /**\r
-  Checks for the presence of capsule descriptors.\r
-  Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...\r
-  and save to DescriptorBuffer.\r
+  Check if the capsules are staged.\r
 \r
-  @param DescriptorBuffer        Pointer to the capsule descriptors\r
+  @param UpdateCapsules   A pointer to return the check result.\r
+\r
+  @retval EFI_INVALID_PARAMETER   The parameter is null.\r
+  @retval EFI_SUCCESS             The Capsules are staged.\r
 \r
-  @retval EFI_SUCCESS     a valid capsule is present\r
-  @retval EFI_NOT_FOUND   if a valid capsule is not present\r
 **/\r
 EFI_STATUS\r
-GetCapsuleDescriptors (\r
-  IN EFI_PHYSICAL_ADDRESS     *DescriptorBuffer\r
+EFIAPI\r
+AreCapsulesStaged(\r
+  OUT BOOLEAN     *UpdateCapsules\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             Size;\r
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI   *PPIVariableServices;\r
+  EFI_PHYSICAL_ADDRESS              CapsuleDataPtr64 = 0;\r
+\r
+  if (UpdateCapsules == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a Invalid parameters.  Inputs can't be NULL\n", __FUNCTION__));\r
+    ASSERT (UpdateCapsules != NULL);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *UpdateCapsules = FALSE;\r
+\r
+  Status = PeiServicesLocatePpi(\r
+              &gEfiPeiReadOnlyVariable2PpiGuid,\r
+              0,\r
+              NULL,\r
+              (VOID **)&PPIVariableServices\r
+              );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Failed to find ReadOnlyVariable2PPI\n"));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Check for Update capsule\r
+  //\r
+  Size = sizeof (CapsuleDataPtr64);\r
+  Status = PPIVariableServices->GetVariable (\r
+                                  PPIVariableServices,\r
+                                  EFI_CAPSULE_VARIABLE_NAME,\r
+                                  &gEfiCapsuleVendorGuid,\r
+                                  NULL,\r
+                                  &Size,\r
+                                  (VOID *)&CapsuleDataPtr64\r
+                                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    *UpdateCapsules = TRUE;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+#define MAX_SG_LIST_HEADS (20)\r
+\r
+/**\r
+  Check all the variables for SG list heads and get the count and addresses.\r
+\r
+  @param ListLength               A pointer would return the SG list length.\r
+  @param HeadList                 A ponter to the capsule SG list.\r
+\r
+  @retval EFI_SUCCESS             a valid capsule is present\r
+  @retval EFI_NOT_FOUND           if a valid capsule is not present\r
+  @retval EFI_INVALID_PARAMETER   the input parameter is invalid\r
+  @retval EFI_OUT_OF_RESOURCES    fail to allocate memory\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetScatterGatherHeadEntries(\r
+  OUT UINTN *ListLength,\r
+  OUT EFI_PHYSICAL_ADDRESS **HeadList\r
   )\r
 {\r
   EFI_STATUS                       Status;\r
@@ -815,6 +881,7 @@ GetCapsuleDescriptors (
   CHAR16                           *TempVarName;\r
   EFI_PHYSICAL_ADDRESS             CapsuleDataPtr64;\r
   EFI_PEI_READ_ONLY_VARIABLE2_PPI  *PPIVariableServices;\r
+  EFI_PHYSICAL_ADDRESS             TempList[MAX_SG_LIST_HEADS];\r
 \r
   Index             = 0;\r
   TempVarName       = NULL;\r
@@ -822,87 +889,96 @@ GetCapsuleDescriptors (
   ValidIndex        = 0;\r
   CapsuleDataPtr64  = 0;\r
 \r
+  if ((ListLength == NULL) || (HeadList == NULL)) {\r
+    DEBUG ((DEBUG_ERROR, "%a Invalid parameters.  Inputs can't be NULL\n", __FUNCTION__));\r
+    ASSERT (ListLength != NULL);\r
+    ASSERT (HeadList != NULL);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *ListLength = 0;\r
+  *HeadList = NULL;\r
+\r
   Status = PeiServicesLocatePpi (\r
               &gEfiPeiReadOnlyVariable2PpiGuid,\r
               0,\r
               NULL,\r
-              (VOID **) &PPIVariableServices\r
+              (VOID **)&PPIVariableServices\r
               );\r
-  if (Status == EFI_SUCCESS) {\r
-    StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME);\r
-    TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Failed to find ReadOnlyVariable2PPI\n"));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // setup var name buffer for update capsules\r
+  //\r
+  StrCpyS (CapsuleVarName, sizeof (CapsuleVarName) / sizeof (CHAR16), EFI_CAPSULE_VARIABLE_NAME);\r
+  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
+  while (ValidIndex < MAX_SG_LIST_HEADS) {\r
+    if (Index != 0) {\r
+      UnicodeValueToStringS (\r
+        TempVarName,\r
+        (sizeof (CapsuleVarName) - ((StrLen (CapsuleVarName) + 1) * sizeof (CHAR16))),\r
+        0,\r
+        Index,\r
+        0\r
+        );\r
+    }\r
     Size = sizeof (CapsuleDataPtr64);\r
-    while (1) {\r
-      if (Index == 0) {\r
-        //\r
-        // For the first Capsule Image\r
-        //\r
-        Status = PPIVariableServices->GetVariable (\r
-                                        PPIVariableServices,\r
-                                        CapsuleVarName,\r
-                                        &gEfiCapsuleVendorGuid,\r
-                                        NULL,\r
-                                        &Size,\r
-                                        (VOID *) &CapsuleDataPtr64\r
-                                        );\r
-        if (EFI_ERROR (Status)) {\r
-          DEBUG ((DEBUG_INFO, "Capsule -- capsule variable not set\n"));\r
-          return EFI_NOT_FOUND;\r
-        }\r
-        //\r
-        // We have a chicken/egg situation where the memory init code needs to\r
-        // know the boot mode prior to initializing memory. For this case, our\r
-        // validate function will fail. We can detect if this is the case if blocklist\r
-        // pointer is null. In that case, return success since we know that the\r
-        // variable is set.\r
-        //\r
-        if (DescriptorBuffer == NULL) {\r
-          return EFI_SUCCESS;\r
-        }\r
-      } else {\r
-        UnicodeValueToStringS (\r
-          TempVarName,\r
-          sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),\r
-          0,\r
-          Index,\r
-          0\r
-          );\r
-        Status = PPIVariableServices->GetVariable (\r
-                                        PPIVariableServices,\r
-                                        CapsuleVarName,\r
-                                        &gEfiCapsuleVendorGuid,\r
-                                        NULL,\r
-                                        &Size,\r
-                                        (VOID *) &CapsuleDataPtr64\r
-                                        );\r
-        if (EFI_ERROR (Status)) {\r
-          break;\r
-        }\r
+    Status = PPIVariableServices->GetVariable (\r
+                                    PPIVariableServices,\r
+                                    CapsuleVarName,\r
+                                    &gEfiCapsuleVendorGuid,\r
+                                    NULL,\r
+                                    &Size,\r
+                                    (VOID *)&CapsuleDataPtr64\r
+                                    );\r
 \r
-        //\r
-        // If this BlockList has been linked before, skip this variable\r
-        //\r
-        Flag = FALSE;\r
-        for (TempIndex = 0; TempIndex < ValidIndex; TempIndex++) {\r
-          if (DescriptorBuffer[TempIndex] == CapsuleDataPtr64)  {\r
-            Flag = TRUE;\r
-            break;\r
-          }\r
-        }\r
-        if (Flag) {\r
-          Index ++;\r
-          continue;\r
-        }\r
+    if (EFI_ERROR (Status)) {\r
+      if (Status != EFI_NOT_FOUND) {\r
+        DEBUG ((DEBUG_ERROR, "Unexpected error getting Capsule Update variable.  Status = %r\n"));\r
       }\r
+      break;\r
+    }\r
 \r
-      //\r
-      // Cache BlockList which has been processed\r
-      //\r
-      DescriptorBuffer[ValidIndex++] = CapsuleDataPtr64;\r
-      Index ++;\r
+    //\r
+    // If this BlockList has been linked before, skip this variable\r
+    //\r
+    Flag = FALSE;\r
+    for (TempIndex = 0; TempIndex < ValidIndex; TempIndex++) {\r
+      if (TempList[TempIndex] == CapsuleDataPtr64) {\r
+        Flag = TRUE;\r
+        break;\r
+      }\r
     }\r
+    if (Flag) {\r
+      Index++;\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // add it to the cached list\r
+    //\r
+    TempList[ValidIndex++] = CapsuleDataPtr64;\r
+    Index++;\r
+  }\r
+\r
+  if (ValidIndex == 0) {\r
+    DEBUG ((DEBUG_ERROR, "%a didn't find any SG lists in variables\n", __FUNCTION__));\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
+  *HeadList = AllocateZeroPool ((ValidIndex + 1) * sizeof (EFI_PHYSICAL_ADDRESS));\r
+  if (*HeadList == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "Failed to allocate memory\n"));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  CopyMem (*HeadList, TempList, (ValidIndex) * sizeof (EFI_PHYSICAL_ADDRESS));\r
+  *ListLength = ValidIndex;\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -937,15 +1013,9 @@ CapsuleCoalesce (
   IN OUT UINTN                       *MemorySize\r
   )\r
 {\r
-  UINTN                                Index;\r
-  UINTN                                Size;\r
-  UINTN                                VariableCount;\r
-  CHAR16                               CapsuleVarName[30];\r
-  CHAR16                               *TempVarName;\r
-  EFI_PHYSICAL_ADDRESS                 CapsuleDataPtr64;\r
   EFI_STATUS                           Status;\r
   EFI_BOOT_MODE                        BootMode;\r
-  EFI_PEI_READ_ONLY_VARIABLE2_PPI      *PPIVariableServices;\r
+  UINTN                                ListLength;\r
   EFI_PHYSICAL_ADDRESS                 *VariableArrayAddress;\r
   MEMORY_RESOURCE_DESCRIPTOR           *MemoryResource;\r
 #ifdef MDE_CPU_IA32\r
@@ -955,10 +1025,8 @@ CapsuleCoalesce (
   EFI_CAPSULE_LONG_MODE_BUFFER         LongModeBuffer;\r
 #endif\r
 \r
-  Index                   = 0;\r
-  VariableCount           = 0;\r
-  CapsuleVarName[0]       = 0;\r
-  CapsuleDataPtr64        = 0;\r
+  ListLength = 0;\r
+  VariableArrayAddress = NULL;\r
 \r
   //\r
   // Someone should have already ascertained the boot mode. If it's not\r
@@ -972,74 +1040,11 @@ CapsuleCoalesce (
   }\r
 \r
   //\r
-  // User may set the same ScatterGatherList with several different variables,\r
-  // so cache all ScatterGatherList for check later.\r
+  // Get SG list entries\r
   //\r
-  Status = PeiServicesLocatePpi (\r
-              &gEfiPeiReadOnlyVariable2PpiGuid,\r
-              0,\r
-              NULL,\r
-              (VOID **) &PPIVariableServices\r
-              );\r
+  Status = GetScatterGatherHeadEntries (&ListLength, &VariableArrayAddress);\r
   if (EFI_ERROR (Status)) {\r
-    goto Done;\r
-  }\r
-  Size = sizeof (CapsuleDataPtr64);\r
-  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME);\r
-  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
-  while (TRUE) {\r
-    if (Index > 0) {\r
-      UnicodeValueToStringS (\r
-        TempVarName,\r
-        sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),\r
-        0,\r
-        Index,\r
-        0\r
-        );\r
-    }\r
-    Status = PPIVariableServices->GetVariable (\r
-                                    PPIVariableServices,\r
-                                    CapsuleVarName,\r
-                                    &gEfiCapsuleVendorGuid,\r
-                                    NULL,\r
-                                    &Size,\r
-                                    (VOID *) &CapsuleDataPtr64\r
-                                    );\r
-    if (EFI_ERROR (Status)) {\r
-      //\r
-      // There is no capsule variables, quit\r
-      //\r
-      DEBUG ((DEBUG_INFO,"Capsule variable Index = %d\n", Index));\r
-      break;\r
-    }\r
-    VariableCount++;\r
-    Index++;\r
-  }\r
-\r
-  DEBUG ((DEBUG_INFO,"Capsule variable count = %d\n", VariableCount));\r
-\r
-  //\r
-  // The last entry is the end flag.\r
-  //\r
-  Status = PeiServicesAllocatePool (\r
-             (VariableCount + 1) * sizeof (EFI_PHYSICAL_ADDRESS),\r
-             (VOID **)&VariableArrayAddress\r
-             );\r
-\r
-  if (Status != EFI_SUCCESS) {\r
-    DEBUG ((DEBUG_ERROR, "AllocatePages Failed!, Status = %x\n", Status));\r
-    goto Done;\r
-  }\r
-\r
-  ZeroMem (VariableArrayAddress, (VariableCount + 1) * sizeof (EFI_PHYSICAL_ADDRESS));\r
-\r
-  //\r
-  // Find out if we actually have a capsule.\r
-  // GetCapsuleDescriptors depends on variable PPI, so it should run in 32-bit environment.\r
-  //\r
-  Status = GetCapsuleDescriptors (VariableArrayAddress);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "Fail to find capsule variables.\n"));\r
+    DEBUG ((DEBUG_ERROR, "%a failed to get Scatter Gather List Head Entries.  Status = %r\n", __FUNCTION__, Status));\r
     goto Done;\r
   }\r
 \r
@@ -1118,7 +1123,17 @@ CheckCapsuleUpdate (
   )\r
 {\r
   EFI_STATUS  Status;\r
-  Status = GetCapsuleDescriptors (NULL);\r
+  BOOLEAN     Update;\r
+\r
+  Status = AreCapsulesStaged (&Update);\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    if (Update) {\r
+      Status = EFI_SUCCESS;\r
+    } else {\r
+      Status = EFI_NOT_FOUND;\r
+    }\r
+  }\r
   return Status;\r
 }\r
 /**\r