+/** @file\r
+ Token Mapper\r
+\r
+ Copyright (c) 2021, Arm Limited. All rights reserved.<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+ @par Glossary:\r
+ - Cm or CM - Configuration Manager\r
+ - Obj or OBJ - Object\r
+**/\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Protocol/ConfigurationManagerProtocol.h>\r
+\r
+#include "TokenMapper.h"\r
+\r
+/** Add a CmObjDesc to the TokenMapper.\r
+\r
+ @param [in] TokenMapper The TokenMapper instance.\r
+ @param [in] Token CmObj token.\r
+ @param [in] ObjectId CmObj ObjectId.\r
+ @param [in] Size CmObj Size.\r
+ @param [in] Data CmObj Data.\r
+ This memory is referenced, not copied.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL Buffer too small.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TokenMapperAddObject (\r
+ IN TOKEN_MAPPER *TokenMapper,\r
+ IN CM_OBJECT_TOKEN Token,\r
+ IN CM_OBJECT_ID ObjectId,\r
+ IN UINT32 Size,\r
+ IN VOID *Data\r
+ )\r
+{\r
+ TOKEN_MAP_DESCRIPTOR *TokenMapDesc;\r
+ CM_OBJ_DESCRIPTOR *CmObjDesc;\r
+\r
+ if ((TokenMapper == NULL) ||\r
+ (TokenMapper->TokenDescArray == NULL) ||\r
+ (Size == 0) ||\r
+ (Data == NULL))\r
+ {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (TokenMapper->ItemCount >= TokenMapper->MaxTokenDescCount) {\r
+ ASSERT (0);\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ TokenMapDesc = &TokenMapper->TokenDescArray[TokenMapper->ItemCount++];\r
+ TokenMapDesc->Token = Token;\r
+ CmObjDesc = &TokenMapDesc->CmObjDesc;\r
+ CmObjDesc->ObjectId = ObjectId;\r
+ CmObjDesc->Size = Size;\r
+\r
+ // Point inside the finalized array.\r
+ CmObjDesc->Data = Data;\r
+\r
+ // Only EArmObjCmRef CmObj can be added as arrays (more than 1 elements).\r
+ if ((GET_CM_NAMESPACE_ID (ObjectId) == EObjNameSpaceArm) &&\r
+ (GET_CM_OBJECT_ID (ObjectId) == EArmObjCmRef))\r
+ {\r
+ CmObjDesc->Count = Size / sizeof (CM_ARM_OBJ_REF);\r
+ } else {\r
+ CmObjDesc->Count = 1;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/** Get a CmObjDesc from a ObjectId/Token couple.\r
+\r
+ The Token parameter is not optional. An existing token must be provided.\r
+\r
+ @param [in] TokenMapper The TokenMapper instance.\r
+ @param [in] Token Token of the CmObj to search.\r
+ @param [in] ObjectId Object Id of the CmObj to search.\r
+ @param [out] CmObjDesc CM_OBJ_DESCRIPTOR containing the CmObj searched.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+ @retval EFI_NOT_FOUND Not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TokenMapperGetObject (\r
+ IN TOKEN_MAPPER *TokenMapper,\r
+ IN CM_OBJECT_TOKEN Token,\r
+ IN CM_OBJECT_ID ObjectId,\r
+ OUT CM_OBJ_DESCRIPTOR *CmObjDesc\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN MaxCount;\r
+ TOKEN_MAP_DESCRIPTOR *TokenMapDesc;\r
+\r
+ // Nothing to do.\r
+ if ((TokenMapper != NULL) && (TokenMapper->MaxTokenDescCount == 0)) {\r
+ goto exit_handler;\r
+ }\r
+\r
+ if ((Token == CM_NULL_TOKEN) ||\r
+ (CmObjDesc == NULL) ||\r
+ (TokenMapper == NULL) ||\r
+ (TokenMapper->TokenDescArray == NULL))\r
+ {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ TokenMapDesc = TokenMapper->TokenDescArray;\r
+ MaxCount = TokenMapper->MaxTokenDescCount;\r
+ for (Index = 0; Index < MaxCount; Index++) {\r
+ if ((TokenMapDesc->CmObjDesc.ObjectId == ObjectId) &&\r
+ (TokenMapDesc->Token == Token))\r
+ {\r
+ CopyMem (\r
+ CmObjDesc,\r
+ &TokenMapDesc->CmObjDesc,\r
+ sizeof (CM_OBJ_DESCRIPTOR)\r
+ );\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ TokenMapDesc++;\r
+ } // for\r
+\r
+exit_handler:\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "INFO: Requested CmObj of type 0x%x with token 0x%x"\r
+ " not found in the dynamic repository\n.",\r
+ ObjectId,\r
+ Token\r
+ ));\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/** Initialise a TokenMapper.\r
+\r
+ @param [in] TokenMapper The TokenMapper to initialise.\r
+ @param [in] DescriptorCount Number of entries to allocate.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_ALREADY_STARTED Instance already initialised.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TokenMapperInitialise (\r
+ IN TOKEN_MAPPER *TokenMapper,\r
+ IN UINTN DescriptorCount\r
+ )\r
+{\r
+ if (TokenMapper == NULL) {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ // Nothing to do.\r
+ if (DescriptorCount == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (TokenMapper->TokenDescArray != NULL) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR: Token mapper already initialised\n."));\r
+ ASSERT (0);\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ TokenMapper->TokenDescArray =\r
+ AllocateZeroPool (sizeof (TOKEN_MAP_DESCRIPTOR) * DescriptorCount);\r
+ if (TokenMapper->TokenDescArray == NULL) {\r
+ ASSERT (0);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ TokenMapper->MaxTokenDescCount = DescriptorCount;\r
+ TokenMapper->ItemCount = 0;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/** Shutdown a TokenMapper.\r
+\r
+ @param [in] TokenMapper The TokenMapper to shutdown.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TokenMapperShutdown (\r
+ IN TOKEN_MAPPER *TokenMapper\r
+ )\r
+{\r
+ // Nothing to do.\r
+ if ((TokenMapper != NULL) && (TokenMapper->MaxTokenDescCount == 0)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if ((TokenMapper == NULL) ||\r
+ (TokenMapper->TokenDescArray == NULL))\r
+ {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ FreePool (TokenMapper->TokenDescArray);\r
+ TokenMapper->TokenDescArray = NULL;\r
+ TokenMapper->MaxTokenDescCount = 0;\r
+\r
+ return EFI_SUCCESS;\r
+}\r