195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2ad5babeeSBob Moore /******************************************************************************
3ad5babeeSBob Moore *
4ad5babeeSBob Moore * Module Name: nsrepair2 - Repair for objects returned by specific
5ad5babeeSBob Moore * predefined methods
6ad5babeeSBob Moore *
7*612c2932SBob Moore * Copyright (C) 2000 - 2023, Intel Corp.
8ad5babeeSBob Moore *
995857638SErik Schmauss *****************************************************************************/
10ad5babeeSBob Moore
11ad5babeeSBob Moore #include <acpi/acpi.h>
12ad5babeeSBob Moore #include "accommon.h"
13ad5babeeSBob Moore #include "acnamesp.h"
14ad5babeeSBob Moore
15ad5babeeSBob Moore #define _COMPONENT ACPI_NAMESPACE
16ad5babeeSBob Moore ACPI_MODULE_NAME("nsrepair2")
17ad5babeeSBob Moore
18ad5babeeSBob Moore /*
19ad5babeeSBob Moore * Information structure and handler for ACPI predefined names that can
20ad5babeeSBob Moore * be repaired on a per-name basis.
21ad5babeeSBob Moore */
22ad5babeeSBob Moore typedef
2329a241ccSBob Moore acpi_status (*acpi_repair_function) (struct acpi_evaluate_info * info,
24f5c1e1c5SLv Zheng union acpi_operand_object **
25f5c1e1c5SLv Zheng return_object_ptr);
26ad5babeeSBob Moore
27ad5babeeSBob Moore typedef struct acpi_repair_info {
2832786755SBob Moore char name[ACPI_NAMESEG_SIZE];
29ad5babeeSBob Moore acpi_repair_function repair_function;
30ad5babeeSBob Moore
31ad5babeeSBob Moore } acpi_repair_info;
32ad5babeeSBob Moore
33ad5babeeSBob Moore /* Local prototypes */
34ad5babeeSBob Moore
35d5a36100SBob Moore static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
36ad5babeeSBob Moore acpi_namespace_node
37ad5babeeSBob Moore *node);
38ad5babeeSBob Moore
39ad5babeeSBob Moore static acpi_status
4029a241ccSBob Moore acpi_ns_repair_ALR(struct acpi_evaluate_info *info,
41ad5babeeSBob Moore union acpi_operand_object **return_object_ptr);
42ad5babeeSBob Moore
43ad5babeeSBob Moore static acpi_status
4429a241ccSBob Moore acpi_ns_repair_CID(struct acpi_evaluate_info *info,
4577b23f71SBob Moore union acpi_operand_object **return_object_ptr);
4677b23f71SBob Moore
4777b23f71SBob Moore static acpi_status
485a9792f3SLv Zheng acpi_ns_repair_CST(struct acpi_evaluate_info *info,
495a9792f3SLv Zheng union acpi_operand_object **return_object_ptr);
505a9792f3SLv Zheng
515a9792f3SLv Zheng static acpi_status
5229a241ccSBob Moore acpi_ns_repair_FDE(struct acpi_evaluate_info *info,
5334c39c75SBob Moore union acpi_operand_object **return_object_ptr);
5434c39c75SBob Moore
5534c39c75SBob Moore static acpi_status
5629a241ccSBob Moore acpi_ns_repair_HID(struct acpi_evaluate_info *info,
5777b23f71SBob Moore union acpi_operand_object **return_object_ptr);
5877b23f71SBob Moore
5977b23f71SBob Moore static acpi_status
60aa6329c4SLv Zheng acpi_ns_repair_PRT(struct acpi_evaluate_info *info,
61aa6329c4SLv Zheng union acpi_operand_object **return_object_ptr);
62aa6329c4SLv Zheng
63aa6329c4SLv Zheng static acpi_status
6429a241ccSBob Moore acpi_ns_repair_PSS(struct acpi_evaluate_info *info,
65ad5babeeSBob Moore union acpi_operand_object **return_object_ptr);
66ad5babeeSBob Moore
67ad5babeeSBob Moore static acpi_status
6829a241ccSBob Moore acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
69ad5babeeSBob Moore union acpi_operand_object **return_object_ptr);
70ad5babeeSBob Moore
71ad5babeeSBob Moore static acpi_status
7229a241ccSBob Moore acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
73ad5babeeSBob Moore union acpi_operand_object *return_object,
745a9792f3SLv Zheng u32 start_index,
75ad5babeeSBob Moore u32 expected_count,
76ad5babeeSBob Moore u32 sort_index,
77ad5babeeSBob Moore u8 sort_direction, char *sort_key_name);
78ad5babeeSBob Moore
79ad5babeeSBob Moore /* Values for sort_direction above */
80ad5babeeSBob Moore
81ad5babeeSBob Moore #define ACPI_SORT_ASCENDING 0
82ad5babeeSBob Moore #define ACPI_SORT_DESCENDING 1
83ad5babeeSBob Moore
845a9792f3SLv Zheng static void
855a9792f3SLv Zheng acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index);
865a9792f3SLv Zheng
875a9792f3SLv Zheng static void
885a9792f3SLv Zheng acpi_ns_sort_list(union acpi_operand_object **elements,
895a9792f3SLv Zheng u32 count, u32 index, u8 sort_direction);
905a9792f3SLv Zheng
91ad5babeeSBob Moore /*
92ad5babeeSBob Moore * This table contains the names of the predefined methods for which we can
93ad5babeeSBob Moore * perform more complex repairs.
94ad5babeeSBob Moore *
9534c39c75SBob Moore * As necessary:
9634c39c75SBob Moore *
9734c39c75SBob Moore * _ALR: Sort the list ascending by ambient_illuminance
9877b23f71SBob Moore * _CID: Strings: uppercase all, remove any leading asterisk
995a9792f3SLv Zheng * _CST: Sort the list ascending by C state type
10043420bbbSBob Moore * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
10143420bbbSBob Moore * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
10277b23f71SBob Moore * _HID: Strings: uppercase all, remove any leading asterisk
103aa6329c4SLv Zheng * _PRT: Fix reversed source_name and source_index
10434c39c75SBob Moore * _PSS: Sort the list descending by Power
10534c39c75SBob Moore * _TSS: Sort the list descending by Power
106aa9d3606SBob Moore *
107aa9d3606SBob Moore * Names that must be packages, but cannot be sorted:
108aa9d3606SBob Moore *
109aa9d3606SBob Moore * _BCL: Values are tied to the Package index where they appear, and cannot
110aa9d3606SBob Moore * be moved or sorted. These index values are used for _BQC and _BCM.
111aa9d3606SBob Moore * However, we can fix the case where a buffer is returned, by converting
112aa9d3606SBob Moore * it to a Package of integers.
113ad5babeeSBob Moore */
114ad5babeeSBob Moore static const struct acpi_repair_info acpi_ns_repairable_names[] = {
115ad5babeeSBob Moore {"_ALR", acpi_ns_repair_ALR},
11677b23f71SBob Moore {"_CID", acpi_ns_repair_CID},
1175a9792f3SLv Zheng {"_CST", acpi_ns_repair_CST},
11834c39c75SBob Moore {"_FDE", acpi_ns_repair_FDE},
11934c39c75SBob Moore {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */
12077b23f71SBob Moore {"_HID", acpi_ns_repair_HID},
121aa6329c4SLv Zheng {"_PRT", acpi_ns_repair_PRT},
122ad5babeeSBob Moore {"_PSS", acpi_ns_repair_PSS},
123ad5babeeSBob Moore {"_TSS", acpi_ns_repair_TSS},
124ad5babeeSBob Moore {{0, 0, 0, 0}, NULL} /* Table terminator */
125ad5babeeSBob Moore };
126ad5babeeSBob Moore
12734c39c75SBob Moore #define ACPI_FDE_FIELD_COUNT 5
12834c39c75SBob Moore #define ACPI_FDE_BYTE_BUFFER_SIZE 5
129231ec06eSBob Moore #define ACPI_FDE_DWORD_BUFFER_SIZE (ACPI_FDE_FIELD_COUNT * (u32) sizeof (u32))
13034c39c75SBob Moore
131ad5babeeSBob Moore /******************************************************************************
132ad5babeeSBob Moore *
133ad5babeeSBob Moore * FUNCTION: acpi_ns_complex_repairs
134ad5babeeSBob Moore *
13529a241ccSBob Moore * PARAMETERS: info - Method execution information block
136ba494beeSBob Moore * node - Namespace node for the method/object
137ad5babeeSBob Moore * validate_status - Original status of earlier validation
138ad5babeeSBob Moore * return_object_ptr - Pointer to the object returned from the
139ad5babeeSBob Moore * evaluation of a method or object
140ad5babeeSBob Moore *
141ad5babeeSBob Moore * RETURN: Status. AE_OK if repair was successful. If name is not
142ad5babeeSBob Moore * matched, validate_status is returned.
143ad5babeeSBob Moore *
144ad5babeeSBob Moore * DESCRIPTION: Attempt to repair/convert a return object of a type that was
145ad5babeeSBob Moore * not expected.
146ad5babeeSBob Moore *
147ad5babeeSBob Moore *****************************************************************************/
148ad5babeeSBob Moore
149ad5babeeSBob Moore 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)15029a241ccSBob Moore acpi_ns_complex_repairs(struct acpi_evaluate_info *info,
151ad5babeeSBob Moore struct acpi_namespace_node *node,
152ad5babeeSBob Moore acpi_status validate_status,
153ad5babeeSBob Moore union acpi_operand_object **return_object_ptr)
154ad5babeeSBob Moore {
155ad5babeeSBob Moore const struct acpi_repair_info *predefined;
156ad5babeeSBob Moore acpi_status status;
157ad5babeeSBob Moore
1580766efdfSErik Kaneda ACPI_FUNCTION_TRACE(ns_complex_repairs);
1590766efdfSErik Kaneda
160ad5babeeSBob Moore /* Check if this name is in the list of repairable names */
161ad5babeeSBob Moore
162d5a36100SBob Moore predefined = acpi_ns_match_complex_repair(node);
163ad5babeeSBob Moore if (!predefined) {
1640766efdfSErik Kaneda return_ACPI_STATUS(validate_status);
165ad5babeeSBob Moore }
166ad5babeeSBob Moore
16729a241ccSBob Moore status = predefined->repair_function(info, return_object_ptr);
1680766efdfSErik Kaneda return_ACPI_STATUS(status);
169ad5babeeSBob Moore }
170ad5babeeSBob Moore
171ad5babeeSBob Moore /******************************************************************************
172ad5babeeSBob Moore *
173d5a36100SBob Moore * FUNCTION: acpi_ns_match_complex_repair
174ad5babeeSBob Moore *
175ba494beeSBob Moore * PARAMETERS: node - Namespace node for the method/object
176ad5babeeSBob Moore *
177ad5babeeSBob Moore * RETURN: Pointer to entry in repair table. NULL indicates not found.
178ad5babeeSBob Moore *
179ad5babeeSBob Moore * DESCRIPTION: Check an object name against the repairable object list.
180ad5babeeSBob Moore *
181ad5babeeSBob Moore *****************************************************************************/
182ad5babeeSBob Moore
acpi_ns_match_complex_repair(struct acpi_namespace_node * node)183d5a36100SBob Moore static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
184ad5babeeSBob Moore acpi_namespace_node
185ad5babeeSBob Moore *node)
186ad5babeeSBob Moore {
187ad5babeeSBob Moore const struct acpi_repair_info *this_name;
188ad5babeeSBob Moore
189ad5babeeSBob Moore /* Search info table for a repairable predefined method/object name */
190ad5babeeSBob Moore
191ad5babeeSBob Moore this_name = acpi_ns_repairable_names;
192ad5babeeSBob Moore while (this_name->repair_function) {
1935599fb69SBob Moore if (ACPI_COMPARE_NAMESEG(node->name.ascii, this_name->name)) {
194ad5babeeSBob Moore return (this_name);
195ad5babeeSBob Moore }
1961fad8738SBob Moore
197ad5babeeSBob Moore this_name++;
198ad5babeeSBob Moore }
199ad5babeeSBob Moore
200ad5babeeSBob Moore return (NULL); /* Not found */
201ad5babeeSBob Moore }
202ad5babeeSBob Moore
203ad5babeeSBob Moore /******************************************************************************
204ad5babeeSBob Moore *
205ad5babeeSBob Moore * FUNCTION: acpi_ns_repair_ALR
206ad5babeeSBob Moore *
20729a241ccSBob Moore * PARAMETERS: info - Method execution information block
208ad5babeeSBob Moore * return_object_ptr - Pointer to the object returned from the
209ad5babeeSBob Moore * evaluation of a method or object
210ad5babeeSBob Moore *
211ad5babeeSBob Moore * RETURN: Status. AE_OK if object is OK or was repaired successfully
212ad5babeeSBob Moore *
213ad5babeeSBob Moore * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
214ad5babeeSBob Moore * ascending by the ambient illuminance values.
215ad5babeeSBob Moore *
216ad5babeeSBob Moore *****************************************************************************/
217ad5babeeSBob Moore
218ad5babeeSBob Moore static acpi_status
acpi_ns_repair_ALR(struct acpi_evaluate_info * info,union acpi_operand_object ** return_object_ptr)21929a241ccSBob Moore acpi_ns_repair_ALR(struct acpi_evaluate_info *info,
220ad5babeeSBob Moore union acpi_operand_object **return_object_ptr)
221ad5babeeSBob Moore {
222ad5babeeSBob Moore union acpi_operand_object *return_object = *return_object_ptr;
223ad5babeeSBob Moore acpi_status status;
224ad5babeeSBob Moore
2255a9792f3SLv Zheng status = acpi_ns_check_sorted_list(info, return_object, 0, 2, 1,
226ad5babeeSBob Moore ACPI_SORT_ASCENDING,
227ad5babeeSBob Moore "AmbientIlluminance");
228ad5babeeSBob Moore
229ad5babeeSBob Moore return (status);
230ad5babeeSBob Moore }
231ad5babeeSBob Moore
232ad5babeeSBob Moore /******************************************************************************
233ad5babeeSBob Moore *
23434c39c75SBob Moore * FUNCTION: acpi_ns_repair_FDE
23534c39c75SBob Moore *
23629a241ccSBob Moore * PARAMETERS: info - Method execution information block
23734c39c75SBob Moore * return_object_ptr - Pointer to the object returned from the
23834c39c75SBob Moore * evaluation of a method or object
23934c39c75SBob Moore *
24034c39c75SBob Moore * RETURN: Status. AE_OK if object is OK or was repaired successfully
24134c39c75SBob Moore *
24234c39c75SBob Moore * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return
24343420bbbSBob Moore * value is a Buffer of 5 DWORDs. This function repairs a common
24443420bbbSBob Moore * problem where the return value is a Buffer of BYTEs, not
24543420bbbSBob Moore * DWORDs.
24634c39c75SBob Moore *
24734c39c75SBob Moore *****************************************************************************/
24834c39c75SBob Moore
24934c39c75SBob Moore static acpi_status
acpi_ns_repair_FDE(struct acpi_evaluate_info * info,union acpi_operand_object ** return_object_ptr)25029a241ccSBob Moore acpi_ns_repair_FDE(struct acpi_evaluate_info *info,
25134c39c75SBob Moore union acpi_operand_object **return_object_ptr)
25234c39c75SBob Moore {
25334c39c75SBob Moore union acpi_operand_object *return_object = *return_object_ptr;
25434c39c75SBob Moore union acpi_operand_object *buffer_object;
25534c39c75SBob Moore u8 *byte_buffer;
25634c39c75SBob Moore u32 *dword_buffer;
25734c39c75SBob Moore u32 i;
25834c39c75SBob Moore
2593a58176eSBob Moore ACPI_FUNCTION_NAME(ns_repair_FDE);
2603a58176eSBob Moore
26134c39c75SBob Moore switch (return_object->common.type) {
26234c39c75SBob Moore case ACPI_TYPE_BUFFER:
26334c39c75SBob Moore
26434c39c75SBob Moore /* This is the expected type. Length should be (at least) 5 DWORDs */
26534c39c75SBob Moore
26634c39c75SBob Moore if (return_object->buffer.length >= ACPI_FDE_DWORD_BUFFER_SIZE) {
26734c39c75SBob Moore return (AE_OK);
26834c39c75SBob Moore }
26934c39c75SBob Moore
27034c39c75SBob Moore /* We can only repair if we have exactly 5 BYTEs */
27134c39c75SBob Moore
27234c39c75SBob Moore if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) {
2731fad8738SBob Moore ACPI_WARN_PREDEFINED((AE_INFO,
2741fad8738SBob Moore info->full_pathname,
27529a241ccSBob Moore info->node_flags,
27634c39c75SBob Moore "Incorrect return buffer length %u, expected %u",
27734c39c75SBob Moore return_object->buffer.length,
27834c39c75SBob Moore ACPI_FDE_DWORD_BUFFER_SIZE));
27934c39c75SBob Moore
28034c39c75SBob Moore return (AE_AML_OPERAND_TYPE);
28134c39c75SBob Moore }
28234c39c75SBob Moore
28334c39c75SBob Moore /* Create the new (larger) buffer object */
28434c39c75SBob Moore
28534c39c75SBob Moore buffer_object =
28634c39c75SBob Moore acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE);
28734c39c75SBob Moore if (!buffer_object) {
28834c39c75SBob Moore return (AE_NO_MEMORY);
28934c39c75SBob Moore }
29034c39c75SBob Moore
29134c39c75SBob Moore /* Expand each byte to a DWORD */
29234c39c75SBob Moore
29334c39c75SBob Moore byte_buffer = return_object->buffer.pointer;
2941fad8738SBob Moore dword_buffer = ACPI_CAST_PTR(u32,
2951fad8738SBob Moore buffer_object->buffer.pointer);
29634c39c75SBob Moore
29734c39c75SBob Moore for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) {
29834c39c75SBob Moore *dword_buffer = (u32) *byte_buffer;
29934c39c75SBob Moore dword_buffer++;
30034c39c75SBob Moore byte_buffer++;
30134c39c75SBob Moore }
30234c39c75SBob Moore
3033a58176eSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
3043a58176eSBob Moore "%s Expanded Byte Buffer to expected DWord Buffer\n",
30529a241ccSBob Moore info->full_pathname));
30634c39c75SBob Moore break;
30734c39c75SBob Moore
30834c39c75SBob Moore default:
3091d1ea1b7SChao Guan
31034c39c75SBob Moore return (AE_AML_OPERAND_TYPE);
31134c39c75SBob Moore }
31234c39c75SBob Moore
31334c39c75SBob Moore /* Delete the original return object, return the new buffer object */
31434c39c75SBob Moore
31534c39c75SBob Moore acpi_ut_remove_reference(return_object);
31634c39c75SBob Moore *return_object_ptr = buffer_object;
31734c39c75SBob Moore
31829a241ccSBob Moore info->return_flags |= ACPI_OBJECT_REPAIRED;
31934c39c75SBob Moore return (AE_OK);
32034c39c75SBob Moore }
32134c39c75SBob Moore
32234c39c75SBob Moore /******************************************************************************
32334c39c75SBob Moore *
32477b23f71SBob Moore * FUNCTION: acpi_ns_repair_CID
32577b23f71SBob Moore *
32629a241ccSBob Moore * PARAMETERS: info - Method execution information block
32777b23f71SBob Moore * return_object_ptr - Pointer to the object returned from the
32877b23f71SBob Moore * evaluation of a method or object
32977b23f71SBob Moore *
33077b23f71SBob Moore * RETURN: Status. AE_OK if object is OK or was repaired successfully
33177b23f71SBob Moore *
33277b23f71SBob Moore * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
33377b23f71SBob Moore * letters are uppercase and that there is no leading asterisk.
33477b23f71SBob Moore * If a Package, ensure same for all string elements.
33577b23f71SBob Moore *
33677b23f71SBob Moore *****************************************************************************/
33777b23f71SBob Moore
33877b23f71SBob Moore static acpi_status
acpi_ns_repair_CID(struct acpi_evaluate_info * info,union acpi_operand_object ** return_object_ptr)33929a241ccSBob Moore acpi_ns_repair_CID(struct acpi_evaluate_info *info,
34077b23f71SBob Moore union acpi_operand_object **return_object_ptr)
34177b23f71SBob Moore {
34277b23f71SBob Moore acpi_status status;
34377b23f71SBob Moore union acpi_operand_object *return_object = *return_object_ptr;
34477b23f71SBob Moore union acpi_operand_object **element_ptr;
34577b23f71SBob Moore union acpi_operand_object *original_element;
34677b23f71SBob Moore u16 original_ref_count;
34777b23f71SBob Moore u32 i;
34877b23f71SBob Moore
3490766efdfSErik Kaneda ACPI_FUNCTION_TRACE(ns_repair_CID);
3500766efdfSErik Kaneda
35177b23f71SBob Moore /* Check for _CID as a simple string */
35277b23f71SBob Moore
35377b23f71SBob Moore if (return_object->common.type == ACPI_TYPE_STRING) {
35429a241ccSBob Moore status = acpi_ns_repair_HID(info, return_object_ptr);
3550766efdfSErik Kaneda return_ACPI_STATUS(status);
35677b23f71SBob Moore }
35777b23f71SBob Moore
35877b23f71SBob Moore /* Exit if not a Package */
35977b23f71SBob Moore
36077b23f71SBob Moore if (return_object->common.type != ACPI_TYPE_PACKAGE) {
3610766efdfSErik Kaneda return_ACPI_STATUS(AE_OK);
36277b23f71SBob Moore }
36377b23f71SBob Moore
36477b23f71SBob Moore /* Examine each element of the _CID package */
36577b23f71SBob Moore
36677b23f71SBob Moore element_ptr = return_object->package.elements;
36777b23f71SBob Moore for (i = 0; i < return_object->package.count; i++) {
36877b23f71SBob Moore original_element = *element_ptr;
36977b23f71SBob Moore original_ref_count = original_element->common.reference_count;
37077b23f71SBob Moore
37129a241ccSBob Moore status = acpi_ns_repair_HID(info, element_ptr);
37277b23f71SBob Moore if (ACPI_FAILURE(status)) {
3730766efdfSErik Kaneda return_ACPI_STATUS(status);
37477b23f71SBob Moore }
37577b23f71SBob Moore
37677b23f71SBob Moore if (original_element != *element_ptr) {
37777b23f71SBob Moore
378ed7f8bc9SBob Moore /* Update reference count of new object */
37977b23f71SBob Moore
38077b23f71SBob Moore (*element_ptr)->common.reference_count =
38177b23f71SBob Moore original_ref_count;
38277b23f71SBob Moore }
38377b23f71SBob Moore
38477b23f71SBob Moore element_ptr++;
38577b23f71SBob Moore }
38677b23f71SBob Moore
3870766efdfSErik Kaneda return_ACPI_STATUS(AE_OK);
38877b23f71SBob Moore }
38977b23f71SBob Moore
39077b23f71SBob Moore /******************************************************************************
39177b23f71SBob Moore *
3925a9792f3SLv Zheng * FUNCTION: acpi_ns_repair_CST
3935a9792f3SLv Zheng *
3945a9792f3SLv Zheng * PARAMETERS: info - Method execution information block
3955a9792f3SLv Zheng * return_object_ptr - Pointer to the object returned from the
3965a9792f3SLv Zheng * evaluation of a method or object
3975a9792f3SLv Zheng *
3985a9792f3SLv Zheng * RETURN: Status. AE_OK if object is OK or was repaired successfully
3995a9792f3SLv Zheng *
4005a9792f3SLv Zheng * DESCRIPTION: Repair for the _CST object:
4015a9792f3SLv Zheng * 1. Sort the list ascending by C state type
4025a9792f3SLv Zheng * 2. Ensure type cannot be zero
4030a16d12aSBob Moore * 3. A subpackage count of zero means _CST is meaningless
4040a16d12aSBob Moore * 4. Count must match the number of C state subpackages
4055a9792f3SLv Zheng *
4065a9792f3SLv Zheng *****************************************************************************/
4075a9792f3SLv Zheng
4085a9792f3SLv Zheng static acpi_status
acpi_ns_repair_CST(struct acpi_evaluate_info * info,union acpi_operand_object ** return_object_ptr)4095a9792f3SLv Zheng acpi_ns_repair_CST(struct acpi_evaluate_info *info,
4105a9792f3SLv Zheng union acpi_operand_object **return_object_ptr)
4115a9792f3SLv Zheng {
4125a9792f3SLv Zheng union acpi_operand_object *return_object = *return_object_ptr;
4135a9792f3SLv Zheng union acpi_operand_object **outer_elements;
4145a9792f3SLv Zheng u32 outer_element_count;
4155a9792f3SLv Zheng union acpi_operand_object *obj_desc;
4165a9792f3SLv Zheng acpi_status status;
4175a9792f3SLv Zheng u8 removing;
4185a9792f3SLv Zheng u32 i;
4195a9792f3SLv Zheng
4205a9792f3SLv Zheng ACPI_FUNCTION_NAME(ns_repair_CST);
4215a9792f3SLv Zheng
4225a9792f3SLv Zheng /*
423341e7ba1SLv Zheng * Check if the C-state type values are proportional.
4245a9792f3SLv Zheng */
4255a9792f3SLv Zheng outer_element_count = return_object->package.count - 1;
4265a9792f3SLv Zheng i = 0;
4275a9792f3SLv Zheng while (i < outer_element_count) {
4285a9792f3SLv Zheng outer_elements = &return_object->package.elements[i + 1];
4295a9792f3SLv Zheng removing = FALSE;
4305a9792f3SLv Zheng
4315a9792f3SLv Zheng if ((*outer_elements)->package.count == 0) {
4321fad8738SBob Moore ACPI_WARN_PREDEFINED((AE_INFO,
4331fad8738SBob Moore info->full_pathname,
4345a9792f3SLv Zheng info->node_flags,
4355a9792f3SLv Zheng "SubPackage[%u] - removing entry due to zero count",
4365a9792f3SLv Zheng i));
4375a9792f3SLv Zheng removing = TRUE;
4385a9792f3SLv Zheng goto remove_element;
4395a9792f3SLv Zheng }
4405a9792f3SLv Zheng
4415a9792f3SLv Zheng obj_desc = (*outer_elements)->package.elements[1]; /* Index1 = Type */
4425a9792f3SLv Zheng if ((u32)obj_desc->integer.value == 0) {
4431fad8738SBob Moore ACPI_WARN_PREDEFINED((AE_INFO,
4441fad8738SBob Moore info->full_pathname,
4455a9792f3SLv Zheng info->node_flags,
4465a9792f3SLv Zheng "SubPackage[%u] - removing entry due to invalid Type(0)",
4475a9792f3SLv Zheng i));
4485a9792f3SLv Zheng removing = TRUE;
4495a9792f3SLv Zheng }
4505a9792f3SLv Zheng
4515a9792f3SLv Zheng remove_element:
4525a9792f3SLv Zheng if (removing) {
4535a9792f3SLv Zheng acpi_ns_remove_element(return_object, i + 1);
4545a9792f3SLv Zheng outer_element_count--;
4555a9792f3SLv Zheng } else {
4565a9792f3SLv Zheng i++;
4575a9792f3SLv Zheng }
4585a9792f3SLv Zheng }
4595a9792f3SLv Zheng
4605a9792f3SLv Zheng /* Update top-level package count, Type "Integer" checked elsewhere */
4615a9792f3SLv Zheng
4625a9792f3SLv Zheng obj_desc = return_object->package.elements[0];
4635a9792f3SLv Zheng obj_desc->integer.value = outer_element_count;
464341e7ba1SLv Zheng
465341e7ba1SLv Zheng /*
466341e7ba1SLv Zheng * Entries (subpackages) in the _CST Package must be sorted by the
467341e7ba1SLv Zheng * C-state type, in ascending order.
468341e7ba1SLv Zheng */
469341e7ba1SLv Zheng status = acpi_ns_check_sorted_list(info, return_object, 1, 4, 1,
470341e7ba1SLv Zheng ACPI_SORT_ASCENDING, "C-State Type");
471341e7ba1SLv Zheng if (ACPI_FAILURE(status)) {
472341e7ba1SLv Zheng return (status);
473341e7ba1SLv Zheng }
474341e7ba1SLv Zheng
4755a9792f3SLv Zheng return (AE_OK);
4765a9792f3SLv Zheng }
4775a9792f3SLv Zheng
4785a9792f3SLv Zheng /******************************************************************************
4795a9792f3SLv Zheng *
48077b23f71SBob Moore * FUNCTION: acpi_ns_repair_HID
48177b23f71SBob Moore *
48229a241ccSBob Moore * PARAMETERS: info - Method execution information block
48377b23f71SBob Moore * return_object_ptr - Pointer to the object returned from the
48477b23f71SBob Moore * evaluation of a method or object
48577b23f71SBob Moore *
48677b23f71SBob Moore * RETURN: Status. AE_OK if object is OK or was repaired successfully
48777b23f71SBob Moore *
48877b23f71SBob Moore * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
48977b23f71SBob Moore * letters are uppercase and that there is no leading asterisk.
49077b23f71SBob Moore *
49177b23f71SBob Moore *****************************************************************************/
49277b23f71SBob Moore
49377b23f71SBob Moore static acpi_status
acpi_ns_repair_HID(struct acpi_evaluate_info * info,union acpi_operand_object ** return_object_ptr)49429a241ccSBob Moore acpi_ns_repair_HID(struct acpi_evaluate_info *info,
49577b23f71SBob Moore union acpi_operand_object **return_object_ptr)
49677b23f71SBob Moore {
49777b23f71SBob Moore union acpi_operand_object *return_object = *return_object_ptr;
498fe0af090SArd Biesheuvel union acpi_operand_object *new_string;
49932cf1a12SErik Kaneda char *source;
500fe0af090SArd Biesheuvel char *dest;
50177b23f71SBob Moore
5029db8a1c2SXiongfeng Wang ACPI_FUNCTION_TRACE(ns_repair_HID);
50377b23f71SBob Moore
50477b23f71SBob Moore /* We only care about string _HID objects (not integers) */
50577b23f71SBob Moore
50677b23f71SBob Moore if (return_object->common.type != ACPI_TYPE_STRING) {
5070766efdfSErik Kaneda return_ACPI_STATUS(AE_OK);
50877b23f71SBob Moore }
50977b23f71SBob Moore
51077b23f71SBob Moore if (return_object->string.length == 0) {
5111fad8738SBob Moore ACPI_WARN_PREDEFINED((AE_INFO,
5121fad8738SBob Moore info->full_pathname, info->node_flags,
51377b23f71SBob Moore "Invalid zero-length _HID or _CID string"));
51477b23f71SBob Moore
51577b23f71SBob Moore /* Return AE_OK anyway, let driver handle it */
51677b23f71SBob Moore
51729a241ccSBob Moore info->return_flags |= ACPI_OBJECT_REPAIRED;
5180766efdfSErik Kaneda return_ACPI_STATUS(AE_OK);
51977b23f71SBob Moore }
52077b23f71SBob Moore
521fe0af090SArd Biesheuvel /* It is simplest to always create a new string object */
522fe0af090SArd Biesheuvel
523fe0af090SArd Biesheuvel new_string = acpi_ut_create_string_object(return_object->string.length);
524fe0af090SArd Biesheuvel if (!new_string) {
525fe0af090SArd Biesheuvel return_ACPI_STATUS(AE_NO_MEMORY);
526fe0af090SArd Biesheuvel }
527fe0af090SArd Biesheuvel
52877b23f71SBob Moore /*
52977b23f71SBob Moore * Remove a leading asterisk if present. For some unknown reason, there
53077b23f71SBob Moore * are many machines in the field that contains IDs like this.
53177b23f71SBob Moore *
53277b23f71SBob Moore * Examples: "*PNP0C03", "*ACPI0003"
53377b23f71SBob Moore */
53477b23f71SBob Moore source = return_object->string.pointer;
53577b23f71SBob Moore if (*source == '*') {
53677b23f71SBob Moore source++;
537fe0af090SArd Biesheuvel new_string->string.length--;
53877b23f71SBob Moore
53977b23f71SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
54077b23f71SBob Moore "%s: Removed invalid leading asterisk\n",
54129a241ccSBob Moore info->full_pathname));
54277b23f71SBob Moore }
54377b23f71SBob Moore
54477b23f71SBob Moore /*
5457fce7a4bSBob Moore * Copy and uppercase the string. From the ACPI 5.0 specification:
54677b23f71SBob Moore *
54777b23f71SBob Moore * A valid PNP ID must be of the form "AAA####" where A is an uppercase
54877b23f71SBob Moore * letter and # is a hex digit. A valid ACPI ID must be of the form
5497fce7a4bSBob Moore * "NNNN####" where N is an uppercase letter or decimal digit, and
5507fce7a4bSBob Moore * # is a hex digit.
55177b23f71SBob Moore */
552fe0af090SArd Biesheuvel for (dest = new_string->string.pointer; *source; dest++, source++) {
5534fa4616eSBob Moore *dest = (char)toupper((int)*source);
55477b23f71SBob Moore }
55577b23f71SBob Moore
556fe0af090SArd Biesheuvel acpi_ut_remove_reference(return_object);
557fe0af090SArd Biesheuvel *return_object_ptr = new_string;
5580766efdfSErik Kaneda return_ACPI_STATUS(AE_OK);
55977b23f71SBob Moore }
56077b23f71SBob Moore
56177b23f71SBob Moore /******************************************************************************
56277b23f71SBob Moore *
563aa6329c4SLv Zheng * FUNCTION: acpi_ns_repair_PRT
564ad5babeeSBob Moore *
56529a241ccSBob Moore * PARAMETERS: info - Method execution information block
566ad5babeeSBob Moore * return_object_ptr - Pointer to the object returned from the
567ad5babeeSBob Moore * evaluation of a method or object
568ad5babeeSBob Moore *
569ad5babeeSBob Moore * RETURN: Status. AE_OK if object is OK or was repaired successfully
570ad5babeeSBob Moore *
571aa6329c4SLv Zheng * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed
572aa6329c4SLv Zheng * source_name and source_index field, a common BIOS bug.
573ad5babeeSBob Moore *
574ad5babeeSBob Moore *****************************************************************************/
575ad5babeeSBob Moore
576ad5babeeSBob Moore static acpi_status
acpi_ns_repair_PRT(struct acpi_evaluate_info * info,union acpi_operand_object ** return_object_ptr)577aa6329c4SLv Zheng acpi_ns_repair_PRT(struct acpi_evaluate_info *info,
578ad5babeeSBob Moore union acpi_operand_object **return_object_ptr)
579ad5babeeSBob Moore {
580aa6329c4SLv Zheng union acpi_operand_object *package_object = *return_object_ptr;
581aa6329c4SLv Zheng union acpi_operand_object **top_object_list;
582aa6329c4SLv Zheng union acpi_operand_object **sub_object_list;
583aa6329c4SLv Zheng union acpi_operand_object *obj_desc;
5841c3c2a54SBob Moore union acpi_operand_object *sub_package;
585aa6329c4SLv Zheng u32 element_count;
586aa6329c4SLv Zheng u32 index;
587aa6329c4SLv Zheng
588aa6329c4SLv Zheng /* Each element in the _PRT package is a subpackage */
589aa6329c4SLv Zheng
590aa6329c4SLv Zheng top_object_list = package_object->package.elements;
591aa6329c4SLv Zheng element_count = package_object->package.count;
592aa6329c4SLv Zheng
59369e6bb68SBob Moore /* Examine each subpackage */
59469e6bb68SBob Moore
59569e6bb68SBob Moore for (index = 0; index < element_count; index++, top_object_list++) {
5961c3c2a54SBob Moore sub_package = *top_object_list;
5971c3c2a54SBob Moore sub_object_list = sub_package->package.elements;
5981c3c2a54SBob Moore
59969e6bb68SBob Moore /* Check for minimum required element count */
60069e6bb68SBob Moore
60169e6bb68SBob Moore if (sub_package->package.count < 4) {
60269e6bb68SBob Moore continue;
6031c3c2a54SBob Moore }
6048f9c9127SFenghua Yu
6058f9c9127SFenghua Yu /*
606aa6329c4SLv Zheng * If the BIOS has erroneously reversed the _PRT source_name (index 2)
607aa6329c4SLv Zheng * and the source_index (index 3), fix it. _PRT is important enough to
608aa6329c4SLv Zheng * workaround this BIOS error. This also provides compatibility with
609aa6329c4SLv Zheng * other ACPI implementations.
6108f9c9127SFenghua Yu */
611aa6329c4SLv Zheng obj_desc = sub_object_list[3];
612aa6329c4SLv Zheng if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) {
613aa6329c4SLv Zheng sub_object_list[3] = sub_object_list[2];
614aa6329c4SLv Zheng sub_object_list[2] = obj_desc;
615aa6329c4SLv Zheng info->return_flags |= ACPI_OBJECT_REPAIRED;
616aa6329c4SLv Zheng
61769e6bb68SBob Moore ACPI_WARN_PREDEFINED((AE_INFO,
61869e6bb68SBob Moore info->full_pathname,
619aa6329c4SLv Zheng info->node_flags,
620aa6329c4SLv Zheng "PRT[%X]: Fixed reversed SourceName and SourceIndex",
621aa6329c4SLv Zheng index));
6228f9c9127SFenghua Yu }
623aa6329c4SLv Zheng }
624aa6329c4SLv Zheng
625aa6329c4SLv Zheng return (AE_OK);
626ad5babeeSBob Moore }
627ad5babeeSBob Moore
628ad5babeeSBob Moore /******************************************************************************
629ad5babeeSBob Moore *
630ad5babeeSBob Moore * FUNCTION: acpi_ns_repair_PSS
631ad5babeeSBob Moore *
63229a241ccSBob Moore * PARAMETERS: info - Method execution information block
633ad5babeeSBob Moore * return_object_ptr - Pointer to the object returned from the
634ad5babeeSBob Moore * evaluation of a method or object
635ad5babeeSBob Moore *
636ad5babeeSBob Moore * RETURN: Status. AE_OK if object is OK or was repaired successfully
637ad5babeeSBob Moore *
638ad5babeeSBob Moore * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
639ad5babeeSBob Moore * by the CPU frequencies. Check that the power dissipation values
640ad5babeeSBob Moore * are all proportional to CPU frequency (i.e., sorting by
641ad5babeeSBob Moore * frequency should be the same as sorting by power.)
642ad5babeeSBob Moore *
643ad5babeeSBob Moore *****************************************************************************/
644ad5babeeSBob Moore
645ad5babeeSBob Moore static acpi_status
acpi_ns_repair_PSS(struct acpi_evaluate_info * info,union acpi_operand_object ** return_object_ptr)64629a241ccSBob Moore acpi_ns_repair_PSS(struct acpi_evaluate_info *info,
647ad5babeeSBob Moore union acpi_operand_object **return_object_ptr)
648ad5babeeSBob Moore {
649ad5babeeSBob Moore union acpi_operand_object *return_object = *return_object_ptr;
650ad5babeeSBob Moore union acpi_operand_object **outer_elements;
651ad5babeeSBob Moore u32 outer_element_count;
652ad5babeeSBob Moore union acpi_operand_object **elements;
653ad5babeeSBob Moore union acpi_operand_object *obj_desc;
654ad5babeeSBob Moore u32 previous_value;
655ad5babeeSBob Moore acpi_status status;
656ad5babeeSBob Moore u32 i;
657ad5babeeSBob Moore
658ad5babeeSBob Moore /*
6590a16d12aSBob Moore * Entries (subpackages) in the _PSS Package must be sorted by power
660ad5babeeSBob Moore * dissipation, in descending order. If it appears that the list is
661ad5babeeSBob Moore * incorrectly sorted, sort it. We sort by cpu_frequency, since this
662ad5babeeSBob Moore * should be proportional to the power.
663ad5babeeSBob Moore */
6645a9792f3SLv Zheng status = acpi_ns_check_sorted_list(info, return_object, 0, 6, 0,
665ad5babeeSBob Moore ACPI_SORT_DESCENDING,
666ad5babeeSBob Moore "CpuFrequency");
667ad5babeeSBob Moore if (ACPI_FAILURE(status)) {
668ad5babeeSBob Moore return (status);
669ad5babeeSBob Moore }
670ad5babeeSBob Moore
671ad5babeeSBob Moore /*
672ad5babeeSBob Moore * We now know the list is correctly sorted by CPU frequency. Check if
673ad5babeeSBob Moore * the power dissipation values are proportional.
674ad5babeeSBob Moore */
675ad5babeeSBob Moore previous_value = ACPI_UINT32_MAX;
676ad5babeeSBob Moore outer_elements = return_object->package.elements;
677ad5babeeSBob Moore outer_element_count = return_object->package.count;
678ad5babeeSBob Moore
679ad5babeeSBob Moore for (i = 0; i < outer_element_count; i++) {
680ad5babeeSBob Moore elements = (*outer_elements)->package.elements;
681ad5babeeSBob Moore obj_desc = elements[1]; /* Index1 = power_dissipation */
682ad5babeeSBob Moore
683ad5babeeSBob Moore if ((u32)obj_desc->integer.value > previous_value) {
6841fad8738SBob Moore ACPI_WARN_PREDEFINED((AE_INFO,
6851fad8738SBob Moore info->full_pathname,
68629a241ccSBob Moore info->node_flags,
687ad5babeeSBob Moore "SubPackage[%u,%u] - suspicious power dissipation values",
688ad5babeeSBob Moore i - 1, i));
689ad5babeeSBob Moore }
690ad5babeeSBob Moore
691ad5babeeSBob Moore previous_value = (u32) obj_desc->integer.value;
692ad5babeeSBob Moore outer_elements++;
693ad5babeeSBob Moore }
694ad5babeeSBob Moore
695ad5babeeSBob Moore return (AE_OK);
696ad5babeeSBob Moore }
697ad5babeeSBob Moore
698ad5babeeSBob Moore /******************************************************************************
699ad5babeeSBob Moore *
700aa6329c4SLv Zheng * FUNCTION: acpi_ns_repair_TSS
701aa6329c4SLv Zheng *
702aa6329c4SLv Zheng * PARAMETERS: info - Method execution information block
703aa6329c4SLv Zheng * return_object_ptr - Pointer to the object returned from the
704aa6329c4SLv Zheng * evaluation of a method or object
705aa6329c4SLv Zheng *
706aa6329c4SLv Zheng * RETURN: Status. AE_OK if object is OK or was repaired successfully
707aa6329c4SLv Zheng *
708aa6329c4SLv Zheng * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
709aa6329c4SLv Zheng * descending by the power dissipation values.
710aa6329c4SLv Zheng *
711aa6329c4SLv Zheng *****************************************************************************/
712aa6329c4SLv Zheng
713aa6329c4SLv Zheng static acpi_status
acpi_ns_repair_TSS(struct acpi_evaluate_info * info,union acpi_operand_object ** return_object_ptr)714aa6329c4SLv Zheng acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
715aa6329c4SLv Zheng union acpi_operand_object **return_object_ptr)
716aa6329c4SLv Zheng {
717aa6329c4SLv Zheng union acpi_operand_object *return_object = *return_object_ptr;
718aa6329c4SLv Zheng acpi_status status;
719aa6329c4SLv Zheng struct acpi_namespace_node *node;
720aa6329c4SLv Zheng
721aa6329c4SLv Zheng /*
722aa6329c4SLv Zheng * We can only sort the _TSS return package if there is no _PSS in the
723aa6329c4SLv Zheng * same scope. This is because if _PSS is present, the ACPI specification
724aa6329c4SLv Zheng * dictates that the _TSS Power Dissipation field is to be ignored, and
725aa6329c4SLv Zheng * therefore some BIOSs leave garbage values in the _TSS Power field(s).
726aa6329c4SLv Zheng * In this case, it is best to just return the _TSS package as-is.
727aa6329c4SLv Zheng * (May, 2011)
728aa6329c4SLv Zheng */
729aa6329c4SLv Zheng status = acpi_ns_get_node(info->node, "^_PSS",
730aa6329c4SLv Zheng ACPI_NS_NO_UPSEARCH, &node);
731aa6329c4SLv Zheng if (ACPI_SUCCESS(status)) {
732aa6329c4SLv Zheng return (AE_OK);
733aa6329c4SLv Zheng }
734aa6329c4SLv Zheng
7355a9792f3SLv Zheng status = acpi_ns_check_sorted_list(info, return_object, 0, 5, 1,
736aa6329c4SLv Zheng ACPI_SORT_DESCENDING,
737aa6329c4SLv Zheng "PowerDissipation");
738aa6329c4SLv Zheng
739aa6329c4SLv Zheng return (status);
740aa6329c4SLv Zheng }
741aa6329c4SLv Zheng
742aa6329c4SLv Zheng /******************************************************************************
743aa6329c4SLv Zheng *
744ad5babeeSBob Moore * FUNCTION: acpi_ns_check_sorted_list
745ad5babeeSBob Moore *
74629a241ccSBob Moore * PARAMETERS: info - Method execution information block
747ad5babeeSBob Moore * return_object - Pointer to the top-level returned object
7480a16d12aSBob Moore * start_index - Index of the first subpackage
7490a16d12aSBob Moore * expected_count - Minimum length of each subpackage
7500a16d12aSBob Moore * sort_index - Subpackage entry to sort on
751ad5babeeSBob Moore * sort_direction - Ascending or descending
752ad5babeeSBob Moore * sort_key_name - Name of the sort_index field
753ad5babeeSBob Moore *
754ad5babeeSBob Moore * RETURN: Status. AE_OK if the list is valid and is sorted correctly or
755ad5babeeSBob Moore * has been repaired by sorting the list.
756ad5babeeSBob Moore *
757ad5babeeSBob Moore * DESCRIPTION: Check if the package list is valid and sorted correctly by the
758ad5babeeSBob Moore * sort_index. If not, then sort the list.
759ad5babeeSBob Moore *
760ad5babeeSBob Moore *****************************************************************************/
761ad5babeeSBob Moore
762ad5babeeSBob Moore 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)76329a241ccSBob Moore acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
764ad5babeeSBob Moore union acpi_operand_object *return_object,
7655a9792f3SLv Zheng u32 start_index,
766ad5babeeSBob Moore u32 expected_count,
767ad5babeeSBob Moore u32 sort_index,
768ad5babeeSBob Moore u8 sort_direction, char *sort_key_name)
769ad5babeeSBob Moore {
770ad5babeeSBob Moore u32 outer_element_count;
771ad5babeeSBob Moore union acpi_operand_object **outer_elements;
772ad5babeeSBob Moore union acpi_operand_object **elements;
773ad5babeeSBob Moore union acpi_operand_object *obj_desc;
774ad5babeeSBob Moore u32 i;
775ad5babeeSBob Moore u32 previous_value;
776ad5babeeSBob Moore
7773a58176eSBob Moore ACPI_FUNCTION_NAME(ns_check_sorted_list);
7783a58176eSBob Moore
779ad5babeeSBob Moore /* The top-level object must be a package */
780ad5babeeSBob Moore
781ad5babeeSBob Moore if (return_object->common.type != ACPI_TYPE_PACKAGE) {
782ad5babeeSBob Moore return (AE_AML_OPERAND_TYPE);
783ad5babeeSBob Moore }
784ad5babeeSBob Moore
785ad5babeeSBob Moore /*
7860a16d12aSBob Moore * NOTE: assumes list of subpackages contains no NULL elements.
787d4085a3fSBob Moore * Any NULL elements should have been removed by earlier call
788d4085a3fSBob Moore * to acpi_ns_remove_null_elements.
789ad5babeeSBob Moore */
790ad5babeeSBob Moore outer_element_count = return_object->package.count;
7915a9792f3SLv Zheng if (!outer_element_count || start_index >= outer_element_count) {
792ad5babeeSBob Moore return (AE_AML_PACKAGE_LIMIT);
793ad5babeeSBob Moore }
794ad5babeeSBob Moore
7955a9792f3SLv Zheng outer_elements = &return_object->package.elements[start_index];
7965a9792f3SLv Zheng outer_element_count -= start_index;
7975a9792f3SLv Zheng
798ad5babeeSBob Moore previous_value = 0;
799ad5babeeSBob Moore if (sort_direction == ACPI_SORT_DESCENDING) {
800ad5babeeSBob Moore previous_value = ACPI_UINT32_MAX;
801ad5babeeSBob Moore }
802ad5babeeSBob Moore
803ad5babeeSBob Moore /* Examine each subpackage */
804ad5babeeSBob Moore
805ad5babeeSBob Moore for (i = 0; i < outer_element_count; i++) {
806ad5babeeSBob Moore
807ad5babeeSBob Moore /* Each element of the top-level package must also be a package */
808ad5babeeSBob Moore
809ad5babeeSBob Moore if ((*outer_elements)->common.type != ACPI_TYPE_PACKAGE) {
810ad5babeeSBob Moore return (AE_AML_OPERAND_TYPE);
811ad5babeeSBob Moore }
812ad5babeeSBob Moore
8130a16d12aSBob Moore /* Each subpackage must have the minimum length */
814ad5babeeSBob Moore
815ad5babeeSBob Moore if ((*outer_elements)->package.count < expected_count) {
816ad5babeeSBob Moore return (AE_AML_PACKAGE_LIMIT);
817ad5babeeSBob Moore }
818ad5babeeSBob Moore
819ad5babeeSBob Moore elements = (*outer_elements)->package.elements;
820ad5babeeSBob Moore obj_desc = elements[sort_index];
821ad5babeeSBob Moore
822ad5babeeSBob Moore if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
823ad5babeeSBob Moore return (AE_AML_OPERAND_TYPE);
824ad5babeeSBob Moore }
825ad5babeeSBob Moore
826ad5babeeSBob Moore /*
827ad5babeeSBob Moore * The list must be sorted in the specified order. If we detect a
8282147d3f0SBob Moore * discrepancy, sort the entire list.
829ad5babeeSBob Moore */
830ad5babeeSBob Moore if (((sort_direction == ACPI_SORT_ASCENDING) &&
831ad5babeeSBob Moore (obj_desc->integer.value < previous_value)) ||
832ad5babeeSBob Moore ((sort_direction == ACPI_SORT_DESCENDING) &&
833ad5babeeSBob Moore (obj_desc->integer.value > previous_value))) {
8345a9792f3SLv Zheng acpi_ns_sort_list(&return_object->package.
8355a9792f3SLv Zheng elements[start_index],
836ad5babeeSBob Moore outer_element_count, sort_index,
837ad5babeeSBob Moore sort_direction);
838ad5babeeSBob Moore
83929a241ccSBob Moore info->return_flags |= ACPI_OBJECT_REPAIRED;
840ad5babeeSBob Moore
8413a58176eSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
8423a58176eSBob Moore "%s: Repaired unsorted list - now sorted by %s\n",
84329a241ccSBob Moore info->full_pathname, sort_key_name));
844ad5babeeSBob Moore return (AE_OK);
845ad5babeeSBob Moore }
846ad5babeeSBob Moore
847ad5babeeSBob Moore previous_value = (u32) obj_desc->integer.value;
848ad5babeeSBob Moore outer_elements++;
849ad5babeeSBob Moore }
850ad5babeeSBob Moore
851ad5babeeSBob Moore return (AE_OK);
852ad5babeeSBob Moore }
853ad5babeeSBob Moore
854ad5babeeSBob Moore /******************************************************************************
855ad5babeeSBob Moore *
856ad5babeeSBob Moore * FUNCTION: acpi_ns_sort_list
857ad5babeeSBob Moore *
858ba494beeSBob Moore * PARAMETERS: elements - Package object element list
859ba494beeSBob Moore * count - Element count for above
860ba494beeSBob Moore * index - Sort by which package element
861ad5babeeSBob Moore * sort_direction - Ascending or Descending sort
862ad5babeeSBob Moore *
8632147d3f0SBob Moore * RETURN: None
864ad5babeeSBob Moore *
865ad5babeeSBob Moore * DESCRIPTION: Sort the objects that are in a package element list.
866ad5babeeSBob Moore *
8672147d3f0SBob Moore * NOTE: Assumes that all NULL elements have been removed from the package,
8682147d3f0SBob Moore * and that all elements have been verified to be of type Integer.
869ad5babeeSBob Moore *
870ad5babeeSBob Moore *****************************************************************************/
871ad5babeeSBob Moore
8722147d3f0SBob Moore static void
acpi_ns_sort_list(union acpi_operand_object ** elements,u32 count,u32 index,u8 sort_direction)873ad5babeeSBob Moore acpi_ns_sort_list(union acpi_operand_object **elements,
874ad5babeeSBob Moore u32 count, u32 index, u8 sort_direction)
875ad5babeeSBob Moore {
876ad5babeeSBob Moore union acpi_operand_object *obj_desc1;
877ad5babeeSBob Moore union acpi_operand_object *obj_desc2;
878ad5babeeSBob Moore union acpi_operand_object *temp_obj;
879ad5babeeSBob Moore u32 i;
880ad5babeeSBob Moore u32 j;
881ad5babeeSBob Moore
882ad5babeeSBob Moore /* Simple bubble sort */
883ad5babeeSBob Moore
884ad5babeeSBob Moore for (i = 1; i < count; i++) {
885ad5babeeSBob Moore for (j = (count - 1); j >= i; j--) {
886ad5babeeSBob Moore obj_desc1 = elements[j - 1]->package.elements[index];
887ad5babeeSBob Moore obj_desc2 = elements[j]->package.elements[index];
888ad5babeeSBob Moore
889ad5babeeSBob Moore if (((sort_direction == ACPI_SORT_ASCENDING) &&
890ad5babeeSBob Moore (obj_desc1->integer.value >
891ad5babeeSBob Moore obj_desc2->integer.value))
892ad5babeeSBob Moore || ((sort_direction == ACPI_SORT_DESCENDING)
893ad5babeeSBob Moore && (obj_desc1->integer.value <
894ad5babeeSBob Moore obj_desc2->integer.value))) {
895ad5babeeSBob Moore temp_obj = elements[j - 1];
896ad5babeeSBob Moore elements[j - 1] = elements[j];
897ad5babeeSBob Moore elements[j] = temp_obj;
898ad5babeeSBob Moore }
899ad5babeeSBob Moore }
900ad5babeeSBob Moore }
901ad5babeeSBob Moore }
9025a9792f3SLv Zheng
9035a9792f3SLv Zheng /******************************************************************************
9045a9792f3SLv Zheng *
9055a9792f3SLv Zheng * FUNCTION: acpi_ns_remove_element
9065a9792f3SLv Zheng *
9075a9792f3SLv Zheng * PARAMETERS: obj_desc - Package object element list
9085a9792f3SLv Zheng * index - Index of element to remove
9095a9792f3SLv Zheng *
9105a9792f3SLv Zheng * RETURN: None
9115a9792f3SLv Zheng *
9125a9792f3SLv Zheng * DESCRIPTION: Remove the requested element of a package and delete it.
9135a9792f3SLv Zheng *
9145a9792f3SLv Zheng *****************************************************************************/
9155a9792f3SLv Zheng
9165a9792f3SLv Zheng static void
acpi_ns_remove_element(union acpi_operand_object * obj_desc,u32 index)9175a9792f3SLv Zheng acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index)
9185a9792f3SLv Zheng {
9195a9792f3SLv Zheng union acpi_operand_object **source;
9205a9792f3SLv Zheng union acpi_operand_object **dest;
9215a9792f3SLv Zheng u32 count;
9225a9792f3SLv Zheng u32 new_count;
9235a9792f3SLv Zheng u32 i;
9245a9792f3SLv Zheng
9255a9792f3SLv Zheng ACPI_FUNCTION_NAME(ns_remove_element);
9265a9792f3SLv Zheng
9275a9792f3SLv Zheng count = obj_desc->package.count;
9285a9792f3SLv Zheng new_count = count - 1;
9295a9792f3SLv Zheng
9305a9792f3SLv Zheng source = obj_desc->package.elements;
9315a9792f3SLv Zheng dest = source;
9325a9792f3SLv Zheng
9335a9792f3SLv Zheng /* Examine all elements of the package object, remove matched index */
9345a9792f3SLv Zheng
9355a9792f3SLv Zheng for (i = 0; i < count; i++) {
9365a9792f3SLv Zheng if (i == index) {
9375a9792f3SLv Zheng acpi_ut_remove_reference(*source); /* Remove one ref for being in pkg */
9385a9792f3SLv Zheng acpi_ut_remove_reference(*source);
9395a9792f3SLv Zheng } else {
9405a9792f3SLv Zheng *dest = *source;
9415a9792f3SLv Zheng dest++;
9425a9792f3SLv Zheng }
9431fad8738SBob Moore
9445a9792f3SLv Zheng source++;
9455a9792f3SLv Zheng }
9465a9792f3SLv Zheng
9475a9792f3SLv Zheng /* NULL terminate list and update the package count */
9485a9792f3SLv Zheng
9495a9792f3SLv Zheng *dest = NULL;
9505a9792f3SLv Zheng obj_desc->package.count = new_count;
9515a9792f3SLv Zheng }
952