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