]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/dev/acpica/compiler/dtutils.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / dev / acpica / compiler / dtutils.c
1 /******************************************************************************
2  *
3  * Module Name: dtutils.c - Utility routines for the data table compiler
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2011, 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 #define __DTUTILS_C__
45
46 #include <contrib/dev/acpica/compiler/aslcompiler.h>
47 #include <contrib/dev/acpica/compiler/dtcompiler.h>
48 #include <contrib/dev/acpica/include/actables.h>
49
50 #define _COMPONENT          DT_COMPILER
51         ACPI_MODULE_NAME    ("dtutils")
52
53 /* Local prototypes */
54
55 static void
56 DtSum (
57     DT_SUBTABLE             *Subtable,
58     void                    *Context,
59     void                    *ReturnValue);
60
61
62 /******************************************************************************
63  *
64  * FUNCTION:    DtError
65  *
66  * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
67  *              MessageId           - Index into global message buffer
68  *              Op                  - Parse node where error happened
69  *              ExtraMessage        - additional error message
70  *
71  * RETURN:      None
72  *
73  * DESCRIPTION: Common error interface for data table compiler
74  *
75  *****************************************************************************/
76
77 void
78 DtError (
79     UINT8                   Level,
80     UINT8                   MessageId,
81     DT_FIELD                *FieldObject,
82     char                    *ExtraMessage)
83 {
84
85     switch (Level)
86     {
87     case ASL_WARNING2:
88     case ASL_WARNING3:
89         if (Gbl_WarningLevel < Level)
90         {
91             return;
92         }
93         break;
94
95     default:
96         break;
97     }
98
99     if (FieldObject)
100     {
101         AslCommonError (Level, MessageId,
102             FieldObject->Line,
103             FieldObject->Line,
104             FieldObject->ByteOffset,
105             FieldObject->Column,
106             Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
107     }
108     else
109     {
110         AslCommonError (Level, MessageId, 0,
111             0, 0, 0, 0, ExtraMessage);
112     }
113 }
114
115
116 /******************************************************************************
117  *
118  * FUNCTION:    DtNameError
119  *
120  * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
121  *              MessageId           - Index into global message buffer
122  *              Op                  - Parse node where error happened
123  *              ExtraMessage        - additional error message
124  *
125  * RETURN:      None
126  *
127  * DESCRIPTION: Error interface for named objects
128  *
129  *****************************************************************************/
130
131 void
132 DtNameError (
133     UINT8                   Level,
134     UINT8                   MessageId,
135     DT_FIELD                *FieldObject,
136     char                    *ExtraMessage)
137 {
138
139     switch (Level)
140     {
141     case ASL_WARNING2:
142     case ASL_WARNING3:
143         if (Gbl_WarningLevel < Level)
144         {
145             return;
146         }
147         break;
148
149     default:
150         break;
151     }
152
153     if (FieldObject)
154     {
155         AslCommonError (Level, MessageId,
156             FieldObject->Line,
157             FieldObject->Line,
158             FieldObject->ByteOffset,
159             FieldObject->NameColumn,
160             Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
161     }
162     else
163     {
164         AslCommonError (Level, MessageId, 0,
165             0, 0, 0, 0, ExtraMessage);
166     }
167 }
168
169
170 /*******************************************************************************
171  *
172  * FUNCTION:    DtFatal
173  *
174  * PARAMETERS:  None
175  *
176  * RETURN:      None
177  *
178  * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
179  *              compile or I/O errors
180  *
181  ******************************************************************************/
182
183 void
184 DtFatal (
185     UINT8                   MessageId,
186     DT_FIELD                *FieldObject,
187     char                    *ExtraMessage)
188 {
189
190     DtError (ASL_ERROR, MessageId, FieldObject, ExtraMessage);
191
192 /*
193  * TBD: remove this entire function, DtFatal
194  *
195  * We cannot abort the compiler on error, because we may be compiling a
196  * list of files. We must move on to the next file.
197  */
198 #ifdef __OBSOLETE
199     CmCleanupAndExit ();
200     exit (1);
201 #endif
202 }
203
204
205 /******************************************************************************
206  *
207  * FUNCTION:    DtStrtoul64
208  *
209  * PARAMETERS:  String              - Null terminated string
210  *              ReturnInteger       - Where the converted integer is returned
211  *
212  * RETURN:      Status
213  *
214  * DESCRIPTION: Simple conversion of a string hex integer constant to unsigned
215  *              value. Assumes no leading "0x" for the constant.
216  *
217  * Portability note: The reason this function exists is because a 64-bit
218  * sscanf is not available in all environments.
219  *
220  *****************************************************************************/
221
222 ACPI_STATUS
223 DtStrtoul64 (
224     char                    *String,
225     UINT64                  *ReturnInteger)
226 {
227     char                    *ThisChar = String;
228     UINT32                  ThisDigit;
229     UINT64                  ReturnValue = 0;
230     int                     DigitCount = 0;
231
232
233     /* Skip over any white space in the buffer */
234
235     while ((*ThisChar == ' ') || (*ThisChar == '\t'))
236     {
237         ThisChar++;
238     }
239
240     /* Skip leading zeros */
241
242     while ((*ThisChar) == '0')
243     {
244         ThisChar++;
245     }
246
247     /* Convert character-by-character */
248
249     while (*ThisChar)
250     {
251         if (ACPI_IS_DIGIT (*ThisChar))
252         {
253             /* Convert ASCII 0-9 to Decimal value */
254
255             ThisDigit = ((UINT8) *ThisChar) - '0';
256         }
257         else /* Letter */
258         {
259             ThisDigit = (UINT32) ACPI_TOUPPER (*ThisChar);
260             if (!ACPI_IS_XDIGIT ((char) ThisDigit))
261             {
262                 /* Not A-F */
263
264                 return (AE_BAD_CHARACTER);
265             }
266
267             /* Convert ASCII Hex char (A-F) to value */
268
269             ThisDigit = (ThisDigit - 'A') + 10;
270         }
271
272         /* Insert the 4-bit hex digit */
273
274         ReturnValue <<= 4;
275         ReturnValue += ThisDigit;
276
277         ThisChar++;
278         DigitCount++;
279         if (DigitCount > 16)
280         {
281             /* Value is too large (> 64 bits/8 bytes/16 hex digits) */
282
283             return (AE_LIMIT);
284         }
285     }
286
287     *ReturnInteger = ReturnValue;
288     return (AE_OK);
289 }
290
291
292 /******************************************************************************
293  *
294  * FUNCTION:    DtGetFileSize
295  *
296  * PARAMETERS:  Handle              - Open file handler
297  *
298  * RETURN:      Current file size
299  *
300  * DESCRIPTION: Get the current size of a file. Seek to the EOF and get the
301  *              offset. Seek back to the original location.
302  *
303  *****************************************************************************/
304
305 UINT32
306 DtGetFileSize (
307     FILE                    *Handle)
308 {
309     int                     CurrentOffset;
310     int                     LastOffset;
311
312
313     CurrentOffset = ftell (Handle);
314     fseek (Handle, 0, SEEK_END);
315     LastOffset = ftell (Handle);
316     fseek (Handle, CurrentOffset, SEEK_SET);
317
318     return ((UINT32) LastOffset);
319 }
320
321
322 /******************************************************************************
323  *
324  * FUNCTION:    DtGetFieldValue
325  *
326  * PARAMETERS:  Field               - Current field list pointer
327  *
328  * RETURN:      Field value
329  *
330  * DESCRIPTION: Get field value
331  *
332  *****************************************************************************/
333
334 char *
335 DtGetFieldValue (
336     DT_FIELD                *Field)
337 {
338     if (!Field)
339     {
340         return (NULL);
341     }
342
343     return (Field->Value);
344 }
345
346
347 /******************************************************************************
348  *
349  * FUNCTION:    DtGetFieldType
350  *
351  * PARAMETERS:  Info                - Data table info
352  *
353  * RETURN:      Field type
354  *
355  * DESCRIPTION: Get field type
356  *
357  *****************************************************************************/
358
359 UINT8
360 DtGetFieldType (
361     ACPI_DMTABLE_INFO       *Info)
362 {
363     UINT8                   Type;
364
365
366     /* DT_FLAG means that this is the start of a block of flag bits */
367     /* TBD - we can make these a separate opcode later */
368
369     if (Info->Flags & DT_FLAG)
370     {
371         return (DT_FIELD_TYPE_FLAGS_INTEGER);
372     }
373
374     /* Type is based upon the opcode for this field in the info table */
375
376     switch (Info->Opcode)
377     {
378     case ACPI_DMT_FLAG0:
379     case ACPI_DMT_FLAG1:
380     case ACPI_DMT_FLAG2:
381     case ACPI_DMT_FLAG3:
382     case ACPI_DMT_FLAG4:
383     case ACPI_DMT_FLAG5:
384     case ACPI_DMT_FLAG6:
385     case ACPI_DMT_FLAG7:
386     case ACPI_DMT_FLAGS0:
387     case ACPI_DMT_FLAGS2:
388         Type = DT_FIELD_TYPE_FLAG;
389         break;
390
391     case ACPI_DMT_NAME4:
392     case ACPI_DMT_SIG:
393     case ACPI_DMT_NAME6:
394     case ACPI_DMT_NAME8:
395     case ACPI_DMT_STRING:
396         Type = DT_FIELD_TYPE_STRING;
397         break;
398
399     case ACPI_DMT_BUFFER:
400     case ACPI_DMT_BUF7:
401     case ACPI_DMT_BUF16:
402     case ACPI_DMT_BUF128:
403     case ACPI_DMT_PCI_PATH:
404         Type = DT_FIELD_TYPE_BUFFER;
405         break;
406
407     case ACPI_DMT_GAS:
408     case ACPI_DMT_HESTNTFY:
409         Type = DT_FIELD_TYPE_INLINE_SUBTABLE;
410         break;
411
412     case ACPI_DMT_UNICODE:
413         Type = DT_FIELD_TYPE_UNICODE;
414         break;
415
416     case ACPI_DMT_UUID:
417         Type = DT_FIELD_TYPE_UUID;
418         break;
419
420     case ACPI_DMT_DEVICE_PATH:
421         Type = DT_FIELD_TYPE_DEVICE_PATH;
422         break;
423
424     case ACPI_DMT_LABEL:
425         Type = DT_FIELD_TYPE_LABEL;
426         break;
427
428     default:
429         Type = DT_FIELD_TYPE_INTEGER;
430         break;
431     }
432
433     return (Type);
434 }
435
436
437 /******************************************************************************
438  *
439  * FUNCTION:    DtGetBufferLength
440  *
441  * PARAMETERS:  Buffer              - List of integers,
442  *                                    for example "10 3A 4F 2E"
443  *
444  * RETURN:      Count of integer
445  *
446  * DESCRIPTION: Get length of bytes needed to store the integers
447  *
448  *****************************************************************************/
449
450 UINT32
451 DtGetBufferLength (
452     char                    *Buffer)
453 {
454     UINT32                  ByteLength = 0;
455
456
457     while (*Buffer)
458     {
459         if (*Buffer == ' ')
460         {
461             ByteLength++;
462
463             while (*Buffer == ' ')
464             {
465                 Buffer++;
466             }
467         }
468
469         Buffer++;
470     }
471
472     return (++ByteLength);
473 }
474
475
476 /******************************************************************************
477  *
478  * FUNCTION:    DtGetFieldLength
479  *
480  * PARAMETERS:  Field               - Current field
481  *              Info                - Data table info
482  *
483  * RETURN:      Field length
484  *
485  * DESCRIPTION: Get length of bytes needed to compile the field
486  *
487  * Note: This function must remain in sync with AcpiDmDumpTable.
488  *
489  *****************************************************************************/
490
491 UINT32
492 DtGetFieldLength (
493     DT_FIELD                *Field,
494     ACPI_DMTABLE_INFO       *Info)
495 {
496     UINT32                  ByteLength = 0;
497     char                    *Value;
498
499
500     /* Length is based upon the opcode for this field in the info table */
501
502     switch (Info->Opcode)
503     {
504     case ACPI_DMT_FLAG0:
505     case ACPI_DMT_FLAG1:
506     case ACPI_DMT_FLAG2:
507     case ACPI_DMT_FLAG3:
508     case ACPI_DMT_FLAG4:
509     case ACPI_DMT_FLAG5:
510     case ACPI_DMT_FLAG6:
511     case ACPI_DMT_FLAG7:
512     case ACPI_DMT_FLAGS0:
513     case ACPI_DMT_FLAGS2:
514     case ACPI_DMT_LABEL:
515         ByteLength = 0;
516         break;
517
518     case ACPI_DMT_UINT8:
519     case ACPI_DMT_CHKSUM:
520     case ACPI_DMT_SPACEID:
521     case ACPI_DMT_ACCWIDTH:
522     case ACPI_DMT_IVRS:
523     case ACPI_DMT_MADT:
524     case ACPI_DMT_SRAT:
525     case ACPI_DMT_ASF:
526     case ACPI_DMT_HESTNTYP:
527     case ACPI_DMT_FADTPM:
528     case ACPI_DMT_EINJACT:
529     case ACPI_DMT_EINJINST:
530     case ACPI_DMT_ERSTACT:
531     case ACPI_DMT_ERSTINST:
532         ByteLength = 1;
533         break;
534
535     case ACPI_DMT_UINT16:
536     case ACPI_DMT_DMAR:
537     case ACPI_DMT_HEST:
538     case ACPI_DMT_PCI_PATH:
539         ByteLength = 2;
540         break;
541
542     case ACPI_DMT_UINT24:
543         ByteLength = 3;
544         break;
545
546     case ACPI_DMT_UINT32:
547     case ACPI_DMT_NAME4:
548     case ACPI_DMT_SLIC:
549     case ACPI_DMT_SIG:
550         ByteLength = 4;
551         break;
552
553     case ACPI_DMT_NAME6:
554         ByteLength = 6;
555         break;
556
557     case ACPI_DMT_UINT56:
558     case ACPI_DMT_BUF7:
559         ByteLength = 7;
560         break;
561
562     case ACPI_DMT_UINT64:
563     case ACPI_DMT_NAME8:
564         ByteLength = 8;
565         break;
566
567     case ACPI_DMT_STRING:
568         Value = DtGetFieldValue (Field);
569         if (Value)
570         {
571             ByteLength = ACPI_STRLEN (Value) + 1;
572         }
573         else
574         {   /* At this point, this is a fatal error */
575
576             sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
577             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
578             return (0);
579         }
580         break;
581
582     case ACPI_DMT_GAS:
583         ByteLength = sizeof (ACPI_GENERIC_ADDRESS);
584         break;
585
586     case ACPI_DMT_HESTNTFY:
587         ByteLength = sizeof (ACPI_HEST_NOTIFY);
588         break;
589
590     case ACPI_DMT_BUFFER:
591         Value = DtGetFieldValue (Field);
592         if (Value)
593         {
594             ByteLength = DtGetBufferLength (Value);
595         }
596         else
597         {   /* At this point, this is a fatal error */
598
599             sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
600             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
601             return (0);
602         }
603         break;
604
605     case ACPI_DMT_BUF16:
606     case ACPI_DMT_UUID:
607         ByteLength = 16;
608         break;
609
610     case ACPI_DMT_BUF128:
611         ByteLength = 128;
612         break;
613
614     case ACPI_DMT_UNICODE:
615         Value = DtGetFieldValue (Field);
616
617         /* TBD: error if Value is NULL? (as below?) */
618
619         ByteLength = (ACPI_STRLEN (Value) + 1) * sizeof(UINT16);
620         break;
621
622     default:
623         DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode");
624         return (0);
625     }
626
627     return (ByteLength);
628 }
629
630
631 /******************************************************************************
632  *
633  * FUNCTION:    DtSum
634  *
635  * PARAMETERS:  DT_WALK_CALLBACK:
636  *              Subtable            - Subtable
637  *              Context             - Unused
638  *              ReturnValue         - Store the checksum of subtable
639  *
640  * RETURN:      Status
641  *
642  * DESCRIPTION: Get the checksum of subtable
643  *
644  *****************************************************************************/
645
646 static void
647 DtSum (
648     DT_SUBTABLE             *Subtable,
649     void                    *Context,
650     void                    *ReturnValue)
651 {
652     UINT8                   Checksum;
653     UINT8                   *Sum = ReturnValue;
654
655
656     Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length);
657     *Sum = (UINT8) (*Sum + Checksum);
658 }
659
660
661 /******************************************************************************
662  *
663  * FUNCTION:    DtSetTableChecksum
664  *
665  * PARAMETERS:  ChecksumPointer     - Where to return the checksum
666  *
667  * RETURN:      None
668  *
669  * DESCRIPTION: Set checksum of the whole data table into the checksum field
670  *
671  *****************************************************************************/
672
673 void
674 DtSetTableChecksum (
675     UINT8                   *ChecksumPointer)
676 {
677     UINT8                   Checksum = 0;
678     UINT8                   OldSum;
679
680
681     DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum);
682
683     OldSum = *ChecksumPointer;
684     Checksum = (UINT8) (Checksum - OldSum);
685
686     /* Compute the final checksum */
687
688     Checksum = (UINT8) (0 - Checksum);
689     *ChecksumPointer = Checksum;
690 }
691
692
693 /******************************************************************************
694  *
695  * FUNCTION:    DtSetTableLength
696  *
697  * PARAMETERS:  None
698  *
699  * RETURN:      None
700  *
701  * DESCRIPTION: Walk the subtables and set all the length fields
702  *
703  *****************************************************************************/
704
705 void
706 DtSetTableLength (
707     void)
708 {
709     DT_SUBTABLE             *ParentTable;
710     DT_SUBTABLE             *ChildTable;
711
712
713     ParentTable = Gbl_RootTable;
714     ChildTable = NULL;
715
716     if (!ParentTable)
717     {
718         return;
719     }
720
721     DtSetSubtableLength (ParentTable);
722
723     while (1)
724     {
725         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
726         if (ChildTable)
727         {
728             if (ChildTable->LengthField)
729             {
730                 DtSetSubtableLength (ChildTable);
731             }
732
733             if (ChildTable->Child)
734             {
735                 ParentTable = ChildTable;
736                 ChildTable = NULL;
737             }
738             else
739             {
740                 ParentTable->TotalLength += ChildTable->TotalLength;
741                 if (ParentTable->LengthField)
742                 {
743                     DtSetSubtableLength (ParentTable);
744                 }
745             }
746         }
747         else
748         {
749             ChildTable = ParentTable;
750
751             if (ChildTable == Gbl_RootTable)
752             {
753                 break;
754             }
755
756             ParentTable = DtGetParentSubtable (ParentTable);
757
758             ParentTable->TotalLength += ChildTable->TotalLength;
759             if (ParentTable->LengthField)
760             {
761                 DtSetSubtableLength (ParentTable);
762             }
763         }
764     }
765 }
766
767
768 /******************************************************************************
769  *
770  * FUNCTION:    DtWalkTableTree
771  *
772  * PARAMETERS:  StartTable          - Subtable in the tree where walking begins
773  *              UserFunction        - Called during the walk
774  *              Context             - Passed to user function
775  *              ReturnValue         - The return value of UserFunction
776  *
777  * RETURN:      None
778  *
779  * DESCRIPTION: Performs a depth-first walk of the subtable tree
780  *
781  *****************************************************************************/
782
783 void
784 DtWalkTableTree (
785     DT_SUBTABLE             *StartTable,
786     DT_WALK_CALLBACK        UserFunction,
787     void                    *Context,
788     void                    *ReturnValue)
789 {
790     DT_SUBTABLE             *ParentTable;
791     DT_SUBTABLE             *ChildTable;
792
793
794     ParentTable = StartTable;
795     ChildTable = NULL;
796
797     if (!ParentTable)
798     {
799         return;
800     }
801
802     UserFunction (ParentTable, Context, ReturnValue);
803
804     while (1)
805     {
806         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
807         if (ChildTable)
808         {
809             UserFunction (ChildTable, Context, ReturnValue);
810
811             if (ChildTable->Child)
812             {
813                 ParentTable = ChildTable;
814                 ChildTable = NULL;
815             }
816         }
817         else
818         {
819             ChildTable = ParentTable;
820             if (ChildTable == Gbl_RootTable)
821             {
822                 break;
823             }
824
825             ParentTable = DtGetParentSubtable (ParentTable);
826
827             if (ChildTable->Peer == StartTable)
828             {
829                 break;
830             }
831         }
832     }
833 }
834
835
836 /******************************************************************************
837  *
838  * FUNCTION:    DtFreeFieldList
839  *
840  * PARAMETERS:  None
841  *
842  * RETURN:      None
843  *
844  * DESCRIPTION: Free the field list
845  *
846  *****************************************************************************/
847
848 void
849 DtFreeFieldList (
850     void)
851 {
852     DT_FIELD                *Field = Gbl_FieldList;
853     DT_FIELD                *NextField;
854
855
856     /* Walk and free entire field list */
857
858     while (Field)
859     {
860         NextField = Field->Next; /* Save link */
861
862         if (!(Field->Flags & DT_FIELD_NOT_ALLOCATED))
863         {
864             ACPI_FREE (Field->Name);
865             ACPI_FREE (Field->Value);
866         }
867
868         ACPI_FREE (Field);
869         Field = NextField;
870     }
871 }