}\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 DescriptorBuffer Pointer to the capsule descriptors\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
- @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
+EFIAPI\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
+ @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
+**/\r
+EFI_STATUS\r
+EFIAPI\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
ValidIndex = 0;\r
CapsuleDataPtr64 = 0;\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
+ Status = PPIVariableServices->GetVariable (\r
+ PPIVariableServices,\r
+ CapsuleVarName,\r
+ &gEfiCapsuleVendorGuid,\r
+ NULL,\r
+ &Size,\r
+ (VOID *)&CapsuleDataPtr64\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
+ 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
- // Cache BlockList which has been processed\r
- //\r
- DescriptorBuffer[ValidIndex++] = CapsuleDataPtr64;\r
- Index ++;\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
+ 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
+ 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
\r
//\r
- // User may set the same ScatterGatherList with several different variables,\r
- // so cache all ScatterGatherList for check later.\r
+ // Get SG list entries\r
//\r
- Status = PeiServicesLocatePpi (\r
- &gEfiPeiReadOnlyVariable2PpiGuid,\r
- 0,\r
- NULL,\r
- (VOID **) &PPIVariableServices\r
- );\r
+ Status = GetScatterGatherHeadEntries (&ListLength, &VariableArrayAddress);\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 ((DEBUG_INFO,"Capsule variable Index = %d\n", Index));\r
- break;\r
- }\r
- VariableCount++;\r
- Index++;\r
- }\r
-\r
- DEBUG ((DEBUG_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 ((DEBUG_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
- //\r
- Status = GetCapsuleDescriptors (VariableArrayAddress);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_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
)\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