dttable1.c revision 1.1.1.17 1 /******************************************************************************
2 *
3 * Module Name: dttable1.c - handling for specific ACPI tables
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2023, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 /* Compile all complex data tables, signatures starting with A-I */
45
46 #include "aslcompiler.h"
47
48 #define _COMPONENT DT_COMPILER
49 ACPI_MODULE_NAME ("dttable1")
50
51
52 static ACPI_DMTABLE_INFO TableInfoAsfAddress[] =
53 {
54 {ACPI_DMT_BUFFER, 0, "Addresses", 0},
55 {ACPI_DMT_EXIT, 0, NULL, 0}
56 };
57
58 static ACPI_DMTABLE_INFO TableInfoDmarPciPath[] =
59 {
60 {ACPI_DMT_PCI_PATH, 0, "PCI Path", 0},
61 {ACPI_DMT_EXIT, 0, NULL, 0}
62 };
63
64
65 /******************************************************************************
66 *
67 * FUNCTION: DtCompileAest
68 *
69 * PARAMETERS: List - Current field list pointer
70 *
71 * RETURN: Status
72 *
73 * DESCRIPTION: Compile AEST.
74 *
75 * NOTE: Assumes the following table structure:
76 * For all AEST Error Nodes:
77 * 1) An AEST Error Node, followed immediately by:
78 * 2) Any node-specific data
79 * 3) An Interface Structure (one)
80 * 4) A list (array) of Interrupt Structures, the count as specified
81 * in the NodeInterruptCount field of the Error Node header.
82 *
83 * AEST - ARM Error Source table. Conforms to:
84 * ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document Sep 2020
85 *
86 *****************************************************************************/
87
88 ACPI_STATUS
89 DtCompileAest (
90 void **List)
91 {
92 ACPI_AEST_HEADER *ErrorNodeHeader;
93 ACPI_AEST_PROCESSOR *AestProcessor;
94 DT_SUBTABLE *Subtable;
95 DT_SUBTABLE *ParentTable;
96 ACPI_DMTABLE_INFO *InfoTable;
97 ACPI_STATUS Status;
98 UINT32 i;
99 UINT32 Offset;
100 DT_FIELD **PFieldList = (DT_FIELD **) List;
101 ACPI_AEST_NODE_INTERFACE_HEADER *AestNodeHeader;
102 UINT8 Revision;
103 ACPI_TABLE_HEADER *Header;
104
105 ParentTable = DtPeekSubtable ();
106
107 Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
108 Revision = Header->Revision;
109
110 while (*PFieldList)
111 {
112 /* Compile the common error node header */
113
114 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestHdr,
115 &Subtable);
116 if (ACPI_FAILURE (Status))
117 {
118 return (Status);
119 }
120
121 ParentTable = DtPeekSubtable ();
122 DtInsertSubtable (ParentTable, Subtable);
123
124 /* Everything past the error node header will be a subtable */
125
126 DtPushSubtable (Subtable);
127
128 /*
129 * Compile the node-specific structure (Based on the error
130 * node header Type field)
131 */
132 ErrorNodeHeader = ACPI_CAST_PTR (ACPI_AEST_HEADER, Subtable->Buffer);
133
134 /* Point past the common error node header */
135
136 Offset = sizeof (ACPI_AEST_HEADER);
137 ErrorNodeHeader->NodeSpecificOffset = Offset;
138
139 /* Decode the error node type */
140
141 switch (ErrorNodeHeader->Type)
142 {
143 case ACPI_AEST_PROCESSOR_ERROR_NODE:
144
145 InfoTable = AcpiDmTableInfoAestProcError;
146 break;
147
148 case ACPI_AEST_MEMORY_ERROR_NODE:
149
150 InfoTable = AcpiDmTableInfoAestMemError;
151 break;
152
153 case ACPI_AEST_SMMU_ERROR_NODE:
154
155 InfoTable = AcpiDmTableInfoAestSmmuError;
156 break;
157
158 case ACPI_AEST_VENDOR_ERROR_NODE:
159 switch (Revision)
160 {
161 case 1:
162 InfoTable = AcpiDmTableInfoAestVendorError;
163 break;
164
165 case 2:
166 InfoTable = AcpiDmTableInfoAestVendorV2Error;
167 break;
168
169 default:
170 AcpiOsPrintf ("Unknown AEST Vendor Error Revision: %X\n",
171 Revision);
172 return (AE_ERROR);
173 }
174 break;
175
176 case ACPI_AEST_GIC_ERROR_NODE:
177
178 InfoTable = AcpiDmTableInfoAestGicError;
179 break;
180
181 case ACPI_AEST_PCIE_ERROR_NODE:
182
183 InfoTable = AcpiDmTableInfoAestPCIeError;
184 break;
185
186 case ACPI_AEST_PROXY_ERROR_NODE:
187
188 InfoTable = AcpiDmTableInfoAestProxyError;
189 break;
190
191 /* Error case below */
192 default:
193 AcpiOsPrintf ("Unknown AEST Subtable Type: %X\n",
194 ErrorNodeHeader->Type);
195 return (AE_ERROR);
196 }
197
198 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
199 if (ACPI_FAILURE (Status))
200 {
201 return (Status);
202 }
203
204 /* Point past the node-specific structure */
205
206 Offset += Subtable->Length;
207 ErrorNodeHeader->NodeInterfaceOffset = Offset;
208
209 ParentTable = DtPeekSubtable ();
210 DtInsertSubtable (ParentTable, Subtable);
211
212 /* Compile any additional node-specific substructures */
213
214 if (ErrorNodeHeader->Type == ACPI_AEST_PROCESSOR_ERROR_NODE)
215 {
216 /*
217 * Special handling for PROCESSOR_ERROR_NODE subtables
218 * (to handle the Resource Substructure via the ResourceType
219 * field).
220 */
221 AestProcessor = ACPI_CAST_PTR (ACPI_AEST_PROCESSOR,
222 Subtable->Buffer);
223
224 switch (AestProcessor->ResourceType)
225 {
226 case ACPI_AEST_CACHE_RESOURCE:
227
228 InfoTable = AcpiDmTableInfoAestCacheRsrc;
229 break;
230
231 case ACPI_AEST_TLB_RESOURCE:
232
233 InfoTable = AcpiDmTableInfoAestTlbRsrc;
234 break;
235
236 case ACPI_AEST_GENERIC_RESOURCE:
237
238 InfoTable = AcpiDmTableInfoAestGenRsrc;
239 AcpiOsPrintf ("Generic Resource Type (%X) is not supported at this time\n",
240 AestProcessor->ResourceType);
241 return (AE_ERROR);
242
243 /* Error case below */
244 default:
245 AcpiOsPrintf ("Unknown AEST Processor Resource Type: %X\n",
246 AestProcessor->ResourceType);
247 return (AE_ERROR);
248 }
249
250 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
251 if (ACPI_FAILURE (Status))
252 {
253 return (Status);
254 }
255
256 /* Point past the resource substructure subtable */
257
258 Offset += Subtable->Length;
259 ErrorNodeHeader->NodeInterfaceOffset = Offset;
260
261 ParentTable = DtPeekSubtable ();
262 DtInsertSubtable (ParentTable, Subtable);
263 }
264
265 /* Compile the (required) node interface structure */
266 if (Revision == 1)
267 {
268 InfoTable = AcpiDmTableInfoAestXface;
269 }
270 else if (Revision == 2)
271 {
272 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestXfaceHeader,
273 &Subtable);
274 if (ACPI_FAILURE (Status))
275 {
276 return (Status);
277 }
278
279 ParentTable = DtPeekSubtable ();
280 DtInsertSubtable (ParentTable, Subtable);
281
282 Offset += Subtable->Length;
283
284 AestNodeHeader = ACPI_CAST_PTR (ACPI_AEST_NODE_INTERFACE_HEADER,
285 Subtable->Buffer);
286
287 switch (AestNodeHeader->GroupFormat)
288 {
289 case ACPI_AEST_NODE_GROUP_FORMAT_4K:
290
291 InfoTable = AcpiDmTableInfoAestXface4k;
292 break;
293
294 case ACPI_AEST_NODE_GROUP_FORMAT_16K:
295
296 InfoTable = AcpiDmTableInfoAestXface16k;
297 break;
298
299 case ACPI_AEST_NODE_GROUP_FORMAT_64K:
300
301 InfoTable = AcpiDmTableInfoAestXface64k;
302 break;
303
304 /* Error case below */
305 default:
306 AcpiOsPrintf ("Unknown AEST Interface Group Format: %X\n",
307 AestNodeHeader->GroupFormat);
308 return (AE_ERROR);
309 }
310 }
311 else
312 {
313 AcpiOsPrintf ("Unknown AEST Revision: %X\n", Revision);
314 }
315
316 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
317 if (ACPI_FAILURE (Status))
318 {
319 return (Status);
320 }
321
322 ErrorNodeHeader->NodeInterruptOffset = 0;
323 ParentTable = DtPeekSubtable ();
324 DtInsertSubtable (ParentTable, Subtable);
325
326 /* Compile each of the node interrupt structures */
327
328 if (ErrorNodeHeader->NodeInterruptCount)
329 {
330 /* Point to the first interrupt structure */
331
332 Offset += Subtable->Length;
333 ErrorNodeHeader->NodeInterruptOffset = Offset;
334 }
335
336 /* Compile each of the interrupt structures */
337
338 for (i = 0; i < ErrorNodeHeader->NodeInterruptCount; i++)
339 {
340 switch (Revision) {
341 case 1:
342
343 InfoTable = AcpiDmTableInfoAestXrupt;
344 break;
345
346 case 2:
347
348 InfoTable = AcpiDmTableInfoAestXruptV2;
349 break;
350
351 default:
352 AcpiOsPrintf ("Unknown AEST Revision: %X\n", Revision);
353 return (AE_ERROR);
354 }
355 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
356 if (ACPI_FAILURE (Status))
357 {
358 return (Status);
359 }
360
361 ParentTable = DtPeekSubtable ();
362 DtInsertSubtable (ParentTable, Subtable);
363 }
364
365 /* Prepare for the next AEST Error node */
366
367 DtPopSubtable ();
368 }
369
370 return (AE_OK);
371 }
372
373
374 /******************************************************************************
375 *
376 * FUNCTION: DtCompileApmt
377 *
378 * PARAMETERS: List - Current field list pointer
379 *
380 * RETURN: Status
381 *
382 * DESCRIPTION: Compile APMT.
383 *
384 *****************************************************************************/
385
386 ACPI_STATUS
387 DtCompileApmt (
388 void **List)
389 {
390 ACPI_STATUS Status;
391 ACPI_TABLE_HEADER *Header;
392 ACPI_APMT_NODE *ApmtNode;
393 ACPI_APMT_NODE *PeerApmtNode;
394 DT_SUBTABLE *Subtable;
395 DT_SUBTABLE *PeerSubtable;
396 DT_SUBTABLE *ParentTable;
397 DT_FIELD **PFieldList = (DT_FIELD**)List;
398 DT_FIELD *SubtableStart;
399 UINT32 CurLength;
400 char MsgBuffer[64] = "";
401
402 ParentTable = DtPeekSubtable();
403
404 Header = ACPI_CAST_PTR(ACPI_TABLE_HEADER, ParentTable->Buffer);
405
406 CurLength = sizeof(ACPI_TABLE_HEADER);
407
408 /* Walk the parse tree */
409
410 while (*PFieldList)
411 {
412 /* APMT Node Subtable */
413
414 SubtableStart = *PFieldList;
415
416 Status = DtCompileTable(PFieldList, AcpiDmTableInfoApmtNode, &Subtable);
417
418 if (ACPI_FAILURE(Status))
419 {
420 return (Status);
421 }
422
423 ApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, Subtable->Buffer);
424
425 if (ApmtNode->Length != sizeof(ACPI_APMT_NODE))
426 {
427 DtFatal(ASL_MSG_INVALID_LENGTH, SubtableStart, "APMT");
428 return (AE_ERROR);
429 }
430
431 if (ApmtNode->Type >= ACPI_APMT_NODE_TYPE_COUNT)
432 {
433 snprintf(MsgBuffer, 64, "Node Type : 0x%X", ApmtNode->Type);
434 DtFatal(ASL_MSG_INVALID_TYPE, SubtableStart, MsgBuffer);
435 return (AE_ERROR);
436 }
437
438 PeerSubtable = DtGetNextSubtable(ParentTable, NULL);
439
440 /* Validate the node id needs to be unique. */
441 while(PeerSubtable)
442 {
443 PeerApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, PeerSubtable->Buffer);
444 if (PeerApmtNode->Id == ApmtNode->Id)
445 {
446 snprintf(MsgBuffer, 64, "Node Id : 0x%X existed", ApmtNode->Id);
447 DtFatal(ASL_MSG_DUPLICATE_ITEM, SubtableStart, MsgBuffer);
448 return (AE_ERROR);
449 }
450
451 PeerSubtable = DtGetNextSubtable(ParentTable, PeerSubtable);
452 }
453
454 CurLength += ApmtNode->Length;
455
456 DtInsertSubtable(ParentTable, Subtable);
457 }
458
459 if (Header->Length != CurLength)
460 {
461 snprintf(MsgBuffer, 64, " - APMT Length : %u (expected: %u)",
462 Header->Length, CurLength);
463 DtFatal(ASL_MSG_INVALID_LENGTH, NULL, MsgBuffer);
464 return (AE_ERROR);
465 }
466
467 return (AE_OK);
468 }
469
470 /******************************************************************************
471 *
472 * FUNCTION: DtCompileAsf
473 *
474 * PARAMETERS: List - Current field list pointer
475 *
476 * RETURN: Status
477 *
478 * DESCRIPTION: Compile ASF!.
479 *
480 *****************************************************************************/
481
482 ACPI_STATUS
483 DtCompileAsf (
484 void **List)
485 {
486 ACPI_ASF_INFO *AsfTable;
487 DT_SUBTABLE *Subtable;
488 DT_SUBTABLE *ParentTable;
489 ACPI_DMTABLE_INFO *InfoTable;
490 ACPI_DMTABLE_INFO *DataInfoTable = NULL;
491 UINT32 DataCount = 0;
492 ACPI_STATUS Status;
493 UINT32 i;
494 DT_FIELD **PFieldList = (DT_FIELD **) List;
495 DT_FIELD *SubtableStart;
496
497
498 while (*PFieldList)
499 {
500 SubtableStart = *PFieldList;
501 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr,
502 &Subtable);
503 if (ACPI_FAILURE (Status))
504 {
505 return (Status);
506 }
507
508 ParentTable = DtPeekSubtable ();
509 DtInsertSubtable (ParentTable, Subtable);
510 DtPushSubtable (Subtable);
511
512 AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer);
513
514 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
515 {
516 case ACPI_ASF_TYPE_INFO:
517
518 InfoTable = AcpiDmTableInfoAsf0;
519 break;
520
521 case ACPI_ASF_TYPE_ALERT:
522
523 InfoTable = AcpiDmTableInfoAsf1;
524 break;
525
526 case ACPI_ASF_TYPE_CONTROL:
527
528 InfoTable = AcpiDmTableInfoAsf2;
529 break;
530
531 case ACPI_ASF_TYPE_BOOT:
532
533 InfoTable = AcpiDmTableInfoAsf3;
534 break;
535
536 case ACPI_ASF_TYPE_ADDRESS:
537
538 InfoTable = AcpiDmTableInfoAsf4;
539 break;
540
541 default:
542
543 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
544 return (AE_ERROR);
545 }
546
547 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
548 if (ACPI_FAILURE (Status))
549 {
550 return (Status);
551 }
552
553 ParentTable = DtPeekSubtable ();
554 DtInsertSubtable (ParentTable, Subtable);
555
556 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
557 {
558 case ACPI_ASF_TYPE_INFO:
559
560 DataInfoTable = NULL;
561 break;
562
563 case ACPI_ASF_TYPE_ALERT:
564
565 DataInfoTable = AcpiDmTableInfoAsf1a;
566 DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT,
567 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
568 sizeof (ACPI_ASF_HEADER)))->Alerts;
569 break;
570
571 case ACPI_ASF_TYPE_CONTROL:
572
573 DataInfoTable = AcpiDmTableInfoAsf2a;
574 DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE,
575 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
576 sizeof (ACPI_ASF_HEADER)))->Controls;
577 break;
578
579 case ACPI_ASF_TYPE_BOOT:
580
581 DataInfoTable = NULL;
582 break;
583
584 case ACPI_ASF_TYPE_ADDRESS:
585
586 DataInfoTable = TableInfoAsfAddress;
587 DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS,
588 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
589 sizeof (ACPI_ASF_HEADER)))->Devices;
590 break;
591
592 default:
593
594 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
595 return (AE_ERROR);
596 }
597
598 if (DataInfoTable)
599 {
600 switch (AsfTable->Header.Type & 0x7F)
601 {
602 case ACPI_ASF_TYPE_ADDRESS:
603
604 while (DataCount > 0)
605 {
606 Status = DtCompileTable (PFieldList, DataInfoTable,
607 &Subtable);
608 if (ACPI_FAILURE (Status))
609 {
610 return (Status);
611 }
612
613 DtInsertSubtable (ParentTable, Subtable);
614 DataCount = DataCount - Subtable->Length;
615 }
616 break;
617
618 default:
619
620 for (i = 0; i < DataCount; i++)
621 {
622 Status = DtCompileTable (PFieldList, DataInfoTable,
623 &Subtable);
624 if (ACPI_FAILURE (Status))
625 {
626 return (Status);
627 }
628
629 DtInsertSubtable (ParentTable, Subtable);
630 }
631 break;
632 }
633 }
634
635 DtPopSubtable ();
636 }
637
638 return (AE_OK);
639 }
640
641 /******************************************************************************
642 *
643 * FUNCTION: DtCompileAspt
644 *
645 * PARAMETERS: List - Current field list pointer
646 *
647 * RETURN: Status
648 *
649 * DESCRIPTION: Compile ASPT.
650 *
651 *****************************************************************************/
652
653 ACPI_STATUS
654 DtCompileAspt (
655 void **List)
656 {
657 ACPI_ASPT_HEADER *AsptTable;
658 DT_SUBTABLE *Subtable;
659 DT_SUBTABLE *ParentTable;
660 ACPI_DMTABLE_INFO *InfoTable;
661 ACPI_STATUS Status;
662 DT_FIELD **PFieldList = (DT_FIELD **) List;
663 DT_FIELD *SubtableStart;
664
665 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAspt, &Subtable);
666 if (ACPI_FAILURE (Status))
667 {
668 return (Status);
669 }
670
671 ParentTable = DtPeekSubtable ();
672 DtInsertSubtable (ParentTable, Subtable);
673
674 while (*PFieldList)
675 {
676 SubtableStart = *PFieldList;
677 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsptHdr,
678 &Subtable);
679 if (ACPI_FAILURE (Status))
680 {
681 return (Status);
682 }
683
684 ParentTable = DtPeekSubtable ();
685 DtInsertSubtable (ParentTable, Subtable);
686 DtPushSubtable (Subtable);
687
688 AsptTable = ACPI_CAST_PTR (ACPI_ASPT_HEADER, Subtable->Buffer);
689
690 switch (AsptTable->Type) /* Mask off top bit */
691 {
692 case ACPI_ASPT_TYPE_GLOBAL_REGS:
693
694 InfoTable = AcpiDmTableInfoAspt0;
695 break;
696
697 case ACPI_ASPT_TYPE_SEV_MBOX_REGS:
698
699 InfoTable = AcpiDmTableInfoAspt1;
700 break;
701
702 case ACPI_ASPT_TYPE_ACPI_MBOX_REGS:
703
704 InfoTable = AcpiDmTableInfoAspt2;
705 break;
706
707 default:
708
709 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASPT");
710 return (AE_ERROR);
711 }
712
713 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
714 if (ACPI_FAILURE (Status))
715 {
716 return (Status);
717 }
718 ParentTable = DtPeekSubtable ();
719 DtInsertSubtable (ParentTable, Subtable);
720 DtPopSubtable ();
721 }
722
723 return (AE_OK);
724 }
725
726
727 /******************************************************************************
728 *
729 * FUNCTION: DtCompileCdat
730 *
731 * PARAMETERS: List - Current field list pointer
732 *
733 * RETURN: Status
734 *
735 * DESCRIPTION: Compile CDAT.
736 *
737 *****************************************************************************/
738
739 ACPI_STATUS
740 DtCompileCdat (
741 void **List)
742 {
743 ACPI_STATUS Status = AE_OK;
744 DT_SUBTABLE *Subtable;
745 DT_SUBTABLE *ParentTable;
746 DT_FIELD **PFieldList = (DT_FIELD **) List;
747 ACPI_CDAT_HEADER *CdatHeader;
748 ACPI_DMTABLE_INFO *InfoTable = NULL;
749 DT_FIELD *SubtableStart;
750
751
752 /* Walk the parse tree.
753 *
754 * Note: Main table consists of only the CDAT table header
755 * (This is not the standard ACPI table header, however)--
756 * Followed by some number of subtables.
757 */
758 while (*PFieldList)
759 {
760 SubtableStart = *PFieldList;
761
762 /* Compile the expected CDAT Subtable header */
763
764 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatHeader,
765 &Subtable);
766 if (ACPI_FAILURE (Status))
767 {
768 return (Status);
769 }
770
771 ParentTable = DtPeekSubtable ();
772 DtInsertSubtable (ParentTable, Subtable);
773 DtPushSubtable (Subtable);
774
775 CdatHeader = ACPI_CAST_PTR (ACPI_CDAT_HEADER, Subtable->Buffer);
776
777 /* Decode the subtable by type */
778
779 switch (CdatHeader->Type)
780 {
781 case ACPI_CDAT_TYPE_DSMAS:
782 InfoTable = AcpiDmTableInfoCdat0;
783 break;
784
785 case ACPI_CDAT_TYPE_DSLBIS:
786 InfoTable = AcpiDmTableInfoCdat1;
787 break;
788
789 case ACPI_CDAT_TYPE_DSMSCIS:
790 InfoTable = AcpiDmTableInfoCdat2;
791 break;
792
793 case ACPI_CDAT_TYPE_DSIS:
794 InfoTable = AcpiDmTableInfoCdat3;
795 break;
796
797 case ACPI_CDAT_TYPE_DSEMTS:
798 InfoTable = AcpiDmTableInfoCdat4;
799 break;
800
801 case ACPI_CDAT_TYPE_SSLBIS:
802 InfoTable = AcpiDmTableInfoCdat5;
803 break;
804
805 default:
806 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CDAT");
807 }
808
809 /* Compile the CDAT subtable */
810
811 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
812 if (ACPI_FAILURE (Status))
813 {
814 return (Status);
815 }
816
817 ParentTable = DtPeekSubtable ();
818 DtInsertSubtable (ParentTable, Subtable);
819
820 switch (CdatHeader->Type)
821 {
822 /* Multiple entries supported for this type */
823
824 case ACPI_CDAT_TYPE_SSLBIS:
825
826 /*
827 * Check for multiple SSLBEs
828 */
829 while (*PFieldList && !AcpiUtStricmp ((*PFieldList)->Name, "Port X ID"))
830 {
831 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatEntries, &Subtable);
832 if (ACPI_FAILURE (Status))
833 {
834 return (Status);
835 }
836 ParentTable = DtPeekSubtable ();
837 DtInsertSubtable (ParentTable, Subtable);
838 }
839 break;
840
841 default:
842 break;
843 }
844
845 /* Pop off the CDAT Subtable header subtree */
846
847 DtPopSubtable ();
848 }
849
850 return (AE_OK);
851 }
852
853
854 /******************************************************************************
855 *
856 * FUNCTION: DtCompileCedt
857 *
858 * PARAMETERS: List - Current field list pointer
859 *
860 * RETURN: Status
861 *
862 * DESCRIPTION: Compile CEDT.
863 *
864 *****************************************************************************/
865
866 ACPI_STATUS
867 DtCompileCedt (
868 void **List)
869 {
870 ACPI_STATUS Status;
871 DT_SUBTABLE *Subtable;
872 DT_SUBTABLE *ParentTable;
873 DT_FIELD **PFieldList = (DT_FIELD **) List;
874 ACPI_CEDT_HEADER *CedtHeader;
875 DT_FIELD *SubtableStart;
876
877
878 /* Walk the parse tree */
879
880 while (*PFieldList)
881 {
882 /* if CFMWS and has more than one target, then set to zero later */
883
884 int InsertFlag = 1;
885 SubtableStart = *PFieldList;
886
887 /* CEDT Header */
888
889 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedtHdr,
890 &Subtable);
891 if (ACPI_FAILURE (Status))
892 {
893 return (Status);
894 }
895
896 ParentTable = DtPeekSubtable ();
897 DtInsertSubtable (ParentTable, Subtable);
898 DtPushSubtable (Subtable);
899
900 CedtHeader = ACPI_CAST_PTR (ACPI_CEDT_HEADER, Subtable->Buffer);
901
902 switch (CedtHeader->Type)
903 {
904 case ACPI_CEDT_TYPE_CHBS:
905 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt0, &Subtable);
906 if (ACPI_FAILURE (Status))
907 {
908 return (Status);
909 }
910 break;
911 case ACPI_CEDT_TYPE_CFMWS: {
912 unsigned char *dump;
913 unsigned int idx, offset, max = 0;
914
915 /* Compile table with first "Interleave target" */
916
917 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1, &Subtable);
918 if (ACPI_FAILURE (Status))
919 {
920 return (Status);
921 }
922
923 /* Look in buffer for the number of targets */
924 offset = (unsigned int) ACPI_OFFSET (ACPI_CEDT_CFMWS, InterleaveWays);
925 dump = (unsigned char *) Subtable->Buffer - 4; /* place at beginning of cedt1 */
926 max = 0x01 << dump[offset]; /* 2^max, so 0=1, 1=2, 2=4, 3=8. 8 is MAX */
927 if (max > 8) max=1; /* Error in encoding Interleaving Ways. */
928 if (max == 1) /* if only one target, then break here. */
929 break; /* break if only one target. */
930
931 /* We need to add more interleave targets, so write the current Subtable. */
932
933 ParentTable = DtPeekSubtable ();
934 DtInsertSubtable (ParentTable, Subtable); /* Insert AcpiDmTableInfoCedt1 table so we can put in */
935 DtPushSubtable (Subtable); /* the targets > the first. */
936
937 /* Now, find out all interleave targets beyond the first. */
938
939 for (idx = 1; idx < max; idx++) {
940 ParentTable = DtPeekSubtable ();
941
942 if (*PFieldList)
943 {
944 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1_te, &Subtable);
945 if (ACPI_FAILURE (Status))
946 {
947 return (Status);
948 }
949 if (Subtable)
950 {
951 DtInsertSubtable (ParentTable, Subtable); /* got a target, so insert table. */
952 InsertFlag = 0;
953 }
954 }
955 }
956
957 DtPopSubtable ();
958 ParentTable = DtPeekSubtable ();
959 break;
960 }
961 case ACPI_CEDT_TYPE_CXIMS: {
962 unsigned char *dump;
963 unsigned int idx, offset, max = 0;
964
965 /* Compile table with first "Xor map" */
966
967 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt2, &Subtable);
968 if (ACPI_FAILURE (Status))
969 {
970 return (Status);
971 }
972
973 /* Look in buffer for the number of Xor maps */
974 offset = (unsigned int) ACPI_OFFSET (ACPI_CEDT_CXIMS, NrXormaps);
975 dump = (unsigned char *) Subtable->Buffer - 4; /* place at beginning of cedt2 */
976 max = dump[offset];
977
978 /* We need to add more XOR maps, so write the current Subtable. */
979
980 ParentTable = DtPeekSubtable ();
981 DtInsertSubtable (ParentTable, Subtable); /* Insert AcpiDmTableInfoCedt2 table so we can put in */
982 DtPushSubtable (Subtable);
983
984 /* Now, find out all Xor maps beyond the first. */
985
986 for (idx = 1; idx < max; idx++) {
987 ParentTable = DtPeekSubtable ();
988
989 if (*PFieldList)
990 {
991 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt2_te, &Subtable);
992 if (ACPI_FAILURE (Status))
993 {
994 return (Status);
995 }
996 if (Subtable)
997 {
998 DtInsertSubtable (ParentTable, Subtable); /* got an Xor map, so insert table. */
999 InsertFlag = 0;
1000 }
1001 }
1002 }
1003
1004 DtPopSubtable ();
1005 ParentTable = DtPeekSubtable ();
1006 break;
1007 }
1008
1009 default:
1010 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CEDT");
1011 return (AE_ERROR);
1012 }
1013
1014 ParentTable = DtPeekSubtable ();
1015 if (InsertFlag == 1) {
1016 DtInsertSubtable (ParentTable, Subtable);
1017 }
1018 DtPopSubtable ();
1019 }
1020
1021 return (AE_OK);
1022 }
1023
1024
1025 /******************************************************************************
1026 *
1027 * FUNCTION: DtCompileCpep
1028 *
1029 * PARAMETERS: List - Current field list pointer
1030 *
1031 * RETURN: Status
1032 *
1033 * DESCRIPTION: Compile CPEP.
1034 *
1035 *****************************************************************************/
1036
1037 ACPI_STATUS
1038 DtCompileCpep (
1039 void **List)
1040 {
1041 ACPI_STATUS Status;
1042
1043
1044 Status = DtCompileTwoSubtables (List,
1045 AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0);
1046 return (Status);
1047 }
1048
1049
1050 /******************************************************************************
1051 *
1052 * FUNCTION: DtCompileCsrt
1053 *
1054 * PARAMETERS: List - Current field list pointer
1055 *
1056 * RETURN: Status
1057 *
1058 * DESCRIPTION: Compile CSRT.
1059 *
1060 *****************************************************************************/
1061
1062 ACPI_STATUS
1063 DtCompileCsrt (
1064 void **List)
1065 {
1066 ACPI_STATUS Status = AE_OK;
1067 DT_SUBTABLE *Subtable;
1068 DT_SUBTABLE *ParentTable;
1069 DT_FIELD **PFieldList = (DT_FIELD **) List;
1070 UINT32 DescriptorCount;
1071 UINT32 GroupLength;
1072
1073
1074 /* Subtables (Resource Groups) */
1075
1076 ParentTable = DtPeekSubtable ();
1077 while (*PFieldList)
1078 {
1079 /* Resource group subtable */
1080
1081 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0,
1082 &Subtable);
1083 if (ACPI_FAILURE (Status))
1084 {
1085 return (Status);
1086 }
1087
1088 /* Compute the number of resource descriptors */
1089
1090 GroupLength =
1091 (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
1092 Subtable->Buffer))->Length -
1093 (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
1094 Subtable->Buffer))->SharedInfoLength -
1095 sizeof (ACPI_CSRT_GROUP);
1096
1097 DescriptorCount = (GroupLength /
1098 sizeof (ACPI_CSRT_DESCRIPTOR));
1099
1100 DtInsertSubtable (ParentTable, Subtable);
1101 DtPushSubtable (Subtable);
1102 ParentTable = DtPeekSubtable ();
1103
1104 /* Shared info subtable (One per resource group) */
1105
1106 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1,
1107 &Subtable);
1108 if (ACPI_FAILURE (Status))
1109 {
1110 return (Status);
1111 }
1112
1113 DtInsertSubtable (ParentTable, Subtable);
1114
1115 /* Sub-Subtables (Resource Descriptors) */
1116
1117 while (*PFieldList && DescriptorCount)
1118 {
1119
1120 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2,
1121 &Subtable);
1122 if (ACPI_FAILURE (Status))
1123 {
1124 return (Status);
1125 }
1126
1127 DtInsertSubtable (ParentTable, Subtable);
1128
1129 DtPushSubtable (Subtable);
1130 ParentTable = DtPeekSubtable ();
1131 if (*PFieldList)
1132 {
1133 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a,
1134 &Subtable);
1135 if (ACPI_FAILURE (Status))
1136 {
1137 return (Status);
1138 }
1139 if (Subtable)
1140 {
1141 DtInsertSubtable (ParentTable, Subtable);
1142 }
1143 }
1144
1145 DtPopSubtable ();
1146 ParentTable = DtPeekSubtable ();
1147 DescriptorCount--;
1148 }
1149
1150 DtPopSubtable ();
1151 ParentTable = DtPeekSubtable ();
1152 }
1153
1154 return (Status);
1155 }
1156
1157
1158 /******************************************************************************
1159 *
1160 * FUNCTION: DtCompileDbg2
1161 *
1162 * PARAMETERS: List - Current field list pointer
1163 *
1164 * RETURN: Status
1165 *
1166 * DESCRIPTION: Compile DBG2.
1167 *
1168 *****************************************************************************/
1169
1170 ACPI_STATUS
1171 DtCompileDbg2 (
1172 void **List)
1173 {
1174 ACPI_STATUS Status;
1175 DT_SUBTABLE *Subtable;
1176 DT_SUBTABLE *ParentTable;
1177 DT_FIELD **PFieldList = (DT_FIELD **) List;
1178 UINT32 SubtableCount;
1179 ACPI_DBG2_HEADER *Dbg2Header;
1180 ACPI_DBG2_DEVICE *DeviceInfo;
1181 UINT16 CurrentOffset;
1182 UINT32 i;
1183
1184
1185 /* Main table */
1186
1187 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable);
1188 if (ACPI_FAILURE (Status))
1189 {
1190 return (Status);
1191 }
1192
1193 ParentTable = DtPeekSubtable ();
1194 DtInsertSubtable (ParentTable, Subtable);
1195
1196 /* Main table fields */
1197
1198 Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer);
1199 Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF (
1200 ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header);
1201
1202 SubtableCount = Dbg2Header->InfoCount;
1203 DtPushSubtable (Subtable);
1204
1205 /* Process all Device Information subtables (Count = InfoCount) */
1206
1207 while (*PFieldList && SubtableCount)
1208 {
1209 /* Subtable: Debug Device Information */
1210
1211 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device,
1212 &Subtable);
1213 if (ACPI_FAILURE (Status))
1214 {
1215 return (Status);
1216 }
1217
1218 DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer);
1219 CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE);
1220
1221 ParentTable = DtPeekSubtable ();
1222 DtInsertSubtable (ParentTable, Subtable);
1223 DtPushSubtable (Subtable);
1224
1225 ParentTable = DtPeekSubtable ();
1226
1227 /* BaseAddressRegister GAS array (Required, size is RegisterCount) */
1228
1229 DeviceInfo->BaseAddressOffset = CurrentOffset;
1230 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
1231 {
1232 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr,
1233 &Subtable);
1234 if (ACPI_FAILURE (Status))
1235 {
1236 return (Status);
1237 }
1238
1239 CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS);
1240 DtInsertSubtable (ParentTable, Subtable);
1241 }
1242
1243 /* AddressSize array (Required, size = RegisterCount) */
1244
1245 DeviceInfo->AddressSizeOffset = CurrentOffset;
1246 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
1247 {
1248 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size,
1249 &Subtable);
1250 if (ACPI_FAILURE (Status))
1251 {
1252 return (Status);
1253 }
1254
1255 CurrentOffset += (UINT16) sizeof (UINT32);
1256 DtInsertSubtable (ParentTable, Subtable);
1257 }
1258
1259 /* NamespaceString device identifier (Required, size = NamePathLength) */
1260
1261 DeviceInfo->NamepathOffset = CurrentOffset;
1262 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name,
1263 &Subtable);
1264 if (ACPI_FAILURE (Status))
1265 {
1266 return (Status);
1267 }
1268
1269 /* Update the device info header */
1270
1271 DeviceInfo->NamepathLength = (UINT16) Subtable->Length;
1272 CurrentOffset += (UINT16) DeviceInfo->NamepathLength;
1273 DtInsertSubtable (ParentTable, Subtable);
1274
1275 /* OemData - Variable-length data (Optional, size = OemDataLength) */
1276
1277 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData,
1278 &Subtable);
1279 if (Status == AE_END_OF_TABLE)
1280 {
1281 /* optional field was not found and we're at the end of the file */
1282
1283 goto subtableDone;
1284 }
1285 else if (ACPI_FAILURE (Status))
1286 {
1287 return (Status);
1288 }
1289
1290 /* Update the device info header (zeros if no OEM data present) */
1291
1292 DeviceInfo->OemDataOffset = 0;
1293 DeviceInfo->OemDataLength = 0;
1294
1295 /* Optional subtable (OemData) */
1296
1297 if (Subtable && Subtable->Length)
1298 {
1299 DeviceInfo->OemDataOffset = CurrentOffset;
1300 DeviceInfo->OemDataLength = (UINT16) Subtable->Length;
1301
1302 DtInsertSubtable (ParentTable, Subtable);
1303 }
1304 subtableDone:
1305 SubtableCount--;
1306 DtPopSubtable (); /* Get next Device Information subtable */
1307 }
1308
1309 DtPopSubtable ();
1310 return (AE_OK);
1311 }
1312
1313
1314 /******************************************************************************
1315 *
1316 * FUNCTION: DtCompileDmar
1317 *
1318 * PARAMETERS: List - Current field list pointer
1319 *
1320 * RETURN: Status
1321 *
1322 * DESCRIPTION: Compile DMAR.
1323 *
1324 *****************************************************************************/
1325
1326 ACPI_STATUS
1327 DtCompileDmar (
1328 void **List)
1329 {
1330 ACPI_STATUS Status;
1331 DT_SUBTABLE *Subtable;
1332 DT_SUBTABLE *ParentTable;
1333 DT_FIELD **PFieldList = (DT_FIELD **) List;
1334 DT_FIELD *SubtableStart;
1335 ACPI_DMTABLE_INFO *InfoTable;
1336 ACPI_DMAR_HEADER *DmarHeader;
1337 ACPI_DMAR_DEVICE_SCOPE *DmarDeviceScope;
1338 UINT32 DeviceScopeLength;
1339 UINT32 PciPathLength;
1340
1341
1342 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable);
1343 if (ACPI_FAILURE (Status))
1344 {
1345 return (Status);
1346 }
1347
1348 ParentTable = DtPeekSubtable ();
1349 DtInsertSubtable (ParentTable, Subtable);
1350 DtPushSubtable (Subtable);
1351
1352 while (*PFieldList)
1353 {
1354 /* DMAR Header */
1355
1356 SubtableStart = *PFieldList;
1357 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr,
1358 &Subtable);
1359 if (ACPI_FAILURE (Status))
1360 {
1361 return (Status);
1362 }
1363
1364 ParentTable = DtPeekSubtable ();
1365 DtInsertSubtable (ParentTable, Subtable);
1366 DtPushSubtable (Subtable);
1367
1368 DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer);
1369
1370 switch (DmarHeader->Type)
1371 {
1372 case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1373
1374 InfoTable = AcpiDmTableInfoDmar0;
1375 break;
1376
1377 case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1378
1379 InfoTable = AcpiDmTableInfoDmar1;
1380 break;
1381
1382 case ACPI_DMAR_TYPE_ROOT_ATS:
1383
1384 InfoTable = AcpiDmTableInfoDmar2;
1385 break;
1386
1387 case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1388
1389 InfoTable = AcpiDmTableInfoDmar3;
1390 break;
1391
1392 case ACPI_DMAR_TYPE_NAMESPACE:
1393
1394 InfoTable = AcpiDmTableInfoDmar4;
1395 break;
1396
1397 case ACPI_DMAR_TYPE_SATC:
1398
1399 InfoTable = AcpiDmTableInfoDmar5;
1400 break;
1401
1402 default:
1403
1404 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR");
1405 return (AE_ERROR);
1406 }
1407
1408 /* DMAR Subtable */
1409
1410 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1411 if (ACPI_FAILURE (Status))
1412 {
1413 return (Status);
1414 }
1415
1416 ParentTable = DtPeekSubtable ();
1417 DtInsertSubtable (ParentTable, Subtable);
1418
1419 /*
1420 * Optional Device Scope subtables
1421 */
1422 if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) ||
1423 (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE))
1424 {
1425 /* These types do not support device scopes */
1426
1427 DtPopSubtable ();
1428 continue;
1429 }
1430
1431 DtPushSubtable (Subtable);
1432 DeviceScopeLength = DmarHeader->Length - Subtable->Length -
1433 ParentTable->Length;
1434 while (DeviceScopeLength)
1435 {
1436 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope,
1437 &Subtable);
1438 if (Status == AE_NOT_FOUND)
1439 {
1440 break;
1441 }
1442
1443 ParentTable = DtPeekSubtable ();
1444 DtInsertSubtable (ParentTable, Subtable);
1445 DtPushSubtable (Subtable);
1446
1447 DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer);
1448
1449 /* Optional PCI Paths */
1450
1451 PciPathLength = DmarDeviceScope->Length - Subtable->Length;
1452 while (PciPathLength)
1453 {
1454 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath,
1455 &Subtable);
1456 if (Status == AE_NOT_FOUND)
1457 {
1458 DtPopSubtable ();
1459 break;
1460 }
1461
1462 ParentTable = DtPeekSubtable ();
1463 DtInsertSubtable (ParentTable, Subtable);
1464 PciPathLength -= Subtable->Length;
1465 }
1466
1467 DtPopSubtable ();
1468 DeviceScopeLength -= DmarDeviceScope->Length;
1469 }
1470
1471 DtPopSubtable ();
1472 DtPopSubtable ();
1473 }
1474
1475 return (AE_OK);
1476 }
1477
1478
1479 /******************************************************************************
1480 *
1481 * FUNCTION: DtCompileDrtm
1482 *
1483 * PARAMETERS: List - Current field list pointer
1484 *
1485 * RETURN: Status
1486 *
1487 * DESCRIPTION: Compile DRTM.
1488 *
1489 *****************************************************************************/
1490
1491 ACPI_STATUS
1492 DtCompileDrtm (
1493 void **List)
1494 {
1495 ACPI_STATUS Status;
1496 DT_SUBTABLE *Subtable;
1497 DT_SUBTABLE *ParentTable;
1498 DT_FIELD **PFieldList = (DT_FIELD **) List;
1499 UINT32 Count;
1500 /* ACPI_TABLE_DRTM *Drtm; */
1501 ACPI_DRTM_VTABLE_LIST *DrtmVtl;
1502 ACPI_DRTM_RESOURCE_LIST *DrtmRl;
1503 /* ACPI_DRTM_DPS_ID *DrtmDps; */
1504
1505
1506 ParentTable = DtPeekSubtable ();
1507
1508 /* Compile DRTM header */
1509
1510 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm,
1511 &Subtable);
1512 if (ACPI_FAILURE (Status))
1513 {
1514 return (Status);
1515 }
1516 DtInsertSubtable (ParentTable, Subtable);
1517
1518 /*
1519 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1520 * should be taken to avoid accessing ACPI_TABLE_HADER fields.
1521 */
1522 #if 0
1523 Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM,
1524 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1525 #endif
1526 /* Compile VTL */
1527
1528 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0,
1529 &Subtable);
1530 if (ACPI_FAILURE (Status))
1531 {
1532 return (Status);
1533 }
1534
1535 DtInsertSubtable (ParentTable, Subtable);
1536 DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer);
1537
1538 DtPushSubtable (Subtable);
1539 ParentTable = DtPeekSubtable ();
1540 Count = 0;
1541
1542 while (*PFieldList)
1543 {
1544 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a,
1545 &Subtable);
1546 if (ACPI_FAILURE (Status))
1547 {
1548 return (Status);
1549 }
1550 if (!Subtable)
1551 {
1552 break;
1553 }
1554 DtInsertSubtable (ParentTable, Subtable);
1555 Count++;
1556 }
1557
1558 DrtmVtl->ValidatedTableCount = Count;
1559 DtPopSubtable ();
1560 ParentTable = DtPeekSubtable ();
1561
1562 /* Compile RL */
1563
1564 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1,
1565 &Subtable);
1566 if (ACPI_FAILURE (Status))
1567 {
1568 return (Status);
1569 }
1570
1571 DtInsertSubtable (ParentTable, Subtable);
1572 DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer);
1573
1574 DtPushSubtable (Subtable);
1575 ParentTable = DtPeekSubtable ();
1576 Count = 0;
1577
1578 while (*PFieldList)
1579 {
1580 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a,
1581 &Subtable);
1582 if (ACPI_FAILURE (Status))
1583 {
1584 return (Status);
1585 }
1586
1587 if (!Subtable)
1588 {
1589 break;
1590 }
1591
1592 DtInsertSubtable (ParentTable, Subtable);
1593 Count++;
1594 }
1595
1596 DrtmRl->ResourceCount = Count;
1597 DtPopSubtable ();
1598 ParentTable = DtPeekSubtable ();
1599
1600 /* Compile DPS */
1601
1602 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2,
1603 &Subtable);
1604 if (ACPI_FAILURE (Status))
1605 {
1606 return (Status);
1607 }
1608 DtInsertSubtable (ParentTable, Subtable);
1609 /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/
1610
1611
1612 return (AE_OK);
1613 }
1614
1615
1616 /******************************************************************************
1617 *
1618 * FUNCTION: DtCompileEinj
1619 *
1620 * PARAMETERS: List - Current field list pointer
1621 *
1622 * RETURN: Status
1623 *
1624 * DESCRIPTION: Compile EINJ.
1625 *
1626 *****************************************************************************/
1627
1628 ACPI_STATUS
1629 DtCompileEinj (
1630 void **List)
1631 {
1632 ACPI_STATUS Status;
1633
1634
1635 Status = DtCompileTwoSubtables (List,
1636 AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
1637 return (Status);
1638 }
1639
1640
1641 /******************************************************************************
1642 *
1643 * FUNCTION: DtCompileErst
1644 *
1645 * PARAMETERS: List - Current field list pointer
1646 *
1647 * RETURN: Status
1648 *
1649 * DESCRIPTION: Compile ERST.
1650 *
1651 *****************************************************************************/
1652
1653 ACPI_STATUS
1654 DtCompileErst (
1655 void **List)
1656 {
1657 ACPI_STATUS Status;
1658
1659
1660 Status = DtCompileTwoSubtables (List,
1661 AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
1662 return (Status);
1663 }
1664
1665
1666 /******************************************************************************
1667 *
1668 * FUNCTION: DtCompileGtdt
1669 *
1670 * PARAMETERS: List - Current field list pointer
1671 *
1672 * RETURN: Status
1673 *
1674 * DESCRIPTION: Compile GTDT.
1675 *
1676 *****************************************************************************/
1677
1678 ACPI_STATUS
1679 DtCompileGtdt (
1680 void **List)
1681 {
1682 ACPI_STATUS Status;
1683 DT_SUBTABLE *Subtable;
1684 DT_SUBTABLE *ParentTable;
1685 DT_FIELD **PFieldList = (DT_FIELD **) List;
1686 DT_FIELD *SubtableStart;
1687 ACPI_SUBTABLE_HEADER *GtdtHeader;
1688 ACPI_DMTABLE_INFO *InfoTable;
1689 UINT32 GtCount;
1690 ACPI_TABLE_HEADER *Header;
1691
1692
1693 ParentTable = DtPeekSubtable ();
1694
1695 Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
1696
1697 /* Compile the main table */
1698
1699 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
1700 &Subtable);
1701 if (ACPI_FAILURE (Status))
1702 {
1703 return (Status);
1704 }
1705
1706 /* GTDT revision 3 later contains 2 extra fields before subtables */
1707
1708 if (Header->Revision > 2)
1709 {
1710 ParentTable = DtPeekSubtable ();
1711 DtInsertSubtable (ParentTable, Subtable);
1712
1713 Status = DtCompileTable (PFieldList,
1714 AcpiDmTableInfoGtdtEl2, &Subtable);
1715 if (ACPI_FAILURE (Status))
1716 {
1717 return (Status);
1718 }
1719 }
1720
1721 ParentTable = DtPeekSubtable ();
1722 DtInsertSubtable (ParentTable, Subtable);
1723
1724 while (*PFieldList)
1725 {
1726 SubtableStart = *PFieldList;
1727 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
1728 &Subtable);
1729 if (ACPI_FAILURE (Status))
1730 {
1731 return (Status);
1732 }
1733
1734 ParentTable = DtPeekSubtable ();
1735 DtInsertSubtable (ParentTable, Subtable);
1736 DtPushSubtable (Subtable);
1737
1738 GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
1739
1740 switch (GtdtHeader->Type)
1741 {
1742 case ACPI_GTDT_TYPE_TIMER_BLOCK:
1743
1744 InfoTable = AcpiDmTableInfoGtdt0;
1745 break;
1746
1747 case ACPI_GTDT_TYPE_WATCHDOG:
1748
1749 InfoTable = AcpiDmTableInfoGtdt1;
1750 break;
1751
1752 default:
1753
1754 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
1755 return (AE_ERROR);
1756 }
1757
1758 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1759 if (ACPI_FAILURE (Status))
1760 {
1761 return (Status);
1762 }
1763
1764 ParentTable = DtPeekSubtable ();
1765 DtInsertSubtable (ParentTable, Subtable);
1766
1767 /*
1768 * Additional GT block subtable data
1769 */
1770
1771 switch (GtdtHeader->Type)
1772 {
1773 case ACPI_GTDT_TYPE_TIMER_BLOCK:
1774
1775 DtPushSubtable (Subtable);
1776 ParentTable = DtPeekSubtable ();
1777
1778 GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
1779 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
1780
1781 while (GtCount)
1782 {
1783 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
1784 &Subtable);
1785 if (ACPI_FAILURE (Status))
1786 {
1787 return (Status);
1788 }
1789
1790 DtInsertSubtable (ParentTable, Subtable);
1791 GtCount--;
1792 }
1793
1794 DtPopSubtable ();
1795 break;
1796
1797 default:
1798
1799 break;
1800 }
1801
1802 DtPopSubtable ();
1803 }
1804
1805 return (AE_OK);
1806 }
1807
1808
1809 /******************************************************************************
1810 *
1811 * FUNCTION: DtCompileFpdt
1812 *
1813 * PARAMETERS: List - Current field list pointer
1814 *
1815 * RETURN: Status
1816 *
1817 * DESCRIPTION: Compile FPDT.
1818 *
1819 *****************************************************************************/
1820
1821 ACPI_STATUS
1822 DtCompileFpdt (
1823 void **List)
1824 {
1825 ACPI_STATUS Status;
1826 ACPI_FPDT_HEADER *FpdtHeader;
1827 DT_SUBTABLE *Subtable;
1828 DT_SUBTABLE *ParentTable;
1829 ACPI_DMTABLE_INFO *InfoTable;
1830 DT_FIELD **PFieldList = (DT_FIELD **) List;
1831 DT_FIELD *SubtableStart;
1832
1833
1834 while (*PFieldList)
1835 {
1836 SubtableStart = *PFieldList;
1837 Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
1838 &Subtable);
1839 if (ACPI_FAILURE (Status))
1840 {
1841 return (Status);
1842 }
1843
1844 ParentTable = DtPeekSubtable ();
1845 DtInsertSubtable (ParentTable, Subtable);
1846 DtPushSubtable (Subtable);
1847
1848 FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
1849
1850 switch (FpdtHeader->Type)
1851 {
1852 case ACPI_FPDT_TYPE_BOOT:
1853
1854 InfoTable = AcpiDmTableInfoFpdt0;
1855 break;
1856
1857 case ACPI_FPDT_TYPE_S3PERF:
1858
1859 InfoTable = AcpiDmTableInfoFpdt1;
1860 break;
1861
1862 default:
1863
1864 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
1865 return (AE_ERROR);
1866 break;
1867 }
1868
1869 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1870 if (ACPI_FAILURE (Status))
1871 {
1872 return (Status);
1873 }
1874
1875 ParentTable = DtPeekSubtable ();
1876 DtInsertSubtable (ParentTable, Subtable);
1877 DtPopSubtable ();
1878 }
1879
1880 return (AE_OK);
1881 }
1882
1883
1884 /******************************************************************************
1885 *
1886 * FUNCTION: DtCompileHest
1887 *
1888 * PARAMETERS: List - Current field list pointer
1889 *
1890 * RETURN: Status
1891 *
1892 * DESCRIPTION: Compile HEST.
1893 *
1894 *****************************************************************************/
1895
1896 ACPI_STATUS
1897 DtCompileHest (
1898 void **List)
1899 {
1900 ACPI_STATUS Status;
1901 DT_SUBTABLE *Subtable;
1902 DT_SUBTABLE *ParentTable;
1903 DT_FIELD **PFieldList = (DT_FIELD **) List;
1904 DT_FIELD *SubtableStart;
1905 ACPI_DMTABLE_INFO *InfoTable;
1906 UINT16 Type;
1907 UINT32 BankCount;
1908
1909
1910 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
1911 &Subtable);
1912 if (ACPI_FAILURE (Status))
1913 {
1914 return (Status);
1915 }
1916
1917 ParentTable = DtPeekSubtable ();
1918 DtInsertSubtable (ParentTable, Subtable);
1919
1920 while (*PFieldList)
1921 {
1922 /* Get subtable type */
1923
1924 SubtableStart = *PFieldList;
1925 DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
1926
1927 switch (Type)
1928 {
1929 case ACPI_HEST_TYPE_IA32_CHECK:
1930
1931 InfoTable = AcpiDmTableInfoHest0;
1932 break;
1933
1934 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1935
1936 InfoTable = AcpiDmTableInfoHest1;
1937 break;
1938
1939 case ACPI_HEST_TYPE_IA32_NMI:
1940
1941 InfoTable = AcpiDmTableInfoHest2;
1942 break;
1943
1944 case ACPI_HEST_TYPE_AER_ROOT_PORT:
1945
1946 InfoTable = AcpiDmTableInfoHest6;
1947 break;
1948
1949 case ACPI_HEST_TYPE_AER_ENDPOINT:
1950
1951 InfoTable = AcpiDmTableInfoHest7;
1952 break;
1953
1954 case ACPI_HEST_TYPE_AER_BRIDGE:
1955
1956 InfoTable = AcpiDmTableInfoHest8;
1957 break;
1958
1959 case ACPI_HEST_TYPE_GENERIC_ERROR:
1960
1961 InfoTable = AcpiDmTableInfoHest9;
1962 break;
1963
1964 case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
1965
1966 InfoTable = AcpiDmTableInfoHest10;
1967 break;
1968
1969 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1970
1971 InfoTable = AcpiDmTableInfoHest11;
1972 break;
1973
1974 default:
1975
1976 /* Cannot continue on unknown type */
1977
1978 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
1979 return (AE_ERROR);
1980 }
1981
1982 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1983 if (ACPI_FAILURE (Status))
1984 {
1985 return (Status);
1986 }
1987
1988 DtInsertSubtable (ParentTable, Subtable);
1989
1990 /*
1991 * Additional subtable data - IA32 Error Bank(s)
1992 */
1993 BankCount = 0;
1994 switch (Type)
1995 {
1996 case ACPI_HEST_TYPE_IA32_CHECK:
1997
1998 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
1999 Subtable->Buffer))->NumHardwareBanks;
2000 break;
2001
2002 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
2003
2004 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
2005 Subtable->Buffer))->NumHardwareBanks;
2006 break;
2007
2008 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
2009
2010 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
2011 Subtable->Buffer))->NumHardwareBanks;
2012 break;
2013
2014 default:
2015
2016 break;
2017 }
2018
2019 while (BankCount)
2020 {
2021 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
2022 &Subtable);
2023 if (ACPI_FAILURE (Status))
2024 {
2025 return (Status);
2026 }
2027
2028 DtInsertSubtable (ParentTable, Subtable);
2029 BankCount--;
2030 }
2031 }
2032
2033 return (AE_OK);
2034 }
2035
2036
2037 /******************************************************************************
2038 *
2039 * FUNCTION: DtCompileHmat
2040 *
2041 * PARAMETERS: List - Current field list pointer
2042 *
2043 * RETURN: Status
2044 *
2045 * DESCRIPTION: Compile HMAT.
2046 *
2047 *****************************************************************************/
2048
2049 ACPI_STATUS
2050 DtCompileHmat (
2051 void **List)
2052 {
2053 ACPI_STATUS Status;
2054 DT_SUBTABLE *Subtable;
2055 DT_SUBTABLE *ParentTable;
2056 DT_FIELD **PFieldList = (DT_FIELD **) List;
2057 DT_FIELD *SubtableStart;
2058 DT_FIELD *EntryStart;
2059 ACPI_HMAT_STRUCTURE *HmatStruct;
2060 ACPI_HMAT_LOCALITY *HmatLocality;
2061 ACPI_HMAT_CACHE *HmatCache;
2062 ACPI_DMTABLE_INFO *InfoTable;
2063 UINT32 IntPDNumber;
2064 UINT32 TgtPDNumber;
2065 UINT64 EntryNumber;
2066 UINT16 SMBIOSHandleNumber;
2067
2068
2069 ParentTable = DtPeekSubtable ();
2070
2071 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
2072 &Subtable);
2073 if (ACPI_FAILURE (Status))
2074 {
2075 return (Status);
2076 }
2077 DtInsertSubtable (ParentTable, Subtable);
2078
2079 while (*PFieldList)
2080 {
2081 /* Compile HMAT structure header */
2082
2083 SubtableStart = *PFieldList;
2084 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
2085 &Subtable);
2086 if (ACPI_FAILURE (Status))
2087 {
2088 return (Status);
2089 }
2090 DtInsertSubtable (ParentTable, Subtable);
2091
2092 HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
2093 HmatStruct->Length = Subtable->Length;
2094
2095 /* Compile HMAT structure body */
2096
2097 switch (HmatStruct->Type)
2098 {
2099 case ACPI_HMAT_TYPE_ADDRESS_RANGE:
2100
2101 InfoTable = AcpiDmTableInfoHmat0;
2102 break;
2103
2104 case ACPI_HMAT_TYPE_LOCALITY:
2105
2106 InfoTable = AcpiDmTableInfoHmat1;
2107 break;
2108
2109 case ACPI_HMAT_TYPE_CACHE:
2110
2111 InfoTable = AcpiDmTableInfoHmat2;
2112 break;
2113
2114 default:
2115
2116 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
2117 return (AE_ERROR);
2118 }
2119
2120 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
2121 if (ACPI_FAILURE (Status))
2122 {
2123 return (Status);
2124 }
2125 DtInsertSubtable (ParentTable, Subtable);
2126 HmatStruct->Length += Subtable->Length;
2127
2128 /* Compile HMAT structure additional */
2129
2130 switch (HmatStruct->Type)
2131 {
2132 case ACPI_HMAT_TYPE_LOCALITY:
2133
2134 HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
2135 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
2136
2137 /* Compile initiator proximity domain list */
2138
2139 IntPDNumber = 0;
2140 while (*PFieldList)
2141 {
2142 Status = DtCompileTable (PFieldList,
2143 AcpiDmTableInfoHmat1a, &Subtable);
2144 if (ACPI_FAILURE (Status))
2145 {
2146 return (Status);
2147 }
2148 if (!Subtable)
2149 {
2150 break;
2151 }
2152 DtInsertSubtable (ParentTable, Subtable);
2153 HmatStruct->Length += Subtable->Length;
2154 IntPDNumber++;
2155 }
2156 HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
2157
2158 /* Compile target proximity domain list */
2159
2160 TgtPDNumber = 0;
2161 while (*PFieldList)
2162 {
2163 Status = DtCompileTable (PFieldList,
2164 AcpiDmTableInfoHmat1b, &Subtable);
2165 if (ACPI_FAILURE (Status))
2166 {
2167 return (Status);
2168 }
2169 if (!Subtable)
2170 {
2171 break;
2172 }
2173 DtInsertSubtable (ParentTable, Subtable);
2174 HmatStruct->Length += Subtable->Length;
2175 TgtPDNumber++;
2176 }
2177 HmatLocality->NumberOfTargetPDs = TgtPDNumber;
2178
2179 /* Save start of the entries for reporting errors */
2180
2181 EntryStart = *PFieldList;
2182
2183 /* Compile latency/bandwidth entries */
2184
2185 EntryNumber = 0;
2186 while (*PFieldList)
2187 {
2188 Status = DtCompileTable (PFieldList,
2189 AcpiDmTableInfoHmat1c, &Subtable);
2190 if (ACPI_FAILURE (Status))
2191 {
2192 return (Status);
2193 }
2194 if (!Subtable)
2195 {
2196 break;
2197 }
2198 DtInsertSubtable (ParentTable, Subtable);
2199 HmatStruct->Length += Subtable->Length;
2200 EntryNumber++;
2201 }
2202
2203 /* Validate number of entries */
2204
2205 if (EntryNumber !=
2206 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
2207 {
2208 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
2209 return (AE_ERROR);
2210 }
2211 break;
2212
2213 case ACPI_HMAT_TYPE_CACHE:
2214
2215 /* Compile SMBIOS handles */
2216
2217 HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
2218 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
2219 SMBIOSHandleNumber = 0;
2220 while (*PFieldList)
2221 {
2222 Status = DtCompileTable (PFieldList,
2223 AcpiDmTableInfoHmat2a, &Subtable);
2224 if (ACPI_FAILURE (Status))
2225 {
2226 return (Status);
2227 }
2228 if (!Subtable)
2229 {
2230 break;
2231 }
2232 DtInsertSubtable (ParentTable, Subtable);
2233 HmatStruct->Length += Subtable->Length;
2234 SMBIOSHandleNumber++;
2235 }
2236 HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
2237 break;
2238
2239 default:
2240
2241 break;
2242 }
2243 }
2244
2245 return (AE_OK);
2246 }
2247
2248
2249 /******************************************************************************
2250 *
2251 * FUNCTION: DtCompileIort
2252 *
2253 * PARAMETERS: List - Current field list pointer
2254 *
2255 * RETURN: Status
2256 *
2257 * DESCRIPTION: Compile IORT.
2258 *
2259 *****************************************************************************/
2260
2261 ACPI_STATUS
2262 DtCompileIort (
2263 void **List)
2264 {
2265 ACPI_STATUS Status;
2266 DT_SUBTABLE *Subtable;
2267 DT_SUBTABLE *ParentTable;
2268 DT_FIELD **PFieldList = (DT_FIELD **) List;
2269 DT_FIELD *SubtableStart;
2270 ACPI_TABLE_HEADER *Table;
2271 ACPI_TABLE_IORT *Iort;
2272 ACPI_IORT_NODE *IortNode;
2273 ACPI_IORT_ITS_GROUP *IortItsGroup;
2274 ACPI_IORT_SMMU *IortSmmu;
2275 ACPI_IORT_RMR *IortRmr;
2276 UINT32 NodeNumber;
2277 UINT32 NodeLength;
2278 UINT32 IdMappingNumber;
2279 UINT32 ItsNumber;
2280 UINT32 ContextIrptNumber;
2281 UINT32 PmuIrptNumber;
2282 UINT32 PaddingLength;
2283 UINT8 Revision;
2284 UINT32 RmrCount;
2285
2286
2287 ParentTable = DtPeekSubtable ();
2288
2289 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
2290 &Subtable);
2291 if (ACPI_FAILURE (Status))
2292 {
2293 return (Status);
2294 }
2295 DtInsertSubtable (ParentTable, Subtable);
2296
2297 Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
2298 Revision = Table->Revision;
2299
2300 /* IORT Revisions E, E.a & E.c have known issues and are not supported */
2301
2302 if (Revision == 1 || Revision == 2 || Revision == 4)
2303 {
2304 DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision");
2305 return (AE_ERROR);
2306 }
2307
2308 /*
2309 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
2310 * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
2311 */
2312 Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
2313 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
2314
2315 /*
2316 * OptionalPadding - Variable-length data
2317 * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
2318 * Optionally allows the generic data types to be used for filling
2319 * this field.
2320 */
2321 Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
2322 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
2323 &Subtable);
2324 if (ACPI_FAILURE (Status))
2325 {
2326 return (Status);
2327 }
2328 if (Subtable)
2329 {
2330 DtInsertSubtable (ParentTable, Subtable);
2331 Iort->NodeOffset += Subtable->Length;
2332 }
2333 else
2334 {
2335 Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
2336 AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
2337 if (ACPI_FAILURE (Status))
2338 {
2339 return (Status);
2340 }
2341 Iort->NodeOffset += PaddingLength;
2342 }
2343
2344 NodeNumber = 0;
2345 while (*PFieldList)
2346 {
2347 SubtableStart = *PFieldList;
2348 if (Revision == 0)
2349 {
2350 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
2351 &Subtable);
2352 }
2353 else if (Revision >= 3)
2354 {
2355 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3,
2356 &Subtable);
2357 }
2358
2359 if (ACPI_FAILURE (Status))
2360 {
2361 return (Status);
2362 }
2363
2364 DtInsertSubtable (ParentTable, Subtable);
2365 IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
2366 NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
2367
2368 DtPushSubtable (Subtable);
2369 ParentTable = DtPeekSubtable ();
2370
2371 switch (IortNode->Type)
2372 {
2373 case ACPI_IORT_NODE_ITS_GROUP:
2374
2375 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
2376 &Subtable);
2377 if (ACPI_FAILURE (Status))
2378 {
2379 return (Status);
2380 }
2381
2382 DtInsertSubtable (ParentTable, Subtable);
2383 IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
2384 NodeLength += Subtable->Length;
2385
2386 ItsNumber = 0;
2387 while (*PFieldList)
2388 {
2389 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
2390 &Subtable);
2391 if (ACPI_FAILURE (Status))
2392 {
2393 return (Status);
2394 }
2395 if (!Subtable)
2396 {
2397 break;
2398 }
2399
2400 DtInsertSubtable (ParentTable, Subtable);
2401 NodeLength += Subtable->Length;
2402 ItsNumber++;
2403 }
2404
2405 IortItsGroup->ItsCount = ItsNumber;
2406 break;
2407
2408 case ACPI_IORT_NODE_NAMED_COMPONENT:
2409
2410 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
2411 &Subtable);
2412 if (ACPI_FAILURE (Status))
2413 {
2414 return (Status);
2415 }
2416
2417 DtInsertSubtable (ParentTable, Subtable);
2418 NodeLength += Subtable->Length;
2419
2420 /*
2421 * Padding - Variable-length data
2422 * Optionally allows the offset of the ID mappings to be used
2423 * for filling this field.
2424 */
2425 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
2426 &Subtable);
2427 if (ACPI_FAILURE (Status))
2428 {
2429 return (Status);
2430 }
2431
2432 if (Subtable)
2433 {
2434 DtInsertSubtable (ParentTable, Subtable);
2435 NodeLength += Subtable->Length;
2436 }
2437 else
2438 {
2439 if (NodeLength > IortNode->MappingOffset)
2440 {
2441 return (AE_BAD_DATA);
2442 }
2443
2444 if (NodeLength < IortNode->MappingOffset)
2445 {
2446 Status = DtCompilePadding (
2447 IortNode->MappingOffset - NodeLength,
2448 &Subtable);
2449 if (ACPI_FAILURE (Status))
2450 {
2451 return (Status);
2452 }
2453
2454 DtInsertSubtable (ParentTable, Subtable);
2455 NodeLength = IortNode->MappingOffset;
2456 }
2457 }
2458 break;
2459
2460 case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
2461
2462 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
2463 &Subtable);
2464 if (ACPI_FAILURE (Status))
2465 {
2466 return (Status);
2467 }
2468
2469 DtInsertSubtable (ParentTable, Subtable);
2470 NodeLength += Subtable->Length;
2471 break;
2472
2473 case ACPI_IORT_NODE_SMMU:
2474
2475 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
2476 &Subtable);
2477 if (ACPI_FAILURE (Status))
2478 {
2479 return (Status);
2480 }
2481
2482 DtInsertSubtable (ParentTable, Subtable);
2483 IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
2484 NodeLength += Subtable->Length;
2485
2486 /* Compile global interrupt array */
2487
2488 IortSmmu->GlobalInterruptOffset = NodeLength;
2489 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
2490 &Subtable);
2491 if (ACPI_FAILURE (Status))
2492 {
2493 return (Status);
2494 }
2495
2496 DtInsertSubtable (ParentTable, Subtable);
2497 NodeLength += Subtable->Length;
2498
2499 /* Compile context interrupt array */
2500
2501 ContextIrptNumber = 0;
2502 IortSmmu->ContextInterruptOffset = NodeLength;
2503 while (*PFieldList)
2504 {
2505 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
2506 &Subtable);
2507 if (ACPI_FAILURE (Status))
2508 {
2509 return (Status);
2510 }
2511
2512 if (!Subtable)
2513 {
2514 break;
2515 }
2516
2517 DtInsertSubtable (ParentTable, Subtable);
2518 NodeLength += Subtable->Length;
2519 ContextIrptNumber++;
2520 }
2521
2522 IortSmmu->ContextInterruptCount = ContextIrptNumber;
2523
2524 /* Compile PMU interrupt array */
2525
2526 PmuIrptNumber = 0;
2527 IortSmmu->PmuInterruptOffset = NodeLength;
2528 while (*PFieldList)
2529 {
2530 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
2531 &Subtable);
2532 if (ACPI_FAILURE (Status))
2533 {
2534 return (Status);
2535 }
2536
2537 if (!Subtable)
2538 {
2539 break;
2540 }
2541
2542 DtInsertSubtable (ParentTable, Subtable);
2543 NodeLength += Subtable->Length;
2544 PmuIrptNumber++;
2545 }
2546
2547 IortSmmu->PmuInterruptCount = PmuIrptNumber;
2548 break;
2549
2550 case ACPI_IORT_NODE_SMMU_V3:
2551
2552 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
2553 &Subtable);
2554 if (ACPI_FAILURE (Status))
2555 {
2556 return (Status);
2557 }
2558
2559 DtInsertSubtable (ParentTable, Subtable);
2560 NodeLength += Subtable->Length;
2561 break;
2562
2563 case ACPI_IORT_NODE_PMCG:
2564
2565 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5,
2566 &Subtable);
2567 if (ACPI_FAILURE (Status))
2568 {
2569 return (Status);
2570 }
2571
2572 DtInsertSubtable (ParentTable, Subtable);
2573 NodeLength += Subtable->Length;
2574 break;
2575
2576 case ACPI_IORT_NODE_RMR:
2577
2578 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6,
2579 &Subtable);
2580 if (ACPI_FAILURE (Status))
2581 {
2582 return (Status);
2583 }
2584
2585 DtInsertSubtable (ParentTable, Subtable);
2586 IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer);
2587 NodeLength += Subtable->Length;
2588
2589 /* Compile RMR Descriptors */
2590
2591 RmrCount = 0;
2592 IortRmr->RmrOffset = NodeLength;
2593 while (*PFieldList)
2594 {
2595 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a,
2596 &Subtable);
2597 if (ACPI_FAILURE (Status))
2598 {
2599 return (Status);
2600 }
2601
2602 if (!Subtable)
2603 {
2604 break;
2605 }
2606
2607 DtInsertSubtable (ParentTable, Subtable);
2608 NodeLength += sizeof (ACPI_IORT_RMR_DESC);
2609 RmrCount++;
2610 }
2611
2612 IortRmr->RmrCount = RmrCount;
2613 break;
2614
2615 default:
2616
2617 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
2618 return (AE_ERROR);
2619 }
2620
2621 /* Compile Array of ID mappings */
2622
2623 IortNode->MappingOffset = NodeLength;
2624 IdMappingNumber = 0;
2625 while (*PFieldList)
2626 {
2627 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
2628 &Subtable);
2629 if (ACPI_FAILURE (Status))
2630 {
2631 return (Status);
2632 }
2633
2634 if (!Subtable)
2635 {
2636 break;
2637 }
2638
2639 DtInsertSubtable (ParentTable, Subtable);
2640 NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
2641 IdMappingNumber++;
2642 }
2643
2644 IortNode->MappingCount = IdMappingNumber;
2645 if (!IdMappingNumber)
2646 {
2647 IortNode->MappingOffset = 0;
2648 }
2649
2650 /*
2651 * Node length can be determined by DT_LENGTH option
2652 * IortNode->Length = NodeLength;
2653 */
2654 DtPopSubtable ();
2655 ParentTable = DtPeekSubtable ();
2656 NodeNumber++;
2657 }
2658
2659 Iort->NodeCount = NodeNumber;
2660 return (AE_OK);
2661 }
2662
2663
2664 /******************************************************************************
2665 *
2666 * FUNCTION: DtCompileIvrs
2667 *
2668 * PARAMETERS: List - Current field list pointer
2669 *
2670 * RETURN: Status
2671 *
2672 * DESCRIPTION: Compile IVRS. Notes:
2673 * The IVRS is essentially a flat table, with the following
2674 * structure:
2675 * <Main ACPI Table Header>
2676 * <Main subtable - virtualization info>
2677 * <IVHD>
2678 * <Device Entries>
2679 * ...
2680 * <IVHD>
2681 * <Device Entries>
2682 * <IVMD>
2683 * ...
2684 *
2685 *****************************************************************************/
2686
2687 ACPI_STATUS
2688 DtCompileIvrs (
2689 void **List)
2690 {
2691 ACPI_STATUS Status;
2692 DT_SUBTABLE *Subtable;
2693 DT_SUBTABLE *ParentTable;
2694 DT_SUBTABLE *MainSubtable;
2695 DT_FIELD **PFieldList = (DT_FIELD **) List;
2696 DT_FIELD *SubtableStart;
2697 ACPI_DMTABLE_INFO *InfoTable = NULL;
2698 UINT8 SubtableType;
2699 UINT8 Temp64[16];
2700 UINT8 Temp8;
2701
2702
2703 /* Main table */
2704
2705 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
2706 &Subtable);
2707 if (ACPI_FAILURE (Status))
2708 {
2709 return (Status);
2710 }
2711
2712 ParentTable = DtPeekSubtable ();
2713 DtInsertSubtable (ParentTable, Subtable);
2714 DtPushSubtable (Subtable);
2715
2716 /* Save a pointer to the main subtable */
2717
2718 MainSubtable = Subtable;
2719
2720 while (*PFieldList)
2721 {
2722 SubtableStart = *PFieldList;
2723
2724 /* Compile the SubtableType integer */
2725
2726 DtCompileInteger (&SubtableType, *PFieldList, 1, 0);
2727
2728 switch (SubtableType)
2729 {
2730
2731 /* Type 10h, IVHD (I/O Virtualization Hardware Definition) */
2732
2733 case ACPI_IVRS_TYPE_HARDWARE1:
2734
2735 InfoTable = AcpiDmTableInfoIvrsHware1;
2736 break;
2737
2738 /* Types 11h, 40h, IVHD (I/O Virtualization Hardware Definition) */
2739
2740 case ACPI_IVRS_TYPE_HARDWARE2:
2741 case ACPI_IVRS_TYPE_HARDWARE3:
2742
2743 InfoTable = AcpiDmTableInfoIvrsHware23;
2744 break;
2745
2746 /* Types 20h, 21h, 22h, IVMD (I/O Virtualization Memory Definition Block) */
2747
2748 case ACPI_IVRS_TYPE_MEMORY1:
2749 case ACPI_IVRS_TYPE_MEMORY2:
2750 case ACPI_IVRS_TYPE_MEMORY3:
2751
2752 InfoTable = AcpiDmTableInfoIvrsMemory;
2753 break;
2754
2755 /* 4-byte device entries */
2756
2757 case ACPI_IVRS_TYPE_PAD4:
2758 case ACPI_IVRS_TYPE_ALL:
2759 case ACPI_IVRS_TYPE_SELECT:
2760 case ACPI_IVRS_TYPE_START:
2761 case ACPI_IVRS_TYPE_END:
2762
2763 InfoTable = AcpiDmTableInfoIvrs4;
2764 break;
2765
2766 /* 8-byte device entries, type A */
2767
2768 case ACPI_IVRS_TYPE_ALIAS_SELECT:
2769 case ACPI_IVRS_TYPE_ALIAS_START:
2770
2771 InfoTable = AcpiDmTableInfoIvrs8a;
2772 break;
2773
2774 /* 8-byte device entries, type B */
2775
2776 case ACPI_IVRS_TYPE_EXT_SELECT:
2777 case ACPI_IVRS_TYPE_EXT_START:
2778
2779 InfoTable = AcpiDmTableInfoIvrs8b;
2780 break;
2781
2782 /* 8-byte device entries, type C */
2783
2784 case ACPI_IVRS_TYPE_SPECIAL:
2785
2786 InfoTable = AcpiDmTableInfoIvrs8c;
2787 break;
2788
2789 /* Variable device entries, type F0h */
2790
2791 case ACPI_IVRS_TYPE_HID:
2792
2793 InfoTable = AcpiDmTableInfoIvrsHid;
2794 break;
2795
2796 default:
2797
2798 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
2799 "IVRS Device Entry");
2800 return (AE_ERROR);
2801 }
2802
2803 /* Compile the InfoTable from above */
2804
2805 Status = DtCompileTable (PFieldList, InfoTable,
2806 &Subtable);
2807 if (ACPI_FAILURE (Status))
2808 {
2809 return (Status);
2810 }
2811
2812 ParentTable = DtPeekSubtable ();
2813 if (SubtableType != ACPI_IVRS_TYPE_HARDWARE1 &&
2814 SubtableType != ACPI_IVRS_TYPE_HARDWARE2 &&
2815 SubtableType != ACPI_IVRS_TYPE_HARDWARE3 &&
2816 SubtableType != ACPI_IVRS_TYPE_HID &&
2817 SubtableType != ACPI_IVRS_TYPE_MEMORY1 &&
2818 SubtableType != ACPI_IVRS_TYPE_MEMORY2 &&
2819 SubtableType != ACPI_IVRS_TYPE_MEMORY3)
2820 {
2821 if (ParentTable)
2822 DtInsertSubtable (ParentTable, Subtable);
2823 }
2824
2825 switch (SubtableType)
2826 {
2827 case ACPI_IVRS_TYPE_HARDWARE1:
2828 case ACPI_IVRS_TYPE_HARDWARE2:
2829 case ACPI_IVRS_TYPE_HARDWARE3:
2830 case ACPI_IVRS_TYPE_MEMORY1:
2831 case ACPI_IVRS_TYPE_MEMORY2:
2832 case ACPI_IVRS_TYPE_MEMORY3:
2833
2834 /* Insert these IVHDs/IVMDs at the root subtable */
2835
2836 DtInsertSubtable (MainSubtable, Subtable);
2837 DtPushSubtable (Subtable);
2838 break;
2839
2840 case ACPI_IVRS_TYPE_HID:
2841
2842 /* Special handling for the HID named device entry (0xF0) */
2843
2844 if (ParentTable)
2845 {
2846 DtInsertSubtable (ParentTable, Subtable);
2847 }
2848
2849 /*
2850 * Process the HID value. First, get the HID value as a string.
2851 */
2852 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
2853
2854 /*
2855 * Determine if the HID is an integer or a string.
2856 * An integer is defined to be 32 bits, with the upper 32 bits
2857 * set to zero. (from the ACPI Spec): "The HID can be a 32-bit
2858 * integer or a character string. If an integer, the lower
2859 * 4 bytes of the field contain the integer and the upper
2860 * 4 bytes are padded with 0".
2861 */
2862 if (UtIsIdInteger ((UINT8 *) &Temp64))
2863 {
2864 /* Compile the HID value as an integer */
2865
2866 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
2867
2868 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidInteger,
2869 &Subtable);
2870 if (ACPI_FAILURE (Status))
2871 {
2872 return (Status);
2873 }
2874 }
2875 else
2876 {
2877 /* Compile the HID value as a string */
2878
2879 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidString,
2880 &Subtable);
2881 if (ACPI_FAILURE (Status))
2882 {
2883 return (Status);
2884 }
2885 }
2886
2887 DtInsertSubtable (ParentTable, Subtable);
2888
2889 /*
2890 * Process the CID value. First, get the CID value as a string.
2891 */
2892 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
2893
2894 if (UtIsIdInteger ((UINT8 *) &Temp64))
2895 {
2896 /* Compile the CID value as an integer */
2897
2898 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
2899
2900 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidInteger,
2901 &Subtable);
2902 if (ACPI_FAILURE (Status))
2903 {
2904 return (Status);
2905 }
2906 }
2907 else
2908 {
2909 /* Compile the CID value as a string */
2910
2911 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidString,
2912 &Subtable);
2913 if (ACPI_FAILURE (Status))
2914 {
2915 return (Status);
2916 }
2917 }
2918
2919 DtInsertSubtable (ParentTable, Subtable);
2920
2921 /*
2922 * Process the UID value. First, get and decode the "UID Format" field (Integer).
2923 */
2924 if (!*PFieldList)
2925 {
2926 return (AE_OK);
2927 }
2928
2929 DtCompileOneField (&Temp8, *PFieldList, 1, DT_FIELD_TYPE_INTEGER, 0);
2930
2931 switch (Temp8)
2932 {
2933 case ACPI_IVRS_UID_NOT_PRESENT:
2934 break;
2935
2936 case ACPI_IVRS_UID_IS_INTEGER:
2937
2938 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidInteger,
2939 &Subtable);
2940 if (ACPI_FAILURE (Status))
2941 {
2942 return (Status);
2943 }
2944 DtInsertSubtable (ParentTable, Subtable);
2945 break;
2946
2947 case ACPI_IVRS_UID_IS_STRING:
2948
2949 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidString,
2950 &Subtable);
2951 if (ACPI_FAILURE (Status))
2952 {
2953 return (Status);
2954 }
2955 DtInsertSubtable (ParentTable, Subtable);
2956 break;
2957
2958 default:
2959
2960 DtFatal (ASL_MSG_UNKNOWN_FORMAT, SubtableStart,
2961 "IVRS Device Entry");
2962 return (AE_ERROR);
2963 }
2964
2965 default:
2966
2967 /* All other subtable types come through here */
2968 break;
2969 }
2970 }
2971
2972 return (AE_OK);
2973 }
2974