Home | History | Annotate | Line # | Download | only in compiler
dtutils.c revision 1.3
      1 /******************************************************************************
      2  *
      3  * Module Name: dtutils.c - Utility routines for the data table compiler
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2014, 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 "aslcompiler.h"
     47 #include "dtcompiler.h"
     48 #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     UINT16                  MessageId,
     81     DT_FIELD                *FieldObject,
     82     char                    *ExtraMessage)
     83 {
     84 
     85     /* Check if user wants to ignore this exception */
     86 
     87     if (AslIsExceptionDisabled (Level, MessageId))
     88     {
     89         return;
     90     }
     91 
     92     if (FieldObject)
     93     {
     94         AslCommonError (Level, MessageId,
     95             FieldObject->Line,
     96             FieldObject->Line,
     97             FieldObject->ByteOffset,
     98             FieldObject->Column,
     99             Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
    100     }
    101     else
    102     {
    103         AslCommonError (Level, MessageId, 0,
    104             0, 0, 0, 0, ExtraMessage);
    105     }
    106 }
    107 
    108 
    109 /******************************************************************************
    110  *
    111  * FUNCTION:    DtNameError
    112  *
    113  * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
    114  *              MessageId           - Index into global message buffer
    115  *              Op                  - Parse node where error happened
    116  *              ExtraMessage        - additional error message
    117  *
    118  * RETURN:      None
    119  *
    120  * DESCRIPTION: Error interface for named objects
    121  *
    122  *****************************************************************************/
    123 
    124 void
    125 DtNameError (
    126     UINT8                   Level,
    127     UINT16                  MessageId,
    128     DT_FIELD                *FieldObject,
    129     char                    *ExtraMessage)
    130 {
    131 
    132     switch (Level)
    133     {
    134     case ASL_WARNING2:
    135     case ASL_WARNING3:
    136 
    137         if (Gbl_WarningLevel < Level)
    138         {
    139             return;
    140         }
    141         break;
    142 
    143     default:
    144 
    145         break;
    146     }
    147 
    148     if (FieldObject)
    149     {
    150         AslCommonError (Level, MessageId,
    151             FieldObject->Line,
    152             FieldObject->Line,
    153             FieldObject->ByteOffset,
    154             FieldObject->NameColumn,
    155             Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
    156     }
    157     else
    158     {
    159         AslCommonError (Level, MessageId, 0,
    160             0, 0, 0, 0, ExtraMessage);
    161     }
    162 }
    163 
    164 
    165 /*******************************************************************************
    166  *
    167  * FUNCTION:    DtFatal
    168  *
    169  * PARAMETERS:  None
    170  *
    171  * RETURN:      None
    172  *
    173  * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
    174  *              compile or I/O errors
    175  *
    176  ******************************************************************************/
    177 
    178 void
    179 DtFatal (
    180     UINT16                  MessageId,
    181     DT_FIELD                *FieldObject,
    182     char                    *ExtraMessage)
    183 {
    184 
    185     DtError (ASL_ERROR, MessageId, FieldObject, ExtraMessage);
    186 
    187 /*
    188  * TBD: remove this entire function, DtFatal
    189  *
    190  * We cannot abort the compiler on error, because we may be compiling a
    191  * list of files. We must move on to the next file.
    192  */
    193 #ifdef __OBSOLETE
    194     CmCleanupAndExit ();
    195     exit (1);
    196 #endif
    197 }
    198 
    199 
    200 /******************************************************************************
    201  *
    202  * FUNCTION:    DtStrtoul64
    203  *
    204  * PARAMETERS:  String              - Null terminated string
    205  *              ReturnInteger       - Where the converted integer is returned
    206  *
    207  * RETURN:      Status
    208  *
    209  * DESCRIPTION: Simple conversion of a string hex integer constant to unsigned
    210  *              value. Assumes no leading "0x" for the constant.
    211  *
    212  * Portability note: The reason this function exists is because a 64-bit
    213  * sscanf is not available in all environments.
    214  *
    215  *****************************************************************************/
    216 
    217 ACPI_STATUS
    218 DtStrtoul64 (
    219     char                    *String,
    220     UINT64                  *ReturnInteger)
    221 {
    222     char                    *ThisChar = String;
    223     UINT32                  ThisDigit;
    224     UINT64                  ReturnValue = 0;
    225     int                     DigitCount = 0;
    226 
    227 
    228     /* Skip over any white space in the buffer */
    229 
    230     while ((*ThisChar == ' ') || (*ThisChar == '\t'))
    231     {
    232         ThisChar++;
    233     }
    234 
    235     /* Skip leading zeros */
    236 
    237     while ((*ThisChar) == '0')
    238     {
    239         ThisChar++;
    240     }
    241 
    242     /* Convert character-by-character */
    243 
    244     while (*ThisChar)
    245     {
    246         if (ACPI_IS_DIGIT (*ThisChar))
    247         {
    248             /* Convert ASCII 0-9 to Decimal value */
    249 
    250             ThisDigit = ((UINT8) *ThisChar) - '0';
    251         }
    252         else /* Letter */
    253         {
    254             ThisDigit = (UINT32) ACPI_TOUPPER (*ThisChar);
    255             if (!ACPI_IS_XDIGIT ((char) ThisDigit))
    256             {
    257                 /* Not A-F */
    258 
    259                 return (AE_BAD_CHARACTER);
    260             }
    261 
    262             /* Convert ASCII Hex char (A-F) to value */
    263 
    264             ThisDigit = (ThisDigit - 'A') + 10;
    265         }
    266 
    267         /* Insert the 4-bit hex digit */
    268 
    269         ReturnValue <<= 4;
    270         ReturnValue += ThisDigit;
    271 
    272         ThisChar++;
    273         DigitCount++;
    274         if (DigitCount > 16)
    275         {
    276             /* Value is too large (> 64 bits/8 bytes/16 hex digits) */
    277 
    278             return (AE_LIMIT);
    279         }
    280     }
    281 
    282     *ReturnInteger = ReturnValue;
    283     return (AE_OK);
    284 }
    285 
    286 
    287 /******************************************************************************
    288  *
    289  * FUNCTION:    DtGetFieldValue
    290  *
    291  * PARAMETERS:  Field               - Current field list pointer
    292  *
    293  * RETURN:      Field value
    294  *
    295  * DESCRIPTION: Get field value
    296  *
    297  *****************************************************************************/
    298 
    299 char *
    300 DtGetFieldValue (
    301     DT_FIELD                *Field)
    302 {
    303     if (!Field)
    304     {
    305         return (NULL);
    306     }
    307 
    308     return (Field->Value);
    309 }
    310 
    311 
    312 /******************************************************************************
    313  *
    314  * FUNCTION:    DtGetFieldType
    315  *
    316  * PARAMETERS:  Info                - Data table info
    317  *
    318  * RETURN:      Field type
    319  *
    320  * DESCRIPTION: Get field type
    321  *
    322  *****************************************************************************/
    323 
    324 UINT8
    325 DtGetFieldType (
    326     ACPI_DMTABLE_INFO       *Info)
    327 {
    328     UINT8                   Type;
    329 
    330 
    331     /* DT_FLAG means that this is the start of a block of flag bits */
    332     /* TBD - we can make these a separate opcode later */
    333 
    334     if (Info->Flags & DT_FLAG)
    335     {
    336         return (DT_FIELD_TYPE_FLAGS_INTEGER);
    337     }
    338 
    339     /* Type is based upon the opcode for this field in the info table */
    340 
    341     switch (Info->Opcode)
    342     {
    343     case ACPI_DMT_FLAG0:
    344     case ACPI_DMT_FLAG1:
    345     case ACPI_DMT_FLAG2:
    346     case ACPI_DMT_FLAG3:
    347     case ACPI_DMT_FLAG4:
    348     case ACPI_DMT_FLAG5:
    349     case ACPI_DMT_FLAG6:
    350     case ACPI_DMT_FLAG7:
    351     case ACPI_DMT_FLAGS0:
    352     case ACPI_DMT_FLAGS1:
    353     case ACPI_DMT_FLAGS2:
    354     case ACPI_DMT_FLAGS4:
    355 
    356         Type = DT_FIELD_TYPE_FLAG;
    357         break;
    358 
    359     case ACPI_DMT_NAME4:
    360     case ACPI_DMT_SIG:
    361     case ACPI_DMT_NAME6:
    362     case ACPI_DMT_NAME8:
    363     case ACPI_DMT_STRING:
    364 
    365         Type = DT_FIELD_TYPE_STRING;
    366         break;
    367 
    368     case ACPI_DMT_BUFFER:
    369     case ACPI_DMT_BUF7:
    370     case ACPI_DMT_BUF10:
    371     case ACPI_DMT_BUF16:
    372     case ACPI_DMT_BUF128:
    373     case ACPI_DMT_PCI_PATH:
    374 
    375         Type = DT_FIELD_TYPE_BUFFER;
    376         break;
    377 
    378     case ACPI_DMT_GAS:
    379     case ACPI_DMT_HESTNTFY:
    380 
    381         Type = DT_FIELD_TYPE_INLINE_SUBTABLE;
    382         break;
    383 
    384     case ACPI_DMT_UNICODE:
    385 
    386         Type = DT_FIELD_TYPE_UNICODE;
    387         break;
    388 
    389     case ACPI_DMT_UUID:
    390 
    391         Type = DT_FIELD_TYPE_UUID;
    392         break;
    393 
    394     case ACPI_DMT_DEVICE_PATH:
    395 
    396         Type = DT_FIELD_TYPE_DEVICE_PATH;
    397         break;
    398 
    399     case ACPI_DMT_LABEL:
    400 
    401         Type = DT_FIELD_TYPE_LABEL;
    402         break;
    403 
    404     default:
    405 
    406         Type = DT_FIELD_TYPE_INTEGER;
    407         break;
    408     }
    409 
    410     return (Type);
    411 }
    412 
    413 
    414 /******************************************************************************
    415  *
    416  * FUNCTION:    DtGetBufferLength
    417  *
    418  * PARAMETERS:  Buffer              - List of integers,
    419  *                                    for example "10 3A 4F 2E"
    420  *
    421  * RETURN:      Count of integer
    422  *
    423  * DESCRIPTION: Get length of bytes needed to store the integers
    424  *
    425  *****************************************************************************/
    426 
    427 UINT32
    428 DtGetBufferLength (
    429     char                    *Buffer)
    430 {
    431     UINT32                  ByteLength = 0;
    432 
    433 
    434     while (*Buffer)
    435     {
    436         if (*Buffer == ' ')
    437         {
    438             ByteLength++;
    439 
    440             while (*Buffer == ' ')
    441             {
    442                 Buffer++;
    443             }
    444         }
    445 
    446         Buffer++;
    447     }
    448 
    449     return (++ByteLength);
    450 }
    451 
    452 
    453 /******************************************************************************
    454  *
    455  * FUNCTION:    DtGetFieldLength
    456  *
    457  * PARAMETERS:  Field               - Current field
    458  *              Info                - Data table info
    459  *
    460  * RETURN:      Field length
    461  *
    462  * DESCRIPTION: Get length of bytes needed to compile the field
    463  *
    464  * Note: This function must remain in sync with AcpiDmDumpTable.
    465  *
    466  *****************************************************************************/
    467 
    468 UINT32
    469 DtGetFieldLength (
    470     DT_FIELD                *Field,
    471     ACPI_DMTABLE_INFO       *Info)
    472 {
    473     UINT32                  ByteLength = 0;
    474     char                    *Value;
    475 
    476 
    477     /* Length is based upon the opcode for this field in the info table */
    478 
    479     switch (Info->Opcode)
    480     {
    481     case ACPI_DMT_FLAG0:
    482     case ACPI_DMT_FLAG1:
    483     case ACPI_DMT_FLAG2:
    484     case ACPI_DMT_FLAG3:
    485     case ACPI_DMT_FLAG4:
    486     case ACPI_DMT_FLAG5:
    487     case ACPI_DMT_FLAG6:
    488     case ACPI_DMT_FLAG7:
    489     case ACPI_DMT_FLAGS0:
    490     case ACPI_DMT_FLAGS1:
    491     case ACPI_DMT_FLAGS2:
    492     case ACPI_DMT_FLAGS4:
    493     case ACPI_DMT_LABEL:
    494     case ACPI_DMT_EXTRA_TEXT:
    495 
    496         ByteLength = 0;
    497         break;
    498 
    499     case ACPI_DMT_UINT8:
    500     case ACPI_DMT_CHKSUM:
    501     case ACPI_DMT_SPACEID:
    502     case ACPI_DMT_ACCWIDTH:
    503     case ACPI_DMT_IVRS:
    504     case ACPI_DMT_GTDT:
    505     case ACPI_DMT_MADT:
    506     case ACPI_DMT_PCCT:
    507     case ACPI_DMT_PMTT:
    508     case ACPI_DMT_SRAT:
    509     case ACPI_DMT_ASF:
    510     case ACPI_DMT_HESTNTYP:
    511     case ACPI_DMT_FADTPM:
    512     case ACPI_DMT_EINJACT:
    513     case ACPI_DMT_EINJINST:
    514     case ACPI_DMT_ERSTACT:
    515     case ACPI_DMT_ERSTINST:
    516     case ACPI_DMT_DMAR_SCOPE:
    517 
    518         ByteLength = 1;
    519         break;
    520 
    521     case ACPI_DMT_UINT16:
    522     case ACPI_DMT_DMAR:
    523     case ACPI_DMT_HEST:
    524     case ACPI_DMT_PCI_PATH:
    525 
    526         ByteLength = 2;
    527         break;
    528 
    529     case ACPI_DMT_UINT24:
    530 
    531         ByteLength = 3;
    532         break;
    533 
    534     case ACPI_DMT_UINT32:
    535     case ACPI_DMT_NAME4:
    536     case ACPI_DMT_SLIC:
    537     case ACPI_DMT_SIG:
    538     case ACPI_DMT_LPIT:
    539 
    540         ByteLength = 4;
    541         break;
    542 
    543     case ACPI_DMT_UINT40:
    544 
    545         ByteLength = 5;
    546         break;
    547 
    548     case ACPI_DMT_UINT48:
    549     case ACPI_DMT_NAME6:
    550 
    551         ByteLength = 6;
    552         break;
    553 
    554     case ACPI_DMT_UINT56:
    555     case ACPI_DMT_BUF7:
    556 
    557         ByteLength = 7;
    558         break;
    559 
    560     case ACPI_DMT_UINT64:
    561     case ACPI_DMT_NAME8:
    562 
    563         ByteLength = 8;
    564         break;
    565 
    566     case ACPI_DMT_STRING:
    567 
    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             snprintf (MsgBuffer, sizeof(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 
    584         ByteLength = sizeof (ACPI_GENERIC_ADDRESS);
    585         break;
    586 
    587     case ACPI_DMT_HESTNTFY:
    588 
    589         ByteLength = sizeof (ACPI_HEST_NOTIFY);
    590         break;
    591 
    592     case ACPI_DMT_BUFFER:
    593 
    594         Value = DtGetFieldValue (Field);
    595         if (Value)
    596         {
    597             ByteLength = DtGetBufferLength (Value);
    598         }
    599         else
    600         {   /* At this point, this is a fatal error */
    601 
    602             snprintf (MsgBuffer, sizeof(MsgBuffer), "Expected \"%s\"", Info->Name);
    603             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
    604             return (0);
    605         }
    606         break;
    607 
    608     case ACPI_DMT_BUF10:
    609 
    610         ByteLength = 10;
    611         break;
    612 
    613     case ACPI_DMT_BUF16:
    614     case ACPI_DMT_UUID:
    615 
    616         ByteLength = 16;
    617         break;
    618 
    619     case ACPI_DMT_BUF128:
    620 
    621         ByteLength = 128;
    622         break;
    623 
    624     case ACPI_DMT_UNICODE:
    625 
    626         Value = DtGetFieldValue (Field);
    627 
    628         /* TBD: error if Value is NULL? (as below?) */
    629 
    630         ByteLength = (ACPI_STRLEN (Value) + 1) * sizeof(UINT16);
    631         break;
    632 
    633     default:
    634 
    635         DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode");
    636         return (0);
    637     }
    638 
    639     return (ByteLength);
    640 }
    641 
    642 
    643 /******************************************************************************
    644  *
    645  * FUNCTION:    DtSum
    646  *
    647  * PARAMETERS:  DT_WALK_CALLBACK:
    648  *              Subtable            - Subtable
    649  *              Context             - Unused
    650  *              ReturnValue         - Store the checksum of subtable
    651  *
    652  * RETURN:      Status
    653  *
    654  * DESCRIPTION: Get the checksum of subtable
    655  *
    656  *****************************************************************************/
    657 
    658 static void
    659 DtSum (
    660     DT_SUBTABLE             *Subtable,
    661     void                    *Context,
    662     void                    *ReturnValue)
    663 {
    664     UINT8                   Checksum;
    665     UINT8                   *Sum = ReturnValue;
    666 
    667 
    668     Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length);
    669     *Sum = (UINT8) (*Sum + Checksum);
    670 }
    671 
    672 
    673 /******************************************************************************
    674  *
    675  * FUNCTION:    DtSetTableChecksum
    676  *
    677  * PARAMETERS:  ChecksumPointer     - Where to return the checksum
    678  *
    679  * RETURN:      None
    680  *
    681  * DESCRIPTION: Set checksum of the whole data table into the checksum field
    682  *
    683  *****************************************************************************/
    684 
    685 void
    686 DtSetTableChecksum (
    687     UINT8                   *ChecksumPointer)
    688 {
    689     UINT8                   Checksum = 0;
    690     UINT8                   OldSum;
    691 
    692 
    693     DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum);
    694 
    695     OldSum = *ChecksumPointer;
    696     Checksum = (UINT8) (Checksum - OldSum);
    697 
    698     /* Compute the final checksum */
    699 
    700     Checksum = (UINT8) (0 - Checksum);
    701     *ChecksumPointer = Checksum;
    702 }
    703 
    704 
    705 /******************************************************************************
    706  *
    707  * FUNCTION:    DtSetTableLength
    708  *
    709  * PARAMETERS:  None
    710  *
    711  * RETURN:      None
    712  *
    713  * DESCRIPTION: Walk the subtables and set all the length fields
    714  *
    715  *****************************************************************************/
    716 
    717 void
    718 DtSetTableLength (
    719     void)
    720 {
    721     DT_SUBTABLE             *ParentTable;
    722     DT_SUBTABLE             *ChildTable;
    723 
    724 
    725     ParentTable = Gbl_RootTable;
    726     ChildTable = NULL;
    727 
    728     if (!ParentTable)
    729     {
    730         return;
    731     }
    732 
    733     DtSetSubtableLength (ParentTable);
    734 
    735     while (1)
    736     {
    737         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
    738         if (ChildTable)
    739         {
    740             if (ChildTable->LengthField)
    741             {
    742                 DtSetSubtableLength (ChildTable);
    743             }
    744 
    745             if (ChildTable->Child)
    746             {
    747                 ParentTable = ChildTable;
    748                 ChildTable = NULL;
    749             }
    750             else
    751             {
    752                 ParentTable->TotalLength += ChildTable->TotalLength;
    753                 if (ParentTable->LengthField)
    754                 {
    755                     DtSetSubtableLength (ParentTable);
    756                 }
    757             }
    758         }
    759         else
    760         {
    761             ChildTable = ParentTable;
    762 
    763             if (ChildTable == Gbl_RootTable)
    764             {
    765                 break;
    766             }
    767 
    768             ParentTable = DtGetParentSubtable (ParentTable);
    769 
    770             ParentTable->TotalLength += ChildTable->TotalLength;
    771             if (ParentTable->LengthField)
    772             {
    773                 DtSetSubtableLength (ParentTable);
    774             }
    775         }
    776     }
    777 }
    778 
    779 
    780 /******************************************************************************
    781  *
    782  * FUNCTION:    DtWalkTableTree
    783  *
    784  * PARAMETERS:  StartTable          - Subtable in the tree where walking begins
    785  *              UserFunction        - Called during the walk
    786  *              Context             - Passed to user function
    787  *              ReturnValue         - The return value of UserFunction
    788  *
    789  * RETURN:      None
    790  *
    791  * DESCRIPTION: Performs a depth-first walk of the subtable tree
    792  *
    793  *****************************************************************************/
    794 
    795 void
    796 DtWalkTableTree (
    797     DT_SUBTABLE             *StartTable,
    798     DT_WALK_CALLBACK        UserFunction,
    799     void                    *Context,
    800     void                    *ReturnValue)
    801 {
    802     DT_SUBTABLE             *ParentTable;
    803     DT_SUBTABLE             *ChildTable;
    804 
    805 
    806     ParentTable = StartTable;
    807     ChildTable = NULL;
    808 
    809     if (!ParentTable)
    810     {
    811         return;
    812     }
    813 
    814     UserFunction (ParentTable, Context, ReturnValue);
    815 
    816     while (1)
    817     {
    818         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
    819         if (ChildTable)
    820         {
    821             UserFunction (ChildTable, Context, ReturnValue);
    822 
    823             if (ChildTable->Child)
    824             {
    825                 ParentTable = ChildTable;
    826                 ChildTable = NULL;
    827             }
    828         }
    829         else
    830         {
    831             ChildTable = ParentTable;
    832             if (ChildTable == Gbl_RootTable)
    833             {
    834                 break;
    835             }
    836 
    837             ParentTable = DtGetParentSubtable (ParentTable);
    838 
    839             if (ChildTable->Peer == StartTable)
    840             {
    841                 break;
    842             }
    843         }
    844     }
    845 }
    846 
    847 
    848 /*******************************************************************************
    849  *
    850  * FUNCTION:    UtSubtableCacheCalloc
    851  *
    852  * PARAMETERS:  None
    853  *
    854  * RETURN:      Pointer to the buffer. Aborts on allocation failure
    855  *
    856  * DESCRIPTION: Allocate a subtable object buffer. Bypass the local
    857  *              dynamic memory manager for performance reasons (This has a
    858  *              major impact on the speed of the compiler.)
    859  *
    860  ******************************************************************************/
    861 
    862 DT_SUBTABLE *
    863 UtSubtableCacheCalloc (
    864     void)
    865 {
    866     ASL_CACHE_INFO          *Cache;
    867 
    868 
    869     if (Gbl_SubtableCacheNext >= Gbl_SubtableCacheLast)
    870     {
    871         /* Allocate a new buffer */
    872 
    873         Cache = UtLocalCalloc (sizeof (Cache->Next) +
    874             (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE));
    875 
    876         /* Link new cache buffer to head of list */
    877 
    878         Cache->Next = Gbl_SubtableCacheList;
    879         Gbl_SubtableCacheList = Cache;
    880 
    881         /* Setup cache management pointers */
    882 
    883         Gbl_SubtableCacheNext = ACPI_CAST_PTR (DT_SUBTABLE, Cache->Buffer);
    884         Gbl_SubtableCacheLast = Gbl_SubtableCacheNext + ASL_SUBTABLE_CACHE_SIZE;
    885     }
    886 
    887     Gbl_SubtableCount++;
    888     return (Gbl_SubtableCacheNext++);
    889 }
    890 
    891 
    892 /*******************************************************************************
    893  *
    894  * FUNCTION:    UtFieldCacheCalloc
    895  *
    896  * PARAMETERS:  None
    897  *
    898  * RETURN:      Pointer to the buffer. Aborts on allocation failure
    899  *
    900  * DESCRIPTION: Allocate a field object buffer. Bypass the local
    901  *              dynamic memory manager for performance reasons (This has a
    902  *              major impact on the speed of the compiler.)
    903  *
    904  ******************************************************************************/
    905 
    906 DT_FIELD *
    907 UtFieldCacheCalloc (
    908     void)
    909 {
    910     ASL_CACHE_INFO          *Cache;
    911 
    912 
    913     if (Gbl_FieldCacheNext >= Gbl_FieldCacheLast)
    914     {
    915         /* Allocate a new buffer */
    916 
    917         Cache = UtLocalCalloc (sizeof (Cache->Next) +
    918             (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE));
    919 
    920         /* Link new cache buffer to head of list */
    921 
    922         Cache->Next = Gbl_FieldCacheList;
    923         Gbl_FieldCacheList = Cache;
    924 
    925         /* Setup cache management pointers */
    926 
    927         Gbl_FieldCacheNext = ACPI_CAST_PTR (DT_FIELD, Cache->Buffer);
    928         Gbl_FieldCacheLast = Gbl_FieldCacheNext + ASL_FIELD_CACHE_SIZE;
    929     }
    930 
    931     Gbl_FieldCount++;
    932     return (Gbl_FieldCacheNext++);
    933 }
    934 
    935 
    936 /*******************************************************************************
    937  *
    938  * FUNCTION:    DtDeleteCaches
    939  *
    940  * PARAMETERS:  None
    941  *
    942  * RETURN:      None
    943  *
    944  * DESCRIPTION: Delete all local cache buffer blocks
    945  *
    946  ******************************************************************************/
    947 
    948 void
    949 DtDeleteCaches (
    950     void)
    951 {
    952     UINT32                  BufferCount;
    953     ASL_CACHE_INFO          *Next;
    954 
    955 
    956     /* Field cache */
    957 
    958     BufferCount = 0;
    959     while (Gbl_FieldCacheList)
    960     {
    961         Next = Gbl_FieldCacheList->Next;
    962         ACPI_FREE (Gbl_FieldCacheList);
    963         Gbl_FieldCacheList = Next;
    964         BufferCount++;
    965     }
    966 
    967     DbgPrint (ASL_DEBUG_OUTPUT,
    968         "%u Fields, Buffer size: %u fields (%u bytes), %u Buffers\n",
    969         Gbl_FieldCount, ASL_FIELD_CACHE_SIZE,
    970         (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE), BufferCount);
    971 
    972     Gbl_FieldCount = 0;
    973     Gbl_FieldCacheNext = NULL;
    974     Gbl_FieldCacheLast = NULL;
    975 
    976     /* Subtable cache */
    977 
    978     BufferCount = 0;
    979     while (Gbl_SubtableCacheList)
    980     {
    981         Next = Gbl_SubtableCacheList->Next;
    982         ACPI_FREE (Gbl_SubtableCacheList);
    983         Gbl_SubtableCacheList = Next;
    984         BufferCount++;
    985     }
    986 
    987     DbgPrint (ASL_DEBUG_OUTPUT,
    988         "%u Subtables, Buffer size: %u subtables (%u bytes), %u Buffers\n",
    989         Gbl_SubtableCount, ASL_SUBTABLE_CACHE_SIZE,
    990         (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE), BufferCount);
    991 
    992     Gbl_SubtableCount = 0;
    993     Gbl_SubtableCacheNext = NULL;
    994     Gbl_SubtableCacheLast = NULL;
    995 }
    996