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