kernel/acpica/components/namespace/nsprepkg.c
/*******************************************************************************
 *
 * FUNCTION:    AcpiNsCheckPackage
 *
 * PARAMETERS:  Info                - Method execution information block
 *              ReturnObjectPtr     - Pointer to the object returned from the
 *                                    evaluation of a method or object
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Check a returned package object for the correct count and
 *              correct type of all sub-objects.
 *
 ******************************************************************************/
AcpiNsCheckPackage
PARAMETERS:  Info                - Method execution information block
ReturnObjectPtr     - Pointer to the object returned from the
evaluation of a method or object

Status

Check a returned package object for the correct count and
correct type of all sub-objects.
AcpiNsCheckPackage PARAMETERS : Info - Method execution information block ReturnObjectPtr - Pointer to the object returned from the evaluation of a method or object Status Check a returned package object for the correct count and correct type of all sub - objects .
ACPI_STATUS
AcpiNsCheckPackage (
    ACPI_EVALUATE_INFO          *Info,
    ACPI_OPERAND_OBJECT         **ReturnObjectPtr)
{
    ACPI_OPERAND_OBJECT         *ReturnObject = *ReturnObjectPtr;
    const ACPI_PREDEFINED_INFO  *Package;
    ACPI_OPERAND_OBJECT         **Elements;
    ACPI_STATUS                 Status = AE_OK;
    UINT32                      ExpectedCount;
    UINT32                      Count;
    UINT32                      i;
    ACPI_FUNCTION_NAME (NsCheckPackage);
    Package = Info->Predefined + 1;
    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
        "%s Validating return Package of Type %X, Count %X\n",
        Info->FullPathname, Package->RetInfo.Type,
        ReturnObject->Package.Count));
    AcpiNsRemoveNullElements (Info, Package->RetInfo.Type, ReturnObject);
    Elements = ReturnObject->Package.Elements;
    Count = ReturnObject->Package.Count;
    if (!Count)
    {
        if (Package->RetInfo.Type == ACPI_PTYPE1_VAR)
        {
            return (AE_OK);
        }
        ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
            "Return Package has no elements (empty)"));
        return (AE_AML_OPERAND_VALUE);
    }
    switch (Package->RetInfo.Type)
    {
    case ACPI_PTYPE_CUSTOM:
        Status = AcpiNsCustomPackage (Info, Elements, Count);
        break;
    case ACPI_PTYPE1_FIXED:
        ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
        if (Count < ExpectedCount)
        {
            goto PackageTooSmall;
        }
        else if (Count > ExpectedCount)
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
                "%s: Return Package is larger than needed - "
                "found %u, expected %u\n",
                Info->FullPathname, Count, ExpectedCount));
        }
        Status = AcpiNsCheckPackageElements (Info, Elements,
            Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
            Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0);
        break;
    case ACPI_PTYPE1_VAR:
        for (i = 0; i < Count; i++)
        {
            Status = AcpiNsCheckObjectType (Info, Elements,
                Package->RetInfo.ObjectType1, i);
            if (ACPI_FAILURE (Status))
            {
                return (Status);
            }
            Elements++;
        }
        break;
    case ACPI_PTYPE1_OPTION:
        ExpectedCount = Package->RetInfo3.Count;
        if (Count < ExpectedCount)
        {
            goto PackageTooSmall;
        }
        for (i = 0; i < Count; i++)
        {
            if (i < Package->RetInfo3.Count)
            {
                Status = AcpiNsCheckObjectType (Info, Elements,
                    Package->RetInfo3.ObjectType[i], i);
                if (ACPI_FAILURE (Status))
                {
                    return (Status);
                }
            }
            else
            {
                Status = AcpiNsCheckObjectType (Info, Elements,
                    Package->RetInfo3.TailObjectType, i);
                if (ACPI_FAILURE (Status))
                {
                    return (Status);
                }
            }
            Elements++;
        }
        break;
    case ACPI_PTYPE2_REV_FIXED:
        Status = AcpiNsCheckObjectType (
            Info, Elements, ACPI_RTYPE_INTEGER, 0);
        if (ACPI_FAILURE (Status))
        {
            return (Status);
        }
        Elements++;
        Count--;
        Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
        break;
    case ACPI_PTYPE2_PKG_COUNT:
        Status = AcpiNsCheckObjectType (
            Info, Elements, ACPI_RTYPE_INTEGER, 0);
        if (ACPI_FAILURE (Status))
        {
            return (Status);
        }
        ExpectedCount = (UINT32) (*Elements)->Integer.Value;
        if (ExpectedCount >= Count)
        {
            goto PackageTooSmall;
        }
        Count = ExpectedCount;
        Elements++;
        Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
        break;
    case ACPI_PTYPE2:
    case ACPI_PTYPE2_FIXED:
    case ACPI_PTYPE2_MIN:
    case ACPI_PTYPE2_COUNT:
    case ACPI_PTYPE2_FIX_VAR:
        if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE))
        {
            Status = AcpiNsWrapWithPackage (
                Info, ReturnObject, ReturnObjectPtr);
            if (ACPI_FAILURE (Status))
            {
                return (Status);
            }
            ReturnObject = *ReturnObjectPtr;
            Elements = ReturnObject->Package.Elements;
            Count = 1;
        }
        Status = AcpiNsCheckPackageList (Info, Package, Elements, Count);
        break;
    case ACPI_PTYPE2_VAR_VAR:
        break;
    case ACPI_PTYPE2_UUID_PAIR:
        if (Count & 1)
        {
            ExpectedCount = Count + 1;
            goto PackageTooSmall;
        }
        while (Count > 0)
        {
            Status = AcpiNsCheckObjectType(Info, Elements,
                Package->RetInfo.ObjectType1, 0);
            if (ACPI_FAILURE(Status))
            {
                return (Status);
            }
            if ((*Elements)->Buffer.Length != 16)
            {
                ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname,
                    Info->NodeFlags, "Invalid length for UUID Buffer"));
                return (AE_AML_OPERAND_VALUE);
            }
            Status = AcpiNsCheckObjectType(Info, Elements + 1,
                Package->RetInfo.ObjectType2, 0);
            if (ACPI_FAILURE(Status))
            {
                return (Status);
            }
            Elements += 2;
            Count -= 2;
        }
        break;
    default:
        ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
            "Invalid internal return type in table entry: %X",
            Package->RetInfo.Type));
        return (AE_AML_INTERNAL);
    }
    return (Status);
