xref: /freebsd/sys/contrib/dev/acpica/compiler/dtutils.c (revision 39ee7a7a6bdd1557b1c3532abf60d139798ac88b)
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 <contrib/dev/acpica/compiler/aslcompiler.h>
45 #include <contrib/dev/acpica/compiler/dtcompiler.h>
46 #include <contrib/dev/acpica/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 (isdigit ((int) *ThisChar))
245         {
246             /* Convert ASCII 0-9 to Decimal value */
247 
248             ThisDigit = ((UINT8) *ThisChar) - '0';
249         }
250         else /* Letter */
251         {
252             ThisDigit = (UINT32) toupper ((int) *ThisChar);
253             if (!isxdigit ((int) 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     case ACPI_DMT_IORTMEM:
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_NFIT:
525     case ACPI_DMT_PCI_PATH:
526 
527         ByteLength = 2;
528         break;
529 
530     case ACPI_DMT_UINT24:
531 
532         ByteLength = 3;
533         break;
534 
535     case ACPI_DMT_UINT32:
536     case ACPI_DMT_NAME4:
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 = strlen (Value) + 1;
572         }
573         else
574         {   /* At this point, this is a fatal error */
575 
576             sprintf (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_IORTMEM:
593 
594         ByteLength = sizeof (ACPI_IORT_MEMORY_ACCESS);
595         break;
596 
597     case ACPI_DMT_BUFFER:
598     case ACPI_DMT_RAW_BUFFER:
599 
600         Value = DtGetFieldValue (Field);
601         if (Value)
602         {
603             ByteLength = DtGetBufferLength (Value);
604         }
605         else
606         {   /* At this point, this is a fatal error */
607 
608             sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
609             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
610             return (0);
611         }
612         break;
613 
614     case ACPI_DMT_BUF10:
615 
616         ByteLength = 10;
617         break;
618 
619     case ACPI_DMT_BUF16:
620     case ACPI_DMT_UUID:
621 
622         ByteLength = 16;
623         break;
624 
625     case ACPI_DMT_BUF128:
626 
627         ByteLength = 128;
628         break;
629 
630     case ACPI_DMT_UNICODE:
631 
632         Value = DtGetFieldValue (Field);
633 
634         /* TBD: error if Value is NULL? (as below?) */
635 
636         ByteLength = (strlen (Value) + 1) * sizeof(UINT16);
637         break;
638 
639     default:
640 
641         DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode");
642         return (0);
643     }
644 
645     return (ByteLength);
646 }
647 
648 
649 /******************************************************************************
650  *
651  * FUNCTION:    DtSum
652  *
653  * PARAMETERS:  DT_WALK_CALLBACK:
654  *              Subtable            - Subtable
655  *              Context             - Unused
656  *              ReturnValue         - Store the checksum of subtable
657  *
658  * RETURN:      Status
659  *
660  * DESCRIPTION: Get the checksum of subtable
661  *
662  *****************************************************************************/
663 
664 static void
665 DtSum (
666     DT_SUBTABLE             *Subtable,
667     void                    *Context,
668     void                    *ReturnValue)
669 {
670     UINT8                   Checksum;
671     UINT8                   *Sum = ReturnValue;
672 
673 
674     Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length);
675     *Sum = (UINT8) (*Sum + Checksum);
676 }
677 
678 
679 /******************************************************************************
680  *
681  * FUNCTION:    DtSetTableChecksum
682  *
683  * PARAMETERS:  ChecksumPointer     - Where to return the checksum
684  *
685  * RETURN:      None
686  *
687  * DESCRIPTION: Set checksum of the whole data table into the checksum field
688  *
689  *****************************************************************************/
690 
691 void
692 DtSetTableChecksum (
693     UINT8                   *ChecksumPointer)
694 {
695     UINT8                   Checksum = 0;
696     UINT8                   OldSum;
697 
698 
699     DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum);
700 
701     OldSum = *ChecksumPointer;
702     Checksum = (UINT8) (Checksum - OldSum);
703 
704     /* Compute the final checksum */
705 
706     Checksum = (UINT8) (0 - Checksum);
707     *ChecksumPointer = Checksum;
708 }
709 
710 
711 /******************************************************************************
712  *
713  * FUNCTION:    DtSetTableLength
714  *
715  * PARAMETERS:  None
716  *
717  * RETURN:      None
718  *
719  * DESCRIPTION: Walk the subtables and set all the length fields
720  *
721  *****************************************************************************/
722 
723 void
724 DtSetTableLength (
725     void)
726 {
727     DT_SUBTABLE             *ParentTable;
728     DT_SUBTABLE             *ChildTable;
729 
730 
731     ParentTable = Gbl_RootTable;
732     ChildTable = NULL;
733 
734     if (!ParentTable)
735     {
736         return;
737     }
738 
739     DtSetSubtableLength (ParentTable);
740 
741     while (1)
742     {
743         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
744         if (ChildTable)
745         {
746             if (ChildTable->LengthField)
747             {
748                 DtSetSubtableLength (ChildTable);
749             }
750 
751             if (ChildTable->Child)
752             {
753                 ParentTable = ChildTable;
754                 ChildTable = NULL;
755             }
756             else
757             {
758                 ParentTable->TotalLength += ChildTable->TotalLength;
759                 if (ParentTable->LengthField)
760                 {
761                     DtSetSubtableLength (ParentTable);
762                 }
763             }
764         }
765         else
766         {
767             ChildTable = ParentTable;
768 
769             if (ChildTable == Gbl_RootTable)
770             {
771                 break;
772             }
773 
774             ParentTable = DtGetParentSubtable (ParentTable);
775 
776             ParentTable->TotalLength += ChildTable->TotalLength;
777             if (ParentTable->LengthField)
778             {
779                 DtSetSubtableLength (ParentTable);
780             }
781         }
782     }
783 }
784 
785 
786 /******************************************************************************
787  *
788  * FUNCTION:    DtWalkTableTree
789  *
790  * PARAMETERS:  StartTable          - Subtable in the tree where walking begins
791  *              UserFunction        - Called during the walk
792  *              Context             - Passed to user function
793  *              ReturnValue         - The return value of UserFunction
794  *
795  * RETURN:      None
796  *
797  * DESCRIPTION: Performs a depth-first walk of the subtable tree
798  *
799  *****************************************************************************/
800 
801 void
802 DtWalkTableTree (
803     DT_SUBTABLE             *StartTable,
804     DT_WALK_CALLBACK        UserFunction,
805     void                    *Context,
806     void                    *ReturnValue)
807 {
808     DT_SUBTABLE             *ParentTable;
809     DT_SUBTABLE             *ChildTable;
810 
811 
812     ParentTable = StartTable;
813     ChildTable = NULL;
814 
815     if (!ParentTable)
816     {
817         return;
818     }
819 
820     UserFunction (ParentTable, Context, ReturnValue);
821 
822     while (1)
823     {
824         ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
825         if (ChildTable)
826         {
827             UserFunction (ChildTable, Context, ReturnValue);
828 
829             if (ChildTable->Child)
830             {
831                 ParentTable = ChildTable;
832                 ChildTable = NULL;
833             }
834         }
835         else
836         {
837             ChildTable = ParentTable;
838             if (ChildTable == Gbl_RootTable)
839             {
840                 break;
841             }
842 
843             ParentTable = DtGetParentSubtable (ParentTable);
844 
845             if (ChildTable->Peer == StartTable)
846             {
847                 break;
848             }
849         }
850     }
851 }
852 
853 
854 /*******************************************************************************
855  *
856  * FUNCTION:    UtSubtableCacheCalloc
857  *
858  * PARAMETERS:  None
859  *
860  * RETURN:      Pointer to the buffer. Aborts on allocation failure
861  *
862  * DESCRIPTION: Allocate a subtable object buffer. Bypass the local
863  *              dynamic memory manager for performance reasons (This has a
864  *              major impact on the speed of the compiler.)
865  *
866  ******************************************************************************/
867 
868 DT_SUBTABLE *
869 UtSubtableCacheCalloc (
870     void)
871 {
872     ASL_CACHE_INFO          *Cache;
873 
874 
875     if (Gbl_SubtableCacheNext >= Gbl_SubtableCacheLast)
876     {
877         /* Allocate a new buffer */
878 
879         Cache = UtLocalCalloc (sizeof (Cache->Next) +
880             (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE));
881 
882         /* Link new cache buffer to head of list */
883 
884         Cache->Next = Gbl_SubtableCacheList;
885         Gbl_SubtableCacheList = Cache;
886 
887         /* Setup cache management pointers */
888 
889         Gbl_SubtableCacheNext = ACPI_CAST_PTR (DT_SUBTABLE, Cache->Buffer);
890         Gbl_SubtableCacheLast = Gbl_SubtableCacheNext + ASL_SUBTABLE_CACHE_SIZE;
891     }
892 
893     Gbl_SubtableCount++;
894     return (Gbl_SubtableCacheNext++);
895 }
896 
897 
898 /*******************************************************************************
899  *
900  * FUNCTION:    UtFieldCacheCalloc
901  *
902  * PARAMETERS:  None
903  *
904  * RETURN:      Pointer to the buffer. Aborts on allocation failure
905  *
906  * DESCRIPTION: Allocate a field object buffer. Bypass the local
907  *              dynamic memory manager for performance reasons (This has a
908  *              major impact on the speed of the compiler.)
909  *
910  ******************************************************************************/
911 
912 DT_FIELD *
913 UtFieldCacheCalloc (
914     void)
915 {
916     ASL_CACHE_INFO          *Cache;
917 
918 
919     if (Gbl_FieldCacheNext >= Gbl_FieldCacheLast)
920     {
921         /* Allocate a new buffer */
922 
923         Cache = UtLocalCalloc (sizeof (Cache->Next) +
924             (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE));
925 
926         /* Link new cache buffer to head of list */
927 
928         Cache->Next = Gbl_FieldCacheList;
929         Gbl_FieldCacheList = Cache;
930 
931         /* Setup cache management pointers */
932 
933         Gbl_FieldCacheNext = ACPI_CAST_PTR (DT_FIELD, Cache->Buffer);
934         Gbl_FieldCacheLast = Gbl_FieldCacheNext + ASL_FIELD_CACHE_SIZE;
935     }
936 
937     Gbl_FieldCount++;
938     return (Gbl_FieldCacheNext++);
939 }
940 
941 
942 /*******************************************************************************
943  *
944  * FUNCTION:    DtDeleteCaches
945  *
946  * PARAMETERS:  None
947  *
948  * RETURN:      None
949  *
950  * DESCRIPTION: Delete all local cache buffer blocks
951  *
952  ******************************************************************************/
953 
954 void
955 DtDeleteCaches (
956     void)
957 {
958     UINT32                  BufferCount;
959     ASL_CACHE_INFO          *Next;
960 
961 
962     /* Field cache */
963 
964     BufferCount = 0;
965     while (Gbl_FieldCacheList)
966     {
967         Next = Gbl_FieldCacheList->Next;
968         ACPI_FREE (Gbl_FieldCacheList);
969         Gbl_FieldCacheList = Next;
970         BufferCount++;
971     }
972 
973     DbgPrint (ASL_DEBUG_OUTPUT,
974         "%u Fields, Buffer size: %u fields (%u bytes), %u Buffers\n",
975         Gbl_FieldCount, ASL_FIELD_CACHE_SIZE,
976         (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE), BufferCount);
977 
978     Gbl_FieldCount = 0;
979     Gbl_FieldCacheNext = NULL;
980     Gbl_FieldCacheLast = NULL;
981 
982     /* Subtable cache */
983 
984     BufferCount = 0;
985     while (Gbl_SubtableCacheList)
986     {
987         Next = Gbl_SubtableCacheList->Next;
988         ACPI_FREE (Gbl_SubtableCacheList);
989         Gbl_SubtableCacheList = Next;
990         BufferCount++;
991     }
992 
993     DbgPrint (ASL_DEBUG_OUTPUT,
994         "%u Subtables, Buffer size: %u subtables (%u bytes), %u Buffers\n",
995         Gbl_SubtableCount, ASL_SUBTABLE_CACHE_SIZE,
996         (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE), BufferCount);
997 
998     Gbl_SubtableCount = 0;
999     Gbl_SubtableCacheNext = NULL;
1000     Gbl_SubtableCacheLast = NULL;
1001 }
1002