]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/CapsulePei/UefiCapsule.c
MdeMoudlePkg/CapsulePei: Fix coding style issue
[mirror_edk2.git] / MdeModulePkg / Universal / CapsulePei / UefiCapsule.c
index cca455ec396c6b28c73e8e470a4d484469695093..b224e200fe182032d6e031613d953f6f8ffca2c9 100644 (file)
@@ -1,17 +1,10 @@
 /** @file\r
   Capsule update PEIM for UEFI2.0\r
 \r
-Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
 \r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions\r
-of the BSD License which accompanies this distribution.  The\r
-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
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -133,7 +126,7 @@ Create4GPageTables (
   IN EFI_PHYSICAL_ADDRESS   PageTablesAddress,\r
   IN BOOLEAN                Page1GSupport\r
   )\r
-{  \r
+{\r
   UINT8                                         PhysicalAddressBits;\r
   EFI_PHYSICAL_ADDRESS                          PageAddress;\r
   UINTN                                         IndexOfPml4Entries;\r
@@ -172,7 +165,7 @@ Create4GPageTables (
   }\r
 \r
   //\r
-  // Pre-allocate big pages to avoid later allocations. \r
+  // Pre-allocate big pages to avoid later allocations.\r
   //\r
   BigPageAddress = (UINTN) PageTablesAddress;\r
 \r
@@ -201,7 +194,7 @@ Create4GPageTables (
 \r
     if (Page1GSupport) {\r
       PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;\r
-    \r
+\r
       for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {\r
         //\r
         // Fill in the Page Directory entries\r
@@ -216,7 +209,7 @@ Create4GPageTables (
         //\r
         // Each Directory Pointer entries points to a page of Page Directory entires.\r
         // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.\r
-        //       \r
+        //\r
         PageDirectoryEntry = (VOID *) BigPageAddress;\r
         BigPageAddress += SIZE_4KB;\r
 \r
@@ -360,7 +353,7 @@ Thunk32To64 (
   if ((UINTN) ReturnContext->ReturnStatus != 0) {\r
     Status = ENCODE_ERROR ((UINTN) ReturnContext->ReturnStatus);\r
   }\r
-  \r
+\r
   return Status;\r
 }\r
 \r
@@ -401,7 +394,7 @@ ModeSwitch (
 \r
   ZeroMem (&Context, sizeof (SWITCH_32_TO_64_CONTEXT));\r
   ZeroMem (&ReturnContext, sizeof (SWITCH_64_TO_32_CONTEXT));\r
-  \r
+\r
   MemoryBase64  = (UINT64) (UINTN) *MemoryBase;\r
   MemorySize64  = (UINT64) (UINTN) *MemorySize;\r
   MemoryEnd64   = MemoryBase64 + MemorySize64;\r
@@ -409,7 +402,7 @@ ModeSwitch (
   Page1GSupport = IsPage1GSupport ();\r
 \r
   //\r
-  // Merge memory range reserved for stack and page table  \r
+  // Merge memory range reserved for stack and page table\r
   //\r
   if (LongModeBuffer->StackBaseAddress < LongModeBuffer->PageTableAddress) {\r
     ReservedRangeBase = LongModeBuffer->StackBaseAddress;\r
@@ -427,7 +420,7 @@ ModeSwitch (
     if (ReservedRangeEnd < MemoryEnd64) {\r
       MemoryBase64 = ReservedRangeEnd;\r
     } else {\r
-      DEBUG ((EFI_D_ERROR, "Memory is not enough to process capsule!\n"));\r
+      DEBUG ((DEBUG_ERROR, "Memory is not enough to process capsule!\n"));\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
   } else if (ReservedRangeBase < MemoryEnd64) {\r
@@ -462,14 +455,14 @@ ModeSwitch (
   // Will save the return status of processing capsule\r
   //\r
   ReturnContext.ReturnStatus       = 0;\r
-  \r
+\r
   //\r
   // Save original GDT\r
   //\r
   AsmReadGdtr ((IA32_DESCRIPTOR *)&ReturnContext.Gdtr);\r
-  \r
+\r
   Status = Thunk32To64 (LongModeBuffer->PageTableAddress, &Context, &ReturnContext);\r
-  \r
+\r
   if (!EFI_ERROR (Status)) {\r
     *MemoryBase = (VOID *) (UINTN) MemoryBase64;\r
     *MemorySize = (UINTN) MemorySize64;\r
@@ -525,7 +518,7 @@ FindCapsuleCoalesceImage (
                            &AuthenticationState\r
                            );\r
       if (EFI_ERROR (Status)) {\r
-        DEBUG ((EFI_D_ERROR, "Unable to find PE32 section in CapsuleX64 image ffs %r!\n", Status));\r
+        DEBUG ((DEBUG_ERROR, "Unable to find PE32 section in CapsuleX64 image ffs %r!\n", Status));\r
         return Status;\r
       }\r
       *CoalesceImageMachineType = PeCoffLoaderGetMachineType ((VOID *) (UINTN) CoalesceImageAddress);\r
@@ -574,7 +567,7 @@ GetLongModeContext (
                                   LongModeBuffer\r
                                   );\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG (( EFI_D_ERROR, "Error Get LongModeBuffer variable %r!\n", Status));\r
+    DEBUG (( DEBUG_ERROR, "Error Get LongModeBuffer variable %r!\n", Status));\r
   }\r
   return Status;\r
 }\r
@@ -624,6 +617,82 @@ GetPhysicalAddressBits (
 }\r
 #endif\r
 \r
+/**\r
+  Sort memory resource entries based upon PhysicalStart, from low to high.\r
+\r
+  @param[in, out] MemoryResource    A pointer to the memory resource entry buffer.\r
+\r
+**/\r
+VOID\r
+SortMemoryResourceDescriptor (\r
+  IN OUT MEMORY_RESOURCE_DESCRIPTOR *MemoryResource\r
+  )\r
+{\r
+  MEMORY_RESOURCE_DESCRIPTOR        *MemoryResourceEntry;\r
+  MEMORY_RESOURCE_DESCRIPTOR        *NextMemoryResourceEntry;\r
+  MEMORY_RESOURCE_DESCRIPTOR        TempMemoryResource;\r
+\r
+  MemoryResourceEntry = MemoryResource;\r
+  NextMemoryResourceEntry = MemoryResource + 1;\r
+  while (MemoryResourceEntry->ResourceLength != 0) {\r
+    while (NextMemoryResourceEntry->ResourceLength != 0) {\r
+      if (MemoryResourceEntry->PhysicalStart > NextMemoryResourceEntry->PhysicalStart) {\r
+        CopyMem (&TempMemoryResource, MemoryResourceEntry, sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+        CopyMem (MemoryResourceEntry, NextMemoryResourceEntry, sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+        CopyMem (NextMemoryResourceEntry, &TempMemoryResource, sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+      }\r
+\r
+      NextMemoryResourceEntry = NextMemoryResourceEntry + 1;\r
+    }\r
+\r
+    MemoryResourceEntry     = MemoryResourceEntry + 1;\r
+    NextMemoryResourceEntry = MemoryResourceEntry + 1;\r
+  }\r
+}\r
+\r
+/**\r
+  Merge continous memory resource entries.\r
+\r
+  @param[in, out] MemoryResource    A pointer to the memory resource entry buffer.\r
+\r
+**/\r
+VOID\r
+MergeMemoryResourceDescriptor (\r
+  IN OUT MEMORY_RESOURCE_DESCRIPTOR *MemoryResource\r
+  )\r
+{\r
+  MEMORY_RESOURCE_DESCRIPTOR        *MemoryResourceEntry;\r
+  MEMORY_RESOURCE_DESCRIPTOR        *NewMemoryResourceEntry;\r
+  MEMORY_RESOURCE_DESCRIPTOR        *NextMemoryResourceEntry;\r
+  MEMORY_RESOURCE_DESCRIPTOR        *MemoryResourceEnd;\r
+\r
+  MemoryResourceEntry = MemoryResource;\r
+  NewMemoryResourceEntry = MemoryResource;\r
+  while (MemoryResourceEntry->ResourceLength != 0) {\r
+    CopyMem (NewMemoryResourceEntry, MemoryResourceEntry, sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+    NextMemoryResourceEntry = MemoryResourceEntry + 1;\r
+\r
+    while ((NextMemoryResourceEntry->ResourceLength != 0) &&\r
+           (NextMemoryResourceEntry->PhysicalStart == (MemoryResourceEntry->PhysicalStart + MemoryResourceEntry->ResourceLength))) {\r
+      MemoryResourceEntry->ResourceLength += NextMemoryResourceEntry->ResourceLength;\r
+      if (NewMemoryResourceEntry != MemoryResourceEntry) {\r
+        NewMemoryResourceEntry->ResourceLength += NextMemoryResourceEntry->ResourceLength;\r
+      }\r
+\r
+      NextMemoryResourceEntry = NextMemoryResourceEntry + 1;\r
+    }\r
+\r
+    MemoryResourceEntry = NextMemoryResourceEntry;\r
+    NewMemoryResourceEntry = NewMemoryResourceEntry + 1;\r
+  }\r
+\r
+  //\r
+  // Set NULL terminate memory resource descriptor after merging.\r
+  //\r
+  MemoryResourceEnd = NewMemoryResourceEntry;\r
+  ZeroMem (MemoryResourceEnd, sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+}\r
+\r
 /**\r
   Build memory resource descriptor from resource descriptor in HOB list.\r
 \r
@@ -658,7 +727,7 @@ BuildMemoryResourceDescriptor (
   }\r
 \r
   if (Index == 0) {\r
-    DEBUG ((EFI_D_INFO | EFI_D_WARN, "No memory resource descriptor reported in HOB list before capsule Coalesce\n"));\r
+    DEBUG ((DEBUG_INFO | DEBUG_WARN, "No memory resource descriptor reported in HOB list before capsule Coalesce\n"));\r
 #if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)\r
     //\r
     // Allocate memory to hold memory resource descriptor,\r
@@ -667,10 +736,10 @@ BuildMemoryResourceDescriptor (
     Status = PeiServicesAllocatePool ((1 + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR), (VOID **) &MemoryResource);\r
     ASSERT_EFI_ERROR (Status);\r
     ZeroMem (MemoryResource, (1 + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
-  \r
+\r
     MemoryResource[0].PhysicalStart = 0;\r
     MemoryResource[0].ResourceLength = LShiftU64 (1, GetPhysicalAddressBits ());\r
-    DEBUG ((EFI_D_INFO, "MemoryResource[0x0] - Start(0x%0lx) Length(0x%0lx)\n",\r
+    DEBUG ((DEBUG_INFO, "MemoryResource[0x0] - Start(0x%0lx) Length(0x%0lx)\n",\r
                         MemoryResource[0x0].PhysicalStart, MemoryResource[0x0].ResourceLength));\r
     return MemoryResource;\r
 #else\r
@@ -694,7 +763,7 @@ BuildMemoryResourceDescriptor (
   while (Hob.Raw != NULL) {\r
     ResourceDescriptor = (EFI_HOB_RESOURCE_DESCRIPTOR *) Hob.Raw;\r
     if (ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
-      DEBUG ((EFI_D_INFO, "MemoryResource[0x%x] - Start(0x%0lx) Length(0x%0lx)\n",\r
+      DEBUG ((DEBUG_INFO, "MemoryResource[0x%x] - Start(0x%0lx) Length(0x%0lx)\n",\r
                           Index, ResourceDescriptor->PhysicalStart, ResourceDescriptor->ResourceLength));\r
       MemoryResource[Index].PhysicalStart = ResourceDescriptor->PhysicalStart;\r
       MemoryResource[Index].ResourceLength = ResourceDescriptor->ResourceLength;\r
@@ -704,22 +773,100 @@ BuildMemoryResourceDescriptor (
     Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);\r
   }\r
 \r
+  SortMemoryResourceDescriptor (MemoryResource);\r
+  MergeMemoryResourceDescriptor (MemoryResource);\r
+\r
+  DEBUG ((DEBUG_INFO, "Dump MemoryResource[] after sorted and merged\n"));\r
+  for (Index = 0; MemoryResource[Index].ResourceLength != 0; Index++) {\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "  MemoryResource[0x%x] - Start(0x%0lx) Length(0x%0lx)\n",\r
+      Index,\r
+      MemoryResource[Index].PhysicalStart,\r
+      MemoryResource[Index].ResourceLength\r
+      ));\r
+  }\r
+\r
   return MemoryResource;\r
 }\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 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
+**/\r
+EFI_STATUS\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
-  @param DescriptorBuffer        Pointer to the capsule descriptors\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
-  @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
+GetScatterGatherHeadEntries (\r
+  OUT UINTN *ListLength,\r
+  OUT EFI_PHYSICAL_ADDRESS **HeadList\r
   )\r
 {\r
   EFI_STATUS                       Status;\r
@@ -732,94 +879,104 @@ 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
   CapsuleVarName[0] = 0;\r
   ValidIndex        = 0;\r
   CapsuleDataPtr64  = 0;\r
-  \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
-        \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
+    Status = PPIVariableServices->GetVariable (\r
+                                    PPIVariableServices,\r
+                                    CapsuleVarName,\r
+                                    &gEfiCapsuleVendorGuid,\r
+                                    NULL,\r
+                                    &Size,\r
+                                    (VOID *)&CapsuleDataPtr64\r
+                                    );\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
+    // 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
-      //\r
-      // Cache BlockList which has been processed\r
-      //\r
-      DescriptorBuffer[ValidIndex++] = CapsuleDataPtr64;\r
-      Index ++;\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
+\r
+  CopyMem (*HeadList, TempList, (ValidIndex) * sizeof (EFI_PHYSICAL_ADDRESS));\r
+  *ListLength = ValidIndex;\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -854,15 +1011,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
@@ -872,10 +1023,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
@@ -883,80 +1032,17 @@ CapsuleCoalesce (
   //\r
   Status = PeiServicesGetBootMode (&BootMode);\r
   if (EFI_ERROR (Status) || (BootMode != BOOT_ON_FLASH_UPDATE)) {\r
-    DEBUG ((EFI_D_ERROR, "Boot mode is not correct for capsule update path.\n"));    \r
+    DEBUG ((DEBUG_ERROR, "Boot mode is not correct for capsule update path.\n"));\r
     Status = EFI_NOT_FOUND;\r
     goto Done;\r
   }\r
-  \r
-  //\r
-  // User may set the same ScatterGatherList with several different variables,\r
-  // so cache all ScatterGatherList for check later.\r
-  //\r
-  Status = PeiServicesLocatePpi (\r
-              &gEfiPeiReadOnlyVariable2PpiGuid,\r
-              0,\r
-              NULL,\r
-              (VOID **) &PPIVariableServices\r
-              );\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 ((EFI_D_INFO,"Capsule variable Index = %d\n", Index));\r
-      break;\r
-    }\r
-    VariableCount++;\r
-    Index++;\r
-  }\r
-  \r
-  DEBUG ((EFI_D_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 ((EFI_D_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
+  // Get SG list entries\r
   //\r
-  Status = GetCapsuleDescriptors (VariableArrayAddress);\r
+  Status = GetScatterGatherHeadEntries (&ListLength, &VariableArrayAddress);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_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
@@ -974,14 +1060,14 @@ CapsuleCoalesce (
     CoalesceImageEntryPoint = 0;\r
     Status = GetLongModeContext (&LongModeBuffer);\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "Fail to find the variable for long mode context!\n"));\r
+      DEBUG ((DEBUG_ERROR, "Fail to find the variable for long mode context!\n"));\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
-    \r
+\r
     Status = FindCapsuleCoalesceImage (&CoalesceImageEntryPoint, &CoalesceImageMachineType);\r
     if ((EFI_ERROR (Status)) || (CoalesceImageMachineType != EFI_IMAGE_MACHINE_X64)) {\r
-      DEBUG ((EFI_D_ERROR, "Fail to find CapsuleX64 module in FV!\n"));\r
+      DEBUG ((DEBUG_ERROR, "Fail to find CapsuleX64 module in FV!\n"));\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
@@ -1000,15 +1086,15 @@ CapsuleCoalesce (
   //\r
   Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryResource, MemoryBase, MemorySize);\r
 #endif\r
-  \r
-  DEBUG ((EFI_D_INFO, "Capsule Coalesce Status = %r!\n", Status));\r
+\r
+  DEBUG ((DEBUG_INFO, "Capsule Coalesce Status = %r!\n", Status));\r
 \r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    DEBUG ((EFI_D_ERROR, "There is not enough memory to process capsule!\n"));\r
+    DEBUG ((DEBUG_ERROR, "There is not enough memory to process capsule!\n"));\r
   }\r
-  \r
+\r
   if (Status == EFI_NOT_FOUND) {\r
-    DEBUG ((EFI_D_ERROR, "Fail to parse capsule descriptor in memory!\n"));\r
+    DEBUG ((DEBUG_ERROR, "Fail to parse capsule descriptor in memory!\n"));\r
     REPORT_STATUS_CODE (\r
       EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
       (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_INVALID_CAPSULE_DESCRIPTOR)\r
@@ -1035,13 +1121,23 @@ 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
-  This function will look at a capsule and determine if it's a test pattern. \r
+  This function will look at a capsule and determine if it's a test pattern.\r
   If it is, then it will verify it and emit an error message if corruption is detected.\r
-  \r
+\r
   @param PeiServices   Standard pei services pointer\r
   @param CapsuleBase   Base address of coalesced capsule, which is preceeded\r
                        by private data. Very implementation specific.\r
@@ -1073,7 +1169,7 @@ CapsuleTestPattern (
   //\r
   if (*TestPtr == 0x54534554) {\r
     RetValue = TRUE;\r
-    DEBUG ((EFI_D_INFO, "Capsule test pattern mode activated...\n"));\r
+    DEBUG ((DEBUG_INFO, "Capsule test pattern mode activated...\n"));\r
     TestSize = TestPtr[1] / sizeof (UINT32);\r
     //\r
     // Skip over the signature and the size fields in the pattern data header\r
@@ -1082,7 +1178,7 @@ CapsuleTestPattern (
     TestCounter = 0;\r
     while (TestSize > 0) {\r
       if (*TestPtr != TestCounter) {\r
-        DEBUG ((EFI_D_INFO, "Capsule test pattern mode FAILED: BaseAddr/FailAddr 0x%X 0x%X\n", (UINT32)(UINTN)(EFI_CAPSULE_PEIM_PRIVATE_DATA *)CapsuleBase, (UINT32)(UINTN)TestPtr));\r
+        DEBUG ((DEBUG_INFO, "Capsule test pattern mode FAILED: BaseAddr/FailAddr 0x%X 0x%X\n", (UINT32)(UINTN)(EFI_CAPSULE_PEIM_PRIVATE_DATA *)CapsuleBase, (UINT32)(UINTN)TestPtr));\r
         return TRUE;\r
       }\r
 \r
@@ -1091,7 +1187,7 @@ CapsuleTestPattern (
       TestSize--;\r
     }\r
 \r
-    DEBUG ((EFI_D_INFO, "Capsule test pattern mode SUCCESS\n"));\r
+    DEBUG ((DEBUG_INFO, "Capsule test pattern mode SUCCESS\n"));\r
   }\r
 \r
   return RetValue;\r
@@ -1130,17 +1226,17 @@ CreateState (
   UINT32                        Index;\r
   EFI_PHYSICAL_ADDRESS          BaseAddress;\r
   UINT64                        Length;\r
\r
+\r
   PrivateData    = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) CapsuleBase;\r
   if (PrivateData->Signature != EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE) {\r
     return EFI_VOLUME_CORRUPTED;\r
   }\r
   if (PrivateData->CapsuleAllImageSize >= MAX_ADDRESS) {\r
-    DEBUG ((EFI_D_ERROR, "CapsuleAllImageSize too big - 0x%lx\n", PrivateData->CapsuleAllImageSize));\r
+    DEBUG ((DEBUG_ERROR, "CapsuleAllImageSize too big - 0x%lx\n", PrivateData->CapsuleAllImageSize));\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   if (PrivateData->CapsuleNumber >= MAX_ADDRESS) {\r
-    DEBUG ((EFI_D_ERROR, "CapsuleNumber too big - 0x%lx\n", PrivateData->CapsuleNumber));\r
+    DEBUG ((DEBUG_ERROR, "CapsuleNumber too big - 0x%lx\n", PrivateData->CapsuleNumber));\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   //\r
@@ -1158,13 +1254,13 @@ CreateState (
              );\r
 \r
   if (Status != EFI_SUCCESS) {\r
-    DEBUG ((EFI_D_ERROR, "AllocatePages Failed!\n"));\r
+    DEBUG ((DEBUG_ERROR, "AllocatePages Failed!\n"));\r
     return Status;\r
   }\r
   //\r
   // Copy to our new buffer for DXE\r
   //\r
-  DEBUG ((EFI_D_INFO, "Capsule copy from 0x%8X to 0x%8X with size 0x%8X\n", (UINTN)((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), (UINTN) NewBuffer, Size));\r
+  DEBUG ((DEBUG_INFO, "Capsule copy from 0x%8X to 0x%8X with size 0x%8X\n", (UINTN)((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), (UINTN) NewBuffer, Size));\r
   CopyMem ((VOID *) (UINTN) NewBuffer, (VOID *) (UINTN) ((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), Size);\r
   //\r
   // Check for test data pattern. If it is the test pattern, then we'll\r
@@ -1186,7 +1282,7 @@ CreateState (
 \r
     BuildCvHob (BaseAddress, Length);\r
   }\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r