Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / usr.sbin / acpitools / aml / aml_evalobj.c
blob6578fd845ab5e88fdc945bb6e793890ce285fc2a
1 /* $NetBSD: aml_evalobj.c,v 1.1 2007/01/14 04:36:13 christos Exp $ */
3 /*-
4 * Copyright (c) 1999 Takanori Watanabe
5 * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
6 * All rights reserved.
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.
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.
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 $
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: aml_evalobj.c,v 1.1 2007/01/14 04:36:13 christos Exp $");
35 #include <sys/param.h>
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>
49 #ifndef _KERNEL
50 #include <sys/param.h>
51 #include <sys/stat.h>
52 #include <sys/mman.h>
54 #include <assert.h>
55 #include <err.h>
56 #include <fcntl.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
61 #include "debug.h"
62 #else /* _KERNEL */
63 #include <sys/systm.h>
64 #endif /* !_KERNEL */
66 static union aml_object *aml_eval_fieldobject(struct aml_environ *env,
67 struct aml_name *name);
69 static union aml_object *
70 aml_eval_fieldobject(struct aml_environ *env, struct aml_name *name)
72 int num;
73 struct aml_name *oname,*wname;
74 struct aml_field *field;
75 struct aml_opregion *or;
76 union aml_object tobj;
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);
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;
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);
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);
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);
130 env->curname = oname;
131 return (&env->tempobject);
134 union aml_object *
135 aml_eval_objref(struct aml_environ *env, union aml_object *obj)
137 int offset;
138 union aml_object num1;
139 union aml_object *ref, *ret;
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;
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;
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;
165 env->tempobject = num1;
166 ret = &env->tempobject;
167 break;
168 default:
169 break;
172 if (obj->objref.alias == 1) {
173 ret = aml_eval_name(env, obj->objref.nameref);
174 goto out;
176 out:
177 return (ret);
181 * Eval named object.
183 union aml_object *
184 aml_eval_name(struct aml_environ *env, struct aml_name *aname)
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;
194 ret = NULL;
195 if (aname == NULL || aname->property == NULL) {
196 return (NULL);
198 if (env->stat == aml_stat_panic) {
199 return (NULL);
201 copy = memman_alloc(aml_memman, memid_aml_environ);
202 if (copy == NULL) {
203 return (NULL);
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;
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;
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(", ");
255 AML_DEBUGPRINT(")\n");
256 aml_local_stack_push(stack);
257 if (env->stat == aml_stat_step) {
258 AML_DEBUGGER(env, copy);
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;
269 if (aml_debug) {
270 aml_showobject(obj);
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;
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;
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;
305 out:
306 memman_free(aml_memman, memid_aml_environ, copy);
307 return (ret);
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.
318 aml_eval_name_simple(struct aml_name *name, va_list ap)
320 struct aml_environ *env;
321 union aml_object *ret;
323 if (name == NULL || name->property == NULL) {
324 return (1);
327 env = memman_alloc(aml_memman, memid_aml_environ);
328 if (env == NULL) {
329 return (1);
331 bzero(env, sizeof(struct aml_environ));
333 aml_local_stack_push(aml_local_stack_create());
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);
345 aml_local_stack_delete(aml_local_stack_pop());
347 memman_free(aml_memman, memid_aml_environ, env);
348 return (0);
352 aml_objtonum(struct aml_environ *env, union aml_object *obj)
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);
363 struct aml_name *
364 aml_execute_method(struct aml_environ *env)
366 struct aml_name *name;
367 struct aml_name_group *newgrp;
369 newgrp = aml_new_name_group((void *)AML_NAME_GROUP_IN_METHOD);
371 AML_DEBUGPRINT("[");
372 aml_print_curname(env->curname);
373 AML_DEBUGPRINT(" START]\n");
375 name = aml_parse_objectlist(env, 0);
376 AML_DEBUGPRINT("[");
377 aml_print_curname(env->curname);
378 AML_DEBUGPRINT(" END]\n");
380 aml_delete_name_group(newgrp);
381 return (name);
384 union aml_object *
385 aml_invoke_method(struct aml_name *name, int argc, union aml_object *argv)
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;
394 retval = NULL;
395 env = memman_alloc(aml_memman, memid_aml_environ);
396 if (env == NULL) {
397 return (NULL);
399 bzero(env, sizeof(struct aml_environ));
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]);
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);
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;
426 memman_free(aml_memman, memid_aml_environ, env);
427 return (retval);
430 union aml_object *
431 aml_invoke_method_by_name(char *method, int argc, union aml_object *argv)
433 struct aml_name *name;
435 name = aml_find_from_namespace(aml_get_rootname(), method);
436 if (name == NULL) {
437 return (NULL);
440 return (aml_invoke_method(name, argc, argv));