1 /******************************************************************************
2 *
3 * Module Name: dmtbdump - Dump ACPI data tables that contain no AML code
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2022, 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
AcpiDmDumpBuffer(void * Table,UINT32 BufferOffset,UINT32 Length,UINT32 AbsoluteOffset,char * Header)82 AcpiDmDumpBuffer (
83 void *Table,
84 UINT32 BufferOffset,
85 UINT32 Length,
86 UINT32 AbsoluteOffset,
87 char *Header)
88 {
89 UINT8 *Buffer;
90 UINT32 i;
91
92
93 if (!Length)
94 {
95 return;
96 }
97
98 Buffer = ACPI_CAST_PTR (UINT8, Table) + BufferOffset;
99 i = 0;
100
101 while (i < Length)
102 {
103 if (!(i % 16))
104 {
105 /* Insert a backslash - line continuation character */
106
107 if (Length > 16)
108 {
109 AcpiOsPrintf ("\\\n ");
110 }
111 }
112
113 AcpiOsPrintf ("%.02X ", *Buffer);
114 i++;
115 Buffer++;
116 AbsoluteOffset++;
117 }
118
119 AcpiOsPrintf ("\n");
120 }
121
122
123 /*******************************************************************************
124 *
125 * FUNCTION: AcpiDmDumpUnicode
126 *
127 * PARAMETERS: Table - ACPI Table or subtable
128 * BufferOffset - Offset of buffer from Table above
129 * ByteLength - Length of the buffer
130 *
131 * RETURN: None
132 *
133 * DESCRIPTION: Validate and dump the contents of a buffer that contains
134 * unicode data. The output is a standard ASCII string. If it
135 * appears that the data is not unicode, the buffer is dumped
136 * as hex characters.
137 *
138 ******************************************************************************/
139
140 void
AcpiDmDumpUnicode(void * Table,UINT32 BufferOffset,UINT32 ByteLength)141 AcpiDmDumpUnicode (
142 void *Table,
143 UINT32 BufferOffset,
144 UINT32 ByteLength)
145 {
146 UINT8 *Buffer;
147 UINT32 Length;
148 UINT32 i;
149
150
151 Buffer = ((UINT8 *) Table) + BufferOffset;
152 Length = ByteLength - 2; /* Last two bytes are the null terminator */
153
154 /* Ensure all low bytes are entirely printable ASCII */
155
156 for (i = 0; i < Length; i += 2)
157 {
158 if (!isprint (Buffer[i]))
159 {
160 goto DumpRawBuffer;
161 }
162 }
163
164 /* Ensure all high bytes are zero */
165
166 for (i = 1; i < Length; i += 2)
167 {
168 if (Buffer[i])
169 {
170 goto DumpRawBuffer;
171 }
172 }
173
174 /* Dump the buffer as a normal string */
175
176 AcpiOsPrintf ("\"");
177 for (i = 0; i < Length; i += 2)
178 {
179 AcpiOsPrintf ("%c", Buffer[i]);
180 }
181
182 AcpiOsPrintf ("\"\n");
183 return;
184
185 DumpRawBuffer:
186 AcpiDmDumpBuffer (Table, BufferOffset, ByteLength,
187 BufferOffset, NULL);
188 AcpiOsPrintf ("\n");
189 }
190
191
192 /*******************************************************************************
193 *
194 * FUNCTION: AcpiDmDumpRsdp
195 *
196 * PARAMETERS: Table - A RSDP
197 *
198 * RETURN: Length of the table (there is not always a length field,
199 * use revision or length if available (ACPI 2.0+))
200 *
201 * DESCRIPTION: Format the contents of a RSDP
202 *
203 ******************************************************************************/
204
205 UINT32
AcpiDmDumpRsdp(ACPI_TABLE_HEADER * Table)206 AcpiDmDumpRsdp (
207 ACPI_TABLE_HEADER *Table)
208 {
209 ACPI_TABLE_RSDP *Rsdp = ACPI_CAST_PTR (ACPI_TABLE_RSDP, Table);
210 UINT32 Length = sizeof (ACPI_RSDP_COMMON);
211 UINT8 Checksum;
212 ACPI_STATUS Status;
213
214
215 /* Dump the common ACPI 1.0 portion */
216
217 Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp1);
218 if (ACPI_FAILURE (Status))
219 {
220 return (Length);
221 }
222
223 /* Validate the first checksum */
224
225 Checksum = AcpiUtGenerateChecksum (Rsdp, sizeof (ACPI_RSDP_COMMON),
226 Rsdp->Checksum);
227 if (Checksum != Rsdp->Checksum)
228 {
229 AcpiOsPrintf ("/* Incorrect Checksum above, should be 0x%2.2X */\n",
230 Checksum);
231 }
232
233 /* The RSDP for ACPI 2.0+ contains more data and has a Length field */
234
235 if (Rsdp->Revision > 0)
236 {
237 Length = Rsdp->Length;
238 Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp2);
239 if (ACPI_FAILURE (Status))
240 {
241 return (Length);
242 }
243
244 /* Validate the extended checksum over entire RSDP */
245
246 Checksum = AcpiUtGenerateChecksum (Rsdp, sizeof (ACPI_TABLE_RSDP),
247 Rsdp->ExtendedChecksum);
248 if (Checksum != Rsdp->ExtendedChecksum)
249 {
250 AcpiOsPrintf (
251 "/* Incorrect Extended Checksum above, should be 0x%2.2X */\n",
252 Checksum);
253 }
254 }
255
256 return (Length);
257 }
258
259
260 /*******************************************************************************
261 *
262 * FUNCTION: AcpiDmDumpRsdt
263 *
264 * PARAMETERS: Table - A RSDT
265 *
266 * RETURN: None
267 *
268 * DESCRIPTION: Format the contents of a RSDT
269 *
270 ******************************************************************************/
271
272 void
AcpiDmDumpRsdt(ACPI_TABLE_HEADER * Table)273 AcpiDmDumpRsdt (
274 ACPI_TABLE_HEADER *Table)
275 {
276 UINT32 *Array;
277 UINT32 Entries;
278 UINT32 Offset;
279 UINT32 i;
280
281
282 /* Point to start of table pointer array */
283
284 Array = ACPI_CAST_PTR (ACPI_TABLE_RSDT, Table)->TableOffsetEntry;
285 Offset = sizeof (ACPI_TABLE_HEADER);
286
287 /* RSDT uses 32-bit pointers */
288
289 Entries = (Table->Length - sizeof (ACPI_TABLE_HEADER)) / sizeof (UINT32);
290
291 for (i = 0; i < Entries; i++)
292 {
293 AcpiDmLineHeader2 (Offset, sizeof (UINT32), "ACPI Table Address", i);
294 AcpiOsPrintf ("%8.8X\n", Array[i]);
295 Offset += sizeof (UINT32);
296 }
297 }
298
299
300 /*******************************************************************************
301 *
302 * FUNCTION: AcpiDmDumpXsdt
303 *
304 * PARAMETERS: Table - A XSDT
305 *
306 * RETURN: None
307 *
308 * DESCRIPTION: Format the contents of a XSDT
309 *
310 ******************************************************************************/
311
312 void
AcpiDmDumpXsdt(ACPI_TABLE_HEADER * Table)313 AcpiDmDumpXsdt (
314 ACPI_TABLE_HEADER *Table)
315 {
316 UINT64 *Array;
317 UINT32 Entries;
318 UINT32 Offset;
319 UINT32 i;
320
321
322 /* Point to start of table pointer array */
323
324 Array = ACPI_CAST_PTR (ACPI_TABLE_XSDT, Table)->TableOffsetEntry;
325 Offset = sizeof (ACPI_TABLE_HEADER);
326
327 /* XSDT uses 64-bit pointers */
328
329 Entries = (Table->Length - sizeof (ACPI_TABLE_HEADER)) / sizeof (UINT64);
330
331 for (i = 0; i < Entries; i++)
332 {
333 AcpiDmLineHeader2 (Offset, sizeof (UINT64), "ACPI Table Address", i);
334 AcpiOsPrintf ("%8.8X%8.8X\n", ACPI_FORMAT_UINT64 (Array[i]));
335 Offset += sizeof (UINT64);
336 }
337 }
338
339
340 /*******************************************************************************
341 *
342 * FUNCTION: AcpiDmDumpFadt
343 *
344 * PARAMETERS: Table - A FADT
345 *
346 * RETURN: None
347 *
348 * DESCRIPTION: Format the contents of a FADT
349 *
350 * NOTE: We cannot depend on the FADT version to indicate the actual
351 * contents of the FADT because of BIOS bugs. The table length
352 * is the only reliable indicator.
353 *
354 ******************************************************************************/
355
356 void
AcpiDmDumpFadt(ACPI_TABLE_HEADER * Table)357 AcpiDmDumpFadt (
358 ACPI_TABLE_HEADER *Table)
359 {
360 ACPI_STATUS Status;
361
362
363 /* Always dump the minimum FADT revision 1 fields (ACPI 1.0) */
364
365 Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
366 AcpiDmTableInfoFadt1);
367 if (ACPI_FAILURE (Status))
368 {
369 return;
370 }
371
372 /* Check for FADT revision 2 fields (ACPI 1.0B MS extensions) */
373
374 if ((Table->Length > ACPI_FADT_V1_SIZE) &&
375 (Table->Length <= ACPI_FADT_V2_SIZE))
376 {
377 Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
378 AcpiDmTableInfoFadt2);
379 if (ACPI_FAILURE (Status))
380 {
381 return;
382 }
383 }
384
385 /* Check for FADT revision 3/4 fields and up (ACPI 2.0+ extended data) */
386
387 else if (Table->Length > ACPI_FADT_V2_SIZE)
388 {
389 Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
390 AcpiDmTableInfoFadt3);
391 if (ACPI_FAILURE (Status))
392 {
393 return;
394 }
395
396 /* Check for FADT revision 5 fields and up (ACPI 5.0+) */
397
398 if (Table->Length > ACPI_FADT_V3_SIZE)
399 {
400 Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
401 AcpiDmTableInfoFadt5);
402 if (ACPI_FAILURE (Status))
403 {
404 return;
405 }
406 }
407
408 /* Check for FADT revision 6 fields and up (ACPI 6.0+) */
409
410 if (Table->Length > ACPI_FADT_V3_SIZE)
411 {
412 Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
413 AcpiDmTableInfoFadt6);
414 if (ACPI_FAILURE (Status))
415 {
416 return;
417 }
418 }
419 }
420
421 /* Validate various fields in the FADT, including length */
422
423 AcpiTbCreateLocalFadt (Table, Table->Length);
424
425 /* Validate FADT length against the revision */
426
427 AcpiDmValidateFadtLength (Table->Revision, Table->Length);
428 }
429
430
431 /*******************************************************************************
432 *
433 * FUNCTION: AcpiDmValidateFadtLength
434 *
435 * PARAMETERS: Revision - FADT revision (Header->Revision)
436 * Length - FADT length (Header->Length
437 *
438 * RETURN: None
439 *
440 * DESCRIPTION: Check the FADT revision against the expected table length for
441 * that revision. Issue a warning if the length is not what was
442 * expected. This seems to be such a common BIOS bug that the
443 * FADT revision has been rendered virtually meaningless.
444 *
445 ******************************************************************************/
446
447 static void
AcpiDmValidateFadtLength(UINT32 Revision,UINT32 Length)448 AcpiDmValidateFadtLength (
449 UINT32 Revision,
450 UINT32 Length)
451 {
452 UINT32 ExpectedLength;
453
454
455 switch (Revision)
456 {
457 case 0:
458
459 AcpiOsPrintf ("// ACPI Warning: Invalid FADT revision: 0\n");
460 return;
461
462 case 1:
463
464 ExpectedLength = ACPI_FADT_V1_SIZE;
465 break;
466
467 case 2:
468
469 ExpectedLength = ACPI_FADT_V2_SIZE;
470 break;
471
472 case 3:
473 case 4:
474
475 ExpectedLength = ACPI_FADT_V3_SIZE;
476 break;
477
478 case 5:
479
480 ExpectedLength = ACPI_FADT_V5_SIZE;
481 break;
482
483 default:
484
485 return;
486 }
487
488 if (Length == ExpectedLength)
489 {
490 return;
491 }
492
493 AcpiOsPrintf (
494 "\n// ACPI Warning: FADT revision %X does not match length: "
495 "found %X expected %X\n",
496 Revision, Length, ExpectedLength);
497 }
498