nsrepair2.c revision 199337
1199323Sjkim/******************************************************************************
2199323Sjkim *
3199323Sjkim * Module Name: nsrepair2 - Repair for objects returned by specific
4199323Sjkim *                          predefined methods
5199323Sjkim *
6199323Sjkim *****************************************************************************/
7199323Sjkim
8199323Sjkim/******************************************************************************
9199323Sjkim *
10199323Sjkim * 1. Copyright Notice
11199323Sjkim *
12199323Sjkim * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
13199323Sjkim * All rights reserved.
14199323Sjkim *
15199323Sjkim * 2. License
16199323Sjkim *
17199323Sjkim * 2.1. This is your license from Intel Corp. under its intellectual property
18199323Sjkim * rights.  You may have additional license terms from the party that provided
19199323Sjkim * you this software, covering your right to use that party's intellectual
20199323Sjkim * property rights.
21199323Sjkim *
22199323Sjkim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23199323Sjkim * copy of the source code appearing in this file ("Covered Code") an
24199323Sjkim * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25199323Sjkim * base code distributed originally by Intel ("Original Intel Code") to copy,
26199323Sjkim * make derivatives, distribute, use and display any portion of the Covered
27199323Sjkim * Code in any form, with the right to sublicense such rights; and
28199323Sjkim *
29199323Sjkim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30199323Sjkim * license (with the right to sublicense), under only those claims of Intel
31199323Sjkim * patents that are infringed by the Original Intel Code, to make, use, sell,
32199323Sjkim * offer to sell, and import the Covered Code and derivative works thereof
33199323Sjkim * solely to the minimum extent necessary to exercise the above copyright
34199323Sjkim * license, and in no event shall the patent license extend to any additions
35199323Sjkim * to or modifications of the Original Intel Code.  No other license or right
36199323Sjkim * is granted directly or by implication, estoppel or otherwise;
37199323Sjkim *
38199323Sjkim * The above copyright and patent license is granted only if the following
39199323Sjkim * conditions are met:
40199323Sjkim *
41199323Sjkim * 3. Conditions
42199323Sjkim *
43199323Sjkim * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44199323Sjkim * Redistribution of source code of any substantial portion of the Covered
45199323Sjkim * Code or modification with rights to further distribute source must include
46199323Sjkim * the above Copyright Notice, the above License, this list of Conditions,
47199323Sjkim * and the following Disclaimer and Export Compliance provision.  In addition,
48199323Sjkim * Licensee must cause all Covered Code to which Licensee contributes to
49199323Sjkim * contain a file documenting the changes Licensee made to create that Covered
50199323Sjkim * Code and the date of any change.  Licensee must include in that file the
51199323Sjkim * documentation of any changes made by any predecessor Licensee.  Licensee
52199323Sjkim * must include a prominent statement that the modification is derived,
53199323Sjkim * directly or indirectly, from Original Intel Code.
54199323Sjkim *
55199323Sjkim * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56199323Sjkim * Redistribution of source code of any substantial portion of the Covered
57199323Sjkim * Code or modification without rights to further distribute source must
58199323Sjkim * include the following Disclaimer and Export Compliance provision in the
59199323Sjkim * documentation and/or other materials provided with distribution.  In
60199323Sjkim * addition, Licensee may not authorize further sublicense of source of any
61199323Sjkim * portion of the Covered Code, and must include terms to the effect that the
62199323Sjkim * license from Licensee to its licensee is limited to the intellectual
63199323Sjkim * property embodied in the software Licensee provides to its licensee, and
64199323Sjkim * not to intellectual property embodied in modifications its licensee may
65199323Sjkim * make.
66199323Sjkim *
67199323Sjkim * 3.3. Redistribution of Executable. Redistribution in executable form of any
68199323Sjkim * substantial portion of the Covered Code or modification must reproduce the
69199323Sjkim * above Copyright Notice, and the following Disclaimer and Export Compliance
70199323Sjkim * provision in the documentation and/or other materials provided with the
71199323Sjkim * distribution.
72199323Sjkim *
73199323Sjkim * 3.4. Intel retains all right, title, and interest in and to the Original
74199323Sjkim * Intel Code.
75199323Sjkim *
76199323Sjkim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77199323Sjkim * Intel shall be used in advertising or otherwise to promote the sale, use or
78199323Sjkim * other dealings in products derived from or relating to the Covered Code
79199323Sjkim * without prior written authorization from Intel.
80199323Sjkim *
81199323Sjkim * 4. Disclaimer and Export Compliance
82199323Sjkim *
83199323Sjkim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84199323Sjkim * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85199323Sjkim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86199323Sjkim * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87199323Sjkim * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88199323Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89199323Sjkim * PARTICULAR PURPOSE.
90199323Sjkim *
91199323Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92199323Sjkim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93199323Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94199323Sjkim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95199323Sjkim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96199323Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97199323Sjkim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98199323Sjkim * LIMITED REMEDY.
99199323Sjkim *
100199323Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this
101199323Sjkim * software or system incorporating such software without first obtaining any
102199323Sjkim * required license or other approval from the U. S. Department of Commerce or
103199323Sjkim * any other agency or department of the United States Government.  In the
104199323Sjkim * event Licensee exports any such software from the United States or
105199323Sjkim * re-exports any such software from a foreign destination, Licensee shall
106199323Sjkim * ensure that the distribution and export/re-export of the software is in
107199323Sjkim * compliance with all laws, regulations, orders, or other restrictions of the
108199323Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109199323Sjkim * any of its subsidiaries will export/re-export any technical data, process,
110199323Sjkim * software, or service, directly or indirectly, to any country for which the
111199323Sjkim * United States government or any agency thereof requires an export license,
112199323Sjkim * other governmental approval, or letter of assurance, without first obtaining
113199323Sjkim * such license, approval or letter.
114199323Sjkim *
115199323Sjkim *****************************************************************************/
116199323Sjkim
117199323Sjkim#define __NSREPAIR2_C__
118199323Sjkim
119199337Sjkim#include <contrib/dev/acpica/include/acpi.h>
120199337Sjkim#include <contrib/dev/acpica/include/accommon.h>
121199337Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
122199323Sjkim
123199323Sjkim#define _COMPONENT          ACPI_NAMESPACE
124199323Sjkim        ACPI_MODULE_NAME    ("nsrepair2")
125199323Sjkim
126199323Sjkim
127199323Sjkim/*
128199323Sjkim * Information structure and handler for ACPI predefined names that can
129199323Sjkim * be repaired on a per-name basis.
130199323Sjkim */
131199323Sjkimtypedef
132199323SjkimACPI_STATUS (*ACPI_REPAIR_FUNCTION) (
133199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
134199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
135199323Sjkim
136199323Sjkimtypedef struct acpi_repair_info
137199323Sjkim{
138199323Sjkim    char                    Name[ACPI_NAME_SIZE];
139199323Sjkim    ACPI_REPAIR_FUNCTION    RepairFunction;
140199323Sjkim
141199323Sjkim} ACPI_REPAIR_INFO;
142199323Sjkim
143199323Sjkim
144199323Sjkim/* Local prototypes */
145199323Sjkim
146199323Sjkimstatic const ACPI_REPAIR_INFO *
147199323SjkimAcpiNsMatchRepairableName (
148199323Sjkim    ACPI_NAMESPACE_NODE     *Node);
149199323Sjkim
150199323Sjkimstatic ACPI_STATUS
151199323SjkimAcpiNsRepair_ALR (
152199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
153199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
154199323Sjkim
155199323Sjkimstatic ACPI_STATUS
156199323SjkimAcpiNsRepair_PSS (
157199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
158199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
159199323Sjkim
160199323Sjkimstatic ACPI_STATUS
161199323SjkimAcpiNsRepair_TSS (
162199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
163199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
164199323Sjkim
165199323Sjkimstatic ACPI_STATUS
166199323SjkimAcpiNsCheckSortedList (
167199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
168199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject,
169199323Sjkim    UINT32                  ExpectedCount,
170199323Sjkim    UINT32                  SortIndex,
171199323Sjkim    UINT8                   SortDirection,
172199323Sjkim    char                    *SortKeyName);
173199323Sjkim
174199323Sjkimstatic ACPI_STATUS
175199323SjkimAcpiNsRemoveNullElements (
176199323Sjkim    ACPI_OPERAND_OBJECT     *Package);
177199323Sjkim
178199323Sjkimstatic ACPI_STATUS
179199323SjkimAcpiNsSortList (
180199323Sjkim    ACPI_OPERAND_OBJECT     **Elements,
181199323Sjkim    UINT32                  Count,
182199323Sjkim    UINT32                  Index,
183199323Sjkim    UINT8                   SortDirection);
184199323Sjkim
185199323Sjkim/* Values for SortDirection above */
186199323Sjkim
187199323Sjkim#define ACPI_SORT_ASCENDING     0
188199323Sjkim#define ACPI_SORT_DESCENDING    1
189199323Sjkim
190199323Sjkim
191199323Sjkim/*
192199323Sjkim * This table contains the names of the predefined methods for which we can
193199323Sjkim * perform more complex repairs.
194199323Sjkim *
195199323Sjkim * _ALR: Sort the list ascending by AmbientIlluminance if necessary
196199323Sjkim * _PSS: Sort the list descending by Power if necessary
197199323Sjkim * _TSS: Sort the list descending by Power if necessary
198199323Sjkim */
199199323Sjkimstatic const ACPI_REPAIR_INFO       AcpiNsRepairableNames[] =
200199323Sjkim{
201199323Sjkim    {"_ALR", AcpiNsRepair_ALR},
202199323Sjkim    {"_PSS", AcpiNsRepair_PSS},
203199323Sjkim    {"_TSS", AcpiNsRepair_TSS},
204199323Sjkim    {{0,0,0,0}, NULL}             /* Table terminator */
205199323Sjkim};
206199323Sjkim
207199323Sjkim
208199323Sjkim/******************************************************************************
209199323Sjkim *
210199323Sjkim * FUNCTION:    AcpiNsComplexRepairs
211199323Sjkim *
212199323Sjkim * PARAMETERS:  Data                - Pointer to validation data structure
213199323Sjkim *              Node                - Namespace node for the method/object
214199323Sjkim *              ValidateStatus      - Original status of earlier validation
215199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
216199323Sjkim *                                    evaluation of a method or object
217199323Sjkim *
218199323Sjkim * RETURN:      Status. AE_OK if repair was successful. If name is not
219199323Sjkim *              matched, ValidateStatus is returned.
220199323Sjkim *
221199323Sjkim * DESCRIPTION: Attempt to repair/convert a return object of a type that was
222199323Sjkim *              not expected.
223199323Sjkim *
224199323Sjkim *****************************************************************************/
225199323Sjkim
226199323SjkimACPI_STATUS
227199323SjkimAcpiNsComplexRepairs (
228199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
229199323Sjkim    ACPI_NAMESPACE_NODE     *Node,
230199323Sjkim    ACPI_STATUS             ValidateStatus,
231199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
232199323Sjkim{
233199323Sjkim    const ACPI_REPAIR_INFO  *Predefined;
234199323Sjkim    ACPI_STATUS             Status;
235199323Sjkim
236199323Sjkim
237199323Sjkim    /* Check if this name is in the list of repairable names */
238199323Sjkim
239199323Sjkim    Predefined = AcpiNsMatchRepairableName (Node);
240199323Sjkim    if (!Predefined)
241199323Sjkim    {
242199323Sjkim        return (ValidateStatus);
243199323Sjkim    }
244199323Sjkim
245199323Sjkim    Status = Predefined->RepairFunction (Data, ReturnObjectPtr);
246199323Sjkim    return (Status);
247199323Sjkim}
248199323Sjkim
249199323Sjkim
250199323Sjkim/******************************************************************************
251199323Sjkim *
252199323Sjkim * FUNCTION:    AcpiNsMatchRepairableName
253199323Sjkim *
254199323Sjkim * PARAMETERS:  Node                - Namespace node for the method/object
255199323Sjkim *
256199323Sjkim * RETURN:      Pointer to entry in repair table. NULL indicates not found.
257199323Sjkim *
258199323Sjkim * DESCRIPTION: Check an object name against the repairable object list.
259199323Sjkim *
260199323Sjkim *****************************************************************************/
261199323Sjkim
262199323Sjkimstatic const ACPI_REPAIR_INFO *
263199323SjkimAcpiNsMatchRepairableName (
264199323Sjkim    ACPI_NAMESPACE_NODE     *Node)
265199323Sjkim{
266199323Sjkim    const ACPI_REPAIR_INFO  *ThisName;
267199323Sjkim
268199323Sjkim
269199323Sjkim    /* Search info table for a repairable predefined method/object name */
270199323Sjkim
271199323Sjkim    ThisName = AcpiNsRepairableNames;
272199323Sjkim    while (ThisName->RepairFunction)
273199323Sjkim    {
274199323Sjkim        if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name))
275199323Sjkim        {
276199323Sjkim            return (ThisName);
277199323Sjkim        }
278199323Sjkim        ThisName++;
279199323Sjkim    }
280199323Sjkim
281199323Sjkim    return (NULL); /* Not found */
282199323Sjkim}
283199323Sjkim
284199323Sjkim
285199323Sjkim/******************************************************************************
286199323Sjkim *
287199323Sjkim * FUNCTION:    AcpiNsRepair_ALR
288199323Sjkim *
289199323Sjkim * PARAMETERS:  Data                - Pointer to validation data structure
290199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
291199323Sjkim *                                    evaluation of a method or object
292199323Sjkim *
293199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
294199323Sjkim *
295199323Sjkim * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
296199323Sjkim *              ascending by the ambient illuminance values.
297199323Sjkim *
298199323Sjkim *****************************************************************************/
299199323Sjkim
300199323Sjkimstatic ACPI_STATUS
301199323SjkimAcpiNsRepair_ALR (
302199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
303199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
304199323Sjkim{
305199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
306199323Sjkim    ACPI_STATUS             Status;
307199323Sjkim
308199323Sjkim
309199323Sjkim    Status = AcpiNsCheckSortedList (Data, ReturnObject, 2, 1,
310199323Sjkim                ACPI_SORT_ASCENDING, "AmbientIlluminance");
311199323Sjkim
312199323Sjkim    return (Status);
313199323Sjkim}
314199323Sjkim
315199323Sjkim
316199323Sjkim/******************************************************************************
317199323Sjkim *
318199323Sjkim * FUNCTION:    AcpiNsRepair_TSS
319199323Sjkim *
320199323Sjkim * PARAMETERS:  Data                - Pointer to validation data structure
321199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
322199323Sjkim *                                    evaluation of a method or object
323199323Sjkim *
324199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
325199323Sjkim *
326199323Sjkim * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
327199323Sjkim *              descending by the power dissipation values.
328199323Sjkim *
329199323Sjkim *****************************************************************************/
330199323Sjkim
331199323Sjkimstatic ACPI_STATUS
332199323SjkimAcpiNsRepair_TSS (
333199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
334199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
335199323Sjkim{
336199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
337199323Sjkim    ACPI_STATUS             Status;
338199323Sjkim
339199323Sjkim
340199323Sjkim    Status = AcpiNsCheckSortedList (Data, ReturnObject, 5, 1,
341199323Sjkim                ACPI_SORT_DESCENDING, "PowerDissipation");
342199323Sjkim
343199323Sjkim    return (Status);
344199323Sjkim}
345199323Sjkim
346199323Sjkim
347199323Sjkim/******************************************************************************
348199323Sjkim *
349199323Sjkim * FUNCTION:    AcpiNsRepair_PSS
350199323Sjkim *
351199323Sjkim * PARAMETERS:  Data                - Pointer to validation data structure
352199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
353199323Sjkim *                                    evaluation of a method or object
354199323Sjkim *
355199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
356199323Sjkim *
357199323Sjkim * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
358199323Sjkim *              by the CPU frequencies. Check that the power dissipation values
359199323Sjkim *              are all proportional to CPU frequency (i.e., sorting by
360199323Sjkim *              frequency should be the same as sorting by power.)
361199323Sjkim *
362199323Sjkim *****************************************************************************/
363199323Sjkim
364199323Sjkimstatic ACPI_STATUS
365199323SjkimAcpiNsRepair_PSS (
366199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
367199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
368199323Sjkim{
369199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
370199323Sjkim    ACPI_OPERAND_OBJECT     **OuterElements;
371199323Sjkim    UINT32                  OuterElementCount;
372199323Sjkim    ACPI_OPERAND_OBJECT     **Elements;
373199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
374199323Sjkim    UINT32                  PreviousValue;
375199323Sjkim    ACPI_STATUS             Status;
376199323Sjkim    UINT32                  i;
377199323Sjkim
378199323Sjkim
379199323Sjkim    /*
380199323Sjkim     * Entries (sub-packages) in the _PSS Package must be sorted by power
381199323Sjkim     * dissipation, in descending order. If it appears that the list is
382199323Sjkim     * incorrectly sorted, sort it. We sort by CpuFrequency, since this
383199323Sjkim     * should be proportional to the power.
384199323Sjkim     */
385199323Sjkim    Status =AcpiNsCheckSortedList (Data, ReturnObject, 6, 0,
386199323Sjkim                ACPI_SORT_DESCENDING, "CpuFrequency");
387199323Sjkim    if (ACPI_FAILURE (Status))
388199323Sjkim    {
389199323Sjkim        return (Status);
390199323Sjkim    }
391199323Sjkim
392199323Sjkim    /*
393199323Sjkim     * We now know the list is correctly sorted by CPU frequency. Check if
394199323Sjkim     * the power dissipation values are proportional.
395199323Sjkim     */
396199323Sjkim    PreviousValue = ACPI_UINT32_MAX;
397199323Sjkim    OuterElements = ReturnObject->Package.Elements;
398199323Sjkim    OuterElementCount = ReturnObject->Package.Count;
399199323Sjkim
400199323Sjkim    for (i = 0; i < OuterElementCount; i++)
401199323Sjkim    {
402199323Sjkim        Elements = (*OuterElements)->Package.Elements;
403199323Sjkim        ObjDesc = Elements[1]; /* Index1 = PowerDissipation */
404199323Sjkim
405199323Sjkim        if ((UINT32) ObjDesc->Integer.Value > PreviousValue)
406199323Sjkim        {
407199323Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
408199323Sjkim                "SubPackage[%u,%u] - suspicious power dissipation values",
409199323Sjkim                i-1, i));
410199323Sjkim        }
411199323Sjkim
412199323Sjkim        PreviousValue = (UINT32) ObjDesc->Integer.Value;
413199323Sjkim        OuterElements++;
414199323Sjkim    }
415199323Sjkim
416199323Sjkim    return (AE_OK);
417199323Sjkim}
418199323Sjkim
419199323Sjkim
420199323Sjkim/******************************************************************************
421199323Sjkim *
422199323Sjkim * FUNCTION:    AcpiNsCheckSortedList
423199323Sjkim *
424199323Sjkim * PARAMETERS:  Data                - Pointer to validation data structure
425199323Sjkim *              ReturnObject        - Pointer to the top-level returned object
426199323Sjkim *              ExpectedCount       - Minimum length of each sub-package
427199323Sjkim *              SortIndex           - Sub-package entry to sort on
428199323Sjkim *              SortDirection       - Ascending or descending
429199323Sjkim *              SortKeyName         - Name of the SortIndex field
430199323Sjkim *
431199323Sjkim * RETURN:      Status. AE_OK if the list is valid and is sorted correctly or
432199323Sjkim *              has been repaired by sorting the list.
433199323Sjkim *
434199323Sjkim * DESCRIPTION: Check if the package list is valid and sorted correctly by the
435199323Sjkim *              SortIndex. If not, then sort the list.
436199323Sjkim *
437199323Sjkim *****************************************************************************/
438199323Sjkim
439199323Sjkimstatic ACPI_STATUS
440199323SjkimAcpiNsCheckSortedList (
441199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
442199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject,
443199323Sjkim    UINT32                  ExpectedCount,
444199323Sjkim    UINT32                  SortIndex,
445199323Sjkim    UINT8                   SortDirection,
446199323Sjkim    char                    *SortKeyName)
447199323Sjkim{
448199323Sjkim    UINT32                  OuterElementCount;
449199323Sjkim    ACPI_OPERAND_OBJECT     **OuterElements;
450199323Sjkim    ACPI_OPERAND_OBJECT     **Elements;
451199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
452199323Sjkim    UINT32                  i;
453199323Sjkim    UINT32                  PreviousValue;
454199323Sjkim    ACPI_STATUS             Status;
455199323Sjkim
456199323Sjkim
457199323Sjkim    /* The top-level object must be a package */
458199323Sjkim
459199323Sjkim    if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
460199323Sjkim    {
461199323Sjkim        return (AE_AML_OPERAND_TYPE);
462199323Sjkim    }
463199323Sjkim
464199323Sjkim    /*
465199323Sjkim     * Detect any NULL package elements and remove them from the
466199323Sjkim     * package.
467199323Sjkim     *
468199323Sjkim     * TBD: We may want to do this for all predefined names that
469199323Sjkim     * return a variable-length package of packages.
470199323Sjkim     */
471199323Sjkim    Status = AcpiNsRemoveNullElements (ReturnObject);
472199323Sjkim    if (Status == AE_NULL_ENTRY)
473199323Sjkim    {
474199323Sjkim        ACPI_INFO_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
475199323Sjkim            "NULL elements removed from package"));
476199323Sjkim
477199323Sjkim        /* Exit if package is now zero length */
478199323Sjkim
479199323Sjkim        if (!ReturnObject->Package.Count)
480199323Sjkim        {
481199323Sjkim            return (AE_NULL_ENTRY);
482199323Sjkim        }
483199323Sjkim    }
484199323Sjkim
485199323Sjkim    OuterElements = ReturnObject->Package.Elements;
486199323Sjkim    OuterElementCount = ReturnObject->Package.Count;
487199323Sjkim    if (!OuterElementCount)
488199323Sjkim    {
489199323Sjkim        return (AE_AML_PACKAGE_LIMIT);
490199323Sjkim    }
491199323Sjkim
492199323Sjkim    PreviousValue = 0;
493199323Sjkim    if (SortDirection == ACPI_SORT_DESCENDING)
494199323Sjkim    {
495199323Sjkim        PreviousValue = ACPI_UINT32_MAX;
496199323Sjkim    }
497199323Sjkim
498199323Sjkim    /* Examine each subpackage */
499199323Sjkim
500199323Sjkim    for (i = 0; i < OuterElementCount; i++)
501199323Sjkim    {
502199323Sjkim        /* Each element of the top-level package must also be a package */
503199323Sjkim
504199323Sjkim        if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE)
505199323Sjkim        {
506199323Sjkim            return (AE_AML_OPERAND_TYPE);
507199323Sjkim        }
508199323Sjkim
509199323Sjkim        /* Each sub-package must have the minimum length */
510199323Sjkim
511199323Sjkim        if ((*OuterElements)->Package.Count < ExpectedCount)
512199323Sjkim        {
513199323Sjkim            return (AE_AML_PACKAGE_LIMIT);
514199323Sjkim        }
515199323Sjkim
516199323Sjkim        Elements = (*OuterElements)->Package.Elements;
517199323Sjkim        ObjDesc = Elements[SortIndex];
518199323Sjkim
519199323Sjkim        if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
520199323Sjkim        {
521199323Sjkim            return (AE_AML_OPERAND_TYPE);
522199323Sjkim        }
523199323Sjkim
524199323Sjkim        /*
525199323Sjkim         * The list must be sorted in the specified order. If we detect a
526199323Sjkim         * discrepancy, issue a warning and sort the entire list
527199323Sjkim         */
528199323Sjkim        if (((SortDirection == ACPI_SORT_ASCENDING) &&
529199323Sjkim                (ObjDesc->Integer.Value < PreviousValue)) ||
530199323Sjkim            ((SortDirection == ACPI_SORT_DESCENDING) &&
531199323Sjkim                (ObjDesc->Integer.Value > PreviousValue)))
532199323Sjkim        {
533199323Sjkim            Status = AcpiNsSortList (ReturnObject->Package.Elements,
534199323Sjkim                        OuterElementCount, SortIndex, SortDirection);
535199323Sjkim            if (ACPI_FAILURE (Status))
536199323Sjkim            {
537199323Sjkim                return (Status);
538199323Sjkim            }
539199323Sjkim
540199323Sjkim            Data->Flags |= ACPI_OBJECT_REPAIRED;
541199323Sjkim
542199323Sjkim            ACPI_INFO_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
543199323Sjkim                "Repaired unsorted list - now sorted by %s", SortKeyName));
544199323Sjkim            return (AE_OK);
545199323Sjkim        }
546199323Sjkim
547199323Sjkim        PreviousValue = (UINT32) ObjDesc->Integer.Value;
548199323Sjkim        OuterElements++;
549199323Sjkim    }
550199323Sjkim
551199323Sjkim    return (AE_OK);
552199323Sjkim}
553199323Sjkim
554199323Sjkim
555199323Sjkim/******************************************************************************
556199323Sjkim *
557199323Sjkim * FUNCTION:    AcpiNsRemoveNullElements
558199323Sjkim *
559199323Sjkim * PARAMETERS:  ObjDesc             - A Package object
560199323Sjkim *
561199323Sjkim * RETURN:      Status. AE_NULL_ENTRY means that one or more elements were
562199323Sjkim *              removed.
563199323Sjkim *
564199323Sjkim * DESCRIPTION: Remove all NULL package elements and update the package count.
565199323Sjkim *
566199323Sjkim *****************************************************************************/
567199323Sjkim
568199323Sjkimstatic ACPI_STATUS
569199323SjkimAcpiNsRemoveNullElements (
570199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc)
571199323Sjkim{
572199323Sjkim    ACPI_OPERAND_OBJECT     **Source;
573199323Sjkim    ACPI_OPERAND_OBJECT     **Dest;
574199323Sjkim    ACPI_STATUS             Status = AE_OK;
575199323Sjkim    UINT32                  Count;
576199323Sjkim    UINT32                  NewCount;
577199323Sjkim    UINT32                  i;
578199323Sjkim
579199323Sjkim
580199323Sjkim    Count = ObjDesc->Package.Count;
581199323Sjkim    NewCount = Count;
582199323Sjkim
583199323Sjkim    Source = ObjDesc->Package.Elements;
584199323Sjkim    Dest = Source;
585199323Sjkim
586199323Sjkim    /* Examine all elements of the package object */
587199323Sjkim
588199323Sjkim    for (i = 0; i < Count; i++)
589199323Sjkim    {
590199323Sjkim        if (!*Source)
591199323Sjkim        {
592199323Sjkim            Status = AE_NULL_ENTRY;
593199323Sjkim            NewCount--;
594199323Sjkim        }
595199323Sjkim        else
596199323Sjkim        {
597199323Sjkim            *Dest = *Source;
598199323Sjkim            Dest++;
599199323Sjkim        }
600199323Sjkim        Source++;
601199323Sjkim    }
602199323Sjkim
603199323Sjkim    if (Status == AE_NULL_ENTRY)
604199323Sjkim    {
605199323Sjkim        /* NULL terminate list and update the package count */
606199323Sjkim
607199323Sjkim        *Dest = NULL;
608199323Sjkim        ObjDesc->Package.Count = NewCount;
609199323Sjkim    }
610199323Sjkim
611199323Sjkim    return (Status);
612199323Sjkim}
613199323Sjkim
614199323Sjkim
615199323Sjkim/******************************************************************************
616199323Sjkim *
617199323Sjkim * FUNCTION:    AcpiNsSortList
618199323Sjkim *
619199323Sjkim * PARAMETERS:  Elements            - Package object element list
620199323Sjkim *              Count               - Element count for above
621199323Sjkim *              Index               - Sort by which package element
622199323Sjkim *              SortDirection       - Ascending or Descending sort
623199323Sjkim *
624199323Sjkim * RETURN:      Status
625199323Sjkim *
626199323Sjkim * DESCRIPTION: Sort the objects that are in a package element list.
627199323Sjkim *
628199323Sjkim * NOTE: Assumes that all NULL elements have been removed from the package.
629199323Sjkim *
630199323Sjkim *****************************************************************************/
631199323Sjkim
632199323Sjkimstatic ACPI_STATUS
633199323SjkimAcpiNsSortList (
634199323Sjkim    ACPI_OPERAND_OBJECT     **Elements,
635199323Sjkim    UINT32                  Count,
636199323Sjkim    UINT32                  Index,
637199323Sjkim    UINT8                   SortDirection)
638199323Sjkim{
639199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc1;
640199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc2;
641199323Sjkim    ACPI_OPERAND_OBJECT     *TempObj;
642199323Sjkim    UINT32                  i;
643199323Sjkim    UINT32                  j;
644199323Sjkim
645199323Sjkim
646199323Sjkim    /* Simple bubble sort */
647199323Sjkim
648199323Sjkim    for (i = 1; i < Count; i++)
649199323Sjkim    {
650199323Sjkim        for (j = (Count - 1); j >= i; j--)
651199323Sjkim        {
652199323Sjkim            ObjDesc1 = Elements[j-1]->Package.Elements[Index];
653199323Sjkim            ObjDesc2 = Elements[j]->Package.Elements[Index];
654199323Sjkim
655199323Sjkim            if (((SortDirection == ACPI_SORT_ASCENDING) &&
656199323Sjkim                    (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) ||
657199323Sjkim
658199323Sjkim                ((SortDirection == ACPI_SORT_DESCENDING) &&
659199323Sjkim                    (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value)))
660199323Sjkim            {
661199323Sjkim                TempObj = Elements[j-1];
662199323Sjkim                Elements[j-1] = Elements[j];
663199323Sjkim                Elements[j] = TempObj;
664199323Sjkim            }
665199323Sjkim        }
666199323Sjkim    }
667199323Sjkim
668199323Sjkim    return (AE_OK);
669199323Sjkim}
670