PackageTooSmall:
    ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
        "Return Package is too small - found %u elements, expected %u",
        Count, ExpectedCount));
    return (AE_AML_OPERAND_VALUE);
}
ACPI_STATUS AcpiNsCheckPackage ( ACPI_EVALUATE_INFO * Info , ACPI_OPERAND_OBJECT * * ReturnObjectPtr ) { ACPI_OPERAND_OBJECT * ReturnObject = * ReturnObjectPtr ; const ACPI_PREDEFINED_INFO * Package ; ACPI_OPERAND_OBJECT * * Elements ; ACPI_STATUS Status = AE_OK ; UINT32 ExpectedCount ; UINT32 Count ; UINT32 i ; ACPI_FUNCTION_NAME ( NsCheckPackage ) ; Package = Info -> Predefined + 1 ; ACPI_DEBUG_PRINT ( ( ACPI_DB_NAMES , " \n " , Info -> FullPathname , Package -> RetInfo . Type , ReturnObject -> Package . Count ) ) ; AcpiNsRemoveNullElements ( Info , Package -> RetInfo . Type , ReturnObject ) ; Elements = ReturnObject -> Package . Elements ; Count = ReturnObject -> Package . Count ; if ( ! Count ) { if ( Package -> RetInfo . Type == ACPI_PTYPE1_VAR ) { return ( AE_OK ) ; } ACPI_WARN_PREDEFINED ( ( AE_INFO , Info -> FullPathname , Info -> NodeFlags , " " ) ) ; return ( AE_AML_OPERAND_VALUE ) ; } switch ( Package -> RetInfo . Type ) { case ACPI_PTYPE_CUSTOM : Status = AcpiNsCustomPackage ( Info , Elements , Count ) ; break ; case ACPI_PTYPE1_FIXED : ExpectedCount = Package -> RetInfo . Count1 + Package -> RetInfo . Count2 ; if ( Count < ExpectedCount ) { goto PackageTooSmall ; } else if ( Count > ExpectedCount ) { ACPI_DEBUG_PRINT ( ( ACPI_DB_REPAIR , " " " \n " , Info -> FullPathname , Count , ExpectedCount ) ) ; } Status = AcpiNsCheckPackageElements ( Info , Elements , Package -> RetInfo . ObjectType1 , Package -> RetInfo . Count1 , Package -> RetInfo . ObjectType2 , Package -> RetInfo . Count2 , 0 ) ; break ; case ACPI_PTYPE1_VAR : for ( i = 0 ; i < Count ; i ++ ) { Status = AcpiNsCheckObjectType ( Info , Elements , Package -> RetInfo . ObjectType1 , i ) ; if ( ACPI_FAILURE ( Status ) ) { return ( Status ) ; } Elements ++ ; } break ; case ACPI_PTYPE1_OPTION : ExpectedCount = Package -> RetInfo3 . Count ; if ( Count < ExpectedCount ) { goto PackageTooSmall ; } for ( i = 0 ; i < Count ; i ++ ) { if ( i < Package -> RetInfo3 . Count ) { Status = AcpiNsCheckObjectType ( Info , Elements , Package -> RetInfo3 . ObjectType [ i ] , i ) ; if ( ACPI_FAILURE ( Status ) ) { return ( Status ) ; } } else { Status = AcpiNsCheckObjectType ( Info , Elements , Package -> RetInfo3 . TailObjectType , i ) ; if ( ACPI_FAILURE ( Status ) ) { return ( Status ) ; } } Elements ++ ; } break ; case ACPI_PTYPE2_REV_FIXED : Status = AcpiNsCheckObjectType ( Info , Elements , ACPI_RTYPE_INTEGER , 0 ) ; if ( ACPI_FAILURE ( Status ) ) { return ( Status ) ; } Elements ++ ; Count -- ; Status = AcpiNsCheckPackageList ( Info , Package , Elements , Count ) ; break ; case ACPI_PTYPE2_PKG_COUNT : Status = AcpiNsCheckObjectType ( Info , Elements , ACPI_RTYPE_INTEGER , 0 ) ; if ( ACPI_FAILURE ( Status ) ) { return ( Status ) ; } ExpectedCount = ( UINT32 ) ( * Elements ) -> Integer . Value ; if ( ExpectedCount >= Count ) { goto PackageTooSmall ; } Count = ExpectedCount ; Elements ++ ; Status = AcpiNsCheckPackageList ( Info , Package , Elements , Count ) ; break ; case ACPI_PTYPE2 : case ACPI_PTYPE2_FIXED : case ACPI_PTYPE2_MIN : case ACPI_PTYPE2_COUNT : case ACPI_PTYPE2_FIX_VAR : if ( * Elements && ( ( * Elements ) -> Common . Type != ACPI_TYPE_PACKAGE ) ) { Status = AcpiNsWrapWithPackage ( Info , ReturnObject , ReturnObjectPtr ) ; if ( ACPI_FAILURE ( Status ) ) { return ( Status ) ; } ReturnObject = * ReturnObjectPtr ; Elements = ReturnObject -> Package . Elements ; Count = 1 ; } Status = AcpiNsCheckPackageList ( Info , Package , Elements , Count ) ; break ; case ACPI_PTYPE2_VAR_VAR : break ; case ACPI_PTYPE2_UUID_PAIR : if ( Count & 1 ) { ExpectedCount = Count + 1 ; goto PackageTooSmall ; } while ( Count > 0 ) { Status = AcpiNsCheckObjectType ( Info , Elements , Package -> RetInfo . ObjectType1 , 0 ) ; if ( ACPI_FAILURE ( Status ) ) { return ( Status ) ; } if ( ( * Elements ) -> Buffer . Length != 16 ) { ACPI_WARN_PREDEFINED ( ( AE_INFO , Info -> FullPathname , Info -> NodeFlags , " " ) ) ; return ( AE_AML_OPERAND_VALUE ) ; } Status = AcpiNsCheckObjectType ( Info , Elements + 1 , Package -> RetInfo . ObjectType2 , 0 ) ; if ( ACPI_FAILURE ( Status ) ) { return ( Status ) ; } Elements += 2 ; Count -= 2 ; } break ; default : ACPI_WARN_PREDEFINED ( ( AE_INFO , Info -> FullPathname , Info -> NodeFlags , " " , Package -> RetInfo . Type ) ) ; return ( AE_AML_INTERNAL ) ; } return ( Status ) ; PackageTooSmall : ACPI_WARN_PREDEFINED ( ( AE_INFO , Info -> FullPathname , Info -> NodeFlags , " " , Count , ExpectedCount ) ) ; return ( AE_AML_OPERAND_VALUE ) ; }
FUNCTION:    AcpiNsCheckPackage
 PARAMETERS:  Info                - Method execution information block
              ReturnObjectPtr     - Pointer to the object returned from the
                                    evaluation of a method or object
