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