[BACK]Return to dtutils.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / external / bsd / acpica / dist / compiler

File: [cvs.NetBSD.org] / src / sys / external / bsd / acpica / dist / compiler / dtutils.c (download)

Revision 1.1.1.8 (vendor branch), Sat Jan 9 19:54:52 2016 UTC (8 years, 3 months ago) by christos
Branch: intel
CVS Tags: acpica-20160527, acpica-20160422, acpica-20160108
Changes since 1.1.1.7: +1 -1 lines

import new acpica:

----------------------------------------
8 January 2016. Summary of changes for version 20160108:

1) ACPICA kernel-resident subsystem:

Updated all ACPICA copyrights and signons to 2016: Added the 2016
copyright to all source code module headers and utility/tool signons.
This includes the standard Linux dual-license header. This affects
virtually every file in the ACPICA core subsystem, iASL compiler, all
ACPICA utilities, and the ACPICA test suite.

Fixed a regression introduced in version 20151218 concerning the
execution of so-called module-level ASL/AML code. Namespace objects
created under a module-level If() construct were not properly/fully
entered into the namespace and could cause an interpreter fault when
accessed.

Example Code and Data Size: These are the sizes for the OS-independent
acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The
debug version of the code includes the debug output trace mechanism and
has a much larger code and data size.

Current Release:
    Non-Debug Version: 102.7K Code, 28.4K Data, 131.1K Total
    Debug Version:     200.4K Code, 81.9K Data, 282.4K Total
  Previous Release:
    Non-Debug Version: 102.6K Code, 28.4K Data, 131.0K Total
    Debug Version:     200.3K Code, 81.9K Data, 282.3K Total


2) iASL Compiler/Disassembler and Tools:

Fixed a problem with the compilation of the GpioIo and GpioInt resource
descriptors. The _PIN field name was incorrectly defined to be an array
of 32-bit values, but the _PIN values are in fact 16 bits each. This
would cause incorrect bit width warnings when using Word (16-bit) fields
to access the descriptors.


----------------------------------------
18 December 2015. Summary of changes for version 20151218:

1) ACPICA kernel-resident subsystem:

Implemented per-AML-table execution of "module-level code" as individual
ACPI tables are loaded into the namespace during ACPICA initialization.
In other words, any module-level code within an AML table is executed
immediately after the table is loaded, instead of batched and executed
after all of the tables have been loaded. This provides compatibility
with other ACPI implementations. ACPICA BZ 1219. Bob Moore, Lv Zheng,
David Box.

To fully support the feature above, the default operation region handlers
for the SystemMemory, SystemIO, and PCI_Config address spaces are now
installed before any ACPI tables are loaded. This enables module-level
code to access these address spaces during the table load and module-
level code execution phase. ACPICA BZ 1220. Bob Moore, Lv Zheng, David
Box.

Implemented several changes to the internal _REG support in conjunction
with the changes above. Also, changes to the AcpiExec/AcpiNames/Examples
utilities for the changes above. Although these tools were changed, host
operating systems that simply use the default handlers for SystemMemory,
SystemIO, and PCI_Config spaces should not require any update. Lv Zheng.

For example, in the code below, DEV1 is conditionally added to the
namespace by the DSDT via module-level code that accesses an operation
region. The SSDT references DEV1 via the Scope operator. DEV1 must be
created immediately after the DSDT is loaded in order for the SSDT to
successfully reference DEV1. Previously, this code would cause an
AE_NOT_EXIST exception during the load of the SSDT. Now, this code is
fully supported by ACPICA.

    DefinitionBlock ("", "DSDT", 2, "Intel", "DSDT1", 1)
    {
        OperationRegion (OPR1, SystemMemory, 0x400, 32)
        Field (OPR1, AnyAcc, NoLock, Preserve)
        {
            FLD1, 1
        }
        If (FLD1)
        {
            Device (\DEV1)
            {
            }
        }
    }
    DefinitionBlock ("", "SSDT", 2, "Intel", "SSDT1", 1)
    {
        External (\DEV1, DeviceObj)
        Scope (\DEV1)
        {
        }
    }

Fixed an AML interpreter problem where control method invocations were
not handled correctly when the invocation was itself a SuperName argument
to another ASL operator. In these cases, the method was not invoked.
ACPICA BZ 1002. Affects the following ASL operators that have a SuperName
argument:
    Store
    Acquire, Wait
    CondRefOf, RefOf
    Decrement, Increment
    Load, Unload
    Notify
    Signal, Release, Reset
    SizeOf

Implemented automatic String-to-ObjectReference conversion support for
packages returned by predefined names (such as _DEP). A common BIOS error
is to add double quotes around an ObjectReference namepath, which turns
the reference into an unexpected string object. This support detects the
problem and corrects it before the package is returned to the caller that
invoked the method. Lv Zheng.

Implemented extensions to the Concatenate operator. Concatenate now
accepts any type of object, it is not restricted to simply
Integer/String/Buffer. For objects other than these 3 basic data types,
the argument is treated as a string containing the name of the object
type. This expands the utility of Concatenate and the Printf/Fprintf
macros. ACPICA BZ 1222.

