1 2 /****************************************************************************** 3 * 4 * Module Name: exstore - AML Interpreter object store support 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2008, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #include <acpi/acpi.h> 46 #include "accommon.h" 47 #include "acdispat.h" 48 #include "acinterp.h" 49 #include "amlcode.h" 50 #include "acnamesp.h" 51 52 #define _COMPONENT ACPI_EXECUTER 53 ACPI_MODULE_NAME("exstore") 54 55 /* Local prototypes */ 56 static void 57 acpi_ex_do_debug_object(union acpi_operand_object *source_desc, 58 u32 level, u32 index); 59 60 static acpi_status 61 acpi_ex_store_object_to_index(union acpi_operand_object *val_desc, 62 union acpi_operand_object *dest_desc, 63 struct acpi_walk_state *walk_state); 64 65 /******************************************************************************* 66 * 67 * FUNCTION: acpi_ex_do_debug_object 68 * 69 * PARAMETERS: source_desc - Value to be stored 70 * Level - Indentation level (used for packages) 71 * Index - Current package element, zero if not pkg 72 * 73 * RETURN: None 74 * 75 * DESCRIPTION: Handles stores to the Debug Object. 76 * 77 ******************************************************************************/ 78 79 static void 80 acpi_ex_do_debug_object(union acpi_operand_object *source_desc, 81 u32 level, u32 index) 82 { 83 u32 i; 84 85 ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); 86 87 /* Print line header as long as we are not in the middle of an object display */ 88 89 if (!((level > 0) && index == 0)) { 90 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", 91 level, " ")); 92 } 93 94 /* Display index for package output only */ 95 96 if (index > 0) { 97 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, 98 "(%.2u) ", index - 1)); 99 } 100 101 if (!source_desc) { 102 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Null Object]\n")); 103 return_VOID; 104 } 105 106 if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { 107 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s ", 108 acpi_ut_get_object_type_name 109 (source_desc))); 110 111 if (!acpi_ut_valid_internal_object(source_desc)) { 112 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, 113 "%p, Invalid Internal Object!\n", 114 source_desc)); 115 return_VOID; 116 } 117 } else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == 118 ACPI_DESC_TYPE_NAMED) { 119 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: %p\n", 120 acpi_ut_get_type_name(((struct 121 acpi_namespace_node 122 *)source_desc)-> 123 type), 124 source_desc)); 125 return_VOID; 126 } else { 127 return_VOID; 128 } 129 130 /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ 131 132 switch (source_desc->common.type) { 133 case ACPI_TYPE_INTEGER: 134 135 /* Output correct integer width */ 136 137 if (acpi_gbl_integer_byte_width == 4) { 138 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n", 139 (u32) source_desc->integer. 140 value)); 141 } else { 142 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, 143 "0x%8.8X%8.8X\n", 144 ACPI_FORMAT_UINT64(source_desc-> 145 integer. 146 value))); 147 } 148 break; 149 150 case ACPI_TYPE_BUFFER: 151 152 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]\n", 153 (u32) source_desc->buffer.length)); 154 ACPI_DUMP_BUFFER(source_desc->buffer.pointer, 155 (source_desc->buffer.length < 156 256) ? source_desc->buffer.length : 256); 157 break; 158 159 case ACPI_TYPE_STRING: 160 161 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n", 162 source_desc->string.length, 163 source_desc->string.pointer)); 164 break; 165 166 case ACPI_TYPE_PACKAGE: 167 168 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, 169 "[Contains 0x%.2X Elements]\n", 170 source_desc->package.count)); 171 172 /* Output the entire contents of the package */ 173 174 for (i = 0; i < source_desc->package.count; i++) { 175 acpi_ex_do_debug_object(source_desc->package. 176 elements[i], level + 4, i + 1); 177 } 178 break; 179 180 case ACPI_TYPE_LOCAL_REFERENCE: 181 182 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s] ", 183 acpi_ut_get_reference_name(source_desc))); 184 185 /* Decode the reference */ 186 187 switch (source_desc->reference.class) { 188 case ACPI_REFCLASS_INDEX: 189 190 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%X\n", 191 source_desc->reference.value)); 192 break; 193 194 case ACPI_REFCLASS_TABLE: 195 196 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, 197 "Table Index 0x%X\n", 198 source_desc->reference.value)); 199 break; 200 201 default: 202 break; 203 } 204 205 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " ")); 206 207 /* Check for valid node first, then valid object */ 208 209 if (source_desc->reference.node) { 210 if (ACPI_GET_DESCRIPTOR_TYPE 211 (source_desc->reference.node) != 212 ACPI_DESC_TYPE_NAMED) { 213 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, 214 " %p - Not a valid namespace node\n", 215 source_desc->reference. 216 node)); 217 } else { 218 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, 219 "Node %p [%4.4s] ", 220 source_desc->reference. 221 node, 222 (source_desc->reference. 223 node)->name.ascii)); 224 225 switch ((source_desc->reference.node)->type) { 226 227 /* These types have no attached object */ 228 229 case ACPI_TYPE_DEVICE: 230 acpi_os_printf("Device\n"); 231 break; 232 233 case ACPI_TYPE_THERMAL: 234 acpi_os_printf("Thermal Zone\n"); 235 break; 236 237 default: 238 acpi_ex_do_debug_object((source_desc-> 239 reference. 240 node)->object, 241 level + 4, 0); 242 break; 243 } 244 } 245 } else if (source_desc->reference.object) { 246 if (ACPI_GET_DESCRIPTOR_TYPE 247 (source_desc->reference.object) == 248 ACPI_DESC_TYPE_NAMED) { 249 acpi_ex_do_debug_object(((struct 250 acpi_namespace_node *) 251 source_desc->reference. 252 object)->object, 253 level + 4, 0); 254 } else { 255 acpi_ex_do_debug_object(source_desc->reference. 256 object, level + 4, 0); 257 } 258 } 259 break; 260 261 default: 262 263 ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p\n", 264 source_desc)); 265 break; 266 } 267 268 ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n")); 269 return_VOID; 270 } 271 272 /******************************************************************************* 273 * 274 * FUNCTION: acpi_ex_store 275 * 276 * PARAMETERS: *source_desc - Value to be stored 277 * *dest_desc - Where to store it. Must be an NS node 278 * or a union acpi_operand_object of type 279 * Reference; 280 * walk_state - Current walk state 281 * 282 * RETURN: Status 283 * 284 * DESCRIPTION: Store the value described by source_desc into the location 285 * described by dest_desc. Called by various interpreter 286 * functions to store the result of an operation into 287 * the destination operand -- not just simply the actual "Store" 288 * ASL operator. 289 * 290 ******************************************************************************/ 291 292 acpi_status 293 acpi_ex_store(union acpi_operand_object *source_desc, 294 union acpi_operand_object *dest_desc, 295 struct acpi_walk_state *walk_state) 296 { 297 acpi_status status = AE_OK; 298 union acpi_operand_object *ref_desc = dest_desc; 299 300 ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc); 301 302 /* Validate parameters */ 303 304 if (!source_desc || !dest_desc) { 305 ACPI_ERROR((AE_INFO, "Null parameter")); 306 return_ACPI_STATUS(AE_AML_NO_OPERAND); 307 } 308 309 /* dest_desc can be either a namespace node or an ACPI object */ 310 311 if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) { 312 /* 313 * Dest is a namespace node, 314 * Storing an object into a Named node. 315 */ 316 status = acpi_ex_store_object_to_node(source_desc, 317 (struct 318 acpi_namespace_node *) 319 dest_desc, walk_state, 320 ACPI_IMPLICIT_CONVERSION); 321 322 return_ACPI_STATUS(status); 323 } 324 325 /* Destination object must be a Reference or a Constant object */ 326 327 switch (dest_desc->common.type) { 328 case ACPI_TYPE_LOCAL_REFERENCE: 329 break; 330 331 case ACPI_TYPE_INTEGER: 332 333 /* Allow stores to Constants -- a Noop as per ACPI spec */ 334 335 if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) { 336 return_ACPI_STATUS(AE_OK); 337 } 338 339 /*lint -fallthrough */ 340 341 default: 342 343 /* Destination is not a Reference object */ 344 345 ACPI_ERROR((AE_INFO, 346 "Target is not a Reference or Constant object - %s [%p]", 347 acpi_ut_get_object_type_name(dest_desc), 348 dest_desc)); 349 350 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 351 } 352 353 /* 354 * Examine the Reference class. These cases are handled: 355 * 356 * 1) Store to Name (Change the object associated with a name) 357 * 2) Store to an indexed area of a Buffer or Package 358 * 3) Store to a Method Local or Arg 359 * 4) Store to the debug object 360 */ 361 switch (ref_desc->reference.class) { 362 case ACPI_REFCLASS_REFOF: 363 364 /* Storing an object into a Name "container" */ 365 366 status = acpi_ex_store_object_to_node(source_desc, 367 ref_desc->reference. 368 object, walk_state, 369 ACPI_IMPLICIT_CONVERSION); 370 break; 371 372 case ACPI_REFCLASS_INDEX: 373 374 /* Storing to an Index (pointer into a packager or buffer) */ 375 376 status = 377 acpi_ex_store_object_to_index(source_desc, ref_desc, 378 walk_state); 379 break; 380 381 case ACPI_REFCLASS_LOCAL: 382 case ACPI_REFCLASS_ARG: 383 384 /* Store to a method local/arg */ 385 386 status = 387 acpi_ds_store_object_to_local(ref_desc->reference.class, 388 ref_desc->reference.value, 389 source_desc, walk_state); 390 break; 391 392 case ACPI_REFCLASS_DEBUG: 393 394 /* 395 * Storing to the Debug object causes the value stored to be 396 * displayed and otherwise has no effect -- see ACPI Specification 397 */ 398 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 399 "**** Write to Debug Object: Object %p %s ****:\n\n", 400 source_desc, 401 acpi_ut_get_object_type_name(source_desc))); 402 403 acpi_ex_do_debug_object(source_desc, 0, 0); 404 break; 405 406 default: 407 408 ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X", 409 ref_desc->reference.class)); 410 ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO); 411 412 status = AE_AML_INTERNAL; 413 break; 414 } 415 416 return_ACPI_STATUS(status); 417 } 418 419 /******************************************************************************* 420 * 421 * FUNCTION: acpi_ex_store_object_to_index 422 * 423 * PARAMETERS: *source_desc - Value to be stored 424 * *dest_desc - Named object to receive the value 425 * walk_state - Current walk state 426 * 427 * RETURN: Status 428 * 429 * DESCRIPTION: Store the object to indexed Buffer or Package element 430 * 431 ******************************************************************************/ 432 433 static acpi_status 434 acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, 435 union acpi_operand_object *index_desc, 436 struct acpi_walk_state *walk_state) 437 { 438 acpi_status status = AE_OK; 439 union acpi_operand_object *obj_desc; 440 union acpi_operand_object *new_desc; 441 u8 value = 0; 442 u32 i; 443 444 ACPI_FUNCTION_TRACE(ex_store_object_to_index); 445 446 /* 447 * Destination must be a reference pointer, and 448 * must point to either a buffer or a package 449 */ 450 switch (index_desc->reference.target_type) { 451 case ACPI_TYPE_PACKAGE: 452 /* 453 * Storing to a package element. Copy the object and replace 454 * any existing object with the new object. No implicit 455 * conversion is performed. 456 * 457 * The object at *(index_desc->Reference.Where) is the 458 * element within the package that is to be modified. 459 * The parent package object is at index_desc->Reference.Object 460 */ 461 obj_desc = *(index_desc->reference.where); 462 463 if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE && 464 source_desc->reference.class == ACPI_REFCLASS_TABLE) { 465 466 /* This is a DDBHandle, just add a reference to it */ 467 468 acpi_ut_add_reference(source_desc); 469 new_desc = source_desc; 470 } else { 471 /* Normal object, copy it */ 472 473 status = 474 acpi_ut_copy_iobject_to_iobject(source_desc, 475 &new_desc, 476 walk_state); 477 if (ACPI_FAILURE(status)) { 478 return_ACPI_STATUS(status); 479 } 480 } 481 482 if (obj_desc) { 483 484 /* Decrement reference count by the ref count of the parent package */ 485 486 for (i = 0; i < ((union acpi_operand_object *) 487 index_desc->reference.object)->common. 488 reference_count; i++) { 489 acpi_ut_remove_reference(obj_desc); 490 } 491 } 492 493 *(index_desc->reference.where) = new_desc; 494 495 /* Increment ref count by the ref count of the parent package-1 */ 496 497 for (i = 1; i < ((union acpi_operand_object *) 498 index_desc->reference.object)->common. 499 reference_count; i++) { 500 acpi_ut_add_reference(new_desc); 501 } 502 503 break; 504 505 case ACPI_TYPE_BUFFER_FIELD: 506 507 /* 508 * Store into a Buffer or String (not actually a real buffer_field) 509 * at a location defined by an Index. 510 * 511 * The first 8-bit element of the source object is written to the 512 * 8-bit Buffer location defined by the Index destination object, 513 * according to the ACPI 2.0 specification. 514 */ 515 516 /* 517 * Make sure the target is a Buffer or String. An error should 518 * not happen here, since the reference_object was constructed 519 * by the INDEX_OP code. 520 */ 521 obj_desc = index_desc->reference.object; 522 if ((obj_desc->common.type != ACPI_TYPE_BUFFER) && 523 (obj_desc->common.type != ACPI_TYPE_STRING)) { 524 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 525 } 526 527 /* 528 * The assignment of the individual elements will be slightly 529 * different for each source type. 530 */ 531 switch (source_desc->common.type) { 532 case ACPI_TYPE_INTEGER: 533 534 /* Use the least-significant byte of the integer */ 535 536 value = (u8) (source_desc->integer.value); 537 break; 538 539 case ACPI_TYPE_BUFFER: 540 case ACPI_TYPE_STRING: 541 542 /* Note: Takes advantage of common string/buffer fields */ 543 544 value = source_desc->buffer.pointer[0]; 545 break; 546 547 default: 548 549 /* All other types are invalid */ 550 551 ACPI_ERROR((AE_INFO, 552 "Source must be Integer/Buffer/String type, not %s", 553 acpi_ut_get_object_type_name(source_desc))); 554 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 555 } 556 557 /* Store the source value into the target buffer byte */ 558 559 obj_desc->buffer.pointer[index_desc->reference.value] = value; 560 break; 561 562 default: 563 ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField")); 564 status = AE_AML_OPERAND_TYPE; 565 break; 566 } 567 568 return_ACPI_STATUS(status); 569 } 570 571 /******************************************************************************* 572 * 573 * FUNCTION: acpi_ex_store_object_to_node 574 * 575 * PARAMETERS: source_desc - Value to be stored 576 * Node - Named object to receive the value 577 * walk_state - Current walk state 578 * implicit_conversion - Perform implicit conversion (yes/no) 579 * 580 * RETURN: Status 581 * 582 * DESCRIPTION: Store the object to the named object. 583 * 584 * The Assignment of an object to a named object is handled here 585 * The value passed in will replace the current value (if any) 586 * with the input value. 587 * 588 * When storing into an object the data is converted to the 589 * target object type then stored in the object. This means 590 * that the target object type (for an initialized target) will 591 * not be changed by a store operation. 592 * 593 * Assumes parameters are already validated. 594 * 595 ******************************************************************************/ 596 597 acpi_status 598 acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, 599 struct acpi_namespace_node *node, 600 struct acpi_walk_state *walk_state, 601 u8 implicit_conversion) 602 { 603 acpi_status status = AE_OK; 604 union acpi_operand_object *target_desc; 605 union acpi_operand_object *new_desc; 606 acpi_object_type target_type; 607 608 ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc); 609 610 /* Get current type of the node, and object attached to Node */ 611 612 target_type = acpi_ns_get_type(node); 613 target_desc = acpi_ns_get_attached_object(node); 614 615 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", 616 source_desc, 617 acpi_ut_get_object_type_name(source_desc), node, 618 acpi_ut_get_type_name(target_type))); 619 620 /* 621 * Resolve the source object to an actual value 622 * (If it is a reference object) 623 */ 624 status = acpi_ex_resolve_object(&source_desc, target_type, walk_state); 625 if (ACPI_FAILURE(status)) { 626 return_ACPI_STATUS(status); 627 } 628 629 /* If no implicit conversion, drop into the default case below */ 630 631 if ((!implicit_conversion) || 632 ((walk_state->opcode == AML_COPY_OP) && 633 (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && 634 (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && 635 (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { 636 /* 637 * Force execution of default (no implicit conversion). Note: 638 * copy_object does not perform an implicit conversion, as per the ACPI 639 * spec -- except in case of region/bank/index fields -- because these 640 * objects must retain their original type permanently. 641 */ 642 target_type = ACPI_TYPE_ANY; 643 } 644 645 /* Do the actual store operation */ 646 647 switch (target_type) { 648 case ACPI_TYPE_BUFFER_FIELD: 649 case ACPI_TYPE_LOCAL_REGION_FIELD: 650 case ACPI_TYPE_LOCAL_BANK_FIELD: 651 case ACPI_TYPE_LOCAL_INDEX_FIELD: 652 653 /* For fields, copy the source data to the target field. */ 654 655 status = acpi_ex_write_data_to_field(source_desc, target_desc, 656 &walk_state->result_obj); 657 break; 658 659 case ACPI_TYPE_INTEGER: 660 case ACPI_TYPE_STRING: 661 case ACPI_TYPE_BUFFER: 662 663 /* 664 * These target types are all of type Integer/String/Buffer, and 665 * therefore support implicit conversion before the store. 666 * 667 * Copy and/or convert the source object to a new target object 668 */ 669 status = 670 acpi_ex_store_object_to_object(source_desc, target_desc, 671 &new_desc, walk_state); 672 if (ACPI_FAILURE(status)) { 673 return_ACPI_STATUS(status); 674 } 675 676 if (new_desc != target_desc) { 677 /* 678 * Store the new new_desc as the new value of the Name, and set 679 * the Name's type to that of the value being stored in it. 680 * source_desc reference count is incremented by attach_object. 681 * 682 * Note: This may change the type of the node if an explicit store 683 * has been performed such that the node/object type has been 684 * changed. 685 */ 686 status = 687 acpi_ns_attach_object(node, new_desc, 688 new_desc->common.type); 689 690 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 691 "Store %s into %s via Convert/Attach\n", 692 acpi_ut_get_object_type_name 693 (source_desc), 694 acpi_ut_get_object_type_name 695 (new_desc))); 696 } 697 break; 698 699 default: 700 701 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 702 "Storing %s (%p) directly into node (%p) with no implicit conversion\n", 703 acpi_ut_get_object_type_name(source_desc), 704 source_desc, node)); 705 706 /* No conversions for all other types. Just attach the source object */ 707 708 status = acpi_ns_attach_object(node, source_desc, 709 source_desc->common.type); 710 break; 711 } 712 713 return_ACPI_STATUS(status); 714 } 715