Subversion Repositories Kolibri OS

Rev

Rev 1498 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1498 serge 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
 *
2216 Serge 12
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
1498 serge 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
 */
131
typedef
132
ACPI_STATUS (*ACPI_REPAIR_FUNCTION) (
133
    ACPI_PREDEFINED_DATA    *Data,
134
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
135
 
136
typedef 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
 
146
static const ACPI_REPAIR_INFO *
147
AcpiNsMatchRepairableName (
148
    ACPI_NAMESPACE_NODE     *Node);
149
 
150
static ACPI_STATUS
151
AcpiNsRepair_ALR (
152
    ACPI_PREDEFINED_DATA    *Data,
153
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
154
 
155
static ACPI_STATUS
2216 Serge 156
AcpiNsRepair_CID (
157
    ACPI_PREDEFINED_DATA    *Data,
158
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
159
 
160
static ACPI_STATUS
1498 serge 161
AcpiNsRepair_FDE (
162
    ACPI_PREDEFINED_DATA    *Data,
163
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
164
 
165
static ACPI_STATUS
2216 Serge 166
AcpiNsRepair_HID (
167
    ACPI_PREDEFINED_DATA    *Data,
168
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
169
 
170
static ACPI_STATUS
1498 serge 171
AcpiNsRepair_PSS (
172
    ACPI_PREDEFINED_DATA    *Data,
173
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
174
 
175
static ACPI_STATUS
176
AcpiNsRepair_TSS (
177
    ACPI_PREDEFINED_DATA    *Data,
178
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
179
 
180
static ACPI_STATUS
181
AcpiNsCheckSortedList (
182
    ACPI_PREDEFINED_DATA    *Data,
183
    ACPI_OPERAND_OBJECT     *ReturnObject,
184
    UINT32                  ExpectedCount,
185
    UINT32                  SortIndex,
186
    UINT8                   SortDirection,
187
    char                    *SortKeyName);
188
 
189
static void
190
AcpiNsSortList (
191
    ACPI_OPERAND_OBJECT     **Elements,
192
    UINT32                  Count,
193
    UINT32                  Index,
194
    UINT8                   SortDirection);
195
 
196
/* Values for SortDirection above */
197
 
198
#define ACPI_SORT_ASCENDING     0
199
#define ACPI_SORT_DESCENDING    1
200
 
201
 
202
/*
203
 * This table contains the names of the predefined methods for which we can
204
 * perform more complex repairs.
205
 *
206
 * As necessary:
207
 *
208
 * _ALR: Sort the list ascending by AmbientIlluminance
2216 Serge 209
 * _CID: Strings: uppercase all, remove any leading asterisk
1498 serge 210
 * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
211
 * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
2216 Serge 212
 * _HID: Strings: uppercase all, remove any leading asterisk
1498 serge 213
 * _PSS: Sort the list descending by Power
214
 * _TSS: Sort the list descending by Power
215
 *
216
 * Names that must be packages, but cannot be sorted:
217
 *
218
 * _BCL: Values are tied to the Package index where they appear, and cannot
219
 * be moved or sorted. These index values are used for _BQC and _BCM.
220
 * However, we can fix the case where a buffer is returned, by converting
221
 * it to a Package of integers.
222
 */
223
static const ACPI_REPAIR_INFO       AcpiNsRepairableNames[] =
224
{
225
    {"_ALR", AcpiNsRepair_ALR},
2216 Serge 226
    {"_CID", AcpiNsRepair_CID},
1498 serge 227
    {"_FDE", AcpiNsRepair_FDE},
228
    {"_GTM", AcpiNsRepair_FDE},     /* _GTM has same repair as _FDE */
2216 Serge 229
    {"_HID", AcpiNsRepair_HID},
1498 serge 230
    {"_PSS", AcpiNsRepair_PSS},
231
    {"_TSS", AcpiNsRepair_TSS},
232
    {{0,0,0,0}, NULL}               /* Table terminator */
233
};
234
 
235
 
236
#define ACPI_FDE_FIELD_COUNT        5
237
#define ACPI_FDE_BYTE_BUFFER_SIZE   5
238
#define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * sizeof (UINT32))
239
 
240
 
241
/******************************************************************************
242
 *
243
 * FUNCTION:    AcpiNsComplexRepairs
244
 *
245
 * PARAMETERS:  Data                - Pointer to validation data structure
246
 *              Node                - Namespace node for the method/object
247
 *              ValidateStatus      - Original status of earlier validation
248
 *              ReturnObjectPtr     - Pointer to the object returned from the
249
 *                                    evaluation of a method or object
250
 *
251
 * RETURN:      Status. AE_OK if repair was successful. If name is not
252
 *              matched, ValidateStatus is returned.
253
 *
254
 * DESCRIPTION: Attempt to repair/convert a return object of a type that was
255
 *              not expected.
256
 *
257
 *****************************************************************************/
258
 
259
ACPI_STATUS
260
AcpiNsComplexRepairs (
261
    ACPI_PREDEFINED_DATA    *Data,
262
    ACPI_NAMESPACE_NODE     *Node,
263
    ACPI_STATUS             ValidateStatus,
264
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
265
{
266
    const ACPI_REPAIR_INFO  *Predefined;
267
    ACPI_STATUS             Status;
268
 
269
 
270
    /* Check if this name is in the list of repairable names */
271
 
272
    Predefined = AcpiNsMatchRepairableName (Node);
273
    if (!Predefined)
274
    {
275
        return (ValidateStatus);
276
    }
277
 
278
    Status = Predefined->RepairFunction (Data, ReturnObjectPtr);
279
    return (Status);
280
}
281
 
282
 
283
/******************************************************************************
284
 *
285
 * FUNCTION:    AcpiNsMatchRepairableName
286
 *
287
 * PARAMETERS:  Node                - Namespace node for the method/object
288
 *
289
 * RETURN:      Pointer to entry in repair table. NULL indicates not found.
290
 *
291
 * DESCRIPTION: Check an object name against the repairable object list.
292
 *
293
 *****************************************************************************/
294
 
295
static const ACPI_REPAIR_INFO *
296
AcpiNsMatchRepairableName (
297
    ACPI_NAMESPACE_NODE     *Node)
298
{
299
    const ACPI_REPAIR_INFO  *ThisName;
300
 
301
 
302
    /* Search info table for a repairable predefined method/object name */
303
 
304
    ThisName = AcpiNsRepairableNames;
305
    while (ThisName->RepairFunction)
306
    {
307
        if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name))
308
        {
309
            return (ThisName);
310
        }
311
        ThisName++;
312
    }
313
 
314
    return (NULL); /* Not found */
315
}
316
 
317
 
318
/******************************************************************************
319
 *
320
 * FUNCTION:    AcpiNsRepair_ALR
321
 *
322
 * PARAMETERS:  Data                - Pointer to validation data structure
323
 *              ReturnObjectPtr     - Pointer to the object returned from the
324
 *                                    evaluation of a method or object
325
 *
326
 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
327
 *
328
 * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
329
 *              ascending by the ambient illuminance values.
330
 *
331
 *****************************************************************************/
332
 
333
static ACPI_STATUS
334
AcpiNsRepair_ALR (
335
    ACPI_PREDEFINED_DATA    *Data,
336
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
337
{
338
    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
339
    ACPI_STATUS             Status;
340
 
341
 
342
    Status = AcpiNsCheckSortedList (Data, ReturnObject, 2, 1,
343
                ACPI_SORT_ASCENDING, "AmbientIlluminance");
344
 
345
    return (Status);
346
}
347
 
348
 
349
/******************************************************************************
350
 *
351
 * FUNCTION:    AcpiNsRepair_FDE
352
 *
353
 * PARAMETERS:  Data                - Pointer to validation data structure
354
 *              ReturnObjectPtr     - Pointer to the object returned from the
355
 *                                    evaluation of a method or object
356
 *
357
 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
358
 *
359
 * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return
360
 *              value is a Buffer of 5 DWORDs. This function repairs a common
361
 *              problem where the return value is a Buffer of BYTEs, not
362
 *              DWORDs.
363
 *
364
 *****************************************************************************/
365
 
366
static ACPI_STATUS
367
AcpiNsRepair_FDE (
368
    ACPI_PREDEFINED_DATA    *Data,
369
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
370
{
371
    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
372
    ACPI_OPERAND_OBJECT     *BufferObject;
373
    UINT8                   *ByteBuffer;
374
    UINT32                  *DwordBuffer;
375
    UINT32                  i;
376
 
377
 
378
    ACPI_FUNCTION_NAME (NsRepair_FDE);
379
 
380
 
381
    switch (ReturnObject->Common.Type)
382
    {
383
    case ACPI_TYPE_BUFFER:
384
 
385
        /* This is the expected type. Length should be (at least) 5 DWORDs */
386
 
387
        if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE)
388
        {
389
            return (AE_OK);
390
        }
391
 
392
        /* We can only repair if we have exactly 5 BYTEs */
393
 
394
        if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE)
395
        {
396
            ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
397
                "Incorrect return buffer length %u, expected %u",
398
                ReturnObject->Buffer.Length, ACPI_FDE_DWORD_BUFFER_SIZE));
399
 
400
            return (AE_AML_OPERAND_TYPE);
401
        }
402
 
403
        /* Create the new (larger) buffer object */
404
 
405
        BufferObject = AcpiUtCreateBufferObject (ACPI_FDE_DWORD_BUFFER_SIZE);
406
        if (!BufferObject)
407
        {
408
            return (AE_NO_MEMORY);
409
        }
410
 
411
        /* Expand each byte to a DWORD */
412
 
413
        ByteBuffer = ReturnObject->Buffer.Pointer;
414
        DwordBuffer = ACPI_CAST_PTR (UINT32, BufferObject->Buffer.Pointer);
415
 
416
        for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++)
417
        {
418
            *DwordBuffer = (UINT32) *ByteBuffer;
419
            DwordBuffer++;
420
            ByteBuffer++;
421
        }
422
 
423
        ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
424
            "%s Expanded Byte Buffer to expected DWord Buffer\n",
425
            Data->Pathname));
426
        break;
427
 
428
    default:
429
        return (AE_AML_OPERAND_TYPE);
430
    }
431
 
432
    /* Delete the original return object, return the new buffer object */
433
 
434
    AcpiUtRemoveReference (ReturnObject);
435
    *ReturnObjectPtr = BufferObject;
436
 
437
    Data->Flags |= ACPI_OBJECT_REPAIRED;
438
    return (AE_OK);
439
}
440
 
441
 
442
/******************************************************************************
443
 *
2216 Serge 444
 * FUNCTION:    AcpiNsRepair_CID
445
 *
446
 * PARAMETERS:  Data                - Pointer to validation data structure
447
 *              ReturnObjectPtr     - Pointer to the object returned from the
448
 *                                    evaluation of a method or object
449
 *
450
 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
451
 *
452
 * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
453
 *              letters are uppercase and that there is no leading asterisk.
454
 *              If a Package, ensure same for all string elements.
455
 *
456
 *****************************************************************************/
457
 
458
static ACPI_STATUS
459
AcpiNsRepair_CID (
460
    ACPI_PREDEFINED_DATA    *Data,
461
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
462
{
463
    ACPI_STATUS             Status;
464
    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
465
    ACPI_OPERAND_OBJECT     **ElementPtr;
466
    ACPI_OPERAND_OBJECT     *OriginalElement;
467
    UINT16                  OriginalRefCount;
468
    UINT32                  i;
469
 
470
 
471
    /* Check for _CID as a simple string */
472
 
473
    if (ReturnObject->Common.Type == ACPI_TYPE_STRING)
474
    {
475
        Status = AcpiNsRepair_HID (Data, ReturnObjectPtr);
476
        return (Status);
477
    }
478
 
479
    /* Exit if not a Package */
480
 
481
    if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
482
    {
483
        return (AE_OK);
484
    }
485
 
486
    /* Examine each element of the _CID package */
487
 
488
    ElementPtr = ReturnObject->Package.Elements;
489
    for (i = 0; i < ReturnObject->Package.Count; i++)
490
    {
491
        OriginalElement = *ElementPtr;
492
        OriginalRefCount = OriginalElement->Common.ReferenceCount;
493
 
494
        Status = AcpiNsRepair_HID (Data, ElementPtr);
495
        if (ACPI_FAILURE (Status))
496
        {
497
            return (Status);
498
        }
499
 
500
        /* Take care with reference counts */
501
 
502
        if (OriginalElement != *ElementPtr)
503
        {
504
            /* Element was replaced */
505
 
506
            (*ElementPtr)->Common.ReferenceCount =
507
                OriginalRefCount;
508
 
509
            AcpiUtRemoveReference (OriginalElement);
510
        }
511
 
512
        ElementPtr++;
513
    }
514
 
515
    return (AE_OK);
516
}
517
 
518
 
519
/******************************************************************************
520
 *
521
 * FUNCTION:    AcpiNsRepair_HID
522
 *
523
 * PARAMETERS:  Data                - Pointer to validation data structure
524
 *              ReturnObjectPtr     - Pointer to the object returned from the
525
 *                                    evaluation of a method or object
526
 *
527
 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
528
 *
529
 * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
530
 *              letters are uppercase and that there is no leading asterisk.
531
 *
532
 *****************************************************************************/
533
 
534
static ACPI_STATUS
535
AcpiNsRepair_HID (
536
    ACPI_PREDEFINED_DATA    *Data,
537
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
538
{
539
    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
540
    ACPI_OPERAND_OBJECT     *NewString;
541
    char                    *Source;
542
    char                    *Dest;
543
 
544
 
545
    ACPI_FUNCTION_NAME (NsRepair_HID);
546
 
547
 
548
    /* We only care about string _HID objects (not integers) */
549
 
550
    if (ReturnObject->Common.Type != ACPI_TYPE_STRING)
551
    {
552
        return (AE_OK);
553
    }
554
 
555
    if (ReturnObject->String.Length == 0)
556
    {
557
        ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
558
            "Invalid zero-length _HID or _CID string"));
559
 
560
        /* Return AE_OK anyway, let driver handle it */
561
 
562
        Data->Flags |= ACPI_OBJECT_REPAIRED;
563
        return (AE_OK);
564
    }
565
 
566
    /* It is simplest to always create a new string object */
567
 
568
    NewString = AcpiUtCreateStringObject (ReturnObject->String.Length);
569
    if (!NewString)
570
    {
571
        return (AE_NO_MEMORY);
572
    }
573
 
574
    /*
575
     * Remove a leading asterisk if present. For some unknown reason, there
576
     * are many machines in the field that contains IDs like this.
577
     *
578
     * Examples: "*PNP0C03", "*ACPI0003"
579
     */
580
    Source = ReturnObject->String.Pointer;
581
    if (*Source == '*')
582
    {
583
        Source++;
584
        NewString->String.Length--;
585
 
586
        ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
587
            "%s: Removed invalid leading asterisk\n", Data->Pathname));
588
    }
