nsrepair2.c revision 202771
1199323Sjkim/******************************************************************************
2199323Sjkim *
3199323Sjkim * Module Name: nsrepair2 - Repair for objects returned by specific
4199323Sjkim *                          predefined methods
5199323Sjkim *
6199323Sjkim *****************************************************************************/
7199323Sjkim
8199323Sjkim/******************************************************************************
9199323Sjkim *
10199323Sjkim * 1. Copyright Notice
11199323Sjkim *
12202771Sjkim * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
13199323Sjkim * All rights reserved.
14199323Sjkim *
15199323Sjkim * 2. License
16199323Sjkim *
17199323Sjkim * 2.1. This is your license from Intel Corp. under its intellectual property
18199323Sjkim * rights.  You may have additional license terms from the party that provided
19199323Sjkim * you this software, covering your right to use that party's intellectual
20199323Sjkim * property rights.
21199323Sjkim *
22199323Sjkim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23199323Sjkim * copy of the source code appearing in this file ("Covered Code") an
24199323Sjkim * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25199323Sjkim * base code distributed originally by Intel ("Original Intel Code") to copy,
26199323Sjkim * make derivatives, distribute, use and display any portion of the Covered
27199323Sjkim * Code in any form, with the right to sublicense such rights; and
28199323Sjkim *
29199323Sjkim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30199323Sjkim * license (with the right to sublicense), under only those claims of Intel
31199323Sjkim * patents that are infringed by the Original Intel Code, to make, use, sell,
32199323Sjkim * offer to sell, and import the Covered Code and derivative works thereof
33199323Sjkim * solely to the minimum extent necessary to exercise the above copyright
34199323Sjkim * license, and in no event shall the patent license extend to any additions
35199323Sjkim * to or modifications of the Original Intel Code.  No other license or right
36199323Sjkim * is granted directly or by implication, estoppel or otherwise;
37199323Sjkim *
38199323Sjkim * The above copyright and patent license is granted only if the following
39199323Sjkim * conditions are met:
40199323Sjkim *
41199323Sjkim * 3. Conditions
42199323Sjkim *
43199323Sjkim * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44199323Sjkim * Redistribution of source code of any substantial portion of the Covered
45199323Sjkim * Code or modification with rights to further distribute source must include
46199323Sjkim * the above Copyright Notice, the above License, this list of Conditions,
47199323Sjkim * and the following Disclaimer and Export Compliance provision.  In addition,
48199323Sjkim * Licensee must cause all Covered Code to which Licensee contributes to
49199323Sjkim * contain a file documenting the changes Licensee made to create that Covered
50199323Sjkim * Code and the date of any change.  Licensee must include in that file the
51199323Sjkim * documentation of any changes made by any predecessor Licensee.  Licensee
52199323Sjkim * must include a prominent statement that the modification is derived,
53199323Sjkim * directly or indirectly, from Original Intel Code.
54199323Sjkim *
55199323Sjkim * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56199323Sjkim * Redistribution of source code of any substantial portion of the Covered
57199323Sjkim * Code or modification without rights to further distribute source must
58199323Sjkim * include the following Disclaimer and Export Compliance provision in the
59199323Sjkim * documentation and/or other materials provided with distribution.  In
60199323Sjkim * addition, Licensee may not authorize further sublicense of source of any
61199323Sjkim * portion of the Covered Code, and must include terms to the effect that the
62199323Sjkim * license from Licensee to its licensee is limited to the intellectual
63199323Sjkim * property embodied in the software Licensee provides to its licensee, and
64199323Sjkim * not to intellectual property embodied in modifications its licensee may
65199323Sjkim * make.
66199323Sjkim *
67199323Sjkim * 3.3. Redistribution of Executable. Redistribution in executable form of any
68199323Sjkim * substantial portion of the Covered Code or modification must reproduce the
69199323Sjkim * above Copyright Notice, and the following Disclaimer and Export Compliance
70199323Sjkim * provision in the documentation and/or other materials provided with the
71199323Sjkim * distribution.
72199323Sjkim *
73199323Sjkim * 3.4. Intel retains all right, title, and interest in and to the Original
74199323Sjkim * Intel Code.
75199323Sjkim *
76199323Sjkim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77199323Sjkim * Intel shall be used in advertising or otherwise to promote the sale, use or
78199323Sjkim * other dealings in products derived from or relating to the Covered Code
79199323Sjkim * without prior written authorization from Intel.
80199323Sjkim *
81199323Sjkim * 4. Disclaimer and Export Compliance
82199323Sjkim *
83199323Sjkim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84199323Sjkim * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85199323Sjkim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86199323Sjkim * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87199323Sjkim * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88199323Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89199323Sjkim * PARTICULAR PURPOSE.
90199323Sjkim *
91199323Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92199323Sjkim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93199323Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94199323Sjkim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95199323Sjkim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96199323Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97199323Sjkim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98199323Sjkim * LIMITED REMEDY.
99199323Sjkim *
100199323Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this
101199323Sjkim * software or system incorporating such software without first obtaining any
102199323Sjkim * required license or other approval from the U. S. Department of Commerce or
103199323Sjkim * any other agency or department of the United States Government.  In the
104199323Sjkim * event Licensee exports any such software from the United States or
105199323Sjkim * re-exports any such software from a foreign destination, Licensee shall
106199323Sjkim * ensure that the distribution and export/re-export of the software is in
107199323Sjkim * compliance with all laws, regulations, orders, or other restrictions of the
108199323Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109199323Sjkim * any of its subsidiaries will export/re-export any technical data, process,
110199323Sjkim * software, or service, directly or indirectly, to any country for which the
111199323Sjkim * United States government or any agency thereof requires an export license,
112199323Sjkim * other governmental approval, or letter of assurance, without first obtaining
113199323Sjkim * such license, approval or letter.
114199323Sjkim *
115199323Sjkim *****************************************************************************/
116199323Sjkim
117199323Sjkim#define __NSREPAIR2_C__
118199323Sjkim
119199337Sjkim#include <contrib/dev/acpica/include/acpi.h>
120199337Sjkim#include <contrib/dev/acpica/include/accommon.h>
121199337Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
122199323Sjkim
123199323Sjkim#define _COMPONENT          ACPI_NAMESPACE
124199323Sjkim        ACPI_MODULE_NAME    ("nsrepair2")
125199323Sjkim
126199323Sjkim
127199323Sjkim/*
128199323Sjkim * Information structure and handler for ACPI predefined names that can
129199323Sjkim * be repaired on a per-name basis.
130199323Sjkim */
131199323Sjkimtypedef
132199323SjkimACPI_STATUS (*ACPI_REPAIR_FUNCTION) (
133199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
134199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
135199323Sjkim
136199323Sjkimtypedef struct acpi_repair_info
137199323Sjkim{
138199323Sjkim    char                    Name[ACPI_NAME_SIZE];
139199323Sjkim    ACPI_REPAIR_FUNCTION    RepairFunction;
140199323Sjkim
141199323Sjkim} ACPI_REPAIR_INFO;
142199323Sjkim
143199323Sjkim
144199323Sjkim/* Local prototypes */
145199323Sjkim
146199323Sjkimstatic const ACPI_REPAIR_INFO *
147199323SjkimAcpiNsMatchRepairableName (
148199323Sjkim    ACPI_NAMESPACE_NODE     *Node);
149199323Sjkim
150199323Sjkimstatic ACPI_STATUS
151199323SjkimAcpiNsRepair_ALR (
152199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
153199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
154199323Sjkim
155199323Sjkimstatic ACPI_STATUS
156200553SjkimAcpiNsRepair_FDE (
157200553Sjkim    ACPI_PREDEFINED_DATA    *Data,
158200553Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
159200553Sjkim
160200553Sjkimstatic ACPI_STATUS
161199323SjkimAcpiNsRepair_PSS (
162199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
163199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
164199323Sjkim
165199323Sjkimstatic ACPI_STATUS
166199323SjkimAcpiNsRepair_TSS (
167199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
168199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
169199323Sjkim
170199323Sjkimstatic ACPI_STATUS
171199323SjkimAcpiNsCheckSortedList (
172199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
173199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject,
174199323Sjkim    UINT32                  ExpectedCount,
175199323Sjkim    UINT32                  SortIndex,
176199323Sjkim    UINT8                   SortDirection,
177199323Sjkim    char                    *SortKeyName);
178199323Sjkim
179202771Sjkimstatic void
180199323SjkimAcpiNsSortList (
181199323Sjkim    ACPI_OPERAND_OBJECT     **Elements,
182199323Sjkim    UINT32                  Count,
183199323Sjkim    UINT32                  Index,
184199323Sjkim    UINT8                   SortDirection);
185199323Sjkim
186199323Sjkim/* Values for SortDirection above */
187199323Sjkim
188199323Sjkim#define ACPI_SORT_ASCENDING     0
189199323Sjkim#define ACPI_SORT_DESCENDING    1
190199323Sjkim
191199323Sjkim
192199323Sjkim/*
193199323Sjkim * This table contains the names of the predefined methods for which we can
194199323Sjkim * perform more complex repairs.
195199323Sjkim *
196200553Sjkim * As necessary:
197200553Sjkim *
198200553Sjkim * _ALR: Sort the list ascending by AmbientIlluminance
199200553Sjkim * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
200200553Sjkim * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
201200553Sjkim * _PSS: Sort the list descending by Power
202200553Sjkim * _TSS: Sort the list descending by Power
203199323Sjkim */
204199323Sjkimstatic const ACPI_REPAIR_INFO       AcpiNsRepairableNames[] =
205199323Sjkim{
206199323Sjkim    {"_ALR", AcpiNsRepair_ALR},
207200553Sjkim    {"_FDE", AcpiNsRepair_FDE},
208200553Sjkim    {"_GTM", AcpiNsRepair_FDE},     /* _GTM has same repair as _FDE */
209199323Sjkim    {"_PSS", AcpiNsRepair_PSS},
210199323Sjkim    {"_TSS", AcpiNsRepair_TSS},
211200553Sjkim    {{0,0,0,0}, NULL}               /* Table terminator */
212199323Sjkim};
213199323Sjkim
214199323Sjkim
215200553Sjkim#define ACPI_FDE_FIELD_COUNT        5
216200553Sjkim#define ACPI_FDE_BYTE_BUFFER_SIZE   5
217200553Sjkim#define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * sizeof (UINT32))
218200553Sjkim
219200553Sjkim
220199323Sjkim/******************************************************************************
221199323Sjkim *
222199323Sjkim * FUNCTION:    AcpiNsComplexRepairs
223199323Sjkim *
224199323Sjkim * PARAMETERS:  Data                - Pointer to validation data structure
225199323Sjkim *              Node                - Namespace node for the method/object
226199323Sjkim *              ValidateStatus      - Original status of earlier validation
227199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
228199323Sjkim *                                    evaluation of a method or object
229199323Sjkim *
230200553Sjkim * RETURN:      Status. AE_OK if repair was successful. If name is not
231199323Sjkim *              matched, ValidateStatus is returned.
232199323Sjkim *
233199323Sjkim * DESCRIPTION: Attempt to repair/convert a return object of a type that was
234199323Sjkim *              not expected.
235199323Sjkim *
236199323Sjkim *****************************************************************************/
237199323Sjkim
238199323SjkimACPI_STATUS
239199323SjkimAcpiNsComplexRepairs (
240199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
241199323Sjkim    ACPI_NAMESPACE_NODE     *Node,
242199323Sjkim    ACPI_STATUS             ValidateStatus,
243199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
244199323Sjkim{
245199323Sjkim    const ACPI_REPAIR_INFO  *Predefined;
246199323Sjkim    ACPI_STATUS             Status;
247199323Sjkim
248199323Sjkim
249199323Sjkim    /* Check if this name is in the list of repairable names */
250199323Sjkim
251199323Sjkim    Predefined = AcpiNsMatchRepairableName (Node);
252199323Sjkim    if (!Predefined)
253199323Sjkim    {
254199323Sjkim        return (ValidateStatus);
255199323Sjkim    }
256199323Sjkim
257199323Sjkim    Status = Predefined->RepairFunction (Data, ReturnObjectPtr);
258199323Sjkim    return (Status);
259199323Sjkim}
260199323Sjkim
261199323Sjkim
262199323Sjkim/******************************************************************************
263199323Sjkim *
264199323Sjkim * FUNCTION:    AcpiNsMatchRepairableName
265199323Sjkim *
266199323Sjkim * PARAMETERS:  Node                - Namespace node for the method/object
267199323Sjkim *
268199323Sjkim * RETURN:      Pointer to entry in repair table. NULL indicates not found.
269199323Sjkim *
270199323Sjkim * DESCRIPTION: Check an object name against the repairable object list.
271199323Sjkim *
272199323Sjkim *****************************************************************************/
273199323Sjkim
274199323Sjkimstatic const ACPI_REPAIR_INFO *
275199323SjkimAcpiNsMatchRepairableName (
276199323Sjkim    ACPI_NAMESPACE_NODE     *Node)
277199323Sjkim{
278199323Sjkim    const ACPI_REPAIR_INFO  *ThisName;
279199323Sjkim
280199323Sjkim
281199323Sjkim    /* Search info table for a repairable predefined method/object name */
282199323Sjkim
283199323Sjkim    ThisName = AcpiNsRepairableNames;
284199323Sjkim    while (ThisName->RepairFunction)
285199323Sjkim    {
286199323Sjkim        if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name))
287199323Sjkim        {
288199323Sjkim            return (ThisName);
289199323Sjkim        }
290199323Sjkim        ThisName++;
291199323Sjkim    }
292199323Sjkim
293199323Sjkim    return (NULL); /* Not found */
294199323Sjkim}
295199323Sjkim
296199323Sjkim
297199323Sjkim/******************************************************************************
298199323Sjkim *
299199323Sjkim * FUNCTION:    AcpiNsRepair_ALR
300199323Sjkim *
301199323Sjkim * PARAMETERS:  Data                - Pointer to validation data structure
302199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
303199323Sjkim *                                    evaluation of a method or object
304199323Sjkim *
305199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
306199323Sjkim *
307199323Sjkim * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
308199323Sjkim *              ascending by the ambient illuminance values.
309199323Sjkim *
310199323Sjkim *****************************************************************************/
311199323Sjkim
312199323Sjkimstatic ACPI_STATUS
313199323SjkimAcpiNsRepair_ALR (
314199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
315199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
316199323Sjkim{
317199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
318199323Sjkim    ACPI_STATUS             Status;
319199323Sjkim
320199323Sjkim
321199323Sjkim    Status = AcpiNsCheckSortedList (Data, ReturnObject, 2, 1,
322199323Sjkim                ACPI_SORT_ASCENDING, "AmbientIlluminance");
323199323Sjkim
324199323Sjkim    return (Status);
325199323Sjkim}
326199323Sjkim
327199323Sjkim
328199323Sjkim/******************************************************************************
329199323Sjkim *
330200553Sjkim * FUNCTION:    AcpiNsRepair_FDE
331200553Sjkim *
332200553Sjkim * PARAMETERS:  Data                - Pointer to validation data structure
333200553Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
334200553Sjkim *                                    evaluation of a method or object
335200553Sjkim *
336200553Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
337200553Sjkim *
338200553Sjkim * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return
339200553Sjkim *              value is a Buffer of 5 DWORDs. This function repairs a common
340200553Sjkim *              problem where the return value is a Buffer of BYTEs, not
341200553Sjkim *              DWORDs.
342200553Sjkim *
343200553Sjkim *****************************************************************************/
344200553Sjkim
345200553Sjkimstatic ACPI_STATUS
346200553SjkimAcpiNsRepair_FDE (
347200553Sjkim    ACPI_PREDEFINED_DATA    *Data,
348200553Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
349200553Sjkim{
350200553Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
351200553Sjkim    ACPI_OPERAND_OBJECT     *BufferObject;
352200553Sjkim    UINT8                   *ByteBuffer;
353200553Sjkim    UINT32                  *DwordBuffer;
354200553Sjkim    UINT32                  i;
355200553Sjkim
356200553Sjkim
357200553Sjkim    ACPI_FUNCTION_NAME (NsRepair_FDE);
358200553Sjkim
359200553Sjkim
360200553Sjkim    switch (ReturnObject->Common.Type)
361200553Sjkim    {
362200553Sjkim    case ACPI_TYPE_BUFFER:
363200553Sjkim
364200553Sjkim        /* This is the expected type. Length should be (at least) 5 DWORDs */
365200553Sjkim
366200553Sjkim        if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE)
367200553Sjkim        {
368200553Sjkim            return (AE_OK);
369200553Sjkim        }
370200553Sjkim
371200553Sjkim        /* We can only repair if we have exactly 5 BYTEs */
372200553Sjkim
373200553Sjkim        if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE)
374200553Sjkim        {
375200553Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
376200553Sjkim                "Incorrect return buffer length %u, expected %u",
377200553Sjkim                ReturnObject->Buffer.Length, ACPI_FDE_DWORD_BUFFER_SIZE));
378200553Sjkim
379200553Sjkim            return (AE_AML_OPERAND_TYPE);
380200553Sjkim        }
381200553Sjkim
382200553Sjkim        /* Create the new (larger) buffer object */
383200553Sjkim
384200553Sjkim        BufferObject = AcpiUtCreateBufferObject (ACPI_FDE_DWORD_BUFFER_SIZE);
385200553Sjkim        if (!BufferObject)
386200553Sjkim        {
387200553Sjkim            return (AE_NO_MEMORY);
388200553Sjkim        }
389200553Sjkim
390200553Sjkim        /* Expand each byte to a DWORD */
391200553Sjkim
392200553Sjkim        ByteBuffer = ReturnObject->Buffer.Pointer;
393200553Sjkim        DwordBuffer = ACPI_CAST_PTR (UINT32, BufferObject->Buffer.Pointer);
394200553Sjkim
395200553Sjkim        for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++)
396200553Sjkim        {
397200553Sjkim            *DwordBuffer = (UINT32) *ByteBuffer;
398200553Sjkim            DwordBuffer++;
399200553Sjkim            ByteBuffer++;
400200553Sjkim        }
401200553Sjkim
402200553Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
403200553Sjkim            "%s Expanded Byte Buffer to expected DWord Buffer\n",
404200553Sjkim            Data->Pathname));
405200553Sjkim        break;
406200553Sjkim
407200553Sjkim    default:
408200553Sjkim        return (AE_AML_OPERAND_TYPE);
409200553Sjkim    }
410200553Sjkim
411200553Sjkim    /* Delete the original return object, return the new buffer object */
412200553Sjkim
413200553Sjkim    AcpiUtRemoveReference (ReturnObject);
414200553Sjkim    *ReturnObjectPtr = BufferObject;
415200553Sjkim
416200553Sjkim    Data->Flags |= ACPI_OBJECT_REPAIRED;
417200553Sjkim    return (AE_OK);
418200553Sjkim}
419200553Sjkim
420200553Sjkim
421200553Sjkim/******************************************************************************
422200553Sjkim *
423199323Sjkim * FUNCTION:    AcpiNsRepair_TSS
424199323Sjkim *
425199323Sjkim * PARAMETERS:  Data                - Pointer to validation data structure
426199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
427199323Sjkim *                                    evaluation of a method or object
428199323Sjkim *
429199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
430199323Sjkim *
431199323Sjkim * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
432199323Sjkim *              descending by the power dissipation values.
433199323Sjkim *
434199323Sjkim *****************************************************************************/
435199323Sjkim
436199323Sjkimstatic ACPI_STATUS
437199323SjkimAcpiNsRepair_TSS (
438199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
439199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
440199323Sjkim{
441199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
442199323Sjkim    ACPI_STATUS             Status;
443199323Sjkim
444199323Sjkim
445199323Sjkim    Status = AcpiNsCheckSortedList (Data, ReturnObject, 5, 1,
446199323Sjkim                ACPI_SORT_DESCENDING, "PowerDissipation");
447199323Sjkim
448199323Sjkim    return (Status);
449199323Sjkim}
450199323Sjkim
451199323Sjkim
452199323Sjkim/******************************************************************************
453199323Sjkim *
454199323Sjkim * FUNCTION:    AcpiNsRepair_PSS
455199323Sjkim *
456199323Sjkim * PARAMETERS:  Data                - Pointer to validation data structure
457199323Sjkim *              ReturnObjectPtr     - Pointer to the object returned from the
458199323Sjkim *                                    evaluation of a method or object
459199323Sjkim *
460199323Sjkim * RETURN:      Status. AE_OK if object is OK or was repaired successfully
461199323Sjkim *
462199323Sjkim * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
463199323Sjkim *              by the CPU frequencies. Check that the power dissipation values
464199323Sjkim *              are all proportional to CPU frequency (i.e., sorting by
465199323Sjkim *              frequency should be the same as sorting by power.)
466199323Sjkim *
467199323Sjkim *****************************************************************************/
468199323Sjkim
469199323Sjkimstatic ACPI_STATUS
470199323SjkimAcpiNsRepair_PSS (
471199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
472199323Sjkim    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
473199323Sjkim{
474199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
475199323Sjkim    ACPI_OPERAND_OBJECT     **OuterElements;
476199323Sjkim    UINT32                  OuterElementCount;
477199323Sjkim    ACPI_OPERAND_OBJECT     **Elements;
478199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
479199323Sjkim    UINT32                  PreviousValue;
480199323Sjkim    ACPI_STATUS             Status;
481199323Sjkim    UINT32                  i;
482199323Sjkim
483199323Sjkim
484199323Sjkim    /*
485199323Sjkim     * Entries (sub-packages) in the _PSS Package must be sorted by power
486199323Sjkim     * dissipation, in descending order. If it appears that the list is
487199323Sjkim     * incorrectly sorted, sort it. We sort by CpuFrequency, since this
488199323Sjkim     * should be proportional to the power.
489199323Sjkim     */
490199323Sjkim    Status =AcpiNsCheckSortedList (Data, ReturnObject, 6, 0,
491199323Sjkim                ACPI_SORT_DESCENDING, "CpuFrequency");
492199323Sjkim    if (ACPI_FAILURE (Status))
493199323Sjkim    {
494199323Sjkim        return (Status);
495199323Sjkim    }
496199323Sjkim
497199323Sjkim    /*
498199323Sjkim     * We now know the list is correctly sorted by CPU frequency. Check if
499199323Sjkim     * the power dissipation values are proportional.
500199323Sjkim     */
501199323Sjkim    PreviousValue = ACPI_UINT32_MAX;
502199323Sjkim    OuterElements = ReturnObject->Package.Elements;
503199323Sjkim    OuterElementCount = ReturnObject->Package.Count;
504199323Sjkim
505199323Sjkim    for (i = 0; i < OuterElementCount; i++)
506199323Sjkim    {
507199323Sjkim        Elements = (*OuterElements)->Package.Elements;
508199323Sjkim        ObjDesc = Elements[1]; /* Index1 = PowerDissipation */
509199323Sjkim
510199323Sjkim        if ((UINT32) ObjDesc->Integer.Value > PreviousValue)
511199323Sjkim        {
512199323Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
513199323Sjkim                "SubPackage[%u,%u] - suspicious power dissipation values",
514199323Sjkim                i-1, i));
515199323Sjkim        }
516199323Sjkim
517199323Sjkim        PreviousValue = (UINT32) ObjDesc->Integer.Value;
518199323Sjkim        OuterElements++;
519199323Sjkim    }
520199323Sjkim
521199323Sjkim    return (AE_OK);
522199323Sjkim}
523199323Sjkim
524199323Sjkim
525199323Sjkim/******************************************************************************
526199323Sjkim *
527199323Sjkim * FUNCTION:    AcpiNsCheckSortedList
528199323Sjkim *
529199323Sjkim * PARAMETERS:  Data                - Pointer to validation data structure
530199323Sjkim *              ReturnObject        - Pointer to the top-level returned object
531199323Sjkim *              ExpectedCount       - Minimum length of each sub-package
532199323Sjkim *              SortIndex           - Sub-package entry to sort on
533199323Sjkim *              SortDirection       - Ascending or descending
534199323Sjkim *              SortKeyName         - Name of the SortIndex field
535199323Sjkim *
536199323Sjkim * RETURN:      Status. AE_OK if the list is valid and is sorted correctly or
537199323Sjkim *              has been repaired by sorting the list.
538199323Sjkim *
539199323Sjkim * DESCRIPTION: Check if the package list is valid and sorted correctly by the
540199323Sjkim *              SortIndex. If not, then sort the list.
541199323Sjkim *
542199323Sjkim *****************************************************************************/
543199323Sjkim
544199323Sjkimstatic ACPI_STATUS
545199323SjkimAcpiNsCheckSortedList (
546199323Sjkim    ACPI_PREDEFINED_DATA    *Data,
547199323Sjkim    ACPI_OPERAND_OBJECT     *ReturnObject,
548199323Sjkim    UINT32                  ExpectedCount,
549199323Sjkim    UINT32                  SortIndex,
550199323Sjkim    UINT8                   SortDirection,
551199323Sjkim    char                    *SortKeyName)
552199323Sjkim{
553199323Sjkim    UINT32                  OuterElementCount;
554199323Sjkim    ACPI_OPERAND_OBJECT     **OuterElements;
555199323Sjkim    ACPI_OPERAND_OBJECT     **Elements;
556199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
557199323Sjkim    UINT32                  i;
558199323Sjkim    UINT32                  PreviousValue;
559199323Sjkim
560199323Sjkim
561200553Sjkim    ACPI_FUNCTION_NAME (NsCheckSortedList);
562200553Sjkim
563200553Sjkim
564199323Sjkim    /* The top-level object must be a package */
565199323Sjkim
566199323Sjkim    if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
567199323Sjkim    {
568199323Sjkim        return (AE_AML_OPERAND_TYPE);
569199323Sjkim    }
570199323Sjkim
571199323Sjkim    /*
572200553Sjkim     * NOTE: assumes list of sub-packages contains no NULL elements.
573200553Sjkim     * Any NULL elements should have been removed by earlier call
574200553Sjkim     * to AcpiNsRemoveNullElements.
575199323Sjkim     */
576199323Sjkim    OuterElements = ReturnObject->Package.Elements;
577199323Sjkim    OuterElementCount = ReturnObject->Package.Count;
578199323Sjkim    if (!OuterElementCount)
579199323Sjkim    {
580199323Sjkim        return (AE_AML_PACKAGE_LIMIT);
581199323Sjkim    }
582199323Sjkim
583199323Sjkim    PreviousValue = 0;
584199323Sjkim    if (SortDirection == ACPI_SORT_DESCENDING)
585199323Sjkim    {
586199323Sjkim        PreviousValue = ACPI_UINT32_MAX;
587199323Sjkim    }
588199323Sjkim
589199323Sjkim    /* Examine each subpackage */
590199323Sjkim
591199323Sjkim    for (i = 0; i < OuterElementCount; i++)
592199323Sjkim    {
593199323Sjkim        /* Each element of the top-level package must also be a package */
594199323Sjkim
595199323Sjkim        if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE)
596199323Sjkim        {
597199323Sjkim            return (AE_AML_OPERAND_TYPE);
598199323Sjkim        }
599199323Sjkim
600199323Sjkim        /* Each sub-package must have the minimum length */
601199323Sjkim
602199323Sjkim        if ((*OuterElements)->Package.Count < ExpectedCount)
603199323Sjkim        {
604199323Sjkim            return (AE_AML_PACKAGE_LIMIT);
605199323Sjkim        }
606199323Sjkim
607199323Sjkim        Elements = (*OuterElements)->Package.Elements;
608199323Sjkim        ObjDesc = Elements[SortIndex];
609199323Sjkim
610199323Sjkim        if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
611199323Sjkim        {
612199323Sjkim            return (AE_AML_OPERAND_TYPE);
613199323Sjkim        }
614199323Sjkim
615199323Sjkim        /*
616199323Sjkim         * The list must be sorted in the specified order. If we detect a
617202771Sjkim         * discrepancy, sort the entire list.
618199323Sjkim         */
619199323Sjkim        if (((SortDirection == ACPI_SORT_ASCENDING) &&
620199323Sjkim                (ObjDesc->Integer.Value < PreviousValue)) ||
621199323Sjkim            ((SortDirection == ACPI_SORT_DESCENDING) &&
622199323Sjkim                (ObjDesc->Integer.Value > PreviousValue)))
623199323Sjkim        {
624202771Sjkim            AcpiNsSortList (ReturnObject->Package.Elements,
625202771Sjkim                OuterElementCount, SortIndex, SortDirection);
626199323Sjkim
627199323Sjkim            Data->Flags |= ACPI_OBJECT_REPAIRED;
628199323Sjkim
629200553Sjkim            ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
630200553Sjkim                "%s: Repaired unsorted list - now sorted by %s\n",
631200553Sjkim                Data->Pathname, SortKeyName));
632199323Sjkim            return (AE_OK);
633199323Sjkim        }
634199323Sjkim
635199323Sjkim        PreviousValue = (UINT32) ObjDesc->Integer.Value;
636199323Sjkim        OuterElements++;
637199323Sjkim    }
638199323Sjkim
639199323Sjkim    return (AE_OK);
640199323Sjkim}
641199323Sjkim
642199323Sjkim
643199323Sjkim/******************************************************************************
644199323Sjkim *
645199323Sjkim * FUNCTION:    AcpiNsSortList
646199323Sjkim *
647199323Sjkim * PARAMETERS:  Elements            - Package object element list
648199323Sjkim *              Count               - Element count for above
649199323Sjkim *              Index               - Sort by which package element
650199323Sjkim *              SortDirection       - Ascending or Descending sort
651199323Sjkim *
652202771Sjkim * RETURN:      None
653199323Sjkim *
654199323Sjkim * DESCRIPTION: Sort the objects that are in a package element list.
655199323Sjkim *
656202771Sjkim * NOTE: Assumes that all NULL elements have been removed from the package,
657202771Sjkim *       and that all elements have been verified to be of type Integer.
658199323Sjkim *
659199323Sjkim *****************************************************************************/
660199323Sjkim
661202771Sjkimstatic void
662199323SjkimAcpiNsSortList (
663199323Sjkim    ACPI_OPERAND_OBJECT     **Elements,
664199323Sjkim    UINT32                  Count,
665199323Sjkim    UINT32                  Index,
666199323Sjkim    UINT8                   SortDirection)
667199323Sjkim{
668199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc1;
669199323Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc2;
670199323Sjkim    ACPI_OPERAND_OBJECT     *TempObj;
671199323Sjkim    UINT32                  i;
672199323Sjkim    UINT32                  j;
673199323Sjkim
674199323Sjkim
675199323Sjkim    /* Simple bubble sort */
676199323Sjkim
677199323Sjkim    for (i = 1; i < Count; i++)
678199323Sjkim    {
679199323Sjkim        for (j = (Count - 1); j >= i; j--)
680199323Sjkim        {
681199323Sjkim            ObjDesc1 = Elements[j-1]->Package.Elements[Index];
682199323Sjkim            ObjDesc2 = Elements[j]->Package.Elements[Index];
683199323Sjkim
684199323Sjkim            if (((SortDirection == ACPI_SORT_ASCENDING) &&
685199323Sjkim                    (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) ||
686199323Sjkim
687199323Sjkim                ((SortDirection == ACPI_SORT_DESCENDING) &&
688199323Sjkim                    (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value)))
689199323Sjkim            {
690199323Sjkim                TempObj = Elements[j-1];
691199323Sjkim                Elements[j-1] = Elements[j];
692199323Sjkim                Elements[j] = TempObj;
693199323Sjkim            }
694199323Sjkim        }
695199323Sjkim    }
696199323Sjkim}
697