1*95b482a8SLen Brown 2*95b482a8SLen Brown /****************************************************************************** 3*95b482a8SLen Brown * 4*95b482a8SLen Brown * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes 5*95b482a8SLen Brown * 6*95b482a8SLen Brown *****************************************************************************/ 7*95b482a8SLen Brown 8*95b482a8SLen Brown /* 9*95b482a8SLen Brown * Copyright (C) 2000 - 2008, Intel Corp. 10*95b482a8SLen Brown * All rights reserved. 11*95b482a8SLen Brown * 12*95b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 13*95b482a8SLen Brown * modification, are permitted provided that the following conditions 14*95b482a8SLen Brown * are met: 15*95b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 16*95b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 17*95b482a8SLen Brown * without modification. 18*95b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19*95b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 20*95b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 21*95b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 22*95b482a8SLen Brown * binary redistribution. 23*95b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 24*95b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 25*95b482a8SLen Brown * from this software without specific prior written permission. 26*95b482a8SLen Brown * 27*95b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 28*95b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 29*95b482a8SLen Brown * Software Foundation. 30*95b482a8SLen Brown * 31*95b482a8SLen Brown * NO WARRANTY 32*95b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33*95b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34*95b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35*95b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36*95b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37*95b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38*95b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39*95b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40*95b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41*95b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42*95b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 43*95b482a8SLen Brown */ 44*95b482a8SLen Brown 45*95b482a8SLen Brown #include <acpi/acpi.h> 46*95b482a8SLen Brown #include <acpi/accommon.h> 47*95b482a8SLen Brown #include <acpi/acinterp.h> 48*95b482a8SLen Brown #include <acpi/amlcode.h> 49*95b482a8SLen Brown #include <acpi/amlresrc.h> 50*95b482a8SLen Brown 51*95b482a8SLen Brown #define _COMPONENT ACPI_EXECUTER 52*95b482a8SLen Brown ACPI_MODULE_NAME("exmisc") 53*95b482a8SLen Brown 54*95b482a8SLen Brown /******************************************************************************* 55*95b482a8SLen Brown * 56*95b482a8SLen Brown * FUNCTION: acpi_ex_get_object_reference 57*95b482a8SLen Brown * 58*95b482a8SLen Brown * PARAMETERS: obj_desc - Create a reference to this object 59*95b482a8SLen Brown * return_desc - Where to store the reference 60*95b482a8SLen Brown * walk_state - Current state 61*95b482a8SLen Brown * 62*95b482a8SLen Brown * RETURN: Status 63*95b482a8SLen Brown * 64*95b482a8SLen Brown * DESCRIPTION: Obtain and return a "reference" to the target object 65*95b482a8SLen Brown * Common code for the ref_of_op and the cond_ref_of_op. 66*95b482a8SLen Brown * 67*95b482a8SLen Brown ******************************************************************************/ 68*95b482a8SLen Brown acpi_status 69*95b482a8SLen Brown acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, 70*95b482a8SLen Brown union acpi_operand_object **return_desc, 71*95b482a8SLen Brown struct acpi_walk_state *walk_state) 72*95b482a8SLen Brown { 73*95b482a8SLen Brown union acpi_operand_object *reference_obj; 74*95b482a8SLen Brown union acpi_operand_object *referenced_obj; 75*95b482a8SLen Brown 76*95b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc); 77*95b482a8SLen Brown 78*95b482a8SLen Brown *return_desc = NULL; 79*95b482a8SLen Brown 80*95b482a8SLen Brown switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { 81*95b482a8SLen Brown case ACPI_DESC_TYPE_OPERAND: 82*95b482a8SLen Brown 83*95b482a8SLen Brown if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) { 84*95b482a8SLen Brown return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 85*95b482a8SLen Brown } 86*95b482a8SLen Brown 87*95b482a8SLen Brown /* 88*95b482a8SLen Brown * Must be a reference to a Local or Arg 89*95b482a8SLen Brown */ 90*95b482a8SLen Brown switch (obj_desc->reference.class) { 91*95b482a8SLen Brown case ACPI_REFCLASS_LOCAL: 92*95b482a8SLen Brown case ACPI_REFCLASS_ARG: 93*95b482a8SLen Brown case ACPI_REFCLASS_DEBUG: 94*95b482a8SLen Brown 95*95b482a8SLen Brown /* The referenced object is the pseudo-node for the local/arg */ 96*95b482a8SLen Brown 97*95b482a8SLen Brown referenced_obj = obj_desc->reference.object; 98*95b482a8SLen Brown break; 99*95b482a8SLen Brown 100*95b482a8SLen Brown default: 101*95b482a8SLen Brown 102*95b482a8SLen Brown ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X", 103*95b482a8SLen Brown obj_desc->reference.class)); 104*95b482a8SLen Brown return_ACPI_STATUS(AE_AML_INTERNAL); 105*95b482a8SLen Brown } 106*95b482a8SLen Brown break; 107*95b482a8SLen Brown 108*95b482a8SLen Brown case ACPI_DESC_TYPE_NAMED: 109*95b482a8SLen Brown 110*95b482a8SLen Brown /* 111*95b482a8SLen Brown * A named reference that has already been resolved to a Node 112*95b482a8SLen Brown */ 113*95b482a8SLen Brown referenced_obj = obj_desc; 114*95b482a8SLen Brown break; 115*95b482a8SLen Brown 116*95b482a8SLen Brown default: 117*95b482a8SLen Brown 118*95b482a8SLen Brown ACPI_ERROR((AE_INFO, "Invalid descriptor type %X", 119*95b482a8SLen Brown ACPI_GET_DESCRIPTOR_TYPE(obj_desc))); 120*95b482a8SLen Brown return_ACPI_STATUS(AE_TYPE); 121*95b482a8SLen Brown } 122*95b482a8SLen Brown 123*95b482a8SLen Brown /* Create a new reference object */ 124*95b482a8SLen Brown 125*95b482a8SLen Brown reference_obj = 126*95b482a8SLen Brown acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); 127*95b482a8SLen Brown if (!reference_obj) { 128*95b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 129*95b482a8SLen Brown } 130*95b482a8SLen Brown 131*95b482a8SLen Brown reference_obj->reference.class = ACPI_REFCLASS_REFOF; 132*95b482a8SLen Brown reference_obj->reference.object = referenced_obj; 133*95b482a8SLen Brown *return_desc = reference_obj; 134*95b482a8SLen Brown 135*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 136*95b482a8SLen Brown "Object %p Type [%s], returning Reference %p\n", 137*95b482a8SLen Brown obj_desc, acpi_ut_get_object_type_name(obj_desc), 138*95b482a8SLen Brown *return_desc)); 139*95b482a8SLen Brown 140*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 141*95b482a8SLen Brown } 142*95b482a8SLen Brown 143*95b482a8SLen Brown /******************************************************************************* 144*95b482a8SLen Brown * 145*95b482a8SLen Brown * FUNCTION: acpi_ex_concat_template 146*95b482a8SLen Brown * 147*95b482a8SLen Brown * PARAMETERS: Operand0 - First source object 148*95b482a8SLen Brown * Operand1 - Second source object 149*95b482a8SLen Brown * actual_return_desc - Where to place the return object 150*95b482a8SLen Brown * walk_state - Current walk state 151*95b482a8SLen Brown * 152*95b482a8SLen Brown * RETURN: Status 153*95b482a8SLen Brown * 154*95b482a8SLen Brown * DESCRIPTION: Concatenate two resource templates 155*95b482a8SLen Brown * 156*95b482a8SLen Brown ******************************************************************************/ 157*95b482a8SLen Brown 158*95b482a8SLen Brown acpi_status 159*95b482a8SLen Brown acpi_ex_concat_template(union acpi_operand_object *operand0, 160*95b482a8SLen Brown union acpi_operand_object *operand1, 161*95b482a8SLen Brown union acpi_operand_object **actual_return_desc, 162*95b482a8SLen Brown struct acpi_walk_state *walk_state) 163*95b482a8SLen Brown { 164*95b482a8SLen Brown acpi_status status; 165*95b482a8SLen Brown union acpi_operand_object *return_desc; 166*95b482a8SLen Brown u8 *new_buf; 167*95b482a8SLen Brown u8 *end_tag; 168*95b482a8SLen Brown acpi_size length0; 169*95b482a8SLen Brown acpi_size length1; 170*95b482a8SLen Brown acpi_size new_length; 171*95b482a8SLen Brown 172*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_concat_template); 173*95b482a8SLen Brown 174*95b482a8SLen Brown /* 175*95b482a8SLen Brown * Find the end_tag descriptor in each resource template. 176*95b482a8SLen Brown * Note1: returned pointers point TO the end_tag, not past it. 177*95b482a8SLen Brown * Note2: zero-length buffers are allowed; treated like one end_tag 178*95b482a8SLen Brown */ 179*95b482a8SLen Brown 180*95b482a8SLen Brown /* Get the length of the first resource template */ 181*95b482a8SLen Brown 182*95b482a8SLen Brown status = acpi_ut_get_resource_end_tag(operand0, &end_tag); 183*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 184*95b482a8SLen Brown return_ACPI_STATUS(status); 185*95b482a8SLen Brown } 186*95b482a8SLen Brown 187*95b482a8SLen Brown length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer); 188*95b482a8SLen Brown 189*95b482a8SLen Brown /* Get the length of the second resource template */ 190*95b482a8SLen Brown 191*95b482a8SLen Brown status = acpi_ut_get_resource_end_tag(operand1, &end_tag); 192*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 193*95b482a8SLen Brown return_ACPI_STATUS(status); 194*95b482a8SLen Brown } 195*95b482a8SLen Brown 196*95b482a8SLen Brown length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer); 197*95b482a8SLen Brown 198*95b482a8SLen Brown /* Combine both lengths, minimum size will be 2 for end_tag */ 199*95b482a8SLen Brown 200*95b482a8SLen Brown new_length = length0 + length1 + sizeof(struct aml_resource_end_tag); 201*95b482a8SLen Brown 202*95b482a8SLen Brown /* Create a new buffer object for the result (with one end_tag) */ 203*95b482a8SLen Brown 204*95b482a8SLen Brown return_desc = acpi_ut_create_buffer_object(new_length); 205*95b482a8SLen Brown if (!return_desc) { 206*95b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 207*95b482a8SLen Brown } 208*95b482a8SLen Brown 209*95b482a8SLen Brown /* 210*95b482a8SLen Brown * Copy the templates to the new buffer, 0 first, then 1 follows. One 211*95b482a8SLen Brown * end_tag descriptor is copied from Operand1. 212*95b482a8SLen Brown */ 213*95b482a8SLen Brown new_buf = return_desc->buffer.pointer; 214*95b482a8SLen Brown ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length0); 215*95b482a8SLen Brown ACPI_MEMCPY(new_buf + length0, operand1->buffer.pointer, length1); 216*95b482a8SLen Brown 217*95b482a8SLen Brown /* Insert end_tag and set the checksum to zero, means "ignore checksum" */ 218*95b482a8SLen Brown 219*95b482a8SLen Brown new_buf[new_length - 1] = 0; 220*95b482a8SLen Brown new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1; 221*95b482a8SLen Brown 222*95b482a8SLen Brown /* Return the completed resource template */ 223*95b482a8SLen Brown 224*95b482a8SLen Brown *actual_return_desc = return_desc; 225*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 226*95b482a8SLen Brown } 227*95b482a8SLen Brown 228*95b482a8SLen Brown /******************************************************************************* 229*95b482a8SLen Brown * 230*95b482a8SLen Brown * FUNCTION: acpi_ex_do_concatenate 231*95b482a8SLen Brown * 232*95b482a8SLen Brown * PARAMETERS: Operand0 - First source object 233*95b482a8SLen Brown * Operand1 - Second source object 234*95b482a8SLen Brown * actual_return_desc - Where to place the return object 235*95b482a8SLen Brown * walk_state - Current walk state 236*95b482a8SLen Brown * 237*95b482a8SLen Brown * RETURN: Status 238*95b482a8SLen Brown * 239*95b482a8SLen Brown * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. 240*95b482a8SLen Brown * 241*95b482a8SLen Brown ******************************************************************************/ 242*95b482a8SLen Brown 243*95b482a8SLen Brown acpi_status 244*95b482a8SLen Brown acpi_ex_do_concatenate(union acpi_operand_object *operand0, 245*95b482a8SLen Brown union acpi_operand_object *operand1, 246*95b482a8SLen Brown union acpi_operand_object **actual_return_desc, 247*95b482a8SLen Brown struct acpi_walk_state *walk_state) 248*95b482a8SLen Brown { 249*95b482a8SLen Brown union acpi_operand_object *local_operand1 = operand1; 250*95b482a8SLen Brown union acpi_operand_object *return_desc; 251*95b482a8SLen Brown char *new_buf; 252*95b482a8SLen Brown acpi_status status; 253*95b482a8SLen Brown 254*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_do_concatenate); 255*95b482a8SLen Brown 256*95b482a8SLen Brown /* 257*95b482a8SLen Brown * Convert the second operand if necessary. The first operand 258*95b482a8SLen Brown * determines the type of the second operand, (See the Data Types 259*95b482a8SLen Brown * section of the ACPI specification.) Both object types are 260*95b482a8SLen Brown * guaranteed to be either Integer/String/Buffer by the operand 261*95b482a8SLen Brown * resolution mechanism. 262*95b482a8SLen Brown */ 263*95b482a8SLen Brown switch (ACPI_GET_OBJECT_TYPE(operand0)) { 264*95b482a8SLen Brown case ACPI_TYPE_INTEGER: 265*95b482a8SLen Brown status = 266*95b482a8SLen Brown acpi_ex_convert_to_integer(operand1, &local_operand1, 16); 267*95b482a8SLen Brown break; 268*95b482a8SLen Brown 269*95b482a8SLen Brown case ACPI_TYPE_STRING: 270*95b482a8SLen Brown status = acpi_ex_convert_to_string(operand1, &local_operand1, 271*95b482a8SLen Brown ACPI_IMPLICIT_CONVERT_HEX); 272*95b482a8SLen Brown break; 273*95b482a8SLen Brown 274*95b482a8SLen Brown case ACPI_TYPE_BUFFER: 275*95b482a8SLen Brown status = acpi_ex_convert_to_buffer(operand1, &local_operand1); 276*95b482a8SLen Brown break; 277*95b482a8SLen Brown 278*95b482a8SLen Brown default: 279*95b482a8SLen Brown ACPI_ERROR((AE_INFO, "Invalid object type: %X", 280*95b482a8SLen Brown ACPI_GET_OBJECT_TYPE(operand0))); 281*95b482a8SLen Brown status = AE_AML_INTERNAL; 282*95b482a8SLen Brown } 283*95b482a8SLen Brown 284*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 285*95b482a8SLen Brown goto cleanup; 286*95b482a8SLen Brown } 287*95b482a8SLen Brown 288*95b482a8SLen Brown /* 289*95b482a8SLen Brown * Both operands are now known to be the same object type 290*95b482a8SLen Brown * (Both are Integer, String, or Buffer), and we can now perform the 291*95b482a8SLen Brown * concatenation. 292*95b482a8SLen Brown */ 293*95b482a8SLen Brown 294*95b482a8SLen Brown /* 295*95b482a8SLen Brown * There are three cases to handle: 296*95b482a8SLen Brown * 297*95b482a8SLen Brown * 1) Two Integers concatenated to produce a new Buffer 298*95b482a8SLen Brown * 2) Two Strings concatenated to produce a new String 299*95b482a8SLen Brown * 3) Two Buffers concatenated to produce a new Buffer 300*95b482a8SLen Brown */ 301*95b482a8SLen Brown switch (ACPI_GET_OBJECT_TYPE(operand0)) { 302*95b482a8SLen Brown case ACPI_TYPE_INTEGER: 303*95b482a8SLen Brown 304*95b482a8SLen Brown /* Result of two Integers is a Buffer */ 305*95b482a8SLen Brown /* Need enough buffer space for two integers */ 306*95b482a8SLen Brown 307*95b482a8SLen Brown return_desc = acpi_ut_create_buffer_object((acpi_size) 308*95b482a8SLen Brown ACPI_MUL_2 309*95b482a8SLen Brown (acpi_gbl_integer_byte_width)); 310*95b482a8SLen Brown if (!return_desc) { 311*95b482a8SLen Brown status = AE_NO_MEMORY; 312*95b482a8SLen Brown goto cleanup; 313*95b482a8SLen Brown } 314*95b482a8SLen Brown 315*95b482a8SLen Brown new_buf = (char *)return_desc->buffer.pointer; 316*95b482a8SLen Brown 317*95b482a8SLen Brown /* Copy the first integer, LSB first */ 318*95b482a8SLen Brown 319*95b482a8SLen Brown ACPI_MEMCPY(new_buf, &operand0->integer.value, 320*95b482a8SLen Brown acpi_gbl_integer_byte_width); 321*95b482a8SLen Brown 322*95b482a8SLen Brown /* Copy the second integer (LSB first) after the first */ 323*95b482a8SLen Brown 324*95b482a8SLen Brown ACPI_MEMCPY(new_buf + acpi_gbl_integer_byte_width, 325*95b482a8SLen Brown &local_operand1->integer.value, 326*95b482a8SLen Brown acpi_gbl_integer_byte_width); 327*95b482a8SLen Brown break; 328*95b482a8SLen Brown 329*95b482a8SLen Brown case ACPI_TYPE_STRING: 330*95b482a8SLen Brown 331*95b482a8SLen Brown /* Result of two Strings is a String */ 332*95b482a8SLen Brown 333*95b482a8SLen Brown return_desc = acpi_ut_create_string_object(((acpi_size) 334*95b482a8SLen Brown operand0->string. 335*95b482a8SLen Brown length + 336*95b482a8SLen Brown local_operand1-> 337*95b482a8SLen Brown string.length)); 338*95b482a8SLen Brown if (!return_desc) { 339*95b482a8SLen Brown status = AE_NO_MEMORY; 340*95b482a8SLen Brown goto cleanup; 341*95b482a8SLen Brown } 342*95b482a8SLen Brown 343*95b482a8SLen Brown new_buf = return_desc->string.pointer; 344*95b482a8SLen Brown 345*95b482a8SLen Brown /* Concatenate the strings */ 346*95b482a8SLen Brown 347*95b482a8SLen Brown ACPI_STRCPY(new_buf, operand0->string.pointer); 348*95b482a8SLen Brown ACPI_STRCPY(new_buf + operand0->string.length, 349*95b482a8SLen Brown local_operand1->string.pointer); 350*95b482a8SLen Brown break; 351*95b482a8SLen Brown 352*95b482a8SLen Brown case ACPI_TYPE_BUFFER: 353*95b482a8SLen Brown 354*95b482a8SLen Brown /* Result of two Buffers is a Buffer */ 355*95b482a8SLen Brown 356*95b482a8SLen Brown return_desc = acpi_ut_create_buffer_object(((acpi_size) 357*95b482a8SLen Brown operand0->buffer. 358*95b482a8SLen Brown length + 359*95b482a8SLen Brown local_operand1-> 360*95b482a8SLen Brown buffer.length)); 361*95b482a8SLen Brown if (!return_desc) { 362*95b482a8SLen Brown status = AE_NO_MEMORY; 363*95b482a8SLen Brown goto cleanup; 364*95b482a8SLen Brown } 365*95b482a8SLen Brown 366*95b482a8SLen Brown new_buf = (char *)return_desc->buffer.pointer; 367*95b482a8SLen Brown 368*95b482a8SLen Brown /* Concatenate the buffers */ 369*95b482a8SLen Brown 370*95b482a8SLen Brown ACPI_MEMCPY(new_buf, operand0->buffer.pointer, 371*95b482a8SLen Brown operand0->buffer.length); 372*95b482a8SLen Brown ACPI_MEMCPY(new_buf + operand0->buffer.length, 373*95b482a8SLen Brown local_operand1->buffer.pointer, 374*95b482a8SLen Brown local_operand1->buffer.length); 375*95b482a8SLen Brown break; 376*95b482a8SLen Brown 377*95b482a8SLen Brown default: 378*95b482a8SLen Brown 379*95b482a8SLen Brown /* Invalid object type, should not happen here */ 380*95b482a8SLen Brown 381*95b482a8SLen Brown ACPI_ERROR((AE_INFO, "Invalid object type: %X", 382*95b482a8SLen Brown ACPI_GET_OBJECT_TYPE(operand0))); 383*95b482a8SLen Brown status = AE_AML_INTERNAL; 384*95b482a8SLen Brown goto cleanup; 385*95b482a8SLen Brown } 386*95b482a8SLen Brown 387*95b482a8SLen Brown *actual_return_desc = return_desc; 388*95b482a8SLen Brown 389*95b482a8SLen Brown cleanup: 390*95b482a8SLen Brown if (local_operand1 != operand1) { 391*95b482a8SLen Brown acpi_ut_remove_reference(local_operand1); 392*95b482a8SLen Brown } 393*95b482a8SLen Brown return_ACPI_STATUS(status); 394*95b482a8SLen Brown } 395*95b482a8SLen Brown 396*95b482a8SLen Brown /******************************************************************************* 397*95b482a8SLen Brown * 398*95b482a8SLen Brown * FUNCTION: acpi_ex_do_math_op 399*95b482a8SLen Brown * 400*95b482a8SLen Brown * PARAMETERS: Opcode - AML opcode 401*95b482a8SLen Brown * Integer0 - Integer operand #0 402*95b482a8SLen Brown * Integer1 - Integer operand #1 403*95b482a8SLen Brown * 404*95b482a8SLen Brown * RETURN: Integer result of the operation 405*95b482a8SLen Brown * 406*95b482a8SLen Brown * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the 407*95b482a8SLen Brown * math functions here is to prevent a lot of pointer dereferencing 408*95b482a8SLen Brown * to obtain the operands. 409*95b482a8SLen Brown * 410*95b482a8SLen Brown ******************************************************************************/ 411*95b482a8SLen Brown 412*95b482a8SLen Brown acpi_integer 413*95b482a8SLen Brown acpi_ex_do_math_op(u16 opcode, acpi_integer integer0, acpi_integer integer1) 414*95b482a8SLen Brown { 415*95b482a8SLen Brown 416*95b482a8SLen Brown ACPI_FUNCTION_ENTRY(); 417*95b482a8SLen Brown 418*95b482a8SLen Brown switch (opcode) { 419*95b482a8SLen Brown case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ 420*95b482a8SLen Brown 421*95b482a8SLen Brown return (integer0 + integer1); 422*95b482a8SLen Brown 423*95b482a8SLen Brown case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ 424*95b482a8SLen Brown 425*95b482a8SLen Brown return (integer0 & integer1); 426*95b482a8SLen Brown 427*95b482a8SLen Brown case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ 428*95b482a8SLen Brown 429*95b482a8SLen Brown return (~(integer0 & integer1)); 430*95b482a8SLen Brown 431*95b482a8SLen Brown case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ 432*95b482a8SLen Brown 433*95b482a8SLen Brown return (integer0 | integer1); 434*95b482a8SLen Brown 435*95b482a8SLen Brown case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ 436*95b482a8SLen Brown 437*95b482a8SLen Brown return (~(integer0 | integer1)); 438*95b482a8SLen Brown 439*95b482a8SLen Brown case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ 440*95b482a8SLen Brown 441*95b482a8SLen Brown return (integer0 ^ integer1); 442*95b482a8SLen Brown 443*95b482a8SLen Brown case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ 444*95b482a8SLen Brown 445*95b482a8SLen Brown return (integer0 * integer1); 446*95b482a8SLen Brown 447*95b482a8SLen Brown case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */ 448*95b482a8SLen Brown 449*95b482a8SLen Brown /* 450*95b482a8SLen Brown * We need to check if the shiftcount is larger than the integer bit 451*95b482a8SLen Brown * width since the behavior of this is not well-defined in the C language. 452*95b482a8SLen Brown */ 453*95b482a8SLen Brown if (integer1 >= acpi_gbl_integer_bit_width) { 454*95b482a8SLen Brown return (0); 455*95b482a8SLen Brown } 456*95b482a8SLen Brown return (integer0 << integer1); 457*95b482a8SLen Brown 458*95b482a8SLen Brown case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */ 459*95b482a8SLen Brown 460*95b482a8SLen Brown /* 461*95b482a8SLen Brown * We need to check if the shiftcount is larger than the integer bit 462*95b482a8SLen Brown * width since the behavior of this is not well-defined in the C language. 463*95b482a8SLen Brown */ 464*95b482a8SLen Brown if (integer1 >= acpi_gbl_integer_bit_width) { 465*95b482a8SLen Brown return (0); 466*95b482a8SLen Brown } 467*95b482a8SLen Brown return (integer0 >> integer1); 468*95b482a8SLen Brown 469*95b482a8SLen Brown case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ 470*95b482a8SLen Brown 471*95b482a8SLen Brown return (integer0 - integer1); 472*95b482a8SLen Brown 473*95b482a8SLen Brown default: 474*95b482a8SLen Brown 475*95b482a8SLen Brown return (0); 476*95b482a8SLen Brown } 477*95b482a8SLen Brown } 478*95b482a8SLen Brown 479*95b482a8SLen Brown /******************************************************************************* 480*95b482a8SLen Brown * 481*95b482a8SLen Brown * FUNCTION: acpi_ex_do_logical_numeric_op 482*95b482a8SLen Brown * 483*95b482a8SLen Brown * PARAMETERS: Opcode - AML opcode 484*95b482a8SLen Brown * Integer0 - Integer operand #0 485*95b482a8SLen Brown * Integer1 - Integer operand #1 486*95b482a8SLen Brown * logical_result - TRUE/FALSE result of the operation 487*95b482a8SLen Brown * 488*95b482a8SLen Brown * RETURN: Status 489*95b482a8SLen Brown * 490*95b482a8SLen Brown * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric 491*95b482a8SLen Brown * operators (LAnd and LOr), both operands must be integers. 492*95b482a8SLen Brown * 493*95b482a8SLen Brown * Note: cleanest machine code seems to be produced by the code 494*95b482a8SLen Brown * below, rather than using statements of the form: 495*95b482a8SLen Brown * Result = (Integer0 && Integer1); 496*95b482a8SLen Brown * 497*95b482a8SLen Brown ******************************************************************************/ 498*95b482a8SLen Brown 499*95b482a8SLen Brown acpi_status 500*95b482a8SLen Brown acpi_ex_do_logical_numeric_op(u16 opcode, 501*95b482a8SLen Brown acpi_integer integer0, 502*95b482a8SLen Brown acpi_integer integer1, u8 * logical_result) 503*95b482a8SLen Brown { 504*95b482a8SLen Brown acpi_status status = AE_OK; 505*95b482a8SLen Brown u8 local_result = FALSE; 506*95b482a8SLen Brown 507*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op); 508*95b482a8SLen Brown 509*95b482a8SLen Brown switch (opcode) { 510*95b482a8SLen Brown case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ 511*95b482a8SLen Brown 512*95b482a8SLen Brown if (integer0 && integer1) { 513*95b482a8SLen Brown local_result = TRUE; 514*95b482a8SLen Brown } 515*95b482a8SLen Brown break; 516*95b482a8SLen Brown 517*95b482a8SLen Brown case AML_LOR_OP: /* LOr (Integer0, Integer1) */ 518*95b482a8SLen Brown 519*95b482a8SLen Brown if (integer0 || integer1) { 520*95b482a8SLen Brown local_result = TRUE; 521*95b482a8SLen Brown } 522*95b482a8SLen Brown break; 523*95b482a8SLen Brown 524*95b482a8SLen Brown default: 525*95b482a8SLen Brown status = AE_AML_INTERNAL; 526*95b482a8SLen Brown break; 527*95b482a8SLen Brown } 528*95b482a8SLen Brown 529*95b482a8SLen Brown /* Return the logical result and status */ 530*95b482a8SLen Brown 531*95b482a8SLen Brown *logical_result = local_result; 532*95b482a8SLen Brown return_ACPI_STATUS(status); 533*95b482a8SLen Brown } 534*95b482a8SLen Brown 535*95b482a8SLen Brown /******************************************************************************* 536*95b482a8SLen Brown * 537*95b482a8SLen Brown * FUNCTION: acpi_ex_do_logical_op 538*95b482a8SLen Brown * 539*95b482a8SLen Brown * PARAMETERS: Opcode - AML opcode 540*95b482a8SLen Brown * Operand0 - operand #0 541*95b482a8SLen Brown * Operand1 - operand #1 542*95b482a8SLen Brown * logical_result - TRUE/FALSE result of the operation 543*95b482a8SLen Brown * 544*95b482a8SLen Brown * RETURN: Status 545*95b482a8SLen Brown * 546*95b482a8SLen Brown * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the 547*95b482a8SLen Brown * functions here is to prevent a lot of pointer dereferencing 548*95b482a8SLen Brown * to obtain the operands and to simplify the generation of the 549*95b482a8SLen Brown * logical value. For the Numeric operators (LAnd and LOr), both 550*95b482a8SLen Brown * operands must be integers. For the other logical operators, 551*95b482a8SLen Brown * operands can be any combination of Integer/String/Buffer. The 552*95b482a8SLen Brown * first operand determines the type to which the second operand 553*95b482a8SLen Brown * will be converted. 554*95b482a8SLen Brown * 555*95b482a8SLen Brown * Note: cleanest machine code seems to be produced by the code 556*95b482a8SLen Brown * below, rather than using statements of the form: 557*95b482a8SLen Brown * Result = (Operand0 == Operand1); 558*95b482a8SLen Brown * 559*95b482a8SLen Brown ******************************************************************************/ 560*95b482a8SLen Brown 561*95b482a8SLen Brown acpi_status 562*95b482a8SLen Brown acpi_ex_do_logical_op(u16 opcode, 563*95b482a8SLen Brown union acpi_operand_object *operand0, 564*95b482a8SLen Brown union acpi_operand_object *operand1, u8 * logical_result) 565*95b482a8SLen Brown { 566*95b482a8SLen Brown union acpi_operand_object *local_operand1 = operand1; 567*95b482a8SLen Brown acpi_integer integer0; 568*95b482a8SLen Brown acpi_integer integer1; 569*95b482a8SLen Brown u32 length0; 570*95b482a8SLen Brown u32 length1; 571*95b482a8SLen Brown acpi_status status = AE_OK; 572*95b482a8SLen Brown u8 local_result = FALSE; 573*95b482a8SLen Brown int compare; 574*95b482a8SLen Brown 575*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_do_logical_op); 576*95b482a8SLen Brown 577*95b482a8SLen Brown /* 578*95b482a8SLen Brown * Convert the second operand if necessary. The first operand 579*95b482a8SLen Brown * determines the type of the second operand, (See the Data Types 580*95b482a8SLen Brown * section of the ACPI 3.0+ specification.) Both object types are 581*95b482a8SLen Brown * guaranteed to be either Integer/String/Buffer by the operand 582*95b482a8SLen Brown * resolution mechanism. 583*95b482a8SLen Brown */ 584*95b482a8SLen Brown switch (ACPI_GET_OBJECT_TYPE(operand0)) { 585*95b482a8SLen Brown case ACPI_TYPE_INTEGER: 586*95b482a8SLen Brown status = 587*95b482a8SLen Brown acpi_ex_convert_to_integer(operand1, &local_operand1, 16); 588*95b482a8SLen Brown break; 589*95b482a8SLen Brown 590*95b482a8SLen Brown case ACPI_TYPE_STRING: 591*95b482a8SLen Brown status = acpi_ex_convert_to_string(operand1, &local_operand1, 592*95b482a8SLen Brown ACPI_IMPLICIT_CONVERT_HEX); 593*95b482a8SLen Brown break; 594*95b482a8SLen Brown 595*95b482a8SLen Brown case ACPI_TYPE_BUFFER: 596*95b482a8SLen Brown status = acpi_ex_convert_to_buffer(operand1, &local_operand1); 597*95b482a8SLen Brown break; 598*95b482a8SLen Brown 599*95b482a8SLen Brown default: 600*95b482a8SLen Brown status = AE_AML_INTERNAL; 601*95b482a8SLen Brown break; 602*95b482a8SLen Brown } 603*95b482a8SLen Brown 604*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 605*95b482a8SLen Brown goto cleanup; 606*95b482a8SLen Brown } 607*95b482a8SLen Brown 608*95b482a8SLen Brown /* 609*95b482a8SLen Brown * Two cases: 1) Both Integers, 2) Both Strings or Buffers 610*95b482a8SLen Brown */ 611*95b482a8SLen Brown if (ACPI_GET_OBJECT_TYPE(operand0) == ACPI_TYPE_INTEGER) { 612*95b482a8SLen Brown /* 613*95b482a8SLen Brown * 1) Both operands are of type integer 614*95b482a8SLen Brown * Note: local_operand1 may have changed above 615*95b482a8SLen Brown */ 616*95b482a8SLen Brown integer0 = operand0->integer.value; 617*95b482a8SLen Brown integer1 = local_operand1->integer.value; 618*95b482a8SLen Brown 619*95b482a8SLen Brown switch (opcode) { 620*95b482a8SLen Brown case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 621*95b482a8SLen Brown 622*95b482a8SLen Brown if (integer0 == integer1) { 623*95b482a8SLen Brown local_result = TRUE; 624*95b482a8SLen Brown } 625*95b482a8SLen Brown break; 626*95b482a8SLen Brown 627*95b482a8SLen Brown case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 628*95b482a8SLen Brown 629*95b482a8SLen Brown if (integer0 > integer1) { 630*95b482a8SLen Brown local_result = TRUE; 631*95b482a8SLen Brown } 632*95b482a8SLen Brown break; 633*95b482a8SLen Brown 634*95b482a8SLen Brown case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 635*95b482a8SLen Brown 636*95b482a8SLen Brown if (integer0 < integer1) { 637*95b482a8SLen Brown local_result = TRUE; 638*95b482a8SLen Brown } 639*95b482a8SLen Brown break; 640*95b482a8SLen Brown 641*95b482a8SLen Brown default: 642*95b482a8SLen Brown status = AE_AML_INTERNAL; 643*95b482a8SLen Brown break; 644*95b482a8SLen Brown } 645*95b482a8SLen Brown } else { 646*95b482a8SLen Brown /* 647*95b482a8SLen Brown * 2) Both operands are Strings or both are Buffers 648*95b482a8SLen Brown * Note: Code below takes advantage of common Buffer/String 649*95b482a8SLen Brown * object fields. local_operand1 may have changed above. Use 650*95b482a8SLen Brown * memcmp to handle nulls in buffers. 651*95b482a8SLen Brown */ 652*95b482a8SLen Brown length0 = operand0->buffer.length; 653*95b482a8SLen Brown length1 = local_operand1->buffer.length; 654*95b482a8SLen Brown 655*95b482a8SLen Brown /* Lexicographic compare: compare the data bytes */ 656*95b482a8SLen Brown 657*95b482a8SLen Brown compare = ACPI_MEMCMP(operand0->buffer.pointer, 658*95b482a8SLen Brown local_operand1->buffer.pointer, 659*95b482a8SLen Brown (length0 > length1) ? length1 : length0); 660*95b482a8SLen Brown 661*95b482a8SLen Brown switch (opcode) { 662*95b482a8SLen Brown case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 663*95b482a8SLen Brown 664*95b482a8SLen Brown /* Length and all bytes must be equal */ 665*95b482a8SLen Brown 666*95b482a8SLen Brown if ((length0 == length1) && (compare == 0)) { 667*95b482a8SLen Brown 668*95b482a8SLen Brown /* Length and all bytes match ==> TRUE */ 669*95b482a8SLen Brown 670*95b482a8SLen Brown local_result = TRUE; 671*95b482a8SLen Brown } 672*95b482a8SLen Brown break; 673*95b482a8SLen Brown 674*95b482a8SLen Brown case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 675*95b482a8SLen Brown 676*95b482a8SLen Brown if (compare > 0) { 677*95b482a8SLen Brown local_result = TRUE; 678*95b482a8SLen Brown goto cleanup; /* TRUE */ 679*95b482a8SLen Brown } 680*95b482a8SLen Brown if (compare < 0) { 681*95b482a8SLen Brown goto cleanup; /* FALSE */ 682*95b482a8SLen Brown } 683*95b482a8SLen Brown 684*95b482a8SLen Brown /* Bytes match (to shortest length), compare lengths */ 685*95b482a8SLen Brown 686*95b482a8SLen Brown if (length0 > length1) { 687*95b482a8SLen Brown local_result = TRUE; 688*95b482a8SLen Brown } 689*95b482a8SLen Brown break; 690*95b482a8SLen Brown 691*95b482a8SLen Brown case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 692*95b482a8SLen Brown 693*95b482a8SLen Brown if (compare > 0) { 694*95b482a8SLen Brown goto cleanup; /* FALSE */ 695*95b482a8SLen Brown } 696*95b482a8SLen Brown if (compare < 0) { 697*95b482a8SLen Brown local_result = TRUE; 698*95b482a8SLen Brown goto cleanup; /* TRUE */ 699*95b482a8SLen Brown } 700*95b482a8SLen Brown 701*95b482a8SLen Brown /* Bytes match (to shortest length), compare lengths */ 702*95b482a8SLen Brown 703*95b482a8SLen Brown if (length0 < length1) { 704*95b482a8SLen Brown local_result = TRUE; 705*95b482a8SLen Brown } 706*95b482a8SLen Brown break; 707*95b482a8SLen Brown 708*95b482a8SLen Brown default: 709*95b482a8SLen Brown status = AE_AML_INTERNAL; 710*95b482a8SLen Brown break; 711*95b482a8SLen Brown } 712*95b482a8SLen Brown } 713*95b482a8SLen Brown 714*95b482a8SLen Brown cleanup: 715*95b482a8SLen Brown 716*95b482a8SLen Brown /* New object was created if implicit conversion performed - delete */ 717*95b482a8SLen Brown 718*95b482a8SLen Brown if (local_operand1 != operand1) { 719*95b482a8SLen Brown acpi_ut_remove_reference(local_operand1); 720*95b482a8SLen Brown } 721*95b482a8SLen Brown 722*95b482a8SLen Brown /* Return the logical result and status */ 723*95b482a8SLen Brown 724*95b482a8SLen Brown *logical_result = local_result; 725*95b482a8SLen Brown return_ACPI_STATUS(status); 726*95b482a8SLen Brown } 727