589
 
590
    /*
591
     * Copy and uppercase the string. From the ACPI specification:
592
     *
593
     * A valid PNP ID must be of the form "AAA####" where A is an uppercase
594
     * letter and # is a hex digit. A valid ACPI ID must be of the form
595
     * "ACPI####" where # is a hex digit.
596
     */
597
    for (Dest = NewString->String.Pointer; *Source; Dest++, Source++)
598
    {
599
        *Dest = (char) ACPI_TOUPPER (*Source);
600
    }
601
 
602
    AcpiUtRemoveReference (ReturnObject);
603
    *ReturnObjectPtr = NewString;
604
    return (AE_OK);
605
}
606
 
607
 
608
/******************************************************************************
609
 *
1498 serge 610
 * FUNCTION:    AcpiNsRepair_TSS
611
 *
612
 * PARAMETERS:  Data                - Pointer to validation data structure
613
 *              ReturnObjectPtr     - Pointer to the object returned from the
614
 *                                    evaluation of a method or object
615
 *
616
 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
617
 *
618
 * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
619
 *              descending by the power dissipation values.
620
 *
621
 *****************************************************************************/
622
 
623
static ACPI_STATUS
624
AcpiNsRepair_TSS (
625
    ACPI_PREDEFINED_DATA    *Data,
626
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
627
{
628
    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
629
    ACPI_STATUS             Status;
2216 Serge 630
    ACPI_NAMESPACE_NODE     *Node;
1498 serge 631
 
632
 
2216 Serge 633
    /*
634
     * We can only sort the _TSS return package if there is no _PSS in the
635
     * same scope. This is because if _PSS is present, the ACPI specification
636
     * dictates that the _TSS Power Dissipation field is to be ignored, and
637
     * therefore some BIOSs leave garbage values in the _TSS Power field(s).
638
     * In this case, it is best to just return the _TSS package as-is.
639
     * (May, 2011)
640
     */
641
    Status = AcpiNsGetNode (Data->Node, "^_PSS", ACPI_NS_NO_UPSEARCH, &Node);
642
    if (ACPI_SUCCESS (Status))
643
    {
644
        return (AE_OK);
645
    }
646
 
1498 serge 647
    Status = AcpiNsCheckSortedList (Data, ReturnObject, 5, 1,
648
                ACPI_SORT_DESCENDING, "PowerDissipation");
649
 
650
    return (Status);
651
}
652
 
653
 
654
/******************************************************************************
655
 *
656
 * FUNCTION:    AcpiNsRepair_PSS
657
 *
658
 * PARAMETERS:  Data                - Pointer to validation data structure
659
 *              ReturnObjectPtr     - Pointer to the object returned from the
660
 *                                    evaluation of a method or object
661
 *
662
 * RETURN:      Status. AE_OK if object is OK or was repaired successfully
663
 *
664
 * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
665
 *              by the CPU frequencies. Check that the power dissipation values
666
 *              are all proportional to CPU frequency (i.e., sorting by
667
 *              frequency should be the same as sorting by power.)
668
 *
669
 *****************************************************************************/
670
 
671
static ACPI_STATUS
672
AcpiNsRepair_PSS (
673
    ACPI_PREDEFINED_DATA    *Data,
674
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
675
{
676
    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
677
    ACPI_OPERAND_OBJECT     **OuterElements;
678
    UINT32                  OuterElementCount;
679
    ACPI_OPERAND_OBJECT     **Elements;
680
    ACPI_OPERAND_OBJECT     *ObjDesc;
681
    UINT32                  PreviousValue;
682
    ACPI_STATUS             Status;
683
    UINT32                  i;
684
 
685
 
686
    /*
687
     * Entries (sub-packages) in the _PSS Package must be sorted by power
688
     * dissipation, in descending order. If it appears that the list is
689
     * incorrectly sorted, sort it. We sort by CpuFrequency, since this
690
     * should be proportional to the power.
691
     */
692
    Status =AcpiNsCheckSortedList (Data, ReturnObject, 6, 0,
693
                ACPI_SORT_DESCENDING, "CpuFrequency");
694
    if (ACPI_FAILURE (Status))
695
    {
696
        return (Status);
697
    }
698
 
699
    /*
700
     * We now know the list is correctly sorted by CPU frequency. Check if
701
     * the power dissipation values are proportional.
702
     */
703
    PreviousValue = ACPI_UINT32_MAX;
704
    OuterElements = ReturnObject->Package.Elements;
705
    OuterElementCount = ReturnObject->Package.Count;
706
 
707
    for (i = 0; i < OuterElementCount; i++)
708
    {
709
        Elements = (*OuterElements)->Package.Elements;
710
        ObjDesc = Elements[1]; /* Index1 = PowerDissipation */
711
 
712
        if ((UINT32) ObjDesc->Integer.Value > PreviousValue)
713
        {
714
            ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
715
                "SubPackage[%u,%u] - suspicious power dissipation values",
716
                i-1, i));
717
        }
718
 
719
        PreviousValue = (UINT32) ObjDesc->Integer.Value;
720
        OuterElements++;
721
    }
722
 
723
    return (AE_OK);
724
}
725
 
