X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FCapsulePei%2FUefiCapsule.c;h=36b04e34064b1caec15d86b4fffb23e9bb6532af;hp=6b934c9e3c91408b39b41d50eb8fecef2a6effd0;hb=9d510e61fceee7b92955ef9a3c20343752d8ce3f;hpb=09d469952352f53df741a903a3f154360f38b8ca
diff --git a/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c b/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c
index 6b934c9e3c..36b04e3406 100644
--- a/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c
+++ b/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c
@@ -1,16 +1,10 @@
/** @file
Capsule update PEIM for UEFI2.0
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2017, AMD Incorporated. All rights reserved.
-This program and the accompanying materials
-are licensed and made available under the terms and conditions
-of the BSD License which accompanies this distribution. The
-full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -41,25 +35,21 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = {
(UINTN) mGdtEntries
};
+
/**
- Calculate the total size of page table.
-
- @return The size of page table.
-
-
+ The function will check if 1G page is supported.
+
+ @retval TRUE 1G page is supported.
+ @retval FALSE 1G page is not supported.
+
**/
-UINTN
-CalculatePageTableSize (
+BOOLEAN
+IsPage1GSupport (
VOID
)
{
UINT32 RegEax;
UINT32 RegEdx;
- UINTN TotalPagesNum;
- UINT8 PhysicalAddressBits;
- VOID *Hob;
- UINT32 NumberOfPml4EntriesNeeded;
- UINT32 NumberOfPdpEntriesNeeded;
BOOLEAN Page1GSupport;
Page1GSupport = FALSE;
@@ -73,29 +63,34 @@ CalculatePageTableSize (
}
}
- //
- // Get physical address bits supported.
- //
- Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
- if (Hob != NULL) {
- PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
- } else {
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
- if (RegEax >= 0x80000008) {
- AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
- PhysicalAddressBits = (UINT8) RegEax;
- } else {
- PhysicalAddressBits = 36;
- }
- }
+ return Page1GSupport;
+}
+
+/**
+ Calculate the total size of page table.
+
+ @param[in] Page1GSupport 1G page support or not.
+
+ @return The size of page table.
+
+**/
+UINTN
+CalculatePageTableSize (
+ IN BOOLEAN Page1GSupport
+ )
+{
+ UINTN ExtraPageTablePages;
+ UINTN TotalPagesNum;
+ UINT8 PhysicalAddressBits;
+ UINT32 NumberOfPml4EntriesNeeded;
+ UINT32 NumberOfPdpEntriesNeeded;
//
- // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
+ // Create 4G page table by default,
+ // and let PF handler to handle > 4G request.
//
- ASSERT (PhysicalAddressBits <= 52);
- if (PhysicalAddressBits > 48) {
- PhysicalAddressBits = 48;
- }
+ PhysicalAddressBits = 32;
+ ExtraPageTablePages = EXTRA_PAGE_TABLE_PAGES;
//
// Calculate the table entries needed.
@@ -113,24 +108,25 @@ CalculatePageTableSize (
} else {
TotalPagesNum = NumberOfPml4EntriesNeeded + 1;
}
+ TotalPagesNum += ExtraPageTablePages;
return EFI_PAGES_TO_SIZE (TotalPagesNum);
}
/**
Allocates and fills in the Page Directory and Page Table Entries to
- establish a 1:1 Virtual to Physical mapping.
+ establish a 4G page table.
- @param[in] PageTablesAddress The base address of page table.
+ @param[in] PageTablesAddress The base address of page table.
+ @param[in] Page1GSupport 1G page support or not.
**/
VOID
-CreateIdentityMappingPageTables (
- IN EFI_PHYSICAL_ADDRESS PageTablesAddress
+Create4GPageTables (
+ IN EFI_PHYSICAL_ADDRESS PageTablesAddress,
+ IN BOOLEAN Page1GSupport
)
-{
- UINT32 RegEax;
- UINT32 RegEdx;
+{
UINT8 PhysicalAddressBits;
EFI_PHYSICAL_ADDRESS PageAddress;
UINTN IndexOfPml4Entries;
@@ -143,42 +139,19 @@ CreateIdentityMappingPageTables (
PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
PAGE_TABLE_ENTRY *PageDirectoryEntry;
UINTN BigPageAddress;
- VOID *Hob;
- BOOLEAN Page1GSupport;
PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
-
- Page1GSupport = FALSE;
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
- if (RegEax >= 0x80000001) {
- AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & BIT26) != 0) {
- Page1GSupport = TRUE;
- }
- }
+ UINT64 AddressEncMask;
//
- // Get physical address bits supported.
+ // Make sure AddressEncMask is contained to smallest supported address field.
//
- Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
- if (Hob != NULL) {
- PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
- } else {
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
- if (RegEax >= 0x80000008) {
- AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
- PhysicalAddressBits = (UINT8) RegEax;
- } else {
- PhysicalAddressBits = 36;
- }
- }
+ AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
//
- // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
+ // Create 4G page table by default,
+ // and let PF handler to handle > 4G request.
//
- ASSERT (PhysicalAddressBits <= 52);
- if (PhysicalAddressBits > 48) {
- PhysicalAddressBits = 48;
- }
+ PhysicalAddressBits = 32;
//
// Calculate the table entries needed.
@@ -192,7 +165,7 @@ CreateIdentityMappingPageTables (
}
//
- // Pre-allocate big pages to avoid later allocations.
+ // Pre-allocate big pages to avoid later allocations.
//
BigPageAddress = (UINTN) PageTablesAddress;
@@ -215,18 +188,18 @@ CreateIdentityMappingPageTables (
//
// Make a PML4 Entry
//
- PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
+ PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry | AddressEncMask;
PageMapLevel4Entry->Bits.ReadWrite = 1;
PageMapLevel4Entry->Bits.Present = 1;
if (Page1GSupport) {
PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
-
+
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
//
// Fill in the Page Directory entries
//
- PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;
+ PageDirectory1GEntry->Uint64 = (UINT64)PageAddress | AddressEncMask;
PageDirectory1GEntry->Bits.ReadWrite = 1;
PageDirectory1GEntry->Bits.Present = 1;
PageDirectory1GEntry->Bits.MustBe1 = 1;
@@ -236,14 +209,14 @@ CreateIdentityMappingPageTables (
//
// Each Directory Pointer entries points to a page of Page Directory entires.
// So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
- //
+ //
PageDirectoryEntry = (VOID *) BigPageAddress;
BigPageAddress += SIZE_4KB;
//
// Fill in a Page Directory Pointer Entries
//
- PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;
+ PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry | AddressEncMask;
PageDirectoryPointerEntry->Bits.ReadWrite = 1;
PageDirectoryPointerEntry->Bits.Present = 1;
@@ -251,7 +224,7 @@ CreateIdentityMappingPageTables (
//
// Fill in the Page Directory entries
//
- PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
+ PageDirectoryEntry->Uint64 = (UINT64)PageAddress | AddressEncMask;
PageDirectoryEntry->Bits.ReadWrite = 1;
PageDirectoryEntry->Bits.Present = 1;
PageDirectoryEntry->Bits.MustBe1 = 1;
@@ -290,20 +263,20 @@ ReturnFunction (
SWITCH_32_TO_64_CONTEXT *EntrypointContext,
SWITCH_64_TO_32_CONTEXT *ReturnContext
)
-{
+{
//
// Restore original GDT
//
AsmWriteGdtr (&ReturnContext->Gdtr);
-
+
//
// return to original caller
//
LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)EntrypointContext->JumpBuffer, 1);
-
+
//
// never be here
- //
+ //
ASSERT (FALSE);
}
@@ -335,10 +308,10 @@ Thunk32To64 (
if (SetJumpFlag == 0) {
//
- // Build Page Tables for all physical memory processor supports
+ // Build 4G Page Tables.
//
- CreateIdentityMappingPageTables (PageTableAddress);
-
+ Create4GPageTables (PageTableAddress, Context->Page1GSupport);
+
//
// Create 64-bit GDT
//
@@ -349,6 +322,14 @@ Thunk32To64 (
//
AsmWriteCr3 ((UINTN) PageTableAddress);
+ DEBUG ((
+ DEBUG_INFO,
+ "%a() Stack Base: 0x%lx, Stack Size: 0x%lx\n",
+ __FUNCTION__,
+ Context->StackBufferBase,
+ Context->StackBufferLength
+ ));
+
//
// Disable interrupt of Debug timer, since the IDT table cannot work in long mode
//
@@ -364,7 +345,7 @@ Thunk32To64 (
Context->StackBufferBase + Context->StackBufferLength
);
}
-
+
//
// Convert to 32-bit Status and return
//
@@ -372,7 +353,7 @@ Thunk32To64 (
if ((UINTN) ReturnContext->ReturnStatus != 0) {
Status = ENCODE_ERROR ((UINTN) ReturnContext->ReturnStatus);
}
-
+
return Status;
}
@@ -382,6 +363,7 @@ Thunk32To64 (
@param LongModeBuffer The context of long mode.
@param CoalesceEntry Entry of coalesce image.
@param BlockListAddr Address of block list.
+ @param MemoryResource Pointer to the buffer of memory resource descriptor.
@param MemoryBase Base of memory range.
@param MemorySize Size of memory range.
@@ -394,6 +376,7 @@ ModeSwitch (
IN EFI_CAPSULE_LONG_MODE_BUFFER *LongModeBuffer,
IN COALESCE_ENTRY CoalesceEntry,
IN EFI_PHYSICAL_ADDRESS BlockListAddr,
+ IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource,
IN OUT VOID **MemoryBase,
IN OUT UINTN *MemorySize
)
@@ -407,25 +390,28 @@ ModeSwitch (
BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
EFI_PHYSICAL_ADDRESS ReservedRangeBase;
EFI_PHYSICAL_ADDRESS ReservedRangeEnd;
+ BOOLEAN Page1GSupport;
ZeroMem (&Context, sizeof (SWITCH_32_TO_64_CONTEXT));
ZeroMem (&ReturnContext, sizeof (SWITCH_64_TO_32_CONTEXT));
-
+
MemoryBase64 = (UINT64) (UINTN) *MemoryBase;
MemorySize64 = (UINT64) (UINTN) *MemorySize;
MemoryEnd64 = MemoryBase64 + MemorySize64;
+ Page1GSupport = IsPage1GSupport ();
+
//
- // Merge memory range reserved for stack and page table
+ // Merge memory range reserved for stack and page table
//
if (LongModeBuffer->StackBaseAddress < LongModeBuffer->PageTableAddress) {
ReservedRangeBase = LongModeBuffer->StackBaseAddress;
- ReservedRangeEnd = LongModeBuffer->PageTableAddress + CalculatePageTableSize ();
+ ReservedRangeEnd = LongModeBuffer->PageTableAddress + CalculatePageTableSize (Page1GSupport);
} else {
ReservedRangeBase = LongModeBuffer->PageTableAddress;
ReservedRangeEnd = LongModeBuffer->StackBaseAddress + LongModeBuffer->StackSize;
}
-
+
//
// Check if memory range reserved is overlap with MemoryBase ~ MemoryBase + MemorySize.
// If they are overlapped, get a larger range to process capsule data.
@@ -444,8 +430,8 @@ ModeSwitch (
} else {
MemorySize64 = (UINT64)(UINTN)(ReservedRangeBase - MemoryBase64);
}
- }
-
+ }
+
//
// Initialize context jumping to 64-bit enviroment
//
@@ -454,8 +440,11 @@ ModeSwitch (
Context.StackBufferLength = LongModeBuffer->StackSize;
Context.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)CoalesceEntry;
Context.BlockListAddr = BlockListAddr;
+ Context.MemoryResource = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryResource;
Context.MemoryBase64Ptr = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemoryBase64;
Context.MemorySize64Ptr = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemorySize64;
+ Context.Page1GSupport = Page1GSupport;
+ Context.AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
//
// Prepare data for return back
@@ -466,14 +455,14 @@ ModeSwitch (
// Will save the return status of processing capsule
//
ReturnContext.ReturnStatus = 0;
-
+
//
// Save original GDT
//
AsmReadGdtr ((IA32_DESCRIPTOR *)&ReturnContext.Gdtr);
-
+
Status = Thunk32To64 (LongModeBuffer->PageTableAddress, &Context, &ReturnContext);
-
+
if (!EFI_ERROR (Status)) {
*MemoryBase = (VOID *) (UINTN) MemoryBase64;
*MemorySize = (UINTN) MemorySize64;
@@ -529,7 +518,7 @@ FindCapsuleCoalesceImage (
&AuthenticationState
);
if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Unable to find PE32 section in CapsuleRelocate image ffs %r!\n", Status));
+ DEBUG ((EFI_D_ERROR, "Unable to find PE32 section in CapsuleX64 image ffs %r!\n", Status));
return Status;
}
*CoalesceImageMachineType = PeCoffLoaderGetMachineType ((VOID *) (UINTN) CoalesceImageAddress);
@@ -542,8 +531,265 @@ FindCapsuleCoalesceImage (
return Status;
}
+/**
+ Gets the reserved long mode buffer.
+
+ @param LongModeBuffer Pointer to the long mode buffer for output.
+
+ @retval EFI_SUCCESS Long mode buffer successfully retrieved.
+ @retval Others Variable storing long mode buffer not found.
+
+**/
+EFI_STATUS
+GetLongModeContext (
+ OUT EFI_CAPSULE_LONG_MODE_BUFFER *LongModeBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PPIVariableServices
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Size = sizeof (EFI_CAPSULE_LONG_MODE_BUFFER);
+ Status = PPIVariableServices->GetVariable (
+ PPIVariableServices,
+ EFI_CAPSULE_LONG_MODE_BUFFER_NAME,
+ &gEfiCapsuleVendorGuid,
+ NULL,
+ &Size,
+ LongModeBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "Error Get LongModeBuffer variable %r!\n", Status));
+ }
+ return Status;
+}
#endif
+#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
+/**
+ Get physical address bits.
+
+ @return Physical address bits.
+
+**/
+UINT8
+GetPhysicalAddressBits (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT8 PhysicalAddressBits;
+ VOID *Hob;
+
+ //
+ // Get physical address bits supported.
+ //
+ Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
+ if (Hob != NULL) {
+ PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
+ } else {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8) RegEax;
+ } else {
+ PhysicalAddressBits = 36;
+ }
+ }
+
+ //
+ // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
+ //
+ ASSERT (PhysicalAddressBits <= 52);
+ if (PhysicalAddressBits > 48) {
+ PhysicalAddressBits = 48;
+ }
+
+ return PhysicalAddressBits;
+}
+#endif
+
+/**
+ Sort memory resource entries based upon PhysicalStart, from low to high.
+
+ @param[in, out] MemoryResource A pointer to the memory resource entry buffer.
+
+**/
+VOID
+SortMemoryResourceDescriptor (
+ IN OUT MEMORY_RESOURCE_DESCRIPTOR *MemoryResource
+ )
+{
+ MEMORY_RESOURCE_DESCRIPTOR *MemoryResourceEntry;
+ MEMORY_RESOURCE_DESCRIPTOR *NextMemoryResourceEntry;
+ MEMORY_RESOURCE_DESCRIPTOR TempMemoryResource;
+
+ MemoryResourceEntry = MemoryResource;
+ NextMemoryResourceEntry = MemoryResource + 1;
+ while (MemoryResourceEntry->ResourceLength != 0) {
+ while (NextMemoryResourceEntry->ResourceLength != 0) {
+ if (MemoryResourceEntry->PhysicalStart > NextMemoryResourceEntry->PhysicalStart) {
+ CopyMem (&TempMemoryResource, MemoryResourceEntry, sizeof (MEMORY_RESOURCE_DESCRIPTOR));
+ CopyMem (MemoryResourceEntry, NextMemoryResourceEntry, sizeof (MEMORY_RESOURCE_DESCRIPTOR));
+ CopyMem (NextMemoryResourceEntry, &TempMemoryResource, sizeof (MEMORY_RESOURCE_DESCRIPTOR));
+ }
+
+ NextMemoryResourceEntry = NextMemoryResourceEntry + 1;
+ }
+
+ MemoryResourceEntry = MemoryResourceEntry + 1;
+ NextMemoryResourceEntry = MemoryResourceEntry + 1;
+ }
+}
+
+/**
+ Merge continous memory resource entries.
+
+ @param[in, out] MemoryResource A pointer to the memory resource entry buffer.
+
+**/
+VOID
+MergeMemoryResourceDescriptor (
+ IN OUT MEMORY_RESOURCE_DESCRIPTOR *MemoryResource
+ )
+{
+ MEMORY_RESOURCE_DESCRIPTOR *MemoryResourceEntry;
+ MEMORY_RESOURCE_DESCRIPTOR *NewMemoryResourceEntry;
+ MEMORY_RESOURCE_DESCRIPTOR *NextMemoryResourceEntry;
+ MEMORY_RESOURCE_DESCRIPTOR *MemoryResourceEnd;
+
+ MemoryResourceEntry = MemoryResource;
+ NewMemoryResourceEntry = MemoryResource;
+ while (MemoryResourceEntry->ResourceLength != 0) {
+ CopyMem (NewMemoryResourceEntry, MemoryResourceEntry, sizeof (MEMORY_RESOURCE_DESCRIPTOR));
+ NextMemoryResourceEntry = MemoryResourceEntry + 1;
+
+ while ((NextMemoryResourceEntry->ResourceLength != 0) &&
+ (NextMemoryResourceEntry->PhysicalStart == (MemoryResourceEntry->PhysicalStart + MemoryResourceEntry->ResourceLength))) {
+ MemoryResourceEntry->ResourceLength += NextMemoryResourceEntry->ResourceLength;
+ if (NewMemoryResourceEntry != MemoryResourceEntry) {
+ NewMemoryResourceEntry->ResourceLength += NextMemoryResourceEntry->ResourceLength;
+ }
+
+ NextMemoryResourceEntry = NextMemoryResourceEntry + 1;
+ }
+
+ MemoryResourceEntry = NextMemoryResourceEntry;
+ NewMemoryResourceEntry = NewMemoryResourceEntry + 1;
+ }
+
+ //
+ // Set NULL terminate memory resource descriptor after merging.
+ //
+ MemoryResourceEnd = NewMemoryResourceEntry;
+ ZeroMem (MemoryResourceEnd, sizeof (MEMORY_RESOURCE_DESCRIPTOR));
+}
+
+/**
+ Build memory resource descriptor from resource descriptor in HOB list.
+
+ @return Pointer to the buffer of memory resource descriptor.
+ NULL if no memory resource descriptor reported in HOB list
+ before capsule Coalesce.
+
+**/
+MEMORY_RESOURCE_DESCRIPTOR *
+BuildMemoryResourceDescriptor (
+ VOID
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN Index;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor;
+ MEMORY_RESOURCE_DESCRIPTOR *MemoryResource;
+ EFI_STATUS Status;
+
+ //
+ // Get the count of memory resource descriptor.
+ //
+ Index = 0;
+ Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+ while (Hob.Raw != NULL) {
+ ResourceDescriptor = (EFI_HOB_RESOURCE_DESCRIPTOR *) Hob.Raw;
+ if (ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+ Index++;
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
+ }
+
+ if (Index == 0) {
+ DEBUG ((EFI_D_INFO | EFI_D_WARN, "No memory resource descriptor reported in HOB list before capsule Coalesce\n"));
+#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
+ //
+ // Allocate memory to hold memory resource descriptor,
+ // include extra one NULL terminate memory resource descriptor.
+ //
+ Status = PeiServicesAllocatePool ((1 + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR), (VOID **) &MemoryResource);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem (MemoryResource, (1 + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR));
+
+ MemoryResource[0].PhysicalStart = 0;
+ MemoryResource[0].ResourceLength = LShiftU64 (1, GetPhysicalAddressBits ());
+ DEBUG ((EFI_D_INFO, "MemoryResource[0x0] - Start(0x%0lx) Length(0x%0lx)\n",
+ MemoryResource[0x0].PhysicalStart, MemoryResource[0x0].ResourceLength));
+ return MemoryResource;
+#else
+ return NULL;
+#endif
+ }
+
+ //
+ // Allocate memory to hold memory resource descriptor,
+ // include extra one NULL terminate memory resource descriptor.
+ //
+ Status = PeiServicesAllocatePool ((Index + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR), (VOID **) &MemoryResource);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem (MemoryResource, (Index + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR));
+
+ //
+ // Get the content of memory resource descriptor.
+ //
+ Index = 0;
+ Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+ while (Hob.Raw != NULL) {
+ ResourceDescriptor = (EFI_HOB_RESOURCE_DESCRIPTOR *) Hob.Raw;
+ if (ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+ DEBUG ((EFI_D_INFO, "MemoryResource[0x%x] - Start(0x%0lx) Length(0x%0lx)\n",
+ Index, ResourceDescriptor->PhysicalStart, ResourceDescriptor->ResourceLength));
+ MemoryResource[Index].PhysicalStart = ResourceDescriptor->PhysicalStart;
+ MemoryResource[Index].ResourceLength = ResourceDescriptor->ResourceLength;
+ Index++;
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
+ }
+
+ SortMemoryResourceDescriptor (MemoryResource);
+ MergeMemoryResourceDescriptor (MemoryResource);
+
+ DEBUG ((DEBUG_INFO, "Dump MemoryResource[] after sorted and merged\n"));
+ for (Index = 0; MemoryResource[Index].ResourceLength != 0; Index++) {
+ DEBUG ((
+ DEBUG_INFO,
+ " MemoryResource[0x%x] - Start(0x%0lx) Length(0x%0lx)\n",
+ Index,
+ MemoryResource[Index].PhysicalStart,
+ MemoryResource[Index].ResourceLength
+ ));
+ }
+
+ return MemoryResource;
+}
+
/**
Checks for the presence of capsule descriptors.
Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
@@ -575,7 +821,7 @@ GetCapsuleDescriptors (
CapsuleVarName[0] = 0;
ValidIndex = 0;
CapsuleDataPtr64 = 0;
-
+
Status = PeiServicesLocatePpi (
&gEfiPeiReadOnlyVariable2PpiGuid,
0,
@@ -583,7 +829,7 @@ GetCapsuleDescriptors (
(VOID **) &PPIVariableServices
);
if (Status == EFI_SUCCESS) {
- StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);
+ StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME);
TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
Size = sizeof (CapsuleDataPtr64);
while (1) {
@@ -600,7 +846,7 @@ GetCapsuleDescriptors (
(VOID *) &CapsuleDataPtr64
);
if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Capsule -- capsule variable not set\n"));
+ DEBUG ((DEBUG_INFO, "Capsule -- capsule variable not set\n"));
return EFI_NOT_FOUND;
}
//
@@ -614,7 +860,13 @@ GetCapsuleDescriptors (
return EFI_SUCCESS;
}
} else {
- UnicodeValueToString (TempVarName, 0, Index, 0);
+ UnicodeValueToStringS (
+ TempVarName,
+ sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),
+ 0,
+ Index,
+ 0
+ );
Status = PPIVariableServices->GetVariable (
PPIVariableServices,
CapsuleVarName,
@@ -626,7 +878,7 @@ GetCapsuleDescriptors (
if (EFI_ERROR (Status)) {
break;
}
-
+
//
// If this BlockList has been linked before, skip this variable
//
@@ -642,7 +894,7 @@ GetCapsuleDescriptors (
continue;
}
}
-
+
//
// Cache BlockList which has been processed
//
@@ -650,49 +902,8 @@ GetCapsuleDescriptors (
Index ++;
}
}
-
- return EFI_SUCCESS;
-}
-
-/**
- Gets the reserved long mode buffer.
-
- @param LongModeBuffer Pointer to the long mode buffer for output.
-
- @retval EFI_SUCCESS Long mode buffer successfully retrieved.
- @retval Others Variable storing long mode buffer not found.
-
-**/
-EFI_STATUS
-GetLongModeContext (
- OUT EFI_CAPSULE_LONG_MODE_BUFFER *LongModeBuffer
- )
-{
- EFI_STATUS Status;
- UINTN Size;
- EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
-
- Status = PeiServicesLocatePpi (
- &gEfiPeiReadOnlyVariable2PpiGuid,
- 0,
- NULL,
- (VOID **) &PPIVariableServices
- );
- ASSERT_EFI_ERROR (Status);
- Size = sizeof (EFI_CAPSULE_LONG_MODE_BUFFER);
- Status = PPIVariableServices->GetVariable (
- PPIVariableServices,
- EFI_CAPSULE_LONG_MODE_BUFFER_NAME,
- &gEfiCapsuleVendorGuid,
- NULL,
- &Size,
- LongModeBuffer
- );
- if (EFI_ERROR (Status)) {
- DEBUG (( EFI_D_ERROR, "Error Get LongModeBuffer variable %r!\n", Status));
- }
- return Status;
+ return EFI_SUCCESS;
}
/**
@@ -731,11 +942,12 @@ CapsuleCoalesce (
UINTN VariableCount;
CHAR16 CapsuleVarName[30];
CHAR16 *TempVarName;
- EFI_PHYSICAL_ADDRESS CapsuleDataPtr64;
+ EFI_PHYSICAL_ADDRESS CapsuleDataPtr64;
EFI_STATUS Status;
EFI_BOOT_MODE BootMode;
EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
EFI_PHYSICAL_ADDRESS *VariableArrayAddress;
+ MEMORY_RESOURCE_DESCRIPTOR *MemoryResource;
#ifdef MDE_CPU_IA32
UINT16 CoalesceImageMachineType;
EFI_PHYSICAL_ADDRESS CoalesceImageEntryPoint;
@@ -754,11 +966,11 @@ CapsuleCoalesce (
//
Status = PeiServicesGetBootMode (&BootMode);
if (EFI_ERROR (Status) || (BootMode != BOOT_ON_FLASH_UPDATE)) {
- DEBUG ((EFI_D_ERROR, "Boot mode is not correct for capsule update path.\n"));
+ DEBUG ((EFI_D_ERROR, "Boot mode is not correct for capsule update path.\n"));
Status = EFI_NOT_FOUND;
goto Done;
}
-
+
//
// User may set the same ScatterGatherList with several different variables,
// so cache all ScatterGatherList for check later.
@@ -773,11 +985,17 @@ CapsuleCoalesce (
goto Done;
}
Size = sizeof (CapsuleDataPtr64);
- StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);
+ StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME);
TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
while (TRUE) {
if (Index > 0) {
- UnicodeValueToString (TempVarName, 0, Index, 0);
+ UnicodeValueToStringS (
+ TempVarName,
+ sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),
+ 0,
+ Index,
+ 0
+ );
}
Status = PPIVariableServices->GetVariable (
PPIVariableServices,
@@ -797,9 +1015,9 @@ CapsuleCoalesce (
VariableCount++;
Index++;
}
-
+
DEBUG ((EFI_D_INFO,"Capsule variable count = %d\n", VariableCount));
-
+
//
// The last entry is the end flag.
//
@@ -812,9 +1030,9 @@ CapsuleCoalesce (
DEBUG ((EFI_D_ERROR, "AllocatePages Failed!, Status = %x\n", Status));
goto Done;
}
-
+
ZeroMem (VariableArrayAddress, (VariableCount + 1) * sizeof (EFI_PHYSICAL_ADDRESS));
-
+
//
// Find out if we actually have a capsule.
// GetCapsuleDescriptors depends on variable PPI, so it should run in 32-bit environment.
@@ -825,6 +1043,8 @@ CapsuleCoalesce (
goto Done;
}
+ MemoryResource = BuildMemoryResourceDescriptor ();
+
#ifdef MDE_CPU_IA32
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
//
@@ -837,11 +1057,11 @@ CapsuleCoalesce (
CoalesceImageEntryPoint = 0;
Status = GetLongModeContext (&LongModeBuffer);
if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Fail to find the variables for long mode context!\n"));
+ DEBUG ((EFI_D_ERROR, "Fail to find the variable for long mode context!\n"));
Status = EFI_NOT_FOUND;
goto Done;
}
-
+
Status = FindCapsuleCoalesceImage (&CoalesceImageEntryPoint, &CoalesceImageMachineType);
if ((EFI_ERROR (Status)) || (CoalesceImageMachineType != EFI_IMAGE_MACHINE_X64)) {
DEBUG ((EFI_D_ERROR, "Fail to find CapsuleX64 module in FV!\n"));
@@ -850,26 +1070,26 @@ CapsuleCoalesce (
}
ASSERT (CoalesceImageEntryPoint != 0);
CoalesceEntry = (COALESCE_ENTRY) (UINTN) CoalesceImageEntryPoint;
- Status = ModeSwitch (&LongModeBuffer, CoalesceEntry, (EFI_PHYSICAL_ADDRESS)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);
+ Status = ModeSwitch (&LongModeBuffer, CoalesceEntry, (EFI_PHYSICAL_ADDRESS)(UINTN)VariableArrayAddress, MemoryResource, MemoryBase, MemorySize);
} else {
//
// Capsule is processed in IA32 mode.
//
- Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);
+ Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryResource, MemoryBase, MemorySize);
}
#else
//
// Process capsule directly.
//
- Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);
+ Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryResource, MemoryBase, MemorySize);
#endif
-
+
DEBUG ((EFI_D_INFO, "Capsule Coalesce Status = %r!\n", Status));
if (Status == EFI_BUFFER_TOO_SMALL) {
DEBUG ((EFI_D_ERROR, "There is not enough memory to process capsule!\n"));
}
-
+
if (Status == EFI_NOT_FOUND) {
DEBUG ((EFI_D_ERROR, "Fail to parse capsule descriptor in memory!\n"));
REPORT_STATUS_CODE (
@@ -902,9 +1122,9 @@ CheckCapsuleUpdate (
return Status;
}
/**
- This function will look at a capsule and determine if it's a test pattern.
+ This function will look at a capsule and determine if it's a test pattern.
If it is, then it will verify it and emit an error message if corruption is detected.
-
+
@param PeiServices Standard pei services pointer
@param CapsuleBase Base address of coalesced capsule, which is preceeded
by private data. Very implementation specific.
@@ -993,7 +1213,7 @@ CreateState (
UINT32 Index;
EFI_PHYSICAL_ADDRESS BaseAddress;
UINT64 Length;
-
+
PrivateData = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) CapsuleBase;
if (PrivateData->Signature != EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE) {
return EFI_VOLUME_CORRUPTED;
@@ -1031,7 +1251,7 @@ CreateState (
CopyMem ((VOID *) (UINTN) NewBuffer, (VOID *) (UINTN) ((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), Size);
//
// Check for test data pattern. If it is the test pattern, then we'll
- // test it ans still create the HOB so that it can be used to verify
+ // test it and still create the HOB so that it can be used to verify
// that capsules don't get corrupted all the way into BDS. BDS will
// still try to turn it into a firmware volume, but will think it's
// corrupted so nothing will happen.
@@ -1049,7 +1269,7 @@ CreateState (
BuildCvHob (BaseAddress, Length);
}
-
+
return EFI_SUCCESS;
}