TianoCore EDK2 master
Loading...
Searching...
No Matches
IortGenerator.c
Go to the documentation of this file.
1
14#include <Library/AcpiLib.h>
15#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
18#include <Protocol/AcpiTable.h>
19
20// Module specific include files.
21#include <AcpiTableGenerator.h>
26
27#include "IortGenerator.h"
28
54 );
55
63 );
64
72 );
73
81 );
82
90 );
91
99 );
100
108 );
109
117 );
118
126 );
127
135 );
136
144 );
145
152STATIC
153UINT32
156 )
157{
158 ASSERT (Node != NULL);
159
160 /* Size of ITS Group Node +
161 Size of ITS Identifier array
162 */
163 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE) +
164 (Node->ItsIdCount * sizeof (UINT32)));
165}
166
182STATIC
183UINT64
185 IN CONST UINT32 NodeStartOffset,
187 IN UINT32 NodeCount,
188 IN OUT IORT_NODE_INDEXER **CONST NodeIndexer
189 )
190{
191 UINT64 Size;
192
193 ASSERT (NodeList != NULL);
194
195 Size = 0;
196 while (NodeCount-- != 0) {
197 (*NodeIndexer)->Token = NodeList->Token;
198 (*NodeIndexer)->Object = (VOID *)NodeList;
199 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
200 (*NodeIndexer)->Identifier = NodeList->Identifier;
201 DEBUG ((
202 DEBUG_INFO,
203 "IORT: Node Indexer = %p, Token = %p, Object = %p,"
204 " Offset = 0x%x, Identifier = 0x%x\n",
205 *NodeIndexer,
206 (*NodeIndexer)->Token,
207 (*NodeIndexer)->Object,
208 (*NodeIndexer)->Offset,
209 (*NodeIndexer)->Identifier
210 ));
211
212 Size += GetItsGroupNodeSize (NodeList);
213 (*NodeIndexer)++;
214 NodeList++;
215 }
216
217 return Size;
218}
219
226STATIC
227UINT32
230 )
231{
232 ASSERT (Node != NULL);
233
234 /* Size of Named Component node +
235 Size of ID mapping array +
236 Size of ASCII string + 'padding to 32-bit word aligned'.
237 */
238 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE) +
239 (Node->IdMappingCount *
241 ALIGN_VALUE (AsciiStrSize (Node->ObjectName), 4));
242}
243
259STATIC
260UINT64
262 IN CONST UINT32 NodeStartOffset,
264 IN UINT32 NodeCount,
265 IN OUT IORT_NODE_INDEXER **CONST NodeIndexer
266 )
267{
268 UINT64 Size;
269
270 ASSERT (NodeList != NULL);
271
272 Size = 0;
273 while (NodeCount-- != 0) {
274 (*NodeIndexer)->Token = NodeList->Token;
275 (*NodeIndexer)->Object = (VOID *)NodeList;
276 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
277 (*NodeIndexer)->Identifier = NodeList->Identifier;
278 DEBUG ((
279 DEBUG_INFO,
280 "IORT: Node Indexer = %p, Token = %p, Object = %p,"
281 " Offset = 0x%x, Identifier = 0x%x\n",
282 *NodeIndexer,
283 (*NodeIndexer)->Token,
284 (*NodeIndexer)->Object,
285 (*NodeIndexer)->Offset,
286 (*NodeIndexer)->Identifier
287 ));
288
289 Size += GetNamedComponentNodeSize (NodeList);
290 (*NodeIndexer)++;
291 NodeList++;
292 }
293
294 return Size;
295}
296
303STATIC
304UINT32
307 )
308{
309 ASSERT (Node != NULL);
310
311 /* Size of Root Complex node +
312 Size of ID mapping array
313 */
314 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE) +
315 (Node->IdMappingCount *
317}
318
334STATIC
335UINT64
337 IN CONST UINT32 NodeStartOffset,
339 IN UINT32 NodeCount,
340 IN OUT IORT_NODE_INDEXER **CONST NodeIndexer
341 )
342{
343 UINT64 Size;
344
345 ASSERT (NodeList != NULL);
346
347 Size = 0;
348 while (NodeCount-- != 0) {
349 (*NodeIndexer)->Token = NodeList->Token;
350 (*NodeIndexer)->Object = (VOID *)NodeList;
351 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
352 (*NodeIndexer)->Identifier = NodeList->Identifier;
353 DEBUG ((
354 DEBUG_INFO,
355 "IORT: Node Indexer = %p, Token = %p, Object = %p,"
356 " Offset = 0x%x, Identifier = 0x%x\n",
357 *NodeIndexer,
358 (*NodeIndexer)->Token,
359 (*NodeIndexer)->Object,
360 (*NodeIndexer)->Offset,
361 (*NodeIndexer)->Identifier
362 ));
363
364 Size += GetRootComplexNodeSize (NodeList);
365 (*NodeIndexer)++;
366 NodeList++;
367 }
368
369 return Size;
370}
371
378STATIC
379UINT32
382 )
383{
384 ASSERT (Node != NULL);
385
386 /* Size of SMMU v1/SMMU v2 node +
387 Size of ID mapping array +
388 Size of context interrupt array +
389 Size of PMU interrupt array
390 */
391 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE) +
392 (Node->IdMappingCount *
394 (Node->ContextInterruptCount *
396 (Node->PmuInterruptCount *
398}
399
415STATIC
416UINT64
418 IN CONST UINT32 NodeStartOffset,
420 IN UINT32 NodeCount,
421 IN OUT IORT_NODE_INDEXER **CONST NodeIndexer
422 )
423{
424 UINT64 Size;
425
426 ASSERT (NodeList != NULL);
427
428 Size = 0;
429 while (NodeCount-- != 0) {
430 (*NodeIndexer)->Token = NodeList->Token;
431 (*NodeIndexer)->Object = (VOID *)NodeList;
432 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
433 (*NodeIndexer)->Identifier = NodeList->Identifier;
434 DEBUG ((
435 DEBUG_INFO,
436 "IORT: Node Indexer = %p, Token = %p, Object = %p,"
437 " Offset = 0x%x, Identifier = 0x%x\n",
438 *NodeIndexer,
439 (*NodeIndexer)->Token,
440 (*NodeIndexer)->Object,
441 (*NodeIndexer)->Offset,
442 (*NodeIndexer)->Identifier
443 ));
444
445 Size += GetSmmuV1V2NodeSize (NodeList);
446 (*NodeIndexer)++;
447 NodeList++;
448 }
449
450 return Size;
451}
452
459STATIC
460UINT32
463 )
464{
465 ASSERT (Node != NULL);
466
467 /* Size of SMMU v1/SMMU v2 node +
468 Size of ID mapping array
469 */
470 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE) +
471 (Node->IdMappingCount *
473}
474
490STATIC
491UINT64
493 IN CONST UINT32 NodeStartOffset,
494 IN CONST CM_ARM_SMMUV3_NODE *NodeList,
495 IN UINT32 NodeCount,
496 IN OUT IORT_NODE_INDEXER **CONST NodeIndexer
497 )
498{
499 UINT64 Size;
500
501 ASSERT (NodeList != NULL);
502
503 Size = 0;
504 while (NodeCount-- != 0) {
505 (*NodeIndexer)->Token = NodeList->Token;
506 (*NodeIndexer)->Object = (VOID *)NodeList;
507 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
508 (*NodeIndexer)->Identifier = NodeList->Identifier;
509 DEBUG ((
510 DEBUG_INFO,
511 "IORT: Node Indexer = %p, Token = %p, Object = %p,"
512 " Offset = 0x%x, Identifier = 0x%x\n",
513 *NodeIndexer,
514 (*NodeIndexer)->Token,
515 (*NodeIndexer)->Object,
516 (*NodeIndexer)->Offset,
517 (*NodeIndexer)->Identifier
518 ));
519
520 Size += GetSmmuV3NodeSize (NodeList);
521 (*NodeIndexer)++;
522 NodeList++;
523 }
524
525 return Size;
526}
527
534STATIC
535UINT32
538 )
539{
540 ASSERT (Node != NULL);
541
542 /* Size of PMCG node +
543 Size of ID mapping array
544 */
545 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE) +
546 (Node->IdMappingCount *
548}
549
565STATIC
566UINT64
568 IN CONST UINT32 NodeStartOffset,
569 IN CONST CM_ARM_PMCG_NODE *NodeList,
570 IN UINT32 NodeCount,
571 IN OUT IORT_NODE_INDEXER **CONST NodeIndexer
572 )
573{
574 UINT64 Size;
575
576 ASSERT (NodeList != NULL);
577
578 Size = 0;
579 while (NodeCount-- != 0) {
580 (*NodeIndexer)->Token = NodeList->Token;
581 (*NodeIndexer)->Object = (VOID *)NodeList;
582 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
583 (*NodeIndexer)->Identifier = NodeList->Identifier;
584 DEBUG ((
585 DEBUG_INFO,
586 "IORT: Node Indexer = %p, Token = %p, Object = %p,"
587 " Offset = 0x%x, Identifier = 0x%x\n",
588 *NodeIndexer,
589 (*NodeIndexer)->Token,
590 (*NodeIndexer)->Object,
591 (*NodeIndexer)->Offset,
592 (*NodeIndexer)->Identifier
593 ));
594
595 Size += GetPmcgNodeSize (NodeList);
596 (*NodeIndexer)++;
597 NodeList++;
598 }
599
600 return Size;
601}
602
609STATIC
610UINT32
613 )
614{
615 ASSERT (Node != NULL);
616
617 /* Size of RMR node +
618 Size of ID mapping array +
619 Size of Memory Range Descriptor array
620 */
621 return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE) +
622 (Node->IdMappingCount *
624 (Node->MemRangeDescCount *
626}
627
643STATIC
644UINT64
646 IN CONST UINT32 NodeStartOffset,
647 IN CONST CM_ARM_RMR_NODE *NodeList,
648 IN UINT32 NodeCount,
649 IN OUT IORT_NODE_INDEXER **CONST NodeIndexer
650 )
651{
652 UINT64 Size;
653
654 ASSERT (NodeList != NULL);
655
656 Size = 0;
657 while (NodeCount-- != 0) {
658 (*NodeIndexer)->Token = NodeList->Token;
659 (*NodeIndexer)->Object = (VOID *)NodeList;
660 (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
661 (*NodeIndexer)->Identifier = NodeList->Identifier;
662 DEBUG ((
663 DEBUG_INFO,
664 "IORT: Node Indexer = %p, Token = %p, Object = %p,"
665 " Offset = 0x%x, Identifier = 0x%x\n",
666 *NodeIndexer,
667 (*NodeIndexer)->Token,
668 (*NodeIndexer)->Object,
669 (*NodeIndexer)->Offset,
670 (*NodeIndexer)->Identifier
671 ));
672
673 Size += GetRmrNodeSize (NodeList);
674 (*NodeIndexer)++;
675 NodeList++;
676 }
677
678 return Size;
679}
680
693STATIC
696 IN IORT_NODE_INDEXER *NodeIndexer,
697 IN UINT32 NodeCount,
698 IN CM_OBJECT_TOKEN Token,
699 OUT UINT32 *NodeOffset
700 )
701{
702 DEBUG ((
703 DEBUG_INFO,
704 "IORT: Node Indexer: Search Token = %p\n",
705 Token
706 ));
707 while (NodeCount-- != 0) {
708 DEBUG ((
709 DEBUG_INFO,
710 "IORT: Node Indexer: NodeIndexer->Token = %p, Offset = %d\n",
711 NodeIndexer->Token,
712 NodeIndexer->Offset
713 ));
714 if (NodeIndexer->Token == Token) {
715 *NodeOffset = NodeIndexer->Offset;
716 DEBUG ((
717 DEBUG_INFO,
718 "IORT: Node Indexer: Token = %p, Found\n",
719 Token
720 ));
721 return EFI_SUCCESS;
722 }
723
724 NodeIndexer++;
725 }
726
727 DEBUG ((
728 DEBUG_INFO,
729 "IORT: Node Indexer: Token = %p, Not Found\n",
730 Token
731 ));
732 return EFI_NOT_FOUND;
733}
734
752STATIC
758 IN UINT32 IdCount,
759 IN CONST CM_OBJECT_TOKEN IdMappingToken
760 )
761{
762 EFI_STATUS Status;
763 CM_ARM_ID_MAPPING *IdMappings;
764 UINT32 IdMappingCount;
766
767 ASSERT (IdMapArray != NULL);
768
770
771 // Get the Id Mapping Array
772 Status = GetEArmObjIdMappingArray (
773 CfgMgrProtocol,
774 IdMappingToken,
775 &IdMappings,
776 &IdMappingCount
777 );
778 if (EFI_ERROR (Status)) {
779 DEBUG ((
780 DEBUG_ERROR,
781 "ERROR: IORT: Failed to get Id Mapping array. Status = %r\n",
782 Status
783 ));
784 return Status;
785 }
786
787 if (IdMappingCount < IdCount) {
788 DEBUG ((
789 DEBUG_ERROR,
790 "ERROR: IORT: Failed to get the required number of Id Mappings.\n"
791 ));
792 return EFI_NOT_FOUND;
793 }
794
795 // Populate the Id Mapping array
796 while (IdCount-- != 0) {
798 Generator->NodeIndexer,
799 Generator->IortNodeCount,
800 IdMappings->OutputReferenceToken,
801 &IdMapArray->OutputReference
802 );
803 if (EFI_ERROR (Status)) {
804 DEBUG ((
805 DEBUG_ERROR,
806 "ERROR: IORT: Failed to get Output Reference for ITS Identifier array."
807 "Reference Token = %p"
808 " Status = %r\n",
809 IdMappings->OutputReferenceToken,
810 Status
811 ));
812 return Status;
813 }
814
815 IdMapArray->InputBase = IdMappings->InputBase;
816 IdMapArray->NumIds = IdMappings->NumIds;
817 IdMapArray->OutputBase = IdMappings->OutputBase;
818 IdMapArray->Flags = IdMappings->Flags;
819
820 IdMapArray++;
821 IdMappings++;
822 } // Id Mapping array
823
824 return EFI_SUCCESS;
825}
826
844STATIC
851 IN CONST UINT32 NodesStartOffset,
853 IN UINT32 NodeCount
854 )
855{
856 EFI_STATUS Status;
858 UINT32 *ItsIds;
859 CM_ARM_ITS_IDENTIFIER *ItsIdentifier;
860 UINT32 ItsIdentifierCount;
861 UINT32 IdIndex;
862 UINT64 NodeLength;
863
864 ASSERT (Iort != NULL);
865
866 ItsGroupNode = (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE *)((UINT8 *)Iort +
867 NodesStartOffset);
868
869 while (NodeCount-- != 0) {
870 NodeLength = GetItsGroupNodeSize (NodeList);
871 if (NodeLength > MAX_UINT16) {
872 Status = EFI_INVALID_PARAMETER;
873 DEBUG ((
874 DEBUG_ERROR,
875 "ERROR: IORT: ITS Id Array Node length 0x%lx > MAX_UINT16."
876 " Status = %r\n",
877 NodeLength,
878 Status
879 ));
880 return Status;
881 }
882
883 // Populate the node header
884 ItsGroupNode->Node.Type = EFI_ACPI_IORT_TYPE_ITS_GROUP;
885 ItsGroupNode->Node.Length = (UINT16)NodeLength;
886 ItsGroupNode->Node.NumIdMappings = 0;
887 ItsGroupNode->Node.IdReference = 0;
888
889 if (AcpiTableInfo->AcpiTableRevision <
890 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
891 {
892 ItsGroupNode->Node.Revision = 0;
893 ItsGroupNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
894 } else {
895 ItsGroupNode->Node.Revision = 1;
896 ItsGroupNode->Node.Identifier = NodeList->Identifier;
897 }
898
899 // IORT specific data
900 ItsGroupNode->NumItsIdentifiers = NodeList->ItsIdCount;
901 ItsIds = (UINT32 *)((UINT8 *)ItsGroupNode +
903
904 Status = GetEArmObjGicItsIdentifierArray (
905 CfgMgrProtocol,
906 NodeList->ItsIdToken,
907 &ItsIdentifier,
908 &ItsIdentifierCount
909 );
910 if (EFI_ERROR (Status)) {
911 DEBUG ((
912 DEBUG_ERROR,
913 "ERROR: IORT: Failed to get ITS Identifier array. Status = %r\n",
914 Status
915 ));
916 return Status;
917 }
918
919 if (ItsIdentifierCount < ItsGroupNode->NumItsIdentifiers) {
920 DEBUG ((
921 DEBUG_ERROR,
922 "ERROR: IORT: Failed to get the required number of ITS Identifiers.\n"
923 ));
924 return EFI_NOT_FOUND;
925 }
926
927 // Populate the ITS identifier array
928 for (IdIndex = 0; IdIndex < ItsGroupNode->NumItsIdentifiers; IdIndex++) {
929 ItsIds[IdIndex] = ItsIdentifier[IdIndex].ItsId;
930 } // ITS identifier array
931
932 // Next IORT Group Node
933 ItsGroupNode = (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE *)((UINT8 *)ItsGroupNode +
934 ItsGroupNode->Node.Length);
935 NodeList++;
936 } // IORT Group Node
937
938 return EFI_SUCCESS;
939}
940
961STATIC
968 IN CONST UINT32 NodesStartOffset,
970 IN UINT32 NodeCount
971 )
972{
973 EFI_STATUS Status;
976 CHAR8 *ObjectName;
977 UINTN ObjectNameLength;
978 UINT64 NodeLength;
979
980 ASSERT (Iort != NULL);
981
982 NcNode = (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE *)((UINT8 *)Iort +
983 NodesStartOffset);
984
985 while (NodeCount-- != 0) {
986 NodeLength = GetNamedComponentNodeSize (NodeList);
987 if (NodeLength > MAX_UINT16) {
988 Status = EFI_INVALID_PARAMETER;
989 DEBUG ((
990 DEBUG_ERROR,
991 "ERROR: IORT: Named Component Node length 0x%lx > MAX_UINT16."
992 " Status = %r\n",
993 NodeLength,
994 Status
995 ));
996 return Status;
997 }
998
999 // Populate the node header
1000 NcNode->Node.Type = EFI_ACPI_IORT_TYPE_NAMED_COMP;
1001 NcNode->Node.Length = (UINT16)NodeLength;
1002 NcNode->Node.NumIdMappings = NodeList->IdMappingCount;
1003
1004 if (AcpiTableInfo->AcpiTableRevision <
1005 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
1006 {
1007 NcNode->Node.Revision = 2;
1008 NcNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
1009 } else {
1010 NcNode->Node.Revision = 4;
1011 NcNode->Node.Identifier = NodeList->Identifier;
1012 }
1013
1014 ObjectNameLength = AsciiStrLen (NodeList->ObjectName) + 1;
1015 NcNode->Node.IdReference = (NodeList->IdMappingCount == 0) ?
1016 0 : ((UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE) +
1017 (ALIGN_VALUE (ObjectNameLength, 4))));
1018
1019 // Named Component specific data
1020 NcNode->Flags = NodeList->Flags;
1021 NcNode->CacheCoherent = NodeList->CacheCoherent;
1022 NcNode->AllocationHints = NodeList->AllocationHints;
1023 NcNode->Reserved = EFI_ACPI_RESERVED_WORD;
1024 NcNode->MemoryAccessFlags = NodeList->MemoryAccessFlags;
1025 NcNode->AddressSizeLimit = NodeList->AddressSizeLimit;
1026
1027 // Copy the object name
1028 ObjectName = (CHAR8 *)((UINT8 *)NcNode +
1030 Status = AsciiStrCpyS (
1031 ObjectName,
1032 ObjectNameLength,
1033 NodeList->ObjectName
1034 );
1035 if (EFI_ERROR (Status)) {
1036 DEBUG ((
1037 DEBUG_ERROR,
1038 "ERROR: IORT: Failed to copy Object Name. Status = %r\n",
1039 Status
1040 ));
1041 return Status;
1042 }
1043
1044 if (NodeList->IdMappingCount > 0) {
1045 if (NodeList->IdMappingToken == CM_NULL_TOKEN) {
1046 Status = EFI_INVALID_PARAMETER;
1047 DEBUG ((
1048 DEBUG_ERROR,
1049 "ERROR: IORT: Invalid Id Mapping token,"
1050 " Token = 0x%x, Status =%r\n",
1051 NodeList->IdMappingToken,
1052 Status
1053 ));
1054 return Status;
1055 }
1056
1057 // Ids for Named Component
1058 IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE *)((UINT8 *)NcNode +
1059 NcNode->Node.IdReference);
1060
1061 Status = AddIdMappingArray (
1062 This,
1063 CfgMgrProtocol,
1064 IdMapArray,
1065 NodeList->IdMappingCount,
1066 NodeList->IdMappingToken
1067 );
1068 if (EFI_ERROR (Status)) {
1069 DEBUG ((
1070 DEBUG_ERROR,
1071 "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
1072 Status
1073 ));
1074 return Status;
1075 }
1076 }
1077
1078 // Next Named Component Node
1079 NcNode = (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE *)((UINT8 *)NcNode +
1080 NcNode->Node.Length);
1081 NodeList++;
1082 } // Named Component Node
1083
1084 return EFI_SUCCESS;
1085}
1086
1106STATIC
1113 IN CONST UINT32 NodesStartOffset,
1115 IN UINT32 NodeCount
1116 )
1117{
1118 EFI_STATUS Status;
1121 UINT64 NodeLength;
1122
1123 ASSERT (Iort != NULL);
1124
1125 RcNode = (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE *)((UINT8 *)Iort +
1126 NodesStartOffset);
1127
1128 while (NodeCount-- != 0) {
1129 NodeLength = GetRootComplexNodeSize (NodeList);
1130 if (NodeLength > MAX_UINT16) {
1131 Status = EFI_INVALID_PARAMETER;
1132 DEBUG ((
1133 DEBUG_ERROR,
1134 "ERROR: IORT: Root Complex Node length 0x%lx > MAX_UINT16."
1135 " Status = %r\n",
1136 NodeLength,
1137 Status
1138 ));
1139 return Status;
1140 }
1141
1142 // Populate the node header
1143 RcNode->Node.Type = EFI_ACPI_IORT_TYPE_ROOT_COMPLEX;
1144 RcNode->Node.Length = (UINT16)NodeLength;
1145 RcNode->Node.NumIdMappings = NodeList->IdMappingCount;
1146 RcNode->Node.IdReference = (NodeList->IdMappingCount == 0) ?
1148
1149 if (AcpiTableInfo->AcpiTableRevision <
1150 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
1151 {
1152 RcNode->Node.Revision = 1;
1153 RcNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
1154 RcNode->PasidCapabilities = EFI_ACPI_RESERVED_WORD;
1155 } else {
1156 RcNode->Node.Revision = 4;
1157 RcNode->Node.Identifier = NodeList->Identifier;
1158 RcNode->PasidCapabilities = NodeList->PasidCapabilities;
1159 RcNode->Flags = NodeList->Flags;
1160 }
1161
1162 // Root Complex specific data
1163 RcNode->CacheCoherent = NodeList->CacheCoherent;
1164 RcNode->AllocationHints = NodeList->AllocationHints;
1165 RcNode->Reserved = EFI_ACPI_RESERVED_WORD;
1166 RcNode->MemoryAccessFlags = NodeList->MemoryAccessFlags;
1167 RcNode->AtsAttribute = NodeList->AtsAttribute;
1168 RcNode->PciSegmentNumber = NodeList->PciSegmentNumber;
1169 RcNode->MemoryAddressSize = NodeList->MemoryAddressSize;
1170 RcNode->Reserved1[0] = EFI_ACPI_RESERVED_BYTE;
1171
1172 if (NodeList->IdMappingCount > 0) {
1173 if (NodeList->IdMappingToken == CM_NULL_TOKEN) {
1174 Status = EFI_INVALID_PARAMETER;
1175 DEBUG ((
1176 DEBUG_ERROR,
1177 "ERROR: IORT: Invalid Id Mapping token,"
1178 " Token = 0x%x, Status =%r\n",
1179 NodeList->IdMappingToken,
1180 Status
1181 ));
1182 return Status;
1183 }
1184
1185 // Ids for Root Complex
1186 IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE *)((UINT8 *)RcNode +
1187 RcNode->Node.IdReference);
1188 Status = AddIdMappingArray (
1189 This,
1190 CfgMgrProtocol,
1191 IdMapArray,
1192 NodeList->IdMappingCount,
1193 NodeList->IdMappingToken
1194 );
1195 if (EFI_ERROR (Status)) {
1196 DEBUG ((
1197 DEBUG_ERROR,
1198 "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
1199 Status
1200 ));
1201 return Status;
1202 }
1203 }
1204
1205 // Next Root Complex Node
1206 RcNode = (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE *)((UINT8 *)RcNode +
1207 RcNode->Node.Length);
1208 NodeList++;
1209 } // Root Complex Node
1210
1211 return EFI_SUCCESS;
1212}
1213
1230STATIC
1235 IN UINT32 InterruptCount,
1236 IN CONST CM_OBJECT_TOKEN InterruptToken
1237 )
1238{
1239 EFI_STATUS Status;
1240 CM_ARM_SMMU_INTERRUPT *SmmuInterrupt;
1241 UINT32 SmmuInterruptCount;
1242
1243 ASSERT (InterruptArray != NULL);
1244
1245 // Get the SMMU Interrupt Array
1246 Status = GetEArmObjSmmuInterruptArray (
1247 CfgMgrProtocol,
1248 InterruptToken,
1249 &SmmuInterrupt,
1250 &SmmuInterruptCount
1251 );
1252 if (EFI_ERROR (Status)) {
1253 DEBUG ((
1254 DEBUG_ERROR,
1255 "ERROR: IORT: Failed to get SMMU Interrupt array. Status = %r\n",
1256 Status
1257 ));
1258 return Status;
1259 }
1260
1261 if (SmmuInterruptCount < InterruptCount) {
1262 DEBUG ((
1263 DEBUG_ERROR,
1264 "ERROR: IORT: Failed to get the required number of SMMU Interrupts.\n"
1265 ));
1266 return EFI_NOT_FOUND;
1267 }
1268
1269 // Populate the Id Mapping array
1270 while (InterruptCount-- != 0) {
1271 InterruptArray->Interrupt = SmmuInterrupt->Interrupt;
1272 InterruptArray->InterruptFlags = SmmuInterrupt->Flags;
1273 InterruptArray++;
1274 SmmuInterrupt++;
1275 } // Id Mapping array
1276
1277 return EFI_SUCCESS;
1278}
1279
1297STATIC
1304 IN CONST UINT32 NodesStartOffset,
1306 IN UINT32 NodeCount
1307 )
1308{
1309 EFI_STATUS Status;
1312
1313 EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT *ContextInterruptArray;
1314 EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT *PmuInterruptArray;
1315 UINT64 NodeLength;
1316 UINT32 Offset;
1317
1318 ASSERT (Iort != NULL);
1319
1320 SmmuNode = (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE *)((UINT8 *)Iort +
1321 NodesStartOffset);
1322
1323 while (NodeCount-- != 0) {
1324 NodeLength = GetSmmuV1V2NodeSize (NodeList);
1325 if (NodeLength > MAX_UINT16) {
1326 Status = EFI_INVALID_PARAMETER;
1327 DEBUG ((
1328 DEBUG_ERROR,
1329 "ERROR: IORT: SMMU V1/V2 Node length 0x%lx > MAX_UINT16. Status = %r\n",
1330 NodeLength,
1331 Status
1332 ));
1333 return Status;
1334 }
1335
1336 // Populate the node header
1337 SmmuNode->Node.Type = EFI_ACPI_IORT_TYPE_SMMUv1v2;
1338 SmmuNode->Node.Length = (UINT16)NodeLength;
1339 SmmuNode->Node.NumIdMappings = NodeList->IdMappingCount;
1340 SmmuNode->Node.IdReference = (NodeList->IdMappingCount == 0) ?
1342 (NodeList->ContextInterruptCount *
1344 (NodeList->PmuInterruptCount *
1346
1347 if (AcpiTableInfo->AcpiTableRevision <
1348 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
1349 {
1350 SmmuNode->Node.Revision = 1;
1351 SmmuNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
1352 } else {
1353 SmmuNode->Node.Revision = 3;
1354 SmmuNode->Node.Identifier = NodeList->Identifier;
1355 }
1356
1357 // SMMU v1/v2 specific data
1358 SmmuNode->Base = NodeList->BaseAddress;
1359 SmmuNode->Span = NodeList->Span;
1360 SmmuNode->Model = NodeList->Model;
1361 SmmuNode->Flags = NodeList->Flags;
1362
1363 // Reference to Global Interrupt Array
1364 SmmuNode->GlobalInterruptArrayRef =
1366
1367 Offset = sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE);
1368 // Context Interrupt
1369 SmmuNode->NumContextInterrupts = NodeList->ContextInterruptCount;
1370 if (NodeList->ContextInterruptCount != 0) {
1371 SmmuNode->ContextInterruptArrayRef = Offset;
1372 ContextInterruptArray =
1373 (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT *)((UINT8 *)SmmuNode + Offset);
1374 Offset += (NodeList->ContextInterruptCount *
1376 }
1377
1378 // PMU Interrupt
1379 SmmuNode->NumPmuInterrupts = NodeList->PmuInterruptCount;
1380 if (NodeList->PmuInterruptCount != 0) {
1381 SmmuNode->PmuInterruptArrayRef = Offset;
1382 PmuInterruptArray =
1383 (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT *)((UINT8 *)SmmuNode + Offset);
1384 }
1385
1386 SmmuNode->SMMU_NSgIrpt = NodeList->SMMU_NSgIrpt;
1387 SmmuNode->SMMU_NSgIrptFlags = NodeList->SMMU_NSgIrptFlags;
1388 SmmuNode->SMMU_NSgCfgIrpt = NodeList->SMMU_NSgCfgIrpt;
1389 SmmuNode->SMMU_NSgCfgIrptFlags = NodeList->SMMU_NSgCfgIrptFlags;
1390
1391 if (NodeList->ContextInterruptCount != 0) {
1392 if (NodeList->ContextInterruptToken == CM_NULL_TOKEN) {
1393 Status = EFI_INVALID_PARAMETER;
1394 DEBUG ((
1395 DEBUG_ERROR,
1396 "ERROR: IORT: Invalid Context Interrupt token,"
1397 " Token = 0x%x, Status =%r\n",
1398 NodeList->ContextInterruptToken,
1399 Status
1400 ));
1401 return Status;
1402 }
1403
1404 // Add Context Interrupt Array
1405 Status = AddSmmuInterruptArray (
1406 CfgMgrProtocol,
1407 ContextInterruptArray,
1408 SmmuNode->NumContextInterrupts,
1409 NodeList->ContextInterruptToken
1410 );
1411 if (EFI_ERROR (Status)) {
1412 DEBUG ((
1413 DEBUG_ERROR,
1414 "ERROR: IORT: Failed to Context Interrupt Array. Status = %r\n",
1415 Status
1416 ));
1417 return Status;
1418 }
1419 }
1420
1421 // Add PMU Interrupt Array
1422 if (SmmuNode->NumPmuInterrupts != 0) {
1423 if (NodeList->PmuInterruptToken == CM_NULL_TOKEN) {
1424 Status = EFI_INVALID_PARAMETER;
1425 DEBUG ((
1426 DEBUG_ERROR,
1427 "ERROR: IORT: Invalid PMU Interrupt token,"
1428 " Token = 0x%x, Status =%r\n",
1429 NodeList->PmuInterruptToken,
1430 Status
1431 ));
1432 return Status;
1433 }
1434
1435 Status = AddSmmuInterruptArray (
1436 CfgMgrProtocol,
1437 PmuInterruptArray,
1438 SmmuNode->NumPmuInterrupts,
1439 NodeList->PmuInterruptToken
1440 );
1441 if (EFI_ERROR (Status)) {
1442 DEBUG ((
1443 DEBUG_ERROR,
1444 "ERROR: IORT: Failed to PMU Interrupt Array. Status = %r\n",
1445 Status
1446 ));
1447 return Status;
1448 }
1449 }
1450
1451 if (NodeList->IdMappingCount > 0) {
1452 if (NodeList->IdMappingToken == CM_NULL_TOKEN) {
1453 Status = EFI_INVALID_PARAMETER;
1454 DEBUG ((
1455 DEBUG_ERROR,
1456 "ERROR: IORT: Invalid Id Mapping token,"
1457 " Token = 0x%x, Status =%r\n",
1458 NodeList->IdMappingToken,
1459 Status
1460 ));
1461 return Status;
1462 }
1463
1464 // Ids for SMMU v1/v2 Node
1465 IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE *)((UINT8 *)SmmuNode +
1466 SmmuNode->Node.IdReference);
1467 Status = AddIdMappingArray (
1468 This,
1469 CfgMgrProtocol,
1470 IdMapArray,
1471 NodeList->IdMappingCount,
1472 NodeList->IdMappingToken
1473 );
1474 if (EFI_ERROR (Status)) {
1475 DEBUG ((
1476 DEBUG_ERROR,
1477 "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
1478 Status
1479 ));
1480 return Status;
1481 }
1482 }
1483
1484 // Next SMMU v1/v2 Node
1485 SmmuNode = (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE *)((UINT8 *)SmmuNode +
1486 SmmuNode->Node.Length);
1487 NodeList++;
1488 } // SMMU v1/v2 Node
1489
1490 return EFI_SUCCESS;
1491}
1492
1510STATIC
1517 IN CONST UINT32 NodesStartOffset,
1518 IN CONST CM_ARM_SMMUV3_NODE *NodeList,
1519 IN UINT32 NodeCount
1520 )
1521{
1522 EFI_STATUS Status;
1525 UINT64 NodeLength;
1526
1527 ASSERT (Iort != NULL);
1528
1529 SmmuV3Node = (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE *)((UINT8 *)Iort +
1530 NodesStartOffset);
1531
1532 while (NodeCount-- != 0) {
1533 NodeLength = GetSmmuV3NodeSize (NodeList);
1534 if (NodeLength > MAX_UINT16) {
1535 Status = EFI_INVALID_PARAMETER;
1536 DEBUG ((
1537 DEBUG_ERROR,
1538 "ERROR: IORT: SMMU V3 Node length 0x%lx > MAX_UINT16. Status = %r\n",
1539 NodeLength,
1540 Status
1541 ));
1542 return Status;
1543 }
1544
1545 // Populate the node header
1546 SmmuV3Node->Node.Type = EFI_ACPI_IORT_TYPE_SMMUv3;
1547 SmmuV3Node->Node.Length = (UINT16)NodeLength;
1548 SmmuV3Node->Node.NumIdMappings = NodeList->IdMappingCount;
1549 SmmuV3Node->Node.IdReference = (NodeList->IdMappingCount == 0) ?
1551
1552 if (AcpiTableInfo->AcpiTableRevision <
1553 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
1554 {
1555 SmmuV3Node->Node.Revision = 2;
1556 SmmuV3Node->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
1557 } else {
1558 SmmuV3Node->Node.Revision = 4;
1559 SmmuV3Node->Node.Identifier = NodeList->Identifier;
1560 }
1561
1562 // SMMUv3 specific data
1563 SmmuV3Node->Base = NodeList->BaseAddress;
1564 SmmuV3Node->Flags = NodeList->Flags;
1565 SmmuV3Node->Reserved = EFI_ACPI_RESERVED_WORD;
1566 SmmuV3Node->VatosAddress = NodeList->VatosAddress;
1567 SmmuV3Node->Model = NodeList->Model;
1568 SmmuV3Node->Event = NodeList->EventInterrupt;
1569 SmmuV3Node->Pri = NodeList->PriInterrupt;
1570 SmmuV3Node->Gerr = NodeList->GerrInterrupt;
1571 SmmuV3Node->Sync = NodeList->SyncInterrupt;
1572
1573 if ((SmmuV3Node->Flags & EFI_ACPI_IORT_SMMUv3_FLAG_PROXIMITY_DOMAIN) != 0) {
1574 // The Proximity Domain Valid flag is set to 1
1575 SmmuV3Node->ProximityDomain = NodeList->ProximityDomain;
1576 } else {
1577 SmmuV3Node->ProximityDomain = 0;
1578 }
1579
1580 if ((SmmuV3Node->Event != 0) && (SmmuV3Node->Pri != 0) &&
1581 (SmmuV3Node->Gerr != 0) && (SmmuV3Node->Sync != 0))
1582 {
1583 // If all the SMMU control interrupts are GSIV based,
1584 // the DeviceID mapping index field is ignored.
1585 SmmuV3Node->DeviceIdMappingIndex = 0;
1586 } else {
1587 SmmuV3Node->DeviceIdMappingIndex = NodeList->DeviceIdMappingIndex;
1588 }
1589
1590 if (NodeList->IdMappingCount > 0) {
1591 if (NodeList->IdMappingToken == CM_NULL_TOKEN) {
1592 Status = EFI_INVALID_PARAMETER;
1593 DEBUG ((
1594 DEBUG_ERROR,
1595 "ERROR: IORT: Invalid Id Mapping token,"
1596 " Token = 0x%x, Status =%r\n",
1597 NodeList->IdMappingToken,
1598 Status
1599 ));
1600 return Status;
1601 }
1602
1603 // Ids for SMMUv3 node
1604 IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE *)((UINT8 *)SmmuV3Node +
1605 SmmuV3Node->Node.IdReference);
1606 Status = AddIdMappingArray (
1607 This,
1608 CfgMgrProtocol,
1609 IdMapArray,
1610 NodeList->IdMappingCount,
1611 NodeList->IdMappingToken
1612 );
1613 if (EFI_ERROR (Status)) {
1614 DEBUG ((
1615 DEBUG_ERROR,
1616 "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
1617 Status
1618 ));
1619 return Status;
1620 }
1621 }
1622
1623 // Next SMMUv3 Node
1624 SmmuV3Node = (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE *)((UINT8 *)SmmuV3Node +
1625 SmmuV3Node->Node.Length);
1626 NodeList++;
1627 } // SMMUv3 Node
1628
1629 return EFI_SUCCESS;
1630}
1631
1649STATIC
1656 IN CONST UINT32 NodesStartOffset,
1657 IN CONST CM_ARM_PMCG_NODE *NodeList,
1658 IN UINT32 NodeCount
1659 )
1660{
1661 EFI_STATUS Status;
1665 UINT64 NodeLength;
1666
1667 ASSERT (Iort != NULL);
1668
1670 PmcgNode = (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE *)((UINT8 *)Iort +
1671 NodesStartOffset);
1672
1673 while (NodeCount-- != 0) {
1674 NodeLength = GetPmcgNodeSize (NodeList);
1675 if (NodeLength > MAX_UINT16) {
1676 Status = EFI_INVALID_PARAMETER;
1677 DEBUG ((
1678 DEBUG_ERROR,
1679 "ERROR: IORT: PMCG Node length 0x%lx > MAX_UINT16. Status = %r\n",
1680 NodeLength,
1681 Status
1682 ));
1683 return Status;
1684 }
1685
1686 // Populate the node header
1687 PmcgNode->Node.Type = EFI_ACPI_IORT_TYPE_PMCG;
1688 PmcgNode->Node.Length = (UINT16)NodeLength;
1689 PmcgNode->Node.NumIdMappings = NodeList->IdMappingCount;
1690 PmcgNode->Node.IdReference = (NodeList->IdMappingCount == 0) ?
1692
1693 if (AcpiTableInfo->AcpiTableRevision <
1694 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
1695 {
1696 PmcgNode->Node.Revision = 1;
1697 PmcgNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
1698 } else {
1699 PmcgNode->Node.Revision = 2;
1700 PmcgNode->Node.Identifier = NodeList->Identifier;
1701 }
1702
1703 // PMCG specific data
1704 PmcgNode->Base = NodeList->BaseAddress;
1705 PmcgNode->OverflowInterruptGsiv = NodeList->OverflowInterrupt;
1706 PmcgNode->Page1Base = NodeList->Page1BaseAddress;
1707
1709 Generator->NodeIndexer,
1710 Generator->IortNodeCount,
1711 NodeList->ReferenceToken,
1712 &PmcgNode->NodeReference
1713 );
1714 if (EFI_ERROR (Status)) {
1715 DEBUG ((
1716 DEBUG_ERROR,
1717 "ERROR: IORT: Failed to get Output Reference for PMCG Node."
1718 "Reference Token = %p"
1719 " Status = %r\n",
1720 NodeList->ReferenceToken,
1721 Status
1722 ));
1723 return Status;
1724 }
1725
1726 if (NodeList->IdMappingCount > 0) {
1727 if (NodeList->IdMappingToken == CM_NULL_TOKEN) {
1728 Status = EFI_INVALID_PARAMETER;
1729 DEBUG ((
1730 DEBUG_ERROR,
1731 "ERROR: IORT: Invalid Id Mapping token,"
1732 " Token = 0x%x, Status =%r\n",
1733 NodeList->IdMappingToken,
1734 Status
1735 ));
1736 return Status;
1737 }
1738
1739 // Ids for PMCG node
1740 IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE *)((UINT8 *)PmcgNode +
1741 PmcgNode->Node.IdReference);
1742
1743 Status = AddIdMappingArray (
1744 This,
1745 CfgMgrProtocol,
1746 IdMapArray,
1747 NodeList->IdMappingCount,
1748 NodeList->IdMappingToken
1749 );
1750 if (EFI_ERROR (Status)) {
1751 DEBUG ((
1752 DEBUG_ERROR,
1753 "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
1754 Status
1755 ));
1756 return Status;
1757 }
1758 }
1759
1760 // Next PMCG Node
1761 PmcgNode = (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE *)((UINT8 *)PmcgNode +
1762 PmcgNode->Node.Length);
1763 NodeList++;
1764 } // PMCG Node
1765
1766 return EFI_SUCCESS;
1767}
1768
1787STATIC
1793 IN UINT32 DescCount,
1794 IN CONST CM_OBJECT_TOKEN DescToken
1795 )
1796{
1797 EFI_STATUS Status;
1798 CM_ARM_MEMORY_RANGE_DESCRIPTOR *MemRangeDesc;
1799 UINT32 MemRangeDescCount;
1800
1801 ASSERT (DescArray != NULL);
1802
1803 // Get the Id Mapping Array
1804 Status = GetEArmObjMemoryRangeDescriptor (
1805 CfgMgrProtocol,
1806 DescToken,
1807 &MemRangeDesc,
1808 &MemRangeDescCount
1809 );
1810 if (EFI_ERROR (Status)) {
1811 DEBUG ((
1812 DEBUG_ERROR,
1813 "ERROR: IORT: Failed to get Memory Range Descriptor array. Status = %r\n",
1814 Status
1815 ));
1816 return Status;
1817 }
1818
1819 if (MemRangeDescCount < DescCount) {
1820 DEBUG ((
1821 DEBUG_ERROR,
1822 "ERROR: IORT: Failed to get the required number of Memory"
1823 " Range Descriptors.\n"
1824 ));
1825 return EFI_NOT_FOUND;
1826 }
1827
1828 // Populate the Memory Range Descriptor array
1829 while (DescCount-- != 0) {
1830 DescArray->Base = MemRangeDesc->BaseAddress;
1831 DescArray->Length = MemRangeDesc->Length;
1832 DescArray->Reserved = EFI_ACPI_RESERVED_DWORD;
1833
1834 DescArray++;
1835 MemRangeDesc++;
1836 }
1837
1838 return EFI_SUCCESS;
1839}
1840
1858STATIC
1865 IN CONST UINT32 NodesStartOffset,
1866 IN CONST CM_ARM_RMR_NODE *NodeList,
1867 IN UINT32 NodeCount
1868 )
1869{
1870 EFI_STATUS Status;
1874 UINT64 NodeLength;
1875
1876 ASSERT (Iort != NULL);
1877
1878 RmrNode = (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE *)((UINT8 *)Iort +
1879 NodesStartOffset);
1880
1881 while (NodeCount-- != 0) {
1882 NodeLength = GetRmrNodeSize (NodeList);
1883 if (NodeLength > MAX_UINT16) {
1884 Status = EFI_INVALID_PARAMETER;
1885 DEBUG ((
1886 DEBUG_ERROR,
1887 "ERROR: IORT: RMR Node length 0x%lx > MAX_UINT16. Status = %r\n",
1888 NodeLength,
1889 Status
1890 ));
1891 return Status;
1892 }
1893
1894 if (NodeList->MemRangeDescCount == 0) {
1895 Status = EFI_INVALID_PARAMETER;
1896 DEBUG ((
1897 DEBUG_ERROR,
1898 "ERROR: IORT: Memory Range Desc count = %d. Status = %r\n",
1899 NodeList->MemRangeDescCount,
1900 Status
1901 ));
1902 return Status;
1903 }
1904
1905 if (NodeList->MemRangeDescToken == CM_NULL_TOKEN) {
1906 Status = EFI_INVALID_PARAMETER;
1907 DEBUG ((
1908 DEBUG_ERROR,
1909 "ERROR: IORT: Invalid Memory Range Descriptor token,"
1910 " Token = 0x%x. Status = %r\n",
1911 NodeList->MemRangeDescToken,
1912 Status
1913 ));
1914 return Status;
1915 }
1916
1917 // Populate the node header
1918 RmrNode->Node.Type = EFI_ACPI_IORT_TYPE_RMR;
1919 RmrNode->Node.Length = (UINT16)NodeLength;
1920 RmrNode->Node.Revision = 3;
1921 RmrNode->Node.Identifier = NodeList->Identifier;
1922 RmrNode->Node.NumIdMappings = NodeList->IdMappingCount;
1923 RmrNode->Node.IdReference = (NodeList->IdMappingCount == 0) ?
1925
1926 // RMR specific data
1927 RmrNode->Flags = NodeList->Flags;
1928 RmrNode->NumMemRangeDesc = NodeList->MemRangeDescCount;
1929 RmrNode->MemRangeDescRef = (NodeList->MemRangeDescCount == 0) ?
1931 (NodeList->IdMappingCount *
1933
1934 if (NodeList->IdMappingCount > 0) {
1935 if (NodeList->IdMappingToken == CM_NULL_TOKEN) {
1936 Status = EFI_INVALID_PARAMETER;
1937 DEBUG ((
1938 DEBUG_ERROR,
1939 "ERROR: IORT: Invalid Id Mapping token,"
1940 " Token = 0x%x, Status =%r\n",
1941 NodeList->IdMappingToken,
1942 Status
1943 ));
1944 return Status;
1945 }
1946
1947 // Ids for RMR node
1948 IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE *)((UINT8 *)RmrNode +
1949 RmrNode->Node.IdReference);
1950
1951 Status = AddIdMappingArray (
1952 This,
1953 CfgMgrProtocol,
1954 IdMapArray,
1955 NodeList->IdMappingCount,
1956 NodeList->IdMappingToken
1957 );
1958 if (EFI_ERROR (Status)) {
1959 DEBUG ((
1960 DEBUG_ERROR,
1961 "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
1962 Status
1963 ));
1964 return Status;
1965 }
1966 }
1967
1968 // Memory Range Descriptors for RMR node
1969 MemRangeDescArray = (EFI_ACPI_6_0_IO_REMAPPING_MEM_RANGE_DESC *)(
1970 (UINT8 *)RmrNode +
1971 RmrNode->MemRangeDescRef
1972 );
1973
1974 Status = AddMemRangeDescArray (
1975 This,
1976 CfgMgrProtocol,
1977 MemRangeDescArray,
1978 NodeList->MemRangeDescCount,
1979 NodeList->MemRangeDescToken
1980 );
1981 if (EFI_ERROR (Status)) {
1982 DEBUG ((
1983 DEBUG_ERROR,
1984 "ERROR: IORT: Failed to Memory Range Descriptor Array. Status = %r\n",
1985 Status
1986 ));
1987 return Status;
1988 }
1989
1990 // Next RMR Node
1991 RmrNode = (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE *)((UINT8 *)RmrNode +
1992 RmrNode->Node.Length);
1993 NodeList++;
1994 } // RMR Node
1995
1996 return EFI_SUCCESS;
1997}
1998
2007STATIC
2010 IN CONST IORT_NODE_INDEXER *CONST NodeIndexer,
2011 IN UINT32 NodeCount
2012 )
2013{
2014 UINT32 IndexI;
2015 UINT32 IndexJ;
2016
2017 for (IndexI = 0; IndexI < NodeCount; IndexI++) {
2018 for (IndexJ = 0; IndexJ < NodeCount; IndexJ++) {
2019 if ((IndexI != IndexJ) &&
2020 (NodeIndexer[IndexI].Identifier == NodeIndexer[IndexJ].Identifier))
2021 {
2022 DEBUG ((
2023 DEBUG_ERROR,
2024 "ERROR: IORT: UID %d of Token %p matches with that of Token %p.\n",
2025 NodeIndexer[IndexI].Identifier,
2026 NodeIndexer[IndexI].Token,
2027 NodeIndexer[IndexJ].Token
2028 ));
2029 return EFI_INVALID_PARAMETER;
2030 }
2031 }// IndexJ
2032 } // IndexI
2033
2034 return EFI_SUCCESS;
2035}
2036
2059STATIC
2061EFIAPI
2067 )
2068{
2069 EFI_STATUS Status;
2070
2071 UINT64 TableSize;
2072 UINT64 NodeSize;
2073
2074 UINT32 IortNodeCount;
2075 UINT32 ItsGroupNodeCount;
2076 UINT32 NamedComponentNodeCount;
2077 UINT32 RootComplexNodeCount;
2078 UINT32 SmmuV1V2NodeCount;
2079 UINT32 SmmuV3NodeCount;
2080 UINT32 PmcgNodeCount;
2081 UINT32 RmrNodeCount;
2082
2083 UINT32 ItsGroupOffset;
2084 UINT32 NamedComponentOffset;
2085 UINT32 RootComplexOffset;
2086 UINT32 SmmuV1V2Offset;
2087 UINT32 SmmuV3Offset;
2088 UINT32 PmcgOffset;
2089 UINT32 RmrOffset;
2090
2091 CM_ARM_ITS_GROUP_NODE *ItsGroupNodeList;
2092 CM_ARM_NAMED_COMPONENT_NODE *NamedComponentNodeList;
2093 CM_ARM_ROOT_COMPLEX_NODE *RootComplexNodeList;
2094 CM_ARM_SMMUV1_SMMUV2_NODE *SmmuV1V2NodeList;
2095 CM_ARM_SMMUV3_NODE *SmmuV3NodeList;
2096 CM_ARM_PMCG_NODE *PmcgNodeList;
2097 CM_ARM_RMR_NODE *RmrNodeList;
2098
2100 IORT_NODE_INDEXER *NodeIndexer;
2102
2103 ASSERT (This != NULL);
2104 ASSERT (AcpiTableInfo != NULL);
2105 ASSERT (CfgMgrProtocol != NULL);
2106 ASSERT (Table != NULL);
2107 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
2108 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
2109
2110 RmrNodeCount = 0;
2111
2112 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
2113 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))
2114 {
2115 DEBUG ((
2116 DEBUG_ERROR,
2117 "ERROR: IORT: Requested table revision = %d, is not supported."
2118 "Supported table revision: Minimum = %d, Maximum = %d\n",
2119 AcpiTableInfo->AcpiTableRevision,
2120 This->MinAcpiTableRevision,
2121 This->AcpiTableRevision
2122 ));
2123 return EFI_INVALID_PARAMETER;
2124 }
2125
2126 if ((AcpiTableInfo->AcpiTableRevision > EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00) &&
2127 (AcpiTableInfo->AcpiTableRevision < EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05))
2128 {
2129 DEBUG ((
2130 DEBUG_ERROR,
2131 "ERROR: IORT: Revisions E (1), E.a(2),b(3),c(4) are not supported.\n"
2132 ));
2133 return EFI_INVALID_PARAMETER;
2134 }
2135
2137 *Table = NULL;
2138
2139 // Get the ITS group node info
2140 Status = GetEArmObjItsGroup (
2141 CfgMgrProtocol,
2143 &ItsGroupNodeList,
2144 &ItsGroupNodeCount
2145 );
2146 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
2147 DEBUG ((
2148 DEBUG_ERROR,
2149 "ERROR: IORT: Failed to get ITS Group Node Info. Status = %r\n",
2150 Status
2151 ));
2152 goto error_handler;
2153 }
2154
2155 // Add the ITS group node count
2156 IortNodeCount = ItsGroupNodeCount;
2157
2158 // Get the Named component node info
2159 Status = GetEArmObjNamedComponent (
2160 CfgMgrProtocol,
2162 &NamedComponentNodeList,
2163 &NamedComponentNodeCount
2164 );
2165 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
2166 DEBUG ((
2167 DEBUG_ERROR,
2168 "ERROR: IORT: Failed to get Named Component Node Info. Status = %r\n",
2169 Status
2170 ));
2171 goto error_handler;
2172 }
2173
2174 // Add the Named Component group count
2175 IortNodeCount += NamedComponentNodeCount;
2176
2177 // Get the Root complex node info
2178 Status = GetEArmObjRootComplex (
2179 CfgMgrProtocol,
2181 &RootComplexNodeList,
2182 &RootComplexNodeCount
2183 );
2184 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
2185 DEBUG ((
2186 DEBUG_ERROR,
2187 "ERROR: IORT: Failed to get Root Complex Node Info. Status = %r\n",
2188 Status
2189 ));
2190 goto error_handler;
2191 }
2192
2193 // Add the Root Complex node count
2194 IortNodeCount += RootComplexNodeCount;
2195
2196 // Get the SMMU v1/v2 node info
2197 Status = GetEArmObjSmmuV1SmmuV2 (
2198 CfgMgrProtocol,
2200 &SmmuV1V2NodeList,
2201 &SmmuV1V2NodeCount
2202 );
2203 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
2204 DEBUG ((
2205 DEBUG_ERROR,
2206 "ERROR: IORT: Failed to get SMMUv1/SMMUv2 Node Info. Status = %r\n",
2207 Status
2208 ));
2209 goto error_handler;
2210 }
2211
2212 // Add the SMMU v1/v2 node count
2213 IortNodeCount += SmmuV1V2NodeCount;
2214
2215 // Get the SMMUv3 node info
2216 Status = GetEArmObjSmmuV3 (
2217 CfgMgrProtocol,
2219 &SmmuV3NodeList,
2220 &SmmuV3NodeCount
2221 );
2222 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
2223 DEBUG ((
2224 DEBUG_ERROR,
2225 "ERROR: IORT: Failed to get SMMUv3 Node Info. Status = %r\n",
2226 Status
2227 ));
2228 goto error_handler;
2229 }
2230
2231 // Add the SMMUv3 node count
2232 IortNodeCount += SmmuV3NodeCount;
2233
2234 // Get the PMCG node info
2235 Status = GetEArmObjPmcg (
2236 CfgMgrProtocol,
2238 &PmcgNodeList,
2239 &PmcgNodeCount
2240 );
2241 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
2242 DEBUG ((
2243 DEBUG_ERROR,
2244 "ERROR: IORT: Failed to get PMCG Node Info. Status = %r\n",
2245 Status
2246 ));
2247 goto error_handler;
2248 }
2249
2250 // Add the PMCG node count
2251 IortNodeCount += PmcgNodeCount;
2252
2253 if (AcpiTableInfo->AcpiTableRevision >=
2254 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
2255 {
2256 // Get the RMR node info
2257 Status = GetEArmObjRmr (
2258 CfgMgrProtocol,
2260 &RmrNodeList,
2261 &RmrNodeCount
2262 );
2263 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
2264 DEBUG ((
2265 DEBUG_ERROR,
2266 "ERROR: IORT: Failed to get RMR Node Info. Status = %r\n",
2267 Status
2268 ));
2269 goto error_handler;
2270 }
2271
2272 // Add the RMR node count
2273 IortNodeCount += RmrNodeCount;
2274 }
2275
2276 // Allocate Node Indexer array
2277 NodeIndexer = (IORT_NODE_INDEXER *)AllocateZeroPool (
2278 (sizeof (IORT_NODE_INDEXER) *
2279 IortNodeCount)
2280 );
2281 if (NodeIndexer == NULL) {
2282 Status = EFI_OUT_OF_RESOURCES;
2283 DEBUG ((
2284 DEBUG_ERROR,
2285 "ERROR: IORT: Failed to allocate memory for Node Indexer" \
2286 " Status = %r\n",
2287 Status
2288 ));
2289 goto error_handler;
2290 }
2291
2292 DEBUG ((DEBUG_INFO, "INFO: NodeIndexer = %p\n", NodeIndexer));
2293 Generator->IortNodeCount = IortNodeCount;
2294 Generator->NodeIndexer = NodeIndexer;
2295
2296 // Calculate the size of the IORT table
2297 TableSize = sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE);
2298
2299 // ITS Group Nodes
2300 if (ItsGroupNodeCount > 0) {
2301 ItsGroupOffset = (UINT32)TableSize;
2302 // Size of ITS Group node list.
2303 NodeSize = GetSizeofItsGroupNodes (
2304 ItsGroupOffset,
2305 ItsGroupNodeList,
2306 ItsGroupNodeCount,
2307 &NodeIndexer
2308 );
2309 if (NodeSize > MAX_UINT32) {
2310 Status = EFI_INVALID_PARAMETER;
2311 DEBUG ((
2312 DEBUG_ERROR,
2313 "ERROR: IORT: Invalid Size of Group Nodes. Status = %r\n",
2314 Status
2315 ));
2316 goto error_handler;
2317 }
2318
2319 TableSize += NodeSize;
2320
2321 DEBUG ((
2322 DEBUG_INFO,
2323 " ItsGroupNodeCount = %d\n" \
2324 " ItsGroupOffset = %d\n",
2325 ItsGroupNodeCount,
2326 ItsGroupOffset
2327 ));
2328 }
2329
2330 // Named Component Nodes
2331 if (NamedComponentNodeCount > 0) {
2332 NamedComponentOffset = (UINT32)TableSize;
2333 // Size of Named Component node list.
2334 NodeSize = GetSizeofNamedComponentNodes (
2335 NamedComponentOffset,
2336 NamedComponentNodeList,
2337 NamedComponentNodeCount,
2338 &NodeIndexer
2339 );
2340 if (NodeSize > MAX_UINT32) {
2341 Status = EFI_INVALID_PARAMETER;
2342 DEBUG ((
2343 DEBUG_ERROR,
2344 "ERROR: IORT: Invalid Size of Named Component Nodes. Status = %r\n",
2345 Status
2346 ));
2347 goto error_handler;
2348 }
2349
2350 TableSize += NodeSize;
2351
2352 DEBUG ((
2353 DEBUG_INFO,
2354 " NamedComponentNodeCount = %d\n" \
2355 " NamedComponentOffset = %d\n",
2356 NamedComponentNodeCount,
2357 NamedComponentOffset
2358 ));
2359 }
2360
2361 // Root Complex Nodes
2362 if (RootComplexNodeCount > 0) {
2363 RootComplexOffset = (UINT32)TableSize;
2364 // Size of Root Complex node list.
2365 NodeSize = GetSizeofRootComplexNodes (
2366 RootComplexOffset,
2367 RootComplexNodeList,
2368 RootComplexNodeCount,
2369 &NodeIndexer
2370 );
2371 if (NodeSize > MAX_UINT32) {
2372 Status = EFI_INVALID_PARAMETER;
2373 DEBUG ((
2374 DEBUG_ERROR,
2375 "ERROR: IORT: Invalid Size of Root Complex Nodes. Status = %r\n",
2376 Status
2377 ));
2378 goto error_handler;
2379 }
2380
2381 TableSize += NodeSize;
2382
2383 DEBUG ((
2384 DEBUG_INFO,
2385 " RootComplexNodeCount = %d\n" \
2386 " RootComplexOffset = %d\n",
2387 RootComplexNodeCount,
2388 RootComplexOffset
2389 ));
2390 }
2391
2392 // SMMUv1/SMMUv2 Nodes
2393 if (SmmuV1V2NodeCount > 0) {
2394 SmmuV1V2Offset = (UINT32)TableSize;
2395 // Size of SMMUv1/SMMUv2 node list.
2396 NodeSize = GetSizeofSmmuV1V2Nodes (
2397 SmmuV1V2Offset,
2398 SmmuV1V2NodeList,
2399 SmmuV1V2NodeCount,
2400 &NodeIndexer
2401 );
2402 if (NodeSize > MAX_UINT32) {
2403 Status = EFI_INVALID_PARAMETER;
2404 DEBUG ((
2405 DEBUG_ERROR,
2406 "ERROR: IORT: Invalid Size of SMMUv1/v2 Nodes. Status = %r\n",
2407 Status
2408 ));
2409 goto error_handler;
2410 }
2411
2412 TableSize += NodeSize;
2413
2414 DEBUG ((
2415 DEBUG_INFO,
2416 " SmmuV1V2NodeCount = %d\n" \
2417 " SmmuV1V2Offset = %d\n",
2418 SmmuV1V2NodeCount,
2419 SmmuV1V2Offset
2420 ));
2421 }
2422
2423 // SMMUv3 Nodes
2424 if (SmmuV3NodeCount > 0) {
2425 SmmuV3Offset = (UINT32)TableSize;
2426 // Size of SMMUv3 node list.
2427 NodeSize = GetSizeofSmmuV3Nodes (
2428 SmmuV3Offset,
2429 SmmuV3NodeList,
2430 SmmuV3NodeCount,
2431 &NodeIndexer
2432 );
2433 if (NodeSize > MAX_UINT32) {
2434 Status = EFI_INVALID_PARAMETER;
2435 DEBUG ((
2436 DEBUG_ERROR,
2437 "ERROR: IORT: Invalid Size of SMMUv3 Nodes. Status = %r\n",
2438 Status
2439 ));
2440 goto error_handler;
2441 }
2442
2443 TableSize += NodeSize;
2444
2445 DEBUG ((
2446 DEBUG_INFO,
2447 " SmmuV3NodeCount = %d\n" \
2448 " SmmuV3Offset = %d\n",
2449 SmmuV3NodeCount,
2450 SmmuV3Offset
2451 ));
2452 }
2453
2454 // PMCG Nodes
2455 if (PmcgNodeCount > 0) {
2456 PmcgOffset = (UINT32)TableSize;
2457 // Size of PMCG node list.
2458 NodeSize = GetSizeofPmcgNodes (
2459 PmcgOffset,
2460 PmcgNodeList,
2461 PmcgNodeCount,
2462 &NodeIndexer
2463 );
2464 if (NodeSize > MAX_UINT32) {
2465 Status = EFI_INVALID_PARAMETER;
2466 DEBUG ((
2467 DEBUG_ERROR,
2468 "ERROR: IORT: Invalid Size of PMCG Nodes. Status = %r\n",
2469 Status
2470 ));
2471 goto error_handler;
2472 }
2473
2474 TableSize += NodeSize;
2475
2476 DEBUG ((
2477 DEBUG_INFO,
2478 " PmcgNodeCount = %d\n" \
2479 " PmcgOffset = %d\n",
2480 PmcgNodeCount,
2481 PmcgOffset
2482 ));
2483 }
2484
2485 // RMR Nodes
2486 if ((AcpiTableInfo->AcpiTableRevision >=
2487 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) &&
2488 (RmrNodeCount > 0))
2489 {
2490 RmrOffset = (UINT32)TableSize;
2491 // Size of RMR node list.
2492 NodeSize = GetSizeofRmrNodes (
2493 RmrOffset,
2494 RmrNodeList,
2495 RmrNodeCount,
2496 &NodeIndexer
2497 );
2498 if (NodeSize > MAX_UINT32) {
2499 Status = EFI_INVALID_PARAMETER;
2500 DEBUG ((
2501 DEBUG_ERROR,
2502 "ERROR: IORT: Invalid Size of RMR Nodes. Status = %r\n",
2503 Status
2504 ));
2505 goto error_handler;
2506 }
2507
2508 TableSize += NodeSize;
2509
2510 DEBUG ((
2511 DEBUG_INFO,
2512 " RmrNodeCount = %d\n" \
2513 " RmrOffset = %d\n",
2514 RmrNodeCount,
2515 RmrOffset
2516 ));
2517 }
2518
2519 DEBUG ((
2520 DEBUG_INFO,
2521 "INFO: IORT:\n" \
2522 " IortNodeCount = %d\n" \
2523 " TableSize = 0x%lx\n",
2524 IortNodeCount,
2525 TableSize
2526 ));
2527
2528 if (TableSize > MAX_UINT32) {
2529 Status = EFI_INVALID_PARAMETER;
2530 DEBUG ((
2531 DEBUG_ERROR,
2532 "ERROR: IORT: IORT Table Size 0x%lx > MAX_UINT32," \
2533 " Status = %r\n",
2534 TableSize,
2535 Status
2536 ));
2537 goto error_handler;
2538 }
2539
2540 // Validate that the identifiers for the nodes are unique
2541 if (AcpiTableInfo->AcpiTableRevision >=
2542 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
2543 {
2544 Status = ValidateNodeIdentifiers (Generator->NodeIndexer, IortNodeCount);
2545 if (EFI_ERROR (Status)) {
2546 DEBUG ((
2547 DEBUG_ERROR,
2548 "ERROR: IORT: Node Identifier not unique. Status = %r\n",
2549 Status
2550 ));
2551 goto error_handler;
2552 }
2553 }
2554
2555 // Allocate the Buffer for IORT table
2556 *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
2557 if (*Table == NULL) {
2558 Status = EFI_OUT_OF_RESOURCES;
2559 DEBUG ((
2560 DEBUG_ERROR,
2561 "ERROR: IORT: Failed to allocate memory for IORT Table, Size = %d," \
2562 " Status = %r\n",
2563 TableSize,
2564 Status
2565 ));
2566 goto error_handler;
2567 }
2568
2569 Iort = (EFI_ACPI_6_0_IO_REMAPPING_TABLE *)*Table;
2570
2571 DEBUG ((
2572 DEBUG_INFO,
2573 "IORT: Iort = 0x%p TableSize = 0x%lx\n",
2574 Iort,
2575 TableSize
2576 ));
2577
2578 Status = AddAcpiHeader (
2579 CfgMgrProtocol,
2580 This,
2581 &Iort->Header,
2582 AcpiTableInfo,
2583 (UINT32)TableSize
2584 );
2585 if (EFI_ERROR (Status)) {
2586 DEBUG ((
2587 DEBUG_ERROR,
2588 "ERROR: IORT: Failed to add ACPI header. Status = %r\n",
2589 Status
2590 ));
2591 goto error_handler;
2592 }
2593
2594 // Update IORT table
2595 Iort->NumNodes = IortNodeCount;
2596 Iort->NodeOffset = sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE);
2597 Iort->Reserved = EFI_ACPI_RESERVED_DWORD;
2598
2599 if (ItsGroupNodeCount > 0) {
2600 Status = AddItsGroupNodes (
2601 This,
2602 CfgMgrProtocol,
2603 AcpiTableInfo,
2604 Iort,
2605 ItsGroupOffset,
2606 ItsGroupNodeList,
2607 ItsGroupNodeCount
2608 );
2609 if (EFI_ERROR (Status)) {
2610 DEBUG ((
2611 DEBUG_ERROR,
2612 "ERROR: IORT: Failed to add ITS Group Node. Status = %r\n",
2613 Status
2614 ));
2615 goto error_handler;
2616 }
2617 }
2618
2619 if (NamedComponentNodeCount > 0) {
2620 Status = AddNamedComponentNodes (
2621 This,
2622 CfgMgrProtocol,
2623 AcpiTableInfo,
2624 Iort,
2625 NamedComponentOffset,
2626 NamedComponentNodeList,
2627 NamedComponentNodeCount
2628 );
2629 if (EFI_ERROR (Status)) {
2630 DEBUG ((
2631 DEBUG_ERROR,
2632 "ERROR: IORT: Failed to add Named Component Node. Status = %r\n",
2633 Status
2634 ));
2635 goto error_handler;
2636 }
2637 }
2638
2639 if (RootComplexNodeCount > 0) {
2640 Status = AddRootComplexNodes (
2641 This,
2642 CfgMgrProtocol,
2643 AcpiTableInfo,
2644 Iort,
2645 RootComplexOffset,
2646 RootComplexNodeList,
2647 RootComplexNodeCount
2648 );
2649 if (EFI_ERROR (Status)) {
2650 DEBUG ((
2651 DEBUG_ERROR,
2652 "ERROR: IORT: Failed to add Root Complex Node. Status = %r\n",
2653 Status
2654 ));
2655 goto error_handler;
2656 }
2657 }
2658
2659 if (SmmuV1V2NodeCount > 0) {
2660 Status = AddSmmuV1V2Nodes (
2661 This,
2662 CfgMgrProtocol,
2663 AcpiTableInfo,
2664 Iort,
2665 SmmuV1V2Offset,
2666 SmmuV1V2NodeList,
2667 SmmuV1V2NodeCount
2668 );
2669 if (EFI_ERROR (Status)) {
2670 DEBUG ((
2671 DEBUG_ERROR,
2672 "ERROR: IORT: Failed to add SMMU v1/v2 Node. Status = %r\n",
2673 Status
2674 ));
2675 goto error_handler;
2676 }
2677 }
2678
2679 if (SmmuV3NodeCount > 0) {
2680 Status = AddSmmuV3Nodes (
2681 This,
2682 CfgMgrProtocol,
2683 AcpiTableInfo,
2684 Iort,
2685 SmmuV3Offset,
2686 SmmuV3NodeList,
2687 SmmuV3NodeCount
2688 );
2689 if (EFI_ERROR (Status)) {
2690 DEBUG ((
2691 DEBUG_ERROR,
2692 "ERROR: IORT: Failed to add SMMUv3 Node. Status = %r\n",
2693 Status
2694 ));
2695 goto error_handler;
2696 }
2697 }
2698
2699 if (PmcgNodeCount > 0) {
2700 Status = AddPmcgNodes (
2701 This,
2702 CfgMgrProtocol,
2703 AcpiTableInfo,
2704 Iort,
2705 PmcgOffset,
2706 PmcgNodeList,
2707 PmcgNodeCount
2708 );
2709 if (EFI_ERROR (Status)) {
2710 DEBUG ((
2711 DEBUG_ERROR,
2712 "ERROR: IORT: Failed to add PMCG Node. Status = %r\n",
2713 Status
2714 ));
2715 goto error_handler;
2716 }
2717 }
2718
2719 if ((AcpiTableInfo->AcpiTableRevision >=
2720 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) &&
2721 (RmrNodeCount > 0))
2722 {
2723 Status = AddRmrNodes (
2724 This,
2725 CfgMgrProtocol,
2726 AcpiTableInfo,
2727 Iort,
2728 RmrOffset,
2729 RmrNodeList,
2730 RmrNodeCount
2731 );
2732 if (EFI_ERROR (Status)) {
2733 DEBUG ((
2734 DEBUG_ERROR,
2735 "ERROR: IORT: Failed to add RMR Node. Status = %r\n",
2736 Status
2737 ));
2738 goto error_handler;
2739 }
2740 }
2741
2742 return EFI_SUCCESS;
2743
2744error_handler:
2745 if (Generator->NodeIndexer != NULL) {
2746 FreePool (Generator->NodeIndexer);
2747 Generator->NodeIndexer = NULL;
2748 }
2749
2750 if (*Table != NULL) {
2751 FreePool (*Table);
2752 *Table = NULL;
2753 }
2754
2755 return Status;
2756}
2757
2769STATIC
2776 )
2777{
2779
2780 ASSERT (This != NULL);
2781 ASSERT (AcpiTableInfo != NULL);
2782 ASSERT (CfgMgrProtocol != NULL);
2783 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
2784 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
2785
2787
2788 // Free any memory allocated by the generator
2789 if (Generator->NodeIndexer != NULL) {
2790 FreePool (Generator->NodeIndexer);
2791 Generator->NodeIndexer = NULL;
2792 }
2793
2794 if ((Table == NULL) || (*Table == NULL)) {
2795 DEBUG ((DEBUG_ERROR, "ERROR: IORT: Invalid Table Pointer\n"));
2796 ASSERT ((Table != NULL) && (*Table != NULL));
2797 return EFI_INVALID_PARAMETER;
2798 }
2799
2800 FreePool (*Table);
2801 *Table = NULL;
2802 return EFI_SUCCESS;
2803}
2804
2807#define IORT_GENERATOR_REVISION CREATE_REVISION (1, 0)
2808
2811STATIC
2813 // ACPI table generator header
2814 {
2815 // Generator ID
2817 // Generator Description
2818 L"ACPI.STD.IORT.GENERATOR",
2819 // ACPI Table Signature
2821 // ACPI Table Revision supported by this Generator
2822 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05,
2823 // Minimum supported ACPI Table Revision
2824 EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00,
2825 // Creator ID
2827 // Creator Revision
2829 // Build Table function
2831 // Free Resource function
2833 // Extended build function not needed
2834 NULL,
2835 // Extended build function not implemented by the generator.
2836 // Hence extended free resource function is not required.
2837 NULL
2838 },
2839
2840 // IORT Generator private data
2841
2842 // Iort Node count
2843 0,
2844 // Pointer to Iort node indexer
2845 NULL
2846};
2847
2859EFIAPI
2861 IN EFI_HANDLE ImageHandle,
2862 IN EFI_SYSTEM_TABLE *SystemTable
2863 )
2864{
2865 EFI_STATUS Status;
2866
2868 DEBUG ((DEBUG_INFO, "IORT: Register Generator. Status = %r\n", Status));
2869 ASSERT_EFI_ERROR (Status);
2870 return Status;
2871}
2872
2883EFIAPI
2885 IN EFI_HANDLE ImageHandle,
2886 IN EFI_SYSTEM_TABLE *SystemTable
2887 )
2888{
2889 EFI_STATUS Status;
2890
2892 DEBUG ((DEBUG_INFO, "Iort: Deregister Generator. Status = %r\n", Status));
2893 ASSERT_EFI_ERROR (Status);
2894 return Status;
2895}
UINT64 UINTN
#define EFI_ACPI_6_4_IO_REMAPPING_TABLE_SIGNATURE
Definition: Acpi64.h:3065
EFI_STATUS EFIAPI RegisterAcpiTableGenerator(IN CONST ACPI_TABLE_GENERATOR *CONST Generator)
EFI_STATUS EFIAPI DeregisterAcpiTableGenerator(IN CONST ACPI_TABLE_GENERATOR *CONST Generator)
#define TABLE_GENERATOR_CREATOR_ID_ARM
#define CREATE_STD_ACPI_TABLE_GEN_ID(TableId)
@ EStdAcpiTableIdIort
IORT Generator.
@ EArmObjSmmuV3
15 - SMMUv3
@ EArmObjPmcg
16 - PMCG
@ EArmObjIdMappingArray
18 - ID Mapping Array
@ EArmObjSmmuV1SmmuV2
14 - SMMUv1 or SMMUv2
@ EArmObjRmr
21 - Reserved Memory Range Node
@ EArmObjSmmuInterruptArray
19 - SMMU Interrupt Array
@ EArmObjItsGroup
11 - ITS Group
@ EArmObjMemoryRangeDescriptor
22 - Memory Range Descriptor
@ EArmObjNamedComponent
12 - Named Component
@ EArmObjRootComplex
13 - Root Complex
@ EArmObjGicItsIdentifierArray
17 - GIC ITS Identifier Array
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
UINTN EFIAPI AsciiStrSize(IN CONST CHAR8 *String)
Definition: String.c:681
RETURN_STATUS EFIAPI AsciiStrCpyS(OUT CHAR8 *Destination, IN UINTN DestMax, IN CONST CHAR8 *Source)
Definition: SafeString.c:1797
#define GET_OBJECT_LIST(CmObjectNameSpace, CmObjectId, Type)
@ EObjNameSpaceArm
ARM Objects Namespace.
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
STATIC UINT32 GetRootComplexNodeSize(IN CONST CM_ARM_ROOT_COMPLEX_NODE *Node)
STATIC UINT32 GetItsGroupNodeSize(IN CONST CM_ARM_ITS_GROUP_NODE *Node)
STATIC EFI_STATUS AddNamedComponentNodes(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_NAMED_COMPONENT_NODE *NodeList, IN UINT32 NodeCount)
STATIC UINT32 GetSmmuV3NodeSize(IN CONST CM_ARM_SMMUV3_NODE *Node)
STATIC UINT32 GetPmcgNodeSize(IN CONST CM_ARM_PMCG_NODE *Node)
STATIC UINT64 GetSizeofPmcgNodes(IN CONST UINT32 NodeStartOffset, IN CONST CM_ARM_PMCG_NODE *NodeList, IN UINT32 NodeCount, IN OUT IORT_NODE_INDEXER **CONST NodeIndexer)
STATIC UINT64 GetSizeofItsGroupNodes(IN CONST UINT32 NodeStartOffset, IN CONST CM_ARM_ITS_GROUP_NODE *NodeList, IN UINT32 NodeCount, IN OUT IORT_NODE_INDEXER **CONST NodeIndexer)
STATIC UINT64 GetSizeofNamedComponentNodes(IN CONST UINT32 NodeStartOffset, IN CONST CM_ARM_NAMED_COMPONENT_NODE *NodeList, IN UINT32 NodeCount, IN OUT IORT_NODE_INDEXER **CONST NodeIndexer)
STATIC UINT32 GetSmmuV1V2NodeSize(IN CONST CM_ARM_SMMUV1_SMMUV2_NODE *Node)
STATIC ACPI_IORT_GENERATOR IortGenerator
#define IORT_GENERATOR_REVISION
STATIC EFI_STATUS AddPmcgNodes(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_PMCG_NODE *NodeList, IN UINT32 NodeCount)
STATIC UINT64 GetSizeofSmmuV3Nodes(IN CONST UINT32 NodeStartOffset, IN CONST CM_ARM_SMMUV3_NODE *NodeList, IN UINT32 NodeCount, IN OUT IORT_NODE_INDEXER **CONST NodeIndexer)
STATIC EFI_STATUS AddRmrNodes(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_RMR_NODE *NodeList, IN UINT32 NodeCount)
EFI_STATUS EFIAPI AcpiIortLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
STATIC UINT64 GetSizeofSmmuV1V2Nodes(IN CONST UINT32 NodeStartOffset, IN CONST CM_ARM_SMMUV1_SMMUV2_NODE *NodeList, IN UINT32 NodeCount, IN OUT IORT_NODE_INDEXER **CONST NodeIndexer)
STATIC EFI_STATUS AddRootComplexNodes(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_ROOT_COMPLEX_NODE *NodeList, IN UINT32 NodeCount)
STATIC EFI_STATUS ValidateNodeIdentifiers(IN CONST IORT_NODE_INDEXER *CONST NodeIndexer, IN UINT32 NodeCount)
STATIC EFI_STATUS AddMemRangeDescArray(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN EFI_ACPI_6_0_IO_REMAPPING_MEM_RANGE_DESC *DescArray, IN UINT32 DescCount, IN CONST CM_OBJECT_TOKEN DescToken)
STATIC UINT32 GetNamedComponentNodeSize(IN CONST CM_ARM_NAMED_COMPONENT_NODE *Node)
STATIC EFI_STATUS AddSmmuV3Nodes(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_SMMUV3_NODE *NodeList, IN UINT32 NodeCount)
STATIC UINT64 GetSizeofRmrNodes(IN CONST UINT32 NodeStartOffset, IN CONST CM_ARM_RMR_NODE *NodeList, IN UINT32 NodeCount, IN OUT IORT_NODE_INDEXER **CONST NodeIndexer)
STATIC EFI_STATUS AddItsGroupNodes(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_ITS_GROUP_NODE *NodeList, IN UINT32 NodeCount)
EFI_STATUS EFIAPI AcpiIortLibDestructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
STATIC EFI_STATUS AddIdMappingArray(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE *IdMapArray, IN UINT32 IdCount, IN CONST CM_OBJECT_TOKEN IdMappingToken)
STATIC EFI_STATUS FreeIortTableResources(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table)
STATIC UINT32 GetRmrNodeSize(IN CONST CM_ARM_RMR_NODE *Node)
STATIC EFI_STATUS AddSmmuV1V2Nodes(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_SMMUV1_SMMUV2_NODE *NodeList, IN UINT32 NodeCount)
STATIC EFI_STATUS GetNodeOffsetReferencedByToken(IN IORT_NODE_INDEXER *NodeIndexer, IN UINT32 NodeCount, IN CM_OBJECT_TOKEN Token, OUT UINT32 *NodeOffset)
STATIC EFI_STATUS EFIAPI BuildIortTable(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table)
STATIC EFI_STATUS AddSmmuInterruptArray(IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN OUT EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT *InterruptArray, IN UINT32 InterruptCount, IN CONST CM_OBJECT_TOKEN InterruptToken)
STATIC UINT64 GetSizeofRootComplexNodes(IN CONST UINT32 NodeStartOffset, IN CONST CM_ARM_ROOT_COMPLEX_NODE *NodeList, IN UINT32 NodeCount, IN OUT IORT_NODE_INDEXER **CONST NodeIndexer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define ALIGN_VALUE(Value, Alignment)
Definition: Base.h:948
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
UINTN CM_OBJECT_TOKEN
#define CM_NULL_TOKEN
EFI_STATUS EFIAPI AddAcpiHeader(IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST ACPI_TABLE_GENERATOR *CONST Generator, IN OUT EFI_ACPI_DESCRIPTION_HEADER *CONST AcpiHeader, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST UINT32 Length)
Definition: TableHelper.c:114
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
ACPI_TABLE_GENERATOR Header
ACPI Table generator header.
Definition: IortGenerator.h:35
UINT32 ItsId
The ITS Identifier.
CM_OBJECT_TOKEN OutputReferenceToken
Reference token for the output node.
UINT32 OutputBase
Output Base.
UINT32 NumIds
Number of input IDs.
UINT32 InputBase
Input base.
UINT32 MemRangeDescRef
Offset of the memory range descriptor array.
UINT32 NumMemRangeDesc
Memory range descriptor count.