726
 
727
/******************************************************************************
728
 *
729
 * FUNCTION:    AcpiNsCheckSortedList
730
 *
731
 * PARAMETERS:  Data                - Pointer to validation data structure
732
 *              ReturnObject        - Pointer to the top-level returned object
733
 *              ExpectedCount       - Minimum length of each sub-package
734
 *              SortIndex           - Sub-package entry to sort on
735
 *              SortDirection       - Ascending or descending
736
 *              SortKeyName         - Name of the SortIndex field
737
 *
738
 * RETURN:      Status. AE_OK if the list is valid and is sorted correctly or
739
 *              has been repaired by sorting the list.
740
 *
741
 * DESCRIPTION: Check if the package list is valid and sorted correctly by the
742
 *              SortIndex. If not, then sort the list.
743
 *
744
 *****************************************************************************/
745
 
746
static ACPI_STATUS
747
AcpiNsCheckSortedList (
748
    ACPI_PREDEFINED_DATA    *Data,
749
    ACPI_OPERAND_OBJECT     *ReturnObject,
750
    UINT32                  ExpectedCount,
751
    UINT32                  SortIndex,
752
    UINT8                   SortDirection,
753
    char                    *SortKeyName)
754
{
755
    UINT32                  OuterElementCount;
756
    ACPI_OPERAND_OBJECT     **OuterElements;
757
    ACPI_OPERAND_OBJECT     **Elements;
758
    ACPI_OPERAND_OBJECT     *ObjDesc;
759
    UINT32                  i;
760
    UINT32                  PreviousValue;
761
 
762
 
763
    ACPI_FUNCTION_NAME (NsCheckSortedList);
764
 
765
 
766
    /* The top-level object must be a package */
767
 
768
    if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
769
    {
770
        return (AE_AML_OPERAND_TYPE);
771
    }
772
 
773
    /*
774
     * NOTE: assumes list of sub-packages contains no NULL elements.
775
     * Any NULL elements should have been removed by earlier call
776
     * to AcpiNsRemoveNullElements.
777
     */
778
    OuterElements = ReturnObject->Package.Elements;
779
    OuterElementCount = ReturnObject->Package.Count;
780
    if (!OuterElementCount)
781
    {
782
        return (AE_AML_PACKAGE_LIMIT);
783
    }
784
 
785
    PreviousValue = 0;
786
    if (SortDirection == ACPI_SORT_DESCENDING)
787
    {
788
        PreviousValue = ACPI_UINT32_MAX;
789
    }
790
 
791
    /* Examine each subpackage */
792
 
793
    for (i = 0; i < OuterElementCount; i++)
794
    {
795
        /* Each element of the top-level package must also be a package */
796
 
797
        if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE)
798
        {
799
            return (AE_AML_OPERAND_TYPE);
800
        }
801
 
802
        /* Each sub-package must have the minimum length */
803
 
804
        if ((*OuterElements)->Package.Count < ExpectedCount)
805
        {
806
            return (AE_AML_PACKAGE_LIMIT);
807
        }
808
 
809
        Elements = (*OuterElements)->Package.Elements;
810
        ObjDesc = Elements[SortIndex];
811
 
812
        if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
813
        {
814
            return (AE_AML_OPERAND_TYPE);
815
        }
816
 
817
        /*
818
         * The list must be sorted in the specified order. If we detect a
819
         * discrepancy, sort the entire list.
820
         */
821
        if (((SortDirection == ACPI_SORT_ASCENDING) &&
822
                (ObjDesc->Integer.Value < PreviousValue)) ||
823
            ((SortDirection == ACPI_SORT_DESCENDING) &&
824
                (ObjDesc->Integer.Value > PreviousValue)))
825
        {
826
            AcpiNsSortList (ReturnObject->Package.Elements,
827
                OuterElementCount, SortIndex, SortDirection);
828
 
829
            Data->Flags |= ACPI_OBJECT_REPAIRED;
830
 
831
            ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
832
                "%s: Repaired unsorted list - now sorted by %s\n",
833
                Data->Pathname, SortKeyName));
