public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v2 0/5] Add DynamicPlatRepoLib
@ 2021-11-23 11:10 PierreGondois
  2021-11-23 11:10 ` [PATCH v2 1/5] DynamicTablesPkg: Definition for DynamicPlatRepoLib interface PierreGondois
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: PierreGondois @ 2021-11-23 11:10 UTC (permalink / raw)
  To: pierre.gondois, devel; +Cc: Sami Mujawar, Alexei Fedorov

From: Pierre Gondois <Pierre.Gondois@arm.com>

v2:
- Various small fixes (change status returned, reset values when
  freeing memory, ...). [Sami]

Ref:https://bugzilla.tianocore.org/show_bug.cgi?id=3743

The DynamicPlatRepoLib is library allowing to receive and then
give Configuration Manager (CM) objects.
After being initialized, a dynamic platform repository can receive
CMObjects. The library generates a token to uniquely identify the
CMObject in the repository. The dynamic platform repository must
then be 'finalized' before receiving CMObject queries.

This library is complementary to the 'static' definition of
CMObjects (i.e. as C structs). It is particularly useful when
using a HwInfoParserLib that dynamically creates CMObjects
(from a device tree for instance).

The changes can be seen at: https://github.com/PierreARM/edk2/tree/1788_Add_Dynamic_Plarform_Repository_Lib_v2

Pierre Gondois (5):
  DynamicTablesPkg: Definition for DynamicPlatRepoLib interface
  DynamicTablesPkg: DynamicPlatRepo: Add TokenGenerator
  DynamicTablesPkg: DynamicPlatRepo: Add TokenFixer
  DynamicTablesPkg: DynamicPlatRepo: Add TokenMapper
  DynamicTablesPkg: Add DynamicPlatRepo library

 DynamicTablesPkg/DynamicTablesPkg.dec         |   3 +
 DynamicTablesPkg/DynamicTablesPkg.dsc         |   1 +
 .../Include/Library/DynamicPlatRepoLib.h      | 114 ++++
 .../DynamicPlatRepoLib/CmObjectTokenFixer.c   | 164 ++++++
 .../DynamicPlatRepoLib/CmObjectTokenFixer.h   |  52 ++
 .../DynamicPlatRepoLib/DynamicPlatRepo.c      | 515 ++++++++++++++++++
 .../DynamicPlatRepoInternal.h                 |  78 +++
 .../DynamicPlatRepoLib/DynamicPlatRepoLib.inf |  33 ++
 .../DynamicPlatRepoLib/TokenGenerator.c       |  28 +
 .../DynamicPlatRepoLib/TokenGenerator.h       |  26 +
 .../Common/DynamicPlatRepoLib/TokenMapper.c   | 218 ++++++++
 .../Common/DynamicPlatRepoLib/TokenMapper.h   | 123 +++++
 12 files changed, 1355 insertions(+)
 create mode 100644 DynamicTablesPkg/Include/Library/DynamicPlatRepoLib.h
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.c
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.h
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepo.c
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoInternal.h
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenGenerator.c
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenGenerator.h
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenMapper.c
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenMapper.h

--
2.25.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/5] DynamicTablesPkg: Definition for DynamicPlatRepoLib interface
  2021-11-23 11:10 [PATCH v2 0/5] Add DynamicPlatRepoLib PierreGondois
@ 2021-11-23 11:10 ` PierreGondois
  2021-11-23 11:10 ` [PATCH v2 2/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenGenerator PierreGondois
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: PierreGondois @ 2021-11-23 11:10 UTC (permalink / raw)
  To: pierre.gondois, devel; +Cc: Sami Mujawar, Alexei Fedorov

From: Pierre Gondois <Pierre.Gondois@arm.com>

The DynamicPlatRepoLib library allows to handle dynamically created
CmObj. The dynamic platform repository can be in the following states:
1 - Non-initialised
2 - Transient:
    Possibility to add CmObj to the platform, but not to query them.
3 - Finalised:
    Possibility to query CmObj, but not to add new.

A token is allocated to each CmObj added to the dynamic platform
repository (except for reference tokens CmObj). This allows to
retrieve dynamic CmObjs among all CmObj (static CmObj for instance).

This patch defines the library interface of the DynamicPlatRepo.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 DynamicTablesPkg/DynamicTablesPkg.dec         |   3 +
 .../Include/Library/DynamicPlatRepoLib.h      | 114 ++++++++++++++++++
 2 files changed, 117 insertions(+)
 create mode 100644 DynamicTablesPkg/Include/Library/DynamicPlatRepoLib.h

diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/DynamicTablesPkg.dec
index 80a61dd2dbac..9b74c5a67178 100644
--- a/DynamicTablesPkg/DynamicTablesPkg.dec
+++ b/DynamicTablesPkg/DynamicTablesPkg.dec
@@ -24,6 +24,9 @@ [LibraryClasses]
   ##  @libraryclass  Defines a set of APIs for Dynamic AML generation.
   AmlLib|Include/Library/AmlLib/AmlLib.h
 
+  ##  @libraryclass  Defines a set of APIs to handle dynamically created CmObj.
+  DynamicPlatRepoLib|Include/Library/DynamicPlatRepoLib.h
+
   ##  @libraryclass  Defines a set of APIs to a hardware information parser.
   HwInfoParserLib|Include/Library/HwInfoParserLib.h
 
diff --git a/DynamicTablesPkg/Include/Library/DynamicPlatRepoLib.h b/DynamicTablesPkg/Include/Library/DynamicPlatRepoLib.h
new file mode 100644
index 000000000000..4a76b30399b4
--- /dev/null
+++ b/DynamicTablesPkg/Include/Library/DynamicPlatRepoLib.h
@@ -0,0 +1,114 @@
+/** @file
+  Dynamic Platform Info Repository
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef DYNAMIC_PLAT_REPO_H_
+#define DYNAMIC_PLAT_REPO_H_
+
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+/** A structure describing the platform configuration
+    manager repository information
+*/
+typedef VOID*                DYNAMIC_PLATFORM_REPOSITORY_INFO;
+
+/** Add an object to the dynamic platform repository.
+
+  @param [in]  This       This dynamic platform repository.
+  @param [in]  CmObjDesc  CmObj to add. The data is copied.
+  @param [out] Token      If not NULL, token allocated to this CmObj.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_OUT_OF_RESOURCES  An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+DynPlatRepoAddObject (
+  IN        DYNAMIC_PLATFORM_REPOSITORY_INFO    * This,
+  IN  CONST CM_OBJ_DESCRIPTOR                   * CmObjDesc,
+  OUT       CM_OBJECT_TOKEN                     * Token OPTIONAL
+  );
+
+/** Finalise the dynamic repository.
+
+  Finalising means:
+   - Preventing any further objects from being added.
+   - Allowing to get objects from the dynamic repository
+     (not possible before a call to this function).
+
+  @param [in]  This       This dynamic platform repository.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_ALREADY_STARTED   Instance already initialised.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_BUFFER_TOO_SMALL  Buffer too small.
+  @retval EFI_OUT_OF_RESOURCES  An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+DynamicPlatRepoFinalise (
+  IN  DYNAMIC_PLATFORM_REPOSITORY_INFO      * This
+  );
+
+/** Get a CmObj from the dynamic repository.
+
+  @param [in]      This        Pointer to the Dynamic Platform Repository.
+  @param [in]      CmObjectId  The Configuration Manager Object ID.
+  @param [in]      Token       An optional token identifying the object. If
+                               unused this must be CM_NULL_TOKEN.
+  @param [in, out] CmObjDesc   Pointer to the Configuration Manager Object
+                               descriptor describing the requested Object.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_NOT_FOUND         The required object information is not found.
+**/
+EFI_STATUS
+EFIAPI
+DynamicPlatRepoGetObject (
+  IN      DYNAMIC_PLATFORM_REPOSITORY_INFO    * This,
+  IN      CM_OBJECT_ID                          CmObjectId,
+  IN      CM_OBJECT_TOKEN                       Token OPTIONAL,
+  IN  OUT CM_OBJ_DESCRIPTOR                   * CmObjDesc
+  );
+
+/** Initialize the dynamic platform repository.
+
+  @param [out]  DynPlatRepo   If success, contains the initialised dynamic
+                              platform repository.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_OUT_OF_RESOURCES  An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+DynamicPlatRepoInit (
+  OUT DYNAMIC_PLATFORM_REPOSITORY_INFO   ** DynPlatRepo
+  );
+
+/** Shutdown the dynamic platform repository.
+
+  Free all the memory allocated for the dynamic platform repository.
+
+  @param [in]  DynPlatRepo    The dynamic platform repository.
+
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_SUCCESS           Success.
+**/
+EFI_STATUS
+EFIAPI
+DynamicPlatRepoShutdown (
+  IN  DYNAMIC_PLATFORM_REPOSITORY_INFO * DynPlatRepo
+  );
+
+#endif // DYNAMIC_PLAT_REPO_H_
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenGenerator
  2021-11-23 11:10 [PATCH v2 0/5] Add DynamicPlatRepoLib PierreGondois
  2021-11-23 11:10 ` [PATCH v2 1/5] DynamicTablesPkg: Definition for DynamicPlatRepoLib interface PierreGondois
