1 /****************************************************************************** 2 * 3 * Module Name: acpixtract - convert ascii ACPI tables to binary 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 /* Local prototypes */ 48 49 static BOOLEAN 50 AxIsFileAscii ( 51 FILE *Handle); 52 53 54 /****************************************************************************** 55 * 56 * FUNCTION: AxExtractTables 57 * 58 * PARAMETERS: InputPathname - Filename for input acpidump file 59 * Signature - Requested ACPI signature to extract. 60 * NULL means extract ALL tables. 61 * MinimumInstances - Min instances that are acceptable 62 * 63 * RETURN: Status 64 * 65 * DESCRIPTION: Convert text ACPI tables to binary 66 * 67 ******************************************************************************/ 68 69 int 70 AxExtractTables ( 71 char *InputPathname, 72 char *Signature, 73 unsigned int MinimumInstances) 74 { 75 FILE *InputFile; 76 FILE *OutputFile = NULL; 77 unsigned int BytesConverted; 78 unsigned int ThisTableBytesWritten = 0; 79 unsigned int FoundTable = 0; 80 unsigned int Instances = 0; 81 unsigned int ThisInstance; 82 char ThisSignature[5]; 83 char UpperSignature[5]; 84 int Status = 0; 85 unsigned int State = AX_STATE_FIND_HEADER; 86 87 88 /* Open input in text mode, output is in binary mode */ 89 90 InputFile = fopen (InputPathname, "rt"); 91 if (!InputFile) 92 { 93 printf ("Could not open input file %s\n", InputPathname); 94 return (-1); 95 } 96 97 if (!AxIsFileAscii (InputFile)) 98 { 99 fclose (InputFile); 100 return (-1); 101 } 102 103 if (Signature) 104 { 105 strncpy (UpperSignature, Signature, 4); 106 UpperSignature[4] = 0; 107 AcpiUtStrupr (UpperSignature); 108 109 /* Are there enough instances of the table to continue? */ 110 111 AxNormalizeSignature (UpperSignature); 112 113 Instances = AxCountTableInstances (InputPathname, UpperSignature); 114 if (Instances < MinimumInstances) 115 { 116 printf ("Table [%s] was not found in %s\n", 117 UpperSignature, InputPathname); 118 fclose (InputFile); 119 return (-1); 120 } 121 122 if (Instances == 0) 123 { 124 fclose (InputFile); 125 return (-1); 126 } 127 } 128 129 /* Convert all instances of the table to binary */ 130 131 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 132 { 133 switch (State) 134 { 135 case AX_STATE_FIND_HEADER: 136 137 if (!AxIsDataBlockHeader ()) 138 { 139 continue; 140 } 141 142 ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer); 143 if (Signature) 144 { 145 /* Ignore signatures that don't match */ 146 147 if (!ACPI_COMPARE_NAME (ThisSignature, UpperSignature)) 148 { 149 continue; 150 } 151 } 152 153 /* 154 * Get the instance number for this signature. Only the 155 * SSDT and PSDT tables can have multiple instances. 156 */ 157 ThisInstance = AxGetNextInstance (InputPathname, ThisSignature); 158 159 /* Build an output filename and create/open the output file */ 160 161 if (ThisInstance > 0) 162 { 163 /* Add instance number to the output filename */ 164 165 sprintf (Gbl_OutputFilename, "%4.4s%u.dat", 166 ThisSignature, ThisInstance); 167 } 168 else 169 { 170 sprintf (Gbl_OutputFilename, "%4.4s.dat", 171 ThisSignature); 172 } 173 174 AcpiUtStrlwr (Gbl_OutputFilename); 175 OutputFile = fopen (Gbl_OutputFilename, "w+b"); 176 if (!OutputFile) 177 { 178 printf ("Could not open output file %s\n", 179 Gbl_OutputFilename); 180 fclose (InputFile); 181 return (-1); 182 } 183 184 /* 185 * Toss this block header of the form "<sig> @ <addr>" line 186 * and move on to the actual data block 187 */ 188 Gbl_TableCount++; 189 FoundTable = 1; 190 ThisTableBytesWritten = 0; 191 State = AX_STATE_EXTRACT_DATA; 192 continue; 193 194 case AX_STATE_EXTRACT_DATA: 195 196 /* Empty line or non-data line terminates the data block */ 197 198 BytesConverted = AxProcessOneTextLine ( 199 OutputFile, ThisSignature, ThisTableBytesWritten); 200 switch (BytesConverted) 201 { 202 case 0: 203 204 State = AX_STATE_FIND_HEADER; /* No more data block lines */ 205 continue; 206 207 case -1: 208 209 goto CleanupAndExit; /* There was a write error */ 210 211 default: /* Normal case, get next line */ 212 213 ThisTableBytesWritten += BytesConverted; 214 continue; 215 } 216 217 default: 218 219 Status = -1; 220 goto CleanupAndExit; 221 } 222 } 223 224 if (!FoundTable) 225 { 226 printf ("No ACPI tables were found in %s\n", InputPathname); 227 } 228 229 230 CleanupAndExit: 231 232 if (State == AX_STATE_EXTRACT_DATA) 233 { 234 /* Received an input file EOF while extracting data */ 235 236 printf (AX_TABLE_INFO_FORMAT, 237 ThisSignature, ThisTableBytesWritten, Gbl_OutputFilename); 238 } 239 240 if (Gbl_TableCount > 1) 241 { 242 printf ("\n%u binary ACPI tables extracted\n", 243 Gbl_TableCount); 244 } 245 246 if (OutputFile) 247 { 248 fclose (OutputFile); 249 } 250 251 fclose (InputFile); 252 return (Status); 253 } 254 255 256 /****************************************************************************** 257 * 258 * FUNCTION: AxExtractToMultiAmlFile 259 * 260 * PARAMETERS: InputPathname - Filename for input acpidump file 261 * 262 * RETURN: Status 263 * 264 * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all 265 * into a single output file. Used to simplify the loading of 266 * multiple/many SSDTs into a utility like acpiexec -- instead 267 * of creating many separate output files. 268 * 269 ******************************************************************************/ 270 271 int 272 AxExtractToMultiAmlFile ( 273 char *InputPathname) 274 { 275 FILE *InputFile; 276 FILE *OutputFile; 277 int Status = 0; 278 unsigned int TotalBytesWritten = 0; 279 unsigned int ThisTableBytesWritten = 0; 280 unsigned int BytesConverted; 281 char ThisSignature[4]; 282 unsigned int State = AX_STATE_FIND_HEADER; 283 284 285 strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME); 286 287 /* Open the input file in text mode */ 288 289 InputFile = fopen (InputPathname, "rt"); 290 if (!InputFile) 291 { 292 printf ("Could not open input file %s\n", InputPathname); 293 return (-1); 294 } 295 296 if (!AxIsFileAscii (InputFile)) 297 { 298 fclose (InputFile); 299 return (-1); 300 } 301 302 /* Open the output file in binary mode */ 303 304 OutputFile = fopen (Gbl_OutputFilename, "w+b"); 305 if (!OutputFile) 306 { 307 printf ("Could not open output file %s\n", Gbl_OutputFilename); 308 fclose (InputFile); 309 return (-1); 310 } 311 312 /* Convert the DSDT and all SSDTs to binary */ 313 314 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 315 { 316 switch (State) 317 { 318 case AX_STATE_FIND_HEADER: 319 320 if (!AxIsDataBlockHeader ()) 321 { 322 continue; 323 } 324 325 ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer); 326 327 /* Only want DSDT and SSDTs */ 328 329 if (!ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_DSDT) && 330 !ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_SSDT)) 331 { 332 continue; 333 } 334 335 /* 336 * Toss this block header of the form "<sig> @ <addr>" line 337 * and move on to the actual data block 338 */ 339 Gbl_TableCount++; 340 ThisTableBytesWritten = 0; 341 State = AX_STATE_EXTRACT_DATA; 342 continue; 343 344 case AX_STATE_EXTRACT_DATA: 345 346 /* Empty line or non-data line terminates the data block */ 347 348 BytesConverted = AxProcessOneTextLine ( 349 OutputFile, ThisSignature, ThisTableBytesWritten); 350 switch (BytesConverted) 351 { 352 case 0: 353 354 State = AX_STATE_FIND_HEADER; /* No more data block lines */ 355 continue; 356 357 case -1: 358 359 goto CleanupAndExit; /* There was a write error */ 360 361 default: /* Normal case, get next line */ 362 363 ThisTableBytesWritten += BytesConverted; 364 TotalBytesWritten += BytesConverted; 365 continue; 366 } 367 368 default: 369 370 Status = -1; 371 goto CleanupAndExit; 372 } 373 } 374 375 376 CleanupAndExit: 377 378 if (State == AX_STATE_EXTRACT_DATA) 379 { 380 /* Received an input file EOF or error while writing data */ 381 382 printf (AX_TABLE_INFO_FORMAT, 383 ThisSignature, ThisTableBytesWritten, Gbl_OutputFilename); 384 } 385 386 printf ("\n%u binary ACPI tables extracted and written to %s (%u bytes)\n", 387 Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten); 388 389 fclose (InputFile); 390 fclose (OutputFile); 391 return (Status); 392 } 393 394 395 /****************************************************************************** 396 * 397 * FUNCTION: AxListTables 398 * 399 * PARAMETERS: InputPathname - Filename for acpidump file 400 * 401 * RETURN: Status 402 * 403 * DESCRIPTION: Display info for all ACPI tables found in input. Does not 404 * perform an actual extraction of the tables. 405 * 406 ******************************************************************************/ 407 408 int 409 AxListTables ( 410 char *InputPathname) 411 { 412 FILE *InputFile; 413 size_t HeaderSize; 414 unsigned char Header[48]; 415 ACPI_TABLE_HEADER *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header; 416 417 418 /* Open input in text mode, output is in binary mode */ 419 420 InputFile = fopen (InputPathname, "rt"); 421 if (!InputFile) 422 { 423 printf ("Could not open input file %s\n", InputPathname); 424 return (-1); 425 } 426 427 if (!AxIsFileAscii (InputFile)) 428 { 429 fclose (InputFile); 430 return (-1); 431 } 432 433 /* Dump the headers for all tables found in the input file */ 434 435 printf ("\nSignature Length Revision OemId OemTableId" 436 " OemRevision CompilerId CompilerRevision\n\n"); 437 438 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 439 { 440 /* Ignore empty lines and lines that start with a space */ 441 442 if (AxIsEmptyLine (Gbl_LineBuffer) || 443 (Gbl_LineBuffer[0] == ' ')) 444 { 445 continue; 446 } 447 448 /* Get the 36 byte header and display the fields */ 449 450 HeaderSize = AxGetTableHeader (InputFile, Header); 451 if (HeaderSize < 16) 452 { 453 continue; 454 } 455 456 /* RSDP has an oddball signature and header */ 457 458 if (!strncmp (TableHeader->Signature, "RSD PTR ", 8)) 459 { 460 AxCheckAscii ((char *) &Header[9], 6); 461 printf ("%7.4s \"%6.6s\"\n", "RSDP", 462 &Header[9]); 463 Gbl_TableCount++; 464 continue; 465 } 466 467 /* Minimum size for table with standard header */ 468 469 if (HeaderSize < sizeof (ACPI_TABLE_HEADER)) 470 { 471 continue; 472 } 473 474 if (!AcpiUtValidNameseg (TableHeader->Signature)) 475 { 476 continue; 477 } 478 479 /* Signature and Table length */ 480 481 Gbl_TableCount++; 482 printf ("%7.4s 0x%8.8X", TableHeader->Signature, 483 TableHeader->Length); 484 485 /* FACS has only signature and length */ 486 487 if (ACPI_COMPARE_NAME (TableHeader->Signature, "FACS")) 488 { 489 printf ("\n"); 490 continue; 491 } 492 493 /* OEM IDs and Compiler IDs */ 494 495 AxCheckAscii (TableHeader->OemId, 6); 496 AxCheckAscii (TableHeader->OemTableId, 8); 497 AxCheckAscii (TableHeader->AslCompilerId, 4); 498 499 printf ( 500 " 0x%2.2X \"%6.6s\" \"%8.8s\" 0x%8.8X" 501 " \"%4.4s\" 0x%8.8X\n", 502 TableHeader->Revision, TableHeader->OemId, 503 TableHeader->OemTableId, TableHeader->OemRevision, 504 TableHeader->AslCompilerId, TableHeader->AslCompilerRevision); 505 } 506 507 printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname); 508 fclose (InputFile); 509 return (0); 510 } 511 512 513 /******************************************************************************* 514 * 515 * FUNCTION: AxIsFileAscii 516 * 517 * PARAMETERS: Handle - To open input file 518 * 519 * RETURN: TRUE if file is entirely ASCII and printable 520 * 521 * DESCRIPTION: Verify that the input file is entirely ASCII. 522 * 523 ******************************************************************************/ 524 525 static BOOLEAN 526 AxIsFileAscii ( 527 FILE *Handle) 528 { 529 UINT8 Byte; 530 531 532 /* Read the entire file */ 533 534 while (fread (&Byte, 1, 1, Handle) == 1) 535 { 536 /* Check for an ASCII character */ 537 538 if (!ACPI_IS_ASCII (Byte)) 539 { 540 goto ErrorExit; 541 } 542 543 /* Ensure character is either printable or a "space" char */ 544 545 else if (!isprint (Byte) && !isspace (Byte)) 546 { 547 goto ErrorExit; 548 } 549 } 550 551 /* File is OK (100% ASCII) */ 552 553 fseek (Handle, 0, SEEK_SET); 554 return (TRUE); 555 556 ErrorExit: 557 558 printf ("File is binary (contains non-text or non-ascii characters)\n"); 559 fseek (Handle, 0, SEEK_SET); 560 return (FALSE); 561 562 } 563