Cleaned up the output of the ASL Debug object. The timer() value is now
optional and no longer emitted by default. Also, the basic data types of
Integer/String/Buffer are simply emitted as their values, without a data
type string -- since the data type is obvious from the output. ACPICA BZ
1221.

Example Code and Data Size: These are the sizes for the OS-independent
acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The
debug version of the code includes the debug output trace mechanism and
has a much larger code and data size.

  Current Release:
    Non-Debug Version: 102.6K Code, 28.4K Data, 131.0K Total
    Debug Version:     200.3K Code, 81.9K Data, 282.3K Total
  Previous Release:
    Non-Debug Version: 102.0K Code, 28.3K Data, 130.3K Total
    Debug Version:     199.6K Code, 81.8K Data, 281.4K Total


2) iASL Compiler/Disassembler and Tools:

iASL: Fixed some issues with the ASL Include() operator. This operator
was incorrectly defined in the iASL parser rules, causing a new scope to
be opened for the code within the include file. This could lead to
several issues, including allowing ASL code that is technically illegal
and not supported by AML interpreters. Note, this does not affect the
related #include preprocessor operator. ACPICA BZ 1212.

iASL/Disassembler: Implemented support for the ASL ElseIf operator. This
operator is essentially an ASL macro since there is no AML opcode
associated with it. The code emitted by the iASL compiler for ElseIf is
an Else opcode followed immediately by an If opcode. The disassembler
will now emit an ElseIf if it finds an Else immediately followed by an
If. This simplifies the decoded ASL, especially for deeply nested
If..Else and large Switch constructs. Thus, the disassembled code more
closely follows the original source ASL. ACPICA BZ 1211. Example:

    Old disassembly:
        Else
        {
            If (Arg0 == 0x02)
            {
                Local0 = 0x05
            }
        }

    New disassembly:
        ElseIf (Arg0 == 0x02)
        {
            Local0 = 0x05
        }

AcpiExec: Added support for the new module level code behavior and the
early region installation. This required a small change to the
initialization, since AcpiExec must install its own operation region
handlers.

AcpiExec: Added support to make the debug object timer optional. Default
is timer disabled. This cleans up the debug object output -- the timer
data is rarely used.

AcpiExec: Multiple ACPI tables are now loaded in the order that they
appear on the command line. This can be important when there are
interdependencies/references between the tables.

iASL/Templates. Add support to generate template files with multiple
SSDTs within a single output file. Also added ommand line support to
specify the number of SSDTs (in addition to a single DSDT). ACPICA BZ
1223, 1225.


----------------------------------------
24 November 2015. Summary of changes for version 20151124:

1) ACPICA kernel-resident subsystem:

Fixed a possible regression for a previous update to FADT handling. The
FADT no longer has a fixed table ID, causing some issues with code that
was hardwired to a specific ID. Lv Zheng.

Fixed a problem where the method auto-serialization could interfere with
the current SyncLevel. This change makes the auto-serialization support
transparent to the SyncLevel support and management.

Removed support for the _SUB predefined name in AcpiGetObjectInfo. This
interface is intended for early access to the namespace during the
initial namespace device discovery walk. The _SUB method has been seen to
access operation regions in some cases, causing errors because the
operation regions are not fully initialized.

AML Debugger: Fixed some issues with the terminate/quit/exit commands
that can cause faults. Lv Zheng.

AML Debugger: Add thread ID support so that single-step mode only applies
to the AML Debugger thread. This prevents runtime errors within some
kernels. Lv Zheng.

Eliminated extraneous warnings from AcpiGetSleepTypeData. Since the _Sx
methods that are invoked by this interface are optional, removed warnings
emitted for the case where one or more of these methods do not exist.
ACPICA BZ 1208, original change by Prarit Bhargava.

Made a major pass through the entire ACPICA source code base to
standardize formatting that has diverged a bit over time. There are no
functional changes, but this will of course cause quite a few code
differences from the previous ACPICA release.

Example Code and Data Size: These are the sizes for the OS-independent
acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The
debug version of the code includes the debug output trace mechanism and
has a much larger code and data size.

  Current Release:
    Non-Debug Version: 102.0K Code, 28.3K Data, 130.3K Total
    Debug Version:     199.6K Code, 81.8K Data, 281.4K Total
  Previous Release:
    Non-Debug Version: 101.7K Code, 27.9K Data, 129.6K Total
    Debug Version:     199.3K Code, 81.4K Data, 280.7K Total


2) iASL Compiler/Disassembler and Tools:

iASL/acpiexec/acpixtract/disassembler: Added support to allow multiple
definition blocks within a single ASL file and the resulting AML file.
Support for this type of file was also added to the various tools that
use binary AML files: acpiexec, acpixtract, and the AML disassembler. The
example code below shows two definition blocks within the same file:

    DefinitionBlock ("dsdt.aml", "DSDT", 2, "Intel", "Template",
0x12345678)
    {
    }
    DefinitionBlock ("", "SSDT", 2, "Intel", "Template", 0xABCDEF01)
    {
    }

