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