1 /****************************************************************************** 2 * 3 * Module Name: aslmaputils - Utilities for the resource descriptor/device maps 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, 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/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 #include <contrib/dev/acpica/include/acapps.h> 47 #include <contrib/dev/acpica/compiler/aslcompiler.h> 48 #include "aslcompiler.y.h" 49 #include <contrib/dev/acpica/include/acinterp.h> 50 #include <contrib/dev/acpica/include/acnamesp.h> 51 #include <contrib/dev/acpica/include/amlcode.h> 52 53 /* This module used for application-level code only */ 54 55 #define _COMPONENT ACPI_COMPILER 56 ACPI_MODULE_NAME ("aslmaputils") 57 58 59 /******************************************************************************* 60 * 61 * FUNCTION: MpGetHidFromParseTree 62 * 63 * PARAMETERS: HidNode - Node for a _HID object 64 * 65 * RETURN: An _HID string value. Automatically converts _HID integers 66 * to strings. Never NULL. 67 * 68 * DESCRIPTION: Extract a _HID value from the parse tree, not the namespace. 69 * Used when a fully initialized namespace is not available. 70 * 71 ******************************************************************************/ 72 73 char * 74 MpGetHidFromParseTree ( 75 ACPI_NAMESPACE_NODE *HidNode) 76 { 77 ACPI_PARSE_OBJECT *Op; 78 ACPI_PARSE_OBJECT *Arg; 79 char *HidString; 80 81 82 Op = HidNode->Op; 83 if (!Op) 84 { 85 /* Object is not resolved, probably an External */ 86 87 return ("Unresolved Symbol - referenced but not defined in this table"); 88 } 89 90 switch (Op->Asl.ParseOpcode) 91 { 92 case PARSEOP_NAME: 93 94 Arg = Op->Asl.Child; /* Get the NameSeg/NameString node */ 95 Arg = Arg->Asl.Next; /* First peer is the object to be associated with the name */ 96 97 switch (Arg->Asl.ParseOpcode) 98 { 99 case PARSEOP_STRING_LITERAL: 100 101 return (Arg->Asl.Value.String); 102 103 case PARSEOP_INTEGER: 104 105 /* Convert EISAID to a string */ 106 107 HidString = UtStringCacheCalloc (ACPI_EISAID_STRING_SIZE); 108 AcpiExEisaIdToString (HidString, Arg->Asl.Value.Integer); 109 return (HidString); 110 111 default: 112 113 return ("UNKNOWN"); 114 } 115 116 default: 117 return ("-No HID-"); 118 } 119 } 120 121 122 /******************************************************************************* 123 * 124 * FUNCTION: MpGetHidValue 125 * 126 * PARAMETERS: DeviceNode - Node for parent device 127 * 128 * RETURN: An _HID string value. Automatically converts _HID integers 129 * to strings. Never NULL. 130 * 131 * DESCRIPTION: Extract _HID value from within a device scope. Does not 132 * actually execute a method, just gets the string or integer 133 * value for the _HID. 134 * 135 ******************************************************************************/ 136 137 char * 138 MpGetHidValue ( 139 ACPI_NAMESPACE_NODE *DeviceNode) 140 { 141 ACPI_NAMESPACE_NODE *HidNode; 142 char *HidString; 143 ACPI_STATUS Status; 144 145 146 Status = AcpiNsGetNode (DeviceNode, METHOD_NAME__HID, 147 ACPI_NS_NO_UPSEARCH, &HidNode); 148 if (ACPI_FAILURE (Status)) 149 { 150 goto ErrorExit; 151 } 152 153 /* If only partial namespace, get the _HID from the parse tree */ 154 155 if (!HidNode->Object) 156 { 157 return (MpGetHidFromParseTree (HidNode)); 158 } 159 160 /* Handle the different _HID flavors */ 161 162 switch (HidNode->Type) 163 { 164 case ACPI_TYPE_STRING: 165 166 return (HidNode->Object->String.Pointer); 167 168 case ACPI_TYPE_INTEGER: 169 170 /* Convert EISAID to a string */ 171 172 HidString = UtStringCacheCalloc (ACPI_EISAID_STRING_SIZE); 173 AcpiExEisaIdToString (HidString, HidNode->Object->Integer.Value); 174 return (HidString); 175 176 case ACPI_TYPE_METHOD: 177 178 return ("-Method-"); 179 180 default: 181 182 FlPrintFile (ASL_FILE_MAP_OUTPUT, "BAD HID TYPE: %u", HidNode->Type); 183 break; 184 } 185 186 187 ErrorExit: 188 return ("-No HID-"); 189 } 190 191 192 /******************************************************************************* 193 * 194 * FUNCTION: MpGetHidViaNamestring 195 * 196 * PARAMETERS: DeviceName - Namepath for parent device 197 * 198 * RETURN: _HID string. Never NULL. 199 * 200 * DESCRIPTION: Get a _HID value via a device pathname (instead of just simply 201 * a device node.) 202 * 203 ******************************************************************************/ 204 205 char * 206 MpGetHidViaNamestring ( 207 char *DeviceName) 208 { 209 ACPI_NAMESPACE_NODE *DeviceNode; 210 ACPI_STATUS Status; 211 212 213 Status = AcpiNsGetNode (NULL, DeviceName, ACPI_NS_NO_UPSEARCH, 214 &DeviceNode); 215 if (ACPI_FAILURE (Status)) 216 { 217 goto ErrorExit; 218 } 219 220 return (MpGetHidValue (DeviceNode)); 221 222 223 ErrorExit: 224 return ("-No HID-"); 225 } 226 227 228 /******************************************************************************* 229 * 230 * FUNCTION: MpGetParentDeviceHid 231 * 232 * PARAMETERS: Op - Parse Op to be examined 233 * TargetNode - Where the field node is returned 234 * ParentDeviceName - Where the node path is returned 235 * 236 * RETURN: _HID string. Never NULL. 237 * 238 * DESCRIPTION: Find the parent Device or Scope Op, get the full pathname to 239 * the parent, and get the _HID associated with the parent. 240 * 241 ******************************************************************************/ 242 243 char * 244 MpGetParentDeviceHid ( 245 ACPI_PARSE_OBJECT *Op, 246 ACPI_NAMESPACE_NODE **TargetNode, 247 char **ParentDeviceName) 248 { 249 ACPI_NAMESPACE_NODE *DeviceNode; 250 251 252 /* Find parent Device() or Scope() Op */ 253 254 while (Op && 255 (Op->Asl.AmlOpcode != AML_DEVICE_OP) && 256 (Op->Asl.AmlOpcode != AML_SCOPE_OP)) 257 { 258 Op = Op->Asl.Parent; 259 } 260 261 if (!Op) 262 { 263 FlPrintFile (ASL_FILE_MAP_OUTPUT, " No_Parent_Device "); 264 goto ErrorExit; 265 } 266 267 /* Get the full pathname to the device and the _HID */ 268 269 DeviceNode = Op->Asl.Node; 270 if (!DeviceNode) 271 { 272 FlPrintFile (ASL_FILE_MAP_OUTPUT, " No_Device_Node "); 273 goto ErrorExit; 274 } 275 276 *ParentDeviceName = AcpiNsGetExternalPathname (DeviceNode); 277 return (MpGetHidValue (DeviceNode)); 278 279 280 ErrorExit: 281 return ("-No HID-"); 282 } 283 284 285 /******************************************************************************* 286 * 287 * FUNCTION: MpGetDdnValue 288 * 289 * PARAMETERS: DeviceName - Namepath for parent device 290 * 291 * RETURN: _DDN description string. NULL on failure. 292 * 293 * DESCRIPTION: Execute the _DDN method for the device. 294 * 295 ******************************************************************************/ 296 297 char * 298 MpGetDdnValue ( 299 char *DeviceName) 300 { 301 ACPI_NAMESPACE_NODE *DeviceNode; 302 ACPI_NAMESPACE_NODE *DdnNode; 303 ACPI_STATUS Status; 304 305 306 Status = AcpiNsGetNode (NULL, DeviceName, ACPI_NS_NO_UPSEARCH, 307 &DeviceNode); 308 if (ACPI_FAILURE (Status)) 309 { 310 goto ErrorExit; 311 } 312 313 Status = AcpiNsGetNode (DeviceNode, METHOD_NAME__DDN, ACPI_NS_NO_UPSEARCH, 314 &DdnNode); 315 if (ACPI_FAILURE (Status)) 316 { 317 goto ErrorExit; 318 } 319 320 if ((DdnNode->Type != ACPI_TYPE_STRING) || 321 !DdnNode->Object) 322 { 323 goto ErrorExit; 324 } 325 326 return (DdnNode->Object->String.Pointer); 327 328 329 ErrorExit: 330 return (NULL); 331 } 332 333 334 /******************************************************************************* 335 * 336 * FUNCTION: MpGetConnectionInfo 337 * 338 * PARAMETERS: Op - Parse Op to be examined 339 * PinIndex - Index into GPIO PinList 340 * TargetNode - Where the field node is returned 341 * TargetName - Where the node path is returned 342 * 343 * RETURN: A substitute _HID string, indicating that the name is actually 344 * a field. NULL if the Op does not refer to a Connection. 345 * 346 * DESCRIPTION: Get the Field Unit that corresponds to the PinIndex after 347 * a Connection() invocation. 348 * 349 ******************************************************************************/ 350 351 char * 352 MpGetConnectionInfo ( 353 ACPI_PARSE_OBJECT *Op, 354 UINT32 PinIndex, 355 ACPI_NAMESPACE_NODE **TargetNode, 356 char **TargetName) 357 { 358 ACPI_PARSE_OBJECT *NextOp; 359 UINT32 i; 360 361 362 /* 363 * Handle Connection() here. Find the next named FieldUnit. 364 * Note: we look at the ParseOpcode for the compiler, look 365 * at the AmlOpcode for the disassembler. 366 */ 367 if ((Op->Asl.AmlOpcode == AML_INT_CONNECTION_OP) || 368 (Op->Asl.ParseOpcode == PARSEOP_CONNECTION)) 369 { 370 /* Find the correct field unit definition */ 371 372 NextOp = Op; 373 for (i = 0; i <= PinIndex;) 374 { 375 NextOp = NextOp->Asl.Next; 376 while (NextOp && 377 (NextOp->Asl.ParseOpcode != PARSEOP_NAMESEG) && 378 (NextOp->Asl.AmlOpcode != AML_INT_NAMEDFIELD_OP)) 379 { 380 NextOp = NextOp->Asl.Next; 381 } 382 383 if (!NextOp) 384 { 385 return ("UNKNOWN"); 386 } 387 388 /* Add length of this field to the current pin index */ 389 390 if (NextOp->Asl.ParseOpcode == PARSEOP_NAMESEG) 391 { 392 i += (UINT32) NextOp->Asl.Child->Asl.Value.Integer; 393 } 394 else /* AML_INT_NAMEDFIELD_OP */ 395 { 396 i += (UINT32) NextOp->Asl.Value.Integer; 397 } 398 } 399 400 /* Return the node and pathname for the field unit */ 401 402 *TargetNode = NextOp->Asl.Node; 403 *TargetName = AcpiNsGetExternalPathname (*TargetNode); 404 return ("-Field-"); 405 } 406 407 return (NULL); 408 } 409