Date   

Re: [PATCH v1 0/5] EDK2 Code First: PI Specification: Update EFI_MM_COMMUNICATE_HEADER

Laszlo Ersek
 

On 06/23/21 08:54, Marvin Häuser wrote:
On 22.06.21 17:34, Laszlo Ersek wrote:
On 06/18/21 11:37, Marvin Häuser wrote:
On 16.06.21 22:58, Kun Qin wrote:
On 06/16/2021 00:02, Marvin Häuser wrote:
2) Is it feasible yet with the current set of supported compilers to
support flexible arrays?
My impression is that flexible arrays are already supported (as seen
in UnitTestFrameworkPkg/PrivateInclude/UnitTestFrameworkTypes.h).
Please correct me if I am wrong.

Would you mind letting me know why this is applicable here? We are
trying to seek ideas on how to catch developer mistakes caused by this
change. So any input is appreciated.
Huh, interesting. Last time I tried I was told about incompatibilities
with MSVC, but I know some have been dropped since then (2005 and 2008
if I recall correctly?), so that'd be great to allow globally.
I too am surprised to see
"UnitTestFrameworkPkg/PrivateInclude/UnitTestFrameworkTypes.h". The
flexible array member is a C99 feature, and I didn't even know that we
disallowed it for the sake of particular VS toolchains -- I thought we
had a more general reason than just "not supported by VS versions X
and Y".

The behavior of OFFSET_OF() would be interesting -- the OFFSET_OF()
macro definition for non-gcc / non-clang:

#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field))

borders on undefined behavior as far as I can tell, so its behavior is
totally up to the compiler. It works thus far okay on Visual Studio, but
I couldn't say if it extended correctly to flexible array members.
Yes, it's UB by the standard, but this is actually how MS implements
them (or used to anyway?). I don't see why it'd cause issues with
flexible arrays, as only the start of the array is relevant (which is
constant for all instances of the structure no matter the amount of
elements actually stored). Any specific concern? If so, they could be
addressed by appropriate STATIC_ASSERTs.
No specific concern; my point was that two aspects of the same "class"
of undefined behavior didn't need to be consistent with each other.

Thanks
Laszlo


Re: [PATCH] OvmfPkg/Bhyve: clean up TPM_ENABLE remnants

Laszlo Ersek
 

On 06/22/21 17:38, Kinney, Michael D wrote:
Hi Laszlo,

I am trying the following configuration that is very conservative:

actions:
queue:
method: rebase
rebase_fallback: none
name: default

The auto rebase only attempts a strict rebase. If that attempt at a
strict rebase fails then it will show that there is a conflict that
the developer must take care of.

I believe any combination of 2 PRs that have overlapping diff stat
should fail a strict rebase. The following link describes the method
and rebase_fallback settings in the queue command.

https://docs.mergify.io/actions/queue/#id2

I would be more concerned if we used a method of merge or a
rebase_fallback of merge.

Are there examples you can think of where the diff stat overlap and
the strict rebase will succeed?
I've read the strict rebase definition and the above link in the mergify
documentation, but I'm none the wiser.

Consider the following test case (with master @ 7471751a4d81):

git checkout -b b1 master
git am b1.patch # attached
git checkout -b b2 master
git am b2.patch # attached
git branch b2-rebase b2
git rebase b1 b2-rebase

Locally, this produces the following message for me:

First, rewinding head to replay your work on top of it...
Applying: world
Using index info to reconstruct a base tree...
M ReadMe.rst
Falling back to patching base and 3-way merge...
Auto-merging ReadMe.rst
The rebase succeeds and produces the expected result, but that result is
*exactly* what a human should review.

I don't know if mergify catches the above. While the rebase succeeds
locally, it should not succeed in mergify.

Using the "git rebase -i" (interactive) command, which uses a different
rebase backend (based on git-cherry-pick, not on git-am), and specifying
a single "pick" command, the rebase still succeeds; this time without
producing any diagnostic messages even. So from an auto-rebase
perspective, it's even less desirable.

Thanks
Laszlo


Another option to consider is to define an additional 'auto-rebase' label that is
off by default to enable the auto rebase feature. By default the PR must be synced
with head when submitted. Only if a maintainer sets the 'auto-rebase' label will
an auto-rebase be attempted.

I also want to make it easy for non-maintainers to submit PRs and get CI test results.
So auto rebase may be useful for that use case. Perhaps the 'auto-rebase' label
can be considered when the 'push' label is also set.

Thanks,

Mike

-----Original Message-----
From: Laszlo Ersek <lersek@...>
Sent: Tuesday, June 22, 2021 8:17 AM
To: Kinney, Michael D <michael.d.kinney@...>; devel@edk2.groups.io; spbrogan@...; ardb@...
Cc: Peter Grehan <grehan@...>; Ard Biesheuvel <ardb+tianocore@...>; Justen, Jordan L
<jordan.l.justen@...>; Sean Brogan <sean.brogan@...>; Rebecca Cran <rebecca@...>
Subject: Re: [edk2-devel] [PATCH] OvmfPkg/Bhyve: clean up TPM_ENABLE remnants

On 06/17/21 23:53, Kinney, Michael D wrote:
Hi Sean,

Mergify had added a queue feature to handle the rebases automatically and make sure
CI passes in the order that the PRs are being applied to the base branch.
I'm opposed to *unconditional* auto-rebase.

On one hand, it is indeed unreasonable to require a human to manually
rebase a "ShellPkg/Application/AcpiViewApp" series just because a series
for "SecurityPkg/FvReportPei" was merged a bit earlier. In other words,
merge requests for unrelated modules should not block each other.

On the other hand, auto-rebase is a bad idea if both series modify at
least one module in common (especially if both series modify at least
one *file* in common). In case there is a contextual conflict, even if
the conflict can be auto-resolved, and even if that resolution
*compiles*, it has to be reviewed by a human first.

I regularly use the git-range-diff command for this.

At Red Hat we've seen obscure bugs due to silent mis-merges (not in edk2
-- in different packages); such issues are difficult to debug.

Bisectability helps for sure, but only if the community treats
bisectability with high priority in the first place. (That is, if every
contributor builds their patch set at every stage, before submitting it
for review.)

Can we restrict the auto-rebase feature to such merge requests whose
cumulative diffstats do not intersect?

Thanks,
Laszlo


Re: [PATCH v4 1/4] OvmfPkg/MemEncryptHypercallLib: add library to support SEV hypercalls.

Ashish Kalra
 

Hello Tom, Brijesh,

Thanks for your comments and feedback on this patch-set.

With reference to those, i will remove the new library and
add the hypercall function inside BaseMemEncryptSevLib library.

Also i will let the hypercall handling for SEV-ES be done
as part of #VC exception handling in VmgExitLib library.

Thanks,
Ashish

On Wed, Jun 23, 2021 at 01:47:47AM +0000, Ashish Kalra wrote:
Hello Tom,

On Tue, Jun 22, 2021 at 05:47:48PM -0500, Tom Lendacky wrote:
On 6/21/21 8:56 AM, Ashish Kalra wrote:
From: Ashish Kalra <ashish.kalra@...>

Add SEV and SEV-ES hypercall abstraction library to support SEV Page
encryption/deceryption status hypercalls for SEV and SEV-ES guests.
Does this have to be a new library? It's just a single function and so I
would think it could live in the BaseMemEncryptSevLib library where the
change to the c-bit is being done anyway.
Actually i like this approach, instead of adding a new library.

Again, IIRC we had discussed this internally and then decided to
create a new hypercall library similar to Xen, with reference to
the email copied below :

...
Xen has support under Ovmf for a Xen hypercall library
(OvmfPkg/Library/XenHypercallLib). Take a look at that and maybe create
something similar for KVM.
...

Thanks,
Ashish


[PATCH v1 5/5] ArmVirtPkg: Enable Acpiview for ArmVirtPkg

PierreGondois
 

From: Sami Mujawar <sami.mujawar@...>

Acpiview is a command line tool allowing to display, dump, or
check installed ACPI tables. Add the tool to ArmVirt platforms.

Signed-off-by: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
ArmVirtPkg/ArmVirt.dsc.inc | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/ArmVirtPkg/ArmVirt.dsc.inc b/ArmVirtPkg/ArmVirt.dsc.inc
index d9abadbe708c..269ac4990a6c 100644
--- a/ArmVirtPkg/ArmVirt.dsc.inc
+++ b/ArmVirtPkg/ArmVirt.dsc.inc
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+# Copyright (c) 2011-2021, Arm Limited. All rights reserved.
# Copyright (c) 2014, Linaro Limited. All rights reserved.
# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
# Copyright (c) Microsoft Corporation.
@@ -398,6 +398,7 @@ [Components.common]
NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
!if $(NETWORK_IP6_ENABLE) == TRUE
--
2.17.1


[PATCH v1 4/5] ArmVirtPkg: Enable ACPI support for Kvmtool

PierreGondois
 

From: Sami Mujawar <sami.mujawar@...>

A Configuration Manager that uses the Dynamic Tables framework
to generate ACPI tables for Kvmtool Guests has been provided.
This Configuration Manager uses the FdtHwInfoParser module to
parse the Kvmtool Device Tree and generate the required
Configuration Manager objects for generating the ACPI tables.

Therefore, enable ACPI table generation for Kvmtool.

Signed-off-by: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
ArmVirtPkg/ArmVirtKvmTool.dsc | 15 +++++++++++++--
ArmVirtPkg/ArmVirtKvmTool.fdf | 11 +++++++++++
2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index 920880796ac2..b02324312f18 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.dsc
+++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
@@ -28,6 +28,7 @@ [Defines]
FLASH_DEFINITION = ArmVirtPkg/ArmVirtKvmTool.fdf

!include ArmVirtPkg/ArmVirt.dsc.inc
+!include DynamicTablesPkg/DynamicTables.dsc.inc

!include MdePkg/MdeLibs.dsc.inc

@@ -144,6 +145,11 @@ [PcdsFixedAtBuild.common]
#
gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16

+ #
+ # ACPI Table Version
+ #
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiExposedTableVersions|0x20
+
[PcdsPatchableInModule.common]
#
# This will be overridden in the code
@@ -198,8 +204,8 @@ [PcdsDynamicDefault.common]
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|640
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|480

- ## Force DTB
- gArmVirtTokenSpaceGuid.PcdForceNoAcpi|TRUE
+ ## Set default option to ACPI
+ gArmVirtTokenSpaceGuid.PcdForceNoAcpi|FALSE

# Setup Flash storage variables
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0
@@ -356,3 +362,8 @@ [Components.common]
}
OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
OvmfPkg/Virtio10Dxe/Virtio10.inf
+ #
+ # ACPI Support
+ #
+ MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+ ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf
diff --git a/ArmVirtPkg/ArmVirtKvmTool.fdf b/ArmVirtPkg/ArmVirtKvmTool.fdf
index 076155199905..5ba4c579f050 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.fdf
+++ b/ArmVirtPkg/ArmVirtKvmTool.fdf
@@ -204,6 +204,17 @@ [FV.FvMain]
INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
INF OvmfPkg/Virtio10Dxe/Virtio10.inf

+ #
+ # ACPI Support
+ #
+ INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+ #
+ # Dynamic Table fdf
+ #
+ !include DynamicTablesPkg/DynamicTables.fdf.inc
+
+ INF ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf
+
#
# TianoCore logo (splash screen)
#
--
2.17.1


[PATCH v1 3/5] ArmVirtPkg: Add Configuration Manager for Kvmtool firmware

PierreGondois
 

From: Sami Mujawar <sami.mujawar@...>

Add Configuration Manager to enable ACPI tables for Kvmtool
firmware. The Configuration Manager for Kvmtool uses the DT
Hardware Information Parser module (FdtHwInfoParser) to parse
the DT provided by Kvmtool. The FdtHwInfoParser parses the DT
and invokes the callback function HW_INFO_ADD_OBJECT to add
the Configuration Manager objects to the Platform Information
repository.

The information for some Configuration Manager objects may not
be available in the DT. Such objects are initialised locally
by the Configuration Manager.

Support for the following ACPI tables is provided:
- DBG2
- DSDT (Empty stub)
- FADT
- GTDT
- MADT
- SPCR
- SSDT (Cpu Hierarchy)
- SSDT (Pcie bus)

Signed-off-by: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
ArmVirtPkg/ArmVirtKvmTool.dsc | 3 +
.../KvmtoolCfgMgrDxe/ConfigurationManager.c | 948 ++++++++++++++++++
.../KvmtoolCfgMgrDxe/ConfigurationManager.h | 94 ++
.../ConfigurationManagerDxe.inf | 58 ++
4 files changed, 1103 insertions(+)
create mode 100644 ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.c
create mode 100644 ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.h
create mode 100644 ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf

diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index 3bd1cc72a1eb..920880796ac2 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.dsc
+++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
@@ -71,6 +71,9 @@ [LibraryClasses.common]
PlatformHookLib|ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.inf
SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf

+ HwInfoParserLib|DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf
+ DynamicPlatRepoLib|DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf
+
[LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM]
PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
PlatformHookLib|ArmVirtPkg/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.inf
diff --git a/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.c b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.c
new file mode 100644
index 000000000000..07b8b403dd4a
--- /dev/null
+++ b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.c
@@ -0,0 +1,948 @@
+/** @file
+ Configuration Manager Dxe
+
+ 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 <IndustryStandard/DebugPort2Table.h>
+#include <IndustryStandard/IoRemappingTable.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DynamicPlatRepoLib.h>
+#include <Library/HobLib.h>
+#include <Library/HwInfoParserLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TableHelperLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include "ConfigurationManager.h"
+
+/** The platform configuration repository information.
+*/
+STATIC
+EDKII_PLATFORM_REPOSITORY_INFO KvmtoolPlatRepositoryInfo = {
+ /// Configuration Manager information
+ { CONFIGURATION_MANAGER_REVISION, CFG_MGR_OEM_ID },
+
+ // ACPI Table List
+ {
+ // FADT Table
+ {
+ EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt),
+ NULL
+ },
+ // GTDT Table
+ {
+ EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdGtdt),
+ NULL
+ },
+ // MADT Table
+ {
+ EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMadt),
+ NULL
+ },
+ // SPCR Table
+ {
+ EFI_ACPI_6_3_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
+ EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr),
+ NULL
+ },
+ // DSDT Table
+ {
+ EFI_ACPI_6_3_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ 0, // Unused
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDsdt),
+ (EFI_ACPI_DESCRIPTION_HEADER*)dsdt_aml_code
+ },
+ // SSDT Cpu Hierarchy Table
+ {
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ 0, // Unused
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtCpuTopology),
+ NULL
+ },
+ // DBG2 Table
+ {
+ EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE,
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDbg2),
+ NULL
+ },
+ // PCI MCFG Table
+ {
+ EFI_ACPI_6_3_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMcfg),
+ NULL
+ },
+ // SSDT table describing the PCI root complex
+ {
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ 0, // Unused
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtPciExpress),
+ NULL
+ },
+ // IORT Table
+ {
+ EFI_ACPI_6_3_IO_REMAPPING_TABLE_SIGNATURE,
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdIort),
+ NULL
+ },
+ },
+
+ // Power management profile information
+ { EFI_ACPI_6_3_PM_PROFILE_ENTERPRISE_SERVER }, // PowerManagement Profile
+
+ // ITS group node
+ {
+ // Reference token for this Iort node
+ REFERENCE_TOKEN (ItsGroupInfo),
+ // The number of ITS identifiers in the ITS node.
+ 1,
+ // Reference token for the ITS identifier array
+ REFERENCE_TOKEN (ItsIdentifierArray)
+ },
+ // ITS identifier array
+ {
+ {
+ // The ITS Identifier
+ 0
+ }
+ },
+
+ // Root Complex node info
+ {
+ // Reference token for this Iort node
+ REFERENCE_TOKEN (RootComplexInfo),
+ // Number of ID mappings
+ 1,
+ // Reference token for the ID mapping array
+ REFERENCE_TOKEN (DeviceIdMapping[0]),
+
+ // Memory access properties : Cache coherent attributes
+ EFI_ACPI_IORT_MEM_ACCESS_PROP_CCA,
+ // Memory access properties : Allocation hints
+ 0,
+ // Memory access properties : Memory access flags
+ 0,
+ // ATS attributes
+ EFI_ACPI_IORT_ROOT_COMPLEX_ATS_UNSUPPORTED,
+ // PCI segment number
+ 0
+ },
+
+ // Array of Device ID mappings
+ {
+ /* RootComplex -> ITS Group
+ */
+ // Device ID mapping for Root complex node
+ {
+ // Input base
+ 0x0,
+ // Number of input IDs
+ 0x0000FFFF,
+ // Output Base
+ 0x0,
+ // Output reference
+ REFERENCE_TOKEN (ItsGroupInfo),
+ // Flags
+ 0
+ },
+ },
+};
+
+/** A helper function for returning the Configuration Manager Objects.
+
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Object Pointer to the Object(s).
+ @param [in] ObjectSize Total size of the Object(s).
+ @param [in] ObjectCount Number of Objects.
+ @param [in, out] CmObjectDesc Pointer to the Configuration Manager Object
+ descriptor describing the requested Object.
+
+ @retval EFI_SUCCESS Success.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+HandleCmObject (
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN VOID * Object,
+ IN CONST UINTN ObjectSize,
+ IN CONST UINTN ObjectCount,
+ IN OUT CM_OBJ_DESCRIPTOR * CONST CmObjectDesc
+ )
+{
+ CmObjectDesc->ObjectId = CmObjectId;
+ CmObjectDesc->Size = ObjectSize;
+ CmObjectDesc->Data = (VOID*)Object;
+ CmObjectDesc->Count = ObjectCount;
+ DEBUG ((
+ DEBUG_INFO,
+ "INFO: CmObjectId = %x, Ptr = 0x%p, Size = %d, Count = %d\n",
+ CmObjectId,
+ CmObjectDesc->Data,
+ CmObjectDesc->Size,
+ CmObjectDesc->Count
+ ));
+ return EFI_SUCCESS;
+}
+
+/** A helper function for returning the Configuration Manager Objects that
+ match the token.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Object Pointer to the Object(s).
+ @param [in] ObjectSize Total size of the Object(s).
+ @param [in] ObjectCount Number of Objects.
+ @param [in] Token A token identifying the object.
+ @param [in] HandlerProc A handler function to search the object
+ referenced by the token.
+ @param [in, out] CmObjectDesc 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.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+HandleCmObjectRefByToken (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN VOID * Object,
+ IN CONST UINTN ObjectSize,
+ IN CONST UINTN ObjectCount,
+ IN CONST CM_OBJECT_TOKEN Token,
+ IN CONST CM_OBJECT_HANDLER_PROC HandlerProc,
+ IN OUT CM_OBJ_DESCRIPTOR * CONST CmObjectDesc
+ )
+{
+ EFI_STATUS Status;
+ CmObjectDesc->ObjectId = CmObjectId;
+ if (Token == CM_NULL_TOKEN) {
+ CmObjectDesc->Size = ObjectSize;
+ CmObjectDesc->Data = (VOID*)Object;
+ CmObjectDesc->Count = ObjectCount;
+ Status = EFI_SUCCESS;
+ } else {
+ Status = HandlerProc (This, CmObjectId, Token, CmObjectDesc);
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "INFO: Token = 0x%p, CmObjectId = %x, Ptr = 0x%p, Size = %d, Count = %d\n",
+ (VOID*)Token,
+ CmObjectId,
+ CmObjectDesc->Data,
+ CmObjectDesc->Size,
+ CmObjectDesc->Count
+ ));
+ return Status;
+}
+
+/** Return an ITS identifier array.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Token A token for identifying the object
+ @param [out] CmObject 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
+GetItsIdentifierArray (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token,
+ OUT CM_OBJ_DESCRIPTOR * CONST CmObject
+ )
+{
+ EDKII_PLATFORM_REPOSITORY_INFO * PlatformRepo;
+
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PlatformRepo = This->PlatRepoInfo;
+
+ if (Token != (CM_OBJECT_TOKEN)&PlatformRepo->ItsIdentifierArray) {
+ return EFI_NOT_FOUND;
+ }
+
+ CmObject->ObjectId = CmObjectId;
+ CmObject->Size = sizeof (PlatformRepo->ItsIdentifierArray);
+ CmObject->Data = (VOID*)&PlatformRepo->ItsIdentifierArray;
+ CmObject->Count = ARRAY_SIZE (PlatformRepo->ItsIdentifierArray);
+ return EFI_SUCCESS;
+}
+
+/** Return a device Id mapping array.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Token A token for identifying the object
+ @param [out] CmObject 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
+GetDeviceIdMappingArray (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token,
+ OUT CM_OBJ_DESCRIPTOR * CONST CmObject
+ )
+{
+ EDKII_PLATFORM_REPOSITORY_INFO * PlatformRepo;
+
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PlatformRepo = This->PlatRepoInfo;
+
+ if (Token != (CM_OBJECT_TOKEN)&PlatformRepo->DeviceIdMapping[0]) {
+ return EFI_NOT_FOUND;
+ }
+
+ CmObject->ObjectId = CmObjectId;
+ CmObject->Size = sizeof (CM_ARM_ID_MAPPING);
+ CmObject->Data = (VOID*)Token;
+ CmObject->Count = 1;
+ return EFI_SUCCESS;
+}
+
+/** Function pointer called by the parser to add information.
+
+ Callback function that the parser can use to add new
+ CmObj. This function must copy the CmObj data and not rely on
+ the parser preserving the CmObj memory.
+ This function is responsible of the Token allocation.
+
+ @param [in] ParserHandle A handle to the parser instance.
+ @param [in] Context A pointer to the caller's context provided in
+ HwInfoParserInit ().
+ @param [in] CmObjDesc CM_OBJ_DESCRIPTOR containing the CmObj(s) to add.
+ @param [out] Token If provided and success, contain the token
+ generated for the CmObj.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+HwInfoAdd (
+ IN HW_INFO_PARSER_HANDLE ParserHandle,
+ IN VOID * Context,
+ IN CONST CM_OBJ_DESCRIPTOR * CmObjDesc,
+ OUT CM_OBJECT_TOKEN * Token OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EDKII_PLATFORM_REPOSITORY_INFO * PlatformRepo;
+
+ if ((ParserHandle == NULL) ||
+ (Context == NULL) ||
+ (CmObjDesc == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PlatformRepo = (EDKII_PLATFORM_REPOSITORY_INFO*)Context;
+
+#ifndef MDEPKG_NDEBUG
+ // Print the received objects.
+ ParseCmObjDesc (CmObjDesc);
+#endif
+
+ Status = DynPlatRepoAddObject (
+ PlatformRepo->DynamicPlatformRepo,
+ CmObjDesc,
+ Token
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ return Status;
+}
+
+/** Cleanup the platform configuration repository.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CleanupPlatformRepository (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST This
+ )
+{
+ EFI_STATUS Status;
+ EDKII_PLATFORM_REPOSITORY_INFO * PlatformRepo;
+
+ if (This == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PlatformRepo = This->PlatRepoInfo;
+
+ // Shutdown the dynamic repo and free all objects.
+ Status = DynamicPlatRepoShutdown (PlatformRepo->DynamicPlatformRepo);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Shutdown parser.
+ Status = HwInfoParserShutdown (PlatformRepo->FdtParserHandle);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ return Status;
+}
+
+/** Initialize the platform configuration repository.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+
+ @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
+InitializePlatformRepository (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST This
+ )
+{
+ EFI_STATUS Status;
+ EDKII_PLATFORM_REPOSITORY_INFO * PlatformRepo;
+ VOID * Hob;
+
+ if (This == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Hob = GetFirstGuidHob (&gFdtHobGuid);
+ if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {
+ ASSERT (0);
+ return EFI_NOT_FOUND;
+ }
+
+ PlatformRepo = This->PlatRepoInfo;
+ PlatformRepo->FdtBase = (VOID *)*(UINTN*)GET_GUID_HOB_DATA (Hob);
+
+ // Initialise the dynamic platform repository.
+ Status = DynamicPlatRepoInit (&PlatformRepo->DynamicPlatformRepo);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Initialise the FDT parser
+ Status = HwInfoParserInit (
+ PlatformRepo->FdtBase,
+ PlatformRepo,
+ HwInfoAdd,
+ &PlatformRepo->FdtParserHandle
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ Status = HwInfoParse (PlatformRepo->FdtParserHandle);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ Status = DynamicPlatRepoFinalise (PlatformRepo->DynamicPlatformRepo);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ return EFI_SUCCESS;
+
+error_handler:
+ CleanupPlatformRepository (This);
+ return Status;
+}
+
+/** Return a standard namespace object.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @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] CmObject 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
+GetStandardNameSpaceObject (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
+ IN OUT CM_OBJ_DESCRIPTOR * CONST CmObject
+ )
+{
+ EFI_STATUS Status;
+ EDKII_PLATFORM_REPOSITORY_INFO * PlatformRepo;
+ UINTN AcpiTableCount;
+ CM_OBJ_DESCRIPTOR CmObjDesc;
+
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (This != NULL);
+ ASSERT (CmObject != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_NOT_FOUND;
+ PlatformRepo = This->PlatRepoInfo;
+
+ switch (GET_CM_OBJECT_ID (CmObjectId)) {
+ case EStdObjCfgMgrInfo:
+ Status = HandleCmObject (
+ CmObjectId,
+ &PlatformRepo->CmInfo,
+ sizeof (PlatformRepo->CmInfo),
+ 1,
+ CmObject
+ );
+ break;
+
+ case EStdObjAcpiTableList:
+ AcpiTableCount = ARRAY_SIZE (PlatformRepo->CmAcpiTableList);
+
+ // Get Pci config space information.
+ Status = DynamicPlatRepoGetObject (
+ PlatformRepo->DynamicPlatformRepo,
+ CREATE_CM_ARM_OBJECT_ID (EArmObjPciConfigSpaceInfo),
+ CM_NULL_TOKEN,
+ &CmObjDesc
+ );
+ if (Status == EFI_NOT_FOUND) {
+ // The last 3 tables are for PCIe. If PCIe information is not
+ // present, Kvmtool was launched without the PCIe option.
+ // Therefore, reduce the table count by 3.
+ AcpiTableCount -= 3;
+ } else if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Get the Gic version.
+ Status = DynamicPlatRepoGetObject (
+ PlatformRepo->DynamicPlatformRepo,
+ CREATE_CM_ARM_OBJECT_ID (EArmObjGicDInfo),
+ CM_NULL_TOKEN,
+ &CmObjDesc
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ if (((CM_ARM_GICD_INFO*)CmObjDesc.Data)->GicVersion < 3) {
+ // IORT is only required for GicV3/4
+ AcpiTableCount -= 1;
+ }
+
+ Status = HandleCmObject (
+ CmObjectId,
+ PlatformRepo->CmAcpiTableList,
+ (sizeof (PlatformRepo->CmAcpiTableList[0]) * AcpiTableCount),
+ AcpiTableCount,
+ CmObject
+ );
+ break;
+
+ default: {
+ Status = EFI_NOT_FOUND;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Object 0x%x. Status = %r\n",
+ CmObjectId,
+ Status
+ ));
+ break;
+ }
+ }
+
+ return Status;
+}
+
+/** Return an ARM namespace object.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @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] CmObject 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
+GetArmNameSpaceObject (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
+ IN OUT CM_OBJ_DESCRIPTOR * CONST CmObject
+ )
+{
+ EFI_STATUS Status;
+ EDKII_PLATFORM_REPOSITORY_INFO * PlatformRepo;
+
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (This != NULL);
+ ASSERT (CmObject != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_NOT_FOUND;
+ PlatformRepo = This->PlatRepoInfo;
+
+ // First check among the static objects.
+ switch (GET_CM_OBJECT_ID (CmObjectId)) {
+ case EArmObjPowerManagementProfileInfo:
+ Status = HandleCmObject (
+ CmObjectId,
+ &PlatformRepo->PmProfileInfo,
+ sizeof (PlatformRepo->PmProfileInfo),
+ 1,
+ CmObject
+ );
+ break;
+
+ case EArmObjItsGroup:
+ Status = HandleCmObject (
+ CmObjectId,
+ &PlatformRepo->ItsGroupInfo,
+ sizeof (PlatformRepo->ItsGroupInfo),
+ 1,
+ CmObject
+ );
+ break;
+
+ case EArmObjGicItsIdentifierArray:
+ Status = HandleCmObjectRefByToken (
+ This,
+ CmObjectId,
+ PlatformRepo->ItsIdentifierArray,
+ sizeof (PlatformRepo->ItsIdentifierArray),
+ ARRAY_SIZE (PlatformRepo->ItsIdentifierArray),
+ Token,
+ GetItsIdentifierArray,
+ CmObject
+ );
+ break;
+
+ case EArmObjRootComplex:
+ Status = HandleCmObject (
+ CmObjectId,
+ &PlatformRepo->RootComplexInfo,
+ sizeof (PlatformRepo->RootComplexInfo),
+ 1,
+ CmObject
+ );
+ break;
+
+ case EArmObjIdMappingArray:
+ Status = HandleCmObjectRefByToken (
+ This,
+ CmObjectId,
+ PlatformRepo->DeviceIdMapping,
+ sizeof (PlatformRepo->DeviceIdMapping),
+ ARRAY_SIZE (PlatformRepo->DeviceIdMapping),
+ Token,
+ GetDeviceIdMappingArray,
+ CmObject
+ );
+ break;
+
+ default:
+ // No match found among the static objects.
+ // Check the dynamic objects.
+ Status = DynamicPlatRepoGetObject (
+ PlatformRepo->DynamicPlatformRepo,
+ CmObjectId,
+ Token,
+ CmObject
+ );
+ break;
+ } // switch
+
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((
+ DEBUG_INFO,
+ "INFO: Object 0x%x. Status = %r\n",
+ CmObjectId,
+ Status
+ ));
+ } else {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/** Return an OEM namespace object.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @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] CmObject 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
+GetOemNameSpaceObject (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
+ IN OUT CM_OBJ_DESCRIPTOR * CONST CmObject
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (This != NULL);
+ ASSERT (CmObject != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (GET_CM_OBJECT_ID (CmObjectId)) {
+ default: {
+ Status = EFI_NOT_FOUND;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Object 0x%x. Status = %r\n",
+ CmObjectId,
+ Status
+ ));
+ break;
+ }
+ }
+
+ return Status;
+}
+
+/** The GetObject function defines the interface implemented by the
+ Configuration Manager Protocol for returning the Configuration
+ Manager Objects.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @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] CmObject 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
+ArmKvmtoolPlatformGetObject (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
+ IN OUT CM_OBJ_DESCRIPTOR * CONST CmObject
+ )
+{
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (This != NULL);
+ ASSERT (CmObject != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (GET_CM_NAMESPACE_ID (CmObjectId)) {
+ case EObjNameSpaceStandard:
+ Status = GetStandardNameSpaceObject (This, CmObjectId, Token, CmObject);
+ break;
+ case EObjNameSpaceArm:
+ Status = GetArmNameSpaceObject (This, CmObjectId, Token, CmObject);
+ break;
+ case EObjNameSpaceOem:
+ Status = GetOemNameSpaceObject (This, CmObjectId, Token, CmObject);
+ break;
+ default: {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Unknown Namespace Object = 0x%x. Status = %r\n",
+ CmObjectId,
+ Status
+ ));
+ break;
+ }
+ }
+
+ return Status;
+}
+
+/** The SetObject function defines the interface implemented by the
+ Configuration Manager Protocol for updating the Configuration
+ Manager Objects.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @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] CmObject Pointer to the Configuration Manager Object
+ descriptor describing the Object.
+
+ @retval EFI_UNSUPPORTED This operation is not supported.
+**/
+EFI_STATUS
+EFIAPI
+ArmKvmtoolPlatformSetObject (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
+ IN CM_OBJ_DESCRIPTOR * CONST CmObject
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/** A structure describing the configuration manager protocol interface.
+*/
+STATIC
+CONST
+EDKII_CONFIGURATION_MANAGER_PROTOCOL KvmtoolPlatformConfigManagerProtocol = {
+ CREATE_REVISION(1,0),
+ ArmKvmtoolPlatformGetObject,
+ ArmKvmtoolPlatformSetObject,
+ &KvmtoolPlatRepositoryInfo
+};
+
+/**
+ Entrypoint of Configuration Manager Dxe.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @return EFI_SUCCESS
+ @return EFI_LOAD_ERROR
+ @return EFI_OUT_OF_RESOURCES
+**/
+EFI_STATUS
+EFIAPI
+ConfigurationManagerDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE * SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ if (PcdGetBool (PcdForceNoAcpi)) {
+ // Use DT and not ACPI.
+ return EFI_SUCCESS;
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gEdkiiConfigurationManagerProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID*)&KvmtoolPlatformConfigManagerProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Failed to get Install Configuration Manager Protocol." \
+ " Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ Status = InitializePlatformRepository (
+ &KvmtoolPlatformConfigManagerProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Failed to initialize the Platform Configuration Repository." \
+ " Status = %r\n",
+ Status
+ ));
+ }
+
+error_handler:
+ return Status;
+}
+
+/**
+ Unload function for this image.
+
+ @param ImageHandle Handle for the image of this driver.
+
+ @retval EFI_SUCCESS Driver unloaded successfully.
+ @return other Driver can not unloaded.
+**/
+EFI_STATUS
+EFIAPI
+ConfigurationManagerDxeUnloadImage (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ return CleanupPlatformRepository (&KvmtoolPlatformConfigManagerProtocol);
+}
diff --git a/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.h b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.h
new file mode 100644
index 000000000000..94cfca3b7671
--- /dev/null
+++ b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.h
@@ -0,0 +1,94 @@
+/** @file
+
+ 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 CONFIGURATION_MANAGER_H_
+#define CONFIGURATION_MANAGER_H_
+
+/** C array containing the compiled AML template.
+ This symbol is defined in the auto generated C file
+ containing the AML bytecode array.
+*/
+extern CHAR8 dsdt_aml_code[];
+
+/** The configuration manager version.
+*/
+#define CONFIGURATION_MANAGER_REVISION CREATE_REVISION (1, 0)
+
+/** The OEM ID
+*/
+#define CFG_MGR_OEM_ID { 'A', 'R', 'M', 'L', 'T', 'D' }
+
+/** A function that prepares Configuration Manager Objects for returning.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Token A token for identifying the object.
+ @param [out] CmObject 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.
+**/
+typedef EFI_STATUS (*CM_OBJECT_HANDLER_PROC) (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token,
+ IN OUT CM_OBJ_DESCRIPTOR * CONST CmObject
+ );
+
+/** A helper macro for mapping a reference token.
+*/
+#define REFERENCE_TOKEN(Field) \
+ (CM_OBJECT_TOKEN)((UINT8*)&KvmtoolPlatRepositoryInfo + \
+ OFFSET_OF (EDKII_PLATFORM_REPOSITORY_INFO, Field))
+
+/** The number of ACPI tables to install
+*/
+#define PLAT_ACPI_TABLE_COUNT 10
+
+/** A structure describing the platform configuration
+ manager repository information
+*/
+typedef struct PlatformRepositoryInfo {
+ /// Configuration Manager Information.
+ CM_STD_OBJ_CONFIGURATION_MANAGER_INFO CmInfo;
+
+ /// List of ACPI tables
+ CM_STD_OBJ_ACPI_TABLE_INFO CmAcpiTableList[PLAT_ACPI_TABLE_COUNT];
+
+ /// Power management profile information
+ CM_ARM_POWER_MANAGEMENT_PROFILE_INFO PmProfileInfo;
+
+ /// ITS Group node
+ CM_ARM_ITS_GROUP_NODE ItsGroupInfo;
+
+ /// ITS Identifier array
+ CM_ARM_ITS_IDENTIFIER ItsIdentifierArray[1];
+
+ /// PCI Root complex node
+ CM_ARM_ROOT_COMPLEX_NODE RootComplexInfo;
+
+ /// Array of DeviceID mapping
+ CM_ARM_ID_MAPPING DeviceIdMapping[1];
+
+ /// Dynamic platform repository.
+ /// CmObj created by parsing the Kvmtool device tree are stored here.
+ DYNAMIC_PLATFORM_REPOSITORY_INFO * DynamicPlatformRepo;
+
+ /// Base address of the FDT.
+ VOID * FdtBase;
+
+ /// A handle to the FDT HwInfoParser.
+ HW_INFO_PARSER_HANDLE FdtParserHandle;
+} EDKII_PLATFORM_REPOSITORY_INFO;
+
+#endif // CONFIGURATION_MANAGER_H_
diff --git a/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf
new file mode 100644
index 000000000000..9f0bf72fce2d
--- /dev/null
+++ b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf
@@ -0,0 +1,58 @@
+## @file
+# Configuration Manager Dxe
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = ConfigurationManagerDxe
+ FILE_GUID = 3C80D366-510C-4154-BB3A-E12439AD337C
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = ConfigurationManagerDxeInitialize
+ UNLOAD_IMAGE = ConfigurationManagerDxeUnloadImage
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = ARM AARCH64
+#
+
+[Sources]
+ AslTables/Dsdt.asl
+ ConfigurationManager.c
+ ConfigurationManager.h
+ ConfigurationManagerDxe.inf
+
+[Packages]
+ ArmVirtPkg/ArmVirtPkg.dec
+ DynamicTablesPkg/DynamicTablesPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DynamicPlatRepoLib
+ HobLib
+ HwInfoParserLib
+ PrintLib
+ TableHelperLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEdkiiConfigurationManagerProtocolGuid
+
+[Guids]
+ gFdtHobGuid
+
+[FixedPcd]
+
+[Pcd]
+ gArmVirtTokenSpaceGuid.PcdForceNoAcpi
+
+[Depex]
+ TRUE
--
2.17.1