@ 2021-11-23 11:10 ` PierreGondois
  2021-11-23 11:10 ` [PATCH v2 3/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenFixer PierreGondois
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: PierreGondois @ 2021-11-23 11:10 UTC (permalink / raw)
  To: pierre.gondois, devel; +Cc: Sami Mujawar, Alexei Fedorov

From: Pierre Gondois <Pierre.Gondois@arm.com>

The DynamicPlatRepo library allows to handle dynamically created
CmObj. The dynamic platform repository can be in the following states:
1 - Non-initialised
2 - Transient:
    Possibility to add CmObj to the platform, but not to query them.
3 - Finalised:
    Possibility to query CmObj, but not to add new.

A token is allocated to each CmObj added to the dynamic platform
repository (except for reference tokens CmObj). This allows to retrieve
dynamic CmObjs among all CmObj (static CmObj for instance).

This patch add the TokenGenerator files.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../DynamicPlatRepoLib/TokenGenerator.c       | 28 +++++++++++++++++++
 .../DynamicPlatRepoLib/TokenGenerator.h       | 26 +++++++++++++++++
 2 files changed, 54 insertions(+)
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenGenerator.c
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenGenerator.h

diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenGenerator.c b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenGenerator.c
new file mode 100644
index 000000000000..637e784bd284
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenGenerator.c
@@ -0,0 +1,28 @@
+/** @file
+  Token Generator
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+/** Generate a token.
+
+  @return A token.
+**/
+CM_OBJECT_TOKEN
+EFIAPI
+GenerateToken (
+  VOID
+  )
+{
+  // Start Tokens at 1 to avoid collisions with CM_NULL_TOKEN.
+  STATIC UINTN CurrentToken = 1;
+  return (CM_OBJECT_TOKEN)(CurrentToken++);
+}
diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenGenerator.h b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenGenerator.h
new file mode 100644
index 000000000000..44d32e5b41a1
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenGenerator.h
@@ -0,0 +1,26 @@
+/** @file
+  Token Generator
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef TOKEN_GENERATOR_H_
+#define TOKEN_GENERATOR_H_
+
+/** Generate a token.
+
+  @return A token.
+**/
+CM_OBJECT_TOKEN
+EFIAPI
+GenerateToken (
+  VOID
+  );
+
+#endif // TOKEN_GENERATOR_H_
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 3/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenFixer
  2021-11-23 11:10 [PATCH v2 0/5] Add DynamicPlatRepoLib PierreGondois
  2021-11-23 11:10 ` [PATCH v2 1/5] DynamicTablesPkg: Definition for DynamicPlatRepoLib interface PierreGondois
  2021-11-23 11:10 ` [PATCH v2 2/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenGenerator PierreGondois
@ 2021-11-23 11:10 ` PierreGondois
  2021-11-23 11:10 ` [PATCH v2 4/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenMapper PierreGondois
  2021-11-23 11:10 ` [PATCH v2 5/5] DynamicTablesPkg: Add DynamicPlatRepo library PierreGondois
  4 siblings, 0 replies; 6+ messages in thread
From: PierreGondois @ 2021-11-23 11:10 UTC (permalink / raw)
  To: pierre.gondois, devel; +Cc: Sami Mujawar, Alexei Fedorov

From: Pierre Gondois <Pierre.Gondois@arm.com>

The DynamicPlatRepo library allows to handle dynamically created
CmObj. The dynamic platform repository can be in the following states:
1 - Non-initialised
2 - Transient:
    Possibility to add CmObj to the platform, but not to query them.
3 - Finalised:
    Possibility to query CmObj, but not to add new.

A token is allocated to each CmObj added to the dynamic platform
repository (except for reference tokens CmObj). This allows to retrieve
dynamic CmObjs among all CmObj (static CmObj for instance).

This patch add the TokenFixer files, allowing to update the
self-token some CmObj have.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../DynamicPlatRepoLib/CmObjectTokenFixer.c   | 164 ++++++++++++++++++
 .../DynamicPlatRepoLib/CmObjectTokenFixer.h   |  52 ++++++
 2 files changed, 216 insertions(+)
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.c
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.h

diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.c b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.c
new file mode 100644
index 000000000000..74eeefccf4ce
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.c
@@ -0,0 +1,164 @@
+/** @file
+  Configuration Manager object token fixer
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#include <Library/DebugLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include "CmObjectTokenFixer.h"
+
+/** Token fixer not implemented.
+
+  Most of the objects are not generated by this parser. Add the missing
+  functions when needed.
+
+  CmObjectToken fixer function that updates the Tokens in the CmObjects.
+
+  @param [in]  CmObject    Pointer to the Configuration Manager Object.
+  @param [in]  Token       Token to be updated in the CmObject.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_UNSUPPORTED       Not supported.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+TokenFixerNotImplemented (
+  IN  CM_OBJ_DESCRIPTOR   * CmObject,
+  IN  CM_OBJECT_TOKEN       Token
+  )
+{
+  ASSERT (0);
+  return EFI_UNSUPPORTED;
+}
+
+/** EArmObjItsGroup token fixer.
+
+  CmObjectToken fixer function that updates the Tokens in the CmObjects.
+
+  @param [in]  CmObject    Pointer to the Configuration Manager Object.
+  @param [in]  Token       Token to be updated in the CmObject.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_UNSUPPORTED       Not supported.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+TokenFixerItsGroup (
+  IN  CM_OBJ_DESCRIPTOR   * CmObject,
+  IN  CM_OBJECT_TOKEN       Token
+  )
+{
+  ASSERT (CmObject != NULL);
+  ((CM_ARM_ITS_GROUP_NODE*)CmObject)->Token = Token;
+  return EFI_SUCCESS;
+}
+
+/** TokenFixer functions table.
+
+  A CmObj having a CM_OBJECT_TOKEN field might need to have its
+  Token fixed. Each CmObj can have its Token in a specific way.
+*/
+CONST
+CM_OBJECT_TOKEN_FIXER TokenFixer[EArmObjMax] = {
+  NULL,                             ///<  0 - Reserved
+  NULL,                             ///<  1 - Boot Architecture Info
+  NULL,                             ///<  2 - CPU Info
+  NULL,                             ///<  3 - Power Management Profile Info
+  NULL,                             ///<  4 - GIC CPU Interface Info
+  NULL,                             ///<  5 - GIC Distributor Info
+  NULL,                             ///<  6 - GIC MSI Frame Info
+  NULL,                             ///<  7 - GIC Redistributor Info
+  NULL,                             ///<  8 - GIC ITS Info
+  NULL,                             ///<  9 - Serial Console Port Info
+  NULL,                             ///< 10 - Serial Debug Port Info
+  NULL,                             ///< 11 - Generic Timer Info
+  NULL,                             ///< 12 - Platform GT Block Info
+  NULL,                             ///< 13 - Generic Timer Block Frame Info
+  NULL,                             ///< 14 - Platform Generic Watchdog
+  NULL,                             ///< 15 - PCI Configuration Space Info
+  NULL,                             ///< 16 - Hypervisor Vendor Id
+  NULL,                             ///< 17 - Fixed feature flags for FADT
+  TokenFixerItsGroup,               ///< 18 - ITS Group
+  TokenFixerNotImplemented,         ///< 19 - Named Component
+  TokenFixerNotImplemented,         ///< 20 - Root Complex
+  TokenFixerNotImplemented,         ///< 21 - SMMUv1 or SMMUv2
+  TokenFixerNotImplemented,         ///< 22 - SMMUv3
+  TokenFixerNotImplemented,         ///< 23 - PMCG
+  NULL,                             ///< 24 - GIC ITS Identifier Array
+  NULL,                             ///< 25 - ID Mapping Array
+  NULL,                             ///< 26 - SMMU Interrupt Array
+  TokenFixerNotImplemented,         ///< 27 - Processor Hierarchy Info
+  TokenFixerNotImplemented,         ///< 28 - Cache Info
+  TokenFixerNotImplemented,         ///< 29 - Processor Node ID Info
+  NULL,                             ///< 30 - CM Object Reference
+  NULL,                             ///< 31 - Memory Affinity Info
+  NULL,                             ///< 32 - Device Handle Acpi
+  NULL,                             ///< 33 - Device Handle Pci
+  NULL,                             ///< 34 - Generic Initiator Affinity
+  NULL,                             ///< 35 - Generic Serial Port Info
+  NULL,                             ///< 36 - CMN-600 Info
+  NULL,                             ///< 37 - Lpi Info
+  NULL,                             ///< 38 - Pci Address Map Info
+  NULL,                             ///< 39 - Pci Interrupt Map Info
+};
+
+/** CmObj token fixer.
+
+  Some CmObj structures have a self-token, i.e. they are storing their own
+  token value in the CmObj. Dynamically created CmObj need to have their
+  self-token assigned at some point.
+
+  @param [in]  CmObjDesc   Pointer to the Configuration Manager Object.
+  @param [in]  Token       Token to update the CmObjDesc with.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_UNSUPPORTED       Not supported.
+**/
+EFI_STATUS
+EFIAPI
+FixupCmObjectSelfToken (
+  IN  CM_OBJ_DESCRIPTOR   * CmObjDesc,
+  IN  CM_OBJECT_TOKEN       Token
+  )
+{
+  EFI_STATUS              Status;
+  CM_OBJECT_TOKEN_FIXER   TokenFixerFunc;
+  CM_OBJECT_ID            ArmNamespaceObjId;
+
+  // Only support Arm objects for now.
+  if ((CmObjDesc == NULL)   ||
+      (GET_CM_NAMESPACE_ID (CmObjDesc->ObjectId) != EObjNameSpaceArm)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ArmNamespaceObjId = GET_CM_OBJECT_ID (CmObjDesc->ObjectId);
+  if (ArmNamespaceObjId >= EArmObjMax) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Fixup self-token if necessary.
+  TokenFixerFunc = TokenFixer[ArmNamespaceObjId];
+  if (TokenFixerFunc != NULL) {
+    Status = TokenFixerFunc (CmObjDesc, Token);
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.h b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.h
new file mode 100644
index 000000000000..d8cc7094697f
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.h
@@ -0,0 +1,52 @@
+/** @file
+  Configuration Manager object token fixer
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef CM_OBJECT_TOKEN_FIXER_H_
+#define CM_OBJECT_TOKEN_FIXER_H_
+
+/** CmObjectToken fixer function that updates the Tokens in the CmObjects.
+
+  @param [in]  CmObject    Pointer to the Configuration Manager Object.
+  @param [in]  Token       Token to be updated in the CmObject.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_UNSUPPORTED       Not supported.
+**/
+typedef
+EFI_STATUS
+(EFIAPI * CM_OBJECT_TOKEN_FIXER) (
+  IN  CM_OBJ_DESCRIPTOR   * CmObject,
+  IN  CM_OBJECT_TOKEN       Token
+  );
+
+/** CmObj token fixer.
+
+  Some CmObj structures have a self-token, i.e. they are storing their own
+  token value in the CmObj. Dynamically created CmObj need to have their
+  self-token assigned at some point.
+
+  @param [in]  CmObjDesc   Pointer to the Configuration Manager Object.
+  @param [in]  Token       Token to update the CmObjDesc with.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_UNSUPPORTED       Not supported.
+**/
+EFI_STATUS
+EFIAPI
+FixupCmObjectSelfToken (
+  IN  CM_OBJ_DESCRIPTOR   * CmObjDesc,
+  IN  CM_OBJECT_TOKEN       Token
+  );
+
+#endif // CM_OBJECT_TOKEN_FIXER_H_
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 4/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenMapper
  2021-11-23 11:10 [PATCH v2 0/5] Add DynamicPlatRepoLib PierreGondois
                   ` (2 preceding siblings ...)
  2021-11-23 11:10 ` [PATCH v2 3/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenFixer PierreGondois
@ 2021-11-23 11:10 ` PierreGondois
  2021-11-23 11:10 ` [PATCH v2 5/5] DynamicTablesPkg: Add DynamicPlatRepo library PierreGondois
  4 siblings, 0 replies; 6+ messages in thread
From: PierreGondois @ 2021-11-23 11:10 UTC (permalink / raw)
  To: pierre.gondois, devel; +Cc: Sami Mujawar, Alexei Fedorov

From: Pierre Gondois <Pierre.Gondois@arm.com>

The DynamicPlatRepo library allows to handle dynamically created
CmObj. The dynamic platform repository can be in the following states:
1 - Non-initialised
2 - Transient:
    Possibility to add CmObj to the platform, but not to query them.
3 - Finalised:
    Possibility to query CmObj, but not to add new.

A token is allocated to each CmObj added to the dynamic platform
repository (except for reference tokens CmObj). This allows to retrieve
dynamic CmObjs among all CmObj (static CmObj for instance).

This patch add the TokenMapper files, allowing to retrieve a CmObj
from a token/CmObjId couple.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../Common/DynamicPlatRepoLib/TokenMapper.c   | 218 ++++++++++++++++++
 .../Common/DynamicPlatRepoLib/TokenMapper.h   | 123 ++++++++++
 2 files changed, 341 insertions(+)
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenMapper.c
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenMapper.h

diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenMapper.c b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenMapper.c
new file mode 100644
index 000000000000..a871320715a3
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenMapper.c
@@ -0,0 +1,218 @@
+/** @file
+  Token Mapper
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include "TokenMapper.h"
+
+/** Add a CmObjDesc to the TokenMapper.
+
+  @param [in] TokenMapper   The TokenMapper instance.
+  @param [in] Token         CmObj token.
+  @param [in] ObjectId      CmObj ObjectId.
+  @param [in] Size          CmObj Size.
+  @param [in] Data          CmObj Data.
+                            This memory is referenced, not copied.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_BUFFER_TOO_SMALL    Buffer too small.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+**/
+EFI_STATUS
+EFIAPI
+TokenMapperAddObject (
+  IN  TOKEN_MAPPER      *TokenMapper,
+  IN  CM_OBJECT_TOKEN   Token,
+  IN  CM_OBJECT_ID      ObjectId,
+  IN  UINT32            Size,
+  IN  VOID              *Data
+  )
+{
+  TOKEN_MAP_DESCRIPTOR  *TokenMapDesc;
+  CM_OBJ_DESCRIPTOR     *CmObjDesc;
+
+  if ((TokenMapper == NULL)                 ||
+      (TokenMapper->TokenDescArray == NULL) ||
+      (Size == 0)                           ||
+      (Data == NULL)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (TokenMapper->ItemCount >= TokenMapper->MaxTokenDescCount) {
+    ASSERT (0);
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  TokenMapDesc = &TokenMapper->TokenDescArray[TokenMapper->ItemCount++];
+  TokenMapDesc->Token = Token;
+  CmObjDesc = &TokenMapDesc->CmObjDesc;
+  CmObjDesc->ObjectId = ObjectId;
+  CmObjDesc->Size = Size;
+
+  // Point inside the finalized array.
+  CmObjDesc->Data = Data;
+
+  // Only EArmObjCmRef CmObj can be added as arrays (more than 1 elements).
+  if ((GET_CM_NAMESPACE_ID (ObjectId) == EObjNameSpaceArm) &&
+      (GET_CM_OBJECT_ID (ObjectId) == EArmObjCmRef)) {
+    CmObjDesc->Count = Size / sizeof (CM_ARM_OBJ_REF);
+  } else {
+    CmObjDesc->Count = 1;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Get a CmObjDesc from a ObjectId/Token couple.
+
+  The Token parameter is not optional. An existing token must be provided.
+
+  @param [in]  TokenMapper   The TokenMapper instance.
+  @param [in]  Token         Token of the CmObj to search.
+  @param [in]  ObjectId      Object Id of the CmObj to search.
+  @param [out] CmObjDesc     CM_OBJ_DESCRIPTOR containing the CmObj searched.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+  @retval EFI_NOT_FOUND           Not found.
+**/
+EFI_STATUS
+EFIAPI
+TokenMapperGetObject (
+  IN  TOKEN_MAPPER        *TokenMapper,
+  IN  CM_OBJECT_TOKEN     Token,
+  IN  CM_OBJECT_ID        ObjectId,
+  OUT CM_OBJ_DESCRIPTOR   *CmObjDesc
+  )
+{
+  UINTN                 Index;
+  UINTN                 MaxCount;
+  TOKEN_MAP_DESCRIPTOR  *TokenMapDesc;
+
+  // Nothing to do.
+  if ((TokenMapper != NULL) && (TokenMapper->MaxTokenDescCount == 0)) {
+    goto exit_handler;
+  }
+
+  if ((Token == CM_NULL_TOKEN)              ||
+      (CmObjDesc == NULL)                   ||
+      (TokenMapper == NULL)                 ||
+      (TokenMapper->TokenDescArray == NULL)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TokenMapDesc = TokenMapper->TokenDescArray;
+  MaxCount = TokenMapper->MaxTokenDescCount;
+  for (Index = 0; Index < MaxCount; Index++) {
+    if ((TokenMapDesc->CmObjDesc.ObjectId == ObjectId)  &&
+        (TokenMapDesc->Token == Token)) {
+      CopyMem (
+        CmObjDesc,
+        &TokenMapDesc->CmObjDesc,
+        sizeof (CM_OBJ_DESCRIPTOR)
+        );
+      return EFI_SUCCESS;
+    }
+    TokenMapDesc++;
+  } // for
+
+exit_handler:
+  DEBUG ((
+    DEBUG_INFO,
+    "INFO: Requested CmObj of type 0x%x with token 0x%x"
+    " not found in the dynamic repository\n.",
+    ObjectId,
+    Token
+    ));
+  return EFI_NOT_FOUND;
+}
+
+/** Initialise a TokenMapper.
+
+  @param [in] TokenMapper       The TokenMapper to initialise.
+  @param [in] DescriptorCount   Number of entries to allocate.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ALREADY_STARTED     Instance already initialised.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+**/
+EFI_STATUS
+EFIAPI
+TokenMapperInitialise (
+  IN  TOKEN_MAPPER  * TokenMapper,
+  IN  UINTN           DescriptorCount
+  )
+{
+  if (TokenMapper == NULL) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Nothing to do.
+  if (DescriptorCount == 0) {
+    return EFI_SUCCESS;
+  }
+
+  if (TokenMapper->TokenDescArray != NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: Token mapper already initialised\n."));
+    ASSERT (0);
+    return EFI_ALREADY_STARTED;
+  }
+
+  TokenMapper->TokenDescArray =
+    AllocateZeroPool (sizeof (TOKEN_MAP_DESCRIPTOR) * DescriptorCount);
+  if (TokenMapper->TokenDescArray == NULL) {
+    ASSERT (0);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  TokenMapper->MaxTokenDescCount = DescriptorCount;
+  TokenMapper->ItemCount = 0;
+
+  return EFI_SUCCESS;
+}
+
+/** Shutdown a TokenMapper.
+
+  @param [in] TokenMapper       The TokenMapper to shutdown.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+**/
+EFI_STATUS
+EFIAPI
+TokenMapperShutdown (
+  IN  TOKEN_MAPPER  * TokenMapper
+  )
+{
+  // Nothing to do.
+  if ((TokenMapper != NULL) && (TokenMapper->MaxTokenDescCount == 0)) {
+    return EFI_SUCCESS;
+  }
+
+  if ((TokenMapper == NULL) ||
+      (TokenMapper->TokenDescArray == NULL)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FreePool (TokenMapper->TokenDescArray);
+  TokenMapper->TokenDescArray = NULL;
+  TokenMapper->MaxTokenDescCount = 0;
+
+  return EFI_SUCCESS;
+}
diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenMapper.h b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenMapper.h
new file mode 100644
index 000000000000..377fc03dcd01
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenMapper.h
@@ -0,0 +1,123 @@
+/** @file
+  Token Mapper
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef TOKEN_MAPPER_H_
+#define TOKEN_MAPPER_H_
+
+#pragma pack(1)
+
+/** Token mapping descriptor.
+
+  Bind a token and a CmObj together.
+*/
+typedef struct TokenMapDescriptor {
+  /// Object Token.
+  CM_OBJECT_TOKEN     Token;
+
+  /// CmObjectDescriptor CM_OBJ_DESCRIPTOR.Data is a reference copy
+  /// and not allocated. It points to the individual objects in the
+  /// Dynamic Plat Repo ArmNameSpaceObjectArray.
+  CM_OBJ_DESCRIPTOR   CmObjDesc;
+} TOKEN_MAP_DESCRIPTOR;
+
+/** Token mapper.
+
+  Contain all the Token/CmObj couple mapping.
+**/
+typedef struct TokenMapper {
+  /// Maximum number of TOKEN_MAP_DESCRIPTOR entries in TokenDescArray.
+  UINTN                   MaxTokenDescCount;
+
+  /// Next TOKEN_MAP_DESCRIPTOR entry to use in TokenDescArray.
+  UINTN                   ItemCount;
+
+  /// Array of TOKEN_MAP_DESCRIPTOR.
+  TOKEN_MAP_DESCRIPTOR  * TokenDescArray;
+} TOKEN_MAPPER;
+
+#pragma pack()
+
+/** Add a CmObjDesc to the TokenMapper.
+
+  @param [in] TokenMapper   The TokenMapper instance.
+  @param [in] Token         CmObj token.
+  @param [in] ObjectId      CmObj ObjectId.
+  @param [in] Size          CmObj Size.
+  @param [in] Data          CmObj Data.
+                            This memory is referenced, not copied.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_BUFFER_TOO_SMALL    Buffer too small.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+**/
+EFI_STATUS
+EFIAPI
+TokenMapperAddObject (
+  IN  TOKEN_MAPPER      *TokenMapper,
+  IN  CM_OBJECT_TOKEN   Token,
+  IN  CM_OBJECT_ID      ObjectId,
+  IN  UINT32            Size,
+  IN  VOID              *Data
+  );
+
+/** Get a CmObjDesc from a ObjectId/Token couple.
+
+  The Token parameter is not optional. An existing token must be provided.
+
+  @param [in]  TokenMapper   The TokenMapper instance.
+  @param [in]  Token         Token of the CmObj to search.
+  @param [in]  ObjectId      Object Id of the CmObj to search.
+  @param [out] CmObjDesc     CM_OBJ_DESCRIPTOR containing the CmObj searched.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+  @retval EFI_NOT_FOUND           Not found.
+**/
+EFI_STATUS
+EFIAPI
+TokenMapperGetObject (
+  IN  TOKEN_MAPPER        *TokenMapper,
+  IN  CM_OBJECT_TOKEN     Token,
+  IN  CM_OBJECT_ID        ObjectId,
+  OUT CM_OBJ_DESCRIPTOR   *CmObjDesc
+  );
+
+/** Initialise a TokenMapper.
+
+  @param [in] TokenMapper       The TokenMapper to initialise.
+  @param [in] DescriptorCount   Number of entries to allocate.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ALREADY_STARTED     Instance already initialised.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+**/
+EFI_STATUS
+EFIAPI
+TokenMapperInitialise (
+  IN  TOKEN_MAPPER  * TokenMapper,
+  IN  UINTN           DescriptorCount
+  );
+
+/** Shutdown a TokenMapper.
+
+  @param [in] TokenMapper       The TokenMapper to shutdown.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+**/
+EFI_STATUS
+EFIAPI
+TokenMapperShutdown (
+  IN  TOKEN_MAPPER  * TokenMapper
+  );
+
+#endif // TOKEN_MAPPER_H_
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 5/5] DynamicTablesPkg: Add DynamicPlatRepo library
  2021-11-23 11:10 [PATCH v2 0/5] Add DynamicPlatRepoLib PierreGondois
                   ` (3 preceding siblings ...)
  2021-11-23 11:10 ` [PATCH v2 4/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenMapper PierreGondois
@ 2021-11-23 11:10 ` PierreGondois
  4 siblings, 0 replies; 6+ messages in thread
From: PierreGondois @ 2021-11-23 11:10 UTC (permalink / raw)
  To: pierre.gondois, devel; +Cc: Sami Mujawar, Alexei Fedorov

From: Pierre Gondois <Pierre.Gondois@arm.com>

The DynamicPlatRepo library allows to handle dynamically created
CmObj. The dynamic platform repository can be in the following states:
1 - Non-initialised
2 - Transient:
    Possibility to add CmObj to the platform, but not to query them.
3 - Finalised:
    Possibility to query CmObj, but not to add new.

A token is allocated to each CmObj added to the dynamic platform
repository (except for reference tokens CmObj). This allows to retrieve
dynamic CmObjs among all CmObj (static CmObj for instance).

This patch add the inf file of the module and the main module
functionnalities and update the dsc file of the package.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 DynamicTablesPkg/DynamicTablesPkg.dsc         |   1 +
 .../DynamicPlatRepoLib/DynamicPlatRepo.c      | 515 ++++++++++++++++++
 .../DynamicPlatRepoInternal.h                 |  78 +++
 .../DynamicPlatRepoLib/DynamicPlatRepoLib.inf |  33 ++
 4 files changed, 627 insertions(+)
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepo.c
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoInternal.h
 create mode 100644 DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf

diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc b/DynamicTablesPkg/DynamicTablesPkg.dsc
index a2a1b8d004d2..068f0bc63080 100644
--- a/DynamicTablesPkg/DynamicTablesPkg.dsc
+++ b/DynamicTablesPkg/DynamicTablesPkg.dsc
@@ -44,6 +44,7 @@ [Components.common]
   DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf
   DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf
   DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf
+  DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf
 
 [BuildOptions]
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepo.c b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepo.c
new file mode 100644
index 000000000000..faa431455761
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepo.c
@@ -0,0 +1,515 @@
+/** @file
+  Dynamic Platform Info Repository
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "CmObjectTokenFixer.h"
+#include "DynamicPlatRepoInternal.h"
+#include "TokenGenerator.h"
+
+/** Allocate a CM_OBJ_NODE.
+
+  @param [in]  CmObjDesc  CmObj to wrap in a node.
+                          All the fields of the CmObj (Data field included),
+                          are copied.
+  @param [in]  Token      Token to assign to this CmObj/node.
+  @param [out] ObjNode    Allocated ObjNode.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_OUT_OF_RESOURCES  An allocation has failed.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AllocCmObjNode (
+  IN  CONST CM_OBJ_DESCRIPTOR   * CmObjDesc,
+  IN        CM_OBJECT_TOKEN       Token,
+  OUT       CM_OBJ_NODE        ** ObjNode
+  )
+{
+  CM_OBJ_NODE       *Node;
+  CM_OBJ_DESCRIPTOR *Desc;
+
+  if ((CmObjDesc == NULL) || (ObjNode == NULL)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Node = AllocateZeroPool (sizeof (CM_OBJ_NODE));
+  if (Node == NULL) {
+    ASSERT (0);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  // Initialise the list head.
+  InitializeListHead (&Node->Link);
+  Node->Token = Token;
+  Desc = &Node->CmObjDesc;
+  Desc->ObjectId = CmObjDesc->ObjectId;
+  Desc->Size = CmObjDesc->Size;
+  Desc->Count = CmObjDesc->Count;
+
+  // Allocate and copy the CmObject Data.
+  Desc->Data = AllocateCopyPool (CmObjDesc->Size, CmObjDesc->Data);
+  if (Desc->Data == NULL) {
+    FreePool (Node);
+    ASSERT (0);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  *ObjNode = Node;
+  return EFI_SUCCESS;
+}
+
+/** Free a CM_OBJ_NODE.
+
+  @param [in]  ObjNode    ObjNode to free.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FreeCmObjNode (
+  IN  CM_OBJ_NODE   * ObjNode
+  )
+{
+  CM_OBJ_DESCRIPTOR   *Desc;
+
+  if (ObjNode == NULL) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Unlink Node
+  RemoveEntryList (&ObjNode->Link);
+
+  Desc = &ObjNode->CmObjDesc;
+  if (Desc->Data != NULL) {
+    FreePool (Desc->Data);
+  }
+
+  FreePool (ObjNode);
+  return EFI_SUCCESS;
+}
+
+/** Add an object to the dynamic platform repository.
+
+  @param [in]  This       This dynamic platform repository.
+  @param [in]  CmObjDesc  CmObj to add. The data is copied.
+  @param [out] Token      If not NULL, token allocated to this CmObj.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_OUT_OF_RESOURCES  An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+DynPlatRepoAddObject (
+  IN        DYNAMIC_PLATFORM_REPOSITORY_INFO    * This,
+  IN  CONST CM_OBJ_DESCRIPTOR                   * CmObjDesc,
+  OUT       CM_OBJECT_TOKEN                     * Token OPTIONAL
+  )
+{
+  EFI_STATUS              Status;
+  CM_OBJ_NODE             *ObjNode;
+  CM_OBJECT_ID            ArmNamespaceObjId;
+  CM_OBJECT_TOKEN         NewToken;
+
+  // The dynamic repository must be able to receive objects.
+  if ((This == NULL)      ||
+      (CmObjDesc == NULL) ||
+      (This->RepoState != DynRepoTransient)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Check the CmObjDesc:
+  //  - only Arm objects are supported for now.
+  //  - only EArmObjCmRef objects can be added as arrays.
+  ArmNamespaceObjId = GET_CM_OBJECT_ID (CmObjDesc->ObjectId);
+  if ((CmObjDesc->Size == 0)              ||
+      (CmObjDesc->Count == 0)             ||
+      (ArmNamespaceObjId >= EArmObjMax)   ||
+      ((CmObjDesc->Count > 1)  && (ArmNamespaceObjId != EArmObjCmRef))  ||
+      (GET_CM_NAMESPACE_ID (CmObjDesc->ObjectId) != EObjNameSpaceArm)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Generate a token.
+  NewToken = GenerateToken ();
+
+  // Create an ObjNode.
+  Status = AllocCmObjNode (CmObjDesc, NewToken, &ObjNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // Fixup self-token if necessary.
+  Status = FixupCmObjectSelfToken (&ObjNode->CmObjDesc, NewToken);
+  if (EFI_ERROR (Status)) {
+    FreeCmObjNode (ObjNode);
+    ASSERT (0);
+    return Status;
+  }
+
+  // Add to link list.
+  InsertTailList (&This->ArmCmObjList[ArmNamespaceObjId], &ObjNode->Link);
+  This->ObjectCount += 1;
+
+  if (Token != NULL) {
+    *Token = NewToken;
+  }
+  return EFI_SUCCESS;
+}
+
+/** Group lists of CmObjNode from the ArmNameSpace to one array.
+
+  @param [in]  This         This dynamic platform repository.
+  @param [in]  ArmObjIndex  Index in EARM_OBJECT_ID
+                            (must be < EArmObjMax).
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_BUFFER_TOO_SMALL    Buffer too small.
+  @retval EFI_OUT_OF_RESOURCES  An allocation has failed.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GroupCmObjNodes (
+  IN  DYNAMIC_PLATFORM_REPOSITORY_INFO    * This,
+  IN  UINT32                                ArmObjIndex
+  )
+{
+  EFI_STATUS          Status;
+  UINTN               Count;
+  UINTN               Size;
+  UINT32              CmObjId;
+  UINT8               *GroupedData;
+  UINT8               *Data;
+  CM_OBJ_DESCRIPTOR   *CmObjDesc;
+  LIST_ENTRY          *ListHead;
+  LIST_ENTRY          *Link;
+
+  if ((This == NULL)  ||
+      (ArmObjIndex >= EArmObjMax)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Count = 0;
+  Size = 0;
+  CmObjId = CREATE_CM_ARM_OBJECT_ID (ArmObjIndex);
+  ListHead = &This->ArmCmObjList[ArmObjIndex];
+  Link = GetFirstNode (ListHead);
+
+  // Compute the total count and size of the CmObj in the list.
+  while (Link != ListHead) {
+    CmObjDesc = &((CM_OBJ_NODE*)Link)->CmObjDesc;
+
+    if (CmObjDesc->ObjectId != CmObjId) {
+      ASSERT (0);
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if ((CmObjDesc->Count != 1) && (ArmObjIndex != EArmObjCmRef)){
+      // We expect each descriptor to contain an individual object.
+      // EArmObjCmRef objects are counted as groups, so +1 as well.
+      ASSERT (0);
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Count++;
+    Size += CmObjDesc->Size;
+
+    // Next Link
+    Link = GetNextNode (ListHead, Link);
+  } // while
+
+  if (Count == 0) {
+    // No objects found.
+    return EFI_SUCCESS;
+  }
+
+  GroupedData = AllocateZeroPool (Size);
+  if (GroupedData == NULL) {
+    ASSERT (0);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  // Copy the Object Data and add to the TokenMapper.
+  Data = GroupedData;
+  Link = GetFirstNode (ListHead);
+  while (Link != ListHead) {
+    CmObjDesc = &((CM_OBJ_NODE*)Link)->CmObjDesc;
+    CopyMem (Data, CmObjDesc->Data, CmObjDesc->Size);
+
+    // Add the object to the Token Mapper.
+    // Note: The CmObject Data field of objects in the Token Mapper point
+    //       to the memory in the GroupedData array.
+    Status = TokenMapperAddObject (
+               &This->TokenMapper,
+               ((CM_OBJ_NODE*)Link)->Token,
+               CmObjDesc->ObjectId,
+               CmObjDesc->Size,
+               Data
+               );
+    if (EFI_ERROR (Status)) {
+      FreePool (GroupedData);
+      return Status;
+    }
+
+    Data += CmObjDesc->Size;
+    Link = GetNextNode (ListHead, Link);
+  } // while
+
+  CmObjDesc = &This->ArmCmObjArray[ArmObjIndex];
+  CmObjDesc->ObjectId = CmObjId;
+  CmObjDesc->Size = Size;
+  CmObjDesc->Count = Count;
+  CmObjDesc->Data = GroupedData;
+
+  return Status;
+}
+
+/** Finalise the dynamic repository.
+
+  Finalising means:
+   - Preventing any further objects from being added.
+   - Allowing to get objects from the dynamic repository
+     (not possible before a call to this function).
+
+  @param [in]  This       This dynamic platform repository.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_ALREADY_STARTED   Instance already initialised.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_BUFFER_TOO_SMALL  Buffer too small.
+  @retval EFI_OUT_OF_RESOURCES  An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+DynamicPlatRepoFinalise (
+  IN  DYNAMIC_PLATFORM_REPOSITORY_INFO      * This
+  )
+{
+  EFI_STATUS    Status;
+  UINTN         ArmObjIndex;
+
+  if ((This == NULL)  ||
+      (This->RepoState != DynRepoTransient)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Prevent any further objects from being added.
+  This->RepoState = DynRepoFinalized;
+
+  // Initialise the token mapper.
+  Status = TokenMapperInitialise (&This->TokenMapper, This->ObjectCount);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // For each CM_OBJECT_ID:
+  //  - Convert the list of nodes to an array
+  //    (the array is wrapped in a CmObjDesc).
+  //  - Add the Token/CmObj binding to the token mapper.
+  for (ArmObjIndex = 0; ArmObjIndex < EArmObjMax; ArmObjIndex++) {
+      Status = GroupCmObjNodes (This, ArmObjIndex);
+      if (EFI_ERROR (Status)) {
+        ASSERT (0);
+        // Free the TokenMapper.
+        // Ignore the returned Status since we already failed.
+        TokenMapperShutdown (&This->TokenMapper);
+        return Status;
+      }
+  } // for
+
+  return EFI_SUCCESS;
+}
+
+/** Get a CmObj from the dynamic repository.
+
+  @param [in]      This        Pointer to the Dynamic Platform Repository.
+  @param [in]      CmObjectId  The Configuration Manager Object ID.
+  @param [in]      Token       An optional token identifying the object. If
+                               unused this must be CM_NULL_TOKEN.
+  @param [in, out] CmObjDesc   Pointer to the Configuration Manager Object
+                               descriptor describing the requested Object.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_NOT_FOUND         The required object information is not found.
+**/
+EFI_STATUS
+EFIAPI
+DynamicPlatRepoGetObject (
+  IN      DYNAMIC_PLATFORM_REPOSITORY_INFO    * This,
+  IN      CM_OBJECT_ID                          CmObjectId,
+  IN      CM_OBJECT_TOKEN                       Token OPTIONAL,
+  IN  OUT CM_OBJ_DESCRIPTOR                   * CmObjDesc
+  )
+{
+  EFI_STATUS          Status;
+  CM_OBJ_DESCRIPTOR   *Desc;
+  CM_OBJECT_ID        ArmNamespaceObjId;
+
+  if ((This == NULL)      ||
+      (CmObjDesc == NULL) ||
+      (This->RepoState != DynRepoFinalized)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ArmNamespaceObjId = GET_CM_OBJECT_ID (CmObjectId);
+  if (ArmNamespaceObjId >= EArmObjMax) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Token != CM_NULL_TOKEN) {
+    // Search in the Token Mapper and return the object.
+    Status = TokenMapperGetObject (
+               &This->TokenMapper,
+               Token,
+               CmObjectId,
+               CmObjDesc
+               );
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  if (ArmNamespaceObjId == EArmObjCmRef) {
+    // EArmObjCmRef object must be requested using a valid token.
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Desc = &This->ArmCmObjArray[ArmNamespaceObjId];
+
+  // Nothing here.
+  if (Desc->Count == 0) {
+    return EFI_NOT_FOUND;
+  } else {
+    // Return the full array.
+    CmObjDesc->ObjectId = Desc->ObjectId;
+    CmObjDesc->Size = Desc->Size;
+    CmObjDesc->Data = Desc->Data;
+    CmObjDesc->Count = Desc->Count;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Initialize the dynamic platform repository.
+
+  @param [out]  DynPlatRepo   If success, contains the initialised dynamic
+                              platform repository.
+
+  @retval EFI_SUCCESS           Success.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_OUT_OF_RESOURCES  An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+DynamicPlatRepoInit (
+  OUT DYNAMIC_PLATFORM_REPOSITORY_INFO   ** DynPlatRepo
+  )
+{
+  UINTN                              Index;
+  DYNAMIC_PLATFORM_REPOSITORY_INFO * Repo;
+
+  if (DynPlatRepo == NULL) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Repo = AllocateZeroPool (sizeof (DYNAMIC_PLATFORM_REPOSITORY_INFO));
+  if (Repo == NULL) {
+    ASSERT (0);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  // Initialise the CmObject List.
+  for (Index = 0; Index < EArmObjMax; Index++) {
+    InitializeListHead (&Repo->ArmCmObjList[Index]);
+  }
+
+  Repo->ObjectCount = 0;
+  Repo->RepoState = DynRepoTransient;
+
+  *DynPlatRepo = Repo;
+
+  return EFI_SUCCESS;
+}
+
+/** Shutdown the dynamic platform repository.
+
+  Free all the memory allocated for the dynamic platform repository.
+
+  @param [in]  DynPlatRepo    The dynamic platform repository.
+
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_SUCCESS           Success.
+**/
+EFI_STATUS
+EFIAPI
+DynamicPlatRepoShutdown (
+  IN  DYNAMIC_PLATFORM_REPOSITORY_INFO * DynPlatRepo
+  )
+{
+  EFI_STATUS            Status;
+  UINT32                Index;
+  LIST_ENTRY          * ListHead;
+  CM_OBJ_DESCRIPTOR   * CmObjDesc;
+  VOID                * Data;
+
+  if (DynPlatRepo == NULL) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Free the list of objects.
+  for (Index = 0; Index < EArmObjMax; Index++) {
+    // Free all the nodes with this object Id.
+    ListHead = &DynPlatRepo->ArmCmObjList[Index];
+    while (!IsListEmpty (ListHead)) {
+      FreeCmObjNode ((CM_OBJ_NODE*)GetFirstNode (ListHead));
+    } // while
+  } // for
+
+  // Free the arrays.
+  CmObjDesc = DynPlatRepo->ArmCmObjArray;
+  for (Index = 0; Index < EArmObjMax; Index++) {
+    Data = CmObjDesc[Index].Data;
+    if (Data != NULL) {
+      FreePool (Data);
+    }
+  } // for
+
+  // Free the TokenMapper
+  Status = TokenMapperShutdown (&DynPlatRepo->TokenMapper);
+  ASSERT_EFI_ERROR (Status);
+  FreePool (DynPlatRepo);
+  return Status;
+}
diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoInternal.h b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoInternal.h
new file mode 100644
index 000000000000..d03fa2b7dcec
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoInternal.h
@@ -0,0 +1,78 @@
+/** @file
+  Dynamic Platform Info Repository Internal
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef DYNAMIC_PLAT_REPO_INTERNAL_H_
+#define DYNAMIC_PLAT_REPO_INTERNAL_H_
+
+#include "TokenMapper.h"
+
+#pragma pack(1)
+
+/** CmObj node.
+
+  This is a node wrapper around the CM_OBJ_DESCRIPTOR structure.
+  It also allows to bind a token to the CM_OBJ_DESCRIPTOR.
+*/
+typedef struct CmObjectNode {
+  /// This must be the first field in this structure.
+  LIST_ENTRY          Link;
+
+  /// Token associated with the CmObjDesc.
+  CM_OBJECT_TOKEN     Token;
+
+  /// CmObjDesc wrapped.
+  /// Note: the CM_OBJ_DESCRIPTOR.Data field is allocated and copied.
+  CM_OBJ_DESCRIPTOR   CmObjDesc;
+} CM_OBJ_NODE;
+
+/** Dynamic repository states.
+
+  The states must progress as:
+  UnInitialised -> Transient -> Finalized
+*/
+typedef enum DynRepoState {
+  DynRepoUnInitialised, ///< Un-Initialised state
+  DynRepoTransient,     ///< Transient state - CmObjects can be added.
+  DynRepoFinalized,     ///< Repo Locked - No further CmObjects can be added.
+                        ///< Getting objects is now possible.
+  DynRepoMax            ///< Max value.
+} EDYNAMIC_REPO_STATE;
+
+/** A structure describing the platform configuration
+    manager repository information
+*/
+typedef struct DynamicPlatformRepositoryInfo {
+  /// Repo state machine.
+  EDYNAMIC_REPO_STATE   RepoState;
+
+  /// Count of all the objects added to the Dynamic Platform Repo
+  /// during the Transient state.
+  UINTN                 ObjectCount;
+
+  /// Link lists of CmObj from the ArmNameSpace
+  /// that are added in the Transient state.
+  LIST_ENTRY            ArmCmObjList[EArmObjMax];
+
+  /// Structure Members used in Finalized state.
+  /// An array of CmObj Descriptors from the ArmNameSpace
+  /// This array is populated when the Repo is finalized.
+  CM_OBJ_DESCRIPTOR     ArmCmObjArray[EArmObjMax];
+
+  /// A token mapper for the objects in the ArmNamespaceObjectArray
+  /// The Token mapper is populated when the Repo is finalized in
+  /// a call to DynamicPlatRepoFinalise ().
+  TOKEN_MAPPER          TokenMapper;
+} DYNAMIC_PLATFORM_REPOSITORY_INFO;
+
+#pragma pack()
+
+#endif // DYNAMIC_PLAT_REPO_INTERNAL_H_
diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf
new file mode 100644
index 000000000000..9a3cc87fd91d
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf
@@ -0,0 +1,33 @@
+## @file
+#  Dynamic Platform Repository
+#
+#  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION    = 0x0001001B
+  BASE_NAME      = DynamicPlatRepoLib
+  FILE_GUID      = 836D253D-3144-4A89-9BEE-BC55AFDC814E
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = DynamicPlatRepoLib
+
+[Sources]
+  CmObjectTokenFixer.c
+  CmObjectTokenFixer.h
+  DynamicPlatRepo.c
+  DynamicPlatRepoInternal.h
+  TokenGenerator.c
+  TokenGenerator.h
+  TokenMapper.c
+  TokenMapper.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  DynamicTablesPkg/DynamicTablesPkg.dec
+
+[LibraryClasses]
+  AcpiHelperLib
+  BaseLib
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-11-23 11:10 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-11-23 11:10 [PATCH v2 0/5] Add DynamicPlatRepoLib PierreGondois
2021-11-23 11:10 ` [PATCH v2 1/5] DynamicTablesPkg: Definition for DynamicPlatRepoLib interface PierreGondois
2021-11-23 11:10 ` [PATCH v2 2/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenGenerator PierreGondois
2021-11-23 11:10 ` [PATCH v2 3/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenFixer PierreGondois
2021-11-23 11:10 ` [PATCH v2 4/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenMapper PierreGondois
2021-11-23 11:10 ` [PATCH v2 5/5] DynamicTablesPkg: Add DynamicPlatRepo library PierreGondois

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox