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 <pierre.gondois@arm.com>
This commit is contained in:
committed by
mergify[bot]
parent
1b7d687dc6
commit
d15e48853c
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
57
DynamicTablesPkg/Include/Library/MetadataHandlerLib.h
Normal file
57
DynamicTablesPkg/Include/Library/MetadataHandlerLib.h
Normal file
@@ -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 <Library/MetadataObjLib.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.
|
||||
**/
|
||||
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_
|
||||
@@ -0,0 +1,112 @@
|
||||
/** @file
|
||||
Metadata Handler Library.
|
||||
|
||||
Copyright (c) 2025, Arm Limited. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <ConfigurationManagerObject.h>
|
||||
|
||||
#include <Library/MetadataObjLib.h>
|
||||
#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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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 <Base.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <ConfigurationManagerObject.h>
|
||||
|
||||
#include <Library/MetadataObjLib.h>
|
||||
#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;
|
||||
}
|
||||
287
DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataUid.c
Normal file
287
DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataUid.c
Normal file
@@ -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 <Base.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <ConfigurationManagerObject.h>
|
||||
|
||||
#include <Library/MetadataObjLib.h>
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user