Skip to content

Commit

Permalink
ACPICA: Predefined name repair: automatically remove null package ele…
Browse files Browse the repository at this point in the history
…ments

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=819

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>
  • Loading branch information
Bob Moore authored and Len Brown committed Dec 15, 2009
1 parent e31c32c commit d4085a3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 78 deletions.
5 changes: 5 additions & 0 deletions drivers/acpi/acpica/acnamesp.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,11 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
acpi_status validate_status,
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
*/
Expand Down
59 changes: 14 additions & 45 deletions drivers/acpi/acpica/nspredef.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
* Note: Package may have been newly created by call above.
*/
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);
if (ACPI_FAILURE(status)) {
goto exit;
Expand Down Expand Up @@ -439,6 +436,13 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
data->pathname, package->ret_info.type,
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 */

elements = return_object->package.elements;
Expand Down Expand Up @@ -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_elements;
acpi_status status;
u8 non_trailing_null = FALSE;
u32 expected_count;
u32 i;
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++) {
/*
* 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_elements = sub_package->package.elements;

Expand Down
79 changes: 46 additions & 33 deletions drivers/acpi/acpica/nsrepair2.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"
#include "acpredef.h"

#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsrepair2")
Expand Down Expand Up @@ -92,9 +93,6 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
u32 sort_index,
u8 sort_direction, char *sort_key_name);

static acpi_status
acpi_ns_remove_null_elements(union acpi_operand_object *package);

static acpi_status
acpi_ns_sort_list(union acpi_operand_object **elements,
u32 count, u32 index, u8 sort_direction);
Expand Down Expand Up @@ -456,25 +454,10 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
}

/*
* Detect any NULL package elements and remove them from the
* package.
*
* TBD: We may want to do this for all predefined names that
* return a variable-length package of packages.
* 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.
*/
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_element_count = return_object->package.count;
if (!outer_element_count) {
Expand Down Expand Up @@ -544,36 +527,63 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
*
* 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
* removed.
* RETURN: None.
*
* 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
acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc)
void
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 **dest;
acpi_status status = AE_OK;
u32 count;
u32 new_count;
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;
new_count = count;

source = obj_desc->package.elements;
dest = source;

/* Examine all elements of the package object */
/* Examine all elements of the package object, remove nulls */

for (i = 0; i < count; i++) {
if (!*source) {
status = AE_NULL_ENTRY;
new_count--;
} else {
*dest = *source;
Expand All @@ -582,15 +592,18 @@ acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc)
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 */

*dest = NULL;
obj_desc->package.count = new_count;
}

return (status);
}

/******************************************************************************
Expand Down

0 comments on commit d4085a3

Please sign in to comment.