834
            return (AE_OK);
835
        }
836
 
837
        PreviousValue = (UINT32) ObjDesc->Integer.Value;
838
        OuterElements++;
839
    }
840
 
841
    return (AE_OK);
842
}
843
 
844
 
845
/******************************************************************************
846
 *
847
 * FUNCTION:    AcpiNsSortList
848
 *
849
 * PARAMETERS:  Elements            - Package object element list
850
 *              Count               - Element count for above
851
 *              Index               - Sort by which package element
852
 *              SortDirection       - Ascending or Descending sort
853
 *
854
 * RETURN:      None
855
 *
856
 * DESCRIPTION: Sort the objects that are in a package element list.
857
 *
858
 * NOTE: Assumes that all NULL elements have been removed from the package,
859
 *       and that all elements have been verified to be of type Integer.
860
 *
861
 *****************************************************************************/
862
 
863
static void
864
AcpiNsSortList (
865
    ACPI_OPERAND_OBJECT     **Elements,
866
    UINT32                  Count,
867
    UINT32                  Index,
868
    UINT8                   SortDirection)
869
{
870
    ACPI_OPERAND_OBJECT     *ObjDesc1;
871
    ACPI_OPERAND_OBJECT     *ObjDesc2;
872
    ACPI_OPERAND_OBJECT     *TempObj;
873
    UINT32                  i;
874
    UINT32                  j;
875
 
876
 
877
    /* Simple bubble sort */
878
 
879
    for (i = 1; i < Count; i++)
880
    {
881
        for (j = (Count - 1); j >= i; j--)
882
        {
883
            ObjDesc1 = Elements[j-1]->Package.Elements[Index];
884
            ObjDesc2 = Elements[j]->Package.Elements[Index];
885
 
886
            if (((SortDirection == ACPI_SORT_ASCENDING) &&
887
                    (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) ||
888
 
889
                ((SortDirection == ACPI_SORT_DESCENDING) &&
890
                    (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value)))
891
            {
892
                TempObj = Elements[j-1];
893
                Elements[j-1] = Elements[j];
894
                Elements[j] = TempObj;
895
            }
896
        }
897
    }
898
}