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