1 1.4 andvar /* $NetBSD: aml_evalobj.c,v 1.4 2024/07/31 20:15:33 andvar 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.4 andvar __RCSID("$NetBSD: aml_evalobj.c,v 1.4 2024/07/31 20:15:33 andvar 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.4 andvar AML_DEBUGPRINT("Inappropriate 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.3 msaitoh AML_DEBUGPRINT("PANIC OCCURRED 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.2 dogcow newgrp = aml_new_name_group((void *)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