1199323Sjkim/******************************************************************************
2199323Sjkim *
3199323Sjkim * Module Name: nsrepair2 - Repair for objects returned by specific
4199323Sjkim *                          predefined methods
5199323Sjkim *
6199323Sjkim *****************************************************************************/
7199323Sjkim
8217365Sjkim/*
9245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
10199323Sjkim * All rights reserved.
11199323Sjkim *
12217365Sjkim * Redistribution and use in source and binary forms, with or without
13217365Sjkim * modification, are permitted provided that the following conditions
14217365Sjkim * are met:
15217365Sjkim * 1. Redistributions of source code must retain the above copyright
16217365Sjkim *    notice, this list of conditions, and the following disclaimer,
17217365Sjkim *    without modification.
18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
20217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
21217365Sjkim *    including a substantially similar Disclaimer requirement for further
22217365Sjkim *    binary redistribution.
23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
24217365Sjkim *    of any contributors may be used to endorse or promote products derived
25217365Sjkim *    from this software without specific prior written permission.
26199323Sjkim *
27217365Sjkim * Alternatively, this software may be distributed under the terms of the
28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
29217365Sjkim * Software Foundation.
30199323Sjkim *
31217365Sjkim * NO WARRANTY
32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
43217365Sjkim */
44199323Sjkim
45199323Sjkim#define __NSREPAIR2_C__
46199323Sjkim
47199337Sjkim#include <contrib/dev/acpica/include/acpi.h>
48199337Sjkim#include <contrib/dev/acpica/include/accommon.h>
49199337Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
50199323Sjkim
51199323Sjkim#define _COMPONENT          ACPI_NAMESPACE
52199323Sjkim        ACPI_MODULE_NAME    ("nsrepair2")
53199323Sjkim
54199323Sjkim
55199323Sjkim/*
56199323Sjkim * Information structure and handler for ACPI predefined names that can
57199323Sjkim * be repaired on a per-name basis.
58199323Sjkim */
59199323Sjkimtypedef
60199323SjkimACPI_STATUS (*ACPI_REPAIR_FUNCTION) (
61249663Sjkim    ACPI_EVALUATE_INFO      *Info,
62199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
63199323Sjkim
64199323Sjkimtypedef struct acpi_repair_info
65199323Sjkim{
66199323Sjkim    char                    Name[ACPI_NAME_SIZE];
67199323Sjkim    ACPI_REPAIR_FUNCTION    RepairFunction;
68199323Sjkim
69199323Sjkim} ACPI_REPAIR_INFO;
70199323Sjkim
71199323Sjkim
72199323Sjkim/* Local prototypes */
73199323Sjkim
74199323Sjkimstatic const ACPI_REPAIR_INFO *
75246849SjkimAcpiNsMatchComplexRepair (
76199323Sjkim    ACPI_NAMESPACE_NODE     *Node);
77199323Sjkim
78199323Sjkimstatic ACPI_STATUS
79199323SjkimAcpiNsRepair_ALR (
80249663Sjkim    ACPI_EVALUATE_INFO      *Info,
81199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
82199323Sjkim
83199323Sjkimstatic ACPI_STATUS
84212761SjkimAcpiNsRepair_CID (
85249663Sjkim    ACPI_EVALUATE_INFO      *Info,
86212761Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
87212761Sjkim
88212761Sjkimstatic ACPI_STATUS
89250838SjkimAcpiNsRepair_CST (
90250838Sjkim    ACPI_EVALUATE_INFO      *Info,
91250838Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
92250838Sjkim
93250838Sjkimstatic ACPI_STATUS
94200553SjkimAcpiNsRepair_FDE (
95249663Sjkim    ACPI_EVALUATE_INFO      *Info,
96200553Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
97200553Sjkim
98200553Sjkimstatic ACPI_STATUS
99212761SjkimAcpiNsRepair_HID (
100249663Sjkim    ACPI_EVALUATE_INFO      *Info,
101212761Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
102212761Sjkim
103212761Sjkimstatic ACPI_STATUS
104250838SjkimAcpiNsRepair_PRT (
105250838Sjkim    ACPI_EVALUATE_INFO      *Info,
106250838Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
107250838Sjkim
108250838Sjkimstatic ACPI_STATUS
109199323SjkimAcpiNsRepair_PSS (
110249663Sjkim    ACPI_EVALUATE_INFO      *Info,
111199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
112199323Sjkim
113199323Sjkimstatic ACPI_STATUS
114199323SjkimAcpiNsRepair_TSS (
115249663Sjkim    ACPI_EVALUATE_INFO      *Info,
116199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
117199323Sjkim
118199323Sjkimstatic ACPI_STATUS
119199323SjkimAcpiNsCheckSortedList (
120249663Sjkim    ACPI_EVALUATE_INFO      *Info,
121199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject,
122250838Sjkim    UINT32                  StartIndex,
123199323Sjkim    UINT32                  ExpectedCount,
124199323Sjkim    UINT32                  SortIndex,
125199323Sjkim    UINT8                   SortDirection,
126199323Sjkim    char                    *SortKeyName);
127199323Sjkim
128250838Sjkim/* Values for SortDirection above */
129250838Sjkim
130250838Sjkim#define ACPI_SORT_ASCENDING     0
131250838Sjkim#define ACPI_SORT_DESCENDING    1
132250838Sjkim
133202771Sjkimstatic void
134250838SjkimAcpiNsRemoveElement (
135250838Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc,
136250838Sjkim    UINT32                  Index);
137250838Sjkim
138250838Sjkimstatic void
139199323SjkimAcpiNsSortList (
140199323Sjkim    ACPI_OPERAND_OBJECT     **Elements,
141199323Sjkim    UINT32                  Count,
142199323Sjkim    UINT32                  Index,
143199323Sjkim    UINT8                   SortDirection);
144199323Sjkim
145199323Sjkim
146199323Sjkim/*
147199323Sjkim * This table contains the names of the predefined methods for which we can
148199323Sjkim * perform more complex repairs.
149199323Sjkim *
150200553Sjkim * As necessary:
151200553Sjkim *
152200553Sjkim * _ALR: Sort the list ascending by AmbientIlluminance
153212761Sjkim * _CID: Strings: uppercase all, remove any leading asterisk
154250838Sjkim * _CST: Sort the list ascending by C state type
155200553Sjkim * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
156200553Sjkim * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
157212761Sjkim * _HID: Strings: uppercase all, remove any leading asterisk
158250838Sjkim * _PRT: Fix reversed SourceName and SourceIndex
159200553Sjkim * _PSS: Sort the list descending by Power
160200553Sjkim * _TSS: Sort the list descending by Power
161209746Sjkim *
162209746Sjkim * Names that must be packages, but cannot be sorted:
163209746Sjkim *
164209746Sjkim * _BCL: Values are tied to the Package index where they appear, and cannot
165209746Sjkim * be moved or sorted. These index values are used for _BQC and _BCM.
166209746Sjkim * However, we can fix the case where a buffer is returned, by converting
167209746Sjkim * it to a Package of integers.
168199323Sjkim */
169199323Sjkimstatic const ACPI_REPAIR_INFO       AcpiNsRepairableNames[] =
170199323Sjkim{
171199323Sjkim    {"_ALR", AcpiNsRepair_ALR},
172212761Sjkim    {"_CID", AcpiNsRepair_CID},
173250838Sjkim    {"_CST", AcpiNsRepair_CST},
174200553Sjkim    {"_FDE", AcpiNsRepair_FDE},
175200553Sjkim    {"_GTM", AcpiNsRepair_FDE},     /* _GTM has same repair as _FDE */
176212761Sjkim    {"_HID", AcpiNsRepair_HID},
177250838Sjkim    {"_PRT", AcpiNsRepair_PRT},
178199323Sjkim    {"_PSS", AcpiNsRepair_PSS},
179199323Sjkim    {"_TSS", AcpiNsRepair_TSS},
180200553Sjkim    {{0,0,0,0}, NULL}               /* Table terminator */
181199323Sjkim};
182199323Sjkim
183199323Sjkim
184200553Sjkim#define ACPI_FDE_FIELD_COUNT        5
185200553Sjkim#define ACPI_FDE_BYTE_BUFFER_SIZE   5
186200553Sjkim#define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * sizeof (UINT32))
187200553Sjkim
188200553Sjkim
189199323Sjkim/******************************************************************************
190199323Sjkim *
191199323Sjkim * FUNCTION:    AcpiNsComplexRepairs
192199323Sjkim *
193249663Sjkim * PARAMETERS:  Info                - Method execution information block
194199323Sjkim *              Node                - Namespace node for the method/object
195199323Sjkim *              ValidateStatus      - Original status of earlier validation
196199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
197199323Sjkim *                                    evaluation of a method or object
198199323Sjkim *
199200553Sjkim * RETURN:      Status. AE_OK if repair was successful. If name is not
200199323Sjkim *              matched, ValidateStatus is returned.
201199323Sjkim *
202199323Sjkim * DESCRIPTION: Attempt to repair/convert a return object of a type that was
203199323Sjkim *              not expected.
204199323Sjkim *
205199323Sjkim *****************************************************************************/
206199323Sjkim
207199323SjkimACPI_STATUS
208199323SjkimAcpiNsComplexRepairs (
209249663Sjkim    ACPI_EVALUATE_INFO      *Info,
210199323Sjkim    ACPI_NAMESPACE_NODE     *Node,
211199323Sjkim    ACPI_STATUS             ValidateStatus,
212199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
213199323Sjkim{
214199323Sjkim    const ACPI_REPAIR_INFO  *Predefined;
215199323Sjkim    ACPI_STATUS             Status;
216199323Sjkim
217199323Sjkim
218199323Sjkim    /* Check if this name is in the list of repairable names */
219199323Sjkim
220246849Sjkim    Predefined = AcpiNsMatchComplexRepair (Node);
221199323Sjkim    if (!Predefined)
222199323Sjkim    {
223199323Sjkim        return (ValidateStatus);
224199323Sjkim    }
225199323Sjkim
226249663Sjkim    Status = Predefined->RepairFunction (Info, ReturnObjectPtr);
227199323Sjkim    return (Status);
228199323Sjkim}
229199323Sjkim
230199323Sjkim
231199323Sjkim/******************************************************************************
232199323Sjkim *
233246849Sjkim * FUNCTION:    AcpiNsMatchComplexRepair
234199323Sjkim *
235199323Sjkim * PARAMETERS:  Node                - Namespace node for the method/object
236199323Sjkim *
237199323Sjkim * RETURN:      Pointer to entry in repair table. NULL indicates not found.
238199323Sjkim *
239199323Sjkim * DESCRIPTION: Check an object name against the repairable object list.
240199323Sjkim *
241199323Sjkim *****************************************************************************/
242199323Sjkim
243199323Sjkimstatic const ACPI_REPAIR_INFO *
244246849SjkimAcpiNsMatchComplexRepair (
245199323Sjkim    ACPI_NAMESPACE_NODE     *Node)
246199323Sjkim{
247199323Sjkim    const ACPI_REPAIR_INFO  *ThisName;
248199323Sjkim
249199323Sjkim
250199323Sjkim    /* Search info table for a repairable predefined method/object name */
251199323Sjkim
252199323Sjkim    ThisName = AcpiNsRepairableNames;
253199323Sjkim    while (ThisName->RepairFunction)
254199323Sjkim    {
255199323Sjkim        if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name))
256199323Sjkim        {
257199323Sjkim            return (ThisName);
258199323Sjkim        }
259199323Sjkim        ThisName++;
260199323Sjkim    }
261199323Sjkim
262199323Sjkim    return (NULL); /* Not found */
263199323Sjkim}
264199323Sjkim
265199323Sjkim
266199323Sjkim/******************************************************************************
267199323Sjkim *
268199323Sjkim * FUNCTION:    AcpiNsRepair_ALR
269199323Sjkim *
270249663Sjkim * PARAMETERS:  Info                - Method execution information block
271199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
272199323Sjkim *                                    evaluation of a method or object
273199323Sjkim *
274199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
275199323Sjkim *
276199323Sjkim * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
277199323Sjkim *              ascending by the ambient illuminance values.
278199323Sjkim *
279199323Sjkim *****************************************************************************/
280199323Sjkim
281199323Sjkimstatic ACPI_STATUS
282199323SjkimAcpiNsRepair_ALR (
283249663Sjkim    ACPI_EVALUATE_INFO      *Info,
284199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
285199323Sjkim{
286199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
287199323Sjkim    ACPI_STATUS             Status;
288199323Sjkim
289199323Sjkim
290250838Sjkim    Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 2, 1,
291199323Sjkim                ACPI_SORT_ASCENDING, "AmbientIlluminance");
292199323Sjkim
293199323Sjkim    return (Status);
294199323Sjkim}
295199323Sjkim
296199323Sjkim
297199323Sjkim/******************************************************************************
298199323Sjkim *
299200553Sjkim * FUNCTION:    AcpiNsRepair_FDE
300200553Sjkim *
301249663Sjkim * PARAMETERS:  Info                - Method execution information block
302200553Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
303200553Sjkim *                                    evaluation of a method or object
304200553Sjkim *
305200553Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
306200553Sjkim *
307200553Sjkim * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return
308200553Sjkim *              value is a Buffer of 5 DWORDs. This function repairs a common
309200553Sjkim *              problem where the return value is a Buffer of BYTEs, not
310200553Sjkim *              DWORDs.
311200553Sjkim *
312200553Sjkim *****************************************************************************/
313200553Sjkim
314200553Sjkimstatic ACPI_STATUS
315200553SjkimAcpiNsRepair_FDE (
316249663Sjkim    ACPI_EVALUATE_INFO      *Info,
317200553Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
318200553Sjkim{
319200553Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
320200553Sjkim    ACPI_OPERAND_OBJECT     *BufferObject;
321200553Sjkim    UINT8                   *ByteBuffer;
322200553Sjkim    UINT32                  *DwordBuffer;
323200553Sjkim    UINT32                  i;
324200553Sjkim
325200553Sjkim
326200553Sjkim    ACPI_FUNCTION_NAME (NsRepair_FDE);
327200553Sjkim
328200553Sjkim
329200553Sjkim    switch (ReturnObject->Common.Type)
330200553Sjkim    {
331200553Sjkim    case ACPI_TYPE_BUFFER:
332200553Sjkim
333200553Sjkim        /* This is the expected type. Length should be (at least) 5 DWORDs */
334200553Sjkim
335200553Sjkim        if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE)
336200553Sjkim        {
337200553Sjkim            return (AE_OK);
338200553Sjkim        }
339200553Sjkim
340200553Sjkim        /* We can only repair if we have exactly 5 BYTEs */
341200553Sjkim
342200553Sjkim        if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE)
343200553Sjkim        {
344249663Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
345200553Sjkim                "Incorrect return buffer length %u, expected %u",
346200553Sjkim                ReturnObject->Buffer.Length, ACPI_FDE_DWORD_BUFFER_SIZE));
347200553Sjkim
348200553Sjkim            return (AE_AML_OPERAND_TYPE);
349200553Sjkim        }
350200553Sjkim
351200553Sjkim        /* Create the new (larger) buffer object */
352200553Sjkim
353200553Sjkim        BufferObject = AcpiUtCreateBufferObject (ACPI_FDE_DWORD_BUFFER_SIZE);
354200553Sjkim        if (!BufferObject)
355200553Sjkim        {
356200553Sjkim            return (AE_NO_MEMORY);
357200553Sjkim        }
358200553Sjkim
359200553Sjkim        /* Expand each byte to a DWORD */
360200553Sjkim
361200553Sjkim        ByteBuffer = ReturnObject->Buffer.Pointer;
362200553Sjkim        DwordBuffer = ACPI_CAST_PTR (UINT32, BufferObject->Buffer.Pointer);
363200553Sjkim
364200553Sjkim        for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++)
365200553Sjkim        {
366200553Sjkim            *DwordBuffer = (UINT32) *ByteBuffer;
367200553Sjkim            DwordBuffer++;
368200553Sjkim            ByteBuffer++;
369200553Sjkim        }
370200553Sjkim
371200553Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
372200553Sjkim            "%s Expanded Byte Buffer to expected DWord Buffer\n",
373249663Sjkim            Info->FullPathname));
374200553Sjkim        break;
375200553Sjkim
376200553Sjkim    default:
377250838Sjkim
378200553Sjkim        return (AE_AML_OPERAND_TYPE);
379200553Sjkim    }
380200553Sjkim
381200553Sjkim    /* Delete the original return object, return the new buffer object */
382200553Sjkim
383200553Sjkim    AcpiUtRemoveReference (ReturnObject);
384200553Sjkim    *ReturnObjectPtr = BufferObject;
385200553Sjkim
386249663Sjkim    Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
387200553Sjkim    return (AE_OK);
388200553Sjkim}
389200553Sjkim
390200553Sjkim
391200553Sjkim/******************************************************************************
392200553Sjkim *
393212761Sjkim * FUNCTION:    AcpiNsRepair_CID
394212761Sjkim *
395249663Sjkim * PARAMETERS:  Info                - Method execution information block
396212761Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
397212761Sjkim *                                    evaluation of a method or object
398212761Sjkim *
399212761Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
400212761Sjkim *
401212761Sjkim * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
402212761Sjkim *              letters are uppercase and that there is no leading asterisk.
403212761Sjkim *              If a Package, ensure same for all string elements.
404212761Sjkim *
405212761Sjkim *****************************************************************************/
406212761Sjkim
407212761Sjkimstatic ACPI_STATUS
408212761SjkimAcpiNsRepair_CID (
409249663Sjkim    ACPI_EVALUATE_INFO      *Info,
410212761Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
411212761Sjkim{
412212761Sjkim    ACPI_STATUS             Status;
413212761Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
414212761Sjkim    ACPI_OPERAND_OBJECT     **ElementPtr;
415212761Sjkim    ACPI_OPERAND_OBJECT     *OriginalElement;
416212761Sjkim    UINT16                  OriginalRefCount;
417212761Sjkim    UINT32                  i;
418212761Sjkim
419212761Sjkim
420212761Sjkim    /* Check for _CID as a simple string */
421212761Sjkim
422212761Sjkim    if (ReturnObject->Common.Type == ACPI_TYPE_STRING)
423212761Sjkim    {
424249663Sjkim        Status = AcpiNsRepair_HID (Info, ReturnObjectPtr);
425212761Sjkim        return (Status);
426212761Sjkim    }
427212761Sjkim
428212761Sjkim    /* Exit if not a Package */
429212761Sjkim
430212761Sjkim    if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
431212761Sjkim    {
432212761Sjkim        return (AE_OK);
433212761Sjkim    }
434212761Sjkim
435212761Sjkim    /* Examine each element of the _CID package */
436212761Sjkim
437212761Sjkim    ElementPtr = ReturnObject->Package.Elements;
438212761Sjkim    for (i = 0; i < ReturnObject->Package.Count; i++)
439212761Sjkim    {
440212761Sjkim        OriginalElement = *ElementPtr;
441212761Sjkim        OriginalRefCount = OriginalElement->Common.ReferenceCount;
442212761Sjkim
443249663Sjkim        Status = AcpiNsRepair_HID (Info, ElementPtr);
444212761Sjkim        if (ACPI_FAILURE (Status))
445212761Sjkim        {
446212761Sjkim            return (Status);
447212761Sjkim        }
448212761Sjkim
449212761Sjkim        /* Take care with reference counts */
450212761Sjkim
451212761Sjkim        if (OriginalElement != *ElementPtr)
452212761Sjkim        {
453212761Sjkim            /* Element was replaced */
454212761Sjkim
455212761Sjkim            (*ElementPtr)->Common.ReferenceCount =
456212761Sjkim                OriginalRefCount;
457212761Sjkim
458212761Sjkim            AcpiUtRemoveReference (OriginalElement);
459212761Sjkim        }
460212761Sjkim
461212761Sjkim        ElementPtr++;
462212761Sjkim    }
463212761Sjkim
464212761Sjkim    return (AE_OK);
465212761Sjkim}
466212761Sjkim
467212761Sjkim
468212761Sjkim/******************************************************************************
469212761Sjkim *
470250838Sjkim * FUNCTION:    AcpiNsRepair_CST
471250838Sjkim *
472250838Sjkim * PARAMETERS:  Info                - Method execution information block
473250838Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
474250838Sjkim *                                    evaluation of a method or object
475250838Sjkim *
476250838Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
477250838Sjkim *
478250838Sjkim * DESCRIPTION: Repair for the _CST object:
479250838Sjkim *              1. Sort the list ascending by C state type
480250838Sjkim *              2. Ensure type cannot be zero
481250838Sjkim *              3. A sub-package count of zero means _CST is meaningless
482250838Sjkim *              4. Count must match the number of C state sub-packages
483250838Sjkim *
484250838Sjkim *****************************************************************************/
485250838Sjkim
486250838Sjkimstatic ACPI_STATUS
487250838SjkimAcpiNsRepair_CST (
488250838Sjkim    ACPI_EVALUATE_INFO      *Info,
489250838Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
490250838Sjkim{
491250838Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
492250838Sjkim    ACPI_OPERAND_OBJECT     **OuterElements;
493250838Sjkim    UINT32                  OuterElementCount;
494250838Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
495250838Sjkim    ACPI_STATUS             Status;
496250838Sjkim    BOOLEAN                 Removing;
497250838Sjkim    UINT32                  i;
498250838Sjkim
499250838Sjkim
500250838Sjkim    ACPI_FUNCTION_NAME (NsRepair_CST);
501250838Sjkim
502250838Sjkim
503250838Sjkim    /*
504252279Sjkim     * Check if the C-state type values are proportional.
505250838Sjkim     */
506250838Sjkim    OuterElementCount = ReturnObject->Package.Count - 1;
507250838Sjkim    i = 0;
508250838Sjkim    while (i < OuterElementCount)
509250838Sjkim    {
510250838Sjkim        OuterElements = &ReturnObject->Package.Elements[i + 1];
511250838Sjkim        Removing = FALSE;
512250838Sjkim
513250838Sjkim        if ((*OuterElements)->Package.Count == 0)
514250838Sjkim        {
515250838Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
516250838Sjkim                "SubPackage[%u] - removing entry due to zero count", i));
517250838Sjkim            Removing = TRUE;
518252279Sjkim            goto RemoveElement;
519250838Sjkim        }
520250838Sjkim
521250838Sjkim        ObjDesc = (*OuterElements)->Package.Elements[1]; /* Index1 = Type */
522250838Sjkim        if ((UINT32) ObjDesc->Integer.Value == 0)
523250838Sjkim        {
524250838Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
525250838Sjkim                "SubPackage[%u] - removing entry due to invalid Type(0)", i));
526250838Sjkim            Removing = TRUE;
527250838Sjkim        }
528250838Sjkim
529252279SjkimRemoveElement:
530250838Sjkim        if (Removing)
531250838Sjkim        {
532250838Sjkim            AcpiNsRemoveElement (ReturnObject, i + 1);
533250838Sjkim            OuterElementCount--;
534250838Sjkim        }
535250838Sjkim        else
536250838Sjkim        {
537250838Sjkim            i++;
538250838Sjkim        }
539250838Sjkim    }
540250838Sjkim
541250838Sjkim    /* Update top-level package count, Type "Integer" checked elsewhere */
542250838Sjkim
543250838Sjkim    ObjDesc = ReturnObject->Package.Elements[0];
544250838Sjkim    ObjDesc->Integer.Value = OuterElementCount;
545252279Sjkim
546252279Sjkim    /*
547252279Sjkim     * Entries (subpackages) in the _CST Package must be sorted by the
548252279Sjkim     * C-state type, in ascending order.
549252279Sjkim     */
550252279Sjkim    Status = AcpiNsCheckSortedList (Info, ReturnObject, 1, 4, 1,
551252279Sjkim                ACPI_SORT_ASCENDING, "C-State Type");
552252279Sjkim    if (ACPI_FAILURE (Status))
553252279Sjkim    {
554252279Sjkim        return (Status);
555252279Sjkim    }
556252279Sjkim
557250838Sjkim    return (AE_OK);
558250838Sjkim}
559250838Sjkim
560250838Sjkim
561250838Sjkim/******************************************************************************
562250838Sjkim *
563212761Sjkim * FUNCTION:    AcpiNsRepair_HID
564212761Sjkim *
565249663Sjkim * PARAMETERS:  Info                - Method execution information block
566212761Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
567212761Sjkim *                                    evaluation of a method or object
568212761Sjkim *
569212761Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
570212761Sjkim *
571212761Sjkim * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
572212761Sjkim *              letters are uppercase and that there is no leading asterisk.
573212761Sjkim *
574212761Sjkim *****************************************************************************/
575212761Sjkim
576212761Sjkimstatic ACPI_STATUS
577212761SjkimAcpiNsRepair_HID (
578249663Sjkim    ACPI_EVALUATE_INFO      *Info,
579212761Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
580212761Sjkim{
581212761Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
582212761Sjkim    ACPI_OPERAND_OBJECT     *NewString;
583212761Sjkim    char                    *Source;
584212761Sjkim    char                    *Dest;
585212761Sjkim
586212761Sjkim
587212761Sjkim    ACPI_FUNCTION_NAME (NsRepair_HID);
588212761Sjkim
589212761Sjkim
590212761Sjkim    /* We only care about string _HID objects (not integers) */
591212761Sjkim
592212761Sjkim    if (ReturnObject->Common.Type != ACPI_TYPE_STRING)
593212761Sjkim    {
594212761Sjkim        return (AE_OK);
595212761Sjkim    }
596212761Sjkim
597212761Sjkim    if (ReturnObject->String.Length == 0)
598212761Sjkim    {
599249663Sjkim        ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
600212761Sjkim            "Invalid zero-length _HID or _CID string"));
601212761Sjkim
602212761Sjkim        /* Return AE_OK anyway, let driver handle it */
603212761Sjkim
604249663Sjkim        Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
605212761Sjkim        return (AE_OK);
606212761Sjkim    }
607212761Sjkim
608212761Sjkim    /* It is simplest to always create a new string object */
609212761Sjkim
610212761Sjkim    NewString = AcpiUtCreateStringObject (ReturnObject->String.Length);
611212761Sjkim    if (!NewString)
612212761Sjkim    {
613212761Sjkim        return (AE_NO_MEMORY);
614212761Sjkim    }
615212761Sjkim
616212761Sjkim    /*
617212761Sjkim     * Remove a leading asterisk if present. For some unknown reason, there
618212761Sjkim     * are many machines in the field that contains IDs like this.
619212761Sjkim     *
620212761Sjkim     * Examples: "*PNP0C03", "*ACPI0003"
621212761Sjkim     */
622212761Sjkim    Source = ReturnObject->String.Pointer;
623212761Sjkim    if (*Source == '*')
624212761Sjkim    {
625212761Sjkim        Source++;
626212761Sjkim        NewString->String.Length--;
627212761Sjkim
628212761Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
629249663Sjkim            "%s: Removed invalid leading asterisk\n", Info->FullPathname));
630212761Sjkim    }
631212761Sjkim
632212761Sjkim    /*
633228110Sjkim     * Copy and uppercase the string. From the ACPI 5.0 specification:
634212761Sjkim     *
635212761Sjkim     * A valid PNP ID must be of the form "AAA####" where A is an uppercase
636212761Sjkim     * letter and # is a hex digit. A valid ACPI ID must be of the form
637228110Sjkim     * "NNNN####" where N is an uppercase letter or decimal digit, and
638228110Sjkim     * # is a hex digit.
639212761Sjkim     */
640212761Sjkim    for (Dest = NewString->String.Pointer; *Source; Dest++, Source++)
641212761Sjkim    {
642212761Sjkim        *Dest = (char) ACPI_TOUPPER (*Source);
643212761Sjkim    }
644212761Sjkim
645212761Sjkim    AcpiUtRemoveReference (ReturnObject);
646212761Sjkim    *ReturnObjectPtr = NewString;
647212761Sjkim    return (AE_OK);
648212761Sjkim}
649212761Sjkim
650212761Sjkim
651212761Sjkim/******************************************************************************
652212761Sjkim *
653250838Sjkim * FUNCTION:    AcpiNsRepair_PRT
654199323Sjkim *
655249663Sjkim * PARAMETERS:  Info                - Method execution information block
656199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
657199323Sjkim *                                    evaluation of a method or object
658199323Sjkim *
659199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
660199323Sjkim *
661250838Sjkim * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed
662250838Sjkim *              SourceName and SourceIndex field, a common BIOS bug.
663199323Sjkim *
664199323Sjkim *****************************************************************************/
665199323Sjkim
666199323Sjkimstatic ACPI_STATUS
667250838SjkimAcpiNsRepair_PRT (
668249663Sjkim    ACPI_EVALUATE_INFO      *Info,
669199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
670199323Sjkim{
671250838Sjkim    ACPI_OPERAND_OBJECT     *PackageObject = *ReturnObjectPtr;
672250838Sjkim    ACPI_OPERAND_OBJECT     **TopObjectList;
673250838Sjkim    ACPI_OPERAND_OBJECT     **SubObjectList;
674250838Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
675250838Sjkim    UINT32                  ElementCount;
676250838Sjkim    UINT32                  Index;
677199323Sjkim
678199323Sjkim
679250838Sjkim    /* Each element in the _PRT package is a subpackage */
680250838Sjkim
681250838Sjkim    TopObjectList = PackageObject->Package.Elements;
682250838Sjkim    ElementCount = PackageObject->Package.Count;
683250838Sjkim
684250838Sjkim    for (Index = 0; Index < ElementCount; Index++)
685228110Sjkim    {
686250838Sjkim        SubObjectList = (*TopObjectList)->Package.Elements;
687250838Sjkim
688250838Sjkim        /*
689250838Sjkim         * If the BIOS has erroneously reversed the _PRT SourceName (index 2)
690250838Sjkim         * and the SourceIndex (index 3), fix it. _PRT is important enough to
691250838Sjkim         * workaround this BIOS error. This also provides compatibility with
692250838Sjkim         * other ACPI implementations.
693250838Sjkim         */
694250838Sjkim        ObjDesc = SubObjectList[3];
695250838Sjkim        if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
696250838Sjkim        {
697250838Sjkim            SubObjectList[3] = SubObjectList[2];
698250838Sjkim            SubObjectList[2] = ObjDesc;
699250838Sjkim            Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
700250838Sjkim
701250838Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
702250838Sjkim                "PRT[%X]: Fixed reversed SourceName and SourceIndex",
703250838Sjkim                Index));
704250838Sjkim        }
705250838Sjkim
706250838Sjkim        /* Point to the next ACPI_OPERAND_OBJECT in the top level package */
707250838Sjkim
708250838Sjkim        TopObjectList++;
709228110Sjkim    }
710228110Sjkim
711250838Sjkim    return (AE_OK);
712199323Sjkim}
713199323Sjkim
714199323Sjkim
715199323Sjkim/******************************************************************************
716199323Sjkim *
717199323Sjkim * FUNCTION:    AcpiNsRepair_PSS
718199323Sjkim *
719249663Sjkim * PARAMETERS:  Info                - Method execution information block
720199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
721199323Sjkim *                                    evaluation of a method or object
722199323Sjkim *
723199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
724199323Sjkim *
725199323Sjkim * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
726199323Sjkim *              by the CPU frequencies. Check that the power dissipation values
727199323Sjkim *              are all proportional to CPU frequency (i.e., sorting by
728199323Sjkim *              frequency should be the same as sorting by power.)
729199323Sjkim *
730199323Sjkim *****************************************************************************/
731199323Sjkim
732199323Sjkimstatic ACPI_STATUS
733199323SjkimAcpiNsRepair_PSS (
734249663Sjkim    ACPI_EVALUATE_INFO      *Info,
735199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
736199323Sjkim{
737199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
738199323Sjkim    ACPI_OPERAND_OBJECT     **OuterElements;
739199323Sjkim    UINT32                  OuterElementCount;
740199323Sjkim    ACPI_OPERAND_OBJECT     **Elements;
741199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
742199323Sjkim    UINT32                  PreviousValue;
743199323Sjkim    ACPI_STATUS             Status;
744199323Sjkim    UINT32                  i;
745199323Sjkim
746199323Sjkim
747199323Sjkim    /*
748199323Sjkim     * Entries (sub-packages) in the _PSS Package must be sorted by power
749199323Sjkim     * dissipation, in descending order. If it appears that the list is
750199323Sjkim     * incorrectly sorted, sort it. We sort by CpuFrequency, since this
751199323Sjkim     * should be proportional to the power.
752199323Sjkim     */
753250838Sjkim    Status =AcpiNsCheckSortedList (Info, ReturnObject, 0, 6, 0,
754199323Sjkim                ACPI_SORT_DESCENDING, "CpuFrequency");
755199323Sjkim    if (ACPI_FAILURE (Status))
756199323Sjkim    {
757199323Sjkim        return (Status);
758199323Sjkim    }
759199323Sjkim
760199323Sjkim    /*
761199323Sjkim     * We now know the list is correctly sorted by CPU frequency. Check if
762199323Sjkim     * the power dissipation values are proportional.
763199323Sjkim     */
764199323Sjkim    PreviousValue = ACPI_UINT32_MAX;
765199323Sjkim    OuterElements = ReturnObject->Package.Elements;
766199323Sjkim    OuterElementCount = ReturnObject->Package.Count;
767199323Sjkim
768199323Sjkim    for (i = 0; i < OuterElementCount; i++)
769199323Sjkim    {
770199323Sjkim        Elements = (*OuterElements)->Package.Elements;
771199323Sjkim        ObjDesc = Elements[1]; /* Index1 = PowerDissipation */
772199323Sjkim
773199323Sjkim        if ((UINT32) ObjDesc->Integer.Value > PreviousValue)
774199323Sjkim        {
775249663Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
776199323Sjkim                "SubPackage[%u,%u] - suspicious power dissipation values",
777199323Sjkim                i-1, i));
778199323Sjkim        }
779199323Sjkim
780199323Sjkim        PreviousValue = (UINT32) ObjDesc->Integer.Value;
781199323Sjkim        OuterElements++;
782199323Sjkim    }
783199323Sjkim
784199323Sjkim    return (AE_OK);
785199323Sjkim}
786199323Sjkim
787199323Sjkim
788199323Sjkim/******************************************************************************
789199323Sjkim *
790250838Sjkim * FUNCTION:    AcpiNsRepair_TSS
791250838Sjkim *
792250838Sjkim * PARAMETERS:  Info                - Method execution information block
793250838Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
794250838Sjkim *                                    evaluation of a method or object
795250838Sjkim *
796250838Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
797250838Sjkim *
798250838Sjkim * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
799250838Sjkim *              descending by the power dissipation values.
800250838Sjkim *
801250838Sjkim *****************************************************************************/
802250838Sjkim
803250838Sjkimstatic ACPI_STATUS
804250838SjkimAcpiNsRepair_TSS (
805250838Sjkim    ACPI_EVALUATE_INFO      *Info,
806250838Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
807250838Sjkim{
808250838Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
809250838Sjkim    ACPI_STATUS             Status;
810250838Sjkim    ACPI_NAMESPACE_NODE     *Node;
811250838Sjkim
812250838Sjkim
813250838Sjkim    /*
814250838Sjkim     * We can only sort the _TSS return package if there is no _PSS in the
815250838Sjkim     * same scope. This is because if _PSS is present, the ACPI specification
816250838Sjkim     * dictates that the _TSS Power Dissipation field is to be ignored, and
817250838Sjkim     * therefore some BIOSs leave garbage values in the _TSS Power field(s).
818250838Sjkim     * In this case, it is best to just return the _TSS package as-is.
819250838Sjkim     * (May, 2011)
820250838Sjkim     */
821250838Sjkim    Status = AcpiNsGetNode (Info->Node, "^_PSS",
822250838Sjkim        ACPI_NS_NO_UPSEARCH, &Node);
823250838Sjkim    if (ACPI_SUCCESS (Status))
824250838Sjkim    {
825250838Sjkim        return (AE_OK);
826250838Sjkim    }
827250838Sjkim
828250838Sjkim    Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 5, 1,
829250838Sjkim                ACPI_SORT_DESCENDING, "PowerDissipation");
830250838Sjkim
831250838Sjkim    return (Status);
832250838Sjkim}
833250838Sjkim
834250838Sjkim
835250838Sjkim/******************************************************************************
836250838Sjkim *
837199323Sjkim * FUNCTION:    AcpiNsCheckSortedList
838199323Sjkim *
839249663Sjkim * PARAMETERS:  Info                - Method execution information block
840199323Sjkim *              ReturnObject        - Pointer to the top-level returned object
841250838Sjkim *              StartIndex          - Index of the first sub-package
842199323Sjkim *              ExpectedCount       - Minimum length of each sub-package
843199323Sjkim *              SortIndex           - Sub-package entry to sort on
844199323Sjkim *              SortDirection       - Ascending or descending
845199323Sjkim *              SortKeyName         - Name of the SortIndex field
846199323Sjkim *
847199323Sjkim * RETURN:      Status. AE_OK if the list is valid and is sorted correctly or
848199323Sjkim *              has been repaired by sorting the list.
849199323Sjkim *
850199323Sjkim * DESCRIPTION: Check if the package list is valid and sorted correctly by the
851199323Sjkim *              SortIndex. If not, then sort the list.
852199323Sjkim *
853199323Sjkim *****************************************************************************/
854199323Sjkim
855199323Sjkimstatic ACPI_STATUS
856199323SjkimAcpiNsCheckSortedList (
857249663Sjkim    ACPI_EVALUATE_INFO      *Info,
858199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject,
859250838Sjkim    UINT32                  StartIndex,
860199323Sjkim    UINT32                  ExpectedCount,
861199323Sjkim    UINT32                  SortIndex,
862199323Sjkim    UINT8                   SortDirection,
863199323Sjkim    char                    *SortKeyName)
864199323Sjkim{
865199323Sjkim    UINT32                  OuterElementCount;
866199323Sjkim    ACPI_OPERAND_OBJECT     **OuterElements;
867199323Sjkim    ACPI_OPERAND_OBJECT     **Elements;
868199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
869199323Sjkim    UINT32                  i;
870199323Sjkim    UINT32                  PreviousValue;
871199323Sjkim
872199323Sjkim
873200553Sjkim    ACPI_FUNCTION_NAME (NsCheckSortedList);
874200553Sjkim
875200553Sjkim
876199323Sjkim    /* The top-level object must be a package */
877199323Sjkim
878199323Sjkim    if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
879199323Sjkim    {
880199323Sjkim        return (AE_AML_OPERAND_TYPE);
881199323Sjkim    }
882199323Sjkim
883199323Sjkim    /*
884200553Sjkim     * NOTE: assumes list of sub-packages contains no NULL elements.
885200553Sjkim     * Any NULL elements should have been removed by earlier call
886200553Sjkim     * to AcpiNsRemoveNullElements.
887199323Sjkim     */
888199323Sjkim    OuterElementCount = ReturnObject->Package.Count;
889250838Sjkim    if (!OuterElementCount || StartIndex >= OuterElementCount)
890199323Sjkim    {
891199323Sjkim        return (AE_AML_PACKAGE_LIMIT);
892199323Sjkim    }
893199323Sjkim
894250838Sjkim    OuterElements = &ReturnObject->Package.Elements[StartIndex];
895250838Sjkim    OuterElementCount -= StartIndex;
896250838Sjkim
897199323Sjkim    PreviousValue = 0;
898199323Sjkim    if (SortDirection == ACPI_SORT_DESCENDING)
899199323Sjkim    {
900199323Sjkim        PreviousValue = ACPI_UINT32_MAX;
901199323Sjkim    }
902199323Sjkim
903199323Sjkim    /* Examine each subpackage */
904199323Sjkim
905199323Sjkim    for (i = 0; i < OuterElementCount; i++)
906199323Sjkim    {
907199323Sjkim        /* Each element of the top-level package must also be a package */
908199323Sjkim
909199323Sjkim        if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE)
910199323Sjkim        {
911199323Sjkim            return (AE_AML_OPERAND_TYPE);
912199323Sjkim        }
913199323Sjkim
914199323Sjkim        /* Each sub-package must have the minimum length */
915199323Sjkim
916199323Sjkim        if ((*OuterElements)->Package.Count < ExpectedCount)
917199323Sjkim        {
918199323Sjkim            return (AE_AML_PACKAGE_LIMIT);
919199323Sjkim        }
920199323Sjkim
921199323Sjkim        Elements = (*OuterElements)->Package.Elements;
922199323Sjkim        ObjDesc = Elements[SortIndex];
923199323Sjkim
924199323Sjkim        if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
925199323Sjkim        {
926199323Sjkim            return (AE_AML_OPERAND_TYPE);
927199323Sjkim        }
928199323Sjkim
929199323Sjkim        /*
930199323Sjkim         * The list must be sorted in the specified order. If we detect a
931202771Sjkim         * discrepancy, sort the entire list.
932199323Sjkim         */
933199323Sjkim        if (((SortDirection == ACPI_SORT_ASCENDING) &&
934199323Sjkim                (ObjDesc->Integer.Value < PreviousValue)) ||
935199323Sjkim            ((SortDirection == ACPI_SORT_DESCENDING) &&
936199323Sjkim                (ObjDesc->Integer.Value > PreviousValue)))
937199323Sjkim        {
938250838Sjkim            AcpiNsSortList (&ReturnObject->Package.Elements[StartIndex],
939202771Sjkim                OuterElementCount, SortIndex, SortDirection);
940199323Sjkim
941249663Sjkim            Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
942199323Sjkim
943200553Sjkim            ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
944200553Sjkim                "%s: Repaired unsorted list - now sorted by %s\n",
945249663Sjkim                Info->FullPathname, SortKeyName));
946199323Sjkim            return (AE_OK);
947199323Sjkim        }
948199323Sjkim
949199323Sjkim        PreviousValue = (UINT32) ObjDesc->Integer.Value;
950199323Sjkim        OuterElements++;
951199323Sjkim    }
952199323Sjkim
953199323Sjkim    return (AE_OK);
954199323Sjkim}
955199323Sjkim
956199323Sjkim
957199323Sjkim/******************************************************************************
958199323Sjkim *
959199323Sjkim * FUNCTION:    AcpiNsSortList
960199323Sjkim *
961199323Sjkim * PARAMETERS:  Elements            - Package object element list
962199323Sjkim *              Count               - Element count for above
963199323Sjkim *              Index               - Sort by which package element
964199323Sjkim *              SortDirection       - Ascending or Descending sort
965199323Sjkim *
966202771Sjkim * RETURN:      None
967199323Sjkim *
968199323Sjkim * DESCRIPTION: Sort the objects that are in a package element list.
969199323Sjkim *
970202771Sjkim * NOTE: Assumes that all NULL elements have been removed from the package,
971202771Sjkim *       and that all elements have been verified to be of type Integer.
972199323Sjkim *
973199323Sjkim *****************************************************************************/
974199323Sjkim
975202771Sjkimstatic void
976199323SjkimAcpiNsSortList (
977199323Sjkim    ACPI_OPERAND_OBJECT     **Elements,
978199323Sjkim    UINT32                  Count,
979199323Sjkim    UINT32                  Index,
980199323Sjkim    UINT8                   SortDirection)
981199323Sjkim{
982199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc1;
983199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc2;
984199323Sjkim    ACPI_OPERAND_OBJECT     *TempObj;
985199323Sjkim    UINT32                  i;
986199323Sjkim    UINT32                  j;
987199323Sjkim
988199323Sjkim
989199323Sjkim    /* Simple bubble sort */
990199323Sjkim
991199323Sjkim    for (i = 1; i < Count; i++)
992199323Sjkim    {
993199323Sjkim        for (j = (Count - 1); j >= i; j--)
994199323Sjkim        {
995199323Sjkim            ObjDesc1 = Elements[j-1]->Package.Elements[Index];
996199323Sjkim            ObjDesc2 = Elements[j]->Package.Elements[Index];
997199323Sjkim
998199323Sjkim            if (((SortDirection == ACPI_SORT_ASCENDING) &&
999199323Sjkim                    (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) ||
1000199323Sjkim
1001199323Sjkim                ((SortDirection == ACPI_SORT_DESCENDING) &&
1002199323Sjkim                    (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value)))
1003199323Sjkim            {
1004199323Sjkim                TempObj = Elements[j-1];
1005199323Sjkim                Elements[j-1] = Elements[j];
1006199323Sjkim                Elements[j] = TempObj;
1007199323Sjkim            }
1008199323Sjkim        }
1009199323Sjkim    }
1010199323Sjkim}
1011250838Sjkim
1012250838Sjkim
1013250838Sjkim/******************************************************************************
1014250838Sjkim *
1015250838Sjkim * FUNCTION:    AcpiNsRemoveElement
1016250838Sjkim *
1017250838Sjkim * PARAMETERS:  ObjDesc             - Package object element list
1018250838Sjkim *              Index               - Index of element to remove
1019250838Sjkim *
1020250838Sjkim * RETURN:      None
1021250838Sjkim *
1022250838Sjkim * DESCRIPTION: Remove the requested element of a package and delete it.
1023250838Sjkim *
1024250838Sjkim *****************************************************************************/
1025250838Sjkim
1026250838Sjkimstatic void
1027250838SjkimAcpiNsRemoveElement (
1028250838Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc,
1029250838Sjkim    UINT32                  Index)
1030250838Sjkim{
1031250838Sjkim    ACPI_OPERAND_OBJECT     **Source;
1032250838Sjkim    ACPI_OPERAND_OBJECT     **Dest;
1033250838Sjkim    UINT32                  Count;
1034250838Sjkim    UINT32                  NewCount;
1035250838Sjkim    UINT32                  i;
1036250838Sjkim
1037250838Sjkim
1038250838Sjkim    ACPI_FUNCTION_NAME (NsRemoveElement);
1039250838Sjkim
1040250838Sjkim
1041250838Sjkim    Count = ObjDesc->Package.Count;
1042250838Sjkim    NewCount = Count - 1;
1043250838Sjkim
1044250838Sjkim    Source = ObjDesc->Package.Elements;
1045250838Sjkim    Dest = Source;
1046250838Sjkim
1047250838Sjkim    /* Examine all elements of the package object, remove matched index */
1048250838Sjkim
1049250838Sjkim    for (i = 0; i < Count; i++)
1050250838Sjkim    {
1051250838Sjkim        if (i == Index)
1052250838Sjkim        {
1053250838Sjkim            AcpiUtRemoveReference (*Source); /* Remove one ref for being in pkg */
1054250838Sjkim            AcpiUtRemoveReference (*Source);
1055250838Sjkim        }
1056250838Sjkim        else
1057250838Sjkim        {
1058250838Sjkim            *Dest = *Source;
1059250838Sjkim            Dest++;
1060250838Sjkim        }
1061250838Sjkim        Source++;
1062250838Sjkim    }
1063250838Sjkim
1064250838Sjkim    /* NULL terminate list and update the package count */
1065250838Sjkim
1066250838Sjkim    *Dest = NULL;
1067250838Sjkim    ObjDesc->Package.Count = NewCount;
1068250838Sjkim}
1069