[PATCH v1 2/5] ArmVirtPkg: Add DSDT ACPI table for Kvmtool firmware

PierreGondois
 

From: Sami Mujawar <sami.mujawar@...>

Most ACPI tables for Kvmtool firmware are dynamically
generated. The AML code is also generated at runtime
for most components in appropriate SSDTs.

Although there may not be much to describe in the DSDT,
the DSDT table is mandatory.

Therefore, add an empty stub for DSDT.

Signed-off-by: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../KvmtoolCfgMgrDxe/AslTables/Dsdt.asl | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 ArmVirtPkg/KvmtoolCfgMgrDxe/AslTables/Dsdt.asl

diff --git a/ArmVirtPkg/KvmtoolCfgMgrDxe/AslTables/Dsdt.asl b/ArmVirtPkg/KvmtoolCfgMgrDxe/AslTables/Dsdt.asl
new file mode 100644
index 000000000000..8467d1ede4ec
--- /dev/null
+++ b/ArmVirtPkg/KvmtoolCfgMgrDxe/AslTables/Dsdt.asl
@@ -0,0 +1,19 @@
+/** @file
+ Differentiated System Description Table Fields (DSDT)
+
+ Copyright (c) 2021, ARM Ltd. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+DefinitionBlock ("DsdtTable.aml", "DSDT", 1, "ARMLTD", "ARM-KVMT", 1) {
+ Scope (_SB) {
+ // Most ACPI tables for Kvmtool firmware are
+ // dynamically generated. The AML code is also
+ // generated at runtime for most components in
+ // appropriate SSDTs.
+ // Although there may not be much to describe
+ // in the DSDT, the DSDT table is mandatory.
+ // Therefore, add an empty stub for DSDT.
+ } // Scope (_SB)
+}
--
2.17.1


[PATCH v1 1/5] ArmVirtPkg: Add cspell exceptions

PierreGondois
 

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

The cpsell tool checks for unknown words in the upstream CI.
Add some new words to the list of exceptions.

Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
ArmVirtPkg/ArmVirtPkg.ci.yaml | 3 +++
1 file changed, 3 insertions(+)

diff --git a/ArmVirtPkg/ArmVirtPkg.ci.yaml b/ArmVirtPkg/ArmVirtPkg.ci.yaml
index 5f427e57233e..e3f30d69e89a 100644
--- a/ArmVirtPkg/ArmVirtPkg.ci.yaml
+++ b/ArmVirtPkg/ArmVirtPkg.ci.yaml
@@ -47,6 +47,7 @@
"MdePkg/MdePkg.dec",
"MdeModulePkg/MdeModulePkg.dec",
"ArmVirtPkg/ArmVirtPkg.dec",
+ "DynamicTablesPkg/DynamicTablesPkg.dec",
"NetworkPkg/NetworkPkg.dec",
"ArmPkg/ArmPkg.dec",
"OvmfPkg/OvmfPkg.dec",
@@ -97,6 +98,8 @@
"AuditOnly": False, # Fails right now with over 270 errors
"IgnoreFiles": [], # use gitignore syntax to ignore errors in matching files
"ExtendWords": [
+ "armltd",
+ "ssdts",
"setjump",
"plong",
"lparam",
--
2.17.1


[PATCH v1 0/5] Add ACPI support for Kvmtool

PierreGondois
 

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

Kvmtool dynamically generates a device tree describing the platform
to boot on. Using the patch-sets listed below, the DynamicTables
framework generates ACPI tables describing a similar platform.

This patch-set:
- adds a ConfigurationManager allowing to generate ACPI tables
for Kvmtool
- adds the acpiview command line utility to the ArmVirtPkg
- update ArmVirtPkg.ci.yaml to add new words and use the
DynamicTablesPkg

This patch sets also set the default platform description format
to ACPI instead of the device tree (c.f.: PcdForceNoAcpi is set
to FALSE).

The changes can be seen at: https://github.com/PierreARM/edk2/tree/1456_Add_ACPI_support_for_Kvmtool_v1
The results of the CI can be seen at: https://github.com/tianocore/edk2/pull/1753

This patch-set is dependent over the following patch-sets:
[PATCH v1 00/10] Various DynamicTablesPkg modifications
https://edk2.groups.io/g/devel/message/76929
and:
[PATCH v1 00/13] Create a SSDT CPU topology generator
https://edk2.groups.io/g/devel/message/76941
and:
[PATCH v1 0/7] Create a SSDT PCIe generator
https://edk2.groups.io/g/devel/message/76958
and:
[PATCH v1 00/14] Implement a FdtHwInfoParserLib
https://edk2.groups.io/g/devel/message/76967
and:
[PATCH v1 0/5] Add DynamicPlatRepoLib
https://edk2.groups.io/g/devel/message/76984

Pierre Gondois (1):
ArmVirtPkg: Add cspell exceptions

Sami Mujawar (4):
ArmVirtPkg: Add DSDT ACPI table for Kvmtool firmware
ArmVirtPkg: Add Configuration Manager for Kvmtool firmware
ArmVirtPkg: Enable ACPI support for Kvmtool
ArmVirtPkg: Enable Acpiview for ArmVirtPkg

ArmVirtPkg/ArmVirt.dsc.inc | 3 +-
ArmVirtPkg/ArmVirtKvmTool.dsc | 18 +-
ArmVirtPkg/ArmVirtKvmTool.fdf | 11 +
ArmVirtPkg/ArmVirtPkg.ci.yaml | 3 +
.../KvmtoolCfgMgrDxe/AslTables/Dsdt.asl | 19 +
.../KvmtoolCfgMgrDxe/ConfigurationManager.c | 948 ++++++++++++++++++
.../KvmtoolCfgMgrDxe/ConfigurationManager.h | 94 ++
.../ConfigurationManagerDxe.inf | 58 ++
8 files changed, 1151 insertions(+), 3 deletions(-)
create mode 100644 ArmVirtPkg/KvmtoolCfgMgrDxe/AslTables/Dsdt.asl
create mode 100644 ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.c
create mode 100644 ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.h
create mode 100644 ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf

--
2.17.1


[PATCH v1 5/5] DynamicTablesPkg: Add DynamicPlatRepo library

PierreGondois
 

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

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: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
DynamicTablesPkg/DynamicTablesPkg.dsc | 1 +
.../Include/Library/DynamicPlatRepoLib.h | 4 +-
.../DynamicPlatRepoLib/DynamicPlatRepo.c | 518 ++++++++++++++++++
.../DynamicPlatRepoInternal.h | 78 +++
.../DynamicPlatRepoLib/DynamicPlatRepoLib.inf | 33 ++
5 files changed, 633 insertions(+), 1 deletion(-)
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 fd7345891cf1..432c958cf8b2 100644
--- a/DynamicTablesPkg/DynamicTablesPkg.dsc
+++ b/DynamicTablesPkg/DynamicTablesPkg.dsc
@@ -43,6 +43,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/Include/Library/DynamicPlatRepoLib.h b/DynamicTablesPkg/Include/Library/DynamicPlatRepoLib.h
index 8e4665bf5c59..4a76b30399b4 100644
--- a/DynamicTablesPkg/Include/Library/DynamicPlatRepoLib.h
+++ b/DynamicTablesPkg/Include/Library/DynamicPlatRepoLib.h
@@ -13,6 +13,8 @@
#ifndef DYNAMIC_PLAT_REPO_H_
#define DYNAMIC_PLAT_REPO_H_

+#include <Protocol/ConfigurationManagerProtocol.h>
+
/** A structure describing the platform configuration
manager repository information
*/
@@ -109,4 +111,4 @@ DynamicPlatRepoShutdown (
IN DYNAMIC_PLATFORM_REPOSITORY_INFO * DynPlatRepo
);

