1 /****************************************************************************** 2 * 3 * Module Name: axutils - Utility functions for acpixtract tool. 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: AxCheckAscii 50 * 51 * PARAMETERS: Name - Ascii string, at least as long as Count 52 * Count - Number of characters to check 53 * 54 * RETURN: None 55 * 56 * DESCRIPTION: Ensure that the requested number of characters are printable 57 * Ascii characters. Sets non-printable and null chars to <space>. 58 * 59 ******************************************************************************/ 60 61 void 62 AxCheckAscii ( 63 char *Name, 64 int Count) 65 { 66 int i; 67 68 69 for (i = 0; i < Count; i++) 70 { 71 if (!Name[i] || !isprint ((int) Name[i])) 72 { 73 Name[i] = ' '; 74 } 75 } 76 } 77 78 79 /****************************************************************************** 80 * 81 * FUNCTION: AxIsEmptyLine 82 * 83 * PARAMETERS: Buffer - Line from input file 84 * 85 * RETURN: TRUE if line is empty (zero or more blanks only) 86 * 87 * DESCRIPTION: Determine if an input line is empty. 88 * 89 ******************************************************************************/ 90 91 int 92 AxIsEmptyLine ( 93 char *Buffer) 94 { 95 96 /* Skip all spaces */ 97 98 while (*Buffer == ' ') 99 { 100 Buffer++; 101 } 102 103 /* If end-of-line, this line is empty */ 104 105 if (*Buffer == '\n') 106 { 107 return (1); 108 } 109 110 return (0); 111 } 112 113 114 /******************************************************************************* 115 * 116 * FUNCTION: AxNormalizeSignature 117 * 118 * PARAMETERS: Name - Ascii string containing an ACPI signature 119 * 120 * RETURN: None 121 * 122 * DESCRIPTION: Change "RSD PTR" to "RSDP" 123 * 124 ******************************************************************************/ 125 126 void 127 AxNormalizeSignature ( 128 char *Signature) 129 { 130 131 if (!strncmp (Signature, "RSD ", 4)) 132 { 133 Signature[3] = 'P'; 134 } 135 } 136 137 138 /****************************************************************************** 139 * 140 * FUNCTION: AxConvertLine 141 * 142 * PARAMETERS: InputLine - One line from the input acpidump file 143 * OutputData - Where the converted data is returned 144 * 145 * RETURN: The number of bytes actually converted 146 * 147 * DESCRIPTION: Convert one line of ascii text binary (up to 16 bytes) 148 * 149 ******************************************************************************/ 150 151 size_t 152 AxConvertLine ( 153 char *InputLine, 154 unsigned char *OutputData) 155 { 156 char *End; 157 int BytesConverted; 158 int Converted[16]; 159 int i; 160 161 162 /* Terminate the input line at the end of the actual data (for sscanf) */ 163 164 End = strstr (InputLine + 2, " "); 165 if (!End) 166 { 167 return (0); /* Don't understand the format */ 168 } 169 *End = 0; 170 171 /* 172 * Convert one line of table data, of the form: 173 * <offset>: <up to 16 bytes of hex data> <ASCII representation> <newline> 174 * 175 * Example: 176 * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08 _SB_LNKD........ 177 */ 178 BytesConverted = sscanf (InputLine, 179 "%*s %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", 180 &Converted[0], &Converted[1], &Converted[2], &Converted[3], 181 &Converted[4], &Converted[5], &Converted[6], &Converted[7], 182 &Converted[8], &Converted[9], &Converted[10], &Converted[11], 183 &Converted[12], &Converted[13], &Converted[14], &Converted[15]); 184 185 /* Pack converted data into a byte array */ 186 187 for (i = 0; i < BytesConverted; i++) 188 { 189 OutputData[i] = (unsigned char) Converted[i]; 190 } 191 192 return ((size_t) BytesConverted); 193 } 194 195 196 /****************************************************************************** 197 * 198 * FUNCTION: AxGetTableHeader 199 * 200 * PARAMETERS: InputFile - Handle for the input acpidump file 201 * OutputData - Where the table header is returned 202 * 203 * RETURN: The actual number of bytes converted 204 * 205 * DESCRIPTION: Extract and convert an ACPI table header 206 * 207 ******************************************************************************/ 208 209 size_t 210 AxGetTableHeader ( 211 FILE *InputFile, 212 unsigned char *OutputData) 213 { 214 size_t BytesConverted; 215 size_t TotalConverted = 0; 216 int i; 217 218 219 /* Get the full 36 byte ACPI table header, requires 3 input text lines */ 220 221 for (i = 0; i < 3; i++) 222 { 223 if (!fgets (Gbl_HeaderBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 224 { 225 return (TotalConverted); 226 } 227 228 BytesConverted = AxConvertLine (Gbl_HeaderBuffer, OutputData); 229 TotalConverted += BytesConverted; 230 OutputData += 16; 231 232 if (BytesConverted != 16) 233 { 234 return (TotalConverted); 235 } 236 } 237 238 return (TotalConverted); 239 } 240 241 242 /****************************************************************************** 243 * 244 * FUNCTION: AxCountTableInstances 245 * 246 * PARAMETERS: InputPathname - Filename for acpidump file 247 * Signature - Requested signature to count 248 * 249 * RETURN: The number of instances of the signature 250 * 251 * DESCRIPTION: Count the instances of tables with the given signature within 252 * the input acpidump file. 253 * 254 ******************************************************************************/ 255 256 unsigned int 257 AxCountTableInstances ( 258 char *InputPathname, 259 char *Signature) 260 { 261 FILE *InputFile; 262 unsigned int Instances = 0; 263 264 265 InputFile = fopen (InputPathname, "rt"); 266 if (!InputFile) 267 { 268 printf ("Could not open input file %s\n", InputPathname); 269 return (0); 270 } 271 272 /* Count the number of instances of this signature */ 273 274 while (fgets (Gbl_InstanceBuffer, AX_LINE_BUFFER_SIZE, InputFile)) 275 { 276 /* Ignore empty lines and lines that start with a space */ 277 278 if (AxIsEmptyLine (Gbl_InstanceBuffer) || 279 (Gbl_InstanceBuffer[0] == ' ')) 280 { 281 continue; 282 } 283 284 AxNormalizeSignature (Gbl_InstanceBuffer); 285 if (ACPI_COMPARE_NAME (Gbl_InstanceBuffer, Signature)) 286 { 287 Instances++; 288 } 289 } 290 291 fclose (InputFile); 292 return (Instances); 293 } 294 295 296 /****************************************************************************** 297 * 298 * FUNCTION: AxGetNextInstance 299 * 300 * PARAMETERS: InputPathname - Filename for acpidump file 301 * Signature - Requested ACPI signature 302 * 303 * RETURN: The next instance number for this signature. Zero if this 304 * is the first instance of this signature. 305 * 306 * DESCRIPTION: Get the next instance number of the specified table. If this 307 * is the first instance of the table, create a new instance 308 * block. Note: only SSDT and PSDT tables can have multiple 309 * instances. 310 * 311 ******************************************************************************/ 312 313 unsigned int 314 AxGetNextInstance ( 315 char *InputPathname, 316 char *Signature) 317 { 318 AX_TABLE_INFO *Info; 319 320 321 Info = Gbl_TableListHead; 322 while (Info) 323 { 324 if (*(UINT32 *) Signature == Info->Signature) 325 { 326 break; 327 } 328 329 Info = Info->Next; 330 } 331 332 if (!Info) 333 { 334 /* Signature not found, create new table info block */ 335 336 Info = malloc (sizeof (AX_TABLE_INFO)); 337 if (!Info) 338 { 339 printf ("Could not allocate memory (0x%X bytes)\n", 340 (unsigned int) sizeof (AX_TABLE_INFO)); 341 exit (0); 342 } 343 344 Info->Signature = *(UINT32 *) Signature; 345 Info->Instances = AxCountTableInstances (InputPathname, Signature); 346 Info->NextInstance = 1; 347 Info->Next = Gbl_TableListHead; 348 Gbl_TableListHead = Info; 349 } 350 351 if (Info->Instances > 1) 352 { 353 return (Info->NextInstance++); 354 } 355 356 return (0); 357 } 358 359 360 /****************************************************************************** 361 * 362 * FUNCTION: AxIsDataBlockHeader 363 * 364 * PARAMETERS: None 365 * 366 * RETURN: Status. 1 if the table header is valid, 0 otherwise. 367 * 368 * DESCRIPTION: Check if the ACPI table identifier in the input acpidump text 369 * file is valid (of the form: <sig> @ <addr>). 370 * 371 ******************************************************************************/ 372 373 int 374 AxIsDataBlockHeader ( 375 void) 376 { 377 378 /* Ignore lines that are too short to be header lines */ 379 380 if (strlen (Gbl_LineBuffer) < AX_MIN_BLOCK_HEADER_LENGTH) 381 { 382 return (0); 383 } 384 385 /* Ignore empty lines and lines that start with a space */ 386 387 if (AxIsEmptyLine (Gbl_LineBuffer) || 388 (Gbl_LineBuffer[0] == ' ')) 389 { 390 return (0); 391 } 392 393 /* 394 * Ignore lines that are not headers of the form <sig> @ <addr>. 395 * Basically, just look for the '@' symbol, surrounded by spaces. 396 * 397 * Examples of headers that must be supported: 398 * 399 * DSDT @ 0x737e4000 400 * XSDT @ 0x737f2fff 401 * RSD PTR @ 0xf6cd0 402 * SSDT @ (nil) 403 */ 404 if (!strstr (Gbl_LineBuffer, " @ ")) 405 { 406 return (0); 407 } 408 409 AxNormalizeSignature (Gbl_LineBuffer); 410 return (1); 411 } 412 413 414 /****************************************************************************** 415 * 416 * FUNCTION: AxProcessOneTextLine 417 * 418 * PARAMETERS: OutputFile - Where to write the binary data 419 * ThisSignature - Signature of current ACPI table 420 * ThisTableBytesWritten - Total count of data written 421 * 422 * RETURN: Length of the converted line 423 * 424 * DESCRIPTION: Convert one line of input hex ascii text to binary, and write 425 * the binary data to the table output file. 426 * 427 ******************************************************************************/ 428 429 long 430 AxProcessOneTextLine ( 431 FILE *OutputFile, 432 char *ThisSignature, 433 unsigned int ThisTableBytesWritten) 434 { 435 size_t BytesWritten; 436 size_t BytesConverted; 437 438 439 /* Check for the end of this table data block */ 440 441 if (AxIsEmptyLine (Gbl_LineBuffer) || 442 (Gbl_LineBuffer[0] != ' ')) 443 { 444 printf (AX_TABLE_INFO_FORMAT, 445 ThisSignature, ThisTableBytesWritten, Gbl_OutputFilename); 446 return (0); 447 } 448 449 /* Convert one line of ascii hex data to binary */ 450 451 BytesConverted = AxConvertLine (Gbl_LineBuffer, Gbl_BinaryData); 452 453 /* Write the binary data */ 454 455 BytesWritten = fwrite (Gbl_BinaryData, 1, BytesConverted, OutputFile); 456 if (BytesWritten != BytesConverted) 457 { 458 printf ("Error while writing file %s\n", Gbl_OutputFilename); 459 return (-1); 460 } 461 462 return (BytesWritten); 463 } 464