ACPICA: Predefined name repair: fix NULL package elements
For the predefined methods that return fixed-length packages (or subpackages), attempt repair for a NULL element. Create an Integer of value 0, a NULL String, or a zero-length buffer as appropriate. http://www.acpica.org/bugzilla/show_bug.cgi?id=818 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>
This commit is contained in:
parent
5f8902acf8
commit
091f4d7186
|
@ -374,6 +374,7 @@ union acpi_predefined_info {
|
|||
struct acpi_predefined_data {
|
||||
char *pathname;
|
||||
const union acpi_predefined_info *predefined;
|
||||
union acpi_operand_object *parent_package;
|
||||
u32 flags;
|
||||
u8 node_flags;
|
||||
};
|
||||
|
|
|
@ -286,6 +286,17 @@ acpi_status
|
|||
acpi_ns_repair_package_list(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object **obj_desc_ptr);
|
||||
|
||||
acpi_status
|
||||
acpi_ns_repair_null_element(struct acpi_predefined_data *data,
|
||||
u32 expected_btypes,
|
||||
u32 package_index,
|
||||
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);
|
||||
|
||||
/*
|
||||
* nsrepair2 - Return object repair for specific
|
||||
* predefined methods/objects
|
||||
|
@ -296,11 +307,6 @@ 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
|
||||
*/
|
||||
|
|
|
@ -231,6 +231,7 @@ 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) {
|
||||
data->parent_package = *return_object_ptr;
|
||||
status = acpi_ns_check_package(data, return_object_ptr);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
|
@ -710,6 +711,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
|
|||
for (i = 0; i < count; i++) {
|
||||
sub_package = *elements;
|
||||
sub_elements = sub_package->package.elements;
|
||||
data->parent_package = sub_package;
|
||||
|
||||
/* Each sub-object must be of type Package */
|
||||
|
||||
|
@ -721,6 +723,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
|
|||
|
||||
/* Examine the different types of expected sub-packages */
|
||||
|
||||
data->parent_package = sub_package;
|
||||
switch (package->ret_info.type) {
|
||||
case ACPI_PTYPE2:
|
||||
case ACPI_PTYPE2_PKG_COUNT:
|
||||
|
@ -800,7 +803,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
|
|||
|
||||
/*
|
||||
* First element is the (Integer) count of elements, including
|
||||
* the count field.
|
||||
* the count field (the ACPI name is num_elements)
|
||||
*/
|
||||
status = acpi_ns_check_object_type(data, sub_elements,
|
||||
ACPI_RTYPE_INTEGER,
|
||||
|
@ -822,6 +825,16 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
|
|||
expected_count = package->ret_info.count1;
|
||||
goto package_too_small;
|
||||
}
|
||||
if (expected_count == 0) {
|
||||
/*
|
||||
* Either the num_entries element was originally zero or it was
|
||||
* a NULL element and repaired to an Integer of value zero.
|
||||
* In either case, repair it by setting num_entries to be the
|
||||
* actual size of the subpackage.
|
||||
*/
|
||||
expected_count = sub_package->package.count;
|
||||
(*sub_elements)->integer.value = expected_count;
|
||||
}
|
||||
|
||||
/* Check the type of each sub-package element */
|
||||
|
||||
|
@ -945,10 +958,18 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data,
|
|||
char type_buffer[48]; /* Room for 5 types */
|
||||
|
||||
/*
|
||||
* If we get a NULL return_object here, it is a NULL package element,
|
||||
* and this is always an error.
|
||||
* If we get a NULL return_object here, it is a NULL package element.
|
||||
* Since all extraneous NULL package elements were removed earlier by a
|
||||
* call to acpi_ns_remove_null_elements, this is an unexpected NULL element.
|
||||
* We will attempt to repair it.
|
||||
*/
|
||||
if (!return_object) {
|
||||
status = acpi_ns_repair_null_element(data, expected_btypes,
|
||||
package_index,
|
||||
return_object_ptr);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
return (AE_OK); /* Repair was successful */
|
||||
}
|
||||
goto type_error_exit;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "accommon.h"
|
||||
#include "acnamesp.h"
|
||||
#include "acinterp.h"
|
||||
#include "acpredef.h"
|
||||
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
ACPI_MODULE_NAME("nsrepair")
|
||||
|
@ -71,6 +72,12 @@ ACPI_MODULE_NAME("nsrepair")
|
|||
* Buffer -> Package of Integers
|
||||
* Package -> Package of one Package
|
||||
*
|
||||
* Additional possible repairs:
|
||||
*
|
||||
* Optional/unnecessary NULL package elements removed
|
||||
* Required package elements that are NULL replaced by Integer/String/Buffer
|
||||
* Incorrect standalone package wrapped with required outer package
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Local prototypes */
|
||||
static acpi_status
|
||||
|
@ -504,6 +511,172 @@ acpi_ns_convert_to_package(union acpi_operand_object *original_object,
|
|||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_repair_null_element
|
||||
*
|
||||
* PARAMETERS: Data - Pointer to validation data structure
|
||||
* expected_btypes - Object types expected
|
||||
* package_index - Index of object within parent package (if
|
||||
* applicable - ACPI_NOT_PACKAGE_ELEMENT
|
||||
* otherwise)
|
||||
* return_object_ptr - Pointer to the object returned from the
|
||||
* evaluation of a method or object
|
||||
*
|
||||
* RETURN: Status. AE_OK if repair was successful.
|
||||
*
|
||||
* DESCRIPTION: Attempt to repair a NULL element of a returned Package object.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ns_repair_null_element(struct acpi_predefined_data *data,
|
||||
u32 expected_btypes,
|
||||
u32 package_index,
|
||||
union acpi_operand_object **return_object_ptr)
|
||||
{
|
||||
union acpi_operand_object *return_object = *return_object_ptr;
|
||||
union acpi_operand_object *new_object;
|
||||
|
||||
ACPI_FUNCTION_NAME(ns_repair_null_element);
|
||||
|
||||
/* No repair needed if return object is non-NULL */
|
||||
|
||||
if (return_object) {
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to repair a NULL element of a Package object. This applies to
|
||||
* predefined names that return a fixed-length package and each element
|
||||
* is required. It does not apply to variable-length packages where NULL
|
||||
* elements are allowed, especially at the end of the package.
|
||||
*/
|
||||
if (expected_btypes & ACPI_RTYPE_INTEGER) {
|
||||
|
||||
/* Need an Integer - create a zero-value integer */
|
||||
|
||||
new_object = acpi_ut_create_integer_object(0);
|
||||
} else if (expected_btypes & ACPI_RTYPE_STRING) {
|
||||
|
||||
/* Need a String - create a NULL string */
|
||||
|
||||
new_object = acpi_ut_create_string_object(0);
|
||||
} else if (expected_btypes & ACPI_RTYPE_BUFFER) {
|
||||
|
||||
/* Need a Buffer - create a zero-length buffer */
|
||||
|
||||
new_object = acpi_ut_create_buffer_object(0);
|
||||
} else {
|
||||
/* Error for all other expected types */
|
||||
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Set the reference count according to the parent Package object */
|
||||
|
||||
new_object->common.reference_count =
|
||||
data->parent_package->common.reference_count;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
|
||||
"%s: Converted NULL package element to expected %s at index %u\n",
|
||||
data->pathname,
|
||||
acpi_ut_get_object_type_name(new_object),
|
||||
package_index));
|
||||
|
||||
*return_object_ptr = new_object;
|
||||
data->flags |= ACPI_OBJECT_REPAIRED;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_remove_null_elements
|
||||
*
|
||||
* PARAMETERS: Data - Pointer to validation data structure
|
||||
* package_type - An acpi_return_package_types value
|
||||
* obj_desc - A Package object
|
||||
*
|
||||
* RETURN: None.
|
||||
*
|
||||
* DESCRIPTION: Remove all NULL package elements from packages that contain
|
||||
* a variable number of sub-packages. For these types of
|
||||
* packages, NULL elements can be safely removed.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
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;
|
||||
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, remove nulls */
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!*source) {
|
||||
new_count--;
|
||||
} else {
|
||||
*dest = *source;
|
||||
dest++;
|
||||
}
|
||||
source++;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_repair_package_list
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "acnamesp.h"
|
||||
#include "acpredef.h"
|
||||
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
ACPI_MODULE_NAME("nsrepair2")
|
||||
|
@ -518,89 +517,6 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
|
|||
return (AE_OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_remove_null_elements
|
||||
*
|
||||
* PARAMETERS: Data - Pointer to validation data structure
|
||||
* package_type - An acpi_return_package_types value
|
||||
* obj_desc - A Package object
|
||||
*
|
||||
* RETURN: None.
|
||||
*
|
||||
* DESCRIPTION: Remove all NULL package elements from packages that contain
|
||||
* a variable number of sub-packages.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
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;
|
||||
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, remove nulls */
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!*source) {
|
||||
new_count--;
|
||||
} else {
|
||||
*dest = *source;
|
||||
dest++;
|
||||
}
|
||||
source++;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_sort_list
|
||||
|
|
Loading…
Reference in New Issue