return Status;\r
}\r
\r
+/**\r
+ Test whether CacheId is unique among the CacheIdList.\r
+\r
+ @param [in] CacheId Cache ID to check.\r
+ @param [in] CacheIdList List of already existing cache IDs.\r
+ @param [in] CacheIdListSize Size of CacheIdList.\r
+\r
+ @retval TRUE CacheId does not exist in CacheIdList.\r
+ @retval FALSE CacheId already exists in CacheIdList.\r
+**/\r
+STATIC\r
+BOOLEAN\r
+IsCacheIdUnique (\r
+ IN CONST UINT32 CacheId,\r
+ IN CONST UINT32 *CacheIdList,\r
+ IN CONST UINT32 CacheIdListSize\r
+ )\r
+{\r
+ UINT32 Index;\r
+\r
+ for (Index = 0; Index < CacheIdListSize; Index++) {\r
+ if (CacheIdList[Index] == CacheId) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
/**\r
Update the Cache Type Structure (Type 1) information.\r
\r
@param [in] Pptt Pointer to PPTT table structure.\r
@param [in] NodesStartOffset Offset from the start of PPTT table to the\r
start of Cache Type Structures.\r
+ @param [in] Revision Revision of the PPTT table being requested.\r
\r
@retval EFI_SUCCESS Structures updated successfully.\r
@retval EFI_INVALID_PARAMETER A parameter is invalid.\r
@retval EFI_NOT_FOUND A required object was not found.\r
+ @retval EFI_OUT_OF_RESOURCES Out of resources.\r
**/\r
STATIC\r
EFI_STATUS\r
IN CONST ACPI_PPTT_GENERATOR *CONST Generator,\r
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
IN CONST EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *Pptt,\r
- IN CONST UINT32 NodesStartOffset\r
+ IN CONST UINT32 NodesStartOffset,\r
+ IN CONST UINT32 Revision\r
)\r
{\r
EFI_STATUS Status;\r
CM_ARM_CACHE_INFO *CacheInfoNode;\r
PPTT_NODE_INDEXER *CacheNodeIterator;\r
UINT32 NodeCount;\r
+ BOOLEAN CacheIdUnique;\r
+ UINT32 NodeIndex;\r
+ UINT32 *FoundCacheIds;\r
\r
ASSERT (\r
(Generator != NULL) &&\r
CacheNodeIterator = Generator->CacheStructIndexedList;\r
NodeCount = Generator->CacheStructCount;\r
\r
- while (NodeCount-- != 0) {\r
+ FoundCacheIds = AllocateZeroPool (NodeCount * sizeof (*FoundCacheIds));\r
+ if (FoundCacheIds == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR: PPTT: Failed to allocate resources.\n"));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (NodeIndex = 0; NodeIndex < NodeCount; NodeIndex++) {\r
CacheInfoNode = (CM_ARM_CACHE_INFO *)CacheNodeIterator->Object;\r
\r
// Populate the node header\r
CacheStruct->Flags.CacheTypeValid = 1;\r
CacheStruct->Flags.WritePolicyValid = 1;\r
CacheStruct->Flags.LineSizeValid = 1;\r
+ CacheStruct->Flags.CacheIdValid = 1;\r
CacheStruct->Flags.Reserved = 0;\r
\r
// Populate the reference to the next level of cache\r
CacheInfoNode->Token,\r
Status\r
));\r
- return Status;\r
+ goto cleanup;\r
}\r
\r
// Update Cache Structure with the offset for the next level of cache\r
CacheInfoNode->NumberOfSets,\r
Status\r
));\r
- return Status;\r
+ goto cleanup;\r
}\r
\r
if (CacheInfoNode->NumberOfSets > PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX) {\r
CacheInfoNode->Associativity,\r
Status\r
));\r
- return Status;\r
+ goto cleanup;\r
}\r
\r
// Validate the Associativity field based on the architecture specification\r
CacheInfoNode->Associativity,\r
Status\r
));\r
- return Status;\r
+ goto cleanup;\r
}\r
\r
if (CacheInfoNode->Associativity > PPTT_ARM_CACHE_ASSOCIATIVITY_MAX) {\r
CacheInfoNode->LineSize,\r
Status\r
));\r
- return Status;\r
+ goto cleanup;\r
}\r
\r
if ((CacheInfoNode->LineSize & (CacheInfoNode->LineSize - 1)) != 0) {\r
CacheInfoNode->LineSize,\r
Status\r
));\r
- return Status;\r
+ goto cleanup;\r
}\r
\r
CacheStruct->LineSize = CacheInfoNode->LineSize;\r
\r
+ if (Revision >= 3) {\r
+ // Validate and populate cache id\r
+ if (CacheInfoNode->CacheId == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: PPTT: The cache id cannot be zero. Status = %r\n",\r
+ Status\r
+ ));\r
+ goto cleanup;\r
+ }\r
+\r
+ CacheIdUnique = IsCacheIdUnique (\r
+ CacheInfoNode->CacheId,\r
+ FoundCacheIds,\r
+ NodeIndex\r
+ );\r
+ if (!CacheIdUnique) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: PPTT: The cache id is not unique. " \\r
+ "CacheId = %d. Status = %r\n",\r
+ CacheInfoNode->CacheId,\r
+ Status\r
+ ));\r
+ goto cleanup;\r
+ }\r
+\r
+ // Store the cache id so we can check future cache ids for uniqueness\r
+ FoundCacheIds[NodeIndex] = CacheInfoNode->CacheId;\r
+\r
+ CacheStruct->CacheId = CacheInfoNode->CacheId;\r
+ }\r
+\r
// Next Cache Type Structure\r
CacheStruct = (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE *)((UINT8 *)CacheStruct +\r
CacheStruct->Length);\r
CacheNodeIterator++;\r
- } // Cache Type Structure\r
+ } // for Cache Type Structure\r
\r
- return EFI_SUCCESS;\r
+ Status = EFI_SUCCESS;\r
+\r
+cleanup:\r
+ FreePool (FoundCacheIds);\r
+\r
+ return Status;\r
}\r
\r
/**\r
Generator,\r
CfgMgrProtocol,\r
Pptt,\r
- CacheStructOffset\r
+ CacheStructOffset,\r
+ AcpiTableInfo->AcpiTableRevision\r
);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((\r