1 /****************************************************************************** 2 * 3 * Module Name: dtutils.c - Utility routines for the data table compiler 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 (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_BUF12: 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 case ACPI_DMT_IORTMEM: 381 382 Type = DT_FIELD_TYPE_INLINE_SUBTABLE; 383 break; 384 385 case ACPI_DMT_UNICODE: 386 387 Type = DT_FIELD_TYPE_UNICODE; 388 break; 389 390 case ACPI_DMT_UUID: 391 392 Type = DT_FIELD_TYPE_UUID; 393 break; 394 395 case ACPI_DMT_DEVICE_PATH: 396 397 Type = DT_FIELD_TYPE_DEVICE_PATH; 398 break; 399 400 case ACPI_DMT_LABEL: 401 402 Type = DT_FIELD_TYPE_LABEL; 403 break; 404 405 default: 406 407 Type = DT_FIELD_TYPE_INTEGER; 408 break; 409 } 410 411 return (Type); 412 } 413 414 415 /****************************************************************************** 416 * 417 * FUNCTION: DtGetBufferLength 418 * 419 * PARAMETERS: Buffer - List of integers, 420 * for example "10 3A 4F 2E" 421 * 422 * RETURN: Count of integer 423 * 424 * DESCRIPTION: Get length of bytes needed to store the integers 425 * 426 *****************************************************************************/ 427 428 UINT32 429 DtGetBufferLength ( 430 char *Buffer) 431 { 432 UINT32 ByteLength = 0; 433 434 435 while (*Buffer) 436 { 437 if (*Buffer == ' ') 438 { 439 ByteLength++; 440 441 while (*Buffer == ' ') 442 { 443 Buffer++; 444 } 445 } 446 447 Buffer++; 448 } 449 450 return (++ByteLength); 451 } 452 453 454 /****************************************************************************** 455 * 456 * FUNCTION: DtGetFieldLength 457 * 458 * PARAMETERS: Field - Current field 459 * Info - Data table info 460 * 461 * RETURN: Field length 462 * 463 * DESCRIPTION: Get length of bytes needed to compile the field 464 * 465 * Note: This function must remain in sync with AcpiDmDumpTable. 466 * 467 *****************************************************************************/ 468 469 UINT32 470 DtGetFieldLength ( 471 DT_FIELD *Field, 472 ACPI_DMTABLE_INFO *Info) 473 { 474 UINT32 ByteLength = 0; 475 char *Value; 476 477 478 /* Length is based upon the opcode for this field in the info table */ 479 480 switch (Info->Opcode) 481 { 482 case ACPI_DMT_FLAG0: 483 case ACPI_DMT_FLAG1: 484 case ACPI_DMT_FLAG2: 485 case ACPI_DMT_FLAG3: 486 case ACPI_DMT_FLAG4: 487 case ACPI_DMT_FLAG5: 488 case ACPI_DMT_FLAG6: 489 case ACPI_DMT_FLAG7: 490 case ACPI_DMT_FLAGS0: 491 case ACPI_DMT_FLAGS1: 492 case ACPI_DMT_FLAGS2: 493 case ACPI_DMT_FLAGS4: 494 case ACPI_DMT_LABEL: 495 case ACPI_DMT_EXTRA_TEXT: 496 497 ByteLength = 0; 498 break; 499 500 case ACPI_DMT_UINT8: 501 case ACPI_DMT_CHKSUM: 502 case ACPI_DMT_SPACEID: 503 case ACPI_DMT_ACCWIDTH: 504 case ACPI_DMT_IVRS: 505 case ACPI_DMT_GTDT: 506 case ACPI_DMT_MADT: 507 case ACPI_DMT_PCCT: 508 case ACPI_DMT_PMTT: 509 case ACPI_DMT_SRAT: 510 case ACPI_DMT_ASF: 511 case ACPI_DMT_HESTNTYP: 512 case ACPI_DMT_FADTPM: 513 case ACPI_DMT_EINJACT: 514 case ACPI_DMT_EINJINST: 515 case ACPI_DMT_ERSTACT: 516 case ACPI_DMT_ERSTINST: 517 case ACPI_DMT_DMAR_SCOPE: 518 519 ByteLength = 1; 520 break; 521 522 case ACPI_DMT_UINT16: 523 case ACPI_DMT_DMAR: 524 case ACPI_DMT_HEST: 525 case ACPI_DMT_NFIT: 526 case ACPI_DMT_PCI_PATH: 527 528 ByteLength = 2; 529 break; 530 531 case ACPI_DMT_UINT24: 532 533 ByteLength = 3; 534 break; 535 536 case ACPI_DMT_UINT32: 537 case ACPI_DMT_NAME4: 538 case ACPI_DMT_SIG: 539 case ACPI_DMT_LPIT: 540 541 ByteLength = 4; 542 break; 543 544 case ACPI_DMT_UINT40: 545 546 ByteLength = 5; 547 break; 548 549 case ACPI_DMT_UINT48: 550 case ACPI_DMT_NAME6: 551 552 ByteLength = 6; 553 break; 554 555 case ACPI_DMT_UINT56: 556 case ACPI_DMT_BUF7: 557 558 ByteLength = 7; 559 break; 560 561 case ACPI_DMT_UINT64: 562 case ACPI_DMT_NAME8: 563 564 ByteLength = 8; 565 break; 566 567 case ACPI_DMT_STRING: 568 569 Value = DtGetFieldValue (Field); 570 if (Value) 571 { 572 ByteLength = strlen (Value) + 1; 573 } 574 else 575 { /* At this point, this is a fatal error */ 576 577 sprintf (MsgBuffer, "Expected \"%s\"", Info->Name); 578 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); 579 return (0); 580 } 581 break; 582 583 case ACPI_DMT_GAS: 584 585 ByteLength = sizeof (ACPI_GENERIC_ADDRESS); 586 break; 587 588 case ACPI_DMT_HESTNTFY: 589 590 ByteLength = sizeof (ACPI_HEST_NOTIFY); 591 break; 592 593 case ACPI_DMT_IORTMEM: 594 595 ByteLength = sizeof (ACPI_IORT_MEMORY_ACCESS); 596 break; 597 598 case ACPI_DMT_BUFFER: 599 case ACPI_DMT_RAW_BUFFER: 600 601 Value = DtGetFieldValue (Field); 602 if (Value) 603 { 604 ByteLength = DtGetBufferLength (Value); 605 } 606 else 607 { /* At this point, this is a fatal error */ 608 609 sprintf (MsgBuffer, "Expected \"%s\"", Info->Name); 610 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); 611 return (0); 612 } 613 break; 614 615 case ACPI_DMT_BUF10: 616 617 ByteLength = 10; 618 break; 619 620 case ACPI_DMT_BUF12: 621 622 ByteLength = 12; 623 break; 624 625 case ACPI_DMT_BUF16: 626 case ACPI_DMT_UUID: 627 628 ByteLength = 16; 629 break; 630 631 case ACPI_DMT_BUF128: 632 633 ByteLength = 128; 634 break; 635 636 case ACPI_DMT_UNICODE: 637 638 Value = DtGetFieldValue (Field); 639 640 /* TBD: error if Value is NULL? (as below?) */ 641 642 ByteLength = (strlen (Value) + 1) * sizeof(UINT16); 643 break; 644 645 default: 646 647 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode"); 648 return (0); 649 } 650 651 return (ByteLength); 652 } 653 654 655 /****************************************************************************** 656 * 657 * FUNCTION: DtSum 658 * 659 * PARAMETERS: DT_WALK_CALLBACK: 660 * Subtable - Subtable 661 * Context - Unused 662 * ReturnValue - Store the checksum of subtable 663 * 664 * RETURN: Status 665 * 666 * DESCRIPTION: Get the checksum of subtable 667 * 668 *****************************************************************************/ 669 670 static void 671 DtSum ( 672 DT_SUBTABLE *Subtable, 673 void *Context, 674 void *ReturnValue) 675 { 676 UINT8 Checksum; 677 UINT8 *Sum = ReturnValue; 678 679 680 Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length); 681 *Sum = (UINT8) (*Sum + Checksum); 682 } 683 684 685 /****************************************************************************** 686 * 687 * FUNCTION: DtSetTableChecksum 688 * 689 * PARAMETERS: ChecksumPointer - Where to return the checksum 690 * 691 * RETURN: None 692 * 693 * DESCRIPTION: Set checksum of the whole data table into the checksum field 694 * 695 *****************************************************************************/ 696 697 void 698 DtSetTableChecksum ( 699 UINT8 *ChecksumPointer) 700 { 701 UINT8 Checksum = 0; 702 UINT8 OldSum; 703 704 705 DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum); 706 707 OldSum = *ChecksumPointer; 708 Checksum = (UINT8) (Checksum - OldSum); 709 710 /* Compute the final checksum */ 711 712 Checksum = (UINT8) (0 - Checksum); 713 *ChecksumPointer = Checksum; 714 } 715 716 717 /****************************************************************************** 718 * 719 * FUNCTION: DtSetTableLength 720 * 721 * PARAMETERS: None 722 * 723 * RETURN: None 724 * 725 * DESCRIPTION: Walk the subtables and set all the length fields 726 * 727 *****************************************************************************/ 728 729 void 730 DtSetTableLength ( 731 void) 732 { 733 DT_SUBTABLE *ParentTable; 734 DT_SUBTABLE *ChildTable; 735 736 737 ParentTable = Gbl_RootTable; 738 ChildTable = NULL; 739 740 if (!ParentTable) 741 { 742 return; 743 } 744 745 DtSetSubtableLength (ParentTable); 746 747 while (1) 748 { 749 ChildTable = DtGetNextSubtable (ParentTable, ChildTable); 750 if (ChildTable) 751 { 752 if (ChildTable->LengthField) 753 { 754 DtSetSubtableLength (ChildTable); 755 } 756 757 if (ChildTable->Child) 758 { 759 ParentTable = ChildTable; 760 ChildTable = NULL; 761 } 762 else 763 { 764 ParentTable->TotalLength += ChildTable->TotalLength; 765 if (ParentTable->LengthField) 766 { 767 DtSetSubtableLength (ParentTable); 768 } 769 } 770 } 771 else 772 { 773 ChildTable = ParentTable; 774 775 if (ChildTable == Gbl_RootTable) 776 { 777 break; 778 } 779 780 ParentTable = DtGetParentSubtable (ParentTable); 781 782 ParentTable->TotalLength += ChildTable->TotalLength; 783 if (ParentTable->LengthField) 784 { 785 DtSetSubtableLength (ParentTable); 786 } 787 } 788 } 789 } 790 791 792 /****************************************************************************** 793 * 794 * FUNCTION: DtWalkTableTree 795 * 796 * PARAMETERS: StartTable - Subtable in the tree where walking begins 797 * UserFunction - Called during the walk 798 * Context - Passed to user function 799 * ReturnValue - The return value of UserFunction 800 * 801 * RETURN: None 802 * 803 * DESCRIPTION: Performs a depth-first walk of the subtable tree 804 * 805 *****************************************************************************/ 806 807 void 808 DtWalkTableTree ( 809 DT_SUBTABLE *StartTable, 810 DT_WALK_CALLBACK UserFunction, 811 void *Context, 812 void *ReturnValue) 813 { 814 DT_SUBTABLE *ParentTable; 815 DT_SUBTABLE *ChildTable; 816 817 818 ParentTable = StartTable; 819 ChildTable = NULL; 820 821 if (!ParentTable) 822 { 823 return; 824 } 825 826 UserFunction (ParentTable, Context, ReturnValue); 827 828 while (1) 829 { 830 ChildTable = DtGetNextSubtable (ParentTable, ChildTable); 831 if (ChildTable) 832 { 833 UserFunction (ChildTable, Context, ReturnValue); 834 835 if (ChildTable->Child) 836 { 837 ParentTable = ChildTable; 838 ChildTable = NULL; 839 } 840 } 841 else 842 { 843 ChildTable = ParentTable; 844 if (ChildTable == Gbl_RootTable) 845 { 846 break; 847 } 848 849 ParentTable = DtGetParentSubtable (ParentTable); 850 851 if (ChildTable->Peer == StartTable) 852 { 853 break; 854 } 855 } 856 } 857 } 858 859 860 /******************************************************************************* 861 * 862 * FUNCTION: UtSubtableCacheCalloc 863 * 864 * PARAMETERS: None 865 * 866 * RETURN: Pointer to the buffer. Aborts on allocation failure 867 * 868 * DESCRIPTION: Allocate a subtable object buffer. Bypass the local 869 * dynamic memory manager for performance reasons (This has a 870 * major impact on the speed of the compiler.) 871 * 872 ******************************************************************************/ 873 874 DT_SUBTABLE * 875 UtSubtableCacheCalloc ( 876 void) 877 { 878 ASL_CACHE_INFO *Cache; 879 880 881 if (Gbl_SubtableCacheNext >= Gbl_SubtableCacheLast) 882 { 883 /* Allocate a new buffer */ 884 885 Cache = UtLocalCalloc (sizeof (Cache->Next) + 886 (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE)); 887 888 /* Link new cache buffer to head of list */ 889 890 Cache->Next = Gbl_SubtableCacheList; 891 Gbl_SubtableCacheList = Cache; 892 893 /* Setup cache management pointers */ 894 895 Gbl_SubtableCacheNext = ACPI_CAST_PTR (DT_SUBTABLE, Cache->Buffer); 896 Gbl_SubtableCacheLast = Gbl_SubtableCacheNext + ASL_SUBTABLE_CACHE_SIZE; 897 } 898 899 Gbl_SubtableCount++; 900 return (Gbl_SubtableCacheNext++); 901 } 902 903 904 /******************************************************************************* 905 * 906 * FUNCTION: UtFieldCacheCalloc 907 * 908 * PARAMETERS: None 909 * 910 * RETURN: Pointer to the buffer. Aborts on allocation failure 911 * 912 * DESCRIPTION: Allocate a field object buffer. Bypass the local 913 * dynamic memory manager for performance reasons (This has a 914 * major impact on the speed of the compiler.) 915 * 916 ******************************************************************************/ 917 918 DT_FIELD * 919 UtFieldCacheCalloc ( 920 void) 921 { 922 ASL_CACHE_INFO *Cache; 923 924 925 if (Gbl_FieldCacheNext >= Gbl_FieldCacheLast) 926 { 927 /* Allocate a new buffer */ 928 929 Cache = UtLocalCalloc (sizeof (Cache->Next) + 930 (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE)); 931 932 /* Link new cache buffer to head of list */ 933 934 Cache->Next = Gbl_FieldCacheList; 935 Gbl_FieldCacheList = Cache; 936 937 /* Setup cache management pointers */ 938 939 Gbl_FieldCacheNext = ACPI_CAST_PTR (DT_FIELD, Cache->Buffer); 940 Gbl_FieldCacheLast = Gbl_FieldCacheNext + ASL_FIELD_CACHE_SIZE; 941 } 942 943 Gbl_FieldCount++; 944 return (Gbl_FieldCacheNext++); 945 } 946 947 948 /******************************************************************************* 949 * 950 * FUNCTION: DtDeleteCaches 951 * 952 * PARAMETERS: None 953 * 954 * RETURN: None 955 * 956 * DESCRIPTION: Delete all local cache buffer blocks 957 * 958 ******************************************************************************/ 959 960 void 961 DtDeleteCaches ( 962 void) 963 { 964 UINT32 BufferCount; 965 ASL_CACHE_INFO *Next; 966 967 968 /* Field cache */ 969 970 BufferCount = 0; 971 while (Gbl_FieldCacheList) 972 { 973 Next = Gbl_FieldCacheList->Next; 974 ACPI_FREE (Gbl_FieldCacheList); 975 Gbl_FieldCacheList = Next; 976 BufferCount++; 977 } 978 979 DbgPrint (ASL_DEBUG_OUTPUT, 980 "%u Fields, Buffer size: %u fields (%u bytes), %u Buffers\n", 981 Gbl_FieldCount, ASL_FIELD_CACHE_SIZE, 982 (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE), BufferCount); 983 984 Gbl_FieldCount = 0; 985 Gbl_FieldCacheNext = NULL; 986 Gbl_FieldCacheLast = NULL; 987 988 /* Subtable cache */ 989 990 BufferCount = 0; 991 while (Gbl_SubtableCacheList) 992 { 993 Next = Gbl_SubtableCacheList->Next; 994 ACPI_FREE (Gbl_SubtableCacheList); 995 Gbl_SubtableCacheList = Next; 996 BufferCount++; 997 } 998 999 DbgPrint (ASL_DEBUG_OUTPUT, 1000 "%u Subtables, Buffer size: %u subtables (%u bytes), %u Buffers\n", 1001 Gbl_SubtableCount, ASL_SUBTABLE_CACHE_SIZE, 1002 (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE), BufferCount); 1003 1004 Gbl_SubtableCount = 0; 1005 Gbl_SubtableCacheNext = NULL; 1006 Gbl_SubtableCacheLast = NULL; 1007 } 1008