1272343Sngie/******************************************************************************
2272343Sngie *
3272343Sngie * Module Name: nsrepair2 - Repair for objects returned by specific
4272343Sngie *                          predefined methods
5272343Sngie *
6272343Sngie *****************************************************************************/
7272343Sngie
8272343Sngie/******************************************************************************
9272343Sngie *
10272343Sngie * 1. Copyright Notice
11272343Sngie *
12272343Sngie * Some or all of this work - Copyright (c) 1999 - 2016, Intel Corp.
13272343Sngie * All rights reserved.
14272343Sngie *
15272343Sngie * 2. License
16272343Sngie *
17272343Sngie * 2.1. This is your license from Intel Corp. under its intellectual property
18272343Sngie * rights. You may have additional license terms from the party that provided
19272343Sngie * you this software, covering your right to use that party's intellectual
20272343Sngie * property rights.
21272343Sngie *
22272343Sngie * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23272343Sngie * copy of the source code appearing in this file ("Covered Code") an
24272343Sngie * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25272343Sngie * base code distributed originally by Intel ("Original Intel Code") to copy,
26272343Sngie * make derivatives, distribute, use and display any portion of the Covered
27272343Sngie * Code in any form, with the right to sublicense such rights; and
28272343Sngie *
29272343Sngie * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30272343Sngie * license (with the right to sublicense), under only those claims of Intel
31272343Sngie * patents that are infringed by the Original Intel Code, to make, use, sell,
32272343Sngie * offer to sell, and import the Covered Code and derivative works thereof
33272343Sngie * solely to the minimum extent necessary to exercise the above copyright
34272343Sngie * license, and in no event shall the patent license extend to any additions
35272343Sngie * to or modifications of the Original Intel Code. No other license or right
36272343Sngie * is granted directly or by implication, estoppel or otherwise;
37272343Sngie *
38272343Sngie * The above copyright and patent license is granted only if the following
39272343Sngie * conditions are met:
40272343Sngie *
41272343Sngie * 3. Conditions
42272343Sngie *
43272343Sngie * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44272343Sngie * Redistribution of source code of any substantial portion of the Covered
45272343Sngie * Code or modification with rights to further distribute source must include
46272343Sngie * the above Copyright Notice, the above License, this list of Conditions,
47272343Sngie * and the following Disclaimer and Export Compliance provision. In addition,
48272343Sngie * Licensee must cause all Covered Code to which Licensee contributes to
49272343Sngie * contain a file documenting the changes Licensee made to create that Covered
50272343Sngie * Code and the date of any change. Licensee must include in that file the
51272343Sngie * documentation of any changes made by any predecessor Licensee. Licensee
52272343Sngie * must include a prominent statement that the modification is derived,
53272343Sngie * directly or indirectly, from Original Intel Code.
54272343Sngie *
55272343Sngie * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56272343Sngie * Redistribution of source code of any substantial portion of the Covered
57272343Sngie * Code or modification without rights to further distribute source must
58272343Sngie * include the following Disclaimer and Export Compliance provision in the
59272343Sngie * documentation and/or other materials provided with distribution. In
60272343Sngie * addition, Licensee may not authorize further sublicense of source of any
61272343Sngie * portion of the Covered Code, and must include terms to the effect that the
62272343Sngie * license from Licensee to its licensee is limited to the intellectual
63272343Sngie * property embodied in the software Licensee provides to its licensee, and
64272343Sngie * not to intellectual property embodied in modifications its licensee may
65272343Sngie * make.
66272343Sngie *
67272343Sngie * 3.3. Redistribution of Executable. Redistribution in executable form of any
68272343Sngie * substantial portion of the Covered Code or modification must reproduce the
69272343Sngie * above Copyright Notice, and the following Disclaimer and Export Compliance
70272343Sngie * provision in the documentation and/or other materials provided with the
71272343Sngie * distribution.
72272343Sngie *
73272343Sngie * 3.4. Intel retains all right, title, and interest in and to the Original
74272343Sngie * Intel Code.
75272343Sngie *
76272343Sngie * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77272343Sngie * Intel shall be used in advertising or otherwise to promote the sale, use or
78272343Sngie * other dealings in products derived from or relating to the Covered Code
79272343Sngie * without prior written authorization from Intel.
80272343Sngie *
81272343Sngie * 4. Disclaimer and Export Compliance
82272343Sngie *
83272343Sngie * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84272343Sngie * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85272343Sngie * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
86272343Sngie * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
87272343Sngie * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
88272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89272343Sngie * PARTICULAR PURPOSE.
90272343Sngie *
91272343Sngie * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92272343Sngie * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93272343Sngie * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94272343Sngie * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95272343Sngie * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96272343Sngie * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
97272343Sngie * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98272343Sngie * LIMITED REMEDY.
99272343Sngie *
100272343Sngie * 4.3. Licensee shall not export, either directly or indirectly, any of this
101272343Sngie * software or system incorporating such software without first obtaining any
102272343Sngie * required license or other approval from the U. S. Department of Commerce or
103272343Sngie * any other agency or department of the United States Government. In the
104272343Sngie * event Licensee exports any such software from the United States or
105272343Sngie * re-exports any such software from a foreign destination, Licensee shall
106272343Sngie * ensure that the distribution and export/re-export of the software is in
107272343Sngie * compliance with all laws, regulations, orders, or other restrictions of the
108272343Sngie * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109272343Sngie * any of its subsidiaries will export/re-export any technical data, process,
110272343Sngie * software, or service, directly or indirectly, to any country for which the
111272343Sngie * United States government or any agency thereof requires an export license,
112272343Sngie * other governmental approval, or letter of assurance, without first obtaining
113272343Sngie * such license, approval or letter.
114272343Sngie *
115272343Sngie *****************************************************************************/
116272343Sngie
117272343Sngie#include "acpi.h"
118272343Sngie#include "accommon.h"
119272343Sngie#include "acnamesp.h"
120272343Sngie
121272343Sngie#define _COMPONENT          ACPI_NAMESPACE
122272343Sngie        ACPI_MODULE_NAME    ("nsrepair2")
123272343Sngie
124272343Sngie
125272343Sngie/*
126272343Sngie * Information structure and handler for ACPI predefined names that can
127272343Sngie * be repaired on a per-name basis.
128272343Sngie */
129272343Sngietypedef
130272343SngieACPI_STATUS (*ACPI_REPAIR_FUNCTION) (
131272343Sngie    ACPI_EVALUATE_INFO      *Info,
132272343Sngie    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
133272343Sngie
134272343Sngietypedef struct acpi_repair_info
135272343Sngie{
136272343Sngie    char                    Name[ACPI_NAME_SIZE];
137272343Sngie    ACPI_REPAIR_FUNCTION    RepairFunction;
138272343Sngie
139272343Sngie} ACPI_REPAIR_INFO;
140272343Sngie
141272343Sngie
142272343Sngie/* Local prototypes */
143272343Sngie
144272343Sngiestatic const ACPI_REPAIR_INFO *
145272343SngieAcpiNsMatchComplexRepair (
146272343Sngie    ACPI_NAMESPACE_NODE     *Node);
147272343Sngie
148272343Sngiestatic ACPI_STATUS
149272343SngieAcpiNsRepair_ALR (
150272343Sngie    ACPI_EVALUATE_INFO      *Info,
151272343Sngie    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
152272343Sngie
153272343Sngiestatic ACPI_STATUS
154272343SngieAcpiNsRepair_CID (
155272343Sngie    ACPI_EVALUATE_INFO      *Info,
156272343Sngie    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
157272343Sngie
158272343Sngiestatic ACPI_STATUS
159272343SngieAcpiNsRepair_CST (
160272343Sngie    ACPI_EVALUATE_INFO      *Info,
161272343Sngie    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
162272343Sngie
163272343Sngiestatic ACPI_STATUS
164272343SngieAcpiNsRepair_FDE (
165272343Sngie    ACPI_EVALUATE_INFO      *Info,
166272343Sngie    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
167272343Sngie
168272343Sngiestatic ACPI_STATUS
169272343SngieAcpiNsRepair_HID (
170272343Sngie    ACPI_EVALUATE_INFO      *Info,
171272343Sngie    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
172272343Sngie
173272343Sngiestatic ACPI_STATUS
174272343SngieAcpiNsRepair_PRT (
175272343Sngie    ACPI_EVALUATE_INFO      *Info,
176272343Sngie    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
177272343Sngie
178272343Sngiestatic ACPI_STATUS
179272343SngieAcpiNsRepair_PSS (
180272343Sngie    ACPI_EVALUATE_INFO      *Info,
181272343Sngie    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
182272343Sngie
183272343Sngiestatic ACPI_STATUS
184272343SngieAcpiNsRepair_TSS (
185272343Sngie    ACPI_EVALUATE_INFO      *Info,
186272343Sngie    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
187272343Sngie
188272343Sngiestatic ACPI_STATUS
189272343SngieAcpiNsCheckSortedList (
190272343Sngie    ACPI_EVALUATE_INFO      *Info,
191272343Sngie    ACPI_OPERAND_OBJECT     *ReturnObject,
192272343Sngie    UINT32                  StartIndex,
193272343Sngie    UINT32                  ExpectedCount,
194272343Sngie    UINT32                  SortIndex,
195272343Sngie    UINT8                   SortDirection,
196272343Sngie    char                    *SortKeyName);
197272343Sngie
198272343Sngie/* Values for SortDirection above */
199272343Sngie
200272343Sngie#define ACPI_SORT_ASCENDING     0
201272343Sngie#define ACPI_SORT_DESCENDING    1
202272343Sngie
203272343Sngiestatic void
204272343SngieAcpiNsRemoveElement (
205272343Sngie    ACPI_OPERAND_OBJECT     *ObjDesc,
206272343Sngie    UINT32                  Index);
207272343Sngie
208272343Sngiestatic void
209272343SngieAcpiNsSortList (
210272343Sngie    ACPI_OPERAND_OBJECT     **Elements,
211272343Sngie    UINT32                  Count,
212272343Sngie    UINT32                  Index,
213272343Sngie    UINT8                   SortDirection);
214272343Sngie
215272343Sngie
216272343Sngie/*
217272343Sngie * This table contains the names of the predefined methods for which we can
218272343Sngie * perform more complex repairs.
219272343Sngie *
220272343Sngie * As necessary:
221272343Sngie *
222272343Sngie * _ALR: Sort the list ascending by AmbientIlluminance
223272343Sngie * _CID: Strings: uppercase all, remove any leading asterisk
224272343Sngie * _CST: Sort the list ascending by C state type
225272343Sngie * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
226272343Sngie * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
227272343Sngie * _HID: Strings: uppercase all, remove any leading asterisk
228272343Sngie * _PRT: Fix reversed SourceName and SourceIndex
229272343Sngie * _PSS: Sort the list descending by Power
230272343Sngie * _TSS: Sort the list descending by Power
231272343Sngie *
232272343Sngie * Names that must be packages, but cannot be sorted:
233272343Sngie *
234272343Sngie * _BCL: Values are tied to the Package index where they appear, and cannot
235272343Sngie * be moved or sorted. These index values are used for _BQC and _BCM.
236272343Sngie * However, we can fix the case where a buffer is returned, by converting
237272343Sngie * it to a Package of integers.
238272343Sngie */
239272343Sngiestatic const ACPI_REPAIR_INFO       AcpiNsRepairableNames[] =
240272343Sngie{
241272343Sngie    {"_ALR", AcpiNsRepair_ALR},
242272343Sngie    {"_CID", AcpiNsRepair_CID},
243272343Sngie    {"_CST", AcpiNsRepair_CST},
244272343Sngie    {"_FDE", AcpiNsRepair_FDE},
245272343Sngie    {"_GTM", AcpiNsRepair_FDE},     /* _GTM has same repair as _FDE */
246272343Sngie    {"_HID", AcpiNsRepair_HID},
247272343Sngie    {"_PRT", AcpiNsRepair_PRT},
248272343Sngie    {"_PSS", AcpiNsRepair_PSS},
249272343Sngie    {"_TSS", AcpiNsRepair_TSS},
250272343Sngie    {{0,0,0,0}, NULL}               /* Table terminator */
251272343Sngie};
252272343Sngie
253272343Sngie
254272343Sngie#define ACPI_FDE_FIELD_COUNT        5
255272343Sngie#define ACPI_FDE_BYTE_BUFFER_SIZE   5
256272343Sngie#define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * sizeof (UINT32))
257272343Sngie
258272343Sngie
259272343Sngie/******************************************************************************
260272343Sngie *
261272343Sngie * FUNCTION:    AcpiNsComplexRepairs
262 *
263 * PARAMETERS:  Info                - Method execution information block
264 *              Node                - Namespace node for the method/object
265 *              ValidateStatus      - Original status of earlier validation
266 *              ReturnObjectPtr     - Pointer to the object returned from the
267 *                                    evaluation of a method or object
268 *
269 * RETURN:      Status. AE_OK if repair was successful. If name is not
270 *              matched, ValidateStatus is returned.
271 *
272 * DESCRIPTION: Attempt to repair/convert a return object of a type that was
273 *              not expected.
274 *
275 *****************************************************************************/
276
277ACPI_STATUS
278AcpiNsComplexRepairs (
279    ACPI_EVALUATE_INFO      *Info,
280    ACPI_NAMESPACE_NODE     *Node,
281    ACPI_STATUS             ValidateStatus,
282    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
283{
284    const ACPI_REPAIR_INFO  *Predefined;
285    ACPI_STATUS             Status;
286
287
288    /* Check if this name is in the list of repairable names */
289
290    Predefined = AcpiNsMatchComplexRepair (Node);
291    if (!Predefined)
292    {
293        return (ValidateStatus);
294    }
295
296    Status = Predefined->RepairFunction (Info, ReturnObjectPtr);
297    return (Status);
298}
299
300
301/******************************************************************************
302 *
303 * FUNCTION:    AcpiNsMatchComplexRepair
304 *
305 * PARAMETERS:  Node                - Namespace node for the method/object
306 *
307 * RETURN:      Pointer to entry in repair table. NULL indicates not found.
308 *
309 * DESCRIPTION: Check an object name against the repairable object list.
310 *
311 *****************************************************************************/
312
313static const ACPI_REPAIR_INFO *
314AcpiNsMatchComplexRepair (
315    ACPI_NAMESPACE_NODE     *Node)
316{
317    const ACPI_REPAIR_INFO  *ThisName;
318
319
320    /* Search info table for a repairable predefined method/object name */
321
322    ThisName = AcpiNsRepairableNames;
323    while (ThisName->RepairFunction)
324    {
325        if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name))
326        {
327            return (ThisName);
328        }
329
330        ThisName++;
331    }
332
333    return (NULL); /* Not found */
334}
335
336
337/******************************************************************************
338 *
339 * FUNCTION:    AcpiNsRepair_ALR
340 *
341 * PARAMETERS:  Info                - Method execution information block
342 *              ReturnObjectPtr     - Pointer to the object returned from the
343 *                                    evaluation of a method or object
344 *
345 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
346 *
347 * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
348 *              ascending by the ambient illuminance values.
349 *
350 *****************************************************************************/
351
352static ACPI_STATUS
353AcpiNsRepair_ALR (
354    ACPI_EVALUATE_INFO      *Info,
355    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
356{
357    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
358    ACPI_STATUS             Status;
359
360
361    Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 2, 1,
362        ACPI_SORT_ASCENDING, "AmbientIlluminance");
363
364    return (Status);
365}
366
367
368/******************************************************************************
369 *
370 * FUNCTION:    AcpiNsRepair_FDE
371 *
372 * PARAMETERS:  Info                - Method execution information block
373 *              ReturnObjectPtr     - Pointer to the object returned from the
374 *                                    evaluation of a method or object
375 *
376 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
377 *
378 * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return
379 *              value is a Buffer of 5 DWORDs. This function repairs a common
380 *              problem where the return value is a Buffer of BYTEs, not
381 *              DWORDs.
382 *
383 *****************************************************************************/
384
385static ACPI_STATUS
386AcpiNsRepair_FDE (
387    ACPI_EVALUATE_INFO      *Info,
388    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
389{
390    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
391    ACPI_OPERAND_OBJECT     *BufferObject;
392    UINT8                   *ByteBuffer;
393    UINT32                  *DwordBuffer;
394    UINT32                  i;
395
396
397    ACPI_FUNCTION_NAME (NsRepair_FDE);
398
399
400    switch (ReturnObject->Common.Type)
401    {
402    case ACPI_TYPE_BUFFER:
403
404        /* This is the expected type. Length should be (at least) 5 DWORDs */
405
406        if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE)
407        {
408            return (AE_OK);
409        }
410
411        /* We can only repair if we have exactly 5 BYTEs */
412
413        if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE)
414        {
415            ACPI_WARN_PREDEFINED ((AE_INFO,
416                Info->FullPathname, Info->NodeFlags,
417                "Incorrect return buffer length %u, expected %u",
418                ReturnObject->Buffer.Length, ACPI_FDE_DWORD_BUFFER_SIZE));
419
420            return (AE_AML_OPERAND_TYPE);
421        }
422
423        /* Create the new (larger) buffer object */
424
425        BufferObject = AcpiUtCreateBufferObject (
426            ACPI_FDE_DWORD_BUFFER_SIZE);
427        if (!BufferObject)
428        {
429            return (AE_NO_MEMORY);
430        }
431
432        /* Expand each byte to a DWORD */
433
434        ByteBuffer = ReturnObject->Buffer.Pointer;
435        DwordBuffer = ACPI_CAST_PTR (UINT32,
436            BufferObject->Buffer.Pointer);
437
438        for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++)
439        {
440            *DwordBuffer = (UINT32) *ByteBuffer;
441            DwordBuffer++;
442            ByteBuffer++;
443        }
444
445        ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
446            "%s Expanded Byte Buffer to expected DWord Buffer\n",
447            Info->FullPathname));
448        break;
449
450    default:
451
452        return (AE_AML_OPERAND_TYPE);
453    }
454
455    /* Delete the original return object, return the new buffer object */
456
457    AcpiUtRemoveReference (ReturnObject);
458    *ReturnObjectPtr = BufferObject;
459
460    Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
461    return (AE_OK);
462}
463
464
465/******************************************************************************
466 *
467 * FUNCTION:    AcpiNsRepair_CID
468 *
469 * PARAMETERS:  Info                - Method execution information block
470 *              ReturnObjectPtr     - Pointer to the object returned from the
471 *                                    evaluation of a method or object
472 *
473 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
474 *
475 * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
476 *              letters are uppercase and that there is no leading asterisk.
477 *              If a Package, ensure same for all string elements.
478 *
479 *****************************************************************************/
480
481static ACPI_STATUS
482AcpiNsRepair_CID (
483    ACPI_EVALUATE_INFO      *Info,
484    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
485{
486    ACPI_STATUS             Status;
487    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
488    ACPI_OPERAND_OBJECT     **ElementPtr;
489    ACPI_OPERAND_OBJECT     *OriginalElement;
490    UINT16                  OriginalRefCount;
491    UINT32                  i;
492
493
494    /* Check for _CID as a simple string */
495
496    if (ReturnObject->Common.Type == ACPI_TYPE_STRING)
497    {
498        Status = AcpiNsRepair_HID (Info, ReturnObjectPtr);
499        return (Status);
500    }
501
502    /* Exit if not a Package */
503
504    if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
505    {
506        return (AE_OK);
507    }
508
509    /* Examine each element of the _CID package */
510
511    ElementPtr = ReturnObject->Package.Elements;
512    for (i = 0; i < ReturnObject->Package.Count; i++)
513    {
514        OriginalElement = *ElementPtr;
515        OriginalRefCount = OriginalElement->Common.ReferenceCount;
516
517        Status = AcpiNsRepair_HID (Info, ElementPtr);
518        if (ACPI_FAILURE (Status))
519        {
520            return (Status);
521        }
522
523        /* Take care with reference counts */
524
525        if (OriginalElement != *ElementPtr)
526        {
527            /* Element was replaced */
528
529            (*ElementPtr)->Common.ReferenceCount =
530                OriginalRefCount;
531
532            AcpiUtRemoveReference (OriginalElement);
533        }
534
535        ElementPtr++;
536    }
537
538    return (AE_OK);
539}
540
541
542/******************************************************************************
543 *
544 * FUNCTION:    AcpiNsRepair_CST
545 *
546 * PARAMETERS:  Info                - Method execution information block
547 *              ReturnObjectPtr     - Pointer to the object returned from the
548 *                                    evaluation of a method or object
549 *
550 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
551 *
552 * DESCRIPTION: Repair for the _CST object:
553 *              1. Sort the list ascending by C state type
554 *              2. Ensure type cannot be zero
555 *              3. A subpackage count of zero means _CST is meaningless
556 *              4. Count must match the number of C state subpackages
557 *
558 *****************************************************************************/
559
560static ACPI_STATUS
561AcpiNsRepair_CST (
562    ACPI_EVALUATE_INFO      *Info,
563    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
564{
565    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
566    ACPI_OPERAND_OBJECT     **OuterElements;
567    UINT32                  OuterElementCount;
568    ACPI_OPERAND_OBJECT     *ObjDesc;
569    ACPI_STATUS             Status;
570    BOOLEAN                 Removing;
571    UINT32                  i;
572
573
574    ACPI_FUNCTION_NAME (NsRepair_CST);
575
576
577    /*
578     * Check if the C-state type values are proportional.
579     */
580    OuterElementCount = ReturnObject->Package.Count - 1;
581    i = 0;
582    while (i < OuterElementCount)
583    {
584        OuterElements = &ReturnObject->Package.Elements[i + 1];
585        Removing = FALSE;
586
587        if ((*OuterElements)->Package.Count == 0)
588        {
589            ACPI_WARN_PREDEFINED ((AE_INFO,
590                Info->FullPathname, Info->NodeFlags,
591                "SubPackage[%u] - removing entry due to zero count", i));
592            Removing = TRUE;
593            goto RemoveElement;
594        }
595
596        ObjDesc = (*OuterElements)->Package.Elements[1]; /* Index1 = Type */
597        if ((UINT32) ObjDesc->Integer.Value == 0)
598        {
599            ACPI_WARN_PREDEFINED ((AE_INFO,
600                Info->FullPathname, Info->NodeFlags,
601                "SubPackage[%u] - removing entry due to invalid Type(0)", i));
602            Removing = TRUE;
603        }
604
605RemoveElement:
606        if (Removing)
607        {
608            AcpiNsRemoveElement (ReturnObject, i + 1);
609            OuterElementCount--;
610        }
611        else
612        {
613            i++;
614        }
615    }
616
617    /* Update top-level package count, Type "Integer" checked elsewhere */
618
619    ObjDesc = ReturnObject->Package.Elements[0];
620    ObjDesc->Integer.Value = OuterElementCount;
621
622    /*
623     * Entries (subpackages) in the _CST Package must be sorted by the
624     * C-state type, in ascending order.
625     */
626    Status = AcpiNsCheckSortedList (Info, ReturnObject, 1, 4, 1,
627        ACPI_SORT_ASCENDING, "C-State Type");
628    if (ACPI_FAILURE (Status))
629    {
630        return (Status);
631    }
632
633    return (AE_OK);
634}
635
636
637/******************************************************************************
638 *
639 * FUNCTION:    AcpiNsRepair_HID
640 *
641 * PARAMETERS:  Info                - Method execution information block
642 *              ReturnObjectPtr     - Pointer to the object returned from the
643 *                                    evaluation of a method or object
644 *
645 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
646 *
647 * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
648 *              letters are uppercase and that there is no leading asterisk.
649 *
650 *****************************************************************************/
651
652static ACPI_STATUS
653AcpiNsRepair_HID (
654    ACPI_EVALUATE_INFO      *Info,
655    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
656{
657    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
658    ACPI_OPERAND_OBJECT     *NewString;
659    char                    *Source;
660    char                    *Dest;
661
662
663    ACPI_FUNCTION_NAME (NsRepair_HID);
664
665
666    /* We only care about string _HID objects (not integers) */
667
668    if (ReturnObject->Common.Type != ACPI_TYPE_STRING)
669    {
670        return (AE_OK);
671    }
672
673    if (ReturnObject->String.Length == 0)
674    {
675        ACPI_WARN_PREDEFINED ((AE_INFO,
676            Info->FullPathname, Info->NodeFlags,
677            "Invalid zero-length _HID or _CID string"));
678
679        /* Return AE_OK anyway, let driver handle it */
680
681        Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
682        return (AE_OK);
683    }
684
685    /* It is simplest to always create a new string object */
686
687    NewString = AcpiUtCreateStringObject (ReturnObject->String.Length);
688    if (!NewString)
689    {
690        return (AE_NO_MEMORY);
691    }
692
693    /*
694     * Remove a leading asterisk if present. For some unknown reason, there
695     * are many machines in the field that contains IDs like this.
696     *
697     * Examples: "*PNP0C03", "*ACPI0003"
698     */
699    Source = ReturnObject->String.Pointer;
700    if (*Source == '*')
701    {
702        Source++;
703        NewString->String.Length--;
704
705        ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
706            "%s: Removed invalid leading asterisk\n", Info->FullPathname));
707    }
708
709    /*
710     * Copy and uppercase the string. From the ACPI 5.0 specification:
711     *
712     * A valid PNP ID must be of the form "AAA####" where A is an uppercase
713     * letter and # is a hex digit. A valid ACPI ID must be of the form
714     * "NNNN####" where N is an uppercase letter or decimal digit, and
715     * # is a hex digit.
716     */
717    for (Dest = NewString->String.Pointer; *Source; Dest++, Source++)
718    {
719        *Dest = (char) toupper ((int) *Source);
720    }
721
722    AcpiUtRemoveReference (ReturnObject);
723    *ReturnObjectPtr = NewString;
724    return (AE_OK);
725}
726
727
728/******************************************************************************
729 *
730 * FUNCTION:    AcpiNsRepair_PRT
731 *
732 * PARAMETERS:  Info                - Method execution information block
733 *              ReturnObjectPtr     - Pointer to the object returned from the
734 *                                    evaluation of a method or object
735 *
736 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
737 *
738 * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed
739 *              SourceName and SourceIndex field, a common BIOS bug.
740 *
741 *****************************************************************************/
742
743static ACPI_STATUS
744AcpiNsRepair_PRT (
745    ACPI_EVALUATE_INFO      *Info,
746    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
747{
748    ACPI_OPERAND_OBJECT     *PackageObject = *ReturnObjectPtr;
749    ACPI_OPERAND_OBJECT     **TopObjectList;
750    ACPI_OPERAND_OBJECT     **SubObjectList;
751    ACPI_OPERAND_OBJECT     *ObjDesc;
752    ACPI_OPERAND_OBJECT     *SubPackage;
753    UINT32                  ElementCount;
754    UINT32                  Index;
755
756
757    /* Each element in the _PRT package is a subpackage */
758
759    TopObjectList = PackageObject->Package.Elements;
760    ElementCount = PackageObject->Package.Count;
761
762    /* Examine each subpackage */
763
764    for (Index = 0; Index < ElementCount; Index++, TopObjectList++)
765    {
766        SubPackage = *TopObjectList;
767        SubObjectList = SubPackage->Package.Elements;
768
769        /* Check for minimum required element count */
770
771        if (SubPackage->Package.Count < 4)
772        {
773            continue;
774        }
775
776        /*
777         * If the BIOS has erroneously reversed the _PRT SourceName (index 2)
778         * and the SourceIndex (index 3), fix it. _PRT is important enough to
779         * workaround this BIOS error. This also provides compatibility with
780         * other ACPI implementations.
781         */
782        ObjDesc = SubObjectList[3];
783        if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
784        {
785            SubObjectList[3] = SubObjectList[2];
786            SubObjectList[2] = ObjDesc;
787            Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
788
789            ACPI_WARN_PREDEFINED ((AE_INFO,
790                Info->FullPathname, Info->NodeFlags,
791                "PRT[%X]: Fixed reversed SourceName and SourceIndex",
792                Index));
793        }
794    }
795
796    return (AE_OK);
797}
798
799
800/******************************************************************************
801 *
802 * FUNCTION:    AcpiNsRepair_PSS
803 *
804 * PARAMETERS:  Info                - Method execution information block
805 *              ReturnObjectPtr     - Pointer to the object returned from the
806 *                                    evaluation of a method or object
807 *
808 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
809 *
810 * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
811 *              by the CPU frequencies. Check that the power dissipation values
812 *              are all proportional to CPU frequency (i.e., sorting by
813 *              frequency should be the same as sorting by power.)
814 *
815 *****************************************************************************/
816
817static ACPI_STATUS
818AcpiNsRepair_PSS (
819    ACPI_EVALUATE_INFO      *Info,
820    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
821{
822    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
823    ACPI_OPERAND_OBJECT     **OuterElements;
824    UINT32                  OuterElementCount;
825    ACPI_OPERAND_OBJECT     **Elements;
826    ACPI_OPERAND_OBJECT     *ObjDesc;
827    UINT32                  PreviousValue;
828    ACPI_STATUS             Status;
829    UINT32                  i;
830
831
832    /*
833     * Entries (subpackages) in the _PSS Package must be sorted by power
834     * dissipation, in descending order. If it appears that the list is
835     * incorrectly sorted, sort it. We sort by CpuFrequency, since this
836     * should be proportional to the power.
837     */
838    Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 6, 0,
839        ACPI_SORT_DESCENDING, "CpuFrequency");
840    if (ACPI_FAILURE (Status))
841    {
842        return (Status);
843    }
844
845    /*
846     * We now know the list is correctly sorted by CPU frequency. Check if
847     * the power dissipation values are proportional.
848     */
849    PreviousValue = ACPI_UINT32_MAX;
850    OuterElements = ReturnObject->Package.Elements;
851    OuterElementCount = ReturnObject->Package.Count;
852
853    for (i = 0; i < OuterElementCount; i++)
854    {
855        Elements = (*OuterElements)->Package.Elements;
856        ObjDesc = Elements[1]; /* Index1 = PowerDissipation */
857
858        if ((UINT32) ObjDesc->Integer.Value > PreviousValue)
859        {
860            ACPI_WARN_PREDEFINED ((AE_INFO,
861                Info->FullPathname, Info->NodeFlags,
862                "SubPackage[%u,%u] - suspicious power dissipation values",
863                i-1, i));
864        }
865
866        PreviousValue = (UINT32) ObjDesc->Integer.Value;
867        OuterElements++;
868    }
869
870    return (AE_OK);
871}
872
873
874/******************************************************************************
875 *
876 * FUNCTION:    AcpiNsRepair_TSS
877 *
878 * PARAMETERS:  Info                - Method execution information block
879 *              ReturnObjectPtr     - Pointer to the object returned from the
880 *                                    evaluation of a method or object
881 *
882 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
883 *
884 * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
885 *              descending by the power dissipation values.
886 *
887 *****************************************************************************/
888
889static ACPI_STATUS
890AcpiNsRepair_TSS (
891    ACPI_EVALUATE_INFO      *Info,
892    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
893{
894    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
895    ACPI_STATUS             Status;
896    ACPI_NAMESPACE_NODE     *Node;
897
898
899    /*
900     * We can only sort the _TSS return package if there is no _PSS in the
901     * same scope. This is because if _PSS is present, the ACPI specification
902     * dictates that the _TSS Power Dissipation field is to be ignored, and
903     * therefore some BIOSs leave garbage values in the _TSS Power field(s).
904     * In this case, it is best to just return the _TSS package as-is.
905     * (May, 2011)
906     */
907    Status = AcpiNsGetNode (Info->Node, "^_PSS",
908        ACPI_NS_NO_UPSEARCH, &Node);
909    if (ACPI_SUCCESS (Status))
910    {
911        return (AE_OK);
912    }
913
914    Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 5, 1,
915        ACPI_SORT_DESCENDING, "PowerDissipation");
916
917    return (Status);
918}
919
920
921/******************************************************************************
922 *
923 * FUNCTION:    AcpiNsCheckSortedList
924 *
925 * PARAMETERS:  Info                - Method execution information block
926 *              ReturnObject        - Pointer to the top-level returned object
927 *              StartIndex          - Index of the first subpackage
928 *              ExpectedCount       - Minimum length of each subpackage
929 *              SortIndex           - Subpackage entry to sort on
930 *              SortDirection       - Ascending or descending
931 *              SortKeyName         - Name of the SortIndex field
932 *
933 * RETURN:      Status. AE_OK if the list is valid and is sorted correctly or
934 *              has been repaired by sorting the list.
935 *
936 * DESCRIPTION: Check if the package list is valid and sorted correctly by the
937 *              SortIndex. If not, then sort the list.
938 *
939 *****************************************************************************/
940
941static ACPI_STATUS
942AcpiNsCheckSortedList (
943    ACPI_EVALUATE_INFO      *Info,
944    ACPI_OPERAND_OBJECT     *ReturnObject,
945    UINT32                  StartIndex,
946    UINT32                  ExpectedCount,
947    UINT32                  SortIndex,
948    UINT8                   SortDirection,
949    char                    *SortKeyName)
950{
951    UINT32                  OuterElementCount;
952    ACPI_OPERAND_OBJECT     **OuterElements;
953    ACPI_OPERAND_OBJECT     **Elements;
954    ACPI_OPERAND_OBJECT     *ObjDesc;
955    UINT32                  i;
956    UINT32                  PreviousValue;
957
958
959    ACPI_FUNCTION_NAME (NsCheckSortedList);
960
961
962    /* The top-level object must be a package */
963
964    if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
965    {
966        return (AE_AML_OPERAND_TYPE);
967    }
968
969    /*
970     * NOTE: assumes list of subpackages contains no NULL elements.
971     * Any NULL elements should have been removed by earlier call
972     * to AcpiNsRemoveNullElements.
973     */
974    OuterElementCount = ReturnObject->Package.Count;
975    if (!OuterElementCount || StartIndex >= OuterElementCount)
976    {
977        return (AE_AML_PACKAGE_LIMIT);
978    }
979
980    OuterElements = &ReturnObject->Package.Elements[StartIndex];
981    OuterElementCount -= StartIndex;
982
983    PreviousValue = 0;
984    if (SortDirection == ACPI_SORT_DESCENDING)
985    {
986        PreviousValue = ACPI_UINT32_MAX;
987    }
988
989    /* Examine each subpackage */
990
991    for (i = 0; i < OuterElementCount; i++)
992    {
993        /* Each element of the top-level package must also be a package */
994
995        if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE)
996        {
997            return (AE_AML_OPERAND_TYPE);
998        }
999
1000        /* Each subpackage must have the minimum length */
1001
1002        if ((*OuterElements)->Package.Count < ExpectedCount)
1003        {
1004            return (AE_AML_PACKAGE_LIMIT);
1005        }
1006
1007        Elements = (*OuterElements)->Package.Elements;
1008        ObjDesc = Elements[SortIndex];
1009
1010        if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
1011        {
1012            return (AE_AML_OPERAND_TYPE);
1013        }
1014
1015        /*
1016         * The list must be sorted in the specified order. If we detect a
1017         * discrepancy, sort the entire list.
1018         */
1019        if (((SortDirection == ACPI_SORT_ASCENDING) &&
1020                (ObjDesc->Integer.Value < PreviousValue)) ||
1021            ((SortDirection == ACPI_SORT_DESCENDING) &&
1022                (ObjDesc->Integer.Value > PreviousValue)))
1023        {
1024            AcpiNsSortList (&ReturnObject->Package.Elements[StartIndex],
1025                OuterElementCount, SortIndex, SortDirection);
1026
1027            Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
1028
1029            ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
1030                "%s: Repaired unsorted list - now sorted by %s\n",
1031                Info->FullPathname, SortKeyName));
1032            return (AE_OK);
1033        }
1034
1035        PreviousValue = (UINT32) ObjDesc->Integer.Value;
1036        OuterElements++;
1037    }
1038
1039    return (AE_OK);
1040}
1041
1042
1043/******************************************************************************
1044 *
1045 * FUNCTION:    AcpiNsSortList
1046 *
1047 * PARAMETERS:  Elements            - Package object element list
1048 *              Count               - Element count for above
1049 *              Index               - Sort by which package element
1050 *              SortDirection       - Ascending or Descending sort
1051 *
1052 * RETURN:      None
1053 *
1054 * DESCRIPTION: Sort the objects that are in a package element list.
1055 *
1056 * NOTE: Assumes that all NULL elements have been removed from the package,
1057 *       and that all elements have been verified to be of type Integer.
1058 *
1059 *****************************************************************************/
1060
1061static void
1062AcpiNsSortList (
1063    ACPI_OPERAND_OBJECT     **Elements,
1064    UINT32                  Count,
1065    UINT32                  Index,
1066    UINT8                   SortDirection)
1067{
1068    ACPI_OPERAND_OBJECT     *ObjDesc1;
1069    ACPI_OPERAND_OBJECT     *ObjDesc2;
1070    ACPI_OPERAND_OBJECT     *TempObj;
1071    UINT32                  i;
1072    UINT32                  j;
1073
1074
1075    /* Simple bubble sort */
1076
1077    for (i = 1; i < Count; i++)
1078    {
1079        for (j = (Count - 1); j >= i; j--)
1080        {
1081            ObjDesc1 = Elements[j-1]->Package.Elements[Index];
1082            ObjDesc2 = Elements[j]->Package.Elements[Index];
1083
1084            if (((SortDirection == ACPI_SORT_ASCENDING) &&
1085                    (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) ||
1086
1087                ((SortDirection == ACPI_SORT_DESCENDING) &&
1088                    (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value)))
1089            {
1090                TempObj = Elements[j-1];
1091                Elements[j-1] = Elements[j];
1092                Elements[j] = TempObj;
1093            }
1094        }
1095    }
1096}
1097
1098
1099/******************************************************************************
1100 *
1101 * FUNCTION:    AcpiNsRemoveElement
1102 *
1103 * PARAMETERS:  ObjDesc             - Package object element list
1104 *              Index               - Index of element to remove
1105 *
1106 * RETURN:      None
1107 *
1108 * DESCRIPTION: Remove the requested element of a package and delete it.
1109 *
1110 *****************************************************************************/
1111
1112static void
1113AcpiNsRemoveElement (
1114    ACPI_OPERAND_OBJECT     *ObjDesc,
1115    UINT32                  Index)
1116{
1117    ACPI_OPERAND_OBJECT     **Source;
1118    ACPI_OPERAND_OBJECT     **Dest;
1119    UINT32                  Count;
1120    UINT32                  NewCount;
1121    UINT32                  i;
1122
1123
1124    ACPI_FUNCTION_NAME (NsRemoveElement);
1125
1126
1127    Count = ObjDesc->Package.Count;
1128    NewCount = Count - 1;
1129
1130    Source = ObjDesc->Package.Elements;
1131    Dest = Source;
1132
1133    /* Examine all elements of the package object, remove matched index */
1134
1135    for (i = 0; i < Count; i++)
1136    {
1137        if (i == Index)
1138        {
1139            AcpiUtRemoveReference (*Source); /* Remove one ref for being in pkg */
1140            AcpiUtRemoveReference (*Source);
1141        }
1142        else
1143        {
1144            *Dest = *Source;
1145            Dest++;
1146        }
1147
1148        Source++;
1149    }
1150
1151    /* NULL terminate list and update the package count */
1152
1153    *Dest = NULL;
1154    ObjDesc->Package.Count = NewCount;
1155}
1156