iASL: Enhanced typechecking for the Name() operator. All expressions for
the value of the named object must be reduced/folded to a single constant
at compile time, as per the ACPI specification (the AML definition of
Name()).

iASL: Fixed some code indentation issues for the -ic and -ia options (C
and assembly headers). Now all emitted code correctly begins in column 1.

iASL: Added an error message for an attempt to open a Scope() on an
object defined in an SSDT. The DSDT is always loaded into the namespace
first, so any attempt to open a Scope on an SSDT object will fail at
runtime.


----------------------------------------
30 September 2015. Summary of changes for version 20150930:

1) ACPICA kernel-resident subsystem:

Debugger: Implemented several changes and bug fixes to assist support for
the in-kernel version of the AML debugger. Lv Zheng.
- Fix the "predefined" command for in-kernel debugger.
- Do not enter debug command loop for the help and version commands.
- Disallow "execute" command during execution/single-step of a method.

Interpreter: Updated runtime typechecking for all operators that have
target operands. The operand is resolved and validated that it is legal.
For example, the target cannot be a non-data object such as a Device,
Mutex, ThermalZone, etc., as per the ACPI specification.

Debugger: Fixed the double-mutex user I/O handshake to work when local
deadlock detection is enabled.

Debugger: limited display of method locals and arguments (LocalX and
ArgX) to only those that have actually been initialized. This prevents
lines of extraneous output.

Updated the definition of the NFIT table to correct the bit polarity of
one flag: ACPI_NFIT_MEM_ARMED --> ACPI_NFIT_MEM_NOT_ARMED

Example Code and Data Size: These are the sizes for the OS-independent
acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The
debug version of the code includes the debug output trace mechanism and
has a much larger code and data size.

  Current Release:
    Non-Debug Version: 101.7K Code, 27.9K Data, 129.6K Total
    Debug Version:     199.3K Code, 81.4K Data, 280.7K Total
  Previous Release:
    Non-Debug Version: 101.3K Code, 27.7K Data, 129.0K Total
    Debug Version:     198.6K Code, 80.9K Data, 279.5K Total


2) iASL Compiler/Disassembler and Tools:

iASL: Improved the compile-time typechecking for operands of many of the
ASL operators:

-- Added an option to disable compiler operand/operator typechecking (-
ot).

-- For the following operators, the TermArg operands are now validated
when possible to be Integer data objects: BankField, OperationRegion,
DataTableRegion, Buffer, and Package.

-- Store (Source, Target): Both the source and target operands are
resolved and checked that the operands are both legal. For example,
neither operand can be a non-data object such as a Device, Mutex,
ThermalZone, etc. Note, as per the ACPI specification, the CopyObject
operator can be used to store an object to any type of target object.

-- Store (Source, Target): If the source is a Package object, the target
must be a Package object, LocalX, ArgX, or Debug. Likewise, if the target
is a Package, the source must also be a Package.

-- Store (Source, Target): A warning is issued if the source and target
resolve to the identical named object.

-- Store (Source, <method invocation>): An error is generated for the
target method invocation, as this construct is not supported by the AML
interpreter.

-- For all ASL math and logic operators, the target operand must be a
data object (Integer, String, Buffer, LocalX, ArgX, or Debug). This
includes the function return value also.

-- External declarations are also included in the typechecking where
possible. External objects defined using the UnknownObj keyword cannot be
typechecked, however.

iASL and Disassembler: Added symbolic (ASL+) support for the ASL Index
operator:
- Legacy code: Index(PKG1, 3)
- New ASL+ code: PKG1[3]
This completes the ACPI 6.0 ASL+ support as it was the only operator not
supported.

iASL: Fixed the file suffix for the preprocessor output file (.i). Two
spaces were inadvertently appended to the filename, causing file access
and deletion problems on some systems.

ASL Test Suite (ASLTS): Updated the master makefile to generate all
possible compiler output files when building the test suite -- thus
exercising these features of the compiler. These files are automatically
deleted when the test suite exits.


----------------------------------------
18 August 2015. Summary of changes for version 20150818:

1) ACPICA kernel-resident subsystem:

Fix a regression for AcpiGetTableByIndex interface causing it to fail. Lv
Zheng. ACPICA BZ 1186.

Completed development to ensure that the ACPICA Disassembler and Debugger
are fully standalone components of ACPICA. Removed cross-component
dependences. Lv Zheng.

The max-number-of-AML-loops is now runtime configurable (previously was
compile-time only). This is essentially a loop timeout to force-abort
infinite AML loops. ACPCIA BZ 1192.

Debugger: Cleanup output to dump ACPI names and namepaths without any
trailing underscores. Lv Zheng. ACPICA BZ 1135.

Removed unnecessary conditional compilations across the Debugger and
Disassembler components where entire modules could be left uncompiled.

The aapits test is deprecated and has been removed from the ACPICA git
tree. The test has never been completed and has not been maintained, thus
becoming rather useless. ACPICA BZ 1015, 794.

A batch of small changes to close bugzilla and other reports:
- Remove duplicate code for _PLD processing. ACPICA BZ 1176.
- Correctly cleanup after a ACPI table load failure. ACPICA BZ 1185.
- iASL: Support POSIX yacc again in makefile. Jung-uk Kim.
- ACPI table support: general cleanup and simplification. Lv Zheng, Bob
Moore.
- ACPI table support: fix for a buffer read overrun in AcpiTbFindTable.
ACPICA BZ 1184.
- Enhance parameter validation for DataTableRegion and LoadTable ASL/AML
operators.
- Debugger: Split debugger initialization/termination interfaces. Lv
Zheng.
- AcpiExec: Emit OemTableId for SSDTs during the load phase for table
identification.
- AcpiExec: Add debug message during _REG method phase during table
load/init.
- AcpiNames: Fix a regression where some output was missing and no longer
emitted.
- Debugger: General cleanup and simplification. Lv Zheng.
- Disassembler: Cleanup use of several global option variables. Lv Zheng.

Example Code and Data Size: These are the sizes for the OS-independent
acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The
debug version of the code includes the debug output trace mechanism and
has a much larger code and data size.

  Current Release:
    Non-Debug Version: 101.3K Code, 27.7K Data, 129.0K Total
    Debug Version:     198.6K Code, 80.9K Data, 279.5K Total
  Previous Release:
    Non-Debug Version: 100.9K Code, 24.5K Data, 125.4K Total
    Debug Version:     197.8K Code, 81.5K Data, 279.3K Total


2) iASL Compiler/Disassembler and Tools:

AcpiExec: Fixed a problem where any more than 32 ACPI tables in the XSDT
were not handled properly and caused load errors. Now, properly invoke
and use the ACPICA auto-reallocate mechanism for ACPI table data
structures. ACPICA BZ 1188

AcpiNames: Add command-line wildcard support for ACPI table files. ACPICA
BZ 1190.

AcpiExec and AcpiNames: Add -l option to load ACPI tables only. For
AcpiExec, this means that no control methods (like _REG/_INI/_STA) are
executed during initialization. ACPICA BZ 1187, 1189.

iASL/Disassembler: Implemented a prototype "listing" mode that emits AML
that corresponds to each disassembled ASL statement, to simplify
debugging. ACPICA BZ 1191.

Debugger: Add option to the "objects" command to display a summary of the
current namespace objects (Object type and count). This is displayed if
the command is entered with no arguments.

AcpiNames: Add -x option to specify debug level, similar to AcpiExec.


----------------------------------------

/******************************************************************************
 *
 * Module Name: dtutils.c - Utility routines for the data table compiler
 *
 *****************************************************************************/

/*
 * Copyright (C) 2000 - 2016, Intel Corp.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

#include "aslcompiler.h"
#include "dtcompiler.h"
#include "actables.h"

#define _COMPONENT          DT_COMPILER
        ACPI_MODULE_NAME    ("dtutils")

/* Local prototypes */

static void
DtSum (
    DT_SUBTABLE             *Subtable,
    void                    *Context,
    void                    *ReturnValue);


/******************************************************************************
 *
 * FUNCTION:    DtError
 *
 * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
 *              MessageId           - Index into global message buffer
 *              Op                  - Parse node where error happened
 *              ExtraMessage        - additional error message
 *
 * RETURN:      None
 *
 * DESCRIPTION: Common error interface for data table compiler
 *
 *****************************************************************************/

