1 /******************************************************************************
3 * Module Name: dtutils.c - Utility routines for the data table compiler
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2016, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
44 #include <contrib/dev/acpica/compiler/aslcompiler.h>
45 #include <contrib/dev/acpica/compiler/dtcompiler.h>
46 #include <contrib/dev/acpica/include/actables.h>
48 #define _COMPONENT DT_COMPILER
49 ACPI_MODULE_NAME ("dtutils")
51 /* Local prototypes */
55 DT_SUBTABLE *Subtable,
60 /******************************************************************************
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
71 * DESCRIPTION: Common error interface for data table compiler
73 *****************************************************************************/
79 DT_FIELD *FieldObject,
83 /* Check if user wants to ignore this exception */
85 if (AslIsExceptionDisabled (Level, MessageId))
92 AslCommonError (Level, MessageId,
95 FieldObject->ByteOffset,
97 Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
101 AslCommonError (Level, MessageId, 0,
102 0, 0, 0, 0, ExtraMessage);
107 /******************************************************************************
109 * FUNCTION: DtNameError
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
118 * DESCRIPTION: Error interface for named objects
120 *****************************************************************************/
126 DT_FIELD *FieldObject,
135 if (Gbl_WarningLevel < Level)
148 AslCommonError (Level, MessageId,
151 FieldObject->ByteOffset,
152 FieldObject->NameColumn,
153 Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
157 AslCommonError (Level, MessageId, 0,
158 0, 0, 0, 0, ExtraMessage);
163 /*******************************************************************************
171 * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
172 * compile or I/O errors
174 ******************************************************************************/
179 DT_FIELD *FieldObject,
183 DtError (ASL_ERROR, MessageId, FieldObject, ExtraMessage);
186 * TBD: remove this entire function, DtFatal
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.
198 /******************************************************************************
200 * FUNCTION: DtGetFieldValue
202 * PARAMETERS: Field - Current field list pointer
204 * RETURN: Field value
206 * DESCRIPTION: Get field value
208 *****************************************************************************/
219 return (Field->Value);
223 /******************************************************************************
225 * FUNCTION: DtGetFieldType
227 * PARAMETERS: Info - Data table info
231 * DESCRIPTION: Get field type
233 *****************************************************************************/
237 ACPI_DMTABLE_INFO *Info)
242 /* DT_FLAG means that this is the start of a block of flag bits */
243 /* TBD - we can make these a separate opcode later */
245 if (Info->Flags & DT_FLAG)
247 return (DT_FIELD_TYPE_FLAGS_INTEGER);
250 /* Type is based upon the opcode for this field in the info table */
252 switch (Info->Opcode)
262 case ACPI_DMT_FLAGS0:
263 case ACPI_DMT_FLAGS1:
264 case ACPI_DMT_FLAGS2:
265 case ACPI_DMT_FLAGS4:
267 Type = DT_FIELD_TYPE_FLAG;
274 case ACPI_DMT_STRING:
276 Type = DT_FIELD_TYPE_STRING;
279 case ACPI_DMT_BUFFER:
280 case ACPI_DMT_RAW_BUFFER:
285 case ACPI_DMT_BUF128:
286 case ACPI_DMT_PCI_PATH:
288 Type = DT_FIELD_TYPE_BUFFER;
292 case ACPI_DMT_HESTNTFY:
293 case ACPI_DMT_IORTMEM:
295 Type = DT_FIELD_TYPE_INLINE_SUBTABLE;
298 case ACPI_DMT_UNICODE:
300 Type = DT_FIELD_TYPE_UNICODE;
305 Type = DT_FIELD_TYPE_UUID;
308 case ACPI_DMT_DEVICE_PATH:
310 Type = DT_FIELD_TYPE_DEVICE_PATH;
315 Type = DT_FIELD_TYPE_LABEL;
320 Type = DT_FIELD_TYPE_INTEGER;
328 /******************************************************************************
330 * FUNCTION: DtGetBufferLength
332 * PARAMETERS: Buffer - List of integers,
333 * for example "10 3A 4F 2E"
335 * RETURN: Count of integer
337 * DESCRIPTION: Get length of bytes needed to store the integers
339 *****************************************************************************/
345 UINT32 ByteLength = 0;
354 while (*Buffer == ' ')
363 return (++ByteLength);
367 /******************************************************************************
369 * FUNCTION: DtGetFieldLength
371 * PARAMETERS: Field - Current field
372 * Info - Data table info
374 * RETURN: Field length
376 * DESCRIPTION: Get length of bytes needed to compile the field
378 * Note: This function must remain in sync with AcpiDmDumpTable.
380 *****************************************************************************/
385 ACPI_DMTABLE_INFO *Info)
387 UINT32 ByteLength = 0;
391 /* Length is based upon the opcode for this field in the info table */
393 switch (Info->Opcode)
403 case ACPI_DMT_FLAGS0:
404 case ACPI_DMT_FLAGS1:
405 case ACPI_DMT_FLAGS2:
406 case ACPI_DMT_FLAGS4:
408 case ACPI_DMT_EXTRA_TEXT:
414 case ACPI_DMT_CHKSUM:
415 case ACPI_DMT_SPACEID:
416 case ACPI_DMT_ACCWIDTH:
424 case ACPI_DMT_HESTNTYP:
425 case ACPI_DMT_FADTPM:
426 case ACPI_DMT_EINJACT:
427 case ACPI_DMT_EINJINST:
428 case ACPI_DMT_ERSTACT:
429 case ACPI_DMT_ERSTINST:
430 case ACPI_DMT_DMAR_SCOPE:
435 case ACPI_DMT_UINT16:
439 case ACPI_DMT_PCI_PATH:
444 case ACPI_DMT_UINT24:
449 case ACPI_DMT_UINT32:
457 case ACPI_DMT_UINT40:
462 case ACPI_DMT_UINT48:
468 case ACPI_DMT_UINT56:
474 case ACPI_DMT_UINT64:
480 case ACPI_DMT_STRING:
482 Value = DtGetFieldValue (Field);
485 ByteLength = strlen (Value) + 1;
488 { /* At this point, this is a fatal error */
490 sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
491 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
498 ByteLength = sizeof (ACPI_GENERIC_ADDRESS);
501 case ACPI_DMT_HESTNTFY:
503 ByteLength = sizeof (ACPI_HEST_NOTIFY);
506 case ACPI_DMT_IORTMEM:
508 ByteLength = sizeof (ACPI_IORT_MEMORY_ACCESS);
511 case ACPI_DMT_BUFFER:
512 case ACPI_DMT_RAW_BUFFER:
514 Value = DtGetFieldValue (Field);
517 ByteLength = DtGetBufferLength (Value);
520 { /* At this point, this is a fatal error */
522 sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
523 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
544 case ACPI_DMT_BUF128:
549 case ACPI_DMT_UNICODE:
551 Value = DtGetFieldValue (Field);
553 /* TBD: error if Value is NULL? (as below?) */
555 ByteLength = (strlen (Value) + 1) * sizeof(UINT16);
560 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode");
568 /******************************************************************************
572 * PARAMETERS: DT_WALK_CALLBACK:
573 * Subtable - Subtable
575 * ReturnValue - Store the checksum of subtable
579 * DESCRIPTION: Get the checksum of subtable
581 *****************************************************************************/
585 DT_SUBTABLE *Subtable,
590 UINT8 *Sum = ReturnValue;
593 Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length);
594 *Sum = (UINT8) (*Sum + Checksum);
598 /******************************************************************************
600 * FUNCTION: DtSetTableChecksum
602 * PARAMETERS: ChecksumPointer - Where to return the checksum
606 * DESCRIPTION: Set checksum of the whole data table into the checksum field
608 *****************************************************************************/
612 UINT8 *ChecksumPointer)
618 DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum);
620 OldSum = *ChecksumPointer;
621 Checksum = (UINT8) (Checksum - OldSum);
623 /* Compute the final checksum */
625 Checksum = (UINT8) (0 - Checksum);
626 *ChecksumPointer = Checksum;
630 /******************************************************************************
632 * FUNCTION: DtSetTableLength
638 * DESCRIPTION: Walk the subtables and set all the length fields
640 *****************************************************************************/
646 DT_SUBTABLE *ParentTable;
647 DT_SUBTABLE *ChildTable;
650 ParentTable = Gbl_RootTable;
658 DtSetSubtableLength (ParentTable);
662 ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
665 if (ChildTable->LengthField)
667 DtSetSubtableLength (ChildTable);
670 if (ChildTable->Child)
672 ParentTable = ChildTable;
677 ParentTable->TotalLength += ChildTable->TotalLength;
678 if (ParentTable->LengthField)
680 DtSetSubtableLength (ParentTable);
686 ChildTable = ParentTable;
688 if (ChildTable == Gbl_RootTable)
693 ParentTable = DtGetParentSubtable (ParentTable);
695 ParentTable->TotalLength += ChildTable->TotalLength;
696 if (ParentTable->LengthField)
698 DtSetSubtableLength (ParentTable);
705 /******************************************************************************
707 * FUNCTION: DtWalkTableTree
709 * PARAMETERS: StartTable - Subtable in the tree where walking begins
710 * UserFunction - Called during the walk
711 * Context - Passed to user function
712 * ReturnValue - The return value of UserFunction
716 * DESCRIPTION: Performs a depth-first walk of the subtable tree
718 *****************************************************************************/
722 DT_SUBTABLE *StartTable,
723 DT_WALK_CALLBACK UserFunction,
727 DT_SUBTABLE *ParentTable;
728 DT_SUBTABLE *ChildTable;
731 ParentTable = StartTable;
739 UserFunction (ParentTable, Context, ReturnValue);
743 ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
746 UserFunction (ChildTable, Context, ReturnValue);
748 if (ChildTable->Child)
750 ParentTable = ChildTable;
756 ChildTable = ParentTable;
757 if (ChildTable == Gbl_RootTable)
762 ParentTable = DtGetParentSubtable (ParentTable);
764 if (ChildTable->Peer == StartTable)
773 /*******************************************************************************
775 * FUNCTION: UtSubtableCacheCalloc
779 * RETURN: Pointer to the buffer. Aborts on allocation failure
781 * DESCRIPTION: Allocate a subtable object buffer. Bypass the local
782 * dynamic memory manager for performance reasons (This has a
783 * major impact on the speed of the compiler.)
785 ******************************************************************************/
788 UtSubtableCacheCalloc (
791 ASL_CACHE_INFO *Cache;
794 if (Gbl_SubtableCacheNext >= Gbl_SubtableCacheLast)
796 /* Allocate a new buffer */
798 Cache = UtLocalCalloc (sizeof (Cache->Next) +
799 (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE));
801 /* Link new cache buffer to head of list */
803 Cache->Next = Gbl_SubtableCacheList;
804 Gbl_SubtableCacheList = Cache;
806 /* Setup cache management pointers */
808 Gbl_SubtableCacheNext = ACPI_CAST_PTR (DT_SUBTABLE, Cache->Buffer);
809 Gbl_SubtableCacheLast = Gbl_SubtableCacheNext + ASL_SUBTABLE_CACHE_SIZE;
813 return (Gbl_SubtableCacheNext++);
817 /*******************************************************************************
819 * FUNCTION: UtFieldCacheCalloc
823 * RETURN: Pointer to the buffer. Aborts on allocation failure
825 * DESCRIPTION: Allocate a field object buffer. Bypass the local
826 * dynamic memory manager for performance reasons (This has a
827 * major impact on the speed of the compiler.)
829 ******************************************************************************/
835 ASL_CACHE_INFO *Cache;
838 if (Gbl_FieldCacheNext >= Gbl_FieldCacheLast)
840 /* Allocate a new buffer */
842 Cache = UtLocalCalloc (sizeof (Cache->Next) +
843 (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE));
845 /* Link new cache buffer to head of list */
847 Cache->Next = Gbl_FieldCacheList;
848 Gbl_FieldCacheList = Cache;
850 /* Setup cache management pointers */
852 Gbl_FieldCacheNext = ACPI_CAST_PTR (DT_FIELD, Cache->Buffer);
853 Gbl_FieldCacheLast = Gbl_FieldCacheNext + ASL_FIELD_CACHE_SIZE;
857 return (Gbl_FieldCacheNext++);
861 /*******************************************************************************
863 * FUNCTION: DtDeleteCaches
869 * DESCRIPTION: Delete all local cache buffer blocks
871 ******************************************************************************/
878 ASL_CACHE_INFO *Next;
884 while (Gbl_FieldCacheList)
886 Next = Gbl_FieldCacheList->Next;
887 ACPI_FREE (Gbl_FieldCacheList);
888 Gbl_FieldCacheList = Next;
892 DbgPrint (ASL_DEBUG_OUTPUT,
893 "%u Fields, Buffer size: %u fields (%u bytes), %u Buffers\n",
894 Gbl_FieldCount, ASL_FIELD_CACHE_SIZE,
895 (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE), BufferCount);
898 Gbl_FieldCacheNext = NULL;
899 Gbl_FieldCacheLast = NULL;
904 while (Gbl_SubtableCacheList)
906 Next = Gbl_SubtableCacheList->Next;
907 ACPI_FREE (Gbl_SubtableCacheList);
908 Gbl_SubtableCacheList = Next;
912 DbgPrint (ASL_DEBUG_OUTPUT,
913 "%u Subtables, Buffer size: %u subtables (%u bytes), %u Buffers\n",
914 Gbl_SubtableCount, ASL_SUBTABLE_CACHE_SIZE,
915 (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE), BufferCount);
917 Gbl_SubtableCount = 0;
918 Gbl_SubtableCacheNext = NULL;
919 Gbl_SubtableCacheLast = NULL;