/** @file\r
Capsule update PEIM for UEFI2.0\r
\r
-Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions\r
-of the BSD License which accompanies this distribution. The\r
-full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
IN EFI_PHYSICAL_ADDRESS PageTablesAddress,\r
IN BOOLEAN Page1GSupport\r
)\r
-{ \r
+{\r
UINT8 PhysicalAddressBits;\r
EFI_PHYSICAL_ADDRESS PageAddress;\r
UINTN IndexOfPml4Entries;\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
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
// 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
if ((UINTN) ReturnContext->ReturnStatus != 0) {\r
Status = ENCODE_ERROR ((UINTN) ReturnContext->ReturnStatus);\r
}\r
- \r
+\r
return Status;\r
}\r
\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
Page1GSupport = IsPage1GSupport ();\r
\r
//\r
- // Merge memory range reserved for stack and page table \r
+ // Merge memory range reserved for stack and page table\r
//\r
if (LongModeBuffer->StackBaseAddress < LongModeBuffer->PageTableAddress) {\r
ReservedRangeBase = LongModeBuffer->StackBaseAddress;\r
if (ReservedRangeEnd < MemoryEnd64) {\r
MemoryBase64 = ReservedRangeEnd;\r
} else {\r
- DEBUG ((EFI_D_ERROR, "Memory is not enough to process capsule!\n"));\r
+ DEBUG ((DEBUG_ERROR, "Memory is not enough to process capsule!\n"));\r
return EFI_OUT_OF_RESOURCES;\r
}\r
} else if (ReservedRangeBase < MemoryEnd64) {\r
// Will save the return status of processing capsule\r
//\r
ReturnContext.ReturnStatus = 0;\r
- \r
+\r
//\r
// Save original GDT\r
//\r
AsmReadGdtr ((IA32_DESCRIPTOR *)&ReturnContext.Gdtr);\r
- \r
+\r
Status = Thunk32To64 (LongModeBuffer->PageTableAddress, &Context, &ReturnContext);\r
- \r
+\r
if (!EFI_ERROR (Status)) {\r
*MemoryBase = (VOID *) (UINTN) MemoryBase64;\r
*MemorySize = (UINTN) MemorySize64;\r
&AuthenticationState\r
);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Unable to find PE32 section in CapsuleX64 image ffs %r!\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "Unable to find PE32 section in CapsuleX64 image ffs %r!\n", Status));\r
return Status;\r
}\r
*CoalesceImageMachineType = PeCoffLoaderGetMachineType ((VOID *) (UINTN) CoalesceImageAddress);\r
LongModeBuffer\r
);\r
if (EFI_ERROR (Status)) {\r
- DEBUG (( EFI_D_ERROR, "Error Get LongModeBuffer variable %r!\n", Status));\r
+ DEBUG (( DEBUG_ERROR, "Error Get LongModeBuffer variable %r!\n", Status));\r
}\r
return Status;\r
}\r
}\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
}\r
\r
if (Index == 0) {\r
- DEBUG ((EFI_D_INFO | EFI_D_WARN, "No memory resource descriptor reported in HOB list before capsule Coalesce\n"));\r
+ DEBUG ((DEBUG_INFO | DEBUG_WARN, "No memory resource descriptor reported in HOB list before capsule Coalesce\n"));\r
#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)\r
//\r
// Allocate memory to hold memory resource descriptor,\r
Status = PeiServicesAllocatePool ((1 + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR), (VOID **) &MemoryResource);\r
ASSERT_EFI_ERROR (Status);\r
ZeroMem (MemoryResource, (1 + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
- \r
+\r
MemoryResource[0].PhysicalStart = 0;\r
MemoryResource[0].ResourceLength = LShiftU64 (1, GetPhysicalAddressBits ());\r
- DEBUG ((EFI_D_INFO, "MemoryResource[0x0] - Start(0x%0lx) Length(0x%0lx)\n",\r
+ DEBUG ((DEBUG_INFO, "MemoryResource[0x0] - Start(0x%0lx) Length(0x%0lx)\n",\r
MemoryResource[0x0].PhysicalStart, MemoryResource[0x0].ResourceLength));\r
return MemoryResource;\r
#else\r
while (Hob.Raw != NULL) {\r
ResourceDescriptor = (EFI_HOB_RESOURCE_DESCRIPTOR *) Hob.Raw;\r
if (ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
- DEBUG ((EFI_D_INFO, "MemoryResource[0x%x] - Start(0x%0lx) Length(0x%0lx)\n",\r
+ DEBUG ((DEBUG_INFO, "MemoryResource[0x%x] - Start(0x%0lx) Length(0x%0lx)\n",\r
Index, ResourceDescriptor->PhysicalStart, ResourceDescriptor->ResourceLength));\r
MemoryResource[Index].PhysicalStart = ResourceDescriptor->PhysicalStart;\r
MemoryResource[Index].ResourceLength = ResourceDescriptor->ResourceLength;\r
Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);\r
}\r
\r
+ SortMemoryResourceDescriptor (MemoryResource);\r
+ MergeMemoryResourceDescriptor (MemoryResource);\r
+\r
+ DEBUG ((DEBUG_INFO, "Dump MemoryResource[] after sorted and merged\n"));\r
+ for (Index = 0; MemoryResource[Index].ResourceLength != 0; Index++) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " MemoryResource[0x%x] - Start(0x%0lx) Length(0x%0lx)\n",\r
+ Index,\r
+ MemoryResource[Index].PhysicalStart,\r
+ MemoryResource[Index].ResourceLength\r
+ ));\r
+ }\r
+\r
return MemoryResource;\r
}\r
\r
/**\r
- Checks for the presence of capsule descriptors.\r
- Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...\r
- and save to DescriptorBuffer.\r
+ Check if the capsules are staged.\r
+\r
+ @param UpdateCapsules A pointer to return the check result.\r
+\r
+ @retval EFI_INVALID_PARAMETER The parameter is null.\r
+ @retval EFI_SUCCESS The Capsules are staged.\r
+\r
+**/\r
+EFI_STATUS\r
+AreCapsulesStaged (\r
+ OUT BOOLEAN *UpdateCapsules\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Size;\r
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;\r
+ EFI_PHYSICAL_ADDRESS CapsuleDataPtr64 = 0;\r
+\r
+ if (UpdateCapsules == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "%a Invalid parameters. Inputs can't be NULL\n", __FUNCTION__));\r
+ ASSERT (UpdateCapsules != NULL);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *UpdateCapsules = FALSE;\r
+\r
+ Status = PeiServicesLocatePpi(\r
+ &gEfiPeiReadOnlyVariable2PpiGuid,\r
+ 0,\r
+ NULL,\r
+ (VOID **)&PPIVariableServices\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to find ReadOnlyVariable2PPI\n"));\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Check for Update capsule\r
+ //\r
+ Size = sizeof (CapsuleDataPtr64);\r
+ Status = PPIVariableServices->GetVariable (\r
+ PPIVariableServices,\r
+ EFI_CAPSULE_VARIABLE_NAME,\r
+ &gEfiCapsuleVendorGuid,\r
+ NULL,\r
+ &Size,\r
+ (VOID *)&CapsuleDataPtr64\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ *UpdateCapsules = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+#define MAX_SG_LIST_HEADS (20)\r
+\r
+/**\r
+ Check all the variables for SG list heads and get the count and addresses.\r
+\r
+ @param ListLength A pointer would return the SG list length.\r
+ @param HeadList A ponter to the capsule SG list.\r
\r
- @param DescriptorBuffer Pointer to the capsule descriptors\r
+ @retval EFI_SUCCESS a valid capsule is present\r
+ @retval EFI_NOT_FOUND if a valid capsule is not present\r
+ @retval EFI_INVALID_PARAMETER the input parameter is invalid\r
+ @retval EFI_OUT_OF_RESOURCES fail to allocate memory\r
\r
- @retval EFI_SUCCESS a valid capsule is present\r
- @retval EFI_NOT_FOUND if a valid capsule is not present\r
**/\r
EFI_STATUS\r
-GetCapsuleDescriptors (\r
- IN EFI_PHYSICAL_ADDRESS *DescriptorBuffer\r
+GetScatterGatherHeadEntries (\r
+ OUT UINTN *ListLength,\r
+ OUT EFI_PHYSICAL_ADDRESS **HeadList\r
)\r
{\r
EFI_STATUS Status;\r
CHAR16 *TempVarName;\r
EFI_PHYSICAL_ADDRESS CapsuleDataPtr64;\r
EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;\r
+ EFI_PHYSICAL_ADDRESS TempList[MAX_SG_LIST_HEADS];\r
\r
Index = 0;\r
TempVarName = NULL;\r
CapsuleVarName[0] = 0;\r
ValidIndex = 0;\r
CapsuleDataPtr64 = 0;\r
- \r
+\r
+ if ((ListLength == NULL) || (HeadList == NULL)) {\r
+ DEBUG ((DEBUG_ERROR, "%a Invalid parameters. Inputs can't be NULL\n", __FUNCTION__));\r
+ ASSERT (ListLength != NULL);\r
+ ASSERT (HeadList != NULL);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *ListLength = 0;\r
+ *HeadList = NULL;\r
+\r
Status = PeiServicesLocatePpi (\r
&gEfiPeiReadOnlyVariable2PpiGuid,\r
0,\r
NULL,\r
- (VOID **) &PPIVariableServices\r
+ (VOID **)&PPIVariableServices\r
);\r
- if (Status == EFI_SUCCESS) {\r
- StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME);\r
- TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to find ReadOnlyVariable2PPI\n"));\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // setup var name buffer for update capsules\r
+ //\r
+ StrCpyS (CapsuleVarName, sizeof (CapsuleVarName) / sizeof (CHAR16), EFI_CAPSULE_VARIABLE_NAME);\r
+ TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
+ while (ValidIndex < MAX_SG_LIST_HEADS) {\r
+ if (Index != 0) {\r
+ UnicodeValueToStringS (\r
+ TempVarName,\r
+ (sizeof (CapsuleVarName) - ((StrLen (CapsuleVarName) + 1) * sizeof (CHAR16))),\r
+ 0,\r
+ Index,\r
+ 0\r
+ );\r
+ }\r
Size = sizeof (CapsuleDataPtr64);\r
- while (1) {\r
- if (Index == 0) {\r
- //\r
- // For the first Capsule Image\r
- //\r
- Status = PPIVariableServices->GetVariable (\r
- PPIVariableServices,\r
- CapsuleVarName,\r
- &gEfiCapsuleVendorGuid,\r
- NULL,\r
- &Size,\r
- (VOID *) &CapsuleDataPtr64\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_INFO, "Capsule -- capsule variable not set\n"));\r
- return EFI_NOT_FOUND;\r
- }\r
- //\r
- // We have a chicken/egg situation where the memory init code needs to\r
- // know the boot mode prior to initializing memory. For this case, our\r
- // validate function will fail. We can detect if this is the case if blocklist\r
- // pointer is null. In that case, return success since we know that the\r
- // variable is set.\r
- //\r
- if (DescriptorBuffer == NULL) {\r
- return EFI_SUCCESS;\r
- }\r
- } else {\r
- UnicodeValueToStringS (\r
- TempVarName,\r
- sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),\r
- 0,\r
- Index,\r
- 0\r
- );\r
- Status = PPIVariableServices->GetVariable (\r
- PPIVariableServices,\r
- CapsuleVarName,\r
- &gEfiCapsuleVendorGuid,\r
- NULL,\r
- &Size,\r
- (VOID *) &CapsuleDataPtr64\r
- );\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- \r
- //\r
- // If this BlockList has been linked before, skip this variable\r
- //\r
- Flag = FALSE;\r
- for (TempIndex = 0; TempIndex < ValidIndex; TempIndex++) {\r
- if (DescriptorBuffer[TempIndex] == CapsuleDataPtr64) {\r
- Flag = TRUE;\r
- break;\r
- }\r
- }\r
- if (Flag) {\r
- Index ++;\r
- continue;\r
- }\r
+ Status = PPIVariableServices->GetVariable (\r
+ PPIVariableServices,\r
+ CapsuleVarName,\r
+ &gEfiCapsuleVendorGuid,\r
+ NULL,\r
+ &Size,\r
+ (VOID *)&CapsuleDataPtr64\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status != EFI_NOT_FOUND) {\r
+ DEBUG ((DEBUG_ERROR, "Unexpected error getting Capsule Update variable. Status = %r\n"));\r
+ }\r
+ break;\r
+ }\r
+\r
+ //\r
+ // If this BlockList has been linked before, skip this variable\r
+ //\r
+ Flag = FALSE;\r
+ for (TempIndex = 0; TempIndex < ValidIndex; TempIndex++) {\r
+ if (TempList[TempIndex] == CapsuleDataPtr64) {\r
+ Flag = TRUE;\r
+ break;\r
}\r
- \r
- //\r
- // Cache BlockList which has been processed\r
- //\r
- DescriptorBuffer[ValidIndex++] = CapsuleDataPtr64;\r
- Index ++;\r
}\r
+ if (Flag) {\r
+ Index++;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // add it to the cached list\r
+ //\r
+ TempList[ValidIndex++] = CapsuleDataPtr64;\r
+ Index++;\r
+ }\r
+\r
+ if (ValidIndex == 0) {\r
+ DEBUG ((DEBUG_ERROR, "%a didn't find any SG lists in variables\n", __FUNCTION__));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ *HeadList = AllocateZeroPool ((ValidIndex + 1) * sizeof (EFI_PHYSICAL_ADDRESS));\r
+ if (*HeadList == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to allocate memory\n"));\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
- \r
+\r
+ CopyMem (*HeadList, TempList, (ValidIndex) * sizeof (EFI_PHYSICAL_ADDRESS));\r
+ *ListLength = ValidIndex;\r
+\r
return EFI_SUCCESS;\r
}\r
\r
IN OUT UINTN *MemorySize\r
)\r
{\r
- UINTN Index;\r
- UINTN Size;\r
- UINTN VariableCount;\r
- CHAR16 CapsuleVarName[30];\r
- CHAR16 *TempVarName;\r
- EFI_PHYSICAL_ADDRESS CapsuleDataPtr64; \r
EFI_STATUS Status;\r
EFI_BOOT_MODE BootMode;\r
- EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;\r
+ UINTN ListLength;\r
EFI_PHYSICAL_ADDRESS *VariableArrayAddress;\r
MEMORY_RESOURCE_DESCRIPTOR *MemoryResource;\r
#ifdef MDE_CPU_IA32\r
EFI_CAPSULE_LONG_MODE_BUFFER LongModeBuffer;\r
#endif\r
\r
- Index = 0;\r
- VariableCount = 0;\r
- CapsuleVarName[0] = 0;\r
- CapsuleDataPtr64 = 0;\r
+ ListLength = 0;\r
+ VariableArrayAddress = NULL;\r
\r
//\r
// Someone should have already ascertained the boot mode. If it's not\r
//\r
Status = PeiServicesGetBootMode (&BootMode);\r
if (EFI_ERROR (Status) || (BootMode != BOOT_ON_FLASH_UPDATE)) {\r
- DEBUG ((EFI_D_ERROR, "Boot mode is not correct for capsule update path.\n")); \r
+ DEBUG ((DEBUG_ERROR, "Boot mode is not correct for capsule update path.\n"));\r
Status = EFI_NOT_FOUND;\r
goto Done;\r
}\r
- \r
- //\r
- // User may set the same ScatterGatherList with several different variables,\r
- // so cache all ScatterGatherList for check later.\r
- //\r
- Status = PeiServicesLocatePpi (\r
- &gEfiPeiReadOnlyVariable2PpiGuid,\r
- 0,\r
- NULL,\r
- (VOID **) &PPIVariableServices\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- Size = sizeof (CapsuleDataPtr64);\r
- StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME);\r
- TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
- while (TRUE) {\r
- if (Index > 0) {\r
- UnicodeValueToStringS (\r
- TempVarName,\r
- sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),\r
- 0,\r
- Index,\r
- 0\r
- );\r
- }\r
- Status = PPIVariableServices->GetVariable (\r
- PPIVariableServices,\r
- CapsuleVarName,\r
- &gEfiCapsuleVendorGuid,\r
- NULL,\r
- &Size,\r
- (VOID *) &CapsuleDataPtr64\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // There is no capsule variables, quit\r
- //\r
- DEBUG ((EFI_D_INFO,"Capsule variable Index = %d\n", Index));\r
- break;\r
- }\r
- VariableCount++;\r
- Index++;\r
- }\r
- \r
- DEBUG ((EFI_D_INFO,"Capsule variable count = %d\n", VariableCount));\r
- \r
- //\r
- // The last entry is the end flag.\r
- //\r
- Status = PeiServicesAllocatePool (\r
- (VariableCount + 1) * sizeof (EFI_PHYSICAL_ADDRESS),\r
- (VOID **)&VariableArrayAddress\r
- );\r
\r
- if (Status != EFI_SUCCESS) {\r
- DEBUG ((EFI_D_ERROR, "AllocatePages Failed!, Status = %x\n", Status));\r
- goto Done;\r
- }\r
- \r
- ZeroMem (VariableArrayAddress, (VariableCount + 1) * sizeof (EFI_PHYSICAL_ADDRESS));\r
- \r
//\r
- // Find out if we actually have a capsule.\r
- // GetCapsuleDescriptors depends on variable PPI, so it should run in 32-bit environment.\r
+ // Get SG list entries\r
//\r
- Status = GetCapsuleDescriptors (VariableArrayAddress);\r
+ Status = GetScatterGatherHeadEntries (&ListLength, &VariableArrayAddress);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Fail to find capsule variables.\n"));\r
+ DEBUG ((DEBUG_ERROR, "%a failed to get Scatter Gather List Head Entries. Status = %r\n", __FUNCTION__, Status));\r
goto Done;\r
}\r
\r
CoalesceImageEntryPoint = 0;\r
Status = GetLongModeContext (&LongModeBuffer);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Fail to find the variable for long mode context!\n"));\r
+ DEBUG ((DEBUG_ERROR, "Fail to find the variable for long mode context!\n"));\r
Status = EFI_NOT_FOUND;\r
goto Done;\r
}\r
- \r
+\r
Status = FindCapsuleCoalesceImage (&CoalesceImageEntryPoint, &CoalesceImageMachineType);\r
if ((EFI_ERROR (Status)) || (CoalesceImageMachineType != EFI_IMAGE_MACHINE_X64)) {\r
- DEBUG ((EFI_D_ERROR, "Fail to find CapsuleX64 module in FV!\n"));\r
+ DEBUG ((DEBUG_ERROR, "Fail to find CapsuleX64 module in FV!\n"));\r
Status = EFI_NOT_FOUND;\r
goto Done;\r
}\r
//\r
Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryResource, MemoryBase, MemorySize);\r
#endif\r
- \r
- DEBUG ((EFI_D_INFO, "Capsule Coalesce Status = %r!\n", Status));\r
+\r
+ DEBUG ((DEBUG_INFO, "Capsule Coalesce Status = %r!\n", Status));\r
\r
if (Status == EFI_BUFFER_TOO_SMALL) {\r
- DEBUG ((EFI_D_ERROR, "There is not enough memory to process capsule!\n"));\r
+ DEBUG ((DEBUG_ERROR, "There is not enough memory to process capsule!\n"));\r
}\r
- \r
+\r
if (Status == EFI_NOT_FOUND) {\r
- DEBUG ((EFI_D_ERROR, "Fail to parse capsule descriptor in memory!\n"));\r
+ DEBUG ((DEBUG_ERROR, "Fail to parse capsule descriptor in memory!\n"));\r
REPORT_STATUS_CODE (\r
EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
(EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_INVALID_CAPSULE_DESCRIPTOR)\r
)\r
{\r
EFI_STATUS Status;\r
- Status = GetCapsuleDescriptors (NULL);\r
+ BOOLEAN Update;\r
+\r
+ Status = AreCapsulesStaged (&Update);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Update) {\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+ }\r
return Status;\r
}\r
/**\r
- This function will look at a capsule and determine if it's a test pattern. \r
+ This function will look at a capsule and determine if it's a test pattern.\r
If it is, then it will verify it and emit an error message if corruption is detected.\r
- \r
+\r
@param PeiServices Standard pei services pointer\r
@param CapsuleBase Base address of coalesced capsule, which is preceeded\r
by private data. Very implementation specific.\r
//\r
if (*TestPtr == 0x54534554) {\r
RetValue = TRUE;\r
- DEBUG ((EFI_D_INFO, "Capsule test pattern mode activated...\n"));\r
+ DEBUG ((DEBUG_INFO, "Capsule test pattern mode activated...\n"));\r
TestSize = TestPtr[1] / sizeof (UINT32);\r
//\r
// Skip over the signature and the size fields in the pattern data header\r
TestCounter = 0;\r
while (TestSize > 0) {\r
if (*TestPtr != TestCounter) {\r
- DEBUG ((EFI_D_INFO, "Capsule test pattern mode FAILED: BaseAddr/FailAddr 0x%X 0x%X\n", (UINT32)(UINTN)(EFI_CAPSULE_PEIM_PRIVATE_DATA *)CapsuleBase, (UINT32)(UINTN)TestPtr));\r
+ DEBUG ((DEBUG_INFO, "Capsule test pattern mode FAILED: BaseAddr/FailAddr 0x%X 0x%X\n", (UINT32)(UINTN)(EFI_CAPSULE_PEIM_PRIVATE_DATA *)CapsuleBase, (UINT32)(UINTN)TestPtr));\r
return TRUE;\r
}\r
\r
TestSize--;\r
}\r
\r
- DEBUG ((EFI_D_INFO, "Capsule test pattern mode SUCCESS\n"));\r
+ DEBUG ((DEBUG_INFO, "Capsule test pattern mode SUCCESS\n"));\r
}\r
\r
return RetValue;\r
UINT32 Index;\r
EFI_PHYSICAL_ADDRESS BaseAddress;\r
UINT64 Length;\r
- \r
+\r
PrivateData = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) CapsuleBase;\r
if (PrivateData->Signature != EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE) {\r
return EFI_VOLUME_CORRUPTED;\r
}\r
if (PrivateData->CapsuleAllImageSize >= MAX_ADDRESS) {\r
- DEBUG ((EFI_D_ERROR, "CapsuleAllImageSize too big - 0x%lx\n", PrivateData->CapsuleAllImageSize));\r
+ DEBUG ((DEBUG_ERROR, "CapsuleAllImageSize too big - 0x%lx\n", PrivateData->CapsuleAllImageSize));\r
return EFI_OUT_OF_RESOURCES;\r
}\r
if (PrivateData->CapsuleNumber >= MAX_ADDRESS) {\r
- DEBUG ((EFI_D_ERROR, "CapsuleNumber too big - 0x%lx\n", PrivateData->CapsuleNumber));\r
+ DEBUG ((DEBUG_ERROR, "CapsuleNumber too big - 0x%lx\n", PrivateData->CapsuleNumber));\r
return EFI_OUT_OF_RESOURCES;\r
}\r
//\r
);\r
\r
if (Status != EFI_SUCCESS) {\r
- DEBUG ((EFI_D_ERROR, "AllocatePages Failed!\n"));\r
+ DEBUG ((DEBUG_ERROR, "AllocatePages Failed!\n"));\r
return Status;\r
}\r
//\r
// Copy to our new buffer for DXE\r
//\r
- DEBUG ((EFI_D_INFO, "Capsule copy from 0x%8X to 0x%8X with size 0x%8X\n", (UINTN)((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), (UINTN) NewBuffer, Size));\r
+ DEBUG ((DEBUG_INFO, "Capsule copy from 0x%8X to 0x%8X with size 0x%8X\n", (UINTN)((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), (UINTN) NewBuffer, Size));\r
CopyMem ((VOID *) (UINTN) NewBuffer, (VOID *) (UINTN) ((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), Size);\r
//\r
// Check for test data pattern. If it is the test pattern, then we'll\r
\r
BuildCvHob (BaseAddress, Length);\r
}\r
- \r
+\r
return EFI_SUCCESS;\r
}\r
\r