xref: /freebsd/sys/contrib/dev/acpica/common/dmtable.c (revision 3ef51c5fb9163f2aafb1c14729e06a8bf0c4d113)
1 /******************************************************************************
2  *
3  * Module Name: dmtable - Support for ACPI tables that contain no AML code
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2012, 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 #include <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/acdisasm.h>
47 #include <contrib/dev/acpica/include/actables.h>
48 #include <contrib/dev/acpica/compiler/aslcompiler.h>
49 #include <contrib/dev/acpica/compiler/dtcompiler.h>
50 
51 /* This module used for application-level code only */
52 
53 #define _COMPONENT          ACPI_CA_DISASSEMBLER
54         ACPI_MODULE_NAME    ("dmtable")
55 
56 /* Local Prototypes */
57 
58 static void
59 AcpiDmCheckAscii (
60     UINT8                   *Target,
61     char                    *RepairedName,
62     UINT32                  Count);
63 
64 
65 /* Common format strings for commented values */
66 
67 #define UINT8_FORMAT        "%2.2X [%s]\n"
68 #define UINT16_FORMAT       "%4.4X [%s]\n"
69 #define UINT32_FORMAT       "%8.8X [%s]\n"
70 #define STRING_FORMAT       "[%s]\n"
71 
72 /* These tables map a subtable type to a description string */
73 
74 static const char           *AcpiDmAsfSubnames[] =
75 {
76     "ASF Information",
77     "ASF Alerts",
78     "ASF Remote Control",
79     "ASF RMCP Boot Options",
80     "ASF Address",
81     "Unknown SubTable Type"         /* Reserved */
82 };
83 
84 static const char           *AcpiDmDmarSubnames[] =
85 {
86     "Hardware Unit Definition",
87     "Reserved Memory Region",
88     "Root Port ATS Capability",
89     "Remapping Hardware Static Affinity",
90     "Unknown SubTable Type"         /* Reserved */
91 };
92 
93 static const char           *AcpiDmEinjActions[] =
94 {
95     "Begin Operation",
96     "Get Trigger Table",
97     "Set Error Type",
98     "Get Error Type",
99     "End Operation",
100     "Execute Operation",
101     "Check Busy Status",
102     "Get Command Status",
103     "Unknown Action"
104 };
105 
106 static const char           *AcpiDmEinjInstructions[] =
107 {
108     "Read Register",
109     "Read Register Value",
110     "Write Register",
111     "Write Register Value",
112     "Noop",
113     "Unknown Instruction"
114 };
115 
116 static const char           *AcpiDmErstActions[] =
117 {
118     "Begin Write Operation",
119     "Begin Read Operation",
120     "Begin Clear Operation",
121     "End Operation",
122     "Set Record Offset",
123     "Execute Operation",
124     "Check Busy Status",
125     "Get Command Status",
126     "Get Record Identifier",
127     "Set Record Identifier",
128     "Get Record Count",
129     "Begin Dummy Write",
130     "Unused/Unknown Action",
131     "Get Error Address Range",
132     "Get Error Address Length",
133     "Get Error Attributes",
134     "Unknown Action"
135 };
136 
137 static const char           *AcpiDmErstInstructions[] =
138 {
139     "Read Register",
140     "Read Register Value",
141     "Write Register",
142     "Write Register Value",
143     "Noop",
144     "Load Var1",
145     "Load Var2",
146     "Store Var1",
147     "Add",
148     "Subtract",
149     "Add Value",
150     "Subtract Value",
151     "Stall",
152     "Stall While True",
153     "Skip Next If True",
154     "GoTo",
155     "Set Source Address",
156     "Set Destination Address",
157     "Move Data",
158     "Unknown Instruction"
159 };
160 
161 static const char           *AcpiDmHestSubnames[] =
162 {
163     "IA-32 Machine Check Exception",
164     "IA-32 Corrected Machine Check",
165     "IA-32 Non-Maskable Interrupt",
166     "Unknown SubTable Type",        /* 3 - Reserved */
167     "Unknown SubTable Type",        /* 4 - Reserved */
168     "Unknown SubTable Type",        /* 5 - Reserved */
169     "PCI Express Root Port AER",
170     "PCI Express AER (AER Endpoint)",
171     "PCI Express/PCI-X Bridge AER",
172     "Generic Hardware Error Source",
173     "Unknown SubTable Type"         /* Reserved */
174 };
175 
176 static const char           *AcpiDmHestNotifySubnames[] =
177 {
178     "Polled",
179     "External Interrupt",
180     "Local Interrupt",
181     "SCI",
182     "NMI",
183     "Unknown Notify Type"           /* Reserved */
184 };
185 
186 static const char           *AcpiDmMadtSubnames[] =
187 {
188     "Processor Local APIC",         /* ACPI_MADT_TYPE_LOCAL_APIC */
189     "I/O APIC",                     /* ACPI_MADT_TYPE_IO_APIC */
190     "Interrupt Source Override",    /* ACPI_MADT_TYPE_INTERRUPT_OVERRIDE */
191     "NMI Source",                   /* ACPI_MADT_TYPE_NMI_SOURCE */
192     "Local APIC NMI",               /* ACPI_MADT_TYPE_LOCAL_APIC_NMI */
193     "Local APIC Address Override",  /* ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE */
194     "I/O SAPIC",                    /* ACPI_MADT_TYPE_IO_SAPIC */
195     "Local SAPIC",                  /* ACPI_MADT_TYPE_LOCAL_SAPIC */
196     "Platform Interrupt Sources",   /* ACPI_MADT_TYPE_INTERRUPT_SOURCE */
197     "Processor Local x2APIC",       /* ACPI_MADT_TYPE_LOCAL_X2APIC */
198     "Local x2APIC NMI",             /* ACPI_MADT_TYPE_LOCAL_X2APIC_NMI */
199     "Generic Interrupt Controller", /* ACPI_MADT_GENERIC_INTERRUPT */
200     "Generic Interrupt Distributor",/* ACPI_MADT_GENERIC_DISTRIBUTOR */
201     "Unknown SubTable Type"         /* Reserved */
202 };
203 
204 static const char           *AcpiDmPmttSubnames[] =
205 {
206     "Socket",                       /* ACPI_PMTT_TYPE_SOCKET */
207     "Memory Controller",            /* ACPI_PMTT_TYPE_CONTROLLER */
208     "Physical Component (DIMM)",    /* ACPI_PMTT_TYPE_DIMM  */
209     "Unknown SubTable Type"         /* Reserved */
210 };
211 
212 static const char           *AcpiDmSlicSubnames[] =
213 {
214     "Public Key Structure",
215     "Windows Marker Structure",
216     "Unknown SubTable Type"         /* Reserved */
217 };
218 
219 static const char           *AcpiDmSratSubnames[] =
220 {
221     "Processor Local APIC/SAPIC Affinity",
222     "Memory Affinity",
223     "Processor Local x2APIC Affinity",
224     "Unknown SubTable Type"         /* Reserved */
225 };
226 
227 static const char           *AcpiDmIvrsSubnames[] =
228 {
229     "Hardware Definition Block",
230     "Memory Definition Block",
231     "Unknown SubTable Type"         /* Reserved */
232 };
233 
234 
235 #define ACPI_FADT_PM_RESERVED       9
236 
237 static const char           *AcpiDmFadtProfiles[] =
238 {
239     "Unspecified",
240     "Desktop",
241     "Mobile",
242     "Workstation",
243     "Enterprise Server",
244     "SOHO Server",
245     "Appliance PC",
246     "Performance Server",
247     "Tablet",
248     "Unknown Profile Type"
249 };
250 
251 #define ACPI_GAS_WIDTH_RESERVED     5
252 
253 static const char           *AcpiDmGasAccessWidth[] =
254 {
255     "Undefined/Legacy",
256     "Byte Access:8",
257     "Word Access:16",
258     "DWord Access:32",
259     "QWord Access:64",
260     "Unknown Width Encoding"
261 };
262 
263 
264 /*******************************************************************************
265  *
266  * ACPI Table Data, indexed by signature.
267  *
268  * Each entry contains: Signature, Table Info, Handler, DtHandler,
269  *  Template, Description
270  *
271  * Simple tables have only a TableInfo structure, complex tables have a
272  * handler. This table must be NULL terminated. RSDP and FACS are
273  * special-cased elsewhere.
274  *
275  ******************************************************************************/
276 
277 ACPI_DMTABLE_DATA    AcpiDmTableData[] =
278 {
279     {ACPI_SIG_ASF,  NULL,                   AcpiDmDumpAsf,  DtCompileAsf,   TemplateAsf,    "Alert Standard Format table"},
280     {ACPI_SIG_BOOT, AcpiDmTableInfoBoot,    NULL,           NULL,           TemplateBoot,   "Simple Boot Flag Table"},
281     {ACPI_SIG_BERT, AcpiDmTableInfoBert,    NULL,           NULL,           TemplateBert,   "Boot Error Record Table"},
282     {ACPI_SIG_BGRT, AcpiDmTableInfoBgrt,    NULL,           NULL,           TemplateBgrt,   "Boot Graphics Resource Table"},
283     {ACPI_SIG_CPEP, NULL,                   AcpiDmDumpCpep, DtCompileCpep,  TemplateCpep,   "Corrected Platform Error Polling table"},
284     {ACPI_SIG_DBGP, AcpiDmTableInfoDbgp,    NULL,           NULL,           TemplateDbgp,   "Debug Port table"},
285     {ACPI_SIG_DMAR, NULL,                   AcpiDmDumpDmar, DtCompileDmar,  TemplateDmar,   "DMA Remapping table"},
286     {ACPI_SIG_ECDT, AcpiDmTableInfoEcdt,    NULL,           NULL,           TemplateEcdt,   "Embedded Controller Boot Resources Table"},
287     {ACPI_SIG_EINJ, NULL,                   AcpiDmDumpEinj, DtCompileEinj,  TemplateEinj,   "Error Injection table"},
288     {ACPI_SIG_ERST, NULL,                   AcpiDmDumpErst, DtCompileErst,  TemplateErst,   "Error Record Serialization Table"},
289     {ACPI_SIG_FADT, NULL,                   AcpiDmDumpFadt, DtCompileFadt,  TemplateFadt,   "Fixed ACPI Description Table"},
290     {ACPI_SIG_FPDT, NULL,                   AcpiDmDumpFpdt, DtCompileFpdt,  TemplateFpdt,   "Firmware Performance Data Table"},
291     {ACPI_SIG_GTDT, AcpiDmTableInfoGtdt,    NULL,           NULL,           TemplateGtdt,   "Generic Timer Description Table"},
292     {ACPI_SIG_HEST, NULL,                   AcpiDmDumpHest, DtCompileHest,  TemplateHest,   "Hardware Error Source Table"},
293     {ACPI_SIG_HPET, AcpiDmTableInfoHpet,    NULL,           NULL,           TemplateHpet,   "High Precision Event Timer table"},
294     {ACPI_SIG_IVRS, NULL,                   AcpiDmDumpIvrs, DtCompileIvrs,  TemplateIvrs,   "I/O Virtualization Reporting Structure"},
295     {ACPI_SIG_MADT, NULL,                   AcpiDmDumpMadt, DtCompileMadt,  TemplateMadt,   "Multiple APIC Description Table"},
296     {ACPI_SIG_MCFG, NULL,                   AcpiDmDumpMcfg, DtCompileMcfg,  TemplateMcfg,   "Memory Mapped Configuration table"},
297     {ACPI_SIG_MCHI, AcpiDmTableInfoMchi,    NULL,           NULL,           TemplateMchi,   "Management Controller Host Interface table"},
298     {ACPI_SIG_MPST, AcpiDmTableInfoMpst,    AcpiDmDumpMpst, DtCompileMpst,  TemplateMpst,   "Memory Power State Table"},
299     {ACPI_SIG_MSCT, NULL,                   AcpiDmDumpMsct, DtCompileMsct,  TemplateMsct,   "Maximum System Characteristics Table"},
300     {ACPI_SIG_PCCT, NULL,                   AcpiDmDumpPcct, NULL,           NULL,           "Platform Communications Channel Table"},
301     {ACPI_SIG_PMTT, NULL,                   AcpiDmDumpPmtt, DtCompilePmtt,  TemplatePmtt,   "Platform Memory Topology Table"},
302     {ACPI_SIG_RSDT, NULL,                   AcpiDmDumpRsdt, DtCompileRsdt,  TemplateRsdt,   "Root System Description Table"},
303     {ACPI_SIG_S3PT, NULL,                   NULL,           NULL,           TemplateS3pt,   "S3 Performance Table"},
304     {ACPI_SIG_SBST, AcpiDmTableInfoSbst,    NULL,           NULL,           TemplateSbst,   "Smart Battery Specification Table"},
305     {ACPI_SIG_SLIC, NULL,                   AcpiDmDumpSlic, DtCompileSlic,  TemplateSlic,   "Software Licensing Description Table"},
306     {ACPI_SIG_SLIT, NULL,                   AcpiDmDumpSlit, DtCompileSlit,  TemplateSlit,   "System Locality Information Table"},
307     {ACPI_SIG_SPCR, AcpiDmTableInfoSpcr,    NULL,           NULL,           TemplateSpcr,   "Serial Port Console Redirection table"},
308     {ACPI_SIG_SPMI, AcpiDmTableInfoSpmi,    NULL,           NULL,           TemplateSpmi,   "Server Platform Management Interface table"},
309     {ACPI_SIG_SRAT, NULL,                   AcpiDmDumpSrat, DtCompileSrat,  TemplateSrat,   "System Resource Affinity Table"},
310     {ACPI_SIG_TCPA, AcpiDmTableInfoTcpa,    NULL,           NULL,           TemplateTcpa,   "Trusted Computing Platform Alliance table"},
311     {ACPI_SIG_UEFI, AcpiDmTableInfoUefi,    NULL,           DtCompileUefi,  TemplateUefi,   "UEFI Boot Optimization Table"},
312     {ACPI_SIG_WAET, AcpiDmTableInfoWaet,    NULL,           NULL,           TemplateWaet,   "Windows ACPI Emulated Devices Table"},
313     {ACPI_SIG_WDAT, NULL,                   AcpiDmDumpWdat, DtCompileWdat,  TemplateWdat,   "Watchdog Action Table"},
314     {ACPI_SIG_WDDT, AcpiDmTableInfoWddt,    NULL,           NULL,           TemplateWddt,   "Watchdog Description Table"},
315     {ACPI_SIG_WDRT, AcpiDmTableInfoWdrt,    NULL,           NULL,           TemplateWdrt,   "Watchdog Resource Table"},
316     {ACPI_SIG_XSDT, NULL,                   AcpiDmDumpXsdt, DtCompileXsdt,  TemplateXsdt,   "Extended System Description Table"},
317     {NULL,          NULL,                   NULL,           NULL,           NULL,           NULL}
318 };
319 
320 
321 /*******************************************************************************
322  *
323  * FUNCTION:    AcpiDmGenerateChecksum
324  *
325  * PARAMETERS:  Table               - Pointer to table to be checksummed
326  *              Length              - Length of the table
327  *              OriginalChecksum    - Value of the checksum field
328  *
329  * RETURN:      8 bit checksum of buffer
330  *
331  * DESCRIPTION: Computes an 8 bit checksum of the table.
332  *
333  ******************************************************************************/
334 
335 UINT8
336 AcpiDmGenerateChecksum (
337     void                    *Table,
338     UINT32                  Length,
339     UINT8                   OriginalChecksum)
340 {
341     UINT8                   Checksum;
342 
343 
344     /* Sum the entire table as-is */
345 
346     Checksum = AcpiTbChecksum ((UINT8 *) Table, Length);
347 
348     /* Subtract off the existing checksum value in the table */
349 
350     Checksum = (UINT8) (Checksum - OriginalChecksum);
351 
352     /* Compute the final checksum */
353 
354     Checksum = (UINT8) (0 - Checksum);
355     return (Checksum);
356 }
357 
358 
359 /*******************************************************************************
360  *
361  * FUNCTION:    AcpiDmGetTableData
362  *
363  * PARAMETERS:  Signature           - ACPI signature (4 chars) to match
364  *
365  * RETURN:      Pointer to a valid ACPI_DMTABLE_DATA. Null if no match found.
366  *
367  * DESCRIPTION: Find a match in the global table of supported ACPI tables
368  *
369  ******************************************************************************/
370 
371 ACPI_DMTABLE_DATA *
372 AcpiDmGetTableData (
373     char                    *Signature)
374 {
375     ACPI_DMTABLE_DATA       *TableData;
376 
377 
378     for (TableData = AcpiDmTableData; TableData->Signature; TableData++)
379     {
380         if (ACPI_COMPARE_NAME (Signature, TableData->Signature))
381         {
382             return (TableData);
383         }
384     }
385 
386     return (NULL);
387 }
388 
389 
390 /*******************************************************************************
391  *
392  * FUNCTION:    AcpiDmDumpDataTable
393  *
394  * PARAMETERS:  Table               - An ACPI table
395  *
396  * RETURN:      None.
397  *
398  * DESCRIPTION: Format the contents of an ACPI data table (any table other
399  *              than an SSDT or DSDT that does not contain executable AML code)
400  *
401  ******************************************************************************/
402 
403 void
404 AcpiDmDumpDataTable (
405     ACPI_TABLE_HEADER       *Table)
406 {
407     ACPI_STATUS             Status;
408     ACPI_DMTABLE_DATA       *TableData;
409     UINT32                  Length;
410 
411 
412     /* Ignore tables that contain AML */
413 
414     if (AcpiUtIsAmlTable (Table))
415     {
416         return;
417     }
418 
419     /*
420      * Handle tables that don't use the common ACPI table header structure.
421      * Currently, these are the FACS, RSDP, and S3PT.
422      */
423     if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_FACS))
424     {
425         Length = Table->Length;
426         AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoFacs);
427     }
428     else if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_RSDP))
429     {
430         Length = AcpiDmDumpRsdp (Table);
431     }
432     else if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_S3PT))
433     {
434         Length = AcpiDmDumpS3pt (Table);
435     }
436     else
437     {
438         /*
439          * All other tables must use the common ACPI table header, dump it now
440          */
441         Length = Table->Length;
442         Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoHeader);
443         if (ACPI_FAILURE (Status))
444         {
445             return;
446         }
447         AcpiOsPrintf ("\n");
448 
449         /* Match signature and dispatch appropriately */
450 
451         TableData = AcpiDmGetTableData (Table->Signature);
452         if (!TableData)
453         {
454             if (!ACPI_STRNCMP (Table->Signature, "OEM", 3))
455             {
456                 AcpiOsPrintf ("\n**** OEM-defined ACPI table [%4.4s], unknown contents\n\n",
457                     Table->Signature);
458             }
459             else
460             {
461                 AcpiOsPrintf ("\n**** Unknown ACPI table type [%4.4s]\n\n",
462                     Table->Signature);
463             }
464         }
465         else if (TableData->TableHandler)
466         {
467             /* Complex table, has a handler */
468 
469             TableData->TableHandler (Table);
470         }
471         else if (TableData->TableInfo)
472         {
473             /* Simple table, just walk the info table */
474 
475             AcpiDmDumpTable (Length, 0, Table, 0, TableData->TableInfo);
476         }
477     }
478 
479     if (!Gbl_DoTemplates || Gbl_VerboseTemplates)
480     {
481         /* Dump the raw table data */
482 
483         AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n",
484             ACPI_RAW_TABLE_DATA_HEADER, Length, Length);
485         AcpiUtDumpBuffer2 (ACPI_CAST_PTR (UINT8, Table), Length, DB_BYTE_DISPLAY);
486     }
487 }
488 
489 
490 /*******************************************************************************
491  *
492  * FUNCTION:    AcpiDmLineHeader
493  *
494  * PARAMETERS:  Offset              - Current byte offset, from table start
495  *              ByteLength          - Length of the field in bytes, 0 for flags
496  *              Name                - Name of this field
497  *              Value               - Optional value, displayed on left of ':'
498  *
499  * RETURN:      None
500  *
501  * DESCRIPTION: Utility routines for formatting output lines. Displays the
502  *              current table offset in hex and decimal, the field length,
503  *              and the field name.
504  *
505  ******************************************************************************/
506 
507 void
508 AcpiDmLineHeader (
509     UINT32                  Offset,
510     UINT32                  ByteLength,
511     char                    *Name)
512 {
513 
514     /* Allow a null name for fields that span multiple lines (large buffers) */
515 
516     if (!Name)
517     {
518         Name = "";
519     }
520 
521     if (Gbl_DoTemplates && !Gbl_VerboseTemplates) /* Terse template */
522     {
523         if (ByteLength)
524         {
525             AcpiOsPrintf ("[%.4d] %34s : ", ByteLength, Name);
526         }
527         else
528         {
529             if (*Name)
530             {
531                 AcpiOsPrintf ("%41s : ", Name);
532             }
533             else
534             {
535                 AcpiOsPrintf ("%41s   ", Name);
536             }
537         }
538     }
539     else /* Normal disassembler or verbose template */
540     {
541         if (ByteLength)
542         {
543             AcpiOsPrintf ("[%3.3Xh %4.4d% 4d] %28s : ",
544                 Offset, Offset, ByteLength, Name);
545         }
546         else
547         {
548             if (*Name)
549             {
550                 AcpiOsPrintf ("%44s : ", Name);
551             }
552             else
553             {
554                 AcpiOsPrintf ("%44s   ", Name);
555             }
556         }
557     }
558 }
559 
560 void
561 AcpiDmLineHeader2 (
562     UINT32                  Offset,
563     UINT32                  ByteLength,
564     char                    *Name,
565     UINT32                  Value)
566 {
567 
568     if (Gbl_DoTemplates && !Gbl_VerboseTemplates) /* Terse template */
569     {
570         if (ByteLength)
571         {
572             AcpiOsPrintf ("[%.4d] %30s %3d : ",
573                 ByteLength, Name, Value);
574         }
575         else
576         {
577             AcpiOsPrintf ("%36s % 3d : ",
578                 Name, Value);
579         }
580     }
581     else /* Normal disassembler or verbose template */
582     {
583         if (ByteLength)
584         {
585             AcpiOsPrintf ("[%3.3Xh %4.4d %3d] %24s %3d : ",
586                 Offset, Offset, ByteLength, Name, Value);
587         }
588         else
589         {
590             AcpiOsPrintf ("[%3.3Xh %4.4d   ] %24s %3d : ",
591                 Offset, Offset, Name, Value);
592         }
593     }
594 }
595 
596 
597 /*******************************************************************************
598  *
599  * FUNCTION:    AcpiDmDumpTable
600  *
601  * PARAMETERS:  TableLength         - Length of the entire ACPI table
602  *              TableOffset         - Starting offset within the table for this
603  *                                    sub-descriptor (0 if main table)
604  *              Table               - The ACPI table
605  *              SubtableLength      - Length of this sub-descriptor
606  *              Info                - Info table for this ACPI table
607  *
608  * RETURN:      None
609  *
610  * DESCRIPTION: Display ACPI table contents by walking the Info table.
611  *
612  * Note: This function must remain in sync with DtGetFieldLength.
613  *
614  ******************************************************************************/
615 
616 ACPI_STATUS
617 AcpiDmDumpTable (
618     UINT32                  TableLength,
619     UINT32                  TableOffset,
620     void                    *Table,
621     UINT32                  SubtableLength,
622     ACPI_DMTABLE_INFO       *Info)
623 {
624     UINT8                   *Target;
625     UINT32                  CurrentOffset;
626     UINT32                  ByteLength;
627     UINT8                   Temp8;
628     UINT16                  Temp16;
629     ACPI_DMTABLE_DATA       *TableData;
630     const char              *Name;
631     BOOLEAN                 LastOutputBlankLine = FALSE;
632     char                    RepairedName[8];
633 
634 
635     if (!Info)
636     {
637         AcpiOsPrintf ("Display not implemented\n");
638         return (AE_NOT_IMPLEMENTED);
639     }
640 
641     /* Walk entire Info table; Null name terminates */
642 
643     for (; Info->Name; Info++)
644     {
645         /*
646          * Target points to the field within the ACPI Table. CurrentOffset is
647          * the offset of the field from the start of the main table.
648          */
649         Target = ACPI_ADD_PTR (UINT8, Table, Info->Offset);
650         CurrentOffset = TableOffset + Info->Offset;
651 
652         /* Check for beyond EOT or beyond subtable end */
653 
654         if ((CurrentOffset >= TableLength) ||
655             (SubtableLength && (Info->Offset >= SubtableLength)))
656         {
657             AcpiOsPrintf ("**** ACPI table terminates in the middle of a data structure!\n");
658             return (AE_BAD_DATA);
659         }
660 
661         /* Generate the byte length for this field */
662 
663         switch (Info->Opcode)
664         {
665         case ACPI_DMT_UINT8:
666         case ACPI_DMT_CHKSUM:
667         case ACPI_DMT_SPACEID:
668         case ACPI_DMT_ACCWIDTH:
669         case ACPI_DMT_IVRS:
670         case ACPI_DMT_MADT:
671         case ACPI_DMT_PMTT:
672         case ACPI_DMT_SRAT:
673         case ACPI_DMT_ASF:
674         case ACPI_DMT_HESTNTYP:
675         case ACPI_DMT_FADTPM:
676         case ACPI_DMT_EINJACT:
677         case ACPI_DMT_EINJINST:
678         case ACPI_DMT_ERSTACT:
679         case ACPI_DMT_ERSTINST:
680             ByteLength = 1;
681             break;
682         case ACPI_DMT_UINT16:
683         case ACPI_DMT_DMAR:
684         case ACPI_DMT_HEST:
685             ByteLength = 2;
686             break;
687         case ACPI_DMT_UINT24:
688             ByteLength = 3;
689             break;
690         case ACPI_DMT_UINT32:
691         case ACPI_DMT_NAME4:
692         case ACPI_DMT_SIG:
693         case ACPI_DMT_SLIC:
694             ByteLength = 4;
695             break;
696         case ACPI_DMT_UINT40:
697             ByteLength = 5;
698             break;
699         case ACPI_DMT_UINT48:
700         case ACPI_DMT_NAME6:
701             ByteLength = 6;
702             break;
703         case ACPI_DMT_UINT56:
704         case ACPI_DMT_BUF7:
705             ByteLength = 7;
706             break;
707         case ACPI_DMT_UINT64:
708         case ACPI_DMT_NAME8:
709             ByteLength = 8;
710             break;
711         case ACPI_DMT_BUF16:
712         case ACPI_DMT_UUID:
713             ByteLength = 16;
714             break;
715         case ACPI_DMT_BUF128:
716             ByteLength = 128;
717             break;
718         case ACPI_DMT_STRING:
719             ByteLength = ACPI_STRLEN (ACPI_CAST_PTR (char, Target)) + 1;
720             break;
721         case ACPI_DMT_GAS:
722             if (!LastOutputBlankLine)
723             {
724                 AcpiOsPrintf ("\n");
725                 LastOutputBlankLine = TRUE;
726             }
727             ByteLength = sizeof (ACPI_GENERIC_ADDRESS);
728             break;
729         case ACPI_DMT_HESTNTFY:
730             if (!LastOutputBlankLine)
731             {
732                 AcpiOsPrintf ("\n");
733                 LastOutputBlankLine = TRUE;
734             }
735             ByteLength = sizeof (ACPI_HEST_NOTIFY);
736             break;
737         default:
738             ByteLength = 0;
739             break;
740         }
741 
742         if (CurrentOffset + ByteLength > TableLength)
743         {
744             AcpiOsPrintf ("**** ACPI table terminates in the middle of a data structure!\n");
745             return (AE_BAD_DATA);
746         }
747 
748         if (Info->Opcode == ACPI_DMT_EXTRA_TEXT)
749         {
750             AcpiOsPrintf ("%s", Info->Name);
751             continue;
752         }
753 
754         /* Start a new line and decode the opcode */
755 
756         AcpiDmLineHeader (CurrentOffset, ByteLength, Info->Name);
757 
758         switch (Info->Opcode)
759         {
760         /* Single-bit Flag fields. Note: Opcode is the bit position */
761 
762         case ACPI_DMT_FLAG0:
763         case ACPI_DMT_FLAG1:
764         case ACPI_DMT_FLAG2:
765         case ACPI_DMT_FLAG3:
766         case ACPI_DMT_FLAG4:
767         case ACPI_DMT_FLAG5:
768         case ACPI_DMT_FLAG6:
769         case ACPI_DMT_FLAG7:
770 
771             AcpiOsPrintf ("%1.1X\n", (*Target >> Info->Opcode) & 0x01);
772             break;
773 
774         /* 2-bit Flag fields */
775 
776         case ACPI_DMT_FLAGS0:
777 
778             AcpiOsPrintf ("%1.1X\n", *Target & 0x03);
779             break;
780 
781         case ACPI_DMT_FLAGS1:
782 
783             AcpiOsPrintf ("%1.1X\n", (*Target >> 1) & 0x03);
784             break;
785 
786         case ACPI_DMT_FLAGS2:
787 
788             AcpiOsPrintf ("%1.1X\n", (*Target >> 2) & 0x03);
789             break;
790 
791         case ACPI_DMT_FLAGS4:
792 
793             AcpiOsPrintf ("%1.1X\n", (*Target >> 4) & 0x03);
794             break;
795 
796         /* Integer Data Types */
797 
798         case ACPI_DMT_UINT8:
799         case ACPI_DMT_UINT16:
800         case ACPI_DMT_UINT24:
801         case ACPI_DMT_UINT32:
802         case ACPI_DMT_UINT40:
803         case ACPI_DMT_UINT48:
804         case ACPI_DMT_UINT56:
805         case ACPI_DMT_UINT64:
806             /*
807              * Dump bytes - high byte first, low byte last.
808              * Note: All ACPI tables are little-endian.
809              */
810             for (Temp8 = (UINT8) ByteLength; Temp8 > 0; Temp8--)
811             {
812                 AcpiOsPrintf ("%2.2X", Target[Temp8 - 1]);
813             }
814             AcpiOsPrintf ("\n");
815             break;
816 
817         case ACPI_DMT_BUF7:
818         case ACPI_DMT_BUF16:
819         case ACPI_DMT_BUF128:
820 
821             /*
822              * Buffer: Size depends on the opcode and was set above.
823              * Each hex byte is separated with a space.
824              * Multiple lines are separated by line continuation char.
825              */
826             for (Temp16 = 0; Temp16 < ByteLength; Temp16++)
827             {
828                 AcpiOsPrintf ("%2.2X", Target[Temp16]);
829                 if ((UINT32) (Temp16 + 1) < ByteLength)
830                 {
831                     if ((Temp16 > 0) && (!((Temp16+1) % 16)))
832                     {
833                         AcpiOsPrintf (" \\\n"); /* Line continuation */
834                         AcpiDmLineHeader (0, 0, NULL);
835                     }
836                     else
837                     {
838                         AcpiOsPrintf (" ");
839                     }
840                 }
841             }
842             AcpiOsPrintf ("\n");
843             break;
844 
845         case ACPI_DMT_UUID:
846 
847             /* Convert 16-byte UUID buffer to 36-byte formatted UUID string */
848 
849             (void) AuConvertUuidToString ((char *) Target, MsgBuffer);
850 
851             AcpiOsPrintf ("%s\n", MsgBuffer);
852             break;
853 
854         case ACPI_DMT_STRING:
855 
856             AcpiOsPrintf ("\"%s\"\n", ACPI_CAST_PTR (char, Target));
857             break;
858 
859         /* Fixed length ASCII name fields */
860 
861         case ACPI_DMT_SIG:
862 
863             AcpiDmCheckAscii (Target, RepairedName, 4);
864             AcpiOsPrintf ("\"%.4s\"    ", RepairedName);
865             TableData = AcpiDmGetTableData (ACPI_CAST_PTR (char, Target));
866             if (TableData)
867             {
868                 AcpiOsPrintf (STRING_FORMAT, TableData->Name);
869             }
870             else
871             {
872                 AcpiOsPrintf ("\n");
873             }
874             break;
875 
876         case ACPI_DMT_NAME4:
877 
878             AcpiDmCheckAscii (Target, RepairedName, 4);
879             AcpiOsPrintf ("\"%.4s\"\n", RepairedName);
880             break;
881 
882         case ACPI_DMT_NAME6:
883 
884             AcpiDmCheckAscii (Target, RepairedName, 6);
885             AcpiOsPrintf ("\"%.6s\"\n", RepairedName);
886             break;
887 
888         case ACPI_DMT_NAME8:
889 
890             AcpiDmCheckAscii (Target, RepairedName, 8);
891             AcpiOsPrintf ("\"%.8s\"\n", RepairedName);
892             break;
893 
894         /* Special Data Types */
895 
896         case ACPI_DMT_CHKSUM:
897 
898             /* Checksum, display and validate */
899 
900             AcpiOsPrintf ("%2.2X", *Target);
901             Temp8 = AcpiDmGenerateChecksum (Table,
902                         ACPI_CAST_PTR (ACPI_TABLE_HEADER, Table)->Length,
903                         ACPI_CAST_PTR (ACPI_TABLE_HEADER, Table)->Checksum);
904             if (Temp8 != ACPI_CAST_PTR (ACPI_TABLE_HEADER, Table)->Checksum)
905             {
906                 AcpiOsPrintf (
907                     "     /* Incorrect checksum, should be %2.2X */", Temp8);
908             }
909             AcpiOsPrintf ("\n");
910             break;
911 
912         case ACPI_DMT_SPACEID:
913 
914             /* Address Space ID */
915 
916             AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiUtGetRegionName (*Target));
917             break;
918 
919         case ACPI_DMT_ACCWIDTH:
920 
921             /* Encoded Access Width */
922 
923             Temp8 = *Target;
924             if (Temp8 > ACPI_GAS_WIDTH_RESERVED)
925             {
926                 Temp8 = ACPI_GAS_WIDTH_RESERVED;
927             }
928 
929             AcpiOsPrintf (UINT8_FORMAT, Temp8, AcpiDmGasAccessWidth[Temp8]);
930             break;
931 
932         case ACPI_DMT_GAS:
933 
934             /* Generic Address Structure */
935 
936             AcpiOsPrintf (STRING_FORMAT, "Generic Address Structure");
937             AcpiDmDumpTable (TableLength, CurrentOffset, Target,
938                 sizeof (ACPI_GENERIC_ADDRESS), AcpiDmTableInfoGas);
939             AcpiOsPrintf ("\n");
940             LastOutputBlankLine = TRUE;
941             break;
942 
943         case ACPI_DMT_ASF:
944 
945             /* ASF subtable types */
946 
947             Temp16 = (UINT16) ((*Target) & 0x7F);  /* Top bit can be zero or one */
948             if (Temp16 > ACPI_ASF_TYPE_RESERVED)
949             {
950                 Temp16 = ACPI_ASF_TYPE_RESERVED;
951             }
952 
953             AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmAsfSubnames[Temp16]);
954             break;
955 
956         case ACPI_DMT_DMAR:
957 
958             /* DMAR subtable types */
959 
960             Temp16 = ACPI_GET16 (Target);
961             if (Temp16 > ACPI_DMAR_TYPE_RESERVED)
962             {
963                 Temp16 = ACPI_DMAR_TYPE_RESERVED;
964             }
965 
966             AcpiOsPrintf (UINT16_FORMAT, ACPI_GET16 (Target), AcpiDmDmarSubnames[Temp16]);
967             break;
968 
969         case ACPI_DMT_EINJACT:
970 
971             /* EINJ Action types */
972 
973             Temp8 = *Target;
974             if (Temp8 > ACPI_EINJ_ACTION_RESERVED)
975             {
976                 Temp8 = ACPI_EINJ_ACTION_RESERVED;
977             }
978 
979             AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmEinjActions[Temp8]);
980             break;
981 
982         case ACPI_DMT_EINJINST:
983 
984             /* EINJ Instruction types */
985 
986             Temp8 = *Target;
987             if (Temp8 > ACPI_EINJ_INSTRUCTION_RESERVED)
988             {
989                 Temp8 = ACPI_EINJ_INSTRUCTION_RESERVED;
990             }
991 
992             AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmEinjInstructions[Temp8]);
993             break;
994 
995         case ACPI_DMT_ERSTACT:
996 
997             /* ERST Action types */
998 
999             Temp8 = *Target;
1000             if (Temp8 > ACPI_ERST_ACTION_RESERVED)
1001             {
1002                 Temp8 = ACPI_ERST_ACTION_RESERVED;
1003             }
1004 
1005             AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmErstActions[Temp8]);
1006             break;
1007 
1008         case ACPI_DMT_ERSTINST:
1009 
1010             /* ERST Instruction types */
1011 
1012             Temp8 = *Target;
1013             if (Temp8 > ACPI_ERST_INSTRUCTION_RESERVED)
1014             {
1015                 Temp8 = ACPI_ERST_INSTRUCTION_RESERVED;
1016             }
1017 
1018             AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmErstInstructions[Temp8]);
1019             break;
1020 
1021         case ACPI_DMT_HEST:
1022 
1023             /* HEST subtable types */
1024 
1025             Temp16 = ACPI_GET16 (Target);
1026             if (Temp16 > ACPI_HEST_TYPE_RESERVED)
1027             {
1028                 Temp16 = ACPI_HEST_TYPE_RESERVED;
1029             }
1030 
1031             AcpiOsPrintf (UINT16_FORMAT, ACPI_GET16 (Target), AcpiDmHestSubnames[Temp16]);
1032             break;
1033 
1034         case ACPI_DMT_HESTNTFY:
1035 
1036             AcpiOsPrintf (STRING_FORMAT, "Hardware Error Notification Structure");
1037             AcpiDmDumpTable (TableLength, CurrentOffset, Target,
1038                 sizeof (ACPI_HEST_NOTIFY), AcpiDmTableInfoHestNotify);
1039             AcpiOsPrintf ("\n");
1040             LastOutputBlankLine = TRUE;
1041             break;
1042 
1043         case ACPI_DMT_HESTNTYP:
1044 
1045             /* HEST Notify types */
1046 
1047             Temp8 = *Target;
1048             if (Temp8 > ACPI_HEST_NOTIFY_RESERVED)
1049             {
1050                 Temp8 = ACPI_HEST_NOTIFY_RESERVED;
1051             }
1052 
1053             AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmHestNotifySubnames[Temp8]);
1054             break;
1055 
1056         case ACPI_DMT_MADT:
1057 
1058             /* MADT subtable types */
1059 
1060             Temp8 = *Target;
1061             if (Temp8 > ACPI_MADT_TYPE_RESERVED)
1062             {
1063                 Temp8 = ACPI_MADT_TYPE_RESERVED;
1064             }
1065 
1066             AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmMadtSubnames[Temp8]);
1067             break;
1068 
1069         case ACPI_DMT_PMTT:
1070 
1071             /* PMTT subtable types */
1072 
1073             Temp8 = *Target;
1074             if (Temp8 > ACPI_PMTT_TYPE_RESERVED)
1075             {
1076                 Temp8 = ACPI_PMTT_TYPE_RESERVED;
1077             }
1078 
1079             AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmPmttSubnames[Temp8]);
1080             break;
1081 
1082         case ACPI_DMT_SLIC:
1083 
1084             /* SLIC subtable types */
1085 
1086             Temp8 = *Target;
1087             if (Temp8 > ACPI_SLIC_TYPE_RESERVED)
1088             {
1089                 Temp8 = ACPI_SLIC_TYPE_RESERVED;
1090             }
1091 
1092             AcpiOsPrintf (UINT32_FORMAT, *Target, AcpiDmSlicSubnames[Temp8]);
1093             break;
1094 
1095         case ACPI_DMT_SRAT:
1096 
1097             /* SRAT subtable types */
1098 
1099             Temp8 = *Target;
1100             if (Temp8 > ACPI_SRAT_TYPE_RESERVED)
1101             {
1102                 Temp8 = ACPI_SRAT_TYPE_RESERVED;
1103             }
1104 
1105             AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmSratSubnames[Temp8]);
1106             break;
1107 
1108         case ACPI_DMT_FADTPM:
1109 
1110             /* FADT Preferred PM Profile names */
1111 
1112             Temp8 = *Target;
1113             if (Temp8 > ACPI_FADT_PM_RESERVED)
1114             {
1115                 Temp8 = ACPI_FADT_PM_RESERVED;
1116             }
1117 
1118             AcpiOsPrintf (UINT8_FORMAT, *Target, AcpiDmFadtProfiles[Temp8]);
1119             break;
1120 
1121         case ACPI_DMT_IVRS:
1122 
1123             /* IVRS subtable types */
1124 
1125             Temp8 = *Target;
1126             switch (Temp8)
1127             {
1128             case ACPI_IVRS_TYPE_HARDWARE:
1129                 Name = AcpiDmIvrsSubnames[0];
1130                 break;
1131 
1132             case ACPI_IVRS_TYPE_MEMORY1:
1133             case ACPI_IVRS_TYPE_MEMORY2:
1134             case ACPI_IVRS_TYPE_MEMORY3:
1135                 Name = AcpiDmIvrsSubnames[1];
1136                 break;
1137 
1138             default:
1139                 Name = AcpiDmIvrsSubnames[2];
1140                 break;
1141             }
1142 
1143             AcpiOsPrintf (UINT8_FORMAT, *Target, Name);
1144             break;
1145 
1146         case ACPI_DMT_EXIT:
1147             return (AE_OK);
1148 
1149         default:
1150             ACPI_ERROR ((AE_INFO,
1151                 "**** Invalid table opcode [0x%X] ****\n", Info->Opcode));
1152             return (AE_SUPPORT);
1153         }
1154     }
1155 
1156     if (TableOffset && !SubtableLength)
1157     {
1158         /* If this table is not the main table, subtable must have valid length */
1159 
1160         AcpiOsPrintf ("Invalid zero length subtable\n");
1161         return (AE_BAD_DATA);
1162     }
1163 
1164     return (AE_OK);
1165 }
1166 
1167 
1168 /*******************************************************************************
1169  *
1170  * FUNCTION:    AcpiDmCheckAscii
1171  *
1172  * PARAMETERS:  Name                - Ascii string
1173  *              Count               - Number of characters to check
1174  *
1175  * RETURN:      None
1176  *
1177  * DESCRIPTION: Ensure that the requested number of characters are printable
1178  *              Ascii characters. Sets non-printable and null chars to <space>.
1179  *
1180  ******************************************************************************/
1181 
1182 static void
1183 AcpiDmCheckAscii (
1184     UINT8                   *Name,
1185     char                    *RepairedName,
1186     UINT32                  Count)
1187 {
1188     UINT32                  i;
1189 
1190 
1191     for (i = 0; i < Count; i++)
1192     {
1193         RepairedName[i] = (char) Name[i];
1194 
1195         if (!Name[i])
1196         {
1197             return;
1198         }
1199         if (!isprint (Name[i]))
1200         {
1201             RepairedName[i] = ' ';
1202         }
1203     }
1204 }
1205