]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/CapsulePei/UefiCapsule.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / CapsulePei / UefiCapsule.c
index 3184eb1a6249fa7be8f3f07080c1fb5f9913365e..36b04e34064b1caec15d86b4fffb23e9bb6532af 100644 (file)
@@ -1,16 +1,10 @@
 /** @file\r
   Capsule update PEIM for UEFI2.0\r
 \r
 /** @file\r
   Capsule update PEIM for UEFI2.0\r
 \r
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
 \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
 \r
 **/\r
 \r
@@ -41,25 +35,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 +63,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 +108,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
-  UINT32                                        RegEax;\r
-  UINT32                                        RegEdx;\r
+{\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 +139,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
@@ -192,7 +165,7 @@ CreateIdentityMappingPageTables (
   }\r
 \r
   //\r
   }\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
   //\r
   BigPageAddress = (UINTN) PageTablesAddress;\r
 \r
@@ -215,18 +188,18 @@ 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
     if (Page1GSupport) {\r
       PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;\r
     PageMapLevel4Entry->Bits.ReadWrite = 1;\r
     PageMapLevel4Entry->Bits.Present = 1;\r
 \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
         //\r
       for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {\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
@@ -236,14 +209,14 @@ CreateIdentityMappingPageTables (
         //\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
         // 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
         //\r
         // Fill in a Page Directory Pointer Entries\r
         //\r
         PageDirectoryEntry = (VOID *) BigPageAddress;\r
         BigPageAddress += SIZE_4KB;\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 +224,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 +263,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 +308,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 +322,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 +345,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
@@ -372,7 +353,7 @@ Thunk32To64 (
   if ((UINTN) ReturnContext->ReturnStatus != 0) {\r
     Status = ENCODE_ERROR ((UINTN) ReturnContext->ReturnStatus);\r
   }\r
   if ((UINTN) ReturnContext->ReturnStatus != 0) {\r
     Status = ENCODE_ERROR ((UINTN) ReturnContext->ReturnStatus);\r
   }\r
-  \r
+\r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r
@@ -382,6 +363,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 +376,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,25 +390,28 @@ 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
-  \r
+\r
   MemoryBase64  = (UINT64) (UINTN) *MemoryBase;\r
   MemorySize64  = (UINT64) (UINTN) *MemorySize;\r
   MemoryEnd64   = MemoryBase64 + MemorySize64;\r
 \r
   MemoryBase64  = (UINT64) (UINTN) *MemoryBase;\r
   MemorySize64  = (UINT64) (UINTN) *MemorySize;\r
   MemoryEnd64   = MemoryBase64 + MemorySize64;\r
 \r
+  Page1GSupport = IsPage1GSupport ();\r
+\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
   //\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 +430,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 +440,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
@@ -466,14 +455,14 @@ ModeSwitch (
   // Will save the return status of processing capsule\r
   //\r
   ReturnContext.ReturnStatus       = 0;\r
   // 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
   // Save original GDT\r
   //\r
   AsmReadGdtr ((IA32_DESCRIPTOR *)&ReturnContext.Gdtr);\r
-  \r
+\r
   Status = Thunk32To64 (LongModeBuffer->PageTableAddress, &Context, &ReturnContext);\r
   Status = Thunk32To64 (LongModeBuffer->PageTableAddress, &Context, &ReturnContext);\r
-  \r
+\r
   if (!EFI_ERROR (Status)) {\r
     *MemoryBase = (VOID *) (UINTN) MemoryBase64;\r
     *MemorySize = (UINTN) MemorySize64;\r
   if (!EFI_ERROR (Status)) {\r
     *MemoryBase = (VOID *) (UINTN) MemoryBase64;\r
     *MemorySize = (UINTN) MemorySize64;\r
@@ -529,7 +518,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,8 +531,265 @@ 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
 #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
+  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
+  @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
+  }\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
+  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
 /**\r
   Checks for the presence of capsule descriptors.\r
   Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...\r
@@ -575,7 +821,7 @@ GetCapsuleDescriptors (
   CapsuleVarName[0] = 0;\r
   ValidIndex        = 0;\r
   CapsuleDataPtr64  = 0;\r
   CapsuleVarName[0] = 0;\r
   ValidIndex        = 0;\r
   CapsuleDataPtr64  = 0;\r
-  \r
+\r
   Status = PeiServicesLocatePpi (\r
               &gEfiPeiReadOnlyVariable2PpiGuid,\r
               0,\r
   Status = PeiServicesLocatePpi (\r
               &gEfiPeiReadOnlyVariable2PpiGuid,\r
               0,\r
@@ -600,7 +846,7 @@ GetCapsuleDescriptors (
                                         (VOID *) &CapsuleDataPtr64\r
                                         );\r
         if (EFI_ERROR (Status)) {\r
                                         (VOID *) &CapsuleDataPtr64\r
                                         );\r
         if (EFI_ERROR (Status)) {\r
-          DEBUG ((EFI_D_ERROR, "Capsule -- capsule variable not set\n"));\r
+          DEBUG ((DEBUG_INFO, "Capsule -- capsule variable not set\n"));\r
           return EFI_NOT_FOUND;\r
         }\r
         //\r
           return EFI_NOT_FOUND;\r
         }\r
         //\r
@@ -614,7 +860,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
@@ -626,7 +878,7 @@ GetCapsuleDescriptors (
         if (EFI_ERROR (Status)) {\r
           break;\r
         }\r
         if (EFI_ERROR (Status)) {\r
           break;\r
         }\r
-        \r
+\r
         //\r
         // If this BlockList has been linked before, skip this variable\r
         //\r
         //\r
         // If this BlockList has been linked before, skip this variable\r
         //\r
@@ -642,7 +894,7 @@ GetCapsuleDescriptors (
           continue;\r
         }\r
       }\r
           continue;\r
         }\r
       }\r
-      \r
+\r
       //\r
       // Cache BlockList which has been processed\r
       //\r
       //\r
       // Cache BlockList which has been processed\r
       //\r
@@ -650,49 +902,8 @@ GetCapsuleDescriptors (
       Index ++;\r
     }\r
   }\r
       Index ++;\r
     }\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
 \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
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -731,11 +942,12 @@ CapsuleCoalesce (
   UINTN                                VariableCount;\r
   CHAR16                               CapsuleVarName[30];\r
   CHAR16                               *TempVarName;\r
   UINTN                                VariableCount;\r
   CHAR16                               CapsuleVarName[30];\r
   CHAR16                               *TempVarName;\r
-  EFI_PHYSICAL_ADDRESS                 CapsuleDataPtr64;  \r
+  EFI_PHYSICAL_ADDRESS                 CapsuleDataPtr64;\r
   EFI_STATUS                           Status;\r
   EFI_BOOT_MODE                        BootMode;\r
   EFI_PEI_READ_ONLY_VARIABLE2_PPI      *PPIVariableServices;\r
   EFI_PHYSICAL_ADDRESS                 *VariableArrayAddress;\r
   EFI_STATUS                           Status;\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
@@ -754,11 +966,11 @@ CapsuleCoalesce (
   //\r
   Status = PeiServicesGetBootMode (&BootMode);\r
   if (EFI_ERROR (Status) || (BootMode != BOOT_ON_FLASH_UPDATE)) {\r
   //\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 ((EFI_D_ERROR, "Boot mode is not correct for capsule update path.\n"));\r
     Status = EFI_NOT_FOUND;\r
     goto Done;\r
   }\r
     Status = EFI_NOT_FOUND;\r
     goto Done;\r
   }\r
-  \r
+\r
   //\r
   // User may set the same ScatterGatherList with several different variables,\r
   // so cache all ScatterGatherList for check later.\r
   //\r
   // User may set the same ScatterGatherList with several different variables,\r
   // so cache all ScatterGatherList for check later.\r
@@ -777,7 +989,13 @@ CapsuleCoalesce (
   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
@@ -797,9 +1015,9 @@ CapsuleCoalesce (
     VariableCount++;\r
     Index++;\r
   }\r
     VariableCount++;\r
     Index++;\r
   }\r
-  \r
+\r
   DEBUG ((EFI_D_INFO,"Capsule variable count = %d\n", VariableCount));\r
   DEBUG ((EFI_D_INFO,"Capsule variable count = %d\n", VariableCount));\r
-  \r
+\r
   //\r
   // The last entry is the end flag.\r
   //\r
   //\r
   // The last entry is the end flag.\r
   //\r
@@ -812,9 +1030,9 @@ CapsuleCoalesce (
     DEBUG ((EFI_D_ERROR, "AllocatePages Failed!, Status = %x\n", Status));\r
     goto Done;\r
   }\r
     DEBUG ((EFI_D_ERROR, "AllocatePages Failed!, Status = %x\n", Status));\r
     goto Done;\r
   }\r
-  \r
+\r
   ZeroMem (VariableArrayAddress, (VariableCount + 1) * sizeof (EFI_PHYSICAL_ADDRESS));\r
   ZeroMem (VariableArrayAddress, (VariableCount + 1) * sizeof (EFI_PHYSICAL_ADDRESS));\r
-  \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
   // Find out if we actually have a capsule.\r
   // GetCapsuleDescriptors depends on variable PPI, so it should run in 32-bit environment.\r
@@ -825,6 +1043,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
@@ -837,11 +1057,11 @@ 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
-    \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
     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
@@ -850,26 +1070,26 @@ 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
 #endif\r
-  \r
+\r
   DEBUG ((EFI_D_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
   }\r
   DEBUG ((EFI_D_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
   }\r
-  \r
+\r
   if (Status == EFI_NOT_FOUND) {\r
     DEBUG ((EFI_D_ERROR, "Fail to parse capsule descriptor in memory!\n"));\r
     REPORT_STATUS_CODE (\r
   if (Status == EFI_NOT_FOUND) {\r
     DEBUG ((EFI_D_ERROR, "Fail to parse capsule descriptor in memory!\n"));\r
     REPORT_STATUS_CODE (\r
@@ -902,9 +1122,9 @@ CheckCapsuleUpdate (
   return Status;\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
   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
   @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
@@ -993,7 +1213,7 @@ CreateState (
   UINT32                        Index;\r
   EFI_PHYSICAL_ADDRESS          BaseAddress;\r
   UINT64                        Length;\r
   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
   PrivateData    = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) CapsuleBase;\r
   if (PrivateData->Signature != EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE) {\r
     return EFI_VOLUME_CORRUPTED;\r
@@ -1031,7 +1251,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
@@ -1049,7 +1269,7 @@ CreateState (
 \r
     BuildCvHob (BaseAddress, Length);\r
   }\r
 \r
     BuildCvHob (BaseAddress, Length);\r
   }\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r