cregit-Linux how code gets into the kernel

Release 4.11 drivers/acpi/acpica/nsrepair2.c

/******************************************************************************
 *
 * Module Name: nsrepair2 - Repair for objects returned by specific
 *                          predefined methods
 *
 *****************************************************************************/

/*
 * Copyright (C) 2000 - 2017, Intel Corp.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"


#define _COMPONENT          ACPI_NAMESPACE
ACPI_MODULE_NAME("nsrepair2")

/*
 * Information structure and handler for ACPI predefined names that can
 * be repaired on a per-name basis.
 */
typedef

acpi_status (*acpi_repair_function) (struct acpi_evaluate_info * info,
				     union acpi_operand_object **
				     return_object_ptr);


typedef struct acpi_repair_info {
	
char name[ACPI_NAME_SIZE];
	
acpi_repair_function repair_function;

} 
acpi_repair_info;

/* Local prototypes */

static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
								   acpi_namespace_node
								   *node);

static acpi_status
acpi_ns_repair_ALR(struct acpi_evaluate_info *info,
		   union acpi_operand_object **return_object_ptr);

static acpi_status
acpi_ns_repair_CID(struct acpi_evaluate_info *info,
		   union acpi_operand_object **return_object_ptr);

static acpi_status
acpi_ns_repair_CST(struct acpi_evaluate_info *info,
		   union acpi_operand_object **return_object_ptr);

static acpi_status
acpi_ns_repair_FDE(struct acpi_evaluate_info *info,
		   union acpi_operand_object **return_object_ptr);

static acpi_status
acpi_ns_repair_HID(struct acpi_evaluate_info *info,
		   union acpi_operand_object **return_object_ptr);

static acpi_status
acpi_ns_repair_PRT(struct acpi_evaluate_info *info,
		   union acpi_operand_object **return_object_ptr);

static acpi_status
acpi_ns_repair_PSS(struct acpi_evaluate_info *info,
		   union acpi_operand_object **return_object_ptr);

static acpi_status
acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
		   union acpi_operand_object **return_object_ptr);

static acpi_status
acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
			  union acpi_operand_object *return_object,
			  u32 start_index,
			  u32 expected_count,
			  u32 sort_index,
			  u8 sort_direction, char *sort_key_name);

/* Values for sort_direction above */


#define ACPI_SORT_ASCENDING     0

#define ACPI_SORT_DESCENDING    1

static void
acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index);

static void
acpi_ns_sort_list(union acpi_operand_object **elements,
		  u32 count, u32 index, u8 sort_direction);

/*
 * This table contains the names of the predefined methods for which we can
 * perform more complex repairs.
 *
 * As necessary:
 *
 * _ALR: Sort the list ascending by ambient_illuminance
 * _CID: Strings: uppercase all, remove any leading asterisk
 * _CST: Sort the list ascending by C state type
 * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
 * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
 * _HID: Strings: uppercase all, remove any leading asterisk
 * _PRT: Fix reversed source_name and source_index
 * _PSS: Sort the list descending by Power
 * _TSS: Sort the list descending by Power
 *
 * Names that must be packages, but cannot be sorted:
 *
 * _BCL: Values are tied to the Package index where they appear, and cannot
 * be moved or sorted. These index values are used for _BQC and _BCM.
 * However, we can fix the case where a buffer is returned, by converting
 * it to a Package of integers.
 */

static const struct acpi_repair_info acpi_ns_repairable_names[] = {
	{"_ALR", acpi_ns_repair_ALR},
	{"_CID", acpi_ns_repair_CID},
	{"_CST", acpi_ns_repair_CST},
	{"_FDE", acpi_ns_repair_FDE},
	{"_GTM", acpi_ns_repair_FDE},	/* _GTM has same repair as _FDE */
	{"_HID", acpi_ns_repair_HID},
	{"_PRT", acpi_ns_repair_PRT},
	{"_PSS", acpi_ns_repair_PSS},
	{"_TSS", acpi_ns_repair_TSS},
	{{0, 0, 0, 0}, NULL}	/* Table terminator */
};


#define ACPI_FDE_FIELD_COUNT        5

#define ACPI_FDE_BYTE_BUFFER_SIZE   5

#define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * sizeof (u32))

/******************************************************************************
 *
 * FUNCTION:    acpi_ns_complex_repairs
 *
 * PARAMETERS:  info                - Method execution information block
 *              node                - Namespace node for the method/object
 *              validate_status     - Original status of earlier validation
 *              return_object_ptr   - Pointer to the object returned from the
 *                                    evaluation of a method or object
 *
 * RETURN:      Status. AE_OK if repair was successful. If name is not
 *              matched, validate_status is returned.
 *
 * DESCRIPTION: Attempt to repair/convert a return object of a type that was
 *              not expected.
 *
 *****************************************************************************/


