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