aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/dispatcher
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2007-02-02 11:48:18 -0500
committerLen Brown <len.brown@intel.com>2007-02-02 21:14:20 -0500
commit8f9337c88335846b01801b1047a4caf10527a320 (patch)
treeadcd64df3b0949f2bec91adcec749c1a5b36510d /drivers/acpi/dispatcher
parent24058054d781934df526be114c612cf2b29cf4e7 (diff)
ACPICA: Handle case NumElements > Package length
Additional update for NumElements fix. Must handle case where NumElements > Package list length, pad package with null elements. Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/dispatcher')
-rw-r--r--drivers/acpi/dispatcher/dsobject.c87
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
283acpi_status 296acpi_status
284acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, 297acpi_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;