nsrepair2.c revision 199323
1/******************************************************************************
2 *
3 * Module Name: nsrepair2 - Repair for objects returned by specific
4 *                          predefined methods
5 *
6 *****************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
13 * All rights reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117#define __NSREPAIR2_C__
118
119#include "acpi.h"
120#include "accommon.h"
121#include "acnamesp.h"
122
123#define _COMPONENT          ACPI_NAMESPACE
124        ACPI_MODULE_NAME    ("nsrepair2")
125
126
127/*
128 * Information structure and handler for ACPI predefined names that can
129 * be repaired on a per-name basis.
130 */
131typedef
132ACPI_STATUS (*ACPI_REPAIR_FUNCTION) (
133    ACPI_PREDEFINED_DATA    *Data,
134    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
135
136typedef struct acpi_repair_info
137{
138    char                    Name[ACPI_NAME_SIZE];
139    ACPI_REPAIR_FUNCTION    RepairFunction;
140
141} ACPI_REPAIR_INFO;
142
143
144/* Local prototypes */
145
146static const ACPI_REPAIR_INFO *
147AcpiNsMatchRepairableName (
148    ACPI_NAMESPACE_NODE     *Node);
149
150static ACPI_STATUS
151AcpiNsRepair_ALR (
152    ACPI_PREDEFINED_DATA    *Data,
153    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
154
155static ACPI_STATUS
156AcpiNsRepair_PSS (
157    ACPI_PREDEFINED_DATA    *Data,
158    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
159
160static ACPI_STATUS
161AcpiNsRepair_TSS (
162    ACPI_PREDEFINED_DATA    *Data,
163    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
164
165static ACPI_STATUS
166AcpiNsCheckSortedList (
167    ACPI_PREDEFINED_DATA    *Data,
168    ACPI_OPERAND_OBJECT     *ReturnObject,
169    UINT32                  ExpectedCount,
170    UINT32                  SortIndex,
171    UINT8                   SortDirection,
172    char                    *SortKeyName);
173
174static ACPI_STATUS
175AcpiNsRemoveNullElements (
176    ACPI_OPERAND_OBJECT     *Package);
177
178static ACPI_STATUS
179AcpiNsSortList (
180    ACPI_OPERAND_OBJECT     **Elements,
181    UINT32                  Count,
182    UINT32                  Index,
183    UINT8                   SortDirection);
184
185/* Values for SortDirection above */
186
187#define ACPI_SORT_ASCENDING     0
188#define ACPI_SORT_DESCENDING    1
189
190
191/*
192 * This table contains the names of the predefined methods for which we can
193 * perform more complex repairs.
194 *
195 * _ALR: Sort the list ascending by AmbientIlluminance if necessary
196 * _PSS: Sort the list descending by Power if necessary
197 * _TSS: Sort the list descending by Power if necessary
198 */
199static const ACPI_REPAIR_INFO       AcpiNsRepairableNames[] =
200{
201    {"_ALR", AcpiNsRepair_ALR},
202    {"_PSS", AcpiNsRepair_PSS},
203    {"_TSS", AcpiNsRepair_TSS},
204    {{0,0,0,0}, NULL}             /* Table terminator */
205};
206
207
208/******************************************************************************
209 *
210 * FUNCTION:    AcpiNsComplexRepairs
211 *
212 * PARAMETERS:  Data                - Pointer to validation data structure
213 *              Node                - Namespace node for the method/object
214 *              ValidateStatus      - Original status of earlier validation
215 *              ReturnObjectPtr     - Pointer to the object returned from the
216 *                                    evaluation of a method or object
217 *
218 * RETURN:      Status. AE_OK if repair was successful. If name is not
219 *              matched, ValidateStatus is returned.
220 *
221 * DESCRIPTION: Attempt to repair/convert a return object of a type that was
222 *              not expected.
223 *
224 *****************************************************************************/
225
226ACPI_STATUS
227AcpiNsComplexRepairs (
228    ACPI_PREDEFINED_DATA    *Data,
229    ACPI_NAMESPACE_NODE     *Node,
230    ACPI_STATUS             ValidateStatus,
231    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
232{
233    const ACPI_REPAIR_INFO  *Predefined;
234    ACPI_STATUS             Status;
235
236
237    /* Check if this name is in the list of repairable names */
238
239    Predefined = AcpiNsMatchRepairableName (Node);
240    if (!Predefined)
241    {
242        return (ValidateStatus);
243    }
244
245    Status = Predefined->RepairFunction (Data, ReturnObjectPtr);
246    return (Status);
247}
248
249
250/******************************************************************************
251 *
252 * FUNCTION:    AcpiNsMatchRepairableName
253 *
254 * PARAMETERS:  Node                - Namespace node for the method/object
255 *
256 * RETURN:      Pointer to entry in repair table. NULL indicates not found.
257 *
258 * DESCRIPTION: Check an object name against the repairable object list.
259 *
260 *****************************************************************************/
261
262static const ACPI_REPAIR_INFO *
263AcpiNsMatchRepairableName (
264    ACPI_NAMESPACE_NODE     *Node)
265{
266    const ACPI_REPAIR_INFO  *ThisName;
267
268
269    /* Search info table for a repairable predefined method/object name */
270
271    ThisName = AcpiNsRepairableNames;
272    while (ThisName->RepairFunction)
273    {
274        if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name))
275        {
276            return (ThisName);
277        }
278        ThisName++;
279    }
280
281    return (NULL); /* Not found */
282}
283
284
285/******************************************************************************
286 *
287 * FUNCTION:    AcpiNsRepair_ALR
288 *
289 * PARAMETERS:  Data                - Pointer to validation data structure
290 *              ReturnObjectPtr     - Pointer to the object returned from the
291 *                                    evaluation of a method or object
292 *
293 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
294 *
295 * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
296 *              ascending by the ambient illuminance values.
297 *
298 *****************************************************************************/
299
300static ACPI_STATUS
301AcpiNsRepair_ALR (
302    ACPI_PREDEFINED_DATA    *Data,
303    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
304{
305    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
306    ACPI_STATUS             Status;
307
308
309    Status = AcpiNsCheckSortedList (Data, ReturnObject, 2, 1,
310                ACPI_SORT_ASCENDING, "AmbientIlluminance");
311
312    return (Status);
313}
314
315
316/******************************************************************************
317 *
318 * FUNCTION:    AcpiNsRepair_TSS
319 *
320 * PARAMETERS:  Data                - Pointer to validation data structure
321 *              ReturnObjectPtr     - Pointer to the object returned from the
322 *                                    evaluation of a method or object
323 *
324 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
325 *
326 * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
327 *              descending by the power dissipation values.
328 *
329 *****************************************************************************/
330
331static ACPI_STATUS
332AcpiNsRepair_TSS (
333    ACPI_PREDEFINED_DATA    *Data,
334    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
335{
336    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
337    ACPI_STATUS             Status;
338
339
340    Status = AcpiNsCheckSortedList (Data, ReturnObject, 5, 1,
341                ACPI_SORT_DESCENDING, "PowerDissipation");
342
343    return (Status);
344}
345
346
347/******************************************************************************
348 *
349 * FUNCTION:    AcpiNsRepair_PSS
350 *
351 * PARAMETERS:  Data                - Pointer to validation data structure
352 *              ReturnObjectPtr     - Pointer to the object returned from the
353 *                                    evaluation of a method or object
354 *
355 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
356 *
357 * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
358 *              by the CPU frequencies. Check that the power dissipation values
359 *              are all proportional to CPU frequency (i.e., sorting by
360 *              frequency should be the same as sorting by power.)
361 *
362 *****************************************************************************/
363
364static ACPI_STATUS
365AcpiNsRepair_PSS (
366    ACPI_PREDEFINED_DATA    *Data,
367    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
368{
369    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
370    ACPI_OPERAND_OBJECT     **OuterElements;
371    UINT32                  OuterElementCount;
372    ACPI_OPERAND_OBJECT     **Elements;
373    ACPI_OPERAND_OBJECT     *ObjDesc;
374    UINT32                  PreviousValue;
375    ACPI_STATUS             Status;
376    UINT32                  i;
377
378
379    /*
380     * Entries (sub-packages) in the _PSS Package must be sorted by power
381     * dissipation, in descending order. If it appears that the list is
382     * incorrectly sorted, sort it. We sort by CpuFrequency, since this
383     * should be proportional to the power.
384     */
385    Status =AcpiNsCheckSortedList (Data, ReturnObject, 6, 0,
386                ACPI_SORT_DESCENDING, "CpuFrequency");
387    if (ACPI_FAILURE (Status))
388    {
389        return (Status);
390    }
391
392    /*
393     * We now know the list is correctly sorted by CPU frequency. Check if
394     * the power dissipation values are proportional.
395     */
396    PreviousValue = ACPI_UINT32_MAX;
397    OuterElements = ReturnObject->Package.Elements;
398    OuterElementCount = ReturnObject->Package.Count;
399
400    for (i = 0; i < OuterElementCount; i++)
401    {
402        Elements = (*OuterElements)->Package.Elements;
403        ObjDesc = Elements[1]; /* Index1 = PowerDissipation */
404
405        if ((UINT32) ObjDesc->Integer.Value > PreviousValue)
406        {
407            ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
408                "SubPackage[%u,%u] - suspicious power dissipation values",
409                i-1, i));
410        }
411
412        PreviousValue = (UINT32) ObjDesc->Integer.Value;
413        OuterElements++;
414    }
415
416    return (AE_OK);
417}
418
419
420/******************************************************************************
421 *
422 * FUNCTION:    AcpiNsCheckSortedList
423 *
424 * PARAMETERS:  Data                - Pointer to validation data structure
425 *              ReturnObject        - Pointer to the top-level returned object
426 *              ExpectedCount       - Minimum length of each sub-package
427 *              SortIndex           - Sub-package entry to sort on
428 *              SortDirection       - Ascending or descending
429 *              SortKeyName         - Name of the SortIndex field
430 *
431 * RETURN:      Status. AE_OK if the list is valid and is sorted correctly or
432 *              has been repaired by sorting the list.
433 *
434 * DESCRIPTION: Check if the package list is valid and sorted correctly by the
435 *              SortIndex. If not, then sort the list.
436 *
437 *****************************************************************************/
438
439static ACPI_STATUS
440AcpiNsCheckSortedList (
441    ACPI_PREDEFINED_DATA    *Data,
442    ACPI_OPERAND_OBJECT     *ReturnObject,
443    UINT32                  ExpectedCount,
444    UINT32                  SortIndex,
445    UINT8                   SortDirection,
446    char                    *SortKeyName)
447{
448    UINT32                  OuterElementCount;
449    ACPI_OPERAND_OBJECT     **OuterElements;
450    ACPI_OPERAND_OBJECT     **Elements;
451    ACPI_OPERAND_OBJECT     *ObjDesc;
452    UINT32                  i;
453    UINT32                  PreviousValue;
454    ACPI_STATUS             Status;
455
456
457    /* The top-level object must be a package */
458
459    if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
460    {
461        return (AE_AML_OPERAND_TYPE);
462    }
463
464    /*
465     * Detect any NULL package elements and remove them from the
466     * package.
467     *
468     * TBD: We may want to do this for all predefined names that
469     * return a variable-length package of packages.
470     */
471    Status = AcpiNsRemoveNullElements (ReturnObject);
472    if (Status == AE_NULL_ENTRY)
473    {
474        ACPI_INFO_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
475            "NULL elements removed from package"));
476
477        /* Exit if package is now zero length */
478
479        if (!ReturnObject->Package.Count)
480        {
481            return (AE_NULL_ENTRY);
482        }
483    }
484
485    OuterElements = ReturnObject->Package.Elements;
486    OuterElementCount = ReturnObject->Package.Count;
487    if (!OuterElementCount)
488    {
489        return (AE_AML_PACKAGE_LIMIT);
490    }
491
492    PreviousValue = 0;
493    if (SortDirection == ACPI_SORT_DESCENDING)
494    {
495        PreviousValue = ACPI_UINT32_MAX;
496    }
497
498    /* Examine each subpackage */
499
500    for (i = 0; i < OuterElementCount; i++)
501    {
502        /* Each element of the top-level package must also be a package */
503
504        if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE)
505        {
506            return (AE_AML_OPERAND_TYPE);
507        }
508
509        /* Each sub-package must have the minimum length */
510
511        if ((*OuterElements)->Package.Count < ExpectedCount)
512        {
513            return (AE_AML_PACKAGE_LIMIT);
514        }
515
516        Elements = (*OuterElements)->Package.Elements;
517        ObjDesc = Elements[SortIndex];
518
519        if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
520        {
521            return (AE_AML_OPERAND_TYPE);
522        }
523
524        /*
525         * The list must be sorted in the specified order. If we detect a
526         * discrepancy, issue a warning and sort the entire list
527         */
528        if (((SortDirection == ACPI_SORT_ASCENDING) &&
529                (ObjDesc->Integer.Value < PreviousValue)) ||
530            ((SortDirection == ACPI_SORT_DESCENDING) &&
531                (ObjDesc->Integer.Value > PreviousValue)))
532        {
533            Status = AcpiNsSortList (ReturnObject->Package.Elements,
534                        OuterElementCount, SortIndex, SortDirection);
535            if (ACPI_FAILURE (Status))
536            {
537                return (Status);
538            }
539
540            Data->Flags |= ACPI_OBJECT_REPAIRED;
541
542            ACPI_INFO_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
543                "Repaired unsorted list - now sorted by %s", SortKeyName));
544            return (AE_OK);
545        }
546
547        PreviousValue = (UINT32) ObjDesc->Integer.Value;
548        OuterElements++;
549    }
550
551    return (AE_OK);
552}
553
554
555/******************************************************************************
556 *
557 * FUNCTION:    AcpiNsRemoveNullElements
558 *
559 * PARAMETERS:  ObjDesc             - A Package object
560 *
561 * RETURN:      Status. AE_NULL_ENTRY means that one or more elements were
562 *              removed.
563 *
564 * DESCRIPTION: Remove all NULL package elements and update the package count.
565 *
566 *****************************************************************************/
567
568static ACPI_STATUS
569AcpiNsRemoveNullElements (
570    ACPI_OPERAND_OBJECT     *ObjDesc)
571{
572    ACPI_OPERAND_OBJECT     **Source;
573    ACPI_OPERAND_OBJECT     **Dest;
574    ACPI_STATUS             Status = AE_OK;
575    UINT32                  Count;
576    UINT32                  NewCount;
577    UINT32                  i;
578
579
580    Count = ObjDesc->Package.Count;
581    NewCount = Count;
582
583    Source = ObjDesc->Package.Elements;
584    Dest = Source;
585
586    /* Examine all elements of the package object */
587
588    for (i = 0; i < Count; i++)
589    {
590        if (!*Source)
591        {
592            Status = AE_NULL_ENTRY;
593            NewCount--;
594        }
595        else
596        {
597            *Dest = *Source;
598            Dest++;
599        }
600        Source++;
601    }
602
603    if (Status == AE_NULL_ENTRY)
604    {
605        /* NULL terminate list and update the package count */
606
607        *Dest = NULL;
608        ObjDesc->Package.Count = NewCount;
609    }
610
611    return (Status);
612}
613
614
615/******************************************************************************
616 *
617 * FUNCTION:    AcpiNsSortList
618 *
619 * PARAMETERS:  Elements            - Package object element list
620 *              Count               - Element count for above
621 *              Index               - Sort by which package element
622 *              SortDirection       - Ascending or Descending sort
623 *
624 * RETURN:      Status
625 *
626 * DESCRIPTION: Sort the objects that are in a package element list.
627 *
628 * NOTE: Assumes that all NULL elements have been removed from the package.
629 *
630 *****************************************************************************/
631
632static ACPI_STATUS
633AcpiNsSortList (
634    ACPI_OPERAND_OBJECT     **Elements,
635    UINT32                  Count,
636    UINT32                  Index,
637    UINT8                   SortDirection)
638{
639    ACPI_OPERAND_OBJECT     *ObjDesc1;
640    ACPI_OPERAND_OBJECT     *ObjDesc2;
641    ACPI_OPERAND_OBJECT     *TempObj;
642    UINT32                  i;
643    UINT32                  j;
644
645
646    /* Simple bubble sort */
647
648    for (i = 1; i < Count; i++)
649    {
650        for (j = (Count - 1); j >= i; j--)
651        {
652            ObjDesc1 = Elements[j-1]->Package.Elements[Index];
653            ObjDesc2 = Elements[j]->Package.Elements[Index];
654
655            if (((SortDirection == ACPI_SORT_ASCENDING) &&
656                    (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) ||
657
658                ((SortDirection == ACPI_SORT_DESCENDING) &&
659                    (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value)))
660            {
661                TempObj = Elements[j-1];
662                Elements[j-1] = Elements[j];
663                Elements[j] = TempObj;
664            }
665        }
666    }
667
668    return (AE_OK);
669}
670