Skip to content

Commit c68e3f3

Browse files
ShellPkg,acpiview: Add RIMT (RISC-V IO Mapping Table) parser
Implementation tested on Qemu-10.1 virt machine with IOMMU enabled. Example of usage: Shell> acpiview -l Installed Table(s): 1. RSDP 2. XSDT 3. FACP 4. DSDT 5. APIC 6. RHCT 7. RIMT 8. SPCR 9. MCFG 10. BGRT Shell> acpiview -s rimt Table Checksum : OK RIMT : Signature : RIMT Length : 128 Revision : 1 Checksum : 0xE1 Oem ID : BOCHS Oem Table ID : BXPC Oem Revision : 0x1 Creator ID : BXPC Creator Revision : 0x1 Number of RIMT Nodes : 2 Offset to RIMT Node Array : 0x30 Reserved : 0x0 Offset to RIMT Node Array: 0x30, Number of Nodes: 2 RIMT Node Address: 0x85BAE030 Type : IOMMU Revision : 0x1 Length : 0x28 Reserved : 0x0 Id : 0 Hardware Id : RSCV0004 (0x3430303056435352) Base Address : 0x3010000 (...) Signed-off-by: Krzysztof Drobiński <krzysztof@plasteli.net>
1 parent 38882a6 commit c68e3f3

File tree

5 files changed

+318
-0
lines changed

5 files changed

+318
-0
lines changed

ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,25 @@ ParseAcpiRasf (
10521052
IN UINT8 AcpiTableRevision
10531053
);
10541054

