xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/dttable2.c (revision 8ecbf5f02b752fcb7debe1a8fab1dc82602bc760)
1 /******************************************************************************
2  *
3  * Module Name: dttable2.c - handling for specific ACPI tables
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2020, 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 L-Z */
45 
46 #include "aslcompiler.h"
47 
48 #define _COMPONENT          DT_COMPILER
49         ACPI_MODULE_NAME    ("dttable2")
50 
51 
52 /******************************************************************************
53  *
54  * FUNCTION:    DtCompileLpit
55  *
56  * PARAMETERS:  List                - Current field list pointer
57  *
58  * RETURN:      Status
59  *
60  * DESCRIPTION: Compile LPIT.
61  *
62  *****************************************************************************/
63 
64 ACPI_STATUS
65 DtCompileLpit (
66     void                    **List)
67 {
68     ACPI_STATUS             Status;
69     DT_SUBTABLE             *Subtable;
70     DT_SUBTABLE             *ParentTable;
71     DT_FIELD                **PFieldList = (DT_FIELD **) List;
72     DT_FIELD                *SubtableStart;
73     ACPI_DMTABLE_INFO       *InfoTable;
74     ACPI_LPIT_HEADER        *LpitHeader;
75 
76 
77     /* Note: Main table consists only of the standard ACPI table header */
78 
79     while (*PFieldList)
80     {
81         SubtableStart = *PFieldList;
82 
83         /* LPIT Subtable header */
84 
85         Status = DtCompileTable (PFieldList, AcpiDmTableInfoLpitHdr,
86             &Subtable);
87         if (ACPI_FAILURE (Status))
88         {
89             return (Status);
90         }
91 
92         ParentTable = DtPeekSubtable ();
93         DtInsertSubtable (ParentTable, Subtable);
94         DtPushSubtable (Subtable);
95 
96         LpitHeader = ACPI_CAST_PTR (ACPI_LPIT_HEADER, Subtable->Buffer);
97 
98         switch (LpitHeader->Type)
99         {
100         case ACPI_LPIT_TYPE_NATIVE_CSTATE:
101 
102             InfoTable = AcpiDmTableInfoLpit0;
103             break;
104 
105         default:
106 
107             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "LPIT");
108             return (AE_ERROR);
109         }
110 
111         /* LPIT Subtable */
112 
113         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
114         if (ACPI_FAILURE (Status))
115         {
116             return (Status);
117         }
118 
119         ParentTable = DtPeekSubtable ();
120         DtInsertSubtable (ParentTable, Subtable);
121         DtPopSubtable ();
122     }
123 
124     return (AE_OK);
125 }
126 
127 
128 /******************************************************************************
129  *
130  * FUNCTION:    DtCompileMadt
131  *
132  * PARAMETERS:  List                - Current field list pointer
133  *
134  * RETURN:      Status
135  *
136  * DESCRIPTION: Compile MADT.
137  *
138  *****************************************************************************/
139 
140 ACPI_STATUS
141 DtCompileMadt (
142     void                    **List)
143 {
144     ACPI_STATUS             Status;
145     DT_SUBTABLE             *Subtable;
146     DT_SUBTABLE             *ParentTable;
147     DT_FIELD                **PFieldList = (DT_FIELD **) List;
148     DT_FIELD                *SubtableStart;
149     ACPI_SUBTABLE_HEADER    *MadtHeader;
150     ACPI_DMTABLE_INFO       *InfoTable;
151 
152 
153     Status = DtCompileTable (PFieldList, AcpiDmTableInfoMadt,
154         &Subtable);
155     if (ACPI_FAILURE (Status))
156     {
157         return (Status);
158     }
159 
160     ParentTable = DtPeekSubtable ();
161     DtInsertSubtable (ParentTable, Subtable);
162 
163     while (*PFieldList)
164     {
165         SubtableStart = *PFieldList;
166         Status = DtCompileTable (PFieldList, AcpiDmTableInfoMadtHdr,
167             &Subtable);
168         if (ACPI_FAILURE (Status))
169         {
170             return (Status);
171         }
172 
173         ParentTable = DtPeekSubtable ();
174         DtInsertSubtable (ParentTable, Subtable);
175         DtPushSubtable (Subtable);
176 
177         MadtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
178 
179         switch (MadtHeader->Type)
180         {
181         case ACPI_MADT_TYPE_LOCAL_APIC:
182 
183             InfoTable = AcpiDmTableInfoMadt0;
184             break;
185 
186         case ACPI_MADT_TYPE_IO_APIC:
187 
188             InfoTable = AcpiDmTableInfoMadt1;
189             break;
190 
191         case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
192 
193             InfoTable = AcpiDmTableInfoMadt2;
194             break;
195 
196         case ACPI_MADT_TYPE_NMI_SOURCE:
197 
198             InfoTable = AcpiDmTableInfoMadt3;
199             break;
200 
201         case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
202 
203             InfoTable = AcpiDmTableInfoMadt4;
204             break;
205 
206         case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
207 
208             InfoTable = AcpiDmTableInfoMadt5;
209             break;
210 
211         case ACPI_MADT_TYPE_IO_SAPIC:
212 
213             InfoTable = AcpiDmTableInfoMadt6;
214             break;
215 
216         case ACPI_MADT_TYPE_LOCAL_SAPIC:
217 
218             InfoTable = AcpiDmTableInfoMadt7;
219             break;
220 
221         case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
222 
223             InfoTable = AcpiDmTableInfoMadt8;
224             break;
225 
226         case ACPI_MADT_TYPE_LOCAL_X2APIC:
227 
228             InfoTable = AcpiDmTableInfoMadt9;
229             break;
230 
231         case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
232 
233             InfoTable = AcpiDmTableInfoMadt10;
234             break;
235 
236         case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
237 
238             InfoTable = AcpiDmTableInfoMadt11;
239             break;
240 
241         case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
242 
243             InfoTable = AcpiDmTableInfoMadt12;
244             break;
245 
246         case ACPI_MADT_TYPE_GENERIC_MSI_FRAME:
247 
248             InfoTable = AcpiDmTableInfoMadt13;
249             break;
250 
251         case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
252 
253             InfoTable = AcpiDmTableInfoMadt14;
254             break;
255 
256         case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
257 
258             InfoTable = AcpiDmTableInfoMadt15;
259             break;
260 
261         default:
262 
263             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "MADT");
264             return (AE_ERROR);
265         }
266 
267         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
268         if (ACPI_FAILURE (Status))
269         {
270             return (Status);
271         }
272 
273         ParentTable = DtPeekSubtable ();
274         DtInsertSubtable (ParentTable, Subtable);
275         DtPopSubtable ();
276     }
277 
278     return (AE_OK);
279 }
280 
281 
282 /******************************************************************************
283  *
284  * FUNCTION:    DtCompileMcfg
285  *
286  * PARAMETERS:  List                - Current field list pointer
287  *
288  * RETURN:      Status
289  *
290  * DESCRIPTION: Compile MCFG.
291  *
292  *****************************************************************************/
293 
294 ACPI_STATUS
295 DtCompileMcfg (
296     void                    **List)
297 {
298     ACPI_STATUS             Status;
299 
300 
301     Status = DtCompileTwoSubtables (List,
302         AcpiDmTableInfoMcfg, AcpiDmTableInfoMcfg0);
303     return (Status);
304 }
305 
306 
307 /******************************************************************************
308  *
309  * FUNCTION:    DtCompileMpst
310  *
311  * PARAMETERS:  List                - Current field list pointer
312  *
313  * RETURN:      Status
314  *
315  * DESCRIPTION: Compile MPST.
316  *
317  *****************************************************************************/
318 
319 ACPI_STATUS
320 DtCompileMpst (
321     void                    **List)
322 {
323     ACPI_STATUS             Status;
324     DT_SUBTABLE             *Subtable;
325     DT_SUBTABLE             *ParentTable;
326     DT_FIELD                **PFieldList = (DT_FIELD **) List;
327     ACPI_MPST_CHANNEL       *MpstChannelInfo;
328     ACPI_MPST_POWER_NODE    *MpstPowerNode;
329     ACPI_MPST_DATA_HDR      *MpstDataHeader;
330     UINT16                  SubtableCount;
331     UINT32                  PowerStateCount;
332     UINT32                  ComponentCount;
333 
334 
335     /* Main table */
336 
337     Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst, &Subtable);
338     if (ACPI_FAILURE (Status))
339     {
340         return (Status);
341     }
342 
343     ParentTable = DtPeekSubtable ();
344     DtInsertSubtable (ParentTable, Subtable);
345     DtPushSubtable (Subtable);
346 
347     MpstChannelInfo = ACPI_CAST_PTR (ACPI_MPST_CHANNEL, Subtable->Buffer);
348     SubtableCount = MpstChannelInfo->PowerNodeCount;
349 
350     while (*PFieldList && SubtableCount)
351     {
352         /* Subtable: Memory Power Node(s) */
353 
354         Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst0,
355             &Subtable);
356         if (ACPI_FAILURE (Status))
357         {
358             return (Status);
359         }
360 
361         ParentTable = DtPeekSubtable ();
362         DtInsertSubtable (ParentTable, Subtable);
363         DtPushSubtable (Subtable);
364 
365         MpstPowerNode = ACPI_CAST_PTR (ACPI_MPST_POWER_NODE, Subtable->Buffer);
366         PowerStateCount = MpstPowerNode->NumPowerStates;
367         ComponentCount = MpstPowerNode->NumPhysicalComponents;
368 
369         ParentTable = DtPeekSubtable ();
370 
371         /* Sub-subtables - Memory Power State Structure(s) */
372 
373         while (*PFieldList && PowerStateCount)
374         {
375             Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst0A,
376                 &Subtable);
377             if (ACPI_FAILURE (Status))
378             {
379                 return (Status);
380             }
381 
382             DtInsertSubtable (ParentTable, Subtable);
383             PowerStateCount--;
384         }
385 
386         /* Sub-subtables - Physical Component ID Structure(s) */
387 
388         while (*PFieldList && ComponentCount)
389         {
390             Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst0B,
391                 &Subtable);
392             if (ACPI_FAILURE (Status))
393             {
394                 return (Status);
395             }
396 
397             DtInsertSubtable (ParentTable, Subtable);
398             ComponentCount--;
399         }
400 
401         SubtableCount--;
402         DtPopSubtable ();
403     }
404 
405     /* Subtable: Count of Memory Power State Characteristic structures */
406 
407     DtPopSubtable ();
408 
409     Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst1, &Subtable);
410     if (ACPI_FAILURE (Status))
411     {
412         return (Status);
413     }
414 
415     ParentTable = DtPeekSubtable ();
416     DtInsertSubtable (ParentTable, Subtable);
417     DtPushSubtable (Subtable);
418 
419     MpstDataHeader = ACPI_CAST_PTR (ACPI_MPST_DATA_HDR, Subtable->Buffer);
420     SubtableCount = MpstDataHeader->CharacteristicsCount;
421 
422     ParentTable = DtPeekSubtable ();
423 
424     /* Subtable: Memory Power State Characteristics structure(s) */
425 
426     while (*PFieldList && SubtableCount)
427     {
428         Status = DtCompileTable (PFieldList, AcpiDmTableInfoMpst2,
429             &Subtable);
430         if (ACPI_FAILURE (Status))
431         {
432             return (Status);
433         }
434 
435         DtInsertSubtable (ParentTable, Subtable);
436         SubtableCount--;
437     }
438 
439     DtPopSubtable ();
440     return (AE_OK);
441 }
442 
443 
444 /******************************************************************************
445  *
446  * FUNCTION:    DtCompileMsct
447  *
448  * PARAMETERS:  List                - Current field list pointer
449  *
450  * RETURN:      Status
451  *
452  * DESCRIPTION: Compile MSCT.
453  *
454  *****************************************************************************/
455 
456 ACPI_STATUS
457 DtCompileMsct (
458     void                    **List)
459 {
460     ACPI_STATUS             Status;
461 
462 
463     Status = DtCompileTwoSubtables (List,
464         AcpiDmTableInfoMsct, AcpiDmTableInfoMsct0);
465     return (Status);
466 }
467 
468 
469 /******************************************************************************
470  *
471  * FUNCTION:    DtCompileMtmr
472  *
473  * PARAMETERS:  List                - Current field list pointer
474  *
475  * RETURN:      Status
476  *
477  * DESCRIPTION: Compile MTMR.
478  *
479  *****************************************************************************/
480 
481 ACPI_STATUS
482 DtCompileMtmr (
483     void                    **List)
484 {
485     ACPI_STATUS             Status;
486 
487 
488     Status = DtCompileTwoSubtables (List,
489         AcpiDmTableInfoMtmr, AcpiDmTableInfoMtmr0);
490     return (Status);
491 }
492 
493 
494 /******************************************************************************
495  *
496  * FUNCTION:    DtCompileNfit
497  *
498  * PARAMETERS:  List                - Current field list pointer
499  *
500  * RETURN:      Status
501  *
502  * DESCRIPTION: Compile NFIT.
503  *
504  *****************************************************************************/
505 
506 ACPI_STATUS
507 DtCompileNfit (
508     void                    **List)
509 {
510     ACPI_STATUS             Status;
511     DT_SUBTABLE             *Subtable;
512     DT_SUBTABLE             *ParentTable;
513     DT_FIELD                **PFieldList = (DT_FIELD **) List;
514     DT_FIELD                *SubtableStart;
515     ACPI_NFIT_HEADER        *NfitHeader;
516     ACPI_DMTABLE_INFO       *InfoTable;
517     UINT32                  Count;
518     ACPI_NFIT_INTERLEAVE    *Interleave = NULL;
519     ACPI_NFIT_FLUSH_ADDRESS *Hint = NULL;
520 
521 
522     /* Main table */
523 
524     Status = DtCompileTable (PFieldList, AcpiDmTableInfoNfit,
525         &Subtable);
526     if (ACPI_FAILURE (Status))
527     {
528         return (Status);
529     }
530 
531     ParentTable = DtPeekSubtable ();
532     DtInsertSubtable (ParentTable, Subtable);
533     DtPushSubtable (Subtable);
534 
535     /* Subtables */
536 
537     while (*PFieldList)
538     {
539         SubtableStart = *PFieldList;
540         Status = DtCompileTable (PFieldList, AcpiDmTableInfoNfitHdr,
541             &Subtable);
542         if (ACPI_FAILURE (Status))
543         {
544             return (Status);
545         }
546 
547         ParentTable = DtPeekSubtable ();
548         DtInsertSubtable (ParentTable, Subtable);
549         DtPushSubtable (Subtable);
550 
551         NfitHeader = ACPI_CAST_PTR (ACPI_NFIT_HEADER, Subtable->Buffer);
552 
553         switch (NfitHeader->Type)
554         {
555         case ACPI_NFIT_TYPE_SYSTEM_ADDRESS:
556 
557             InfoTable = AcpiDmTableInfoNfit0;
558             break;
559 
560         case ACPI_NFIT_TYPE_MEMORY_MAP:
561 
562             InfoTable = AcpiDmTableInfoNfit1;
563             break;
564 
565         case ACPI_NFIT_TYPE_INTERLEAVE:
566 
567             Interleave = ACPI_CAST_PTR (ACPI_NFIT_INTERLEAVE, Subtable->Buffer);
568             InfoTable = AcpiDmTableInfoNfit2;
569             break;
570 
571         case ACPI_NFIT_TYPE_SMBIOS:
572 
573             InfoTable = AcpiDmTableInfoNfit3;
574             break;
575 
576         case ACPI_NFIT_TYPE_CONTROL_REGION:
577 
578             InfoTable = AcpiDmTableInfoNfit4;
579             break;
580 
581         case ACPI_NFIT_TYPE_DATA_REGION:
582 
583             InfoTable = AcpiDmTableInfoNfit5;
584             break;
585 
586         case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
587 
588             Hint = ACPI_CAST_PTR (ACPI_NFIT_FLUSH_ADDRESS, Subtable->Buffer);
589             InfoTable = AcpiDmTableInfoNfit6;
590             break;
591 
592         case ACPI_NFIT_TYPE_CAPABILITIES:
593 
594             InfoTable = AcpiDmTableInfoNfit7;
595             break;
596 
597         default:
598 
599             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "NFIT");
600             return (AE_ERROR);
601         }
602 
603         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
604         if (ACPI_FAILURE (Status))
605         {
606             return (Status);
607         }
608 
609         ParentTable = DtPeekSubtable ();
610         DtInsertSubtable (ParentTable, Subtable);
611         DtPopSubtable ();
612 
613         switch (NfitHeader->Type)
614         {
615         case ACPI_NFIT_TYPE_INTERLEAVE:
616 
617             Count = 0;
618             DtPushSubtable (Subtable);
619             while (*PFieldList)
620             {
621                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoNfit2a,
622                     &Subtable);
623                 if (ACPI_FAILURE (Status))
624                 {
625                     return (Status);
626                 }
627 
628                 if (!Subtable)
629                 {
630                     DtPopSubtable ();
631                     break;
632                 }
633 
634                 ParentTable = DtPeekSubtable ();
635                 DtInsertSubtable (ParentTable, Subtable);
636                 Count++;
637             }
638 
639             Interleave->LineCount = Count;
640             break;
641 
642         case ACPI_NFIT_TYPE_SMBIOS:
643 
644             if (*PFieldList)
645             {
646                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoNfit3a,
647                     &Subtable);
648                 if (ACPI_FAILURE (Status))
649                 {
650                     return (Status);
651                 }
652 
653                 if (Subtable)
654                 {
655                     DtInsertSubtable (ParentTable, Subtable);
656                 }
657             }
658             break;
659 
660         case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
661 
662             Count = 0;
663             DtPushSubtable (Subtable);
664             while (*PFieldList)
665             {
666                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoNfit6a,
667                     &Subtable);
668                 if (ACPI_FAILURE (Status))
669                 {
670                     return (Status);
671                 }
672 
673                 if (!Subtable)
674                 {
675                     DtPopSubtable ();
676                     break;
677                 }
678 
679                 ParentTable = DtPeekSubtable ();
680                 DtInsertSubtable (ParentTable, Subtable);
681                 Count++;
682             }
683 
684             Hint->HintCount = (UINT16) Count;
685             break;
686 
687         default:
688             break;
689         }
690     }
691 
692     return (AE_OK);
693 }
694 
695 
696 /******************************************************************************
697  *
698  * FUNCTION:    DtCompilePcct
699  *
700  * PARAMETERS:  List                - Current field list pointer
701  *
702  * RETURN:      Status
703  *
704  * DESCRIPTION: Compile PCCT.
705  *
706  *****************************************************************************/
707 
708 ACPI_STATUS
709 DtCompilePcct (
710     void                    **List)
711 {
712     ACPI_STATUS             Status;
713     DT_SUBTABLE             *Subtable;
714     DT_SUBTABLE             *ParentTable;
715     DT_FIELD                **PFieldList = (DT_FIELD **) List;
716     DT_FIELD                *SubtableStart;
717     ACPI_SUBTABLE_HEADER    *PcctHeader;
718     ACPI_DMTABLE_INFO       *InfoTable;
719 
720 
721     /* Main table */
722 
723     Status = DtCompileTable (PFieldList, AcpiDmTableInfoPcct,
724         &Subtable);
725     if (ACPI_FAILURE (Status))
726     {
727         return (Status);
728     }
729 
730     ParentTable = DtPeekSubtable ();
731     DtInsertSubtable (ParentTable, Subtable);
732 
733     /* Subtables */
734 
735     while (*PFieldList)
736     {
737         SubtableStart = *PFieldList;
738         Status = DtCompileTable (PFieldList, AcpiDmTableInfoPcctHdr,
739             &Subtable);
740         if (ACPI_FAILURE (Status))
741         {
742             return (Status);
743         }
744 
745         ParentTable = DtPeekSubtable ();
746         DtInsertSubtable (ParentTable, Subtable);
747         DtPushSubtable (Subtable);
748 
749         PcctHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
750 
751         switch (PcctHeader->Type)
752         {
753         case ACPI_PCCT_TYPE_GENERIC_SUBSPACE:
754 
755             InfoTable = AcpiDmTableInfoPcct0;
756             break;
757 
758         case ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE:
759 
760             InfoTable = AcpiDmTableInfoPcct1;
761             break;
762 
763         case ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2:
764 
765             InfoTable = AcpiDmTableInfoPcct2;
766             break;
767 
768         case ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE:
769 
770             InfoTable = AcpiDmTableInfoPcct3;
771             break;
772 
773         case ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE:
774 
775             InfoTable = AcpiDmTableInfoPcct4;
776             break;
777 
778         default:
779 
780             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "PCCT");
781             return (AE_ERROR);
782         }
783 
784         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
785         if (ACPI_FAILURE (Status))
786         {
787             return (Status);
788         }
789 
790         ParentTable = DtPeekSubtable ();
791         DtInsertSubtable (ParentTable, Subtable);
792         DtPopSubtable ();
793     }
794 
795     return (AE_OK);
796 }
797 
798 
799 /******************************************************************************
800  *
801  * FUNCTION:    DtCompilePdtt
802  *
803  * PARAMETERS:  List                - Current field list pointer
804  *
805  * RETURN:      Status
806  *
807  * DESCRIPTION: Compile PDTT.
808  *
809  *****************************************************************************/
810 
811 ACPI_STATUS
812 DtCompilePdtt (
813     void                    **List)
814 {
815     ACPI_STATUS             Status;
816     DT_SUBTABLE             *Subtable;
817     DT_SUBTABLE             *ParentTable;
818     DT_FIELD                **PFieldList = (DT_FIELD **) List;
819     ACPI_TABLE_PDTT         *PdttHeader;
820     UINT32                  Count = 0;
821 
822 
823     /* Main table */
824 
825     Status = DtCompileTable (PFieldList, AcpiDmTableInfoPdtt, &Subtable);
826     if (ACPI_FAILURE (Status))
827     {
828         return (Status);
829     }
830 
831     ParentTable = DtPeekSubtable ();
832     DtInsertSubtable (ParentTable, Subtable);
833 
834     PdttHeader = ACPI_CAST_PTR (ACPI_TABLE_PDTT, ParentTable->Buffer);
835     PdttHeader->ArrayOffset = sizeof (ACPI_TABLE_PDTT);
836 
837     /* There is only one type of subtable at this time, no need to decode */
838 
839     while (*PFieldList)
840     {
841         /* List of subchannel IDs, each 2 bytes */
842 
843         Status = DtCompileTable (PFieldList, AcpiDmTableInfoPdtt0,
844             &Subtable);
845         if (ACPI_FAILURE (Status))
846         {
847             return (Status);
848         }
849 
850         DtInsertSubtable (ParentTable, Subtable);
851         Count++;
852     }
853 
854     PdttHeader->TriggerCount = (UINT8) Count;
855     return (AE_OK);
856 }
857 
858 
859 /******************************************************************************
860  *
861  * FUNCTION:    DtCompilePmtt
862  *
863  * PARAMETERS:  List                - Current field list pointer
864  *
865  * RETURN:      Status
866  *
867  * DESCRIPTION: Compile PMTT.
868  *
869  *****************************************************************************/
870 
871 ACPI_STATUS
872 DtCompilePmtt (
873     void                    **List)
874 {
875     ACPI_STATUS             Status;
876     DT_SUBTABLE             *Subtable;
877     DT_SUBTABLE             *ParentTable;
878     DT_FIELD                **PFieldList = (DT_FIELD **) List;
879     DT_FIELD                *SubtableStart;
880     ACPI_PMTT_HEADER        *PmttHeader;
881     ACPI_PMTT_CONTROLLER    *PmttController;
882     UINT16                  DomainCount;
883     UINT8                   PrevType = ACPI_PMTT_TYPE_SOCKET;
884 
885 
886     /* Main table */
887 
888     Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmtt, &Subtable);
889     if (ACPI_FAILURE (Status))
890     {
891         return (Status);
892     }
893 
894     ParentTable = DtPeekSubtable ();
895     DtInsertSubtable (ParentTable, Subtable);
896     DtPushSubtable (Subtable);
897 
898     while (*PFieldList)
899     {
900         SubtableStart = *PFieldList;
901         Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmttHdr,
902             &Subtable);
903         if (ACPI_FAILURE (Status))
904         {
905             return (Status);
906         }
907 
908         PmttHeader = ACPI_CAST_PTR (ACPI_PMTT_HEADER, Subtable->Buffer);
909         while (PrevType >= PmttHeader->Type)
910         {
911             DtPopSubtable ();
912 
913             if (PrevType == ACPI_PMTT_TYPE_SOCKET)
914             {
915                 break;
916             }
917 
918             PrevType--;
919         }
920 
921         PrevType = PmttHeader->Type;
922 
923         ParentTable = DtPeekSubtable ();
924         DtInsertSubtable (ParentTable, Subtable);
925         DtPushSubtable (Subtable);
926 
927         switch (PmttHeader->Type)
928         {
929         case ACPI_PMTT_TYPE_SOCKET:
930 
931             /* Subtable: Socket Structure */
932 
933             Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmtt0,
934                 &Subtable);
935             if (ACPI_FAILURE (Status))
936             {
937                 return (Status);
938             }
939 
940             ParentTable = DtPeekSubtable ();
941             DtInsertSubtable (ParentTable, Subtable);
942             break;
943 
944         case ACPI_PMTT_TYPE_CONTROLLER:
945 
946             /* Subtable: Memory Controller Structure */
947 
948             Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmtt1,
949                 &Subtable);
950             if (ACPI_FAILURE (Status))
951             {
952                 return (Status);
953             }
954 
955             ParentTable = DtPeekSubtable ();
956             DtInsertSubtable (ParentTable, Subtable);
957 
958             PmttController = ACPI_CAST_PTR (ACPI_PMTT_CONTROLLER,
959                 (Subtable->Buffer - sizeof (ACPI_PMTT_HEADER)));
960             DomainCount = PmttController->DomainCount;
961 
962             while (DomainCount)
963             {
964                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmtt1a,
965                     &Subtable);
966                 if (ACPI_FAILURE (Status))
967                 {
968                     return (Status);
969                 }
970 
971                 DtInsertSubtable (ParentTable, Subtable);
972                 DomainCount--;
973             }
974             break;
975 
976         case ACPI_PMTT_TYPE_DIMM:
977 
978             /* Subtable: Physical Component Structure */
979 
980             Status = DtCompileTable (PFieldList, AcpiDmTableInfoPmtt2,
981                 &Subtable);
982             if (ACPI_FAILURE (Status))
983             {
984                 return (Status);
985             }
986 
987             ParentTable = DtPeekSubtable ();
988             DtInsertSubtable (ParentTable, Subtable);
989             break;
990 
991         default:
992 
993             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "PMTT");
994             return (AE_ERROR);
995         }
996     }
997 
998     return (Status);
999 }
1000 
1001 
1002 /******************************************************************************
1003  *
1004  * FUNCTION:    DtCompilePptt
1005  *
1006  * PARAMETERS:  List                - Current field list pointer
1007  *
1008  * RETURN:      Status
1009  *
1010  * DESCRIPTION: Compile PPTT.
1011  *
1012  *****************************************************************************/
1013 
1014 ACPI_STATUS
1015 DtCompilePptt (
1016     void                    **List)
1017 {
1018     ACPI_STATUS             Status;
1019     ACPI_SUBTABLE_HEADER    *PpttHeader;
1020     ACPI_PPTT_PROCESSOR     *PpttProcessor = NULL;
1021     DT_SUBTABLE             *Subtable;
1022     DT_SUBTABLE             *ParentTable;
1023     ACPI_DMTABLE_INFO       *InfoTable;
1024     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1025     DT_FIELD                *SubtableStart;
1026 
1027 
1028     ParentTable = DtPeekSubtable ();
1029     while (*PFieldList)
1030     {
1031         SubtableStart = *PFieldList;
1032 
1033         /* Compile PPTT subtable header */
1034 
1035         Status = DtCompileTable (PFieldList, AcpiDmTableInfoPpttHdr,
1036             &Subtable);
1037         if (ACPI_FAILURE (Status))
1038         {
1039             return (Status);
1040         }
1041         DtInsertSubtable (ParentTable, Subtable);
1042         PpttHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
1043         PpttHeader->Length = (UINT8)(Subtable->Length);
1044 
1045         switch (PpttHeader->Type)
1046         {
1047         case ACPI_PPTT_TYPE_PROCESSOR:
1048 
1049             InfoTable = AcpiDmTableInfoPptt0;
1050             break;
1051 
1052         case ACPI_PPTT_TYPE_CACHE:
1053 
1054             InfoTable = AcpiDmTableInfoPptt1;
1055             break;
1056 
1057         case ACPI_PPTT_TYPE_ID:
1058 
1059             InfoTable = AcpiDmTableInfoPptt2;
1060             break;
1061 
1062         default:
1063 
1064             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "PPTT");
1065             return (AE_ERROR);
1066         }
1067 
1068         /* Compile PPTT subtable body */
1069 
1070         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1071         if (ACPI_FAILURE (Status))
1072         {
1073             return (Status);
1074         }
1075         DtInsertSubtable (ParentTable, Subtable);
1076         PpttHeader->Length += (UINT8)(Subtable->Length);
1077 
1078         /* Compile PPTT subtable additionals */
1079 
1080         switch (PpttHeader->Type)
1081         {
1082         case ACPI_PPTT_TYPE_PROCESSOR:
1083 
1084             PpttProcessor = ACPI_SUB_PTR (ACPI_PPTT_PROCESSOR,
1085                 Subtable->Buffer, sizeof (ACPI_SUBTABLE_HEADER));
1086             if (PpttProcessor)
1087             {
1088                 /* Compile initiator proximity domain list */
1089 
1090                 PpttProcessor->NumberOfPrivResources = 0;
1091                 while (*PFieldList)
1092                 {
1093                     Status = DtCompileTable (PFieldList,
1094                         AcpiDmTableInfoPptt0a, &Subtable);
1095                     if (ACPI_FAILURE (Status))
1096                     {
1097                         return (Status);
1098                     }
1099                     if (!Subtable)
1100                     {
1101                         break;
1102                     }
1103 
1104                     DtInsertSubtable (ParentTable, Subtable);
1105                     PpttHeader->Length += (UINT8)(Subtable->Length);
1106                     PpttProcessor->NumberOfPrivResources++;
1107                 }
1108             }
1109             break;
1110 
1111         default:
1112 
1113             break;
1114         }
1115     }
1116 
1117     return (AE_OK);
1118 }
1119 
1120 
1121 /******************************************************************************
1122  *
1123  * FUNCTION:    DtCompileRsdt
1124  *
1125  * PARAMETERS:  List                - Current field list pointer
1126  *
1127  * RETURN:      Status
1128  *
1129  * DESCRIPTION: Compile RSDT.
1130  *
1131  *****************************************************************************/
1132 
1133 ACPI_STATUS
1134 DtCompileRsdt (
1135     void                    **List)
1136 {
1137     DT_SUBTABLE             *Subtable;
1138     DT_SUBTABLE             *ParentTable;
1139     DT_FIELD                *FieldList = *(DT_FIELD **) List;
1140     UINT32                  Address;
1141 
1142 
1143     ParentTable = DtPeekSubtable ();
1144 
1145     while (FieldList)
1146     {
1147         DtCompileInteger ((UINT8 *) &Address, FieldList, 4, DT_NON_ZERO);
1148 
1149         DtCreateSubtable ((UINT8 *) &Address, 4, &Subtable);
1150         DtInsertSubtable (ParentTable, Subtable);
1151         FieldList = FieldList->Next;
1152     }
1153 
1154     return (AE_OK);
1155 }
1156 
1157 
1158 /******************************************************************************
1159  *
1160  * FUNCTION:    DtCompileS3pt
1161  *
1162  * PARAMETERS:  PFieldList          - Current field list pointer
1163  *
1164  * RETURN:      Status
1165  *
1166  * DESCRIPTION: Compile S3PT (Pointed to by FPDT)
1167  *
1168  *****************************************************************************/
1169 
1170 ACPI_STATUS
1171 DtCompileS3pt (
1172     DT_FIELD                **PFieldList)
1173 {
1174     ACPI_STATUS             Status;
1175     ACPI_FPDT_HEADER        *S3ptHeader;
1176     DT_SUBTABLE             *Subtable;
1177     DT_SUBTABLE             *ParentTable;
1178     ACPI_DMTABLE_INFO       *InfoTable;
1179     DT_FIELD                *SubtableStart;
1180 
1181 
1182     Status = DtCompileTable (PFieldList, AcpiDmTableInfoS3pt,
1183         &AslGbl_RootTable);
1184     if (ACPI_FAILURE (Status))
1185     {
1186         return (Status);
1187     }
1188 
1189     DtPushSubtable (AslGbl_RootTable);
1190 
1191     while (*PFieldList)
1192     {
1193         SubtableStart = *PFieldList;
1194         Status = DtCompileTable (PFieldList, AcpiDmTableInfoS3ptHdr,
1195             &Subtable);
1196         if (ACPI_FAILURE (Status))
1197         {
1198             return (Status);
1199         }
1200 
1201         ParentTable = DtPeekSubtable ();
1202         DtInsertSubtable (ParentTable, Subtable);
1203         DtPushSubtable (Subtable);
1204 
1205         S3ptHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
1206 
1207         switch (S3ptHeader->Type)
1208         {
1209         case ACPI_S3PT_TYPE_RESUME:
1210 
1211             InfoTable = AcpiDmTableInfoS3pt0;
1212             break;
1213 
1214         case ACPI_S3PT_TYPE_SUSPEND:
1215 
1216             InfoTable = AcpiDmTableInfoS3pt1;
1217             break;
1218 
1219         default:
1220 
1221             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "S3PT");
1222             return (AE_ERROR);
1223         }
1224 
1225         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1226         if (ACPI_FAILURE (Status))
1227         {
1228             return (Status);
1229         }
1230 
1231         ParentTable = DtPeekSubtable ();
1232         DtInsertSubtable (ParentTable, Subtable);
1233         DtPopSubtable ();
1234     }
1235 
1236     return (AE_OK);
1237 }
1238 
1239 
1240 /******************************************************************************
1241  *
1242  * FUNCTION:    DtCompileSdev
1243  *
1244  * PARAMETERS:  List                - Current field list pointer
1245  *
1246  * RETURN:      Status
1247  *
1248  * DESCRIPTION: Compile SDEV.
1249  *
1250  *****************************************************************************/
1251 
1252 ACPI_STATUS
1253 DtCompileSdev (
1254     void                    **List)
1255 {
1256     ACPI_STATUS             Status;
1257     ACPI_SDEV_HEADER        *SdevHeader;
1258     DT_SUBTABLE             *Subtable;
1259     DT_SUBTABLE             *ParentTable;
1260     ACPI_DMTABLE_INFO       *InfoTable;
1261     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1262     DT_FIELD                *SubtableStart;
1263     ACPI_SDEV_PCIE          *Pcie = NULL;
1264     ACPI_SDEV_NAMESPACE     *Namesp = NULL;
1265     UINT32                  EntryCount;
1266 
1267 
1268     /* Subtables */
1269 
1270     while (*PFieldList)
1271     {
1272         /* Compile common SDEV subtable header */
1273 
1274         SubtableStart = *PFieldList;
1275         Status = DtCompileTable (PFieldList, AcpiDmTableInfoSdevHdr,
1276             &Subtable);
1277         if (ACPI_FAILURE (Status))
1278         {
1279             return (Status);
1280         }
1281 
1282         ParentTable = DtPeekSubtable ();
1283         DtInsertSubtable (ParentTable, Subtable);
1284         DtPushSubtable (Subtable);
1285 
1286         SdevHeader = ACPI_CAST_PTR (ACPI_SDEV_HEADER, Subtable->Buffer);
1287         SdevHeader->Length = (UINT8)(sizeof (ACPI_SDEV_HEADER));
1288 
1289         switch (SdevHeader->Type)
1290         {
1291         case ACPI_SDEV_TYPE_NAMESPACE_DEVICE:
1292 
1293             InfoTable = AcpiDmTableInfoSdev0;
1294             Namesp = ACPI_CAST_PTR (ACPI_SDEV_NAMESPACE, Subtable->Buffer);
1295             break;
1296 
1297         case ACPI_SDEV_TYPE_PCIE_ENDPOINT_DEVICE:
1298 
1299             InfoTable = AcpiDmTableInfoSdev1;
1300             Pcie = ACPI_CAST_PTR (ACPI_SDEV_PCIE, Subtable->Buffer);
1301             break;
1302 
1303         default:
1304 
1305             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "SDEV");
1306             return (AE_ERROR);
1307         }
1308 
1309         /* Compile SDEV subtable body */
1310 
1311         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1312         if (ACPI_FAILURE (Status))
1313         {
1314             return (Status);
1315         }
1316 
1317         ParentTable = DtPeekSubtable ();
1318         DtInsertSubtable (ParentTable, Subtable);
1319 
1320         /* Optional data fields are appended to the main subtable body */
1321 
1322         switch (SdevHeader->Type)
1323         {
1324         case ACPI_SDEV_TYPE_NAMESPACE_DEVICE:
1325 
1326             /* Append DeviceId namespace string */
1327 
1328             Status = DtCompileTable (PFieldList, AcpiDmTableInfoSdev0a,
1329                 &Subtable);
1330             if (ACPI_FAILURE (Status))
1331             {
1332                 return (Status);
1333             }
1334 
1335             if (!Subtable)
1336             {
1337                 break;
1338             }
1339 
1340             ParentTable = DtPeekSubtable ();
1341             DtInsertSubtable (ParentTable, Subtable);
1342 
1343             Namesp->DeviceIdOffset = sizeof (ACPI_SDEV_NAMESPACE);
1344             Namesp->DeviceIdLength = (UINT16) Subtable->Length;
1345 
1346             /* Append Vendor data */
1347 
1348             Namesp->VendorDataLength = 0;
1349             Namesp->VendorDataOffset = 0;
1350 
1351             if (*PFieldList)
1352             {
1353                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoSdev1b,
1354                     &Subtable);
1355                 if (ACPI_FAILURE (Status))
1356                 {
1357                     return (Status);
1358                 }
1359 
1360                 if (Subtable)
1361                 {
1362                     ParentTable = DtPeekSubtable ();
1363                     DtInsertSubtable (ParentTable, Subtable);
1364 
1365                     Namesp->VendorDataOffset =
1366                         Namesp->DeviceIdOffset + Namesp->DeviceIdLength;
1367                     Namesp->VendorDataLength =
1368                         (UINT16) Subtable->Length;
1369 
1370                     /* Final size of entire namespace structure */
1371 
1372                     SdevHeader->Length = (UINT16)(sizeof(ACPI_SDEV_NAMESPACE) +
1373                         Subtable->Length + Namesp->DeviceIdLength);
1374                 }
1375             }
1376 
1377             break;
1378 
1379         case ACPI_SDEV_TYPE_PCIE_ENDPOINT_DEVICE:
1380 
1381             /* Append the PCIe path info first */
1382 
1383             EntryCount = 0;
1384             while (*PFieldList && !strcmp ((*PFieldList)->Name, "Device"))
1385             {
1386                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoSdev1a,
1387                     &Subtable);
1388                 if (ACPI_FAILURE (Status))
1389                 {
1390                     return (Status);
1391                 }
1392 
1393                 if (!Subtable)
1394                 {
1395                     DtPopSubtable ();
1396                     break;
1397                 }
1398 
1399                 ParentTable = DtPeekSubtable ();
1400                 DtInsertSubtable (ParentTable, Subtable);
1401                 EntryCount++;
1402             }
1403 
1404             /* Path offset will point immediately after the main subtable */
1405 
1406             Pcie->PathOffset = sizeof (ACPI_SDEV_PCIE);
1407             Pcie->PathLength = (UINT16)
1408                 (EntryCount * sizeof (ACPI_SDEV_PCIE_PATH));
1409 
1410             /* Append the Vendor Data last */
1411 
1412             Pcie->VendorDataLength = 0;
1413             Pcie->VendorDataOffset = 0;
1414 
1415             if (*PFieldList)
1416             {
1417                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoSdev1b,
1418                     &Subtable);
1419                 if (ACPI_FAILURE (Status))
1420                 {
1421                     return (Status);
1422                 }
1423 
1424                 if (Subtable)
1425                 {
1426                     ParentTable = DtPeekSubtable ();
1427                     DtInsertSubtable (ParentTable, Subtable);
1428 
1429                     Pcie->VendorDataOffset =
1430                         Pcie->PathOffset + Pcie->PathLength;
1431                     Pcie->VendorDataLength = (UINT16)
1432                         Subtable->Length;
1433                 }
1434             }
1435 
1436             SdevHeader->Length =
1437                 sizeof (ACPI_SDEV_PCIE) +
1438                 Pcie->PathLength + Pcie->VendorDataLength;
1439             break;
1440 
1441         default:
1442 
1443             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "SDEV");
1444             return (AE_ERROR);
1445         }
1446 
1447         DtPopSubtable ();
1448     }
1449 
1450     return (AE_OK);
1451 }
1452 
1453 
1454 /******************************************************************************
1455  *
1456  * FUNCTION:    DtCompileSlic
1457  *
1458  * PARAMETERS:  List                - Current field list pointer
1459  *
1460  * RETURN:      Status
1461  *
1462  * DESCRIPTION: Compile SLIC.
1463  *
1464  *****************************************************************************/
1465 
1466 ACPI_STATUS
1467 DtCompileSlic (
1468     void                    **List)
1469 {
1470     ACPI_STATUS             Status;
1471     DT_SUBTABLE             *Subtable;
1472     DT_SUBTABLE             *ParentTable;
1473     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1474 
1475 
1476     while (*PFieldList)
1477     {
1478         Status = DtCompileTable (PFieldList, AcpiDmTableInfoSlic,
1479             &Subtable);
1480         if (ACPI_FAILURE (Status))
1481         {
1482             return (Status);
1483         }
1484 
1485         ParentTable = DtPeekSubtable ();
1486         DtInsertSubtable (ParentTable, Subtable);
1487         DtPushSubtable (Subtable);
1488         DtPopSubtable ();
1489     }
1490 
1491     return (AE_OK);
1492 }
1493 
1494 
1495 /******************************************************************************
1496  *
1497  * FUNCTION:    DtCompileSlit
1498  *
1499  * PARAMETERS:  List                - Current field list pointer
1500  *
1501  * RETURN:      Status
1502  *
1503  * DESCRIPTION: Compile SLIT.
1504  *
1505  *****************************************************************************/
1506 
1507 ACPI_STATUS
1508 DtCompileSlit (
1509     void                    **List)
1510 {
1511     ACPI_STATUS             Status;
1512     DT_SUBTABLE             *Subtable;
1513     DT_SUBTABLE             *ParentTable;
1514     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1515     DT_FIELD                *FieldList;
1516     DT_FIELD                *EndOfFieldList = NULL;
1517     UINT32                  Localities;
1518     UINT32                  LocalityListLength;
1519     UINT8                   *LocalityBuffer;
1520 
1521 
1522     Status = DtCompileTable (PFieldList, AcpiDmTableInfoSlit,
1523         &Subtable);
1524     if (ACPI_FAILURE (Status))
1525     {
1526         return (Status);
1527     }
1528 
1529     ParentTable = DtPeekSubtable ();
1530     DtInsertSubtable (ParentTable, Subtable);
1531 
1532     Localities = *ACPI_CAST_PTR (UINT32, Subtable->Buffer);
1533     LocalityBuffer = UtLocalCalloc (Localities);
1534     LocalityListLength = 0;
1535 
1536     /* Compile each locality buffer */
1537 
1538     FieldList = *PFieldList;
1539     while (FieldList)
1540     {
1541         DtCompileBuffer (LocalityBuffer,
1542             FieldList->Value, FieldList, Localities);
1543 
1544         LocalityListLength++;
1545         DtCreateSubtable (LocalityBuffer, Localities, &Subtable);
1546         DtInsertSubtable (ParentTable, Subtable);
1547         EndOfFieldList = FieldList;
1548         FieldList = FieldList->Next;
1549     }
1550 
1551     if (LocalityListLength != Localities)
1552     {
1553         sprintf(AslGbl_MsgBuffer,
1554             "Found %u entries, must match LocalityCount: %u",
1555             LocalityListLength, Localities);
1556         DtError (ASL_ERROR, ASL_MSG_ENTRY_LIST, EndOfFieldList, AslGbl_MsgBuffer);
1557         ACPI_FREE (LocalityBuffer);
1558         return (AE_LIMIT);
1559     }
1560 
1561     ACPI_FREE (LocalityBuffer);
1562     return (AE_OK);
1563 }
1564 
1565 
1566 /******************************************************************************
1567  *
1568  * FUNCTION:    DtCompileSrat
1569  *
1570  * PARAMETERS:  List                - Current field list pointer
1571  *
1572  * RETURN:      Status
1573  *
1574  * DESCRIPTION: Compile SRAT.
1575  *
1576  *****************************************************************************/
1577 
1578 ACPI_STATUS
1579 DtCompileSrat (
1580     void                    **List)
1581 {
1582     ACPI_STATUS             Status;
1583     DT_SUBTABLE             *Subtable;
1584     DT_SUBTABLE             *ParentTable;
1585     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1586     DT_FIELD                *SubtableStart;
1587     ACPI_SUBTABLE_HEADER    *SratHeader;
1588     ACPI_DMTABLE_INFO       *InfoTable;
1589 
1590 
1591     Status = DtCompileTable (PFieldList, AcpiDmTableInfoSrat,
1592         &Subtable);
1593     if (ACPI_FAILURE (Status))
1594     {
1595         return (Status);
1596     }
1597 
1598     ParentTable = DtPeekSubtable ();
1599     DtInsertSubtable (ParentTable, Subtable);
1600 
1601     while (*PFieldList)
1602     {
1603         SubtableStart = *PFieldList;
1604         Status = DtCompileTable (PFieldList, AcpiDmTableInfoSratHdr,
1605             &Subtable);
1606         if (ACPI_FAILURE (Status))
1607         {
1608             return (Status);
1609         }
1610 
1611         ParentTable = DtPeekSubtable ();
1612         DtInsertSubtable (ParentTable, Subtable);
1613         DtPushSubtable (Subtable);
1614 
1615         SratHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
1616 
1617         switch (SratHeader->Type)
1618         {
1619         case ACPI_SRAT_TYPE_CPU_AFFINITY:
1620 
1621             InfoTable = AcpiDmTableInfoSrat0;
1622             break;
1623 
1624         case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1625 
1626             InfoTable = AcpiDmTableInfoSrat1;
1627             break;
1628 
1629         case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1630 
1631             InfoTable = AcpiDmTableInfoSrat2;
1632             break;
1633 
1634         case ACPI_SRAT_TYPE_GICC_AFFINITY:
1635 
1636             InfoTable = AcpiDmTableInfoSrat3;
1637             break;
1638 
1639         case ACPI_SRAT_TYPE_GIC_ITS_AFFINITY:
1640 
1641             InfoTable = AcpiDmTableInfoSrat4;
1642             break;
1643 
1644         case ACPI_SRAT_TYPE_GENERIC_AFFINITY:
1645 
1646             InfoTable = AcpiDmTableInfoSrat5;
1647             break;
1648 
1649         default:
1650 
1651             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "SRAT");
1652             return (AE_ERROR);
1653         }
1654 
1655         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1656         if (ACPI_FAILURE (Status))
1657         {
1658             return (Status);
1659         }
1660 
1661         ParentTable = DtPeekSubtable ();
1662         DtInsertSubtable (ParentTable, Subtable);
1663         DtPopSubtable ();
1664     }
1665 
1666     return (AE_OK);
1667 }
1668 
1669 
1670 /******************************************************************************
1671  *
1672  * FUNCTION:    DtCompileStao
1673  *
1674  * PARAMETERS:  PFieldList          - Current field list pointer
1675  *
1676  * RETURN:      Status
1677  *
1678  * DESCRIPTION: Compile STAO.
1679  *
1680  *****************************************************************************/
1681 
1682 ACPI_STATUS
1683 DtCompileStao (
1684     void                    **List)
1685 {
1686     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1687     DT_SUBTABLE             *Subtable;
1688     DT_SUBTABLE             *ParentTable;
1689     ACPI_STATUS             Status;
1690 
1691 
1692     /* Compile the main table */
1693 
1694     Status = DtCompileTable (PFieldList, AcpiDmTableInfoStao,
1695         &Subtable);
1696     if (ACPI_FAILURE (Status))
1697     {
1698         return (Status);
1699     }
1700 
1701     ParentTable = DtPeekSubtable ();
1702     DtInsertSubtable (ParentTable, Subtable);
1703 
1704     /* Compile each ASCII namestring as a subtable */
1705 
1706     while (*PFieldList)
1707     {
1708         Status = DtCompileTable (PFieldList, AcpiDmTableInfoStaoStr,
1709             &Subtable);
1710         if (ACPI_FAILURE (Status))
1711         {
1712             return (Status);
1713         }
1714 
1715         ParentTable = DtPeekSubtable ();
1716         DtInsertSubtable (ParentTable, Subtable);
1717     }
1718 
1719     return (AE_OK);
1720 }
1721 
1722 
1723 /******************************************************************************
1724  *
1725  * FUNCTION:    DtCompileTcpa
1726  *
1727  * PARAMETERS:  PFieldList          - Current field list pointer
1728  *
1729  * RETURN:      Status
1730  *
1731  * DESCRIPTION: Compile TCPA.
1732  *
1733  *****************************************************************************/
1734 
1735 ACPI_STATUS
1736 DtCompileTcpa (
1737     void                    **List)
1738 {
1739     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1740     DT_SUBTABLE             *Subtable;
1741     ACPI_TABLE_TCPA_HDR     *TcpaHeader;
1742     DT_SUBTABLE             *ParentTable;
1743     ACPI_STATUS             Status;
1744 
1745 
1746     /* Compile the main table */
1747 
1748     Status = DtCompileTable (PFieldList, AcpiDmTableInfoTcpaHdr,
1749         &Subtable);
1750     if (ACPI_FAILURE (Status))
1751     {
1752         return (Status);
1753     }
1754 
1755     ParentTable = DtPeekSubtable ();
1756     DtInsertSubtable (ParentTable, Subtable);
1757 
1758     /*
1759      * Examine the PlatformClass field to determine the table type.
1760      * Either a client or server table. Only one.
1761      */
1762     TcpaHeader = ACPI_CAST_PTR (ACPI_TABLE_TCPA_HDR, ParentTable->Buffer);
1763 
1764     switch (TcpaHeader->PlatformClass)
1765     {
1766     case ACPI_TCPA_CLIENT_TABLE:
1767 
1768         Status = DtCompileTable (PFieldList, AcpiDmTableInfoTcpaClient,
1769             &Subtable);
1770         break;
1771 
1772     case ACPI_TCPA_SERVER_TABLE:
1773 
1774         Status = DtCompileTable (PFieldList, AcpiDmTableInfoTcpaServer,
1775             &Subtable);
1776         break;
1777 
1778     default:
1779 
1780         AcpiOsPrintf ("\n**** Unknown TCPA Platform Class 0x%X\n",
1781             TcpaHeader->PlatformClass);
1782         Status = AE_ERROR;
1783         break;
1784     }
1785 
1786     ParentTable = DtPeekSubtable ();
1787     DtInsertSubtable (ParentTable, Subtable);
1788     return (Status);
1789 }
1790 
1791 
1792 /******************************************************************************
1793  *
1794  * FUNCTION:    DtCompileTpm2Rev3
1795  *
1796  * PARAMETERS:  PFieldList          - Current field list pointer
1797  *
1798  * RETURN:      Status
1799  *
1800  * DESCRIPTION: Compile TPM2 revision 3
1801  *
1802  *****************************************************************************/
1803 static ACPI_STATUS
1804 DtCompileTpm2Rev3 (
1805     void                    **List)
1806 {
1807     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1808     DT_SUBTABLE             *Subtable;
1809     ACPI_TABLE_TPM23        *Tpm23Header;
1810     DT_SUBTABLE             *ParentTable;
1811     ACPI_STATUS             Status = AE_OK;
1812 
1813 
1814     Status = DtCompileTable (PFieldList, AcpiDmTableInfoTpm23,
1815         &Subtable);
1816 
1817     ParentTable = DtPeekSubtable ();
1818     DtInsertSubtable (ParentTable, Subtable);
1819     Tpm23Header = ACPI_CAST_PTR (ACPI_TABLE_TPM23, ParentTable->Buffer);
1820 
1821     /* Subtable type depends on the StartMethod */
1822 
1823     switch (Tpm23Header->StartMethod)
1824     {
1825     case ACPI_TPM23_ACPI_START_METHOD:
1826 
1827         /* Subtable specific to to ARM_SMC */
1828 
1829         Status = DtCompileTable (PFieldList, AcpiDmTableInfoTpm23a,
1830             &Subtable);
1831         if (ACPI_FAILURE (Status))
1832         {
1833             return (Status);
1834         }
1835 
1836         ParentTable = DtPeekSubtable ();
1837         DtInsertSubtable (ParentTable, Subtable);
1838         break;
1839 
1840     default:
1841         break;
1842     }
1843 
1844     return (Status);
1845 }
1846 
1847 
1848 /******************************************************************************
1849  *
1850  * FUNCTION:    DtCompileTpm2
1851  *
1852  * PARAMETERS:  PFieldList          - Current field list pointer
1853  *
1854  * RETURN:      Status
1855  *
1856  * DESCRIPTION: Compile TPM2.
1857  *
1858  *****************************************************************************/
1859 
1860 ACPI_STATUS
1861 DtCompileTpm2 (
1862     void                    **List)
1863 {
1864     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1865     DT_SUBTABLE             *Subtable;
1866     ACPI_TABLE_TPM2         *Tpm2Header;
1867     DT_SUBTABLE             *ParentTable;
1868     ACPI_STATUS             Status = AE_OK;
1869     ACPI_TABLE_HEADER       *Header;
1870 
1871 
1872     ParentTable = DtPeekSubtable ();
1873 
1874     Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
1875 
1876     if (Header->Revision == 3)
1877     {
1878         return (DtCompileTpm2Rev3 (List));
1879     }
1880 
1881     /* Compile the main table */
1882 
1883     Status = DtCompileTable (PFieldList, AcpiDmTableInfoTpm2,
1884         &Subtable);
1885     if (ACPI_FAILURE (Status))
1886     {
1887         return (Status);
1888     }
1889 
1890     ParentTable = DtPeekSubtable ();
1891     DtInsertSubtable (ParentTable, Subtable);
1892 
1893     Tpm2Header = ACPI_CAST_PTR (ACPI_TABLE_TPM2, ParentTable->Buffer);
1894 
1895     /* Method parameters */
1896     /* Optional: Log area minimum length */
1897     /* Optional: Log area start address */
1898     /* TBD: Optional fields above not fully implemented (not optional at this time) */
1899 
1900     Status = DtCompileTable (PFieldList, AcpiDmTableInfoTpm2a,
1901         &Subtable);
1902     if (ACPI_FAILURE (Status))
1903     {
1904         return (Status);
1905     }
1906 
1907     ParentTable = DtPeekSubtable ();
1908     DtInsertSubtable (ParentTable, Subtable);
1909 
1910 
1911     /* Subtable type depends on the StartMethod */
1912 
1913     switch (Tpm2Header->StartMethod)
1914     {
1915     case ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC:
1916 
1917         /* Subtable specific to to ARM_SMC */
1918 
1919         Status = DtCompileTable (PFieldList, AcpiDmTableInfoTpm211,
1920             &Subtable);
1921         if (ACPI_FAILURE (Status))
1922         {
1923             return (Status);
1924         }
1925 
1926         ParentTable = DtPeekSubtable ();
1927         DtInsertSubtable (ParentTable, Subtable);
1928         break;
1929 
1930     case ACPI_TPM2_START_METHOD:
1931     case ACPI_TPM2_MEMORY_MAPPED:
1932     case ACPI_TPM2_COMMAND_BUFFER:
1933     case ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD:
1934         break;
1935 
1936     case ACPI_TPM2_RESERVED1:
1937     case ACPI_TPM2_RESERVED3:
1938     case ACPI_TPM2_RESERVED4:
1939     case ACPI_TPM2_RESERVED5:
1940     case ACPI_TPM2_RESERVED9:
1941     case ACPI_TPM2_RESERVED10:
1942 
1943         AcpiOsPrintf ("\n**** Reserved TPM2 Start Method type 0x%X\n",
1944             Tpm2Header->StartMethod);
1945         Status = AE_ERROR;
1946         break;
1947 
1948     case ACPI_TPM2_NOT_ALLOWED:
1949     default:
1950 
1951         AcpiOsPrintf ("\n**** Unknown TPM2 Start Method type 0x%X\n",
1952             Tpm2Header->StartMethod);
1953         Status = AE_ERROR;
1954         break;
1955     }
1956 
1957     return (Status);
1958 }
1959 
1960 
1961 /******************************************************************************
1962  *
1963  * FUNCTION:    DtGetGenericTableInfo
1964  *
1965  * PARAMETERS:  Name                - Generic type name
1966  *
1967  * RETURN:      Info entry
1968  *
1969  * DESCRIPTION: Obtain table info for a generic name entry
1970  *
1971  *****************************************************************************/
1972 
1973 ACPI_DMTABLE_INFO *
1974 DtGetGenericTableInfo (
1975     char                    *Name)
1976 {
1977     ACPI_DMTABLE_INFO       *Info;
1978     UINT32                  i;
1979 
1980 
1981     if (!Name)
1982     {
1983         return (NULL);
1984     }
1985 
1986     /* Search info table for name match */
1987 
1988     for (i = 0; ; i++)
1989     {
1990         Info = AcpiDmTableInfoGeneric[i];
1991         if (Info->Opcode == ACPI_DMT_EXIT)
1992         {
1993             Info = NULL;
1994             break;
1995         }
1996 
1997         /* Use caseless compare for generic keywords */
1998 
1999         if (!AcpiUtStricmp (Name, Info->Name))
2000         {
2001             break;
2002         }
2003     }
2004 
2005     return (Info);
2006 }
2007 
2008 
2009 /******************************************************************************
2010  *
2011  * FUNCTION:    DtCompileUefi
2012  *
2013  * PARAMETERS:  List                - Current field list pointer
2014  *
2015  * RETURN:      Status
2016  *
2017  * DESCRIPTION: Compile UEFI.
2018  *
2019  *****************************************************************************/
2020 
2021 ACPI_STATUS
2022 DtCompileUefi (
2023     void                    **List)
2024 {
2025     ACPI_STATUS             Status;
2026     DT_SUBTABLE             *Subtable;
2027     DT_SUBTABLE             *ParentTable;
2028     DT_FIELD                **PFieldList = (DT_FIELD **) List;
2029     UINT16                  *DataOffset;
2030 
2031 
2032     /* Compile the predefined portion of the UEFI table */
2033 
2034     Status = DtCompileTable (PFieldList, AcpiDmTableInfoUefi,
2035         &Subtable);
2036     if (ACPI_FAILURE (Status))
2037     {
2038         return (Status);
2039     }
2040 
2041     DataOffset = (UINT16 *) (Subtable->Buffer + 16);
2042     *DataOffset = sizeof (ACPI_TABLE_UEFI);
2043 
2044     ParentTable = DtPeekSubtable ();
2045     DtInsertSubtable (ParentTable, Subtable);
2046 
2047     /*
2048      * Compile the "generic" portion of the UEFI table. This
2049      * part of the table is not predefined and any of the generic
2050      * operators may be used.
2051      */
2052     DtCompileGeneric ((void **) PFieldList, NULL, NULL);
2053     return (AE_OK);
2054 }
2055 
2056 
2057 /******************************************************************************
2058  *
2059  * FUNCTION:    DtCompileVrtc
2060  *
2061  * PARAMETERS:  List                - Current field list pointer
2062  *
2063  * RETURN:      Status
2064  *
2065  * DESCRIPTION: Compile VRTC.
2066  *
2067  *****************************************************************************/
2068 
2069 ACPI_STATUS
2070 DtCompileVrtc (
2071     void                    **List)
2072 {
2073     ACPI_STATUS             Status;
2074 
2075 
2076     Status = DtCompileTwoSubtables (List,
2077         AcpiDmTableInfoVrtc, AcpiDmTableInfoVrtc0);
2078     return (Status);
2079 }
2080 
2081 
2082 /******************************************************************************
2083  *
2084  * FUNCTION:    DtCompileWdat
2085  *
2086  * PARAMETERS:  List                - Current field list pointer
2087  *
2088  * RETURN:      Status
2089  *
2090  * DESCRIPTION: Compile WDAT.
2091  *
2092  *****************************************************************************/
2093 
2094 ACPI_STATUS
2095 DtCompileWdat (
2096     void                    **List)
2097 {
2098     ACPI_STATUS             Status;
2099 
2100 
2101     Status = DtCompileTwoSubtables (List,
2102         AcpiDmTableInfoWdat, AcpiDmTableInfoWdat0);
2103     return (Status);
2104 }
2105 
2106 
2107 /******************************************************************************
2108  *
2109  * FUNCTION:    DtCompileWpbt
2110  *
2111  * PARAMETERS:  List                - Current field list pointer
2112  *
2113  * RETURN:      Status
2114  *
2115  * DESCRIPTION: Compile WPBT.
2116  *
2117  *****************************************************************************/
2118 
2119 ACPI_STATUS
2120 DtCompileWpbt (
2121     void                    **List)
2122 {
2123     DT_FIELD                **PFieldList = (DT_FIELD **) List;
2124     DT_SUBTABLE             *Subtable;
2125     DT_SUBTABLE             *ParentTable;
2126     ACPI_TABLE_WPBT         *Table;
2127     ACPI_STATUS             Status;
2128     UINT16                  Length;
2129 
2130 
2131     /* Compile the main table */
2132 
2133     Status = DtCompileTable (PFieldList, AcpiDmTableInfoWpbt,
2134         &Subtable);
2135     if (ACPI_FAILURE (Status))
2136     {
2137         return (Status);
2138     }
2139 
2140     ParentTable = DtPeekSubtable ();
2141     DtInsertSubtable (ParentTable, Subtable);
2142 
2143     /* Compile the argument list subtable */
2144 
2145     Status = DtCompileTable (PFieldList, AcpiDmTableInfoWpbt0,
2146         &Subtable);
2147     if (ACPI_FAILURE (Status))
2148     {
2149         return (Status);
2150     }
2151 
2152     /* Extract the length of the Arguments buffer, insert into main table */
2153 
2154     Length = (UINT16) Subtable->TotalLength;
2155     Table = ACPI_CAST_PTR (ACPI_TABLE_WPBT, ParentTable->Buffer);
2156     Table->ArgumentsLength = Length;
2157 
2158     ParentTable = DtPeekSubtable ();
2159     DtInsertSubtable (ParentTable, Subtable);
2160     return (AE_OK);
2161 }
2162 
2163 
2164 /******************************************************************************
2165  *
2166  * FUNCTION:    DtCompileXsdt
2167  *
2168  * PARAMETERS:  List                - Current field list pointer
2169  *
2170  * RETURN:      Status
2171  *
2172  * DESCRIPTION: Compile XSDT.
2173  *
2174  *****************************************************************************/
2175 
2176 ACPI_STATUS
2177 DtCompileXsdt (
2178     void                    **List)
2179 {
2180     DT_SUBTABLE             *Subtable;
2181     DT_SUBTABLE             *ParentTable;
2182     DT_FIELD                *FieldList = *(DT_FIELD **) List;
2183     UINT64                  Address;
2184 
2185 
2186     ParentTable = DtPeekSubtable ();
2187 
2188     while (FieldList)
2189     {
2190         DtCompileInteger ((UINT8 *) &Address, FieldList, 8, DT_NON_ZERO);
2191 
2192         DtCreateSubtable ((UINT8 *) &Address, 8, &Subtable);
2193         DtInsertSubtable (ParentTable, Subtable);
2194         FieldList = FieldList->Next;
2195     }
2196 
2197     return (AE_OK);
2198 }
2199 
2200 
2201 /******************************************************************************
2202  *
2203  * FUNCTION:    DtCompileGeneric
2204  *
2205  * PARAMETERS:  List                - Current field list pointer
2206  *              Name                - Field name to end generic compiling
2207  *              Length              - Compiled table length to return
2208  *
2209  * RETURN:      Status
2210  *
2211  * DESCRIPTION: Compile generic unknown table.
2212  *
2213  *****************************************************************************/
2214 
2215 ACPI_STATUS
2216 DtCompileGeneric (
2217     void                    **List,
2218     char                    *Name,
2219     UINT32                  *Length)
2220 {
2221     ACPI_STATUS             Status;
2222     DT_SUBTABLE             *Subtable;
2223     DT_SUBTABLE             *ParentTable;
2224     DT_FIELD                **PFieldList = (DT_FIELD **) List;
2225     ACPI_DMTABLE_INFO       *Info;
2226 
2227 
2228     ParentTable = DtPeekSubtable ();
2229 
2230     /*
2231      * Compile the "generic" portion of the table. This
2232      * part of the table is not predefined and any of the generic
2233      * operators may be used.
2234      */
2235 
2236     /* Find any and all labels in the entire generic portion */
2237 
2238     DtDetectAllLabels (*PFieldList);
2239 
2240     /* Now we can actually compile the parse tree */
2241 
2242     if (Length && *Length)
2243     {
2244         *Length = 0;
2245     }
2246     while (*PFieldList)
2247     {
2248         if (Name && !strcmp ((*PFieldList)->Name, Name))
2249         {
2250             break;
2251         }
2252 
2253         Info = DtGetGenericTableInfo ((*PFieldList)->Name);
2254         if (!Info)
2255         {
2256             sprintf (AslGbl_MsgBuffer, "Generic data type \"%s\" not found",
2257                 (*PFieldList)->Name);
2258             DtNameError (ASL_ERROR, ASL_MSG_INVALID_FIELD_NAME,
2259                 (*PFieldList), AslGbl_MsgBuffer);
2260 
2261             *PFieldList = (*PFieldList)->Next;
2262             continue;
2263         }
2264 
2265         Status = DtCompileTable (PFieldList, Info,
2266             &Subtable);
2267         if (ACPI_SUCCESS (Status))
2268         {
2269             DtInsertSubtable (ParentTable, Subtable);
2270             if (Length)
2271             {
2272                 *Length += Subtable->Length;
2273             }
2274         }
2275         else
2276         {
2277             *PFieldList = (*PFieldList)->Next;
2278 
2279             if (Status == AE_NOT_FOUND)
2280             {
2281                 sprintf (AslGbl_MsgBuffer, "Generic data type \"%s\" not found",
2282                     (*PFieldList)->Name);
2283                 DtNameError (ASL_ERROR, ASL_MSG_INVALID_FIELD_NAME,
2284                     (*PFieldList), AslGbl_MsgBuffer);
2285             }
2286         }
2287     }
2288 
2289     return (AE_OK);
2290 }
2291