asloffset.c revision 250838
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    char                    *OpName,
62249109Sjkim    UINT64                  Value,
63249109Sjkim    UINT8                   AmlOpcode);
64249109Sjkim
65249109Sjkim
66249109Sjkim/*******************************************************************************
67249109Sjkim *
68249109Sjkim * FUNCTION:    LsAmlOffsetWalk
69249109Sjkim *
70249109Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
71249109Sjkim *
72249109Sjkim * RETURN:      Status
73249109Sjkim *
74249109Sjkim * DESCRIPTION: Process one node during a offset table file generation.
75249109Sjkim *
76249109Sjkim * Three types of objects are currently emitted to the offset table:
77249109Sjkim *   1) Tagged (named) resource descriptors
78249109Sjkim *   2) Named integer objects with constant integer values
79250838Sjkim *   3) Named package objects
80250838Sjkim *   4) Operation Regions that have constant Offset (address) parameters
81250838Sjkim *   5) Control methods
82249109Sjkim *
83249109Sjkim * The offset table allows the BIOS to dynamically update the values of these
84249109Sjkim * objects at boot time.
85249109Sjkim *
86249109Sjkim ******************************************************************************/
87249109Sjkim
88249109SjkimACPI_STATUS
89249109SjkimLsAmlOffsetWalk (
90249109Sjkim    ACPI_PARSE_OBJECT       *Op,
91249109Sjkim    UINT32                  Level,
92249109Sjkim    void                    *Context)
93249109Sjkim{
94249109Sjkim    UINT32                  FileId = (UINT32) ACPI_TO_INTEGER (Context);
95249109Sjkim    ACPI_NAMESPACE_NODE     *Node;
96249109Sjkim    UINT32                  Length;
97249109Sjkim    UINT32                  OffsetOfOpcode;
98250838Sjkim    ACPI_PARSE_OBJECT       *NextOp;
99249109Sjkim
100249109Sjkim
101249109Sjkim    /* Ignore actual data blocks for resource descriptors */
102249109Sjkim
103249109Sjkim    if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA)
104249109Sjkim    {
105249109Sjkim        return (AE_OK); /* Do NOT update the global AML offset */
106249109Sjkim    }
107249109Sjkim
108249109Sjkim    /* We are only interested in named objects (have a namespace node) */
109249109Sjkim
110249109Sjkim    Node = Op->Asl.Node;
111249109Sjkim    if (!Node)
112249109Sjkim    {
113249109Sjkim        Gbl_CurrentAmlOffset += Op->Asl.FinalAmlLength;
114249109Sjkim        return (AE_OK);
115249109Sjkim    }
116249109Sjkim
117249109Sjkim    /* Named resource descriptor (has a descriptor tag) */
118249109Sjkim
119249109Sjkim    if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE) &&
120249109Sjkim        (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
121249109Sjkim    {
122249109Sjkim        LsEmitOffsetTableEntry (FileId, Node, Gbl_CurrentAmlOffset,
123250838Sjkim            Op->Asl.ParseOpName, 0, Op->Asl.Extra);
124250838Sjkim        Gbl_CurrentAmlOffset += Op->Asl.FinalAmlLength;
125250838Sjkim        return (AE_OK);
126249109Sjkim    }
127249109Sjkim
128250838Sjkim    switch (Op->Asl.AmlOpcode)
129250838Sjkim    {
130250838Sjkim    case AML_NAME_OP:
131249109Sjkim
132250838Sjkim        /* Named object -- Name (NameString, DataRefObject) */
133250838Sjkim
134249109Sjkim        if (!Op->Asl.Child)
135249109Sjkim        {
136249109Sjkim            FlPrintFile (FileId, "%s NO CHILD!\n", MsgBuffer);
137249109Sjkim            return (AE_OK);
138249109Sjkim        }
139249109Sjkim
140249109Sjkim        Length = Op->Asl.FinalAmlLength;
141249109Sjkim
142249109Sjkim        /* Get to the NameSeg/NamePath Op (and length of the name) */
143249109Sjkim
144249109Sjkim        Op = Op->Asl.Child;
145249109Sjkim        OffsetOfOpcode = Length + Op->Asl.FinalAmlLength;
146249109Sjkim
147249109Sjkim        /* Get actual value associated with the name */
148249109Sjkim
149249109Sjkim        Op = Op->Asl.Next;
150249109Sjkim        switch (Op->Asl.AmlOpcode)
151249109Sjkim        {
152249109Sjkim        /*
153249109Sjkim         * We are only interested in integer constants that can be changed
154249109Sjkim         * at boot time. Note, the One/Ones/Zero opcodes are considered
155249109Sjkim         * non-changeable, so we ignore them here.
156249109Sjkim         */
157249109Sjkim        case AML_BYTE_OP:
158249109Sjkim        case AML_WORD_OP:
159249109Sjkim        case AML_DWORD_OP:
160249109Sjkim        case AML_QWORD_OP:
161249109Sjkim
162250838Sjkim            /* The +1 is to handle the integer size prefix (opcode) */
163249109Sjkim
164249109Sjkim            LsEmitOffsetTableEntry (FileId, Node,
165249109Sjkim                (Gbl_CurrentAmlOffset + OffsetOfOpcode + 1),
166250838Sjkim                Op->Asl.ParseOpName, Op->Asl.Value.Integer,
167250838Sjkim                (UINT8) Op->Asl.AmlOpcode);
168249109Sjkim            break;
169249109Sjkim
170250838Sjkim        case AML_PACKAGE_OP:
171250838Sjkim        case AML_VAR_PACKAGE_OP:
172250838Sjkim
173250838Sjkim            NextOp = Op->Asl.Child;
174250838Sjkim
175250838Sjkim            LsEmitOffsetTableEntry (FileId, Node,
176250838Sjkim                (Gbl_CurrentAmlOffset + OffsetOfOpcode),
177250838Sjkim                Op->Asl.ParseOpName,
178250838Sjkim                NextOp->Asl.Value.Integer,
179250838Sjkim                (UINT8) Op->Asl.AmlOpcode);
180249109Sjkim            break;
181250838Sjkim
182250838Sjkim         default:
183250838Sjkim             break;
184249109Sjkim        }
185249109Sjkim
186249109Sjkim        Gbl_CurrentAmlOffset += Length;
187249109Sjkim        return (AE_OK);
188249109Sjkim
189250838Sjkim    case AML_REGION_OP:
190249109Sjkim
191250838Sjkim        /* OperationRegion (NameString, RegionSpace, RegionOffset, RegionLength) */
192250838Sjkim
193249109Sjkim        Length = Op->Asl.FinalAmlLength;
194249109Sjkim
195249109Sjkim        /* Get the name/namepath node */
196249109Sjkim
197250838Sjkim        NextOp = Op->Asl.Child;
198250838Sjkim        OffsetOfOpcode = Length + NextOp->Asl.FinalAmlLength + 1;
199249109Sjkim
200249109Sjkim        /* Get the SpaceId node, then the Offset (address) node */
201249109Sjkim
202250838Sjkim        NextOp = NextOp->Asl.Next;
203250838Sjkim        NextOp = NextOp->Asl.Next;
204249109Sjkim
205250838Sjkim        switch (NextOp->Asl.AmlOpcode)
206249109Sjkim        {
207249109Sjkim        /*
208249109Sjkim         * We are only interested in integer constants that can be changed
209249109Sjkim         * at boot time. Note, the One/Ones/Zero opcodes are considered
210249109Sjkim         * non-changeable, so we ignore them here.
211249109Sjkim         */
212249109Sjkim        case AML_BYTE_OP:
213249109Sjkim        case AML_WORD_OP:
214249109Sjkim        case AML_DWORD_OP:
215249109Sjkim        case AML_QWORD_OP:
216249109Sjkim
217249109Sjkim            LsEmitOffsetTableEntry (FileId, Node,
218249109Sjkim                (Gbl_CurrentAmlOffset + OffsetOfOpcode + 1),
219250838Sjkim                Op->Asl.ParseOpName, NextOp->Asl.Value.Integer,
220250838Sjkim                (UINT8) NextOp->Asl.AmlOpcode);
221249109Sjkim
222249109Sjkim            Gbl_CurrentAmlOffset += Length;
223249109Sjkim            return (AE_OK);
224249109Sjkim
225249109Sjkim        default:
226249109Sjkim            break;
227249109Sjkim        }
228250838Sjkim        break;
229250838Sjkim
230250838Sjkim    case AML_METHOD_OP:
231250838Sjkim
232250838Sjkim        /* Method (Namepath, ...) */
233250838Sjkim
234250838Sjkim        Length = Op->Asl.FinalAmlLength;
235250838Sjkim
236250838Sjkim        /* Get the NameSeg/NamePath Op */
237250838Sjkim
238250838Sjkim        NextOp = Op->Asl.Child;
239250838Sjkim
240250838Sjkim        /* Point to the *last* nameseg in the namepath */
241250838Sjkim
242250838Sjkim        OffsetOfOpcode = NextOp->Asl.FinalAmlLength - ACPI_NAME_SIZE;
243250838Sjkim
244250838Sjkim        LsEmitOffsetTableEntry (FileId, Node,
245250838Sjkim            (Gbl_CurrentAmlOffset + OffsetOfOpcode + Length),
246250838Sjkim            Op->Asl.ParseOpName,
247250838Sjkim            *((UINT32 *) &NextOp->Asl.Value.Buffer[OffsetOfOpcode]),
248250838Sjkim            (UINT8) Op->Asl.AmlOpcode);
249250838Sjkim        break;
250250838Sjkim
251250838Sjkim    default:
252250838Sjkim        break;
253249109Sjkim    }
254249109Sjkim
255249109Sjkim    Gbl_CurrentAmlOffset += Op->Asl.FinalAmlLength;
256249109Sjkim    return (AE_OK);
257249109Sjkim}
258249109Sjkim
259249109Sjkim
260249109Sjkim/*******************************************************************************
261249109Sjkim *
262249109Sjkim * FUNCTION:    LsEmitOffsetTableEntry
263249109Sjkim *
264249109Sjkim * PARAMETERS:  FileId          - ID of current listing file
265249109Sjkim *              Node            - Namespace node associated with the name
266249109Sjkim *              Offset          - Offset of the value within the AML table
267249109Sjkim *              OpName          - Name of the AML opcode
268249109Sjkim *              Value           - Current value of the AML field
269249109Sjkim *              AmlOpcode       - Opcode associated with the field
270249109Sjkim *
271249109Sjkim * RETURN:      None
272249109Sjkim *
273249109Sjkim * DESCRIPTION: Emit a line of the offset table (-so option)
274249109Sjkim *
275249109Sjkim ******************************************************************************/
276249109Sjkim
277249109Sjkimstatic void
278249109SjkimLsEmitOffsetTableEntry (
279249109Sjkim    UINT32                  FileId,
280249109Sjkim    ACPI_NAMESPACE_NODE     *Node,
281249109Sjkim    UINT32                  Offset,
282249109Sjkim    char                    *OpName,
283249109Sjkim    UINT64                  Value,
284249109Sjkim    UINT8                   AmlOpcode)
285249109Sjkim{
286249109Sjkim    ACPI_BUFFER             TargetPath;
287249109Sjkim    ACPI_STATUS             Status;
288249109Sjkim
289249109Sjkim
290249109Sjkim    /* Get the full pathname to the namespace node */
291249109Sjkim
292249109Sjkim    TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
293249109Sjkim    Status = AcpiNsHandleToPathname (Node, &TargetPath);
294249109Sjkim    if (ACPI_FAILURE (Status))
295249109Sjkim    {
296249109Sjkim        return;
297249109Sjkim    }
298249109Sjkim
299249109Sjkim    /* [1] - Skip the opening backslash for the path */
300249109Sjkim
301249109Sjkim    strcpy (MsgBuffer, "\"");
302249109Sjkim    strcat (MsgBuffer, &((char *) TargetPath.Pointer)[1]);
303249109Sjkim    strcat (MsgBuffer, "\",");
304249109Sjkim    ACPI_FREE (TargetPath.Pointer);
305249109Sjkim
306249109Sjkim    /*
307249109Sjkim     * Max offset is 4G, constrained by 32-bit ACPI table length.
308249109Sjkim     * Max Length for Integers is 8 bytes.
309249109Sjkim     */
310249109Sjkim    FlPrintFile (FileId,
311249109Sjkim        "    {%-29s 0x%8.8X, 0x%2.2X, 0x%8.8X%8.8X}, /* %s */\n",
312249109Sjkim        MsgBuffer, Offset, AmlOpcode, ACPI_FORMAT_UINT64 (Value), OpName);
313249109Sjkim}
314249109Sjkim
315249109Sjkim
316249109Sjkim/*******************************************************************************
317249109Sjkim *
318249109Sjkim * FUNCTION:    LsDoOffsetTableHeader, LsDoOffsetTableFooter
319249109Sjkim *
320249109Sjkim * PARAMETERS:  FileId          - ID of current listing file
321249109Sjkim *
322249109Sjkim * RETURN:      None
323249109Sjkim *
324249109Sjkim * DESCRIPTION: Header and footer for the offset table file.
325249109Sjkim *
326249109Sjkim ******************************************************************************/
327249109Sjkim
328249109Sjkimvoid
329249109SjkimLsDoOffsetTableHeader (
330249109Sjkim    UINT32                  FileId)
331249109Sjkim{
332249109Sjkim
333249109Sjkim    FlPrintFile (FileId,
334249109Sjkim        "#ifndef __AML_OFFSET_TABLE_H\n"
335249109Sjkim        "#define __AML_OFFSET_TABLE_H\n\n");
336249109Sjkim
337249109Sjkim    FlPrintFile (FileId, "typedef struct {\n"
338249109Sjkim        "    char                   *Pathname;\n"
339249109Sjkim        "    unsigned long          Offset;\n"
340250838Sjkim        "    unsigned char          Opcode;\n"
341250838Sjkim        "    unsigned long long     Value;\n"
342249109Sjkim        "} AML_OFFSET_TABLE_ENTRY;\n\n");
343249109Sjkim
344249109Sjkim    FlPrintFile (FileId,
345249109Sjkim        "#endif /* __AML_OFFSET_TABLE_H */\n\n");
346249109Sjkim
347249109Sjkim    FlPrintFile (FileId,
348250838Sjkim        "/*\n"
349250838Sjkim        " * Information about supported object types:\n"
350250838Sjkim        " *\n"
351250838Sjkim        " * Integers:\n"
352250838Sjkim        " *    Offset points to the actual integer data\n"
353250838Sjkim        " *    Opcode is the integer prefix, indicates length of the data\n"
354250838Sjkim        " *    Value is the existing value in the AML\n"
355250838Sjkim        " *\n"
356250838Sjkim        " * Packages:\n"
357250838Sjkim        " *    Offset points to the package opcode\n"
358250838Sjkim        " *    Opcode is the package or var_package opcode\n"
359250838Sjkim        " *    Value is the package element cound\n"
360250838Sjkim        " *\n"
361250838Sjkim        " * Operation Regions:\n"
362250838Sjkim        " *    Offset points to the region address data\n"
363250838Sjkim        " *    Opcode is the address integer prefix, indicates length of the data\n"
364250838Sjkim        " *    Value is the existing address value in the AML\n"
365250838Sjkim        " *\n"
366250838Sjkim        " * Control Methods:\n"
367250838Sjkim        " *    Offset points to the first byte of the namepath\n"
368250838Sjkim        " *\n"
369250838Sjkim        " * Resource Descriptors:\n"
370250838Sjkim        " *    Offset points to the start of the descriptor\n"
371250838Sjkim        " *    Opcode is the descriptor type\n"
372250838Sjkim        " */\n");
373250838Sjkim
374250838Sjkim    FlPrintFile (FileId,
375249109Sjkim        "AML_OFFSET_TABLE_ENTRY   %s_%s_OffsetTable[] =\n{\n",
376249109Sjkim        Gbl_TableSignature, Gbl_TableId);
377249109Sjkim}
378249109Sjkim
379249109Sjkim
380249109Sjkimvoid
381249109SjkimLsDoOffsetTableFooter (
382249109Sjkim    UINT32                  FileId)
383249109Sjkim{
384249109Sjkim
385249109Sjkim    FlPrintFile (FileId,
386249109Sjkim        "    {0,0,0,0} /* Table terminator */\n};\n\n");
387249109Sjkim    Gbl_CurrentAmlOffset = 0;
388249109Sjkim}
389