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 63int 64AxExtractTables ( 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 82 /* Open input in text mode, output is in binary mode */ 83 84 InputFile = fopen (InputPathname, "r"); 85 if (!InputFile) 86 { 87 printf ("Could not open input file %s\n", InputPathname); 88 return (-1); 89 } 90 91 if (!AxIsFileAscii (InputFile)) 92 { 93 fclose (InputFile); 94 return (-1); 95 } 96 97 if (Signature) 98 { 99 strncpy (UpperSignature, Signature, ACPI_NAMESEG_SIZE); 100 AcpiUtStrupr (UpperSignature); 101 102 /* Are there enough instances of the table to continue? */ 103 104 AxNormalizeSignature (UpperSignature); 105 Instances = AxCountTableInstances (InputPathname, UpperSignature); 106 107 if (Instances < MinimumInstances) 108 { 109 printf ("Table [%s] was not found in %s\n", 110 UpperSignature, InputPathname); 111 fclose (InputFile); 112 return (0); /* Don't abort */ 113 } 114 115 if (Instances == 0) 116 { 117 fclose (InputFile); 118 return (-1); 119 } 120 } 121 122 /* Convert all instances of the table to binary */ 123 124 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 125 { 126 /* 127 * Check up front if we have a header line of the form: 128 * DSDT @ 0xdfffd0c0 (10999 bytes) 129 */ 130 if (AX_IS_TABLE_BLOCK_HEADER && 131 (State == AX_STATE_EXTRACT_DATA)) 132 { 133 /* End of previous table, start of new table */ 134 135 if (ThisTableBytesWritten) 136 { 137 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, 138 ThisTableBytesWritten, Gbl_OutputFilename); 139 } 140 else 141 { 142 Gbl_TableCount--; 143 } 144 145 State = AX_STATE_FIND_HEADER; 146 } 147 148 switch (State) 149 { 150 case AX_STATE_FIND_HEADER: 151 152 if (!AxIsDataBlockHeader ()) 153 { 154 continue; 155 } 156 157 ACPI_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer); 158 if (Signature) 159 { 160 /* Ignore signatures that don't match */ 161 162 if (!ACPI_COMPARE_NAMESEG (ThisSignature, UpperSignature)) 163 { 164 continue; 165 } 166 } 167 168 /* 169 * Get the instance number for this signature. Only the 170 * SSDT and PSDT tables can have multiple instances. 171 */ 172 ThisInstance = AxGetNextInstance (InputPathname, ThisSignature); 173 174 /* Build an output filename and create/open the output file */ 175 176 if (ThisInstance > 0) 177 { 178 /* Add instance number to the output filename */ 179 180 sprintf (Gbl_OutputFilename, "%4.4s%u.dat", 181 ThisSignature, ThisInstance); 182 } 183 else 184 { 185 sprintf (Gbl_OutputFilename, "%4.4s.dat", 186 ThisSignature); 187 } 188 189 AcpiUtStrlwr (Gbl_OutputFilename); 190 OutputFile = fopen (Gbl_OutputFilename, "w+b"); 191 if (!OutputFile) 192 { 193 printf ("Could not open output file %s\n", 194 Gbl_OutputFilename); 195 fclose (InputFile); 196 return (-1); 197 } 198 199 /* 200 * Toss this block header of the form "<sig> @ <addr>" line 201 * and move on to the actual data block 202 */ 203 Gbl_TableCount++; 204 FoundTable = 1; 205 ThisTableBytesWritten = 0; 206 State = AX_STATE_EXTRACT_DATA; 207 continue; 208 209 case AX_STATE_EXTRACT_DATA: 210 211 if (!AxIsHexDataLine ()) 212 { 213 continue; /* Toss any lines that are not raw hex data */ 214 } 215 216 /* Empty line or non-data line terminates the data block */ 217 218 BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature); 219 switch (BytesConverted) 220 { 221 case 0: 222 223 State = AX_STATE_FIND_HEADER; /* No more data block lines */ 224 continue; 225 226 case -1: 227 228 Status = -1; 229 goto CleanupAndExit; /* There was a write error */ 230 231 default: /* Normal case, get next line */ 232 233 ThisTableBytesWritten += BytesConverted; 234 continue; 235 } 236 237 default: 238 239 Status = -1; 240 goto CleanupAndExit; 241 } 242 } 243 244 if (!FoundTable) 245 { 246 printf ("No ACPI tables were found in %s\n", InputPathname); 247 } 248 249 250CleanupAndExit: 251 252 if (State == AX_STATE_EXTRACT_DATA) 253 { 254 /* Received an input file EOF while extracting data */ 255 256 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, 257 ThisTableBytesWritten, Gbl_OutputFilename); 258 } 259 260 if (OutputFile) 261 { 262 fclose (OutputFile); 263 } 264 265 fclose (InputFile); 266 return (Status); 267} 268 269 270/****************************************************************************** 271 * 272 * FUNCTION: AxExtractToMultiAmlFile 273 * 274 * PARAMETERS: InputPathname - Filename for input acpidump file 275 * 276 * RETURN: Status 277 * 278 * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all 279 * into a single output file. Used to simplify the loading of 280 * multiple/many SSDTs into a utility like acpiexec -- instead 281 * of creating many separate output files. 282 * 283 ******************************************************************************/ 284 285int 286AxExtractToMultiAmlFile ( 287 char *InputPathname) 288{ 289 FILE *InputFile; 290 FILE *OutputFile; 291 int Status = 0; 292 int TotalBytesWritten = 0; 293 int ThisTableBytesWritten = 0; 294 unsigned int BytesConverted; 295 char ThisSignature[4]; 296 unsigned int State = AX_STATE_FIND_HEADER; 297 298 299 strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME); 300 301 /* Open the input file in text mode */ 302 303 InputFile = fopen (InputPathname, "r"); 304 if (!InputFile) 305 { 306 printf ("Could not open input file %s\n", InputPathname); 307 return (-1); 308 } 309 310 if (!AxIsFileAscii (InputFile)) 311 { 312 fclose (InputFile); 313 return (-1); 314 } 315 316 /* Open the output file in binary mode */ 317 318 OutputFile = fopen (Gbl_OutputFilename, "w+b"); 319 if (!OutputFile) 320 { 321 printf ("Could not open output file %s\n", Gbl_OutputFilename); 322 fclose (InputFile); 323 return (-1); 324 } 325 326 /* Convert the DSDT and all SSDTs to binary */ 327 328 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 329 { 330 /* 331 * Check up front if we have a header line of the form: 332 * DSDT @ 0xdfffd0c0 (10999 bytes) 333 */ 334 if (AX_IS_TABLE_BLOCK_HEADER && 335 (State == AX_STATE_EXTRACT_DATA)) 336 { 337 /* End of previous table, start of new table */ 338 339 if (ThisTableBytesWritten) 340 { 341 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, 342 ThisTableBytesWritten, Gbl_OutputFilename); 343 } 344 else 345 { 346 Gbl_TableCount--; 347 } 348 349 State = AX_STATE_FIND_HEADER; 350 } 351 352 switch (State) 353 { 354 case AX_STATE_FIND_HEADER: 355 356 if (!AxIsDataBlockHeader ()) 357 { 358 continue; 359 } 360 361 ACPI_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer); 362 363 /* Only want DSDT and SSDTs */ 364 365 if (!ACPI_COMPARE_NAMESEG (ThisSignature, ACPI_SIG_DSDT) && 366 !ACPI_COMPARE_NAMESEG (ThisSignature, ACPI_SIG_SSDT)) 367 { 368 continue; 369 } 370 371 /* 372 * Toss this block header of the form "<sig> @ <addr>" line 373 * and move on to the actual data block 374 */ 375 Gbl_TableCount++; 376 ThisTableBytesWritten = 0; 377 State = AX_STATE_EXTRACT_DATA; 378 continue; 379 380 case AX_STATE_EXTRACT_DATA: 381 382 if (!AxIsHexDataLine ()) 383 { 384 continue; /* Toss any lines that are not raw hex data */ 385 } 386 387 /* Empty line or non-data line terminates the data block */ 388 389 BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature); 390 switch (BytesConverted) 391 { 392 case 0: 393 394 State = AX_STATE_FIND_HEADER; /* No more data block lines */ 395 continue; 396 397 case -1: 398 399 Status = -1; 400 goto CleanupAndExit; /* There was a write error */ 401 402 default: /* Normal case, get next line */ 403 404 ThisTableBytesWritten += BytesConverted; 405 TotalBytesWritten += BytesConverted; 406 continue; 407 } 408 409 default: 410 411 Status = -1; 412 goto CleanupAndExit; 413 } 414 } 415 416 417CleanupAndExit: 418 419 if (State == AX_STATE_EXTRACT_DATA) 420 { 421 /* Received an input file EOF or error while writing data */ 422 423 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, 424 ThisTableBytesWritten, Gbl_OutputFilename); 425 } 426 427 printf ("\n%u binary ACPI tables extracted and written to %s (%u bytes)\n", 428 Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten); 429 430 fclose (InputFile); 431 fclose (OutputFile); 432 return (Status); 433} 434 435 436/****************************************************************************** 437 * 438 * FUNCTION: AxListAllTables 439 * 440 * PARAMETERS: InputPathname - Filename for acpidump file 441 * 442 * RETURN: Status 443 * 444 * DESCRIPTION: Display info for all ACPI tables found in input. Does not 445 * perform an actual extraction of the tables. 446 * 447 ******************************************************************************/ 448 449int 450AxListAllTables ( 451 char *InputPathname) 452{ 453 FILE *InputFile; 454 unsigned char Header[48]; 455 UINT32 ByteCount = 0; 456 INT32 ThisLineByteCount; 457 unsigned int State = AX_STATE_FIND_HEADER; 458 459 460 /* Open input in text mode, output is in binary mode */ 461 462 InputFile = fopen (InputPathname, "r"); 463 if (!InputFile) 464 { 465 printf ("Could not open input file %s\n", InputPathname); 466 return (-1); 467 } 468 469 if (!AxIsFileAscii (InputFile)) 470 { 471 fclose (InputFile); 472 return (-1); 473 } 474 475 /* Info header */ 476 477 printf ("\n Signature Length Version Oem Oem " 478 "Oem Compiler Compiler\n"); 479 printf ( " Id TableId " 480 "RevisionId Name Revision\n"); 481 printf ( " _________ __________ ____ ________ __________ " 482 "__________ _______ __________\n\n"); 483 484 /* Dump the headers for all tables found in the input file */ 485 486 while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 487 { 488 /* Ignore empty lines */ 489 490 if (AxIsEmptyLine (Gbl_LineBuffer)) 491 { 492 continue; 493 } 494 495 /* 496 * Check up front if we have a header line of the form: 497 * DSDT @ 0xdfffd0c0 (10999 bytes) 498 */ 499 if (AX_IS_TABLE_BLOCK_HEADER && 500 (State == AX_STATE_EXTRACT_DATA)) 501 { 502 State = AX_STATE_FIND_HEADER; 503 } 504 505 switch (State) 506 { 507 case AX_STATE_FIND_HEADER: 508 509 ByteCount = 0; 510 if (!AxIsDataBlockHeader ()) 511 { 512 continue; 513 } 514 515 State = AX_STATE_EXTRACT_DATA; 516 continue; 517 518 case AX_STATE_EXTRACT_DATA: 519 520 /* Ignore any lines that don't look like a data line */ 521 522 if (!AxIsHexDataLine ()) 523 { 524 continue; /* Toss any lines that are not raw hex data */ 525 } 526 527 /* Convert header to hex and display it */ 528 529 ThisLineByteCount = AxConvertToBinary (Gbl_LineBuffer, 530 &Header[ByteCount]); 531 if (ThisLineByteCount == EOF) 532 { 533 fclose (InputFile); 534 return (-1); 535 } 536 537 ByteCount += ThisLineByteCount; 538 if (ByteCount >= sizeof (ACPI_TABLE_HEADER)) 539 { 540 AxDumpTableHeader (Header); 541 State = AX_STATE_FIND_HEADER; 542 } 543 continue; 544 545 default: 546 break; 547 } 548 } 549 550 printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname); 551 fclose (InputFile); 552 return (0); 553} 554