Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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



Signed-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
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -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
 */
 */
+14 −45
Original line number Original line Diff line number Diff line
@@ -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,
			  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,
	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 */

	for (i = 0; i < count; i++) {
	/*
	/*
		 * Handling for NULL package elements. For now, we will simply allow
	 * Validate each sub-Package in the parent Package
		 * a parent package with trailing NULL elements. This can happen if
	 *
		 * the package was defined to be longer than the initializer list.
	 * NOTE: assumes list of sub-packages contains no NULL elements.
		 * This is legal as per the ACPI specification. It is often used
	 * Any NULL elements should have been removed by earlier call
		 * to allow for dynamic initialization of a Package.
	 * to acpi_ns_remove_null_elements.
		 *
		 * A future enhancement may be to simply truncate the package to
		 * remove the trailing NULL elements.
	 */
	 */
		if (!(*elements)) {
	for (i = 0; i < count; i++) {
			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;


+46 −33
Original line number Original line Diff line number Diff line
@@ -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,
			  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,
	}
	}


	/*
	/*
	 * 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,
 *
 *
 * 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)
		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);
}
}


/******************************************************************************
/******************************************************************************