void
DtError (
    UINT8                   Level,
    UINT16                  MessageId,
    DT_FIELD                *FieldObject,
    char                    *ExtraMessage)
{

    /* Check if user wants to ignore this exception */

    if (AslIsExceptionDisabled (Level, MessageId))
    {
        return;
    }

    if (FieldObject)
    {
        AslCommonError (Level, MessageId,
            FieldObject->Line,
            FieldObject->Line,
            FieldObject->ByteOffset,
            FieldObject->Column,
            Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
    }
    else
    {
        AslCommonError (Level, MessageId, 0,
            0, 0, 0, 0, ExtraMessage);
    }
}


/******************************************************************************
 *
 * FUNCTION:    DtNameError
 *
 * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
 *              MessageId           - Index into global message buffer
 *              Op                  - Parse node where error happened
 *              ExtraMessage        - additional error message
 *
 * RETURN:      None
 *
 * DESCRIPTION: Error interface for named objects
 *
 *****************************************************************************/

void
DtNameError (
    UINT8                   Level,
    UINT16                  MessageId,
    DT_FIELD                *FieldObject,
    char                    *ExtraMessage)
{

    switch (Level)
    {
    case ASL_WARNING2:
    case ASL_WARNING3:

        if (Gbl_WarningLevel < Level)
        {
            return;
        }
        break;

    default:

        break;
    }

    if (FieldObject)
    {
        AslCommonError (Level, MessageId,
            FieldObject->Line,
            FieldObject->Line,
            FieldObject->ByteOffset,
            FieldObject->NameColumn,
            Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
    }
    else
    {
        AslCommonError (Level, MessageId, 0,
            0, 0, 0, 0, ExtraMessage);
    }
}


/*******************************************************************************
 *
 * FUNCTION:    DtFatal
 *
 * PARAMETERS:  None
 *
 * RETURN:      None
 *
 * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
 *              compile or I/O errors
 *
 ******************************************************************************/

void
DtFatal (
    UINT16                  MessageId,
    DT_FIELD                *FieldObject,
    char                    *ExtraMessage)
{

    DtError (ASL_ERROR, MessageId, FieldObject, ExtraMessage);

/*
 * TBD: remove this entire function, DtFatal
 *
 * We cannot abort the compiler on error, because we may be compiling a
 * list of files. We must move on to the next file.
 */
#ifdef __OBSOLETE
    CmCleanupAndExit ();
    exit (1);
#endif
}


/******************************************************************************
 *
 * FUNCTION:    DtStrtoul64
 *
 * PARAMETERS:  String              - Null terminated string
 *              ReturnInteger       - Where the converted integer is returned
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Simple conversion of a string hex integer constant to unsigned
 *              value. Assumes no leading "0x" for the constant.
 *
 * Portability note: The reason this function exists is because a 64-bit
 * sscanf is not available in all environments.
 *
 *****************************************************************************/

ACPI_STATUS
DtStrtoul64 (
    char                    *String,
    UINT64                  *ReturnInteger)
{
    char                    *ThisChar = String;
    UINT32                  ThisDigit;
    UINT64                  ReturnValue = 0;
    int                     DigitCount = 0;


    /* Skip over any white space in the buffer */

    while ((*ThisChar == ' ') || (*ThisChar == '\t'))
    {
        ThisChar++;
    }

    /* Skip leading zeros */

    while ((*ThisChar) == '0')
    {
        ThisChar++;
    }

    /* Convert character-by-character */

    while (*ThisChar)
    {
        if (isdigit ((int) *ThisChar))
        {
            /* Convert ASCII 0-9 to Decimal value */

            ThisDigit = ((UINT8) *ThisChar) - '0';
        }
        else /* Letter */
        {
            ThisDigit = (UINT32) toupper ((int) *ThisChar);
            if (!isxdigit ((int) ThisDigit))
            {
                /* Not A-F */

                return (AE_BAD_CHARACTER);
            }

            /* Convert ASCII Hex char (A-F) to value */

            ThisDigit = (ThisDigit - 'A') + 10;
        }

        /* Insert the 4-bit hex digit */

        ReturnValue <<= 4;
        ReturnValue += ThisDigit;

        ThisChar++;
        DigitCount++;
        if (DigitCount > 16)
        {
            /* Value is too large (> 64 bits/8 bytes/16 hex digits) */

            return (AE_LIMIT);
        }
    }

    *ReturnInteger = ReturnValue;
    return (AE_OK);
}


/******************************************************************************
 *
 * FUNCTION:    DtGetFieldValue
 *
 * PARAMETERS:  Field               - Current field list pointer
 *
 * RETURN:      Field value
 *
 * DESCRIPTION: Get field value
 *
 *****************************************************************************/

char *
DtGetFieldValue (
    DT_FIELD                *Field)
{
    if (!Field)
    {
        return (NULL);
    }

    return (Field->Value);
}


/******************************************************************************
 *
 * FUNCTION:    DtGetFieldType
 *
 * PARAMETERS:  Info                - Data table info
 *
 * RETURN:      Field type
 *
 * DESCRIPTION: Get field type
 *
 *****************************************************************************/

UINT8
DtGetFieldType (
    ACPI_DMTABLE_INFO       *Info)
{
    UINT8                   Type;


    /* DT_FLAG means that this is the start of a block of flag bits */
    /* TBD - we can make these a separate opcode later */

    if (Info->Flags & DT_FLAG)
    {
        return (DT_FIELD_TYPE_FLAGS_INTEGER);
    }

    /* Type is based upon the opcode for this field in the info table */

    switch (Info->Opcode)
    {
    case ACPI_DMT_FLAG0:
    case ACPI_DMT_FLAG1:
    case ACPI_DMT_FLAG2:
    case ACPI_DMT_FLAG3:
    case ACPI_DMT_FLAG4:
    case ACPI_DMT_FLAG5:
    case ACPI_DMT_FLAG6:
    case ACPI_DMT_FLAG7:
    case ACPI_DMT_FLAGS0:
    case ACPI_DMT_FLAGS1:
    case ACPI_DMT_FLAGS2:
    case ACPI_DMT_FLAGS4:

        Type = DT_FIELD_TYPE_FLAG;
        break;

    case ACPI_DMT_NAME4:
    case ACPI_DMT_SIG:
    case ACPI_DMT_NAME6:
    case ACPI_DMT_NAME8:
    case ACPI_DMT_STRING:

        Type = DT_FIELD_TYPE_STRING;
        break;

    case ACPI_DMT_BUFFER:
    case ACPI_DMT_RAW_BUFFER:
    case ACPI_DMT_BUF7:
    case ACPI_DMT_BUF10:
    case ACPI_DMT_BUF16:
    case ACPI_DMT_BUF128:
    case ACPI_DMT_PCI_PATH:

        Type = DT_FIELD_TYPE_BUFFER;
        break;

    case ACPI_DMT_GAS:
    case ACPI_DMT_HESTNTFY:
    case ACPI_DMT_IORTMEM:

        Type = DT_FIELD_TYPE_INLINE_SUBTABLE;
        break;

    case ACPI_DMT_UNICODE:

        Type = DT_FIELD_TYPE_UNICODE;
        break;

    case ACPI_DMT_UUID:

        Type = DT_FIELD_TYPE_UUID;
        break;

    case ACPI_DMT_DEVICE_PATH:

        Type = DT_FIELD_TYPE_DEVICE_PATH;
        break;

    case ACPI_DMT_LABEL:

        Type = DT_FIELD_TYPE_LABEL;
        break;

    default:

        Type = DT_FIELD_TYPE_INTEGER;
        break;
    }

    return (Type);
}


/******************************************************************************
 *
 * FUNCTION:    DtGetBufferLength
 *
 * PARAMETERS:  Buffer              - List of integers,
 *                                    for example "10 3A 4F 2E"
 *
 * RETURN:      Count of integer
 *
 * DESCRIPTION: Get length of bytes needed to store the integers
 *
 *****************************************************************************/

UINT32
DtGetBufferLength (
    char                    *Buffer)
{
    UINT32                  ByteLength = 0;


    while (*Buffer)
    {
        if (*Buffer == ' ')
        {
            ByteLength++;

            while (*Buffer == ' ')
            {
                Buffer++;
            }
        }

        Buffer++;
    }

    return (++ByteLength);
}


/******************************************************************************
 *
 * FUNCTION:    DtGetFieldLength
 *
 * PARAMETERS:  Field               - Current field
 *              Info                - Data table info
 *
 * RETURN:      Field length
 *
 * DESCRIPTION: Get length of bytes needed to compile the field
 *
 * Note: This function must remain in sync with AcpiDmDumpTable.
 *
 *****************************************************************************/

UINT32
DtGetFieldLength (
    DT_FIELD                *Field,
    ACPI_DMTABLE_INFO       *Info)
{
    UINT32                  ByteLength = 0;
    char                    *Value;


    /* Length is based upon the opcode for this field in the info table */

    switch (Info->Opcode)
    {
    case ACPI_DMT_FLAG0:
    case ACPI_DMT_FLAG1:
    case ACPI_DMT_FLAG2:
    case ACPI_DMT_FLAG3:
    case ACPI_DMT_FLAG4:
    case ACPI_DMT_FLAG5:
    case ACPI_DMT_FLAG6:
    case ACPI_DMT_FLAG7:
    case ACPI_DMT_FLAGS0:
    case ACPI_DMT_FLAGS1:
    case ACPI_DMT_FLAGS2:
    case ACPI_DMT_FLAGS4:
    case ACPI_DMT_LABEL:
    case ACPI_DMT_EXTRA_TEXT:

        ByteLength = 0;
        break;

    case ACPI_DMT_UINT8:
    case ACPI_DMT_CHKSUM:
    case ACPI_DMT_SPACEID:
    case ACPI_DMT_ACCWIDTH:
    case ACPI_DMT_IVRS:
    case ACPI_DMT_GTDT:
    case ACPI_DMT_MADT:
    case ACPI_DMT_PCCT:
    case ACPI_DMT_PMTT:
    case ACPI_DMT_SRAT:
    case ACPI_DMT_ASF:
    case ACPI_DMT_HESTNTYP:
    case ACPI_DMT_FADTPM:
    case ACPI_DMT_EINJACT:
    case ACPI_DMT_EINJINST:
    case ACPI_DMT_ERSTACT:
    case ACPI_DMT_ERSTINST:
    case ACPI_DMT_DMAR_SCOPE:

        ByteLength = 1;
        break;

    case ACPI_DMT_UINT16:
    case ACPI_DMT_DMAR:
    case ACPI_DMT_HEST:
    case ACPI_DMT_NFIT:
    case ACPI_DMT_PCI_PATH:

        ByteLength = 2;
        break;

    case ACPI_DMT_UINT24:

        ByteLength = 3;
        break;

    case ACPI_DMT_UINT32:
    case ACPI_DMT_NAME4:
    case ACPI_DMT_SIG:
    case ACPI_DMT_LPIT:

        ByteLength = 4;
        break;

    case ACPI_DMT_UINT40:

        ByteLength = 5;
        break;

    case ACPI_DMT_UINT48:
    case ACPI_DMT_NAME6:

        ByteLength = 6;
        break;

    case ACPI_DMT_UINT56:
    case ACPI_DMT_BUF7:

        ByteLength = 7;
        break;

    case ACPI_DMT_UINT64:
    case ACPI_DMT_NAME8:

        ByteLength = 8;
        break;

    case ACPI_DMT_STRING:

        Value = DtGetFieldValue (Field);
        if (Value)
        {
            ByteLength = strlen (Value) + 1;
        }
        else
        {   /* At this point, this is a fatal error */

            sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
            DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
            return (0);
        }
        break;

    case ACPI_DMT_GAS:

        ByteLength = sizeof (ACPI_GENERIC_ADDRESS);
        break;

    case ACPI_DMT_HESTNTFY:

        ByteLength = sizeof (ACPI_HEST_NOTIFY);
        break;

    case ACPI_DMT_IORTMEM:

        ByteLength = sizeof (ACPI_IORT_MEMORY_ACCESS);
        break;

    case ACPI_DMT_BUFFER:
    case ACPI_DMT_RAW_BUFFER:

        Value = DtGetFieldValue (Field);
        if (Value)
        {
            ByteLength = DtGetBufferLength (Value);
        }
        else
        {   /* At this point, this is a fatal error */

            sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
            DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
            return (0);
        }
        break;

    case ACPI_DMT_BUF10:

        ByteLength = 10;
        break;

    case ACPI_DMT_BUF16:
    case ACPI_DMT_UUID:

        ByteLength = 16;
        break;

    case ACPI_DMT_BUF128:

        ByteLength = 128;
        break;

    case ACPI_DMT_UNICODE:

        Value = DtGetFieldValue (Field);

        /* TBD: error if Value is NULL? (as below?) */

        ByteLength = (strlen (Value) + 1) * sizeof(UINT16);
        break;

    default:

        DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode");
        return (0);
    }

    return (ByteLength);
}


/******************************************************************************
 *
 * FUNCTION:    DtSum
 *
 * PARAMETERS:  DT_WALK_CALLBACK:
 *              Subtable            - Subtable
 *              Context             - Unused
 *              ReturnValue         - Store the checksum of subtable
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Get the checksum of subtable
 *
 *****************************************************************************/

static void
DtSum (
    DT_SUBTABLE             *Subtable,
    void                    *Context,
    void                    *ReturnValue)
{
    UINT8                   Checksum;
    UINT8                   *Sum = ReturnValue;


    Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length);
    *Sum = (UINT8) (*Sum + Checksum);
}


/******************************************************************************
 *
 * FUNCTION:    DtSetTableChecksum
 *
 * PARAMETERS:  ChecksumPointer     - Where to return the checksum
 *
 * RETURN:      None
 *
 * DESCRIPTION: Set checksum of the whole data table into the checksum field
 *
 *****************************************************************************/

void
DtSetTableChecksum (
    UINT8                   *ChecksumPointer)
{
    UINT8                   Checksum = 0;
    UINT8                   OldSum;


    DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum);

    OldSum = *ChecksumPointer;
    Checksum = (UINT8) (Checksum - OldSum);

    /* Compute the final checksum */

    Checksum = (UINT8) (0 - Checksum);
    *ChecksumPointer = Checksum;
}


