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