-#endif DYNAMIC_PLAT_REPO_H_
+#endif // DYNAMIC_PLAT_REPO_H_
diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepo.c b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepo.c
new file mode 100644
index 000000000000..f26f8ad32bc8
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepo.c
@@ -0,0 +1,518 @@
+/** @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);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+
+ 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.17.1


[PATCH v1 4/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenMapper

PierreGondois
 

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

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: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../Common/DynamicPlatRepoLib/TokenMapper.c | 214 ++++++++++++++++++
.../Common/DynamicPlatRepoLib/TokenMapper.h | 123 ++++++++++
2 files changed, 337 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..f23bc8c1c7db
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/TokenMapper.c
@@ -0,0 +1,214 @@
+/** @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)) {
+ return EFI_SUCCESS;
+ }
+
+ 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
+
+ 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);
+ 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.17.1


[PATCH v1 3/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenFixer

PierreGondois
 

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

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: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../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.17.1


[PATCH v1 2/5] DynamicTablesPkg: DynamicPlatRepo: Add TokenGenerator

PierreGondois
 

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

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: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../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.17.1


[PATCH v1 1/5] DynamicTablesPkg: Definition for DynamicPlatRepoLib interface

PierreGondois
 

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

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: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
DynamicTablesPkg/DynamicTablesPkg.dec | 3 +
.../Include/Library/DynamicPlatRepoLib.h | 112 ++++++++++++++++++
2 files changed, 115 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..8e4665bf5c59
--- /dev/null
+++ b/DynamicTablesPkg/Include/Library/DynamicPlatRepoLib.h
@@ -0,0 +1,112 @@
+/** @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_
+
+/** 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.17.1


[PATCH v1 0/5] Add DynamicPlatRepoLib

PierreGondois
 

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

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_v1
The results of the CI can be seen at: https://github.com/tianocore/edk2/pull/1752

This patch-set is dependent over the following patch-sets:
[PATCH v1 00/10] Various DynamicTablesPkg modifications
https://edk2.groups.io/g/devel/message/76929
and:
[PATCH v1 00/13] Create a SSDT CPU topology generator
https://edk2.groups.io/g/devel/message/76941
and:
[PATCH v1 0/7] Create a SSDT PCIe generator
https://edk2.groups.io/g/devel/message/76958
and:
[PATCH v1 00/14] Implement a FdtHwInfoParserLib
https://edk2.groups.io/g/devel/message/76967

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 | 518 ++++++++++++++++++
.../DynamicPlatRepoInternal.h | 78 +++
.../DynamicPlatRepoLib/DynamicPlatRepoLib.inf | 33 ++
.../DynamicPlatRepoLib/TokenGenerator.c | 28 +
.../DynamicPlatRepoLib/TokenGenerator.h | 26 +
.../Common/DynamicPlatRepoLib/TokenMapper.c | 214 ++++++++
.../Common/DynamicPlatRepoLib/TokenMapper.h | 123 +++++
12 files changed, 1354 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.17.1


Re: [PATCH v4 0/4] SEV Live Migration support for OVMF.

Dov Murik
 

+cc Tobin


On 22/06/2021 20:46, Ashish Kalra via groups.io wrote:
Hello Laszlo,

Please see my replies below :

On Tue, Jun 22, 2021 at 07:20:53PM +0200, Laszlo Ersek wrote:
-snip-



Anyway, where I'm particularly lost is that I (very vaguely) recall conflicting approaches from AMD and IBM on migration. Has an agreement been reached there?
Yes, these are the slow SEV live migration patches. The fast migration
support is being developed by IBM and that is a separate effort.

As this slow live migration support has now been included in KVM, we
will need the corresponding OVMF and QEMU support now.

I'll also add that the fast (guest-assisted) SEV migration we (IBM) are
working on uses some of the features of the "slow" migration. For
example, for sure, patches 1-3 in this series will be needed to keep the
record of which of the guest pages are encrypted and which are shared
(also in fast migration).

-Dov


Re: [PATCH v6 0/2] CryptoPkg/OpensslLib: Add native instruction support for X64

Yao, Jiewen
 

Hi Christopher
Thank you very much to resume this work. :-)

I have no problem to approve CryptoPkg. (I believe I already did that in last year).

But since you updated base tool. We need base tool package maintainer to approve that change.

A good practice is to split the patch from package level. Then we can let each package maintainer approve its own package.

I will be waiting for the response from base tool owner to review " BaseTools/Scripts/GccBase.lds " and give R-B.


Thank you
Yao Jiewen

-----Original Message-----
From: Christopher Zurcher <christopher.zurcher@...>
Sent: Tuesday, June 22, 2021 6:05 AM
To: devel@edk2.groups.io; gaoliming@...
Cc: Yao, Jiewen <jiewen.yao@...>; Wang, Jian J <jian.j.wang@...>;
Lu, XiaoyuX <xiaoyux.lu@...>; Kinney, Michael D
<michael.d.kinney@...>; 'Ard Biesheuvel' <ard.biesheuvel@...>
Subject: RE: [edk2-devel] [PATCH v6 0/2] CryptoPkg/OpensslLib: Add native
instruction support for X64

Yes this was discussed last year, sorry for the delay in follow-up, I was changing
jobs.
The problem is that the assembly code provided by OpenSSL uses
"wrt ..imagebase" which is only supported by win64, not elf64. It was requested
at the time that I include the OpenSSL-provided .S files as a GCC tool chain
alternative.

Thanks,
Christopher Zurcher

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of gaoliming
Sent: Sunday, June 20, 2021 18:34
To: devel@edk2.groups.io; christopher.zurcher@...
Cc: 'Jiewen Yao' <jiewen.yao@...>; 'Jian J Wang'
<jian.j.wang@...>; 'Xiaoyu Lu' <xiaoyux.lu@...>; 'Mike Kinney'
<michael.d.kinney@...>; 'Ard Biesheuvel' <ard.biesheuvel@...>
Subject: 回复: [edk2-devel] [PATCH v6 0/2] CryptoPkg/OpensslLib: Add native
instruction support for X64

Christopher:
Nasm should support GCC tool chain. Do you meet with the problem on nasm
version assembly code?
So, you have to add GAS assembly code. This topic may be discussed last year.
Can you give some detail for it?

Thanks
Liming
-----邮件原件-----
发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Christopher
Zurcher
发送时间: 2021年6月19日 10:09
收件人: devel@edk2.groups.io
抄送: Jiewen Yao <jiewen.yao@...>; Jian J Wang
<jian.j.wang@...>; Xiaoyu Lu <xiaoyux.lu@...>; Mike Kinney
<michael.d.kinney@...>; Ard Biesheuvel <ard.biesheuvel@...>
主题: [edk2-devel] [PATCH v6 0/2] CryptoPkg/OpensslLib: Add native
instruction support for X64

From: Christopher Zurcher <christopher.zurcher@...>

V6 Changes:
Add GCC-compatible version of these modifications. Supporting GCC
build
of
native OpenSSL .S files requires removal of *(COMMON) from the
/DISCARD/
section of the GCC linker script.
The VS/CLANG portion of the patch is unchanged from the
previously-approved
patchset.

V5 Changes:
Move ApiHooks.c into X64 folder
Update process_files.pl to clean architecture-specific subfolders
without
removing them
Rebased INF file to merge latest changes regarding RngLib vs.
TimerLib

V4 Changes:
Add copyright header to uefi-asm.conf
Move [Sources.X64] block to cover entire X64-specific config

V3 Changes:
Added definitions for ptrdiff_t and wchar_t to CrtLibSupport.h for
LLVM/Clang build support.
Added -UWIN32 to GCC Flags for LLVM/Clang build support.
Added missing AES GCM assembly file.

V2 Changes:
Limit scope of assembly config to SHA and AES functions.
Removed IA32 native support (reduced config was causing build
failure
and
can be added in a later patch).
Removed XMM instructions from assembly generation.
Added automatic copyright header porting for generated assembly files.

This patch adds support for building the native instruction algorithms
for the X64 architecture in OpensslLib. The process_files.pl script
was
modified
to parse the .asm file targets from the OpenSSL build config data
struct,
and
generate the necessary assembly files for the EDK2 build environment.

For the X64 variant, OpenSSL includes calls to a Windows error
handling
API,
and that function has been stubbed out in ApiHooks.c.

For all variants, a constructor is added to call the required CPUID
function
within OpenSSL to facilitate processor capability checks in the native
algorithms.

Additional native architecture variants should be simple to add by
following
the changes made for this architecture.

The OpenSSL assembly files are traditionally generated at build time
using
a
perl script. To avoid that burden on EDK2 users, these end-result
assembly files are generated during the configuration steps performed
by the
package
maintainer (through process_files.pl). The perl generator scripts
inside OpenSSL do not parse file comments as they are only meant to
create intermediate build files, so process_files.pl contains
additional hooks to preserve the copyright headers as well as clean up
tabs and line endings
to
comply with EDK2 coding standards. The resulting file headers align
with the generated .h files which are already included in the EDK2 repository.

Cc: Jiewen Yao <jiewen.yao@...>
Cc: Jian J Wang <jian.j.wang@...>
Cc: Xiaoyu Lu <xiaoyux.lu@...>
Cc: Mike Kinney <michael.d.kinney@...>
Cc: Ard Biesheuvel <ard.biesheuvel@...>

Christopher Zurcher (2):
CryptoPkg/OpensslLib: Add native instruction support for X64
CryptoPkg/OpensslLib: Commit the auto-generated assembly files for
X64

BaseTools/Scripts/GccBase.lds
| 1 -
CryptoPkg/CryptoPkg.ci.yaml
| 21 +-
CryptoPkg/Library/Include/CrtLibSupport.h
| 2 +
CryptoPkg/Library/Include/openssl/opensslconf.h
| 3 -
CryptoPkg/Library/OpensslLib/OpensslLib.inf
| 2 +-
CryptoPkg/Library/OpensslLib/OpensslLibConstructor.c
| 44 +
CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
| 2 +-
CryptoPkg/Library/OpensslLib/OpensslLibX64.inf
| 653 +++
CryptoPkg/Library/OpensslLib/OpensslLibX64Gcc.inf
| 653 +++
CryptoPkg/Library/OpensslLib/UefiAsm.conf
| 30 +
CryptoPkg/Library/OpensslLib/X64/ApiHooks.c
| 22 +
CryptoPkg/Library/OpensslLib/X64/crypto/aes/aesni-mb-x86_64.nasm
| 732 +++
CryptoPkg/Library/OpensslLib/X64/crypto/aes/aesni-sha1-x86_64.nasm
| 1916 ++++++++
CryptoPkg/Library/OpensslLib/X64/crypto/aes/aesni-sha256-x86_64.nasm
| 78 +
CryptoPkg/Library/OpensslLib/X64/crypto/aes/aesni-x86_64.nasm
| 5103 ++++++++++++++++++++
CryptoPkg/Library/OpensslLib/X64/crypto/aes/vpaes-x86_64.nasm
| 1173 +++++
CryptoPkg/Library/OpensslLib/X64/crypto/modes/aesni-gcm-x86_64.nasm
| 34 +
CryptoPkg/Library/OpensslLib/X64/crypto/modes/ghash-x86_64.nasm
| 1569 ++++++
CryptoPkg/Library/OpensslLib/X64/crypto/sha/sha1-mb-x86_64.nasm
| 3137 ++++++++++++
CryptoPkg/Library/OpensslLib/X64/crypto/sha/sha1-x86_64.nasm
| 2884 +++++++++++
CryptoPkg/Library/OpensslLib/X64/crypto/sha/sha256-mb-x86_64.nasm
| 3461 +++++++++++++
CryptoPkg/Library/OpensslLib/X64/crypto/sha/sha256-x86_64.nasm
| 3313 +++++++++++++
CryptoPkg/Library/OpensslLib/X64/crypto/sha/sha512-x86_64.nasm
| 1938 ++++++++
CryptoPkg/Library/OpensslLib/X64/crypto/x86_64cpuid.nasm
| 491 ++
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/aes/aesni-mb-x86_64.S
| 552 +++
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/aes/aesni-sha1-x86_64.S
| 1719 +++++++
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/aes/aesni-sha256-x86_64.S
|
69 +
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/aes/aesni-x86_64.S
| 4484 +++++++++++++++++
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/aes/vpaes-x86_64.S
| 863 ++++
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/modes/aesni-gcm-x86_64.S
| 29 +
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/modes/ghash-x86_64.S
| 1386 ++++++
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/sha/sha1-mb-x86_64.S
| 2962 ++++++++++++
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/sha/sha1-x86_64.S
| 2631 ++++++++++
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/sha/sha256-mb-x86_64.S
| 3286 +++++++++++++
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/sha/sha256-x86_64.S
| 3097 ++++++++++++
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/sha/sha512-x86_64.S
| 1811 +++++++
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/x86_64cpuid.S
| 491 ++
CryptoPkg/Library/OpensslLib/process_files.pl
| 241 +-
38 files changed, 50828 insertions(+), 55 deletions(-) create mode
100644 CryptoPkg/Library/OpensslLib/OpensslLibConstructor.c
create mode 100644 CryptoPkg/Library/OpensslLib/OpensslLibX64.inf
create mode 100644 CryptoPkg/Library/OpensslLib/OpensslLibX64Gcc.inf
create mode 100644 CryptoPkg/Library/OpensslLib/UefiAsm.conf
create mode 100644 CryptoPkg/Library/OpensslLib/X64/ApiHooks.c
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/aes/aesni-mb-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/aes/aesni-sha1-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/aes/aesni-sha256-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/aes/aesni-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/aes/vpaes-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/modes/aesni-gcm-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/modes/ghash-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/sha/sha1-mb-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/sha/sha1-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/sha/sha256-mb-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/sha/sha256-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/sha/sha512-x86_64.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64/crypto/x86_64cpuid.nasm
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/aes/aesni-mb-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/aes/aesni-sha1-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/aes/aesni-sha256-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/aes/aesni-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/aes/vpaes-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/modes/aesni-gcm-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/modes/ghash-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/sha/sha1-mb-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/sha/sha1-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/sha/sha256-mb-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/sha/sha256-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/sha/sha512-x86_64.S
create mode 100644
CryptoPkg/Library/OpensslLib/X64Gcc/crypto/x86_64cpuid.S

--
2.32.0.windows.1










[PATCH v1 14/14] DynamicTablesPkg: Add FdtHwInfoParser library

PierreGondois
 

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

Hardware information parser is an optional module defined
by the Dynamic Tables Framework. It can either parse an
XML, a Device Tree or a Json file containing the platform
hardware information to populate the platform information
repository.

FdtHwInfoParser library is an instance of a HwInfoParser
that parses a Device Tree and populates the Configuration
Manager Platform information repository.

FdtHwInfoParser library is aimed at providing a solution
for generating ACPI tables for Guest Partitions launched
by virtual machine managers (VMMs). One such use case is
Kvmtool where the Device Tree for the Guest is passed on
to the firmware by Kvmtool. The Configuration Manager for
Kvmtool firmware shall invoke the FdtHwInfoParser to parse
the Device Tree to populate the hardware information in
the Platform Info Repository. The Kvmtool Configuration
Manager can the process this information to generate the
required ACPI tables for the Guest VM.

This approach also scales well if the number of CPUs or
if the hardware configuration of the Guest partition is
varied.

FdtHwInfoParser thereby introduces 'Dynamic Tables for
Virtual Machines'.

Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
Signed-off-by: Sami Mujawar <sami.mujawar@...>
---
DynamicTablesPkg/DynamicTablesPkg.dsc | 3 +-
.../FdtHwInfoParserLib/FdtHwInfoParser.c | 193 ++++++++++++++++++
.../FdtHwInfoParserLib/FdtHwInfoParser.h | 63 ++++++
.../FdtHwInfoParserInclude.h | 17 ++
.../FdtHwInfoParserLib/FdtHwInfoParserLib.inf | 56 +++++
5 files changed, 331 insertions(+), 1 deletion(-)
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParser.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserInclude.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf

diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc b/DynamicTablesPkg/DynamicTablesPkg.dsc
index 46b2e667fd25..fd7345891cf1 100644
--- a/DynamicTablesPkg/DynamicTablesPkg.dsc
+++ b/DynamicTablesPkg/DynamicTablesPkg.dsc
@@ -2,7 +2,7 @@
# Dsc file for Dynamic Tables Framework.
#
# Copyright (c) 2019, Linaro Limited. All rights reserved.<BR>
-# Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+# Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -42,6 +42,7 @@ [Components.common]
DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf
DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf
DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf
+ DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf

[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParser.c b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParser.c
new file mode 100644
index 000000000000..ab3ac58b994e
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParser.c
@@ -0,0 +1,193 @@
+/** @file
+ Flattened Device Tree parser library for KvmTool.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "FdtHwInfoParser.h"
+#include "BootArch/ArmBootArchParser.h"
+#include "GenericTimer/ArmGenericTimerParser.h"
+#include "Gic/ArmGicDispatcher.h"
+#include "Pci/ArmPciConfigSpaceParser.h"
+#include "Serial/ArmSerialPortParser.h"
+
+/** Ordered table of parsers/dispatchers.
+
+ A parser parses a Device Tree to populate a specific CmObj type. None,
+ one or many CmObj can be created by the parser.
+ The created CmObj are then handed to the parser's caller through the
+ HW_INFO_ADD_OBJECT interface.
+ This can also be a dispatcher. I.e. a function that not parsing a
+ Device Tree but calling other parsers.
+*/
+STATIC CONST FDT_HW_INFO_PARSER_FUNC HwInfoParserTable[] = {
+ ArmBootArchInfoParser,
+ ArmGenericTimerInfoParser,
+ ArmGicDispatcher,
+ ArmPciConfigInfoParser,
+ SerialPortDispatcher
+};
+
+/** Main dispatcher: sequentially call the parsers/dispatchers
+ of the HwInfoParserTable.
+
+ A parser parses a Device Tree to populate a specific CmObj type. None,
+ one or many CmObj can be created by the parser.
+ The created CmObj are then handed to the parser's caller through the
+ HW_INFO_ADD_OBJECT interface.
+ This can also be a dispatcher. I.e. a function that not parsing a
+ Device Tree but calling other parsers.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] FdtBranch When searching for DT node name, restrict
+ the search to this Device Tree branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+MainDispatcher (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN INT32 FdtBranch
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+
+ if (fdt_check_header (FdtParserHandle->Fdt) < 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Index = 0; Index < ARRAY_SIZE (HwInfoParserTable); Index++) {
+ Status = HwInfoParserTable[Index] (
+ FdtParserHandle,
+ FdtBranch
+ );
+ if (EFI_ERROR (Status) &&
+ (Status != EFI_NOT_FOUND)) {
+ // If EFI_NOT_FOUND, the parser didn't find information in the DT.
+ // Don't trigger an error.
+ ASSERT (0);
+ return Status;
+ }
+ } // for
+
+ return EFI_SUCCESS;
+}
+
+/** Initialise the HwInfoParser.
+
+ The HwInfoParser shall use the information provided by the HwDataSource
+ to initialise the internal state of the parser or to index the data. This
+ internal state shall be linked to the ParserHandle using an implementation
+ defined mechanism.
+
+ @param [in] HwDataSource Pointer to the blob containing the hardware
+ information. It can be a pointer to a Device
+ Tree, an XML file, etc. or any other data
+ structure defined by the HwInfoParser.
+ @param [in] Context A pointer to the caller's context.
+ @param [in] HwInfoAdd Function pointer called by the parser when
+ adding information.
+ @param [out] ParserHandle A handle to the parser instance.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+HwInfoParserInit (
+ IN VOID * HwDataSource,
+ IN VOID * Context,
+ IN HW_INFO_ADD_OBJECT HwInfoAdd,
+ OUT HW_INFO_PARSER_HANDLE * ParserHandle
+ )
+{
+ FDT_HW_INFO_PARSER * FdtParserHandle;
+
+ if ((ParserHandle == NULL) ||
+ (HwInfoAdd == NULL) ||
+ (HwDataSource == NULL) ||
+ (fdt_check_header (HwDataSource) < 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FdtParserHandle = AllocateZeroPool (sizeof (FDT_HW_INFO_PARSER));
+ if (FdtParserHandle == NULL) {
+ *ParserHandle = NULL;
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // The HwDataSource is a pointer to the FDT data.
+ FdtParserHandle->Fdt = HwDataSource;
+ FdtParserHandle->Context = Context;
+ FdtParserHandle->HwInfoAdd = HwInfoAdd;
+
+ *ParserHandle = (HW_INFO_PARSER_HANDLE)FdtParserHandle;
+ return EFI_SUCCESS;
+}
+
+/** Parse the data provided by the HwDataSource.
+
+ @param [in] ParserHandle A handle to the parser instance.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+HwInfoParse (
+ IN HW_INFO_PARSER_HANDLE ParserHandle
+ )
+{
+ EFI_STATUS Status;
+
+ if (ParserHandle == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Call all the parsers from the root node (-1).
+ Status = MainDispatcher (
+ (FDT_HW_INFO_PARSER_HANDLE)ParserHandle,
+ -1
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+
+ return Status;
+}
+
+/** Cleanup any internal state and resources that were allocated
+ by the the HwInfoParser.
+
+ @param [in] ParserHandle A handle to the parser instance.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+HwInfoParserShutdown (
+ IN HW_INFO_PARSER_HANDLE ParserHandle
+)
+{
+ if (ParserHandle == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FreePool (ParserHandle);
+
+ return EFI_SUCCESS;
+}
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParser.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParser.h
new file mode 100644
index 000000000000..1c40fc5587c9
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParser.h
@@ -0,0 +1,63 @@
+/** @file
+ Flattened Device Tree parser definitions.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef FDT_HW_INFO_PARSER_H_
+#define FDT_HW_INFO_PARSER_H_
+
+#include <FdtHwInfoParserInclude.h>
+
+#include <ConfigurationManagerObject.h>
+#include <Library/HwInfoParserLib.h>
+
+#include "FdtUtility.h"
+
+/** A structure describing the instance of the FdtHwInfoParser.
+*/
+typedef struct FdtHwInfoParser {
+ /// Pointer to the HwDataSource i.e. the
+ /// Flattened Device Tree (Fdt).
+ VOID * Fdt;
+
+ /// Pointer to the caller's context.
+ VOID * Context;
+
+ /// Function pointer called by the
+ /// parser when adding information.
+ HW_INFO_ADD_OBJECT HwInfoAdd;
+} FDT_HW_INFO_PARSER;
+
+/** A pointer type for FDT_HW_INFO_PARSER.
+*/
+typedef FDT_HW_INFO_PARSER* FDT_HW_INFO_PARSER_HANDLE;
+
+/** Function pointer to a parser function.
+
+ A parser parses a Device Tree to populate a specific CmObj type. None,
+ one or many CmObj can be created by the parser.
+ The created CmObj are then handed to the parser's caller through the
+ HW_INFO_ADD_OBJECT interface.
+ This can also be a dispatcher. I.e. a function that not parsing a
+ Device Tree but calling other parsers.
+
+ @param [in] ParserHandle Handle to the parser instance.
+ @param [in] FdtBranch When searching for DT node name, restrict
+ the search to this Device Tree branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+typedef
+EFI_STATUS
+(EFIAPI * FDT_HW_INFO_PARSER_FUNC) (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE ParserHandle,
+ IN INT32 FdtBranch
+ );
+
+#endif // FDT_HW_INFO_PARSER_H_
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserInclude.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserInclude.h
new file mode 100644
index 000000000000..583f290095d9
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserInclude.h
@@ -0,0 +1,17 @@
+/** @file
+ Include file for Fdt HwInfoParser.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef FDT_HW_INFO_PARSER_INCLUDE_H_
+#define FDT_HW_INFO_PARSER_INCLUDE_H_
+
+#include <Base.h>
+#include <libfdt.h>
+#include <Library/ArmLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#endif // FDT_HW_INFO_PARSER_INCLUDE_H_
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf
new file mode 100644
index 000000000000..d2c171accaa5
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf
@@ -0,0 +1,56 @@
+## @file
+# Flattened Device Tree information parser.
+#
+# Copyright (c) 2021, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010019
+ BASE_NAME = FdtHwInfoParserLib
+ FILE_GUID = F174A422-BC86-41E2-9E9C-C6D6E437F4AD
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ LIBRARY_CLASS = HwInfoParserLib
+
+[Sources]
+ CmObjectDescUtility.c
+ CmObjectDescUtility.h
+ FdtHwInfoParserInclude.h
+ FdtHwInfoParser.c
+ FdtHwInfoParser.h
+ FdtUtility.c
+ FdtUtility.h
+ BootArch/ArmBootArchParser.c
+ BootArch/ArmBootArchParser.h
+ GenericTimer/ArmGenericTimerParser.c
+ GenericTimer/ArmGenericTimerParser.h
+ Gic/ArmGicCParser.c
+ Gic/ArmGicCParser.h
+ Gic/ArmGicDispatcher.c
+ Gic/ArmGicDispatcher.h
+ Gic/ArmGicDParser.c
+ Gic/ArmGicDParser.h
+ Gic/ArmGicItsParser.c
+ Gic/ArmGicItsParser.h
+ Gic/ArmGicMsiFrameParser.c
+ Gic/ArmGicMsiFrameParser.h
+ Gic/ArmGicRParser.c
+ Gic/ArmGicRParser.h
+ Pci/ArmPciConfigSpaceParser.c
+ Pci/ArmPciConfigSpaceParser.h
+ Serial/ArmSerialPortParser.c
+ Serial/ArmSerialPortParser.h
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ DynamicTablesPkg/DynamicTablesPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ FdtLib
+ MemoryAllocationLib
--
2.17.1


[PATCH v1 13/14] DynamicTablesPkg: FdtHwInfoParser: Add PCI config parser

PierreGondois
 

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

On platforms that implement PCIe, the PCIe configuration space
information must be described to a standards-based operating
system in the Memory mapped configuration space base address
Description (MCFG) table.

The PCIe information is described in the platform Device Tree,
the bindings for which can be found at:
- linux/Documentation/devicetree/bindings/pci/
host-generic-pci.yaml

The FdtHwInfoParser implements a PCI configuration space Parser
that parses the platform Device Tree to create
CM_ARM_PCI_CONFIG_SPACE_INFO objects which are encapsulated in a
Configuration Manager descriptor object and added to the platform
information repository.

The platform Configuration Manager can then utilise this
information when generating the MCFG table.

Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
Signed-off-by: Sami Mujawar <sami.mujawar@...>
---
.../Pci/ArmPciConfigSpaceParser.c | 799 ++++++++++++++++++
.../Pci/ArmPciConfigSpaceParser.h | 142 ++++
2 files changed, 941 insertions(+)
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Pci/ArmPciConfigSpaceParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Pci/ArmPciConfigSpaceParser.h

diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/Pci/ArmPciConfigSpaceParser.c b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Pci/ArmPciConfigSpaceParser.c
new file mode 100644
index 000000000000..2b1b0749b903
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Pci/ArmPciConfigSpaceParser.c
@@ -0,0 +1,799 @@
+/** @file
+ Arm PCI Configuration Space Parser.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - linux/Documentation/devicetree/bindings/pci/host-generic-pci.yaml
+ - PCI Firmware Specification - Revision 3.0
+ - Open Firmware Recommended Practice: Interrupt Mapping, Version 0.9
+ - Devicetree Specification Release v0.3
+ - linux kernel code
+**/
+
+#include "CmObjectDescUtility.h"
+#include <Library/DebugLib.h>
+
+#include "FdtHwInfoParser.h"
+#include "Pci/ArmPciConfigSpaceParser.h"
+#include "Gic/ArmGicDispatcher.h"
+
+/** List of "compatible" property values for host PCIe bridges nodes.
+
+ Any other "compatible" value is not supported by this module.
+*/
+STATIC CONST COMPATIBILITY_STR PciCompatibleStr[] = {
+ {"pci-host-ecam-generic"}
+};
+
+/** COMPATIBILITY_INFO structure for the PCIe.
+*/
+STATIC CONST COMPATIBILITY_INFO PciCompatibleInfo = {
+ ARRAY_SIZE (PciCompatibleStr),
+ PciCompatibleStr
+};
+
+/** Get the Segment group (also called: Domain Id) of a host-pci node.
+
+ kernel/Documentation/devicetree/bindings/pci/pci.txt:
+ "It is required to either not set this property at all or set it for all
+ host bridges in the system"
+
+ The function checks the "linux,pci-domain" property of the host-pci node.
+ Either all host-pci nodes must have this property, or none of them. If the
+ property is available, read it. Otherwise dynamically assign the Ids.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [in] HostPciNode Offset of a host-pci node.
+ @param [out] SegGroup Segment group assigned to the host-pci controller.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GetPciSegGroup (
+ IN CONST VOID * Fdt,
+ IN INT32 HostPciNode,
+ OUT INT32 * SegGroup
+ )
+{
+ CONST UINT8 * Data;
+ INT32 DataSize;
+ STATIC INT32 LocalSegGroup = 0;
+
+ if ((Fdt == NULL) ||
+ (SegGroup == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data = fdt_getprop (Fdt, HostPciNode, "linux,pci-domain", &DataSize);
+ if ((Data == NULL) || (DataSize < 0)) {
+ // Did not find property, assign the DomainIds ourselves.
+ if (LocalSegGroup < 0) {
+ // "linux,pci-domain" property was defined for another node.
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ *SegGroup = LocalSegGroup++;
+ return EFI_SUCCESS;
+ }
+
+ if ((DataSize > sizeof (UINT32)) ||
+ (LocalSegGroup > 0)) {
+ // Property on more than 1 cell or
+ // "linux,pci-domain" property was not defined for a node.
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ // If one node has the "linux,pci-domain" property, then all the host-pci
+ // nodes must have it.
+ LocalSegGroup = -1;
+
+ *SegGroup = fdt32_to_cpu (*(UINT32*)Data);
+ return EFI_SUCCESS;
+}
+
+/** Parse the bus-range controlled by this host-pci node.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [in] HostPciNode Offset of a host-pci node.
+ @param [in, out] PciInfo PCI_PARSER_TABLE structure storing
+ information about the current host-pci.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+PopulateBusRange (
+ IN CONST VOID * Fdt,
+ IN INT32 HostPciNode,
+ IN OUT PCI_PARSER_TABLE * PciInfo
+ )
+{
+ CONST UINT8 * Data;
+ INT32 DataSize;
+ UINT32 StartBus;
+ UINT32 EndBus;
+
+ if ((Fdt == NULL) ||
+ (PciInfo == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data = fdt_getprop (Fdt, HostPciNode, "bus-range", &DataSize);
+ if ((Data == NULL) || (DataSize < 0)) {
+ // No evidence this property is mandatory. Use default values.
+ StartBus = 0;
+ EndBus = 255;
+ } else if (DataSize == (2 * sizeof (UINT32))) {
+ // If available, the property is on two integers.
+ StartBus = fdt32_to_cpu (((UINT32*)Data)[0]);
+ EndBus = fdt32_to_cpu (((UINT32*)Data)[1]);
+ } else {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ PciInfo->PciConfigSpaceInfo.StartBusNumber = StartBus;
+ PciInfo->PciConfigSpaceInfo.EndBusNumber = EndBus;
+
+ return EFI_SUCCESS;
+}
+
+/** Parse the PCI address map.
+
+ The PCI address map is available in the "ranges" device-tree property.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [in] HostPciNode Offset of a host-pci node.
+ @param [in] AddressCells # of cells used to encode an address on
+ the parent bus.
+ @param [in, out] PciInfo PCI_PARSER_TABLE structure storing
+ information about the current host-pci.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES An allocation has failed.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ParseAddressMap (
+ IN CONST VOID * Fdt,
+ IN INT32 HostPciNode,
+ IN INT32 AddressCells,
+ IN OUT PCI_PARSER_TABLE * PciInfo
+ )
+{
+ CONST UINT8 * Data;
+ INT32 DataSize;
+ UINT32 Index;
+ UINT32 Offset;
+ UINT32 AddressMapSize;
+ UINT32 Count;
+ UINT32 PciAddressAttr;
+
+ CM_ARM_PCI_ADDRESS_MAP_INFO * PciAddressMapInfo;
+ UINT32 BufferSize;
+
+ // The mapping is done on AddressMapSize bytes.
+ AddressMapSize = (PCI_ADDRESS_CELLS + AddressCells + PCI_SIZE_CELLS) *
+ sizeof (UINT32);
+
+ Data = fdt_getprop (Fdt, HostPciNode, "ranges", &DataSize);
+ if ((Data == NULL) ||
+ (DataSize < 0) ||
+ ((DataSize % AddressMapSize) != 0)) {
+ // If error or not on AddressMapSize bytes.
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ Count = DataSize / AddressMapSize;
+
+ // Allocate a buffer to store each address mapping.
+ BufferSize = Count * sizeof (CM_ARM_PCI_ADDRESS_MAP_INFO);
+ PciAddressMapInfo = AllocateZeroPool (BufferSize);
+ if (PciAddressMapInfo == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ Offset = Index * AddressMapSize;
+
+ // Pci address attributes
+ PciAddressAttr = fdt32_to_cpu (*(UINT32*)&Data[Offset]);
+ PciAddressMapInfo[Index].SpaceCode = READ_PCI_SS (PciAddressAttr);
+ Offset += sizeof (UINT32);
+
+ // Pci address
+ PciAddressMapInfo[Index].PciAddress =
+ fdt64_to_cpu (*(UINT64*)&Data[Offset]);
+ Offset += (PCI_ADDRESS_CELLS - 1) * sizeof (UINT32);
+
+ // Cpu address
+ if (AddressCells == 2) {
+ PciAddressMapInfo[Index].CpuAddress =
+ fdt64_to_cpu (*(UINT64*)&Data[Offset]);
+ } else {
+ PciAddressMapInfo[Index].CpuAddress =
+ fdt32_to_cpu (*(UINT32*)&Data[Offset]);
+ }
+ Offset += AddressCells * sizeof (UINT32);
+
+ // Address size
+ PciAddressMapInfo[Index].AddressSize =
+ fdt64_to_cpu (*(UINT64*)&Data[Offset]);
+ Offset += PCI_SIZE_CELLS * sizeof (UINT32);
+ } // for
+
+ PciInfo->Mapping[PciMappingTableAddress].ObjectId =
+ CREATE_CM_ARM_OBJECT_ID (EArmObjPciAddressMapInfo);
+ PciInfo->Mapping[PciMappingTableAddress].Size =
+ sizeof (CM_ARM_PCI_ADDRESS_MAP_INFO) * Count;
+ PciInfo->Mapping[PciMappingTableAddress].Data = PciAddressMapInfo;
+ PciInfo->Mapping[PciMappingTableAddress].Count = Count;
+
+ return EFI_SUCCESS;
+}
+
+/** Parse the PCI interrupt map.
+
+ The PCI interrupt map is available in the "interrupt-map"
+ and "interrupt-map-mask" device-tree properties.
+
+ Cf Devicetree Specification Release v0.3,
+ s2.4.3 Interrupt Nexus Properties
+
+ An interrupt-map must be as:
+ interrupt-map = < [child unit address] [child interrupt specifier]
+ [interrupt-parent]
+ [parent unit address] [parent interrupt specifier] >
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [in] HostPciNode Offset of a host-pci node.
+ @param [in, out] PciInfo PCI_PARSER_TABLE structure storing
+ information about the current host-pci.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES An allocation has failed.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ParseIrqMap (
+ IN CONST VOID * Fdt,
+ IN INT32 HostPciNode,
+ IN OUT PCI_PARSER_TABLE * PciInfo
+ )
+{
+ EFI_STATUS Status;
+ CONST UINT8 * Data;
+ INT32 DataSize;
+ UINT32 Index;
+ UINT32 Offset;
+
+ INT32 IntcNode;
+ INT32 IntcAddressCells;
+ INT32 IntcCells;
+
+ INT32 PciIntCells;
+ INT32 IntcPhandle;
+
+ INT32 IrqMapSize;
+ UINT32 IrqMapCount;
+ CONST UINT8 * IrqMapMask;
+ INT32 IrqMapMaskSize;
+
+ INT32 PHandleOffset;
+ UINT32 GicVersion;
+
+ UINT32 PciAddressAttr;
+
+
+ CM_ARM_PCI_INTERRUPT_MAP_INFO * PciInterruptMapInfo;
+ UINT32 BufferSize;
+
+ Data = fdt_getprop (Fdt, HostPciNode, "interrupt-map", &DataSize);
+ if ((Data == NULL) || (DataSize < 0)) {
+ // We cannot check the # for now
+ ASSERT (0);
+ return EFI_ABORTED;
+ } else if (DataSize == 0) {
+ // No device described, so no interrupt-mapping.
+ DEBUG ((
+ DEBUG_WARN,
+ "Fdt parser: No Pci device described in the device tree.\n"
+ ));
+ return EFI_SUCCESS;
+ }
+
+ // PCI interrupts are expected to be on 1 cell. Check it.
+ Status = FdtGetInterruptCellsInfo (Fdt, HostPciNode, &PciIntCells);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ if (PciIntCells != PCI_INTERRUPTS_CELLS) {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ IrqMapMask = fdt_getprop (
+ Fdt,
+ HostPciNode,
+ "interrupt-map-mask",
+ &IrqMapMaskSize
+ );
+ if ((IrqMapMask == NULL) ||
+ (IrqMapMaskSize !=
+ (PCI_ADDRESS_CELLS + PCI_INTERRUPTS_CELLS) * sizeof (UINT32))) {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ // Get the interrupt-controller of the first irq mapping.
+ PHandleOffset = (PCI_ADDRESS_CELLS + PciIntCells) * sizeof (UINT32);
+ if (PHandleOffset > DataSize) {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+ IntcPhandle = fdt32_to_cpu (*(UINT32*)&Data[PHandleOffset]);
+ IntcNode = fdt_node_offset_by_phandle (Fdt, IntcPhandle);
+ if (IntcNode < 0) {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ // Only support Gic(s) for now.
+ Status = GetGicVersion (Fdt, IntcNode, &GicVersion);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Get the "address-cells" property of the IntcNode.
+ Status = FdtGetAddressInfo (Fdt, IntcNode, &IntcAddressCells, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Get the "interrupt-cells" property of the IntcNode.
+ Status = FdtGetInterruptCellsInfo (Fdt, IntcNode, &IntcCells);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // An irq mapping is done on IrqMapSize bytes
+ // (which includes 1 cell for the PHandle).
+ IrqMapSize = (PCI_ADDRESS_CELLS + PciIntCells + 1
+ + IntcAddressCells + IntcCells) * sizeof (UINT32);
+ if ((DataSize % IrqMapSize) != 0) {
+ // The mapping is not done on IrqMapSize bytes.
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+ IrqMapCount = DataSize / IrqMapSize;
+
+ // We assume the same interrupt-controller is used for all the mappings.
+ // Check this is correct.
+ for (Index = 0; Index < IrqMapCount; Index++) {
+ if (IntcPhandle != fdt32_to_cpu (
+ *(UINT32*)&Data[(Index * IrqMapSize) + PHandleOffset])) {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+ }
+
+ // Allocate a buffer to store each interrupt mapping.
+ IrqMapCount = DataSize / IrqMapSize;
+ BufferSize = IrqMapCount * sizeof (CM_ARM_PCI_ADDRESS_MAP_INFO);
+ PciInterruptMapInfo = AllocateZeroPool (BufferSize);
+ if (PciInterruptMapInfo == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < IrqMapCount; Index++) {
+ Offset = Index * IrqMapSize;
+
+ // Pci address attributes
+ PciAddressAttr = fdt32_to_cpu (
+ (*(UINT32*)&Data[Offset]) &
+ (*(UINT32*)&IrqMapMask[0])
+ );
+ PciInterruptMapInfo[Index].PciBus = READ_PCI_BBBBBBBB (PciAddressAttr);
+ PciInterruptMapInfo[Index].PciDevice = READ_PCI_DDDDD (PciAddressAttr);
+ Offset += PCI_ADDRESS_CELLS * sizeof (UINT32);
+
+ // Pci irq
+ PciInterruptMapInfo[Index].PciInterrupt = fdt32_to_cpu (
+ (*(UINT32*)&Data[Offset]) &
+ (*(UINT32*)&IrqMapMask[3 * sizeof (UINT32)])
+ );
+ // -1 to translate from device-tree (INTA=1) to ACPI (INTA=0) irq IDs.
+ PciInterruptMapInfo[Index].PciInterrupt -= 1;
+ Offset += PCI_INTERRUPTS_CELLS * sizeof (UINT32);
+
+ // PHandle (skip it)
+ Offset += sizeof (UINT32);
+
+ // "Parent unit address" (skip it)
+ Offset += IntcAddressCells * sizeof (UINT32);
+
+ // Interrupt controller interrupt and flags
+ PciInterruptMapInfo[Index].IntcInterrupt.Interrupt =
+ FdtGetInterruptId ((UINT32*)&Data[Offset]);
+ PciInterruptMapInfo[Index].IntcInterrupt.Flags =
+ FdtGetInterruptFlags ((UINT32*)&Data[Offset]);
+ } // for
+
+ PciInfo->Mapping[PciMappingTableInterrupt].ObjectId =
+ CREATE_CM_ARM_OBJECT_ID (EArmObjPciInterruptMapInfo);
+ PciInfo->Mapping[PciMappingTableInterrupt].Size =
+ sizeof (CM_ARM_PCI_INTERRUPT_MAP_INFO) * IrqMapCount;
+ PciInfo->Mapping[PciMappingTableInterrupt].Data = PciInterruptMapInfo;
+ PciInfo->Mapping[PciMappingTableInterrupt].Count = IrqMapCount;
+
+ return Status;
+}
+
+/** Parse a Host-pci node.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [in] HostPciNode Offset of a host-pci node.
+ @param [in, out] PciInfo The CM_ARM_PCI_CONFIG_SPACE_INFO to populate.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES An allocation has failed.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+PciNodeParser (
+ IN CONST VOID * Fdt,
+ IN INT32 HostPciNode,
+ IN OUT PCI_PARSER_TABLE * PciInfo
+ )
+{
+ EFI_STATUS Status;
+ INT32 AddressCells;
+ INT32 SizeCells;
+ CONST UINT8 * Data;
+ INT32 DataSize;
+ INT32 SegGroup;
+
+ if ((Fdt == NULL) ||
+ (PciInfo == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Segment Group / DomainId
+ Status = GetPciSegGroup (Fdt, HostPciNode, &SegGroup);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ PciInfo->PciConfigSpaceInfo.PciSegmentGroupNumber = SegGroup;
+
+ // Bus range
+ Status = PopulateBusRange (Fdt, HostPciNode, PciInfo);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = FdtGetParentAddressInfo (
+ Fdt,
+ HostPciNode,
+ &AddressCells,
+ &SizeCells
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Only support 32/64 bits addresses.
+ if ((AddressCells < 1) ||
+ (AddressCells > 2) ||
+ (SizeCells < 1) ||
+ (SizeCells > 2)) {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ Data = fdt_getprop (Fdt, HostPciNode, "reg", &DataSize);
+ if ((Data == NULL) ||
+ (DataSize != ((AddressCells + SizeCells) * sizeof (UINT32)))) {
+ // If error or wrong size.
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ // Base address
+ if (AddressCells == 2) {
+ PciInfo->PciConfigSpaceInfo.BaseAddress = fdt64_to_cpu (*(UINT64*)Data);
+ } else {
+ PciInfo->PciConfigSpaceInfo.BaseAddress = fdt32_to_cpu (*(UINT32*)Data);
+ }
+
+ // Address map
+ Status = ParseAddressMap (
+ Fdt,
+ HostPciNode,
+ AddressCells,
+ PciInfo
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Irq map
+ Status = ParseIrqMap (
+ Fdt,
+ HostPciNode,
+ PciInfo
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+
+ return Status;
+}
+
+/** Add the parsed Pci information to the Configuration Manager.
+
+ CmObj of the following types are concerned:
+ - EArmObjPciConfigSpaceInfo
+ - EArmObjPciAddressMapInfo
+ - EArmObjPciInterruptMapInfo
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] PciTableInfo PCI_PARSER_TABLE structure containing the
+ CmObjs to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES An allocation has failed.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+PciInfoAdd (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN PCI_PARSER_TABLE *PciTableInfo
+ )
+{
+ EFI_STATUS Status;
+ CM_ARM_PCI_CONFIG_SPACE_INFO *PciConfigSpaceInfo;
+
+ if ((FdtParserHandle == NULL) ||
+ (PciTableInfo == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PciConfigSpaceInfo = &PciTableInfo->PciConfigSpaceInfo;
+
+ // Add the address map space CmObj to the Configuration Manager.
+ Status = AddMultipleCmObjWithCmObjRef (
+ FdtParserHandle,
+ &PciTableInfo->Mapping[PciMappingTableAddress],
+ &PciConfigSpaceInfo->AddressMapToken
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Add the interrupt map space CmObj to the Configuration Manager.
+ // Possible to have no device described, and thus no interrupt-mapping.
+ if (PciTableInfo->Mapping[PciMappingTableInterrupt].Count != 0) {
+ Status = AddMultipleCmObjWithCmObjRef (
+ FdtParserHandle,
+ &PciTableInfo->Mapping[PciMappingTableInterrupt],
+ &PciConfigSpaceInfo->InterruptMapToken
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ // Add the configuration space CmObj to the Configuration Manager.
+ Status = AddSingleCmObj (
+ FdtParserHandle,
+ CREATE_CM_ARM_OBJECT_ID (EArmObjPciConfigSpaceInfo),
+ &PciTableInfo->PciConfigSpaceInfo,
+ sizeof (CM_ARM_PCI_CONFIG_SPACE_INFO),
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ return Status;
+}
+
+/** Free the CmObjDesc of the ParserTable.
+
+ @param [in] PciTableInfo PCI_PARSER_TABLE structure containing the
+ CmObjs to free.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FreeParserTable (
+ IN PCI_PARSER_TABLE *PciTableInfo
+ )
+{
+ UINT32 Index;
+ VOID *Data;
+
+ if (PciTableInfo == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Index = 0; Index < PciMappingTableMax; Index++) {
+ Data = PciTableInfo->Mapping[Index].Data;
+ if (Data != NULL) {
+ FreePool (Data);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** CM_ARM_PCI_CONFIG_SPACE_INFO parser function.
+
+ The following structure is populated:
+ typedef struct CmArmPciConfigSpaceInfo {
+ UINT64 BaseAddress; // {Populated}
+ UINT16 PciSegmentGroupNumber; // {Populated}
+ UINT8 StartBusNumber; // {Populated}
+ UINT8 EndBusNumber; // {Populated}
+ } CM_ARM_PCI_CONFIG_SPACE_INFO;
+
+ typedef struct CmArmPciAddressMapInfo {
+ UINT8 SpaceCode; // {Populated}
+ UINT64 PciAddress; // {Populated}
+ UINT64 CpuAddress; // {Populated}
+ UINT64 AddressSize; // {Populated}
+ } CM_ARM_PCI_ADDRESS_MAP_INFO;
+
+ typedef struct CmArmPciInterruptMapInfo {
+ UINT8 PciBus; // {Populated}
+ UINT8 PciDevice; // {Populated}
+ UINT8 PciInterrupt; // {Populated}
+ CM_ARM_GENERIC_INTERRUPT IntcInterrupt; // {Populated}
+ } CM_ARM_PCI_INTERRUPT_MAP_INFO;
+
+ A parser parses a Device Tree to populate a specific CmObj type. None,
+ one or many CmObj can be created by the parser.
+ The created CmObj are then handed to the parser's caller through the
+ HW_INFO_ADD_OBJECT interface.
+ This can also be a dispatcher. I.e. a function that not parsing a
+ Device Tree but calling other parsers.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] FdtBranch When searching for DT node name, restrict
+ the search to this Device Tree branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+ArmPciConfigInfoParser (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN INT32 FdtBranch
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ INT32 PciNode;
+ UINT32 PciNodeCount;
+ PCI_PARSER_TABLE PciTableInfo;
+ VOID *Fdt;
+
+ if (FdtParserHandle == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Fdt = FdtParserHandle->Fdt;
+
+ // Only search host-pci devices.
+ // PCI Firmware Specification Revision 3.0, s4.1.2. "MCFG Table Description":
+ // "This table directly refers to PCI Segment Groups defined in the system
+ // via the _SEG object in the ACPI name space for the applicable host bridge
+ // device."
+ Status = FdtCountCompatNodeInBranch (
+ Fdt,
+ FdtBranch,
+ &PciCompatibleInfo,
+ &PciNodeCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ if (PciNodeCount == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ // Parse each host-pci node in the branch.
+ PciNode = FdtBranch;
+ for (Index = 0; Index < PciNodeCount; Index++) {
+ ZeroMem (&PciTableInfo, sizeof (PCI_PARSER_TABLE));
+
+ Status = FdtGetNextCompatNodeInBranch (
+ Fdt,
+ FdtBranch,
+ &PciCompatibleInfo,
+ &PciNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ if (Status == EFI_NOT_FOUND) {
+ // Should have found the node.
+ Status = EFI_ABORTED;
+ }
+ return Status;
+ }
+
+ Status = PciNodeParser (Fdt, PciNode, &PciTableInfo);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ // Add Pci information to the Configuration Manager.
+ Status = PciInfoAdd (FdtParserHandle, &PciTableInfo);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ Status = FreeParserTable (&PciTableInfo);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ } // for
+
+ return Status;
+
+error_handler:
+ FreeParserTable (&PciTableInfo);
+ return Status;
+}
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/Pci/ArmPciConfigSpaceParser.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Pci/ArmPciConfigSpaceParser.h
new file mode 100644
index 000000000000..b260c53a82ab
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Pci/ArmPciConfigSpaceParser.h
@@ -0,0 +1,142 @@
+/** @file
+ Arm PCI Configuration Space Parser.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - linux/Documentation/devicetree/bindings/pci/host-generic-pci.yaml
+ - PCI Firmware Specification - Revision 3.0
+ - Open Firmware Recommended Practice: Interrupt Mapping, Version 0.9
+ - Devicetree Specification Release v0.3
+ - linux kernel code
+**/
+
+#ifndef ARM_PCI_CONFIG_SPACE_PARSER_H_
+#define ARM_PCI_CONFIG_SPACE_PARSER_H_
+
+/** Read LEN bits at OFF offsets bits of the ADDR.
+
+ @param [in] ADDR Address to read the bits from.
+ @param [in] OFF Offset of the bits to read.
+ @param [in] LEN Number of bits to read.
+
+ @return The bits read.
+**/
+#define READ_BITS(ADDR, OFF, LEN) (((ADDR) >> (OFF)) & ((1<<(LEN))-1))
+
+/* Pci address attributes.
+*/
+/// 0 if relocatable.
+#define READ_PCI_N(ADDR) READ_BITS((ADDR), 31, 1)
+/// 1 if prefetchable.
+#define READ_PCI_P(ADDR) READ_BITS((ADDR), 30, 1)
+/// 1 if aliased.
+#define READ_PCI_T(ADDR) READ_BITS((ADDR), 29, 1)
+/** Space code.
+
+ 00: Configuration Space
+ 01: I/O Space
+ 10: 32-bit-address Memory Space
+ 11: 64-bit-address Memory Space
+*/
+#define READ_PCI_SS(ADDR) READ_BITS((ADDR), 24, 2)
+/// Bus number.
+#define READ_PCI_BBBBBBBB(ADDR) READ_BITS((ADDR), 16, 8)
+/// Device number.
+#define READ_PCI_DDDDD(ADDR) READ_BITS((ADDR), 11, 5)
+
+/** Number of device-tree cells used for PCI nodes properties.
+
+ Values are well defined, except the "#interrupt-cells" which
+ is assumed to be 1.
+*/
+#define PCI_ADDRESS_CELLS 3U
+#define PCI_SIZE_CELLS 2U
+#define PCI_INTERRUPTS_CELLS 1U
+
+/** PCI interrupt flags for device-tree.
+
+ Local Bus Specification Revision 3.0, s2.2.6., Interrupt Pins:
+ - 'Interrupts on PCI are optional and defined as "level sensitive,"
+ asserted low (negative true)'
+*/
+#define DT_PCI_IRQ_FLAGS(x) (((x) & 0xF) == BIT0)
+
+/** Indexes in the mapping table.
+*/
+typedef enum PciMappingTable {
+ PciMappingTableAddress, ///< 0 - Address mapping
+ PciMappingTableInterrupt, ///< 1 - Interrupt mapping
+ PciMappingTableMax, ///< 2 - Max
+} PCI_MAPPING_TABLE;
+
+#pragma pack(1)
+
+/** PCI parser table
+
+ Multiple address-map and interrupt map can correspond to
+ one host-pci device. This structure allows to temporarily
+ store the CmObjects created and generate tokens once
+ the whole device tree is parsed.
+*/
+typedef struct PciParserTable {
+ /// PCI Configuration Space Info
+ CM_ARM_PCI_CONFIG_SPACE_INFO PciConfigSpaceInfo;
+
+ /// Store the address mapping and interrupt mapping as CmObjDesc
+ /// before adding them to the Configuration Manager.
+ CM_OBJ_DESCRIPTOR Mapping[PciMappingTableMax];
+} PCI_PARSER_TABLE;
+
+#pragma pack()
+
+/** CM_ARM_PCI_CONFIG_SPACE_INFO parser function.
+
+ The following structure is populated:
+ typedef struct CmArmPciConfigSpaceInfo {
+ UINT64 BaseAddress; // {Populated}
+ UINT16 PciSegmentGroupNumber; // {Populated}
+ UINT8 StartBusNumber; // {Populated}
+ UINT8 EndBusNumber; // {Populated}
+ } CM_ARM_PCI_CONFIG_SPACE_INFO;
+
+ typedef struct CmArmPciAddressMapInfo {
+ UINT8 SpaceCode; // {Populated}
+ UINT64 PciAddress; // {Populated}
+ UINT64 CpuAddress; // {Populated}
+ UINT64 AddressSize; // {Populated}
+ } CM_ARM_PCI_ADDRESS_MAP_INFO;
+
+ typedef struct CmArmPciInterruptMapInfo {
+ UINT8 PciBus; // {Populated}
+ UINT8 PciDevice; // {Populated}
+ UINT8 PciInterrupt; // {Populated}
+ CM_ARM_GENERIC_INTERRUPT IntcInterrupt; // {Populated}
+ } CM_ARM_PCI_INTERRUPT_MAP_INFO;
+
+ A parser parses a Device Tree to populate a specific CmObj type. None,
+ one or many CmObj can be created by the parser.
+ The created CmObj are then handed to the parser's caller through the
+ HW_INFO_ADD_OBJECT interface.
+ This can also be a dispatcher. I.e. a function that not parsing a
+ Device Tree but calling other parsers.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] FdtBranch When searching for DT node name, restrict
+ the search to this Device Tree branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+ArmPciConfigInfoParser (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN INT32 FdtBranch
+ );
+
+#endif // ARM_PCI_CONFIG_SPACE_PARSER_H_
--
2.17.1


[PATCH v1 12/14] DynamicTablesPkg: FdtHwInfoParser: Add GIC dispatcher

PierreGondois
 

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

The GIC Dispatcher is the top-level component that is responsible
for invoking the respective parsers for GICC, GICD, GIC MSI Frame,
GIC ITS and the GICR.

Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
Signed-off-by: Sami Mujawar <sami.mujawar@...>
---
.../FdtHwInfoParserLib/Gic/ArmGicDispatcher.c | 212 ++++++++++++++++++
.../FdtHwInfoParserLib/Gic/ArmGicDispatcher.h | 72 ++++++
2 files changed, 284 insertions(+)
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDispatcher.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDispatcher.h

diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDispatcher.c b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDispatcher.c
new file mode 100644
index 000000000000..3e5d7fb0cba6
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDispatcher.c
@@ -0,0 +1,212 @@
+/** @file
+ Arm Gic dispatcher.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic.yaml
+ - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
+**/
+
+#include "FdtHwInfoParser.h"
+#include "Gic/ArmGicCParser.h"
+#include "Gic/ArmGicDispatcher.h"
+#include "Gic/ArmGicDParser.h"
+#include "Gic/ArmGicItsParser.h"
+#include "Gic/ArmGicMsiFrameParser.h"
+#include "Gic/ArmGicRParser.h"
+
+/** List of "compatible" property values for GicV2 interrupt nodes.
+
+ Any other "compatible" value is not supported by this module.
+*/
+STATIC CONST COMPATIBILITY_STR GicV2CompatibleStr[] = {
+ {"arm,cortex-a15-gic"}
+};
+
+/** COMPATIBILITY_INFO structure for the GICv2.
+*/
+CONST COMPATIBILITY_INFO GicV2CompatibleInfo = {
+ ARRAY_SIZE (GicV2CompatibleStr),
+ GicV2CompatibleStr
+};
+
+/** List of "compatible" property values for GicV3 interrupt nodes.
+
+ Any other "compatible" value is not supported by this module.
+*/
+STATIC CONST COMPATIBILITY_STR GicV3CompatibleStr[] = {
+ {"arm,gic-v3"}
+};
+
+/** COMPATIBILITY_INFO structure for the GICv3.
+*/
+CONST COMPATIBILITY_INFO GicV3CompatibleInfo = {
+ ARRAY_SIZE (GicV3CompatibleStr),
+ GicV3CompatibleStr
+};
+
+/** Get the Gic version of am interrupt-controller node.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [in] IntcNode Interrupt-controller node.
+ @param [out] GicVersion If success, contains the Gic version of the
+ interrupt-controller node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+GetGicVersion (
+ IN CONST VOID * Fdt,
+ IN INT32 IntcNode,
+ OUT UINT32 * GicVersion
+ )
+{
+ if ((Fdt == NULL) ||
+ (GicVersion == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FdtNodeIsCompatible (Fdt, IntcNode, &GicV2CompatibleInfo)) {
+ *GicVersion = 2;
+ } else if (FdtNodeIsCompatible (Fdt, IntcNode, &GicV3CompatibleInfo)) {
+ *GicVersion = 3;
+ } else {
+ // Unsupported Gic version.
+ ASSERT (0);
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Gic dispatcher.
+
+ This disptacher populates the following structures:
+ - CM_ARM_GICC_INFO
+ - CM_ARM_GICD_INFO
+ - CM_ARM_GIC_MSI_FRAME_INFO
+
+ A parser parses a Device Tree to populate a specific CmObj type. None,
+ one or many CmObj can be created by the parser.
+ The created CmObj are then handed to the parser's caller through the
+ HW_INFO_ADD_OBJECT interface.
+ This can also be a dispatcher. I.e. a function that not parsing a
+ Device Tree but calling other parsers.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] FdtBranch When searching for DT node name, restrict
+ the search to this Device Tree branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+ArmGicDispatcher (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN INT32 FdtBranch
+ )
+{
+ EFI_STATUS Status;
+ INT32 CpusNode;
+ INT32 IntcNode;
+ UINT32 GicVersion;
+ VOID * Fdt;
+
+ if (FdtParserHandle == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Fdt = FdtParserHandle->Fdt;
+
+ // The "cpus" node resides at the the root of the DT. Fetch it.
+ CpusNode = fdt_path_offset (Fdt, "/cpus");
+ if (CpusNode < 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ // Get the interrupt-controller node associated to the "cpus" node.
+ Status = FdtGetIntcParentNode (Fdt, CpusNode, &IntcNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ if (Status == EFI_NOT_FOUND) {
+ // Should have found the node.
+ Status = EFI_ABORTED;
+ }
+ return Status;
+ }
+
+ Status = GetGicVersion (Fdt, IntcNode, &GicVersion);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Parse the GicC information.
+ Status = ArmGicCInfoParser (FdtParserHandle, CpusNode);
+ if (EFI_ERROR (Status)) {
+ // Don't try to parse GicD and GicMsiFrame information
+ // if no GicC information is found. Return.
+ ASSERT (Status == EFI_NOT_FOUND);
+ return Status;
+ }
+
+ // Parse the GicD information of the "cpus" interrupt-controller node.
+ Status = ArmGicDInfoParser (FdtParserHandle, IntcNode);
+ if (EFI_ERROR (Status)) {
+ // EFI_NOT_FOUND is not tolerated at this point.
+ ASSERT (0);
+ return Status;
+ }
+
+ switch (GicVersion) {
+ case 4:
+ case 3:
+ {
+ // Parse the GicR information of the interrupt-controller node.
+ Status = ArmGicRInfoParser (FdtParserHandle, IntcNode);
+ if (EFI_ERROR (Status)) {
+ // EFI_NOT_FOUND is not tolerated at this point.
+ ASSERT (0);
+ return Status;
+ }
+
+ // Parse the GicIts information of the interrupt-controller node.
+ Status = ArmGicItsInfoParser (FdtParserHandle, IntcNode);
+ if (EFI_ERROR (Status) &&
+ (Status != EFI_NOT_FOUND)) {
+ ASSERT (0);
+ return Status;
+ }
+ break;
+ }
+ case 2:
+ {
+ // Parse the GicMsiFrame information.
+ Status = ArmGicMsiFrameInfoParser (FdtParserHandle, IntcNode);
+ if (EFI_ERROR (Status) &&
+ (Status != EFI_NOT_FOUND)) {
+ ASSERT (0);
+ return Status;
+ }
+ break;
+ }
+ default:
+ {
+ ASSERT (0);
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDispatcher.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDispatcher.h
new file mode 100644
index 000000000000..a0671cea8a67
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDispatcher.h
@@ -0,0 +1,72 @@
+/** @file
+ Arm Gic dispatcher.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic.yaml
+ - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
+**/
+
+#ifndef ARM_GIC_DISPATCHER_H_
+#define ARM_GIC_DISPATCHER_H_
+
+#include <FdtHwInfoParserInclude.h>
+#include "FdtUtility.h"
+
+/** COMPATIBILITY_INFO structure for the GICv2.
+*/
+extern CONST COMPATIBILITY_INFO GicV2CompatibleInfo;
+
+/** Get the Gic version of the interrupt-controller node.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [in] IntcNode Interrupt-controller node.
+ @param [out] GicVersion If success, contains the Gic version of the
+ interrupt-controller node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+GetGicVersion (
+ IN CONST VOID * Fdt,
+ IN INT32 IntcNode,
+ OUT UINT32 * GicVersion
+ );
+
+/** Gic dispatcher.
+
+ This disptacher populates the following structures:
+ - CM_ARM_GICC_INFO
+ - CM_ARM_GICD_INFO
+ - CM_ARM_GIC_MSI_FRAME_INFO
+
+ A parser parses a Device Tree to populate a specific CmObj type. None,
+ one or many CmObj can be created by the parser.
+ The created CmObj are then handed to the parser's caller through the
+ HW_INFO_ADD_OBJECT interface.
+ This can also be a dispatcher. I.e. a function that not parsing a
+ Device Tree but calling other parsers.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] FdtBranch When searching for DT node name, restrict
+ the search to this Device Tree branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+ArmGicDispatcher (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN INT32 FdtBranch
+ );
+
+#endif // ARM_GIC_DISPATCHER_H_
--
2.17.1

19721 - 19740 of 96644