1 /****************************************************************************** 2 * 3 * Module Name: acpixtract - Top level functions to convert ascii/hex 4 * ACPI tables to the original binary tables 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2023, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #include "acpixtract.h" 46 47 48 /****************************************************************************** 49 * 50 * FUNCTION: AxExtractTables 51 * 52 * PARAMETERS: InputPathname - Filename for input acpidump file 53 * Signature - Requested ACPI signature to extract. 54 * NULL means extract ALL tables. 55 * MinimumInstances - Min instances that are acceptable 56 * 57 * RETURN: Status 58 * 59 * DESCRIPTION: Convert text ACPI tables to binary 60 * 61 ******************************************************************************/ 62 63 int 64 AxExtractTables ( 65 char *InputPathname, 66 char *Signature, 67 unsigned int MinimumInstances) 68 { 69 FILE *InputFile; 70 FILE *OutputFile = NULL; 71 int BytesConverted; 72 int ThisTableBytesWritten = 0; 73 unsigned int FoundTable = 0; 74 unsigned int Instances = 0; 75 unsigned int ThisInstance; 76 char ThisSignature[5]; 77 char UpperSignature[5]; 78 int Status = 0; 79 unsigned int State = AX_STATE_FIND_HEADER; 80 81 memset (UpperSignature, 0, sizeof(UpperSignature)); 82 83 /* Open input in text mode, output is in binary mode */ 84 85 InputFile = fopen (InputPathname, "r"); 86 if (!InputFile) 87 { 88 printf ("Could not open input file %s\n", InputPathname); 89 return (-1); 90 } 91 92 if (!AxIsFileAscii (InputFile)) 93 { 94 fclose (InputFile); 95 return (-1); 96 } 97 98 if (Signature) 99 { 100 strncpy (UpperSignature, Signature, ACPI_NAMESEG_SIZE); 101 AcpiUtStrupr (UpperSignature); 102 103 /* Are there enough instances of the table to continue? */ 104 105 AxNormalizeSignature (UpperSignature); 106 Instances = AxCountTableInstances (InputPathname, UpperSignature); 107 108 if (Instances < MinimumInstances || MinimumInstances == AX_OPTIONAL_TABLES) 109 { 110 printf ("Table [%s] was not found in %s\n", 111 UpperSignature, InputPathname); 112 fclose (InputFile); 113 return (0); /* Don't abort */ 114 } 115 116 if (Instances == 0) 117 { 118 fclose (InputFile); 119 return (-1); 120 } 121 } 122 123 /* Convert all instances of the table to binary */ 124 125 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 126 { 127 /* 128 * Check up front if we have a header line of the form: 129 * DSDT @ 0xdfffd0c0 (10999 bytes) 130 */ 131 if (AX_IS_TABLE_BLOCK_HEADER && 132 (State == AX_STATE_EXTRACT_DATA)) 133 { 134 /* End of previous table, start of new table */ 135 136 if (ThisTableBytesWritten) 137 { 138 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, 139 ThisTableBytesWritten, Gbl_OutputFilename); 140 } 141 else 142 { 143 Gbl_TableCount--; 144 } 145 146 State = AX_STATE_FIND_HEADER; 147 } 148 149 switch (State) 150 { 151 case AX_STATE_FIND_HEADER: 152 153 if (!AxIsDataBlockHeader ()) 154 { 155 continue; 156 } 157 158 ACPI_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer); 159 if (Signature) 160 { 161 /* Ignore signatures that don't match */ 162 163 if (!ACPI_COMPARE_NAMESEG (ThisSignature, UpperSignature)) 164 { 165 continue; 166 } 167 } 168 169 /* 170 * Get the instance number for this signature. Only the 171 * SSDT and PSDT tables can have multiple instances. 172 */ 173 ThisInstance = AxGetNextInstance (InputPathname, ThisSignature); 174 175 /* Build an output filename and create/open the output file */ 176 177 if (ThisInstance > 0) 178 { 179 /* Add instance number to the output filename */ 180 181 sprintf (Gbl_OutputFilename, "%4.4s%u.dat", 182 ThisSignature, ThisInstance); 183 } 184 else 185 { 186 sprintf (Gbl_OutputFilename, "%4.4s.dat", 187 ThisSignature); 188 } 189 190 AcpiUtStrlwr (Gbl_OutputFilename); 191 OutputFile = fopen (Gbl_OutputFilename, "w+b"); 192 if (!OutputFile) 193 { 194 printf ("Could not open output file %s\n", 195 Gbl_OutputFilename); 196 fclose (InputFile); 197 return (-1); 198 } 199 200 /* 201 * Toss this block header of the form "<sig> @ <addr>" line 202 * and move on to the actual data block 203 */ 204 Gbl_TableCount++; 205 FoundTable = 1; 206 ThisTableBytesWritten = 0; 207 State = AX_STATE_EXTRACT_DATA; 208 continue; 209 210 case AX_STATE_EXTRACT_DATA: 211 212 if (!AxIsHexDataLine ()) 213 { 214 continue; /* Toss any lines that are not raw hex data */ 215 } 216 217 /* Empty line or non-data line terminates the data block */ 218 219 BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature); 220 switch (BytesConverted) 221 { 222 case 0: 223 224 State = AX_STATE_FIND_HEADER; /* No more data block lines */ 225 continue; 226 227 case -1: 228 229 Status = -1; 230 goto CleanupAndExit; /* There was a write error */ 231 232 default: /* Normal case, get next line */ 233 234 ThisTableBytesWritten += BytesConverted; 235 continue; 236 } 237 238 default: 239 240 Status = -1; 241 goto CleanupAndExit; 242 } 243 } 244 245 if (!FoundTable) 246 { 247 printf ("No ACPI tables were found in %s\n", InputPathname); 248 } 249 250 251 CleanupAndExit: 252 253 if (State == AX_STATE_EXTRACT_DATA) 254 { 255 /* Received an input file EOF while extracting data */ 256 257 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, 258 ThisTableBytesWritten, Gbl_OutputFilename); 259 } 260 261 if (OutputFile) 262 { 263 fclose (OutputFile); 264 } 265 266 fclose (InputFile); 267 return (Status); 268 } 269 270 271 /****************************************************************************** 272 * 273 * FUNCTION: AxExtractToMultiAmlFile 274 * 275 * PARAMETERS: InputPathname - Filename for input acpidump file 276 * 277 * RETURN: Status 278 * 279 * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all 280 * into a single output file. Used to simplify the loading of 281 * multiple/many SSDTs into a utility like acpiexec -- instead 282 * of creating many separate output files. 283 * 284 ******************************************************************************/ 285 286 int 287 AxExtractToMultiAmlFile ( 288 char *InputPathname) 289 { 290 FILE *InputFile; 291 FILE *OutputFile; 292 int Status = 0; 293 int TotalBytesWritten = 0; 294 int ThisTableBytesWritten = 0; 295 unsigned int BytesConverted; 296 char ThisSignature[4]; 297 unsigned int State = AX_STATE_FIND_HEADER; 298 299 300 strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME); 301 302 /* Open the input file in text mode */ 303 304 InputFile = fopen (InputPathname, "r"); 305 if (!InputFile) 306 { 307 printf ("Could not open input file %s\n", InputPathname); 308 return (-1); 309 } 310 311 if (!AxIsFileAscii (InputFile)) 312 { 313 fclose (InputFile); 314 return (-1); 315 } 316 317 /* Open the output file in binary mode */ 318 319 OutputFile = fopen (Gbl_OutputFilename, "w+b"); 320 if (!OutputFile) 321 { 322 printf ("Could not open output file %s\n", Gbl_OutputFilename); 323 fclose (InputFile); 324 return (-1); 325 } 326 327 /* Convert the DSDT and all SSDTs to binary */ 328 329 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 330 { 331 /* 332 * Check up front if we have a header line of the form: 333 * DSDT @ 0xdfffd0c0 (10999 bytes) 334 */ 335 if (AX_IS_TABLE_BLOCK_HEADER && 336 (State == AX_STATE_EXTRACT_DATA)) 337 { 338 /* End of previous table, start of new table */ 339 340 if (ThisTableBytesWritten) 341 { 342 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, 343 ThisTableBytesWritten, Gbl_OutputFilename); 344 } 345 else 346 { 347 Gbl_TableCount--; 348 } 349 350 State = AX_STATE_FIND_HEADER; 351 } 352 353 switch (State) 354 { 355 case AX_STATE_FIND_HEADER: 356 357 if (!AxIsDataBlockHeader ()) 358 { 359 continue; 360 } 361 362 ACPI_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer); 363 364 /* Only want DSDT and SSDTs */ 365 366 if (!ACPI_COMPARE_NAMESEG (ThisSignature, ACPI_SIG_DSDT) && 367 !ACPI_COMPARE_NAMESEG (ThisSignature, ACPI_SIG_SSDT)) 368 { 369 continue; 370 } 371 372 /* 373 * Toss this block header of the form "<sig> @ <addr>" line 374 * and move on to the actual data block 375 */ 376 Gbl_TableCount++; 377 ThisTableBytesWritten = 0; 378 State = AX_STATE_EXTRACT_DATA; 379 continue; 380 381 case AX_STATE_EXTRACT_DATA: 382 383 if (!AxIsHexDataLine ()) 384 { 385 continue; /* Toss any lines that are not raw hex data */ 386 } 387 388 /* Empty line or non-data line terminates the data block */ 389 390 BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature); 391 switch (BytesConverted) 392 { 393 case 0: 394 395 State = AX_STATE_FIND_HEADER; /* No more data block lines */ 396 continue; 397 398 case -1: 399 400 Status = -1; 401 goto CleanupAndExit; /* There was a write error */ 402 403 default: /* Normal case, get next line */ 404 405 ThisTableBytesWritten += BytesConverted; 406 TotalBytesWritten += BytesConverted; 407 continue; 408 } 409 410 default: 411 412 Status = -1; 413 goto CleanupAndExit; 414 } 415 } 416 417 418 CleanupAndExit: 419 420 if (State == AX_STATE_EXTRACT_DATA) 421 { 422 /* Received an input file EOF or error while writing data */ 423 424 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, 425 ThisTableBytesWritten, Gbl_OutputFilename); 426 } 427 428 printf ("\n%u binary ACPI tables extracted and written to %s (%u bytes)\n", 429 Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten); 430 431 fclose (InputFile); 432 fclose (OutputFile); 433 return (Status); 434 } 435 436 437 /****************************************************************************** 438 * 439 * FUNCTION: AxListAllTables 440 * 441 * PARAMETERS: InputPathname - Filename for acpidump file 442 * 443 * RETURN: Status 444 * 445 * DESCRIPTION: Display info for all ACPI tables found in input. Does not 446 * perform an actual extraction of the tables. 447 * 448 ******************************************************************************/ 449 450 int 451 AxListAllTables ( 452 char *InputPathname) 453 { 454 FILE *InputFile; 455 unsigned char Header[48]; 456 UINT32 ByteCount = 0; 457 INT32 ThisLineByteCount; 458 unsigned int State = AX_STATE_FIND_HEADER; 459 460 461 /* Open input in text mode, output is in binary mode */ 462 463 InputFile = fopen (InputPathname, "r"); 464 if (!InputFile) 465 { 466 printf ("Could not open input file %s\n", InputPathname); 467 return (-1); 468 } 469 470 if (!AxIsFileAscii (InputFile)) 471 { 472 fclose (InputFile); 473 return (-1); 474 } 475 476 /* Info header */ 477 478 printf ("\n Signature Length Version Oem Oem " 479 "Oem Compiler Compiler\n"); 480 printf ( " Id TableId " 481 "RevisionId Name Revision\n"); 482 printf ( " _________ __________ ____ ________ __________ " 483 "__________ _______ __________\n\n"); 484 485 /* Dump the headers for all tables found in the input file */ 486 487 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 488 { 489 /* Ignore empty lines */ 490 491 if (AxIsEmptyLine (Gbl_LineBuffer)) 492 { 493 continue; 494 } 495 496 /* 497 * Check up front if we have a header line of the form: 498 * DSDT @ 0xdfffd0c0 (10999 bytes) 499 */ 500 if (AX_IS_TABLE_BLOCK_HEADER && 501 (State == AX_STATE_EXTRACT_DATA)) 502 { 503 State = AX_STATE_FIND_HEADER; 504 } 505 506 switch (State) 507 { 508 case AX_STATE_FIND_HEADER: 509 510 ByteCount = 0; 511 if (!AxIsDataBlockHeader ()) 512 { 513 continue; 514 } 515 516 State = AX_STATE_EXTRACT_DATA; 517 continue; 518 519 case AX_STATE_EXTRACT_DATA: 520 521 /* Ignore any lines that don't look like a data line */ 522 523 if (!AxIsHexDataLine ()) 524 { 525 continue; /* Toss any lines that are not raw hex data */ 526 } 527 528 /* Convert header to hex and display it */ 529 530 ThisLineByteCount = AxConvertToBinary (Gbl_LineBuffer, 531 &Header[ByteCount]); 532 if (ThisLineByteCount == EOF) 533 { 534 fclose (InputFile); 535 return (-1); 536 } 537 538 ByteCount += ThisLineByteCount; 539 if (ByteCount >= sizeof (ACPI_TABLE_HEADER)) 540 { 541 AxDumpTableHeader (Header); 542 State = AX_STATE_FIND_HEADER; 543 } 544 continue; 545 546 default: 547 break; 548 } 549 } 550 551 printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname); 552 fclose (InputFile); 553 return (0); 554 } 555