1/* $NetBSD: aml_evalobj.c,v 1.1 2007/01/14 04:36:13 christos 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.1 2007/01/14 04:36:13 christos 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 66static union aml_object *aml_eval_fieldobject(struct aml_environ *env, 67 struct aml_name *name); 68 69static union aml_object * 70aml_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 134union aml_object * 135aml_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 } 176out: 177 return (ret); 178} 179 180/* 181 * Eval named object. 182 */ 183union aml_object * 184aml_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; 207reevaluate: 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 } 305out: 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 317int 318aml_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 351int 352aml_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 363struct aml_name * 364aml_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 384union aml_object * 385aml_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 430union aml_object * 431aml_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