]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/CapsulePei/UefiCapsule.c
MdeModulePkg: Replace [Ascii|Unicode]ValueToString
[mirror_edk2.git] / MdeModulePkg / Universal / CapsulePei / UefiCapsule.c
index 37ba341e608d308742491a9b4eb33c23ca4c0b89..d61d5ff5e3b250ac803c3c76015fbdd3f2702dba 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
   Capsule update PEIM for UEFI2.0\r
 \r
 /** @file\r
   Capsule update PEIM for UEFI2.0\r
 \r
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2017, 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
 \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
@@ -41,25 +42,21 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = {
   (UINTN) mGdtEntries\r
   };\r
 \r
   (UINTN) mGdtEntries\r
   };\r
 \r
+\r
 /**\r
 /**\r
-  Calculate the total size of page table.\r
-  \r
-  @return The size of page table.\r
-  \r
-  \r
+  The function will check if 1G page is supported.\r
+\r
+  @retval TRUE   1G page is supported.\r
+  @retval FALSE  1G page is not supported.\r
+\r
 **/\r
 **/\r
-UINTN\r
-CalculatePageTableSize (\r
+BOOLEAN\r
+IsPage1GSupport (\r
   VOID\r
   )\r
 {\r
   UINT32                                        RegEax;\r
   UINT32                                        RegEdx;\r
   VOID\r
   )\r
 {\r
   UINT32                                        RegEax;\r
   UINT32                                        RegEdx;\r
-  UINTN                                         TotalPagesNum;\r
-  UINT8                                         PhysicalAddressBits;\r
-  VOID                                          *Hob;\r
-  UINT32                                        NumberOfPml4EntriesNeeded;\r
-  UINT32                                        NumberOfPdpEntriesNeeded;\r
   BOOLEAN                                       Page1GSupport;\r
 \r
   Page1GSupport = FALSE;\r
   BOOLEAN                                       Page1GSupport;\r
 \r
   Page1GSupport = FALSE;\r
@@ -73,29 +70,34 @@ CalculatePageTableSize (
     }\r
   }\r
 \r
     }\r
   }\r
 \r
-  //\r
-  // Get physical address bits supported.\r
-  //\r
-  Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
-  if (Hob != NULL) {\r
-    PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
-  } else {\r
-    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
-    if (RegEax >= 0x80000008) {\r
-      AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
-      PhysicalAddressBits = (UINT8) RegEax;\r
-    } else {\r
-      PhysicalAddressBits = 36;\r
-    }\r
-  }\r
+  return Page1GSupport;\r
+}\r
+\r
+/**\r
+  Calculate the total size of page table.\r
+\r
+  @param[in] Page1GSupport      1G page support or not.\r
+\r
+  @return The size of page table.\r
+\r
+**/\r
+UINTN\r
+CalculatePageTableSize (\r
+  IN BOOLEAN                                    Page1GSupport\r
+  )\r
+{\r
+  UINTN                                         ExtraPageTablePages;\r
+  UINTN                                         TotalPagesNum;\r
+  UINT8                                         PhysicalAddressBits;\r
+  UINT32                                        NumberOfPml4EntriesNeeded;\r
+  UINT32                                        NumberOfPdpEntriesNeeded;\r
 \r
   //\r
 \r
   //\r
-  // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.\r
+  // Create 4G page table by default,\r
+  // and let PF handler to handle > 4G request.\r
   //\r
   //\r
-  ASSERT (PhysicalAddressBits <= 52);\r
-  if (PhysicalAddressBits > 48) {\r
-    PhysicalAddressBits = 48;\r
-  }\r
+  PhysicalAddressBits = 32;\r
+  ExtraPageTablePages = EXTRA_PAGE_TABLE_PAGES;\r
 \r
   //\r
   // Calculate the table entries needed.\r
 \r
   //\r
   // Calculate the table entries needed.\r
@@ -113,24 +115,25 @@ CalculatePageTableSize (
   } else {\r
     TotalPagesNum = NumberOfPml4EntriesNeeded + 1;\r
   }\r
   } else {\r
     TotalPagesNum = NumberOfPml4EntriesNeeded + 1;\r
   }\r
