diff options
Diffstat (limited to 'source/components/namespace/nsrepair2.c')
| -rw-r--r-- | source/components/namespace/nsrepair2.c | 304 | 
1 files changed, 271 insertions, 33 deletions
| diff --git a/source/components/namespace/nsrepair2.c b/source/components/namespace/nsrepair2.c index 63fb36dd279a..0dcfaadf0ee1 100644 --- a/source/components/namespace/nsrepair2.c +++ b/source/components/namespace/nsrepair2.c @@ -86,6 +86,11 @@ AcpiNsRepair_CID (      ACPI_OPERAND_OBJECT     **ReturnObjectPtr);  static ACPI_STATUS +AcpiNsRepair_CST ( +    ACPI_EVALUATE_INFO      *Info, +    ACPI_OPERAND_OBJECT     **ReturnObjectPtr); + +static ACPI_STATUS  AcpiNsRepair_FDE (      ACPI_EVALUATE_INFO      *Info,      ACPI_OPERAND_OBJECT     **ReturnObjectPtr); @@ -96,6 +101,11 @@ AcpiNsRepair_HID (      ACPI_OPERAND_OBJECT     **ReturnObjectPtr);  static ACPI_STATUS +AcpiNsRepair_PRT ( +    ACPI_EVALUATE_INFO      *Info, +    ACPI_OPERAND_OBJECT     **ReturnObjectPtr); + +static ACPI_STATUS  AcpiNsRepair_PSS (      ACPI_EVALUATE_INFO      *Info,      ACPI_OPERAND_OBJECT     **ReturnObjectPtr); @@ -109,11 +119,22 @@ static ACPI_STATUS  AcpiNsCheckSortedList (      ACPI_EVALUATE_INFO      *Info,      ACPI_OPERAND_OBJECT     *ReturnObject, +    UINT32                  StartIndex,      UINT32                  ExpectedCount,      UINT32                  SortIndex,      UINT8                   SortDirection,      char                    *SortKeyName); +/* Values for SortDirection above */ + +#define ACPI_SORT_ASCENDING     0 +#define ACPI_SORT_DESCENDING    1 + +static void +AcpiNsRemoveElement ( +    ACPI_OPERAND_OBJECT     *ObjDesc, +    UINT32                  Index); +  static void  AcpiNsSortList (      ACPI_OPERAND_OBJECT     **Elements, @@ -121,11 +142,6 @@ AcpiNsSortList (      UINT32                  Index,      UINT8                   SortDirection); -/* Values for SortDirection above */ - -#define ACPI_SORT_ASCENDING     0 -#define ACPI_SORT_DESCENDING    1 -  /*   * This table contains the names of the predefined methods for which we can @@ -135,9 +151,11 @@ AcpiNsSortList (   *   * _ALR: Sort the list ascending by AmbientIlluminance   * _CID: Strings: uppercase all, remove any leading asterisk + * _CST: Sort the list ascending by C state type   * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs   * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs   * _HID: Strings: uppercase all, remove any leading asterisk + * _PRT: Fix reversed SourceName and SourceIndex   * _PSS: Sort the list descending by Power   * _TSS: Sort the list descending by Power   * @@ -152,9 +170,11 @@ static const ACPI_REPAIR_INFO       AcpiNsRepairableNames[] =  {      {"_ALR", AcpiNsRepair_ALR},      {"_CID", AcpiNsRepair_CID}, +    {"_CST", AcpiNsRepair_CST},      {"_FDE", AcpiNsRepair_FDE},      {"_GTM", AcpiNsRepair_FDE},     /* _GTM has same repair as _FDE */      {"_HID", AcpiNsRepair_HID}, +    {"_PRT", AcpiNsRepair_PRT},      {"_PSS", AcpiNsRepair_PSS},      {"_TSS", AcpiNsRepair_TSS},      {{0,0,0,0}, NULL}               /* Table terminator */ @@ -267,7 +287,7 @@ AcpiNsRepair_ALR (      ACPI_STATUS             Status; -    Status = AcpiNsCheckSortedList (Info, ReturnObject, 2, 1, +    Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 2, 1,                  ACPI_SORT_ASCENDING, "AmbientIlluminance");      return (Status); @@ -354,6 +374,7 @@ AcpiNsRepair_FDE (          break;      default: +          return (AE_AML_OPERAND_TYPE);      } @@ -446,6 +467,97 @@ AcpiNsRepair_CID (  /******************************************************************************   * + * FUNCTION:    AcpiNsRepair_CST + * + * PARAMETERS:  Info                - Method execution information block + *              ReturnObjectPtr     - Pointer to the object returned from the + *                                    evaluation of a method or object + * + * RETURN:      Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _CST object: + *              1. Sort the list ascending by C state type + *              2. Ensure type cannot be zero + *              3. A sub-package count of zero means _CST is meaningless + *              4. Count must match the number of C state sub-packages + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsRepair_CST ( +    ACPI_EVALUATE_INFO      *Info, +    ACPI_OPERAND_OBJECT     **ReturnObjectPtr) +{ +    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr; +    ACPI_OPERAND_OBJECT     **OuterElements; +    UINT32                  OuterElementCount; +    ACPI_OPERAND_OBJECT     *ObjDesc; +    ACPI_STATUS             Status; +    BOOLEAN                 Removing; +    UINT32                  i; + + +    ACPI_FUNCTION_NAME (NsRepair_CST); + + +    /* +     * Entries (subpackages) in the _CST Package must be sorted by the +     * C-state type, in ascending order. +     */ +    Status = AcpiNsCheckSortedList (Info, ReturnObject, 1, 4, 1, +                ACPI_SORT_ASCENDING, "C-State Type"); +    if (ACPI_FAILURE (Status)) +    { +        return (Status); +    } + +    /* +     * We now know the list is correctly sorted by C-state type. Check if +     * the C-state type values are proportional. +     */ +    OuterElementCount = ReturnObject->Package.Count - 1; +    i = 0; +    while (i < OuterElementCount) +    { +        OuterElements = &ReturnObject->Package.Elements[i + 1]; +        Removing = FALSE; + +        if ((*OuterElements)->Package.Count == 0) +        { +            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, +                "SubPackage[%u] - removing entry due to zero count", i)); +            Removing = TRUE; +        } + +        ObjDesc = (*OuterElements)->Package.Elements[1]; /* Index1 = Type */ +        if ((UINT32) ObjDesc->Integer.Value == 0) +        { +            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, +                "SubPackage[%u] - removing entry due to invalid Type(0)", i)); +            Removing = TRUE; +        } + +        if (Removing) +        { +            AcpiNsRemoveElement (ReturnObject, i + 1); +            OuterElementCount--; +        } +        else +        { +            i++; +        } +    } + +    /* Update top-level package count, Type "Integer" checked elsewhere */ + +    ObjDesc = ReturnObject->Package.Elements[0]; +    ObjDesc->Integer.Value = OuterElementCount; +    return (AE_OK); +} + + +/****************************************************************************** + *   * FUNCTION:    AcpiNsRepair_HID   *   * PARAMETERS:  Info                - Method execution information block @@ -536,7 +648,7 @@ AcpiNsRepair_HID (  /******************************************************************************   * - * FUNCTION:    AcpiNsRepair_TSS + * FUNCTION:    AcpiNsRepair_PRT   *   * PARAMETERS:  Info                - Method execution information block   *              ReturnObjectPtr     - Pointer to the object returned from the @@ -544,40 +656,57 @@ AcpiNsRepair_HID (   *   * RETURN:      Status. AE_OK if object is OK or was repaired successfully   * - * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list - *              descending by the power dissipation values. + * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed + *              SourceName and SourceIndex field, a common BIOS bug.   *   *****************************************************************************/  static ACPI_STATUS -AcpiNsRepair_TSS ( +AcpiNsRepair_PRT (      ACPI_EVALUATE_INFO      *Info,      ACPI_OPERAND_OBJECT     **ReturnObjectPtr)  { -    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr; -    ACPI_STATUS             Status; -    ACPI_NAMESPACE_NODE     *Node; +    ACPI_OPERAND_OBJECT     *PackageObject = *ReturnObjectPtr; +    ACPI_OPERAND_OBJECT     **TopObjectList; +    ACPI_OPERAND_OBJECT     **SubObjectList; +    ACPI_OPERAND_OBJECT     *ObjDesc; +    UINT32                  ElementCount; +    UINT32                  Index; -    /* -     * We can only sort the _TSS return package if there is no _PSS in the -     * same scope. This is because if _PSS is present, the ACPI specification -     * dictates that the _TSS Power Dissipation field is to be ignored, and -     * therefore some BIOSs leave garbage values in the _TSS Power field(s). -     * In this case, it is best to just return the _TSS package as-is. -     * (May, 2011) -     */ -    Status = AcpiNsGetNode (Info->Node, "^_PSS", -        ACPI_NS_NO_UPSEARCH, &Node); -    if (ACPI_SUCCESS (Status)) +    /* Each element in the _PRT package is a subpackage */ + +    TopObjectList = PackageObject->Package.Elements; +    ElementCount = PackageObject->Package.Count; + +    for (Index = 0; Index < ElementCount; Index++)      { -        return (AE_OK); -    } +        SubObjectList = (*TopObjectList)->Package.Elements; -    Status = AcpiNsCheckSortedList (Info, ReturnObject, 5, 1, -                ACPI_SORT_DESCENDING, "PowerDissipation"); +        /* +         * If the BIOS has erroneously reversed the _PRT SourceName (index 2) +         * and the SourceIndex (index 3), fix it. _PRT is important enough to +         * workaround this BIOS error. This also provides compatibility with +         * other ACPI implementations. +         */ +        ObjDesc = SubObjectList[3]; +        if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)) +        { +            SubObjectList[3] = SubObjectList[2]; +            SubObjectList[2] = ObjDesc; +            Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; -    return (Status); +            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, +                "PRT[%X]: Fixed reversed SourceName and SourceIndex", +                Index)); +        } + +        /* Point to the next ACPI_OPERAND_OBJECT in the top level package */ + +        TopObjectList++; +    } + +    return (AE_OK);  } @@ -619,7 +748,7 @@ AcpiNsRepair_PSS (       * incorrectly sorted, sort it. We sort by CpuFrequency, since this       * should be proportional to the power.       */ -    Status =AcpiNsCheckSortedList (Info, ReturnObject, 6, 0, +    Status =AcpiNsCheckSortedList (Info, ReturnObject, 0, 6, 0,                  ACPI_SORT_DESCENDING, "CpuFrequency");      if (ACPI_FAILURE (Status))      { @@ -656,10 +785,58 @@ AcpiNsRepair_PSS (  /******************************************************************************   * + * FUNCTION:    AcpiNsRepair_TSS + * + * PARAMETERS:  Info                - Method execution information block + *              ReturnObjectPtr     - Pointer to the object returned from the + *                                    evaluation of a method or object + * + * RETURN:      Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list + *              descending by the power dissipation values. + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsRepair_TSS ( +    ACPI_EVALUATE_INFO      *Info, +    ACPI_OPERAND_OBJECT     **ReturnObjectPtr) +{ +    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr; +    ACPI_STATUS             Status; +    ACPI_NAMESPACE_NODE     *Node; + + +    /* +     * We can only sort the _TSS return package if there is no _PSS in the +     * same scope. This is because if _PSS is present, the ACPI specification +     * dictates that the _TSS Power Dissipation field is to be ignored, and +     * therefore some BIOSs leave garbage values in the _TSS Power field(s). +     * In this case, it is best to just return the _TSS package as-is. +     * (May, 2011) +     */ +    Status = AcpiNsGetNode (Info->Node, "^_PSS", +        ACPI_NS_NO_UPSEARCH, &Node); +    if (ACPI_SUCCESS (Status)) +    { +        return (AE_OK); +    } + +    Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 5, 1, +                ACPI_SORT_DESCENDING, "PowerDissipation"); + +    return (Status); +} + + +/****************************************************************************** + *   * FUNCTION:    AcpiNsCheckSortedList   *   * PARAMETERS:  Info                - Method execution information block   *              ReturnObject        - Pointer to the top-level returned object + *              StartIndex          - Index of the first sub-package   *              ExpectedCount       - Minimum length of each sub-package   *              SortIndex           - Sub-package entry to sort on   *              SortDirection       - Ascending or descending @@ -677,6 +854,7 @@ static ACPI_STATUS  AcpiNsCheckSortedList (      ACPI_EVALUATE_INFO      *Info,      ACPI_OPERAND_OBJECT     *ReturnObject, +    UINT32                  StartIndex,      UINT32                  ExpectedCount,      UINT32                  SortIndex,      UINT8                   SortDirection, @@ -705,13 +883,15 @@ AcpiNsCheckSortedList (       * Any NULL elements should have been removed by earlier call       * to AcpiNsRemoveNullElements.       */ -    OuterElements = ReturnObject->Package.Elements;      OuterElementCount = ReturnObject->Package.Count; -    if (!OuterElementCount) +    if (!OuterElementCount || StartIndex >= OuterElementCount)      {          return (AE_AML_PACKAGE_LIMIT);      } +    OuterElements = &ReturnObject->Package.Elements[StartIndex]; +    OuterElementCount -= StartIndex; +      PreviousValue = 0;      if (SortDirection == ACPI_SORT_DESCENDING)      { @@ -753,7 +933,7 @@ AcpiNsCheckSortedList (              ((SortDirection == ACPI_SORT_DESCENDING) &&                  (ObjDesc->Integer.Value > PreviousValue)))          { -            AcpiNsSortList (ReturnObject->Package.Elements, +            AcpiNsSortList (&ReturnObject->Package.Elements[StartIndex],                  OuterElementCount, SortIndex, SortDirection);              Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; @@ -826,3 +1006,61 @@ AcpiNsSortList (          }      }  } + + +/****************************************************************************** + * + * FUNCTION:    AcpiNsRemoveElement + * + * PARAMETERS:  ObjDesc             - Package object element list + *              Index               - Index of element to remove + * + * RETURN:      None + * + * DESCRIPTION: Remove the requested element of a package and delete it. + * + *****************************************************************************/ + +static void +AcpiNsRemoveElement ( +    ACPI_OPERAND_OBJECT     *ObjDesc, +    UINT32                  Index) +{ +    ACPI_OPERAND_OBJECT     **Source; +    ACPI_OPERAND_OBJECT     **Dest; +    UINT32                  Count; +    UINT32                  NewCount; +    UINT32                  i; + + +    ACPI_FUNCTION_NAME (NsRemoveElement); + + +    Count = ObjDesc->Package.Count; +    NewCount = Count - 1; + +    Source = ObjDesc->Package.Elements; +    Dest = Source; + +    /* Examine all elements of the package object, remove matched index */ + +    for (i = 0; i < Count; i++) +    { +        if (i == Index) +        { +            AcpiUtRemoveReference (*Source); /* Remove one ref for being in pkg */ +            AcpiUtRemoveReference (*Source); +        } +        else +        { +            *Dest = *Source; +            Dest++; +        } +        Source++; +    } + +    /* NULL terminate list and update the package count */ + +    *Dest = NULL; +    ObjDesc->Package.Count = NewCount; +} | 
