1 /****************************************************************************** 2 * 3 * Module Name: exstore - AML Interpreter object store support 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 #define __EXSTORE_C__ 45 46 #include <contrib/dev/acpica/include/acpi.h> 47 #include <contrib/dev/acpica/include/accommon.h> 48 #include <contrib/dev/acpica/include/acdispat.h> 49 #include <contrib/dev/acpica/include/acinterp.h> 50 #include <contrib/dev/acpica/include/amlcode.h> 51 #include <contrib/dev/acpica/include/acnamesp.h> 52 53 54 #define _COMPONENT ACPI_EXECUTER 55 ACPI_MODULE_NAME ("exstore") 56 57 /* Local prototypes */ 58 59 static ACPI_STATUS 60 AcpiExStoreObjectToIndex ( 61 ACPI_OPERAND_OBJECT *ValDesc, 62 ACPI_OPERAND_OBJECT *DestDesc, 63 ACPI_WALK_STATE *WalkState); 64 65 66 /******************************************************************************* 67 * 68 * FUNCTION: AcpiExStore 69 * 70 * PARAMETERS: *SourceDesc - Value to be stored 71 * *DestDesc - Where to store it. Must be an NS node 72 * or ACPI_OPERAND_OBJECT of type 73 * Reference; 74 * WalkState - Current walk state 75 * 76 * RETURN: Status 77 * 78 * DESCRIPTION: Store the value described by SourceDesc into the location 79 * described by DestDesc. Called by various interpreter 80 * functions to store the result of an operation into 81 * the destination operand -- not just simply the actual "Store" 82 * ASL operator. 83 * 84 ******************************************************************************/ 85 86 ACPI_STATUS 87 AcpiExStore ( 88 ACPI_OPERAND_OBJECT *SourceDesc, 89 ACPI_OPERAND_OBJECT *DestDesc, 90 ACPI_WALK_STATE *WalkState) 91 { 92 ACPI_STATUS Status = AE_OK; 93 ACPI_OPERAND_OBJECT *RefDesc = DestDesc; 94 95 96 ACPI_FUNCTION_TRACE_PTR (ExStore, DestDesc); 97 98 99 /* Validate parameters */ 100 101 if (!SourceDesc || !DestDesc) 102 { 103 ACPI_ERROR ((AE_INFO, "Null parameter")); 104 return_ACPI_STATUS (AE_AML_NO_OPERAND); 105 } 106 107 /* DestDesc can be either a namespace node or an ACPI object */ 108 109 if (ACPI_GET_DESCRIPTOR_TYPE (DestDesc) == ACPI_DESC_TYPE_NAMED) 110 { 111 /* 112 * Dest is a namespace node, 113 * Storing an object into a Named node. 114 */ 115 Status = AcpiExStoreObjectToNode (SourceDesc, 116 (ACPI_NAMESPACE_NODE *) DestDesc, WalkState, 117 ACPI_IMPLICIT_CONVERSION); 118 119 return_ACPI_STATUS (Status); 120 } 121 122 /* Destination object must be a Reference or a Constant object */ 123 124 switch (DestDesc->Common.Type) 125 { 126 case ACPI_TYPE_LOCAL_REFERENCE: 127 128 break; 129 130 case ACPI_TYPE_INTEGER: 131 132 /* Allow stores to Constants -- a Noop as per ACPI spec */ 133 134 if (DestDesc->Common.Flags & AOPOBJ_AML_CONSTANT) 135 { 136 return_ACPI_STATUS (AE_OK); 137 } 138 139 /*lint -fallthrough */ 140 141 default: 142 143 /* Destination is not a Reference object */ 144 145 ACPI_ERROR ((AE_INFO, 146 "Target is not a Reference or Constant object - %s [%p]", 147 AcpiUtGetObjectTypeName (DestDesc), DestDesc)); 148 149 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 150 } 151 152 /* 153 * Examine the Reference class. These cases are handled: 154 * 155 * 1) Store to Name (Change the object associated with a name) 156 * 2) Store to an indexed area of a Buffer or Package 157 * 3) Store to a Method Local or Arg 158 * 4) Store to the debug object 159 */ 160 switch (RefDesc->Reference.Class) 161 { 162 case ACPI_REFCLASS_REFOF: 163 164 /* Storing an object into a Name "container" */ 165 166 Status = AcpiExStoreObjectToNode (SourceDesc, 167 RefDesc->Reference.Object, 168 WalkState, ACPI_IMPLICIT_CONVERSION); 169 break; 170 171 case ACPI_REFCLASS_INDEX: 172 173 /* Storing to an Index (pointer into a packager or buffer) */ 174 175 Status = AcpiExStoreObjectToIndex (SourceDesc, RefDesc, WalkState); 176 break; 177 178 case ACPI_REFCLASS_LOCAL: 179 case ACPI_REFCLASS_ARG: 180 181 /* Store to a method local/arg */ 182 183 Status = AcpiDsStoreObjectToLocal (RefDesc->Reference.Class, 184 RefDesc->Reference.Value, SourceDesc, WalkState); 185 break; 186 187 case ACPI_REFCLASS_DEBUG: 188 /* 189 * Storing to the Debug object causes the value stored to be 190 * displayed and otherwise has no effect -- see ACPI Specification 191 */ 192 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 193 "**** Write to Debug Object: Object %p %s ****:\n\n", 194 SourceDesc, AcpiUtGetObjectTypeName (SourceDesc))); 195 196 ACPI_DEBUG_OBJECT (SourceDesc, 0, 0); 197 break; 198 199 default: 200 201 ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X", 202 RefDesc->Reference.Class)); 203 ACPI_DUMP_ENTRY (RefDesc, ACPI_LV_INFO); 204 205 Status = AE_AML_INTERNAL; 206 break; 207 } 208 209 return_ACPI_STATUS (Status); 210 } 211 212 213 /******************************************************************************* 214 * 215 * FUNCTION: AcpiExStoreObjectToIndex 216 * 217 * PARAMETERS: *SourceDesc - Value to be stored 218 * *DestDesc - Named object to receive the value 219 * WalkState - Current walk state 220 * 221 * RETURN: Status 222 * 223 * DESCRIPTION: Store the object to indexed Buffer or Package element 224 * 225 ******************************************************************************/ 226 227 static ACPI_STATUS 228 AcpiExStoreObjectToIndex ( 229 ACPI_OPERAND_OBJECT *SourceDesc, 230 ACPI_OPERAND_OBJECT *IndexDesc, 231 ACPI_WALK_STATE *WalkState) 232 { 233 ACPI_STATUS Status = AE_OK; 234 ACPI_OPERAND_OBJECT *ObjDesc; 235 ACPI_OPERAND_OBJECT *NewDesc; 236 UINT8 Value = 0; 237 UINT32 i; 238 239 240 ACPI_FUNCTION_TRACE (ExStoreObjectToIndex); 241 242 243 /* 244 * Destination must be a reference pointer, and 245 * must point to either a buffer or a package 246 */ 247 switch (IndexDesc->Reference.TargetType) 248 { 249 case ACPI_TYPE_PACKAGE: 250 /* 251 * Storing to a package element. Copy the object and replace 252 * any existing object with the new object. No implicit 253 * conversion is performed. 254 * 255 * The object at *(IndexDesc->Reference.Where) is the 256 * element within the package that is to be modified. 257 * The parent package object is at IndexDesc->Reference.Object 258 */ 259 ObjDesc = *(IndexDesc->Reference.Where); 260 261 if (SourceDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE && 262 SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE) 263 { 264 /* This is a DDBHandle, just add a reference to it */ 265 266 AcpiUtAddReference (SourceDesc); 267 NewDesc = SourceDesc; 268 } 269 else 270 { 271 /* Normal object, copy it */ 272 273 Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState); 274 if (ACPI_FAILURE (Status)) 275 { 276 return_ACPI_STATUS (Status); 277 } 278 } 279 280 if (ObjDesc) 281 { 282 /* Decrement reference count by the ref count of the parent package */ 283 284 for (i = 0; 285 i < ((ACPI_OPERAND_OBJECT *) 286 IndexDesc->Reference.Object)->Common.ReferenceCount; 287 i++) 288 { 289 AcpiUtRemoveReference (ObjDesc); 290 } 291 } 292 293 *(IndexDesc->Reference.Where) = NewDesc; 294 295 /* Increment ref count by the ref count of the parent package-1 */ 296 297 for (i = 1; 298 i < ((ACPI_OPERAND_OBJECT *) 299 IndexDesc->Reference.Object)->Common.ReferenceCount; 300 i++) 301 { 302 AcpiUtAddReference (NewDesc); 303 } 304 305 break; 306 307 case ACPI_TYPE_BUFFER_FIELD: 308 /* 309 * Store into a Buffer or String (not actually a real BufferField) 310 * at a location defined by an Index. 311 * 312 * The first 8-bit element of the source object is written to the 313 * 8-bit Buffer location defined by the Index destination object, 314 * according to the ACPI 2.0 specification. 315 */ 316 317 /* 318 * Make sure the target is a Buffer or String. An error should 319 * not happen here, since the ReferenceObject was constructed 320 * by the INDEX_OP code. 321 */ 322 ObjDesc = IndexDesc->Reference.Object; 323 if ((ObjDesc->Common.Type != ACPI_TYPE_BUFFER) && 324 (ObjDesc->Common.Type != ACPI_TYPE_STRING)) 325 { 326 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 327 } 328 329 /* 330 * The assignment of the individual elements will be slightly 331 * different for each source type. 332 */ 333 switch (SourceDesc->Common.Type) 334 { 335 case ACPI_TYPE_INTEGER: 336 337 /* Use the least-significant byte of the integer */ 338 339 Value = (UINT8) (SourceDesc->Integer.Value); 340 break; 341 342 case ACPI_TYPE_BUFFER: 343 case ACPI_TYPE_STRING: 344 345 /* Note: Takes advantage of common string/buffer fields */ 346 347 Value = SourceDesc->Buffer.Pointer[0]; 348 break; 349 350 default: 351 352 /* All other types are invalid */ 353 354 ACPI_ERROR ((AE_INFO, 355 "Source must be Integer/Buffer/String type, not %s", 356 AcpiUtGetObjectTypeName (SourceDesc))); 357 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 358 } 359 360 /* Store the source value into the target buffer byte */ 361 362 ObjDesc->Buffer.Pointer[IndexDesc->Reference.Value] = Value; 363 break; 364 365 default: 366 ACPI_ERROR ((AE_INFO, 367 "Target is not a Package or BufferField")); 368 Status = AE_AML_OPERAND_TYPE; 369 break; 370 } 371 372 return_ACPI_STATUS (Status); 373 } 374 375 376 /******************************************************************************* 377 * 378 * FUNCTION: AcpiExStoreObjectToNode 379 * 380 * PARAMETERS: SourceDesc - Value to be stored 381 * Node - Named object to receive the value 382 * WalkState - Current walk state 383 * ImplicitConversion - Perform implicit conversion (yes/no) 384 * 385 * RETURN: Status 386 * 387 * DESCRIPTION: Store the object to the named object. 388 * 389 * The Assignment of an object to a named object is handled here 390 * The value passed in will replace the current value (if any) 391 * with the input value. 392 * 393 * When storing into an object the data is converted to the 394 * target object type then stored in the object. This means 395 * that the target object type (for an initialized target) will 396 * not be changed by a store operation. 397 * 398 * Assumes parameters are already validated. 399 * 400 ******************************************************************************/ 401 402 ACPI_STATUS 403 AcpiExStoreObjectToNode ( 404 ACPI_OPERAND_OBJECT *SourceDesc, 405 ACPI_NAMESPACE_NODE *Node, 406 ACPI_WALK_STATE *WalkState, 407 UINT8 ImplicitConversion) 408 { 409 ACPI_STATUS Status = AE_OK; 410 ACPI_OPERAND_OBJECT *TargetDesc; 411 ACPI_OPERAND_OBJECT *NewDesc; 412 ACPI_OBJECT_TYPE TargetType; 413 414 415 ACPI_FUNCTION_TRACE_PTR (ExStoreObjectToNode, SourceDesc); 416 417 418 /* Get current type of the node, and object attached to Node */ 419 420 TargetType = AcpiNsGetType (Node); 421 TargetDesc = AcpiNsGetAttachedObject (Node); 422 423 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", 424 SourceDesc, AcpiUtGetObjectTypeName (SourceDesc), 425 Node, AcpiUtGetTypeName (TargetType))); 426 427 /* 428 * Resolve the source object to an actual value 429 * (If it is a reference object) 430 */ 431 Status = AcpiExResolveObject (&SourceDesc, TargetType, WalkState); 432 if (ACPI_FAILURE (Status)) 433 { 434 return_ACPI_STATUS (Status); 435 } 436 437 /* If no implicit conversion, drop into the default case below */ 438 439 if ((!ImplicitConversion) || 440 ((WalkState->Opcode == AML_COPY_OP) && 441 (TargetType != ACPI_TYPE_LOCAL_REGION_FIELD) && 442 (TargetType != ACPI_TYPE_LOCAL_BANK_FIELD) && 443 (TargetType != ACPI_TYPE_LOCAL_INDEX_FIELD))) 444 { 445 /* 446 * Force execution of default (no implicit conversion). Note: 447 * CopyObject does not perform an implicit conversion, as per the ACPI 448 * spec -- except in case of region/bank/index fields -- because these 449 * objects must retain their original type permanently. 450 */ 451 TargetType = ACPI_TYPE_ANY; 452 } 453 454 /* Do the actual store operation */ 455 456 switch (TargetType) 457 { 458 case ACPI_TYPE_BUFFER_FIELD: 459 case ACPI_TYPE_LOCAL_REGION_FIELD: 460 case ACPI_TYPE_LOCAL_BANK_FIELD: 461 case ACPI_TYPE_LOCAL_INDEX_FIELD: 462 463 /* For fields, copy the source data to the target field. */ 464 465 Status = AcpiExWriteDataToField (SourceDesc, TargetDesc, 466 &WalkState->ResultObj); 467 break; 468 469 case ACPI_TYPE_INTEGER: 470 case ACPI_TYPE_STRING: 471 case ACPI_TYPE_BUFFER: 472 /* 473 * These target types are all of type Integer/String/Buffer, and 474 * therefore support implicit conversion before the store. 475 * 476 * Copy and/or convert the source object to a new target object 477 */ 478 Status = AcpiExStoreObjectToObject (SourceDesc, TargetDesc, 479 &NewDesc, WalkState); 480 if (ACPI_FAILURE (Status)) 481 { 482 return_ACPI_STATUS (Status); 483 } 484 485 if (NewDesc != TargetDesc) 486 { 487 /* 488 * Store the new NewDesc as the new value of the Name, and set 489 * the Name's type to that of the value being stored in it. 490 * SourceDesc reference count is incremented by AttachObject. 491 * 492 * Note: This may change the type of the node if an explicit store 493 * has been performed such that the node/object type has been 494 * changed. 495 */ 496 Status = AcpiNsAttachObject (Node, NewDesc, NewDesc->Common.Type); 497 498 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 499 "Store %s into %s via Convert/Attach\n", 500 AcpiUtGetObjectTypeName (SourceDesc), 501 AcpiUtGetObjectTypeName (NewDesc))); 502 } 503 break; 504 505 default: 506 507 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 508 "Storing [%s] (%p) directly into node [%s] (%p)" 509 " with no implicit conversion\n", 510 AcpiUtGetObjectTypeName (SourceDesc), SourceDesc, 511 AcpiUtGetObjectTypeName (TargetDesc), Node)); 512 513 /* 514 * No conversions for all other types. Directly store a copy of 515 * the source object. NOTE: This is a departure from the ACPI 516 * spec, which states "If conversion is impossible, abort the 517 * running control method". 518 * 519 * This code implements "If conversion is impossible, treat the 520 * Store operation as a CopyObject". 521 */ 522 Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState); 523 if (ACPI_FAILURE (Status)) 524 { 525 return_ACPI_STATUS (Status); 526 } 527 528 Status = AcpiNsAttachObject (Node, NewDesc, NewDesc->Common.Type); 529 AcpiUtRemoveReference (NewDesc); 530 break; 531 } 532 533 return_ACPI_STATUS (Status); 534 } 535