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