diff options
Diffstat (limited to 'drivers/acpi/acpica/nseval.c')
-rw-r--r-- | drivers/acpi/acpica/nseval.c | 247 |
1 files changed, 142 insertions, 105 deletions
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index b61db69d5675..18108bc2e51c 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c | |||
@@ -61,7 +61,7 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, | |||
61 | * | 61 | * |
62 | * PARAMETERS: info - Evaluation info block, contains: | 62 | * PARAMETERS: info - Evaluation info block, contains: |
63 | * prefix_node - Prefix or Method/Object Node to execute | 63 | * prefix_node - Prefix or Method/Object Node to execute |
64 | * pathname - Name of method to execute, If NULL, the | 64 | * relative_path - Name of method to execute, If NULL, the |
65 | * Node is the object to execute | 65 | * Node is the object to execute |
66 | * parameters - List of parameters to pass to the method, | 66 | * parameters - List of parameters to pass to the method, |
67 | * terminated by NULL. Params itself may be | 67 | * terminated by NULL. Params itself may be |
@@ -82,10 +82,9 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, | |||
82 | * | 82 | * |
83 | ******************************************************************************/ | 83 | ******************************************************************************/ |
84 | 84 | ||
85 | acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | 85 | acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) |
86 | { | 86 | { |
87 | acpi_status status; | 87 | acpi_status status; |
88 | struct acpi_namespace_node *node; | ||
89 | 88 | ||
90 | ACPI_FUNCTION_TRACE(ns_evaluate); | 89 | ACPI_FUNCTION_TRACE(ns_evaluate); |
91 | 90 | ||
@@ -93,83 +92,138 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | |||
93 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 92 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
94 | } | 93 | } |
95 | 94 | ||
96 | /* Initialize the return value to an invalid object */ | 95 | if (!info->node) { |
97 | |||
98 | info->return_object = NULL; | ||
99 | info->param_count = 0; | ||
100 | |||
101 | if (!info->resolved_node) { | ||
102 | /* | 96 | /* |
103 | * Get the actual namespace node for the target object if we need to. | 97 | * Get the actual namespace node for the target object if we |
104 | * Handles these cases: | 98 | * need to. Handles these cases: |
105 | * | 99 | * |
106 | * 1) Null node, Pathname (absolute path) | 100 | * 1) Null node, valid pathname from root (absolute path) |
107 | * 2) Node, Pathname (path relative to Node) | 101 | * 2) Node and valid pathname (path relative to Node) |
108 | * 3) Node, Null Pathname | 102 | * 3) Node, Null pathname |
109 | */ | 103 | */ |
110 | status = acpi_ns_get_node(info->prefix_node, info->pathname, | 104 | status = |
111 | ACPI_NS_NO_UPSEARCH, | 105 | acpi_ns_get_node(info->prefix_node, info->relative_pathname, |
112 | &info->resolved_node); | 106 | ACPI_NS_NO_UPSEARCH, &info->node); |
113 | if (ACPI_FAILURE(status)) { | 107 | if (ACPI_FAILURE(status)) { |
114 | return_ACPI_STATUS(status); | 108 | return_ACPI_STATUS(status); |
115 | } | 109 | } |
116 | } | 110 | } |
117 | 111 | ||
118 | /* | 112 | /* |
119 | * For a method alias, we must grab the actual method node so that proper | 113 | * For a method alias, we must grab the actual method node so that |
120 | * scoping context will be established before execution. | 114 | * proper scoping context will be established before execution. |
121 | */ | 115 | */ |
122 | if (acpi_ns_get_type(info->resolved_node) == | 116 | if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { |
123 | ACPI_TYPE_LOCAL_METHOD_ALIAS) { | 117 | info->node = |
124 | info->resolved_node = | ||
125 | ACPI_CAST_PTR(struct acpi_namespace_node, | 118 | ACPI_CAST_PTR(struct acpi_namespace_node, |
126 | info->resolved_node->object); | 119 | info->node->object); |
120 | } | ||
121 | |||
122 | /* Complete the info block initialization */ | ||
123 | |||
124 | info->return_object = NULL; | ||
125 | info->node_flags = info->node->flags; | ||
126 | info->obj_desc = acpi_ns_get_attached_object(info->node); | ||
127 | |||
128 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", | ||
129 | info->relative_pathname, info->node, | ||
130 | acpi_ns_get_attached_object(info->node))); | ||
131 | |||
132 | /* Get info if we have a predefined name (_HID, etc.) */ | ||
133 | |||
134 | info->predefined = | ||
135 | acpi_ut_match_predefined_method(info->node->name.ascii); | ||
136 | |||
137 | /* Get the full pathname to the object, for use in warning messages */ | ||
138 | |||
139 | info->full_pathname = acpi_ns_get_external_pathname(info->node); | ||
140 | if (!info->full_pathname) { | ||
141 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
127 | } | 142 | } |
128 | 143 | ||
129 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname, | 144 | /* Count the number of arguments being passed in */ |
130 | info->resolved_node, | 145 | |
131 | acpi_ns_get_attached_object(info->resolved_node))); | 146 | info->param_count = 0; |
147 | if (info->parameters) { | ||
148 | while (info->parameters[info->param_count]) { | ||
149 | info->param_count++; | ||
150 | } | ||
151 | |||
152 | /* Warn on impossible argument count */ | ||
153 | |||
154 | if (info->param_count > ACPI_METHOD_NUM_ARGS) { | ||
155 | ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, | ||
156 | ACPI_WARN_ALWAYS, | ||
157 | "Excess arguments (%u) - using only %u", | ||
158 | info->param_count, | ||
159 | ACPI_METHOD_NUM_ARGS)); | ||
160 | |||
161 | info->param_count = ACPI_METHOD_NUM_ARGS; | ||
162 | } | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * For predefined names: Check that the declared argument count | ||
167 | * matches the ACPI spec -- otherwise this is a BIOS error. | ||
168 | */ | ||
169 | acpi_ns_check_acpi_compliance(info->full_pathname, info->node, | ||
170 | info->predefined); | ||
171 | |||
172 | /* | ||
173 | * For all names: Check that the incoming argument count for | ||
174 | * this method/object matches the actual ASL/AML definition. | ||
175 | */ | ||
176 | acpi_ns_check_argument_count(info->full_pathname, info->node, | ||
177 | info->param_count, info->predefined); | ||
132 | 178 | ||
133 | node = info->resolved_node; | 179 | /* For predefined names: Typecheck all incoming arguments */ |
180 | |||
181 | acpi_ns_check_argument_types(info); | ||
134 | 182 | ||
135 | /* | 183 | /* |
136 | * Two major cases here: | 184 | * Three major evaluation cases: |
137 | * | 185 | * |
138 | * 1) The object is a control method -- execute it | 186 | * 1) Object types that cannot be evaluated by definition |
139 | * 2) The object is not a method -- just return it's current value | 187 | * 2) The object is a control method -- execute it |
188 | * 3) The object is not a method -- just return it's current value | ||
140 | */ | 189 | */ |
141 | if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) { | 190 | switch (acpi_ns_get_type(info->node)) { |
191 | case ACPI_TYPE_DEVICE: | ||
192 | case ACPI_TYPE_EVENT: | ||
193 | case ACPI_TYPE_MUTEX: | ||
194 | case ACPI_TYPE_REGION: | ||
195 | case ACPI_TYPE_THERMAL: | ||
196 | case ACPI_TYPE_LOCAL_SCOPE: | ||
197 | /* | ||
198 | * 1) Disallow evaluation of certain object types. For these, | ||
199 | * object evaluation is undefined and not supported. | ||
200 | */ | ||
201 | ACPI_ERROR((AE_INFO, | ||
202 | "%s: Evaluation of object type [%s] is not supported", | ||
203 | info->full_pathname, | ||
204 | acpi_ut_get_type_name(info->node->type))); | ||
205 | |||
206 | status = AE_TYPE; | ||
207 | goto cleanup; | ||
208 | |||
209 | case ACPI_TYPE_METHOD: | ||
142 | /* | 210 | /* |
143 | * 1) Object is a control method - execute it | 211 | * 2) Object is a control method - execute it |
144 | */ | 212 | */ |
145 | 213 | ||
146 | /* Verify that there is a method object associated with this node */ | 214 | /* Verify that there is a method object associated with this node */ |
147 | 215 | ||
148 | info->obj_desc = | ||
149 | acpi_ns_get_attached_object(info->resolved_node); | ||
150 | if (!info->obj_desc) { | 216 | if (!info->obj_desc) { |
151 | ACPI_ERROR((AE_INFO, | 217 | ACPI_ERROR((AE_INFO, |
152 | "Control method has no attached sub-object")); | 218 | "%s: Method has no attached sub-object", |
153 | return_ACPI_STATUS(AE_NULL_OBJECT); | 219 | info->full_pathname)); |
220 | status = AE_NULL_OBJECT; | ||
221 | goto cleanup; | ||
154 | } | 222 | } |
155 | 223 | ||
156 | /* Count the number of arguments being passed to the method */ | ||
157 | |||
158 | if (info->parameters) { | ||
159 | while (info->parameters[info->param_count]) { | ||
160 | if (info->param_count > ACPI_METHOD_MAX_ARG) { | ||
161 | return_ACPI_STATUS(AE_LIMIT); | ||
162 | } | ||
163 | info->param_count++; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | |||
168 | ACPI_DUMP_PATHNAME(info->resolved_node, "ACPI: Execute Method", | ||
169 | ACPI_LV_INFO, _COMPONENT); | ||
170 | |||
171 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 224 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
172 | "Method at AML address %p Length %X\n", | 225 | "**** Execute method [%s] at AML address %p length %X\n", |
226 | info->full_pathname, | ||
173 | info->obj_desc->method.aml_start + 1, | 227 | info->obj_desc->method.aml_start + 1, |
174 | info->obj_desc->method.aml_length - 1)); | 228 | info->obj_desc->method.aml_length - 1)); |
175 | 229 | ||
@@ -184,81 +238,61 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | |||
184 | acpi_ex_enter_interpreter(); | 238 | acpi_ex_enter_interpreter(); |
185 | status = acpi_ps_execute_method(info); | 239 | status = acpi_ps_execute_method(info); |
186 | acpi_ex_exit_interpreter(); | 240 | acpi_ex_exit_interpreter(); |
187 | } else { | 241 | break; |
242 | |||
243 | default: | ||
188 | /* | 244 | /* |
189 | * 2) Object is not a method, return its current value | 245 | * 3) All other non-method objects -- get the current object value |
190 | * | ||
191 | * Disallow certain object types. For these, "evaluation" is undefined. | ||
192 | */ | 246 | */ |
193 | switch (info->resolved_node->type) { | ||
194 | case ACPI_TYPE_DEVICE: | ||
195 | case ACPI_TYPE_EVENT: | ||
196 | case ACPI_TYPE_MUTEX: | ||
197 | case ACPI_TYPE_REGION: | ||
198 | case ACPI_TYPE_THERMAL: | ||
199 | case ACPI_TYPE_LOCAL_SCOPE: | ||
200 | |||
201 | ACPI_ERROR((AE_INFO, | ||
202 | "[%4.4s] Evaluation of object type [%s] is not supported", | ||
203 | info->resolved_node->name.ascii, | ||
204 | acpi_ut_get_type_name(info->resolved_node-> | ||
205 | type))); | ||
206 | |||
207 | return_ACPI_STATUS(AE_TYPE); | ||
208 | |||
209 | default: | ||
210 | break; | ||
211 | } | ||
212 | 247 | ||
213 | /* | 248 | /* |
214 | * Objects require additional resolution steps (e.g., the Node may be | 249 | * Some objects require additional resolution steps (e.g., the Node |
215 | * a field that must be read, etc.) -- we can't just grab the object | 250 | * may be a field that must be read, etc.) -- we can't just grab |
216 | * out of the node. | 251 | * the object out of the node. |
217 | * | 252 | * |
218 | * Use resolve_node_to_value() to get the associated value. | 253 | * Use resolve_node_to_value() to get the associated value. |
219 | * | 254 | * |
220 | * NOTE: we can get away with passing in NULL for a walk state because | 255 | * NOTE: we can get away with passing in NULL for a walk state because |
221 | * resolved_node is guaranteed to not be a reference to either a method | 256 | * the Node is guaranteed to not be a reference to either a method |
222 | * local or a method argument (because this interface is never called | 257 | * local or a method argument (because this interface is never called |
223 | * from a running method.) | 258 | * from a running method.) |
224 | * | 259 | * |
225 | * Even though we do not directly invoke the interpreter for object | 260 | * Even though we do not directly invoke the interpreter for object |
226 | * resolution, we must lock it because we could access an opregion. | 261 | * resolution, we must lock it because we could access an op_region. |
227 | * The opregion access code assumes that the interpreter is locked. | 262 | * The op_region access code assumes that the interpreter is locked. |
228 | */ | 263 | */ |
229 | acpi_ex_enter_interpreter(); | 264 | acpi_ex_enter_interpreter(); |
230 | 265 | ||
231 | /* Function has a strange interface */ | 266 | /* TBD: resolve_node_to_value has a strange interface, fix */ |
267 | |||
268 | info->return_object = | ||
269 | ACPI_CAST_PTR(union acpi_operand_object, info->node); | ||
232 | 270 | ||
233 | status = | 271 | status = |
234 | acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); | 272 | acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR |
273 | (struct acpi_namespace_node, | ||
274 | &info->return_object), NULL); | ||
235 | acpi_ex_exit_interpreter(); | 275 | acpi_ex_exit_interpreter(); |
236 | 276 | ||
237 | /* | 277 | if (ACPI_FAILURE(status)) { |
238 | * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed | 278 | goto cleanup; |
239 | * in resolved_node. | ||
240 | */ | ||
241 | if (ACPI_SUCCESS(status)) { | ||
242 | status = AE_CTRL_RETURN_VALUE; | ||
243 | info->return_object = | ||
244 | ACPI_CAST_PTR(union acpi_operand_object, | ||
245 | info->resolved_node); | ||
246 | |||
247 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, | ||
248 | "Returning object %p [%s]\n", | ||
249 | info->return_object, | ||
250 | acpi_ut_get_object_type_name(info-> | ||
251 | return_object))); | ||
252 | } | 279 | } |
280 | |||
281 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Returned object %p [%s]\n", | ||
282 | info->return_object, | ||
283 | acpi_ut_get_object_type_name(info-> | ||
284 | return_object))); | ||
285 | |||
286 | status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */ | ||
287 | break; | ||
253 | } | 288 | } |
254 | 289 | ||
255 | /* | 290 | /* |
256 | * Check input argument count against the ASL-defined count for a method. | 291 | * For predefined names, check the return value against the ACPI |
257 | * Also check predefined names: argument count and return value against | 292 | * specification. Some incorrect return value types are repaired. |
258 | * the ACPI specification. Some incorrect return value types are repaired. | ||
259 | */ | 293 | */ |
260 | (void)acpi_ns_check_predefined_names(node, info->param_count, | 294 | (void)acpi_ns_check_return_value(info->node, info, info->param_count, |
261 | status, &info->return_object); | 295 | status, &info->return_object); |
262 | 296 | ||
263 | /* Check if there is a return value that must be dealt with */ | 297 | /* Check if there is a return value that must be dealt with */ |
264 | 298 | ||
@@ -278,12 +312,15 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | |||
278 | 312 | ||
279 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, | 313 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
280 | "*** Completed evaluation of object %s ***\n", | 314 | "*** Completed evaluation of object %s ***\n", |
281 | info->pathname)); | 315 | info->relative_pathname)); |
282 | 316 | ||
317 | cleanup: | ||
283 | /* | 318 | /* |
284 | * Namespace was unlocked by the handling acpi_ns* function, so we | 319 | * Namespace was unlocked by the handling acpi_ns* function, so we |
285 | * just return | 320 | * just free the pathname and return |
286 | */ | 321 | */ |
322 | ACPI_FREE(info->full_pathname); | ||
323 | info->full_pathname = NULL; | ||
287 | return_ACPI_STATUS(status); | 324 | return_ACPI_STATUS(status); |
288 | } | 325 | } |
289 | 326 | ||