static ACPI_STATUS AcpiNsCheckPackageElements ( ACPI_EVALUATE_INFO *Info, ACPI_OPERAND_OBJECT **Elements, UINT8 Type1, UINT32 Count1, UINT8 Type2, UINT32 Count2, UINT32 StartIndex) { ACPI_OPERAND_OBJECT **ThisElement = Elements; ACPI_STATUS Status; UINT32 i; /* * Up to two groups of package elements are supported by the data * structure. All elements in each group must be of the same type. * The second group can have a count of zero. */ for (i = 0; i < Count1; i++) { Status = AcpiNsCheckObjectType (Info, ThisElement, Type1, i + StartIndex); if (ACPI_FAILURE (Status)) { return (Status); } ThisElement++; } for (i = 0; i < Count2; i++) { Status = AcpiNsCheckObjectType (Info, ThisElement, Type2, (i + Count1 + StartIndex)); if (ACPI_FAILURE (Status)) { return (Status); } ThisElement++; } return (AE_OK); }
static ACPI_STATUS AcpiNsCheckPackageList ( ACPI_PREDEFINED_DATA *Data, const ACPI_PREDEFINED_INFO *Package, ACPI_OPERAND_OBJECT **Elements, UINT32 Count) { ACPI_OPERAND_OBJECT *SubPackage; ACPI_OPERAND_OBJECT **SubElements; ACPI_STATUS Status; UINT32 ExpectedCount; UINT32 i; UINT32 j; /* * Validate each sub-Package in the parent Package * * NOTE: assumes list of sub-packages contains no NULL elements. * Any NULL elements should have been removed by earlier call * to AcpiNsRemoveNullElements. */ for (i = 0; i < Count; i++) { SubPackage = *Elements; SubElements = SubPackage->Package.Elements; Data->ParentPackage = SubPackage; /* Each sub-object must be of type Package */ Status = AcpiNsCheckObjectType (Data, &SubPackage, ACPI_RTYPE_PACKAGE, i); if (ACPI_FAILURE (Status)) { return (Status); } /* Examine the different types of expected sub-packages */ Data->ParentPackage = SubPackage; switch (Package->RetInfo.Type) { case ACPI_PTYPE2: case ACPI_PTYPE2_PKG_COUNT: case ACPI_PTYPE2_REV_FIXED: /* Each subpackage has a fixed number of elements */ ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } Status = AcpiNsCheckPackageElements (Data, SubElements, Package->RetInfo.ObjectType1, Package->RetInfo.Count1, Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0); if (ACPI_FAILURE (Status)) { return (Status); } break; case ACPI_PTYPE2_FIX_VAR: /* * Each subpackage has a fixed number of elements and an * optional element */ ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } Status = AcpiNsCheckPackageElements (Data, SubElements, Package->RetInfo.ObjectType1, Package->RetInfo.Count1, Package->RetInfo.ObjectType2, SubPackage->Package.Count - Package->RetInfo.Count1, 0); if (ACPI_FAILURE (Status)) { return (Status); } break; case ACPI_PTYPE2_FIXED: /* Each sub-package has a fixed length */ ExpectedCount = Package->RetInfo2.Count; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } /* Check the type of each sub-package element */ for (j = 0; j < ExpectedCount; j++) { Status = AcpiNsCheckObjectType (Data, &SubElements[j], Package->RetInfo2.ObjectType[j], j); if (ACPI_FAILURE (Status)) { return (Status); } } break; case ACPI_PTYPE2_MIN: /* Each sub-package has a variable but minimum length */ ExpectedCount = Package->RetInfo.Count1; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } /* Check the type of each sub-package element */ Status = AcpiNsCheckPackageElements (Data, SubElements, Package->RetInfo.ObjectType1, SubPackage->Package.Count, 0, 0, 0); if (ACPI_FAILURE (Status)) { return (Status); } break; case ACPI_PTYPE2_COUNT: /* * First element is the (Integer) count of elements, including * the count field (the ACPI name is NumElements) */ Status = AcpiNsCheckObjectType (Data, SubElements, ACPI_RTYPE_INTEGER, 0); if (ACPI_FAILURE (Status)) { return (Status); } /* * Make sure package is large enough for the Count and is * is as large as the minimum size */ ExpectedCount = (UINT32) (*SubElements)->Integer.Value; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } if (SubPackage->Package.Count < Package->RetInfo.Count1) { ExpectedCount = Package->RetInfo.Count1; goto PackageTooSmall; } if (ExpectedCount == 0) { /* * Either the NumEntries element was originally zero or it was * a NULL element and repaired to an Integer of value zero. * In either case, repair it by setting NumEntries to be the * actual size of the subpackage. */ ExpectedCount = SubPackage->Package.Count; (*SubElements)->Integer.Value = ExpectedCount; } /* Check the type of each sub-package element */ Status = AcpiNsCheckPackageElements (Data, (SubElements + 1), Package->RetInfo.ObjectType1, (ExpectedCount - 1), 0, 0, 1); if (ACPI_FAILURE (Status)) { return (Status); } break; default: /* Should not get here, type was validated by caller */ return (AE_AML_INTERNAL); } Elements++; } return (AE_OK); PackageTooSmall: /* The sub-package count was smaller than required */ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, "Return Sub-Package[%u] is too small - found %u elements, expected %u", i, SubPackage->Package.Count, ExpectedCount)); return (AE_AML_OPERAND_VALUE); }
static ACPI_STATUS AcpiNsCheckPackage ( ACPI_PREDEFINED_DATA *Data, 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); /* The package info for this name is in the next table entry */ Package = Data->Predefined + 1; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s Validating return Package of Type %X, Count %X\n", Data->Pathname, Package->RetInfo.Type, ReturnObject->Package.Count)); /* * For variable-length Packages, we can safely remove all embedded * and trailing NULL package elements */ AcpiNsRemoveNullElements (Data, Package->RetInfo.Type, ReturnObject); /* Extract package count and elements array */ Elements = ReturnObject->Package.Elements; Count = ReturnObject->Package.Count; /* The package must have at least one element, else invalid */ if (!Count) { ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, "Return Package has no elements (empty)")); return (AE_AML_OPERAND_VALUE); } /* * Decode the type of the expected package contents * * PTYPE1 packages contain no subpackages * PTYPE2 packages contain sub-packages */ switch (Package->RetInfo.Type) { case ACPI_PTYPE1_FIXED: /* * The package count is fixed and there are no sub-packages * * If package is too small, exit. * If package is larger than expected, issue warning but continue */ 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", Data->Pathname, Count, ExpectedCount)); } /* Validate all elements of the returned package */ Status = AcpiNsCheckPackageElements (Data, Elements, Package->RetInfo.ObjectType1, Package->RetInfo.Count1, Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0); break; case ACPI_PTYPE1_VAR: /* * The package count is variable, there are no sub-packages, and all * elements must be of the same type */ for (i = 0; i < Count; i++) { Status = AcpiNsCheckObjectType (Data, Elements, Package->RetInfo.ObjectType1, i); if (ACPI_FAILURE (Status)) { return (Status); } Elements++; } break; case ACPI_PTYPE1_OPTION: /* * The package count is variable, there are no sub-packages. 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 */ ExpectedCount = Package->RetInfo3.Count; if (Count < ExpectedCount) { goto PackageTooSmall; } /* Variable number of sub-objects */ for (i = 0; i < Count; i++) { if (i < Package->RetInfo3.Count) { /* These are the required package elements (0, 1, or 2) */ Status = AcpiNsCheckObjectType (Data, Elements, Package->RetInfo3.ObjectType[i], i); if (ACPI_FAILURE (Status)) { return (Status); } } else { /* These are the optional package elements */ Status = AcpiNsCheckObjectType (Data, Elements, Package->RetInfo3.TailObjectType, i); if (ACPI_FAILURE (Status)) { return (Status); } } Elements++; } break; case ACPI_PTYPE2_REV_FIXED: /* First element is the (Integer) revision */ Status = AcpiNsCheckObjectType (Data, Elements, ACPI_RTYPE_INTEGER, 0); if (ACPI_FAILURE (Status)) { return (Status); } Elements++; Count--; /* Examine the sub-packages */ Status = AcpiNsCheckPackageList (Data, Package, Elements, Count); break; case ACPI_PTYPE2_PKG_COUNT: /* First element is the (Integer) count of sub-packages to follow */ Status = AcpiNsCheckObjectType (Data, Elements, ACPI_RTYPE_INTEGER, 0); if (ACPI_FAILURE (Status)) { return (Status); } /* * Count cannot be larger than the parent package length, but allow it * to be smaller. The >= accounts for the Integer above. */ ExpectedCount = (UINT32) (*Elements)->Integer.Value; if (ExpectedCount >= Count) { goto PackageTooSmall; } Count = ExpectedCount; Elements++; /* Examine the sub-packages */ Status = AcpiNsCheckPackageList (Data, Package, Elements, Count); break; case ACPI_PTYPE2: case ACPI_PTYPE2_FIXED: case ACPI_PTYPE2_MIN: case ACPI_PTYPE2_COUNT: case ACPI_PTYPE2_FIX_VAR: /* * These types all return a single Package that consists of a * variable number of sub-Packages. * * First, ensure that the first element is a sub-Package. 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. */ if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE)) { /* Create the new outer package and populate it */ Status = AcpiNsRepairPackageList (Data, ReturnObjectPtr); if (ACPI_FAILURE (Status)) { return (Status); } /* Update locals to point to the new package (of 1 element) */ ReturnObject = *ReturnObjectPtr; Elements = ReturnObject->Package.Elements; Count = 1; } /* Examine the sub-packages */ Status = AcpiNsCheckPackageList (Data, Package, Elements, Count); break; default: /* Should not get here if predefined info table is correct */ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, "Invalid internal return type in table entry: %X", Package->RetInfo.Type)); return (AE_AML_INTERNAL); } return (Status); PackageTooSmall: /* Error exit for the case with an incorrect package count */ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, "Return Package is too small - found %u elements, expected %u", Count, ExpectedCount)); return (AE_AML_OPERAND_VALUE); }
ACPI_STATUS AcpiNsCheckPredefinedNames ( ACPI_NAMESPACE_NODE *Node, UINT32 UserParamCount, ACPI_STATUS ReturnStatus, ACPI_OPERAND_OBJECT **ReturnObjectPtr) { ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; ACPI_STATUS Status = AE_OK; const ACPI_PREDEFINED_INFO *Predefined; char *Pathname; ACPI_PREDEFINED_DATA *Data; /* Match the name for this method/object against the predefined list */ Predefined = AcpiNsCheckForPredefinedName (Node); /* Get the full pathname to the object, for use in warning messages */ Pathname = AcpiNsGetExternalPathname (Node); if (!Pathname) { return (AE_OK); /* Could not get pathname, ignore */ } /* * Check that the parameter count for this method matches the ASL * definition. For predefined names, ensure that both the caller and * the method itself are in accordance with the ACPI specification. */ AcpiNsCheckParameterCount (Pathname, Node, UserParamCount, Predefined); /* If not a predefined name, we cannot validate the return object */ if (!Predefined) { goto Cleanup; } /* * If the method failed or did not actually return an object, we cannot * validate the return object */ if ((ReturnStatus != AE_OK) && (ReturnStatus != AE_CTRL_RETURN_VALUE)) { goto Cleanup; } /* * If there is no return value, check if we require a return value for * this predefined name. Either one return value is expected, or none, * for both methods and other objects. * * Exit now if there is no return object. Warning if one was expected. */ if (!ReturnObject) { if ((Predefined->Info.ExpectedBtypes) && (!(Predefined->Info.ExpectedBtypes & ACPI_RTYPE_NONE))) { ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "Missing expected return value")); Status = AE_AML_NO_RETURN_VALUE; } goto Cleanup; } /* * Return value validation and possible repair. * * 1) Don't perform return value validation/repair if this feature * has been disabled via a global option. * * 2) We have a return value, but if one wasn't expected, just exit, * this is not a problem. For example, if the "Implicit Return" * feature is enabled, methods will always return a value. * * 3) If the return value can be of any type, then we cannot perform * any validation, just exit. */ if (AcpiGbl_DisableAutoRepair || (!Predefined->Info.ExpectedBtypes) || (Predefined->Info.ExpectedBtypes == ACPI_RTYPE_ALL)) { goto Cleanup; } /* Create the parameter data block for object validation */ Data = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PREDEFINED_DATA)); if (!Data) { goto Cleanup; } Data->Predefined = Predefined; Data->Node = Node; Data->NodeFlags = Node->Flags; Data->Pathname = Pathname; /* * Check that the type of the main return object is what is expected * for this predefined name */ Status = AcpiNsCheckObjectType (Data, ReturnObjectPtr, Predefined->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT); if (ACPI_FAILURE (Status)) { goto Exit; } /* * For returned Package objects, check the type of all sub-objects. * Note: Package may have been newly created by call above. */ if ((*ReturnObjectPtr)->Common.Type == ACPI_TYPE_PACKAGE) { Data->ParentPackage = *ReturnObjectPtr; Status = AcpiNsCheckPackage (Data, ReturnObjectPtr); if (ACPI_FAILURE (Status)) { goto Exit; } } /* * The return object was OK, or it was successfully repaired above. * Now make some additional checks such as verifying that package * objects are sorted correctly (if required) or buffer objects have * the correct data width (bytes vs. dwords). These repairs are * performed on a per-name basis, i.e., the code is specific to * particular predefined names. */ Status = AcpiNsComplexRepairs (Data, Node, Status, ReturnObjectPtr); Exit: /* * If the object validation failed or if we successfully repaired one * or more objects, mark the parent node to suppress further warning * messages during the next evaluation of the same method/object. */ if (ACPI_FAILURE (Status) || (Data->Flags & ACPI_OBJECT_REPAIRED)) { Node->Flags |= ANOBJ_EVALUATED; } ACPI_FREE (Data); Cleanup: ACPI_FREE (Pathname); return (Status); }
ACPI_STATUS AcpiNsCheckReturnValue ( ACPI_NAMESPACE_NODE *Node, ACPI_EVALUATE_INFO *Info, UINT32 UserParamCount, ACPI_STATUS ReturnStatus, ACPI_OPERAND_OBJECT **ReturnObjectPtr) { ACPI_STATUS Status; const ACPI_PREDEFINED_INFO *Predefined; /* If not a predefined name, we cannot validate the return object */ Predefined = Info->Predefined; if (!Predefined) { return (AE_OK); } /* * If the method failed or did not actually return an object, we cannot * validate the return object */ if ((ReturnStatus != AE_OK) && (ReturnStatus != AE_CTRL_RETURN_VALUE)) { return (AE_OK); } /* * Return value validation and possible repair. * * 1) Don't perform return value validation/repair if this feature * has been disabled via a global option. * * 2) We have a return value, but if one wasn't expected, just exit, * this is not a problem. For example, if the "Implicit Return" * feature is enabled, methods will always return a value. * * 3) If the return value can be of any type, then we cannot perform * any validation, just exit. */ if (AcpiGbl_DisableAutoRepair || (!Predefined->Info.ExpectedBtypes) || (Predefined->Info.ExpectedBtypes == ACPI_RTYPE_ALL)) { return (AE_OK); } /* * Check that the type of the main return object is what is expected * for this predefined name */ Status = AcpiNsCheckObjectType (Info, ReturnObjectPtr, Predefined->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT); if (ACPI_FAILURE (Status)) { goto Exit; } /* * * 4) If there is no return value and it is optional, just return * AE_OK (_WAK). */ if (!(*ReturnObjectPtr)) { goto Exit; } /* * For returned Package objects, check the type of all sub-objects. * Note: Package may have been newly created by call above. */ if ((*ReturnObjectPtr)->Common.Type == ACPI_TYPE_PACKAGE) { Info->ParentPackage = *ReturnObjectPtr; Status = AcpiNsCheckPackage (Info, ReturnObjectPtr); if (ACPI_FAILURE (Status)) { /* We might be able to fix some errors */ if ((Status != AE_AML_OPERAND_TYPE) && (Status != AE_AML_OPERAND_VALUE)) { goto Exit; } } } /* * The return object was OK, or it was successfully repaired above. * Now make some additional checks such as verifying that package * objects are sorted correctly (if required) or buffer objects have * the correct data width (bytes vs. dwords). These repairs are * performed on a per-name basis, i.e., the code is specific to * particular predefined names. */ Status = AcpiNsComplexRepairs (Info, Node, Status, ReturnObjectPtr); Exit: /* * If the object validation failed or if we successfully repaired one * or more objects, mark the parent node to suppress further warning * messages during the next evaluation of the same method/object. */ if (ACPI_FAILURE (Status) || (Info->ReturnFlags & ACPI_OBJECT_REPAIRED)) { Node->Flags |= ANOBJ_EVALUATED; } return (Status); }
static ACPI_STATUS AcpiNsCheckPackageList ( ACPI_PREDEFINED_DATA *Data, const ACPI_PREDEFINED_INFO *Package, ACPI_OPERAND_OBJECT **Elements, UINT32 Count) { ACPI_OPERAND_OBJECT *SubPackage; ACPI_OPERAND_OBJECT **SubElements; ACPI_STATUS Status; UINT32 ExpectedCount; UINT32 i; UINT32 j; /* Validate each sub-Package in the parent Package */ for (i = 0; i < Count; i++) { SubPackage = *Elements; SubElements = SubPackage->Package.Elements; /* Each sub-object must be of type Package */ Status = AcpiNsCheckObjectType (Data, &SubPackage, ACPI_RTYPE_PACKAGE, i); if (ACPI_FAILURE (Status)) { return (Status); } /* Examine the different types of expected sub-packages */ switch (Package->RetInfo.Type) { case ACPI_PTYPE2: case ACPI_PTYPE2_PKG_COUNT: case ACPI_PTYPE2_REV_FIXED: /* Each subpackage has a fixed number of elements */ ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } Status = AcpiNsCheckPackageElements (Data, SubElements, Package->RetInfo.ObjectType1, Package->RetInfo.Count1, Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0); if (ACPI_FAILURE (Status)) { return (Status); } break; case ACPI_PTYPE2_FIXED: /* Each sub-package has a fixed length */ ExpectedCount = Package->RetInfo2.Count; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } /* Check the type of each sub-package element */ for (j = 0; j < ExpectedCount; j++) { Status = AcpiNsCheckObjectType (Data, &SubElements[j], Package->RetInfo2.ObjectType[j], j); if (ACPI_FAILURE (Status)) { return (Status); } } break; case ACPI_PTYPE2_MIN: /* Each sub-package has a variable but minimum length */ ExpectedCount = Package->RetInfo.Count1; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } /* Check the type of each sub-package element */ Status = AcpiNsCheckPackageElements (Data, SubElements, Package->RetInfo.ObjectType1, SubPackage->Package.Count, 0, 0, 0); if (ACPI_FAILURE (Status)) { return (Status); } break; case ACPI_PTYPE2_COUNT: /* * First element is the (Integer) count of elements, including * the count field. */ Status = AcpiNsCheckObjectType (Data, SubElements, ACPI_RTYPE_INTEGER, 0); if (ACPI_FAILURE (Status)) { return (Status); } /* * Make sure package is large enough for the Count and is * is as large as the minimum size */ ExpectedCount = (UINT32) (*SubElements)->Integer.Value; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } if (SubPackage->Package.Count < Package->RetInfo.Count1) { ExpectedCount = Package->RetInfo.Count1; goto PackageTooSmall; } /* Check the type of each sub-package element */ Status = AcpiNsCheckPackageElements (Data, (SubElements + 1), Package->RetInfo.ObjectType1, (ExpectedCount - 1), 0, 0, 1); if (ACPI_FAILURE (Status)) { return (Status); } break; default: /* Should not get here, type was validated by caller */ return (AE_AML_INTERNAL); } Elements++; } return (AE_OK); PackageTooSmall: /* The sub-package count was smaller than required */ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, "Return Sub-Package[%u] is too small - found %u elements, expected %u", i, SubPackage->Package.Count, ExpectedCount)); return (AE_AML_OPERAND_VALUE); }
ACPI_STATUS AcpiNsCheckPredefinedNames ( ACPI_NAMESPACE_NODE *Node, UINT32 UserParamCount, ACPI_STATUS ReturnStatus, ACPI_OPERAND_OBJECT **ReturnObjectPtr) { ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; ACPI_STATUS Status = AE_OK; const ACPI_PREDEFINED_INFO *Predefined; char *Pathname; ACPI_PREDEFINED_DATA *Data; /* Match the name for this method/object against the predefined list */ Predefined = AcpiNsCheckForPredefinedName (Node); /* Get the full pathname to the object, for use in warning messages */ #ifdef ACPI_DEBUG_OUTPUT /* AB */ Pathname = AcpiNsGetExternalPathname (Node); #else Pathname = NULL; #endif if (!Pathname) { return (AE_OK); /* Could not get pathname, ignore */ } /* * Check that the parameter count for this method matches the ASL * definition. For predefined names, ensure that both the caller and * the method itself are in accordance with the ACPI specification. */ AcpiNsCheckParameterCount (Pathname, Node, UserParamCount, Predefined); /* If not a predefined name, we cannot validate the return object */ if (!Predefined) { goto Cleanup; } /* * If the method failed or did not actually return an object, we cannot * validate the return object */ if ((ReturnStatus != AE_OK) && (ReturnStatus != AE_CTRL_RETURN_VALUE)) { goto Cleanup; } /* * If there is no return value, check if we require a return value for * this predefined name. Either one return value is expected, or none, * for both methods and other objects. * * Exit now if there is no return object. Warning if one was expected. */ if (!ReturnObject) { if ((Predefined->Info.ExpectedBtypes) && (!(Predefined->Info.ExpectedBtypes & ACPI_RTYPE_NONE))) { ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "Missing expected return value")); Status = AE_AML_NO_RETURN_VALUE; } goto Cleanup; } /* * 1) We have a return value, but if one wasn't expected, just exit, this is * not a problem. For example, if the "Implicit Return" feature is * enabled, methods will always return a value. * * 2) If the return value can be of any type, then we cannot perform any * validation, exit. */ if ((!Predefined->Info.ExpectedBtypes) || (Predefined->Info.ExpectedBtypes == ACPI_RTYPE_ALL)) { goto Cleanup; } /* Create the parameter data block for object validation */ Data = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PREDEFINED_DATA)); if (!Data) { goto Cleanup; } Data->Predefined = Predefined; Data->NodeFlags = Node->Flags; Data->Pathname = Pathname; /* * Check that the type of the return object is what is expected for * this predefined name */ Status = AcpiNsCheckObjectType (Data, ReturnObjectPtr, Predefined->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT); if (ACPI_FAILURE (Status)) { goto CheckValidationStatus; } /* For returned Package objects, check the type of all sub-objects */ if (ReturnObject->Common.Type == ACPI_TYPE_PACKAGE) { Status = AcpiNsCheckPackage (Data, ReturnObjectPtr); } CheckValidationStatus: /* * If the object validation failed or if we successfully repaired one * or more objects, mark the parent node to suppress further warning * messages during the next evaluation of the same method/object. */ if (ACPI_FAILURE (Status) || (Data->Flags & ACPI_OBJECT_REPAIRED)) { Node->Flags |= ANOBJ_EVALUATED; } ACPI_FREE (Data); Cleanup: ACPI_FREE (Pathname); return (Status); }
static ACPI_STATUS AcpiNsCheckPackageList ( ACPI_PREDEFINED_DATA *Data, const ACPI_PREDEFINED_INFO *Package, ACPI_OPERAND_OBJECT **Elements, UINT32 Count) { ACPI_OPERAND_OBJECT *SubPackage; ACPI_OPERAND_OBJECT **SubElements; ACPI_STATUS Status; BOOLEAN NonTrailingNull = FALSE; UINT32 ExpectedCount; UINT32 i; UINT32 j; /* Validate each sub-Package in the parent Package */ for (i = 0; i < Count; i++) { /* * Handling for NULL package elements. For now, we will simply allow * a parent package with trailing NULL elements. This can happen if * the package was defined to be longer than the initializer list. * This is legal as per the ACPI specification. It is often used * to allow for dynamic initialization of a Package. * * A future enhancement may be to simply truncate the package to * remove the trailing NULL elements. */ if (!(*Elements)) { if (!NonTrailingNull) { /* Ensure the remaining elements are all NULL */ for (j = 1; j < (Count - i + 1); j++) { if (Elements[j]) { NonTrailingNull = TRUE; } } if (!NonTrailingNull) { /* Ignore the trailing NULL elements */ return (AE_OK); } } /* There are trailing non-null elements, issue warning */ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, "Found NULL element at package index %u", i)); Elements++; continue; } SubPackage = *Elements; SubElements = SubPackage->Package.Elements; /* Each sub-object must be of type Package */ Status = AcpiNsCheckObjectType (Data, &SubPackage, ACPI_RTYPE_PACKAGE, i); if (ACPI_FAILURE (Status)) { return (Status); } /* Examine the different types of expected sub-packages */ switch (Package->RetInfo.Type) { case ACPI_PTYPE2: case ACPI_PTYPE2_PKG_COUNT: case ACPI_PTYPE2_REV_FIXED: /* Each subpackage has a fixed number of elements */ ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } Status = AcpiNsCheckPackageElements (Data, SubElements, Package->RetInfo.ObjectType1, Package->RetInfo.Count1, Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0); if (ACPI_FAILURE (Status)) { return (Status); } break; case ACPI_PTYPE2_FIXED: /* Each sub-package has a fixed length */ ExpectedCount = Package->RetInfo2.Count; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } /* Check the type of each sub-package element */ for (j = 0; j < ExpectedCount; j++) { Status = AcpiNsCheckObjectType (Data, &SubElements[j], Package->RetInfo2.ObjectType[j], j); if (ACPI_FAILURE (Status)) { return (Status); } } break; case ACPI_PTYPE2_MIN: /* Each sub-package has a variable but minimum length */ ExpectedCount = Package->RetInfo.Count1; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } /* Check the type of each sub-package element */ Status = AcpiNsCheckPackageElements (Data, SubElements, Package->RetInfo.ObjectType1, SubPackage->Package.Count, 0, 0, 0); if (ACPI_FAILURE (Status)) { return (Status); } break; case ACPI_PTYPE2_COUNT: /* * First element is the (Integer) count of elements, including * the count field. */ Status = AcpiNsCheckObjectType (Data, SubElements, ACPI_RTYPE_INTEGER, 0); if (ACPI_FAILURE (Status)) { return (Status); } /* * Make sure package is large enough for the Count and is * is as large as the minimum size */ ExpectedCount = (UINT32) (*SubElements)->Integer.Value; if (SubPackage->Package.Count < ExpectedCount) { goto PackageTooSmall; } if (SubPackage->Package.Count < Package->RetInfo.Count1) { ExpectedCount = Package->RetInfo.Count1; goto PackageTooSmall; } /* Check the type of each sub-package element */ Status = AcpiNsCheckPackageElements (Data, (SubElements + 1), Package->RetInfo.ObjectType1, (ExpectedCount - 1), 0, 0, 1); if (ACPI_FAILURE (Status)) { return (Status); } break; default: /* Should not get here, type was validated by caller */ return (AE_AML_INTERNAL); } Elements++; } return (AE_OK); PackageTooSmall: /* The sub-package count was smaller than required */ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, "Return Sub-Package[%u] is too small - found %u elements, expected %u", i, SubPackage->Package.Count, ExpectedCount)); return (AE_AML_OPERAND_VALUE); }