1 /****************************************************************************** 2 * 3 * Module Name: acpixtract - convert ascii ACPI tables to binary 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 "acpi.h" 45 #include "accommon.h" 46 #include "acapps.h" 47 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <ctype.h> 52 53 /* Local prototypes */ 54 55 static void 56 AxStrlwr ( 57 char *String); 58 59 static void 60 AxCheckAscii ( 61 char *Name, 62 int Count); 63 64 static void 65 AxNormalizeSignature ( 66 char *Signature); 67 68 static unsigned int 69 AxGetNextInstance ( 70 char *InputPathname, 71 char *Signature); 72 73 static size_t 74 AxGetTableHeader ( 75 FILE *InputFile, 76 unsigned char *OutputData); 77 78 static unsigned int 79 AxCountTableInstances ( 80 char *InputPathname, 81 char *Signature); 82 83 int 84 AxExtractTables ( 85 char *InputPathname, 86 char *Signature, 87 unsigned int MinimumInstances); 88 89 int 90 AxListTables ( 91 char *InputPathname); 92 93 static size_t 94 AxConvertLine ( 95 char *InputLine, 96 unsigned char *OutputData); 97 98 static int 99 AxIsEmptyLine ( 100 char *Buffer); 101 102 typedef struct AxTableInfo 103 { 104 UINT32 Signature; 105 unsigned int Instances; 106 unsigned int NextInstance; 107 struct AxTableInfo *Next; 108 109 } AX_TABLE_INFO; 110 111 /* Extraction states */ 112 113 #define AX_STATE_FIND_HEADER 0 114 #define AX_STATE_EXTRACT_DATA 1 115 116 /* Miscellaneous constants */ 117 118 #define AX_LINE_BUFFER_SIZE 256 119 #define AX_MIN_TABLE_NAME_LENGTH 6 /* strlen ("DSDT @") */ 120 121 122 static AX_TABLE_INFO *AxTableListHead = NULL; 123 static char Filename[16]; 124 static unsigned char Data[16]; 125 static char LineBuffer[AX_LINE_BUFFER_SIZE]; 126 static char HeaderBuffer[AX_LINE_BUFFER_SIZE]; 127 static char InstanceBuffer[AX_LINE_BUFFER_SIZE]; 128 129 130 /******************************************************************************* 131 * 132 * FUNCTION: AxStrlwr 133 * 134 * PARAMETERS: String - Ascii string 135 * 136 * RETURN: None 137 * 138 * DESCRIPTION: String lowercase function. 139 * 140 ******************************************************************************/ 141 142 static void 143 AxStrlwr ( 144 char *String) 145 { 146 147 while (*String) 148 { 149 *String = (char) tolower ((int) *String); 150 String++; 151 } 152 } 153 154 155 /******************************************************************************* 156 * 157 * FUNCTION: AxCheckAscii 158 * 159 * PARAMETERS: Name - Ascii string, at least as long as Count 160 * Count - Number of characters to check 161 * 162 * RETURN: None 163 * 164 * DESCRIPTION: Ensure that the requested number of characters are printable 165 * Ascii characters. Sets non-printable and null chars to <space>. 166 * 167 ******************************************************************************/ 168 169 static void 170 AxCheckAscii ( 171 char *Name, 172 int Count) 173 { 174 int i; 175 176 177 for (i = 0; i < Count; i++) 178 { 179 if (!Name[i] || !isprint ((int) Name[i])) 180 { 181 Name[i] = ' '; 182 } 183 } 184 } 185 186 187 /****************************************************************************** 188 * 189 * FUNCTION: AxIsEmptyLine 190 * 191 * PARAMETERS: Buffer - Line from input file 192 * 193 * RETURN: TRUE if line is empty (zero or more blanks only) 194 * 195 * DESCRIPTION: Determine if an input line is empty. 196 * 197 ******************************************************************************/ 198 199 static int 200 AxIsEmptyLine ( 201 char *Buffer) 202 { 203 204 /* Skip all spaces */ 205 206 while (*Buffer == ' ') 207 { 208 Buffer++; 209 } 210 211 /* If end-of-line, this line is empty */ 212 213 if (*Buffer == '\n') 214 { 215 return (1); 216 } 217 218 return (0); 219 } 220 221 222 /******************************************************************************* 223 * 224 * FUNCTION: AxNormalizeSignature 225 * 226 * PARAMETERS: Name - Ascii string containing an ACPI signature 227 * 228 * RETURN: None 229 * 230 * DESCRIPTION: Change "RSD PTR" to "RSDP" 231 * 232 ******************************************************************************/ 233 234 static void 235 AxNormalizeSignature ( 236 char *Signature) 237 { 238 239 if (!strncmp (Signature, "RSD ", 4)) 240 { 241 Signature[3] = 'P'; 242 } 243 } 244 245 246 /****************************************************************************** 247 * 248 * FUNCTION: AxConvertLine 249 * 250 * PARAMETERS: InputLine - One line from the input acpidump file 251 * OutputData - Where the converted data is returned 252 * 253 * RETURN: The number of bytes actually converted 254 * 255 * DESCRIPTION: Convert one line of ascii text binary (up to 16 bytes) 256 * 257 ******************************************************************************/ 258 259 static size_t 260 AxConvertLine ( 261 char *InputLine, 262 unsigned char *OutputData) 263 { 264 char *End; 265 int BytesConverted; 266 int Converted[16]; 267 int i; 268 269 270 /* Terminate the input line at the end of the actual data (for sscanf) */ 271 272 End = strstr (InputLine + 2, " "); 273 if (!End) 274 { 275 return (0); /* Don't understand the format */ 276 } 277 *End = 0; 278 279 /* 280 * Convert one line of table data, of the form: 281 * <offset>: <up to 16 bytes of hex data> <ASCII representation> <newline> 282 * 283 * Example: 284 * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08 _SB_LNKD........ 285 */ 286 BytesConverted = sscanf (InputLine, 287 "%*s %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", 288 &Converted[0], &Converted[1], &Converted[2], &Converted[3], 289 &Converted[4], &Converted[5], &Converted[6], &Converted[7], 290 &Converted[8], &Converted[9], &Converted[10], &Converted[11], 291 &Converted[12], &Converted[13], &Converted[14], &Converted[15]); 292 293 /* Pack converted data into a byte array */ 294 295 for (i = 0; i < BytesConverted; i++) 296 { 297 OutputData[i] = (unsigned char) Converted[i]; 298 } 299 300 return ((size_t) BytesConverted); 301 } 302 303 304 /****************************************************************************** 305 * 306 * FUNCTION: AxGetTableHeader 307 * 308 * PARAMETERS: InputFile - Handle for the input acpidump file 309 * OutputData - Where the table header is returned 310 * 311 * RETURN: The actual number of bytes converted 312 * 313 * DESCRIPTION: Extract and convert an ACPI table header 314 * 315 ******************************************************************************/ 316 317 static size_t 318 AxGetTableHeader ( 319 FILE *InputFile, 320 unsigned char *OutputData) 321 { 322 size_t BytesConverted; 323 size_t TotalConverted = 0; 324 int i; 325 326 327 /* Get the full 36 byte ACPI table header, requires 3 input text lines */ 328 329 for (i = 0; i < 3; i++) 330 { 331 if (!fgets (HeaderBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 332 { 333 return (TotalConverted); 334 } 335 336 BytesConverted = AxConvertLine (HeaderBuffer, OutputData); 337 TotalConverted += BytesConverted; 338 OutputData += 16; 339 340 if (BytesConverted != 16) 341 { 342 return (TotalConverted); 343 } 344 } 345 346 return (TotalConverted); 347 } 348 349 350 /****************************************************************************** 351 * 352 * FUNCTION: AxCountTableInstances 353 * 354 * PARAMETERS: InputPathname - Filename for acpidump file 355 * Signature - Requested signature to count 356 * 357 * RETURN: The number of instances of the signature 358 * 359 * DESCRIPTION: Count the instances of tables with the given signature within 360 * the input acpidump file. 361 * 362 ******************************************************************************/ 363 364 static unsigned int 365 AxCountTableInstances ( 366 char *InputPathname, 367 char *Signature) 368 { 369 FILE *InputFile; 370 unsigned int Instances = 0; 371 372 373 InputFile = fopen (InputPathname, "rt"); 374 if (!InputFile) 375 { 376 printf ("Could not open file %s\n", InputPathname); 377 return (0); 378 } 379 380 /* Count the number of instances of this signature */ 381 382 while (fgets (InstanceBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 383 { 384 /* Ignore empty lines and lines that start with a space */ 385 386 if (AxIsEmptyLine (InstanceBuffer) || 387 (InstanceBuffer[0] == ' ')) 388 { 389 continue; 390 } 391 392 AxNormalizeSignature (InstanceBuffer); 393 if (ACPI_COMPARE_NAME (InstanceBuffer, Signature)) 394 { 395 Instances++; 396 } 397 } 398 399 fclose (InputFile); 400 return (Instances); 401 } 402 403 404 /****************************************************************************** 405 * 406 * FUNCTION: AxGetNextInstance 407 * 408 * PARAMETERS: InputPathname - Filename for acpidump file 409 * Signature - Requested ACPI signature 410 * 411 * RETURN: The next instance number for this signature. Zero if this 412 * is the first instance of this signature. 413 * 414 * DESCRIPTION: Get the next instance number of the specified table. If this 415 * is the first instance of the table, create a new instance 416 * block. Note: only SSDT and PSDT tables can have multiple 417 * instances. 418 * 419 ******************************************************************************/ 420 421 static unsigned int 422 AxGetNextInstance ( 423 char *InputPathname, 424 char *Signature) 425 { 426 AX_TABLE_INFO *Info; 427 428 429 Info = AxTableListHead; 430 while (Info) 431 { 432 if (*(UINT32 *) Signature == Info->Signature) 433 { 434 break; 435 } 436 437 Info = Info->Next; 438 } 439 440 if (!Info) 441 { 442 /* Signature not found, create new table info block */ 443 444 Info = malloc (sizeof (AX_TABLE_INFO)); 445 if (!Info) 446 { 447 printf ("Could not allocate memory\n"); 448 exit (0); 449 } 450 451 Info->Signature = *(UINT32 *) Signature; 452 Info->Instances = AxCountTableInstances (InputPathname, Signature); 453 Info->NextInstance = 1; 454 Info->Next = AxTableListHead; 455 AxTableListHead = Info; 456 } 457 458 if (Info->Instances > 1) 459 { 460 return (Info->NextInstance++); 461 } 462 463 return (0); 464 } 465 466 467 /****************************************************************************** 468 * 469 * FUNCTION: AxExtractTables 470 * 471 * PARAMETERS: InputPathname - Filename for acpidump file 472 * Signature - Requested ACPI signature to extract. 473 * NULL means extract ALL tables. 474 * MinimumInstances - Min instances that are acceptable 475 * 476 * RETURN: Status 477 * 478 * DESCRIPTION: Convert text ACPI tables to binary 479 * 480 ******************************************************************************/ 481 482 int 483 AxExtractTables ( 484 char *InputPathname, 485 char *Signature, 486 unsigned int MinimumInstances) 487 { 488 FILE *InputFile; 489 FILE *OutputFile = NULL; 490 size_t BytesWritten; 491 size_t TotalBytesWritten = 0; 492 size_t BytesConverted; 493 unsigned int State = AX_STATE_FIND_HEADER; 494 unsigned int FoundTable = 0; 495 unsigned int Instances = 0; 496 unsigned int ThisInstance; 497 char ThisSignature[4]; 498 int Status = 0; 499 500 501 /* Open input in text mode, output is in binary mode */ 502 503 InputFile = fopen (InputPathname, "rt"); 504 if (!InputFile) 505 { 506 printf ("Could not open file %s\n", InputPathname); 507 return (-1); 508 } 509 510 if (Signature) 511 { 512 /* Are there enough instances of the table to continue? */ 513 514 AxNormalizeSignature (Signature); 515 516 Instances = AxCountTableInstances (InputPathname, Signature); 517 if (Instances < MinimumInstances) 518 { 519 printf ("Table %s was not found in %s\n", Signature, InputPathname); 520 Status = -1; 521 goto CleanupAndExit; 522 } 523 524 if (Instances == 0) 525 { 526 goto CleanupAndExit; 527 } 528 } 529 530 /* Convert all instances of the table to binary */ 531 532 while (fgets (LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 533 { 534 switch (State) 535 { 536 case AX_STATE_FIND_HEADER: 537 538 /* Ignore lines that are too short to be header lines */ 539 540 if (strlen (LineBuffer) < AX_MIN_TABLE_NAME_LENGTH) 541 { 542 continue; 543 } 544 545 /* Ignore empty lines and lines that start with a space */ 546 547 if (AxIsEmptyLine (LineBuffer) || 548 (LineBuffer[0] == ' ')) 549 { 550 continue; 551 } 552 553 /* 554 * Ignore lines that are not of the form <sig> @ <addr>. 555 * Examples of lines that must be supported: 556 * 557 * DSDT @ 0x737e4000 558 * XSDT @ 0x737f2fff 559 * RSD PTR @ 0xf6cd0 560 * SSDT @ (nil) 561 */ 562 if (!strstr (LineBuffer, " @ ")) 563 { 564 continue; 565 } 566 567 AxNormalizeSignature (LineBuffer); 568 ACPI_MOVE_NAME (ThisSignature, LineBuffer); 569 570 if (Signature) 571 { 572 /* Ignore signatures that don't match */ 573 574 if (!ACPI_COMPARE_NAME (ThisSignature, Signature)) 575 { 576 continue; 577 } 578 } 579 580 /* 581 * Get the instance number for this signature. Only the 582 * SSDT and PSDT tables can have multiple instances. 583 */ 584 ThisInstance = AxGetNextInstance (InputPathname, ThisSignature); 585 586 /* Build an output filename and create/open the output file */ 587 588 if (ThisInstance > 0) 589 { 590 sprintf (Filename, "%4.4s%u.dat", ThisSignature, ThisInstance); 591 } 592 else 593 { 594 sprintf (Filename, "%4.4s.dat", ThisSignature); 595 } 596 597 AxStrlwr (Filename); 598 OutputFile = fopen (Filename, "w+b"); 599 if (!OutputFile) 600 { 601 printf ("Could not open file %s\n", Filename); 602 Status = -1; 603 goto CleanupAndExit; 604 } 605 606 State = AX_STATE_EXTRACT_DATA; 607 TotalBytesWritten = 0; 608 FoundTable = 1; 609 continue; 610 611 case AX_STATE_EXTRACT_DATA: 612 613 /* Empty line or non-data line terminates the data */ 614 615 if (AxIsEmptyLine (LineBuffer) || 616 (LineBuffer[0] != ' ')) 617 { 618 fclose (OutputFile); 619 OutputFile = NULL; 620 State = AX_STATE_FIND_HEADER; 621 622 printf ("Acpi table [%4.4s] - %u bytes written to %s\n", 623 ThisSignature, (unsigned int) TotalBytesWritten, Filename); 624 continue; 625 } 626 627 /* Convert the ascii data (one line of text) to binary */ 628 629 BytesConverted = AxConvertLine (LineBuffer, Data); 630 631 /* Write the binary data */ 632 633 BytesWritten = fwrite (Data, 1, BytesConverted, OutputFile); 634 if (BytesWritten != BytesConverted) 635 { 636 printf ("Error when writing file %s\n", Filename); 637 fclose (OutputFile); 638 OutputFile = NULL; 639 Status = -1; 640 goto CleanupAndExit; 641 } 642 643 TotalBytesWritten += BytesConverted; 644 continue; 645 646 default: 647 648 Status = -1; 649 goto CleanupAndExit; 650 } 651 } 652 653 if (!FoundTable) 654 { 655 printf ("Table %s was not found in %s\n", Signature, InputPathname); 656 } 657 658 659 CleanupAndExit: 660 661 if (OutputFile) 662 { 663 fclose (OutputFile); 664 if (State == AX_STATE_EXTRACT_DATA) 665 { 666 /* Received an EOF while extracting data */ 667 668 printf ("Acpi table [%4.4s] - %u bytes written to %s\n", 669 ThisSignature, (unsigned int) TotalBytesWritten, Filename); 670 } 671 } 672 673 fclose (InputFile); 674 return (Status); 675 } 676 677 678 /****************************************************************************** 679 * 680 * FUNCTION: AxListTables 681 * 682 * PARAMETERS: InputPathname - Filename for acpidump file 683 * 684 * RETURN: Status 685 * 686 * DESCRIPTION: Display info for all ACPI tables found in input. Does not 687 * perform an actual extraction of the tables. 688 * 689 ******************************************************************************/ 690 691 int 692 AxListTables ( 693 char *InputPathname) 694 { 695 FILE *InputFile; 696 size_t HeaderSize; 697 unsigned char Header[48]; 698 int TableCount = 0; 699 ACPI_TABLE_HEADER *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header; 700 701 702 /* Open input in text mode, output is in binary mode */ 703 704 InputFile = fopen (InputPathname, "rt"); 705 if (!InputFile) 706 { 707 printf ("Could not open file %s\n", InputPathname); 708 return (-1); 709 } 710 711 /* Dump the headers for all tables found in the input file */ 712 713 printf ("\nSignature Length Revision OemId OemTableId" 714 " OemRevision CompilerId CompilerRevision\n\n"); 715 716 while (fgets (LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 717 { 718 /* Ignore empty lines and lines that start with a space */ 719 720 if (AxIsEmptyLine (LineBuffer) || 721 (LineBuffer[0] == ' ')) 722 { 723 continue; 724 } 725 726 /* Get the 36 byte header and display the fields */ 727 728 HeaderSize = AxGetTableHeader (InputFile, Header); 729 if (HeaderSize < 16) 730 { 731 continue; 732 } 733 734 /* RSDP has an oddball signature and header */ 735 736 if (!strncmp (TableHeader->Signature, "RSD PTR ", 8)) 737 { 738 AxCheckAscii ((char *) &Header[9], 6); 739 printf ("%7.4s \"%6.6s\"\n", "RSDP", &Header[9]); 740 TableCount++; 741 continue; 742 } 743 744 /* Minimum size for table with standard header */ 745 746 if (HeaderSize < sizeof (ACPI_TABLE_HEADER)) 747 { 748 continue; 749 } 750 751 /* Signature and Table length */ 752 753 TableCount++; 754 printf ("%7.4s 0x%8.8X", TableHeader->Signature, TableHeader->Length); 755 756 /* FACS has only signature and length */ 757 758 if (ACPI_COMPARE_NAME (TableHeader->Signature, "FACS")) 759 { 760 printf ("\n"); 761 continue; 762 } 763 764 /* OEM IDs and Compiler IDs */ 765 766 AxCheckAscii (TableHeader->OemId, 6); 767 AxCheckAscii (TableHeader->OemTableId, 8); 768 AxCheckAscii (TableHeader->AslCompilerId, 4); 769 770 printf (" 0x%2.2X \"%6.6s\" \"%8.8s\" 0x%8.8X \"%4.4s\" 0x%8.8X\n", 771 TableHeader->Revision, TableHeader->OemId, 772 TableHeader->OemTableId, TableHeader->OemRevision, 773 TableHeader->AslCompilerId, TableHeader->AslCompilerRevision); 774 } 775 776 printf ("\nFound %u ACPI tables\n", TableCount); 777 fclose (InputFile); 778 return (0); 779 }