1 /****************************************************************************** 2 * 3 * Module Name: axutils - Utility functions for acpixtract tool. 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, 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 "acpixtract.h" 45 46 47 /******************************************************************************* 48 * 49 * FUNCTION: AxCheckAscii 50 * 51 * PARAMETERS: Name - Ascii string, at least as long as Count 52 * Count - Number of characters to check 53 * 54 * RETURN: None 55 * 56 * DESCRIPTION: Ensure that the requested number of characters are printable 57 * Ascii characters. Sets non-printable and null chars to <space>. 58 * 59 ******************************************************************************/ 60 61 void 62 AxCheckAscii ( 63 char *Name, 64 int Count) 65 { 66 int i; 67 68 69 for (i = 0; i < Count; i++) 70 { 71 if (!Name[i] || !isprint ((int) Name[i])) 72 { 73 Name[i] = ' '; 74 } 75 } 76 } 77 78 79 /******************************************************************************* 80 * 81 * FUNCTION: AxIsFileAscii 82 * 83 * PARAMETERS: Handle - To open input file 84 * 85 * RETURN: TRUE if file is entirely ASCII and printable 86 * 87 * DESCRIPTION: Verify that the input file is entirely ASCII. 88 * 89 ******************************************************************************/ 90 91 BOOLEAN 92 AxIsFileAscii ( 93 FILE *Handle) 94 { 95 UINT8 Byte; 96 UINT32 Offset = 0; 97 98 99 /* Read the entire file */ 100 101 fseek (Handle, 0, SEEK_SET); 102 while (fread (&Byte, 1, 1, Handle) == 1) 103 { 104 /* 105 * Ignore null characters. Some acpidump-type utilities insert 106 * a few of these, probably a bug in the utility. As long as these 107 * characters are in lines that are tossed (non-data), they 108 * won't cause a problem. 109 */ 110 if (!Byte) 111 { 112 continue; 113 } 114 115 /* Check for an ASCII character */ 116 117 if (!ACPI_IS_ASCII (Byte)) 118 { 119 printf ("Found non-ascii char: %2.2X at file offset %u (0x%X)\n", 120 Byte, Offset, Offset); 121 if (!Gbl_ForceExtraction) 122 { 123 goto ErrorExit; 124 } 125 } 126 127 /* Ensure character is either printable or a "space" char */ 128 129 else if (!isprint (Byte) && !isspace (Byte)) 130 { 131 printf ("Found non-printable char: %2.2X at file offset %u (0x%X)\n", 132 Byte, Offset, Offset); 133 if (!Gbl_ForceExtraction) 134 { 135 goto ErrorExit; 136 } 137 } 138 139 Offset++; 140 } 141 142 /* File is OK (100% ASCII) */ 143 144 fseek (Handle, 0, SEEK_SET); 145 return (TRUE); 146 147 ErrorExit: 148 149 printf ("File appears to be binary " 150 "(contains non-text or non-ascii characters)\n"); 151 fseek (Handle, 0, SEEK_SET); 152 return (FALSE); 153 } 154 155 156 /****************************************************************************** 157 * 158 * FUNCTION: AxIsEmptyLine 159 * 160 * PARAMETERS: Buffer - Line from input file 161 * 162 * RETURN: TRUE if line is empty (zero or more blanks only) 163 * 164 * DESCRIPTION: Determine if an input line is empty. 165 * 166 ******************************************************************************/ 167 168 BOOLEAN 169 AxIsEmptyLine ( 170 char *Buffer) 171 { 172 173 /* Skip all spaces */ 174 175 while (*Buffer == ' ') 176 { 177 Buffer++; 178 } 179 180 /* Line is empty when a Unix or DOS-style line terminator is found. */ 181 182 if ((*Buffer == '\r') || (*Buffer == '\n')) 183 { 184 return (1); 185 } 186 187 return (0); 188 } 189 190 191 /****************************************************************************** 192 * 193 * FUNCTION: AxIsHexDataLine 194 * 195 * PARAMETERS: None 196 * 197 * RETURN: Status. 1 if the table header is valid, 0 otherwise. 198 * 199 * DESCRIPTION: Check for a valid line of hex data of the form: 200 * 201 * 00a0: 0c 00 00 00 03 00 00 00 43 48 41 35 0c 00 00 00 ........CHA5.... 202 * 203 ******************************************************************************/ 204 205 BOOLEAN 206 AxIsHexDataLine ( 207 void) 208 { 209 210 if (AxIsEmptyLine (Gbl_LineBuffer) || 211 (Gbl_LineBuffer[0] != ' ')) 212 { 213 return (FALSE); 214 } 215 216 if (!strstr (Gbl_LineBuffer, ": ")) 217 { 218 /* Not valid data line */ 219 220 return (FALSE); 221 } 222 223 return (TRUE); 224 } 225 226 227 /****************************************************************************** 228 * 229 * FUNCTION: AxIsDataBlockHeader 230 * 231 * PARAMETERS: None 232 * 233 * RETURN: Status. 1 if the table header is valid, 0 otherwise. 234 * 235 * DESCRIPTION: Check if the ACPI table identifier in the input acpidump text 236 * file is valid (of the form: <sig> @ <addr>). 237 * 238 ******************************************************************************/ 239 240 BOOLEAN 241 AxIsDataBlockHeader ( 242 void) 243 { 244 245 /* Ignore lines that are too short to be header lines */ 246 247 if (strlen (Gbl_LineBuffer) < AX_MIN_BLOCK_HEADER_LENGTH) 248 { 249 return (FALSE); 250 } 251 252 /* Ignore empty lines and lines that start with a space */ 253 254 if (AxIsEmptyLine (Gbl_LineBuffer) || 255 (Gbl_LineBuffer[0] == ' ')) 256 { 257 return (FALSE); 258 } 259 260 /* 261 * Ignore lines that are not headers of the form <sig> @ <addr>. 262 * Basically, just look for the '@' symbol, surrounded by spaces. 263 * 264 * Examples of headers that must be supported: 265 * 266 * DSDT @ 0x737e4000 267 * XSDT @ 0x737f2fff 268 * RSD PTR @ 0xf6cd0 269 * SSDT @ (nil) 270 */ 271 if (!AX_IS_TABLE_BLOCK_HEADER) 272 { 273 return (FALSE); 274 } 275 276 AxNormalizeSignature (Gbl_LineBuffer); 277 return (TRUE); 278 } 279 280 281 /******************************************************************************* 282 * 283 * FUNCTION: AxNormalizeSignature 284 * 285 * PARAMETERS: Name - Ascii string containing an ACPI signature 286 * 287 * RETURN: None 288 * 289 * DESCRIPTION: Change "RSD PTR" to "RSDP" 290 * 291 ******************************************************************************/ 292 293 void 294 AxNormalizeSignature ( 295 char *Signature) 296 { 297 298 if (!strncmp (Signature, "RSD ", 4)) 299 { 300 Signature[3] = 'P'; 301 } 302 } 303 304 305 /****************************************************************************** 306 * 307 * FUNCTION: AxConvertToBinary 308 * 309 * PARAMETERS: InputLine - One line from the input acpidump file 310 * OutputData - Where the converted data is returned 311 * 312 * RETURN: The number of bytes actually converted 313 * 314 * DESCRIPTION: Convert one line of ascii text binary (up to 16 bytes) 315 * 316 * NOTE: Assumes the input data line has been validated to be of the form: 317 * 318 * 0010: 48 53 57 55 4c 54 2d 52 01 00 00 00 49 4e 54 4c HSWULT-R....INTL 319 * 320 ******************************************************************************/ 321 322 size_t 323 AxConvertToBinary ( 324 char *InputLine, 325 unsigned char *OutputData) 326 { 327 int BytesConverted; 328 int Converted[16]; 329 int i; 330 331 332 /* 333 * Terminate input line immediately after the data. Otherwise, the 334 * second line below will not scan correctly. 335 * 336 * 00b0: 03 00 00 00 43 48 41 36 0c 00 00 00 03 00 00 00 ....CHA6........ 337 * 00c0: 43 48 41 37 CHA7 338 */ 339 InputLine [AX_END_OF_HEX_DATA] = 0; 340 341 /* 342 * Convert one line of table data, of the form: 343 * <offset>: <up to 16 bytes of hex data> <ASCII representation> <newline> 344 * 345 * Example: 346 * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08 _SB_LNKD........ 347 */ 348 BytesConverted = sscanf (InputLine, 349 "%*s %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X", 350 &Converted[0], &Converted[1], &Converted[2], &Converted[3], 351 &Converted[4], &Converted[5], &Converted[6], &Converted[7], 352 &Converted[8], &Converted[9], &Converted[10], &Converted[11], 353 &Converted[12], &Converted[13], &Converted[14], &Converted[15]); 354 355 /* Pack converted data into a byte array */ 356 357 for (i = 0; i < BytesConverted; i++) 358 { 359 OutputData[i] = (unsigned char) Converted[i]; 360 } 361 362 return ((size_t) BytesConverted); 363 } 364 365 366 /****************************************************************************** 367 * 368 * FUNCTION: AxCountTableInstances 369 * 370 * PARAMETERS: InputPathname - Filename for acpidump file 371 * Signature - Requested signature to count 372 * 373 * RETURN: The number of instances of the signature 374 * 375 * DESCRIPTION: Count the instances of tables with the given signature within 376 * the input acpidump file. 377 * 378 ******************************************************************************/ 379 380 unsigned int 381 AxCountTableInstances ( 382 char *InputPathname, 383 char *Signature) 384 { 385 FILE *InputFile; 386 unsigned int Instances = 0; 387 388 389 InputFile = fopen (InputPathname, "r"); 390 if (!InputFile) 391 { 392 printf ("Could not open input file %s\n", InputPathname); 393 return (0); 394 } 395 396 /* Count the number of instances of this signature */ 397 398 while (fgets (Gbl_InstanceBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 399 { 400 /* Ignore empty lines and lines that start with a space */ 401 402 if (AxIsEmptyLine (Gbl_InstanceBuffer) || 403 (Gbl_InstanceBuffer[0] == ' ')) 404 { 405 continue; 406 } 407 408 AxNormalizeSignature (Gbl_InstanceBuffer); 409 if (ACPI_COMPARE_NAME (Gbl_InstanceBuffer, Signature)) 410 { 411 Instances++; 412 } 413 } 414 415 fclose (InputFile); 416 return (Instances); 417 } 418 419 420 /****************************************************************************** 421 * 422 * FUNCTION: AxGetNextInstance 423 * 424 * PARAMETERS: InputPathname - Filename for acpidump file 425 * Signature - Requested ACPI signature 426 * 427 * RETURN: The next instance number for this signature. Zero if this 428 * is the first instance of this signature. 429 * 430 * DESCRIPTION: Get the next instance number of the specified table. If this 431 * is the first instance of the table, create a new instance 432 * block. Note: only SSDT and PSDT tables can have multiple 433 * instances. 434 * 435 ******************************************************************************/ 436 437 unsigned int 438 AxGetNextInstance ( 439 char *InputPathname, 440 char *Signature) 441 { 442 AX_TABLE_INFO *Info; 443 444 445 Info = Gbl_TableListHead; 446 while (Info) 447 { 448 if (*(UINT32 *) Signature == Info->Signature) 449 { 450 break; 451 } 452 453 Info = Info->Next; 454 } 455 456 if (!Info) 457 { 458 /* Signature not found, create new table info block */ 459 460 Info = malloc (sizeof (AX_TABLE_INFO)); 461 if (!Info) 462 { 463 printf ("Could not allocate memory (0x%X bytes)\n", 464 (unsigned int) sizeof (AX_TABLE_INFO)); 465 exit (0); 466 } 467 468 Info->Signature = *(UINT32 *) Signature; 469 Info->Instances = AxCountTableInstances (InputPathname, Signature); 470 Info->NextInstance = 1; 471 Info->Next = Gbl_TableListHead; 472 Gbl_TableListHead = Info; 473 } 474 475 if (Info->Instances > 1) 476 { 477 return (Info->NextInstance++); 478 } 479 480 return (0); 481 } 482 483 484 /****************************************************************************** 485 * 486 * FUNCTION: AxConvertAndWrite 487 * 488 * PARAMETERS: OutputFile - Where to write the binary data 489 * ThisSignature - Signature of current ACPI table 490 * ThisTableBytesWritten - Total count of data written 491 * 492 * RETURN: Length of the converted line 493 * 494 * DESCRIPTION: Convert one line of input hex ascii text to binary, and write 495 * the binary data to the table output file. 496 * 497 * NOTE: Assumes the input data line has been validated to be of the form: 498 * 499 * 0010: 48 53 57 55 4c 54 2d 52 01 00 00 00 49 4e 54 4c HSWULT-R....INTL 500 * 501 ******************************************************************************/ 502 503 long 504 AxConvertAndWrite ( 505 FILE *OutputFile, 506 char *ThisSignature, 507 unsigned int ThisTableBytesWritten) 508 { 509 size_t BytesWritten; 510 size_t BytesConverted; 511 512 513 /* Convert one line of ascii hex data to binary */ 514 515 BytesConverted = AxConvertToBinary (Gbl_LineBuffer, Gbl_BinaryData); 516 517 /* Write the binary data */ 518 519 if (!BytesConverted) 520 { 521 return (0); 522 } 523 524 BytesWritten = fwrite (Gbl_BinaryData, 1, BytesConverted, OutputFile); 525 if (BytesWritten != BytesConverted) 526 { 527 printf ("Error while writing file %s\n", Gbl_OutputFilename); 528 return (-1); 529 } 530 531 return (BytesWritten); 532 } 533 534 535 /****************************************************************************** 536 * 537 * FUNCTION: AxDumpTableHeader 538 * 539 * PARAMETERS: Header - A binary ACPI table header 540 * 541 * RETURN: None 542 * 543 * DESCRIPTION: Display the contents of a standard ACPI table header 544 * 545 ******************************************************************************/ 546 547 void 548 AxDumpTableHeader ( 549 unsigned char *Header) 550 { 551 ACPI_TABLE_HEADER *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header; 552 ACPI_TABLE_RSDP *Rsdp = (ACPI_TABLE_RSDP *) (void *) Header; 553 ACPI_TABLE_FACS *Facs = (ACPI_TABLE_FACS *) (void *) Header; 554 555 556 /* RSDP has an oddball signature and header */ 557 558 if (!strncmp (TableHeader->Signature, "RSD PTR ", 8)) 559 { 560 AxCheckAscii ((char *) &Header[9], 6); 561 562 Gbl_TableCount++; 563 printf (" %.2u) %5.4s 0x%8.8X 0x%2.2X \"%6.6s\"\n", 564 Gbl_TableCount, "RSDP", Rsdp->Length, Rsdp->Revision, Rsdp->OemId); 565 return; 566 } 567 568 if (!AcpiUtValidNameseg (TableHeader->Signature)) 569 { 570 return; 571 } 572 573 /* Signature and Table length */ 574 575 Gbl_TableCount++; 576 printf (" %.2u) %5.4s 0x%8.8X", Gbl_TableCount, TableHeader->Signature, 577 TableHeader->Length); 578 579 /* FACS has only signature and length */ 580 581 if (ACPI_COMPARE_NAME (TableHeader->Signature, "FACS")) 582 { 583 printf (" 0x%2.2X\n", Facs->Version); 584 return; 585 } 586 587 /* OEM IDs and Compiler IDs */ 588 589 AxCheckAscii (TableHeader->OemId, 6); 590 AxCheckAscii (TableHeader->OemTableId, 8); 591 AxCheckAscii (TableHeader->AslCompilerId, 4); 592 593 printf ( 594 " 0x%2.2X \"%6.6s\" \"%8.8s\" 0x%8.8X" 595 " \"%4.4s\" 0x%8.8X\n", 596 TableHeader->Revision, TableHeader->OemId, 597 TableHeader->OemTableId, TableHeader->OemRevision, 598 TableHeader->AslCompilerId, TableHeader->AslCompilerRevision); 599 } 600 601 602 #ifdef _AX_FUTURE_ENHANCEMENTS 603 604 /* Possible enhancement to validate table lengths */ 605 606 void 607 AxCheckTableLengths ( 608 UINT32 ByteCount, 609 UINT32 AmlByteCount) 610 { 611 612 if (AmlByteCount == 0) 613 { 614 return; 615 } 616 617 if (ByteCount == 0) 618 { 619 return; 620 } 621 622 if ((ByteCount < sizeof (ACPI_TABLE_HEADER)) && 623 (ByteCount >= ACPI_NAME_SIZE)) 624 { 625 printf (" : (Table too short for an ACPI table)"); 626 } 627 628 else if (ByteCount != AmlByteCount) 629 { 630 printf (" : (Hex data length mismatch with AML length 0x%X)", 631 AmlByteCount); 632 } 633 634 printf ("\n"); 635 } 636 #endif 637