asloffset.c revision 249109
1139823Simp/******************************************************************************
21541Srgrimes *
31541Srgrimes * Module Name: asloffset - Generate a C "offset table" for BIOS use.
41541Srgrimes *
51541Srgrimes *****************************************************************************/
61541Srgrimes
71541Srgrimes/*
81541Srgrimes * Copyright (C) 2000 - 2013, Intel Corp.
91541Srgrimes * All rights reserved.
101541Srgrimes *
111541Srgrimes * Redistribution and use in source and binary forms, with or without
121541Srgrimes * modification, are permitted provided that the following conditions
131541Srgrimes * are met:
141541Srgrimes * 1. Redistributions of source code must retain the above copyright
151541Srgrimes *    notice, this list of conditions, and the following disclaimer,
161541Srgrimes *    without modification.
171541Srgrimes * 2. Redistributions in binary form must reproduce at minimum a disclaimer
181541Srgrimes *    substantially similar to the "NO WARRANTY" disclaimer below
191541Srgrimes *    ("Disclaimer") and any redistribution must be conditioned upon
201541Srgrimes *    including a substantially similar Disclaimer requirement for further
211541Srgrimes *    binary redistribution.
221541Srgrimes * 3. Neither the names of the above-listed copyright holders nor the names
231541Srgrimes *    of any contributors may be used to endorse or promote products derived
241541Srgrimes *    from this software without specific prior written permission.
251541Srgrimes *
261541Srgrimes * Alternatively, this software may be distributed under the terms of the
271541Srgrimes * GNU General Public License ("GPL") version 2 as published by the Free
281541Srgrimes * Software Foundation.
2910939Swollman *
3050477Speter * NO WARRANTY
311541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
321541Srgrimes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
332169Spaul * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
342169Spaul * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
352169Spaul * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
367280Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3784102Sjlemon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
387280Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
391541Srgrimes * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
401541Srgrimes * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4121666Swollman * POSSIBILITY OF SUCH DAMAGES.
421541Srgrimes */
431541Srgrimes
441541Srgrimes#include "aslcompiler.h"
451541Srgrimes#include "aslcompiler.y.h"
461541Srgrimes#include "amlcode.h"
471541Srgrimes#include "acnamesp.h"
481541Srgrimes
491541Srgrimes
501541Srgrimes#define _COMPONENT          ACPI_COMPILER
511541Srgrimes        ACPI_MODULE_NAME    ("asloffset")
521541Srgrimes
531541Srgrimes
541541Srgrimes/* Local prototypes */
5584102Sjlemon
5684102Sjlemonstatic void
571541SrgrimesLsEmitOffsetTableEntry (
581541Srgrimes    UINT32                  FileId,
591541Srgrimes    ACPI_NAMESPACE_NODE     *Node,
601541Srgrimes    UINT32                  Offset,
611541Srgrimes    UINT32                  Length,
621541Srgrimes    char                    *OpName,
631541Srgrimes    UINT64                  Value,
641541Srgrimes    UINT8                   AmlOpcode);
651541Srgrimes
661541Srgrimes
671541Srgrimes/*******************************************************************************
681541Srgrimes *
691541Srgrimes * FUNCTION:    LsAmlOffsetWalk
701541Srgrimes *
711541Srgrimes * PARAMETERS:  ASL_WALK_CALLBACK
721541Srgrimes *
731541Srgrimes * RETURN:      Status
743865Sswallace *
753865Sswallace * DESCRIPTION: Process one node during a offset table file generation.
761541Srgrimes *
771541Srgrimes * Three types of objects are currently emitted to the offset table:
781541Srgrimes *   1) Tagged (named) resource descriptors
791541Srgrimes *   2) Named integer objects with constant integer values
808876Srgrimes *   3) Operation Regions that have constant Offset (address) parameters
8155205Speter *
827090Sbde * The offset table allows the BIOS to dynamically update the values of these
831541Srgrimes * objects at boot time.
84133874Srwatson *
8584102Sjlemon ******************************************************************************/
8684102Sjlemon
8784102SjlemonACPI_STATUS
8884102SjlemonLsAmlOffsetWalk (
8984102Sjlemon    ACPI_PARSE_OBJECT       *Op,
9084102Sjlemon    UINT32                  Level,
9184102Sjlemon    void                    *Context)
9284102Sjlemon{
9384102Sjlemon    UINT32                  FileId = (UINT32) ACPI_TO_INTEGER (Context);
9484102Sjlemon    ACPI_NAMESPACE_NODE     *Node;
9584102Sjlemon    UINT32                  Length;
9684102Sjlemon    UINT32                  OffsetOfOpcode;
9784102Sjlemon    ACPI_PARSE_OBJECT       *AddressOp;
981541Srgrimes
991541Srgrimes
1001541Srgrimes    /* Ignore actual data blocks for resource descriptors */
1011541Srgrimes
1021541Srgrimes    if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA)
1031541Srgrimes    {
1041541Srgrimes        return (AE_OK); /* Do NOT update the global AML offset */
1051541Srgrimes    }
10679821Sru
1071541Srgrimes    /* We are only interested in named objects (have a namespace node) */
10884109Sjlemon
10979821Sru    Node = Op->Asl.Node;
11079821Sru    if (!Node)
1111541Srgrimes    {
1121541Srgrimes        Gbl_CurrentAmlOffset += Op->Asl.FinalAmlLength;
1131541Srgrimes        return (AE_OK);
1141541Srgrimes    }
1151541Srgrimes
1161541Srgrimes    /* Named resource descriptor (has a descriptor tag) */
1171541Srgrimes
1181541Srgrimes    if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE) &&
1191541Srgrimes        (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
1201541Srgrimes    {
1211541Srgrimes        LsEmitOffsetTableEntry (FileId, Node, Gbl_CurrentAmlOffset,
12271998Sphk            Op->Asl.FinalAmlLength, Op->Asl.ParseOpName, 0, Op->Asl.Extra);
1231541Srgrimes    }
12471998Sphk
1251541Srgrimes    /* Named object -- Name (NameString, DataRefObject) */
1261541Srgrimes
1271541Srgrimes    else if (Op->Asl.AmlOpcode == AML_NAME_OP)
1281541Srgrimes    {
1291541Srgrimes        if (!Op->Asl.Child)
1302531Swollman        {
1312531Swollman            FlPrintFile (FileId, "%s NO CHILD!\n", MsgBuffer);
1322531Swollman            return (AE_OK);
1332531Swollman        }
1342531Swollman
13514622Sfenner        Length = Op->Asl.FinalAmlLength;
13614622Sfenner
13714622Sfenner        /* Get to the NameSeg/NamePath Op (and length of the name) */
138119180Srwatson
1392531Swollman        Op = Op->Asl.Child;
1402531Swollman        OffsetOfOpcode = Length + Op->Asl.FinalAmlLength;
1412531Swollman
1421541Srgrimes        /* Get actual value associated with the name */
1431541Srgrimes
14421666Swollman        Op = Op->Asl.Next;
14521666Swollman        switch (Op->Asl.AmlOpcode)
14621666Swollman        {
14721666Swollman        /*
1481541Srgrimes         * We are only interested in integer constants that can be changed
1491541Srgrimes         * at boot time. Note, the One/Ones/Zero opcodes are considered
15060938Sjake         * non-changeable, so we ignore them here.
15121666Swollman         */
1521541Srgrimes        case AML_BYTE_OP:
15321666Swollman        case AML_WORD_OP:
1541541Srgrimes        case AML_DWORD_OP:
1552531Swollman        case AML_QWORD_OP:
1562531Swollman
1571541Srgrimes            /* The +1/-1 is to handle the integer size prefix (opcode) */
1581541Srgrimes
15955205Speter            LsEmitOffsetTableEntry (FileId, Node,
16044078Sdfr                (Gbl_CurrentAmlOffset + OffsetOfOpcode + 1),
16144078Sdfr                (Op->Asl.FinalAmlLength - 1), Op->Asl.ParseOpName,
162136713Sandre                Op->Asl.Value.Integer, (UINT8) Op->Asl.AmlOpcode);
16344078Sdfr            break;
16444078Sdfr
16544078Sdfr        default:
16644078Sdfr            break;
16760938Sjake        }
16821666Swollman
1691541Srgrimes        Gbl_CurrentAmlOffset += Length;
1701541Srgrimes        return (AE_OK);
1711541Srgrimes    }
1721541Srgrimes
1731541Srgrimes    /* OperationRegion (NameString, RegionSpace, RegionOffset, RegionLength) */
1741541Srgrimes
1751541Srgrimes    else if (Op->Asl.AmlOpcode == AML_REGION_OP)
1761541Srgrimes    {
1771541Srgrimes        Length = Op->Asl.FinalAmlLength;
1781541Srgrimes
17921666Swollman        /* Get the name/namepath node */
1801541Srgrimes
1811541Srgrimes        AddressOp = Op->Asl.Child;
1821541Srgrimes        OffsetOfOpcode = Length + AddressOp->Asl.FinalAmlLength + 1;
1831541Srgrimes
1841541Srgrimes        /* Get the SpaceId node, then the Offset (address) node */
18520407Swollman
18679821Sru        AddressOp = AddressOp->Asl.Next;
1871541Srgrimes        AddressOp = AddressOp->Asl.Next;
188148653Srwatson
18972084Sphk        switch (AddressOp->Asl.AmlOpcode)
19021666Swollman        {
19121929Swollman        /*
19221666Swollman         * We are only interested in integer constants that can be changed
19321666Swollman         * at boot time. Note, the One/Ones/Zero opcodes are considered
19421666Swollman         * non-changeable, so we ignore them here.
19521666Swollman         */
196148653Srwatson        case AML_BYTE_OP:
19720407Swollman        case AML_WORD_OP:
1981541Srgrimes        case AML_DWORD_OP:
1991541Srgrimes        case AML_QWORD_OP:
2001541Srgrimes
2011541Srgrimes            /* The +1/-1 is to handle the integer size prefix (opcode) */
2021541Srgrimes
2031541Srgrimes            LsEmitOffsetTableEntry (FileId, Node,
2041541Srgrimes                (Gbl_CurrentAmlOffset + OffsetOfOpcode + 1),
2051541Srgrimes                (AddressOp->Asl.FinalAmlLength - 1), Op->Asl.ParseOpName,
2061541Srgrimes                AddressOp->Asl.Value.Integer, (UINT8) AddressOp->Asl.AmlOpcode);
2071541Srgrimes
2081541Srgrimes            Gbl_CurrentAmlOffset += Length;
20920407Swollman            return (AE_OK);
2101541Srgrimes
21171998Sphk        default:
21220407Swollman            break;
2131541Srgrimes        }
2141541Srgrimes    }
2151541Srgrimes
2161541Srgrimes    Gbl_CurrentAmlOffset += Op->Asl.FinalAmlLength;
21720407Swollman    return (AE_OK);
21871998Sphk}
2191541Srgrimes
22020407Swollman
2211541Srgrimes/*******************************************************************************
22236192Sdg *
22392723Salfred * FUNCTION:    LsEmitOffsetTableEntry
22492723Salfred *
22592723Salfred * PARAMETERS:  FileId          - ID of current listing file
22693085Sbde *              Node            - Namespace node associated with the name
22792723Salfred *              Offset          - Offset of the value within the AML table
22892723Salfred *              Length          - Length in bytes of the value
22992723Salfred *              OpName          - Name of the AML opcode
23092723Salfred *              Value           - Current value of the AML field
231122702Sandre *              AmlOpcode       - Opcode associated with the field
2322169Spaul *
23355205Speter * RETURN:      None
23410939Swollman *
23552904Sshin * DESCRIPTION: Emit a line of the offset table (-so option)
23652904Sshin *
23752904Sshin ******************************************************************************/
23810939Swollman
239static void
240LsEmitOffsetTableEntry (
241    UINT32                  FileId,
242    ACPI_NAMESPACE_NODE     *Node,
243    UINT32                  Offset,
244    UINT32                  Length,
245    char                    *OpName,
246    UINT64                  Value,
247    UINT8                   AmlOpcode)
248{
249    ACPI_BUFFER             TargetPath;
250    ACPI_STATUS             Status;
251
252
253    /* Get the full pathname to the namespace node */
254
255    TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
256    Status = AcpiNsHandleToPathname (Node, &TargetPath);
257    if (ACPI_FAILURE (Status))
258    {
259        return;
260    }
261
262    /* [1] - Skip the opening backslash for the path */
263
264    strcpy (MsgBuffer, "\"");
265    strcat (MsgBuffer, &((char *) TargetPath.Pointer)[1]);
266    strcat (MsgBuffer, "\",");
267    ACPI_FREE (TargetPath.Pointer);
268
269    /*
270     * Max offset is 4G, constrained by 32-bit ACPI table length.
271     * Max Length for Integers is 8 bytes.
272     */
273    FlPrintFile (FileId,
274        "    {%-29s 0x%8.8X, 0x%2.2X, 0x%8.8X%8.8X}, /* %s */\n",
275        MsgBuffer, Offset, AmlOpcode, ACPI_FORMAT_UINT64 (Value), OpName);
276}
277
278
279/*******************************************************************************
280 *
281 * FUNCTION:    LsDoOffsetTableHeader, LsDoOffsetTableFooter
282 *
283 * PARAMETERS:  FileId          - ID of current listing file
284 *
285 * RETURN:      None
286 *
287 * DESCRIPTION: Header and footer for the offset table file.
288 *
289 ******************************************************************************/
290
291void
292LsDoOffsetTableHeader (
293    UINT32                  FileId)
294{
295
296    Gbl_CurrentAmlOffset = 0;
297
298    FlPrintFile (FileId,
299        "#ifndef __AML_OFFSET_TABLE_H\n"
300        "#define __AML_OFFSET_TABLE_H\n\n");
301
302    FlPrintFile (FileId, "typedef struct {\n"
303        "    char                   *Pathname;\n"
304        "    unsigned long          Offset;\n"
305        "    unsigned char          AmlOpcode;\n"
306        "    unsigned long long     AmlValue;\n"
307        "} AML_OFFSET_TABLE_ENTRY;\n\n");
308
309    FlPrintFile (FileId,
310        "#endif /* __AML_OFFSET_TABLE_H */\n\n");
311
312    FlPrintFile (FileId,
313        "AML_OFFSET_TABLE_ENTRY   %s_%s_OffsetTable[] =\n{\n",
314        Gbl_TableSignature, Gbl_TableId);
315}
316
317
318void
319LsDoOffsetTableFooter (
320    UINT32                  FileId)
321{
322
323    FlPrintFile (FileId,
324        "    {0,0,0,0} /* Table terminator */\n};\n\n");
325    Gbl_CurrentAmlOffset = 0;
326}
327