1/******************************************************************************
2 *
3 * Module Name: dtutils.c - Utility routines for the data table compiler
4 *
5 *****************************************************************************/
6
7/******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2016, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************/
115
116#include "aslcompiler.h"
117#include "dtcompiler.h"
118#include "actables.h"
119
120#define _COMPONENT          DT_COMPILER
121        ACPI_MODULE_NAME    ("dtutils")
122
123/* Local prototypes */
124
125static void
126DtSum (
127    DT_SUBTABLE             *Subtable,
128    void                    *Context,
129    void                    *ReturnValue);
130
131
132/******************************************************************************
133 *
134 * FUNCTION:    DtError
135 *
136 * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
137 *              MessageId           - Index into global message buffer
138 *              Op                  - Parse node where error happened
139 *              ExtraMessage        - additional error message
140 *
141 * RETURN:      None
142 *
143 * DESCRIPTION: Common error interface for data table compiler
144 *
145 *****************************************************************************/
146
147void
148DtError (
149    UINT8                   Level,
150    UINT16                  MessageId,
151    DT_FIELD                *FieldObject,
152    char                    *ExtraMessage)
153{
154
155    /* Check if user wants to ignore this exception */
156
157    if (AslIsExceptionDisabled (Level, MessageId))
158    {
159        return;
160    }
161
162    if (FieldObject)
163    {
164        AslCommonError (Level, MessageId,
165            FieldObject->Line,
166            FieldObject->Line,
167            FieldObject->ByteOffset,
168            FieldObject->Column,
169            Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
170    }
171    else
172    {
173        AslCommonError (Level, MessageId, 0,
174            0, 0, 0, 0, ExtraMessage);
175    }
176}
177
178
179/******************************************************************************
180 *
181 * FUNCTION:    DtNameError
182 *
183 * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
184 *              MessageId           - Index into global message buffer
185 *              Op                  - Parse node where error happened
186 *              ExtraMessage        - additional error message
187 *
188 * RETURN:      None
189 *
190 * DESCRIPTION: Error interface for named objects
191 *
192 *****************************************************************************/
193
194void
195DtNameError (
196    UINT8                   Level,
197    UINT16                  MessageId,
198    DT_FIELD                *FieldObject,
199    char                    *ExtraMessage)
200{
201
202    switch (Level)
203    {
204    case ASL_WARNING2:
205    case ASL_WARNING3:
206
207        if (Gbl_WarningLevel < Level)
208        {
209            return;
210        }
211        break;
212
213    default:
214
215        break;
216    }
217
218    if (FieldObject)
219    {
220        AslCommonError (Level, MessageId,
221            FieldObject->Line,
222            FieldObject->Line,
223            FieldObject->ByteOffset,
224            FieldObject->NameColumn,
225            Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
226    }
227    else
228    {
229        AslCommonError (Level, MessageId, 0,
230            0, 0, 0, 0, ExtraMessage);
231    }
232}
233
234
235/*******************************************************************************
236 *
237 * FUNCTION:    DtFatal
238 *
239 * PARAMETERS:  None
240 *
241 * RETURN:      None
242 *
243 * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
244 *              compile or I/O errors
245 *
246 ******************************************************************************/
247
248void
249DtFatal (
250    UINT16                  MessageId,
251    DT_FIELD                *FieldObject,
252    char                    *ExtraMessage)
253{
254
255    DtError (ASL_ERROR, MessageId, FieldObject, ExtraMessage);
256
257/*
258 * TBD: remove this entire function, DtFatal
259 *
260 * We cannot abort the compiler on error, because we may be compiling a
261 * list of files. We must move on to the next file.
262 */
263#ifdef __OBSOLETE
264    CmCleanupAndExit ();
265    exit (1);
266#endif
267}
268
269
270/******************************************************************************
271 *
272 * FUNCTION:    DtStrtoul64
273 *
274 * PARAMETERS:  String              - Null terminated string
275 *              ReturnInteger       - Where the converted integer is returned
276 *
277 * RETURN:      Status
278 *
279 * DESCRIPTION: Simple conversion of a string hex integer constant to unsigned
280 *              value. Assumes no leading "0x" for the constant.
281 *
282 * Portability note: The reason this function exists is because a 64-bit
283 * sscanf is not available in all environments.
284 *
285 *****************************************************************************/
286
287ACPI_STATUS
288DtStrtoul64 (
289    char                    *String,
290    UINT64                  *ReturnInteger)
291{
292    char                    *ThisChar = String;
293    UINT32                  ThisDigit;
294    UINT64                  ReturnValue = 0;
295    int                     DigitCount = 0;
296
297
298    /* Skip over any white space in the buffer */
299
300    while ((*ThisChar == ' ') || (*ThisChar == '\t'))
301    {
302        ThisChar++;
303    }
304
305    /* Skip leading zeros */
306
307    while ((*ThisChar) == '0')
308    {
309        ThisChar++;
310    }
311
312    /* Convert character-by-character */
313
314    while (*ThisChar)
315    {
316        if (isdigit ((int) *ThisChar))
317        {
318            /* Convert ASCII 0-9 to Decimal value */
319
320            ThisDigit = ((UINT8) *ThisChar) - '0';
321        }
322        else /* Letter */
323        {
324            ThisDigit = (UINT32) toupper ((int) *ThisChar);
325            if (!isxdigit ((int) ThisDigit))
326            {
327                /* Not A-F */
328
329                return (AE_BAD_CHARACTER);
330            }
331
332            /* Convert ASCII Hex char (A-F) to value */
333
334            ThisDigit = (ThisDigit - 'A') + 10;
335        }
336
337        /* Insert the 4-bit hex digit */
338
339        ReturnValue <<= 4;
340        ReturnValue += ThisDigit;
341
342        ThisChar++;
343        DigitCount++;
344        if (DigitCount > 16)
345        {
346            /* Value is too large (> 64 bits/8 bytes/16 hex digits) */
347
348            return (AE_LIMIT);
349        }
350    }
351
352    *ReturnInteger = ReturnValue;
353    return (AE_OK);
354}
355
356
357/******************************************************************************
358 *
359 * FUNCTION:    DtGetFieldValue
360 *
361 * PARAMETERS:  Field               - Current field list pointer
362 *
363 * RETURN:      Field value
364 *
365 * DESCRIPTION: Get field value
366 *
367 *****************************************************************************/
368
369char *
370DtGetFieldValue (
371    DT_FIELD                *Field)
372{
373    if (!Field)
374    {
375        return (NULL);
376    }
377
378    return (Field->Value);
379}
380
381
382/******************************************************************************
383 *
384 * FUNCTION:    DtGetFieldType
385 *
386 * PARAMETERS:  Info                - Data table info
387 *
388 * RETURN:      Field type
389 *
390 * DESCRIPTION: Get field type
391 *
392 *****************************************************************************/
393
394UINT8
395DtGetFieldType (
396    ACPI_DMTABLE_INFO       *Info)
397{
398    UINT8                   Type;
399
400
401    /* DT_FLAG means that this is the start of a block of flag bits */
402    /* TBD - we can make these a separate opcode later */
403
404    if (Info->Flags & DT_FLAG)
405    {
406        return (DT_FIELD_TYPE_FLAGS_INTEGER);
407    }
408
409    /* Type is based upon the opcode for this field in the info table */
410
411    switch (Info->Opcode)
412    {
413    case ACPI_DMT_FLAG0:
414    case ACPI_DMT_FLAG1:
415    case ACPI_DMT_FLAG2:
416    case ACPI_DMT_FLAG3:
417    case ACPI_DMT_FLAG4:
418    case ACPI_DMT_FLAG5:
419    case ACPI_DMT_FLAG6:
420    case ACPI_DMT_FLAG7:
421    case ACPI_DMT_FLAGS0:
422    case ACPI_DMT_FLAGS1:
423    case ACPI_DMT_FLAGS2:
424    case ACPI_DMT_FLAGS4:
425
426        Type = DT_FIELD_TYPE_FLAG;
427        break;
428
429    case ACPI_DMT_NAME4:
430    case ACPI_DMT_SIG:
431    case ACPI_DMT_NAME6:
432    case ACPI_DMT_NAME8:
433    case ACPI_DMT_STRING:
434
435        Type = DT_FIELD_TYPE_STRING;
436        break;
437
438    case ACPI_DMT_BUFFER:
439    case ACPI_DMT_RAW_BUFFER:
440    case ACPI_DMT_BUF7:
441    case ACPI_DMT_BUF10:
442    case ACPI_DMT_BUF12:
443    case ACPI_DMT_BUF16:
444    case ACPI_DMT_BUF128:
445    case ACPI_DMT_PCI_PATH:
446
447        Type = DT_FIELD_TYPE_BUFFER;
448        break;
449
450    case ACPI_DMT_GAS:
451    case ACPI_DMT_HESTNTFY:
452    case ACPI_DMT_IORTMEM:
453
454        Type = DT_FIELD_TYPE_INLINE_SUBTABLE;
455        break;
456
457    case ACPI_DMT_UNICODE:
458
459        Type = DT_FIELD_TYPE_UNICODE;
460        break;
461
462    case ACPI_DMT_UUID:
463
464        Type = DT_FIELD_TYPE_UUID;
465        break;
466
467    case ACPI_DMT_DEVICE_PATH:
468
469        Type = DT_FIELD_TYPE_DEVICE_PATH;
470        break;
471
472    case ACPI_DMT_LABEL:
473
474        Type = DT_FIELD_TYPE_LABEL;
475        break;
476
477    default:
478
479        Type = DT_FIELD_TYPE_INTEGER;
480        break;
481    }
482
483    return (Type);
484}
485
486
487/******************************************************************************
488 *
489 * FUNCTION:    DtGetBufferLength
490 *
491 * PARAMETERS:  Buffer              - List of integers,
492 *                                    for example "10 3A 4F 2E"
493 *
494 * RETURN:      Count of integer
495 *
496 * DESCRIPTION: Get length of bytes needed to store the integers
497 *
498 *****************************************************************************/
499
500UINT32
501DtGetBufferLength (
502    char                    *Buffer)
503{
504    UINT32                  ByteLength = 0;
505
506
507    while (*Buffer)
508    {
509        if (*Buffer == ' ')
510        {
511            ByteLength++;
512
513            while (*Buffer == ' ')
514            {
515                Buffer++;
516            }
517        }
518
519        Buffer++;
520    }
521
522    return (++ByteLength);
523}
524
525
526/******************************************************************************
527 *
528 * FUNCTION:    DtGetFieldLength
529 *
530 * PARAMETERS:  Field               - Current field
531 *              Info                - Data table info
532 *
533 * RETURN:      Field length
534 *
535 * DESCRIPTION: Get length of bytes needed to compile the field
536 *
537 * Note: This function must remain in sync with AcpiDmDumpTable.
538 *
539 *****************************************************************************/
540
541UINT32
542DtGetFieldLength (
543    DT_FIELD                *Field,
544    ACPI_DMTABLE_INFO       *Info)
545{
546    UINT32                  ByteLength = 0;
547    char                    *Value;
548
549
550    /* Length is based upon the opcode for this field in the info table */
551
552    switch (Info->Opcode)
553    {
554    case ACPI_DMT_FLAG0:
555    case ACPI_DMT_FLAG1:
556    case ACPI_DMT_FLAG2:
557    case ACPI_DMT_FLAG3:
558    case ACPI_DMT_FLAG4:
559    case ACPI_DMT_FLAG5:
560    case ACPI_DMT_FLAG6:
561    case ACPI_DMT_FLAG7:
562    case ACPI_DMT_FLAGS0:
563    case ACPI_DMT_FLAGS1:
564    case ACPI_DMT_FLAGS2:
565    case ACPI_DMT_FLAGS4:
566    case ACPI_DMT_LABEL:
567    case ACPI_DMT_EXTRA_TEXT:
568
569        ByteLength = 0;
570        break;
571
572    case ACPI_DMT_UINT8:
573    case ACPI_DMT_CHKSUM:
574    case ACPI_DMT_SPACEID:
575    case ACPI_DMT_ACCWIDTH:
576    case ACPI_DMT_IVRS:
577    case ACPI_DMT_GTDT:
578    case ACPI_DMT_MADT:
579    case ACPI_DMT_PCCT:
580    case ACPI_DMT_PMTT:
581    case ACPI_DMT_SRAT:
582    case ACPI_DMT_ASF:
583    case ACPI_DMT_HESTNTYP:
584    case ACPI_DMT_FADTPM:
585    case ACPI_DMT_EINJACT:
586    case ACPI_DMT_EINJINST:
587    case ACPI_DMT_ERSTACT:
588    case ACPI_DMT_ERSTINST:
589    case ACPI_DMT_DMAR_SCOPE:
590
591        ByteLength = 1;
592        break;
593
594    case ACPI_DMT_UINT16:
595    case ACPI_DMT_DMAR:
596    case ACPI_DMT_HEST:
597    case ACPI_DMT_NFIT:
598    case ACPI_DMT_PCI_PATH:
599
600        ByteLength = 2;
601        break;
602
603    case ACPI_DMT_UINT24:
604
605        ByteLength = 3;
606        break;
607
608    case ACPI_DMT_UINT32:
609    case ACPI_DMT_NAME4:
610    case ACPI_DMT_SIG:
611    case ACPI_DMT_LPIT:
612
613        ByteLength = 4;
614        break;
615
616    case ACPI_DMT_UINT40:
617
618        ByteLength = 5;
619        break;
620
621    case ACPI_DMT_UINT48:
622    case ACPI_DMT_NAME6:
623
624        ByteLength = 6;
625        break;
626
627    case ACPI_DMT_UINT56:
628    case ACPI_DMT_BUF7:
629
630        ByteLength = 7;
631        break;
632
633    case ACPI_DMT_UINT64:
634    case ACPI_DMT_NAME8:
635
636        ByteLength = 8;
637        break;
638
639    case ACPI_DMT_STRING:
640
641        Value = DtGetFieldValue (Field);
642        if (Value)
643        {
644            ByteLength = strlen (Value) + 1;
645        }
646        else
647        {   /* At this point, this is a fatal error */
648
649            sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
650            DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
651            return (0);
652        }
653        break;
654
655    case ACPI_DMT_GAS:
656
657        ByteLength = sizeof (ACPI_GENERIC_ADDRESS);
658        break;
659
660    case ACPI_DMT_HESTNTFY:
661
662        ByteLength = sizeof (ACPI_HEST_NOTIFY);
663        break;
664
665    case ACPI_DMT_IORTMEM:
666
667        ByteLength = sizeof (ACPI_IORT_MEMORY_ACCESS);
668        break;
669
670    case ACPI_DMT_BUFFER:
671    case ACPI_DMT_RAW_BUFFER:
672
673        Value = DtGetFieldValue (Field);
674        if (Value)
675        {
676            ByteLength = DtGetBufferLength (Value);
677        }
678        else
679        {   /* At this point, this is a fatal error */
680
681            sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
682            DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
683            return (0);
684        }
685        break;
686
687    case ACPI_DMT_BUF10:
688
689        ByteLength = 10;
690        break;
691
692    case ACPI_DMT_BUF12:
693
694        ByteLength = 12;
695        break;
696
697    case ACPI_DMT_BUF16:
698    case ACPI_DMT_UUID:
699
700        ByteLength = 16;
701        break;
702
703    case ACPI_DMT_BUF128:
704
705        ByteLength = 128;
706        break;
707
708    case ACPI_DMT_UNICODE:
709
710        Value = DtGetFieldValue (Field);
711
712        /* TBD: error if Value is NULL? (as below?) */
713
714        ByteLength = (strlen (Value) + 1) * sizeof(UINT16);
715        break;
716
717    default:
718
719        DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode");
720        return (0);
721    }
722
723    return (ByteLength);
724}
725
726
727/******************************************************************************
728 *
729 * FUNCTION:    DtSum
730 *
731 * PARAMETERS:  DT_WALK_CALLBACK:
732 *              Subtable            - Subtable
733 *              Context             - Unused
734 *              ReturnValue         - Store the checksum of subtable
735 *
736 * RETURN:      Status
737 *
738 * DESCRIPTION: Get the checksum of subtable
739 *
740 *****************************************************************************/
741
742static void
743DtSum (
744    DT_SUBTABLE             *Subtable,
745    void                    *Context,
746    void                    *ReturnValue)
747{
748    UINT8                   Checksum;
749    UINT8                   *Sum = ReturnValue;
750
751
752    Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length);
753    *Sum = (UINT8) (*Sum + Checksum);
754}
755
756
757/******************************************************************************
758 *
759 * FUNCTION:    DtSetTableChecksum
760 *
761 * PARAMETERS:  ChecksumPointer     - Where to return the checksum
762 *
763 * RETURN:      None
764 *
765 * DESCRIPTION: Set checksum of the whole data table into the checksum field
766 *
767 *****************************************************************************/
768
769void
770DtSetTableChecksum (
771    UINT8                   *ChecksumPointer)
772{
773    UINT8                   Checksum = 0;
774    UINT8                   OldSum;
775
776
777    DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum);
778
779    OldSum = *ChecksumPointer;
780    Checksum = (UINT8) (Checksum - OldSum);
781
782    /* Compute the final checksum */
783
784    Checksum = (UINT8) (0 - Checksum);
785    *ChecksumPointer = Checksum;
786}
787
788
789/******************************************************************************
790 *
791 * FUNCTION:    DtSetTableLength
792 *
793 * PARAMETERS:  None
794 *
795 * RETURN:      None
796 *
797 * DESCRIPTION: Walk the subtables and set all the length fields
798 *
799 *****************************************************************************/
800
801void
802DtSetTableLength (
803    void)
804{
805    DT_SUBTABLE             *ParentTable;
806    DT_SUBTABLE             *ChildTable;
807
808
809    ParentTable = Gbl_RootTable;
810    ChildTable = NULL;
811
812    if (!ParentTable)
813    {
814        return;
815    }
816
817    DtSetSubtableLength (ParentTable);
818
819    while (1)
820    {
821        ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
822        if (ChildTable)
823        {
824            if (ChildTable->LengthField)
825            {
826                DtSetSubtableLength (ChildTable);
827            }
828
829            if (ChildTable->Child)
830            {
831                ParentTable = ChildTable;
832                ChildTable = NULL;
833            }
834            else
835            {
836                ParentTable->TotalLength += ChildTable->TotalLength;
837                if (ParentTable->LengthField)
838                {
839                    DtSetSubtableLength (ParentTable);
840                }
841            }
842        }
843        else
844        {
845            ChildTable = ParentTable;
846
847            if (ChildTable == Gbl_RootTable)
848            {
849                break;
850            }
851
852            ParentTable = DtGetParentSubtable (ParentTable);
853
854            ParentTable->TotalLength += ChildTable->TotalLength;
855            if (ParentTable->LengthField)
856            {
857                DtSetSubtableLength (ParentTable);
858            }
859        }
860    }
861}
862
863
864/******************************************************************************
865 *
866 * FUNCTION:    DtWalkTableTree
867 *
868 * PARAMETERS:  StartTable          - Subtable in the tree where walking begins
869 *              UserFunction        - Called during the walk
870 *              Context             - Passed to user function
871 *              ReturnValue         - The return value of UserFunction
872 *
873 * RETURN:      None
874 *
875 * DESCRIPTION: Performs a depth-first walk of the subtable tree
876 *
877 *****************************************************************************/
878
879void
880DtWalkTableTree (
881    DT_SUBTABLE             *StartTable,
882    DT_WALK_CALLBACK        UserFunction,
883    void                    *Context,
884    void                    *ReturnValue)
885{
886    DT_SUBTABLE             *ParentTable;
887    DT_SUBTABLE             *ChildTable;
888
889
890    ParentTable = StartTable;
891    ChildTable = NULL;
892
893    if (!ParentTable)
894    {
895        return;
896    }
897
898    UserFunction (ParentTable, Context, ReturnValue);
899
900    while (1)
901    {
902        ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
903        if (ChildTable)
904        {
905            UserFunction (ChildTable, Context, ReturnValue);
906
907            if (ChildTable->Child)
908            {
909                ParentTable = ChildTable;
910                ChildTable = NULL;
911            }
912        }
913        else
914        {
915            ChildTable = ParentTable;
916            if (ChildTable == Gbl_RootTable)
917            {
918                break;
919            }
920
921            ParentTable = DtGetParentSubtable (ParentTable);
922
923            if (ChildTable->Peer == StartTable)
924            {
925                break;
926            }
927        }
928    }
929}
930
931
932/*******************************************************************************
933 *
934 * FUNCTION:    UtSubtableCacheCalloc
935 *
936 * PARAMETERS:  None
937 *
938 * RETURN:      Pointer to the buffer. Aborts on allocation failure
939 *
940 * DESCRIPTION: Allocate a subtable object buffer. Bypass the local
941 *              dynamic memory manager for performance reasons (This has a
942 *              major impact on the speed of the compiler.)
943 *
944 ******************************************************************************/
945
946DT_SUBTABLE *
947UtSubtableCacheCalloc (
948    void)
949{
950    ASL_CACHE_INFO          *Cache;
951
952
953    if (Gbl_SubtableCacheNext >= Gbl_SubtableCacheLast)
954    {
955        /* Allocate a new buffer */
956
957        Cache = UtLocalCalloc (sizeof (Cache->Next) +
958            (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE));
959
960        /* Link new cache buffer to head of list */
961
962        Cache->Next = Gbl_SubtableCacheList;
963        Gbl_SubtableCacheList = Cache;
964
965        /* Setup cache management pointers */
966
967        Gbl_SubtableCacheNext = ACPI_CAST_PTR (DT_SUBTABLE, Cache->Buffer);
968        Gbl_SubtableCacheLast = Gbl_SubtableCacheNext + ASL_SUBTABLE_CACHE_SIZE;
969    }
970
971    Gbl_SubtableCount++;
972    return (Gbl_SubtableCacheNext++);
973}
974
975
976/*******************************************************************************
977 *
978 * FUNCTION:    UtFieldCacheCalloc
979 *
980 * PARAMETERS:  None
981 *
982 * RETURN:      Pointer to the buffer. Aborts on allocation failure
983 *
984 * DESCRIPTION: Allocate a field object buffer. Bypass the local
985 *              dynamic memory manager for performance reasons (This has a
986 *              major impact on the speed of the compiler.)
987 *
988 ******************************************************************************/
989
990DT_FIELD *
991UtFieldCacheCalloc (
992    void)
993{
994    ASL_CACHE_INFO          *Cache;
995
996
997    if (Gbl_FieldCacheNext >= Gbl_FieldCacheLast)
998    {
999        /* Allocate a new buffer */
1000
1001        Cache = UtLocalCalloc (sizeof (Cache->Next) +
1002            (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE));
1003
1004        /* Link new cache buffer to head of list */
1005
1006        Cache->Next = Gbl_FieldCacheList;
1007        Gbl_FieldCacheList = Cache;
1008
1009        /* Setup cache management pointers */
1010
1011        Gbl_FieldCacheNext = ACPI_CAST_PTR (DT_FIELD, Cache->Buffer);
1012        Gbl_FieldCacheLast = Gbl_FieldCacheNext + ASL_FIELD_CACHE_SIZE;
1013    }
1014
1015    Gbl_FieldCount++;
1016    return (Gbl_FieldCacheNext++);
1017}
1018
1019
1020/*******************************************************************************
1021 *
1022 * FUNCTION:    DtDeleteCaches
1023 *
1024 * PARAMETERS:  None
1025 *
1026 * RETURN:      None
1027 *
1028 * DESCRIPTION: Delete all local cache buffer blocks
1029 *
1030 ******************************************************************************/
1031
1032void
1033DtDeleteCaches (
1034    void)
1035{
1036    UINT32                  BufferCount;
1037    ASL_CACHE_INFO          *Next;
1038
1039
1040    /* Field cache */
1041
1042    BufferCount = 0;
1043    while (Gbl_FieldCacheList)
1044    {
1045        Next = Gbl_FieldCacheList->Next;
1046        ACPI_FREE (Gbl_FieldCacheList);
1047        Gbl_FieldCacheList = Next;
1048        BufferCount++;
1049    }
1050
1051    DbgPrint (ASL_DEBUG_OUTPUT,
1052        "%u Fields, Buffer size: %u fields (%u bytes), %u Buffers\n",
1053        Gbl_FieldCount, ASL_FIELD_CACHE_SIZE,
1054        (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE), BufferCount);
1055
1056    Gbl_FieldCount = 0;
1057    Gbl_FieldCacheNext = NULL;
1058    Gbl_FieldCacheLast = NULL;
1059
1060    /* Subtable cache */
1061
1062    BufferCount = 0;
1063    while (Gbl_SubtableCacheList)
1064    {
1065        Next = Gbl_SubtableCacheList->Next;
1066        ACPI_FREE (Gbl_SubtableCacheList);
1067        Gbl_SubtableCacheList = Next;
1068        BufferCount++;
1069    }
1070
1071    DbgPrint (ASL_DEBUG_OUTPUT,
1072        "%u Subtables, Buffer size: %u subtables (%u bytes), %u Buffers\n",
1073        Gbl_SubtableCount, ASL_SUBTABLE_CACHE_SIZE,
1074        (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE), BufferCount);
1075
1076    Gbl_SubtableCount = 0;
1077    Gbl_SubtableCacheNext = NULL;
1078    Gbl_SubtableCacheLast = NULL;
1079}
1080