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