]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c
DynamicTablesPkg: Fix IORT node length assignment
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiIortLibArm / IortGenerator.c
CommitLineData
dfaffc69
SM
1/** @file\r
2 IORT Table Generator\r
3\r
4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.\r
9cd9bdc6 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
dfaffc69
SM
6\r
7 @par Reference(s):\r
8 - IO Remapping Table, Platform Design Document,\r
9 Document number: ARM DEN 0049D, Issue D, March 2018\r
10\r
11**/\r
12\r
13#include <IndustryStandard/IoRemappingTable.h>\r
14#include <Library/AcpiLib.h>\r
15#include <Library/BaseLib.h>\r
16#include <Library/DebugLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
18#include <Protocol/AcpiTable.h>\r
19\r
20// Module specific include files.\r
21#include <AcpiTableGenerator.h>\r
22#include <ConfigurationManagerObject.h>\r
23#include <ConfigurationManagerHelper.h>\r
24#include <Library/TableHelperLib.h>\r
25#include <Protocol/ConfigurationManagerProtocol.h>\r
26\r
27#include "IortGenerator.h"\r
28\r
29/** ARM standard IORT Generator\r
30\r
31Requirements:\r
32 The following Configuration Manager Object(s) are required by\r
33 this Generator:\r
34 - EArmObjItsGroup\r
35 - EArmObjNamedComponent\r
36 - EArmObjRootComplex\r
37 - EArmObjSmmuV1SmmuV2\r
38 - EArmObjSmmuV3\r
39 - EArmObjPmcg\r
40 - EArmObjGicItsIdentifierArray\r
98a4a7a9 41 - EArmObjIdMappingArray\r
dfaffc69
SM
42 - EArmObjGicItsIdentifierArray\r
43*/\r
44\r
45/** This macro expands to a function that retrieves the ITS\r
46 Group node information from the Configuration Manager.\r
47*/\r
48GET_OBJECT_LIST (\r
49 EObjNameSpaceArm,\r
50 EArmObjItsGroup,\r
51 CM_ARM_ITS_GROUP_NODE\r
52 );\r
53\r
54/** This macro expands to a function that retrieves the\r
55 Named Component node information from the Configuration Manager.\r
56*/\r
57GET_OBJECT_LIST (\r
58 EObjNameSpaceArm,\r
59 EArmObjNamedComponent,\r
60 CM_ARM_NAMED_COMPONENT_NODE\r
61 );\r
62\r
63/** This macro expands to a function that retrieves the\r
64 Root Complex node information from the Configuration Manager.\r
65*/\r
66GET_OBJECT_LIST (\r
67 EObjNameSpaceArm,\r
68 EArmObjRootComplex,\r
69 CM_ARM_ROOT_COMPLEX_NODE\r
70 );\r
71\r
72/** This macro expands to a function that retrieves the\r
73 SMMU v1/v2 node information from the Configuration Manager.\r
74*/\r
75GET_OBJECT_LIST (\r
76 EObjNameSpaceArm,\r
77 EArmObjSmmuV1SmmuV2,\r
78 CM_ARM_SMMUV1_SMMUV2_NODE\r
79 );\r
80\r
81/** This macro expands to a function that retrieves the\r
82 SMMU v3 node information from the Configuration Manager.\r
83*/\r
84GET_OBJECT_LIST (\r
85 EObjNameSpaceArm,\r
86 EArmObjSmmuV3,\r
87 CM_ARM_SMMUV3_NODE\r
88 );\r
89\r
90/** This macro expands to a function that retrieves the\r
91 PMCG node information from the Configuration Manager.\r
92*/\r
93GET_OBJECT_LIST (\r
94 EObjNameSpaceArm,\r
95 EArmObjPmcg,\r
96 CM_ARM_PMCG_NODE\r
97 );\r
98\r
99/** This macro expands to a function that retrieves the\r
100 ITS Identifier Array information from the Configuration Manager.\r
101*/\r
102GET_OBJECT_LIST (\r
103 EObjNameSpaceArm,\r
104 EArmObjGicItsIdentifierArray,\r
105 CM_ARM_ITS_IDENTIFIER\r
106 );\r
107\r
108/** This macro expands to a function that retrieves the\r
109 Id Mapping Array information from the Configuration Manager.\r
110*/\r
111GET_OBJECT_LIST (\r
112 EObjNameSpaceArm,\r
98a4a7a9 113 EArmObjIdMappingArray,\r
dfaffc69
SM
114 CM_ARM_ID_MAPPING\r
115 );\r
116\r
117/** This macro expands to a function that retrieves the\r
118 SMMU Interrupt Array information from the Configuration Manager.\r
119*/\r
120GET_OBJECT_LIST (\r
121 EObjNameSpaceArm,\r
122 EArmObjSmmuInterruptArray,\r
123 CM_ARM_SMMU_INTERRUPT\r
124 );\r
125\r
126/** Returns the size of the ITS Group node.\r
127\r
128 @param [in] Node Pointer to ITS Group node.\r
129\r
130 @retval Size of the ITS Group Node.\r
131**/\r
132STATIC\r
133UINT32\r
134GetItsGroupNodeSize (\r
135 IN CONST CM_ARM_ITS_GROUP_NODE * Node\r
136 )\r
137{\r
138 ASSERT (Node != NULL);\r
139\r
140 /* Size of ITS Group Node +\r
141 Size of ITS Identifier array\r
142 */\r
8b2ac43b
SM
143 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE) +\r
144 (Node->ItsIdCount * sizeof (UINT32)));\r
dfaffc69
SM
145}\r
146\r
147/** Returns the total size required for the ITS Group nodes and\r
148 updates the Node Indexer.\r
149\r
150 This function calculates the size required for the node group\r
151 and also populates the Node Indexer array with offsets for the\r
152 individual nodes.\r
153\r
154 @param [in] NodeStartOffset Offset from the start of the\r
155 IORT where this node group starts.\r
156 @param [in] NodeList Pointer to ITS Group node list.\r
157 @param [in] NodeCount Count of the ITS Group nodes.\r
158 @param [in, out] NodeIndexer Pointer to the next Node Indexer.\r
159\r
160 @retval Total size of the ITS Group Nodes.\r
161**/\r
162STATIC\r
8b2ac43b 163UINT64\r
dfaffc69
SM
164GetSizeofItsGroupNodes (\r
165 IN CONST UINT32 NodeStartOffset,\r
166 IN CONST CM_ARM_ITS_GROUP_NODE * NodeList,\r
167 IN UINT32 NodeCount,\r
168 IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer\r
169 )\r
170{\r
8b2ac43b 171 UINT64 Size;\r
dfaffc69
SM
172\r
173 ASSERT (NodeList != NULL);\r
174\r
175 Size = 0;\r
176 while (NodeCount-- != 0) {\r
177 (*NodeIndexer)->Token = NodeList->Token;\r
178 (*NodeIndexer)->Object = (VOID*)NodeList;\r
8b2ac43b 179 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);\r
dfaffc69
SM
180 DEBUG ((\r
181 DEBUG_INFO,\r
182 "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",\r
183 *NodeIndexer,\r
184 (*NodeIndexer)->Token,\r
185 (*NodeIndexer)->Object,\r
186 (*NodeIndexer)->Offset\r
187 ));\r
188\r
189 Size += GetItsGroupNodeSize (NodeList);\r
190 (*NodeIndexer)++;\r
191 NodeList++;\r
192 }\r
193 return Size;\r
194}\r
195\r
196/** Returns the size of the Named Component node.\r
197\r
198 @param [in] Node Pointer to Named Component node.\r
199\r
200 @retval Size of the Named Component node.\r
201**/\r
202STATIC\r
203UINT32\r
204GetNamedComponentNodeSize (\r
205 IN CONST CM_ARM_NAMED_COMPONENT_NODE * Node\r
206 )\r
207{\r
208 ASSERT (Node != NULL);\r
209\r
210 /* Size of Named Component node +\r
211 Size of ID mapping array +\r
212 Size of ASCII string + 'padding to 32-bit word aligned'.\r
213 */\r
8b2ac43b
SM
214 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE) +\r
215 (Node->IdMappingCount *\r
216 sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE)) +\r
217 ALIGN_VALUE (AsciiStrSize (Node->ObjectName), 4));\r
dfaffc69
SM
218}\r
219\r
220/** Returns the total size required for the Named Component nodes and\r
221 updates the Node Indexer.\r
222\r
223 This function calculates the size required for the node group\r
224 and also populates the Node Indexer array with offsets for the\r
225 individual nodes.\r
226\r
227 @param [in] NodeStartOffset Offset from the start of the\r
228 IORT where this node group starts.\r
229 @param [in] NodeList Pointer to Named Component node list.\r
230 @param [in] NodeCount Count of the Named Component nodes.\r
231 @param [in, out] NodeIndexer Pointer to the next Node Indexer.\r
232\r
233 @retval Total size of the Named Component nodes.\r
234**/\r
235STATIC\r
8b2ac43b 236UINT64\r
dfaffc69
SM
237GetSizeofNamedComponentNodes (\r
238 IN CONST UINT32 NodeStartOffset,\r
239 IN CONST CM_ARM_NAMED_COMPONENT_NODE * NodeList,\r
240 IN UINT32 NodeCount,\r
241 IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer\r
242 )\r
243{\r
8b2ac43b 244 UINT64 Size;\r
dfaffc69
SM
245\r
246 ASSERT (NodeList != NULL);\r
247\r
248 Size = 0;\r
249 while (NodeCount-- != 0) {\r
250 (*NodeIndexer)->Token = NodeList->Token;\r
251 (*NodeIndexer)->Object = (VOID*)NodeList;\r
8b2ac43b 252 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);\r
dfaffc69
SM
253 DEBUG ((\r
254 DEBUG_INFO,\r
255 "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",\r
256 *NodeIndexer,\r
257 (*NodeIndexer)->Token,\r
258 (*NodeIndexer)->Object,\r
259 (*NodeIndexer)->Offset\r
260 ));\r
261\r
262 Size += GetNamedComponentNodeSize (NodeList);\r
263 (*NodeIndexer)++;\r
264 NodeList++;\r
265 }\r
266\r
267 return Size;\r
268}\r
269\r
270/** Returns the size of the Root Complex node.\r
271\r
272 @param [in] Node Pointer to Root Complex node.\r
273\r
274 @retval Size of the Root Complex node.\r
275**/\r
276STATIC\r
277UINT32\r
278GetRootComplexNodeSize (\r
279 IN CONST CM_ARM_ROOT_COMPLEX_NODE * Node\r
280 )\r
281{\r
282 ASSERT (Node != NULL);\r
283\r
284 /* Size of Root Complex node +\r
285 Size of ID mapping array\r
286 */\r
8b2ac43b
SM
287 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE) +\r
288 (Node->IdMappingCount *\r
289 sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE)));\r
dfaffc69
SM
290}\r
291\r
292/** Returns the total size required for the Root Complex nodes and\r
293 updates the Node Indexer.\r
294\r
295 This function calculates the size required for the node group\r
296 and also populates the Node Indexer array with offsets for the\r
297 individual nodes.\r
298\r
299 @param [in] NodeStartOffset Offset from the start of the\r
300 IORT where this node group starts.\r
301 @param [in] NodeList Pointer to Root Complex node list.\r
302 @param [in] NodeCount Count of the Root Complex nodes.\r
303 @param [in, out] NodeIndexer Pointer to the next Node Indexer.\r
304\r
305 @retval Total size of the Root Complex nodes.\r
306**/\r
307STATIC\r
8b2ac43b 308UINT64\r
dfaffc69
SM
309GetSizeofRootComplexNodes (\r
310 IN CONST UINT32 NodeStartOffset,\r
311 IN CONST CM_ARM_ROOT_COMPLEX_NODE * NodeList,\r
312 IN UINT32 NodeCount,\r
313 IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer\r
314 )\r
315{\r
8b2ac43b 316 UINT64 Size;\r
dfaffc69
SM
317\r
318 ASSERT (NodeList != NULL);\r
319\r
320 Size = 0;\r
321 while (NodeCount-- != 0) {\r
322 (*NodeIndexer)->Token = NodeList->Token;\r
323 (*NodeIndexer)->Object = (VOID*)NodeList;\r
8b2ac43b 324 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);\r
dfaffc69
SM
325 DEBUG ((\r
326 DEBUG_INFO,\r
327 "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",\r
328 *NodeIndexer,\r
329 (*NodeIndexer)->Token,\r
330 (*NodeIndexer)->Object,\r
331 (*NodeIndexer)->Offset\r
332 ));\r
333\r
334 Size += GetRootComplexNodeSize (NodeList);\r
335 (*NodeIndexer)++;\r
336 NodeList++;\r
337 }\r
338\r
339 return Size;\r
340}\r
341\r
342/** Returns the size of the SMMUv1/SMMUv2 node.\r
343\r
344 @param [in] Node Pointer to SMMUv1/SMMUv2 node list.\r
345\r
346 @retval Size of the SMMUv1/SMMUv2 node.\r
347**/\r
348STATIC\r
349UINT32\r
350GetSmmuV1V2NodeSize (\r
351 IN CONST CM_ARM_SMMUV1_SMMUV2_NODE * Node\r
352 )\r
353{\r
354 ASSERT (Node != NULL);\r
355\r
356 /* Size of SMMU v1/SMMU v2 node +\r
357 Size of ID mapping array +\r
358 Size of context interrupt array +\r
359 Size of PMU interrupt array\r
360 */\r
8b2ac43b
SM
361 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE) +\r
362 (Node->IdMappingCount *\r
363 sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE)) +\r
364 (Node->ContextInterruptCount *\r
365 sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT)) +\r
366 (Node->PmuInterruptCount *\r
367 sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT)));\r
dfaffc69
SM
368}\r
369\r
370/** Returns the total size required for the SMMUv1/SMMUv2 nodes and\r
371 updates the Node Indexer.\r
372\r
373 This function calculates the size required for the node group\r
374 and also populates the Node Indexer array with offsets for the\r
375 individual nodes.\r
376\r
377 @param [in] NodeStartOffset Offset from the start of the\r
378 IORT where this node group starts.\r
379 @param [in] NodeList Pointer to SMMUv1/SMMUv2 node list.\r
380 @param [in] NodeCount Count of the SMMUv1/SMMUv2 nodes.\r
381 @param [in, out] NodeIndexer Pointer to the next Node Indexer.\r
382\r
383 @retval Total size of the SMMUv1/SMMUv2 nodes.\r
384**/\r
385STATIC\r
8b2ac43b 386UINT64\r
dfaffc69
SM
387GetSizeofSmmuV1V2Nodes (\r
388 IN CONST UINT32 NodeStartOffset,\r
389 IN CONST CM_ARM_SMMUV1_SMMUV2_NODE * NodeList,\r
390 IN UINT32 NodeCount,\r
391 IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer\r
392 )\r
393{\r
8b2ac43b 394 UINT64 Size;\r
dfaffc69
SM
395\r
396 ASSERT (NodeList != NULL);\r
397\r
398 Size = 0;\r
399 while (NodeCount-- != 0) {\r
400 (*NodeIndexer)->Token = NodeList->Token;\r
401 (*NodeIndexer)->Object = (VOID*)NodeList;\r
8b2ac43b 402 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);\r
dfaffc69
SM
403 DEBUG ((\r
404 DEBUG_INFO,\r
405 "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",\r
406 *NodeIndexer,\r
407 (*NodeIndexer)->Token,\r
408 (*NodeIndexer)->Object,\r
409 (*NodeIndexer)->Offset\r
410 ));\r
411\r
412 Size += GetSmmuV1V2NodeSize (NodeList);\r
413 (*NodeIndexer)++;\r
414 NodeList++;\r
415 }\r
416 return Size;\r
417}\r
418\r
419/** Returns the size of the SMMUv3 node.\r
420\r
421 @param [in] Node Pointer to SMMUv3 node list.\r
422\r
423 @retval Total size of the SMMUv3 nodes.\r
424**/\r
425STATIC\r
426UINT32\r
427GetSmmuV3NodeSize (\r
428 IN CONST CM_ARM_SMMUV3_NODE * Node\r
429 )\r
430{\r
431 ASSERT (Node != NULL);\r
432\r
433 /* Size of SMMU v1/SMMU v2 node +\r
434 Size of ID mapping array\r
435 */\r
8b2ac43b
SM
436 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE) +\r
437 (Node->IdMappingCount *\r
438 sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE)));\r
dfaffc69
SM
439}\r
440\r
441/** Returns the total size required for the SMMUv3 nodes and\r
442 updates the Node Indexer.\r
443\r
444 This function calculates the size required for the node group\r
445 and also populates the Node Indexer array with offsets for the\r
446 individual nodes.\r
447\r
448 @param [in] NodeStartOffset Offset from the start of the\r
449 IORT where this node group starts.\r
450 @param [in] NodeList Pointer to SMMUv3 node list.\r
451 @param [in] NodeCount Count of the SMMUv3 nodes.\r
452 @param [in, out] NodeIndexer Pointer to the next Node Indexer.\r
453\r
454 @retval Total size of the SMMUv3 nodes.\r
455**/\r
456STATIC\r
8b2ac43b 457UINT64\r
dfaffc69
SM
458GetSizeofSmmuV3Nodes (\r
459 IN CONST UINT32 NodeStartOffset,\r
460 IN CONST CM_ARM_SMMUV3_NODE * NodeList,\r
461 IN UINT32 NodeCount,\r
462 IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer\r
463 )\r
464{\r
8b2ac43b 465 UINT64 Size;\r
dfaffc69
SM
466\r
467 ASSERT (NodeList != NULL);\r
468\r
469 Size = 0;\r
470 while (NodeCount-- != 0) {\r
471 (*NodeIndexer)->Token = NodeList->Token;\r
472 (*NodeIndexer)->Object = (VOID*)NodeList;\r
8b2ac43b 473 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);\r
dfaffc69
SM
474 DEBUG ((\r
475 DEBUG_INFO,\r
476 "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",\r
477 *NodeIndexer,\r
478 (*NodeIndexer)->Token,\r
479 (*NodeIndexer)->Object,\r
480 (*NodeIndexer)->Offset\r
481 ));\r
482\r
483 Size += GetSmmuV3NodeSize (NodeList);\r
484 (*NodeIndexer)++;\r
485 NodeList++;\r
486 }\r
487 return Size;\r
488}\r
489\r
490/** Returns the size of the PMCG node.\r
491\r
492 @param [in] Node Pointer to PMCG node.\r
493\r
494 @retval Size of the PMCG node.\r
495**/\r
496STATIC\r
497UINT32\r
498GetPmcgNodeSize (\r
499 IN CONST CM_ARM_PMCG_NODE * Node\r
500 )\r
501{\r
502 ASSERT (Node != NULL);\r
503\r
504 /* Size of PMCG node +\r
505 Size of ID mapping array\r
506 */\r
8b2ac43b
SM
507 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE) +\r
508 (Node->IdMappingCount *\r
509 sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE)));\r
dfaffc69
SM
510}\r
511\r
512/** Returns the total size required for the PMCG nodes and\r
513 updates the Node Indexer.\r
514\r
515 This function calculates the size required for the node group\r
516 and also populates the Node Indexer array with offsets for the\r
517 individual nodes.\r
518\r
519 @param [in] NodeStartOffset Offset from the start of the\r
520 IORT where this node group starts.\r
521 @param [in] NodeList Pointer to PMCG node list.\r
522 @param [in] NodeCount Count of the PMCG nodes.\r
523 @param [in, out] NodeIndexer Pointer to the next Node Indexer.\r
524\r
525 @retval Total size of the PMCG nodes.\r
526**/\r
527STATIC\r
8b2ac43b 528UINT64\r
dfaffc69
SM
529GetSizeofPmcgNodes (\r
530 IN CONST UINT32 NodeStartOffset,\r
531 IN CONST CM_ARM_PMCG_NODE * NodeList,\r
532 IN UINT32 NodeCount,\r
533 IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer\r
534 )\r
535{\r
8b2ac43b 536 UINT64 Size;\r
dfaffc69
SM
537\r
538 ASSERT (NodeList != NULL);\r
539\r
540 Size = 0;\r
541 while (NodeCount-- != 0) {\r
542 (*NodeIndexer)->Token = NodeList->Token;\r
543 (*NodeIndexer)->Object = (VOID*)NodeList;\r
8b2ac43b 544 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);\r
dfaffc69
SM
545 DEBUG ((\r
546 DEBUG_INFO,\r
547 "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",\r
548 *NodeIndexer,\r
549 (*NodeIndexer)->Token,\r
550 (*NodeIndexer)->Object,\r
551 (*NodeIndexer)->Offset\r
552 ));\r
553\r
554 Size += GetPmcgNodeSize (NodeList);\r
555 (*NodeIndexer)++;\r
556 NodeList++;\r
557 }\r
558 return Size;\r
559}\r
560\r
561/** Returns the offset of the Node referenced by the Token.\r
562\r
563 @param [in] NodeIndexer Pointer to node indexer array.\r
564 @param [in] NodeCount Count of the nodes.\r
565 @param [in] Token Reference token for the node.\r
566 @param [out] NodeOffset Offset of the node from the\r
567 start of the IORT table.\r
568\r
569 @retval EFI_SUCCESS Success.\r
570 @retval EFI_NOT_FOUND No matching token reference\r
571 found in node indexer array.\r
572**/\r
573STATIC\r
574EFI_STATUS\r
575GetNodeOffsetReferencedByToken (\r
576 IN IORT_NODE_INDEXER * NodeIndexer,\r
577 IN UINT32 NodeCount,\r
578 IN CM_OBJECT_TOKEN Token,\r
579 OUT UINT32 * NodeOffset\r
580 )\r
581{\r
582 DEBUG ((\r
583 DEBUG_INFO,\r
584 "IORT: Node Indexer: Search Token = %p\n",\r
585 Token\r
586 ));\r
587 while (NodeCount-- != 0) {\r
588 DEBUG ((\r
589 DEBUG_INFO,\r
590 "IORT: Node Indexer: NodeIndexer->Token = %p, Offset = %d\n",\r
591 NodeIndexer->Token,\r
592 NodeIndexer->Offset\r
593 ));\r
594 if (NodeIndexer->Token == Token) {\r
595 *NodeOffset = NodeIndexer->Offset;\r
596 DEBUG ((\r
597 DEBUG_INFO,\r
598 "IORT: Node Indexer: Token = %p, Found\n",\r
599 Token\r
600 ));\r
601 return EFI_SUCCESS;\r
602 }\r
603 NodeIndexer++;\r
604 }\r
605 DEBUG ((\r
606 DEBUG_INFO,\r
607 "IORT: Node Indexer: Token = %p, Not Found\n",\r
608 Token\r
609 ));\r
610 return EFI_NOT_FOUND;\r
611}\r
612\r
613/** Update the Id Mapping Array.\r
614\r
615 This function retrieves the Id Mapping Array object referenced by the\r
616 IdMappingToken and updates the IdMapArray.\r
617\r
618 @param [in] This Pointer to the table Generator.\r
619 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
620 Protocol Interface.\r
621 @param [in] IdMapArray Pointer to an array of Id Mappings.\r
622 @param [in] IdCount Number of Id Mappings.\r
623 @param [in] IdMappingToken Reference Token for retrieving the\r
624 Id Mapping Array object.\r
625\r
626 @retval EFI_SUCCESS Table generated successfully.\r
627 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
628 @retval EFI_NOT_FOUND The required object was not found.\r
629**/\r
630STATIC\r
631EFI_STATUS\r
632AddIdMappingArray (\r
633 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
634 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
635 IN EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray,\r
636 IN UINT32 IdCount,\r
637 IN CONST CM_OBJECT_TOKEN IdMappingToken\r
638 )\r
639{\r
640 EFI_STATUS Status;\r
641 CM_ARM_ID_MAPPING * IdMappings;\r
642 UINT32 IdMappingCount;\r
643 ACPI_IORT_GENERATOR * Generator;\r
644\r
645 ASSERT (IdMapArray != NULL);\r
646\r
647 Generator = (ACPI_IORT_GENERATOR*)This;\r
648\r
649 // Get the Id Mapping Array\r
98a4a7a9 650 Status = GetEArmObjIdMappingArray (\r
dfaffc69
SM
651 CfgMgrProtocol,\r
652 IdMappingToken,\r
653 &IdMappings,\r
654 &IdMappingCount\r
655 );\r
656 if (EFI_ERROR (Status)) {\r
657 DEBUG ((\r
658 DEBUG_ERROR,\r
659 "ERROR: IORT: Failed to get Id Mapping array. Status = %r\n",\r
660 Status\r
661 ));\r
662 return Status;\r
663 }\r
664\r
665 if (IdMappingCount < IdCount) {\r
666 DEBUG ((\r
667 DEBUG_ERROR,\r
668 "ERROR: IORT: Failed to get the required number of Id Mappings.\n"\r
669 ));\r
670 return EFI_NOT_FOUND;\r
671 }\r
672\r
673 // Populate the Id Mapping array\r
674 while (IdCount-- != 0) {\r
675 Status = GetNodeOffsetReferencedByToken (\r
676 Generator->NodeIndexer,\r
677 Generator->IortNodeCount,\r
678 IdMappings->OutputReferenceToken,\r
679 &IdMapArray->OutputReference\r
680 );\r
681 if (EFI_ERROR (Status)) {\r
682 DEBUG ((\r
683 DEBUG_ERROR,\r
684 "ERROR: IORT: Failed to get Output Reference for ITS Identifier array."\r
685 "Reference Token = %p"\r
686 " Status = %r\n",\r
687 IdMappings->OutputReferenceToken,\r
688 Status\r
689 ));\r
690 return Status;\r
691 }\r
692\r
693 IdMapArray->InputBase = IdMappings->InputBase;\r
694 IdMapArray->NumIds = IdMappings->NumIds;\r
695 IdMapArray->OutputBase = IdMappings->OutputBase;\r
696 IdMapArray->Flags = IdMappings->Flags;\r
697\r
698 IdMapArray++;\r
699 IdMappings++;\r
700 } // Id Mapping array\r
701\r
702 return EFI_SUCCESS;\r
703}\r
704\r
705/** Update the ITS Group Node Information.\r
706\r
707 @param [in] This Pointer to the table Generator.\r
708 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
709 Protocol Interface.\r
710 @param [in] Iort Pointer to IORT table structure.\r
711 @param [in] NodesStartOffset Offset for the start of the ITS Group\r
712 Nodes.\r
713 @param [in] NodeList Pointer to an array of ITS Group Node\r
714 Objects.\r
715 @param [in] NodeCount Number of ITS Group Node Objects.\r
716\r
717 @retval EFI_SUCCESS Table generated successfully.\r
718 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
719 @retval EFI_NOT_FOUND The required object was not found.\r
720**/\r
721STATIC\r
722EFI_STATUS\r
723AddItsGroupNodes (\r
724 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
725 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
726 IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,\r
727 IN CONST UINT32 NodesStartOffset,\r
728 IN CONST CM_ARM_ITS_GROUP_NODE * NodeList,\r
729 IN UINT32 NodeCount\r
730 )\r
731{\r
732 EFI_STATUS Status;\r
733 EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE * ItsGroupNode;\r
734 UINT32 * ItsIds;\r
735 CM_ARM_ITS_IDENTIFIER * ItsIdentifier;\r
736 UINT32 ItsIdentifierCount;\r
737 UINT32 IdIndex;\r
8b2ac43b 738 UINT64 NodeLength;\r
dfaffc69
SM
739\r
740 ASSERT (Iort != NULL);\r
741\r
742 ItsGroupNode = (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE*)((UINT8*)Iort +\r
743 NodesStartOffset);\r
744\r
745 while (NodeCount-- != 0) {\r
8b2ac43b
SM
746 NodeLength = GetItsGroupNodeSize (NodeList);\r
747 if (NodeLength > MAX_UINT16) {\r
748 Status = EFI_INVALID_PARAMETER;\r
749 DEBUG ((\r
750 DEBUG_ERROR,\r
751 "ERROR: IORT: ITS Id Array Node length 0x%lx > MAX_UINT16."\r
752 " Status = %r\n",\r
753 NodeLength,\r
754 Status\r
755 ));\r
756 return Status;\r
757 }\r
758\r
dfaffc69
SM
759 // Populate the node header\r
760 ItsGroupNode->Node.Type = EFI_ACPI_IORT_TYPE_ITS_GROUP;\r
8b2ac43b 761 ItsGroupNode->Node.Length = (UINT16)NodeLength;\r
dfaffc69
SM
762 ItsGroupNode->Node.Revision = 0;\r
763 ItsGroupNode->Node.Reserved = EFI_ACPI_RESERVED_DWORD;\r
764 ItsGroupNode->Node.NumIdMappings = 0;\r
765 ItsGroupNode->Node.IdReference = 0;\r
766\r
767 // IORT specific data\r
768 ItsGroupNode->NumItsIdentifiers = NodeList->ItsIdCount;\r
769 ItsIds = (UINT32*)((UINT8*)ItsGroupNode +\r
770 sizeof (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE));\r
771\r
772 Status = GetEArmObjGicItsIdentifierArray (\r
773 CfgMgrProtocol,\r
774 NodeList->ItsIdToken,\r
775 &ItsIdentifier,\r
776 &ItsIdentifierCount\r
777 );\r
778 if (EFI_ERROR (Status)) {\r
779 DEBUG ((\r
780 DEBUG_ERROR,\r
781 "ERROR: IORT: Failed to get ITS Identifier array. Status = %r\n",\r
782 Status\r
783 ));\r
784 return Status;\r
785 }\r
786\r
787 if (ItsIdentifierCount < ItsGroupNode->NumItsIdentifiers) {\r
788 DEBUG ((\r
789 DEBUG_ERROR,\r
790 "ERROR: IORT: Failed to get the required number of ITS Identifiers.\n"\r
791 ));\r
792 return EFI_NOT_FOUND;\r
793 }\r
794\r
795 // Populate the ITS identifier array\r
796 for (IdIndex = 0; IdIndex < ItsGroupNode->NumItsIdentifiers; IdIndex++) {\r
797 ItsIds[IdIndex] = ItsIdentifier[IdIndex].ItsId;\r
798 } // ITS identifier array\r
799\r
800 // Next IORT Group Node\r
801 ItsGroupNode = (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE*)((UINT8*)ItsGroupNode +\r
802 ItsGroupNode->Node.Length);\r
803 NodeList++;\r
804 } // IORT Group Node\r
805\r
806 return EFI_SUCCESS;\r
807}\r
808\r
809/** Update the Named Component Node Information.\r
810\r
811 This function updates the Named Component node information in the IORT\r
812 table.\r
813\r
814 @param [in] This Pointer to the table Generator.\r
815 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
816 Protocol Interface.\r
817 @param [in] Iort Pointer to IORT table structure.\r
818 @param [in] NodesStartOffset Offset for the start of the Named\r
819 Component Nodes.\r
820 @param [in] NodeList Pointer to an array of Named Component\r
821 Node Objects.\r
822 @param [in] NodeCount Number of Named Component Node Objects.\r
823\r
824 @retval EFI_SUCCESS Table generated successfully.\r
825 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
826 @retval EFI_NOT_FOUND The required object was not found.\r
827**/\r
828STATIC\r
829EFI_STATUS\r
830AddNamedComponentNodes (\r
831 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
832 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
833 IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,\r
834 IN CONST UINT32 NodesStartOffset,\r
835 IN CONST CM_ARM_NAMED_COMPONENT_NODE * NodeList,\r
836 IN UINT32 NodeCount\r
837 )\r
838{\r
839 EFI_STATUS Status;\r
840 EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE * NcNode;\r
841 EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray;\r
dfaffc69 842 CHAR8 * ObjectName;\r
8b2ac43b
SM
843 UINTN ObjectNameLength;\r
844 UINT64 NodeLength;\r
dfaffc69
SM
845\r
846 ASSERT (Iort != NULL);\r
847\r
848 NcNode = (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE*)((UINT8*)Iort +\r
849 NodesStartOffset);\r
850\r
851 while (NodeCount-- != 0) {\r
8b2ac43b
SM
852 NodeLength = GetNamedComponentNodeSize (NodeList);\r
853 if (NodeLength > MAX_UINT16) {\r
854 Status = EFI_INVALID_PARAMETER;\r
855 DEBUG ((\r
856 DEBUG_ERROR,\r
857 "ERROR: IORT: Named Component Node length 0x%lx > MAX_UINT16."\r
858 " Status = %r\n",\r
859 NodeLength,\r
860 Status\r
861 ));\r
862 return Status;\r
863 }\r
864\r
dfaffc69
SM
865 // Populate the node header\r
866 NcNode->Node.Type = EFI_ACPI_IORT_TYPE_NAMED_COMP;\r
8b2ac43b 867 NcNode->Node.Length = (UINT16)NodeLength;\r
dfaffc69
SM
868 NcNode->Node.Revision = 2;\r
869 NcNode->Node.Reserved = EFI_ACPI_RESERVED_DWORD;\r
870 NcNode->Node.NumIdMappings = NodeList->IdMappingCount;\r
871\r
8b2ac43b 872 ObjectNameLength = AsciiStrLen (NodeList->ObjectName) + 1;\r
dfaffc69 873 NcNode->Node.IdReference =\r
8b2ac43b
SM
874 (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE) +\r
875 (ALIGN_VALUE (ObjectNameLength, 4)));\r
dfaffc69
SM
876\r
877 // Named Component specific data\r
878 NcNode->Flags = NodeList->Flags;\r
879 NcNode->CacheCoherent = NodeList->CacheCoherent;\r
880 NcNode->AllocationHints = NodeList->AllocationHints;\r
881 NcNode->Reserved = EFI_ACPI_RESERVED_WORD;\r
882 NcNode->MemoryAccessFlags = NodeList->MemoryAccessFlags;\r
883 NcNode->AddressSizeLimit = NodeList->AddressSizeLimit;\r
884\r
885 // Copy the object name\r
886 ObjectName = (CHAR8*)((UINT8*)NcNode +\r
887 sizeof (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE));\r
888 Status = AsciiStrCpyS (\r
889 ObjectName,\r
8b2ac43b 890 ObjectNameLength,\r
dfaffc69
SM
891 NodeList->ObjectName\r
892 );\r
893 if (EFI_ERROR (Status)) {\r
894 DEBUG ((\r
895 DEBUG_ERROR,\r
896 "ERROR: IORT: Failed to copy Object Name. Status = %r\n",\r
897 Status\r
898 ));\r
899 return Status;\r
900 }\r
901\r
902 if ((NodeList->IdMappingCount > 0) &&\r
903 (NodeList->IdMappingToken != CM_NULL_TOKEN)) {\r
904 // Ids for Named Component\r
905 IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE*)((UINT8*)NcNode +\r
906 NcNode->Node.IdReference);\r
907\r
908 Status = AddIdMappingArray (\r
909 This,\r
910 CfgMgrProtocol,\r
911 IdMapArray,\r
912 NodeList->IdMappingCount,\r
913 NodeList->IdMappingToken\r
914 );\r
915 if (EFI_ERROR (Status)) {\r
916 DEBUG ((\r
917 DEBUG_ERROR,\r
918 "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",\r
919 Status\r
920 ));\r
921 return Status;\r
922 }\r
923 }\r
924\r
925 // Next Named Component Node\r
926 NcNode = (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE*)((UINT8*)NcNode +\r
927 NcNode->Node.Length);\r
928 NodeList++;\r
929 } // Named Component Node\r
930\r
931 return EFI_SUCCESS;\r
932}\r
933\r
934/** Update the Root Complex Node Information.\r
935\r
936 This function updates the Root Complex node information in the IORT table.\r
937\r
938 @param [in] This Pointer to the table Generator.\r
939 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
940 Protocol Interface.\r
941 @param [in] Iort Pointer to IORT table structure.\r
942 @param [in] NodesStartOffset Offset for the start of the Root Complex\r
943 Nodes.\r
944 @param [in] NodeList Pointer to an array of Root Complex Node\r
945 Objects.\r
946 @param [in] NodeCount Number of Root Complex Node Objects.\r
947\r
948 @retval EFI_SUCCESS Table generated successfully.\r
949 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
950 @retval EFI_NOT_FOUND The required object was not found.\r
951**/\r
952STATIC\r
953EFI_STATUS\r
954AddRootComplexNodes (\r
955 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
956 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
957 IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,\r
958 IN CONST UINT32 NodesStartOffset,\r
959 IN CONST CM_ARM_ROOT_COMPLEX_NODE * NodeList,\r
960 IN UINT32 NodeCount\r
961 )\r
962{\r
963 EFI_STATUS Status;\r
964 EFI_ACPI_6_0_IO_REMAPPING_RC_NODE * RcNode;\r
965 EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray;\r
8b2ac43b 966 UINT64 NodeLength;\r
dfaffc69
SM
967\r
968 ASSERT (Iort != NULL);\r
969\r
970 RcNode = (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE*)((UINT8*)Iort +\r
971 NodesStartOffset);\r
972\r
973 while (NodeCount-- != 0) {\r
8b2ac43b
SM
974 NodeLength = GetRootComplexNodeSize (NodeList);\r
975 if (NodeLength > MAX_UINT16) {\r
976 Status = EFI_INVALID_PARAMETER;\r
977 DEBUG ((\r
978 DEBUG_ERROR,\r
979 "ERROR: IORT: Root Complex Node length 0x%lx > MAX_UINT16."\r
980 " Status = %r\n",\r
981 NodeLength,\r
982 Status\r
983 ));\r
984 return Status;\r
985 }\r
986\r
dfaffc69
SM
987 // Populate the node header\r
988 RcNode->Node.Type = EFI_ACPI_IORT_TYPE_ROOT_COMPLEX;\r
8b2ac43b 989 RcNode->Node.Length = (UINT16)NodeLength;\r
dfaffc69
SM
990 RcNode->Node.Revision = 1;\r
991 RcNode->Node.Reserved = EFI_ACPI_RESERVED_DWORD;\r
992 RcNode->Node.NumIdMappings = NodeList->IdMappingCount;\r
993 RcNode->Node.IdReference = sizeof (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE);\r
994\r
995 // Root Complex specific data\r
996 RcNode->CacheCoherent = NodeList->CacheCoherent;\r
997 RcNode->AllocationHints = NodeList->AllocationHints;\r
998 RcNode->Reserved = EFI_ACPI_RESERVED_WORD;\r
999 RcNode->MemoryAccessFlags = NodeList->MemoryAccessFlags;\r
1000 RcNode->AtsAttribute = NodeList->AtsAttribute;\r
1001 RcNode->PciSegmentNumber = NodeList->PciSegmentNumber;\r
1002 RcNode->MemoryAddressSize = NodeList->MemoryAddressSize;\r
1003 RcNode->Reserved1[0] = EFI_ACPI_RESERVED_BYTE;\r
1004 RcNode->Reserved1[1] = EFI_ACPI_RESERVED_BYTE;\r
1005 RcNode->Reserved1[2] = EFI_ACPI_RESERVED_BYTE;\r
1006\r
1007 if ((NodeList->IdMappingCount > 0) &&\r
1008 (NodeList->IdMappingToken != CM_NULL_TOKEN)) {\r
1009 // Ids for Root Complex\r
1010 IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE*)((UINT8*)RcNode +\r
1011 RcNode->Node.IdReference);\r
1012 Status = AddIdMappingArray (\r
1013 This,\r
1014 CfgMgrProtocol,\r
1015 IdMapArray,\r
1016 NodeList->IdMappingCount,\r
1017 NodeList->IdMappingToken\r
1018 );\r
1019 if (EFI_ERROR (Status)) {\r
1020 DEBUG ((\r
1021 DEBUG_ERROR,\r
1022 "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",\r
1023 Status\r
1024 ));\r
1025 return Status;\r
1026 }\r
1027 }\r
1028\r
1029 // Next Root Complex Node\r
1030 RcNode = (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE*)((UINT8*)RcNode +\r
1031 RcNode->Node.Length);\r
1032 NodeList++;\r
1033 } // Root Complex Node\r
1034\r
1035 return EFI_SUCCESS;\r
1036}\r
1037\r
1038/** Update the SMMU Interrupt Array.\r
1039\r
1040 This function retrieves the InterruptArray object referenced by the\r
1041 InterruptToken and updates the SMMU InterruptArray.\r
1042\r
1043 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
1044 Protocol Interface.\r
1045 @param [in, out] InterruptArray Pointer to an array of Interrupts.\r
1046 @param [in] InterruptCount Number of entries in the InterruptArray.\r
1047 @param [in] InterruptToken Reference Token for retrieving the SMMU\r
1048 InterruptArray object.\r
1049\r
1050 @retval EFI_SUCCESS Table generated successfully.\r
1051 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
1052 @retval EFI_NOT_FOUND The required object was not found.\r
1053**/\r
1054STATIC\r
1055EFI_STATUS\r
1056AddSmmuInterrruptArray (\r
1057 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
1058 IN OUT EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT * InterruptArray,\r
1059 IN UINT32 InterruptCount,\r
1060 IN CONST CM_OBJECT_TOKEN InterruptToken\r
1061 )\r
1062{\r
1063 EFI_STATUS Status;\r
1064 CM_ARM_SMMU_INTERRUPT * SmmuInterrupt;\r
1065 UINT32 SmmuInterruptCount;\r
1066\r
1067 ASSERT (InterruptArray != NULL);\r
1068\r
1069 // Get the SMMU Interrupt Array\r
1070 Status = GetEArmObjSmmuInterruptArray (\r
1071 CfgMgrProtocol,\r
1072 InterruptToken,\r
1073 &SmmuInterrupt,\r
1074 &SmmuInterruptCount\r
1075 );\r
1076 if (EFI_ERROR (Status)) {\r
1077 DEBUG ((\r
1078 DEBUG_ERROR,\r
1079 "ERROR: IORT: Failed to get SMMU Interrupt array. Status = %r\n",\r
1080 Status\r
1081 ));\r
1082 return Status;\r
1083 }\r
1084\r
1085 if (SmmuInterruptCount < InterruptCount) {\r
1086 DEBUG ((\r
1087 DEBUG_ERROR,\r
1088 "ERROR: IORT: Failed to get the required number of SMMU Interrupts.\n"\r
1089 ));\r
1090 return EFI_NOT_FOUND;\r
1091 }\r
1092\r
1093 // Populate the Id Mapping array\r
1094 while (InterruptCount-- != 0) {\r
1095 InterruptArray->Interrupt = SmmuInterrupt->Interrupt;\r
1096 InterruptArray->InterruptFlags = SmmuInterrupt->Flags;\r
1097 InterruptArray++;\r
1098 SmmuInterrupt++;\r
1099 } // Id Mapping array\r
1100\r
1101 return EFI_SUCCESS;\r
1102}\r
1103\r
1104/** Update the SMMU v1/v2 Node Information.\r
1105\r
1106 @param [in] This Pointer to the table Generator.\r
1107 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
1108 Protocol Interface.\r
1109 @param [in] Iort Pointer to IORT table structure.\r
1110 @param [in] NodesStartOffset Offset for the start of the SMMU v1/v2\r
1111 Nodes.\r
1112 @param [in] NodeList Pointer to an array of SMMU v1/v2 Node\r
1113 Objects.\r
1114 @param [in] NodeCount Number of SMMU v1/v2 Node Objects.\r
1115\r
1116 @retval EFI_SUCCESS Table generated successfully.\r
1117 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
1118 @retval EFI_NOT_FOUND The required object was not found.\r
1119**/\r
1120STATIC\r
1121EFI_STATUS\r
1122AddSmmuV1V2Nodes (\r
1123 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
1124 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
1125 IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,\r
1126 IN CONST UINT32 NodesStartOffset,\r
1127 IN CONST CM_ARM_SMMUV1_SMMUV2_NODE * NodeList,\r
1128 IN UINT32 NodeCount\r
1129 )\r
1130{\r
1131 EFI_STATUS Status;\r
1132 EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE * SmmuNode;\r
1133 EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray;\r
1134\r
1135 EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT * ContextInterruptArray;\r
1136 EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT * PmuInterruptArray;\r
8b2ac43b 1137 UINT64 NodeLength;\r
dfaffc69
SM
1138\r
1139 ASSERT (Iort != NULL);\r
1140\r
1141 SmmuNode = (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE*)((UINT8*)Iort +\r
1142 NodesStartOffset);\r
1143\r
1144 while (NodeCount-- != 0) {\r
8b2ac43b
SM
1145 NodeLength = GetSmmuV1V2NodeSize (NodeList);\r
1146 if (NodeLength > MAX_UINT16) {\r
1147 Status = EFI_INVALID_PARAMETER;\r
1148 DEBUG ((\r
1149 DEBUG_ERROR,\r
1150 "ERROR: IORT: SMMU V1/V2 Node length 0x%lx > MAX_UINT16. Status = %r\n",\r
1151 NodeLength,\r
1152 Status\r
1153 ));\r
1154 return Status;\r
1155 }\r
1156\r
dfaffc69
SM
1157 // Populate the node header\r
1158 SmmuNode->Node.Type = EFI_ACPI_IORT_TYPE_SMMUv1v2;\r
8b2ac43b 1159 SmmuNode->Node.Length = (UINT16)NodeLength;\r
dfaffc69
SM
1160 SmmuNode->Node.Revision = 0;\r
1161 SmmuNode->Node.Reserved = EFI_ACPI_RESERVED_DWORD;\r
1162 SmmuNode->Node.NumIdMappings = NodeList->IdMappingCount;\r
1163 SmmuNode->Node.IdReference = sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE) +\r
1164 (NodeList->ContextInterruptCount *\r
1165 sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT)) +\r
1166 (NodeList->PmuInterruptCount *\r
1167 sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT));\r
1168\r
1169 // SMMU v1/v2 specific data\r
1170 SmmuNode->Base = NodeList->BaseAddress;\r
1171 SmmuNode->Span = NodeList->Span;\r
1172 SmmuNode->Model = NodeList->Model;\r
1173 SmmuNode->Flags = NodeList->Flags;\r
1174\r
1175 // Reference to Global Interrupt Array\r
1176 SmmuNode->GlobalInterruptArrayRef =\r
1177 OFFSET_OF (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE, SMMU_NSgIrpt);\r
1178\r
1179 // Context Interrupt\r
1180 SmmuNode->NumContextInterrupts = NodeList->ContextInterruptCount;\r
1181 SmmuNode->ContextInterruptArrayRef =\r
1182 sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE);\r
1183 ContextInterruptArray =\r
1184 (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT*)((UINT8*)SmmuNode +\r
1185 sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE));\r
1186\r
1187 // PMU Interrupt\r
1188 SmmuNode->NumPmuInterrupts = NodeList->PmuInterruptCount;\r
1189 SmmuNode->PmuInterruptArrayRef = SmmuNode->ContextInterruptArrayRef +\r
1190 (NodeList->ContextInterruptCount *\r
1191 sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT));\r
1192 PmuInterruptArray =\r
1193 (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT*)((UINT8*)SmmuNode +\r
1194 SmmuNode->PmuInterruptArrayRef);\r
1195\r
1196 SmmuNode->SMMU_NSgIrpt = NodeList->SMMU_NSgIrpt;\r
1197 SmmuNode->SMMU_NSgIrptFlags = NodeList->SMMU_NSgIrptFlags;\r
1198 SmmuNode->SMMU_NSgCfgIrpt = NodeList->SMMU_NSgCfgIrpt;\r
1199 SmmuNode->SMMU_NSgCfgIrptFlags = NodeList->SMMU_NSgCfgIrptFlags;\r
1200\r
1201 // Add Context Interrupt Array\r
1202 Status = AddSmmuInterrruptArray (\r
1203 CfgMgrProtocol,\r
1204 ContextInterruptArray,\r
1205 SmmuNode->NumContextInterrupts,\r
1206 NodeList->ContextInterruptToken\r
1207 );\r
1208 if (EFI_ERROR (Status)) {\r
1209 DEBUG ((\r
1210 DEBUG_ERROR,\r
1211 "ERROR: IORT: Failed to Context Interrupt Array. Status = %r\n",\r
1212 Status\r
1213 ));\r
1214 return Status;\r
1215 }\r
1216\r
1217 // Add PMU Interrupt Array\r
1218 if ((SmmuNode->NumPmuInterrupts > 0) &&\r
1219 (NodeList->PmuInterruptToken != CM_NULL_TOKEN)) {\r
1220 Status = AddSmmuInterrruptArray (\r
1221 CfgMgrProtocol,\r
1222 PmuInterruptArray,\r
1223 SmmuNode->NumPmuInterrupts,\r
1224 NodeList->PmuInterruptToken\r
1225 );\r
1226 if (EFI_ERROR (Status)) {\r
1227 DEBUG ((\r
1228 DEBUG_ERROR,\r
1229 "ERROR: IORT: Failed to PMU Interrupt Array. Status = %r\n",\r
1230 Status\r
1231 ));\r
1232 return Status;\r
1233 }\r
1234 }\r
1235\r
1236 if ((NodeList->IdMappingCount > 0) &&\r
1237 (NodeList->IdMappingToken != CM_NULL_TOKEN)) {\r
1238 // Ids for SMMU v1/v2 Node\r
1239 IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE*)((UINT8*)SmmuNode +\r
1240 SmmuNode->Node.IdReference);\r
1241 Status = AddIdMappingArray (\r
1242 This,\r
1243 CfgMgrProtocol,\r
1244 IdMapArray,\r
1245 NodeList->IdMappingCount,\r
1246 NodeList->IdMappingToken\r
1247 );\r
1248 if (EFI_ERROR (Status)) {\r
1249 DEBUG ((\r
1250 DEBUG_ERROR,\r
1251 "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",\r
1252 Status\r
1253 ));\r
1254 return Status;\r
1255 }\r
1256 }\r
1257 // Next SMMU v1/v2 Node\r
1258 SmmuNode = (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE*)((UINT8*)SmmuNode +\r
1259 SmmuNode->Node.Length);\r
1260 NodeList++;\r
1261 } // SMMU v1/v2 Node\r
1262\r
1263 return EFI_SUCCESS;\r
1264}\r
1265\r
1266/** Update the SMMUv3 Node Information.\r
1267\r
1268 This function updates the SMMUv3 node information in the IORT table.\r
1269\r
1270 @param [in] This Pointer to the table Generator.\r
1271 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
1272 Protocol Interface.\r
1273 @param [in] Iort Pointer to IORT table structure.\r
1274 @param [in] NodesStartOffset Offset for the start of the SMMUv3 Nodes.\r
1275 @param [in] NodeList Pointer to an array of SMMUv3 Node Objects.\r
1276 @param [in] NodeCount Number of SMMUv3 Node Objects.\r
1277\r
1278 @retval EFI_SUCCESS Table generated successfully.\r
1279 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
1280 @retval EFI_NOT_FOUND The required object was not found.\r
1281**/\r
1282STATIC\r
1283EFI_STATUS\r
1284AddSmmuV3Nodes (\r
1285 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
1286 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
1287 IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,\r
1288 IN CONST UINT32 NodesStartOffset,\r
1289 IN CONST CM_ARM_SMMUV3_NODE * NodeList,\r
1290 IN UINT32 NodeCount\r
1291 )\r
1292{\r
1293 EFI_STATUS Status;\r
1294 EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE * SmmuV3Node;\r
1295 EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray;\r
8b2ac43b 1296 UINT64 NodeLength;\r
dfaffc69
SM
1297\r
1298 ASSERT (Iort != NULL);\r
1299\r
1300 SmmuV3Node = (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE*)((UINT8*)Iort +\r
1301 NodesStartOffset);\r
1302\r
1303 while (NodeCount-- != 0) {\r
8b2ac43b
SM
1304 NodeLength = GetSmmuV3NodeSize (NodeList);\r
1305 if (NodeLength > MAX_UINT16) {\r
1306 Status = EFI_INVALID_PARAMETER;\r
1307 DEBUG ((\r
1308 DEBUG_ERROR,\r
1309 "ERROR: IORT: SMMU V3 Node length 0x%lx > MAX_UINT16. Status = %r\n",\r
1310 NodeLength,\r
1311 Status\r
1312 ));\r
1313 return Status;\r
1314 }\r
1315\r
dfaffc69
SM
1316 // Populate the node header\r
1317 SmmuV3Node->Node.Type = EFI_ACPI_IORT_TYPE_SMMUv3;\r
8b2ac43b 1318 SmmuV3Node->Node.Length = (UINT16)NodeLength;\r
dfaffc69
SM
1319 SmmuV3Node->Node.Revision = 2;\r
1320 SmmuV3Node->Node.Reserved = EFI_ACPI_RESERVED_DWORD;\r
1321 SmmuV3Node->Node.NumIdMappings = NodeList->IdMappingCount;\r
1322 SmmuV3Node->Node.IdReference =\r
1323 sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE);\r
1324\r
1325 // SMMUv3 specific data\r
1326 SmmuV3Node->Base = NodeList->BaseAddress;\r
1327 SmmuV3Node->Flags = NodeList->Flags;\r
1328 SmmuV3Node->Reserved = EFI_ACPI_RESERVED_WORD;\r
1329 SmmuV3Node->VatosAddress = NodeList->VatosAddress;\r
1330 SmmuV3Node->Model = NodeList->Model;\r
1331 SmmuV3Node->Event = NodeList->EventInterrupt;\r
1332 SmmuV3Node->Pri = NodeList->PriInterrupt;\r
1333 SmmuV3Node->Gerr = NodeList->GerrInterrupt;\r
1334 SmmuV3Node->Sync = NodeList->SyncInterrupt;\r
1335\r
1336 if ((SmmuV3Node->Flags & EFI_ACPI_IORT_SMMUv3_FLAG_PROXIMITY_DOMAIN) != 0) {\r
1337 // The Proximity Domain Valid flag is set to 1\r
1338 SmmuV3Node->ProximityDomain = NodeList->ProximityDomain;\r
1339 } else {\r
1340 SmmuV3Node->ProximityDomain = 0;\r
1341 }\r
1342\r
1343 if ((SmmuV3Node->Event != 0) && (SmmuV3Node->Pri != 0) &&\r
1344 (SmmuV3Node->Gerr != 0) && (SmmuV3Node->Sync != 0)) {\r
1345 // If all the SMMU control interrupts are GSIV based,\r
1346 // the DeviceID mapping index field is ignored.\r
1347 SmmuV3Node->DeviceIdMappingIndex = 0;\r
1348 } else {\r
1349 SmmuV3Node->DeviceIdMappingIndex = NodeList->DeviceIdMappingIndex;\r
1350 }\r
1351\r
1352 if ((NodeList->IdMappingCount > 0) &&\r
1353 (NodeList->IdMappingToken != CM_NULL_TOKEN)) {\r
1354 // Ids for SMMUv3 node\r
1355 IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE*)((UINT8*)SmmuV3Node +\r
1356 SmmuV3Node->Node.IdReference);\r
1357 Status = AddIdMappingArray (\r
1358 This,\r
1359 CfgMgrProtocol,\r
1360 IdMapArray,\r
1361 NodeList->IdMappingCount,\r
1362 NodeList->IdMappingToken\r
1363 );\r
1364 if (EFI_ERROR (Status)) {\r
1365 DEBUG ((\r
1366 DEBUG_ERROR,\r
1367 "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",\r
1368 Status\r
1369 ));\r
1370 return Status;\r
1371 }\r
1372 }\r
1373\r
1374 // Next SMMUv3 Node\r
1375 SmmuV3Node = (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE*)((UINT8*)SmmuV3Node +\r
1376 SmmuV3Node->Node.Length);\r
1377 NodeList++;\r
1378 } // SMMUv3 Node\r
1379\r
1380 return EFI_SUCCESS;\r
1381}\r
1382\r
1383/** Update the PMCG Node Information.\r
1384\r
1385 This function updates the PMCG node information in the IORT table.\r
1386\r
1387 @param [in] This Pointer to the table Generator.\r
1388 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
1389 Protocol Interface.\r
1390 @param [in] Iort Pointer to IORT table structure.\r
1391 @param [in] NodesStartOffset Offset for the start of the PMCG Nodes.\r
1392 @param [in] NodeList Pointer to an array of PMCG Node Objects.\r
1393 @param [in] NodeCount Number of PMCG Node Objects.\r
1394\r
1395 @retval EFI_SUCCESS Table generated successfully.\r
1396 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
1397 @retval EFI_NOT_FOUND The required object was not found.\r
1398**/\r
1399STATIC\r
1400EFI_STATUS\r
1401AddPmcgNodes (\r
1402 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
1403 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
1404 IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,\r
1405 IN CONST UINT32 NodesStartOffset,\r
1406 IN CONST CM_ARM_PMCG_NODE * NodeList,\r
1407 IN UINT32 NodeCount\r
1408 )\r
1409{\r
1410 EFI_STATUS Status;\r
1411 EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE * PmcgNode;\r
1412 EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray;\r
1413 ACPI_IORT_GENERATOR * Generator;\r
8b2ac43b 1414 UINT64 NodeLength;\r
dfaffc69
SM
1415\r
1416 ASSERT (Iort != NULL);\r
1417\r
1418 Generator = (ACPI_IORT_GENERATOR*)This;\r
1419 PmcgNode = (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE*)((UINT8*)Iort +\r
1420 NodesStartOffset);\r
1421\r
1422 while (NodeCount-- != 0) {\r
8b2ac43b
SM
1423 NodeLength = GetPmcgNodeSize (NodeList);\r
1424 if (NodeLength > MAX_UINT16) {\r
1425 Status = EFI_INVALID_PARAMETER;\r
1426 DEBUG ((\r
1427 DEBUG_ERROR,\r
1428 "ERROR: IORT: PMCG Node length 0x%lx > MAX_UINT16. Status = %r\n",\r
1429 NodeLength,\r
1430 Status\r
1431 ));\r
1432 return Status;\r
1433 }\r
1434\r
dfaffc69
SM
1435 // Populate the node header\r
1436 PmcgNode->Node.Type = EFI_ACPI_IORT_TYPE_PMCG;\r
8b2ac43b 1437 PmcgNode->Node.Length = (UINT16)NodeLength;\r
dfaffc69
SM
1438 PmcgNode->Node.Revision = 1;\r
1439 PmcgNode->Node.Reserved = EFI_ACPI_RESERVED_DWORD;\r
1440 PmcgNode->Node.NumIdMappings = NodeList->IdMappingCount;\r
1441 PmcgNode->Node.IdReference = sizeof (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE);\r
1442\r
1443 // PMCG specific data\r
1444 PmcgNode->Base = NodeList->BaseAddress;\r
1445 PmcgNode->OverflowInterruptGsiv = NodeList->OverflowInterrupt;\r
1446 PmcgNode->Page1Base = NodeList->Page1BaseAddress;\r
1447\r
1448 Status = GetNodeOffsetReferencedByToken (\r
1449 Generator->NodeIndexer,\r
1450 Generator->IortNodeCount,\r
1451 NodeList->ReferenceToken,\r
1452 &PmcgNode->NodeReference\r
1453 );\r
1454 if (EFI_ERROR (Status)) {\r
1455 DEBUG ((\r
1456 DEBUG_ERROR,\r
1457 "ERROR: IORT: Failed to get Output Reference for PMCG Node."\r
1458 "Reference Token = %p"\r
1459 " Status = %r\n",\r
1460 NodeList->ReferenceToken,\r
1461 Status\r
1462 ));\r
1463 return Status;\r
1464 }\r
1465\r
1466 if ((NodeList->IdMappingCount > 0) &&\r
1467 (NodeList->IdMappingToken != CM_NULL_TOKEN)) {\r
1468 // Ids for PMCG node\r
1469 IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE*)((UINT8*)PmcgNode +\r
1470 PmcgNode->Node.IdReference);\r
1471\r
1472 Status = AddIdMappingArray (\r
1473 This,\r
1474 CfgMgrProtocol,\r
1475 IdMapArray,\r
1476 NodeList->IdMappingCount,\r
1477 NodeList->IdMappingToken\r
1478 );\r
1479 if (EFI_ERROR (Status)) {\r
1480 DEBUG ((\r
1481 DEBUG_ERROR,\r
1482 "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",\r
1483 Status\r
1484 ));\r
1485 return Status;\r
1486 }\r
1487 }\r
1488\r
1489 // Next PMCG Node\r
1490 PmcgNode = (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE*)((UINT8*)PmcgNode +\r
1491 PmcgNode->Node.Length);\r
1492 NodeList++;\r
1493 } // PMCG Node\r
1494\r
1495 return EFI_SUCCESS;\r
1496}\r
1497\r
1498/** Construct the IORT ACPI table.\r
1499\r
1500 This function invokes the Configuration Manager protocol interface\r
1501 to get the required hardware information for generating the ACPI\r
1502 table.\r
1503\r
1504 If this function allocates any resources then they must be freed\r
1505 in the FreeXXXXTableResources function.\r
1506\r
1507 @param [in] This Pointer to the table generator.\r
1508 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
1509 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
1510 Protocol Interface.\r
1511 @param [out] Table Pointer to the constructed ACPI Table.\r
1512\r
1513 @retval EFI_SUCCESS Table generated successfully.\r
1514 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
1515 @retval EFI_NOT_FOUND The required object was not found.\r
1516 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
1517 Manager is less than the Object size for the\r
1518 requested object.\r
1519**/\r
1520STATIC\r
1521EFI_STATUS\r
1522EFIAPI\r
1523BuildIortTable (\r
1524 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
1525 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
1526 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
1527 OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
1528 )\r
1529{\r
1530 EFI_STATUS Status;\r
dfaffc69 1531\r
8b2ac43b
SM
1532 UINT64 TableSize;\r
1533 UINT64 NodeSize;\r
1534\r
1535 UINT32 IortNodeCount;\r
dfaffc69
SM
1536 UINT32 ItsGroupNodeCount;\r
1537 UINT32 NamedComponentNodeCount;\r
1538 UINT32 RootComplexNodeCount;\r
1539 UINT32 SmmuV1V2NodeCount;\r
1540 UINT32 SmmuV3NodeCount;\r
1541 UINT32 PmcgNodeCount;\r
1542\r
1543 UINT32 ItsGroupOffset;\r
1544 UINT32 NamedComponentOffset;\r
1545 UINT32 RootComplexOffset;\r
1546 UINT32 SmmuV1V2Offset;\r
1547 UINT32 SmmuV3Offset;\r
1548 UINT32 PmcgOffset;\r
1549\r
1550 CM_ARM_ITS_GROUP_NODE * ItsGroupNodeList;\r
1551 CM_ARM_NAMED_COMPONENT_NODE * NamedComponentNodeList;\r
1552 CM_ARM_ROOT_COMPLEX_NODE * RootComplexNodeList;\r
1553 CM_ARM_SMMUV1_SMMUV2_NODE * SmmuV1V2NodeList;\r
1554 CM_ARM_SMMUV3_NODE * SmmuV3NodeList;\r
1555 CM_ARM_PMCG_NODE * PmcgNodeList;\r
1556\r
1557 EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort;\r
1558 IORT_NODE_INDEXER * NodeIndexer;\r
1559 ACPI_IORT_GENERATOR * Generator;\r
1560\r
1561 ASSERT (This != NULL);\r
1562 ASSERT (AcpiTableInfo != NULL);\r
1563 ASSERT (CfgMgrProtocol != NULL);\r
1564 ASSERT (Table != NULL);\r
1565 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
1566 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
1567\r
1568 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
1569 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {\r
1570 DEBUG ((\r
1571 DEBUG_ERROR,\r
1572 "ERROR: IORT: Requested table revision = %d, is not supported."\r
1573 "Supported table revision: Minimum = %d, Maximum = %d\n",\r
1574 AcpiTableInfo->AcpiTableRevision,\r
1575 This->MinAcpiTableRevision,\r
1576 This->AcpiTableRevision\r
1577 ));\r
1578 return EFI_INVALID_PARAMETER;\r
1579 }\r
1580\r
1581 Generator = (ACPI_IORT_GENERATOR*)This;\r
1582 *Table = NULL;\r
1583\r
1584 // Get the ITS group node info\r
1585 Status = GetEArmObjItsGroup (\r
1586 CfgMgrProtocol,\r
1587 CM_NULL_TOKEN,\r
1588 &ItsGroupNodeList,\r
1589 &ItsGroupNodeCount\r
1590 );\r
1591 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
1592 DEBUG ((\r
1593 DEBUG_ERROR,\r
1594 "ERROR: IORT: Failed to get ITS Group Node Info. Status = %r\n",\r
1595 Status\r
1596 ));\r
1597 goto error_handler;\r
1598 }\r
1599\r
1600 // Add the ITS group node count\r
1601 IortNodeCount = ItsGroupNodeCount;\r
1602\r
1603 // Get the Named component node info\r
1604 Status = GetEArmObjNamedComponent (\r
1605 CfgMgrProtocol,\r
1606 CM_NULL_TOKEN,\r
1607 &NamedComponentNodeList,\r
1608 &NamedComponentNodeCount\r
1609 );\r
1610 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
1611 DEBUG ((\r
1612 DEBUG_ERROR,\r
1613 "ERROR: IORT: Failed to get Named Component Node Info. Status = %r\n",\r
1614 Status\r
1615 ));\r
1616 goto error_handler;\r
1617 }\r
1618\r
1619 // Add the Named Component group count\r
1620 IortNodeCount += NamedComponentNodeCount;\r
1621\r
1622 // Get the Root complex node info\r
1623 Status = GetEArmObjRootComplex (\r
1624 CfgMgrProtocol,\r
1625 CM_NULL_TOKEN,\r
1626 &RootComplexNodeList,\r
1627 &RootComplexNodeCount\r
1628 );\r
1629 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
1630 DEBUG ((\r
1631 DEBUG_ERROR,\r
1632 "ERROR: IORT: Failed to get Root Complex Node Info. Status = %r\n",\r
1633 Status\r
1634 ));\r
1635 goto error_handler;\r
1636 }\r
1637\r
1638 // Add the Root Complex node count\r
1639 IortNodeCount += RootComplexNodeCount;\r
1640\r
1641 // Get the SMMU v1/v2 node info\r
1642 Status = GetEArmObjSmmuV1SmmuV2 (\r
1643 CfgMgrProtocol,\r
1644 CM_NULL_TOKEN,\r
1645 &SmmuV1V2NodeList,\r
1646 &SmmuV1V2NodeCount\r
1647 );\r
1648 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
1649 DEBUG ((\r
1650 DEBUG_ERROR,\r
1651 "ERROR: IORT: Failed to get SMMUv1/SMMUv2 Node Info. Status = %r\n",\r
1652 Status\r
1653 ));\r
1654 goto error_handler;\r
1655 }\r
1656\r
1657 // Add the SMMU v1/v2 node count\r
1658 IortNodeCount += SmmuV1V2NodeCount;\r
1659\r
1660 // Get the SMMUv3 node info\r
1661 Status = GetEArmObjSmmuV3 (\r
1662 CfgMgrProtocol,\r
1663 CM_NULL_TOKEN,\r
1664 &SmmuV3NodeList,\r
1665 &SmmuV3NodeCount\r
1666 );\r
1667 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
1668 DEBUG ((\r
1669 DEBUG_ERROR,\r
1670 "ERROR: IORT: Failed to get SMMUv3 Node Info. Status = %r\n",\r
1671 Status\r
1672 ));\r
1673 goto error_handler;\r
1674 }\r
1675\r
1676 // Add the SMMUv3 node count\r
1677 IortNodeCount += SmmuV3NodeCount;\r
1678\r
1679 // Get the PMCG node info\r
1680 Status = GetEArmObjPmcg (\r
1681 CfgMgrProtocol,\r
1682 CM_NULL_TOKEN,\r
1683 &PmcgNodeList,\r
1684 &PmcgNodeCount\r
1685 );\r
1686 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
1687 DEBUG ((\r
1688 DEBUG_ERROR,\r
1689 "ERROR: IORT: Failed to get PMCG Node Info. Status = %r\n",\r
1690 Status\r
1691 ));\r
1692 goto error_handler;\r
1693 }\r
1694\r
1695 // Add the PMCG node count\r
1696 IortNodeCount += PmcgNodeCount;\r
1697\r
1698 // Allocate Node Indexer array\r
1699 NodeIndexer = (IORT_NODE_INDEXER*)AllocateZeroPool (\r
1700 (sizeof (IORT_NODE_INDEXER) *\r
1701 IortNodeCount)\r
1702 );\r
1703 if (NodeIndexer == NULL) {\r
1704 Status = EFI_OUT_OF_RESOURCES;\r
1705 DEBUG ((\r
1706 DEBUG_ERROR,\r
1707 "ERROR: IORT: Failed to allocate memory for Node Indexer" \\r
1708 " Status = %r\n",\r
1709 Status\r
1710 ));\r
1711 goto error_handler;\r
1712 }\r
1713\r
1714 DEBUG ((DEBUG_INFO, "INFO: NodeIndexer = %p\n", NodeIndexer));\r
1715 Generator->IortNodeCount = IortNodeCount;\r
1716 Generator->NodeIndexer = NodeIndexer;\r
1717\r
1718 // Calculate the size of the IORT table\r
1719 TableSize = sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE);\r
1720\r
1721 // ITS Group Nodes\r
1722 if (ItsGroupNodeCount > 0) {\r
8b2ac43b 1723 ItsGroupOffset = (UINT32)TableSize;\r
dfaffc69 1724 // Size of ITS Group node list.\r
8b2ac43b
SM
1725 NodeSize = GetSizeofItsGroupNodes (\r
1726 ItsGroupOffset,\r
1727 ItsGroupNodeList,\r
1728 ItsGroupNodeCount,\r
1729 &NodeIndexer\r
1730 );\r
1731 if (NodeSize > MAX_UINT32) {\r
1732 Status = EFI_INVALID_PARAMETER;\r
1733 DEBUG ((\r
1734 DEBUG_ERROR,\r
1735 "ERROR: IORT: Invalid Size of Group Nodes. Status = %r\n",\r
1736 Status\r
1737 ));\r
1738 goto error_handler;\r
1739 }\r
1740 TableSize += NodeSize;\r
dfaffc69
SM
1741 }\r
1742\r
1743 // Named Component Nodes\r
1744 if (NamedComponentNodeCount > 0) {\r
8b2ac43b 1745 NamedComponentOffset = (UINT32)TableSize;\r
dfaffc69 1746 // Size of Named Component node list.\r
8b2ac43b
SM
1747 NodeSize = GetSizeofNamedComponentNodes (\r
1748 NamedComponentOffset,\r
1749 NamedComponentNodeList,\r
1750 NamedComponentNodeCount,\r
1751 &NodeIndexer\r
1752 );\r
1753 if (NodeSize > MAX_UINT32) {\r
1754 Status = EFI_INVALID_PARAMETER;\r
1755 DEBUG ((\r
1756 DEBUG_ERROR,\r
1757 "ERROR: IORT: Invalid Size of Named Component Nodes. Status = %r\n",\r
1758 Status\r
1759 ));\r
1760 goto error_handler;\r
1761 }\r
1762 TableSize += NodeSize;\r
dfaffc69
SM
1763 }\r
1764\r
1765 // Root Complex Nodes\r
1766 if (RootComplexNodeCount > 0) {\r
8b2ac43b 1767 RootComplexOffset = (UINT32)TableSize;\r
dfaffc69 1768 // Size of Root Complex node list.\r
8b2ac43b
SM
1769 NodeSize = GetSizeofRootComplexNodes (\r
1770 RootComplexOffset,\r
1771 RootComplexNodeList,\r
1772 RootComplexNodeCount,\r
1773 &NodeIndexer\r
1774 );\r
1775 if (NodeSize > MAX_UINT32) {\r
1776 Status = EFI_INVALID_PARAMETER;\r
1777 DEBUG ((\r
1778 DEBUG_ERROR,\r
1779 "ERROR: IORT: Invalid Size of Root Complex Nodes. Status = %r\n",\r
1780 Status\r
1781 ));\r
1782 goto error_handler;\r
1783 }\r
1784 TableSize += NodeSize;\r
dfaffc69
SM
1785 }\r
1786\r
1787 // SMMUv1/SMMUv2 Nodes\r
1788 if (SmmuV1V2NodeCount > 0) {\r
8b2ac43b 1789 SmmuV1V2Offset = (UINT32)TableSize;\r
dfaffc69 1790 // Size of SMMUv1/SMMUv2 node list.\r
8b2ac43b
SM
1791 NodeSize = GetSizeofSmmuV1V2Nodes (\r
1792 SmmuV1V2Offset,\r
1793 SmmuV1V2NodeList,\r
1794 SmmuV1V2NodeCount,\r
1795 &NodeIndexer\r
1796 );\r
1797 if (NodeSize > MAX_UINT32) {\r
1798 Status = EFI_INVALID_PARAMETER;\r
1799 DEBUG ((\r
1800 DEBUG_ERROR,\r
1801 "ERROR: IORT: Invalid Size of SMMUv1/v2 Nodes. Status = %r\n",\r
1802 Status\r
1803 ));\r
1804 goto error_handler;\r
1805 }\r
1806 TableSize += NodeSize;\r
dfaffc69
SM
1807 }\r
1808\r
1809 // SMMUv3 Nodes\r
1810 if (SmmuV3NodeCount > 0) {\r
8b2ac43b 1811 SmmuV3Offset = (UINT32)TableSize;\r
dfaffc69 1812 // Size of SMMUv3 node list.\r
8b2ac43b
SM
1813 NodeSize = GetSizeofSmmuV3Nodes (\r
1814 SmmuV3Offset,\r
1815 SmmuV3NodeList,\r
1816 SmmuV3NodeCount,\r
1817 &NodeIndexer\r
1818 );\r
1819 if (NodeSize > MAX_UINT32) {\r
1820 Status = EFI_INVALID_PARAMETER;\r
1821 DEBUG ((\r
1822 DEBUG_ERROR,\r
1823 "ERROR: IORT: Invalid Size of SMMUv3 Nodes. Status = %r\n",\r
1824 Status\r
1825 ));\r
1826 goto error_handler;\r
1827 }\r
1828 TableSize += NodeSize;\r
dfaffc69
SM
1829 }\r
1830\r
1831 // PMCG Nodes\r
1832 if (PmcgNodeCount > 0) {\r
8b2ac43b 1833 PmcgOffset = (UINT32)TableSize;\r
dfaffc69 1834 // Size of PMCG node list.\r
8b2ac43b
SM
1835 NodeSize = GetSizeofPmcgNodes (\r
1836 PmcgOffset,\r
1837 PmcgNodeList,\r
1838 PmcgNodeCount,\r
1839 &NodeIndexer\r
1840 );\r
1841 if (NodeSize > MAX_UINT32) {\r
1842 Status = EFI_INVALID_PARAMETER;\r
1843 DEBUG ((\r
1844 DEBUG_ERROR,\r
1845 "ERROR: IORT: Invalid Size of PMCG Nodes. Status = %r\n",\r
1846 Status\r
1847 ));\r
1848 goto error_handler;\r
1849 }\r
1850 TableSize += NodeSize;\r
dfaffc69
SM
1851 }\r
1852\r
1853 DEBUG ((\r
1854 DEBUG_INFO,\r
1855 "INFO: IORT:\n" \\r
1856 " IortNodeCount = %d\n" \\r
8b2ac43b 1857 " TableSize = 0x%lx\n",\r
dfaffc69
SM
1858 IortNodeCount,\r
1859 TableSize\r
1860 ));\r
1861\r
1862 DEBUG ((\r
1863 DEBUG_INFO,\r
1864 " ItsGroupNodeCount = %d\n" \\r
1865 " ItsGroupOffset = %d\n",\r
1866 ItsGroupNodeCount,\r
1867 ItsGroupOffset\r
1868 ));\r
1869\r
1870 DEBUG ((\r
1871 DEBUG_INFO,\r
1872 " NamedComponentNodeCount = %d\n" \\r
1873 " NamedComponentOffset = %d\n",\r
1874 NamedComponentNodeCount,\r
1875 NamedComponentOffset\r
1876 ));\r
1877\r
1878 DEBUG ((\r
1879 DEBUG_INFO,\r
1880 " RootComplexNodeCount = %d\n" \\r
1881 " RootComplexOffset = %d\n",\r
1882 RootComplexNodeCount,\r
1883 RootComplexOffset\r
1884 ));\r
1885\r
1886 DEBUG ((\r
1887 DEBUG_INFO,\r
1888 " SmmuV1V2NodeCount = %d\n" \\r
1889 " SmmuV1V2Offset = %d\n",\r
1890 SmmuV1V2NodeCount,\r
1891 SmmuV1V2Offset\r
1892 ));\r
1893\r
1894 DEBUG ((\r
1895 DEBUG_INFO,\r
1896 " SmmuV3NodeCount = %d\n" \\r
1897 " SmmuV3Offset = %d\n",\r
1898 SmmuV3NodeCount,\r
1899 SmmuV3Offset\r
1900 ));\r
1901\r
1902 DEBUG ((\r
1903 DEBUG_INFO,\r
1904 " PmcgNodeCount = %d\n" \\r
1905 " PmcgOffset = %d\n",\r
1906 PmcgNodeCount,\r
1907 PmcgOffset\r
1908 ));\r
1909\r
8b2ac43b
SM
1910 if (TableSize > MAX_UINT32) {\r
1911 Status = EFI_INVALID_PARAMETER;\r
1912 DEBUG ((\r
1913 DEBUG_ERROR,\r
1914 "ERROR: IORT: IORT Table Size 0x%lx > MAX_UINT32," \\r
1915 " Status = %r\n",\r
1916 TableSize,\r
1917 Status\r
1918 ));\r
1919 goto error_handler;\r
1920 }\r
1921\r
dfaffc69
SM
1922 // Allocate the Buffer for IORT table\r
1923 *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);\r
1924 if (*Table == NULL) {\r
1925 Status = EFI_OUT_OF_RESOURCES;\r
1926 DEBUG ((\r
1927 DEBUG_ERROR,\r
1928 "ERROR: IORT: Failed to allocate memory for IORT Table, Size = %d," \\r
1929 " Status = %r\n",\r
1930 TableSize,\r
1931 Status\r
1932 ));\r
1933 goto error_handler;\r
1934 }\r
1935\r
1936 Iort = (EFI_ACPI_6_0_IO_REMAPPING_TABLE*)*Table;\r
1937\r
1938 DEBUG ((\r
1939 DEBUG_INFO,\r
8b2ac43b 1940 "IORT: Iort = 0x%p TableSize = 0x%lx\n",\r
dfaffc69
SM
1941 Iort,\r
1942 TableSize\r
1943 ));\r
1944\r
1945 Status = AddAcpiHeader (\r
1946 CfgMgrProtocol,\r
1947 This,\r
1948 &Iort->Header,\r
e12bdeb1 1949 AcpiTableInfo,\r
8b2ac43b 1950 (UINT32)TableSize\r
dfaffc69
SM
1951 );\r
1952 if (EFI_ERROR (Status)) {\r
1953 DEBUG ((\r
1954 DEBUG_ERROR,\r
1955 "ERROR: IORT: Failed to add ACPI header. Status = %r\n",\r
1956 Status\r
1957 ));\r
1958 goto error_handler;\r
1959 }\r
1960\r
1961 // Update IORT table\r
1962 Iort->NumNodes = IortNodeCount;\r
1963 Iort->NodeOffset = sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE);\r
1964 Iort->Reserved = EFI_ACPI_RESERVED_DWORD;\r
1965\r
1966 if (ItsGroupNodeCount > 0) {\r
1967 Status = AddItsGroupNodes (\r
1968 This,\r
1969 CfgMgrProtocol,\r
1970 Iort,\r
1971 ItsGroupOffset,\r
1972 ItsGroupNodeList,\r
1973 ItsGroupNodeCount\r
1974 );\r
1975 if (EFI_ERROR (Status)) {\r
1976 DEBUG ((\r
1977 DEBUG_ERROR,\r
1978 "ERROR: IORT: Failed to add ITS Group Node. Status = %r\n",\r
1979 Status\r
1980 ));\r
1981 goto error_handler;\r
1982 }\r
1983 }\r
1984\r
1985 if (NamedComponentNodeCount > 0) {\r
1986 Status = AddNamedComponentNodes (\r
1987 This,\r
1988 CfgMgrProtocol,\r
1989 Iort,\r
1990 NamedComponentOffset,\r
1991 NamedComponentNodeList,\r
1992 NamedComponentNodeCount\r
1993 );\r
1994 if (EFI_ERROR (Status)) {\r
1995 DEBUG ((\r
1996 DEBUG_ERROR,\r
1997 "ERROR: IORT: Failed to add Named Component Node. Status = %r\n",\r
1998 Status\r
1999 ));\r
2000 goto error_handler;\r
2001 }\r
2002 }\r
2003\r
2004 if (RootComplexNodeCount > 0) {\r
2005 Status = AddRootComplexNodes (\r
2006 This,\r
2007 CfgMgrProtocol,\r
2008 Iort,\r
2009 RootComplexOffset,\r
2010 RootComplexNodeList,\r
2011 RootComplexNodeCount\r
2012 );\r
2013 if (EFI_ERROR (Status)) {\r
2014 DEBUG ((\r
2015 DEBUG_ERROR,\r
2016 "ERROR: IORT: Failed to add Root Complex Node. Status = %r\n",\r
2017 Status\r
2018 ));\r
2019 goto error_handler;\r
2020 }\r
2021 }\r
2022\r
2023 if (SmmuV1V2NodeCount > 0) {\r
2024 Status = AddSmmuV1V2Nodes (\r
2025 This,\r
2026 CfgMgrProtocol,\r
2027 Iort,\r
2028 SmmuV1V2Offset,\r
2029 SmmuV1V2NodeList,\r
2030 SmmuV1V2NodeCount\r
2031 );\r
2032 if (EFI_ERROR (Status)) {\r
2033 DEBUG ((\r
2034 DEBUG_ERROR,\r
2035 "ERROR: IORT: Failed to add SMMU v1/v2 Node. Status = %r\n",\r
2036 Status\r
2037 ));\r
2038 goto error_handler;\r
2039 }\r
2040 }\r
2041\r
2042 if (SmmuV3NodeCount > 0) {\r
2043 Status = AddSmmuV3Nodes (\r
2044 This,\r
2045 CfgMgrProtocol,\r
2046 Iort,\r
2047 SmmuV3Offset,\r
2048 SmmuV3NodeList,\r
2049 SmmuV3NodeCount\r
2050 );\r
2051 if (EFI_ERROR (Status)) {\r
2052 DEBUG ((\r
2053 DEBUG_ERROR,\r
2054 "ERROR: IORT: Failed to add SMMUv3 Node. Status = %r\n",\r
2055 Status\r
2056 ));\r
2057 goto error_handler;\r
2058 }\r
2059 }\r
2060\r
2061 if (PmcgNodeCount > 0) {\r
2062 Status = AddPmcgNodes (\r
2063 This,\r
2064 CfgMgrProtocol,\r
2065 Iort,\r
2066 PmcgOffset,\r
2067 PmcgNodeList,\r
2068 PmcgNodeCount\r
2069 );\r
2070 if (EFI_ERROR (Status)) {\r
2071 DEBUG ((\r
2072 DEBUG_ERROR,\r
2073 "ERROR: IORT: Failed to add SMMUv3 Node. Status = %r\n",\r
2074 Status\r
2075 ));\r
2076 goto error_handler;\r
2077 }\r
2078 }\r
2079\r
2080 return EFI_SUCCESS;\r
2081\r
2082error_handler:\r
2083 if (Generator->NodeIndexer != NULL) {\r
2084 FreePool (Generator->NodeIndexer);\r
2085 Generator->NodeIndexer = NULL;\r
2086 }\r
2087\r
2088 if (*Table != NULL) {\r
2089 FreePool (*Table);\r
2090 *Table = NULL;\r
2091 }\r
2092 return Status;\r
2093}\r
2094\r
2095/** Free any resources allocated for constructing the IORT\r
2096\r
2097 @param [in] This Pointer to the table generator.\r
2098 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
2099 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
2100 Protocol Interface.\r
2101 @param [in, out] Table Pointer to the ACPI Table.\r
2102\r
2103 @retval EFI_SUCCESS The resources were freed successfully.\r
2104 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.\r
2105**/\r
2106STATIC\r
2107EFI_STATUS\r
2108FreeIortTableResources (\r
2109 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
2110 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
2111 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
2112 IN OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
2113 )\r
2114{\r
2115 ACPI_IORT_GENERATOR * Generator;\r
2116 ASSERT (This != NULL);\r
2117 ASSERT (AcpiTableInfo != NULL);\r
2118 ASSERT (CfgMgrProtocol != NULL);\r
2119 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
2120 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
2121\r
2122 Generator = (ACPI_IORT_GENERATOR*)This;\r
2123\r
2124 // Free any memory allocated by the generator\r
2125 if (Generator->NodeIndexer != NULL) {\r
2126 FreePool (Generator->NodeIndexer);\r
2127 Generator->NodeIndexer = NULL;\r
2128 }\r
2129\r
2130 if ((Table == NULL) || (*Table == NULL)) {\r
2131 DEBUG ((DEBUG_ERROR, "ERROR: IORT: Invalid Table Pointer\n"));\r
2132 ASSERT ((Table != NULL) && (*Table != NULL));\r
2133 return EFI_INVALID_PARAMETER;\r
2134 }\r
2135\r
2136 FreePool (*Table);\r
2137 *Table = NULL;\r
2138 return EFI_SUCCESS;\r
2139}\r
2140\r
2141/** The IORT Table Generator revision.\r
2142*/\r
2143#define IORT_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
2144\r
2145/** The interface for the MADT Table Generator.\r
2146*/\r
2147STATIC\r
2148ACPI_IORT_GENERATOR IortGenerator = {\r
2149 // ACPI table generator header\r
2150 {\r
2151 // Generator ID\r
2152 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdIort),\r
2153 // Generator Description\r
2154 L"ACPI.STD.IORT.GENERATOR",\r
2155 // ACPI Table Signature\r
2156 EFI_ACPI_6_2_IO_REMAPPING_TABLE_SIGNATURE,\r
2157 // ACPI Table Revision supported by this Generator\r
2158 EFI_ACPI_IO_REMAPPING_TABLE_REVISION,\r
2159 // Minimum supported ACPI Table Revision\r
2160 EFI_ACPI_IO_REMAPPING_TABLE_REVISION,\r
2161 // Creator ID\r
2162 TABLE_GENERATOR_CREATOR_ID_ARM,\r
2163 // Creator Revision\r
2164 IORT_GENERATOR_REVISION,\r
2165 // Build Table function\r
2166 BuildIortTable,\r
2167 // Free Resource function\r
2168 FreeIortTableResources,\r
2169 // Extended build function not needed\r
2170 NULL,\r
2171 // Extended build function not implemented by the generator.\r
2172 // Hence extended free resource function is not required.\r
2173 NULL\r
2174 },\r
2175\r
2176 // IORT Generator private data\r
2177\r
2178 // Iort Node count\r
2179 0,\r
2180 // Pointer to Iort node indexer\r
2181 NULL\r
2182};\r
2183\r
2184/** Register the Generator with the ACPI Table Factory.\r
2185\r
2186 @param [in] ImageHandle The handle to the image.\r
2187 @param [in] SystemTable Pointer to the System Table.\r
2188\r
2189 @retval EFI_SUCCESS The Generator is registered.\r
2190 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
2191 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
2192 is already registered.\r
2193**/\r
2194EFI_STATUS\r
2195EFIAPI\r
2196AcpiIortLibConstructor (\r
43a0e08d
SM
2197 IN EFI_HANDLE ImageHandle,\r
2198 IN EFI_SYSTEM_TABLE * SystemTable\r
dfaffc69
SM
2199 )\r
2200{\r
2201 EFI_STATUS Status;\r
2202 Status = RegisterAcpiTableGenerator (&IortGenerator.Header);\r
2203 DEBUG ((DEBUG_INFO, "IORT: Register Generator. Status = %r\n", Status));\r
2204 ASSERT_EFI_ERROR (Status);\r
2205 return Status;\r
2206}\r
2207\r
2208/** Deregister the Generator from the ACPI Table Factory.\r
2209\r
2210 @param [in] ImageHandle The handle to the image.\r
2211 @param [in] SystemTable Pointer to the System Table.\r
2212\r
2213 @retval EFI_SUCCESS The Generator is deregistered.\r
2214 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
2215 @retval EFI_NOT_FOUND The Generator is not registered.\r
2216**/\r
2217EFI_STATUS\r
2218EFIAPI\r
2219AcpiIortLibDestructor (\r
43a0e08d
SM
2220 IN EFI_HANDLE ImageHandle,\r
2221 IN EFI_SYSTEM_TABLE * SystemTable\r
dfaffc69
SM
2222 )\r
2223{\r
2224 EFI_STATUS Status;\r
2225 Status = DeregisterAcpiTableGenerator (&IortGenerator.Header);\r
2226 DEBUG ((DEBUG_INFO, "Iort: Deregister Generator. Status = %r\n", Status));\r
2227 ASSERT_EFI_ERROR (Status);\r
2228 return Status;\r
2229}\r