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