asloffset.c revision 249112
1/******************************************************************************
2 *
3 * Module Name: asloffset - Generate a C "offset table" for BIOS use.
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2013, 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 <contrib/dev/acpica/compiler/aslcompiler.h>
45#include "aslcompiler.y.h"
46#include <contrib/dev/acpica/include/amlcode.h>
47#include <contrib/dev/acpica/include/acnamesp.h>
48
49
50#define _COMPONENT          ACPI_COMPILER
51        ACPI_MODULE_NAME    ("asloffset")
52
53
54/* Local prototypes */
55
56static void
57LsEmitOffsetTableEntry (
58    UINT32                  FileId,
59    ACPI_NAMESPACE_NODE     *Node,
60    UINT32                  Offset,
61    UINT32                  Length,
62    char                    *OpName,
63    UINT64                  Value,
64    UINT8                   AmlOpcode);
65
66
67/*******************************************************************************
68 *
69 * FUNCTION:    LsAmlOffsetWalk
70 *
71 * PARAMETERS:  ASL_WALK_CALLBACK
72 *
73 * RETURN:      Status
74 *
75 * DESCRIPTION: Process one node during a offset table file generation.
76 *
77 * Three types of objects are currently emitted to the offset table:
78 *   1) Tagged (named) resource descriptors
79 *   2) Named integer objects with constant integer values
80 *   3) Operation Regions that have constant Offset (address) parameters
81 *
82 * The offset table allows the BIOS to dynamically update the values of these
83 * objects at boot time.
84 *
85 ******************************************************************************/
86
87ACPI_STATUS
88LsAmlOffsetWalk (
89    ACPI_PARSE_OBJECT       *Op,
90    UINT32                  Level,
91    void                    *Context)
92{
93    UINT32                  FileId = (UINT32) ACPI_TO_INTEGER (Context);
94    ACPI_NAMESPACE_NODE     *Node;
95    UINT32                  Length;
96    UINT32                  OffsetOfOpcode;
97    ACPI_PARSE_OBJECT       *AddressOp;
98
99
100    /* Ignore actual data blocks for resource descriptors */
101
102    if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA)
103    {
104        return (AE_OK); /* Do NOT update the global AML offset */
105    }
106
107    /* We are only interested in named objects (have a namespace node) */
108
109    Node = Op->Asl.Node;
110    if (!Node)
111    {
112        Gbl_CurrentAmlOffset += Op->Asl.FinalAmlLength;
113        return (AE_OK);
114    }
115
116    /* Named resource descriptor (has a descriptor tag) */
117
118    if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE) &&
119        (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
120    {
121        LsEmitOffsetTableEntry (FileId, Node, Gbl_CurrentAmlOffset,
122            Op->Asl.FinalAmlLength, Op->Asl.ParseOpName, 0, Op->Asl.Extra);
123    }
124
125    /* Named object -- Name (NameString, DataRefObject) */
126
127    else if (Op->Asl.AmlOpcode == AML_NAME_OP)
128    {
129        if (!Op->Asl.Child)
130        {
131            FlPrintFile (FileId, "%s NO CHILD!\n", MsgBuffer);
132            return (AE_OK);
133        }
134
135        Length = Op->Asl.FinalAmlLength;
136
137        /* Get to the NameSeg/NamePath Op (and length of the name) */
138
139        Op = Op->Asl.Child;
140        OffsetOfOpcode = Length + Op->Asl.FinalAmlLength;
141
142        /* Get actual value associated with the name */
143
144        Op = Op->Asl.Next;
145        switch (Op->Asl.AmlOpcode)
146        {
147        /*
148         * We are only interested in integer constants that can be changed
149         * at boot time. Note, the One/Ones/Zero opcodes are considered
150         * non-changeable, so we ignore them here.
151         */
152        case AML_BYTE_OP:
153        case AML_WORD_OP:
154        case AML_DWORD_OP:
155        case AML_QWORD_OP:
156
157            /* The +1/-1 is to handle the integer size prefix (opcode) */
158
159            LsEmitOffsetTableEntry (FileId, Node,
160                (Gbl_CurrentAmlOffset + OffsetOfOpcode + 1),
161                (Op->Asl.FinalAmlLength - 1), Op->Asl.ParseOpName,
162                Op->Asl.Value.Integer, (UINT8) Op->Asl.AmlOpcode);
163            break;
164
165        default:
166            break;
167        }
168
169        Gbl_CurrentAmlOffset += Length;
170        return (AE_OK);
171    }
172
173    /* OperationRegion (NameString, RegionSpace, RegionOffset, RegionLength) */
174
175    else if (Op->Asl.AmlOpcode == AML_REGION_OP)
176    {
177        Length = Op->Asl.FinalAmlLength;
178
179        /* Get the name/namepath node */
180
181        AddressOp = Op->Asl.Child;
182        OffsetOfOpcode = Length + AddressOp->Asl.FinalAmlLength + 1;
183
184        /* Get the SpaceId node, then the Offset (address) node */
185
186        AddressOp = AddressOp->Asl.Next;
187        AddressOp = AddressOp->Asl.Next;
188
189        switch (AddressOp->Asl.AmlOpcode)
190        {
191        /*
192         * We are only interested in integer constants that can be changed
193         * at boot time. Note, the One/Ones/Zero opcodes are considered
194         * non-changeable, so we ignore them here.
195         */
196        case AML_BYTE_OP:
197        case AML_WORD_OP:
198        case AML_DWORD_OP:
199        case AML_QWORD_OP:
200
201            /* The +1/-1 is to handle the integer size prefix (opcode) */
202
203            LsEmitOffsetTableEntry (FileId, Node,
204                (Gbl_CurrentAmlOffset + OffsetOfOpcode + 1),
205                (AddressOp->Asl.FinalAmlLength - 1), Op->Asl.ParseOpName,
206                AddressOp->Asl.Value.Integer, (UINT8) AddressOp->Asl.AmlOpcode);
207
208            Gbl_CurrentAmlOffset += Length;
209            return (AE_OK);
210
211        default:
212            break;
213        }
214    }
215
216    Gbl_CurrentAmlOffset += Op->Asl.FinalAmlLength;
217    return (AE_OK);
218}
219
220
221/*******************************************************************************
222 *
223 * FUNCTION:    LsEmitOffsetTableEntry
224 *
225 * PARAMETERS:  FileId          - ID of current listing file
226 *              Node            - Namespace node associated with the name
227 *              Offset          - Offset of the value within the AML table
228 *              Length          - Length in bytes of the value
229 *              OpName          - Name of the AML opcode
230 *              Value           - Current value of the AML field
231 *              AmlOpcode       - Opcode associated with the field
232 *
233 * RETURN:      None
234 *
235 * DESCRIPTION: Emit a line of the offset table (-so option)
236 *
237 ******************************************************************************/
238
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