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