xref: /freebsd/sys/contrib/dev/acpica/compiler/asloffset.c (revision b7579f77d18196a58ff700756c84dc9a302a7f67)
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 
56 static void
57 LsEmitOffsetTableEntry (
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 
87 ACPI_STATUS
88 LsAmlOffsetWalk (
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 
239 static void
240 LsEmitOffsetTableEntry (
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 
291 void
292 LsDoOffsetTableHeader (
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 
318 void
319 LsDoOffsetTableFooter (
320     UINT32                  FileId)
321 {
322 
323     FlPrintFile (FileId,
324         "    {0,0,0,0} /* Table terminator */\n};\n\n");
325     Gbl_CurrentAmlOffset = 0;
326 }
327