/******************************************************************************
 *
 * FUNCTION:    DtSetTableLength
 *
 * PARAMETERS:  None
 *
 * RETURN:      None
 *
 * DESCRIPTION: Walk the subtables and set all the length fields
 *
 *****************************************************************************/

void
DtSetTableLength (
    void)
{
    DT_SUBTABLE             *ParentTable;
    DT_SUBTABLE             *ChildTable;


    ParentTable = Gbl_RootTable;
    ChildTable = NULL;

    if (!ParentTable)
    {
        return;
    }

    DtSetSubtableLength (ParentTable);

    while (1)
    {
        ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
        if (ChildTable)
        {
            if (ChildTable->LengthField)
            {
                DtSetSubtableLength (ChildTable);
            }

            if (ChildTable->Child)
            {
                ParentTable = ChildTable;
                ChildTable = NULL;
            }
            else
            {
                ParentTable->TotalLength += ChildTable->TotalLength;
                if (ParentTable->LengthField)
                {
                    DtSetSubtableLength (ParentTable);
                }
            }
        }
        else
        {
            ChildTable = ParentTable;

            if (ChildTable == Gbl_RootTable)
            {
                break;
            }

            ParentTable = DtGetParentSubtable (ParentTable);

            ParentTable->TotalLength += ChildTable->TotalLength;
            if (ParentTable->LengthField)
            {
                DtSetSubtableLength (ParentTable);
            }
        }
    }
}