acpi_status acpi_ns_complex_repairs(struct acpi_evaluate_info *info, struct acpi_namespace_node *node, acpi_status validate_status, union acpi_operand_object **return_object_ptr) { const struct acpi_repair_info *predefined; acpi_status status; /* Check if this name is in the list of repairable names */ predefined = acpi_ns_match_complex_repair(node); if (!predefined) { return (validate_status); } status = predefined->repair_function(info, return_object_ptr); return (status); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Moore69100.00%3100.00%
Total69100.00%3100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_match_complex_repair * * PARAMETERS: node - Namespace node for the method/object * * RETURN: Pointer to entry in repair table. NULL indicates not found. * * DESCRIPTION: Check an object name against the repairable object list. * *****************************************************************************/
static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct acpi_namespace_node *node) { const struct acpi_repair_info *this_name; /* Search info table for a repairable predefined method/object name */ this_name = acpi_ns_repairable_names; while (this_name->repair_function) { if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) { return (this_name); } this_name++; } return (NULL); /* Not found */ }

Contributors

PersonTokensPropCommitsCommitProp
Robert Moore64100.00%2100.00%
Total64100.00%2100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_repair_ALR * * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * * RETURN: Status. AE_OK if object is OK or was repaired successfully * * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list * ascending by the ambient illuminance values. * *****************************************************************************/
static acpi_status acpi_ns_repair_ALR(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; acpi_status status; status = acpi_ns_check_sorted_list(info, return_object, 0, 2, 1, ACPI_SORT_ASCENDING, "AmbientIlluminance"); return (status); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Moore5096.15%266.67%
Lv Zheng23.85%133.33%
Total52100.00%3100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_repair_FDE * * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * * RETURN: Status. AE_OK if object is OK or was repaired successfully * * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return * value is a Buffer of 5 DWORDs. This function repairs a common * problem where the return value is a Buffer of BYTEs, not * DWORDs. * *****************************************************************************/
static acpi_status acpi_ns_repair_FDE(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; union acpi_operand_object *buffer_object; u8 *byte_buffer; u32 *dword_buffer; u32 i; ACPI_FUNCTION_NAME(ns_repair_FDE); switch (return_object->common.type) { case ACPI_TYPE_BUFFER: /* This is the expected type. Length should be (at least) 5 DWORDs */ if (return_object->buffer.length >= ACPI_FDE_DWORD_BUFFER_SIZE) { return (AE_OK); } /* We can only repair if we have exactly 5 BYTEs */ if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) { ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "Incorrect return buffer length %u, expected %u", return_object->buffer.length, ACPI_FDE_DWORD_BUFFER_SIZE)); return (AE_AML_OPERAND_TYPE); } /* Create the new (larger) buffer object */ buffer_object = acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE); if (!buffer_object) { return (AE_NO_MEMORY); } /* Expand each byte to a DWORD */ byte_buffer = return_object->buffer.pointer; dword_buffer = ACPI_CAST_PTR(u32, buffer_object->buffer.pointer); for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) { *dword_buffer = (u32) *byte_buffer; dword_buffer++; byte_buffer++; } ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s Expanded Byte Buffer to expected DWord Buffer\n", info->full_pathname)); break; default: return (AE_AML_OPERAND_TYPE); } /* Delete the original return object, return the new buffer object */ acpi_ut_remove_reference(return_object); *return_object_ptr = buffer_object; info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Moore234100.00%3100.00%
Total234100.00%3100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_repair_CID * * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * * RETURN: Status. AE_OK if object is OK or was repaired successfully * * DESCRIPTION: Repair for the _CID object. If a string, ensure that all * letters are uppercase and that there is no leading asterisk. * If a Package, ensure same for all string elements. * *****************************************************************************/
static acpi_status acpi_ns_repair_CID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { acpi_status status; union acpi_operand_object *return_object = *return_object_ptr; union acpi_operand_object **element_ptr; union acpi_operand_object *original_element; u16 original_ref_count; u32 i; /* Check for _CID as a simple string */ if (return_object->common.type == ACPI_TYPE_STRING) { status = acpi_ns_repair_HID(info, return_object_ptr); return (status); } /* Exit if not a Package */ if (return_object->common.type != ACPI_TYPE_PACKAGE) { return (AE_OK); } /* Examine each element of the _CID package */ element_ptr = return_object->package.elements; for (i = 0; i < return_object->package.count; i++) { original_element = *element_ptr; original_ref_count = original_element->common.reference_count; status = acpi_ns_repair_HID(info, element_ptr); if (ACPI_FAILURE(status)) { return (status); } /* Take care with reference counts */ if (original_element != *element_ptr) { /* Element was replaced */ (*element_ptr)->common.reference_count = original_ref_count; acpi_ut_remove_reference(original_element); } element_ptr++; } return (AE_OK); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Moore189100.00%2100.00%
Total189100.00%2100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_repair_CST * * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * * RETURN: Status. AE_OK if object is OK or was repaired successfully * * DESCRIPTION: Repair for the _CST object: * 1. Sort the list ascending by C state type * 2. Ensure type cannot be zero * 3. A subpackage count of zero means _CST is meaningless * 4. Count must match the number of C state subpackages * *****************************************************************************/
static acpi_status acpi_ns_repair_CST(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; union acpi_operand_object **outer_elements; u32 outer_element_count; union acpi_operand_object *obj_desc; acpi_status status; u8 removing; u32 i; ACPI_FUNCTION_NAME(ns_repair_CST); /* * Check if the C-state type values are proportional. */ outer_element_count = return_object->package.count - 1; i = 0; while (i < outer_element_count) { outer_elements = &return_object->package.elements[i + 1]; removing = FALSE; if ((*outer_elements)->package.count == 0) { ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "SubPackage[%u] - removing entry due to zero count", i)); removing = TRUE; goto remove_element; } obj_desc = (*outer_elements)->package.elements[1]; /* Index1 = Type */ if ((u32)obj_desc->integer.value == 0) { ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "SubPackage[%u] - removing entry due to invalid Type(0)", i)); removing = TRUE; } remove_element: if (removing) { acpi_ns_remove_element(return_object, i + 1); outer_element_count--; } else { i++; } } /* Update top-level package count, Type "Integer" checked elsewhere */ obj_desc = return_object->package.elements[0]; obj_desc->integer.value = outer_element_count; /* * Entries (subpackages) in the _CST Package must be sorted by the * C-state type, in ascending order. */ status = acpi_ns_check_sorted_list(info, return_object, 1, 4, 1, ACPI_SORT_ASCENDING, "C-State Type"); if (ACPI_FAILURE(status)) { return (status); } return (AE_OK); }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng273100.00%2100.00%
Total273100.00%2100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_repair_HID * * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * * RETURN: Status. AE_OK if object is OK or was repaired successfully * * DESCRIPTION: Repair for the _HID object. If a string, ensure that all * letters are uppercase and that there is no leading asterisk. * *****************************************************************************/
static acpi_status acpi_ns_repair_HID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; union acpi_operand_object *new_string; char *source; char *dest; ACPI_FUNCTION_NAME(ns_repair_HID); /* We only care about string _HID objects (not integers) */ if (return_object->common.type != ACPI_TYPE_STRING) { return (AE_OK); } if (return_object->string.length == 0) { ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "Invalid zero-length _HID or _CID string")); /* Return AE_OK anyway, let driver handle it */ info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } /* It is simplest to always create a new string object */ new_string = acpi_ut_create_string_object(return_object->string.length); if (!new_string) { return (AE_NO_MEMORY); } /* * Remove a leading asterisk if present. For some unknown reason, there * are many machines in the field that contains IDs like this. * * Examples: "*PNP0C03", "*ACPI0003" */ source = return_object->string.pointer; if (*source == '*') { source++; new_string->string.length--; ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Removed invalid leading asterisk\n", info->full_pathname)); } /* * Copy and uppercase the string. From the ACPI 5.0 specification: * * A valid PNP ID must be of the form "AAA####" where A is an uppercase * letter and # is a hex digit. A valid ACPI ID must be of the form * "NNNN####" where N is an uppercase letter or decimal digit, and * # is a hex digit. */ for (dest = new_string->string.pointer; *source; dest++, source++) { *dest = (char)toupper((int)*source); } acpi_ut_remove_reference(return_object); *return_object_ptr = new_string; return (AE_OK); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Moore219100.00%4100.00%
Total219100.00%4100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_repair_PRT * * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * * RETURN: Status. AE_OK if object is OK or was repaired successfully * * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed * source_name and source_index field, a common BIOS bug. * *****************************************************************************/
static acpi_status acpi_ns_repair_PRT(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *package_object = *return_object_ptr; union acpi_operand_object **top_object_list; union acpi_operand_object **sub_object_list; union acpi_operand_object *obj_desc; union acpi_operand_object *sub_package; u32 element_count; u32 index; /* Each element in the _PRT package is a subpackage */ top_object_list = package_object->package.elements; element_count = package_object->package.count; /* Examine each subpackage */ for (index = 0; index < element_count; index++, top_object_list++) { sub_package = *top_object_list; sub_object_list = sub_package->package.elements; /* Check for minimum required element count */ if (sub_package->package.count < 4) { continue; } /* * If the BIOS has erroneously reversed the _PRT source_name (index 2) * and the source_index (index 3), fix it. _PRT is important enough to * workaround this BIOS error. This also provides compatibility with * other ACPI implementations. */ obj_desc = sub_object_list[3]; if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { sub_object_list[3] = sub_object_list[2]; sub_object_list[2] = obj_desc; info->return_flags |= ACPI_OBJECT_REPAIRED; ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "PRT[%X]: Fixed reversed SourceName and SourceIndex", index)); } } return (AE_OK); }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng11862.77%116.67%
Robert Moore6132.45%466.67%
Fenghua Yu94.79%116.67%
Total188100.00%6100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_repair_PSS * * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * * RETURN: Status. AE_OK if object is OK or was repaired successfully * * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list * by the CPU frequencies. Check that the power dissipation values * are all proportional to CPU frequency (i.e., sorting by * frequency should be the same as sorting by power.) * *****************************************************************************/
static acpi_status acpi_ns_repair_PSS(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; union acpi_operand_object **outer_elements; u32 outer_element_count; union acpi_operand_object **elements; union acpi_operand_object *obj_desc; u32 previous_value; acpi_status status; u32 i; /* * Entries (subpackages) in the _PSS Package must be sorted by power * dissipation, in descending order. If it appears that the list is * incorrectly sorted, sort it. We sort by cpu_frequency, since this * should be proportional to the power. */ status = acpi_ns_check_sorted_list(info, return_object, 0, 6, 0, ACPI_SORT_DESCENDING, "CpuFrequency"); if (ACPI_FAILURE(status)) { return (status); } /* * We now know the list is correctly sorted by CPU frequency. Check if * the power dissipation values are proportional. */ previous_value = ACPI_UINT32_MAX; outer_elements = return_object->package.elements; outer_element_count = return_object->package.count; for (i = 0; i < outer_element_count; i++) { elements = (*outer_elements)->package.elements; obj_desc = elements[1]; /* Index1 = power_dissipation */ if ((u32)obj_desc->integer.value > previous_value) { ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "SubPackage[%u,%u] - suspicious power dissipation values", i - 1, i)); } previous_value = (u32) obj_desc->integer.value; outer_elements++; } return (AE_OK); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Moore19899.00%375.00%
Lv Zheng21.00%125.00%
Total200100.00%4100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_repair_TSS * * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * * RETURN: Status. AE_OK if object is OK or was repaired successfully * * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list * descending by the power dissipation values. * *****************************************************************************/
static acpi_status acpi_ns_repair_TSS(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; acpi_status status; struct acpi_namespace_node *node; /* * We can only sort the _TSS return package if there is no _PSS in the * same scope. This is because if _PSS is present, the ACPI specification * dictates that the _TSS Power Dissipation field is to be ignored, and * therefore some BIOSs leave garbage values in the _TSS Power field(s). * In this case, it is best to just return the _TSS package as-is. * (May, 2011) */ status = acpi_ns_get_node(info->node, "^_PSS", ACPI_NS_NO_UPSEARCH, &node); if (ACPI_SUCCESS(status)) { return (AE_OK); } status = acpi_ns_check_sorted_list(info, return_object, 0, 5, 1, ACPI_SORT_DESCENDING, "PowerDissipation"); return (status); }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng88100.00%2100.00%
Total88100.00%2100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_check_sorted_list * * PARAMETERS: info - Method execution information block * return_object - Pointer to the top-level returned object * start_index - Index of the first subpackage * expected_count - Minimum length of each subpackage * sort_index - Subpackage entry to sort on * sort_direction - Ascending or descending * sort_key_name - Name of the sort_index field * * RETURN: Status. AE_OK if the list is valid and is sorted correctly or * has been repaired by sorting the list. * * DESCRIPTION: Check if the package list is valid and sorted correctly by the * sort_index. If not, then sort the list. * *****************************************************************************/
static acpi_status acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, union acpi_operand_object *return_object, u32 start_index, u32 expected_count, u32 sort_index, u8 sort_direction, char *sort_key_name) { u32 outer_element_count; union acpi_operand_object **outer_elements; union acpi_operand_object **elements; union acpi_operand_object *obj_desc; u32 i; u32 previous_value; ACPI_FUNCTION_NAME(ns_check_sorted_list); /* The top-level object must be a package */ if (return_object->common.type != ACPI_TYPE_PACKAGE) { return (AE_AML_OPERAND_TYPE); } /* * NOTE: assumes list of subpackages contains no NULL elements. * Any NULL elements should have been removed by earlier call * to acpi_ns_remove_null_elements. */ outer_element_count = return_object->package.count; if (!outer_element_count || start_index >= outer_element_count) { return (AE_AML_PACKAGE_LIMIT); } outer_elements = &return_object->package.elements[start_index]; outer_element_count -= start_index; previous_value = 0; if (sort_direction == ACPI_SORT_DESCENDING) { previous_value = ACPI_UINT32_MAX; } /* Examine each subpackage */ for (i = 0; i < outer_element_count; i++) { /* Each element of the top-level package must also be a package */ if ((*outer_elements)->common.type != ACPI_TYPE_PACKAGE) { return (AE_AML_OPERAND_TYPE); } /* Each subpackage must have the minimum length */ if ((*outer_elements)->package.count < expected_count) { return (AE_AML_PACKAGE_LIMIT); } elements = (*outer_elements)->package.elements; obj_desc = elements[sort_index]; if (obj_desc->common.type != ACPI_TYPE_INTEGER) { return (AE_AML_OPERAND_TYPE); } /* * The list must be sorted in the specified order. If we detect a * discrepancy, sort the entire list. */ if (((sort_direction == ACPI_SORT_ASCENDING) && (obj_desc->integer.value < previous_value)) || ((sort_direction == ACPI_SORT_DESCENDING) && (obj_desc->integer.value > previous_value))) { acpi_ns_sort_list(&return_object->package. elements[start_index], outer_element_count, sort_index, sort_direction); info->return_flags |= ACPI_OBJECT_REPAIRED; ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Repaired unsorted list - now sorted by %s\n", info->full_pathname, sort_key_name)); return (AE_OK); } previous_value = (u32) obj_desc->integer.value; outer_elements++; } return (AE_OK); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Moore30991.96%583.33%
Lv Zheng278.04%116.67%
Total336100.00%6100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_sort_list * * PARAMETERS: elements - Package object element list * count - Element count for above * index - Sort by which package element * sort_direction - Ascending or Descending sort * * RETURN: None * * DESCRIPTION: Sort the objects that are in a package element list. * * NOTE: Assumes that all NULL elements have been removed from the package, * and that all elements have been verified to be of type Integer. * *****************************************************************************/
static void acpi_ns_sort_list(union acpi_operand_object **elements, u32 count, u32 index, u8 sort_direction) { union acpi_operand_object *obj_desc1; union acpi_operand_object *obj_desc2; union acpi_operand_object *temp_obj; u32 i; u32 j; /* Simple bubble sort */ for (i = 1; i < count; i++) { for (j = (count - 1); j >= i; j--) { obj_desc1 = elements[j - 1]->package.elements[index]; obj_desc2 = elements[j]->package.elements[index]; if (((sort_direction == ACPI_SORT_ASCENDING) && (obj_desc1->integer.value > obj_desc2->integer.value)) || ((sort_direction == ACPI_SORT_DESCENDING) && (obj_desc1->integer.value < obj_desc2->integer.value))) { temp_obj = elements[j - 1]; elements[j - 1] = elements[j]; elements[j] = temp_obj; } } } }

Contributors

PersonTokensPropCommitsCommitProp
Robert Moore183100.00%2100.00%
Total183100.00%2100.00%

/****************************************************************************** * * FUNCTION: acpi_ns_remove_element * * PARAMETERS: obj_desc - Package object element list * index - Index of element to remove * * RETURN: None * * DESCRIPTION: Remove the requested element of a package and delete it. * *****************************************************************************/
static void acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index) { union acpi_operand_object **source; union acpi_operand_object **dest; u32 count; u32 new_count; u32 i; ACPI_FUNCTION_NAME(ns_remove_element); count = obj_desc->package.count; new_count = count - 1; source = obj_desc->package.elements; dest = source; /* Examine all elements of the package object, remove matched index */ for (i = 0; i < count; i++) { if (i == index) { acpi_ut_remove_reference(*source); /* Remove one ref for being in pkg */ acpi_ut_remove_reference(*source); } else { *dest = *source; dest++; } source++; } /* NULL terminate list and update the package count */ *dest = NULL; obj_desc->package.count = new_count; }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng132100.00%1100.00%
Total132100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Robert Moore187872.18%1477.78%
Lv Zheng71527.48%316.67%
Fenghua Yu90.35%15.56%
Total2602100.00%18100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.