Commit d4085a3f authored by Bob Moore's avatar Bob Moore Committed by Len Brown

ACPICA: Predefined name repair: automatically remove null package elements

This change will automatically remove embedded and trailing NULL
package elements from returned package objects that are defined
to containe a variable number of sub-packages. The driver is then
presented with a package with no null elements to deal with.
ACPICA BZ 819.

http://www.acpica.org/bugzilla/show_bug.cgi?id=819Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent e31c32cf
...@@ -296,6 +296,11 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data, ...@@ -296,6 +296,11 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
acpi_status validate_status, acpi_status validate_status,
union acpi_operand_object **return_object_ptr); union acpi_operand_object **return_object_ptr);
void
acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
u8 package_type,
union acpi_operand_object *obj_desc);
/* /*
* nssearch - Namespace searching and entry * nssearch - Namespace searching and entry
*/ */
......
...@@ -231,9 +231,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, ...@@ -231,9 +231,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
* Note: Package may have been newly created by call above. * Note: Package may have been newly created by call above.
*/ */
if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) {
/* TBD: For variable-length Packages, remove NULL elements here */
status = acpi_ns_check_package(data, return_object_ptr); status = acpi_ns_check_package(data, return_object_ptr);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto exit; goto exit;
...@@ -439,6 +436,13 @@ acpi_ns_check_package(struct acpi_predefined_data *data, ...@@ -439,6 +436,13 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
data->pathname, package->ret_info.type, data->pathname, package->ret_info.type,
return_object->package.count)); return_object->package.count));
/*
* For variable-length Packages, we can safely remove all embedded
* and trailing NULL package elements
*/
acpi_ns_remove_null_elements(data, package->ret_info.type,
return_object);
/* Extract package count and elements array */ /* Extract package count and elements array */
elements = return_object->package.elements; elements = return_object->package.elements;
...@@ -692,53 +696,18 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, ...@@ -692,53 +696,18 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
union acpi_operand_object *sub_package; union acpi_operand_object *sub_package;
union acpi_operand_object **sub_elements; union acpi_operand_object **sub_elements;
acpi_status status; acpi_status status;
u8 non_trailing_null = FALSE;
u32 expected_count; u32 expected_count;
u32 i; u32 i;
u32 j; u32 j;
/* Validate each sub-Package in the parent Package */ /*
* Validate each sub-Package in the parent Package
*
* NOTE: assumes list of sub-packages contains no NULL elements.
* Any NULL elements should have been removed by earlier call
* to acpi_ns_remove_null_elements.
*/
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
/*
* Handling for NULL package elements. For now, we will simply allow
* a parent package with trailing NULL elements. This can happen if
* the package was defined to be longer than the initializer list.
* This is legal as per the ACPI specification. It is often used
* to allow for dynamic initialization of a Package.
*
* A future enhancement may be to simply truncate the package to
* remove the trailing NULL elements.
*/
if (!(*elements)) {
if (!non_trailing_null) {
/* Ensure the remaining elements are all NULL */
for (j = 1; j < (count - i + 1); j++) {
if (elements[j]) {
non_trailing_null = TRUE;
}
}
if (!non_trailing_null) {
/* Ignore the trailing NULL elements */
return (AE_OK);
}
}
/* There are trailing non-null elements, issue warning */
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
data->node_flags,
"Found NULL element at package index %u",
i));
elements++;
continue;
}
sub_package = *elements; sub_package = *elements;
sub_elements = sub_package->package.elements; sub_elements = sub_package->package.elements;
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include "accommon.h" #include "accommon.h"
#include "acnamesp.h" #include "acnamesp.h"
#include "acpredef.h"
#define _COMPONENT ACPI_NAMESPACE #define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsrepair2") ACPI_MODULE_NAME("nsrepair2")
...@@ -92,9 +93,6 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, ...@@ -92,9 +93,6 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
u32 sort_index, u32 sort_index,
u8 sort_direction, char *sort_key_name); u8 sort_direction, char *sort_key_name);
static acpi_status
acpi_ns_remove_null_elements(union acpi_operand_object *package);
static acpi_status static acpi_status
acpi_ns_sort_list(union acpi_operand_object **elements, acpi_ns_sort_list(union acpi_operand_object **elements,
u32 count, u32 index, u8 sort_direction); u32 count, u32 index, u8 sort_direction);
...@@ -456,25 +454,10 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, ...@@ -456,25 +454,10 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
} }
/* /*
* Detect any NULL package elements and remove them from the * NOTE: assumes list of sub-packages contains no NULL elements.
* package. * Any NULL elements should have been removed by earlier call
* * to acpi_ns_remove_null_elements.
* TBD: We may want to do this for all predefined names that
* return a variable-length package of packages.
*/ */
status = acpi_ns_remove_null_elements(return_object);
if (status == AE_NULL_ENTRY) {
ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
"%s: NULL elements removed from package\n",
data->pathname));
/* Exit if package is now zero length */
if (!return_object->package.count) {
return (AE_NULL_ENTRY);
}
}
outer_elements = return_object->package.elements; outer_elements = return_object->package.elements;
outer_element_count = return_object->package.count; outer_element_count = return_object->package.count;
if (!outer_element_count) { if (!outer_element_count) {
...@@ -544,36 +527,63 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, ...@@ -544,36 +527,63 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
* *
* FUNCTION: acpi_ns_remove_null_elements * FUNCTION: acpi_ns_remove_null_elements
* *
* PARAMETERS: obj_desc - A Package object * PARAMETERS: Data - Pointer to validation data structure
* package_type - An acpi_return_package_types value
* obj_desc - A Package object
* *
* RETURN: Status. AE_NULL_ENTRY means that one or more elements were * RETURN: None.
* removed.
* *
* DESCRIPTION: Remove all NULL package elements and update the package count. * DESCRIPTION: Remove all NULL package elements from packages that contain
* a variable number of sub-packages.
* *
*****************************************************************************/ *****************************************************************************/
static acpi_status void
acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc) acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
u8 package_type,
union acpi_operand_object *obj_desc)
{ {
union acpi_operand_object **source; union acpi_operand_object **source;
union acpi_operand_object **dest; union acpi_operand_object **dest;
acpi_status status = AE_OK;
u32 count; u32 count;
u32 new_count; u32 new_count;
u32 i; u32 i;
ACPI_FUNCTION_NAME(ns_remove_null_elements);
/*
* PTYPE1 packages contain no subpackages.
* PTYPE2 packages contain a variable number of sub-packages. We can
* safely remove all NULL elements from the PTYPE2 packages.
*/
switch (package_type) {
case ACPI_PTYPE1_FIXED:
case ACPI_PTYPE1_VAR:
case ACPI_PTYPE1_OPTION:
return;
case ACPI_PTYPE2:
case ACPI_PTYPE2_COUNT:
case ACPI_PTYPE2_PKG_COUNT:
case ACPI_PTYPE2_FIXED:
case ACPI_PTYPE2_MIN:
case ACPI_PTYPE2_REV_FIXED:
break;
default:
return;
}
count = obj_desc->package.count; count = obj_desc->package.count;
new_count = count; new_count = count;
source = obj_desc->package.elements; source = obj_desc->package.elements;
dest = source; dest = source;
/* Examine all elements of the package object */ /* Examine all elements of the package object, remove nulls */
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (!*source) { if (!*source) {
status = AE_NULL_ENTRY;
new_count--; new_count--;
} else { } else {
*dest = *source; *dest = *source;
...@@ -582,15 +592,18 @@ acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc) ...@@ -582,15 +592,18 @@ acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc)
source++; source++;
} }
if (status == AE_NULL_ENTRY) { /* Update parent package if any null elements were removed */
if (new_count < count) {
ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
"%s: Found and removed %u NULL elements\n",
data->pathname, (count - new_count)));
/* NULL terminate list and update the package count */ /* NULL terminate list and update the package count */
*dest = NULL; *dest = NULL;
obj_desc->package.count = new_count; obj_desc->package.count = new_count;
} }
return (status);
} }
/****************************************************************************** /******************************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment