diff options
-rw-r--r-- | drivers/acpi/acpica/acpredef.h | 5 | ||||
-rw-r--r-- | drivers/acpi/acpica/nspredef.c | 326 |
2 files changed, 196 insertions, 135 deletions
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index 63f656ae360..144b1f41663 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 0091504df07..0b2cdb37a67 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); } |