1 /******************************************************************************
   2  *
   3  * Module Name: nsrepair2 - Repair for objects returned by specific
   4  *                          predefined methods
   5  *
   6  *****************************************************************************/
   7 
   8 /*
   9  * Copyright (C) 2000 - 2014, Intel Corp.
  10  * All rights reserved.
  11  *
  12  * Redistribution and use in source and binary forms, with or without
  13  * modification, are permitted provided that the following conditions
  14  * are met:
  15  * 1. Redistributions of source code must retain the above copyright
  16  *    notice, this list of conditions, and the following disclaimer,
  17  *    without modification.
  18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  19  *    substantially similar to the "NO WARRANTY" disclaimer below
  20  *    ("Disclaimer") and any redistribution must be conditioned upon
  21  *    including a substantially similar Disclaimer requirement for further
  22  *    binary redistribution.
  23  * 3. Neither the names of the above-listed copyright holders nor the names
  24  *    of any contributors may be used to endorse or promote products derived
  25  *    from this software without specific prior written permission.
  26  *
  27  * Alternatively, this software may be distributed under the terms of the
  28  * GNU General Public License ("GPL") version 2 as published by the Free
  29  * Software Foundation.
  30  *
  31  * NO WARRANTY
  32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42  * POSSIBILITY OF SUCH DAMAGES.
  43  */
  44 
  45 #define __NSREPAIR2_C__
  46 
  47 #include "acpi.h"
  48 #include "accommon.h"
  49 #include "acnamesp.h"
  50 
  51 #define _COMPONENT          ACPI_NAMESPACE
  52         ACPI_MODULE_NAME    ("nsrepair2")
  53 
  54 
  55 /*
  56  * Information structure and handler for ACPI predefined names that can
  57  * be repaired on a per-name basis.
  58  */
  59 typedef
  60 ACPI_STATUS (*ACPI_REPAIR_FUNCTION) (
  61     ACPI_EVALUATE_INFO      *Info,
  62     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
  63 
  64 typedef struct acpi_repair_info
  65 {
  66     char                    Name[ACPI_NAME_SIZE];
  67     ACPI_REPAIR_FUNCTION    RepairFunction;
  68 
  69 } ACPI_REPAIR_INFO;
  70 
  71 
  72 /* Local prototypes */
  73 
  74 static const ACPI_REPAIR_INFO *
  75 AcpiNsMatchComplexRepair (
  76     ACPI_NAMESPACE_NODE     *Node);
  77 
  78 static ACPI_STATUS
  79 AcpiNsRepair_ALR (
  80     ACPI_EVALUATE_INFO      *Info,
  81     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
  82 
  83 static ACPI_STATUS
  84 AcpiNsRepair_CID (
  85     ACPI_EVALUATE_INFO      *Info,
  86     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
  87 
  88 static ACPI_STATUS
  89 AcpiNsRepair_CST (
  90     ACPI_EVALUATE_INFO      *Info,
  91     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
  92 
  93 static ACPI_STATUS
  94 AcpiNsRepair_FDE (
  95     ACPI_EVALUATE_INFO      *Info,
  96     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
  97 
  98 static ACPI_STATUS
  99 AcpiNsRepair_HID (
 100     ACPI_EVALUATE_INFO      *Info,
 101     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
 102 
 103 static ACPI_STATUS
 104 AcpiNsRepair_PRT (
 105     ACPI_EVALUATE_INFO      *Info,
 106     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
 107 
 108 static ACPI_STATUS
 109 AcpiNsRepair_PSS (
 110     ACPI_EVALUATE_INFO      *Info,
 111     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
 112 
 113 static ACPI_STATUS
 114 AcpiNsRepair_TSS (
 115     ACPI_EVALUATE_INFO      *Info,
 116     ACPI_OPERAND_OBJECT     **ReturnObjectPtr);
 117 
 118 static ACPI_STATUS
 119 AcpiNsCheckSortedList (
 120     ACPI_EVALUATE_INFO      *Info,
 121     ACPI_OPERAND_OBJECT     *ReturnObject,
 122     UINT32                  StartIndex,
 123     UINT32                  ExpectedCount,
 124     UINT32                  SortIndex,
 125     UINT8                   SortDirection,
 126     char                    *SortKeyName);
 127 
 128 /* Values for SortDirection above */
 129 
 130 #define ACPI_SORT_ASCENDING     0
 131 #define ACPI_SORT_DESCENDING    1
 132 
 133 static void
 134 AcpiNsRemoveElement (
 135     ACPI_OPERAND_OBJECT     *ObjDesc,
 136     UINT32                  Index);
 137 
 138 static void
 139 AcpiNsSortList (
 140     ACPI_OPERAND_OBJECT     **Elements,
 141     UINT32                  Count,
 142     UINT32                  Index,
 143     UINT8                   SortDirection);
 144 
 145 
 146 /*
 147  * This table contains the names of the predefined methods for which we can
 148  * perform more complex repairs.
 149  *
 150  * As necessary:
 151  *
 152  * _ALR: Sort the list ascending by AmbientIlluminance
 153  * _CID: Strings: uppercase all, remove any leading asterisk
 154  * _CST: Sort the list ascending by C state type
 155  * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
 156  * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
 157  * _HID: Strings: uppercase all, remove any leading asterisk
 158  * _PRT: Fix reversed SourceName and SourceIndex
 159  * _PSS: Sort the list descending by Power
 160  * _TSS: Sort the list descending by Power
 161  *
 162  * Names that must be packages, but cannot be sorted:
 163  *
 164  * _BCL: Values are tied to the Package index where they appear, and cannot
 165  * be moved or sorted. These index values are used for _BQC and _BCM.
 166  * However, we can fix the case where a buffer is returned, by converting
 167  * it to a Package of integers.
 168  */
 169 static const ACPI_REPAIR_INFO       AcpiNsRepairableNames[] =
 170 {
 171     {"_ALR", AcpiNsRepair_ALR},
 172     {"_CID", AcpiNsRepair_CID},
 173     {"_CST", AcpiNsRepair_CST},
 174     {"_FDE", AcpiNsRepair_FDE},
 175     {"_GTM", AcpiNsRepair_FDE},     /* _GTM has same repair as _FDE */
 176     {"_HID", AcpiNsRepair_HID},
 177     {"_PRT", AcpiNsRepair_PRT},
 178     {"_PSS", AcpiNsRepair_PSS},
 179     {"_TSS", AcpiNsRepair_TSS},
 180     {{0,0,0,0}, NULL}               /* Table terminator */
 181 };
 182 
 183 
 184 #define ACPI_FDE_FIELD_COUNT        5
 185 #define ACPI_FDE_BYTE_BUFFER_SIZE   5
 186 #define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * sizeof (UINT32))
 187 
 188 
 189 /******************************************************************************
 190  *
 191  * FUNCTION:    AcpiNsComplexRepairs
 192  *
 193  * PARAMETERS:  Info                - Method execution information block
 194  *              Node                - Namespace node for the method/object
 195  *              ValidateStatus      - Original status of earlier validation
 196  *              ReturnObjectPtr     - Pointer to the object returned from the
 197  *                                    evaluation of a method or object
 198  *
 199  * RETURN:      Status. AE_OK if repair was successful. If name is not
 200  *              matched, ValidateStatus is returned.
 201  *
 202  * DESCRIPTION: Attempt to repair/convert a return object of a type that was
 203  *              not expected.
 204  *
 205  *****************************************************************************/
 206 
 207 ACPI_STATUS
 208 AcpiNsComplexRepairs (
 209     ACPI_EVALUATE_INFO      *Info,
 210     ACPI_NAMESPACE_NODE     *Node,
 211     ACPI_STATUS             ValidateStatus,
 212     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
 213 {
 214     const ACPI_REPAIR_INFO  *Predefined;
 215     ACPI_STATUS             Status;
 216 
 217 
 218     /* Check if this name is in the list of repairable names */
 219 
 220     Predefined = AcpiNsMatchComplexRepair (Node);
 221     if (!Predefined)
 222     {
 223         return (ValidateStatus);
 224     }
 225 
 226     Status = Predefined->RepairFunction (Info, ReturnObjectPtr);
 227     return (Status);
 228 }
 229 
 230 
 231 /******************************************************************************
 232  *
 233  * FUNCTION:    AcpiNsMatchComplexRepair
 234  *
 235  * PARAMETERS:  Node                - Namespace node for the method/object
 236  *
 237  * RETURN:      Pointer to entry in repair table. NULL indicates not found.
 238  *
 239  * DESCRIPTION: Check an object name against the repairable object list.
 240  *
 241  *****************************************************************************/
 242 
 243 static const ACPI_REPAIR_INFO *
 244 AcpiNsMatchComplexRepair (
 245     ACPI_NAMESPACE_NODE     *Node)
 246 {
 247     const ACPI_REPAIR_INFO  *ThisName;
 248 
 249 
 250     /* Search info table for a repairable predefined method/object name */
 251 
 252     ThisName = AcpiNsRepairableNames;
 253     while (ThisName->RepairFunction)
 254     {
 255         if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name))
 256         {
 257             return (ThisName);
 258         }
 259         ThisName++;
 260     }
 261 
 262     return (NULL); /* Not found */
 263 }
 264 
 265 
 266 /******************************************************************************
 267  *
 268  * FUNCTION:    AcpiNsRepair_ALR
 269  *
 270  * PARAMETERS:  Info                - Method execution information block
 271  *              ReturnObjectPtr     - Pointer to the object returned from the
 272  *                                    evaluation of a method or object
 273  *
 274  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
 275  *
 276  * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
 277  *              ascending by the ambient illuminance values.
 278  *
 279  *****************************************************************************/
 280 
 281 static ACPI_STATUS
 282 AcpiNsRepair_ALR (
 283     ACPI_EVALUATE_INFO      *Info,
 284     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
 285 {
 286     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
 287     ACPI_STATUS             Status;
 288 
 289 
 290     Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 2, 1,
 291                 ACPI_SORT_ASCENDING, "AmbientIlluminance");
 292 
 293     return (Status);
 294 }
 295 
 296 
 297 /******************************************************************************
 298  *
 299  * FUNCTION:    AcpiNsRepair_FDE
 300  *
 301  * PARAMETERS:  Info                - Method execution information block
 302  *              ReturnObjectPtr     - Pointer to the object returned from the
 303  *                                    evaluation of a method or object
 304  *
 305  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
 306  *
 307  * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return
 308  *              value is a Buffer of 5 DWORDs. This function repairs a common
 309  *              problem where the return value is a Buffer of BYTEs, not
 310  *              DWORDs.
 311  *
 312  *****************************************************************************/
 313 
 314 static ACPI_STATUS
 315 AcpiNsRepair_FDE (
 316     ACPI_EVALUATE_INFO      *Info,
 317     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
 318 {
 319     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
 320     ACPI_OPERAND_OBJECT     *BufferObject;
 321     UINT8                   *ByteBuffer;
 322     UINT32                  *DwordBuffer;
 323     UINT32                  i;
 324 
 325 
 326     ACPI_FUNCTION_NAME (NsRepair_FDE);
 327 
 328 
 329     switch (ReturnObject->Common.Type)
 330     {
 331     case ACPI_TYPE_BUFFER:
 332 
 333         /* This is the expected type. Length should be (at least) 5 DWORDs */
 334 
 335         if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE)
 336         {
 337             return (AE_OK);
 338         }
 339 
 340         /* We can only repair if we have exactly 5 BYTEs */
 341 
 342         if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE)
 343         {
 344             ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 345                 "Incorrect return buffer length %u, expected %u",
 346                 ReturnObject->Buffer.Length, ACPI_FDE_DWORD_BUFFER_SIZE));
 347 
 348             return (AE_AML_OPERAND_TYPE);
 349         }
 350 
 351         /* Create the new (larger) buffer object */
 352 
 353         BufferObject = AcpiUtCreateBufferObject (ACPI_FDE_DWORD_BUFFER_SIZE);
 354         if (!BufferObject)
 355         {
 356             return (AE_NO_MEMORY);
 357         }
 358 
 359         /* Expand each byte to a DWORD */
 360 
 361         ByteBuffer = ReturnObject->Buffer.Pointer;
 362         DwordBuffer = ACPI_CAST_PTR (UINT32, BufferObject->Buffer.Pointer);
 363 
 364         for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++)
 365         {
 366             *DwordBuffer = (UINT32) *ByteBuffer;
 367             DwordBuffer++;
 368             ByteBuffer++;
 369         }
 370 
 371         ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
 372             "%s Expanded Byte Buffer to expected DWord Buffer\n",
 373             Info->FullPathname));
 374         break;
 375 
 376     default:
 377 
 378         return (AE_AML_OPERAND_TYPE);
 379     }
 380 
 381     /* Delete the original return object, return the new buffer object */
 382 
 383     AcpiUtRemoveReference (ReturnObject);
 384     *ReturnObjectPtr = BufferObject;
 385 
 386     Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
 387     return (AE_OK);
 388 }
 389 
 390 
 391 /******************************************************************************
 392  *
 393  * FUNCTION:    AcpiNsRepair_CID
 394  *
 395  * PARAMETERS:  Info                - Method execution information block
 396  *              ReturnObjectPtr     - Pointer to the object returned from the
 397  *                                    evaluation of a method or object
 398  *
 399  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
 400  *
 401  * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
 402  *              letters are uppercase and that there is no leading asterisk.
 403  *              If a Package, ensure same for all string elements.
 404  *
 405  *****************************************************************************/
 406 
 407 static ACPI_STATUS
 408 AcpiNsRepair_CID (
 409     ACPI_EVALUATE_INFO      *Info,
 410     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
 411 {
 412     ACPI_STATUS             Status;
 413     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
 414     ACPI_OPERAND_OBJECT     **ElementPtr;
 415     ACPI_OPERAND_OBJECT     *OriginalElement;
 416     UINT16                  OriginalRefCount;
 417     UINT32                  i;
 418 
 419 
 420     /* Check for _CID as a simple string */
 421 
 422     if (ReturnObject->Common.Type == ACPI_TYPE_STRING)
 423     {
 424         Status = AcpiNsRepair_HID (Info, ReturnObjectPtr);
 425         return (Status);
 426     }
 427 
 428     /* Exit if not a Package */
 429 
 430     if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
 431     {
 432         return (AE_OK);
 433     }
 434 
 435     /* Examine each element of the _CID package */
 436 
 437     ElementPtr = ReturnObject->Package.Elements;
 438     for (i = 0; i < ReturnObject->Package.Count; i++)
 439     {
 440         OriginalElement = *ElementPtr;
 441         OriginalRefCount = OriginalElement->Common.ReferenceCount;
 442 
 443         Status = AcpiNsRepair_HID (Info, ElementPtr);
 444         if (ACPI_FAILURE (Status))
 445         {
 446             return (Status);
 447         }
 448 
 449         /* Take care with reference counts */
 450 
 451         if (OriginalElement != *ElementPtr)
 452         {
 453             /* Element was replaced */
 454 
 455             (*ElementPtr)->Common.ReferenceCount =
 456                 OriginalRefCount;
 457 
 458             AcpiUtRemoveReference (OriginalElement);
 459         }
 460 
 461         ElementPtr++;
 462     }
 463 
 464     return (AE_OK);
 465 }
 466 
 467 
 468 /******************************************************************************
 469  *
 470  * FUNCTION:    AcpiNsRepair_CST
 471  *
 472  * PARAMETERS:  Info                - Method execution information block
 473  *              ReturnObjectPtr     - Pointer to the object returned from the
 474  *                                    evaluation of a method or object
 475  *
 476  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
 477  *
 478  * DESCRIPTION: Repair for the _CST object:
 479  *              1. Sort the list ascending by C state type
 480  *              2. Ensure type cannot be zero
 481  *              3. A sub-package count of zero means _CST is meaningless
 482  *              4. Count must match the number of C state sub-packages
 483  *
 484  *****************************************************************************/
 485 
 486 static ACPI_STATUS
 487 AcpiNsRepair_CST (
 488     ACPI_EVALUATE_INFO      *Info,
 489     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
 490 {
 491     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
 492     ACPI_OPERAND_OBJECT     **OuterElements;
 493     UINT32                  OuterElementCount;
 494     ACPI_OPERAND_OBJECT     *ObjDesc;
 495     ACPI_STATUS             Status;
 496     BOOLEAN                 Removing;
 497     UINT32                  i;
 498 
 499 
 500     ACPI_FUNCTION_NAME (NsRepair_CST);
 501 
 502 
 503     /*
 504      * Check if the C-state type values are proportional.
 505      */
 506     OuterElementCount = ReturnObject->Package.Count - 1;
 507     i = 0;
 508     while (i < OuterElementCount)
 509     {
 510         OuterElements = &ReturnObject->Package.Elements[i + 1];
 511         Removing = FALSE;
 512 
 513         if ((*OuterElements)->Package.Count == 0)
 514         {
 515             ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 516                 "SubPackage[%u] - removing entry due to zero count", i));
 517             Removing = TRUE;
 518             goto RemoveElement;
 519         }
 520 
 521         ObjDesc = (*OuterElements)->Package.Elements[1]; /* Index1 = Type */
 522         if ((UINT32) ObjDesc->Integer.Value == 0)
 523         {
 524             ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 525                 "SubPackage[%u] - removing entry due to invalid Type(0)", i));
 526             Removing = TRUE;
 527         }
 528 
 529 RemoveElement:
 530         if (Removing)
 531         {
 532             AcpiNsRemoveElement (ReturnObject, i + 1);
 533             OuterElementCount--;
 534         }
 535         else
 536         {
 537             i++;
 538         }
 539     }
 540 
 541     /* Update top-level package count, Type "Integer" checked elsewhere */
 542 
 543     ObjDesc = ReturnObject->Package.Elements[0];
 544     ObjDesc->Integer.Value = OuterElementCount;
 545 
 546     /*
 547      * Entries (subpackages) in the _CST Package must be sorted by the
 548      * C-state type, in ascending order.
 549      */
 550     Status = AcpiNsCheckSortedList (Info, ReturnObject, 1, 4, 1,
 551                 ACPI_SORT_ASCENDING, "C-State Type");
 552     if (ACPI_FAILURE (Status))
 553     {
 554         return (Status);
 555     }
 556 
 557     return (AE_OK);
 558 }
 559 
 560 
 561 /******************************************************************************
 562  *
 563  * FUNCTION:    AcpiNsRepair_HID
 564  *
 565  * PARAMETERS:  Info                - Method execution information block
 566  *              ReturnObjectPtr     - Pointer to the object returned from the
 567  *                                    evaluation of a method or object
 568  *
 569  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
 570  *
 571  * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
 572  *              letters are uppercase and that there is no leading asterisk.
 573  *
 574  *****************************************************************************/
 575 
 576 static ACPI_STATUS
 577 AcpiNsRepair_HID (
 578     ACPI_EVALUATE_INFO      *Info,
 579     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
 580 {
 581     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
 582     ACPI_OPERAND_OBJECT     *NewString;
 583     char                    *Source;
 584     char                    *Dest;
 585 
 586 
 587     ACPI_FUNCTION_NAME (NsRepair_HID);
 588 
 589 
 590     /* We only care about string _HID objects (not integers) */
 591 
 592     if (ReturnObject->Common.Type != ACPI_TYPE_STRING)
 593     {
 594         return (AE_OK);
 595     }
 596 
 597     if (ReturnObject->String.Length == 0)
 598     {
 599         ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 600             "Invalid zero-length _HID or _CID string"));
 601 
 602         /* Return AE_OK anyway, let driver handle it */
 603 
 604         Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
 605         return (AE_OK);
 606     }
 607 
 608     /* It is simplest to always create a new string object */
 609 
 610     NewString = AcpiUtCreateStringObject (ReturnObject->String.Length);
 611     if (!NewString)
 612     {
 613         return (AE_NO_MEMORY);
 614     }
 615 
 616     /*
 617      * Remove a leading asterisk if present. For some unknown reason, there
 618      * are many machines in the field that contains IDs like this.
 619      *
 620      * Examples: "*PNP0C03", "*ACPI0003"
 621      */
 622     Source = ReturnObject->String.Pointer;
 623     if (*Source == '*')
 624     {
 625         Source++;
 626         NewString->String.Length--;
 627 
 628         ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
 629             "%s: Removed invalid leading asterisk\n", Info->FullPathname));
 630     }
 631 
 632     /*
 633      * Copy and uppercase the string. From the ACPI 5.0 specification:
 634      *
 635      * A valid PNP ID must be of the form "AAA####" where A is an uppercase
 636      * letter and # is a hex digit. A valid ACPI ID must be of the form
 637      * "NNNN####" where N is an uppercase letter or decimal digit, and
 638      * # is a hex digit.
 639      */
 640     for (Dest = NewString->String.Pointer; *Source; Dest++, Source++)
 641     {
 642         *Dest = (char) ACPI_TOUPPER (*Source);
 643     }
 644 
 645     AcpiUtRemoveReference (ReturnObject);
 646     *ReturnObjectPtr = NewString;
 647     return (AE_OK);
 648 }
 649 
 650 
 651 /******************************************************************************
 652  *
 653  * FUNCTION:    AcpiNsRepair_PRT
 654  *
 655  * PARAMETERS:  Info                - Method execution information block
 656  *              ReturnObjectPtr     - Pointer to the object returned from the
 657  *                                    evaluation of a method or object
 658  *
 659  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
 660  *
 661  * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed
 662  *              SourceName and SourceIndex field, a common BIOS bug.
 663  *
 664  *****************************************************************************/
 665 
 666 static ACPI_STATUS
 667 AcpiNsRepair_PRT (
 668     ACPI_EVALUATE_INFO      *Info,
 669     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
 670 {
 671     ACPI_OPERAND_OBJECT     *PackageObject = *ReturnObjectPtr;
 672     ACPI_OPERAND_OBJECT     **TopObjectList;
 673     ACPI_OPERAND_OBJECT     **SubObjectList;
 674     ACPI_OPERAND_OBJECT     *ObjDesc;
 675     UINT32                  ElementCount;
 676     UINT32                  Index;
 677 
 678 
 679     /* Each element in the _PRT package is a subpackage */
 680 
 681     TopObjectList = PackageObject->Package.Elements;
 682     ElementCount = PackageObject->Package.Count;
 683 
 684     for (Index = 0; Index < ElementCount; Index++)
 685     {
 686         SubObjectList = (*TopObjectList)->Package.Elements;
 687 
 688         /*
 689          * If the BIOS has erroneously reversed the _PRT SourceName (index 2)
 690          * and the SourceIndex (index 3), fix it. _PRT is important enough to
 691          * workaround this BIOS error. This also provides compatibility with
 692          * other ACPI implementations.
 693          */
 694         ObjDesc = SubObjectList[3];
 695         if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
 696         {
 697             SubObjectList[3] = SubObjectList[2];
 698             SubObjectList[2] = ObjDesc;
 699             Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
 700 
 701             ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 702                 "PRT[%X]: Fixed reversed SourceName and SourceIndex",
 703                 Index));
 704         }
 705 
 706         /* Point to the next ACPI_OPERAND_OBJECT in the top level package */
 707 
 708         TopObjectList++;
 709     }
 710 
 711     return (AE_OK);
 712 }
 713 
 714 
 715 /******************************************************************************
 716  *
 717  * FUNCTION:    AcpiNsRepair_PSS
 718  *
 719  * PARAMETERS:  Info                - Method execution information block
 720  *              ReturnObjectPtr     - Pointer to the object returned from the
 721  *                                    evaluation of a method or object
 722  *
 723  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
 724  *
 725  * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
 726  *              by the CPU frequencies. Check that the power dissipation values
 727  *              are all proportional to CPU frequency (i.e., sorting by
 728  *              frequency should be the same as sorting by power.)
 729  *
 730  *****************************************************************************/
 731 
 732 static ACPI_STATUS
 733 AcpiNsRepair_PSS (
 734     ACPI_EVALUATE_INFO      *Info,
 735     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
 736 {
 737     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
 738     ACPI_OPERAND_OBJECT     **OuterElements;
 739     UINT32                  OuterElementCount;
 740     ACPI_OPERAND_OBJECT     **Elements;
 741     ACPI_OPERAND_OBJECT     *ObjDesc;
 742     UINT32                  PreviousValue;
 743     ACPI_STATUS             Status;
 744     UINT32                  i;
 745 
 746 
 747     /*
 748      * Entries (sub-packages) in the _PSS Package must be sorted by power
 749      * dissipation, in descending order. If it appears that the list is
 750      * incorrectly sorted, sort it. We sort by CpuFrequency, since this
 751      * should be proportional to the power.
 752      */
 753     Status =AcpiNsCheckSortedList (Info, ReturnObject, 0, 6, 0,
 754                 ACPI_SORT_DESCENDING, "CpuFrequency");
 755     if (ACPI_FAILURE (Status))
 756     {
 757         return (Status);
 758     }
 759 
 760     /*
 761      * We now know the list is correctly sorted by CPU frequency. Check if
 762      * the power dissipation values are proportional.
 763      */
 764     PreviousValue = ACPI_UINT32_MAX;
 765     OuterElements = ReturnObject->Package.Elements;
 766     OuterElementCount = ReturnObject->Package.Count;
 767 
 768     for (i = 0; i < OuterElementCount; i++)
 769     {
 770         Elements = (*OuterElements)->Package.Elements;
 771         ObjDesc = Elements[1]; /* Index1 = PowerDissipation */
 772 
 773         if ((UINT32) ObjDesc->Integer.Value > PreviousValue)
 774         {
 775             ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
 776                 "SubPackage[%u,%u] - suspicious power dissipation values",
 777                 i-1, i));
 778         }
 779 
 780         PreviousValue = (UINT32) ObjDesc->Integer.Value;
 781         OuterElements++;
 782     }
 783 
 784     return (AE_OK);
 785 }
 786 
 787 
 788 /******************************************************************************
 789  *
 790  * FUNCTION:    AcpiNsRepair_TSS
 791  *
 792  * PARAMETERS:  Info                - Method execution information block
 793  *              ReturnObjectPtr     - Pointer to the object returned from the
 794  *                                    evaluation of a method or object
 795  *
 796  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
 797  *
 798  * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
 799  *              descending by the power dissipation values.
 800  *
 801  *****************************************************************************/
 802 
 803 static ACPI_STATUS
 804 AcpiNsRepair_TSS (
 805     ACPI_EVALUATE_INFO      *Info,
 806     ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
 807 {
 808     ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
 809     ACPI_STATUS             Status;
 810     ACPI_NAMESPACE_NODE     *Node;
 811 
 812 
 813     /*
 814      * We can only sort the _TSS return package if there is no _PSS in the
 815      * same scope. This is because if _PSS is present, the ACPI specification
 816      * dictates that the _TSS Power Dissipation field is to be ignored, and
 817      * therefore some BIOSs leave garbage values in the _TSS Power field(s).
 818      * In this case, it is best to just return the _TSS package as-is.
 819      * (May, 2011)
 820      */
 821     Status = AcpiNsGetNode (Info->Node, "^_PSS",
 822         ACPI_NS_NO_UPSEARCH, &Node);
 823     if (ACPI_SUCCESS (Status))
 824     {
 825         return (AE_OK);
 826     }
 827 
 828     Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 5, 1,
 829                 ACPI_SORT_DESCENDING, "PowerDissipation");
 830 
 831     return (Status);
 832 }
 833 
 834 
 835 /******************************************************************************
 836  *
 837  * FUNCTION:    AcpiNsCheckSortedList
 838  *
 839  * PARAMETERS:  Info                - Method execution information block
 840  *              ReturnObject        - Pointer to the top-level returned object
 841  *              StartIndex          - Index of the first sub-package
 842  *              ExpectedCount       - Minimum length of each sub-package
 843  *              SortIndex           - Sub-package entry to sort on
 844  *              SortDirection       - Ascending or descending
 845  *              SortKeyName         - Name of the SortIndex field
 846  *
 847  * RETURN:      Status. AE_OK if the list is valid and is sorted correctly or
 848  *              has been repaired by sorting the list.
 849  *
 850  * DESCRIPTION: Check if the package list is valid and sorted correctly by the
 851  *              SortIndex. If not, then sort the list.
 852  *
 853  *****************************************************************************/
 854 
 855 static ACPI_STATUS
 856 AcpiNsCheckSortedList (
 857     ACPI_EVALUATE_INFO      *Info,
 858     ACPI_OPERAND_OBJECT     *ReturnObject,
 859     UINT32                  StartIndex,
 860     UINT32                  ExpectedCount,
 861     UINT32                  SortIndex,
 862     UINT8                   SortDirection,
 863     char                    *SortKeyName)
 864 {
 865     UINT32                  OuterElementCount;
 866     ACPI_OPERAND_OBJECT     **OuterElements;
 867     ACPI_OPERAND_OBJECT     **Elements;
 868     ACPI_OPERAND_OBJECT     *ObjDesc;
 869     UINT32                  i;
 870     UINT32                  PreviousValue;
 871 
 872 
 873     ACPI_FUNCTION_NAME (NsCheckSortedList);
 874 
 875 
 876     /* The top-level object must be a package */
 877 
 878     if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
 879     {
 880         return (AE_AML_OPERAND_TYPE);
 881     }
 882 
 883     /*
 884      * NOTE: assumes list of sub-packages contains no NULL elements.
 885      * Any NULL elements should have been removed by earlier call
 886      * to AcpiNsRemoveNullElements.
 887      */
 888     OuterElementCount = ReturnObject->Package.Count;
 889     if (!OuterElementCount || StartIndex >= OuterElementCount)
 890     {
 891         return (AE_AML_PACKAGE_LIMIT);
 892     }
 893 
 894     OuterElements = &ReturnObject->Package.Elements[StartIndex];
 895     OuterElementCount -= StartIndex;
 896 
 897     PreviousValue = 0;
 898     if (SortDirection == ACPI_SORT_DESCENDING)
 899     {
 900         PreviousValue = ACPI_UINT32_MAX;
 901     }
 902 
 903     /* Examine each subpackage */
 904 
 905     for (i = 0; i < OuterElementCount; i++)
 906     {
 907         /* Each element of the top-level package must also be a package */
 908 
 909         if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE)
 910         {
 911             return (AE_AML_OPERAND_TYPE);
 912         }
 913 
 914         /* Each sub-package must have the minimum length */
 915 
 916         if ((*OuterElements)->Package.Count < ExpectedCount)
 917         {
 918             return (AE_AML_PACKAGE_LIMIT);
 919         }
 920 
 921         Elements = (*OuterElements)->Package.Elements;
 922         ObjDesc = Elements[SortIndex];
 923 
 924         if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
 925         {
 926             return (AE_AML_OPERAND_TYPE);
 927         }
 928 
 929         /*
 930          * The list must be sorted in the specified order. If we detect a
 931          * discrepancy, sort the entire list.
 932          */
 933         if (((SortDirection == ACPI_SORT_ASCENDING) &&
 934                 (ObjDesc->Integer.Value < PreviousValue)) ||
 935             ((SortDirection == ACPI_SORT_DESCENDING) &&
 936                 (ObjDesc->Integer.Value > PreviousValue)))
 937         {
 938             AcpiNsSortList (&ReturnObject->Package.Elements[StartIndex],
 939                 OuterElementCount, SortIndex, SortDirection);
 940 
 941             Info->ReturnFlags |= ACPI_OBJECT_REPAIRED;
 942 
 943             ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
 944                 "%s: Repaired unsorted list - now sorted by %s\n",
 945                 Info->FullPathname, SortKeyName));
 946             return (AE_OK);
 947         }
 948 
 949         PreviousValue = (UINT32) ObjDesc->Integer.Value;
 950         OuterElements++;
 951     }
 952 
 953     return (AE_OK);
 954 }
 955 
 956 
 957 /******************************************************************************
 958  *
 959  * FUNCTION:    AcpiNsSortList
 960  *
 961  * PARAMETERS:  Elements            - Package object element list
 962  *              Count               - Element count for above
 963  *              Index               - Sort by which package element
 964  *              SortDirection       - Ascending or Descending sort
 965  *
 966  * RETURN:      None
 967  *
 968  * DESCRIPTION: Sort the objects that are in a package element list.
 969  *
 970  * NOTE: Assumes that all NULL elements have been removed from the package,
 971  *       and that all elements have been verified to be of type Integer.
 972  *
 973  *****************************************************************************/
 974 
 975 static void
 976 AcpiNsSortList (
 977     ACPI_OPERAND_OBJECT     **Elements,
 978     UINT32                  Count,
 979     UINT32                  Index,
 980     UINT8                   SortDirection)
 981 {
 982     ACPI_OPERAND_OBJECT     *ObjDesc1;
 983     ACPI_OPERAND_OBJECT     *ObjDesc2;
 984     ACPI_OPERAND_OBJECT     *TempObj;
 985     UINT32                  i;
 986     UINT32                  j;
 987 
 988 
 989     /* Simple bubble sort */
 990 
 991     for (i = 1; i < Count; i++)
 992     {
 993         for (j = (Count - 1); j >= i; j--)
 994         {
 995             ObjDesc1 = Elements[j-1]->Package.Elements[Index];
 996             ObjDesc2 = Elements[j]->Package.Elements[Index];
 997 
 998             if (((SortDirection == ACPI_SORT_ASCENDING) &&
 999                     (ObjDesc1->Integer.Value > ObjDesc2->Integer.Value)) ||
1000 
1001                 ((SortDirection == ACPI_SORT_DESCENDING) &&
1002                     (ObjDesc1->Integer.Value < ObjDesc2->Integer.Value)))
1003             {
1004                 TempObj = Elements[j-1];
1005                 Elements[j-1] = Elements[j];
1006                 Elements[j] = TempObj;
1007             }
1008         }
1009     }
1010 }
1011 
1012 
1013 /******************************************************************************
1014  *
1015  * FUNCTION:    AcpiNsRemoveElement
1016  *
1017  * PARAMETERS:  ObjDesc             - Package object element list
1018  *              Index               - Index of element to remove
1019  *
1020  * RETURN:      None
1021  *
1022  * DESCRIPTION: Remove the requested element of a package and delete it.
1023  *
1024  *****************************************************************************/
1025 
1026 static void
1027 AcpiNsRemoveElement (
1028     ACPI_OPERAND_OBJECT     *ObjDesc,
1029     UINT32                  Index)
1030 {
1031     ACPI_OPERAND_OBJECT     **Source;
1032     ACPI_OPERAND_OBJECT     **Dest;
1033     UINT32                  Count;
1034     UINT32                  NewCount;
1035     UINT32                  i;
1036 
1037 
1038     ACPI_FUNCTION_NAME (NsRemoveElement);
1039 
1040 
1041     Count = ObjDesc->Package.Count;
1042     NewCount = Count - 1;
1043 
1044     Source = ObjDesc->Package.Elements;
1045     Dest = Source;
1046 
1047     /* Examine all elements of the package object, remove matched index */
1048 
1049     for (i = 0; i < Count; i++)
1050     {
1051         if (i == Index)
1052         {
1053             AcpiUtRemoveReference (*Source); /* Remove one ref for being in pkg */
1054             AcpiUtRemoveReference (*Source);
1055         }
1056         else
1057         {
1058             *Dest = *Source;
1059             Dest++;
1060         }
1061         Source++;
1062     }
1063 
1064     /* NULL terminate list and update the package count */
1065 
1066     *Dest = NULL;
1067     ObjDesc->Package.Count = NewCount;
1068 }