/******************************************************************************
 *
 * FUNCTION:    DtWalkTableTree
 *
 * PARAMETERS:  StartTable          - Subtable in the tree where walking begins
 *              UserFunction        - Called during the walk
 *              Context             - Passed to user function
 *              ReturnValue         - The return value of UserFunction
 *
 * RETURN:      None
 *
 * DESCRIPTION: Performs a depth-first walk of the subtable tree
 *
 *****************************************************************************/

void
DtWalkTableTree (
    DT_SUBTABLE             *StartTable,
    DT_WALK_CALLBACK        UserFunction,
    void                    *Context,
    void                    *ReturnValue)
{
    DT_SUBTABLE             *ParentTable;
    DT_SUBTABLE             *ChildTable;


    ParentTable = StartTable;
    ChildTable = NULL;

    if (!ParentTable)
    {
        return;
    }

    UserFunction (ParentTable, Context, ReturnValue);

    while (1)
    {
        ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
        if (ChildTable)
        {
            UserFunction (ChildTable, Context, ReturnValue);

            if (ChildTable->Child)
            {
                ParentTable = ChildTable;
                ChildTable = NULL;
            }
        }
        else
        {
            ChildTable = ParentTable;
            if (ChildTable == Gbl_RootTable)
            {
                break;
            }

            ParentTable = DtGetParentSubtable (ParentTable);

            if (ChildTable->Peer == StartTable)
            {
                break;
            }
        }
    }
}


