static ACPI_STATUS AcpiDbWalkForPredefinedNames ( ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context, void **ReturnValue) { ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; UINT32 *Count = (UINT32 *) Context; const ACPI_PREDEFINED_INFO *Predefined; const ACPI_PREDEFINED_INFO *Package = NULL; char *Pathname; char StringBuffer[48]; Predefined = AcpiUtMatchPredefinedMethod (Node->Name.Ascii); if (!Predefined) { return (AE_OK); } Pathname = AcpiNsGetExternalPathname (Node); if (!Pathname) { return (AE_OK); } /* If method returns a package, the info is in the next table entry */ if (Predefined->Info.ExpectedBtypes & ACPI_RTYPE_PACKAGE) { Package = Predefined + 1; } AcpiUtGetExpectedReturnTypes (StringBuffer, Predefined->Info.ExpectedBtypes); AcpiOsPrintf ("%-32s Arguments %X, Return Types: %s", Pathname, METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList), StringBuffer); if (Package) { AcpiOsPrintf (" (PkgType %2.2X, ObjType %2.2X, Count %2.2X)", Package->RetInfo.Type, Package->RetInfo.ObjectType1, Package->RetInfo.Count1); } AcpiOsPrintf("\n"); /* Check that the declared argument count matches the ACPI spec */ AcpiNsCheckAcpiCompliance (Pathname, Node, Predefined); ACPI_FREE (Pathname); (*Count)++; return (AE_OK); }
static acpi_status acpi_db_walk_for_predefined_names(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { struct acpi_namespace_node *node = (struct acpi_namespace_node *)obj_handle; u32 *count = (u32 *)context; const union acpi_predefined_info *predefined; const union acpi_predefined_info *package = NULL; char *pathname; char string_buffer[48]; predefined = acpi_ut_match_predefined_method(node->name.ascii); if (!predefined) { return (AE_OK); } pathname = acpi_ns_get_normalized_pathname(node, TRUE); if (!pathname) { return (AE_OK); } /* If method returns a package, the info is in the next table entry */ if (predefined->info.expected_btypes & ACPI_RTYPE_PACKAGE) { package = predefined + 1; } acpi_ut_get_expected_return_types(string_buffer, predefined->info.expected_btypes); acpi_os_printf("%-32s Arguments %X, Return Types: %s", pathname, METHOD_GET_ARG_COUNT(predefined->info.argument_list), string_buffer); if (package) { acpi_os_printf(" (PkgType %2.2X, ObjType %2.2X, Count %2.2X)", package->ret_info.type, package->ret_info.object_type1, package->ret_info.count1); } acpi_os_printf("\n"); /* Check that the declared argument count matches the ACPI spec */ acpi_ns_check_acpi_compliance(pathname, node, predefined); ACPI_FREE(pathname); (*count)++; return (AE_OK); }
static UINT32 AcpiUtGetArgumentTypes ( char *Buffer, UINT16 ArgumentTypes) { UINT16 ThisArgumentType; UINT16 SubIndex; UINT16 ArgCount; UINT32 i; *Buffer = 0; SubIndex = 2; /* First field in the types list is the count of args to follow */ ArgCount = METHOD_GET_ARG_COUNT (ArgumentTypes); if (ArgCount > METHOD_PREDEF_ARGS_MAX) { printf ("**** Invalid argument count (%u) " "in predefined info structure\n", ArgCount); return (ArgCount); } /* Get each argument from the list, convert to ascii, store to buffer */ for (i = 0; i < ArgCount; i++) { ThisArgumentType = METHOD_GET_NEXT_TYPE (ArgumentTypes); if (!ThisArgumentType || (ThisArgumentType > METHOD_MAX_ARG_TYPE)) { printf ("**** Invalid argument type (%u) " "in predefined info structure\n", ThisArgumentType); return (ArgCount); } strcat (Buffer, UtExternalTypeNames[ThisArgumentType] + SubIndex); SubIndex = 0; } return (ArgCount); }
static u32 acpi_ut_get_argument_types(char *buffer, u16 argument_types) { u16 this_argument_type; u16 sub_index; u16 arg_count; u32 i; *buffer = 0; sub_index = 2; /* First field in the types list is the count of args to follow */ arg_count = METHOD_GET_ARG_COUNT(argument_types); if (arg_count > METHOD_PREDEF_ARGS_MAX) { printf("**** Invalid argument count (%u) " "in predefined info structure\n", arg_count); return (arg_count); } /* Get each argument from the list, convert to ascii, store to buffer */ for (i = 0; i < arg_count; i++) { this_argument_type = METHOD_GET_NEXT_TYPE(argument_types); if (!this_argument_type || (this_argument_type > METHOD_MAX_ARG_TYPE)) { printf("**** Invalid argument type (%u) " "in predefined info structure\n", this_argument_type); return (arg_count); } strcat(buffer, ut_external_type_names[this_argument_type] + sub_index); sub_index = 0; } return (arg_count); }
void AcpiNsCheckArgumentTypes ( ACPI_EVALUATE_INFO *Info) { UINT16 ArgTypeList; UINT8 ArgCount; UINT8 ArgType; UINT8 UserArgType; UINT32 i; /* If not a predefined name, cannot typecheck args */ if (!Info->Predefined) { return; } ArgTypeList = Info->Predefined->Info.ArgumentList; ArgCount = METHOD_GET_ARG_COUNT (ArgTypeList); /* Typecheck all arguments */ for (i = 0; ((i < ArgCount) && (i < Info->ParamCount)); i++) { ArgType = METHOD_GET_NEXT_TYPE (ArgTypeList); UserArgType = Info->Parameters[i]->Common.Type; if (UserArgType != ArgType) { ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS, "Argument #%u type mismatch - " "Found [%s], ACPI requires [%s]", (i + 1), AcpiUtGetTypeName (UserArgType), AcpiUtGetTypeName (ArgType))); } } }
BOOLEAN ApCheckForPredefinedMethod ( ACPI_PARSE_OBJECT *Op, ASL_METHOD_INFO *MethodInfo) { UINT32 Index; UINT32 RequiredArgCount; const ACPI_PREDEFINED_INFO *ThisName; /* Check for a match against the predefined name list */ Index = ApCheckForPredefinedName (Op, Op->Asl.NameSeg); switch (Index) { case ACPI_NOT_RESERVED_NAME: /* No underscore or _Txx or _xxx name not matched */ case ACPI_PREDEFINED_NAME: /* Resource Name or reserved scope name */ case ACPI_COMPILER_RESERVED_NAME: /* A _Txx that was not emitted by compiler */ /* Just return, nothing to do */ return (FALSE); case ACPI_EVENT_RESERVED_NAME: /* _Lxx/_Exx/_Wxx/_Qxx methods */ Gbl_ReservedMethods++; /* NumArguments must be zero for all _Lxx/_Exx/_Wxx/_Qxx methods */ if (MethodInfo->NumArguments != 0) { sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName, 0); AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op, MsgBuffer); } break; default: /* * Matched a predefined method name - validate the ASL-defined * argument count against the ACPI specification. * * Some methods are allowed to have a "minimum" number of args * (_SCP) because their definition in ACPI has changed over time. */ Gbl_ReservedMethods++; ThisName = &AcpiGbl_PredefinedMethods[Index]; RequiredArgCount = METHOD_GET_ARG_COUNT (ThisName->Info.ArgumentList); if (MethodInfo->NumArguments != RequiredArgCount) { sprintf (MsgBuffer, "%4.4s requires %u", ThisName->Info.Name, RequiredArgCount); if (MethodInfo->NumArguments < RequiredArgCount) { AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_LO, Op, MsgBuffer); } else if ((MethodInfo->NumArguments > RequiredArgCount) && !(ThisName->Info.ArgumentList & ARG_COUNT_IS_MINIMUM)) { AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op, MsgBuffer); } } /* * Check if method returns no value, but the predefined name is * required to return a value */ if (MethodInfo->NumReturnNoValue && ThisName->Info.ExpectedBtypes) { AcpiUtGetExpectedReturnTypes (StringBuffer, ThisName->Info.ExpectedBtypes); sprintf (MsgBuffer, "%s required for %4.4s", StringBuffer, ThisName->Info.Name); AslError (ASL_WARNING, ASL_MSG_RESERVED_RETURN_VALUE, Op, MsgBuffer); } break; } return (TRUE); }
void ApCheckForPredefinedObject ( ACPI_PARSE_OBJECT *Op, char *Name) { UINT32 Index; ACPI_PARSE_OBJECT *ObjectOp; const ACPI_PREDEFINED_INFO *ThisName; /* * Check for a real predefined name -- not a resource descriptor name * or a predefined scope name */ Index = ApCheckForPredefinedName (Op, Name); switch (Index) { case ACPI_NOT_RESERVED_NAME: /* No underscore or _Txx or _xxx name not matched */ case ACPI_PREDEFINED_NAME: /* Resource Name or reserved scope name */ case ACPI_COMPILER_RESERVED_NAME: /* A _Txx that was not emitted by compiler */ /* Nothing to do */ return; case ACPI_EVENT_RESERVED_NAME: /* _Lxx/_Exx/_Wxx/_Qxx methods */ /* * These names must be control methods, by definition in ACPI spec. * Also because they are defined to return no value. None of them * require any arguments. */ AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, "with zero arguments"); return; default: break; } /* A standard predefined ACPI name */ /* * If this predefined name requires input arguments, then * it must be implemented as a control method */ ThisName = &AcpiGbl_PredefinedMethods[Index]; if (METHOD_GET_ARG_COUNT (ThisName->Info.ArgumentList) > 0) { AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, "with arguments"); return; } /* * If no return value is expected from this predefined name, then * it follows that it must be implemented as a control method * (with zero args, because the args > 0 case was handled above) * Examples are: _DIS, _INI, _IRC, _OFF, _ON, _PSx */ if (!ThisName->Info.ExpectedBtypes) { AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, "with zero arguments"); return; } /* Typecheck the actual object, it is the next argument */ ObjectOp = Op->Asl.Child->Asl.Next; ApCheckObjectType (ThisName->Info.Name, Op->Asl.Child->Asl.Next, ThisName->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT); /* For packages, check the individual package elements */ if (ObjectOp->Asl.ParseOpcode == PARSEOP_PACKAGE) { ApCheckPackage (ObjectOp, ThisName); } }
static ACPI_STATUS AcpiDbWalkForExecute ( ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context, void **ReturnValue) { ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; ACPI_DB_EXECUTE_WALK *Info = (ACPI_DB_EXECUTE_WALK *) Context; char *Pathname; const ACPI_PREDEFINED_INFO *Predefined; ACPI_DEVICE_INFO *ObjInfo; ACPI_OBJECT_LIST ParamObjects; ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; ACPI_OBJECT *ThisParam; ACPI_BUFFER ReturnObj; ACPI_STATUS Status; UINT16 ArgTypeList; UINT8 ArgCount; UINT8 ArgType; UINT32 i; /* The name must be a predefined ACPI name */ Predefined = AcpiUtMatchPredefinedMethod (Node->Name.Ascii); if (!Predefined) { return (AE_OK); } if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) { return (AE_OK); } Pathname = AcpiNsGetExternalPathname (Node); if (!Pathname) { return (AE_OK); } /* Get the object info for number of method parameters */ Status = AcpiGetObjectInfo (ObjHandle, &ObjInfo); if (ACPI_FAILURE (Status)) { return (Status); } ParamObjects.Count = 0; ParamObjects.Pointer = NULL; if (ObjInfo->Type == ACPI_TYPE_METHOD) { /* Setup default parameters (with proper types) */ ArgTypeList = Predefined->Info.ArgumentList; ArgCount = METHOD_GET_ARG_COUNT (ArgTypeList); /* * Setup the ACPI-required number of arguments, regardless of what * the actual method defines. If there is a difference, then the * method is wrong and a warning will be issued during execution. */ ThisParam = Params; for (i = 0; i < ArgCount; i++) { ArgType = METHOD_GET_NEXT_TYPE (ArgTypeList); ThisParam->Type = ArgType; switch (ArgType) { case ACPI_TYPE_INTEGER: ThisParam->Integer.Value = 1; break; case ACPI_TYPE_STRING: ThisParam->String.Pointer = __UNCONST( "This is the default argument string"); ThisParam->String.Length = ACPI_STRLEN (ThisParam->String.Pointer); break; case ACPI_TYPE_BUFFER: ThisParam->Buffer.Pointer = (UINT8 *) Params; /* just a garbage buffer */ ThisParam->Buffer.Length = 48; break; case ACPI_TYPE_PACKAGE: ThisParam->Package.Elements = NULL; ThisParam->Package.Count = 0; break; default: AcpiOsPrintf ("%s: Unsupported argument type: %u\n", Pathname, ArgType); break; } ThisParam++; } ParamObjects.Count = ArgCount; ParamObjects.Pointer = Params; } ACPI_FREE (ObjInfo); ReturnObj.Pointer = NULL; ReturnObj.Length = ACPI_ALLOCATE_BUFFER; /* Do the actual method execution */ AcpiGbl_MethodExecuting = TRUE; Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj); AcpiOsPrintf ("%-32s returned %s\n", Pathname, AcpiFormatException (Status)); AcpiGbl_MethodExecuting = FALSE; ACPI_FREE (Pathname); /* Ignore status from method execution */ Status = AE_OK; /* Update count, check if we have executed enough methods */ Info->Count++; if (Info->Count >= Info->MaxCount) { Status = AE_CTRL_TERMINATE; } return (Status); }
static acpi_status acpi_db_evaluate_one_predefined_name(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { struct acpi_namespace_node *node = (struct acpi_namespace_node *)obj_handle; struct acpi_db_execute_walk *info = (struct acpi_db_execute_walk *)context; char *pathname; const union acpi_predefined_info *predefined; struct acpi_device_info *obj_info; struct acpi_object_list param_objects; union acpi_object params[ACPI_METHOD_NUM_ARGS]; union acpi_object *this_param; struct acpi_buffer return_obj; acpi_status status; u16 arg_type_list; u8 arg_count; u8 arg_type; u32 i; /* The name must be a predefined ACPI name */ predefined = acpi_ut_match_predefined_method(node->name.ascii); if (!predefined) { return (AE_OK); } if (node->type == ACPI_TYPE_LOCAL_SCOPE) { return (AE_OK); } pathname = acpi_ns_get_normalized_pathname(node, TRUE); if (!pathname) { return (AE_OK); } /* Get the object info for number of method parameters */ status = acpi_get_object_info(obj_handle, &obj_info); if (ACPI_FAILURE(status)) { ACPI_FREE(pathname); return (status); } param_objects.count = 0; param_objects.pointer = NULL; if (obj_info->type == ACPI_TYPE_METHOD) { /* Setup default parameters (with proper types) */ arg_type_list = predefined->info.argument_list; arg_count = METHOD_GET_ARG_COUNT(arg_type_list); /* * Setup the ACPI-required number of arguments, regardless of what * the actual method defines. If there is a difference, then the * method is wrong and a warning will be issued during execution. */ this_param = params; for (i = 0; i < arg_count; i++) { arg_type = METHOD_GET_NEXT_TYPE(arg_type_list); this_param->type = arg_type; switch (arg_type) { case ACPI_TYPE_INTEGER: this_param->integer.value = 1; break; case ACPI_TYPE_STRING: this_param->string.pointer = "This is the default argument string"; this_param->string.length = strlen(this_param->string.pointer); break; case ACPI_TYPE_BUFFER: this_param->buffer.pointer = (u8 *)params; /* just a garbage buffer */ this_param->buffer.length = 48; break; case ACPI_TYPE_PACKAGE: this_param->package.elements = NULL; this_param->package.count = 0; break; default: acpi_os_printf ("%s: Unsupported argument type: %u\n", pathname, arg_type); break; } this_param++; } param_objects.count = arg_count; param_objects.pointer = params; } ACPI_FREE(obj_info); return_obj.pointer = NULL; return_obj.length = ACPI_ALLOCATE_BUFFER; /* Do the actual method execution */ acpi_gbl_method_executing = TRUE; status = acpi_evaluate_object(node, NULL, ¶m_objects, &return_obj); acpi_os_printf("%-32s returned %s\n", pathname, acpi_format_exception(status)); acpi_gbl_method_executing = FALSE; ACPI_FREE(pathname); /* Ignore status from method execution */ status = AE_OK; /* Update count, check if we have executed enough methods */ info->count++; if (info->count >= info->max_count) { status = AE_CTRL_TERMINATE; } return (status); }
void AcpiNsCheckArgumentCount ( char *Pathname, ACPI_NAMESPACE_NODE *Node, UINT32 UserParamCount, const ACPI_PREDEFINED_INFO *Predefined) { UINT32 AmlParamCount; UINT32 RequiredParamCount; if (!Predefined) { /* * Not a predefined name. Check the incoming user argument count * against the count that is specified in the method/object. */ if (Node->Type != ACPI_TYPE_METHOD) { if (UserParamCount) { ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "%u arguments were passed to a non-method ACPI object (%s)", UserParamCount, AcpiUtGetTypeName (Node->Type))); } return; } /* * This is a control method. Check the parameter count. * We can only check the incoming argument count against the * argument count declared for the method in the ASL/AML. * * Emit a message if too few or too many arguments have been passed * by the caller. * * Note: Too many arguments will not cause the method to * fail. However, the method will fail if there are too few * arguments and the method attempts to use one of the missing ones. */ AmlParamCount = Node->Object->Method.ParamCount; if (UserParamCount < AmlParamCount) { ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "Insufficient arguments - " "Caller passed %u, method requires %u", UserParamCount, AmlParamCount)); } else if (UserParamCount > AmlParamCount) { ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "Excess arguments - " "Caller passed %u, method requires %u", UserParamCount, AmlParamCount)); } return; } /* * This is a predefined name. Validate the user-supplied parameter * count against the ACPI specification. We don't validate against * the method itself because what is important here is that the * caller is in conformance with the spec. (The arg count for the * method was checked against the ACPI spec earlier.) * * Some methods are allowed to have a "minimum" number of args (_SCP) * because their definition in ACPI has changed over time. */ RequiredParamCount = METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList); if (UserParamCount < RequiredParamCount) { ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "Insufficient arguments - " "Caller passed %u, ACPI requires %u", UserParamCount, RequiredParamCount)); } else if ((UserParamCount > RequiredParamCount) && !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM)) { ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "Excess arguments - " "Caller passed %u, ACPI requires %u", UserParamCount, RequiredParamCount)); } }
void AcpiNsCheckAcpiCompliance ( char *Pathname, ACPI_NAMESPACE_NODE *Node, const ACPI_PREDEFINED_INFO *Predefined) { UINT32 AmlParamCount; UINT32 RequiredParamCount; if (!Predefined) { return; } /* Get the ACPI-required arg count from the predefined info table */ RequiredParamCount = METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList); /* * If this object is not a control method, we can check if the ACPI * spec requires that it be a method. */ if (Node->Type != ACPI_TYPE_METHOD) { if (RequiredParamCount > 0) { /* Object requires args, must be implemented as a method */ ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "Object (%s) must be a control method with %u arguments", AcpiUtGetTypeName (Node->Type), RequiredParamCount)); } else if (!RequiredParamCount && !Predefined->Info.ExpectedBtypes) { /* Object requires no args and no return value, must be a method */ ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "Object (%s) must be a control method " "with no arguments and no return value", AcpiUtGetTypeName (Node->Type))); } return; } /* * This is a control method. * Check that the ASL/AML-defined parameter count for this method * matches the ACPI-required parameter count * * Some methods are allowed to have a "minimum" number of args (_SCP) * because their definition in ACPI has changed over time. * * Note: These are BIOS errors in the declaration of the object */ AmlParamCount = Node->Object->Method.ParamCount; if (AmlParamCount < RequiredParamCount) { ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "Insufficient arguments - " "ASL declared %u, ACPI requires %u", AmlParamCount, RequiredParamCount)); } else if ((AmlParamCount > RequiredParamCount) && !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM)) { ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "Excess arguments - " "ASL declared %u, ACPI requires %u", AmlParamCount, RequiredParamCount)); } }