1/******************************************************************************
2 *
3 * Module Name: dmtbdump3 - Dump ACPI data tables that contain no AML code
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2023, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include "acpi.h"
45#include "accommon.h"
46#include "acdisasm.h"
47#include "actables.h"
48
49/* This module used for application-level code only */
50
51#define _COMPONENT          ACPI_CA_DISASSEMBLER
52        ACPI_MODULE_NAME    ("dmtbdump3")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION:    AcpiDmDumpSlic
58 *
59 * PARAMETERS:  Table               - A SLIC table
60 *
61 * RETURN:      None
62 *
63 * DESCRIPTION: Format the contents of a SLIC
64 *
65 ******************************************************************************/
66
67void
68AcpiDmDumpSlic (
69    ACPI_TABLE_HEADER       *Table)
70{
71
72    (void) AcpiDmDumpTable (Table->Length, sizeof (ACPI_TABLE_HEADER), Table,
73        Table->Length - sizeof (*Table), AcpiDmTableInfoSlic);
74}
75
76
77/*******************************************************************************
78 *
79 * FUNCTION:    AcpiDmDumpSlit
80 *
81 * PARAMETERS:  Table               - An SLIT
82 *
83 * RETURN:      None
84 *
85 * DESCRIPTION: Format the contents of a SLIT
86 *
87 ******************************************************************************/
88
89void
90AcpiDmDumpSlit (
91    ACPI_TABLE_HEADER       *Table)
92{
93    ACPI_STATUS             Status;
94    UINT32                  Offset;
95    UINT8                   *Row;
96    UINT32                  Localities;
97    UINT32                  i;
98    UINT32                  j;
99
100
101    /* Main table */
102
103    Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoSlit);
104    if (ACPI_FAILURE (Status))
105    {
106        return;
107    }
108
109    /* Display the Locality NxN Matrix */
110
111    Localities = (UINT32) ACPI_CAST_PTR (ACPI_TABLE_SLIT, Table)->LocalityCount;
112    Offset = ACPI_OFFSET (ACPI_TABLE_SLIT, Entry[0]);
113    Row = (UINT8 *) ACPI_CAST_PTR (ACPI_TABLE_SLIT, Table)->Entry;
114
115    for (i = 0; i < Localities; i++)
116    {
117        /* Display one row of the matrix */
118
119        AcpiDmLineHeader2 (Offset, Localities, "Locality", i);
120        for  (j = 0; j < Localities; j++)
121        {
122            /* Check for beyond EOT */
123
124            if (Offset >= Table->Length)
125            {
126                AcpiOsPrintf (
127                    "\n**** Not enough room in table for all localities\n");
128                return;
129            }
130
131            AcpiOsPrintf ("%2.2X", Row[j]);
132            Offset++;
133
134            /* Display up to 16 bytes per output row */
135
136            if ((j+1) < Localities)
137            {
138                AcpiOsPrintf (" ");
139
140                if (j && (((j+1) % 16) == 0))
141                {
142                    AcpiOsPrintf ("\\\n"); /* With line continuation char */
143                    AcpiDmLineHeader (Offset, 0, NULL);
144                }
145            }
146        }
147
148        /* Point to next row */
149
150        AcpiOsPrintf ("\n");
151        Row += Localities;
152    }
153}
154
155
156/*******************************************************************************
157 *
158 * FUNCTION:    AcpiDmDumpSrat
159 *
160 * PARAMETERS:  Table               - A SRAT table
161 *
162 * RETURN:      None
163 *
164 * DESCRIPTION: Format the contents of a SRAT
165 *
166 ******************************************************************************/
167
168void
169AcpiDmDumpSrat (
170    ACPI_TABLE_HEADER       *Table)
171{
172    ACPI_STATUS             Status;
173    UINT32                  Offset = sizeof (ACPI_TABLE_SRAT);
174    ACPI_SUBTABLE_HEADER    *Subtable;
175    ACPI_DMTABLE_INFO       *InfoTable;
176
177
178    /* Main table */
179
180    Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoSrat);
181    if (ACPI_FAILURE (Status))
182    {
183        return;
184    }
185
186    /* Subtables */
187
188    Subtable = ACPI_ADD_PTR (ACPI_SUBTABLE_HEADER, Table, Offset);
189    while (Offset < Table->Length)
190    {
191        /* Common subtable header */
192
193        AcpiOsPrintf ("\n");
194        Status = AcpiDmDumpTable (Table->Length, Offset, Subtable,
195            Subtable->Length, AcpiDmTableInfoSratHdr);
196        if (ACPI_FAILURE (Status))
197        {
198            return;
199        }
200
201        switch (Subtable->Type)
202        {
203        case ACPI_SRAT_TYPE_CPU_AFFINITY:
204
205            InfoTable = AcpiDmTableInfoSrat0;
206            break;
207
208        case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
209
210            InfoTable = AcpiDmTableInfoSrat1;
211            break;
212
213        case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
214
215            InfoTable = AcpiDmTableInfoSrat2;
216            break;
217
218        case ACPI_SRAT_TYPE_GICC_AFFINITY:
219
220            InfoTable = AcpiDmTableInfoSrat3;
221            break;
222
223        case ACPI_SRAT_TYPE_GIC_ITS_AFFINITY:
224
225            InfoTable = AcpiDmTableInfoSrat4;
226            break;
227
228        case ACPI_SRAT_TYPE_GENERIC_AFFINITY:
229
230            InfoTable = AcpiDmTableInfoSrat5;
231            break;
232
233        case ACPI_SRAT_TYPE_GENERIC_PORT_AFFINITY:
234
235            InfoTable = AcpiDmTableInfoSrat6;
236            break;
237
238        default:
239            AcpiOsPrintf ("\n**** Unknown SRAT subtable type 0x%X\n",
240                Subtable->Type);
241
242            /* Attempt to continue */
243
244            if (!Subtable->Length)
245            {
246                AcpiOsPrintf ("Invalid zero length subtable\n");
247                return;
248            }
249            goto NextSubtable;
250        }
251
252        AcpiOsPrintf ("\n");
253        Status = AcpiDmDumpTable (Table->Length, Offset, Subtable,
254            Subtable->Length, InfoTable);
255        if (ACPI_FAILURE (Status))
256        {
257            return;
258        }
259
260NextSubtable:
261        /* Point to next subtable */
262
263        Offset += Subtable->Length;
264        Subtable = ACPI_ADD_PTR (ACPI_SUBTABLE_HEADER, Subtable,
265            Subtable->Length);
266    }
267}
268
269
270/*******************************************************************************
271 *
272 * FUNCTION:    AcpiDmDumpStao
273 *
274 * PARAMETERS:  Table               - A STAO table
275 *
276 * RETURN:      None
277 *
278 * DESCRIPTION: Format the contents of a STAO. This is a variable-length
279 *              table that contains an open-ended number of ASCII strings
280 *              at the end of the table.
281 *
282 ******************************************************************************/
283
284void
285AcpiDmDumpStao (
286    ACPI_TABLE_HEADER       *Table)
287{
288    ACPI_STATUS             Status;
289    char                    *Namepath;
290    UINT32                  Length = Table->Length;
291    UINT32                  StringLength;
292    UINT32                  Offset = sizeof (ACPI_TABLE_STAO);
293
294
295    /* Main table */
296
297    Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoStao);
298    if (ACPI_FAILURE (Status))
299    {
300        return;
301    }
302
303    /* The rest of the table consists of Namepath strings */
304
305    while (Offset < Table->Length)
306    {
307        Namepath = ACPI_ADD_PTR (char, Table, Offset);
308        StringLength = strlen (Namepath) + 1;
309
310        AcpiDmLineHeader (Offset, StringLength, "Namepath");
311        AcpiOsPrintf ("\"%s\"\n", Namepath);
312
313        /* Point to next namepath */
314
315        Offset += StringLength;
316    }
317}
318
319
320/*******************************************************************************
321 *
322 * FUNCTION:    AcpiDmDumpSvkl
323 *
324 * PARAMETERS:  Table               - A SVKL table
325 *
326 * RETURN:      None
327 *
328 * DESCRIPTION: Format the contents of a SVKL. This is a variable-length
329 *              table that contains an open-ended number of key subtables at
330 *              the end of the header.
331 *
332 * NOTES: SVKL is essentially a flat table, with a small main table and
333 *          a variable number of a single type of subtable.
334 *
335 ******************************************************************************/
336
337void
338AcpiDmDumpSvkl (
339    ACPI_TABLE_HEADER       *Table)
340{
341    ACPI_STATUS             Status;
342    UINT32                  Length = Table->Length;
343    UINT32                  Offset = sizeof (ACPI_TABLE_SVKL);
344    ACPI_SVKL_KEY           *Subtable;
345
346
347    /* Main table */
348
349    Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoSvkl);
350    if (ACPI_FAILURE (Status))
351    {
352        return;
353    }
354
355    /* The rest of the table consists of subtables (single type) */
356
357    Subtable = ACPI_ADD_PTR (ACPI_SVKL_KEY, Table, Offset);
358    while (Offset < Table->Length)
359    {
360        /* Dump the subtable */
361
362        AcpiOsPrintf ("\n");
363        Status = AcpiDmDumpTable (Table->Length, Offset, Subtable,
364            sizeof (ACPI_SVKL_KEY), AcpiDmTableInfoSvkl0);
365        if (ACPI_FAILURE (Status))
366        {
367            return;
368        }
369
370        /* Point to next subtable */
371
372        Offset += sizeof (ACPI_SVKL_KEY);
373        Subtable = ACPI_ADD_PTR (ACPI_SVKL_KEY, Subtable,
374            sizeof (ACPI_SVKL_KEY));
375    }
376}
377
378
379/*******************************************************************************
380 *
381 * FUNCTION:    AcpiDmDumpTcpa
382 *
383 * PARAMETERS:  Table               - A TCPA table
384 *
385 * RETURN:      None
386 *
387 * DESCRIPTION: Format the contents of a TCPA.
388 *
389 * NOTE:        There are two versions of the table with the same signature:
390 *              the client version and the server version. The common
391 *              PlatformClass field is used to differentiate the two types of
392 *              tables.
393 *
394 ******************************************************************************/
395
396void
397AcpiDmDumpTcpa (
398    ACPI_TABLE_HEADER       *Table)
399{
400    UINT32                  Offset = sizeof (ACPI_TABLE_TCPA_HDR);
401    ACPI_TABLE_TCPA_HDR     *CommonHeader = ACPI_CAST_PTR (
402                                ACPI_TABLE_TCPA_HDR, Table);
403    ACPI_TABLE_TCPA_HDR     *Subtable = ACPI_ADD_PTR (
404                                ACPI_TABLE_TCPA_HDR, Table, Offset);
405    ACPI_STATUS             Status;
406
407
408    /* Main table */
409
410    Status = AcpiDmDumpTable (Table->Length, 0, Table,
411        0, AcpiDmTableInfoTcpaHdr);
412    if (ACPI_FAILURE (Status))
413    {
414        return;
415    }
416
417    /*
418     * Examine the PlatformClass field to determine the table type.
419     * Either a client or server table. Only one.
420     */
421    switch (CommonHeader->PlatformClass)
422    {
423    case ACPI_TCPA_CLIENT_TABLE:
424
425        Status = AcpiDmDumpTable (Table->Length, Offset, Subtable,
426            Table->Length - Offset, AcpiDmTableInfoTcpaClient);
427        break;
428
429    case ACPI_TCPA_SERVER_TABLE:
430
431        Status = AcpiDmDumpTable (Table->Length, Offset, Subtable,
432            Table->Length - Offset, AcpiDmTableInfoTcpaServer);
433        break;
434
435    default:
436
437        AcpiOsPrintf ("\n**** Unknown TCPA Platform Class 0x%X\n",
438            CommonHeader->PlatformClass);
439        Status = AE_ERROR;
440        break;
441    }
442
443    if (ACPI_FAILURE (Status))
444    {
445        AcpiOsPrintf ("\n**** Cannot disassemble TCPA table\n");
446    }
447}
448
449
450/*******************************************************************************
451 *
452 * FUNCTION:    AcpiDmDumpTpm2
453 *
454 * PARAMETERS:  Table               - A TPM2 table
455 *
456 * RETURN:      None
457 *
458 * DESCRIPTION: Format the contents of a TPM2.
459 *
460 ******************************************************************************/
461
462static void
463AcpiDmDumpTpm2Rev3 (
464    ACPI_TABLE_HEADER       *Table)
465{
466    UINT32                  Offset = sizeof (ACPI_TABLE_TPM23);
467    ACPI_TABLE_TPM23        *CommonHeader = ACPI_CAST_PTR (ACPI_TABLE_TPM23, Table);
468    ACPI_TPM23_TRAILER      *Subtable = ACPI_ADD_PTR (ACPI_TPM23_TRAILER, Table, Offset);
469    ACPI_STATUS             Status;
470
471
472    /* Main table */
473
474    Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoTpm23);
475    if (ACPI_FAILURE (Status))
476    {
477        return;
478    }
479
480    /* Optional subtable if start method is ACPI start method */
481
482    switch (CommonHeader->StartMethod)
483    {
484    case ACPI_TPM23_ACPI_START_METHOD:
485
486        (void) AcpiDmDumpTable (Table->Length, Offset, Subtable,
487            Table->Length - Offset, AcpiDmTableInfoTpm23a);
488        break;
489
490    default:
491        break;
492    }
493}
494
495
496/*******************************************************************************
497 *
498 * FUNCTION:    AcpiDmDumpTpm2
499 *
500 * PARAMETERS:  Table               - A TPM2 table
501 *
502 * RETURN:      None
503 *
504 * DESCRIPTION: Format the contents of a TPM2.
505 *
506 ******************************************************************************/
507
508void
509AcpiDmDumpTpm2 (
510    ACPI_TABLE_HEADER       *Table)
511{
512    UINT32                  Offset = sizeof (ACPI_TABLE_TPM2);
513    ACPI_TABLE_TPM2         *CommonHeader = ACPI_CAST_PTR (ACPI_TABLE_TPM2, Table);
514    ACPI_TPM2_TRAILER       *Subtable = ACPI_ADD_PTR (ACPI_TPM2_TRAILER, Table, Offset);
515    ACPI_TPM2_ARM_SMC       *ArmSubtable;
516    ACPI_STATUS             Status;
517
518
519    if (Table->Revision == 3)
520    {
521        AcpiDmDumpTpm2Rev3(Table);
522        return;
523    }
524
525    /* Main table */
526
527    Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoTpm2);
528
529    if (ACPI_FAILURE (Status))
530    {
531        return;
532    }
533
534    AcpiOsPrintf ("\n");
535    Status = AcpiDmDumpTable (Table->Length, Offset, Subtable,
536        Table->Length - Offset, AcpiDmTableInfoTpm2a);
537    if (ACPI_FAILURE (Status))
538    {
539        return;
540    }
541
542    switch (CommonHeader->StartMethod)
543    {
544    case ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC:
545
546        ArmSubtable = ACPI_ADD_PTR (ACPI_TPM2_ARM_SMC, Subtable,
547            sizeof (ACPI_TPM2_TRAILER));
548        Offset += sizeof (ACPI_TPM2_TRAILER);
549
550        AcpiOsPrintf ("\n");
551        (void) AcpiDmDumpTable (Table->Length, Offset, ArmSubtable,
552            Table->Length - Offset, AcpiDmTableInfoTpm211);
553        break;
554
555    default:
556        break;
557    }
558}
559
560
561/*******************************************************************************
562 *
563 * FUNCTION:    AcpiDmDumpViot
564 *
565 * PARAMETERS:  Table               - A VIOT table
566 *
567 * RETURN:      None
568 *
569 * DESCRIPTION: Format the contents of a VIOT
570 *
571 ******************************************************************************/
572
573void
574AcpiDmDumpViot (
575    ACPI_TABLE_HEADER       *Table)
576{
577    ACPI_STATUS             Status;
578    ACPI_TABLE_VIOT         *Viot;
579    ACPI_VIOT_HEADER        *ViotHeader;
580    UINT16                  Length;
581    UINT32                  Offset;
582    ACPI_DMTABLE_INFO       *InfoTable;
583
584    /* Main table */
585
586    Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoViot);
587    if (ACPI_FAILURE (Status))
588    {
589        return;
590    }
591
592    Viot = ACPI_CAST_PTR (ACPI_TABLE_VIOT, Table);
593
594    Offset = Viot->NodeOffset;
595    while (Offset < Table->Length)
596    {
597        /* Common subtable header */
598        ViotHeader = ACPI_ADD_PTR (ACPI_VIOT_HEADER, Table, Offset);
599        AcpiOsPrintf ("\n");
600
601        Length = sizeof (ACPI_VIOT_HEADER);
602        Status = AcpiDmDumpTable (Table->Length, Offset, ViotHeader, Length,
603            AcpiDmTableInfoViotHeader);
604        if (ACPI_FAILURE (Status))
605        {
606            return;
607        }
608
609        Length = ViotHeader->Length;
610        switch (ViotHeader->Type)
611        {
612        case ACPI_VIOT_NODE_PCI_RANGE:
613
614            InfoTable = AcpiDmTableInfoViot1;
615            break;
616
617        case ACPI_VIOT_NODE_MMIO:
618
619            InfoTable = AcpiDmTableInfoViot2;
620            break;
621
622        case ACPI_VIOT_NODE_VIRTIO_IOMMU_PCI:
623
624            InfoTable = AcpiDmTableInfoViot3;
625            break;
626
627        case ACPI_VIOT_NODE_VIRTIO_IOMMU_MMIO:
628
629            InfoTable = AcpiDmTableInfoViot4;
630            break;
631
632        default:
633
634            AcpiOsPrintf ("\n*** Unknown VIOT node type 0x%X\n",
635                ViotHeader->Type);
636
637            /* Attempt to continue */
638
639            if (!Length)
640            {
641                AcpiOsPrintf ("Invalid zero length VIOT node\n");
642                return;
643            }
644            goto NextSubtable;
645        }
646
647        AcpiOsPrintf ("\n");
648        Status = AcpiDmDumpTable (Table->Length, Offset, ViotHeader, Length,
649            InfoTable);
650        if (ACPI_FAILURE (Status))
651        {
652            return;
653        }
654
655NextSubtable:
656        Offset += Length;
657    }
658}
659
660
661/*******************************************************************************
662 *
663 * FUNCTION:    AcpiDmDumpWdat
664 *
665 * PARAMETERS:  Table               - A WDAT table
666 *
667 * RETURN:      None
668 *
669 * DESCRIPTION: Format the contents of a WDAT
670 *
671 ******************************************************************************/
672
673void
674AcpiDmDumpWdat (
675    ACPI_TABLE_HEADER       *Table)
676{
677    ACPI_STATUS             Status;
678    UINT32                  Offset = sizeof (ACPI_TABLE_WDAT);
679    ACPI_WDAT_ENTRY         *Subtable;
680
681
682    /* Main table */
683
684    Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoWdat);
685    if (ACPI_FAILURE (Status))
686    {
687        return;
688    }
689
690    /* Subtables */
691
692    Subtable = ACPI_ADD_PTR (ACPI_WDAT_ENTRY, Table, Offset);
693    while (Offset < Table->Length)
694    {
695        /* Common subtable header */
696
697        AcpiOsPrintf ("\n");
698        Status = AcpiDmDumpTable (Table->Length, Offset, Subtable,
699            sizeof (ACPI_WDAT_ENTRY), AcpiDmTableInfoWdat0);
700        if (ACPI_FAILURE (Status))
701        {
702            return;
703        }
704
705        /* Point to next subtable */
706
707        Offset += sizeof (ACPI_WDAT_ENTRY);
708        Subtable = ACPI_ADD_PTR (ACPI_WDAT_ENTRY, Subtable,
709            sizeof (ACPI_WDAT_ENTRY));
710    }
711}
712
713
714/*******************************************************************************
715 *
716 * FUNCTION:    AcpiDmDumpWpbt
717 *
718 * PARAMETERS:  Table               - A WPBT table
719 *
720 * RETURN:      None
721 *
722 * DESCRIPTION: Format the contents of a WPBT. This table type consists
723 *              of an open-ended arguments buffer at the end of the table.
724 *
725 ******************************************************************************/
726
727void
728AcpiDmDumpWpbt (
729    ACPI_TABLE_HEADER       *Table)
730{
731    ACPI_STATUS             Status;
732    ACPI_TABLE_WPBT         *Subtable;
733    UINT16                  ArgumentsLength;
734
735
736    /* Dump the main table */
737
738    Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoWpbt);
739    if (ACPI_FAILURE (Status))
740    {
741        return;
742    }
743
744    /* Extract the arguments buffer length from the main table */
745
746    Subtable = ACPI_CAST_PTR (ACPI_TABLE_WPBT, Table);
747    ArgumentsLength = Subtable->ArgumentsLength;
748
749    /* Dump the arguments buffer if present */
750
751    if (ArgumentsLength)
752    {
753        (void) AcpiDmDumpTable (Table->Length, 0, Table, ArgumentsLength,
754            AcpiDmTableInfoWpbt0);
755    }
756}
757