[PATCH v2 4/8] ShellPkg: Acpiview: IORT parser update for IORT Rev E.b spec


Sami Mujawar
 

Bugzilla: 3458 - Add support IORT Rev E.b specification updates
(https://bugzilla.tianocore.org/show_bug.cgi?id=3458)

The IO Remapping Table, Platform Design Document, Revision E.b,
Feb 2021 (https://developer.arm.com/documentation/den0049/)
introduces the following updates, collectively including the
updates and errata fixes to Rev E and Rev E.a:
- increments the IORT table revision to 3.
- updates the node definition to add an 'Identifier' field.
- adds definition of node type 6 - Reserved Memory Range node.
- adds definition for Memory Range Descriptors.
- adds flag to indicate PRI support for root complexes.
- adds flag to indicate if the root complex supports forwarding
of PASID information on translated transactions to the SMMU.

Therefore, update the IORT parser to:
- parse the Identifier field.
- parse Reserved Memory Range node.
- parse Memory Range Descriptors.
- add validations to check that the physical range base
and size of the Memory Range Descriptor is 64KB aligned.
- add validation to check that the ID mapping count is
set to 1.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---

Notes:
v2:
- No code change since v1. Re-sending with v2 series. [SAMI]

ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c | 196 +++++++++++++++++++-
1 file changed, 191 insertions(+), 5 deletions(-)

diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
index fcecaff5134256497bda87241f339076897c3ece..1507dd3a4d79e61024b0c5526e21ffdacb782251 100644
--- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
@@ -5,10 +5,12 @@
SPDX-License-Identifier: BSD-2-Clause-Patent

@par Reference(s):
- - IO Remapping Table, Platform Design Document, Revision D, March 2018
+ - IO Remapping Table, Platform Design Document, Revision E.b, Feb 2021
+ (https://developer.arm.com/documentation/den0049/)

@par Glossary:
- Ref - Reference
+ - Desc - Descriptor
**/

#include <IndustryStandard/IoRemappingTable.h>
@@ -36,6 +38,9 @@ STATIC CONST UINT32* PmuInterruptOffset;

STATIC CONST UINT32* ItsCount;

+STATIC CONST UINT32* RmrMemDescCount;
+STATIC CONST UINT32* RmrMemDescOffset;
+
/**
This function validates the ID Mapping array count for the ITS node.

@@ -100,6 +105,72 @@ ValidateItsIdArrayReference (
}
}

+/**
+ This function validates that the address or length is 64K aligned.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+Validate64KAlignment (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT64 Address;
+ Address = *(UINT64*)Ptr;
+ if ((Address & (SIZE_64KB - 1)) != 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Value must be 64K aligned.");
+ }
+}
+
+/**
+ This function validates that the RMR memory range descriptor count.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateRmrMemDescCount (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*(UINT32*)Ptr == 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Memory Range Descriptor count must be >=1.");
+ }
+}
+
+/**
+ This function validates the ID Mapping array count for the Reserved
+ Memory Range (RMR) node.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateRmrIdMappingCount (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*(UINT32*)Ptr != 1) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: IORT ID Mapping count must be set to 1.");
+ }
+}
+
/**
Helper Macro for populating the IORT Node header in the ACPI_PARSER array.

@@ -113,7 +184,7 @@ ValidateItsIdArrayReference (
{ L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL }, \
{ L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \
{ L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL }, \
- { L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \
+ { L"Identifier", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \
{ L"Number of ID mappings", 4, 8, L"%d", NULL, \
(VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL }, \
{ L"Reference to ID Array", 4, 12, L"0x%x", NULL, \
@@ -253,6 +324,29 @@ STATIC CONST ACPI_PARSER IortNodePmcgParser[] = {
{L"Page 1 Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}
};

+/**
+ An ACPI_PARSER array describing the IORT RMR node.
+**/
+STATIC CONST ACPI_PARSER IortNodeRmrParser[] = {
+ PARSE_IORT_NODE_HEADER (ValidateRmrIdMappingCount, NULL),
+ {L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Memory Range Desc count", 4, 20, L"%d", NULL,
+ (VOID**)&RmrMemDescCount, ValidateRmrMemDescCount, NULL},
+ {L"Memory Range Desc Ref", 4, 24, L"0x%x", NULL,
+ (VOID**)&RmrMemDescOffset, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the IORT RMR Memory Range Descriptor.
+**/
+STATIC CONST ACPI_PARSER IortNodeRmrMemRangeDescParser[] = {
+ {L"Physical Range offset", 8, 0, L"0x%lx", NULL, NULL, Validate64KAlignment,
+ NULL},
+ {L"Physical Range length", 8, 8, L"0x%lx", NULL, NULL, Validate64KAlignment,
+ NULL},
+ {L"Reserved", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
/**
This function parses the IORT Node Id Mapping array.

@@ -601,9 +695,93 @@ DumpIortNodePmcg (
);
}

+/**
+ This function parses the IORT RMR Node Memory Range Descriptor array.
+
+ @param [in] Ptr Pointer to the start of the Memory Range Descriptor
+ array.
+ @param [in] Length Length of the buffer.
+ @param [in] DescCount Memory Range Descriptor count.
+**/
+STATIC
+VOID
+DumpIortNodeRmrMemRangeDesc (
+ IN UINT8* Ptr,
+ IN UINT32 Length,
+ IN UINT32 DescCount
+ )
+{
+ UINT32 Index;
+ UINT32 Offset;
+ CHAR8 Buffer[40]; // Used for AsciiName param of ParseAcpi
+
+ Index = 0;
+ Offset = 0;
+
+ while ((Index < DescCount) &&
+ (Offset < Length)) {
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "Mem range Descriptor [%d]",
+ Index
+ );
+ Offset += ParseAcpi (
+ TRUE,
+ 4,
+ Buffer,
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (IortNodeRmrMemRangeDescParser)
+ );
+ Index++;
+ }
+}
+
+/**
+ This function parses the IORT RMR node.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Length Length of the buffer.
+ @param [in] MappingCount The ID Mapping count.
+ @param [in] MappingOffset The offset of the ID Mapping array
+ from the start of the IORT table.
+**/
+STATIC
+VOID
+DumpIortNodeRmr (
+ IN UINT8* Ptr,
+ IN UINT16 Length,
+ IN UINT32 MappingCount,
+ IN UINT32 MappingOffset
+)
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "RMR Node",
+ Ptr,
+ Length,
+ PARSER_PARAMS (IortNodeRmrParser)
+ );
+
+ DumpIortNodeIdMappings (
+ Ptr + MappingOffset,
+ Length - MappingOffset,
+ MappingCount
+ );
+
+ DumpIortNodeRmrMemRangeDesc (
+ Ptr + (*RmrMemDescOffset),
+ Length - (*RmrMemDescOffset),
+ *RmrMemDescCount
+ );
+}
+
/**
This function parses the ACPI IORT table.
- When trace is enabled this function parses the IORT table and traces the ACPI fields.
+ When trace is enabled this function parses the IORT table and traces the ACPI
+ fields.

This function also parses the following nodes:
- ITS Group
@@ -612,6 +790,7 @@ DumpIortNodePmcg (
- SMMUv1/2
- SMMUv3
- PMCG
+ - RMR

This function also performs validation of the ACPI table fields.

@@ -753,9 +932,16 @@ ParseAcpiIort (
*IortNodeLength,
*IortIdMappingCount,
*IortIdMappingOffset
- );
+ );
+ break;
+ case EFI_ACPI_IORT_TYPE_RMR:
+ DumpIortNodeRmr (
+ NodePtr,
+ *IortNodeLength,
+ *IortIdMappingCount,
+ *IortIdMappingOffset
+ );
break;
-
default:
IncrementErrorCount ();
Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType);
--
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


Gao, Zhichao
 

Reviewed-by: Zhichao Gao <zhichao.gao@intel.com>

Thanks,
Zhichao

-----Original Message-----
From: Sami Mujawar <sami.mujawar@arm.com>
Sent: Thursday, June 17, 2021 5:56 PM
To: devel@edk2.groups.io
Cc: Sami Mujawar <sami.mujawar@arm.com>; Alexei.Fedorov@arm.com;
steven.price@arm.com; Lorenzo.Pieralisi@arm.com;
Matteo.Carlini@arm.com; Ben.Adderson@arm.com; Ni, Ray
<ray.ni@intel.com>; Gao, Zhichao <zhichao.gao@intel.com>; nd@arm.com
Subject: [PATCH v2 4/8] ShellPkg: Acpiview: IORT parser update for IORT Rev
E.b spec

Bugzilla: 3458 - Add support IORT Rev E.b specification updates
(https://bugzilla.tianocore.org/show_bug.cgi?id=3458)

The IO Remapping Table, Platform Design Document, Revision E.b, Feb 2021
(https://developer.arm.com/documentation/den0049/)
introduces the following updates, collectively including the updates and
errata fixes to Rev E and Rev E.a:
- increments the IORT table revision to 3.
- updates the node definition to add an 'Identifier' field.
- adds definition of node type 6 - Reserved Memory Range node.
- adds definition for Memory Range Descriptors.
- adds flag to indicate PRI support for root complexes.
- adds flag to indicate if the root complex supports forwarding
of PASID information on translated transactions to the SMMU.

Therefore, update the IORT parser to:
- parse the Identifier field.
- parse Reserved Memory Range node.
- parse Memory Range Descriptors.
- add validations to check that the physical range base
and size of the Memory Range Descriptor is 64KB aligned.
- add validation to check that the ID mapping count is
set to 1.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---

Notes:
v2:
- No code change since v1. Re-sending with v2 series. [SAMI]

ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c |
196 +++++++++++++++++++-
1 file changed, 191 insertions(+), 5 deletions(-)

diff --git
a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
index
fcecaff5134256497bda87241f339076897c3ece..1507dd3a4d79e61024b0c5526e
21ffdacb782251 100644
---
a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortPars
+++ er.c
@@ -5,10 +5,12 @@
SPDX-License-Identifier: BSD-2-Clause-Patent

@par Reference(s):
- - IO Remapping Table, Platform Design Document, Revision D, March 2018
+ - IO Remapping Table, Platform Design Document, Revision E.b, Feb 2021
+ (https://developer.arm.com/documentation/den0049/)

@par Glossary:
- Ref - Reference
+ - Desc - Descriptor
**/

#include <IndustryStandard/IoRemappingTable.h>
@@ -36,6 +38,9 @@ STATIC CONST UINT32* PmuInterruptOffset;

STATIC CONST UINT32* ItsCount;

+STATIC CONST UINT32* RmrMemDescCount;
+STATIC CONST UINT32* RmrMemDescOffset;
+
/**
This function validates the ID Mapping array count for the ITS node.

@@ -100,6 +105,72 @@ ValidateItsIdArrayReference (
}
}

+/**
+ This function validates that the address or length is 64K aligned.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+Validate64KAlignment (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT64 Address;
+ Address = *(UINT64*)Ptr;
+ if ((Address & (SIZE_64KB - 1)) != 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Value must be 64K aligned.");
+ }
+}
+
+/**
+ This function validates that the RMR memory range descriptor count.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateRmrMemDescCount (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*(UINT32*)Ptr == 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Memory Range Descriptor count must be >=1.");
+ }
+}
+
+/**
+ This function validates the ID Mapping array count for the Reserved
+ Memory Range (RMR) node.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateRmrIdMappingCount (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*(UINT32*)Ptr != 1) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: IORT ID Mapping count must be set to 1.");
+ }
+}
+
/**
Helper Macro for populating the IORT Node header in the ACPI_PARSER
array.

@@ -113,7 +184,7 @@ ValidateItsIdArrayReference (
{ L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL }, \
{ L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \
{ L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL }, \
- { L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \
+ { L"Identifier", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \
{ L"Number of ID mappings", 4, 8, L"%d", NULL, \
(VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL }, \
{ L"Reference to ID Array", 4, 12, L"0x%x", NULL, \
@@ -253,6 +324,29 @@ STATIC CONST ACPI_PARSER IortNodePmcgParser[]
= {
{L"Page 1 Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL} };

+/**
+ An ACPI_PARSER array describing the IORT RMR node.
+**/
+STATIC CONST ACPI_PARSER IortNodeRmrParser[] = {
+ PARSE_IORT_NODE_HEADER (ValidateRmrIdMappingCount, NULL),
+ {L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Memory Range Desc count", 4, 20, L"%d", NULL,
+ (VOID**)&RmrMemDescCount, ValidateRmrMemDescCount, NULL},
+ {L"Memory Range Desc Ref", 4, 24, L"0x%x", NULL,
+ (VOID**)&RmrMemDescOffset, NULL, NULL} };
+
+/**
+ An ACPI_PARSER array describing the IORT RMR Memory Range Descriptor.
+**/
+STATIC CONST ACPI_PARSER IortNodeRmrMemRangeDescParser[] = {
+ {L"Physical Range offset", 8, 0, L"0x%lx", NULL, NULL,
Validate64KAlignment,
+ NULL},
+ {L"Physical Range length", 8, 8, L"0x%lx", NULL, NULL,
Validate64KAlignment,
+ NULL},
+ {L"Reserved", 4, 16, L"0x%x", NULL, NULL, NULL, NULL} };
+
/**
This function parses the IORT Node Id Mapping array.

@@ -601,9 +695,93 @@ DumpIortNodePmcg (
);
}

+/**
+ This function parses the IORT RMR Node Memory Range Descriptor array.
+
+ @param [in] Ptr Pointer to the start of the Memory Range Descriptor
+ array.
+ @param [in] Length Length of the buffer.
+ @param [in] DescCount Memory Range Descriptor count.
+**/
+STATIC
+VOID
+DumpIortNodeRmrMemRangeDesc (
+ IN UINT8* Ptr,
+ IN UINT32 Length,
+ IN UINT32 DescCount
+ )
+{
+ UINT32 Index;
+ UINT32 Offset;
+ CHAR8 Buffer[40]; // Used for AsciiName param of ParseAcpi
+
+ Index = 0;
+ Offset = 0;
+
+ while ((Index < DescCount) &&
+ (Offset < Length)) {
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "Mem range Descriptor [%d]",
+ Index
+ );
+ Offset += ParseAcpi (
+ TRUE,
+ 4,
+ Buffer,
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (IortNodeRmrMemRangeDescParser)
+ );
+ Index++;
+ }
+}
+
+/**
+ This function parses the IORT RMR node.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Length Length of the buffer.
+ @param [in] MappingCount The ID Mapping count.
+ @param [in] MappingOffset The offset of the ID Mapping array
+ from the start of the IORT table.
+**/
+STATIC
+VOID
+DumpIortNodeRmr (
+ IN UINT8* Ptr,
+ IN UINT16 Length,
+ IN UINT32 MappingCount,
+ IN UINT32 MappingOffset
+)
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "RMR Node",
+ Ptr,
+ Length,
+ PARSER_PARAMS (IortNodeRmrParser)
+ );
+
+ DumpIortNodeIdMappings (
+ Ptr + MappingOffset,
+ Length - MappingOffset,
+ MappingCount
+ );
+
+ DumpIortNodeRmrMemRangeDesc (
+ Ptr + (*RmrMemDescOffset),
+ Length - (*RmrMemDescOffset),
+ *RmrMemDescCount
+ );
+}
+
/**
This function parses the ACPI IORT table.
- When trace is enabled this function parses the IORT table and traces the
ACPI fields.
+ When trace is enabled this function parses the IORT table and traces
+ the ACPI fields.

This function also parses the following nodes:
- ITS Group
@@ -612,6 +790,7 @@ DumpIortNodePmcg (
- SMMUv1/2
- SMMUv3
- PMCG
+ - RMR

This function also performs validation of the ACPI table fields.

@@ -753,9 +932,16 @@ ParseAcpiIort (
*IortNodeLength,
*IortIdMappingCount,
*IortIdMappingOffset
- );
+ );
+ break;
+ case EFI_ACPI_IORT_TYPE_RMR:
+ DumpIortNodeRmr (
+ NodePtr,
+ *IortNodeLength,
+ *IortIdMappingCount,
+ *IortIdMappingOffset
+ );
break;
-
default:
IncrementErrorCount ();
Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType);
--
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'