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
AxCheckAscii(char * Name,int Count)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
AxIsEmptyLine(char * Buffer)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
AxNormalizeSignature(char * Signature)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
AxConvertLine(char * InputLine,unsigned char * OutputData)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
AxGetTableHeader(FILE * InputFile,unsigned char * OutputData)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
AxCountTableInstances(char * InputPathname,char * Signature)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
AxGetNextInstance(char * InputPathname,char * Signature)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
AxIsDataBlockHeader(void)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
AxProcessOneTextLine(FILE * OutputFile,char * ThisSignature,unsigned int ThisTableBytesWritten)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