asloffset.c revision 249112
1249109Sjkim/******************************************************************************
2249109Sjkim *
3249109Sjkim * Module Name: asloffset - Generate a C "offset table" for BIOS use.
4249109Sjkim *
5249109Sjkim *****************************************************************************/
6249109Sjkim
7249109Sjkim/*
8249109Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
9249109Sjkim * All rights reserved.
10249109Sjkim *
11249109Sjkim * Redistribution and use in source and binary forms, with or without
12249109Sjkim * modification, are permitted provided that the following conditions
13249109Sjkim * are met:
14249109Sjkim * 1. Redistributions of source code must retain the above copyright
15249109Sjkim *    notice, this list of conditions, and the following disclaimer,
16249109Sjkim *    without modification.
17249109Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18249109Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19249109Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20249109Sjkim *    including a substantially similar Disclaimer requirement for further
21249109Sjkim *    binary redistribution.
22249109Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23249109Sjkim *    of any contributors may be used to endorse or promote products derived
24249109Sjkim *    from this software without specific prior written permission.
25249109Sjkim *
26249109Sjkim * Alternatively, this software may be distributed under the terms of the
27249109Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28249109Sjkim * Software Foundation.
29249109Sjkim *
30249109Sjkim * NO WARRANTY
31249109Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32249109Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33249109Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34249109Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35249109Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36249109Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37249109Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38249109Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39249109Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40249109Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41249109Sjkim * POSSIBILITY OF SUCH DAMAGES.
42249109Sjkim */
43249109Sjkim
44249112Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
45249109Sjkim#include "aslcompiler.y.h"
46249112Sjkim#include <contrib/dev/acpica/include/amlcode.h>
47249112Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
48249109Sjkim
49249109Sjkim
50249109Sjkim#define _COMPONENT          ACPI_COMPILER
51249109Sjkim        ACPI_MODULE_NAME    ("asloffset")
52249109Sjkim
53249109Sjkim
54249109Sjkim/* Local prototypes */
55249109Sjkim
56249109Sjkimstatic void
57249109SjkimLsEmitOffsetTableEntry (
58249109Sjkim    UINT32                  FileId,
59249109Sjkim    ACPI_NAMESPACE_NODE     *Node,
60249109Sjkim    UINT32                  Offset,
61249109Sjkim    UINT32                  Length,
62249109Sjkim    char                    *OpName,
63249109Sjkim    UINT64                  Value,
64249109Sjkim    UINT8                   AmlOpcode);
65249109Sjkim
66249109Sjkim
67249109Sjkim/*******************************************************************************
68249109Sjkim *
69249109Sjkim * FUNCTION:    LsAmlOffsetWalk
70249109Sjkim *
71249109Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
72249109Sjkim *
73249109Sjkim * RETURN:      Status
74249109Sjkim *
75249109Sjkim * DESCRIPTION: Process one node during a offset table file generation.
76249109Sjkim *
77249109Sjkim * Three types of objects are currently emitted to the offset table:
78249109Sjkim *   1) Tagged (named) resource descriptors
79249109Sjkim *   2) Named integer objects with constant integer values
80249109Sjkim *   3) Operation Regions that have constant Offset (address) parameters
81249109Sjkim *
82249109Sjkim * The offset table allows the BIOS to dynamically update the values of these
83249109Sjkim * objects at boot time.
84249109Sjkim *
85249109Sjkim ******************************************************************************/
86249109Sjkim
87249109SjkimACPI_STATUS
88249109SjkimLsAmlOffsetWalk (
89249109Sjkim    ACPI_PARSE_OBJECT       *Op,
90249109Sjkim    UINT32                  Level,
91249109Sjkim    void                    *Context)
92249109Sjkim{
93249109Sjkim    UINT32                  FileId = (UINT32) ACPI_TO_INTEGER (Context);
94249109Sjkim    ACPI_NAMESPACE_NODE     *Node;
95249109Sjkim    UINT32                  Length;
96249109Sjkim    UINT32                  OffsetOfOpcode;
97249109Sjkim    ACPI_PARSE_OBJECT       *AddressOp;
98249109Sjkim
99249109Sjkim
100249109Sjkim    /* Ignore actual data blocks for resource descriptors */
101249109Sjkim
102249109Sjkim    if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA)
103249109Sjkim    {
104249109Sjkim        return (AE_OK); /* Do NOT update the global AML offset */
105249109Sjkim    }
106249109Sjkim
107249109Sjkim    /* We are only interested in named objects (have a namespace node) */
108249109Sjkim
109249109Sjkim    Node = Op->Asl.Node;
110249109Sjkim    if (!Node)
111249109Sjkim    {
112249109Sjkim        Gbl_CurrentAmlOffset += Op->Asl.FinalAmlLength;
113249109Sjkim        return (AE_OK);
114249109Sjkim    }
115249109Sjkim
116249109Sjkim    /* Named resource descriptor (has a descriptor tag) */
117249109Sjkim
118249109Sjkim    if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE) &&
119249109Sjkim        (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
120249109Sjkim    {
121249109Sjkim        LsEmitOffsetTableEntry (FileId, Node, Gbl_CurrentAmlOffset,
122249109Sjkim            Op->Asl.FinalAmlLength, Op->Asl.ParseOpName, 0, Op->Asl.Extra);
123249109Sjkim    }
124249109Sjkim
125249109Sjkim    /* Named object -- Name (NameString, DataRefObject) */
126249109Sjkim
127249109Sjkim    else if (Op->Asl.AmlOpcode == AML_NAME_OP)
128249109Sjkim    {
129249109Sjkim        if (!Op->Asl.Child)
130249109Sjkim        {
131249109Sjkim            FlPrintFile (FileId, "%s NO CHILD!\n", MsgBuffer);
132249109Sjkim            return (AE_OK);
133249109Sjkim        }
134249109Sjkim
135249109Sjkim        Length = Op->Asl.FinalAmlLength;
136249109Sjkim
137249109Sjkim        /* Get to the NameSeg/NamePath Op (and length of the name) */
138249109Sjkim
139249109Sjkim        Op = Op->Asl.Child;
140249109Sjkim        OffsetOfOpcode = Length + Op->Asl.FinalAmlLength;
141249109Sjkim
142249109Sjkim        /* Get actual value associated with the name */
143249109Sjkim
144249109Sjkim        Op = Op->Asl.Next;
145249109Sjkim        switch (Op->Asl.AmlOpcode)
146249109Sjkim        {
147249109Sjkim        /*
148249109Sjkim         * We are only interested in integer constants that can be changed
149249109Sjkim         * at boot time. Note, the One/Ones/Zero opcodes are considered
150249109Sjkim         * non-changeable, so we ignore them here.
151249109Sjkim         */
152249109Sjkim        case AML_BYTE_OP:
153249109Sjkim        case AML_WORD_OP:
154249109Sjkim        case AML_DWORD_OP:
155249109Sjkim        case AML_QWORD_OP:
156249109Sjkim
157249109Sjkim            /* The +1/-1 is to handle the integer size prefix (opcode) */
158249109Sjkim
159249109Sjkim            LsEmitOffsetTableEntry (FileId, Node,
160249109Sjkim                (Gbl_CurrentAmlOffset + OffsetOfOpcode + 1),
161249109Sjkim                (Op->Asl.FinalAmlLength - 1), Op->Asl.ParseOpName,
162249109Sjkim                Op->Asl.Value.Integer, (UINT8) Op->Asl.AmlOpcode);
163249109Sjkim            break;
164249109Sjkim
165249109Sjkim        default:
166249109Sjkim            break;
167249109Sjkim        }
168249109Sjkim
169249109Sjkim        Gbl_CurrentAmlOffset += Length;
170249109Sjkim        return (AE_OK);
171249109Sjkim    }
172249109Sjkim
173249109Sjkim    /* OperationRegion (NameString, RegionSpace, RegionOffset, RegionLength) */
174249109Sjkim
175249109Sjkim    else if (Op->Asl.AmlOpcode == AML_REGION_OP)
176249109Sjkim    {
177249109Sjkim        Length = Op->Asl.FinalAmlLength;
178249109Sjkim
179249109Sjkim        /* Get the name/namepath node */
180249109Sjkim
181249109Sjkim        AddressOp = Op->Asl.Child;
182249109Sjkim        OffsetOfOpcode = Length + AddressOp->Asl.FinalAmlLength + 1;
183249109Sjkim
184249109Sjkim        /* Get the SpaceId node, then the Offset (address) node */
185249109Sjkim
186249109Sjkim        AddressOp = AddressOp->Asl.Next;
187249109Sjkim        AddressOp = AddressOp->Asl.Next;
188249109Sjkim
189249109Sjkim        switch (AddressOp->Asl.AmlOpcode)
190249109Sjkim        {
191249109Sjkim        /*
192249109Sjkim         * We are only interested in integer constants that can be changed
193249109Sjkim         * at boot time. Note, the One/Ones/Zero opcodes are considered
194249109Sjkim         * non-changeable, so we ignore them here.
195249109Sjkim         */
196249109Sjkim        case AML_BYTE_OP:
197249109Sjkim        case AML_WORD_OP:
198249109Sjkim        case AML_DWORD_OP:
199249109Sjkim        case AML_QWORD_OP:
200249109Sjkim
201249109Sjkim            /* The +1/-1 is to handle the integer size prefix (opcode) */
202249109Sjkim
203249109Sjkim            LsEmitOffsetTableEntry (FileId, Node,
204249109Sjkim                (Gbl_CurrentAmlOffset + OffsetOfOpcode + 1),
205249109Sjkim                (AddressOp->Asl.FinalAmlLength - 1), Op->Asl.ParseOpName,
206249109Sjkim                AddressOp->Asl.Value.Integer, (UINT8) AddressOp->Asl.AmlOpcode);
207249109Sjkim
208249109Sjkim            Gbl_CurrentAmlOffset += Length;
209249109Sjkim            return (AE_OK);
210249109Sjkim
211249109Sjkim        default:
212249109Sjkim            break;
213249109Sjkim        }
214249109Sjkim    }
215249109Sjkim
216249109Sjkim    Gbl_CurrentAmlOffset += Op->Asl.FinalAmlLength;
217249109Sjkim    return (AE_OK);
218249109Sjkim}
219249109Sjkim
220249109Sjkim
221249109Sjkim/*******************************************************************************
222249109Sjkim *
223249109Sjkim * FUNCTION:    LsEmitOffsetTableEntry
224249109Sjkim *
225249109Sjkim * PARAMETERS:  FileId          - ID of current listing file
226249109Sjkim *              Node            - Namespace node associated with the name
227249109Sjkim *              Offset          - Offset of the value within the AML table
228249109Sjkim *              Length          - Length in bytes of the value
229249109Sjkim *              OpName          - Name of the AML opcode
230249109Sjkim *              Value           - Current value of the AML field
231249109Sjkim *              AmlOpcode       - Opcode associated with the field
232249109Sjkim *
233249109Sjkim * RETURN:      None
234249109Sjkim *
235249109Sjkim * DESCRIPTION: Emit a line of the offset table (-so option)
236249109Sjkim *
237249109Sjkim ******************************************************************************/
238249109Sjkim
239249109Sjkimstatic void
240249109SjkimLsEmitOffsetTableEntry (
241249109Sjkim    UINT32                  FileId,
242249109Sjkim    ACPI_NAMESPACE_NODE     *Node,
243249109Sjkim    UINT32                  Offset,
244249109Sjkim    UINT32                  Length,
245249109Sjkim    char                    *OpName,
246249109Sjkim    UINT64                  Value,
247249109Sjkim    UINT8                   AmlOpcode)
248249109Sjkim{
249249109Sjkim    ACPI_BUFFER             TargetPath;
250249109Sjkim    ACPI_STATUS             Status;
251249109Sjkim
252249109Sjkim
253249109Sjkim    /* Get the full pathname to the namespace node */
254249109Sjkim
255249109Sjkim    TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
256249109Sjkim    Status = AcpiNsHandleToPathname (Node, &TargetPath);
257249109Sjkim    if (ACPI_FAILURE (Status))
258249109Sjkim    {
259249109Sjkim        return;
260249109Sjkim    }
261249109Sjkim
262249109Sjkim    /* [1] - Skip the opening backslash for the path */
263249109Sjkim
264249109Sjkim    strcpy (MsgBuffer, "\"");
265249109Sjkim    strcat (MsgBuffer, &((char *) TargetPath.Pointer)[1]);
266249109Sjkim    strcat (MsgBuffer, "\",");
267249109Sjkim    ACPI_FREE (TargetPath.Pointer);
268249109Sjkim
269249109Sjkim    /*
270249109Sjkim     * Max offset is 4G, constrained by 32-bit ACPI table length.
271249109Sjkim     * Max Length for Integers is 8 bytes.
272249109Sjkim     */
273249109Sjkim    FlPrintFile (FileId,
274249109Sjkim        "    {%-29s 0x%8.8X, 0x%2.2X, 0x%8.8X%8.8X}, /* %s */\n",
275249109Sjkim        MsgBuffer, Offset, AmlOpcode, ACPI_FORMAT_UINT64 (Value), OpName);
276249109Sjkim}
277249109Sjkim
278249109Sjkim
279249109Sjkim/*******************************************************************************
280249109Sjkim *
281249109Sjkim * FUNCTION:    LsDoOffsetTableHeader, LsDoOffsetTableFooter
282249109Sjkim *
283249109Sjkim * PARAMETERS:  FileId          - ID of current listing file
284249109Sjkim *
285249109Sjkim * RETURN:      None
286249109Sjkim *
287249109Sjkim * DESCRIPTION: Header and footer for the offset table file.
288249109Sjkim *
289249109Sjkim ******************************************************************************/
290249109Sjkim
291249109Sjkimvoid
292249109SjkimLsDoOffsetTableHeader (
293249109Sjkim    UINT32                  FileId)
294249109Sjkim{
295249109Sjkim
296249109Sjkim    Gbl_CurrentAmlOffset = 0;
297249109Sjkim
298249109Sjkim    FlPrintFile (FileId,
299249109Sjkim        "#ifndef __AML_OFFSET_TABLE_H\n"
300249109Sjkim        "#define __AML_OFFSET_TABLE_H\n\n");
301249109Sjkim
302249109Sjkim    FlPrintFile (FileId, "typedef struct {\n"
303249109Sjkim        "    char                   *Pathname;\n"
304249109Sjkim        "    unsigned long          Offset;\n"
305249109Sjkim        "    unsigned char          AmlOpcode;\n"
306249109Sjkim        "    unsigned long long     AmlValue;\n"
307249109Sjkim        "} AML_OFFSET_TABLE_ENTRY;\n\n");
308249109Sjkim
309249109Sjkim    FlPrintFile (FileId,
310249109Sjkim        "#endif /* __AML_OFFSET_TABLE_H */\n\n");
311249109Sjkim
312249109Sjkim    FlPrintFile (FileId,
313249109Sjkim        "AML_OFFSET_TABLE_ENTRY   %s_%s_OffsetTable[] =\n{\n",
314249109Sjkim        Gbl_TableSignature, Gbl_TableId);
315249109Sjkim}
316249109Sjkim
317249109Sjkim
318249109Sjkimvoid
319249109SjkimLsDoOffsetTableFooter (
320249109Sjkim    UINT32                  FileId)
321249109Sjkim{
322249109Sjkim
323249109Sjkim    FlPrintFile (FileId,
324249109Sjkim        "    {0,0,0,0} /* Table terminator */\n};\n\n");
325249109Sjkim    Gbl_CurrentAmlOffset = 0;
326249109Sjkim}
327