dttable1.c revision 1.1.1.5 1 /******************************************************************************
2 *
3 * Module Name: dttable1.c - handling for specific ACPI tables
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2017, 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 MERCHANTIBILITY 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 #include "dtcompiler.h"
48
49 #define _COMPONENT DT_COMPILER
50 ACPI_MODULE_NAME ("dttable1")
51
52
53 static ACPI_DMTABLE_INFO TableInfoAsfAddress[] =
54 {
55 {ACPI_DMT_BUFFER, 0, "Addresses", 0},
56 {ACPI_DMT_EXIT, 0, NULL, 0}
57 };
58
59 static ACPI_DMTABLE_INFO TableInfoDmarPciPath[] =
60 {
61 {ACPI_DMT_PCI_PATH, 0, "PCI Path", 0},
62 {ACPI_DMT_EXIT, 0, NULL, 0}
63 };
64
65
66 /******************************************************************************
67 *
68 * FUNCTION: DtCompileAsf
69 *
70 * PARAMETERS: List - Current field list pointer
71 *
72 * RETURN: Status
73 *
74 * DESCRIPTION: Compile ASF!.
75 *
76 *****************************************************************************/
77
78 ACPI_STATUS
79 DtCompileAsf (
80 void **List)
81 {
82 ACPI_ASF_INFO *AsfTable;
83 DT_SUBTABLE *Subtable;
84 DT_SUBTABLE *ParentTable;
85 ACPI_DMTABLE_INFO *InfoTable;
86 ACPI_DMTABLE_INFO *DataInfoTable = NULL;
87 UINT32 DataCount = 0;
88 ACPI_STATUS Status;
89 UINT32 i;
90 DT_FIELD **PFieldList = (DT_FIELD **) List;
91 DT_FIELD *SubtableStart;
92
93
94 while (*PFieldList)
95 {
96 SubtableStart = *PFieldList;
97 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr,
98 &Subtable, TRUE);
99 if (ACPI_FAILURE (Status))
100 {
101 return (Status);
102 }
103
104 ParentTable = DtPeekSubtable ();
105 DtInsertSubtable (ParentTable, Subtable);
106 DtPushSubtable (Subtable);
107
108 AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer);
109
110 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
111 {
112 case ACPI_ASF_TYPE_INFO:
113
114 InfoTable = AcpiDmTableInfoAsf0;
115 break;
116
117 case ACPI_ASF_TYPE_ALERT:
118
119 InfoTable = AcpiDmTableInfoAsf1;
120 break;
121
122 case ACPI_ASF_TYPE_CONTROL:
123
124 InfoTable = AcpiDmTableInfoAsf2;
125 break;
126
127 case ACPI_ASF_TYPE_BOOT:
128
129 InfoTable = AcpiDmTableInfoAsf3;
130 break;
131
132 case ACPI_ASF_TYPE_ADDRESS:
133
134 InfoTable = AcpiDmTableInfoAsf4;
135 break;
136
137 default:
138
139 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
140 return (AE_ERROR);
141 }
142
143 Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
144 if (ACPI_FAILURE (Status))
145 {
146 return (Status);
147 }
148
149 ParentTable = DtPeekSubtable ();
150 DtInsertSubtable (ParentTable, Subtable);
151
152 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
153 {
154 case ACPI_ASF_TYPE_INFO:
155
156 DataInfoTable = NULL;
157 break;
158
159 case ACPI_ASF_TYPE_ALERT:
160
161 DataInfoTable = AcpiDmTableInfoAsf1a;
162 DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT,
163 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
164 sizeof (ACPI_ASF_HEADER)))->Alerts;
165 break;
166
167 case ACPI_ASF_TYPE_CONTROL:
168
169 DataInfoTable = AcpiDmTableInfoAsf2a;
170 DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE,
171 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
172 sizeof (ACPI_ASF_HEADER)))->Controls;
173 break;
174
175 case ACPI_ASF_TYPE_BOOT:
176
177 DataInfoTable = NULL;
178 break;
179
180 case ACPI_ASF_TYPE_ADDRESS:
181
182 DataInfoTable = TableInfoAsfAddress;
183 DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS,
184 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
185 sizeof (ACPI_ASF_HEADER)))->Devices;
186 break;
187
188 default:
189
190 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
191 return (AE_ERROR);
192 }
193
194 if (DataInfoTable)
195 {
196 switch (AsfTable->Header.Type & 0x7F)
197 {
198 case ACPI_ASF_TYPE_ADDRESS:
199
200 while (DataCount > 0)
201 {
202 Status = DtCompileTable (PFieldList, DataInfoTable,
203 &Subtable, TRUE);
204 if (ACPI_FAILURE (Status))
205 {
206 return (Status);
207 }
208
209 DtInsertSubtable (ParentTable, Subtable);
210 DataCount = DataCount - Subtable->Length;
211 }
212 break;
213
214 default:
215
216 for (i = 0; i < DataCount; i++)
217 {
218 Status = DtCompileTable (PFieldList, DataInfoTable,
219 &Subtable, TRUE);
220 if (ACPI_FAILURE (Status))
221 {
222 return (Status);
223 }
224
225 DtInsertSubtable (ParentTable, Subtable);
226 }
227 break;
228 }
229 }
230
231 DtPopSubtable ();
232 }
233
234 return (AE_OK);
235 }
236
237
238 /******************************************************************************
239 *
240 * FUNCTION: DtCompileCpep
241 *
242 * PARAMETERS: List - Current field list pointer
243 *
244 * RETURN: Status
245 *
246 * DESCRIPTION: Compile CPEP.
247 *
248 *****************************************************************************/
249
250 ACPI_STATUS
251 DtCompileCpep (
252 void **List)
253 {
254 ACPI_STATUS Status;
255
256
257 Status = DtCompileTwoSubtables (List,
258 AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0);
259 return (Status);
260 }
261
262
263 /******************************************************************************
264 *
265 * FUNCTION: DtCompileCsrt
266 *
267 * PARAMETERS: List - Current field list pointer
268 *
269 * RETURN: Status
270 *
271 * DESCRIPTION: Compile CSRT.
272 *
273 *****************************************************************************/
274
275 ACPI_STATUS
276 DtCompileCsrt (
277 void **List)
278 {
279 ACPI_STATUS Status = AE_OK;
280 DT_SUBTABLE *Subtable;
281 DT_SUBTABLE *ParentTable;
282 DT_FIELD **PFieldList = (DT_FIELD **) List;
283 UINT32 DescriptorCount;
284 UINT32 GroupLength;
285
286
287 /* Subtables (Resource Groups) */
288
289 ParentTable = DtPeekSubtable ();
290 while (*PFieldList)
291 {
292 /* Resource group subtable */
293
294 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0,
295 &Subtable, TRUE);
296 if (ACPI_FAILURE (Status))
297 {
298 return (Status);
299 }
300
301 /* Compute the number of resource descriptors */
302
303 GroupLength =
304 (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
305 Subtable->Buffer))->Length -
306 (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
307 Subtable->Buffer))->SharedInfoLength -
308 sizeof (ACPI_CSRT_GROUP);
309
310 DescriptorCount = (GroupLength /
311 sizeof (ACPI_CSRT_DESCRIPTOR));
312
313 DtInsertSubtable (ParentTable, Subtable);
314 DtPushSubtable (Subtable);
315 ParentTable = DtPeekSubtable ();
316
317 /* Shared info subtable (One per resource group) */
318
319 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1,
320 &Subtable, TRUE);
321 if (ACPI_FAILURE (Status))
322 {
323 return (Status);
324 }
325
326 DtInsertSubtable (ParentTable, Subtable);
327
328 /* Sub-Subtables (Resource Descriptors) */
329
330 while (*PFieldList && DescriptorCount)
331 {
332
333 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2,
334 &Subtable, TRUE);
335 if (ACPI_FAILURE (Status))
336 {
337 return (Status);
338 }
339
340 DtInsertSubtable (ParentTable, Subtable);
341
342 DtPushSubtable (Subtable);
343 ParentTable = DtPeekSubtable ();
344 if (*PFieldList)
345 {
346 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a,
347 &Subtable, TRUE);
348 if (ACPI_FAILURE (Status))
349 {
350 return (Status);
351 }
352 if (Subtable)
353 {
354 DtInsertSubtable (ParentTable, Subtable);
355 }
356 }
357
358 DtPopSubtable ();
359 ParentTable = DtPeekSubtable ();
360 DescriptorCount--;
361 }
362
363 DtPopSubtable ();
364 ParentTable = DtPeekSubtable ();
365 }
366
367 return (Status);
368 }
369
370
371 /******************************************************************************
372 *
373 * FUNCTION: DtCompileDbg2
374 *
375 * PARAMETERS: List - Current field list pointer
376 *
377 * RETURN: Status
378 *
379 * DESCRIPTION: Compile DBG2.
380 *
381 *****************************************************************************/
382
383 ACPI_STATUS
384 DtCompileDbg2 (
385 void **List)
386 {
387 ACPI_STATUS Status;
388 DT_SUBTABLE *Subtable;
389 DT_SUBTABLE *ParentTable;
390 DT_FIELD **PFieldList = (DT_FIELD **) List;
391 UINT32 SubtableCount;
392 ACPI_DBG2_HEADER *Dbg2Header;
393 ACPI_DBG2_DEVICE *DeviceInfo;
394 UINT16 CurrentOffset;
395 UINT32 i;
396
397
398 /* Main table */
399
400 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable, TRUE);
401 if (ACPI_FAILURE (Status))
402 {
403 return (Status);
404 }
405
406 ParentTable = DtPeekSubtable ();
407 DtInsertSubtable (ParentTable, Subtable);
408
409 /* Main table fields */
410
411 Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer);
412 Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF (
413 ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header);
414
415 SubtableCount = Dbg2Header->InfoCount;
416 DtPushSubtable (Subtable);
417
418 /* Process all Device Information subtables (Count = InfoCount) */
419
420 while (*PFieldList && SubtableCount)
421 {
422 /* Subtable: Debug Device Information */
423
424 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device,
425 &Subtable, TRUE);
426 if (ACPI_FAILURE (Status))
427 {
428 return (Status);
429 }
430
431 DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer);
432 CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE);
433
434 ParentTable = DtPeekSubtable ();
435 DtInsertSubtable (ParentTable, Subtable);
436 DtPushSubtable (Subtable);
437
438 ParentTable = DtPeekSubtable ();
439
440 /* BaseAddressRegister GAS array (Required, size is RegisterCount) */
441
442 DeviceInfo->BaseAddressOffset = CurrentOffset;
443 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
444 {
445 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr,
446 &Subtable, TRUE);
447 if (ACPI_FAILURE (Status))
448 {
449 return (Status);
450 }
451
452 CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS);
453 DtInsertSubtable (ParentTable, Subtable);
454 }
455
456 /* AddressSize array (Required, size = RegisterCount) */
457
458 DeviceInfo->AddressSizeOffset = CurrentOffset;
459 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
460 {
461 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size,
462 &Subtable, TRUE);
463 if (ACPI_FAILURE (Status))
464 {
465 return (Status);
466 }
467
468 CurrentOffset += (UINT16) sizeof (UINT32);
469 DtInsertSubtable (ParentTable, Subtable);
470 }
471
472 /* NamespaceString device identifier (Required, size = NamePathLength) */
473
474 DeviceInfo->NamepathOffset = CurrentOffset;
475 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name,
476 &Subtable, TRUE);
477 if (ACPI_FAILURE (Status))
478 {
479 return (Status);
480 }
481
482 /* Update the device info header */
483
484 DeviceInfo->NamepathLength = (UINT16) Subtable->Length;
485 CurrentOffset += (UINT16) DeviceInfo->NamepathLength;
486 DtInsertSubtable (ParentTable, Subtable);
487
488 /* OemData - Variable-length data (Optional, size = OemDataLength) */
489
490 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData,
491 &Subtable, TRUE);
492 if (ACPI_FAILURE (Status))
493 {
494 return (Status);
495 }
496
497 /* Update the device info header (zeros if no OEM data present) */
498
499 DeviceInfo->OemDataOffset = 0;
500 DeviceInfo->OemDataLength = 0;
501
502 /* Optional subtable (OemData) */
503
504 if (Subtable && Subtable->Length)
505 {
506 DeviceInfo->OemDataOffset = CurrentOffset;
507 DeviceInfo->OemDataLength = (UINT16) Subtable->Length;
508
509 DtInsertSubtable (ParentTable, Subtable);
510 }
511
512 SubtableCount--;
513 DtPopSubtable (); /* Get next Device Information subtable */
514 }
515
516 DtPopSubtable ();
517 return (AE_OK);
518 }
519
520
521 /******************************************************************************
522 *
523 * FUNCTION: DtCompileDmar
524 *
525 * PARAMETERS: List - Current field list pointer
526 *
527 * RETURN: Status
528 *
529 * DESCRIPTION: Compile DMAR.
530 *
531 *****************************************************************************/
532
533 ACPI_STATUS
534 DtCompileDmar (
535 void **List)
536 {
537 ACPI_STATUS Status;
538 DT_SUBTABLE *Subtable;
539 DT_SUBTABLE *ParentTable;
540 DT_FIELD **PFieldList = (DT_FIELD **) List;
541 DT_FIELD *SubtableStart;
542 ACPI_DMTABLE_INFO *InfoTable;
543 ACPI_DMAR_HEADER *DmarHeader;
544 ACPI_DMAR_DEVICE_SCOPE *DmarDeviceScope;
545 UINT32 DeviceScopeLength;
546 UINT32 PciPathLength;
547
548
549 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable, TRUE);
550 if (ACPI_FAILURE (Status))
551 {
552 return (Status);
553 }
554
555 ParentTable = DtPeekSubtable ();
556 DtInsertSubtable (ParentTable, Subtable);
557 DtPushSubtable (Subtable);
558
559 while (*PFieldList)
560 {
561 /* DMAR Header */
562
563 SubtableStart = *PFieldList;
564 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr,
565 &Subtable, TRUE);
566 if (ACPI_FAILURE (Status))
567 {
568 return (Status);
569 }
570
571 ParentTable = DtPeekSubtable ();
572 DtInsertSubtable (ParentTable, Subtable);
573 DtPushSubtable (Subtable);
574
575 DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer);
576
577 switch (DmarHeader->Type)
578 {
579 case ACPI_DMAR_TYPE_HARDWARE_UNIT:
580
581 InfoTable = AcpiDmTableInfoDmar0;
582 break;
583
584 case ACPI_DMAR_TYPE_RESERVED_MEMORY:
585
586 InfoTable = AcpiDmTableInfoDmar1;
587 break;
588
589 case ACPI_DMAR_TYPE_ROOT_ATS:
590
591 InfoTable = AcpiDmTableInfoDmar2;
592 break;
593
594 case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
595
596 InfoTable = AcpiDmTableInfoDmar3;
597 break;
598
599 case ACPI_DMAR_TYPE_NAMESPACE:
600
601 InfoTable = AcpiDmTableInfoDmar4;
602 break;
603
604 default:
605
606 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR");
607 return (AE_ERROR);
608 }
609
610 /* DMAR Subtable */
611
612 Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
613 if (ACPI_FAILURE (Status))
614 {
615 return (Status);
616 }
617
618 ParentTable = DtPeekSubtable ();
619 DtInsertSubtable (ParentTable, Subtable);
620
621 /*
622 * Optional Device Scope subtables
623 */
624 if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) ||
625 (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE))
626 {
627 /* These types do not support device scopes */
628
629 DtPopSubtable ();
630 continue;
631 }
632
633 DtPushSubtable (Subtable);
634 DeviceScopeLength = DmarHeader->Length - Subtable->Length -
635 ParentTable->Length;
636 while (DeviceScopeLength)
637 {
638 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope,
639 &Subtable, FALSE);
640 if (Status == AE_NOT_FOUND)
641 {
642 break;
643 }
644
645 ParentTable = DtPeekSubtable ();
646 DtInsertSubtable (ParentTable, Subtable);
647 DtPushSubtable (Subtable);
648
649 DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer);
650
651 /* Optional PCI Paths */
652
653 PciPathLength = DmarDeviceScope->Length - Subtable->Length;
654 while (PciPathLength)
655 {
656 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath,
657 &Subtable, FALSE);
658 if (Status == AE_NOT_FOUND)
659 {
660 DtPopSubtable ();
661 break;
662 }
663
664 ParentTable = DtPeekSubtable ();
665 DtInsertSubtable (ParentTable, Subtable);
666 PciPathLength -= Subtable->Length;
667 }
668
669 DtPopSubtable ();
670 DeviceScopeLength -= DmarDeviceScope->Length;
671 }
672
673 DtPopSubtable ();
674 DtPopSubtable ();
675 }
676
677 return (AE_OK);
678 }
679
680
681 /******************************************************************************
682 *
683 * FUNCTION: DtCompileDrtm
684 *
685 * PARAMETERS: List - Current field list pointer
686 *
687 * RETURN: Status
688 *
689 * DESCRIPTION: Compile DRTM.
690 *
691 *****************************************************************************/
692
693 ACPI_STATUS
694 DtCompileDrtm (
695 void **List)
696 {
697 ACPI_STATUS Status;
698 DT_SUBTABLE *Subtable;
699 DT_SUBTABLE *ParentTable;
700 DT_FIELD **PFieldList = (DT_FIELD **) List;
701 UINT32 Count;
702 /* ACPI_TABLE_DRTM *Drtm; */
703 ACPI_DRTM_VTABLE_LIST *DrtmVtl;
704 ACPI_DRTM_RESOURCE_LIST *DrtmRl;
705 /* ACPI_DRTM_DPS_ID *DrtmDps; */
706
707
708 ParentTable = DtPeekSubtable ();
709
710 /* Compile DRTM header */
711
712 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm,
713 &Subtable, TRUE);
714 if (ACPI_FAILURE (Status))
715 {
716 return (Status);
717 }
718 DtInsertSubtable (ParentTable, Subtable);
719
720 /*
721 * Using ACPI_SUB_PTR, We needn't define a seperate structure. Care
722 * should be taken to avoid accessing ACPI_TABLE_HADER fields.
723 */
724 #if 0
725 Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM,
726 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
727 #endif
728 /* Compile VTL */
729
730 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0,
731 &Subtable, TRUE);
732 if (ACPI_FAILURE (Status))
733 {
734 return (Status);
735 }
736
737 DtInsertSubtable (ParentTable, Subtable);
738 DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer);
739
740 DtPushSubtable (Subtable);
741 ParentTable = DtPeekSubtable ();
742 Count = 0;
743
744 while (*PFieldList)
745 {
746 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a,
747 &Subtable, TRUE);
748 if (ACPI_FAILURE (Status))
749 {
750 return (Status);
751 }
752 if (!Subtable)
753 {
754 break;
755 }
756 DtInsertSubtable (ParentTable, Subtable);
757 Count++;
758 }
759
760 DrtmVtl->ValidatedTableCount = Count;
761 DtPopSubtable ();
762 ParentTable = DtPeekSubtable ();
763
764 /* Compile RL */
765
766 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1,
767 &Subtable, TRUE);
768 if (ACPI_FAILURE (Status))
769 {
770 return (Status);
771 }
772
773 DtInsertSubtable (ParentTable, Subtable);
774 DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer);
775
776 DtPushSubtable (Subtable);
777 ParentTable = DtPeekSubtable ();
778 Count = 0;
779
780 while (*PFieldList)
781 {
782 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a,
783 &Subtable, TRUE);
784 if (ACPI_FAILURE (Status))
785 {
786 return (Status);
787 }
788
789 if (!Subtable)
790 {
791 break;
792 }
793
794 DtInsertSubtable (ParentTable, Subtable);
795 Count++;
796 }
797
798 DrtmRl->ResourceCount = Count;
799 DtPopSubtable ();
800 ParentTable = DtPeekSubtable ();
801
802 /* Compile DPS */
803
804 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2,
805 &Subtable, TRUE);
806 if (ACPI_FAILURE (Status))
807 {
808 return (Status);
809 }
810 DtInsertSubtable (ParentTable, Subtable);
811 /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/
812
813
814 return (AE_OK);
815 }
816
817
818 /******************************************************************************
819 *
820 * FUNCTION: DtCompileEinj
821 *
822 * PARAMETERS: List - Current field list pointer
823 *
824 * RETURN: Status
825 *
826 * DESCRIPTION: Compile EINJ.
827 *
828 *****************************************************************************/
829
830 ACPI_STATUS
831 DtCompileEinj (
832 void **List)
833 {
834 ACPI_STATUS Status;
835
836
837 Status = DtCompileTwoSubtables (List,
838 AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
839 return (Status);
840 }
841
842
843 /******************************************************************************
844 *
845 * FUNCTION: DtCompileErst
846 *
847 * PARAMETERS: List - Current field list pointer
848 *
849 * RETURN: Status
850 *
851 * DESCRIPTION: Compile ERST.
852 *
853 *****************************************************************************/
854
855 ACPI_STATUS
856 DtCompileErst (
857 void **List)
858 {
859 ACPI_STATUS Status;
860
861
862 Status = DtCompileTwoSubtables (List,
863 AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
864 return (Status);
865 }
866
867
868 /******************************************************************************
869 *
870 * FUNCTION: DtCompileGtdt
871 *
872 * PARAMETERS: List - Current field list pointer
873 *
874 * RETURN: Status
875 *
876 * DESCRIPTION: Compile GTDT.
877 *
878 *****************************************************************************/
879
880 ACPI_STATUS
881 DtCompileGtdt (
882 void **List)
883 {
884 ACPI_STATUS Status;
885 DT_SUBTABLE *Subtable;
886 DT_SUBTABLE *ParentTable;
887 DT_FIELD **PFieldList = (DT_FIELD **) List;
888 DT_FIELD *SubtableStart;
889 ACPI_SUBTABLE_HEADER *GtdtHeader;
890 ACPI_DMTABLE_INFO *InfoTable;
891 UINT32 GtCount;
892
893
894 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
895 &Subtable, TRUE);
896 if (ACPI_FAILURE (Status))
897 {
898 return (Status);
899 }
900
901 ParentTable = DtPeekSubtable ();
902 DtInsertSubtable (ParentTable, Subtable);
903
904 while (*PFieldList)
905 {
906 SubtableStart = *PFieldList;
907 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
908 &Subtable, TRUE);
909 if (ACPI_FAILURE (Status))
910 {
911 return (Status);
912 }
913
914 ParentTable = DtPeekSubtable ();
915 DtInsertSubtable (ParentTable, Subtable);
916 DtPushSubtable (Subtable);
917
918 GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
919
920 switch (GtdtHeader->Type)
921 {
922 case ACPI_GTDT_TYPE_TIMER_BLOCK:
923
924 InfoTable = AcpiDmTableInfoGtdt0;
925 break;
926
927 case ACPI_GTDT_TYPE_WATCHDOG:
928
929 InfoTable = AcpiDmTableInfoGtdt1;
930 break;
931
932 default:
933
934 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
935 return (AE_ERROR);
936 }
937
938 Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
939 if (ACPI_FAILURE (Status))
940 {
941 return (Status);
942 }
943
944 ParentTable = DtPeekSubtable ();
945 DtInsertSubtable (ParentTable, Subtable);
946
947 /*
948 * Additional GT block subtable data
949 */
950
951 switch (GtdtHeader->Type)
952 {
953 case ACPI_GTDT_TYPE_TIMER_BLOCK:
954
955 DtPushSubtable (Subtable);
956 ParentTable = DtPeekSubtable ();
957
958 GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
959 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
960
961 while (GtCount)
962 {
963 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
964 &Subtable, TRUE);
965 if (ACPI_FAILURE (Status))
966 {
967 return (Status);
968 }
969
970 DtInsertSubtable (ParentTable, Subtable);
971 GtCount--;
972 }
973
974 DtPopSubtable ();
975 break;
976
977 default:
978
979 break;
980 }
981
982 DtPopSubtable ();
983 }
984
985 return (AE_OK);
986 }
987
988
989 /******************************************************************************
990 *
991 * FUNCTION: DtCompileFpdt
992 *
993 * PARAMETERS: List - Current field list pointer
994 *
995 * RETURN: Status
996 *
997 * DESCRIPTION: Compile FPDT.
998 *
999 *****************************************************************************/
1000
1001 ACPI_STATUS
1002 DtCompileFpdt (
1003 void **List)
1004 {
1005 ACPI_STATUS Status;
1006 ACPI_FPDT_HEADER *FpdtHeader;
1007 DT_SUBTABLE *Subtable;
1008 DT_SUBTABLE *ParentTable;
1009 ACPI_DMTABLE_INFO *InfoTable;
1010 DT_FIELD **PFieldList = (DT_FIELD **) List;
1011 DT_FIELD *SubtableStart;
1012
1013
1014 while (*PFieldList)
1015 {
1016 SubtableStart = *PFieldList;
1017 Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
1018 &Subtable, TRUE);
1019 if (ACPI_FAILURE (Status))
1020 {
1021 return (Status);
1022 }
1023
1024 ParentTable = DtPeekSubtable ();
1025 DtInsertSubtable (ParentTable, Subtable);
1026 DtPushSubtable (Subtable);
1027
1028 FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
1029
1030 switch (FpdtHeader->Type)
1031 {
1032 case ACPI_FPDT_TYPE_BOOT:
1033
1034 InfoTable = AcpiDmTableInfoFpdt0;
1035 break;
1036
1037 case ACPI_FPDT_TYPE_S3PERF:
1038
1039 InfoTable = AcpiDmTableInfoFpdt1;
1040 break;
1041
1042 default:
1043
1044 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
1045 return (AE_ERROR);
1046 break;
1047 }
1048
1049 Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
1050 if (ACPI_FAILURE (Status))
1051 {
1052 return (Status);
1053 }
1054
1055 ParentTable = DtPeekSubtable ();
1056 DtInsertSubtable (ParentTable, Subtable);
1057 DtPopSubtable ();
1058 }
1059
1060 return (AE_OK);
1061 }
1062
1063
1064 /******************************************************************************
1065 *
1066 * FUNCTION: DtCompileHest
1067 *
1068 * PARAMETERS: List - Current field list pointer
1069 *
1070 * RETURN: Status
1071 *
1072 * DESCRIPTION: Compile HEST.
1073 *
1074 *****************************************************************************/
1075
1076 ACPI_STATUS
1077 DtCompileHest (
1078 void **List)
1079 {
1080 ACPI_STATUS Status;
1081 DT_SUBTABLE *Subtable;
1082 DT_SUBTABLE *ParentTable;
1083 DT_FIELD **PFieldList = (DT_FIELD **) List;
1084 DT_FIELD *SubtableStart;
1085 ACPI_DMTABLE_INFO *InfoTable;
1086 UINT16 Type;
1087 UINT32 BankCount;
1088
1089
1090 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
1091 &Subtable, TRUE);
1092 if (ACPI_FAILURE (Status))
1093 {
1094 return (Status);
1095 }
1096
1097 ParentTable = DtPeekSubtable ();
1098 DtInsertSubtable (ParentTable, Subtable);
1099
1100 while (*PFieldList)
1101 {
1102 /* Get subtable type */
1103
1104 SubtableStart = *PFieldList;
1105 DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
1106
1107 switch (Type)
1108 {
1109 case ACPI_HEST_TYPE_IA32_CHECK:
1110
1111 InfoTable = AcpiDmTableInfoHest0;
1112 break;
1113
1114 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1115
1116 InfoTable = AcpiDmTableInfoHest1;
1117 break;
1118
1119 case ACPI_HEST_TYPE_IA32_NMI:
1120
1121 InfoTable = AcpiDmTableInfoHest2;
1122 break;
1123
1124 case ACPI_HEST_TYPE_AER_ROOT_PORT:
1125
1126 InfoTable = AcpiDmTableInfoHest6;
1127 break;
1128
1129 case ACPI_HEST_TYPE_AER_ENDPOINT:
1130
1131 InfoTable = AcpiDmTableInfoHest7;
1132 break;
1133
1134 case ACPI_HEST_TYPE_AER_BRIDGE:
1135
1136 InfoTable = AcpiDmTableInfoHest8;
1137 break;
1138
1139 case ACPI_HEST_TYPE_GENERIC_ERROR:
1140
1141 InfoTable = AcpiDmTableInfoHest9;
1142 break;
1143
1144 case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
1145
1146 InfoTable = AcpiDmTableInfoHest10;
1147 break;
1148
1149 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1150
1151 InfoTable = AcpiDmTableInfoHest11;
1152 break;
1153
1154 default:
1155
1156 /* Cannot continue on unknown type */
1157
1158 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
1159 return (AE_ERROR);
1160 }
1161
1162 Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
1163 if (ACPI_FAILURE (Status))
1164 {
1165 return (Status);
1166 }
1167
1168 DtInsertSubtable (ParentTable, Subtable);
1169
1170 /*
1171 * Additional subtable data - IA32 Error Bank(s)
1172 */
1173 BankCount = 0;
1174 switch (Type)
1175 {
1176 case ACPI_HEST_TYPE_IA32_CHECK:
1177
1178 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
1179 Subtable->Buffer))->NumHardwareBanks;
1180 break;
1181
1182 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1183
1184 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
1185 Subtable->Buffer))->NumHardwareBanks;
1186 break;
1187
1188 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1189
1190 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
1191 Subtable->Buffer))->NumHardwareBanks;
1192 break;
1193
1194 default:
1195
1196 break;
1197 }
1198
1199 while (BankCount)
1200 {
1201 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
1202 &Subtable, TRUE);
1203 if (ACPI_FAILURE (Status))
1204 {
1205 return (Status);
1206 }
1207
1208 DtInsertSubtable (ParentTable, Subtable);
1209 BankCount--;
1210 }
1211 }
1212
1213 return (AE_OK);
1214 }
1215
1216
1217 /******************************************************************************
1218 *
1219 * FUNCTION: DtCompileHmat
1220 *
1221 * PARAMETERS: List - Current field list pointer
1222 *
1223 * RETURN: Status
1224 *
1225 * DESCRIPTION: Compile HMAT.
1226 *
1227 *****************************************************************************/
1228
1229 ACPI_STATUS
1230 DtCompileHmat (
1231 void **List)
1232 {
1233 ACPI_STATUS Status;
1234 DT_SUBTABLE *Subtable;
1235 DT_SUBTABLE *ParentTable;
1236 DT_FIELD **PFieldList = (DT_FIELD **) List;
1237 DT_FIELD *SubtableStart;
1238 DT_FIELD *EntryStart;
1239 ACPI_HMAT_STRUCTURE *HmatStruct;
1240 ACPI_HMAT_LOCALITY *HmatLocality;
1241 ACPI_HMAT_CACHE *HmatCache;
1242 ACPI_DMTABLE_INFO *InfoTable;
1243 UINT32 IntPDNumber;
1244 UINT32 TgtPDNumber;
1245 UINT64 EntryNumber;
1246 UINT16 SMBIOSHandleNumber;
1247
1248
1249 ParentTable = DtPeekSubtable ();
1250
1251 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
1252 &Subtable, TRUE);
1253 if (ACPI_FAILURE (Status))
1254 {
1255 return (Status);
1256 }
1257 DtInsertSubtable (ParentTable, Subtable);
1258
1259 while (*PFieldList)
1260 {
1261 /* Compile HMAT structure header */
1262
1263 SubtableStart = *PFieldList;
1264 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
1265 &Subtable, TRUE);
1266 if (ACPI_FAILURE (Status))
1267 {
1268 return (Status);
1269 }
1270 DtInsertSubtable (ParentTable, Subtable);
1271
1272 HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
1273 HmatStruct->Length = Subtable->Length;
1274
1275 /* Compile HMAT structure body */
1276
1277 switch (HmatStruct->Type)
1278 {
1279 case ACPI_HMAT_TYPE_ADDRESS_RANGE:
1280
1281 InfoTable = AcpiDmTableInfoHmat0;
1282 break;
1283
1284 case ACPI_HMAT_TYPE_LOCALITY:
1285
1286 InfoTable = AcpiDmTableInfoHmat1;
1287 break;
1288
1289 case ACPI_HMAT_TYPE_CACHE:
1290
1291 InfoTable = AcpiDmTableInfoHmat2;
1292 break;
1293
1294 default:
1295
1296 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
1297 return (AE_ERROR);
1298 }
1299
1300 Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
1301 if (ACPI_FAILURE (Status))
1302 {
1303 return (Status);
1304 }
1305 DtInsertSubtable (ParentTable, Subtable);
1306 HmatStruct->Length += Subtable->Length;
1307
1308 /* Compile HMAT structure additionals */
1309
1310 switch (HmatStruct->Type)
1311 {
1312 case ACPI_HMAT_TYPE_LOCALITY:
1313
1314 HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
1315 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1316
1317 /* Compile initiator proximity domain list */
1318
1319 IntPDNumber = 0;
1320 while (*PFieldList)
1321 {
1322 Status = DtCompileTable (PFieldList,
1323 AcpiDmTableInfoHmat1a, &Subtable, TRUE);
1324 if (ACPI_FAILURE (Status))
1325 {
1326 return (Status);
1327 }
1328 if (!Subtable)
1329 {
1330 break;
1331 }
1332 DtInsertSubtable (ParentTable, Subtable);
1333 HmatStruct->Length += Subtable->Length;
1334 IntPDNumber++;
1335 }
1336 HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
1337
1338 /* Compile target proximity domain list */
1339
1340 TgtPDNumber = 0;
1341 while (*PFieldList)
1342 {
1343 Status = DtCompileTable (PFieldList,
1344 AcpiDmTableInfoHmat1b, &Subtable, TRUE);
1345 if (ACPI_FAILURE (Status))
1346 {
1347 return (Status);
1348 }
1349 if (!Subtable)
1350 {
1351 break;
1352 }
1353 DtInsertSubtable (ParentTable, Subtable);
1354 HmatStruct->Length += Subtable->Length;
1355 TgtPDNumber++;
1356 }
1357 HmatLocality->NumberOfTargetPDs = TgtPDNumber;
1358
1359 /* Save start of the entries for reporting errors */
1360
1361 EntryStart = *PFieldList;
1362
1363 /* Compile latency/bandwidth entries */
1364
1365 EntryNumber = 0;
1366 while (*PFieldList)
1367 {
1368 Status = DtCompileTable (PFieldList,
1369 AcpiDmTableInfoHmat1c, &Subtable, TRUE);
1370 if (ACPI_FAILURE (Status))
1371 {
1372 return (Status);
1373 }
1374 if (!Subtable)
1375 {
1376 break;
1377 }
1378 DtInsertSubtable (ParentTable, Subtable);
1379 HmatStruct->Length += Subtable->Length;
1380 EntryNumber++;
1381 }
1382
1383 /* Validate number of entries */
1384
1385 if (EntryNumber !=
1386 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
1387 {
1388 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
1389 return (AE_ERROR);
1390 }
1391 break;
1392
1393 case ACPI_HMAT_TYPE_CACHE:
1394
1395 /* Compile SMBIOS handles */
1396
1397 HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
1398 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1399 SMBIOSHandleNumber = 0;
1400 while (*PFieldList)
1401 {
1402 Status = DtCompileTable (PFieldList,
1403 AcpiDmTableInfoHmat2a, &Subtable, TRUE);
1404 if (ACPI_FAILURE (Status))
1405 {
1406 return (Status);
1407 }
1408 if (!Subtable)
1409 {
1410 break;
1411 }
1412 DtInsertSubtable (ParentTable, Subtable);
1413 HmatStruct->Length += Subtable->Length;
1414 SMBIOSHandleNumber++;
1415 }
1416 HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
1417 break;
1418
1419 default:
1420
1421 break;
1422 }
1423 }
1424
1425 return (AE_OK);
1426 }
1427
1428
1429 /******************************************************************************
1430 *
1431 * FUNCTION: DtCompileIort
1432 *
1433 * PARAMETERS: List - Current field list pointer
1434 *
1435 * RETURN: Status
1436 *
1437 * DESCRIPTION: Compile IORT.
1438 *
1439 *****************************************************************************/
1440
1441 ACPI_STATUS
1442 DtCompileIort (
1443 void **List)
1444 {
1445 ACPI_STATUS Status;
1446 DT_SUBTABLE *Subtable;
1447 DT_SUBTABLE *ParentTable;
1448 DT_FIELD **PFieldList = (DT_FIELD **) List;
1449 DT_FIELD *SubtableStart;
1450 ACPI_TABLE_IORT *Iort;
1451 ACPI_IORT_NODE *IortNode;
1452 ACPI_IORT_ITS_GROUP *IortItsGroup;
1453 ACPI_IORT_SMMU *IortSmmu;
1454 UINT32 NodeNumber;
1455 UINT32 NodeLength;
1456 UINT32 IdMappingNumber;
1457 UINT32 ItsNumber;
1458 UINT32 ContextIrptNumber;
1459 UINT32 PmuIrptNumber;
1460 UINT32 PaddingLength;
1461
1462
1463 ParentTable = DtPeekSubtable ();
1464
1465 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
1466 &Subtable, TRUE);
1467 if (ACPI_FAILURE (Status))
1468 {
1469 return (Status);
1470 }
1471 DtInsertSubtable (ParentTable, Subtable);
1472
1473 /*
1474 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1475 * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
1476 */
1477 Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
1478 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1479
1480 /*
1481 * OptionalPadding - Variable-length data
1482 * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
1483 * Optionally allows the generic data types to be used for filling
1484 * this field.
1485 */
1486 Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
1487 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
1488 &Subtable, TRUE);
1489 if (ACPI_FAILURE (Status))
1490 {
1491 return (Status);
1492 }
1493 if (Subtable)
1494 {
1495 DtInsertSubtable (ParentTable, Subtable);
1496 Iort->NodeOffset += Subtable->Length;
1497 }
1498 else
1499 {
1500 Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
1501 AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
1502 if (ACPI_FAILURE (Status))
1503 {
1504 return (Status);
1505 }
1506 Iort->NodeOffset += PaddingLength;
1507 }
1508
1509 NodeNumber = 0;
1510 while (*PFieldList)
1511 {
1512 SubtableStart = *PFieldList;
1513 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
1514 &Subtable, TRUE);
1515 if (ACPI_FAILURE (Status))
1516 {
1517 return (Status);
1518 }
1519
1520 DtInsertSubtable (ParentTable, Subtable);
1521 IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
1522 NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
1523
1524 DtPushSubtable (Subtable);
1525 ParentTable = DtPeekSubtable ();
1526
1527 switch (IortNode->Type)
1528 {
1529 case ACPI_IORT_NODE_ITS_GROUP:
1530
1531 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
1532 &Subtable, TRUE);
1533 if (ACPI_FAILURE (Status))
1534 {
1535 return (Status);
1536 }
1537
1538 DtInsertSubtable (ParentTable, Subtable);
1539 IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
1540 NodeLength += Subtable->Length;
1541
1542 ItsNumber = 0;
1543 while (*PFieldList)
1544 {
1545 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
1546 &Subtable, TRUE);
1547 if (ACPI_FAILURE (Status))
1548 {
1549 return (Status);
1550 }
1551 if (!Subtable)
1552 {
1553 break;
1554 }
1555
1556 DtInsertSubtable (ParentTable, Subtable);
1557 NodeLength += Subtable->Length;
1558 ItsNumber++;
1559 }
1560
1561 IortItsGroup->ItsCount = ItsNumber;
1562 break;
1563
1564 case ACPI_IORT_NODE_NAMED_COMPONENT:
1565
1566 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
1567 &Subtable, TRUE);
1568 if (ACPI_FAILURE (Status))
1569 {
1570 return (Status);
1571 }
1572
1573 DtInsertSubtable (ParentTable, Subtable);
1574 NodeLength += Subtable->Length;
1575
1576 /*
1577 * Padding - Variable-length data
1578 * Optionally allows the offset of the ID mappings to be used
1579 * for filling this field.
1580 */
1581 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
1582 &Subtable, TRUE);
1583 if (ACPI_FAILURE (Status))
1584 {
1585 return (Status);
1586 }
1587
1588 if (Subtable)
1589 {
1590 DtInsertSubtable (ParentTable, Subtable);
1591 NodeLength += Subtable->Length;
1592 }
1593 else
1594 {
1595 if (NodeLength > IortNode->MappingOffset)
1596 {
1597 return (AE_BAD_DATA);
1598 }
1599
1600 if (NodeLength < IortNode->MappingOffset)
1601 {
1602 Status = DtCompilePadding (
1603 IortNode->MappingOffset - NodeLength,
1604 &Subtable);
1605 if (ACPI_FAILURE (Status))
1606 {
1607 return (Status);
1608 }
1609
1610 DtInsertSubtable (ParentTable, Subtable);
1611 NodeLength = IortNode->MappingOffset;
1612 }
1613 }
1614 break;
1615
1616 case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
1617
1618 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
1619 &Subtable, TRUE);
1620 if (ACPI_FAILURE (Status))
1621 {
1622 return (Status);
1623 }
1624
1625 DtInsertSubtable (ParentTable, Subtable);
1626 NodeLength += Subtable->Length;
1627 break;
1628
1629 case ACPI_IORT_NODE_SMMU:
1630
1631 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
1632 &Subtable, TRUE);
1633 if (ACPI_FAILURE (Status))
1634 {
1635 return (Status);
1636 }
1637
1638 DtInsertSubtable (ParentTable, Subtable);
1639 IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
1640 NodeLength += Subtable->Length;
1641
1642 /* Compile global interrupt array */
1643
1644 IortSmmu->GlobalInterruptOffset = NodeLength;
1645 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
1646 &Subtable, TRUE);
1647 if (ACPI_FAILURE (Status))
1648 {
1649 return (Status);
1650 }
1651
1652 DtInsertSubtable (ParentTable, Subtable);
1653 NodeLength += Subtable->Length;
1654
1655 /* Compile context interrupt array */
1656
1657 ContextIrptNumber = 0;
1658 IortSmmu->ContextInterruptOffset = NodeLength;
1659 while (*PFieldList)
1660 {
1661 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
1662 &Subtable, TRUE);
1663 if (ACPI_FAILURE (Status))
1664 {
1665 return (Status);
1666 }
1667
1668 if (!Subtable)
1669 {
1670 break;
1671 }
1672
1673 DtInsertSubtable (ParentTable, Subtable);
1674 NodeLength += Subtable->Length;
1675 ContextIrptNumber++;
1676 }
1677
1678 IortSmmu->ContextInterruptCount = ContextIrptNumber;
1679
1680 /* Compile PMU interrupt array */
1681
1682 PmuIrptNumber = 0;
1683 IortSmmu->PmuInterruptOffset = NodeLength;
1684 while (*PFieldList)
1685 {
1686 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
1687 &Subtable, TRUE);
1688 if (ACPI_FAILURE (Status))
1689 {
1690 return (Status);
1691 }
1692
1693 if (!Subtable)
1694 {
1695 break;
1696 }
1697
1698 DtInsertSubtable (ParentTable, Subtable);
1699 NodeLength += Subtable->Length;
1700 PmuIrptNumber++;
1701 }
1702
1703 IortSmmu->PmuInterruptCount = PmuIrptNumber;
1704 break;
1705
1706 case ACPI_IORT_NODE_SMMU_V3:
1707
1708 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
1709 &Subtable, TRUE);
1710 if (ACPI_FAILURE (Status))
1711 {
1712 return (Status);
1713 }
1714
1715 DtInsertSubtable (ParentTable, Subtable);
1716 NodeLength += Subtable->Length;
1717 break;
1718
1719 default:
1720
1721 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
1722 return (AE_ERROR);
1723 }
1724
1725 /* Compile Array of ID mappings */
1726
1727 IortNode->MappingOffset = NodeLength;
1728 IdMappingNumber = 0;
1729 while (*PFieldList)
1730 {
1731 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
1732 &Subtable, TRUE);
1733 if (ACPI_FAILURE (Status))
1734 {
1735 return (Status);
1736 }
1737
1738 if (!Subtable)
1739 {
1740 break;
1741 }
1742
1743 DtInsertSubtable (ParentTable, Subtable);
1744 NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
1745 IdMappingNumber++;
1746 }
1747
1748 IortNode->MappingCount = IdMappingNumber;
1749 if (!IdMappingNumber)
1750 {
1751 IortNode->MappingOffset = 0;
1752 }
1753
1754 /*
1755 * Node length can be determined by DT_LENGTH option
1756 * IortNode->Length = NodeLength;
1757 */
1758 DtPopSubtable ();
1759 ParentTable = DtPeekSubtable ();
1760 NodeNumber++;
1761 }
1762
1763 Iort->NodeCount = NodeNumber;
1764 return (AE_OK);
1765 }
1766
1767
1768 /******************************************************************************
1769 *
1770 * FUNCTION: DtCompileIvrs
1771 *
1772 * PARAMETERS: List - Current field list pointer
1773 *
1774 * RETURN: Status
1775 *
1776 * DESCRIPTION: Compile IVRS.
1777 *
1778 *****************************************************************************/
1779
1780 ACPI_STATUS
1781 DtCompileIvrs (
1782 void **List)
1783 {
1784 ACPI_STATUS Status;
1785 DT_SUBTABLE *Subtable;
1786 DT_SUBTABLE *ParentTable;
1787 DT_FIELD **PFieldList = (DT_FIELD **) List;
1788 DT_FIELD *SubtableStart;
1789 ACPI_DMTABLE_INFO *InfoTable;
1790 ACPI_IVRS_HEADER *IvrsHeader;
1791 UINT8 EntryType;
1792
1793
1794 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
1795 &Subtable, TRUE);
1796 if (ACPI_FAILURE (Status))
1797 {
1798 return (Status);
1799 }
1800
1801 ParentTable = DtPeekSubtable ();
1802 DtInsertSubtable (ParentTable, Subtable);
1803
1804 while (*PFieldList)
1805 {
1806 SubtableStart = *PFieldList;
1807 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHdr,
1808 &Subtable, TRUE);
1809 if (ACPI_FAILURE (Status))
1810 {
1811 return (Status);
1812 }
1813
1814 ParentTable = DtPeekSubtable ();
1815 DtInsertSubtable (ParentTable, Subtable);
1816 DtPushSubtable (Subtable);
1817
1818 IvrsHeader = ACPI_CAST_PTR (ACPI_IVRS_HEADER, Subtable->Buffer);
1819
1820 switch (IvrsHeader->Type)
1821 {
1822 case ACPI_IVRS_TYPE_HARDWARE:
1823
1824 InfoTable = AcpiDmTableInfoIvrs0;
1825 break;
1826
1827 case ACPI_IVRS_TYPE_MEMORY1:
1828 case ACPI_IVRS_TYPE_MEMORY2:
1829 case ACPI_IVRS_TYPE_MEMORY3:
1830
1831 InfoTable = AcpiDmTableInfoIvrs1;
1832 break;
1833
1834 default:
1835
1836 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IVRS");
1837 return (AE_ERROR);
1838 }
1839
1840 Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
1841 if (ACPI_FAILURE (Status))
1842 {
1843 return (Status);
1844 }
1845
1846 ParentTable = DtPeekSubtable ();
1847 DtInsertSubtable (ParentTable, Subtable);
1848
1849 if (IvrsHeader->Type == ACPI_IVRS_TYPE_HARDWARE)
1850 {
1851 while (*PFieldList &&
1852 !strcmp ((*PFieldList)->Name, "Entry Type"))
1853 {
1854 SubtableStart = *PFieldList;
1855 DtCompileInteger (&EntryType, *PFieldList, 1, 0);
1856
1857 switch (EntryType)
1858 {
1859 /* 4-byte device entries */
1860
1861 case ACPI_IVRS_TYPE_PAD4:
1862 case ACPI_IVRS_TYPE_ALL:
1863 case ACPI_IVRS_TYPE_SELECT:
1864 case ACPI_IVRS_TYPE_START:
1865 case ACPI_IVRS_TYPE_END:
1866
1867 InfoTable = AcpiDmTableInfoIvrs4;
1868 break;
1869
1870 /* 8-byte entries, type A */
1871
1872 case ACPI_IVRS_TYPE_ALIAS_SELECT:
1873 case ACPI_IVRS_TYPE_ALIAS_START:
1874
1875 InfoTable = AcpiDmTableInfoIvrs8a;
1876 break;
1877
1878 /* 8-byte entries, type B */
1879
1880 case ACPI_IVRS_TYPE_PAD8:
1881 case ACPI_IVRS_TYPE_EXT_SELECT:
1882 case ACPI_IVRS_TYPE_EXT_START:
1883
1884 InfoTable = AcpiDmTableInfoIvrs8b;
1885 break;
1886
1887 /* 8-byte entries, type C */
1888
1889 case ACPI_IVRS_TYPE_SPECIAL:
1890
1891 InfoTable = AcpiDmTableInfoIvrs8c;
1892 break;
1893
1894 default:
1895
1896 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
1897 "IVRS Device Entry");
1898 return (AE_ERROR);
1899 }
1900
1901 Status = DtCompileTable (PFieldList, InfoTable,
1902 &Subtable, TRUE);
1903 if (ACPI_FAILURE (Status))
1904 {
1905 return (Status);
1906 }
1907
1908 DtInsertSubtable (ParentTable, Subtable);
1909 }
1910 }
1911
1912 DtPopSubtable ();
1913 }
1914
1915 return (AE_OK);
1916 }
1917