1 2/****************************************************************************** 3 * 4 * Module Name: exresolv - AML Interpreter object resolution 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 "amlcode.h" 30#include "acparser.h" 31#include "acdispat.h" 32#include "acinterp.h" 33#include "acnamesp.h" 34#include "actables.h" 35#include "acevents.h" 36 37 38#define _COMPONENT ACPI_EXECUTER 39 MODULE_NAME ("exresolv") 40 41 42/******************************************************************************* 43 * 44 * FUNCTION: Acpi_ex_get_buffer_field_value 45 * 46 * PARAMETERS: *Obj_desc - Pointer to a Buffer_field 47 * *Result_desc - Pointer to an empty descriptor which will 48 * become an Integer with the field's value 49 * 50 * RETURN: Status 51 * 52 * DESCRIPTION: Retrieve the value from a Buffer_field 53 * 54 ******************************************************************************/ 55 56acpi_status 57acpi_ex_get_buffer_field_value ( 58 acpi_operand_object *obj_desc, 59 acpi_operand_object *result_desc) 60{ 61 acpi_status status; 62 u32 mask; 63 u8 *location; 64 65 66 FUNCTION_TRACE ("Ex_get_buffer_field_value"); 67 68 69 /* 70 * Parameter validation 71 */ 72 if (!obj_desc) { 73 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null field pointer\n")); 74 return_ACPI_STATUS (AE_AML_NO_OPERAND); 75 } 76 77 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { 78 status = acpi_ds_get_buffer_field_arguments (obj_desc); 79 if (ACPI_FAILURE (status)) { 80 return_ACPI_STATUS (status); 81 } 82 } 83 84 if (!obj_desc->buffer_field.buffer_obj) { 85 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null container pointer\n")); 86 return_ACPI_STATUS (AE_AML_INTERNAL); 87 } 88 89 if (ACPI_TYPE_BUFFER != obj_desc->buffer_field.buffer_obj->common.type) { 90 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - container is not a Buffer\n")); 91 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 92 } 93 94 if (!result_desc) { 95 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null result pointer\n")); 96 return_ACPI_STATUS (AE_AML_INTERNAL); 97 } 98 99 100 /* Field location is (base of buffer) + (byte offset) */ 101 102 location = obj_desc->buffer_field.buffer_obj->buffer.pointer 103 + obj_desc->buffer_field.base_byte_offset; 104 105 /* 106 * Construct Mask with as many 1 bits as the field width 107 * 108 * NOTE: Only the bottom 5 bits are valid for a shift operation, so 109 * special care must be taken for any shift greater than 31 bits. 110 * 111 * TBD: [Unhandled] Fields greater than 32 bits will not work. 112 */ 113 if (obj_desc->buffer_field.bit_length < 32) { 114 mask = ((u32) 1 << obj_desc->buffer_field.bit_length) - (u32) 1; 115 } 116 else { 117 mask = ACPI_UINT32_MAX; 118 } 119 120 result_desc->integer.type = (u8) ACPI_TYPE_INTEGER; 121 122 /* Get the 32 bit value at the location */ 123 124 MOVE_UNALIGNED32_TO_32 (&result_desc->integer.value, location); 125 126 /* 127 * Shift the 32-bit word containing the field, and mask off the 128 * resulting value 129 */ 130 result_desc->integer.value = 131 (result_desc->integer.value >> obj_desc->buffer_field.start_field_bit_offset) & mask; 132 133 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 134 "** Read from buffer %p byte %d bit %d width %d addr %p mask %08X val %8.8X%8.8X\n", 135 obj_desc->buffer_field.buffer_obj->buffer.pointer, 136 obj_desc->buffer_field.base_byte_offset, 137 obj_desc->buffer_field.start_field_bit_offset, 138 obj_desc->buffer_field.bit_length, 139 location, mask, 140 HIDWORD(result_desc->integer.value), 141 LODWORD(result_desc->integer.value))); 142 143 return_ACPI_STATUS (AE_OK); 144} 145 146 147/******************************************************************************* 148 * 149 * FUNCTION: Acpi_ex_resolve_to_value 150 * 151 * PARAMETERS: **Stack_ptr - Points to entry on Obj_stack, which can 152 * be either an (acpi_operand_object *) 153 * or an acpi_handle. 154 * Walk_state - Current method state 155 * 156 * RETURN: Status 157 * 158 * DESCRIPTION: Convert Reference objects to values 159 * 160 ******************************************************************************/ 161 162acpi_status 163acpi_ex_resolve_to_value ( 164 acpi_operand_object **stack_ptr, 165 acpi_walk_state *walk_state) 166{ 167 acpi_status status; 168 169 170 FUNCTION_TRACE_PTR ("Ex_resolve_to_value", stack_ptr); 171 172 173 if (!stack_ptr || !*stack_ptr) { 174 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null pointer\n")); 175 return_ACPI_STATUS (AE_AML_NO_OPERAND); 176 } 177 178 179 /* 180 * The entity pointed to by the Stack_ptr can be either 181 * 1) A valid acpi_operand_object, or 182 * 2) A acpi_namespace_node (Named_obj) 183 */ 184 if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_INTERNAL)) { 185 status = acpi_ex_resolve_object_to_value (stack_ptr, walk_state); 186 if (ACPI_FAILURE (status)) { 187 return_ACPI_STATUS (status); 188 } 189 } 190 191 /* 192 * Object on the stack may have changed if Acpi_ex_resolve_object_to_value() 193 * was called (i.e., we can't use an _else_ here.) 194 */ 195 if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_NAMED)) { 196 status = acpi_ex_resolve_node_to_value ((acpi_namespace_node **) stack_ptr, 197 walk_state); 198 if (ACPI_FAILURE (status)) { 199 return_ACPI_STATUS (status); 200 } 201 } 202 203 204 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Resolved object %p\n", *stack_ptr)); 205 return_ACPI_STATUS (AE_OK); 206} 207 208 209/******************************************************************************* 210 * 211 * FUNCTION: Acpi_ex_resolve_object_to_value 212 * 213 * PARAMETERS: Stack_ptr - Pointer to a stack location that contains a 214 * ptr to an internal object. 215 * Walk_state - Current method state 216 * 217 * RETURN: Status 218 * 219 * DESCRIPTION: Retrieve the value from an internal object. The Reference type 220 * uses the associated AML opcode to determine the value. 221 * 222 ******************************************************************************/ 223 224acpi_status 225acpi_ex_resolve_object_to_value ( 226 acpi_operand_object **stack_ptr, 227 acpi_walk_state *walk_state) 228{ 229 acpi_status status = AE_OK; 230 acpi_operand_object *stack_desc; 231 void *temp_node; 232 acpi_operand_object *obj_desc; 233 u16 opcode; 234 235 236 FUNCTION_TRACE ("Ex_resolve_object_to_value"); 237 238 239 stack_desc = *stack_ptr; 240 241 /* This is an acpi_operand_object */ 242 243 switch (stack_desc->common.type) { 244 245 case INTERNAL_TYPE_REFERENCE: 246 247 opcode = stack_desc->reference.opcode; 248 249 switch (opcode) { 250 251 case AML_NAME_OP: 252 253 /* 254 * Convert indirect name ptr to a direct name ptr. 255 * Then, Acpi_ex_resolve_node_to_value can be used to get the value 256 */ 257 temp_node = stack_desc->reference.object; 258 259 /* Delete the Reference Object */ 260 261 acpi_ut_remove_reference (stack_desc); 262 263 /* Put direct name pointer onto stack and exit */ 264 265 (*stack_ptr) = temp_node; 266 break; 267 268 269 case AML_LOCAL_OP: 270 case AML_ARG_OP: 271 272 /* 273 * Get the local from the method's state info 274 * Note: this increments the local's object reference count 275 */ 276 status = acpi_ds_method_data_get_value (opcode, 277 stack_desc->reference.offset, walk_state, &obj_desc); 278 if (ACPI_FAILURE (status)) { 279 return_ACPI_STATUS (status); 280 } 281 282 /* 283 * Now we can delete the original Reference Object and 284 * replace it with the resolve value 285 */ 286 acpi_ut_remove_reference (stack_desc); 287 *stack_ptr = obj_desc; 288 289 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "[Arg/Local %d] Value_obj is %p\n", 290 stack_desc->reference.offset, obj_desc)); 291 break; 292 293 294 /* 295 * For constants, we must change the reference/constant object 296 * to a real integer object 297 */ 298 case AML_ZERO_OP: 299 case AML_ONE_OP: 300 case AML_ONES_OP: 301 case AML_REVISION_OP: 302 303 /* Create a new integer object */ 304 305 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); 306 if (!obj_desc) { 307 return_ACPI_STATUS (AE_NO_MEMORY); 308 } 309 310 switch (opcode) { 311 case AML_ZERO_OP: 312 obj_desc->integer.value = 0; 313 break; 314 315 case AML_ONE_OP: 316 obj_desc->integer.value = 1; 317 break; 318 319 case AML_ONES_OP: 320 obj_desc->integer.value = ACPI_INTEGER_MAX; 321 322 /* Truncate value if we are executing from a 32-bit ACPI table */ 323 324 acpi_ex_truncate_for32bit_table (obj_desc, walk_state); 325 break; 326 327 case AML_REVISION_OP: 328 obj_desc->integer.value = ACPI_CA_SUPPORT_LEVEL; 329 break; 330 } 331 332 /* 333 * Remove a reference from the original reference object 334 * and put the new object in its place 335 */ 336 acpi_ut_remove_reference (stack_desc); 337 *stack_ptr = obj_desc; 338 break; 339 340 341 case AML_INDEX_OP: 342 343 switch (stack_desc->reference.target_type) { 344 case ACPI_TYPE_BUFFER_FIELD: 345 346 /* Just return - leave the Reference on the stack */ 347 break; 348 349 350 case ACPI_TYPE_PACKAGE: 351 obj_desc = *stack_desc->reference.where; 352 if (obj_desc) { 353 /* 354 * Valid obj descriptor, copy pointer to return value 355 * (i.e., dereference the package index) 356 * Delete the ref object, increment the returned object 357 */ 358 acpi_ut_remove_reference (stack_desc); 359 acpi_ut_add_reference (obj_desc); 360 *stack_ptr = obj_desc; 361 } 362 363 else { 364 /* 365 * A NULL object descriptor means an unitialized element of 366 * the package, can't dereference it 367 */ 368 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 369 "Attempt to deref an Index to NULL pkg element Idx=%p\n", 370 stack_desc)); 371 status = AE_AML_UNINITIALIZED_ELEMENT; 372 } 373 break; 374 375 default: 376 /* Invalid reference object */ 377 378 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 379 "Unknown Target_type %X in Index/Reference obj %p\n", 380 stack_desc->reference.target_type, stack_desc)); 381 status = AE_AML_INTERNAL; 382 break; 383 } 384 385 break; 386 387 388 case AML_DEBUG_OP: 389 390 /* Just leave the object as-is */ 391 break; 392 393 394 default: 395 396 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference object subtype %02X in %p\n", 397 opcode, stack_desc)); 398 status = AE_AML_INTERNAL; 399 break; 400 401 } /* switch (Opcode) */ 402 403 break; /* case INTERNAL_TYPE_REFERENCE */ 404 405 406 case ACPI_TYPE_BUFFER_FIELD: 407 408 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_ANY); 409 if (!obj_desc) { 410 return_ACPI_STATUS (AE_NO_MEMORY); 411 } 412 413 status = acpi_ex_get_buffer_field_value (stack_desc, obj_desc); 414 if (ACPI_FAILURE (status)) { 415 acpi_ut_remove_reference (obj_desc); 416 obj_desc = NULL; 417 } 418 419 *stack_ptr = (void *) obj_desc; 420 break; 421 422 423 case INTERNAL_TYPE_BANK_FIELD: 424 425 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_ANY); 426 if (!obj_desc) { 427 return_ACPI_STATUS (AE_NO_MEMORY); 428 } 429 430 /* TBD: WRONG! */ 431 432 status = acpi_ex_get_buffer_field_value (stack_desc, obj_desc); 433 if (ACPI_FAILURE (status)) { 434 acpi_ut_remove_reference (obj_desc); 435 obj_desc = NULL; 436 } 437 438 *stack_ptr = (void *) obj_desc; 439 break; 440 441 442 /* TBD: [Future] - may need to handle Index_field, and Def_field someday */ 443 444 default: 445 446 break; 447 448 } /* switch (Stack_desc->Common.Type) */ 449 450 451 return_ACPI_STATUS (status); 452} 453 454 455