Home | History | Annotate | Line # | Download | only in compiler
dtutils.c revision 1.7.2.1
      1 /******************************************************************************
      2  *
      3  * Module Name: dtutils.c - Utility routines for the data table compiler
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "aslcompiler.h"
     45 #include "dtcompiler.h"
     46 #include "actables.h"
     47 
     48 #define _COMPONENT          DT_COMPILER
     49         ACPI_MODULE_NAME    ("dtutils")
     50 
     51 /* Local prototypes */
     52 
     53 static void
     54 DtSum (
     55     DT_SUBTABLE             *Subtable,
     56     void                    *Context,
     57     void                    *ReturnValue);
     58 
     59 
     60 /******************************************************************************
     61  *
     62  * FUNCTION:    DtError
     63  *
     64  * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
     65  *              MessageId           - Index into global message buffer
     66  *              Op                  - Parse node where error happened
     67  *              ExtraMessage        - additional error message
     68  *
     69  * RETURN:      None
     70  *
     71  * DESCRIPTION: Common error interface for data table compiler
     72  *
     73  *****************************************************************************/
     74 
     75 void
     76 DtError (
     77     UINT8                   Level,
     78     UINT16                  MessageId,
     79     DT_FIELD                *FieldObject,
     80     char                    *ExtraMessage)
     81 {
     82 
     83     /* Check if user wants to ignore this exception */
     84 
     85     if (AslIsExceptionDisabled (Level, MessageId))
     86     {
     87         return;
     88     }
     89 
     90     if (FieldObject)
     91     {
     92         AslCommonError (Level, MessageId,
     93             FieldObject->Line,
     94             FieldObject->Line,
     95             FieldObject->ByteOffset,
     96             FieldObject->Column,
     97             Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
     98     }
     99     else
    100     {
    101         AslCommonError (Level, MessageId, 0,
    102             0, 0, 0, 0, ExtraMessage);
    103     }
    104 }
    105 
    106 
    107 /******************************************************************************
    108  *
    109  * FUNCTION:    DtNameError
    110  *
    111  * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
    112  *              MessageId           - Index into global message buffer
    113  *              Op                  - Parse node where error happened
    114  *              ExtraMessage        - additional error message
    115  *
    116  * RETURN:      None
    117  *
    118  * DESCRIPTION: Error interface for named objects
    119  *
    120  *****************************************************************************/
    121 
    122 void
    123 DtNameError (
    124     UINT8                   Level,
    125     UINT16                  MessageId,
    126     DT_FIELD                *FieldObject,
    127     char                    *ExtraMessage)
    128 {
    129 
    130     switch (Level)
    131     {
    132     case ASL_WARNING2:
    133     case ASL_WARNING3:
    134 
    135         if (Gbl_WarningLevel < Level)
    136         {
    137             return;
    138         }
    139         break;
    140 
    141     default:
    142 
    143         break;
    144     }
    145 
    146     if (FieldObject)
    147     {
    148         AslCommonError (Level, MessageId,
    149             FieldObject->Line,
    150             FieldObject->Line,
    151             FieldObject->ByteOffset,
    152             FieldObject->NameColumn,
    153             Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
    154     }
    155     else
    156     {
    157         AslCommonError (Level, MessageId, 0,
    158             0, 0, 0, 0, ExtraMessage);
    159     }
    160 }
    161 
    162 
    163 /*******************************************************************************
    164  *
    165  * FUNCTION:    DtFatal
    166  *
    167  * PARAMETERS:  None
    168  *
    169  * RETURN:      None
    170  *
    171  * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
    172  *              compile or I/O errors
    173  *
    174  ******************************************************************************/
    175 
    176 void
    177 DtFatal (
    178     UINT16                  MessageId,
    179     DT_FIELD                *FieldObject,
    180     char                    *ExtraMessage)
    181 {
    182 
    183     DtError (ASL_ERROR, MessageId, FieldObject, ExtraMessage);
    184 
    185 /*
    186  * TBD: remove this entire function, DtFatal
    187  *
    188  * We cannot abort the compiler on error, because we may be compiling a
    189  * list of files. We must move on to the next file.
    190  */
    191 #ifdef __OBSOLETE
    192     CmCleanupAndExit ();
    193     exit (1);
    194 #endif
    195 }
    196 
    197 
    198 /******************************************************************************
    199  *
    200  * FUNCTION:    DtGetFieldValue
    201  *
    202  * PARAMETERS:  Field               - Current field list pointer
    203  *
    204  * RETURN:      Field value
    205  *
    206  * DESCRIPTION: Get field value
    207  *
    208  *****************************************************************************/
    209 
    210 char *
    211 DtGetFieldValue (
    212     DT_FIELD                *Field)
    213 {
    214     if (!Field)
    215     {
    216         return (NULL);
    217     }
    218 
    219     return (Field->Value);
    220 }
    221 
    222 
    223 /******************************************************************************
    224  *
    225  * FUNCTION:    DtGetFieldType
    226  *
    227  * PARAMETERS:  Info                - Data table info
    228  *
    229  * RETURN:      Field type
    230  *
    231  * DESCRIPTION: Get field type
    232  *
    233  *****************************************************************************/
    234 
    235 UINT8
    236 DtGetFieldType (
    237     ACPI_DMTABLE_INFO       *Info)
    238 {
    239     UINT8                   Type;
    240 
    241 
    242     /* DT_FLAG means that this is the start of a block of flag bits */
    243     /* TBD - we can make these a separate opcode later */
    244 
    245     if (Info->Flags & DT_FLAG)
    246     {
    247         return (DT_FIELD_TYPE_FLAGS_INTEGER);
    248     }
    249 
    250     /* Type is based upon the opcode for this field in the info table */
    251 
    252     switch (Info->Opcode)
    253     {
    254     case ACPI_DMT_FLAG0:
    255     case ACPI_DMT_FLAG1:
    256     case ACPI_DMT_FLAG2:
    257     case ACPI_DMT_FLAG3:
    258     case ACPI_DMT_FLAG4:
    259     case ACPI_DMT_FLAG5:
    260     case ACPI_DMT_FLAG6:
    261     case ACPI_DMT_FLAG7:
    262     case ACPI_DMT_FLAGS0:
    263     case ACPI_DMT_FLAGS1:
    264     case ACPI_DMT_FLAGS2:
    265     case ACPI_DMT_FLAGS4:
    266 
    267         Type = DT_FIELD_TYPE_FLAG;
    268         break;
    269 
    270     case ACPI_DMT_NAME4:
    271     case ACPI_DMT_SIG:
    272     case ACPI_DMT_NAME6:
    273     case ACPI_DMT_NAME8:
    274     case ACPI_DMT_STRING:
    275 
    276         Type = DT_FIELD_TYPE_STRING;
    277         break;
    278 
    279     case ACPI_DMT_BUFFER:
    280     case ACPI_DMT_RAW_BUFFER:
    281     case ACPI_DMT_BUF7:
    282     case ACPI_DMT_BUF10:
    283     case ACPI_DMT_BUF12:
    284     case ACPI_DMT_BUF16:
    285     case ACPI_DMT_BUF128:
    286     case ACPI_DMT_PCI_PATH:
    287 
    288         Type = DT_FIELD_TYPE_BUFFER;
    289         break;
    290 
    291     case ACPI_DMT_GAS:
    292     case ACPI_DMT_HESTNTFY:
    293     case ACPI_DMT_IORTMEM:
    294 
    295         Type = DT_FIELD_TYPE_INLINE_SUBTABLE;
    296         break;
    297 
    298     case ACPI_DMT_UNICODE:
    299 
    300         Type = DT_FIELD_TYPE_UNICODE;
    301         break;
    302 
    303     case ACPI_DMT_UUID:
    304 
    305         Type = DT_FIELD_TYPE_UUID;
    306         break;
    307 
    308     case ACPI_DMT_DEVICE_PATH:
    309 
    310         Type = DT_FIELD_TYPE_DEVICE_PATH;
    311         break;
    312 
    313     case ACPI_DMT_LABEL:
    314 
    315         Type = DT_FIELD_TYPE_LABEL;
    316         break;
    317 
    318     default:
    319 
    320         Type = DT_FIELD_TYPE_INTEGER;
    321         break;
    322     }
    323 
    324     return (Type);
    325 }
    326 
    327 
    328 /******************************************************************************
    329  *
    330  * FUNCTION:    DtGetBufferLength
    331  *
    332  * PARAMETERS:  Buffer              - List of integers,
    333  *                                    for example "10 3A 4F 2E"
    334  *
    335  * RETURN:      Count of integer
    336  *
    337  * DESCRIPTION: Get length of bytes needed to store the integers
    338  *
    339  *****************************************************************************/
    340 
    341 UINT32
    342 DtGetBufferLength (
    343     char                    *Buffer)
    344 {
    345     UINT32                  ByteLength = 0;
    346 
    347 
    348     while (*Buffer)
    349     {
    350         if (*Buffer == ' ')
    351         {
    352             ByteLength++;
    353 
    354             while (*Buffer == ' ')
    355             {
    356                 Buffer++;
    357             }
    358         }
    359 
    360         Buffer++;
    361     }
    362 
    363     return (++ByteLength);
    364 }
    365 
    366 
    367 /******************************************************************************
    368  *
    369  * FUNCTION:    DtGetFieldLength
    370  *
    371  * PARAMETERS:  Field               - Current field
    372  *              Info                - Data table info
    373  *
    374  * RETURN:      Field length
    375  *
    376  * DESCRIPTION: Get length of bytes needed to compile the field
    377  *
    378  * Note: This function must remain in sync with AcpiDmDumpTable.
    379  *
    380  *****************************************************************************/
    381 
    382 UINT32
    383 DtGetFieldLength (
    384     DT_FIELD                *Field,
    385     ACPI_DMTABLE_INFO       *Info)
    386 {
    387     UINT32                  ByteLength = 0;
    388     char                    *Value;
    389 
    390 
    391     /* Length is based upon the opcode for this field in the info table */
    392 
    393     switch (Info->Opcode)
    394     {
    395     case ACPI_DMT_FLAG0:
    396     case ACPI_DMT_FLAG1:
    397     case ACPI_DMT_FLAG2:
    398     case ACPI_DMT_FLAG3:
    399     case ACPI_DMT_FLAG4:
    400     case ACPI_DMT_FLAG5:
    401     case ACPI_DMT_FLAG6:
    402     case ACPI_DMT_FLAG7:
    403     case ACPI_DMT_FLAGS0:
    404     case ACPI_DMT_FLAGS1:
    405     case ACPI_DMT_FLAGS2:
    406     case ACPI_DMT_FLAGS4:
    407     case ACPI_DMT_LABEL:
    408     case ACPI_DMT_EXTRA_TEXT:
    409 
    410         ByteLength = 0;
    411         break;
    412 
    413     case ACPI_DMT_UINT8:
    414     case ACPI_DMT_CHKSUM:
    415     case ACPI_DMT_SPACEID:
    416     case ACPI_DMT_ACCWIDTH:
    417     case ACPI_DMT_IVRS:
    418     case ACPI_DMT_GTDT:
    419     case ACPI_DMT_MADT:
    420     case ACPI_DMT_PCCT:
    421     case ACPI_DMT_PMTT:
    422     case ACPI_DMT_SRAT:
    423     case ACPI_DMT_ASF:
    424     case ACPI_DMT_HESTNTYP:
    425     case ACPI_DMT_FADTPM:
    426     case ACPI_DMT_EINJACT:
    427     case ACPI_DMT_EINJINST:
    428     case ACPI_DMT_ERSTACT:
    429     case ACPI_DMT_ERSTINST:
    430     case ACPI_DMT_DMAR_SCOPE:
    431 
    432         ByteLength = 1;
    433         break;
    434 
    435     case ACPI_DMT_UINT16:
    436     case ACPI_DMT_DMAR:
    437     case ACPI_DMT_HEST:
    438     case ACPI_DMT_NFIT:
    439     case ACPI_DMT_PCI_PATH:
    440 
    441         ByteLength = 2;
    442         break;
    443 
    444     case ACPI_DMT_UINT24:
    445 
    446         ByteLength = 3;
    447         break;
    448 
    449     case ACPI_DMT_UINT32:
    450     case ACPI_DMT_NAME4:
    451     case ACPI_DMT_SIG:
    452     case ACPI_DMT_LPIT:
    453 
    454         ByteLength = 4;
    455         break;
    456 
    457     case ACPI_DMT_UINT40:
    458 
    459         ByteLength = 5;
    460         break;
    461 
    462     case ACPI_DMT_UINT48:
    463     case ACPI_DMT_NAME6:
    464 
    465         ByteLength = 6;
    466         break;
    467 
    468     case ACPI_DMT_UINT56:
    469     case ACPI_DMT_BUF7:
    470 
    471         ByteLength = 7;
    472         break;
    473 
    474     case ACPI_DMT_UINT64:
    475     case ACPI_DMT_NAME8:
    476 
    477         ByteLength = 8;
    478         break;
    479 
    480     case ACPI_DMT_STRING:
    481 
    482         Value = DtGetFieldValue (Field);
    483         if (Value)
    484         {
    485             ByteLength = strlen (Value) + 1;
    486         }
    487         else
    488         {   /* At this point, this is a fatal error */
    489 
    490             snprintf (MsgBuffer, sizeof(MsgBuffer), "Expected \"%s\"", Info->Name);
    491             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
    492             return (0);
    493         }
    494         break;
    495 
    496     case ACPI_DMT_GAS:
    497 
    498         ByteLength = sizeof (ACPI_GENERIC_ADDRESS);
    499         break;
    500 
    501     case ACPI_DMT_HESTNTFY:
    502 
    503         ByteLength = sizeof (ACPI_HEST_NOTIFY);
    504         break;
    505 
    506     case ACPI_DMT_IORTMEM:
    507 
    508         ByteLength = sizeof (ACPI_IORT_MEMORY_ACCESS);
    509         break;
    510 
    511     case ACPI_DMT_BUFFER:
    512     case ACPI_DMT_RAW_BUFFER:
    513 
    514         Value = DtGetFieldValue (Field);
    515         if (Value)
    516         {
    517             ByteLength = DtGetBufferLength (Value);
    518         }
    519         else
    520         {   /* At this point, this is a fatal error */
    521 
    522             snprintf (MsgBuffer, sizeof(MsgBuffer), "Expected \"%s\"", Info->Name);
    523             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
    524             return (0);
    525         }
    526         break;
    527 
    528     case ACPI_DMT_BUF10:
    529 
    530         ByteLength = 10;
    531         break;
    532 
    533     case ACPI_DMT_BUF12:
    534 
    535         ByteLength = 12;
    536         break;
    537 
    538     case ACPI_DMT_BUF16:
    539     case ACPI_DMT_UUID:
    540 
    541         ByteLength = 16;
    542         break;
    543 
    544     case ACPI_DMT_BUF128:
    545 
    546         ByteLength = 128;
    547         break;
    548 
    549     case ACPI_DMT_UNICODE:
    550 
    551         Value = DtGetFieldValue (Field);
    552 
    553         /* TBD: error if Value is NULL? (as below?) */
    554 
    555         ByteLength = (strlen (Value) + 1) * sizeof(UINT16);
    556         break;
    557 
    558     default:
    559 
    560         DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode");
    561         return (0);
    562     }
    563 
    564     return (ByteLength);
    565 }
    566 
    567 
    568 /******************************************************************************
    569  *
    570  * FUNCTION:    DtSum
    571  *
    572  * PARAMETERS:  DT_WALK_CALLBACK:
    573  *              Subtable            - Subtable
    574  *              Context             - Unused
    575  *              ReturnValue         - Store the checksum of subtable
    576  *
    577  * RETURN:      Status
    578  *
    579  * DESCRIPTION: Get the checksum of subtable
    580  *
    581  *****************************************************************************/
    582 
    583 static void
    584 DtSum (
    585     DT_SUBTABLE             *Subtable,
    586     void                    *Context,
    587     void                    *ReturnValue)
    588 {
    589     UINT8                   Checksum;
    590     UINT8                   *Sum = ReturnValue;
    591 
    592 
    593     Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length);
    594     *Sum = (UINT8) (*Sum + Checksum);
    595 }
    596 
    597 
    598 /******************************************************************************
    599  *
    600  * FUNCTION:    DtSetTableChecksum
    601  *
    602  * PARAMETERS:  ChecksumPointer     - Where to return the checksum
    603  *
    604  * RETURN:      None
    605  *
    606  * DESCRIPTION: Set checksum of the whole data table into the checksum field
    607  *
    608  *****************************************************************************/
    609 
    610 void
    611 DtSetTableChecksum (
    612     UINT8                   *ChecksumPointer)
    613 {
    614     UINT8                   Checksum = 0;
    615     UINT8                   OldSum;
    616 
    617 
    618     DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum);
    619 
    620     OldSum = *ChecksumPointer;
    621     Checksum = (UINT8) (Checksum - OldSum);
    622 
    623     /* Compute the final checksum */
    624 
    625     Checksum = (UINT8) (0 - Checksum);
    626     *ChecksumPointer = Checksum;
    627 }
    628 
    629 
    630 /******************************************************************************
    631  *
    632  * FUNCTION:    DtSetTableLength
    633  *
    634  * PARAMETERS:  None
    635  *
    636  * RETURN:      None
    637  *
    638  * DESCRIPTION: Walk the subtables and set all the length fields
    639  *
    640  *****************************************************************************/
    641 
    642 void
    643 DtSetTableLength (
    644     void)
    645 {
    646     DT_SUBTABLE             *ParentTable;
    647     DT_SUBTABLE             *ChildTable;
    648 
    649 
    650     ParentTable = Gbl_RootTable;
    651     ChildTable = NULL;
    652 
    653     if (!ParentTable)
    654     {
    655         return;
    656     }
    657 
    658     DtSetSubtableLength (ParentTable);
    659 
    660     while (1)
    661     {
    662         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
    663         if (ChildTable)
    664         {
    665             if (ChildTable->LengthField)
    666             {
    667                 DtSetSubtableLength (ChildTable);
    668             }
    669 
    670             if (ChildTable->Child)
    671             {
    672                 ParentTable = ChildTable;
    673                 ChildTable = NULL;
    674             }
    675             else
    676             {
    677                 ParentTable->TotalLength += ChildTable->TotalLength;
    678                 if (ParentTable->LengthField)
    679                 {
    680                     DtSetSubtableLength (ParentTable);
    681                 }
    682             }
    683         }
    684         else
    685         {
    686             ChildTable = ParentTable;
    687 
    688             if (ChildTable == Gbl_RootTable)
    689             {
    690                 break;
    691             }
    692 
    693             ParentTable = DtGetParentSubtable (ParentTable);
    694 
    695             ParentTable->TotalLength += ChildTable->TotalLength;
    696             if (ParentTable->LengthField)
    697             {
    698                 DtSetSubtableLength (ParentTable);
    699             }
    700         }
    701     }
    702 }
    703 
    704 
    705 /******************************************************************************
    706  *
    707  * FUNCTION:    DtWalkTableTree
    708  *
    709  * PARAMETERS:  StartTable          - Subtable in the tree where walking begins
    710  *              UserFunction        - Called during the walk
    711  *              Context             - Passed to user function
    712  *              ReturnValue         - The return value of UserFunction
    713  *
    714  * RETURN:      None
    715  *
    716  * DESCRIPTION: Performs a depth-first walk of the subtable tree
    717  *
    718  *****************************************************************************/
    719 
    720 void
    721 DtWalkTableTree (
    722     DT_SUBTABLE             *StartTable,
    723     DT_WALK_CALLBACK        UserFunction,
    724     void                    *Context,
    725     void                    *ReturnValue)
    726 {
    727     DT_SUBTABLE             *ParentTable;
    728     DT_SUBTABLE             *ChildTable;
    729 
    730 
    731     ParentTable = StartTable;
    732     ChildTable = NULL;
    733 
    734     if (!ParentTable)
    735     {
    736         return;
    737     }
    738 
    739     UserFunction (ParentTable, Context, ReturnValue);
    740 
    741     while (1)
    742     {
    743         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
    744         if (ChildTable)
    745         {
    746             UserFunction (ChildTable, Context, ReturnValue);
    747 
    748             if (ChildTable->Child)
    749             {
    750                 ParentTable = ChildTable;
    751                 ChildTable = NULL;
    752             }
    753         }
    754         else
    755         {
    756             ChildTable = ParentTable;
    757             if (ChildTable == Gbl_RootTable)
    758             {
    759                 break;
    760             }
    761 
    762             ParentTable = DtGetParentSubtable (ParentTable);
    763 
    764             if (ChildTable->Peer == StartTable)
    765             {
    766                 break;
    767             }
    768         }
    769     }
    770 }
    771 
    772 
    773 /*******************************************************************************
    774  *
    775  * FUNCTION:    UtSubtableCacheCalloc
    776  *
    777  * PARAMETERS:  None
    778  *
    779  * RETURN:      Pointer to the buffer. Aborts on allocation failure
    780  *
    781  * DESCRIPTION: Allocate a subtable object buffer. Bypass the local
    782  *              dynamic memory manager for performance reasons (This has a
    783  *              major impact on the speed of the compiler.)
    784  *
    785  ******************************************************************************/
    786 
    787 DT_SUBTABLE *
    788 UtSubtableCacheCalloc (
    789     void)
    790 {
    791     ASL_CACHE_INFO          *Cache;
    792 
    793 
    794     if (Gbl_SubtableCacheNext >= Gbl_SubtableCacheLast)
    795     {
    796         /* Allocate a new buffer */
    797 
    798         Cache = UtLocalCalloc (sizeof (Cache->Next) +
    799             (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE));
    800 
    801         /* Link new cache buffer to head of list */
    802 
    803         Cache->Next = Gbl_SubtableCacheList;
    804         Gbl_SubtableCacheList = Cache;
    805 
    806         /* Setup cache management pointers */
    807 
    808         Gbl_SubtableCacheNext = ACPI_CAST_PTR (DT_SUBTABLE, Cache->Buffer);
    809         Gbl_SubtableCacheLast = Gbl_SubtableCacheNext + ASL_SUBTABLE_CACHE_SIZE;
    810     }
    811 
    812     Gbl_SubtableCount++;
    813     return (Gbl_SubtableCacheNext++);
    814 }
    815 
    816 
    817 /*******************************************************************************
    818  *
    819  * FUNCTION:    UtFieldCacheCalloc
    820  *
    821  * PARAMETERS:  None
    822  *
    823  * RETURN:      Pointer to the buffer. Aborts on allocation failure
    824  *
    825  * DESCRIPTION: Allocate a field object buffer. Bypass the local
    826  *              dynamic memory manager for performance reasons (This has a
    827  *              major impact on the speed of the compiler.)
    828  *
    829  ******************************************************************************/
    830 
    831 DT_FIELD *
    832 UtFieldCacheCalloc (
    833     void)
    834 {
    835     ASL_CACHE_INFO          *Cache;
    836 
    837 
    838     if (Gbl_FieldCacheNext >= Gbl_FieldCacheLast)
    839     {
    840         /* Allocate a new buffer */
    841 
    842         Cache = UtLocalCalloc (sizeof (Cache->Next) +
    843             (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE));
    844 
    845         /* Link new cache buffer to head of list */
    846 
    847         Cache->Next = Gbl_FieldCacheList;
    848         Gbl_FieldCacheList = Cache;
    849 
    850         /* Setup cache management pointers */
    851 
    852         Gbl_FieldCacheNext = ACPI_CAST_PTR (DT_FIELD, Cache->Buffer);
    853         Gbl_FieldCacheLast = Gbl_FieldCacheNext + ASL_FIELD_CACHE_SIZE;
    854     }
    855 
    856     Gbl_FieldCount++;
    857     return (Gbl_FieldCacheNext++);
    858 }
    859 
    860 
    861 /*******************************************************************************
    862  *
    863  * FUNCTION:    DtDeleteCaches
    864  *
    865  * PARAMETERS:  None
    866  *
    867  * RETURN:      None
    868  *
    869  * DESCRIPTION: Delete all local cache buffer blocks
    870  *
    871  ******************************************************************************/
    872 
    873 void
    874 DtDeleteCaches (
    875     void)
    876 {
    877     UINT32                  BufferCount;
    878     ASL_CACHE_INFO          *Next;
    879 
    880 
    881     /* Field cache */
    882 
    883     BufferCount = 0;
    884     while (Gbl_FieldCacheList)
    885     {
    886         Next = Gbl_FieldCacheList->Next;
    887         ACPI_FREE (Gbl_FieldCacheList);
    888         Gbl_FieldCacheList = Next;
    889         BufferCount++;
    890     }
    891 
    892     DbgPrint (ASL_DEBUG_OUTPUT,
    893         "%u Fields, Buffer size: %u fields (%u bytes), %u Buffers\n",
    894         Gbl_FieldCount, ASL_FIELD_CACHE_SIZE,
    895         (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE), BufferCount);
    896 
    897     Gbl_FieldCount = 0;
    898     Gbl_FieldCacheNext = NULL;
    899     Gbl_FieldCacheLast = NULL;
    900 
    901     /* Subtable cache */
    902 
    903     BufferCount = 0;
    904     while (Gbl_SubtableCacheList)
    905     {
    906         Next = Gbl_SubtableCacheList->Next;
    907         ACPI_FREE (Gbl_SubtableCacheList);
    908         Gbl_SubtableCacheList = Next;
    909         BufferCount++;
    910     }
    911 
    912     DbgPrint (ASL_DEBUG_OUTPUT,
    913         "%u Subtables, Buffer size: %u subtables (%u bytes), %u Buffers\n",
    914         Gbl_SubtableCount, ASL_SUBTABLE_CACHE_SIZE,
    915         (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE), BufferCount);
    916 
    917     Gbl_SubtableCount = 0;
    918     Gbl_SubtableCacheNext = NULL;
    919     Gbl_SubtableCacheLast = NULL;
    920 }
    921