Home | History | Annotate | Line # | Download | only in compiler
dtutils.c revision 1.1.1.3.2.1
      1 /******************************************************************************
      2  *
      3  * Module Name: dtutils.c - Utility routines for the data table compiler
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2013, 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     UINT8                   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     UINT8                   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     UINT8                   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:    DtGetFileSize
    290  *
    291  * PARAMETERS:  Handle              - Open file handler
    292  *
    293  * RETURN:      Current file size
    294  *
    295  * DESCRIPTION: Get the current size of a file. Seek to the EOF and get the
    296  *              offset. Seek back to the original location.
    297  *
    298  *****************************************************************************/
    299 
    300 UINT32
    301 DtGetFileSize (
    302     FILE                    *Handle)
    303 {
    304     int                     CurrentOffset;
    305     int                     LastOffset;
    306 
    307 
    308     CurrentOffset = ftell (Handle);
    309     fseek (Handle, 0, SEEK_END);
    310     LastOffset = ftell (Handle);
    311     fseek (Handle, CurrentOffset, SEEK_SET);
    312 
    313     return ((UINT32) LastOffset);
    314 }
    315 
    316 
    317 /******************************************************************************
    318  *
    319  * FUNCTION:    DtGetFieldValue
    320  *
    321  * PARAMETERS:  Field               - Current field list pointer
    322  *
    323  * RETURN:      Field value
    324  *
    325  * DESCRIPTION: Get field value
    326  *
    327  *****************************************************************************/
    328 
    329 char *
    330 DtGetFieldValue (
    331     DT_FIELD                *Field)
    332 {
    333     if (!Field)
    334     {
    335         return (NULL);
    336     }
    337 
    338     return (Field->Value);
    339 }
    340 
    341 
    342 /******************************************************************************
    343  *
    344  * FUNCTION:    DtGetFieldType
    345  *
    346  * PARAMETERS:  Info                - Data table info
    347  *
    348  * RETURN:      Field type
    349  *
    350  * DESCRIPTION: Get field type
    351  *
    352  *****************************************************************************/
    353 
    354 UINT8
    355 DtGetFieldType (
    356     ACPI_DMTABLE_INFO       *Info)
    357 {
    358     UINT8                   Type;
    359 
    360 
    361     /* DT_FLAG means that this is the start of a block of flag bits */
    362     /* TBD - we can make these a separate opcode later */
    363 
    364     if (Info->Flags & DT_FLAG)
    365     {
    366         return (DT_FIELD_TYPE_FLAGS_INTEGER);
    367     }
    368 
    369     /* Type is based upon the opcode for this field in the info table */
    370 
    371     switch (Info->Opcode)
    372     {
    373     case ACPI_DMT_FLAG0:
    374     case ACPI_DMT_FLAG1:
    375     case ACPI_DMT_FLAG2:
    376     case ACPI_DMT_FLAG3:
    377     case ACPI_DMT_FLAG4:
    378     case ACPI_DMT_FLAG5:
    379     case ACPI_DMT_FLAG6:
    380     case ACPI_DMT_FLAG7:
    381     case ACPI_DMT_FLAGS0:
    382     case ACPI_DMT_FLAGS1:
    383     case ACPI_DMT_FLAGS2:
    384     case ACPI_DMT_FLAGS4:
    385 
    386         Type = DT_FIELD_TYPE_FLAG;
    387         break;
    388 
    389     case ACPI_DMT_NAME4:
    390     case ACPI_DMT_SIG:
    391     case ACPI_DMT_NAME6:
    392     case ACPI_DMT_NAME8:
    393     case ACPI_DMT_STRING:
    394 
    395         Type = DT_FIELD_TYPE_STRING;
    396         break;
    397 
    398     case ACPI_DMT_BUFFER:
    399     case ACPI_DMT_BUF7:
    400     case ACPI_DMT_BUF10:
    401     case ACPI_DMT_BUF16:
    402     case ACPI_DMT_BUF128:
    403     case ACPI_DMT_PCI_PATH:
    404 
    405         Type = DT_FIELD_TYPE_BUFFER;
    406         break;
    407 
    408     case ACPI_DMT_GAS:
    409     case ACPI_DMT_HESTNTFY:
    410 
    411         Type = DT_FIELD_TYPE_INLINE_SUBTABLE;
    412         break;
    413 
    414     case ACPI_DMT_UNICODE:
    415 
    416         Type = DT_FIELD_TYPE_UNICODE;
    417         break;
    418 
    419     case ACPI_DMT_UUID:
    420 
    421         Type = DT_FIELD_TYPE_UUID;
    422         break;
    423 
    424     case ACPI_DMT_DEVICE_PATH:
    425 
    426         Type = DT_FIELD_TYPE_DEVICE_PATH;
    427         break;
    428 
    429     case ACPI_DMT_LABEL:
    430 
    431         Type = DT_FIELD_TYPE_LABEL;
    432         break;
    433 
    434     default:
    435 
    436         Type = DT_FIELD_TYPE_INTEGER;
    437         break;
    438     }
    439 
    440     return (Type);
    441 }
    442 
    443 
    444 /******************************************************************************
    445  *
    446  * FUNCTION:    DtGetBufferLength
    447  *
    448  * PARAMETERS:  Buffer              - List of integers,
    449  *                                    for example "10 3A 4F 2E"
    450  *
    451  * RETURN:      Count of integer
    452  *
    453  * DESCRIPTION: Get length of bytes needed to store the integers
    454  *
    455  *****************************************************************************/
    456 
    457 UINT32
    458 DtGetBufferLength (
    459     char                    *Buffer)
    460 {
    461     UINT32                  ByteLength = 0;
    462 
    463 
    464     while (*Buffer)
    465     {
    466         if (*Buffer == ' ')
    467         {
    468             ByteLength++;
    469 
    470             while (*Buffer == ' ')
    471             {
    472                 Buffer++;
    473             }
    474         }
    475 
    476         Buffer++;
    477     }
    478 
    479     return (++ByteLength);
    480 }
    481 
    482 
    483 /******************************************************************************
    484  *
    485  * FUNCTION:    DtGetFieldLength
    486  *
    487  * PARAMETERS:  Field               - Current field
    488  *              Info                - Data table info
    489  *
    490  * RETURN:      Field length
    491  *
    492  * DESCRIPTION: Get length of bytes needed to compile the field
    493  *
    494  * Note: This function must remain in sync with AcpiDmDumpTable.
    495  *
    496  *****************************************************************************/
    497 
    498 UINT32
    499 DtGetFieldLength (
    500     DT_FIELD                *Field,
    501     ACPI_DMTABLE_INFO       *Info)
    502 {
    503     UINT32                  ByteLength = 0;
    504     char                    *Value;
    505 
    506 
    507     /* Length is based upon the opcode for this field in the info table */
    508 
    509     switch (Info->Opcode)
    510     {
    511     case ACPI_DMT_FLAG0:
    512     case ACPI_DMT_FLAG1:
    513     case ACPI_DMT_FLAG2:
    514     case ACPI_DMT_FLAG3:
    515     case ACPI_DMT_FLAG4:
    516     case ACPI_DMT_FLAG5:
    517     case ACPI_DMT_FLAG6:
    518     case ACPI_DMT_FLAG7:
    519     case ACPI_DMT_FLAGS0:
    520     case ACPI_DMT_FLAGS1:
    521     case ACPI_DMT_FLAGS2:
    522     case ACPI_DMT_FLAGS4:
    523     case ACPI_DMT_LABEL:
    524     case ACPI_DMT_EXTRA_TEXT:
    525 
    526         ByteLength = 0;
    527         break;
    528 
    529     case ACPI_DMT_UINT8:
    530     case ACPI_DMT_CHKSUM:
    531     case ACPI_DMT_SPACEID:
    532     case ACPI_DMT_ACCWIDTH:
    533     case ACPI_DMT_IVRS:
    534     case ACPI_DMT_MADT:
    535     case ACPI_DMT_PCCT:
    536     case ACPI_DMT_PMTT:
    537     case ACPI_DMT_SRAT:
    538     case ACPI_DMT_ASF:
    539     case ACPI_DMT_HESTNTYP:
    540     case ACPI_DMT_FADTPM:
    541     case ACPI_DMT_EINJACT:
    542     case ACPI_DMT_EINJINST:
    543     case ACPI_DMT_ERSTACT:
    544     case ACPI_DMT_ERSTINST:
    545 
    546         ByteLength = 1;
    547         break;
    548 
    549     case ACPI_DMT_UINT16:
    550     case ACPI_DMT_DMAR:
    551     case ACPI_DMT_HEST:
    552     case ACPI_DMT_PCI_PATH:
    553 
    554         ByteLength = 2;
    555         break;
    556 
    557     case ACPI_DMT_UINT24:
    558 
    559         ByteLength = 3;
    560         break;
    561 
    562     case ACPI_DMT_UINT32:
    563     case ACPI_DMT_NAME4:
    564     case ACPI_DMT_SLIC:
    565     case ACPI_DMT_SIG:
    566 
    567         ByteLength = 4;
    568         break;
    569 
    570     case ACPI_DMT_UINT40:
    571 
    572         ByteLength = 5;
    573         break;
    574 
    575     case ACPI_DMT_UINT48:
    576     case ACPI_DMT_NAME6:
    577 
    578         ByteLength = 6;
    579         break;
    580 
    581     case ACPI_DMT_UINT56:
    582     case ACPI_DMT_BUF7:
    583 
    584         ByteLength = 7;
    585         break;
    586 
    587     case ACPI_DMT_UINT64:
    588     case ACPI_DMT_NAME8:
    589 
    590         ByteLength = 8;
    591         break;
    592 
    593     case ACPI_DMT_STRING:
    594 
    595         Value = DtGetFieldValue (Field);
    596         if (Value)
    597         {
    598             ByteLength = ACPI_STRLEN (Value) + 1;
    599         }
    600         else
    601         {   /* At this point, this is a fatal error */
    602 
    603             snprintf (MsgBuffer, sizeof(MsgBuffer), "Expected \"%s\"", Info->Name);
    604             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
    605             return (0);
    606         }
    607         break;
    608 
    609     case ACPI_DMT_GAS:
    610 
    611         ByteLength = sizeof (ACPI_GENERIC_ADDRESS);
    612         break;
    613 
    614     case ACPI_DMT_HESTNTFY:
    615 
    616         ByteLength = sizeof (ACPI_HEST_NOTIFY);
    617         break;
    618 
    619     case ACPI_DMT_BUFFER:
    620 
    621         Value = DtGetFieldValue (Field);
    622         if (Value)
    623         {
    624             ByteLength = DtGetBufferLength (Value);
    625         }
    626         else
    627         {   /* At this point, this is a fatal error */
    628 
    629             snprintf (MsgBuffer, sizeof(MsgBuffer), "Expected \"%s\"", Info->Name);
    630             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
    631             return (0);
    632         }
    633         break;
    634 
    635     case ACPI_DMT_BUF10:
    636 
    637         ByteLength = 10;
    638         break;
    639 
    640     case ACPI_DMT_BUF16:
    641     case ACPI_DMT_UUID:
    642 
    643         ByteLength = 16;
    644         break;
    645 
    646     case ACPI_DMT_BUF128:
    647 
    648         ByteLength = 128;
    649         break;
    650 
    651     case ACPI_DMT_UNICODE:
    652 
    653         Value = DtGetFieldValue (Field);
    654 
    655         /* TBD: error if Value is NULL? (as below?) */
    656 
    657         ByteLength = (ACPI_STRLEN (Value) + 1) * sizeof(UINT16);
    658         break;
    659 
    660     default:
    661 
    662         DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode");
    663         return (0);
    664     }
    665 
    666     return (ByteLength);
    667 }
    668 
    669 
    670 /******************************************************************************
    671  *
    672  * FUNCTION:    DtSum
    673  *
    674  * PARAMETERS:  DT_WALK_CALLBACK:
    675  *              Subtable            - Subtable
    676  *              Context             - Unused
    677  *              ReturnValue         - Store the checksum of subtable
    678  *
    679  * RETURN:      Status
    680  *
    681  * DESCRIPTION: Get the checksum of subtable
    682  *
    683  *****************************************************************************/
    684 
    685 static void
    686 DtSum (
    687     DT_SUBTABLE             *Subtable,
    688     void                    *Context,
    689     void                    *ReturnValue)
    690 {
    691     UINT8                   Checksum;
    692     UINT8                   *Sum = ReturnValue;
    693 
    694 
    695     Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length);
    696     *Sum = (UINT8) (*Sum + Checksum);
    697 }
    698 
    699 
    700 /******************************************************************************
    701  *
    702  * FUNCTION:    DtSetTableChecksum
    703  *
    704  * PARAMETERS:  ChecksumPointer     - Where to return the checksum
    705  *
    706  * RETURN:      None
    707  *
    708  * DESCRIPTION: Set checksum of the whole data table into the checksum field
    709  *
    710  *****************************************************************************/
    711 
    712 void
    713 DtSetTableChecksum (
    714     UINT8                   *ChecksumPointer)
    715 {
    716     UINT8                   Checksum = 0;
    717     UINT8                   OldSum;
    718 
    719 
    720     DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum);
    721 
    722     OldSum = *ChecksumPointer;
    723     Checksum = (UINT8) (Checksum - OldSum);
    724 
    725     /* Compute the final checksum */
    726 
    727     Checksum = (UINT8) (0 - Checksum);
    728     *ChecksumPointer = Checksum;
    729 }
    730 
    731 
    732 /******************************************************************************
    733  *
    734  * FUNCTION:    DtSetTableLength
    735  *
    736  * PARAMETERS:  None
    737  *
    738  * RETURN:      None
    739  *
    740  * DESCRIPTION: Walk the subtables and set all the length fields
    741  *
    742  *****************************************************************************/
    743 
    744 void
    745 DtSetTableLength (
    746     void)
    747 {
    748     DT_SUBTABLE             *ParentTable;
    749     DT_SUBTABLE             *ChildTable;
    750 
    751 
    752     ParentTable = Gbl_RootTable;
    753     ChildTable = NULL;
    754 
    755     if (!ParentTable)
    756     {
    757         return;
    758     }
    759 
    760     DtSetSubtableLength (ParentTable);
    761 
    762     while (1)
    763     {
    764         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
    765         if (ChildTable)
    766         {
    767             if (ChildTable->LengthField)
    768             {
    769                 DtSetSubtableLength (ChildTable);
    770             }
    771 
    772             if (ChildTable->Child)
    773             {
    774                 ParentTable = ChildTable;
    775                 ChildTable = NULL;
    776             }
    777             else
    778             {
    779                 ParentTable->TotalLength += ChildTable->TotalLength;
    780                 if (ParentTable->LengthField)
    781                 {
    782                     DtSetSubtableLength (ParentTable);
    783                 }
    784             }
    785         }
    786         else
    787         {
    788             ChildTable = ParentTable;
    789 
    790             if (ChildTable == Gbl_RootTable)
    791             {
    792                 break;
    793             }
    794 
    795             ParentTable = DtGetParentSubtable (ParentTable);
    796 
    797             ParentTable->TotalLength += ChildTable->TotalLength;
    798             if (ParentTable->LengthField)
    799             {
    800                 DtSetSubtableLength (ParentTable);
    801             }
    802         }
    803     }
    804 }
    805 
    806 
    807 /******************************************************************************
    808  *
    809  * FUNCTION:    DtWalkTableTree
    810  *
    811  * PARAMETERS:  StartTable          - Subtable in the tree where walking begins
    812  *              UserFunction        - Called during the walk
    813  *              Context             - Passed to user function
    814  *              ReturnValue         - The return value of UserFunction
    815  *
    816  * RETURN:      None
    817  *
    818  * DESCRIPTION: Performs a depth-first walk of the subtable tree
    819  *
    820  *****************************************************************************/
    821 
    822 void
    823 DtWalkTableTree (
    824     DT_SUBTABLE             *StartTable,
    825     DT_WALK_CALLBACK        UserFunction,
    826     void                    *Context,
    827     void                    *ReturnValue)
    828 {
    829     DT_SUBTABLE             *ParentTable;
    830     DT_SUBTABLE             *ChildTable;
    831 
    832 
    833     ParentTable = StartTable;
    834     ChildTable = NULL;
    835 
    836     if (!ParentTable)
    837     {
    838         return;
    839     }
    840 
    841     UserFunction (ParentTable, Context, ReturnValue);
    842 
    843     while (1)
    844     {
    845         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
    846         if (ChildTable)
    847         {
    848             UserFunction (ChildTable, Context, ReturnValue);
    849 
    850             if (ChildTable->Child)
    851             {
    852                 ParentTable = ChildTable;
    853                 ChildTable = NULL;
    854             }
    855         }
    856         else
    857         {
    858             ChildTable = ParentTable;
    859             if (ChildTable == Gbl_RootTable)
    860             {
    861                 break;
    862             }
    863 
    864             ParentTable = DtGetParentSubtable (ParentTable);
    865 
    866             if (ChildTable->Peer == StartTable)
    867             {
    868                 break;
    869             }
    870         }
    871     }
    872 }
    873 
    874 
    875 /******************************************************************************
    876  *
    877  * FUNCTION:    DtFreeFieldList
    878  *
    879  * PARAMETERS:  None
    880  *
    881  * RETURN:      None
    882  *
    883  * DESCRIPTION: Free the field list
    884  *
    885  *****************************************************************************/
    886 
    887 void
    888 DtFreeFieldList (
    889     void)
    890 {
    891     DT_FIELD                *Field = Gbl_FieldList;
    892     DT_FIELD                *NextField;
    893 
    894 
    895     /* Walk and free entire field list */
    896 
    897     while (Field)
    898     {
    899         NextField = Field->Next; /* Save link */
    900 
    901         if (!(Field->Flags & DT_FIELD_NOT_ALLOCATED))
    902         {
    903             ACPI_FREE (Field->Name);
    904             ACPI_FREE (Field->Value);
    905         }
    906 
    907         ACPI_FREE (Field);
    908         Field = NextField;
    909     }
    910 }
    911