summaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2009-07-24 05:22:11 +0200
committerLen Brown <len.brown@intel.com>2009-08-29 01:40:38 +0200
commit53e9387bdd8bfef6cffff2d2eb6bd28eca812682 (patch)
tree5c69463c9c13640435f2ba91bc194c25b2dbb047 /drivers/acpi
parentACPICA: Add repair for predefined methods that return nested packages (diff)
downloadlinux-53e9387bdd8bfef6cffff2d2eb6bd28eca812682.tar.xz
linux-53e9387bdd8bfef6cffff2d2eb6bd28eca812682.zip
ACPICA: ACPI 4.0 : Add new return package type, restructure module.
Added one new package type, a package that contains a revision number and a variable number of sub-packages. Restructured the module to put the sub-package list traversal in a separate function. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpica/acpredef.h5
-rw-r--r--drivers/acpi/acpica/nspredef.c326
2 files changed, 196 insertions, 135 deletions
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h
index 63f656ae3604..144b1f41663f 100644
--- a/drivers/acpi/acpica/acpredef.h
+++ b/drivers/acpi/acpica/acpredef.h
@@ -91,6 +91,8 @@
* ACPI_PTYPE2_MIN: Each subpackage has a variable but minimum length
* (Used for _HPX)
*
+ * ACPI_PTYPE2_REV_FIXED: Revision at start, each subpackage is Fixed-length
+ *
*****************************************************************************/
enum acpi_return_package_types {
@@ -101,7 +103,8 @@ enum acpi_return_package_types {
ACPI_PTYPE2_COUNT = 5,
ACPI_PTYPE2_PKG_COUNT = 6,
ACPI_PTYPE2_FIXED = 7,
- ACPI_PTYPE2_MIN = 8
+ ACPI_PTYPE2_MIN = 8,
+ ACPI_PTYPE2_REV_FIXED = 9
};
/*
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index 0091504df074..0b2cdb37a678 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -76,6 +76,11 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
union acpi_operand_object **return_object_ptr);
static acpi_status
+acpi_ns_check_package_list(struct acpi_predefined_data *data,
+ const union acpi_predefined_info *package,
+ union acpi_operand_object **elements, u32 count);
+
+static acpi_status
acpi_ns_check_package_elements(struct acpi_predefined_data *data,
union acpi_operand_object **elements,
u8 type1,
@@ -393,14 +398,11 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
{
union acpi_operand_object *return_object = *return_object_ptr;
const union acpi_predefined_info *package;
- union acpi_operand_object *sub_package;
union acpi_operand_object **elements;
- union acpi_operand_object **sub_elements;
- acpi_status status;
+ acpi_status status = AE_OK;
u32 expected_count;
u32 count;
u32 i;
- u32 j;
ACPI_FUNCTION_NAME(ns_check_package);
@@ -465,9 +467,6 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
object_type2,
package->ret_info.
count2, 0);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
break;
case ACPI_PTYPE1_VAR:
@@ -534,6 +533,25 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
}
break;
+ case ACPI_PTYPE2_REV_FIXED:
+
+ /* First element is the (Integer) revision */
+
+ status = acpi_ns_check_object_type(data, elements,
+ ACPI_RTYPE_INTEGER, 0);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ elements++;
+ count--;
+
+ /* Examine the sub-packages */
+
+ status =
+ acpi_ns_check_package_list(data, package, elements, count);
+ break;
+
case ACPI_PTYPE2_PKG_COUNT:
/* First element is the (Integer) count of sub-packages to follow */
@@ -556,9 +574,11 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
count = expected_count;
elements++;
- /* Now we can walk the sub-packages */
+ /* Examine the sub-packages */
- /*lint -fallthrough */
+ status =
+ acpi_ns_check_package_list(data, package, elements, count);
+ break;
case ACPI_PTYPE2:
case ACPI_PTYPE2_FIXED:
@@ -593,175 +613,213 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
count = 1;
}
- /* Validate each sub-Package in the parent Package */
+ /* Examine the sub-packages */
- for (i = 0; i < count; i++) {
- sub_package = *elements;
- sub_elements = sub_package->package.elements;
+ status =
+ acpi_ns_check_package_list(data, package, elements, count);
+ break;
- /* Each sub-object must be of type Package */
+ default:
- status = acpi_ns_check_object_type(data, &sub_package,
- ACPI_RTYPE_PACKAGE,
- i);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
+ /* Should not get here if predefined info table is correct */
- /* Examine the different types of sub-packages */
+ ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
+ "Invalid internal return type in table entry: %X",
+ package->ret_info.type));
- switch (package->ret_info.type) {
- case ACPI_PTYPE2:
- case ACPI_PTYPE2_PKG_COUNT:
+ return (AE_AML_INTERNAL);
+ }
- /* Each subpackage has a fixed number of elements */
+ return (status);
- expected_count =
- package->ret_info.count1 +
- package->ret_info.count2;
- if (sub_package->package.count !=
- expected_count) {
- count = sub_package->package.count;
- goto package_too_small;
- }
+package_too_small:
- status =
- acpi_ns_check_package_elements(data,
- sub_elements,
- package->
- ret_info.
- object_type1,
- package->
- ret_info.
- count1,
- package->
- ret_info.
- object_type2,
- package->
- ret_info.
- count2, 0);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
- break;
+ /* Error exit for the case with an incorrect package count */
- case ACPI_PTYPE2_FIXED:
+ ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
+ "Return Package is too small - found %u elements, expected %u",
+ count, expected_count));
- /* Each sub-package has a fixed length */
+ return (AE_AML_OPERAND_VALUE);
+}
- expected_count = package->ret_info2.count;
- if (sub_package->package.count < expected_count) {
- count = sub_package->package.count;
- goto package_too_small;
- }
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_check_package_list
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * Package - Pointer to package-specific info for method
+ * Elements - Element list of parent package. All elements
+ * of this list should be of type Package.
+ * Count - Count of subpackages
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Examine a list of subpackages
+ *
+ ******************************************************************************/
- /* Check the type of each sub-package element */
+static acpi_status
+acpi_ns_check_package_list(struct acpi_predefined_data *data,
+ const union acpi_predefined_info *package,
+ union acpi_operand_object **elements, u32 count)
+{
+ union acpi_operand_object *sub_package;
+ union acpi_operand_object **sub_elements;
+ acpi_status status;
+ u32 expected_count;
+ u32 i;
+ u32 j;
- for (j = 0; j < expected_count; j++) {
- status =
- acpi_ns_check_object_type(data,
- &sub_elements[j],
- package->ret_info2.object_type[j], j);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
- }
- break;
+ /* Validate each sub-Package in the parent Package */
- case ACPI_PTYPE2_MIN:
+ for (i = 0; i < count; i++) {
+ sub_package = *elements;
+ sub_elements = sub_package->package.elements;
- /* Each sub-package has a variable but minimum length */
+ /* Each sub-object must be of type Package */
- expected_count = package->ret_info.count1;
- if (sub_package->package.count < expected_count) {
- count = sub_package->package.count;
- goto package_too_small;
- }
+ status = acpi_ns_check_object_type(data, &sub_package,
+ ACPI_RTYPE_PACKAGE, i);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
- /* Check the type of each sub-package element */
+ /* Examine the different types of expected sub-packages */
- status =
- acpi_ns_check_package_elements(data,
- sub_elements,
- package->
- ret_info.
- object_type1,
- sub_package->
- package.
- count, 0, 0,
- 0);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
- break;
+ switch (package->ret_info.type) {
+ case ACPI_PTYPE2:
+ case ACPI_PTYPE2_PKG_COUNT:
+ case ACPI_PTYPE2_REV_FIXED:
+
+ /* Each subpackage has a fixed number of elements */
+
+ expected_count =
+ package->ret_info.count1 + package->ret_info.count2;
+ if (sub_package->package.count < expected_count) {
+ goto package_too_small;
+ }
+
+ status =
+ acpi_ns_check_package_elements(data, sub_elements,
+ package->ret_info.
+ object_type1,
+ package->ret_info.
+ count1,
+ package->ret_info.
+ object_type2,
+ package->ret_info.
+ count2, 0);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ break;
+
+ case ACPI_PTYPE2_FIXED:
+
+ /* Each sub-package has a fixed length */
- case ACPI_PTYPE2_COUNT:
+ expected_count = package->ret_info2.count;
+ if (sub_package->package.count < expected_count) {
+ goto package_too_small;
+ }
- /* First element is the (Integer) count of elements to follow */
+ /* Check the type of each sub-package element */
+ for (j = 0; j < expected_count; j++) {
status =
acpi_ns_check_object_type(data,
- sub_elements,
- ACPI_RTYPE_INTEGER,
- 0);
+ &sub_elements[j],
+ package->
+ ret_info2.
+ object_type[j],
+ j);
if (ACPI_FAILURE(status)) {
return (status);
}
+ }
+ break;
- /* Make sure package is large enough for the Count */
+ case ACPI_PTYPE2_MIN:
- expected_count =
- (u32) (*sub_elements)->integer.value;
- if (sub_package->package.count < expected_count) {
- count = sub_package->package.count;
- goto package_too_small;
- }
+ /* Each sub-package has a variable but minimum length */
- /* Check the type of each sub-package element */
+ expected_count = package->ret_info.count1;
+ if (sub_package->package.count < expected_count) {
+ goto package_too_small;
+ }
- status =
- acpi_ns_check_package_elements(data,
- (sub_elements
- + 1),
- package->
- ret_info.
- object_type1,
- (expected_count
- - 1), 0, 0,
- 1);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
- break;
+ /* Check the type of each sub-package element */
- default:
- break;
+ status =
+ acpi_ns_check_package_elements(data, sub_elements,
+ package->ret_info.
+ object_type1,
+ sub_package->package.
+ count, 0, 0, 0);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
+ break;
- elements++;
- }
- break;
+ case ACPI_PTYPE2_COUNT:
- default:
+ /*
+ * First element is the (Integer) count of elements, including
+ * the count field.
+ */
+ status = acpi_ns_check_object_type(data, sub_elements,
+ ACPI_RTYPE_INTEGER,
+ 0);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
- /* Should not get here if predefined info table is correct */
+ /*
+ * Make sure package is large enough for the Count and is
+ * is as large as the minimum size
+ */
+ expected_count = (u32)(*sub_elements)->integer.value;
+ if (sub_package->package.count < expected_count) {
+ goto package_too_small;
+ }
+ if (sub_package->package.count <
+ package->ret_info.count1) {
+ expected_count = package->ret_info.count1;
+ goto package_too_small;
+ }
- ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
- "Invalid internal return type in table entry: %X",
- package->ret_info.type));
+ /* Check the type of each sub-package element */
- return (AE_AML_INTERNAL);
+ status =
+ acpi_ns_check_package_elements(data,
+ (sub_elements + 1),
+ package->ret_info.
+ object_type1,
+ (expected_count - 1),
+ 0, 0, 1);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ break;
+
+ default: /* Should not get here, type was validated by caller */
+
+ return (AE_AML_INTERNAL);
+ }
+
+ elements++;
}
return (AE_OK);
- package_too_small:
+package_too_small:
- /* Error exit for the case with an incorrect package count */
+ /* The sub-package count was smaller than required */
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
- "Return Package is too small - found %u, expected %u",
- count, expected_count));
+ "Return Sub-Package[%u] is too small - found %u elements, expected %u",
+ i, sub_package->package.count, expected_count));
return (AE_AML_OPERAND_VALUE);
}