From d15e48853c6ace628d98dac8b5f905f40c50a887 Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Fri, 25 Apr 2025 11:13:05 +0200 Subject: [PATCH] DynamicTablesPkg: Add MetadataHandlerLib library Built on top of the MetadataObjLib, this library aims to provide functions for each METADATA_ID to: - Generate new Metadata on the fly: the caller provides minimal information for a METADATA_ID, and the library generates the missing information. - Validate all the Metadata objects for a METADATA_ID. For instance, _UID must be unique for a _HID/_CID/EISAID. This patch also adds support for generation/validation of: - UIDs: For each EISAID or NameId, UIDs must be unique. The generation if UIDs is done by a per-EISAID/NameId incrementing counter. The validation of the Metadata consists in checking for the uniqueness of the UID per EISAID/NameId. - ProximityDomains: Proximity Domain Ids are generated by a counter, starting from 0. The validation of the Metadata consists in checking for the uniqueness of the proximity domain Ids. Signed-off-by: Pierre Gondois --- DynamicTablesPkg/DynamicTables.dsc.inc | 1 + DynamicTablesPkg/DynamicTablesPkg.dec | 3 + DynamicTablesPkg/DynamicTablesPkg.dsc | 1 + .../Include/Library/MetadataHandlerLib.h | 57 ++++ .../MetadataHandlerLib/MetadataHandler.c | 112 +++++++ .../MetadataHandlerLib/MetadataHandler.h | 144 +++++++++ .../MetadataHandlerLib/MetadataHandlerLib.inf | 29 ++ .../MetadataProximityDomain.c | 154 ++++++++++ .../Common/MetadataHandlerLib/MetadataUid.c | 287 ++++++++++++++++++ 9 files changed, 788 insertions(+) create mode 100644 DynamicTablesPkg/Include/Library/MetadataHandlerLib.h create mode 100644 DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandler.c create mode 100644 DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandler.h create mode 100644 DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandlerLib.inf create mode 100644 DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataProximityDomain.c create mode 100644 DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataUid.c diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc index 781e8c61c6..d5d7c268c7 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -23,6 +23,7 @@ TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf SmbiosStringTableLib|DynamicTablesPkg/Library/Common/SmbiosStringTableLib/SmbiosStringTableLib.inf MetadataObjLib|DynamicTablesPkg/Library/Common/MetadataObjLib/MetadataObjLib.inf + MetadataHandlerLib|DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandlerLib.inf [LibraryClasses.AARCH64] DynamicTablesScmiInfoLib|DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.inf diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/DynamicTablesPkg.dec index 3ae95dc6eb..babd6130eb 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dec +++ b/DynamicTablesPkg/DynamicTablesPkg.dec @@ -46,6 +46,9 @@ ## @libraryclass Defines a set of APIs to a handle Metadata around CmObj. MetadataObjLib|Include/Library/MetadataObjLib.h + ## @libraryclass Defines a set of APIs to a handle Metadata generation/validation. + MetadataHandlerLib|Include/Library/MetadataHandlerLib.h + [LibraryClasses.AARCH64] ## @libraryclass Defines a set of APIs to populate CmObj using SCMI. DynamicTablesScmiInfoLib|Include/Library/DynamicTablesScmiInfoLib.h diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc b/DynamicTablesPkg/DynamicTablesPkg.dsc index 8e11a6e0a4..c2e6f5c454 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dsc +++ b/DynamicTablesPkg/DynamicTablesPkg.dsc @@ -49,6 +49,7 @@ DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf DynamicTablesPkg/Library/Common/SmbiosStringTableLib/SmbiosStringTableLib.inf DynamicTablesPkg/Library/Common/MetadataObjLib/MetadataObjLib.inf + DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandlerLib.inf [Components.ARM, Components.AARCH64] DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf diff --git a/DynamicTablesPkg/Include/Library/MetadataHandlerLib.h b/DynamicTablesPkg/Include/Library/MetadataHandlerLib.h new file mode 100644 index 0000000000..db210413c9 --- /dev/null +++ b/DynamicTablesPkg/Include/Library/MetadataHandlerLib.h @@ -0,0 +1,57 @@ +/** @file + Metadata Handler Library. + + Copyright (c) 2025, Arm Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef METADATA_HANDLER_LIB_H_ +#define METADATA_HANDLER_LIB_H_ + +#include + +/** Query the MetadataObjLib for metadata matching the input (Type/Token). + If the metadata exists, return it. + Otherwise: + - Generate a new metadata object + - Add it to the MetadataObjLib + - return it + + @param[in] Root Root of the Metadata information. + @param[in] Type METADATA_TYPE of the entry to generate. + @param[in] Token Token uniquely identifying an entry among other + objects with the input METADATA_TYPE. + @param[in] Context Optional context to use during the Metadata generation. + @param[in, out] Metadata On input, can contain METADATA_TYPE-specific information. + On output and if success, contains the generated + Metadata object. + @param[in] MetadataSize Size of the input Metadata. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataHandlerGenerate ( + IN METADATA_ROOT_HANDLE Root, + IN METADATA_TYPE Type, + IN CM_OBJECT_TOKEN Token, + IN VOID *Context, + IN OUT VOID *Metadata, + IN UINT32 MetadataSize + ); + +/** Validate the Metadata. + + @param[in] Root Root of the Metadata information. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataHandlerValidate ( + IN METADATA_ROOT_HANDLE Root + ); + +#endif // METADATA_HANDLER_LIB_H_ diff --git a/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandler.c b/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandler.c new file mode 100644 index 0000000000..ad2be3a047 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandler.c @@ -0,0 +1,112 @@ +/** @file + Metadata Handler Library. + + Copyright (c) 2025, Arm Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +#include +#include "MetadataHandler.h" + +/* Metadata handlers. */ +STATIC METADATA_HANDLERS mMetadataHandlers[MetadataTypeMax] = { + // MetadataTypeUid + { + MetadataGenerateUid, + MetadataValidateUid, + }, + // MetadataTypeProximityDomain + { + MetadataGenerateProximityDomain, + MetadataValidateProximityDomain, + }, +}; + +/** Query the MetadataObjLib for metadata matching the input (Type/Token). + If the metadata exists, return it. + Otherwise: + - Generate a new metadata object + - Add it to the MetadataObjLib + - return it + + @param[in] Root Root of the Metadata information. + @param[in] Type METADATA_TYPE of the entry to generate. + @param[in] Token Token uniquely identifying an entry among other + objects with the input METADATA_TYPE. + @param[in] Context Optional context to use during the Metadata generation. + @param[in, out] Metadata On input, can contain METADATA_TYPE-specific information. + On output and if success, contains the generated + Metadata object. + @param[in] MetadataSize Size of the input Metadata. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataHandlerGenerate ( + IN METADATA_ROOT_HANDLE Root, + IN METADATA_TYPE Type, + IN CM_OBJECT_TOKEN Token, + IN VOID *Context, + IN OUT VOID *Metadata, + IN UINT32 MetadataSize + ) +{ + EFI_STATUS Status; + + if ((Type >= MetadataTypeMax) || + (Token == CM_NULL_TOKEN) || + (Metadata == NULL) || + (MetadataSize == 0)) + { + ASSERT (Type < MetadataTypeMax); + ASSERT (Token != CM_NULL_TOKEN); + ASSERT (Metadata != NULL); + ASSERT (MetadataSize != 0); + return EFI_INVALID_PARAMETER; + } + + Status = mMetadataHandlers[Type].Generate ( + Root, + Type, + Token, + Context, + Metadata, + MetadataSize + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Validate the Metadata. + + @param[in] Root Root of the Metadata information. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataHandlerValidate ( + IN METADATA_ROOT_HANDLE Root + ) +{ + EFI_STATUS Status; + METADATA_TYPE Type; + + for (Type = 0; Type < MetadataTypeMax; Type++) { + Status = mMetadataHandlers[Type].Validate (Root); + ASSERT_EFI_ERROR (Status); + } + + return Status; +} diff --git a/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandler.h b/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandler.h new file mode 100644 index 0000000000..bdaa7c0695 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandler.h @@ -0,0 +1,144 @@ +/** @file + Metadata Handler Library. + + Copyright (c) 2025, Arm Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef METADATA_HANDLER_H_ +#define METADATA_HANDLER_H_ + +/** Query the MetadataObjLib for metadata matching the input (Type/Token). + If the metadata exists, return it. + Otherwise: + - Generate a new metadata object + - Add it to the MetadataObjLib + - return it + + @param[in] Root Root of the Metadata information. + @param[in] Type METADATA_TYPE of the entry to generate. + @param[in] Token Token uniquely identifying an entry among other + objects with the input METADATA_TYPE. + @param[in] Context Optional context to use during the Metadata generation. + @param[in, out] Metadata On input, can contain METADATA_TYPE-specific information. + On output and if success, contains the generated + Metadata object. + @param[in] MetadataSize Size of the input Metadata. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +typedef EFI_STATUS (EFIAPI *METADATA_GENERATOR)( + IN METADATA_ROOT_HANDLE Root, + IN METADATA_TYPE Type, + IN CM_OBJECT_TOKEN Token, + IN VOID *Context, + IN OUT VOID *Metadata, + IN UINT32 MetadataSize + ); + +/** Validate the Metadata. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +typedef EFI_STATUS (EFIAPI *METADATA_VALIDATOR)( + IN METADATA_ROOT_HANDLE Root + ); + +/** Metadata Handlers. + */ +typedef struct MetadataHandlers { + METADATA_GENERATOR Generate; + METADATA_VALIDATOR Validate; +} METADATA_HANDLERS; + +/** Query the MetadataObjLib for metadata matching the input (Type/Token). + If the metadata exists, return it. + Otherwise: + - Generate a new metadata object + - Add it to the MetadataObjLib + - return it + + @param[in] Root Root of the Metadata information. + @param[in] Type METADATA_TYPE of the entry to generate. + @param[in] Token Token uniquely identifying an entry among other + objects with the input METADATA_TYPE. + @param[in] Context Optional context to use during the Metadata generation. + @param[in, out] Metadata On input, can contain METADATA_TYPE-specific information. + On output and if success, contains the generated + Metadata object. + @param[in] MetadataSize Size of the input Metadata. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataGenerateUid ( + IN METADATA_ROOT_HANDLE Root, + IN METADATA_TYPE Type, + IN CM_OBJECT_TOKEN Token, + IN VOID *Context, + IN OUT VOID *Metadata, + IN UINT32 MetadataSize + ); + +/** Validate the Metadata. + + @param[in] Root Root of the Metadata information. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataValidateUid ( + IN METADATA_ROOT_HANDLE Root + ); + +/** Query the MetadataObjLib for metadata matching the input (Type/Token). + If the metadata exists, return it. + Otherwise: + - Generate a new metadata object + - Add it to the MetadataObjLib + - return it + + @param[in] Root Root of the Metadata information. + @param[in] Type METADATA_TYPE of the entry to generate. + @param[in] Token Token uniquely identifying an entry among other + objects with the input METADATA_TYPE. + @param[in] Context Optional context to use during the Metadata generation. + @param[in, out] Metadata On input, can contain METADATA_TYPE-specific information. + On output and if success, contains the generated + Metadata object. + @param[in] MetadataSize Size of the input Metadata. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataGenerateProximityDomain ( + IN METADATA_ROOT_HANDLE Root, + IN METADATA_TYPE Type, + IN CM_OBJECT_TOKEN Token, + IN VOID *Context, + IN OUT VOID *Metadata, + IN UINT32 MetadataSize + ); + +/** Validate the Metadata. + + @param[in] Root Root of the Metadata information. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataValidateProximityDomain ( + IN METADATA_ROOT_HANDLE Root + ); + +#endif // METADATA_HANDLER_H_ diff --git a/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandlerLib.inf b/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandlerLib.inf new file mode 100644 index 0000000000..69f0b85fcc --- /dev/null +++ b/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandlerLib.inf @@ -0,0 +1,29 @@ +## @file +# Metadata Handler Library +# +# Copyright (c) 2025, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = MetadataHandlerLib + FILE_GUID = 60E0B01A-94E6-48C6-B21B-F772E58352E9 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = MetadataHandlerLib + +[Sources] + MetadataHandler.c + MetadataHandler.h + MetadataProximityDomain.c + MetadataUid.c + +[Packages] + MdePkg/MdePkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + BaseLib + MetadataObjLib diff --git a/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataProximityDomain.c b/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataProximityDomain.c new file mode 100644 index 0000000000..daa539f1b6 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataProximityDomain.c @@ -0,0 +1,154 @@ +/** @file + Metadata Proximity Domain handlers. + + Copyright (c) 2025, Arm Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +#include +#include "MetadataHandler.h" + +typedef struct ProximityDomainData { + /// Current Id used for the Proximity Domain Id generation. + UINT32 CurrentId; +} PROXIMITY_DOMAIN_DATA; + +STATIC PROXIMITY_DOMAIN_DATA mProximityDomainData = { + 0 +}; + +/** Query the MetadataObjLib for metadata matching the input (Type/Token). + If the metadata exists, return it. + Otherwise: + - Generate a new metadata object + - Add it to the MetadataObjLib + - return it + + @param[in] Root Root of the Metadata information. + @param[in] Type METADATA_TYPE of the entry to generate. + @param[in] Token Token uniquely identifying an entry among other + objects with the input METADATA_TYPE. + @param[in] Context Optional context to use during the Metadata generation. + @param[in, out] Metadata On input, can contain METADATA_TYPE-specific information. + On output and if success, contains the generated + Metadata object. + @param[in] MetadataSize Size of the input Metadata. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataGenerateProximityDomain ( + IN METADATA_ROOT_HANDLE Root, + IN METADATA_TYPE Type, + IN CM_OBJECT_TOKEN Token, + IN VOID *Context, + IN OUT VOID *Metadata, + IN UINT32 MetadataSize + ) +{ + EFI_STATUS Status; + METADATA_OBJ_PROXIMITY_DOMAIN *ProximityDomain; + + if ((Type != MetadataTypeProximityDomain) || + (Token == CM_NULL_TOKEN) || + (Metadata == NULL)) + { + ASSERT (Type == MetadataTypeProximityDomain); + ASSERT (Token != CM_NULL_TOKEN); + ASSERT (Metadata != NULL); + return EFI_INVALID_PARAMETER; + } + + Status = MetadataGet (Root, Type, Token, Metadata, MetadataSize); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + return Status; + } else if (Status == EFI_SUCCESS) { + // Metadata for this (Type/Token) already exists. + return EFI_SUCCESS; + } + + // Generate new Metadata (i.e. Status == EFI_NOT_FOUND). + + ProximityDomain = (METADATA_OBJ_PROXIMITY_DOMAIN *)Metadata; + ProximityDomain->Id = mProximityDomainData.CurrentId++; + + Status = MetadataAdd (Root, Type, Token, Metadata, MetadataSize); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + return EFI_SUCCESS; +} + +/** Validate the Metadata. + + @param[in] Root Root of the Metadata information. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataValidateProximityDomain ( + IN METADATA_ROOT_HANDLE Root + ) +{ + METADATA_HANDLE Handle0; + METADATA_HANDLE Handle1; + METADATA_OBJ_PROXIMITY_DOMAIN Metadata0; + METADATA_OBJ_PROXIMITY_DOMAIN Metadata1; + + Handle0 = NULL; + + while (TRUE) { + Handle0 = MetadataIterate ( + Root, + MetadataTypeProximityDomain, + Handle0, + &Metadata0, + sizeof (METADATA_OBJ_PROXIMITY_DOMAIN) + ); + if (Handle0 == NULL) { + break; + } + + // Loop starting from Handle0 + Handle1 = Handle0; + + while (TRUE) { + Handle1 = MetadataIterate ( + Root, + MetadataTypeProximityDomain, + Handle1, + &Metadata1, + sizeof (METADATA_OBJ_PROXIMITY_DOMAIN) + ); + + if (Handle1 == NULL) { + break; + } + + if (Metadata0.Id == Metadata1.Id) { + DEBUG (( + DEBUG_ERROR, + "Metadata: ProximityDomain: Same Id: %d\n", + Metadata0.Id + )); + ASSERT (0); + } + } + } + + return EFI_SUCCESS; +} diff --git a/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataUid.c b/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataUid.c new file mode 100644 index 0000000000..7183371c93 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataUid.c @@ -0,0 +1,287 @@ +/** @file + Metadata Proximity Domain handlers. + + Copyright (c) 2025, Arm Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +#include +#include "MetadataHandler.h" + +/** Uid Entry + + One entry is allocated for each HID/CID/EISAID. Each entry + contains a counter used for the generation of UID values. +**/ +typedef struct MetadataUidEntry { + LIST_ENTRY List; + + /// _HID or _CID of the device (NULL-terminated string). + /// This provides a mean to uniquely identify a device type. + /// If not populated, EisaId must be set. + CHAR8 NameId[9]; + + /// EisaId of the device. + /// This provides a mean to uniquely identify a device type. + /// If not populated, NameId must be set. + UINT32 EisaId; + + /// Current Id used for the generation of a HID/CID/EisaId. + UINT32 CurrId; +} METADATA_UID_ENTRY; + +// List of METADATA_UID_ENTRY +STATIC LIST_ENTRY mUidList = INITIALIZE_LIST_HEAD_VARIABLE (mUidList); + +/** Allocate a METADATA_UID_ENTRY. + + @param [in] Metadata Metadata containing the NameId/EisaId to use. + @param [out] OutEntry Allocated Entry. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +STATIC +EFI_STATUS +EFIAPI +AllocateUidEntry ( + IN METADATA_OBJ_UID *Metadata, + OUT METADATA_UID_ENTRY **OutEntry + ) +{ + METADATA_UID_ENTRY *Entry; + + if ((Metadata == NULL) || (OutEntry == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Entry = AllocateZeroPool (sizeof (METADATA_UID_ENTRY)); + if (Entry == NULL) { + ASSERT (Entry != NULL); + return EFI_OUT_OF_RESOURCES; + } + + InitializeListHead (&Entry->List); + Entry->CurrId = 0; + + if (Metadata->NameId[0] != 0) { + AsciiStrCpyS (Entry->NameId, sizeof (Metadata->NameId), Metadata->NameId); + } else { + Entry->EisaId = Metadata->EisaId; + } + + *OutEntry = Entry; + return EFI_SUCCESS; +} + +/** Find a matching METADATA_UID_ENTRY. + If no Entry is found, allocate one. + + @param [in] Metadata Metadata containing the NameId/EisaId to search. + @param [out] OutEntry Matching or allocated Entry. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +STATIC +EFI_STATUS +EFIAPI +FindEntry ( + IN METADATA_OBJ_UID *Metadata, + OUT METADATA_UID_ENTRY **OutEntry + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + METADATA_UID_ENTRY *Entry; + + if ((Metadata == NULL) || (OutEntry == NULL)) { + ASSERT (Metadata != NULL); + ASSERT (OutEntry != NULL); + return EFI_INVALID_PARAMETER; + } + + Link = GetNextNode (&mUidList, &mUidList); + + while (Link != &mUidList) { + Entry = (METADATA_UID_ENTRY *)Link; + + if (Entry->NameId[0] != 0) { + if (AsciiStrnCmp (Entry->NameId, Metadata->NameId, sizeof (Metadata->NameId)) == 0) { + break; + } + } else if (Metadata->EisaId != 0) { + if (Entry->EisaId == Metadata->EisaId) { + break; + } + } else { + DEBUG ((DEBUG_ERROR, "MetadatUid: Empty NameId and EisaId\n")); + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Link = GetNextNode (&mUidList, Link); + } // while + + // No matching METADATA_UID_ENTRY found. + if (Link == &mUidList) { + Status = AllocateUidEntry (Metadata, &Entry); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + InsertTailList (&mUidList, &Entry->List); + } + + *OutEntry = Entry; + return EFI_SUCCESS; +} + +/** Query the MetadataObjLib for metadata matching the input (Type/Token). + If the metadata exists, return it. + Otherwise: + - Generate a new metadata object + - Add it to the MetadataObjLib + - return it + + @param[in] Root Root of the Metadata information. + @param[in] Type METADATA_TYPE of the entry to generate. + @param[in] Token Token uniquely identifying an entry among other + objects with the input METADATA_TYPE. + @param[in] Context Optional context to use during the Metadata generation. + @param[in, out] Metadata On input, can contain METADATA_TYPE-specific information. + On output and if success, contains the generated + Metadata object. + @param[in] MetadataSize Size of the input Metadata. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataGenerateUid ( + IN METADATA_ROOT_HANDLE Root, + IN METADATA_TYPE Type, + IN CM_OBJECT_TOKEN Token, + IN VOID *Context, + IN OUT VOID *Metadata, + IN UINT32 MetadataSize + ) +{ + EFI_STATUS Status; + METADATA_OBJ_UID *Uid; + METADATA_UID_ENTRY *Entry; + + if ((Type != MetadataTypeUid) || + (Token == CM_NULL_TOKEN) || + (Metadata == NULL)) + { + ASSERT (Type == MetadataTypeUid); + ASSERT (Token != CM_NULL_TOKEN); + ASSERT (Metadata != NULL); + return EFI_INVALID_PARAMETER; + } + + Status = MetadataGet (Root, Type, Token, Metadata, MetadataSize); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + return Status; + } else if (Status == EFI_SUCCESS) { + // Metadata for this (Type/Token) already exists. + return EFI_SUCCESS; + } + + // Generate new Metadata (i.e. Status == EFI_NOT_FOUND). + + // Get the Current Type for this HID/CID/EISAID + Status = FindEntry (Metadata, &Entry); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + Uid = (METADATA_OBJ_UID *)Metadata; + Uid->Uid = Entry->CurrId++; + + Status = MetadataAdd (Root, Type, Token, Metadata, MetadataSize); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + return EFI_SUCCESS; +} + +/** Validate the Metadata. + + @param[in] Root Root of the Metadata information. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +EFI_STATUS +EFIAPI +MetadataValidateUid ( + IN METADATA_ROOT_HANDLE Root + ) +{ + METADATA_HANDLE Handle0; + METADATA_HANDLE Handle1; + METADATA_OBJ_UID Metadata0; + METADATA_OBJ_UID Metadata1; + + Handle0 = NULL; + + while (TRUE) { + Handle0 = MetadataIterate ( + Root, + MetadataTypeUid, + Handle0, + &Metadata0, + sizeof (METADATA_OBJ_UID) + ); + if (Handle0 == NULL) { + break; + } + + // Loop starting from Handle0 + Handle1 = Handle0; + + while (TRUE) { + Handle1 = MetadataIterate ( + Root, + MetadataTypeUid, + Handle1, + &Metadata1, + sizeof (METADATA_OBJ_UID) + ); + + if (Handle1 == NULL) { + break; + } + + if (CompareMem (&Metadata0, &Metadata1, sizeof (METADATA_OBJ_UID)) == 0) { + DEBUG (( + DEBUG_ERROR, + "Metadata: Uid: Same Type: EisaId=%d NameId=%a Uid=%d \n", + Metadata0.EisaId, + Metadata0.NameId, + Metadata0.Uid + )); + ASSERT (0); + } + } + } + + return EFI_SUCCESS; +}