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