+  TotalPagesNum += ExtraPageTablePages;\r
 \r
   return EFI_PAGES_TO_SIZE (TotalPagesNum);\r
 }\r
 \r
 /**\r
   Allocates and fills in the Page Directory and Page Table Entries to\r
 \r
   return EFI_PAGES_TO_SIZE (TotalPagesNum);\r
 }\r
 \r
 /**\r
   Allocates and fills in the Page Directory and Page Table Entries to\r
-  establish a 1:1 Virtual to Physical mapping.\r
+  establish a 4G page table.\r
 \r
 \r
-  @param[in]  PageTablesAddress  The base address of page table.\r
+  @param[in] PageTablesAddress  The base address of page table.\r
+  @param[in] Page1GSupport      1G page support or not.\r
 \r
 **/\r
 VOID\r
 \r
 **/\r
 VOID\r
-CreateIdentityMappingPageTables (\r
-  IN  EFI_PHYSICAL_ADDRESS  PageTablesAddress\r
+Create4GPageTables (\r
+  IN EFI_PHYSICAL_ADDRESS   PageTablesAddress,\r
+  IN BOOLEAN                Page1GSupport\r
   )\r
 {  \r
   )\r
 {  \r
-  UINT32                                        RegEax;\r
-  UINT32                                        RegEdx;\r
   UINT8                                         PhysicalAddressBits;\r
   EFI_PHYSICAL_ADDRESS                          PageAddress;\r
   UINTN                                         IndexOfPml4Entries;\r
   UINT8                                         PhysicalAddressBits;\r
   EFI_PHYSICAL_ADDRESS                          PageAddress;\r
   UINTN                                         IndexOfPml4Entries;\r
@@ -143,42 +146,19 @@ CreateIdentityMappingPageTables (
   PAGE_MAP_AND_DIRECTORY_POINTER                *PageDirectoryPointerEntry;\r
   PAGE_TABLE_ENTRY                              *PageDirectoryEntry;\r
   UINTN                                         BigPageAddress;\r
   PAGE_MAP_AND_DIRECTORY_POINTER                *PageDirectoryPointerEntry;\r
   PAGE_TABLE_ENTRY                              *PageDirectoryEntry;\r
   UINTN                                         BigPageAddress;\r
-  VOID                                          *Hob;\r
-  BOOLEAN                                       Page1GSupport;\r
   PAGE_TABLE_1G_ENTRY                           *PageDirectory1GEntry;\r
   PAGE_TABLE_1G_ENTRY                           *PageDirectory1GEntry;\r
-\r
-  Page1GSupport = FALSE;\r
-  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
-  if (RegEax >= 0x80000001) {\r
-    AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
-    if ((RegEdx & BIT26) != 0) {\r
-      Page1GSupport = TRUE;\r
-    }\r
-  }\r
+  UINT64                                        AddressEncMask;\r
 \r
   //\r
 \r
   //\r
-  // Get physical address bits supported.\r
+  // Make sure AddressEncMask is contained to smallest supported address field.\r
   //\r
   //\r
-  Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
-  if (Hob != NULL) {\r
-    PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
-  } else {\r
-    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
-    if (RegEax >= 0x80000008) {\r
-      AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
-      PhysicalAddressBits = (UINT8) RegEax;\r
-    } else {\r
-      PhysicalAddressBits = 36;\r
-    }\r
-  }\r
+  AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;\r
 \r
   //\r
 \r
   //\r
-  // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.\r
+  // Create 4G page table by default,\r
+  // and let PF handler to handle > 4G request.\r
   //\r
   //\r
-  ASSERT (PhysicalAddressBits <= 52);\r
-  if (PhysicalAddressBits > 48) {\r
-    PhysicalAddressBits = 48;\r
-  }\r
+  PhysicalAddressBits = 32;\r
 \r
   //\r
   // Calculate the table entries needed.\r
 \r
   //\r
   // Calculate the table entries needed.\r
@@ -215,7 +195,7 @@ CreateIdentityMappingPageTables (
     //\r
     // Make a PML4 Entry\r
     //\r
     //\r
     // Make a PML4 Entry\r
     //\r
-    PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;\r
+    PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry | AddressEncMask;\r
     PageMapLevel4Entry->Bits.ReadWrite = 1;\r
     PageMapLevel4Entry->Bits.Present = 1;\r
 \r
     PageMapLevel4Entry->Bits.ReadWrite = 1;\r
     PageMapLevel4Entry->Bits.Present = 1;\r
 \r
@@ -226,7 +206,7 @@ CreateIdentityMappingPageTables (
         //\r
         // Fill in the Page Directory entries\r
         //\r
         //\r
         // Fill in the Page Directory entries\r
         //\r
-        PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;\r
+        PageDirectory1GEntry->Uint64 = (UINT64)PageAddress | AddressEncMask;\r
         PageDirectory1GEntry->Bits.ReadWrite = 1;\r
         PageDirectory1GEntry->Bits.Present = 1;\r
         PageDirectory1GEntry->Bits.MustBe1 = 1;\r
         PageDirectory1GEntry->Bits.ReadWrite = 1;\r
         PageDirectory1GEntry->Bits.Present = 1;\r
         PageDirectory1GEntry->Bits.MustBe1 = 1;\r
@@ -243,7 +223,7 @@ CreateIdentityMappingPageTables (
         //\r
         // Fill in a Page Directory Pointer Entries\r
         //\r
         //\r
         // Fill in a Page Directory Pointer Entries\r
         //\r
-        PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;\r
+        PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry | AddressEncMask;\r
         PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
         PageDirectoryPointerEntry->Bits.Present = 1;\r
 \r
         PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
         PageDirectoryPointerEntry->Bits.Present = 1;\r
 \r
@@ -251,7 +231,7 @@ CreateIdentityMappingPageTables (
           //\r
           // Fill in the Page Directory entries\r
           //\r
           //\r
           // Fill in the Page Directory entries\r
           //\r
-          PageDirectoryEntry->Uint64 = (UINT64)PageAddress;\r
+          PageDirectoryEntry->Uint64 = (UINT64)PageAddress | AddressEncMask;\r
           PageDirectoryEntry->Bits.ReadWrite = 1;\r
           PageDirectoryEntry->Bits.Present = 1;\r
           PageDirectoryEntry->Bits.MustBe1 = 1;\r
           PageDirectoryEntry->Bits.ReadWrite = 1;\r
           PageDirectoryEntry->Bits.Present = 1;\r
           PageDirectoryEntry->Bits.MustBe1 = 1;\r
@@ -290,20 +270,20 @@ ReturnFunction (
   SWITCH_32_TO_64_CONTEXT  *EntrypointContext,\r
   SWITCH_64_TO_32_CONTEXT  *ReturnContext\r
   )\r
   SWITCH_32_TO_64_CONTEXT  *EntrypointContext,\r
   SWITCH_64_TO_32_CONTEXT  *ReturnContext\r
   )\r
-{ \r
+{\r
   //\r
   // Restore original GDT\r
   //\r
   AsmWriteGdtr (&ReturnContext->Gdtr);\r
   //\r
   // Restore original GDT\r
   //\r
   AsmWriteGdtr (&ReturnContext->Gdtr);\r
-  \r
+\r
   //\r
   // return to original caller\r
   //\r
   LongJump ((BASE_LIBRARY_JUMP_BUFFER  *)(UINTN)EntrypointContext->JumpBuffer, 1);\r
   //\r
   // return to original caller\r
   //\r
   LongJump ((BASE_LIBRARY_JUMP_BUFFER  *)(UINTN)EntrypointContext->JumpBuffer, 1);\r
\r
+\r
   //\r
   // never be here\r
   //\r
   // never be here\r
-  // \r
+  //\r
   ASSERT (FALSE);\r
 }\r
 \r
   ASSERT (FALSE);\r
 }\r
 \r
@@ -335,10 +315,10 @@ Thunk32To64 (
   if (SetJumpFlag == 0) {\r
 \r
     //\r
   if (SetJumpFlag == 0) {\r
 \r
     //\r
-    // Build Page Tables for all physical memory processor supports\r
+    // Build 4G Page Tables.\r
     //\r
     //\r
-    CreateIdentityMappingPageTables (PageTableAddress);\r
-    \r
+    Create4GPageTables (PageTableAddress, Context->Page1GSupport);\r
+\r
     //\r
     // Create 64-bit GDT\r
     //\r
     //\r
     // Create 64-bit GDT\r
     //\r
@@ -349,6 +329,14 @@ Thunk32To64 (
     //\r
     AsmWriteCr3 ((UINTN) PageTableAddress);\r
 \r
     //\r
     AsmWriteCr3 ((UINTN) PageTableAddress);\r
 \r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a() Stack Base: 0x%lx, Stack Size: 0x%lx\n",\r
+      __FUNCTION__,\r
+      Context->StackBufferBase,\r
+      Context->StackBufferLength\r
+      ));\r
+\r
     //\r
     // Disable interrupt of Debug timer, since the IDT table cannot work in long mode\r
     //\r
     //\r
     // Disable interrupt of Debug timer, since the IDT table cannot work in long mode\r
     //\r
@@ -364,7 +352,7 @@ Thunk32To64 (
       Context->StackBufferBase + Context->StackBufferLength\r
       );\r
   }\r
       Context->StackBufferBase + Context->StackBufferLength\r
       );\r
   }\r
-  \r
+\r
   //\r
   // Convert to 32-bit Status and return\r
   //\r
   //\r
   // Convert to 32-bit Status and return\r
   //\r
@@ -382,6 +370,7 @@ Thunk32To64 (
   @param  LongModeBuffer            The context of long mode.\r
   @param  CoalesceEntry             Entry of coalesce image.\r
   @param  BlockListAddr             Address of block list.\r
   @param  LongModeBuffer            The context of long mode.\r
   @param  CoalesceEntry             Entry of coalesce image.\r
   @param  BlockListAddr             Address of block list.\r
+  @param  MemoryResource            Pointer to the buffer of memory resource descriptor.\r
   @param  MemoryBase                Base of memory range.\r
   @param  MemorySize                Size of memory range.\r
 \r
   @param  MemoryBase                Base of memory range.\r
   @param  MemorySize                Size of memory range.\r
 \r
@@ -394,6 +383,7 @@ ModeSwitch (
   IN EFI_CAPSULE_LONG_MODE_BUFFER   *LongModeBuffer,\r
   IN COALESCE_ENTRY                 CoalesceEntry,\r
   IN EFI_PHYSICAL_ADDRESS           BlockListAddr,\r
   IN EFI_CAPSULE_LONG_MODE_BUFFER   *LongModeBuffer,\r
   IN COALESCE_ENTRY                 CoalesceEntry,\r
   IN EFI_PHYSICAL_ADDRESS           BlockListAddr,\r
+  IN MEMORY_RESOURCE_DESCRIPTOR     *MemoryResource,\r
   IN OUT VOID                       **MemoryBase,\r
   IN OUT UINTN                      *MemorySize\r
   )\r
   IN OUT VOID                       **MemoryBase,\r
   IN OUT UINTN                      *MemorySize\r
   )\r
@@ -407,6 +397,7 @@ ModeSwitch (
   BASE_LIBRARY_JUMP_BUFFER             JumpBuffer;\r
   EFI_PHYSICAL_ADDRESS                 ReservedRangeBase;\r
   EFI_PHYSICAL_ADDRESS                 ReservedRangeEnd;\r
   BASE_LIBRARY_JUMP_BUFFER             JumpBuffer;\r
   EFI_PHYSICAL_ADDRESS                 ReservedRangeBase;\r
   EFI_PHYSICAL_ADDRESS                 ReservedRangeEnd;\r
+  BOOLEAN                              Page1GSupport;\r
 \r
   ZeroMem (&Context, sizeof (SWITCH_32_TO_64_CONTEXT));\r
   ZeroMem (&ReturnContext, sizeof (SWITCH_64_TO_32_CONTEXT));\r
 \r
   ZeroMem (&Context, sizeof (SWITCH_32_TO_64_CONTEXT));\r
   ZeroMem (&ReturnContext, sizeof (SWITCH_64_TO_32_CONTEXT));\r
@@ -415,17 +406,19 @@ ModeSwitch (
   MemorySize64  = (UINT64) (UINTN) *MemorySize;\r
   MemoryEnd64   = MemoryBase64 + MemorySize64;\r
 \r
   MemorySize64  = (UINT64) (UINTN) *MemorySize;\r
   MemoryEnd64   = MemoryBase64 + MemorySize64;\r
 \r
+  Page1GSupport = IsPage1GSupport ();\r
+\r
   //\r
   // Merge memory range reserved for stack and page table  \r
   //\r
   if (LongModeBuffer->StackBaseAddress < LongModeBuffer->PageTableAddress) {\r
     ReservedRangeBase = LongModeBuffer->StackBaseAddress;\r
   //\r
   // Merge memory range reserved for stack and page table  \r
   //\r
   if (LongModeBuffer->StackBaseAddress < LongModeBuffer->PageTableAddress) {\r
     ReservedRangeBase = LongModeBuffer->StackBaseAddress;\r
-    ReservedRangeEnd  = LongModeBuffer->PageTableAddress + CalculatePageTableSize ();\r
+    ReservedRangeEnd  = LongModeBuffer->PageTableAddress + CalculatePageTableSize (Page1GSupport);\r
   } else {\r
     ReservedRangeBase = LongModeBuffer->PageTableAddress;\r
     ReservedRangeEnd  = LongModeBuffer->StackBaseAddress + LongModeBuffer->StackSize;\r
   }\r
   } else {\r
     ReservedRangeBase = LongModeBuffer->PageTableAddress;\r
     ReservedRangeEnd  = LongModeBuffer->StackBaseAddress + LongModeBuffer->StackSize;\r
   }\r
-  \r
+\r
   //\r
   // Check if memory range reserved is overlap with MemoryBase ~ MemoryBase + MemorySize.\r
   // If they are overlapped, get a larger range to process capsule data.\r
   //\r
   // Check if memory range reserved is overlap with MemoryBase ~ MemoryBase + MemorySize.\r
   // If they are overlapped, get a larger range to process capsule data.\r
@@ -444,8 +437,8 @@ ModeSwitch (
     } else {\r
       MemorySize64 = (UINT64)(UINTN)(ReservedRangeBase - MemoryBase64);\r
     }\r
     } else {\r
       MemorySize64 = (UINT64)(UINTN)(ReservedRangeBase - MemoryBase64);\r
     }\r
-  }  \r
-  \r
+  }\r
+\r
   //\r
   // Initialize context jumping to 64-bit enviroment\r
   //\r
   //\r
   // Initialize context jumping to 64-bit enviroment\r
   //\r
@@ -454,8 +447,11 @@ ModeSwitch (
   Context.StackBufferLength     = LongModeBuffer->StackSize;\r
   Context.EntryPoint            = (EFI_PHYSICAL_ADDRESS)(UINTN)CoalesceEntry;\r
   Context.BlockListAddr         = BlockListAddr;\r
   Context.StackBufferLength     = LongModeBuffer->StackSize;\r
   Context.EntryPoint            = (EFI_PHYSICAL_ADDRESS)(UINTN)CoalesceEntry;\r
   Context.BlockListAddr         = BlockListAddr;\r
+  Context.MemoryResource        = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryResource;\r
   Context.MemoryBase64Ptr       = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemoryBase64;\r
   Context.MemorySize64Ptr       = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemorySize64;\r
   Context.MemoryBase64Ptr       = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemoryBase64;\r
   Context.MemorySize64Ptr       = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemorySize64;\r
+  Context.Page1GSupport         = Page1GSupport;\r
+  Context.AddressEncMask        = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;\r
 \r
   //\r
   // Prepare data for return back\r
 \r
   //\r
   // Prepare data for return back\r
@@ -529,7 +525,7 @@ FindCapsuleCoalesceImage (
                            &AuthenticationState\r
                            );\r
       if (EFI_ERROR (Status)) {\r
                            &AuthenticationState\r
                            );\r
       if (EFI_ERROR (Status)) {\r
-        DEBUG ((EFI_D_ERROR, "Unable to find PE32 section in CapsuleRelocate image ffs %r!\n", Status));\r
+        DEBUG ((EFI_D_ERROR, "Unable to find PE32 section in CapsuleX64 image ffs %r!\n", Status));\r
         return Status;\r
       }\r
       *CoalesceImageMachineType = PeCoffLoaderGetMachineType ((VOID *) (UINTN) CoalesceImageAddress);\r
         return Status;\r
       }\r
       *CoalesceImageMachineType = PeCoffLoaderGetMachineType ((VOID *) (UINTN) CoalesceImageAddress);\r
@@ -542,7 +538,174 @@ FindCapsuleCoalesceImage (
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r
+/**\r
+  Gets the reserved long mode buffer.\r
+\r
+  @param  LongModeBuffer  Pointer to the long mode buffer for output.\r
+\r
+  @retval EFI_SUCCESS     Long mode buffer successfully retrieved.\r
+  @retval Others          Variable storing long mode buffer not found.\r
+\r
+**/\r
+EFI_STATUS\r
+GetLongModeContext (\r
+  OUT EFI_CAPSULE_LONG_MODE_BUFFER *LongModeBuffer\r
+  )\r
+{\r
+  EFI_STATUS   Status;\r
+  UINTN        Size;\r
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;\r
+\r
+  Status = PeiServicesLocatePpi (\r
+             &gEfiPeiReadOnlyVariable2PpiGuid,\r
+             0,\r
+             NULL,\r
+             (VOID **) &PPIVariableServices\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Size = sizeof (EFI_CAPSULE_LONG_MODE_BUFFER);\r
+  Status = PPIVariableServices->GetVariable (\r
+                                  PPIVariableServices,\r
+                                  EFI_CAPSULE_LONG_MODE_BUFFER_NAME,\r
+                                  &gEfiCapsuleVendorGuid,\r
+                                  NULL,\r
+                                  &Size,\r
+                                  LongModeBuffer\r
+                                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG (( EFI_D_ERROR, "Error Get LongModeBuffer variable %r!\n", Status));\r
+  }\r
+  return Status;\r
+}\r
+#endif\r
+\r
+#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)\r
+/**\r
+  Get physical address bits.\r
+\r
+  @return Physical address bits.\r
+\r
+**/\r
+UINT8\r
+GetPhysicalAddressBits (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                        RegEax;\r
+  UINT8                         PhysicalAddressBits;\r
+  VOID                          *Hob;\r
+\r
+  //\r
+  // Get physical address bits supported.\r
+  //\r
+  Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
+  if (Hob != NULL) {\r
+    PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
+  } else {\r
+    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+    if (RegEax >= 0x80000008) {\r
+      AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+      PhysicalAddressBits = (UINT8) RegEax;\r
+    } else {\r
+      PhysicalAddressBits = 36;\r
+    }\r
+  }\r
+\r
+  //\r
+  // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.\r
+  //\r
+  ASSERT (PhysicalAddressBits <= 52);\r
+  if (PhysicalAddressBits > 48) {\r
+    PhysicalAddressBits = 48;\r
+  }\r
+\r
+  return PhysicalAddressBits;\r
+}\r
+#endif\r
+\r
+/**\r
+  Build memory resource descriptor from resource descriptor in HOB list.\r
+\r
+  @return Pointer to the buffer of memory resource descriptor.\r
+          NULL if no memory resource descriptor reported in HOB list\r
+          before capsule Coalesce.\r
+\r
+**/\r
+MEMORY_RESOURCE_DESCRIPTOR *\r
+BuildMemoryResourceDescriptor (\r
+  VOID\r
+  )\r
+{\r
+  EFI_PEI_HOB_POINTERS          Hob;\r
+  UINTN                         Index;\r
+  EFI_HOB_RESOURCE_DESCRIPTOR   *ResourceDescriptor;\r
+  MEMORY_RESOURCE_DESCRIPTOR    *MemoryResource;\r
+  EFI_STATUS                    Status;\r
+\r
+  //\r
+  // Get the count of memory resource descriptor.\r
+  //\r
+  Index = 0;\r
+  Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r
+  while (Hob.Raw != NULL) {\r
+    ResourceDescriptor = (EFI_HOB_RESOURCE_DESCRIPTOR *) Hob.Raw;\r
+    if (ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
+      Index++;\r
+    }\r
+    Hob.Raw = GET_NEXT_HOB (Hob);\r
+    Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);\r
+  }\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
+#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)\r
+    //\r
+    // Allocate memory to hold memory resource descriptor,\r
+    // include extra one NULL terminate memory resource descriptor.\r
+    //\r
+    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
+    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
+                        MemoryResource[0x0].PhysicalStart, MemoryResource[0x0].ResourceLength));\r
+    return MemoryResource;\r
+#else\r
+    return NULL;\r
 #endif\r
 #endif\r
+  }\r
+\r
+  //\r
+  // Allocate memory to hold memory resource descriptor,\r
+  // include extra one NULL terminate memory resource descriptor.\r
+  //\r
+  Status = PeiServicesAllocatePool ((Index + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR), (VOID **) &MemoryResource);\r
+  ASSERT_EFI_ERROR (Status);\r
+  ZeroMem (MemoryResource, (Index + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+\r
+  //\r
+  // Get the content of memory resource descriptor.\r
+  //\r
+  Index = 0;\r
+  Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r
+  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
+                          Index, ResourceDescriptor->PhysicalStart, ResourceDescriptor->ResourceLength));\r
+      MemoryResource[Index].PhysicalStart = ResourceDescriptor->PhysicalStart;\r
+      MemoryResource[Index].ResourceLength = ResourceDescriptor->ResourceLength;\r
+      Index++;\r
+    }\r
+    Hob.Raw = GET_NEXT_HOB (Hob);\r
+    Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);\r
+  }\r
+\r
+  return MemoryResource;\r
+}\r
 \r
 /**\r
   Checks for the presence of capsule descriptors.\r
 \r
 /**\r
   Checks for the presence of capsule descriptors.\r
@@ -574,6 +737,7 @@ GetCapsuleDescriptors (
   TempVarName       = NULL;\r
   CapsuleVarName[0] = 0;\r
   ValidIndex        = 0;\r
   TempVarName       = NULL;\r
   CapsuleVarName[0] = 0;\r
   ValidIndex        = 0;\r
+  CapsuleDataPtr64  = 0;\r
   \r
   Status = PeiServicesLocatePpi (\r
               &gEfiPeiReadOnlyVariable2PpiGuid,\r
   \r
   Status = PeiServicesLocatePpi (\r
               &gEfiPeiReadOnlyVariable2PpiGuid,\r
@@ -582,7 +746,7 @@ GetCapsuleDescriptors (
               (VOID **) &PPIVariableServices\r
               );\r
   if (Status == EFI_SUCCESS) {\r
               (VOID **) &PPIVariableServices\r
               );\r
   if (Status == EFI_SUCCESS) {\r
-    StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);\r
+    StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME);\r
     TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
     Size = sizeof (CapsuleDataPtr64);\r
     while (1) {\r
     TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
     Size = sizeof (CapsuleDataPtr64);\r
     while (1) {\r
@@ -613,7 +777,13 @@ GetCapsuleDescriptors (
           return EFI_SUCCESS;\r
         }\r
       } else {\r
           return EFI_SUCCESS;\r
         }\r
       } else {\r
-        UnicodeValueToString (TempVarName, 0, Index, 0);\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
         Status = PPIVariableServices->GetVariable (\r
                                         PPIVariableServices,\r
                                         CapsuleVarName,\r
@@ -653,47 +823,6 @@ GetCapsuleDescriptors (
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-/**\r
-  Gets the reserved long mode buffer.\r
-\r
-  @param  LongModeBuffer  Pointer to the long mode buffer for output.\r
-\r
-  @retval EFI_SUCCESS     Long mode buffer successfully retrieved.\r
-  @retval Others          Variable storing long mode buffer not found.\r
-\r
-**/\r
-EFI_STATUS\r
-GetLongModeContext (\r
-  OUT EFI_CAPSULE_LONG_MODE_BUFFER *LongModeBuffer\r
-  )\r
-{\r
-  EFI_STATUS   Status;\r
-  UINTN        Size;\r
-  EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;\r
-\r
-  Status = PeiServicesLocatePpi (\r
-             &gEfiPeiReadOnlyVariable2PpiGuid,\r
-             0,\r
-             NULL,\r
-             (VOID **) &PPIVariableServices\r
-             );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Size = sizeof (EFI_CAPSULE_LONG_MODE_BUFFER);\r
-  Status = PPIVariableServices->GetVariable (\r
-                                  PPIVariableServices,\r
-                                  EFI_CAPSULE_LONG_MODE_BUFFER_NAME,\r
-                                  &gEfiCapsuleVendorGuid,\r
-                                  NULL,\r
-                                  &Size,\r
-                                  LongModeBuffer\r
-                                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG (( EFI_D_ERROR, "Error Get LongModeBuffer variable %r!\n", Status));\r
-  }\r
-  return Status;\r
-}\r
-\r
 /**\r
   Capsule PPI service to coalesce a fragmented capsule in memory.\r
 \r
 /**\r
   Capsule PPI service to coalesce a fragmented capsule in memory.\r
 \r
@@ -735,6 +864,7 @@ CapsuleCoalesce (
   EFI_BOOT_MODE                        BootMode;\r
   EFI_PEI_READ_ONLY_VARIABLE2_PPI      *PPIVariableServices;\r
   EFI_PHYSICAL_ADDRESS                 *VariableArrayAddress;\r
   EFI_BOOT_MODE                        BootMode;\r
   EFI_PEI_READ_ONLY_VARIABLE2_PPI      *PPIVariableServices;\r
   EFI_PHYSICAL_ADDRESS                 *VariableArrayAddress;\r
+  MEMORY_RESOURCE_DESCRIPTOR           *MemoryResource;\r
 #ifdef MDE_CPU_IA32\r
   UINT16                               CoalesceImageMachineType;\r
   EFI_PHYSICAL_ADDRESS                 CoalesceImageEntryPoint;\r
 #ifdef MDE_CPU_IA32\r
   UINT16                               CoalesceImageMachineType;\r
   EFI_PHYSICAL_ADDRESS                 CoalesceImageEntryPoint;\r
@@ -745,6 +875,7 @@ CapsuleCoalesce (
   Index                   = 0;\r
   VariableCount           = 0;\r
   CapsuleVarName[0]       = 0;\r
   Index                   = 0;\r
   VariableCount           = 0;\r
   CapsuleVarName[0]       = 0;\r
+  CapsuleDataPtr64        = 0;\r
 \r
   //\r
   // Someone should have already ascertained the boot mode. If it's not\r
 \r
   //\r
   // Someone should have already ascertained the boot mode. If it's not\r
@@ -771,11 +902,17 @@ CapsuleCoalesce (
     goto Done;\r
   }\r
   Size = sizeof (CapsuleDataPtr64);\r
     goto Done;\r
   }\r
   Size = sizeof (CapsuleDataPtr64);\r
-  StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);\r
+  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME);\r
   TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
   while (TRUE) {\r
     if (Index > 0) {\r
   TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
   while (TRUE) {\r
     if (Index > 0) {\r
-      UnicodeValueToString (TempVarName, 0, 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
     }\r
     Status = PPIVariableServices->GetVariable (\r
                                     PPIVariableServices,\r
@@ -823,6 +960,8 @@ CapsuleCoalesce (
     goto Done;\r
   }\r
 \r
     goto Done;\r
   }\r
 \r
+  MemoryResource = BuildMemoryResourceDescriptor ();\r
+\r
 #ifdef MDE_CPU_IA32\r
   if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
     //\r
 #ifdef MDE_CPU_IA32\r
   if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
     //\r
@@ -835,7 +974,7 @@ CapsuleCoalesce (
     CoalesceImageEntryPoint = 0;\r
     Status = GetLongModeContext (&LongModeBuffer);\r
     if (EFI_ERROR (Status)) {\r
     CoalesceImageEntryPoint = 0;\r
     Status = GetLongModeContext (&LongModeBuffer);\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "Fail to find the variables for long mode context!\n"));\r
+      DEBUG ((EFI_D_ERROR, "Fail to find the variable for long mode context!\n"));\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
@@ -848,18 +987,18 @@ CapsuleCoalesce (
     }\r
     ASSERT (CoalesceImageEntryPoint != 0);\r
     CoalesceEntry = (COALESCE_ENTRY) (UINTN) CoalesceImageEntryPoint;\r
     }\r
     ASSERT (CoalesceImageEntryPoint != 0);\r
     CoalesceEntry = (COALESCE_ENTRY) (UINTN) CoalesceImageEntryPoint;\r
-    Status = ModeSwitch (&LongModeBuffer, CoalesceEntry, (EFI_PHYSICAL_ADDRESS)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);\r
+    Status = ModeSwitch (&LongModeBuffer, CoalesceEntry, (EFI_PHYSICAL_ADDRESS)(UINTN)VariableArrayAddress, MemoryResource, MemoryBase, MemorySize);\r
   } else {\r
     //\r
     // Capsule is processed in IA32 mode.\r
     //\r
   } else {\r
     //\r
     // Capsule is processed in IA32 mode.\r
     //\r
-    Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);\r
+    Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryResource, MemoryBase, MemorySize);\r
   }\r
 #else\r
   //\r
   // Process capsule directly.\r
   //\r
   }\r
 #else\r
   //\r
   // Process capsule directly.\r
   //\r
-  Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);\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
 #endif\r
   \r
   DEBUG ((EFI_D_INFO, "Capsule Coalesce Status = %r!\n", Status));\r
@@ -1029,7 +1168,7 @@ CreateState (
   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
   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
-  // test it ans still create the HOB so that it can be used to verify\r
+  // test it and still create the HOB so that it can be used to verify\r
   // that capsules don't get corrupted all the way into BDS. BDS will\r
   // still try to turn it into a firmware volume, but will think it's\r
   // corrupted so nothing will happen.\r
   // that capsules don't get corrupted all the way into BDS. BDS will\r
   // still try to turn it into a firmware volume, but will think it's\r
   // corrupted so nothing will happen.\r
@@ -1051,7 +1190,7 @@ CreateState (
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-CONST PEI_CAPSULE_PPI        mCapsulePpi = {\r
+CONST EFI_PEI_CAPSULE_PPI        mCapsulePpi = {\r
   CapsuleCoalesce,\r
   CheckCapsuleUpdate,\r
   CreateState\r
   CapsuleCoalesce,\r
   CheckCapsuleUpdate,\r
   CreateState\r
@@ -1059,8 +1198,8 @@ CONST PEI_CAPSULE_PPI        mCapsulePpi = {
 \r
 CONST EFI_PEI_PPI_DESCRIPTOR mUefiPpiListCapsule = {\r
   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
 \r
 CONST EFI_PEI_PPI_DESCRIPTOR mUefiPpiListCapsule = {\r
   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
-  &gPeiCapsulePpiGuid,\r
-  (PEI_CAPSULE_PPI *) &mCapsulePpi\r
+  &gEfiPeiCapsulePpiGuid,\r
+  (EFI_PEI_CAPSULE_PPI *) &mCapsulePpi\r
 };\r
 \r
 /**\r
 };\r
 \r
 /**\r