diff options
author | Bob Moore <robert.moore@intel.com> | 2007-02-02 11:48:18 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-02-02 21:14:20 -0500 |
commit | 24058054d781934df526be114c612cf2b29cf4e7 (patch) | |
tree | 66ca3e558fea81ec8ec38127f49df17c88f51115 | |
parent | c9e3ba2c1d178195e17bb4f1d49c32e0be8dbb16 (diff) |
ACPICA: Handle mis-matched package length
Implement support within the AML interpreter for
package objects that contain a mismatch between the AML
length and package element count. In this case, the lesser
of the two is used. Some BIOS code apparently modifies
the package length on the fly, and this change supports
this. Provides compatibility with the MS AML interpreter.
Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/acpi/dispatcher/dsobject.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 72190abb1d59..aaeb9f987ecc 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c | |||
@@ -318,9 +318,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
318 | obj_desc->package.node = parent->common.node; | 318 | obj_desc->package.node = parent->common.node; |
319 | } | 319 | } |
320 | 320 | ||
321 | obj_desc->package.count = package_length; | 321 | /* Count the *actual* number of items in the package list */ |
322 | |||
323 | /* Count the number of items in the package list */ | ||
324 | 322 | ||
325 | arg = op->common.value.arg; | 323 | arg = op->common.value.arg; |
326 | arg = arg->common.next; | 324 | arg = arg->common.next; |
@@ -329,11 +327,24 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
329 | } | 327 | } |
330 | 328 | ||
331 | /* | 329 | /* |
332 | * The package length (number of elements) will be the greater | 330 | * The number of elements in the package will be the lesser of the |
333 | * of the specified length and the length of the initializer list | 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. | ||
334 | */ | 337 | */ |
335 | if (package_list_length > package_length) { | 338 | obj_desc->package.count = package_length; |
336 | obj_desc->package.count = package_list_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 | } | ||
337 | } | 348 | } |
338 | 349 | ||
339 | /* | 350 | /* |
@@ -356,7 +367,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
356 | */ | 367 | */ |
357 | arg = op->common.value.arg; | 368 | arg = op->common.value.arg; |
358 | arg = arg->common.next; | 369 | arg = arg->common.next; |
359 | for (i = 0; arg; i++) { | 370 | for (i = 0; i < obj_desc->package.count; i++) { |
360 | if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { | 371 | if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { |
361 | 372 | ||
362 | /* Object (package or buffer) is already built */ | 373 | /* Object (package or buffer) is already built */ |