diff options
| -rw-r--r-- | drivers/acpi/dispatcher/dsobject.c | 87 |
1 files changed, 41 insertions, 46 deletions
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index aaeb9f987ecc..f9f6862b1dff 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c | |||
| @@ -260,7 +260,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, | |||
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | obj_desc->buffer.flags |= AOPOBJ_DATA_VALID; | 262 | obj_desc->buffer.flags |= AOPOBJ_DATA_VALID; |
| 263 | op->common.node = (struct acpi_namespace_node *)obj_desc; | 263 | op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); |
| 264 | return_ACPI_STATUS(AE_OK); | 264 | return_ACPI_STATUS(AE_OK); |
| 265 | } | 265 | } |
| 266 | 266 | ||
| @@ -270,7 +270,8 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, | |||
| 270 | * | 270 | * |
| 271 | * PARAMETERS: walk_state - Current walk state | 271 | * PARAMETERS: walk_state - Current walk state |
| 272 | * Op - Parser object to be translated | 272 | * Op - Parser object to be translated |
| 273 | * package_length - Number of elements in the package | 273 | * element_count - Number of elements in the package - this is |
| 274 | * the num_elements argument to Package() | ||
| 274 | * obj_desc_ptr - Where the ACPI internal object is returned | 275 | * obj_desc_ptr - Where the ACPI internal object is returned |
| 275 | * | 276 | * |
| 276 | * RETURN: Status | 277 | * RETURN: Status |
| @@ -278,18 +279,29 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, | |||
| 278 | * DESCRIPTION: Translate a parser Op package object to the equivalent | 279 | * DESCRIPTION: Translate a parser Op package object to the equivalent |
| 279 | * namespace object | 280 | * namespace object |
| 280 | * | 281 | * |
| 282 | * NOTE: The number of elements in the package will be always be the num_elements | ||
| 283 | * count, regardless of the number of elements in the package list. If | ||
| 284 | * num_elements is smaller, only that many package list elements are used. | ||
| 285 | * if num_elements is larger, the Package object is padded out with | ||
| 286 | * objects of type Uninitialized (as per ACPI spec.) | ||
| 287 | * | ||
| 288 | * Even though the ASL compilers do not allow num_elements to be smaller | ||
| 289 | * than the Package list length (for the fixed length package opcode), some | ||
| 290 | * BIOS code modifies the AML on the fly to adjust the num_elements, and | ||
| 291 | * this code compensates for that. This also provides compatibility with | ||
| 292 | * other AML interpreters. | ||
| 293 | * | ||
| 281 | ******************************************************************************/ | 294 | ******************************************************************************/ |
| 282 | 295 | ||
| 283 | acpi_status | 296 | acpi_status |
| 284 | acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | 297 | acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, |
| 285 | union acpi_parse_object *op, | 298 | union acpi_parse_object *op, |
| 286 | u32 package_length, | 299 | u32 element_count, |
| 287 | union acpi_operand_object **obj_desc_ptr) | 300 | union acpi_operand_object **obj_desc_ptr) |
| 288 | { | 301 | { |
| 289 | union acpi_parse_object *arg; | 302 | union acpi_parse_object *arg; |
| 290 | union acpi_parse_object *parent; | 303 | union acpi_parse_object *parent; |
| 291 | union acpi_operand_object *obj_desc = NULL; | 304 | union acpi_operand_object *obj_desc = NULL; |
| 292 | u32 package_list_length; | ||
| 293 | acpi_status status = AE_OK; | 305 | acpi_status status = AE_OK; |
| 294 | acpi_native_uint i; | 306 | acpi_native_uint i; |
| 295 | 307 | ||
| @@ -318,43 +330,13 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
| 318 | obj_desc->package.node = parent->common.node; | 330 | obj_desc->package.node = parent->common.node; |
| 319 | } | 331 | } |
| 320 | 332 | ||
| 321 | /* Count the *actual* number of items in the package list */ | ||
| 322 | |||
| 323 | arg = op->common.value.arg; | ||
| 324 | arg = arg->common.next; | ||
| 325 | for (package_list_length = 0; arg; package_list_length++) { | ||
| 326 | arg = arg->common.next; | ||
| 327 | } | ||
| 328 | |||
| 329 | /* | ||
| 330 | * The number of elements in the package will be the lesser of the | ||
| 331 | * specified element count and the length of the initializer list. | ||
| 332 | * | ||
| 333 | * Even though the ASL compilers do not allow this to happen (for the | ||
| 334 | * fixed length package opcode), some BIOS code modifies the AML on the | ||
| 335 | * fly to adjust the package length, and this code compensates for that. | ||
| 336 | * This also provides compatibility with other AML interpreters. | ||
| 337 | */ | ||
| 338 | obj_desc->package.count = package_length; | ||
| 339 | |||
| 340 | if (package_list_length != package_length) { | ||
| 341 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 342 | "Package length mismatch, using lesser of %X(Length Arg) and %X(AML Length)\n", | ||
| 343 | package_length, package_list_length)); | ||
| 344 | |||
| 345 | if (package_list_length < package_length) { | ||
| 346 | obj_desc->package.count = package_list_length; | ||
| 347 | } | ||
| 348 | } | ||
| 349 | |||
| 350 | /* | 333 | /* |
| 351 | * Allocate the pointer array (array of pointers to the | 334 | * Allocate the element array (array of pointers to the individual |
| 352 | * individual objects). Add an extra pointer slot so | 335 | * objects) based on the num_elements parameter. Add an extra pointer slot |
| 353 | * that the list is always null terminated. | 336 | * so that the list is always null terminated. |
| 354 | */ | 337 | */ |
| 355 | obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) | 338 | obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) |
| 356 | obj_desc->package. | 339 | element_count + |
| 357 | count + | ||
| 358 | 1) * sizeof(void *)); | 340 | 1) * sizeof(void *)); |
| 359 | 341 | ||
| 360 | if (!obj_desc->package.elements) { | 342 | if (!obj_desc->package.elements) { |
| @@ -362,15 +344,20 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
| 362 | return_ACPI_STATUS(AE_NO_MEMORY); | 344 | return_ACPI_STATUS(AE_NO_MEMORY); |
| 363 | } | 345 | } |
| 364 | 346 | ||
| 347 | obj_desc->package.count = element_count; | ||
| 348 | |||
| 365 | /* | 349 | /* |
| 366 | * Initialize all elements of the package | 350 | * Initialize the elements of the package, up to the num_elements count. |
| 351 | * Package is automatically padded with uninitialized (NULL) elements | ||
| 352 | * if num_elements is greater than the package list length. Likewise, | ||
| 353 | * Package is truncated if num_elements is less than the list length. | ||
| 367 | */ | 354 | */ |
| 368 | arg = op->common.value.arg; | 355 | arg = op->common.value.arg; |
| 369 | arg = arg->common.next; | 356 | arg = arg->common.next; |
| 370 | for (i = 0; i < obj_desc->package.count; i++) { | 357 | for (i = 0; arg && (i < element_count); i++) { |
| 371 | if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { | 358 | if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { |
| 372 | 359 | ||
| 373 | /* Object (package or buffer) is already built */ | 360 | /* This package element is already built, just get it */ |
| 374 | 361 | ||
| 375 | obj_desc->package.elements[i] = | 362 | obj_desc->package.elements[i] = |
| 376 | ACPI_CAST_PTR(union acpi_operand_object, | 363 | ACPI_CAST_PTR(union acpi_operand_object, |
| @@ -384,8 +371,14 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
| 384 | arg = arg->common.next; | 371 | arg = arg->common.next; |
| 385 | } | 372 | } |
| 386 | 373 | ||
| 374 | if (!arg) { | ||
| 375 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 376 | "Package List length larger than NumElements count (%X), truncated\n", | ||
| 377 | element_count)); | ||
| 378 | } | ||
| 379 | |||
| 387 | obj_desc->package.flags |= AOPOBJ_DATA_VALID; | 380 | obj_desc->package.flags |= AOPOBJ_DATA_VALID; |
| 388 | op->common.node = (struct acpi_namespace_node *)obj_desc; | 381 | op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); |
| 389 | return_ACPI_STATUS(status); | 382 | return_ACPI_STATUS(status); |
| 390 | } | 383 | } |
| 391 | 384 | ||
| @@ -499,8 +492,9 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, | |||
| 499 | /* | 492 | /* |
| 500 | * Defer evaluation of Buffer term_arg operand | 493 | * Defer evaluation of Buffer term_arg operand |
| 501 | */ | 494 | */ |
| 502 | obj_desc->buffer.node = (struct acpi_namespace_node *) | 495 | obj_desc->buffer.node = |
| 503 | walk_state->operands[0]; | 496 | ACPI_CAST_PTR(struct acpi_namespace_node, |
| 497 | walk_state->operands[0]); | ||
| 504 | obj_desc->buffer.aml_start = op->named.data; | 498 | obj_desc->buffer.aml_start = op->named.data; |
| 505 | obj_desc->buffer.aml_length = op->named.length; | 499 | obj_desc->buffer.aml_length = op->named.length; |
| 506 | break; | 500 | break; |
| @@ -510,8 +504,9 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, | |||
| 510 | /* | 504 | /* |
| 511 | * Defer evaluation of Package term_arg operand | 505 | * Defer evaluation of Package term_arg operand |
| 512 | */ | 506 | */ |
| 513 | obj_desc->package.node = (struct acpi_namespace_node *) | 507 | obj_desc->package.node = |
| 514 | walk_state->operands[0]; | 508 | ACPI_CAST_PTR(struct acpi_namespace_node, |
| 509 | walk_state->operands[0]); | ||
| 515 | obj_desc->package.aml_start = op->named.data; | 510 | obj_desc->package.aml_start = op->named.data; |
| 516 | obj_desc->package.aml_length = op->named.length; | 511 | obj_desc->package.aml_length = op->named.length; |
| 517 | break; | 512 | break; |
