1 2/****************************************************************************** 3 * 4 * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes 5 * $Revision: 1.1.1.1 $ 6 * 7 *****************************************************************************/ 8 9/* 10 * Copyright (C) 2000, 2001 R. Byron Moore 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 */ 26 27 28#include "acpi.h" 29#include "acparser.h" 30#include "acinterp.h" 31#include "amlcode.h" 32#include "acdispat.h" 33 34 35#define _COMPONENT ACPI_EXECUTER 36 MODULE_NAME ("exmisc") 37 38 39/******************************************************************************* 40 * 41 * FUNCTION: Acpi_ex_get_object_reference 42 * 43 * PARAMETERS: Obj_desc - Create a reference to this object 44 * Return_desc - Where to store the reference 45 * 46 * RETURN: Status 47 * 48 * DESCRIPTION: Obtain and return a "reference" to the target object 49 * Common code for the Ref_of_op and the Cond_ref_of_op. 50 * 51 ******************************************************************************/ 52 53acpi_status 54acpi_ex_get_object_reference ( 55 acpi_operand_object *obj_desc, 56 acpi_operand_object **return_desc, 57 acpi_walk_state *walk_state) 58{ 59 acpi_status status = AE_OK; 60 61 62 FUNCTION_TRACE_PTR ("Ex_get_object_reference", obj_desc); 63 64 65 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { 66 if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) { 67 *return_desc = NULL; 68 status = AE_TYPE; 69 goto cleanup; 70 } 71 72 /* 73 * Not a Name -- an indirect name pointer would have 74 * been converted to a direct name pointer in Acpi_ex_resolve_operands 75 */ 76 switch (obj_desc->reference.opcode) { 77 case AML_LOCAL_OP: 78 case AML_ARG_OP: 79 80 *return_desc = (void *) acpi_ds_method_data_get_node (obj_desc->reference.opcode, 81 obj_desc->reference.offset, walk_state); 82 break; 83 84 default: 85 86 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(Internal) Unknown Ref subtype %02x\n", 87 obj_desc->reference.opcode)); 88 *return_desc = NULL; 89 status = AE_AML_INTERNAL; 90 goto cleanup; 91 } 92 93 } 94 95 else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { 96 /* Must be a named object; Just return the Node */ 97 98 *return_desc = obj_desc; 99 } 100 101 else { 102 *return_desc = NULL; 103 status = AE_TYPE; 104 } 105 106 107cleanup: 108 109 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p Ref=%p\n", obj_desc, *return_desc)); 110 return_ACPI_STATUS (status); 111} 112 113 114/******************************************************************************* 115 * 116 * FUNCTION: Acpi_ex_do_concatenate 117 * 118 * PARAMETERS: *Obj_desc - Object to be converted. Must be an 119 * Integer, Buffer, or String 120 * Walk_state - Current walk state 121 * 122 * RETURN: Status 123 * 124 * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. 125 * 126 ******************************************************************************/ 127 128acpi_status 129acpi_ex_do_concatenate ( 130 acpi_operand_object *obj_desc, 131 acpi_operand_object *obj_desc2, 132 acpi_operand_object **actual_return_desc, 133 acpi_walk_state *walk_state) 134{ 135 acpi_status status; 136 u32 i; 137 acpi_integer this_integer; 138 acpi_operand_object *return_desc; 139 NATIVE_CHAR *new_buf; 140 u32 integer_size = sizeof (acpi_integer); 141 142 143 FUNCTION_ENTRY (); 144 145 146 /* 147 * There are three cases to handle: 148 * 1) Two Integers concatenated to produce a buffer 149 * 2) Two Strings concatenated to produce a string 150 * 3) Two Buffers concatenated to produce a buffer 151 */ 152 switch (obj_desc->common.type) { 153 case ACPI_TYPE_INTEGER: 154 155 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ 156 157 if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { 158 /* 159 * We are running a method that exists in a 32-bit ACPI table. 160 * Truncate the value to 32 bits by zeroing out the upper 161 * 32-bit field 162 */ 163 integer_size = sizeof (u32); 164 } 165 166 /* Result of two integers is a buffer */ 167 168 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); 169 if (!return_desc) { 170 return (AE_NO_MEMORY); 171 } 172 173 /* Need enough space for two integers */ 174 175 return_desc->buffer.length = integer_size * 2; 176 new_buf = ACPI_MEM_CALLOCATE (return_desc->buffer.length); 177 if (!new_buf) { 178 REPORT_ERROR 179 (("Ex_do_concatenate: Buffer allocation failure\n")); 180 status = AE_NO_MEMORY; 181 goto cleanup; 182 } 183 184 return_desc->buffer.pointer = (u8 *) new_buf; 185 186 /* Convert the first integer */ 187 188 this_integer = obj_desc->integer.value; 189 for (i = 0; i < integer_size; i++) { 190 new_buf[i] = (u8) this_integer; 191 this_integer >>= 8; 192 } 193 194 /* Convert the second integer */ 195 196 this_integer = obj_desc2->integer.value; 197 for (; i < (integer_size * 2); i++) { 198 new_buf[i] = (u8) this_integer; 199 this_integer >>= 8; 200 } 201 202 break; 203 204 205 case ACPI_TYPE_STRING: 206 207 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); 208 if (!return_desc) { 209 return (AE_NO_MEMORY); 210 } 211 212 /* Operand0 is string */ 213 214 new_buf = ACPI_MEM_ALLOCATE (obj_desc->string.length + 215 obj_desc2->string.length + 1); 216 if (!new_buf) { 217 REPORT_ERROR 218 (("Ex_do_concatenate: String allocation failure\n")); 219 status = AE_NO_MEMORY; 220 goto cleanup; 221 } 222 223 STRCPY (new_buf, obj_desc->string.pointer); 224 STRCPY (new_buf + obj_desc->string.length, 225 obj_desc2->string.pointer); 226 227 /* Point the return object to the new string */ 228 229 return_desc->string.pointer = new_buf; 230 return_desc->string.length = obj_desc->string.length += 231 obj_desc2->string.length; 232 break; 233 234 235 case ACPI_TYPE_BUFFER: 236 237 /* Operand0 is a buffer */ 238 239 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); 240 if (!return_desc) { 241 return (AE_NO_MEMORY); 242 } 243 244 new_buf = ACPI_MEM_ALLOCATE (obj_desc->buffer.length + 245 obj_desc2->buffer.length); 246 if (!new_buf) { 247 REPORT_ERROR 248 (("Ex_do_concatenate: Buffer allocation failure\n")); 249 status = AE_NO_MEMORY; 250 goto cleanup; 251 } 252 253 MEMCPY (new_buf, obj_desc->buffer.pointer, 254 obj_desc->buffer.length); 255 MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer, 256 obj_desc2->buffer.length); 257 258 /* 259 * Point the return object to the new buffer 260 */ 261 262 return_desc->buffer.pointer = (u8 *) new_buf; 263 return_desc->buffer.length = obj_desc->buffer.length + 264 obj_desc2->buffer.length; 265 break; 266 267 268 default: 269 status = AE_AML_INTERNAL; 270 return_desc = NULL; 271 } 272 273 274 *actual_return_desc = return_desc; 275 return (AE_OK); 276 277 278cleanup: 279 280 acpi_ut_remove_reference (return_desc); 281 return (status); 282} 283 284 285/******************************************************************************* 286 * 287 * FUNCTION: Acpi_ex_do_math_op 288 * 289 * PARAMETERS: Opcode - AML opcode 290 * Operand0 - Integer operand #0 291 * Operand0 - Integer operand #1 292 * 293 * RETURN: Integer result of the operation 294 * 295 * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the 296 * math functions here is to prevent a lot of pointer dereferencing 297 * to obtain the operands. 298 * 299 ******************************************************************************/ 300 301acpi_integer 302acpi_ex_do_math_op ( 303 u16 opcode, 304 acpi_integer operand0, 305 acpi_integer operand1) 306{ 307 308 309 switch (opcode) { 310 case AML_ADD_OP: /* Add (Operand0, Operand1, Result) */ 311 312 return (operand0 + operand1); 313 314 315 case AML_BIT_AND_OP: /* And (Operand0, Operand1, Result) */ 316 317 return (operand0 & operand1); 318 319 320 case AML_BIT_NAND_OP: /* NAnd (Operand0, Operand1, Result) */ 321 322 return (~(operand0 & operand1)); 323 324 325 case AML_BIT_OR_OP: /* Or (Operand0, Operand1, Result) */ 326 327 return (operand0 | operand1); 328 329 330 case AML_BIT_NOR_OP: /* NOr (Operand0, Operand1, Result) */ 331 332 return (~(operand0 | operand1)); 333 334 335 case AML_BIT_XOR_OP: /* XOr (Operand0, Operand1, Result) */ 336 337 return (operand0 ^ operand1); 338 339 340 case AML_MULTIPLY_OP: /* Multiply (Operand0, Operand1, Result) */ 341 342 return (operand0 * operand1); 343 344 345 case AML_SHIFT_LEFT_OP: /* Shift_left (Operand, Shift_count, Result) */ 346 347 return (operand0 << operand1); 348 349 350 case AML_SHIFT_RIGHT_OP: /* Shift_right (Operand, Shift_count, Result) */ 351 352 return (operand0 >> operand1); 353 354 355 case AML_SUBTRACT_OP: /* Subtract (Operand0, Operand1, Result) */ 356 357 return (operand0 - operand1); 358 359 default: 360 361 return (0); 362 } 363} 364 365 366/******************************************************************************* 367 * 368 * FUNCTION: Acpi_ex_do_logical_op 369 * 370 * PARAMETERS: Opcode - AML opcode 371 * Operand0 - Integer operand #0 372 * Operand0 - Integer operand #1 373 * 374 * RETURN: TRUE/FALSE result of the operation 375 * 376 * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the 377 * functions here is to prevent a lot of pointer dereferencing 378 * to obtain the operands and to simplify the generation of the 379 * logical value. 380 * 381 * Note: cleanest machine code seems to be produced by the code 382 * below, rather than using statements of the form: 383 * Result = (Operand0 == Operand1); 384 * 385 ******************************************************************************/ 386 387u8 388acpi_ex_do_logical_op ( 389 u16 opcode, 390 acpi_integer operand0, 391 acpi_integer operand1) 392{ 393 394 395 switch (opcode) { 396 397 case AML_LAND_OP: /* LAnd (Operand0, Operand1) */ 398 399 if (operand0 && operand1) { 400 return (TRUE); 401 } 402 break; 403 404 405 case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 406 407 if (operand0 == operand1) { 408 return (TRUE); 409 } 410 break; 411 412 413 case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 414 415 if (operand0 > operand1) { 416 return (TRUE); 417 } 418 break; 419 420 421 case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 422 423 if (operand0 < operand1) { 424 return (TRUE); 425 } 426 break; 427 428 429 case AML_LOR_OP: /* LOr (Operand0, Operand1) */ 430 431 if (operand0 || operand1) { 432 return (TRUE); 433 } 434 break; 435 } 436 437 return (FALSE); 438} 439 440 441