FUNCTION : AcpiNsCheckPackage PARAMETERS : Info - Method execution information block ReturnObjectPtr - Pointer to the object returned from the evaluation of a method or object
/* The package info for this name is in the next table entry */ /*
     * For variable-length Packages, we can safely remove all embedded
     * and trailing NULL package elements
     */ /* Extract package count and elements array */ /*
     * Most packages must have at least one element. The only exception
     * is the variable-length package (ACPI_PTYPE1_VAR).
     */ /*
     * Decode the type of the expected package contents
     *
     * PTYPE1 packages contain no subpackages
     * PTYPE2 packages contain subpackages
     */ /*
         * The package count is fixed and there are no subpackages
         *
         * If package is too small, exit.
         * If package is larger than expected, issue warning but continue
         */ /* Validate all elements of the returned package */ /*
         * The package count is variable, there are no subpackages, and all
         * elements must be of the same type
         */ /*
         * The package count is variable, there are no subpackages. There are
         * a fixed number of required elements, and a variable number of
         * optional elements.
         *
         * Check if package is at least as large as the minimum required
         */ /* Variable number of sub-objects */ /* These are the required package elements (0, 1, or 2) */ /* These are the optional package elements */ /* First element is the (Integer) revision */ /* Examine the subpackages */ /* First element is the (Integer) count of subpackages to follow */ /*
         * Count cannot be larger than the parent package length, but allow it
         * to be smaller. The >= accounts for the Integer above.
         */ /* Examine the subpackages */ /*
         * These types all return a single Package that consists of a
         * variable number of subpackages.
         *
         * First, ensure that the first element is a subpackage. If not,
         * the BIOS may have incorrectly returned the object as a single
         * package instead of a Package of Packages (a common error if
         * there is only one entry). We may be able to repair this by
         * wrapping the returned Package with a new outer Package.
         */ /* Create the new outer package and populate it */ /* Update locals to point to the new package (of 1 element) */ /* Examine the subpackages */ /*
         * Returns a variable list of packages, each with a variable list
         * of objects.
         */ /* The package must contain pairs of (UUID + type) */ /* Validate length of the UUID buffer */ /* Should not get here if predefined info table is correct */ /* Error exit for the case with an incorrect package count */