/*******************************************************************************
 *
 * FUNCTION:    UtSubtableCacheCalloc
 *
 * PARAMETERS:  None
 *
 * RETURN:      Pointer to the buffer. Aborts on allocation failure
 *
 * DESCRIPTION: Allocate a subtable object buffer. Bypass the local
 *              dynamic memory manager for performance reasons (This has a
 *              major impact on the speed of the compiler.)
 *
 ******************************************************************************/

DT_SUBTABLE *
UtSubtableCacheCalloc (
    void)
{
    ASL_CACHE_INFO          *Cache;


    if (Gbl_SubtableCacheNext >= Gbl_SubtableCacheLast)
    {
        /* Allocate a new buffer */

        Cache = UtLocalCalloc (sizeof (Cache->Next) +
            (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE));

        /* Link new cache buffer to head of list */

        Cache->Next = Gbl_SubtableCacheList;
        Gbl_SubtableCacheList = Cache;

        /* Setup cache management pointers */

        Gbl_SubtableCacheNext = ACPI_CAST_PTR (DT_SUBTABLE, Cache->Buffer);
        Gbl_SubtableCacheLast = Gbl_SubtableCacheNext + ASL_SUBTABLE_CACHE_SIZE;
    }

    Gbl_SubtableCount++;
    return (Gbl_SubtableCacheNext++);
}


/*******************************************************************************
 *
 * FUNCTION:    UtFieldCacheCalloc
 *
 * PARAMETERS:  None
 *
 * RETURN:      Pointer to the buffer. Aborts on allocation failure
 *
 * DESCRIPTION: Allocate a field object buffer. Bypass the local
 *              dynamic memory manager for performance reasons (This has a
 *              major impact on the speed of the compiler.)
 *
 ******************************************************************************/

DT_FIELD *
UtFieldCacheCalloc (
    void)
{
    ASL_CACHE_INFO          *Cache;


    if (Gbl_FieldCacheNext >= Gbl_FieldCacheLast)
    {
        /* Allocate a new buffer */

        Cache = UtLocalCalloc (sizeof (Cache->Next) +
            (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE));

        /* Link new cache buffer to head of list */

        Cache->Next = Gbl_FieldCacheList;
        Gbl_FieldCacheList = Cache;

        /* Setup cache management pointers */

        Gbl_FieldCacheNext = ACPI_CAST_PTR (DT_FIELD, Cache->Buffer);
        Gbl_FieldCacheLast = Gbl_FieldCacheNext + ASL_FIELD_CACHE_SIZE;
    }

    Gbl_FieldCount++;
    return (Gbl_FieldCacheNext++);
}


/*******************************************************************************
 *
 * FUNCTION:    DtDeleteCaches
 *
 * PARAMETERS:  None
 *
 * RETURN:      None
 *
 * DESCRIPTION: Delete all local cache buffer blocks
 *
 ******************************************************************************/

void
DtDeleteCaches (
    void)
{
    UINT32                  BufferCount;
    ASL_CACHE_INFO          *Next;


    /* Field cache */

    BufferCount = 0;
    while (Gbl_FieldCacheList)
    {
        Next = Gbl_FieldCacheList->Next;
        ACPI_FREE (Gbl_FieldCacheList);
        Gbl_FieldCacheList = Next;
        BufferCount++;
    }

    DbgPrint (ASL_DEBUG_OUTPUT,
        "%u Fields, Buffer size: %u fields (%u bytes), %u Buffers\n",
        Gbl_FieldCount, ASL_FIELD_CACHE_SIZE,
        (sizeof (DT_FIELD) * ASL_FIELD_CACHE_SIZE), BufferCount);

    Gbl_FieldCount = 0;
    Gbl_FieldCacheNext = NULL;
    Gbl_FieldCacheLast = NULL;

    /* Subtable cache */

    BufferCount = 0;
    while (Gbl_SubtableCacheList)
    {
        Next = Gbl_SubtableCacheList->Next;
        ACPI_FREE (Gbl_SubtableCacheList);
        Gbl_SubtableCacheList = Next;
        BufferCount++;
    }

    DbgPrint (ASL_DEBUG_OUTPUT,
        "%u Subtables, Buffer size: %u subtables (%u bytes), %u Buffers\n",
        Gbl_SubtableCount, ASL_SUBTABLE_CACHE_SIZE,
        (sizeof (DT_SUBTABLE) * ASL_SUBTABLE_CACHE_SIZE), BufferCount);

    Gbl_SubtableCount = 0;
    Gbl_SubtableCacheNext = NULL;
    Gbl_SubtableCacheLast = NULL;
}