dmtbdump.c revision 1.17 1 /******************************************************************************
2 *
3 * Module Name: dmtbdump - Dump ACPI data tables that contain no AML code
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2023, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acdisasm.h"
47 #include "actables.h"
48
49 /* This module used for application-level code only */
50
51 #define _COMPONENT ACPI_CA_DISASSEMBLER
52 ACPI_MODULE_NAME ("dmtbdump")
53
54
55 /* Local prototypes */
56
57 static void
58 AcpiDmValidateFadtLength (
59 UINT32 Revision,
60 UINT32 Length);
61
62
63 /*******************************************************************************
64 *
65 * FUNCTION: AcpiDmDumpBuffer
66 *
67 * PARAMETERS: Table - ACPI Table or subtable
68 * BufferOffset - Offset of buffer from Table above
69 * Length - Length of the buffer
70 * AbsoluteOffset - Offset of buffer in the main ACPI table
71 * Header - Name of the buffer field (printed on the
72 * first line only.)
73 *
74 * RETURN: None
75 *
76 * DESCRIPTION: Format the contents of an arbitrary length data buffer (in the
77 * disassembler output format.)
78 *
79 ******************************************************************************/
80
81 void
82 AcpiDmDumpBuffer (
83 void *Table,
84 UINT32 BufferOffset,
85 UINT32 Length,
86 UINT32 AbsoluteOffset,
87 char *Header)
88 {
89 UINT8 *Buffer;
90 UINT8 BufChar;
91 UINT32 i;
92 UINT32 j;
93
94
95 if (!Length)
96 {
97 return;
98 }
99
100 Buffer = ACPI_CAST_PTR (UINT8, Table) + BufferOffset;
101 i = 0;
102
103 while (i < Length)
104 {
105 if ((Length > 16) && (i != 0))
106 {
107 if ((Length - i) < 16)
108 AcpiOsPrintf ("\n/* %3.3Xh %4.4u %3u */ ", AbsoluteOffset, AbsoluteOffset, Length - i);
109 else
110 AcpiOsPrintf ("\n/* %3.3Xh %4.4u 16 */ ", AbsoluteOffset, AbsoluteOffset);
111 }
112 AbsoluteOffset += 16;
113
114 /* Emit the raw data bytes*/
115
116 for (j = 0; j < 16; j++)
117 {
118 if (i + j >= Length)
119 {
120 /* Dump fill spaces */
121
122 AcpiOsPrintf ("%*s", (48 - (3 * (Length -i))), " ");
123 break;
124 }
125 AcpiOsPrintf ("%.02X ", Buffer[(ACPI_SIZE) i + j]);
126 }
127
128 /* Emit the ASCII equivalent to the raw data bytes */
129
130 for (j = 0; j < 16; j++)
131 {
132 if (i + j >= Length)
133 {
134 AcpiOsPrintf (" */\\\n");
135 return;
136 }
137
138 /*
139 * Add comment characters so rest of line is ignored when
140 * compiled
141 */
142 if (j == 0)
143 {
144 AcpiOsPrintf ("/* ");
145 }
146
147 BufChar = Buffer[(ACPI_SIZE) i + j];
148 if (isprint (BufChar))
149 {
150 AcpiOsPrintf ("%c", BufChar);
151 }
152 else
153 {
154 AcpiOsPrintf (".");
155 }
156 }
157
158 /* Done with that line. */
159 /* Close the comment and insert a backslash - line continuation character */
160
161 AcpiOsPrintf (" */\\");
162
163 i += 16; /* Point to next line */
164 }
165
166 AcpiOsPrintf ("\n");
167 }
168
169
170 /*******************************************************************************
171 *
172 * FUNCTION: AcpiDmDumpUnicode
173 *
174 * PARAMETERS: Table - ACPI Table or subtable
175 * BufferOffset - Offset of buffer from Table above
176 * ByteLength - Length of the buffer
177 *
178 * RETURN: None
179 *
180 * DESCRIPTION: Validate and dump the contents of a buffer that contains
181 * unicode data. The output is a standard ASCII string. If it
182 * appears that the data is not unicode, the buffer is dumped
183 * as hex characters.
184 *
185 ******************************************************************************/
186
187 void
188 AcpiDmDumpUnicode (
189 void *Table,
190 UINT32 BufferOffset,
191 UINT32 ByteLength)
192 {
193 UINT8 *Buffer;
194 UINT32 Length;
195 UINT32 i;
196
197
198 Buffer = ((UINT8 *) Table) + BufferOffset;
199 Length = ByteLength - 2; /* Last two bytes are the null terminator */
200
201 /* Ensure all low bytes are entirely printable ASCII */
202
203 for (i = 0; i < Length; i += 2)
204 {
205 if (!isprint (Buffer[i]))
206 {
207 goto DumpRawBuffer;
208 }
209 }
210
211 /* Ensure all high bytes are zero */
212
213 for (i = 1; i < Length; i += 2)
214 {
215 if (Buffer[i])
216 {
217 goto DumpRawBuffer;
218 }
219 }
220
221 /* Dump the buffer as a normal string */
222
223 AcpiOsPrintf ("\"");
224 for (i = 0; i < Length; i += 2)
225 {
226 AcpiOsPrintf ("%c", Buffer[i]);
227 }
228
229 AcpiOsPrintf ("\"\n");
230 return;
231
232 DumpRawBuffer:
233 AcpiDmDumpBuffer (Table, BufferOffset, ByteLength,
234 BufferOffset, NULL);
235 AcpiOsPrintf ("\n");
236 }
237
238
239 /*******************************************************************************
240 *
241 * FUNCTION: AcpiDmDumpRsdp
242 *
243 * PARAMETERS: Table - A RSDP
244 *
245 * RETURN: Length of the table (there is not always a length field,
246 * use revision or length if available (ACPI 2.0+))
247 *
248 * DESCRIPTION: Format the contents of a RSDP
249 *
250 ******************************************************************************/
251
252 UINT32
253 AcpiDmDumpRsdp (
254 ACPI_TABLE_HEADER *Table)
255 {
256 ACPI_TABLE_RSDP *Rsdp = ACPI_CAST_PTR (ACPI_TABLE_RSDP, Table);
257 UINT32 Length = sizeof (ACPI_RSDP_COMMON);
258 UINT8 Checksum;
259 ACPI_STATUS Status;
260
261
262 /* Dump the common ACPI 1.0 portion */
263
264 Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp1);
265 if (ACPI_FAILURE (Status))
266 {
267 return (Length);
268 }
269
270 /* Validate the first checksum */
271
272 Checksum = AcpiUtGenerateChecksum (Rsdp, sizeof (ACPI_RSDP_COMMON),
273 Rsdp->Checksum);
274 if (Checksum != Rsdp->Checksum)
275 {
276 AcpiOsPrintf ("/* Incorrect Checksum above, should be 0x%2.2X */\n",
277 Checksum);
278 }
279
280 /* The RSDP for ACPI 2.0+ contains more data and has a Length field */
281
282 if (Rsdp->Revision > 0)
283 {
284 Length = Rsdp->Length;
285 Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp2);
286 if (ACPI_FAILURE (Status))
287 {
288 return (Length);
289 }
290
291 /* Validate the extended checksum over entire RSDP */
292
293 Checksum = AcpiUtGenerateChecksum (Rsdp, sizeof (ACPI_TABLE_RSDP),
294 Rsdp->ExtendedChecksum);
295 if (Checksum != Rsdp->ExtendedChecksum)
296 {
297 AcpiOsPrintf (
298 "/* Incorrect Extended Checksum above, should be 0x%2.2X */\n",
299 Checksum);
300 }
301 }
302
303 return (Length);
304 }
305
306
307 /*******************************************************************************
308 *
309 * FUNCTION: AcpiDmDumpRsdt
310 *
311 * PARAMETERS: Table - A RSDT
312 *
313 * RETURN: None
314 *
315 * DESCRIPTION: Format the contents of a RSDT
316 *
317 ******************************************************************************/
318
319 void
320 AcpiDmDumpRsdt (
321 ACPI_TABLE_HEADER *Table)
322 {
323 UINT32 *Array;
324 UINT32 Entries;
325 UINT32 Offset;
326 UINT32 i;
327
328
329 /* Point to start of table pointer array */
330
331 Array = ACPI_CAST_PTR (ACPI_TABLE_RSDT, Table)->TableOffsetEntry;
332 Offset = sizeof (ACPI_TABLE_HEADER);
333
334 /* RSDT uses 32-bit pointers */
335
336 Entries = (Table->Length - sizeof (ACPI_TABLE_HEADER)) / sizeof (UINT32);
337
338 for (i = 0; i < Entries; i++)
339 {
340 AcpiDmLineHeader2 (Offset, sizeof (UINT32), "ACPI Table Address", i);
341 AcpiOsPrintf ("%8.8X\n", Array[i]);
342 Offset += sizeof (UINT32);
343 }
344 }
345
346
347 /*******************************************************************************
348 *
349 * FUNCTION: AcpiDmDumpXsdt
350 *
351 * PARAMETERS: Table - A XSDT
352 *
353 * RETURN: None
354 *
355 * DESCRIPTION: Format the contents of a XSDT
356 *
357 ******************************************************************************/
358
359 void
360 AcpiDmDumpXsdt (
361 ACPI_TABLE_HEADER *Table)
362 {
363 UINT64 *Array;
364 UINT32 Entries;
365 UINT32 Offset;
366 UINT32 i;
367
368
369 /* Point to start of table pointer array */
370
371 Array = ACPI_CAST_PTR (ACPI_TABLE_XSDT, Table)->TableOffsetEntry;
372 Offset = sizeof (ACPI_TABLE_HEADER);
373
374 /* XSDT uses 64-bit pointers */
375
376 Entries = (Table->Length - sizeof (ACPI_TABLE_HEADER)) / sizeof (UINT64);
377
378 for (i = 0; i < Entries; i++)
379 {
380 AcpiDmLineHeader2 (Offset, sizeof (UINT64), "ACPI Table Address", i);
381 AcpiOsPrintf ("%8.8X%8.8X\n", ACPI_FORMAT_UINT64 (Array[i]));
382 Offset += sizeof (UINT64);
383 }
384 }
385
386
387 /*******************************************************************************
388 *
389 * FUNCTION: AcpiDmDumpFadt
390 *
391 * PARAMETERS: Table - A FADT
392 *
393 * RETURN: None
394 *
395 * DESCRIPTION: Format the contents of a FADT
396 *
397 * NOTE: We cannot depend on the FADT version to indicate the actual
398 * contents of the FADT because of BIOS bugs. The table length
399 * is the only reliable indicator.
400 *
401 ******************************************************************************/
402
403 void
404 AcpiDmDumpFadt (
405 ACPI_TABLE_HEADER *Table)
406 {
407 ACPI_STATUS Status;
408
409
410 /* Always dump the minimum FADT revision 1 fields (ACPI 1.0) */
411
412 Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
413 AcpiDmTableInfoFadt1);
414 if (ACPI_FAILURE (Status))
415 {
416 return;
417 }
418
419 /* Check for FADT revision 2 fields (ACPI 1.0B MS extensions) */
420
421 if ((Table->Length > ACPI_FADT_V1_SIZE) &&
422 (Table->Length <= ACPI_FADT_V2_SIZE))
423 {
424 Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
425 AcpiDmTableInfoFadt2);
426 if (ACPI_FAILURE (Status))
427 {
428 return;
429 }
430 }
431
432 /* Check for FADT revision 3/4 fields and up (ACPI 2.0+ extended data) */
433
434 else if (Table->Length > ACPI_FADT_V2_SIZE)
435 {
436 Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
437 AcpiDmTableInfoFadt3);
438 if (ACPI_FAILURE (Status))
439 {
440 return;
441 }
442
443 /* Check for FADT revision 5 fields and up (ACPI 5.0+) */
444
445 if (Table->Length > ACPI_FADT_V3_SIZE)
446 {
447 Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
448 AcpiDmTableInfoFadt5);
449 if (ACPI_FAILURE (Status))
450 {
451 return;
452 }
453 }
454
455 /* Check for FADT revision 6 fields and up (ACPI 6.0+) */
456
457 if (Table->Length > ACPI_FADT_V5_SIZE)
458 {
459 Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
460 AcpiDmTableInfoFadt6);
461 if (ACPI_FAILURE (Status))
462 {
463 return;
464 }
465 }
466 }
467
468 /* Validate various fields in the FADT, including length */
469
470 AcpiTbCreateLocalFadt (Table, Table->Length);
471
472 /* Validate FADT length against the revision */
473
474 AcpiDmValidateFadtLength (Table->Revision, Table->Length);
475 }
476
477
478 /*******************************************************************************
479 *
480 * FUNCTION: AcpiDmValidateFadtLength
481 *
482 * PARAMETERS: Revision - FADT revision (Header->Revision)
483 * Length - FADT length (Header->Length
484 *
485 * RETURN: None
486 *
487 * DESCRIPTION: Check the FADT revision against the expected table length for
488 * that revision. Issue a warning if the length is not what was
489 * expected. This seems to be such a common BIOS bug that the
490 * FADT revision has been rendered virtually meaningless.
491 *
492 ******************************************************************************/
493
494 static void
495 AcpiDmValidateFadtLength (
496 UINT32 Revision,
497 UINT32 Length)
498 {
499 UINT32 ExpectedLength;
500
501
502 switch (Revision)
503 {
504 case 0:
505
506 AcpiOsPrintf ("// ACPI Warning: Invalid FADT revision: 0\n");
507 return;
508
509 case 1:
510
511 ExpectedLength = ACPI_FADT_V1_SIZE;
512 break;
513
514 case 2:
515
516 ExpectedLength = ACPI_FADT_V2_SIZE;
517 break;
518
519 case 3:
520 case 4:
521
522 ExpectedLength = ACPI_FADT_V3_SIZE;
523 break;
524
525 case 5:
526
527 ExpectedLength = ACPI_FADT_V5_SIZE;
528 break;
529
530 case 6:
531
532 ExpectedLength = ACPI_FADT_V6_SIZE;
533 break;
534
535 default:
536
537 return;
538 }
539
540 if (Length == ExpectedLength)
541 {
542 return;
543 }
544
545 AcpiOsPrintf (
546 "\n// ACPI Warning: FADT revision %X does not match length: "
547 "found %X expected %X\n",
548 Revision, Length, ExpectedLength);
549 }
550