1055+
/**
1056+
This function parses the ACPI RIMT table.
1057+
When trace is enabled this function parses the RIMT table and
1058+
traces the ACPI table fields.
1059+
1060+
@param [in] Trace If TRUE, trace the ACPI fields.
1061+
@param [in] Ptr Pointer to the start of the buffer.
1062+
@param [in] AcpiTableLength Length of the ACPI table.
1063+
@param [in] AcpiTableRevision Revision of the ACPI table.
1064+
**/
1065+
VOID
1066+
EFIAPI
1067+
ParseAcpiRimt (
1068+
IN BOOLEAN Trace,
1069+
IN UINT8 *Ptr,
1070+
IN UINT32 AcpiTableLength,
1071+
IN UINT8 AcpiTableRevision
1072+
);
1073+
10551074
/**
10561075
This function parses the ACPI RSDP table.
10571076
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/** @file
2+
RISC-V IO Mapping Table (RIMT) parser
3+
4+
Copyright (c) 2025, Plasteli.net. All rights reserved.
5+
SPDX-License-Identifier: BSD-2-Clause-Patent
6+
7+
Reference(s):
8+
- ACPI 6.6 Specification
9+
- RISC-V IO Mapping Table (RIMT) Specification Version v1.0, 2025-03-31: Ratified
10+
**/
11+
12+
#include <IndustryStandard/Acpi.h>
13+
#include <Library/UefiLib.h>
14+
#include "AcpiParser.h"
15+
#include "AcpiTableParser.h"
16+
17+
typedef enum {
18+
IOMMU = 0,
19+
PCIERC,
20+
PLATFORM,
21+
UNSUPPORTED
22+
} RimtNodeType;
23+
24+
// Local variables
25+
STATIC EFI_ACPI_6_6_RIMT_STRUCTURE RimtHdrInfo;
26+
27+
/**
28+
An ACPI_PARSER array describing the RISC-V IO Mapping Table.
29+
**/
30+
STATIC CONST ACPI_PARSER RimtParser[] = {
31+
PARSE_ACPI_HEADER (&RimtHdrInfo.Header),
32+
{ L"Number of RIMT Nodes", 4, 36, L"%d", NULL, NULL, NULL, NULL },
33+
{ L"Offset to RIMT Node Array", 4, 40, L"0x%x", NULL, NULL, NULL, NULL },
34+
{ L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL }
35+
};
36+
STATIC CHAR16 *RimtNodeTypeName[] = {
37+
L"IOMMU",
38+
L"PCIe Root Complex",
39+
L"Platform Device",
40+
L"Unsupported"
41+
};
42+
STATIC CHAR16 *RimtNodeIommuTypeName[] = {
43+
L"Platform",
44+
L"PCIe"
45+
};
46+
STATIC CHAR16 *RimtNodeIommuProximityDomainTypeName[] = {
47+
L"Invalid",
48+
L"Valid"
49+
};
50+
STATIC CHAR16 *RimtNodeIdMappingFlag[] = {
51+
L"Not Required",
52+
L"Required"
53+
};
54+
#define HARDWARE_ID_STRING_SIZE 9
55+
STATIC CHAR8 HardwareIdStr[HARDWARE_ID_STRING_SIZE];
56+
#define GET_INDEX(type) (((type) >= UNSUPPORTED) ? UNSUPPORTED : (type))
57+
58+
/**
59+
This function parses the ACPI RIMT Node header.
60+
RIMT header is common for all RIMT node types
61+
62+
@param [in] Node Pointer to RIMT node.
63+
64+
**/
65+
STATIC
66+
VOID
67+
EFIAPI
68+
PrintRimtNodeHeader (
69+
IN EFI_ACPI_6_6_RIMT_NODE_HEADER_STRUCTURE *Node
70+
)
71+
{
72+
Print (L"\nRIMT Node Address: 0x%p\n", Node);
73+
Print (L"\tType : %s\n", RimtNodeTypeName[GET_INDEX (Node->Type)]);
74+
Print (L"\tRevision : 0x%x\n", Node->Revision);
75+
Print (L"\tLength : 0x%x\n", Node->Length);
76+
Print (L"\tReserved : 0x%x\n", Node->Reserved);
77+
Print (L"\tId : %d\n", Node->Id);
78+
}
79+
80+
/**
81+
This function generates ASCII string from ACPI RIMT Node HardwareID
82+
memory.
83+
84+
@param [in] HardwareId Pointer to HardwareId binary data
85+
@param [out] Str Converted binary data to ASCII string
86+
**/
87+
STATIC
88+
VOID
89+
EFIAPI
90+
HardwareIdToString (
91+
IN UINT64 *HardwareId,
92+
OUT CHAR8 *Str
93+
)
94+
{
95+
UINT8 i;
96+
UINT8 Eol;
97+
98+
Eol = HARDWARE_ID_STRING_SIZE - 1;
99+
for (i = 0; i < Eol; i++) {
100+
Str[i] = ((CHAR8 *)HardwareId)[i];
101+
}
102+
103+
Str[Eol] = '\0';
104+
}
105+
106+
#define GET_BIT(BIT_POS, VALUE) ((VALUE & (1 << BIT_POS)) == 0 ? 0 : 1)
107+
108+
/**
109+
This function parses the ACPI RIMT Node of type IOMMU.
110+
111+
@param [in] Node Pointer to RIMT node of type IOMMU
112+
**/
113+
STATIC
114+
VOID
115+
EFIAPI
116+
PrintRimtNodeIommu (
117+
IN EFI_ACPI_6_6_RIMT_IOMMU_NODE_STRUCTURE *Node
118+
)
119+
{
120+
PrintRimtNodeHeader ((EFI_ACPI_6_6_RIMT_NODE_HEADER_STRUCTURE *)Node);
121+
HardwareIdToString (&Node->HardwareId, HardwareIdStr);
122+
AsciiPrint ("\tHardware Id : %a (0x%lx)\n", HardwareIdStr, Node->HardwareId);
123+
Print (L"\tBase Address : 0x%x\n", Node->BaseAddress);
124+
Print (
125+
L"\tFlags : (0x%x) %s Device | Proximity Domain %s\n",
126+
Node->Flags,
127+
RimtNodeIommuTypeName[GET_BIT (0, Node->Flags)],
128+
RimtNodeIommuProximityDomainTypeName[GET_BIT (1, Node->Flags)]
129+
);
130+
Print (L"\tProximity Domain : %d\n", Node->ProximityDomain);
131+
Print (L"\tPCIe Segment Number : %d\n", Node->PcieSegmentNumber);
132+
Print (L"\tPCIe B/D/F : 0x%x\n", Node->PcieBdf);
133+
Print (L"\tNumber of IRQ Wires : %d\n", Node->NumberOfInterruptWires);
134+
Print (L"\tOffset to IRQ Wire Array : 0x%x\n", Node->InterruptWireArrayOffset);
135+
}
136+
137+
/**
138+
This function parses the ID Mapping Node.
139+
@param [in] Node Pointer to ID Mapping node
140+
**/
141+
STATIC
142+
VOID
143+
EFIAPI
144+
PrintPcieRcIdMappingNode (
145+
IN EFI_ACPI_6_6_RIMT_ID_MAPPING_STRUCTURE *IdMapping
146+
)
147+
{
148+
Print (L"\t\tSource Id Base : 0x%x\n", IdMapping->SourceIdBase);
149+
Print (L"\t\tNumber Of IDs in Range : %d\n", IdMapping->NumberOfIDs);
150+
Print (L"\t\tDestination Device ID Base : 0x%x\n", IdMapping->DestinationDeviceIdBase);
151+
Print (L"\t\tDestination IOMMU Offset : 0x%x\n", IdMapping->DestinationIommuOffset);
152+
Print (
153+
L"\t\tFlags : (0x%x) ATS %s | PRI %s\n",
154+
IdMapping->Flags,
155+
RimtNodeIdMappingFlag[GET_BIT (0, IdMapping->Flags)],
156+
RimtNodeIdMappingFlag[GET_BIT (1, IdMapping->Flags)]
157+
);
158+
}
159+
160+
/**
161+
This function parses ID Mapping array.
162+
@param [in] IdMappingArray Pointer to ID mappings
163+
@param [in] NumberOfIdMappings Number of ID mappings
164+
**/
165+
STATIC
166+
VOID
167+
EFIAPI
168+
PrintRimtNodePcieRcIdMappings (
169+
IN EFI_ACPI_6_6_RIMT_ID_MAPPING_STRUCTURE *IdMappingArray,
170+
IN UINT16 NumberOfIdMappings
171+
)
172+
{
173+
UINT16 i;
174+
175+
for (i = 0; i < NumberOfIdMappings; i++) {
176+
Print (L"\tId Mapping [%d]:\n", i);
177+
PrintPcieRcIdMappingNode (&IdMappingArray[i]);
178+
}
179+
}
180+
181+
/**
182+
This function parses the Root Complex Node together with corresponding ID Mapping nodes.
183+
@param [in] Node Pointer to PCIe Root Complex node
184+
**/
185+
STATIC
186+
VOID
187+
EFIAPI
188+
PrintRimtNodePcieRc (
189+
IN EFI_ACPI_6_6_RIMT_PCIE_ROOT_COMPLEX_NODE_STRUCTURE *Node
190+
)
191+
{
192+
EFI_ACPI_6_6_RIMT_ID_MAPPING_STRUCTURE *IdMappingArray;
193+
194+
IdMappingArray = (EFI_ACPI_6_6_RIMT_ID_MAPPING_STRUCTURE *)((UINTN)(Node) + (UINTN)(Node->IdMappingArrayOffset));
195+
PrintRimtNodeHeader ((EFI_ACPI_6_6_RIMT_NODE_HEADER_STRUCTURE *)Node);
196+
Print (
197+
L"\tFlags : (0x%x) ATS %s | PRI %s\n",
198+
Node->Flags,
199+
RimtNodeIdMappingFlag[GET_BIT (0, Node->Flags)],
200+
RimtNodeIdMappingFlag[GET_BIT (1, Node->Flags)]
201+
);
202+
Print (L"\tReserved : 0x%x\n", Node->Reserved);
203+
Print (L"\tPCI Segment Number : %d\n", Node->PcieSegmentNumber);
204+
Print (L"\tOffset to ID Mapping Array : 0x%x\n", Node->IdMappingArrayOffset);
205+
Print (L"\tNumber of ID Mappings : %d\n", Node->NumberOfIdMappings);
206+
PrintRimtNodePcieRcIdMappings (IdMappingArray, Node->NumberOfIdMappings);
207+
}
208+
209+
/**
210+
TODO: This has been not tested
211+
This function parses the Platform Device Node and corresponding ID Mapping nodes.
212+
@param [in] Node Pointer to Platform device node
213+
**/
214+
STATIC
215+
VOID
216+
EFIAPI
217+
PrintRimtNodePlatformDevice (
218+
IN EFI_ACPI_6_6_RIMT_PLATFORM_DEVICE_NODE_STRUCTURE *Node
219+
)
220+
{
221+
PrintRimtNodeHeader ((EFI_ACPI_6_6_RIMT_NODE_HEADER_STRUCTURE *)Node);
222+
Print (L"\tParser not implemented for Platform Device RIMT node\n");
223+
}
224+
225+
/**
226+
This function Iterates over RIMT Nodes and prints every node.
227+
228+
@param [in] Rimt Pointer to the start of RIMT
229+
**/
230+
STATIC
231+
VOID
232+
EFIAPI
233+
ParseAcpiRimtNodes (
234+
IN EFI_ACPI_6_6_RIMT_STRUCTURE *Rimt
235+
)
236+
{
237+
UINT32 i;
238+
UINT32 NumberOfRimtNodes;
239+
EFI_ACPI_6_6_RIMT_NODE_HEADER_STRUCTURE *Node;
240+
241+
Node = (EFI_ACPI_6_6_RIMT_NODE_HEADER_STRUCTURE *)((UINTN)Rimt + (UINTN)(Rimt->OffsetToRimtNodeArray));
242+
NumberOfRimtNodes = Rimt->NumberOfRimtNodes;
243+
Print (L"\nOffset to RIMT Node Array: 0x%x, Number of Nodes: %d\n", Rimt->OffsetToRimtNodeArray, NumberOfRimtNodes);
244+
for (i = 0; i < NumberOfRimtNodes; i++) {
245+
if (Node->Type == IOMMU) {
246+
PrintRimtNodeIommu ((EFI_ACPI_6_6_RIMT_IOMMU_NODE_STRUCTURE *)Node);
247+
} else if (Node->Type == PCIERC) {
248+
PrintRimtNodePcieRc ((EFI_ACPI_6_6_RIMT_PCIE_ROOT_COMPLEX_NODE_STRUCTURE *)Node);
249+
} else if (Node->Type == PLATFORM) {
250+
/* TODO: Printing platform device nodes Not tested */
251+
PrintRimtNodePlatformDevice ((EFI_ACPI_6_6_RIMT_PLATFORM_DEVICE_NODE_STRUCTURE *)Node);
252+
} else {
253+
Print (L"\nError!!!!\n");
254+
}
255+
256+
Node = (EFI_ACPI_6_6_RIMT_NODE_HEADER_STRUCTURE *)((UINTN)Node + (UINTN)(Node->Length));
257+
}
258+
}
259+
260+
/**
261+
This function parses the ACPI RIMT table.
262+
When trace is enabled this function parses the RIMT table and
263+
traces the ACPI table fields.
264+
265+
@param [in] Trace If TRUE, trace the ACPI fields.
266+
@param [in] Ptr Pointer to the start of the buffer.
267+
@param [in] AcpiTableLength Length of the ACPI table.
268+
@param [in] AcpiTableRevision Revision of the ACPI table.
269+
**/
270+
VOID
271+
EFIAPI
272+
ParseAcpiRimt (
273+
IN BOOLEAN Trace,
274+
IN UINT8 *Ptr,
275+
IN UINT32 AcpiTableLength,
276+
IN UINT8 AcpiTableRevision
277+
)
278+
{
279+
UINT32 Offset;
280+
EFI_ACPI_6_6_RIMT_STRUCTURE *Rimt;
281+
282+
if (!Trace) {
283+
return;
284+
}
285+
286+
Offset = ParseAcpi (
287+
Trace,
288+
1,
289+
"RIMT",
290+
Ptr,
291+
AcpiTableLength,
292+
PARSER_PARAMS (RimtParser)
293+
);
294+
Rimt = (EFI_ACPI_6_6_RIMT_STRUCTURE *)Ptr;
295+
ParseAcpiRimtNodes (Rimt);
296+
}

ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ ACPI_TABLE_PARSER ParserList[] = {
7373
ParseAcpiPptt },
7474
{ EFI_ACPI_6_5_ACPI_RAS2_FEATURE_TABLE_SIGNATURE, ParseAcpiRas2 },
7575
{ EFI_ACPI_6_5_ACPI_RAS_FEATURE_TABLE_SIGNATURE, ParseAcpiRasf },
76+
{ EFI_ACPI_6_6_RIMT_TABLE_SIGNATURE, ParseAcpiRimt },
7677
{ RSDP_TABLE_INFO, ParseAcpiRsdp },
7778
{ EFI_ACPI_6_2_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE, ParseAcpiSlit },
7879
{ EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, ParseAcpiSpcr },

ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
Parsers/Pptt/PpttParser.h
5353
Parsers/Ras2/Ras2Parser.c
5454
Parsers/Rasf/RasfParser.c
55+
Parsers/Rimt/RimtParser.c
5556
Parsers/Rsdp/RsdpParser.c
5657
Parsers/Slit/SlitParser.c
5758
Parsers/Spcr/SpcrParser.c

ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
" MPAM - Memory System Resource Partitioning and Monitoring Table\r\n"
9393
" PPTT - Processor Properties Topology Table\r\n"
9494
" RSDP - Root System Description Pointer\r\n"
95+
" RIMT - RISC-V IO Mapping Table\r\n"
9596
" SLIT - System Locality Information Table\r\n"
9697
" SPCR - Serial Port Console Redirection Table\r\n"
9798
" SRAT - System Resource Affinity Table\r\n"

0 commit comments

Comments
 (0)