xref: /netbsd/usr.sbin/acpitools/aml/aml_evalobj.c (revision 6550d01e)
1 /*	$NetBSD: aml_evalobj.c,v 1.2 2007/01/14 05:33:18 dogcow Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999 Takanori Watanabe
5  * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *	Id: aml_evalobj.c,v 1.27 2000/08/16 18:14:53 iwasaki Exp
30  *	$FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_evalobj.c,v 1.4 2000/11/09 06:24:45 iwasaki Exp $
31  */
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: aml_evalobj.c,v 1.2 2007/01/14 05:33:18 dogcow Exp $");
34 
35 #include <sys/param.h>
36 
37 #include <acpi_common.h>
38 #include <aml/aml_amlmem.h>
39 #include <aml/aml_common.h>
40 #include <aml/aml_env.h>
41 #include <aml/aml_evalobj.h>
42 #include <aml/aml_name.h>
43 #include <aml/aml_obj.h>
44 #include <aml/aml_parse.h>
45 #include <aml/aml_region.h>
46 #include <aml/aml_status.h>
47 #include <aml/aml_store.h>
48 
49 #ifndef _KERNEL
50 #include <sys/param.h>
51 #include <sys/stat.h>
52 #include <sys/mman.h>
53 
54 #include <assert.h>
55 #include <err.h>
56 #include <fcntl.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 
61 #include "debug.h"
62 #else /* _KERNEL */
63 #include <sys/systm.h>
64 #endif /* !_KERNEL */
65 
66 static union aml_object	*aml_eval_fieldobject(struct aml_environ *env,
67 					      struct aml_name *name);
68 
69 static union aml_object *
70 aml_eval_fieldobject(struct aml_environ *env, struct aml_name *name)
71 {
72 	int	num;
73 	struct	aml_name *oname,*wname;
74 	struct	aml_field *field;
75 	struct	aml_opregion *or;
76 	union	aml_object tobj;
77 
78 	num = 0;
79 	/* CANNOT OCCUR! */
80 	if (name == NULL || name->property == NULL ||
81 	    name->property->type != aml_t_field) {
82 		printf("????\n");
83 		env->stat = aml_stat_panic;
84 		return (NULL);
85 	}
86 	field = &name->property->field;
87 	oname = env->curname;
88 	if (field->bitlen > 32) {
89 		env->tempobject.type = aml_t_regfield;
90 	} else {
91 		env->tempobject.type = aml_t_num;
92 	}
93 	env->curname = name;
94 	if (field->f.ftype == f_t_field) {
95 		wname = aml_search_name(env, field->f.fld.regname);
96 		if (wname == NULL || wname->property == NULL ||
97 		    wname->property->type != aml_t_opregion) {
98 			AML_DEBUGPRINT("Inappropreate Type\n");
99 			env->stat = aml_stat_panic;
100 			env->curname = oname;
101 			return (NULL);
102 		}
103 		or = &wname->property->opregion;
104 		if (env->tempobject.type == aml_t_regfield) {
105 			env->tempobject.regfield.space = or->space;
106 			env->tempobject.regfield.flags = field->flags;
107 			env->tempobject.regfield.offset = or->offset;
108 			env->tempobject.regfield.bitoffset = field->bitoffset;
109 			env->tempobject.regfield.bitlen = field->bitlen;
110 		} else {
111 			env->tempobject.type = aml_t_num;
112 			env->tempobject.num.number = aml_region_read(env,
113 			    or->space, field->flags, or->offset,
114 			    field->bitoffset, field->bitlen);
115 			AML_DEBUGPRINT("[read(%d, 0x%x)->0x%x]",
116 			    or->space, or->offset + field->bitoffset / 8,
117 			    env->tempobject.num.number);
118 		}
119 	} else if (field->f.ftype == f_t_index) {
120 		wname = aml_search_name(env, field->f.ifld.indexname);
121 		tobj.type = aml_t_num;
122 		tobj.num.number = field->bitoffset / 8;/* AccessType Boundary */
123 		aml_store_to_name(env, &tobj, wname);
124 		wname = aml_search_name(env, field->f.ifld.dataname);
125 		num = aml_objtonum(env, aml_eval_name(env, wname));
126 		env->tempobject.type = aml_t_num;
127 		env->tempobject.num.number = (num >> (field->bitoffset & 7)) &
128 		    ((1 << field->bitlen) - 1);
129 	}
130 	env->curname = oname;
131 	return (&env->tempobject);
132 }
133 
134 union aml_object *
135 aml_eval_objref(struct aml_environ *env, union aml_object *obj)
136 {
137 	int	offset;
138 	union	aml_object num1;
139 	union	aml_object *ref, *ret;
140 
141 	ret = obj;
142 	if (obj->objref.deref == 1) {
143 		num1.type = aml_t_num;
144 		offset = obj->objref.offset;
145 		ref = obj->objref.ref;
146 		if (ref == NULL) {
147 			goto out;
148 		}
149 		switch (ref->type) {
150 		case aml_t_package:
151 			if (ref->package.elements > offset) {
152 				ret = ref->package.objects[offset];
153 			} else {
154 				num1.num.number = 0;
155 				env->tempobject = num1;
156 				ret = &env->tempobject;
157 			}
158 			break;
159 		case aml_t_buffer:
160 			if (ref->buffer.size > offset) {
161 				num1.num.number = ref->buffer.data[offset] & 0xff;
162 			} else {
163 				num1.num.number = 0;
164 			}
165 			env->tempobject = num1;
166 			ret = &env->tempobject;
167 			break;
168 		default:
169 			break;
170 		}
171 	}
172 	if (obj->objref.alias == 1) {
173 		ret = aml_eval_name(env, obj->objref.nameref);
174 		goto out;
175 	}
176 out:
177 	return (ret);
178 }
179 
180 /*
181  * Eval named object.
182  */
183 union aml_object *
184 aml_eval_name(struct aml_environ *env, struct aml_name *aname)
185 {
186 	int	argnum, i;
187 	int	num;
188 	struct	aml_name *tmp;
189 	struct	aml_environ *copy;
190 	struct	aml_local_stack *stack;
191 	union	aml_object *obj, *ret;
192 	union	aml_object *src;
193 
194 	ret = NULL;
195 	if (aname == NULL || aname->property == NULL) {
196 		return (NULL);
197 	}
198 	if (env->stat == aml_stat_panic) {
199 		return (NULL);
200 	}
201 	copy = memman_alloc(aml_memman, memid_aml_environ);
202 	if (copy == NULL) {
203 		return (NULL);
204 	}
205 	ret = aname->property;
206 	i = 0;
207 reevaluate:
208 	if (i > 10) {
209 		env->stat = aml_stat_panic;
210 		printf("TOO MANY LOOP\n");
211 		ret = NULL;
212 		goto out;
213 	}
214 	switch (aname->property->type) {
215 	case aml_t_namestr:
216 		tmp = aname;
217 		aname = aml_search_name(env, aname->property->nstr.dp);
218 		if (aname == NULL) {
219 			aname = tmp;
220 		}
221 		i++;
222 		goto reevaluate;
223 	case aml_t_objref:
224 		ret = aml_eval_objref(env, aname->property);
225 		goto out;
226 	case aml_t_num:
227 	case aml_t_string:
228 	case aml_t_buffer:
229 	case aml_t_package:
230 	case aml_t_debug:
231 		ret = aname->property;
232 		goto out;
233 	case aml_t_field:
234 		aml_free_objectcontent(&env->tempobject);
235 		ret = aml_eval_fieldobject(env, aname);
236 		goto out;
237 	case aml_t_method:
238 		aml_free_objectcontent(&env->tempobject);
239 		argnum = aname->property->meth.argnum & 7;
240 		*copy = *env;
241 		copy->curname = aname;
242 		copy->dp = aname->property->meth.from;
243 		copy->end = aname->property->meth.to;
244 		copy->stat = aml_stat_none;
245 		stack = aml_local_stack_create();
246 		AML_DEBUGPRINT("(");
247 		for (i = 0; i < argnum; i++) {
248 			aml_local_stack_getArgX(stack, i)->property =
249 			    aml_copy_object(env,
250 				aml_eval_name(env,
251 				    aml_parse_termobj(env, 0)));
252 			if (i < argnum - 1)
253 				AML_DEBUGPRINT(", ");
254 		}
255 		AML_DEBUGPRINT(")\n");
256 		aml_local_stack_push(stack);
257 		if (env->stat == aml_stat_step) {
258 			AML_DEBUGGER(env, copy);
259 		}
260 		tmp = aml_execute_method(copy);
261 		obj = aml_eval_name(env, tmp);
262 		if (copy->stat == aml_stat_panic) {
263 			AML_DEBUGPRINT("PANIC OCCURED IN METHOD");
264 			env->stat = aml_stat_panic;
265 			ret = NULL;
266 			aml_local_stack_delete(aml_local_stack_pop());
267 			goto out;
268 		}
269 		if (aml_debug) {
270 			aml_showobject(obj);
271 		}
272 
273 		if (tmp)
274 			tmp->property = NULL;
275 		aml_local_stack_delete(aml_local_stack_pop());
276 		if (obj) {
277 			aml_create_local_object()->property = obj;
278 			ret = obj;
279 		} else {
280 			env->tempobject.type = aml_t_num;
281 			env->tempobject.num.number = 0;
282 		}
283 
284 		goto out;
285 	case aml_t_bufferfield:
286 		aml_free_objectcontent(&env->tempobject);
287 		if (aname->property->bfld.bitlen > 32) {
288 			ret = aname->property;
289 		} else {
290 			src = aname->property;
291 			num = aml_bufferfield_read(src->bfld.origin,
292 			    src->bfld.bitoffset, src->bfld.bitlen);
293 			env->tempobject.type = aml_t_num;
294 			env->tempobject.num.number = num;
295 			ret = &env->tempobject;
296 		}
297 		goto out;
298 	default:
299 		AML_DEBUGPRINT("I eval the object that I should not eval, %s%d",
300 		    aname->name, aname->property->type);
301 		AML_SYSABORT();
302 		ret = NULL;
303 		goto out;
304 	}
305 out:
306 	memman_free(aml_memman, memid_aml_environ, copy);
307 	return (ret);
308 }
309 
310 /*
311  * Eval named object but env variable is not required and return
312  * status of evaluation (success is zero).  This function is assumed
313  * to be called by aml_apply_foreach_found_objects().
314  * Note that no arguments are passed if object is a method.
315  */
316 
317 int
318 aml_eval_name_simple(struct aml_name *name, va_list ap)
319 {
320 	struct	aml_environ *env;
321 	union	aml_object *ret;
322 
323 	if (name == NULL || name->property == NULL) {
324 		return (1);
325 	}
326 
327 	env = memman_alloc(aml_memman, memid_aml_environ);
328 	if (env == NULL) {
329 		return (1);
330 	}
331 	bzero(env, sizeof(struct aml_environ));
332 
333 	aml_local_stack_push(aml_local_stack_create());
334 
335 	AML_DEBUGPRINT("Evaluating ");
336 	aml_print_curname(name);
337 	ret = aml_eval_name(env, name);
338 	if (name->property->type != aml_t_method) {
339 		AML_DEBUGPRINT("\n");
340 		if (aml_debug) {
341 			aml_showobject(ret);
342 		}
343 	}
344 
345 	aml_local_stack_delete(aml_local_stack_pop());
346 
347 	memman_free(aml_memman, memid_aml_environ, env);
348 	return (0);
349 }
350 
351 int
352 aml_objtonum(struct aml_environ *env, union aml_object *obj)
353 {
354 
355 	if (obj != NULL && obj->type == aml_t_num) {
356 		return (obj->num.number);
357 	} else {
358 		env->stat = aml_stat_panic;
359 		return (-1);
360 	}
361 }
362 
363 struct aml_name *
364 aml_execute_method(struct aml_environ *env)
365 {
366 	struct	aml_name *name;
367 	struct	aml_name_group *newgrp;
368 
369 	newgrp = aml_new_name_group((void *)AML_NAME_GROUP_IN_METHOD);
370 
371 	AML_DEBUGPRINT("[");
372 	aml_print_curname(env->curname);
373 	AML_DEBUGPRINT(" START]\n");
374 
375 	name = aml_parse_objectlist(env, 0);
376 	AML_DEBUGPRINT("[");
377 	aml_print_curname(env->curname);
378 	AML_DEBUGPRINT(" END]\n");
379 
380 	aml_delete_name_group(newgrp);
381 	return (name);
382 }
383 
384 union aml_object *
385 aml_invoke_method(struct aml_name *name, int argc, union aml_object *argv)
386 {
387 	int	i;
388 	struct	aml_name *tmp;
389 	struct	aml_environ *env;
390 	struct	aml_local_stack *stack;
391 	union	aml_object *retval;
392 	union	aml_object *obj;
393 
394 	retval = NULL;
395 	env = memman_alloc(aml_memman, memid_aml_environ);
396 	if (env == NULL) {
397 		return (NULL);
398 	}
399 	bzero(env, sizeof(struct aml_environ));
400 
401 	if (name != NULL && name->property != NULL &&
402 	    name->property->type == aml_t_method) {
403 		env->curname = name;
404 		env->dp = name->property->meth.from;
405 		env->end = name->property->meth.to;
406 		AML_DEBUGGER(env, env);
407 		stack = aml_local_stack_create();
408 		for (i = 0; i < argc; i++) {
409 			aml_local_stack_getArgX(stack, i)->property =
410 			    aml_alloc_object(argv[i].type, &argv[i]);
411 		}
412 		aml_local_stack_push(stack);
413 		obj = aml_eval_name(env, tmp = aml_execute_method(env));
414 		if (aml_debug) {
415 			aml_showtree(name, 0);
416 		}
417 
418 		if (tmp)
419 			tmp->property = NULL;
420 		aml_local_stack_delete(aml_local_stack_pop());
421 		if (obj) {
422 			aml_create_local_object()->property = obj;
423 			retval = obj;
424 		}
425 	}
426 	memman_free(aml_memman, memid_aml_environ, env);
427 	return (retval);
428 }
429 
430 union aml_object *
431 aml_invoke_method_by_name(char *method, int argc, union aml_object *argv)
432 {
433 	struct	aml_name *name;
434 
435 	name = aml_find_from_namespace(aml_get_rootname(), method);
436 	if (name == NULL) {
437 		return (NULL);
438 	}
439 
440 	return (aml_invoke_method(name, argc, argv));
441 }
442