diff options
Diffstat (limited to 'source/components')
25 files changed, 761 insertions, 462 deletions
| diff --git a/source/components/disassembler/dmbuffer.c b/source/components/disassembler/dmbuffer.c index 42920500ba2d7..7e2b6f90a71b8 100644 --- a/source/components/disassembler/dmbuffer.c +++ b/source/components/disassembler/dmbuffer.c @@ -439,12 +439,16 @@ AcpiDmIsUnicodeBuffer (          return (FALSE);      } -    /* For each word, 1st byte must be ascii (1-0x7F), 2nd byte must be zero */ - +    /* +     * For each word, 1st byte must be printable ascii, and the +     * 2nd byte must be zero. This does not allow for escape +     * sequences, but it is the most secure way to detect a +     * unicode string. +     */      for (i = 0; i < (ByteCount - 2); i += 2)      {          if ((ByteData[i] == 0) || -            (ByteData[i] > 0x7F) || +            !(isprint (ByteData[i])) ||              (ByteData[(ACPI_SIZE) i + 1] != 0))          {              return (FALSE); @@ -507,12 +511,27 @@ AcpiDmIsStringBuffer (          return (FALSE);      } +    /* +     * Check for a possible standalone resource EndTag, ignore it +     * here. However, this sequence is also the string "Y", but +     * this seems rare enough to be acceptable. +     */ +    if ((ByteCount == 2) && (ByteData[0] == 0x79)) +    { +        return (FALSE); +    } + +    /* Check all bytes for ASCII */ +      for (i = 0; i < (ByteCount - 1); i++)      { -        /* TBD: allow some escapes (non-ascii chars). +        /* +         * TBD: allow some escapes (non-ascii chars).           * they will be handled in the string output routine           */ +        /* Not a string if not printable ascii */ +          if (!isprint (ByteData[i]))          {              return (FALSE); diff --git a/source/components/disassembler/dmcstyle.c b/source/components/disassembler/dmcstyle.c index 939168f242572..f5e9560a90712 100644 --- a/source/components/disassembler/dmcstyle.c +++ b/source/components/disassembler/dmcstyle.c @@ -73,6 +73,11 @@ AcpiDmIsTargetAnOperand (      ACPI_PARSE_OBJECT       *Operand,      BOOLEAN                 TopLevel); +static BOOLEAN +AcpiDmIsOptimizationIgnored ( +    ACPI_PARSE_OBJECT       *StoreOp, +    ACPI_PARSE_OBJECT       *StoreArgument); +  /*******************************************************************************   * @@ -95,12 +100,10 @@ AcpiDmCheckForSymbolicOpcode (      ACPI_OP_WALK_INFO       *Info)  {      char                    *OperatorSymbol = NULL; -    ACPI_PARSE_OBJECT       *Child1; -    ACPI_PARSE_OBJECT       *Child2; +    ACPI_PARSE_OBJECT       *Argument1; +    ACPI_PARSE_OBJECT       *Argument2;      ACPI_PARSE_OBJECT       *Target; -    ACPI_PARSE_OBJECT       *GrandChild1; -    ACPI_PARSE_OBJECT       *GrandChild2; -    ACPI_PARSE_OBJECT       *GrandTarget = NULL; +    ACPI_PARSE_OBJECT       *Target2;      /* Exit immediately if ASL+ not enabled */ @@ -110,25 +113,17 @@ AcpiDmCheckForSymbolicOpcode (          return (FALSE);      } -    /* Check for a non-ASL+ statement, propagate the flag */ - -    if (Op->Common.Parent->Common.DisasmFlags & ACPI_PARSEOP_LEGACY_ASL_ONLY) -    { -        Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; -        return (FALSE); -    } -      /* Get the first operand */ -    Child1 = AcpiPsGetArg (Op, 0); -    if (!Child1) +    Argument1 = AcpiPsGetArg (Op, 0); +    if (!Argument1)      {          return (FALSE);      }      /* Get the second operand */ -    Child2 = Child1->Common.Next; +    Argument2 = Argument1->Common.Next;      /* Setup the operator string for this opcode */ @@ -202,7 +197,7 @@ AcpiDmCheckForSymbolicOpcode (           * LNotEqual, LLessEqual, and LGreaterEqual. There are           * no actual AML opcodes for these operators.           */ -        switch (Child1->Common.AmlOpcode) +        switch (Argument1->Common.AmlOpcode)          {          case AML_LEQUAL_OP:              OperatorSymbol = " != "; @@ -224,19 +219,18 @@ AcpiDmCheckForSymbolicOpcode (              return (TRUE);          } -        Child1->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX; +        Argument1->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;          Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX; -        Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT;          /* Save symbol string in the next child (not peer) */ -        Child2 = AcpiPsGetArg (Child1, 0); -        if (!Child2) +        Argument2 = AcpiPsGetArg (Argument1, 0); +        if (!Argument2)          {              return (FALSE);          } -        Child2->Common.OperatorSymbol = OperatorSymbol; +        Argument2->Common.OperatorSymbol = OperatorSymbol;          return (TRUE);      case AML_INDEX_OP: @@ -246,10 +240,10 @@ AcpiDmCheckForSymbolicOpcode (           * the symbolic operators for Index(). It doesn't make sense to           * use Index() with a constant anyway.           */ -        if ((Child1->Common.AmlOpcode == AML_STRING_OP)  || -            (Child1->Common.AmlOpcode == AML_BUFFER_OP)  || -            (Child1->Common.AmlOpcode == AML_PACKAGE_OP) || -            (Child1->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) +        if ((Argument1->Common.AmlOpcode == AML_STRING_OP)  || +            (Argument1->Common.AmlOpcode == AML_BUFFER_OP)  || +            (Argument1->Common.AmlOpcode == AML_PACKAGE_OP) || +            (Argument1->Common.AmlOpcode == AML_VAR_PACKAGE_OP))          {              Op->Common.DisasmFlags |= ACPI_PARSEOP_CLOSING_PAREN;              return (FALSE); @@ -257,8 +251,8 @@ AcpiDmCheckForSymbolicOpcode (          /* Index operator is [] */ -        Child1->Common.OperatorSymbol = " ["; -        Child2->Common.OperatorSymbol = "]"; +        Argument1->Common.OperatorSymbol = " ["; +        Argument2->Common.OperatorSymbol = "]";          break;      /* Unary operators */ @@ -280,7 +274,7 @@ AcpiDmCheckForSymbolicOpcode (          return (FALSE);      } -    if (Child1->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX) +    if (Argument1->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX)      {          return (TRUE);      } @@ -291,9 +285,9 @@ AcpiDmCheckForSymbolicOpcode (       * deferring symbol output until after the first operand has been       * emitted.       */ -    if (!Child1->Common.OperatorSymbol) +    if (!Argument1->Common.OperatorSymbol)      { -        Child1->Common.OperatorSymbol = OperatorSymbol; +        Argument1->Common.OperatorSymbol = OperatorSymbol;      }      /* @@ -323,23 +317,58 @@ AcpiDmCheckForSymbolicOpcode (          /* Target is 3rd operand */ -        Target = Child2->Common.Next; +        Target = Argument2->Common.Next;          if (Op->Common.AmlOpcode == AML_DIVIDE_OP)          { +            Target2 = Target->Common.Next; +              /*               * Divide has an extra target operand (Remainder). -             * If this extra target is specified, it cannot be converted -             * to a C-style operator +             * Default behavior is to simply ignore ASL+ conversion +             * if the remainder target (modulo) is specified.               */ -            if (AcpiDmIsValidTarget (Target)) +            if (!AcpiGbl_DoDisassemblerOptimizations)              { -                Child1->Common.OperatorSymbol = NULL; -                Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; -                return (FALSE); +                if (AcpiDmIsValidTarget (Target)) +                { +                    Argument1->Common.OperatorSymbol = NULL; +                    Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; +                    return (FALSE); +                } + +                Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; +                Target = Target2;              } +            else +            { +                /* +                 * Divide has an extra target operand (Remainder). +                 * If both targets are specified, it cannot be converted +                 * to a C-style operator. +                 */ +                if (AcpiDmIsValidTarget (Target) && +                    AcpiDmIsValidTarget (Target2)) +                { +                    Argument1->Common.OperatorSymbol = NULL; +                    Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; +                    return (FALSE); +                } + +                if (AcpiDmIsValidTarget (Target)) /* Only first Target is valid (remainder) */ +                { +                    /* Convert the Divide to Modulo */ + +                    Op->Common.AmlOpcode = AML_MOD_OP; -            Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; -            Target = Target->Common.Next; +                    Argument1->Common.OperatorSymbol = " % "; +                    Target2->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; +                } +                else /* Only second Target (quotient) is valid */ +                { +                    Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; +                    Target = Target2; +                } +            }          }          /* Parser should ensure there is at least a placeholder target */ @@ -351,13 +380,6 @@ AcpiDmCheckForSymbolicOpcode (          if (!AcpiDmIsValidTarget (Target))          { -            if (Op->Common.Parent->Common.AmlOpcode == AML_STORE_OP) -            { -                Op->Common.DisasmFlags = 0; -                Child1->Common.OperatorSymbol = NULL; -                return (FALSE); -            } -              /* Not a valid target (placeholder only, from parser) */              break;          } @@ -390,8 +412,8 @@ AcpiDmCheckForSymbolicOpcode (               *      Add (B, A, A) --> A += B               *      Add (B, C, A) --> A = (B + C)               */ -            if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE)) || -                (AcpiDmIsTargetAnOperand (Target, Child2, TRUE))) +            if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE)) || +                (AcpiDmIsTargetAnOperand (Target, Argument2, TRUE)))              {                  Target->Common.OperatorSymbol =                      AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode); @@ -399,7 +421,7 @@ AcpiDmCheckForSymbolicOpcode (                  /* Convert operator to compound assignment */                  Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT; -                Child1->Common.OperatorSymbol = NULL; +                Argument1->Common.OperatorSymbol = NULL;                  return (TRUE);              }              break; @@ -419,7 +441,7 @@ AcpiDmCheckForSymbolicOpcode (               *      Subtract (A, B, A) --> A -= B               *      Subtract (B, A, A) --> A = (B - A)               */ -            if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE))) +            if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE)))              {                  Target->Common.OperatorSymbol =                      AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode); @@ -427,7 +449,7 @@ AcpiDmCheckForSymbolicOpcode (                  /* Convert operator to compound assignment */                  Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT; -                Child1->Common.OperatorSymbol = NULL; +                Argument1->Common.OperatorSymbol = NULL;                  return (TRUE);              }              break; @@ -481,7 +503,7 @@ AcpiDmCheckForSymbolicOpcode (          /* Target is optional, 3rd operand */ -        Target = Child2->Common.Next; +        Target = Argument2->Common.Next;          if (AcpiDmIsValidTarget (Target))          {              AcpiDmPromoteTarget (Op, Target); @@ -495,75 +517,23 @@ AcpiDmCheckForSymbolicOpcode (      case AML_STORE_OP:          /* -         * Target is the 2nd operand. -         * We know the target is valid, it is not optional. +         * For Store, the Target is the 2nd operand. We know the target +         * is valid, because it is not optional.           * -         * The following block implements "Ignore conversion if a store -         * is followed by a math/bit operator that has no target". Used -         * only for the ASL test suite. +         * Ignore any optimizations/folding if flag is set. +         * Used for iASL/disassembler test suite only.           */ -        if (!AcpiGbl_DoDisassemblerOptimizations) +        if (AcpiDmIsOptimizationIgnored (Op, Argument1))          { -            switch (Child1->Common.AmlOpcode) -            { -            /* This operator has two operands and two targets */ - -            case AML_DIVIDE_OP: - -                GrandChild1 = Child1->Common.Value.Arg; -                GrandChild2 = GrandChild1->Common.Next; -                GrandTarget = GrandChild2->Common.Next; - -                if (GrandTarget && !AcpiDmIsValidTarget (GrandTarget)) -                { -                    Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; -                    return (FALSE); -                } -                GrandTarget = GrandTarget->Common.Next; -                break; - -            case AML_ADD_OP: -            case AML_SUBTRACT_OP: -            case AML_MULTIPLY_OP: -            case AML_MOD_OP: -            case AML_SHIFT_LEFT_OP: -            case AML_SHIFT_RIGHT_OP: -            case AML_BIT_AND_OP: -            case AML_BIT_OR_OP: -            case AML_BIT_XOR_OP: -            case AML_INDEX_OP: - -                /* These operators have two operands and a target */ - -                GrandChild1 = Child1->Common.Value.Arg; -                GrandChild2 = GrandChild1->Common.Next; -                GrandTarget = GrandChild2->Common.Next; -                break; - -            case AML_BIT_NOT_OP: - -                /* This operator has one operand and a target */ - -                GrandChild1 = Child1->Common.Value.Arg; -                GrandTarget = GrandChild1->Common.Next; -                break; - -            default: -                break; -            } - -            if (GrandTarget && !AcpiDmIsValidTarget (GrandTarget)) -            { -                Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; -                return (FALSE); -            } +            return (FALSE);          }          /* +         * Perform conversion.           * In the parse tree, simply swap the target with the           * source so that the target is processed first.           */ -        Target = Child1->Common.Next; +        Target = Argument1->Common.Next;          if (!Target)          {              return (FALSE); @@ -580,7 +550,7 @@ AcpiDmCheckForSymbolicOpcode (          /* Target is optional, 2nd operand */ -        Target = Child1->Common.Next; +        Target = Argument1->Common.Next;          if (!Target)          {              return (FALSE); @@ -605,23 +575,129 @@ AcpiDmCheckForSymbolicOpcode (          break;      } +    /* All other operators, emit an open paren */ + +    AcpiOsPrintf ("("); +    return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION:    AcpiDmIsOptimizationIgnored + * + * PARAMETERS:  StoreOp             - Store operator parse object + *              StoreArgument       - Target associate with the Op + * + * RETURN:      TRUE if this Store operator should not be converted/removed. + * + * DESCRIPTION: The following function implements "Do not optimize if a + *              store is immediately followed by a math/bit operator that + *              has no target". + * + *              Function is ignored if DoDisassemblerOptimizations is TRUE. + *              This is the default, ignore this function. + * + *              Disables these types of optimizations, and simply emits + *              legacy ASL code: + *                  Store (Add (INT1, 4), INT2) --> Add (INT1, 4, INT2) + *                                              --> INT2 = INT1 + 4 + * + *                  Store (Not (INT1), INT2)    --> Not (INT1, INT2) + *                                              --> INT2 = ~INT1 + * + *              Used only for the ASL test suite. For the test suite, we + *              don't want to perform some optimizations to ensure binary + *              compatibility with the generation of the legacy ASL->AML. + *              In other words, for all test modules we want exactly: + *                  (ASL+ -> AML) == (ASL- -> AML) + * + ******************************************************************************/ + +static BOOLEAN +AcpiDmIsOptimizationIgnored ( +    ACPI_PARSE_OBJECT       *StoreOp, +    ACPI_PARSE_OBJECT       *StoreArgument) +{ +    ACPI_PARSE_OBJECT       *Argument1; +    ACPI_PARSE_OBJECT       *Argument2; +    ACPI_PARSE_OBJECT       *Target; + + +    /* No optimizations/folding for the typical case */ + +    if (AcpiGbl_DoDisassemblerOptimizations) +    { +        return (FALSE); +    } +      /* -     * Nodes marked with ACPI_PARSEOP_PARAMLIST don't need a parens -     * output here. We also need to check the parent to see if this op -     * is part of a compound test (!=, >=, <=). +     * Only a small subset of ASL/AML operators can be optimized. +     * Can only optimize/fold if there is no target (or targets) +     * specified for the operator. And of course, the operator +     * is surrrounded by a Store() operator.       */ -    if ((Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) || -       ((Op->Common.Parent->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) && -        (Op->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX))) +    switch (StoreArgument->Common.AmlOpcode)      { -        /* Do Nothing. Paren already generated */ -        return (TRUE); -    } +    case AML_ADD_OP: +    case AML_SUBTRACT_OP: +    case AML_MULTIPLY_OP: +    case AML_MOD_OP: +    case AML_SHIFT_LEFT_OP: +    case AML_SHIFT_RIGHT_OP: +    case AML_BIT_AND_OP: +    case AML_BIT_OR_OP: +    case AML_BIT_XOR_OP: +    case AML_INDEX_OP: -    /* All other operators, emit an open paren */ +        /* These operators have two arguments and one target */ -    AcpiOsPrintf ("("); -    return (TRUE); +        Argument1 = StoreArgument->Common.Value.Arg; +        Argument2 = Argument1->Common.Next; +        Target = Argument2->Common.Next; + +        if (!AcpiDmIsValidTarget (Target)) +        { +            StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; +            return (TRUE); +        } +        break; + +    case AML_DIVIDE_OP: + +        /* This operator has two arguments and two targets */ + +        Argument1 = StoreArgument->Common.Value.Arg; +        Argument2 = Argument1->Common.Next; +        Target = Argument2->Common.Next; + +        if (!AcpiDmIsValidTarget (Target) || +            !AcpiDmIsValidTarget (Target->Common.Next)) +        { +            StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; +            return (TRUE); +        } +        break; + +    case AML_BIT_NOT_OP: + +        /* This operator has one operand and one target */ + +        Argument1 = StoreArgument->Common.Value.Arg; +        Target = Argument1->Common.Next; + +        if (!AcpiDmIsValidTarget (Target)) +        { +            StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; +            return (TRUE); +        } +        break; + +    default: +        break; +    } + +    return (FALSE);  } @@ -643,8 +719,6 @@ void  AcpiDmCloseOperator (      ACPI_PARSE_OBJECT       *Op)  { -    BOOLEAN                 IsCStyleOp = FALSE; -      /* Always emit paren if ASL+ disassembly disabled */ @@ -654,8 +728,6 @@ AcpiDmCloseOperator (          return;      } -    /* Check for a non-ASL+ statement */ -      if (Op->Common.DisasmFlags & ACPI_PARSEOP_LEGACY_ASL_ONLY)      {          AcpiOsPrintf (")"); @@ -695,8 +767,6 @@ AcpiDmCloseOperator (          {              AcpiOsPrintf (")");          } - -        IsCStyleOp = TRUE;          break;      case AML_INDEX_OP: @@ -724,21 +794,7 @@ AcpiDmCloseOperator (          break;      } -    /* -     * Nodes marked with ACPI_PARSEOP_PARAMLIST don't need a parens -     * output here. We also need to check the parent to see if this op -     * is part of a compound test (!=, >=, <=). -     */ -    if (IsCStyleOp && -       ((Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) || -       ((Op->Common.Parent->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) && -        (Op->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX)))) -    { -        return; -    } -      AcpiOsPrintf (")"); -    return;  } diff --git a/source/components/disassembler/dmresrc.c b/source/components/disassembler/dmresrc.c index a486f1d892087..ee4a55fcfaa41 100644 --- a/source/components/disassembler/dmresrc.c +++ b/source/components/disassembler/dmresrc.c @@ -392,7 +392,8 @@ AcpiDmIsResourceTemplate (      ACPI_PARSE_OBJECT       *NextOp;      UINT8                   *Aml;      UINT8                   *EndAml; -    ACPI_SIZE               Length; +    UINT32                  BufferLength; +    UINT32                  DeclaredBufferLength;      /* This op must be a buffer */ @@ -402,8 +403,10 @@ AcpiDmIsResourceTemplate (          return (AE_TYPE);      } -    /* Get the ByteData list and length */ - +    /* +     * Get the declared length of the buffer. +     * This is the nn in "Buffer (nn)" +     */      NextOp = Op->Common.Value.Arg;      if (!NextOp)      { @@ -411,6 +414,10 @@ AcpiDmIsResourceTemplate (          return (AE_TYPE);      } +    DeclaredBufferLength = NextOp->Common.Value.Size; + +    /* Get the length of the raw initialization byte list */ +      NextOp = NextOp->Common.Next;      if (!NextOp)      { @@ -418,11 +425,22 @@ AcpiDmIsResourceTemplate (      }      Aml = NextOp->Named.Data; -    Length = (ACPI_SIZE) NextOp->Common.Value.Integer; +    BufferLength = NextOp->Common.Value.Size; + +    /* +     * Not a template if declared buffer length != actual length of the +     * intialization byte list. Because the resource macros will create +     * a buffer of the exact required length (buffer length will be equal +     * to the actual length). +     */ +    if (DeclaredBufferLength != BufferLength) +    { +        return (AE_TYPE); +    }      /* Walk the byte list, abort on any invalid descriptor type or length */ -    Status = AcpiUtWalkAmlResources (WalkState, Aml, Length, +    Status = AcpiUtWalkAmlResources (WalkState, Aml, BufferLength,          NULL, ACPI_CAST_INDIRECT_PTR (void, &EndAml));      if (ACPI_FAILURE (Status))      { @@ -435,7 +453,7 @@ AcpiDmIsResourceTemplate (       * of a ResourceTemplate, the buffer must not have any extra data after       * the EndTag.)       */ -    if ((Aml + Length - sizeof (AML_RESOURCE_END_TAG)) != EndAml) +    if ((Aml + BufferLength - sizeof (AML_RESOURCE_END_TAG)) != EndAml)      {          return (AE_AML_NO_RESOURCE_END_TAG);      } diff --git a/source/components/dispatcher/dsinit.c b/source/components/dispatcher/dsinit.c index 74e974da0315e..67c8d61c028a2 100644 --- a/source/components/dispatcher/dsinit.c +++ b/source/components/dispatcher/dsinit.c @@ -46,6 +46,7 @@  #include "acdispat.h"  #include "acnamesp.h"  #include "actables.h" +#include "acinterp.h"  #define _COMPONENT          ACPI_DISPATCHER          ACPI_MODULE_NAME    ("dsinit") @@ -231,23 +232,16 @@ AcpiDsInitializeObjects (      /* Walk entire namespace from the supplied root */ -    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); -    if (ACPI_FAILURE (Status)) -    { -        return_ACPI_STATUS (Status); -    } -      /*       * We don't use AcpiWalkNamespace since we do not want to acquire       * the namespace reader lock.       */      Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, StartNode, ACPI_UINT32_MAX, -        ACPI_NS_WALK_UNLOCK, AcpiDsInitOneObject, NULL, &Info, NULL); +        ACPI_NS_WALK_NO_UNLOCK, AcpiDsInitOneObject, NULL, &Info, NULL);      if (ACPI_FAILURE (Status))      {          ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace"));      } -    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);      Status = AcpiGetTableByIndex (TableIndex, &Table);      if (ACPI_FAILURE (Status)) diff --git a/source/components/dispatcher/dsmethod.c b/source/components/dispatcher/dsmethod.c index 4c4ff2270127d..92bdb2fc80f46 100644 --- a/source/components/dispatcher/dsmethod.c +++ b/source/components/dispatcher/dsmethod.c @@ -107,15 +107,12 @@ AcpiDsAutoSerializeMethod (          "Method auto-serialization parse [%4.4s] %p\n",          AcpiUtGetNodeName (Node), Node)); -    AcpiExEnterInterpreter (); -      /* Create/Init a root op for the method parse tree */      Op = AcpiPsAllocOp (AML_METHOD_OP, ObjDesc->Method.AmlStart);      if (!Op)      { -        Status = AE_NO_MEMORY; -        goto Unlock; +        return_ACPI_STATUS (AE_NO_MEMORY);      }      AcpiPsSetName (Op, Node->Name.Integer); @@ -127,8 +124,7 @@ AcpiDsAutoSerializeMethod (      if (!WalkState)      {          AcpiPsFreeOp (Op); -        Status = AE_NO_MEMORY; -        goto Unlock; +        return_ACPI_STATUS (AE_NO_MEMORY);      }      Status = AcpiDsInitAmlWalk (WalkState, Op, Node, @@ -147,8 +143,6 @@ AcpiDsAutoSerializeMethod (      Status = AcpiPsParseAml (WalkState);      AcpiPsDeleteParseTree (Op); -Unlock: -    AcpiExExitInterpreter ();      return_ACPI_STATUS (Status);  } @@ -784,26 +778,6 @@ AcpiDsTerminateControlMethod (          AcpiDsMethodDataDeleteAll (WalkState);          /* -         * If method is serialized, release the mutex and restore the -         * current sync level for this thread -         */ -        if (MethodDesc->Method.Mutex) -        { -            /* Acquisition Depth handles recursive calls */ - -            MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--; -            if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth) -            { -                WalkState->Thread->CurrentSyncLevel = -                    MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel; - -                AcpiOsReleaseMutex ( -                    MethodDesc->Method.Mutex->Mutex.OsMutex); -                MethodDesc->Method.Mutex->Mutex.ThreadId = 0; -            } -        } - -        /*           * Delete any namespace objects created anywhere within the           * namespace by the execution of this method. Unless:           * 1) This method is a module-level executable code method, in which @@ -836,6 +810,26 @@ AcpiDsTerminateControlMethod (                      ~ACPI_METHOD_MODIFIED_NAMESPACE;              }          } + +        /* +         * If method is serialized, release the mutex and restore the +         * current sync level for this thread +         */ +        if (MethodDesc->Method.Mutex) +        { +            /* Acquisition Depth handles recursive calls */ + +            MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--; +            if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth) +            { +                WalkState->Thread->CurrentSyncLevel = +                    MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel; + +                AcpiOsReleaseMutex ( +                    MethodDesc->Method.Mutex->Mutex.OsMutex); +                MethodDesc->Method.Mutex->Mutex.ThreadId = 0; +            } +        }      }      /* Decrement the thread count on the method */ diff --git a/source/components/dispatcher/dsopcode.c b/source/components/dispatcher/dsopcode.c index 1c6b34257092c..5cd9107d8669a 100644 --- a/source/components/dispatcher/dsopcode.c +++ b/source/components/dispatcher/dsopcode.c @@ -90,7 +90,7 @@ AcpiDsInitializeRegion (      /* Namespace is NOT locked */ -    Status = AcpiEvInitializeRegion (ObjDesc, FALSE); +    Status = AcpiEvInitializeRegion (ObjDesc);      return (Status);  } diff --git a/source/components/dispatcher/dswload2.c b/source/components/dispatcher/dswload2.c index ae076e2587cab..c0e4ad47e8971 100644 --- a/source/components/dispatcher/dswload2.c +++ b/source/components/dispatcher/dswload2.c @@ -626,23 +626,8 @@ AcpiDsLoad2EndOp (                  }              } -            AcpiExExitInterpreter ();              Status = AcpiEvInitializeRegion ( -                AcpiNsGetAttachedObject (Node), FALSE); -            AcpiExEnterInterpreter (); - -            if (ACPI_FAILURE (Status)) -            { -                /* -                 *  If AE_NOT_EXIST is returned, it is not fatal -                 *  because many regions get created before a handler -                 *  is installed for said region. -                 */ -                if (AE_NOT_EXIST == Status) -                { -                    Status = AE_OK; -                } -            } +                AcpiNsGetAttachedObject (Node));              break;          case AML_NAME_OP: diff --git a/source/components/events/evrgnini.c b/source/components/events/evrgnini.c index 51e3ce99aa736..171602a59c250 100644 --- a/source/components/events/evrgnini.c +++ b/source/components/events/evrgnini.c @@ -45,6 +45,7 @@  #include "accommon.h"  #include "acevents.h"  #include "acnamesp.h" +#include "acinterp.h"  #define _COMPONENT          ACPI_EVENTS          ACPI_MODULE_NAME    ("evrgnini") @@ -537,7 +538,6 @@ AcpiEvDefaultRegionSetup (   * FUNCTION:    AcpiEvInitializeRegion   *   * PARAMETERS:  RegionObj       - Region we are initializing - *              AcpiNsLocked    - Is namespace locked?   *   * RETURN:      Status   * @@ -555,21 +555,33 @@ AcpiEvDefaultRegionSetup (   * MUTEX:       Interpreter should be unlocked, because we may run the _REG   *              method for this region.   * + * NOTE:        Possible incompliance: + *              There is a behavior conflict in automatic _REG execution: + *              1. When the interpreter is evaluating a method, we can only + *                 automatically run _REG for the following case: + *                   Method(_REG, 2) {} + *                   OperationRegion (OPR1, 0x80, 0x1000010, 0x4) + *              2. When the interpreter is loading a table, we can also + *                 automatically run _REG for the following case: + *                   OperationRegion (OPR1, 0x80, 0x1000010, 0x4) + *                   Method(_REG, 2) {} + *              Though this may not be compliant to the de-facto standard, the + *              logic is kept in order not to trigger regressions. And keeping + *              this logic should be taken care by the caller of this function. + *   ******************************************************************************/  ACPI_STATUS  AcpiEvInitializeRegion ( -    ACPI_OPERAND_OBJECT     *RegionObj, -    BOOLEAN                 AcpiNsLocked) +    ACPI_OPERAND_OBJECT     *RegionObj)  {      ACPI_OPERAND_OBJECT     *HandlerObj;      ACPI_OPERAND_OBJECT     *ObjDesc;      ACPI_ADR_SPACE_TYPE     SpaceId;      ACPI_NAMESPACE_NODE     *Node; -    ACPI_STATUS             Status; -    ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked); +    ACPI_FUNCTION_TRACE (EvInitializeRegion);      if (!RegionObj) @@ -641,33 +653,15 @@ AcpiEvInitializeRegion (                      "Found handler %p for region %p in obj %p\n",                      HandlerObj, RegionObj, ObjDesc)); -                Status = AcpiEvAttachRegion (HandlerObj, RegionObj, -                    AcpiNsLocked); +                (void) AcpiEvAttachRegion (HandlerObj, RegionObj, FALSE);                  /*                   * Tell all users that this region is usable by                   * running the _REG method                   */ -                if (AcpiNsLocked) -                { -                    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); -                    if (ACPI_FAILURE (Status)) -                    { -                        return_ACPI_STATUS (Status); -                    } -                } - -                Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); - -                if (AcpiNsLocked) -                { -                    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); -                    if (ACPI_FAILURE (Status)) -                    { -                        return_ACPI_STATUS (Status); -                    } -                } - +                AcpiExExitInterpreter (); +                (void) AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); +                AcpiExEnterInterpreter ();                  return_ACPI_STATUS (AE_OK);              }          } @@ -677,11 +671,14 @@ AcpiEvInitializeRegion (          Node = Node->Parent;      } -    /* If we get here, there is no handler for this region */ - +    /* +     * If we get here, there is no handler for this region. This is not +     * fatal because many regions get created before a handler is installed +     * for said region. +     */      ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,          "No handler for RegionType %s(%X) (RegionObj %p)\n",          AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); -    return_ACPI_STATUS (AE_NOT_EXIST); +    return_ACPI_STATUS (AE_OK);  } diff --git a/source/components/executer/exconfig.c b/source/components/executer/exconfig.c index c17beab9961c2..f49b0a9fa9bb4 100644 --- a/source/components/executer/exconfig.c +++ b/source/components/executer/exconfig.c @@ -480,7 +480,7 @@ AcpiExLoadOp (      ACPI_INFO (("Dynamic OEM Table Load:"));      AcpiExExitInterpreter (); -    Status = AcpiTbInstallAndLoadTable (Table, ACPI_PTR_TO_PHYSADDR (Table), +    Status = AcpiTbInstallAndLoadTable (ACPI_PTR_TO_PHYSADDR (Table),          ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, TRUE, &TableIndex);      AcpiExEnterInterpreter ();      if (ACPI_FAILURE (Status)) @@ -545,7 +545,6 @@ AcpiExUnloadTable (      ACPI_STATUS             Status = AE_OK;      ACPI_OPERAND_OBJECT     *TableDesc = DdbHandle;      UINT32                  TableIndex; -    ACPI_TABLE_HEADER       *Table;      ACPI_FUNCTION_TRACE (ExUnloadTable); @@ -586,42 +585,7 @@ AcpiExUnloadTable (       * strict order requirement against it.       */      AcpiExExitInterpreter (); - -    /* Ensure the table is still loaded */ - -    if (!AcpiTbIsTableLoaded (TableIndex)) -    { -        Status = AE_NOT_EXIST; -        goto LockAndExit; -    } - -    /* Invoke table handler if present */ - -    if (AcpiGbl_TableHandler) -    { -        Status = AcpiGetTableByIndex (TableIndex, &Table); -        if (ACPI_SUCCESS (Status)) -        { -            (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, Table, -                AcpiGbl_TableHandlerContext); -        } -    } - -    /* Delete the portion of the namespace owned by this table */ - -    Status = AcpiTbDeleteNamespaceByOwner (TableIndex); -    if (ACPI_FAILURE (Status)) -    { -        goto LockAndExit; -    } - -    (void) AcpiTbReleaseOwnerId (TableIndex); -    AcpiTbSetTableLoadedFlag (TableIndex, FALSE); - -LockAndExit: - -    /* Re-acquire the interpreter lock */ - +    Status = AcpiTbUnloadTable (TableIndex);      AcpiExEnterInterpreter ();      /* diff --git a/source/components/executer/exconvrt.c b/source/components/executer/exconvrt.c index 5e0f5499aa4ae..ddbcc46b5b915 100644 --- a/source/components/executer/exconvrt.c +++ b/source/components/executer/exconvrt.c @@ -645,7 +645,6 @@ AcpiExConvertToTargetType (      switch (GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs))      {      case ARGI_SIMPLE_TARGET: -    case ARGI_FIXED_TARGET:      case ARGI_INTEGER_REF:      /* Handles Increment, Decrement cases */          switch (DestinationType) diff --git a/source/components/executer/exresop.c b/source/components/executer/exresop.c index d4352e297c167..bf1edd42145e2 100644 --- a/source/components/executer/exresop.c +++ b/source/components/executer/exresop.c @@ -321,7 +321,6 @@ AcpiExResolveOperands (          case ARGI_OBJECT_REF:          case ARGI_DEVICE_REF:          case ARGI_TARGETREF:     /* Allows implicit conversion rules before store */ -        case ARGI_FIXED_TARGET:  /* No implicit conversion before store to target */          case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion  */          case ARGI_STORE_TARGET: diff --git a/source/components/namespace/nsload.c b/source/components/namespace/nsload.c index 6e11d6b706243..d7dbf8955fa00 100644 --- a/source/components/namespace/nsload.c +++ b/source/components/namespace/nsload.c @@ -154,7 +154,9 @@ Unlock:      ACPI_DEBUG_PRINT ((ACPI_DB_INFO,          "**** Begin Table Object Initialization\n")); +    AcpiExEnterInterpreter ();      Status = AcpiDsInitializeObjects (TableIndex, Node); +    AcpiExExitInterpreter ();      ACPI_DEBUG_PRINT ((ACPI_DB_INFO,          "**** Completed Table Object Initialization\n")); diff --git a/source/components/namespace/nsnames.c b/source/components/namespace/nsnames.c index 95f8c8db970ca..8af12f1972794 100644 --- a/source/components/namespace/nsnames.c +++ b/source/components/namespace/nsnames.c @@ -110,6 +110,58 @@ AcpiNsGetPathnameLength (  /*******************************************************************************   * + * FUNCTION:    AcpiNsHandleToName + * + * PARAMETERS:  TargetHandle            - Handle of named object whose name is + *                                        to be found + *              Buffer                  - Where the name is returned + * + * RETURN:      Status, Buffer is filled with name if status is AE_OK + * + * DESCRIPTION: Build and return a full namespace name + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsHandleToName ( +    ACPI_HANDLE             TargetHandle, +    ACPI_BUFFER             *Buffer) +{ +    ACPI_STATUS             Status; +    ACPI_NAMESPACE_NODE     *Node; +    const char              *NodeName; + + +    ACPI_FUNCTION_TRACE_PTR (NsHandleToName, TargetHandle); + + +    Node = AcpiNsValidateHandle (TargetHandle); +    if (!Node) +    { +        return_ACPI_STATUS (AE_BAD_PARAMETER); +    } + +    /* Validate/Allocate/Clear caller buffer */ + +    Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH); +    if (ACPI_FAILURE (Status)) +    { +        return_ACPI_STATUS (Status); +    } + +    /* Just copy the ACPI name from the Node and zero terminate it */ + +    NodeName = AcpiUtGetNodeName (Node); +    ACPI_MOVE_NAME (Buffer->Pointer, NodeName); +    ((char *) Buffer->Pointer) [ACPI_NAME_SIZE] = 0; + +    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%4.4s\n", (char *) Buffer->Pointer)); +    return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + *   * FUNCTION:    AcpiNsHandleToPathname   *   * PARAMETERS:  TargetHandle            - Handle of named object whose name is diff --git a/source/components/namespace/nsxfname.c b/source/components/namespace/nsxfname.c index cfd6937f497fb..1621ba985da90 100644 --- a/source/components/namespace/nsxfname.c +++ b/source/components/namespace/nsxfname.c @@ -176,8 +176,6 @@ AcpiGetName (      ACPI_BUFFER             *Buffer)  {      ACPI_STATUS             Status; -    ACPI_NAMESPACE_NODE     *Node; -    const char              *NodeName;      /* Parameter validation */ @@ -193,16 +191,6 @@ AcpiGetName (          return (Status);      } -    if (NameType == ACPI_FULL_PATHNAME || -        NameType == ACPI_FULL_PATHNAME_NO_TRAILING) -    { -        /* Get the full pathname (From the namespace root) */ - -        Status = AcpiNsHandleToPathname (Handle, Buffer, -            NameType == ACPI_FULL_PATHNAME ? FALSE : TRUE); -        return (Status); -    } -      /*       * Wants the single segment ACPI name.       * Validate handle and convert to a namespace Node @@ -213,30 +201,20 @@ AcpiGetName (          return (Status);      } -    Node = AcpiNsValidateHandle (Handle); -    if (!Node) +    if (NameType == ACPI_FULL_PATHNAME || +        NameType == ACPI_FULL_PATHNAME_NO_TRAILING)      { -        Status = AE_BAD_PARAMETER; -        goto UnlockAndExit; -    } - -    /* Validate/Allocate/Clear caller buffer */ +        /* Get the full pathname (From the namespace root) */ -    Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH); -    if (ACPI_FAILURE (Status)) -    { -        goto UnlockAndExit; +        Status = AcpiNsHandleToPathname (Handle, Buffer, +            NameType == ACPI_FULL_PATHNAME ? FALSE : TRUE);      } +    else +    { +        /* Get the single name */ -    /* Just copy the ACPI name from the Node and zero terminate it */ - -    NodeName = AcpiUtGetNodeName (Node); -    ACPI_MOVE_NAME (Buffer->Pointer, NodeName); -    ((char *) Buffer->Pointer) [ACPI_NAME_SIZE] = 0; -    Status = AE_OK; - - -UnlockAndExit: +        Status = AcpiNsHandleToName (Handle, Buffer); +    }      (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);      return (Status); diff --git a/source/components/parser/psargs.c b/source/components/parser/psargs.c index a4745c3adc1df..5cc328612e118 100644 --- a/source/components/parser/psargs.c +++ b/source/components/parser/psargs.c @@ -298,23 +298,12 @@ AcpiPsGetNextNamepath (          PossibleMethodCall &&          (Node->Type == ACPI_TYPE_METHOD))      { -        if (WalkState->Opcode == AML_UNLOAD_OP) -        { -            /* -             * AcpiPsGetNextNamestring has increased the AML pointer, -             * so we need to restore the saved AML pointer for method call. -             */ -            WalkState->ParserState.Aml = Start; -            WalkState->ArgCount = 1; -            AcpiPsInitOp (Arg, AML_INT_METHODCALL_OP); -            return_ACPI_STATUS (AE_OK); -        } -          /* This name is actually a control method invocation */          MethodDesc = AcpiNsGetAttachedObject (Node);          ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, -            "Control Method - %p Desc %p Path=%p\n", Node, MethodDesc, Path)); +            "Control Method invocation %4.4s - %p Desc %p Path=%p\n", +            Node->Name.Ascii, Node, MethodDesc, Path));          NameOp = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, Start);          if (!NameOp) @@ -771,6 +760,10 @@ AcpiPsGetNextArg (      ACPI_FUNCTION_TRACE_PTR (PsGetNextArg, ParserState); +    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, +        "Expected argument type ARGP: %s (%2.2X)\n", +        AcpiUtGetArgumentTypeName (ArgType), ArgType)); +      switch (ArgType)      {      case ARGP_BYTEDATA: @@ -854,11 +847,13 @@ AcpiPsGetNextArg (          }          break; -    case ARGP_TARGET: -    case ARGP_SUPERNAME:      case ARGP_SIMPLENAME:      case ARGP_NAME_OR_REF: +        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, +            "**** SimpleName/NameOrRef: %s (%2.2X)\n", +            AcpiUtGetArgumentTypeName (ArgType), ArgType)); +          Subop = AcpiPsPeekOpcode (ParserState);          if (Subop == 0                  ||              AcpiPsIsLeadingChar (Subop) || @@ -873,28 +868,37 @@ AcpiPsGetNextArg (                  return_ACPI_STATUS (AE_NO_MEMORY);              } -            /* To support SuperName arg of Unload */ +            Status = AcpiPsGetNextNamepath (WalkState, ParserState, +                Arg, ACPI_NOT_METHOD_CALL); +        } +        else +        { +            /* Single complex argument, nothing returned */ -            if (WalkState->Opcode == AML_UNLOAD_OP) -            { -                Status = AcpiPsGetNextNamepath (WalkState, ParserState, -                    Arg, ACPI_POSSIBLE_METHOD_CALL); - -                /* -                 * If the SuperName argument is a method call, we have -                 * already restored the AML pointer, just free this Arg -                 */ -                if (Arg->Common.AmlOpcode == AML_INT_METHODCALL_OP) -                { -                    AcpiPsFreeOp (Arg); -                    Arg = NULL; -                } -            } -            else +            WalkState->ArgCount = 1; +        } +        break; + +    case ARGP_TARGET: +    case ARGP_SUPERNAME: + +        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, +            "**** Target/Supername: %s (%2.2X)\n", +            AcpiUtGetArgumentTypeName (ArgType), ArgType)); + +        Subop = AcpiPsPeekOpcode (ParserState); +        if (Subop == 0) +        { +            /* NULL target (zero). Convert to a NULL namepath */ + +            Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, ParserState->Aml); +            if (!Arg)              { -                Status = AcpiPsGetNextNamepath (WalkState, ParserState, -                    Arg, ACPI_NOT_METHOD_CALL); +                return_ACPI_STATUS (AE_NO_MEMORY);              } + +            Status = AcpiPsGetNextNamepath (WalkState, ParserState, +                Arg, ACPI_POSSIBLE_METHOD_CALL);          }          else          { @@ -907,6 +911,11 @@ AcpiPsGetNextArg (      case ARGP_DATAOBJ:      case ARGP_TERMARG: + +    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, +        "**** TermArg/DataObj: %s (%2.2X)\n", +        AcpiUtGetArgumentTypeName (ArgType), ArgType)); +          /* Single complex argument, nothing returned */          WalkState->ArgCount = 1; diff --git a/source/components/parser/psloop.c b/source/components/parser/psloop.c index e0839fd7d828b..5056cd1de7f0a 100644 --- a/source/components/parser/psloop.c +++ b/source/components/parser/psloop.c @@ -104,6 +104,9 @@ AcpiPsGetArguments (      ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState); +    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, +        "Get arguments for opcode [%s]\n", Op->Common.AmlOpName)); +      switch (Op->Common.AmlOpcode)      {      case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */ diff --git a/source/components/parser/psobject.c b/source/components/parser/psobject.c index 7edc39e2b7ad2..d027f6d9892c8 100644 --- a/source/components/parser/psobject.c +++ b/source/components/parser/psobject.c @@ -373,7 +373,13 @@ AcpiPsCreateOp (                  Op->Common.Flags |= ACPI_PARSEOP_TARGET;              }          } -        else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP) + +        /* +         * Special case for both Increment() and Decrement(), where +         * the lone argument is both a source and a target. +         */ +        else if ((ParentScope->Common.AmlOpcode == AML_INCREMENT_OP) || +                (ParentScope->Common.AmlOpcode == AML_DECREMENT_OP))          {              Op->Common.Flags |= ACPI_PARSEOP_TARGET;          } diff --git a/source/components/parser/pstree.c b/source/components/parser/pstree.c index 729856982b649..0d6ab6373b6e5 100644 --- a/source/components/parser/pstree.c +++ b/source/components/parser/pstree.c @@ -142,12 +142,12 @@ AcpiPsAppendArg (      const ACPI_OPCODE_INFO  *OpInfo; -    ACPI_FUNCTION_ENTRY (); +    ACPI_FUNCTION_TRACE ("PsAppendArg");      if (!Op)      { -        return; +        return_VOID;      }      /* Get the info structure for this opcode */ @@ -159,7 +159,7 @@ AcpiPsAppendArg (          ACPI_ERROR ((AE_INFO, "Invalid AML Opcode: 0x%2.2X",              Op->Common.AmlOpcode)); -        return; +        return_VOID;      }      /* Check if this opcode requires argument sub-objects */ @@ -168,7 +168,7 @@ AcpiPsAppendArg (      {          /* Has no linked argument objects */ -        return; +        return_VOID;      }      /* Append the argument to the linked argument list */ @@ -200,6 +200,8 @@ AcpiPsAppendArg (          Op->Common.ArgListLength++;      } + +    return_VOID;  } diff --git a/source/components/tables/tbdata.c b/source/components/tables/tbdata.c index 81b3abcfdd7bf..95b5b2672cd27 100644 --- a/source/components/tables/tbdata.c +++ b/source/components/tables/tbdata.c @@ -937,9 +937,9 @@ AcpiTbLoadTable (   *   * FUNCTION:    AcpiTbInstallAndLoadTable   * - * PARAMETERS:  Table                   - Pointer to the table - *              Address                 - Physical address of the table + * PARAMETERS:  Address                 - Physical address of the table   *              Flags                   - Allocation flags of the table + *              Override                - Whether override should be performed   *              TableIndex              - Where table index is returned   *   * RETURN:      Status @@ -950,7 +950,6 @@ AcpiTbLoadTable (  ACPI_STATUS  AcpiTbInstallAndLoadTable ( -    ACPI_TABLE_HEADER       *Table,      ACPI_PHYSICAL_ADDRESS   Address,      UINT8                   Flags,      BOOLEAN                 Override, @@ -958,10 +957,9 @@ AcpiTbInstallAndLoadTable (  {      ACPI_STATUS             Status;      UINT32                  i; -    ACPI_OWNER_ID           OwnerId; -    ACPI_FUNCTION_TRACE (AcpiLoadTable); +    ACPI_FUNCTION_TRACE (TbInstallAndLoadTable);      (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); @@ -975,48 +973,68 @@ AcpiTbInstallAndLoadTable (          goto UnlockAndExit;      } -    /* -     * Note: Now table is "INSTALLED", it must be validated before -     * using. -     */ -    Status = AcpiTbValidateTable (&AcpiGbl_RootTableList.Tables[i]); -    if (ACPI_FAILURE (Status)) -    { -        goto UnlockAndExit; -    } +    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); +    Status = AcpiTbLoadTable (i, AcpiGbl_RootNode); +    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); +UnlockAndExit: +    *TableIndex = i;      (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); -    Status = AcpiNsLoadTable (i, AcpiGbl_RootNode); +    return_ACPI_STATUS (Status); +} -    /* Execute any module-level code that was found in the table */ -    if (!AcpiGbl_ParseTableAsTermList && AcpiGbl_GroupModuleLevelCode) -    { -        AcpiNsExecModuleCodeList (); -    } +/******************************************************************************* + * + * FUNCTION:    AcpiTbUnloadTable + * + * PARAMETERS:  TableIndex              - Table index + * + * RETURN:      Status + * + * DESCRIPTION: Unload an ACPI table + * + ******************************************************************************/ -    /* -     * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is -     * responsible for discovering any new wake GPEs by running _PRW methods -     * that may have been loaded by this table. -     */ -    Status = AcpiTbGetOwnerId (i, &OwnerId); -    if (ACPI_SUCCESS (Status)) +ACPI_STATUS +AcpiTbUnloadTable ( +    UINT32                  TableIndex) +{ +    ACPI_STATUS             Status = AE_OK; +    ACPI_TABLE_HEADER       *Table; + + +    ACPI_FUNCTION_TRACE (TbUnloadTable); + + +    /* Ensure the table is still loaded */ + +    if (!AcpiTbIsTableLoaded (TableIndex))      { -        AcpiEvUpdateGpes (OwnerId); +        return_ACPI_STATUS (AE_NOT_EXIST);      }      /* Invoke table handler if present */      if (AcpiGbl_TableHandler)      { -        (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, -            AcpiGbl_TableHandlerContext); +        Status = AcpiGetTableByIndex (TableIndex, &Table); +        if (ACPI_SUCCESS (Status)) +        { +            (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, Table, +                AcpiGbl_TableHandlerContext); +        }      } -    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); -UnlockAndExit: -    *TableIndex = i; -    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); +    /* Delete the portion of the namespace owned by this table */ + +    Status = AcpiTbDeleteNamespaceByOwner (TableIndex); +    if (ACPI_FAILURE (Status)) +    { +        return_ACPI_STATUS (Status); +    } + +    (void) AcpiTbReleaseOwnerId (TableIndex); +    AcpiTbSetTableLoadedFlag (TableIndex, FALSE);      return_ACPI_STATUS (Status);  } diff --git a/source/components/tables/tbfadt.c b/source/components/tables/tbfadt.c index b75b52d9d0b97..1d327dc3113bb 100644 --- a/source/components/tables/tbfadt.c +++ b/source/components/tables/tbfadt.c @@ -341,6 +341,8 @@ AcpiTbParseFadt (  {      UINT32                  Length;      ACPI_TABLE_HEADER       *Table; +    ACPI_TABLE_DESC         *FadtDesc; +    ACPI_STATUS             Status;      /* @@ -350,14 +352,13 @@ AcpiTbParseFadt (       * Get a local copy of the FADT and convert it to a common format       * Map entire FADT, assumed to be smaller than one page.       */ -    Length = AcpiGbl_RootTableList.Tables[AcpiGbl_FadtIndex].Length; - -    Table = AcpiOsMapMemory ( -        AcpiGbl_RootTableList.Tables[AcpiGbl_FadtIndex].Address, Length); -    if (!Table) +    FadtDesc = &AcpiGbl_RootTableList.Tables[AcpiGbl_FadtIndex]; +    Status = AcpiTbGetTable (FadtDesc, &Table); +    if (ACPI_FAILURE (Status))      {          return;      } +    Length = FadtDesc->Length;      /*       * Validate the FADT checksum before we copy the table. Ignore @@ -371,7 +372,7 @@ AcpiTbParseFadt (      /* All done with the real FADT, unmap it */ -    AcpiOsUnmapMemory (Table, Length); +    AcpiTbPutTable (FadtDesc);      /* Obtain the DSDT and FACS tables via their addresses within the FADT */ @@ -522,19 +523,17 @@ AcpiTbConvertFadt (      /* -     * For ACPI 1.0 FADTs (revision 1), ensure that reserved fields which +     * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which       * should be zero are indeed zero. This will workaround BIOSs that       * inadvertently place values in these fields.       *       * The ACPI 1.0 reserved fields that will be zeroed are the bytes located       * at offset 45, 55, 95, and the word located at offset 109, 110.       * -     * Note: The FADT revision value is unreliable because of BIOS errors. -     * The table length is instead used as the final word on the version. -     * -     * Note: FADT revision 3 is the ACPI 2.0 version of the FADT. +     * Note: The FADT revision value is unreliable. Only the length can be +     * trusted.       */ -    if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V3_SIZE) +    if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE)      {          AcpiGbl_FADT.PreferredProfile = 0;          AcpiGbl_FADT.PstateControl = 0; diff --git a/source/components/tables/tbutils.c b/source/components/tables/tbutils.c index 85b9c3e4c561a..6fc30a69fa388 100644 --- a/source/components/tables/tbutils.c +++ b/source/components/tables/tbutils.c @@ -411,3 +411,99 @@ NextTable:      AcpiOsUnmapMemory (Table, Length);      return_ACPI_STATUS (AE_OK);  } + + +/******************************************************************************* + * + * FUNCTION:    AcpiTbGetTable + * + * PARAMETERS:  TableDesc           - Table descriptor + *              OutTable            - Where the pointer to the table is returned + * + * RETURN:      Status and pointer to the requested table + * + * DESCRIPTION: Increase a reference to a table descriptor and return the + *              validated table pointer. + *              If the table descriptor is an entry of the root table list, + *              this API must be invoked with ACPI_MTX_TABLES acquired. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbGetTable ( +    ACPI_TABLE_DESC        *TableDesc, +    ACPI_TABLE_HEADER      **OutTable) +{ +    ACPI_STATUS            Status; + + +    ACPI_FUNCTION_TRACE (AcpiTbGetTable); + + +    if (TableDesc->ValidationCount == 0) +    { +        /* Table need to be "VALIDATED" */ + +        Status = AcpiTbValidateTable (TableDesc); +        if (ACPI_FAILURE (Status)) +        { +            return_ACPI_STATUS (Status); +        } +    } + +    TableDesc->ValidationCount++; +    if (TableDesc->ValidationCount == 0) +    { +        ACPI_ERROR ((AE_INFO, +            "Table %p, Validation count is zero after increment\n", +            TableDesc)); +        TableDesc->ValidationCount--; +        return_ACPI_STATUS (AE_LIMIT); +    } + +    *OutTable = TableDesc->Pointer; +    return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION:    AcpiTbPutTable + * + * PARAMETERS:  TableDesc           - Table descriptor + * + * RETURN:      None + * + * DESCRIPTION: Decrease a reference to a table descriptor and release the + *              validated table pointer if no references. + *              If the table descriptor is an entry of the root table list, + *              this API must be invoked with ACPI_MTX_TABLES acquired. + * + ******************************************************************************/ + +void +AcpiTbPutTable ( +    ACPI_TABLE_DESC        *TableDesc) +{ + +    ACPI_FUNCTION_TRACE (AcpiTbPutTable); + + +    if (TableDesc->ValidationCount == 0) +    { +        ACPI_WARNING ((AE_INFO, +            "Table %p, Validation count is zero before decrement\n", +            TableDesc)); +        return_VOID; +    } +    TableDesc->ValidationCount--; + +    if (TableDesc->ValidationCount == 0) +    { +        /* Table need to be "INVALIDATED" */ + +        AcpiTbInvalidateTable (TableDesc); +    } + +    return_VOID; +} diff --git a/source/components/tables/tbxface.c b/source/components/tables/tbxface.c index 4c8c065cf3730..9346933cf5274 100644 --- a/source/components/tables/tbxface.c +++ b/source/components/tables/tbxface.c @@ -184,6 +184,7 @@ AcpiReallocateRootTable (      void)  {      ACPI_STATUS             Status; +    UINT32                  i;      ACPI_FUNCTION_TRACE (AcpiReallocateRootTable); @@ -198,6 +199,22 @@ AcpiReallocateRootTable (          return_ACPI_STATUS (AE_SUPPORT);      } +    /* +     * Ensure OS early boot logic, which is required by some hosts. If the +     * table state is reported to be wrong, developers should fix the +     * issue by invoking AcpiPutTable() for the reported table during the +     * early stage. +     */ +    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) +    { +        if (AcpiGbl_RootTableList.Tables[i].Pointer) +        { +            ACPI_ERROR ((AE_INFO, +                "Table [%4.4s] is not invalidated during early boot stage", +                AcpiGbl_RootTableList.Tables[i].Signature.Ascii)); +        } +    } +      AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ALLOW_RESIZE;      Status = AcpiTbResizeRootTableList (); @@ -307,6 +324,11 @@ ACPI_EXPORT_SYMBOL (AcpiGetTableHeader)   *   * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the   *              RSDT/XSDT. + *              Note that an early stage AcpiGetTable() call must be paired + *              with an early stage AcpiPutTable() call. otherwise the table + *              pointer mapped by the early stage mapping implementation may be + *              erroneously unmapped by the late stage unmapping implementation + *              in an AcpiPutTable() invoked during the late stage.   *   ******************************************************************************/ @@ -318,7 +340,8 @@ AcpiGetTable (  {      UINT32                  i;      UINT32                  j; -    ACPI_STATUS             Status; +    ACPI_STATUS             Status = AE_NOT_FOUND; +    ACPI_TABLE_DESC         *TableDesc;      /* Parameter validation */ @@ -328,12 +351,22 @@ AcpiGetTable (          return (AE_BAD_PARAMETER);      } +    /* +     * Note that the following line is required by some OSPMs, they only +     * check if the returned table is NULL instead of the returned status +     * to determined if this function is succeeded. +     */ +    *OutTable = NULL; + +    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); +      /* Walk the root table list */      for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)      { -        if (!ACPI_COMPARE_NAME ( -                &(AcpiGbl_RootTableList.Tables[i].Signature), Signature)) +        TableDesc = &AcpiGbl_RootTableList.Tables[i]; + +        if (!ACPI_COMPARE_NAME (&TableDesc->Signature, Signature))          {              continue;          } @@ -343,19 +376,66 @@ AcpiGetTable (              continue;          } -        Status = AcpiTbValidateTable (&AcpiGbl_RootTableList.Tables[i]); -        if (ACPI_SUCCESS (Status)) +        Status = AcpiTbGetTable (TableDesc, OutTable); +        break; +    } + +    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); +    return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetTable) + + +/******************************************************************************* + * + * FUNCTION:    AcpiPutTable + * + * PARAMETERS:  Table               - The pointer to the table + * + * RETURN:      None + * + * DESCRIPTION: Release a table returned by AcpiGetTable() and its clones. + *              Note that it is not safe if this function was invoked after an + *              uninstallation happened to the original table descriptor. + *              Currently there is no OSPMs' requirement to handle such + *              situations. + * + ******************************************************************************/ + +void +AcpiPutTable ( +    ACPI_TABLE_HEADER       *Table) +{ +    UINT32                  i; +    ACPI_TABLE_DESC         *TableDesc; + + +    ACPI_FUNCTION_TRACE (AcpiPutTable); + + +    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + +    /* Walk the root table list */ + +    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) +    { +        TableDesc = &AcpiGbl_RootTableList.Tables[i]; + +        if (TableDesc->Pointer != Table)          { -            *OutTable = AcpiGbl_RootTableList.Tables[i].Pointer; +            continue;          } -        return (Status); +        AcpiTbPutTable (TableDesc); +        break;      } -    return (AE_NOT_FOUND); +    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); +    return_VOID;  } -ACPI_EXPORT_SYMBOL (AcpiGetTable) +ACPI_EXPORT_SYMBOL (AcpiPutTable)  /******************************************************************************* @@ -363,7 +443,7 @@ ACPI_EXPORT_SYMBOL (AcpiGetTable)   * FUNCTION:    AcpiGetTableByIndex   *   * PARAMETERS:  TableIndex          - Table index - *              Table               - Where the pointer to the table is returned + *              OutTable            - Where the pointer to the table is returned   *   * RETURN:      Status and pointer to the requested table   * @@ -375,7 +455,7 @@ ACPI_EXPORT_SYMBOL (AcpiGetTable)  ACPI_STATUS  AcpiGetTableByIndex (      UINT32                  TableIndex, -    ACPI_TABLE_HEADER       **Table) +    ACPI_TABLE_HEADER       **OutTable)  {      ACPI_STATUS             Status; @@ -385,37 +465,34 @@ AcpiGetTableByIndex (      /* Parameter validation */ -    if (!Table) +    if (!OutTable)      {          return_ACPI_STATUS (AE_BAD_PARAMETER);      } +    /* +     * Note that the following line is required by some OSPMs, they only +     * check if the returned table is NULL instead of the returned status +     * to determined if this function is succeeded. +     */ +    *OutTable = NULL; +      (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);      /* Validate index */      if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)      { -        (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); -        return_ACPI_STATUS (AE_BAD_PARAMETER); +        Status = AE_BAD_PARAMETER; +        goto UnlockAndExit;      } -    if (!AcpiGbl_RootTableList.Tables[TableIndex].Pointer) -    { -        /* Table is not mapped, map it */ - -        Status = AcpiTbValidateTable ( -            &AcpiGbl_RootTableList.Tables[TableIndex]); -        if (ACPI_FAILURE (Status)) -        { -            (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); -            return_ACPI_STATUS (Status); -        } -    } +    Status = AcpiTbGetTable ( +        &AcpiGbl_RootTableList.Tables[TableIndex], OutTable); -    *Table = AcpiGbl_RootTableList.Tables[TableIndex].Pointer; +UnlockAndExit:      (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); -    return_ACPI_STATUS (AE_OK); +    return_ACPI_STATUS (Status);  }  ACPI_EXPORT_SYMBOL (AcpiGetTableByIndex) diff --git a/source/components/tables/tbxfload.c b/source/components/tables/tbxfload.c index 43fe397fde568..30c6534a56995 100644 --- a/source/components/tables/tbxfload.c +++ b/source/components/tables/tbxfload.c @@ -372,7 +372,7 @@ AcpiLoadTable (      /* Install the table and load it into the namespace */      ACPI_INFO (("Host-directed Dynamic ACPI Table Load:")); -    Status = AcpiTbInstallAndLoadTable (Table, ACPI_PTR_TO_PHYSADDR (Table), +    Status = AcpiTbInstallAndLoadTable (ACPI_PTR_TO_PHYSADDR (Table),          ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, FALSE, &TableIndex);      return_ACPI_STATUS (Status);  } @@ -459,39 +459,8 @@ AcpiUnloadParentTable (              break;          } -        /* Ensure the table is actually loaded */ -          (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); -        if (!AcpiTbIsTableLoaded (i)) -        { -            Status = AE_NOT_EXIST; -            (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); -            break; -        } - -        /* Invoke table handler if present */ - -        if (AcpiGbl_TableHandler) -        { -            (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, -                AcpiGbl_RootTableList.Tables[i].Pointer, -                AcpiGbl_TableHandlerContext); -        } - -        /* -         * Delete all namespace objects owned by this table. Note that -         * these objects can appear anywhere in the namespace by virtue -         * of the AML "Scope" operator. Thus, we need to track ownership -         * by an ID, not simply a position within the hierarchy. -         */ -        Status = AcpiTbDeleteNamespaceByOwner (i); -        if (ACPI_FAILURE (Status)) -        { -            break; -        } - -        Status = AcpiTbReleaseOwnerId (i); -        AcpiTbSetTableLoadedFlag (i, FALSE); +        Status = AcpiTbUnloadTable (i);          (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);          break;      } diff --git a/source/components/utilities/utdecode.c b/source/components/utilities/utdecode.c index 5c8f2cec80552..45adf14c6d9e6 100644 --- a/source/components/utilities/utdecode.c +++ b/source/components/utilities/utdecode.c @@ -44,6 +44,7 @@  #include "acpi.h"  #include "accommon.h"  #include "acnamesp.h" +#include "amlcode.h"  #define _COMPONENT          ACPI_UTILITIES          ACPI_MODULE_NAME    ("utdecode") @@ -604,6 +605,59 @@ AcpiUtGetNotifyName (      return ("Hardware-Specific");  } + + +/******************************************************************************* + * + * FUNCTION:    AcpiUtGetArgumentTypeName + * + * PARAMETERS:  ArgType             - an ARGP_* parser argument type + * + * RETURN:      Decoded ARGP_* type + * + * DESCRIPTION: Decode an ARGP_* parser type, as defined in the amlcode.h file, + *              and used in the acopcode.h file. For example, ARGP_TERMARG. + *              Used for debug only. + * + ******************************************************************************/ + +static const char           *AcpiGbl_ArgumentType[20] = +{ +    /* 00 */ "Unknown ARGP", +    /* 01 */ "ByteData", +    /* 02 */ "ByteList", +    /* 03 */ "CharList", +    /* 04 */ "DataObject", +    /* 05 */ "DataObjectList", +    /* 06 */ "DWordData", +    /* 07 */ "FieldList", +    /* 08 */ "Name", +    /* 09 */ "NameString", +    /* 0A */ "ObjectList", +    /* 0B */ "PackageLength", +    /* 0C */ "SuperName", +    /* 0D */ "Target", +    /* 0E */ "TermArg", +    /* 0F */ "TermList", +    /* 10 */ "WordData", +    /* 11 */ "QWordData", +    /* 12 */ "SimpleName", +    /* 13 */ "NameOrRef" +}; + +const char * +AcpiUtGetArgumentTypeName ( +    UINT32                  ArgType) +{ + +    if (ArgType > ARGP_MAX) +    { +        return ("Unknown ARGP"); +    } + +    return (AcpiGbl_ArgumentType[ArgType]); +} +  #endif diff --git a/source/components/utilities/utresrc.c b/source/components/utilities/utresrc.c index 8efae429777c2..8c44a1cab8f89 100644 --- a/source/components/utilities/utresrc.c +++ b/source/components/utilities/utresrc.c @@ -468,9 +468,11 @@ AcpiUtWalkAmlResources (      ACPI_FUNCTION_TRACE (UtWalkAmlResources); -    /* The absolute minimum resource template is one EndTag descriptor */ - -    if (AmlLength < sizeof (AML_RESOURCE_END_TAG)) +    /* +     * The absolute minimum resource template is one EndTag descriptor. +     * However, we will treat a lone EndTag as just a simple buffer. +     */ +    if (AmlLength <= sizeof (AML_RESOURCE_END_TAG))      {          return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);      } @@ -503,8 +505,8 @@ AcpiUtWalkAmlResources (          if (UserFunction)          { -            Status = UserFunction ( -                Aml, Length, Offset, ResourceIndex, Context); +            Status = UserFunction (Aml, Length, Offset, +                ResourceIndex, Context);              if (ACPI_FAILURE (Status))              {                  return_ACPI_STATUS (Status); @@ -531,6 +533,13 @@ AcpiUtWalkAmlResources (                  *Context = Aml;              } +            /* Check if buffer is defined to be longer than the resource length */ + +            if (AmlLength > (Offset + Length)) +            { +                return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); +            } +              /* Normal exit */              return_ACPI_STATUS (AE_OK); | 
