1199323Sjkim/******************************************************************************
2199323Sjkim *
3199323Sjkim * Module Name: nsrepair2 - Repair for objects returned by specific
4199323Sjkim *                          predefined methods
5199323Sjkim *
6199323Sjkim *****************************************************************************/
7199323Sjkim
8217365Sjkim/*
9306536Sjkim * Copyright (C) 2000 - 2016, 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
45199337Sjkim#include <contrib/dev/acpica/include/acpi.h>
46199337Sjkim#include <contrib/dev/acpica/include/accommon.h>
47199337Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
48199323Sjkim
49199323Sjkim#define _COMPONENT          ACPI_NAMESPACE
50199323Sjkim        ACPI_MODULE_NAME    ("nsrepair2")
51199323Sjkim
52199323Sjkim
53199323Sjkim/*
54199323Sjkim * Information structure and handler for ACPI predefined names that can
55199323Sjkim * be repaired on a per-name basis.
56199323Sjkim */
57199323Sjkimtypedef
58199323SjkimACPI_STATUS (*ACPI_REPAIR_FUNCTION) (
59249663Sjkim    ACPI_EVALUATE_INFO      *Info,
60199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
61199323Sjkim
62199323Sjkimtypedef struct acpi_repair_info
63199323Sjkim{
64199323Sjkim    char                    Name[ACPI_NAME_SIZE];
65199323Sjkim    ACPI_REPAIR_FUNCTION    RepairFunction;
66199323Sjkim
67199323Sjkim} ACPI_REPAIR_INFO;
68199323Sjkim
69199323Sjkim
70199323Sjkim/* Local prototypes */
71199323Sjkim
72199323Sjkimstatic const ACPI_REPAIR_INFO *
73246849SjkimAcpiNsMatchComplexRepair (
74199323Sjkim    ACPI_NAMESPACE_NODE     *Node);
75199323Sjkim
76199323Sjkimstatic ACPI_STATUS
77199323SjkimAcpiNsRepair_ALR (
78249663Sjkim    ACPI_EVALUATE_INFO      *Info,
79199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
80199323Sjkim
81199323Sjkimstatic ACPI_STATUS
82212761SjkimAcpiNsRepair_CID (
83249663Sjkim    ACPI_EVALUATE_INFO      *Info,
84212761Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
85212761Sjkim
86212761Sjkimstatic ACPI_STATUS
87250838SjkimAcpiNsRepair_CST (
88250838Sjkim    ACPI_EVALUATE_INFO      *Info,
89250838Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
90250838Sjkim
91250838Sjkimstatic ACPI_STATUS
92200553SjkimAcpiNsRepair_FDE (
93249663Sjkim    ACPI_EVALUATE_INFO      *Info,
94200553Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
95200553Sjkim
96200553Sjkimstatic ACPI_STATUS
97212761SjkimAcpiNsRepair_HID (
98249663Sjkim    ACPI_EVALUATE_INFO      *Info,
99212761Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
100212761Sjkim
101212761Sjkimstatic ACPI_STATUS
102250838SjkimAcpiNsRepair_PRT (
103250838Sjkim    ACPI_EVALUATE_INFO      *Info,
104250838Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
105250838Sjkim
106250838Sjkimstatic ACPI_STATUS
107199323SjkimAcpiNsRepair_PSS (
108249663Sjkim    ACPI_EVALUATE_INFO      *Info,
109199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
110199323Sjkim
111199323Sjkimstatic ACPI_STATUS
112199323SjkimAcpiNsRepair_TSS (
113249663Sjkim    ACPI_EVALUATE_INFO      *Info,
114199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
115199323Sjkim
116199323Sjkimstatic ACPI_STATUS
117199323SjkimAcpiNsCheckSortedList (
118249663Sjkim    ACPI_EVALUATE_INFO      *Info,
119199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject,
120250838Sjkim    UINT32                  StartIndex,
121199323Sjkim    UINT32                  ExpectedCount,
122199323Sjkim    UINT32                  SortIndex,
123199323Sjkim    UINT8                   SortDirection,
124199323Sjkim    char                    *SortKeyName);
125199323Sjkim
126250838Sjkim/* Values for SortDirection above */
127250838Sjkim
128250838Sjkim#define ACPI_SORT_ASCENDING     0
129250838Sjkim#define ACPI_SORT_DESCENDING    1
130250838Sjkim
131202771Sjkimstatic void
132250838SjkimAcpiNsRemoveElement (
133250838Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc,
134250838Sjkim    UINT32                  Index);
135250838Sjkim
136250838Sjkimstatic void
137199323SjkimAcpiNsSortList (
138199323Sjkim    ACPI_OPERAND_OBJECT     **Elements,
139199323Sjkim    UINT32                  Count,
140199323Sjkim    UINT32                  Index,
141199323Sjkim    UINT8                   SortDirection);
142199323Sjkim
143199323Sjkim
144199323Sjkim/*
145199323Sjkim * This table contains the names of the predefined methods for which we can
146199323Sjkim * perform more complex repairs.
147199323Sjkim *
148200553Sjkim * As necessary:
149200553Sjkim *
150200553Sjkim * _ALR: Sort the list ascending by AmbientIlluminance
151212761Sjkim * _CID: Strings: uppercase all, remove any leading asterisk
152250838Sjkim * _CST: Sort the list ascending by C state type
153200553Sjkim * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
154200553Sjkim * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
155212761Sjkim * _HID: Strings: uppercase all, remove any leading asterisk
156250838Sjkim * _PRT: Fix reversed SourceName and SourceIndex
157200553Sjkim * _PSS: Sort the list descending by Power
158200553Sjkim * _TSS: Sort the list descending by Power
159209746Sjkim *
160209746Sjkim * Names that must be packages, but cannot be sorted:
161209746Sjkim *
162209746Sjkim * _BCL: Values are tied to the Package index where they appear, and cannot
163209746Sjkim * be moved or sorted. These index values are used for _BQC and _BCM.
164209746Sjkim * However, we can fix the case where a buffer is returned, by converting
165209746Sjkim * it to a Package of integers.
166199323Sjkim */
167199323Sjkimstatic const ACPI_REPAIR_INFO       AcpiNsRepairableNames[] =
168199323Sjkim{
169199323Sjkim    {"_ALR", AcpiNsRepair_ALR},
170212761Sjkim    {"_CID", AcpiNsRepair_CID},
171250838Sjkim    {"_CST", AcpiNsRepair_CST},
172200553Sjkim    {"_FDE", AcpiNsRepair_FDE},
173200553Sjkim    {"_GTM", AcpiNsRepair_FDE},     /* _GTM has same repair as _FDE */
174212761Sjkim    {"_HID", AcpiNsRepair_HID},
175250838Sjkim    {"_PRT", AcpiNsRepair_PRT},
176199323Sjkim    {"_PSS", AcpiNsRepair_PSS},
177199323Sjkim    {"_TSS", AcpiNsRepair_TSS},
178200553Sjkim    {{0,0,0,0}, NULL}               /* Table terminator */
179199323Sjkim};
180199323Sjkim
181199323Sjkim
182200553Sjkim#define ACPI_FDE_FIELD_COUNT        5
183200553Sjkim#define ACPI_FDE_BYTE_BUFFER_SIZE   5
184200553Sjkim#define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * sizeof (UINT32))
185200553Sjkim
186200553Sjkim
187199323Sjkim/******************************************************************************
188199323Sjkim *
189199323Sjkim * FUNCTION:    AcpiNsComplexRepairs
190199323Sjkim *
191249663Sjkim * PARAMETERS:  Info                - Method execution information block
192199323Sjkim *              Node                - Namespace node for the method/object
193199323Sjkim *              ValidateStatus      - Original status of earlier validation
194199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
195199323Sjkim *                                    evaluation of a method or object
196199323Sjkim *
197200553Sjkim * RETURN:      Status. AE_OK if repair was successful. If name is not
198199323Sjkim *              matched, ValidateStatus is returned.
199199323Sjkim *
200199323Sjkim * DESCRIPTION: Attempt to repair/convert a return object of a type that was
201199323Sjkim *              not expected.
202199323Sjkim *
203199323Sjkim *****************************************************************************/
204199323Sjkim
205199323SjkimACPI_STATUS
206199323SjkimAcpiNsComplexRepairs (
207249663Sjkim    ACPI_EVALUATE_INFO      *Info,
208199323Sjkim    ACPI_NAMESPACE_NODE     *Node,
209199323Sjkim    ACPI_STATUS             ValidateStatus,
210199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
211199323Sjkim{
212199323Sjkim    const ACPI_REPAIR_INFO  *Predefined;
213199323Sjkim    ACPI_STATUS             Status;
214199323Sjkim
215199323Sjkim
216199323Sjkim    /* Check if this name is in the list of repairable names */
217199323Sjkim
218246849Sjkim    Predefined = AcpiNsMatchComplexRepair (Node);
219199323Sjkim    if (!Predefined)
220199323Sjkim    {
221199323Sjkim        return (ValidateStatus);
222199323Sjkim    }
223199323Sjkim
224249663Sjkim    Status = Predefined->RepairFunction (Info, ReturnObjectPtr);
225199323Sjkim    return (Status);
226199323Sjkim}
227199323Sjkim
228199323Sjkim
229199323Sjkim/******************************************************************************
230199323Sjkim *
231246849Sjkim * FUNCTION:    AcpiNsMatchComplexRepair
232199323Sjkim *
233199323Sjkim * PARAMETERS:  Node                - Namespace node for the method/object
234199323Sjkim *
235199323Sjkim * RETURN:      Pointer to entry in repair table. NULL indicates not found.
236199323Sjkim *
237199323Sjkim * DESCRIPTION: Check an object name against the repairable object list.
238199323Sjkim *
239199323Sjkim *****************************************************************************/
240199323Sjkim
241199323Sjkimstatic const ACPI_REPAIR_INFO *
242246849SjkimAcpiNsMatchComplexRepair (
243199323Sjkim    ACPI_NAMESPACE_NODE     *Node)
244199323Sjkim{
245199323Sjkim    const ACPI_REPAIR_INFO  *ThisName;
246199323Sjkim
247199323Sjkim
248199323Sjkim    /* Search info table for a repairable predefined method/object name */
249199323Sjkim
250199323Sjkim    ThisName = AcpiNsRepairableNames;
251199323Sjkim    while (ThisName->RepairFunction)
252199323Sjkim    {
253199323Sjkim        if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name))
254199323Sjkim        {
255199323Sjkim            return (ThisName);
256199323Sjkim        }
257306536Sjkim
258199323Sjkim        ThisName++;
259199323Sjkim    }
260199323Sjkim
261199323Sjkim    return (NULL); /* Not found */
262199323Sjkim}
263199323Sjkim
264199323Sjkim
265199323Sjkim/******************************************************************************
266199323Sjkim *
267199323Sjkim * FUNCTION:    AcpiNsRepair_ALR
268199323Sjkim *
269249663Sjkim * PARAMETERS:  Info                - Method execution information block
270199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
271199323Sjkim *                                    evaluation of a method or object
272199323Sjkim *
273199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
274199323Sjkim *
275199323Sjkim * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
276199323Sjkim *              ascending by the ambient illuminance values.
277199323Sjkim *
278199323Sjkim *****************************************************************************/
279199323Sjkim
280199323Sjkimstatic ACPI_STATUS
281199323SjkimAcpiNsRepair_ALR (
282249663Sjkim    ACPI_EVALUATE_INFO      *Info,
283199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
284199323Sjkim{
285199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
286199323Sjkim    ACPI_STATUS             Status;
287199323Sjkim
288199323Sjkim
289250838Sjkim    Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 2, 1,
290306536Sjkim        ACPI_SORT_ASCENDING, "AmbientIlluminance");
291199323Sjkim
292199323Sjkim    return (Status);
293199323Sjkim}
294199323Sjkim
295199323Sjkim
296199323Sjkim/******************************************************************************
297199323Sjkim *
298200553Sjkim * FUNCTION:    AcpiNsRepair_FDE
299200553Sjkim *
300249663Sjkim * PARAMETERS:  Info                - Method execution information block
301200553Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
302200553Sjkim *                                    evaluation of a method or object
303200553Sjkim *
304200553Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
305200553Sjkim *
306200553Sjkim * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return
307200553Sjkim *              value is a Buffer of 5 DWORDs. This function repairs a common
308200553Sjkim *              problem where the return value is a Buffer of BYTEs, not
309200553Sjkim *              DWORDs.
310200553Sjkim *
311200553Sjkim *****************************************************************************/
312200553Sjkim
313200553Sjkimstatic ACPI_STATUS
314200553SjkimAcpiNsRepair_FDE (
315249663Sjkim    ACPI_EVALUATE_INFO      *Info,
316200553Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
317200553Sjkim{
318200553Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
319200553Sjkim    ACPI_OPERAND_OBJECT     *BufferObject;
320200553Sjkim    UINT8                   *ByteBuffer;
321200553Sjkim    UINT32                  *DwordBuffer;
322200553Sjkim    UINT32                  i;
323200553Sjkim
324200553Sjkim
325200553Sjkim    ACPI_FUNCTION_NAME (NsRepair_FDE);
326200553Sjkim
327200553Sjkim
328200553Sjkim    switch (ReturnObject->Common.Type)
329200553Sjkim    {
330200553Sjkim    case ACPI_TYPE_BUFFER:
331200553Sjkim
332200553Sjkim        /* This is the expected type. Length should be (at least) 5 DWORDs */
333200553Sjkim
334200553Sjkim        if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE)
335200553Sjkim        {
336200553Sjkim            return (AE_OK);
337200553Sjkim        }
338200553Sjkim
339200553Sjkim        /* We can only repair if we have exactly 5 BYTEs */
340200553Sjkim
341200553Sjkim        if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE)
342200553Sjkim        {
343306536Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO,
344306536Sjkim                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
353306536Sjkim        BufferObject = AcpiUtCreateBufferObject (
354306536Sjkim            ACPI_FDE_DWORD_BUFFER_SIZE);
355200553Sjkim        if (!BufferObject)
356200553Sjkim        {
357200553Sjkim            return (AE_NO_MEMORY);
358200553Sjkim        }
359200553Sjkim
360200553Sjkim        /* Expand each byte to a DWORD */
361200553Sjkim
362200553Sjkim        ByteBuffer = ReturnObject->Buffer.Pointer;
363306536Sjkim        DwordBuffer = ACPI_CAST_PTR (UINT32,
364306536Sjkim            BufferObject->Buffer.Pointer);
365200553Sjkim
366200553Sjkim        for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++)
367200553Sjkim        {
368200553Sjkim            *DwordBuffer = (UINT32) *ByteBuffer;
369200553Sjkim            DwordBuffer++;
370200553Sjkim            ByteBuffer++;
371200553Sjkim        }
372200553Sjkim
373200553Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
374200553Sjkim            "%s Expanded Byte Buffer to expected DWord Buffer\n",
375249663Sjkim            Info->FullPathname));
376200553Sjkim        break;
377200553Sjkim
378200553Sjkim    default:
379250838Sjkim
380200553Sjkim        return (AE_AML_OPERAND_TYPE);
381200553Sjkim    }
382200553Sjkim
383200553Sjkim    /* Delete the original return object, return the new buffer object */
384200553Sjkim
385200553Sjkim    AcpiUtRemoveReference (ReturnObject);
386200553Sjkim    *ReturnObjectPtr = BufferObject;
387200553Sjkim
388249663Sjkim    Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
389200553Sjkim    return (AE_OK);
390200553Sjkim}
391200553Sjkim
392200553Sjkim
393200553Sjkim/******************************************************************************
394200553Sjkim *
395212761Sjkim * FUNCTION:    AcpiNsRepair_CID
396212761Sjkim *
397249663Sjkim * PARAMETERS:  Info                - Method execution information block
398212761Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
399212761Sjkim *                                    evaluation of a method or object
400212761Sjkim *
401212761Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
402212761Sjkim *
403212761Sjkim * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
404212761Sjkim *              letters are uppercase and that there is no leading asterisk.
405212761Sjkim *              If a Package, ensure same for all string elements.
406212761Sjkim *
407212761Sjkim *****************************************************************************/
408212761Sjkim
409212761Sjkimstatic ACPI_STATUS
410212761SjkimAcpiNsRepair_CID (
411249663Sjkim    ACPI_EVALUATE_INFO      *Info,
412212761Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
413212761Sjkim{
414212761Sjkim    ACPI_STATUS             Status;
415212761Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
416212761Sjkim    ACPI_OPERAND_OBJECT     **ElementPtr;
417212761Sjkim    ACPI_OPERAND_OBJECT     *OriginalElement;
418212761Sjkim    UINT16                  OriginalRefCount;
419212761Sjkim    UINT32                  i;
420212761Sjkim
421212761Sjkim
422212761Sjkim    /* Check for _CID as a simple string */
423212761Sjkim
424212761Sjkim    if (ReturnObject->Common.Type == ACPI_TYPE_STRING)
425212761Sjkim    {
426249663Sjkim        Status = AcpiNsRepair_HID (Info, ReturnObjectPtr);
427212761Sjkim        return (Status);
428212761Sjkim    }
429212761Sjkim
430212761Sjkim    /* Exit if not a Package */
431212761Sjkim
432212761Sjkim    if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
433212761Sjkim    {
434212761Sjkim        return (AE_OK);
435212761Sjkim    }
436212761Sjkim
437212761Sjkim    /* Examine each element of the _CID package */
438212761Sjkim
439212761Sjkim    ElementPtr = ReturnObject->Package.Elements;
440212761Sjkim    for (i = 0; i < ReturnObject->Package.Count; i++)
441212761Sjkim    {
442212761Sjkim        OriginalElement = *ElementPtr;
443212761Sjkim        OriginalRefCount = OriginalElement->Common.ReferenceCount;
444212761Sjkim
445249663Sjkim        Status = AcpiNsRepair_HID (Info, ElementPtr);
446212761Sjkim        if (ACPI_FAILURE (Status))
447212761Sjkim        {
448212761Sjkim            return (Status);
449212761Sjkim        }
450212761Sjkim
451212761Sjkim        /* Take care with reference counts */
452212761Sjkim
453212761Sjkim        if (OriginalElement != *ElementPtr)
454212761Sjkim        {
455212761Sjkim            /* Element was replaced */
456212761Sjkim
457212761Sjkim            (*ElementPtr)->Common.ReferenceCount =
458212761Sjkim                OriginalRefCount;
459212761Sjkim
460212761Sjkim            AcpiUtRemoveReference (OriginalElement);
461212761Sjkim        }
462212761Sjkim
463212761Sjkim        ElementPtr++;
464212761Sjkim    }
465212761Sjkim
466212761Sjkim    return (AE_OK);
467212761Sjkim}
468212761Sjkim
469212761Sjkim
470212761Sjkim/******************************************************************************
471212761Sjkim *
472250838Sjkim * FUNCTION:    AcpiNsRepair_CST
473250838Sjkim *
474250838Sjkim * PARAMETERS:  Info                - Method execution information block
475250838Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
476250838Sjkim *                                    evaluation of a method or object
477250838Sjkim *
478250838Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
479250838Sjkim *
480250838Sjkim * DESCRIPTION: Repair for the _CST object:
481250838Sjkim *              1. Sort the list ascending by C state type
482250838Sjkim *              2. Ensure type cannot be zero
483281075Sdim *              3. A subpackage count of zero means _CST is meaningless
484281075Sdim *              4. Count must match the number of C state subpackages
485250838Sjkim *
486250838Sjkim *****************************************************************************/
487250838Sjkim
488250838Sjkimstatic ACPI_STATUS
489250838SjkimAcpiNsRepair_CST (
490250838Sjkim    ACPI_EVALUATE_INFO      *Info,
491250838Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
492250838Sjkim{
493250838Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
494250838Sjkim    ACPI_OPERAND_OBJECT     **OuterElements;
495250838Sjkim    UINT32                  OuterElementCount;
496250838Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
497250838Sjkim    ACPI_STATUS             Status;
498250838Sjkim    BOOLEAN                 Removing;
499250838Sjkim    UINT32                  i;
500250838Sjkim
501250838Sjkim
502250838Sjkim    ACPI_FUNCTION_NAME (NsRepair_CST);
503250838Sjkim
504250838Sjkim
505250838Sjkim    /*
506252279Sjkim     * Check if the C-state type values are proportional.
507250838Sjkim     */
508250838Sjkim    OuterElementCount = ReturnObject->Package.Count - 1;
509250838Sjkim    i = 0;
510250838Sjkim    while (i < OuterElementCount)
511250838Sjkim    {
512250838Sjkim        OuterElements = &ReturnObject->Package.Elements[i + 1];
513250838Sjkim        Removing = FALSE;
514250838Sjkim
515250838Sjkim        if ((*OuterElements)->Package.Count == 0)
516250838Sjkim        {
517306536Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO,
518306536Sjkim                Info->FullPathname, Info->NodeFlags,
519250838Sjkim                "SubPackage[%u] - removing entry due to zero count", i));
520250838Sjkim            Removing = TRUE;
521252279Sjkim            goto RemoveElement;
522250838Sjkim        }
523250838Sjkim
524250838Sjkim        ObjDesc = (*OuterElements)->Package.Elements[1]; /* Index1 = Type */
525250838Sjkim        if ((UINT32) ObjDesc->Integer.Value == 0)
526250838Sjkim        {
527306536Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO,
528306536Sjkim                Info->FullPathname, Info->NodeFlags,
529250838Sjkim                "SubPackage[%u] - removing entry due to invalid Type(0)", i));
530250838Sjkim            Removing = TRUE;
531250838Sjkim        }
532250838Sjkim
533252279SjkimRemoveElement:
534250838Sjkim        if (Removing)
535250838Sjkim        {
536250838Sjkim            AcpiNsRemoveElement (ReturnObject, i + 1);
537250838Sjkim            OuterElementCount--;
538250838Sjkim        }
539250838Sjkim        else
540250838Sjkim        {
541250838Sjkim            i++;
542250838Sjkim        }
543250838Sjkim    }
544250838Sjkim
545250838Sjkim    /* Update top-level package count, Type "Integer" checked elsewhere */
546250838Sjkim
547250838Sjkim    ObjDesc = ReturnObject->Package.Elements[0];
548250838Sjkim    ObjDesc->Integer.Value = OuterElementCount;
549252279Sjkim
550252279Sjkim    /*
551252279Sjkim     * Entries (subpackages) in the _CST Package must be sorted by the
552252279Sjkim     * C-state type, in ascending order.
553252279Sjkim     */
554252279Sjkim    Status = AcpiNsCheckSortedList (Info, ReturnObject, 1, 4, 1,
555306536Sjkim        ACPI_SORT_ASCENDING, "C-State Type");
556252279Sjkim    if (ACPI_FAILURE (Status))
557252279Sjkim    {
558252279Sjkim        return (Status);
559252279Sjkim    }
560252279Sjkim
561250838Sjkim    return (AE_OK);
562250838Sjkim}
563250838Sjkim
564250838Sjkim
565250838Sjkim/******************************************************************************
566250838Sjkim *
567212761Sjkim * FUNCTION:    AcpiNsRepair_HID
568212761Sjkim *
569249663Sjkim * PARAMETERS:  Info                - Method execution information block
570212761Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
571212761Sjkim *                                    evaluation of a method or object
572212761Sjkim *
573212761Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
574212761Sjkim *
575212761Sjkim * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
576212761Sjkim *              letters are uppercase and that there is no leading asterisk.
577212761Sjkim *
578212761Sjkim *****************************************************************************/
579212761Sjkim
580212761Sjkimstatic ACPI_STATUS
581212761SjkimAcpiNsRepair_HID (
582249663Sjkim    ACPI_EVALUATE_INFO      *Info,
583212761Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
584212761Sjkim{
585212761Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
586212761Sjkim    ACPI_OPERAND_OBJECT     *NewString;
587212761Sjkim    char                    *Source;
588212761Sjkim    char                    *Dest;
589212761Sjkim
590212761Sjkim
591212761Sjkim    ACPI_FUNCTION_NAME (NsRepair_HID);
592212761Sjkim
593212761Sjkim
594212761Sjkim    /* We only care about string _HID objects (not integers) */
595212761Sjkim
596212761Sjkim    if (ReturnObject->Common.Type != ACPI_TYPE_STRING)
597212761Sjkim    {
598212761Sjkim        return (AE_OK);
599212761Sjkim    }
600212761Sjkim
601212761Sjkim    if (ReturnObject->String.Length == 0)
602212761Sjkim    {
603306536Sjkim        ACPI_WARN_PREDEFINED ((AE_INFO,
604306536Sjkim            Info->FullPathname, Info->NodeFlags,
605212761Sjkim            "Invalid zero-length _HID or _CID string"));
606212761Sjkim
607212761Sjkim        /* Return AE_OK anyway, let driver handle it */
608212761Sjkim
609249663Sjkim        Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
610212761Sjkim        return (AE_OK);
611212761Sjkim    }
612212761Sjkim
613212761Sjkim    /* It is simplest to always create a new string object */
614212761Sjkim
615212761Sjkim    NewString = AcpiUtCreateStringObject (ReturnObject->String.Length);
616212761Sjkim    if (!NewString)
617212761Sjkim    {
618212761Sjkim        return (AE_NO_MEMORY);
619212761Sjkim    }
620212761Sjkim
621212761Sjkim    /*
622212761Sjkim     * Remove a leading asterisk if present. For some unknown reason, there
623212761Sjkim     * are many machines in the field that contains IDs like this.
624212761Sjkim     *
625212761Sjkim     * Examples: "*PNP0C03", "*ACPI0003"
626212761Sjkim     */
627212761Sjkim    Source = ReturnObject->String.Pointer;
628212761Sjkim    if (*Source == '*')
629212761Sjkim    {
630212761Sjkim        Source++;
631212761Sjkim        NewString->String.Length--;
632212761Sjkim
633212761Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
634249663Sjkim            "%s: Removed invalid leading asterisk\n", Info->FullPathname));
635212761Sjkim    }
636212761Sjkim
637212761Sjkim    /*
638228110Sjkim     * Copy and uppercase the string. From the ACPI 5.0 specification:
639212761Sjkim     *
640212761Sjkim     * A valid PNP ID must be of the form "AAA####" where A is an uppercase
641212761Sjkim     * letter and # is a hex digit. A valid ACPI ID must be of the form
642228110Sjkim     * "NNNN####" where N is an uppercase letter or decimal digit, and
643228110Sjkim     * # is a hex digit.
644212761Sjkim     */
645212761Sjkim    for (Dest = NewString->String.Pointer; *Source; Dest++, Source++)
646212761Sjkim    {
647306536Sjkim        *Dest = (char) toupper ((int) *Source);
648212761Sjkim    }
649212761Sjkim
650212761Sjkim    AcpiUtRemoveReference (ReturnObject);
651212761Sjkim    *ReturnObjectPtr = NewString;
652212761Sjkim    return (AE_OK);
653212761Sjkim}
654212761Sjkim
655212761Sjkim
656212761Sjkim/******************************************************************************
657212761Sjkim *
658250838Sjkim * FUNCTION:    AcpiNsRepair_PRT
659199323Sjkim *
660249663Sjkim * PARAMETERS:  Info                - Method execution information block
661199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
662199323Sjkim *                                    evaluation of a method or object
663199323Sjkim *
664199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
665199323Sjkim *
666250838Sjkim * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed
667250838Sjkim *              SourceName and SourceIndex field, a common BIOS bug.
668199323Sjkim *
669199323Sjkim *****************************************************************************/
670199323Sjkim
671199323Sjkimstatic ACPI_STATUS
672250838SjkimAcpiNsRepair_PRT (
673249663Sjkim    ACPI_EVALUATE_INFO      *Info,
674199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
675199323Sjkim{
676250838Sjkim    ACPI_OPERAND_OBJECT     *PackageObject = *ReturnObjectPtr;
677250838Sjkim    ACPI_OPERAND_OBJECT     **TopObjectList;
678250838Sjkim    ACPI_OPERAND_OBJECT     **SubObjectList;
679250838Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
680281075Sdim    ACPI_OPERAND_OBJECT     *SubPackage;
681250838Sjkim    UINT32                  ElementCount;
682250838Sjkim    UINT32                  Index;
683199323Sjkim
684199323Sjkim
685250838Sjkim    /* Each element in the _PRT package is a subpackage */
686250838Sjkim
687250838Sjkim    TopObjectList = PackageObject->Package.Elements;
688250838Sjkim    ElementCount = PackageObject->Package.Count;
689250838Sjkim
690281075Sdim    /* Examine each subpackage */
691281075Sdim
692281075Sdim    for (Index = 0; Index < ElementCount; Index++, TopObjectList++)
693228110Sjkim    {
694281075Sdim        SubPackage = *TopObjectList;
695281075Sdim        SubObjectList = SubPackage->Package.Elements;
696250838Sjkim
697281075Sdim        /* Check for minimum required element count */
698281075Sdim
699281075Sdim        if (SubPackage->Package.Count < 4)
700281075Sdim        {
701281075Sdim            continue;
702281075Sdim        }
703281075Sdim
704250838Sjkim        /*
705250838Sjkim         * If the BIOS has erroneously reversed the _PRT SourceName (index 2)
706250838Sjkim         * and the SourceIndex (index 3), fix it. _PRT is important enough to
707250838Sjkim         * workaround this BIOS error. This also provides compatibility with
708250838Sjkim         * other ACPI implementations.
709250838Sjkim         */
710250838Sjkim        ObjDesc = SubObjectList[3];
711250838Sjkim        if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
712250838Sjkim        {
713250838Sjkim            SubObjectList[3] = SubObjectList[2];
714250838Sjkim            SubObjectList[2] = ObjDesc;
715250838Sjkim            Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
716250838Sjkim
717281075Sdim            ACPI_WARN_PREDEFINED ((AE_INFO,
718281075Sdim                Info->FullPathname, Info->NodeFlags,
719250838Sjkim                "PRT[%X]: Fixed reversed SourceName and SourceIndex",
720250838Sjkim                Index));
721250838Sjkim        }
722228110Sjkim    }
723228110Sjkim
724250838Sjkim    return (AE_OK);
725199323Sjkim}
726199323Sjkim
727199323Sjkim
728199323Sjkim/******************************************************************************
729199323Sjkim *
730199323Sjkim * FUNCTION:    AcpiNsRepair_PSS
731199323Sjkim *
732249663Sjkim * PARAMETERS:  Info                - Method execution information block
733199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
734199323Sjkim *                                    evaluation of a method or object
735199323Sjkim *
736199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
737199323Sjkim *
738199323Sjkim * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
739199323Sjkim *              by the CPU frequencies. Check that the power dissipation values
740199323Sjkim *              are all proportional to CPU frequency (i.e., sorting by
741199323Sjkim *              frequency should be the same as sorting by power.)
742199323Sjkim *
743199323Sjkim *****************************************************************************/
744199323Sjkim
745199323Sjkimstatic ACPI_STATUS
746199323SjkimAcpiNsRepair_PSS (
747249663Sjkim    ACPI_EVALUATE_INFO      *Info,
748199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
749199323Sjkim{
750199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
751199323Sjkim    ACPI_OPERAND_OBJECT     **OuterElements;
752199323Sjkim    UINT32                  OuterElementCount;
753199323Sjkim    ACPI_OPERAND_OBJECT     **Elements;
754199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
755199323Sjkim    UINT32                  PreviousValue;
756199323Sjkim    ACPI_STATUS             Status;
757199323Sjkim    UINT32                  i;
758199323Sjkim
759199323Sjkim
760199323Sjkim    /*
761281075Sdim     * Entries (subpackages) in the _PSS Package must be sorted by power
762199323Sjkim     * dissipation, in descending order. If it appears that the list is
763199323Sjkim     * incorrectly sorted, sort it. We sort by CpuFrequency, since this
764199323Sjkim     * should be proportional to the power.
765199323Sjkim     */
766306536Sjkim    Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 6, 0,
767306536Sjkim        ACPI_SORT_DESCENDING, "CpuFrequency");
768199323Sjkim    if (ACPI_FAILURE (Status))
769199323Sjkim    {
770199323Sjkim        return (Status);
771199323Sjkim    }
772199323Sjkim
773199323Sjkim    /*
774199323Sjkim     * We now know the list is correctly sorted by CPU frequency. Check if
775199323Sjkim     * the power dissipation values are proportional.
776199323Sjkim     */
777199323Sjkim    PreviousValue = ACPI_UINT32_MAX;
778199323Sjkim    OuterElements = ReturnObject->Package.Elements;
779199323Sjkim    OuterElementCount = ReturnObject->Package.Count;
780199323Sjkim
781199323Sjkim    for (i = 0; i < OuterElementCount; i++)
782199323Sjkim    {
783199323Sjkim        Elements = (*OuterElements)->Package.Elements;
784199323Sjkim        ObjDesc = Elements[1]; /* Index1 = PowerDissipation */
785199323Sjkim
786199323Sjkim        if ((UINT32) ObjDesc->Integer.Value > PreviousValue)
787199323Sjkim        {
788306536Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO,
789306536Sjkim                Info->FullPathname, Info->NodeFlags,
790199323Sjkim                "SubPackage[%u,%u] - suspicious power dissipation values",
791199323Sjkim                i-1, i));
792199323Sjkim        }
793199323Sjkim
794199323Sjkim        PreviousValue = (UINT32) ObjDesc->Integer.Value;
795199323Sjkim        OuterElements++;
796199323Sjkim    }
797199323Sjkim
798199323Sjkim    return (AE_OK);
799199323Sjkim}
800199323Sjkim
801199323Sjkim
802199323Sjkim/******************************************************************************
803199323Sjkim *
804250838Sjkim * FUNCTION:    AcpiNsRepair_TSS
805250838Sjkim *
806250838Sjkim * PARAMETERS:  Info                - Method execution information block
807250838Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
808250838Sjkim *                                    evaluation of a method or object
809250838Sjkim *
810250838Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
811250838Sjkim *
812250838Sjkim * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
813250838Sjkim *              descending by the power dissipation values.
814250838Sjkim *
815250838Sjkim *****************************************************************************/
816250838Sjkim
817250838Sjkimstatic ACPI_STATUS
818250838SjkimAcpiNsRepair_TSS (
819250838Sjkim    ACPI_EVALUATE_INFO      *Info,
820250838Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
821250838Sjkim{
822250838Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
823250838Sjkim    ACPI_STATUS             Status;
824250838Sjkim    ACPI_NAMESPACE_NODE     *Node;
825250838Sjkim
826250838Sjkim
827250838Sjkim    /*
828250838Sjkim     * We can only sort the _TSS return package if there is no _PSS in the
829250838Sjkim     * same scope. This is because if _PSS is present, the ACPI specification
830250838Sjkim     * dictates that the _TSS Power Dissipation field is to be ignored, and
831250838Sjkim     * therefore some BIOSs leave garbage values in the _TSS Power field(s).
832250838Sjkim     * In this case, it is best to just return the _TSS package as-is.
833250838Sjkim     * (May, 2011)
834250838Sjkim     */
835250838Sjkim    Status = AcpiNsGetNode (Info->Node, "^_PSS",
836250838Sjkim        ACPI_NS_NO_UPSEARCH, &Node);
837250838Sjkim    if (ACPI_SUCCESS (Status))
838250838Sjkim    {
839250838Sjkim        return (AE_OK);
840250838Sjkim    }
841250838Sjkim
842250838Sjkim    Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 5, 1,
843306536Sjkim        ACPI_SORT_DESCENDING, "PowerDissipation");
844250838Sjkim
845250838Sjkim    return (Status);
846250838Sjkim}
847250838Sjkim
848250838Sjkim
849250838Sjkim/******************************************************************************
850250838Sjkim *
851199323Sjkim * FUNCTION:    AcpiNsCheckSortedList
852199323Sjkim *
853249663Sjkim * PARAMETERS:  Info                - Method execution information block
854199323Sjkim *              ReturnObject        - Pointer to the top-level returned object
855281075Sdim *              StartIndex          - Index of the first subpackage
856281075Sdim *              ExpectedCount       - Minimum length of each subpackage
857281075Sdim *              SortIndex           - Subpackage entry to sort on
858199323Sjkim *              SortDirection       - Ascending or descending
859199323Sjkim *              SortKeyName         - Name of the SortIndex field
860199323Sjkim *
861199323Sjkim * RETURN:      Status. AE_OK if the list is valid and is sorted correctly or
862199323Sjkim *              has been repaired by sorting the list.
863199323Sjkim *
864199323Sjkim * DESCRIPTION: Check if the package list is valid and sorted correctly by the
865199323Sjkim *              SortIndex. If not, then sort the list.
866199323Sjkim *
867199323Sjkim *****************************************************************************/
868199323Sjkim
869199323Sjkimstatic ACPI_STATUS
870199323SjkimAcpiNsCheckSortedList (
871249663Sjkim    ACPI_EVALUATE_INFO      *Info,
872199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject,
873250838Sjkim    UINT32                  StartIndex,
874199323Sjkim    UINT32                  ExpectedCount,
875199323Sjkim    UINT32                  SortIndex,
876199323Sjkim    UINT8                   SortDirection,
877199323Sjkim    char                    *SortKeyName)
878199323Sjkim{
879199323Sjkim    UINT32                  OuterElementCount;
880199323Sjkim    ACPI_OPERAND_OBJECT     **OuterElements;
881199323Sjkim    ACPI_OPERAND_OBJECT     **Elements;
882199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
883199323Sjkim    UINT32                  i;
884199323Sjkim    UINT32                  PreviousValue;
885199323Sjkim
886199323Sjkim
887200553Sjkim    ACPI_FUNCTION_NAME (NsCheckSortedList);
888200553Sjkim
889200553Sjkim
890199323Sjkim    /* The top-level object must be a package */
891199323Sjkim
892199323Sjkim    if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
893199323Sjkim    {
894199323Sjkim        return (AE_AML_OPERAND_TYPE);
895199323Sjkim    }
896199323Sjkim
897199323Sjkim    /*
898281075Sdim     * NOTE: assumes list of subpackages contains no NULL elements.
899200553Sjkim     * Any NULL elements should have been removed by earlier call
900200553Sjkim     * to AcpiNsRemoveNullElements.
901199323Sjkim     */
902199323Sjkim    OuterElementCount = ReturnObject->Package.Count;
903250838Sjkim    if (!OuterElementCount || StartIndex >= OuterElementCount)
904199323Sjkim    {
905199323Sjkim        return (AE_AML_PACKAGE_LIMIT);
906199323Sjkim    }
907199323Sjkim
908250838Sjkim    OuterElements = &ReturnObject->Package.Elements[StartIndex];
909250838Sjkim    OuterElementCount -= StartIndex;
910250838Sjkim
911199323Sjkim    PreviousValue = 0;
912199323Sjkim    if (SortDirection == ACPI_SORT_DESCENDING)
913199323Sjkim    {
914199323Sjkim        PreviousValue = ACPI_UINT32_MAX;
915199323Sjkim    }
916199323Sjkim
917199323Sjkim    /* Examine each subpackage */
918199323Sjkim
919199323Sjkim    for (i = 0; i < OuterElementCount; i++)
920199323Sjkim    {
921199323Sjkim        /* Each element of the top-level package must also be a package */
922199323Sjkim
923199323Sjkim        if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE)
924199323Sjkim        {
925199323Sjkim            return (AE_AML_OPERAND_TYPE);
926199323Sjkim        }
927199323Sjkim
928281075Sdim        /* Each subpackage must have the minimum length */
929199323Sjkim
930199323Sjkim        if ((*OuterElements)->Package.Count < ExpectedCount)
931199323Sjkim        {
932199323Sjkim            return (AE_AML_PACKAGE_LIMIT);
933199323Sjkim        }
934199323Sjkim
935199323Sjkim        Elements = (*OuterElements)->Package.Elements;
936199323Sjkim        ObjDesc = Elements[SortIndex];
937199323Sjkim
938199323Sjkim        if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
939199323Sjkim        {
940199323Sjkim            return (AE_AML_OPERAND_TYPE);
941199323Sjkim        }
942199323Sjkim
943199323Sjkim        /*
944199323Sjkim         * The list must be sorted in the specified order. If we detect a
945202771Sjkim         * discrepancy, sort the entire list.
946199323Sjkim         */
947199323Sjkim        if (((SortDirection == ACPI_SORT_ASCENDING) &&
948199323Sjkim                (ObjDesc->Integer.Value < PreviousValue)) ||
949199323Sjkim            ((SortDirection == ACPI_SORT_DESCENDING) &&
950199323Sjkim                (ObjDesc->Integer.Value > PreviousValue)))
951199323Sjkim        {
952250838Sjkim            AcpiNsSortList (&ReturnObject->Package.Elements[StartIndex],
953202771Sjkim                OuterElementCount, SortIndex, SortDirection);
954199323Sjkim
955249663Sjkim            Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
956199323Sjkim
957200553Sjkim            ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
958200553Sjkim                "%s: Repaired unsorted list - now sorted by %s\n",
959249663Sjkim                Info->FullPathname, SortKeyName));
960199323Sjkim            return (AE_OK);
961199323Sjkim        }
962199323Sjkim
963199323Sjkim        PreviousValue = (UINT32) ObjDesc->Integer.Value;
964199323Sjkim        OuterElements++;
965199323Sjkim    }
966199323Sjkim
967199323Sjkim    return (AE_OK);
968199323Sjkim}
969199323Sjkim
970199323Sjkim
971199323Sjkim/******************************************************************************
972199323Sjkim *
973199323Sjkim * FUNCTION:    AcpiNsSortList
974199323Sjkim *
975199323Sjkim * PARAMETERS:  Elements            - Package object element list
976199323Sjkim *              Count               - Element count for above
977199323Sjkim *              Index               - Sort by which package element
978199323Sjkim *              SortDirection       - Ascending or Descending sort
979199323Sjkim *
980202771Sjkim * RETURN:      None
981199323Sjkim *
982199323Sjkim * DESCRIPTION: Sort the objects that are in a package element list.
983199323Sjkim *
984202771Sjkim * NOTE: Assumes that all NULL elements have been removed from the package,
985202771Sjkim *       and that all elements have been verified to be of type Integer.
986199323Sjkim *
987199323Sjkim *****************************************************************************/
988199323Sjkim
989202771Sjkimstatic void
990199323SjkimAcpiNsSortList (
991199323Sjkim    ACPI_OPERAND_OBJECT     **Elements,
992199323Sjkim    UINT32                  Count,
993199323Sjkim    UINT32                  Index,
994199323Sjkim    UINT8                   SortDirection)
995199323Sjkim{
996199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc1;
997199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc2;
998199323Sjkim    ACPI_OPERAND_OBJECT     *TempObj;
999199323Sjkim    UINT32                  i;
1000199323Sjkim    UINT32                  j;
1001199323Sjkim
1002199323Sjkim
1003199323Sjkim    /* Simple bubble sort */
1004199323Sjkim
1005199323Sjkim    for (i = 1; i < Count; i++)
1006199323Sjkim    {
1007199323Sjkim        for (j = (Count - 1); j >= i; j--)
1008199323Sjkim        {
1009199323Sjkim            ObjDesc1 = Elements[j-1]->Package.Elements[Index];
1010199323Sjkim            ObjDesc2 = Elements[j]->Package.Elements[Index];
1011199323Sjkim
1012199323Sjkim            if (((SortDirection == ACPI_SORT_ASCENDING) &&
1013199323Sjkim                    (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) ||
1014199323Sjkim
1015199323Sjkim                ((SortDirection == ACPI_SORT_DESCENDING) &&
1016199323Sjkim                    (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value)))
1017199323Sjkim            {
1018199323Sjkim                TempObj = Elements[j-1];
1019199323Sjkim                Elements[j-1] = Elements[j];
1020199323Sjkim                Elements[j] = TempObj;
1021199323Sjkim            }
1022199323Sjkim        }
1023199323Sjkim    }
1024199323Sjkim}
1025250838Sjkim
1026250838Sjkim
1027250838Sjkim/******************************************************************************
1028250838Sjkim *
1029250838Sjkim * FUNCTION:    AcpiNsRemoveElement
1030250838Sjkim *
1031250838Sjkim * PARAMETERS:  ObjDesc             - Package object element list
1032250838Sjkim *              Index               - Index of element to remove
1033250838Sjkim *
1034250838Sjkim * RETURN:      None
1035250838Sjkim *
1036250838Sjkim * DESCRIPTION: Remove the requested element of a package and delete it.
1037250838Sjkim *
1038250838Sjkim *****************************************************************************/
1039250838Sjkim
1040250838Sjkimstatic void
1041250838SjkimAcpiNsRemoveElement (
1042250838Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc,
1043250838Sjkim    UINT32                  Index)
1044250838Sjkim{
1045250838Sjkim    ACPI_OPERAND_OBJECT     **Source;
1046250838Sjkim    ACPI_OPERAND_OBJECT     **Dest;
1047250838Sjkim    UINT32                  Count;
1048250838Sjkim    UINT32                  NewCount;
1049250838Sjkim    UINT32                  i;
1050250838Sjkim
1051250838Sjkim
1052250838Sjkim    ACPI_FUNCTION_NAME (NsRemoveElement);
1053250838Sjkim
1054250838Sjkim
1055250838Sjkim    Count = ObjDesc->Package.Count;
1056250838Sjkim    NewCount = Count - 1;
1057250838Sjkim
1058250838Sjkim    Source = ObjDesc->Package.Elements;
1059250838Sjkim    Dest = Source;
1060250838Sjkim
1061250838Sjkim    /* Examine all elements of the package object, remove matched index */
1062250838Sjkim
1063250838Sjkim    for (i = 0; i < Count; i++)
1064250838Sjkim    {
1065250838Sjkim        if (i == Index)
1066250838Sjkim        {
1067250838Sjkim            AcpiUtRemoveReference (*Source); /* Remove one ref for being in pkg */
1068250838Sjkim            AcpiUtRemoveReference (*Source);
1069250838Sjkim        }
1070250838Sjkim        else
1071250838Sjkim        {
1072250838Sjkim            *Dest = *Source;
1073250838Sjkim            Dest++;
1074250838Sjkim        }
1075306536Sjkim
1076250838Sjkim        Source++;
1077250838Sjkim    }
1078250838Sjkim
1079250838Sjkim    /* NULL terminate list and update the package count */
1080250838Sjkim
1081250838Sjkim    *Dest = NULL;
1082250838Sjkim    ObjDesc->Package.Count = NewCount;
1083250838Sjkim}
1084