1 /* $OpenBSD: dsdt.c,v 1.191 2011/06/15 08:11:51 pirofti Exp $ */ 2 /* 3 * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/kernel.h> 21 #include <sys/device.h> 22 #include <sys/malloc.h> 23 #include <sys/proc.h> 24 25 #include <machine/bus.h> 26 27 #ifdef DDB 28 #include <machine/db_machdep.h> 29 #include <ddb/db_command.h> 30 #endif 31 32 #include <dev/acpi/acpireg.h> 33 #include <dev/acpi/acpivar.h> 34 #include <dev/acpi/amltypes.h> 35 #include <dev/acpi/dsdt.h> 36 37 #ifdef SMALL_KERNEL 38 #undef ACPI_DEBUG 39 #endif 40 41 #define opsize(opcode) (((opcode) & 0xFF00) ? 2 : 1) 42 43 #define AML_FIELD_RESERVED 0x00 44 #define AML_FIELD_ATTRIB 0x01 45 46 #define AML_REVISION 0x01 47 #define AML_INTSTRLEN 16 48 #define AML_NAMESEG_LEN 4 49 50 struct acpi_q *acpi_maptable(struct acpi_softc *sc, paddr_t, 51 const char *, const char *, 52 const char *, int); 53 struct aml_scope *aml_load(struct acpi_softc *, struct aml_scope *, 54 struct aml_value *, struct aml_value *); 55 56 void aml_copyvalue(struct aml_value *, struct aml_value *); 57 58 void aml_setvalue(struct aml_scope *, struct aml_value *, 59 struct aml_value *, int64_t); 60 void aml_freevalue(struct aml_value *); 61 struct aml_value *aml_allocvalue(int, int64_t, const void *); 62 struct aml_value *_aml_setvalue(struct aml_value *, int, int64_t, 63 const void *); 64 65 u_int64_t aml_convradix(u_int64_t, int, int); 66 int64_t aml_evalexpr(int64_t, int64_t, int); 67 int aml_lsb(u_int64_t); 68 int aml_msb(u_int64_t); 69 70 int aml_tstbit(const u_int8_t *, int); 71 void aml_setbit(u_int8_t *, int, int); 72 73 void aml_addref(struct aml_value *, const char *); 74 void aml_delref(struct aml_value **, const char *); 75 76 void aml_bufcpy(void *, int, const void *, int, int); 77 78 int aml_pc(uint8_t *); 79 80 struct aml_value *aml_parseop(struct aml_scope *, struct aml_value *,int); 81 struct aml_value *aml_parsetarget(struct aml_scope *, struct aml_value *, 82 struct aml_value **); 83 struct aml_value *aml_parseterm(struct aml_scope *, struct aml_value *); 84 85 struct aml_value *aml_evaltarget(struct aml_scope *scope, 86 struct aml_value *res); 87 int aml_evalterm(struct aml_scope *scope, 88 struct aml_value *raw, struct aml_value *dst); 89 90 struct aml_opcode *aml_findopcode(int); 91 92 #define acpi_os_malloc(sz) _acpi_os_malloc(sz, __FUNCTION__, __LINE__) 93 #define acpi_os_free(ptr) _acpi_os_free(ptr, __FUNCTION__, __LINE__) 94 95 void *_acpi_os_malloc(size_t, const char *, int); 96 void _acpi_os_free(void *, const char *, int); 97 void acpi_stall(int); 98 99 struct aml_value *aml_callosi(struct aml_scope *, struct aml_value *); 100 101 const char *aml_getname(const char *); 102 int64_t aml_hextoint(const char *); 103 void aml_dump(int, u_int8_t *); 104 void _aml_die(const char *fn, int line, const char *fmt, ...); 105 #define aml_die(x...) _aml_die(__FUNCTION__, __LINE__, x) 106 107 void aml_notify_task(void *, int); 108 void acpi_poll_notify_task(void *, int); 109 110 /* 111 * @@@: Global variables 112 */ 113 int aml_intlen = 64; 114 struct aml_node aml_root; 115 struct aml_value *aml_global_lock; 116 117 /* Perfect Hash key */ 118 #define HASH_OFF 6904 119 #define HASH_SIZE 179 120 #define HASH_KEY(k) (((k) ^ HASH_OFF) % HASH_SIZE) 121 122 /* 123 * XXX this array should be sorted, and then aml_findopcode() should 124 * do a binary search 125 */ 126 struct aml_opcode **aml_ophash; 127 struct aml_opcode aml_table[] = { 128 /* Simple types */ 129 { AMLOP_ZERO, "Zero", "c", }, 130 { AMLOP_ONE, "One", "c", }, 131 { AMLOP_ONES, "Ones", "c", }, 132 { AMLOP_REVISION, "Revision", "R", }, 133 { AMLOP_BYTEPREFIX, ".Byte", "b", }, 134 { AMLOP_WORDPREFIX, ".Word", "w", }, 135 { AMLOP_DWORDPREFIX, ".DWord", "d", }, 136 { AMLOP_QWORDPREFIX, ".QWord", "q", }, 137 { AMLOP_STRINGPREFIX, ".String", "a", }, 138 { AMLOP_DEBUG, "DebugOp", "D", }, 139 { AMLOP_BUFFER, "Buffer", "piB", }, 140 { AMLOP_PACKAGE, "Package", "pbT", }, 141 { AMLOP_VARPACKAGE, "VarPackage", "piT", }, 142 143 /* Simple objects */ 144 { AMLOP_LOCAL0, "Local0", "L", }, 145 { AMLOP_LOCAL1, "Local1", "L", }, 146 { AMLOP_LOCAL2, "Local2", "L", }, 147 { AMLOP_LOCAL3, "Local3", "L", }, 148 { AMLOP_LOCAL4, "Local4", "L", }, 149 { AMLOP_LOCAL5, "Local5", "L", }, 150 { AMLOP_LOCAL6, "Local6", "L", }, 151 { AMLOP_LOCAL7, "Local7", "L", }, 152 { AMLOP_ARG0, "Arg0", "A", }, 153 { AMLOP_ARG1, "Arg1", "A", }, 154 { AMLOP_ARG2, "Arg2", "A", }, 155 { AMLOP_ARG3, "Arg3", "A", }, 156 { AMLOP_ARG4, "Arg4", "A", }, 157 { AMLOP_ARG5, "Arg5", "A", }, 158 { AMLOP_ARG6, "Arg6", "A", }, 159 160 /* Control flow */ 161 { AMLOP_IF, "If", "piI", }, 162 { AMLOP_ELSE, "Else", "pT" }, 163 { AMLOP_WHILE, "While", "piT", }, 164 { AMLOP_BREAK, "Break", "" }, 165 { AMLOP_CONTINUE, "Continue", "" }, 166 { AMLOP_RETURN, "Return", "t", }, 167 { AMLOP_FATAL, "Fatal", "bdi", }, 168 { AMLOP_NOP, "Nop", "", }, 169 { AMLOP_BREAKPOINT, "BreakPoint", "", }, 170 171 /* Arithmetic operations */ 172 { AMLOP_INCREMENT, "Increment", "S", }, 173 { AMLOP_DECREMENT, "Decrement", "S", }, 174 { AMLOP_ADD, "Add", "iir", }, 175 { AMLOP_SUBTRACT, "Subtract", "iir", }, 176 { AMLOP_MULTIPLY, "Multiply", "iir", }, 177 { AMLOP_DIVIDE, "Divide", "iirr", }, 178 { AMLOP_SHL, "ShiftLeft", "iir", }, 179 { AMLOP_SHR, "ShiftRight", "iir", }, 180 { AMLOP_AND, "And", "iir", }, 181 { AMLOP_NAND, "Nand", "iir", }, 182 { AMLOP_OR, "Or", "iir", }, 183 { AMLOP_NOR, "Nor", "iir", }, 184 { AMLOP_XOR, "Xor", "iir", }, 185 { AMLOP_NOT, "Not", "ir", }, 186 { AMLOP_MOD, "Mod", "iir", }, 187 { AMLOP_FINDSETLEFTBIT, "FindSetLeftBit", "ir", }, 188 { AMLOP_FINDSETRIGHTBIT,"FindSetRightBit", "ir",}, 189 190 /* Logical test operations */ 191 { AMLOP_LAND, "LAnd", "ii", }, 192 { AMLOP_LOR, "LOr", "ii", }, 193 { AMLOP_LNOT, "LNot", "i", }, 194 { AMLOP_LNOTEQUAL, "LNotEqual", "tt", }, 195 { AMLOP_LLESSEQUAL, "LLessEqual", "tt", }, 196 { AMLOP_LGREATEREQUAL, "LGreaterEqual", "tt", }, 197 { AMLOP_LEQUAL, "LEqual", "tt", }, 198 { AMLOP_LGREATER, "LGreater", "tt", }, 199 { AMLOP_LLESS, "LLess", "tt", }, 200 201 /* Named objects */ 202 { AMLOP_NAMECHAR, ".NameRef", "n", }, 203 { AMLOP_ALIAS, "Alias", "nN", }, 204 { AMLOP_NAME, "Name", "Nt", }, 205 { AMLOP_EVENT, "Event", "N", }, 206 { AMLOP_MUTEX, "Mutex", "Nb", }, 207 { AMLOP_DATAREGION, "DataRegion", "Nttt", }, 208 { AMLOP_OPREGION, "OpRegion", "Nbii", }, 209 { AMLOP_SCOPE, "Scope", "pnT", }, 210 { AMLOP_DEVICE, "Device", "pNT", }, 211 { AMLOP_POWERRSRC, "Power Resource", "pNbwT",}, 212 { AMLOP_THERMALZONE, "ThermalZone", "pNT", }, 213 { AMLOP_PROCESSOR, "Processor", "pNbdbT", }, 214 { AMLOP_METHOD, "Method", "pNbM", }, 215 216 /* Field operations */ 217 { AMLOP_FIELD, "Field", "pnbF", }, 218 { AMLOP_INDEXFIELD, "IndexField", "pnnbF",}, 219 { AMLOP_BANKFIELD, "BankField", "pnnibF",}, 220 { AMLOP_CREATEFIELD, "CreateField", "tiiN", }, 221 { AMLOP_CREATEQWORDFIELD, "CreateQWordField","tiN",}, 222 { AMLOP_CREATEDWORDFIELD, "CreateDWordField","tiN",}, 223 { AMLOP_CREATEWORDFIELD, "CreateWordField", "tiN",}, 224 { AMLOP_CREATEBYTEFIELD, "CreateByteField", "tiN",}, 225 { AMLOP_CREATEBITFIELD, "CreateBitField", "tiN", }, 226 227 /* Conversion operations */ 228 { AMLOP_TOINTEGER, "ToInteger", "tr", }, 229 { AMLOP_TOBUFFER, "ToBuffer", "tr", }, 230 { AMLOP_TODECSTRING, "ToDecString", "ir", }, 231 { AMLOP_TOHEXSTRING, "ToHexString", "ir", }, 232 { AMLOP_TOSTRING, "ToString", "tir", }, 233 { AMLOP_MID, "Mid", "tiir", }, 234 { AMLOP_FROMBCD, "FromBCD", "ir", }, 235 { AMLOP_TOBCD, "ToBCD", "ir", }, 236 237 /* Mutex/Signal operations */ 238 { AMLOP_ACQUIRE, "Acquire", "Sw", }, 239 { AMLOP_RELEASE, "Release", "S", }, 240 { AMLOP_SIGNAL, "Signal", "S", }, 241 { AMLOP_WAIT, "Wait", "Si", }, 242 { AMLOP_RESET, "Reset", "S", }, 243 244 { AMLOP_INDEX, "Index", "tir", }, 245 { AMLOP_DEREFOF, "DerefOf", "t", }, 246 { AMLOP_REFOF, "RefOf", "S", }, 247 { AMLOP_CONDREFOF, "CondRef", "Sr", }, 248 249 { AMLOP_LOADTABLE, "LoadTable", "tttttt" }, 250 { AMLOP_STALL, "Stall", "i", }, 251 { AMLOP_SLEEP, "Sleep", "i", }, 252 { AMLOP_LOAD, "Load", "nS", }, 253 { AMLOP_UNLOAD, "Unload", "t" }, 254 { AMLOP_STORE, "Store", "tS", }, 255 { AMLOP_CONCAT, "Concat", "ttr", }, 256 { AMLOP_CONCATRES, "ConcatRes", "ttt" }, 257 { AMLOP_NOTIFY, "Notify", "Si", }, 258 { AMLOP_SIZEOF, "Sizeof", "S", }, 259 { AMLOP_MATCH, "Match", "tbibii", }, 260 { AMLOP_OBJECTTYPE, "ObjectType", "S", }, 261 { AMLOP_COPYOBJECT, "CopyObject", "tS", }, 262 }; 263 264 int aml_pc(uint8_t *src) 265 { 266 return src - aml_root.start; 267 } 268 269 struct aml_scope *aml_lastscope; 270 271 void 272 _aml_die(const char *fn, int line, const char *fmt, ...) 273 { 274 #ifndef SMALL_KERNEL 275 struct aml_scope *root; 276 struct aml_value *sp; 277 int idx; 278 #endif /* SMALL_KERNEL */ 279 va_list ap; 280 281 va_start(ap, fmt); 282 vprintf(fmt, ap); 283 printf("\n"); 284 va_end(ap); 285 286 #ifndef SMALL_KERNEL 287 for (root = aml_lastscope; root && root->pos; root = root->parent) { 288 printf("%.4x Called: %s\n", aml_pc(root->pos), 289 aml_nodename(root->node)); 290 for (idx = 0; idx < AML_MAX_ARG; idx++) { 291 sp = aml_getstack(root, AMLOP_ARG0+idx); 292 if (sp && sp->type) { 293 printf(" arg%d: ", idx); 294 aml_showvalue(sp, 0); 295 } 296 } 297 for (idx = 0; idx < AML_MAX_LOCAL; idx++) { 298 sp = aml_getstack(root, AMLOP_LOCAL0+idx); 299 if (sp && sp->type) { 300 printf(" local%d: ", idx); 301 aml_showvalue(sp, 0); 302 } 303 } 304 } 305 #endif /* SMALL_KERNEL */ 306 307 /* XXX: don't panic */ 308 panic("aml_die %s:%d", fn, line); 309 } 310 311 void 312 aml_hashopcodes(void) 313 { 314 int i; 315 316 /* Dynamically allocate hash table */ 317 aml_ophash = (struct aml_opcode **)acpi_os_malloc(HASH_SIZE * 318 sizeof(struct aml_opcode *)); 319 for (i = 0; i < sizeof(aml_table) / sizeof(aml_table[0]); i++) 320 aml_ophash[HASH_KEY(aml_table[i].opcode)] = &aml_table[i]; 321 } 322 323 struct aml_opcode * 324 aml_findopcode(int opcode) 325 { 326 struct aml_opcode *hop; 327 328 hop = aml_ophash[HASH_KEY(opcode)]; 329 if (hop && hop->opcode == opcode) 330 return hop; 331 return NULL; 332 } 333 334 #if defined(DDB) || !defined(SMALL_KERNEL) 335 const char * 336 aml_mnem(int opcode, uint8_t *pos) 337 { 338 struct aml_opcode *tab; 339 static char mnemstr[32]; 340 341 if ((tab = aml_findopcode(opcode)) != NULL) { 342 strlcpy(mnemstr, tab->mnem, sizeof(mnemstr)); 343 if (pos != NULL) { 344 switch (opcode) { 345 case AMLOP_STRINGPREFIX: 346 snprintf(mnemstr, sizeof(mnemstr), "\"%s\"", pos); 347 break; 348 case AMLOP_BYTEPREFIX: 349 snprintf(mnemstr, sizeof(mnemstr), "0x%.2x", 350 *(uint8_t *)pos); 351 break; 352 case AMLOP_WORDPREFIX: 353 snprintf(mnemstr, sizeof(mnemstr), "0x%.4x", 354 *(uint16_t *)pos); 355 break; 356 case AMLOP_DWORDPREFIX: 357 snprintf(mnemstr, sizeof(mnemstr), "0x%.4x", 358 *(uint16_t *)pos); 359 break; 360 case AMLOP_NAMECHAR: 361 strlcpy(mnemstr, aml_getname(pos), sizeof(mnemstr)); 362 break; 363 } 364 } 365 return mnemstr; 366 } 367 return ("xxx"); 368 } 369 #endif /* defined(DDB) || !defined(SMALL_KERNEL) */ 370 371 struct aml_notify_data { 372 struct aml_node *node; 373 char pnpid[20]; 374 void *cbarg; 375 int (*cbproc)(struct aml_node *, int, void *); 376 int poll; 377 378 SLIST_ENTRY(aml_notify_data) link; 379 }; 380 381 SLIST_HEAD(aml_notify_head, aml_notify_data); 382 struct aml_notify_head aml_notify_list = 383 LIST_HEAD_INITIALIZER(&aml_notify_list); 384 385 /* 386 * @@@: Memory management functions 387 */ 388 389 long acpi_nalloc; 390 391 struct acpi_memblock { 392 size_t size; 393 #ifdef ACPI_MEMDEBUG 394 const char *fn; 395 int line; 396 int sig; 397 LIST_ENTRY(acpi_memblock) link; 398 #endif 399 }; 400 401 #ifdef ACPI_MEMDEBUG 402 LIST_HEAD(, acpi_memblock) acpi_memhead; 403 int acpi_memsig; 404 405 int 406 acpi_walkmem(int sig, const char *lbl) 407 { 408 struct acpi_memblock *sptr; 409 410 printf("--- walkmem:%s %x --- %x bytes alloced\n", lbl, sig, acpi_nalloc); 411 LIST_FOREACH(sptr, &acpi_memhead, link) { 412 if (sptr->sig < sig) 413 break; 414 printf("%.4x Alloc %.8lx bytes @ %s:%d\n", 415 sptr->sig, sptr->size, sptr->fn, sptr->line); 416 } 417 return acpi_memsig; 418 } 419 #endif /* ACPI_MEMDEBUG */ 420 421 void * 422 _acpi_os_malloc(size_t size, const char *fn, int line) 423 { 424 struct acpi_memblock *sptr; 425 426 sptr = malloc(size+sizeof(*sptr), M_ACPI, M_WAITOK | M_ZERO); 427 dnprintf(99, "alloc: %x %s:%d\n", sptr, fn, line); 428 acpi_nalloc += size; 429 sptr->size = size; 430 #ifdef ACPI_MEMDEBUG 431 sptr->line = line; 432 sptr->fn = fn; 433 sptr->sig = ++acpi_memsig; 434 435 LIST_INSERT_HEAD(&acpi_memhead, sptr, link); 436 #endif 437 438 return &sptr[1]; 439 } 440 441 void 442 _acpi_os_free(void *ptr, const char *fn, int line) 443 { 444 struct acpi_memblock *sptr; 445 446 if (ptr != NULL) { 447 sptr = &(((struct acpi_memblock *)ptr)[-1]); 448 acpi_nalloc -= sptr->size; 449 450 #ifdef ACPI_MEMDEBUG 451 LIST_REMOVE(sptr, link); 452 #endif 453 454 dnprintf(99, "free: %x %s:%d\n", sptr, fn, line); 455 free(sptr, M_ACPI); 456 } 457 } 458 459 void 460 acpi_sleep(int ms, char *reason) 461 { 462 static int acpinowait; 463 int to = ms * hz / 1000; 464 465 if (cold) 466 delay(ms * 1000); 467 else { 468 if (to <= 0) 469 to = 1; 470 tsleep(&acpinowait, PWAIT, reason, to); 471 } 472 } 473 474 void 475 acpi_stall(int us) 476 { 477 delay(us); 478 } 479 480 /* 481 * @@@: Misc utility functions 482 */ 483 484 #ifdef ACPI_DEBUG 485 void 486 aml_dump(int len, u_int8_t *buf) 487 { 488 int idx; 489 490 dnprintf(50, "{ "); 491 for (idx = 0; idx < len; idx++) { 492 dnprintf(50, "%s0x%.2x", idx ? ", " : "", buf[idx]); 493 } 494 dnprintf(50, " }\n"); 495 } 496 #endif 497 498 /* Bit mangling code */ 499 int 500 aml_tstbit(const u_int8_t *pb, int bit) 501 { 502 pb += aml_bytepos(bit); 503 504 return (*pb & aml_bitmask(bit)); 505 } 506 507 void 508 aml_setbit(u_int8_t *pb, int bit, int val) 509 { 510 pb += aml_bytepos(bit); 511 512 if (val) 513 *pb |= aml_bitmask(bit); 514 else 515 *pb &= ~aml_bitmask(bit); 516 } 517 518 /* 519 * @@@: Notify functions 520 */ 521 #ifndef SMALL_KERNEL 522 void 523 acpi_poll(void *arg) 524 { 525 int s; 526 527 s = spltty(); 528 acpi_addtask(acpi_softc, acpi_poll_notify_task, NULL, 0); 529 acpi_softc->sc_threadwaiting = 0; 530 wakeup(acpi_softc); 531 splx(s); 532 533 timeout_add_sec(&acpi_softc->sc_dev_timeout, 10); 534 } 535 #endif 536 537 void 538 aml_notify_task(void *node, int notify_value) 539 { 540 struct aml_notify_data *pdata = NULL; 541 542 dnprintf(10,"run notify: %s %x\n", aml_nodename(node), notify_value); 543 SLIST_FOREACH(pdata, &aml_notify_list, link) 544 if (pdata->node == node) 545 pdata->cbproc(pdata->node, notify_value, pdata->cbarg); 546 } 547 548 void 549 aml_register_notify(struct aml_node *node, const char *pnpid, 550 int (*proc)(struct aml_node *, int, void *), void *arg, int poll) 551 { 552 struct aml_notify_data *pdata; 553 extern int acpi_poll_enabled; 554 555 dnprintf(10, "aml_register_notify: %s %s %x\n", 556 node->name, pnpid ? pnpid : "", proc); 557 558 pdata = acpi_os_malloc(sizeof(struct aml_notify_data)); 559 pdata->node = node; 560 pdata->cbarg = arg; 561 pdata->cbproc = proc; 562 pdata->poll = poll; 563 564 if (pnpid) 565 strlcpy(pdata->pnpid, pnpid, sizeof(pdata->pnpid)); 566 567 SLIST_INSERT_HEAD(&aml_notify_list, pdata, link); 568 569 if (poll && !acpi_poll_enabled) 570 timeout_add_sec(&acpi_softc->sc_dev_timeout, 10); 571 } 572 573 void 574 aml_notify(struct aml_node *node, int notify_value) 575 { 576 if (node == NULL) 577 return; 578 579 dnprintf(10,"queue notify: %s %x\n", aml_nodename(node), notify_value); 580 acpi_addtask(acpi_softc, aml_notify_task, node, notify_value); 581 } 582 583 #ifndef SMALL_KERNEL 584 void 585 aml_notify_dev(const char *pnpid, int notify_value) 586 { 587 struct aml_notify_data *pdata = NULL; 588 589 if (pnpid == NULL) 590 return; 591 592 SLIST_FOREACH(pdata, &aml_notify_list, link) 593 if (pdata->pnpid && !strcmp(pdata->pnpid, pnpid)) 594 pdata->cbproc(pdata->node, notify_value, pdata->cbarg); 595 } 596 597 void 598 acpi_poll_notify_task(void *arg0, int arg1) 599 { 600 struct aml_notify_data *pdata = NULL; 601 602 SLIST_FOREACH(pdata, &aml_notify_list, link) 603 if (pdata->cbproc && pdata->poll) 604 pdata->cbproc(pdata->node, 0, pdata->cbarg); 605 } 606 #endif 607 608 /* 609 * @@@: Namespace functions 610 */ 611 612 struct aml_node *__aml_search(struct aml_node *, uint8_t *, int); 613 void aml_delchildren(struct aml_node *); 614 615 616 /* Search for a name in children nodes */ 617 struct aml_node * 618 __aml_search(struct aml_node *root, uint8_t *nameseg, int create) 619 { 620 struct aml_node *node; 621 622 /* XXX: Replace with SLIST/SIMPLEQ routines */ 623 if (root == NULL) 624 return NULL; 625 SIMPLEQ_FOREACH(node, &root->son, sib) { 626 if (!strncmp(node->name, nameseg, AML_NAMESEG_LEN)) 627 return node; 628 } 629 if (create) { 630 node = acpi_os_malloc(sizeof(struct aml_node)); 631 memcpy((void *)node->name, nameseg, AML_NAMESEG_LEN); 632 node->value = aml_allocvalue(0,0,NULL); 633 node->value->node = node; 634 node->parent = root; 635 636 SIMPLEQ_INIT(&node->son); 637 SIMPLEQ_INSERT_TAIL(&root->son, node, sib); 638 } 639 return node; 640 } 641 642 /* Get absolute pathname of AML node */ 643 const char * 644 aml_nodename(struct aml_node *node) 645 { 646 static char namebuf[128]; 647 648 namebuf[0] = 0; 649 if (node) { 650 aml_nodename(node->parent); 651 if (node->parent != &aml_root) 652 strlcat(namebuf, ".", sizeof(namebuf)); 653 strlcat(namebuf, node->name, sizeof(namebuf)); 654 return namebuf+1; 655 } 656 return namebuf; 657 } 658 659 const char * 660 aml_getname(const char *name) 661 { 662 static char namebuf[128], *p; 663 int count; 664 665 p = namebuf; 666 while (*name == AMLOP_ROOTCHAR || *name == AMLOP_PARENTPREFIX) 667 *(p++) = *(name++); 668 switch (*name) { 669 case 0x00: 670 count = 0; 671 break; 672 case AMLOP_MULTINAMEPREFIX: 673 count = name[1]; 674 name += 2; 675 break; 676 case AMLOP_DUALNAMEPREFIX: 677 count = 2; 678 name += 1; 679 break; 680 default: 681 count = 1; 682 } 683 while (count--) { 684 memcpy(p, name, 4); 685 p[4] = '.'; 686 p += 5; 687 name += 4; 688 if (*name == '.') name++; 689 } 690 *(--p) = 0; 691 return namebuf; 692 } 693 694 /* Free all children nodes/values */ 695 void 696 aml_delchildren(struct aml_node *node) 697 { 698 struct aml_node *onode; 699 700 if (node == NULL) 701 return; 702 while ((onode = SIMPLEQ_FIRST(&node->son)) != NULL) { 703 SIMPLEQ_REMOVE_HEAD(&node->son, sib); 704 705 aml_delchildren(onode); 706 707 /* Don't delete values that have references */ 708 if (onode->value && onode->value->refcnt > 1) 709 onode->value->node = NULL; 710 711 /* Decrease reference count */ 712 aml_delref(&onode->value, ""); 713 714 /* Delete node */ 715 acpi_os_free(onode); 716 } 717 } 718 719 /* 720 * @@@: Value functions 721 */ 722 723 /* 724 * Field I/O code 725 */ 726 void aml_unlockfield(struct aml_scope *, struct aml_value *); 727 void aml_lockfield(struct aml_scope *, struct aml_value *); 728 729 long acpi_acquire_global_lock(void*); 730 long acpi_release_global_lock(void*); 731 static long global_lock_count = 0; 732 #define acpi_acquire_global_lock(x) 1 733 #define acpi_release_global_lock(x) 0 734 void 735 aml_lockfield(struct aml_scope *scope, struct aml_value *field) 736 { 737 int st = 0; 738 739 if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON) 740 return; 741 742 /* If lock is already ours, just continue */ 743 if (global_lock_count++) 744 return; 745 746 /* Spin to acquire lock */ 747 while (!st) { 748 st = acpi_acquire_global_lock(&acpi_softc->sc_facs->global_lock); 749 /* XXX - yield/delay? */ 750 } 751 752 return; 753 } 754 755 void 756 aml_unlockfield(struct aml_scope *scope, struct aml_value *field) 757 { 758 int st, x, s; 759 760 if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON) 761 return; 762 763 /* If we are the last ones, turn out the lights */ 764 if (--global_lock_count) 765 return; 766 767 /* Release lock */ 768 st = acpi_release_global_lock(&acpi_softc->sc_facs->global_lock); 769 if (!st) 770 return; 771 772 /* Signal others if someone waiting */ 773 s = spltty(); 774 x = acpi_read_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0); 775 x |= ACPI_PM1_GBL_RLS; 776 acpi_write_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0, x); 777 splx(s); 778 779 return; 780 } 781 782 /* 783 * @@@: Value set/compare/alloc/free routines 784 */ 785 786 #ifndef SMALL_KERNEL 787 void 788 aml_showvalue(struct aml_value *val, int lvl) 789 { 790 int idx; 791 792 if (val == NULL) 793 return; 794 795 if (val->node) 796 printf(" [%s]", aml_nodename(val->node)); 797 printf(" %p cnt:%.2x stk:%.2x", val, val->refcnt, val->stack); 798 switch (val->type) { 799 case AML_OBJTYPE_INTEGER: 800 printf(" integer: %llx\n", val->v_integer); 801 break; 802 case AML_OBJTYPE_STRING: 803 printf(" string: %s\n", val->v_string); 804 break; 805 case AML_OBJTYPE_METHOD: 806 printf(" method: %.2x\n", val->v_method.flags); 807 break; 808 case AML_OBJTYPE_PACKAGE: 809 printf(" package: %.2x\n", val->length); 810 for (idx = 0; idx < val->length; idx++) 811 aml_showvalue(val->v_package[idx], lvl); 812 break; 813 case AML_OBJTYPE_BUFFER: 814 printf(" buffer: %.2x {", val->length); 815 for (idx = 0; idx < val->length; idx++) 816 printf("%s%.2x", idx ? ", " : "", val->v_buffer[idx]); 817 printf("}\n"); 818 break; 819 case AML_OBJTYPE_FIELDUNIT: 820 case AML_OBJTYPE_BUFFERFIELD: 821 printf(" field: bitpos=%.4x bitlen=%.4x ref1:%p ref2:%p [%s]\n", 822 val->v_field.bitpos, val->v_field.bitlen, 823 val->v_field.ref1, val->v_field.ref2, 824 aml_mnem(val->v_field.type, NULL)); 825 if (val->v_field.ref1) 826 printf(" ref1: %s\n", aml_nodename(val->v_field.ref1->node)); 827 if (val->v_field.ref2) 828 printf(" ref2: %s\n", aml_nodename(val->v_field.ref2->node)); 829 break; 830 case AML_OBJTYPE_MUTEX: 831 printf(" mutex: %s ref: %d\n", 832 val->v_mutex ? val->v_mutex->amt_name : "", 833 val->v_mutex ? val->v_mutex->amt_ref_count : 0); 834 break; 835 case AML_OBJTYPE_EVENT: 836 printf(" event:\n"); 837 break; 838 case AML_OBJTYPE_OPREGION: 839 printf(" opregion: %.2x,%.8llx,%x\n", 840 val->v_opregion.iospace, val->v_opregion.iobase, 841 val->v_opregion.iolen); 842 break; 843 case AML_OBJTYPE_NAMEREF: 844 printf(" nameref: %s\n", aml_getname(val->v_nameref)); 845 break; 846 case AML_OBJTYPE_DEVICE: 847 printf(" device:\n"); 848 break; 849 case AML_OBJTYPE_PROCESSOR: 850 printf(" cpu: %.2x,%.4x,%.2x\n", 851 val->v_processor.proc_id, val->v_processor.proc_addr, 852 val->v_processor.proc_len); 853 break; 854 case AML_OBJTYPE_THERMZONE: 855 printf(" thermzone:\n"); 856 break; 857 case AML_OBJTYPE_POWERRSRC: 858 printf(" pwrrsrc: %.2x,%.2x\n", 859 val->v_powerrsrc.pwr_level, val->v_powerrsrc.pwr_order); 860 break; 861 case AML_OBJTYPE_OBJREF: 862 printf(" objref: %p index:%x opcode:%s\n", val->v_objref.ref, 863 val->v_objref.index, aml_mnem(val->v_objref.type, 0)); 864 aml_showvalue(val->v_objref.ref, lvl); 865 break; 866 default: 867 printf(" !!type: %x\n", val->type); 868 } 869 } 870 #endif /* SMALL_KERNEL */ 871 872 int64_t 873 aml_val2int(struct aml_value *rval) 874 { 875 int64_t ival = 0; 876 877 if (rval == NULL) { 878 dnprintf(50, "null val2int\n"); 879 return (0); 880 } 881 switch (rval->type) { 882 case AML_OBJTYPE_INTEGER: 883 ival = rval->v_integer; 884 break; 885 case AML_OBJTYPE_BUFFER: 886 aml_bufcpy(&ival, 0, rval->v_buffer, 0, 887 min(aml_intlen, rval->length*8)); 888 break; 889 case AML_OBJTYPE_STRING: 890 ival = aml_hextoint(rval->v_string); 891 break; 892 } 893 return (ival); 894 } 895 896 /* Sets value into LHS: lhs must already be cleared */ 897 struct aml_value * 898 _aml_setvalue(struct aml_value *lhs, int type, int64_t ival, const void *bval) 899 { 900 memset(&lhs->_, 0x0, sizeof(lhs->_)); 901 902 lhs->type = type; 903 switch (lhs->type) { 904 case AML_OBJTYPE_INTEGER: 905 lhs->length = aml_intlen>>3; 906 lhs->v_integer = ival; 907 break; 908 case AML_OBJTYPE_METHOD: 909 lhs->v_method.flags = ival; 910 lhs->v_method.fneval = bval; 911 break; 912 case AML_OBJTYPE_NAMEREF: 913 lhs->v_nameref = (uint8_t *)bval; 914 break; 915 case AML_OBJTYPE_OBJREF: 916 lhs->v_objref.type = ival; 917 lhs->v_objref.ref = (struct aml_value *)bval; 918 break; 919 case AML_OBJTYPE_BUFFER: 920 lhs->length = ival; 921 lhs->v_buffer = (uint8_t *)acpi_os_malloc(ival); 922 if (bval) 923 memcpy(lhs->v_buffer, bval, ival); 924 break; 925 case AML_OBJTYPE_STRING: 926 if (ival == -1) 927 ival = strlen((const char *)bval); 928 lhs->length = ival; 929 lhs->v_string = (char *)acpi_os_malloc(ival+1); 930 if (bval) 931 strncpy(lhs->v_string, (const char *)bval, ival); 932 break; 933 case AML_OBJTYPE_PACKAGE: 934 lhs->length = ival; 935 lhs->v_package = (struct aml_value **)acpi_os_malloc(ival * 936 sizeof(struct aml_value *)); 937 for (ival = 0; ival < lhs->length; ival++) 938 lhs->v_package[ival] = aml_allocvalue( 939 AML_OBJTYPE_UNINITIALIZED, 0, NULL); 940 break; 941 } 942 return lhs; 943 } 944 945 /* Copy object to another value: lhs must already be cleared */ 946 void 947 aml_copyvalue(struct aml_value *lhs, struct aml_value *rhs) 948 { 949 int idx; 950 951 lhs->type = rhs->type; 952 switch (lhs->type) { 953 case AML_OBJTYPE_UNINITIALIZED: 954 break; 955 case AML_OBJTYPE_INTEGER: 956 lhs->length = aml_intlen>>3; 957 lhs->v_integer = rhs->v_integer; 958 break; 959 case AML_OBJTYPE_MUTEX: 960 lhs->v_mutex = rhs->v_mutex; 961 break; 962 case AML_OBJTYPE_POWERRSRC: 963 lhs->v_powerrsrc = rhs->v_powerrsrc; 964 break; 965 case AML_OBJTYPE_METHOD: 966 lhs->v_method = rhs->v_method; 967 break; 968 case AML_OBJTYPE_BUFFER: 969 _aml_setvalue(lhs, rhs->type, rhs->length, rhs->v_buffer); 970 break; 971 case AML_OBJTYPE_STRING: 972 _aml_setvalue(lhs, rhs->type, rhs->length, rhs->v_string); 973 break; 974 case AML_OBJTYPE_OPREGION: 975 lhs->v_opregion = rhs->v_opregion; 976 break; 977 case AML_OBJTYPE_PROCESSOR: 978 lhs->v_processor = rhs->v_processor; 979 break; 980 case AML_OBJTYPE_NAMEREF: 981 lhs->v_nameref = rhs->v_nameref; 982 break; 983 case AML_OBJTYPE_PACKAGE: 984 _aml_setvalue(lhs, rhs->type, rhs->length, NULL); 985 for (idx = 0; idx < rhs->length; idx++) 986 aml_copyvalue(lhs->v_package[idx], rhs->v_package[idx]); 987 break; 988 case AML_OBJTYPE_OBJREF: 989 lhs->v_objref = rhs->v_objref; 990 aml_addref(lhs->v_objref.ref, ""); 991 break; 992 default: 993 printf("copyvalue: %x", rhs->type); 994 break; 995 } 996 } 997 998 /* Allocate dynamic AML value 999 * type : Type of object to allocate (AML_OBJTYPE_XXXX) 1000 * ival : Integer value (action depends on type) 1001 * bval : Buffer value (action depends on type) 1002 */ 1003 struct aml_value * 1004 aml_allocvalue(int type, int64_t ival, const void *bval) 1005 { 1006 struct aml_value *rv; 1007 1008 rv = (struct aml_value *)acpi_os_malloc(sizeof(struct aml_value)); 1009 if (rv != NULL) { 1010 aml_addref(rv, ""); 1011 return _aml_setvalue(rv, type, ival, bval); 1012 } 1013 return NULL; 1014 } 1015 1016 void 1017 aml_freevalue(struct aml_value *val) 1018 { 1019 int idx; 1020 1021 if (val == NULL) 1022 return; 1023 switch (val->type) { 1024 case AML_OBJTYPE_STRING: 1025 acpi_os_free(val->v_string); 1026 break; 1027 case AML_OBJTYPE_BUFFER: 1028 acpi_os_free(val->v_buffer); 1029 break; 1030 case AML_OBJTYPE_PACKAGE: 1031 for (idx = 0; idx < val->length; idx++) { 1032 aml_freevalue(val->v_package[idx]); 1033 acpi_os_free(val->v_package[idx]); 1034 } 1035 acpi_os_free(val->v_package); 1036 break; 1037 case AML_OBJTYPE_OBJREF: 1038 aml_delref(&val->v_objref.ref, ""); 1039 break; 1040 case AML_OBJTYPE_BUFFERFIELD: 1041 case AML_OBJTYPE_FIELDUNIT: 1042 aml_delref(&val->v_field.ref1, ""); 1043 aml_delref(&val->v_field.ref2, ""); 1044 break; 1045 } 1046 val->type = 0; 1047 memset(&val->_, 0, sizeof(val->_)); 1048 } 1049 1050 /* 1051 * @@@: Math eval routines 1052 */ 1053 1054 /* Convert number from one radix to another 1055 * Used in BCD conversion routines */ 1056 u_int64_t 1057 aml_convradix(u_int64_t val, int iradix, int oradix) 1058 { 1059 u_int64_t rv = 0, pwr; 1060 1061 rv = 0; 1062 pwr = 1; 1063 while (val) { 1064 rv += (val % iradix) * pwr; 1065 val /= iradix; 1066 pwr *= oradix; 1067 } 1068 return rv; 1069 } 1070 1071 /* Calculate LSB */ 1072 int 1073 aml_lsb(u_int64_t val) 1074 { 1075 int lsb; 1076 1077 if (val == 0) 1078 return (0); 1079 1080 for (lsb = 1; !(val & 0x1); lsb++) 1081 val >>= 1; 1082 1083 return (lsb); 1084 } 1085 1086 /* Calculate MSB */ 1087 int 1088 aml_msb(u_int64_t val) 1089 { 1090 int msb; 1091 1092 if (val == 0) 1093 return (0); 1094 1095 for (msb = 1; val != 0x1; msb++) 1096 val >>= 1; 1097 1098 return (msb); 1099 } 1100 1101 /* Evaluate Math operands */ 1102 int64_t 1103 aml_evalexpr(int64_t lhs, int64_t rhs, int opcode) 1104 { 1105 int64_t res = 0; 1106 1107 switch (opcode) { 1108 /* Math operations */ 1109 case AMLOP_INCREMENT: 1110 case AMLOP_ADD: 1111 res = (lhs + rhs); 1112 break; 1113 case AMLOP_DECREMENT: 1114 case AMLOP_SUBTRACT: 1115 res = (lhs - rhs); 1116 break; 1117 case AMLOP_MULTIPLY: 1118 res = (lhs * rhs); 1119 break; 1120 case AMLOP_DIVIDE: 1121 res = (lhs / rhs); 1122 break; 1123 case AMLOP_MOD: 1124 res = (lhs % rhs); 1125 break; 1126 case AMLOP_SHL: 1127 res = (lhs << rhs); 1128 break; 1129 case AMLOP_SHR: 1130 res = (lhs >> rhs); 1131 break; 1132 case AMLOP_AND: 1133 res = (lhs & rhs); 1134 break; 1135 case AMLOP_NAND: 1136 res = ~(lhs & rhs); 1137 break; 1138 case AMLOP_OR: 1139 res = (lhs | rhs); 1140 break; 1141 case AMLOP_NOR: 1142 res = ~(lhs | rhs); 1143 break; 1144 case AMLOP_XOR: 1145 res = (lhs ^ rhs); 1146 break; 1147 case AMLOP_NOT: 1148 res = ~(lhs); 1149 break; 1150 1151 /* Conversion/misc */ 1152 case AMLOP_FINDSETLEFTBIT: 1153 res = aml_msb(lhs); 1154 break; 1155 case AMLOP_FINDSETRIGHTBIT: 1156 res = aml_lsb(lhs); 1157 break; 1158 case AMLOP_TOINTEGER: 1159 res = (lhs); 1160 break; 1161 case AMLOP_FROMBCD: 1162 res = aml_convradix(lhs, 16, 10); 1163 break; 1164 case AMLOP_TOBCD: 1165 res = aml_convradix(lhs, 10, 16); 1166 break; 1167 1168 /* Logical/Comparison */ 1169 case AMLOP_LAND: 1170 res = -(lhs && rhs); 1171 break; 1172 case AMLOP_LOR: 1173 res = -(lhs || rhs); 1174 break; 1175 case AMLOP_LNOT: 1176 res = -(!lhs); 1177 break; 1178 case AMLOP_LNOTEQUAL: 1179 res = -(lhs != rhs); 1180 break; 1181 case AMLOP_LLESSEQUAL: 1182 res = -(lhs <= rhs); 1183 break; 1184 case AMLOP_LGREATEREQUAL: 1185 res = -(lhs >= rhs); 1186 break; 1187 case AMLOP_LEQUAL: 1188 res = -(lhs == rhs); 1189 break; 1190 case AMLOP_LGREATER: 1191 res = -(lhs > rhs); 1192 break; 1193 case AMLOP_LLESS: 1194 res = -(lhs < rhs); 1195 break; 1196 } 1197 1198 dnprintf(15,"aml_evalexpr: %s %llx %llx = %llx\n", 1199 aml_mnem(opcode, NULL), lhs, rhs, res); 1200 1201 return res; 1202 } 1203 1204 /* 1205 * aml_bufcpy copies/shifts buffer data, special case for aligned transfers 1206 * dstPos/srcPos are bit positions within destination/source buffers 1207 */ 1208 void 1209 aml_bufcpy(void *pvDst, int dstPos, const void *pvSrc, int srcPos, int len) 1210 { 1211 const u_int8_t *pSrc = pvSrc; 1212 u_int8_t *pDst = pvDst; 1213 int idx; 1214 1215 if (aml_bytealigned(dstPos|srcPos|len)) { 1216 /* Aligned transfer: use memcpy */ 1217 memcpy(pDst+aml_bytepos(dstPos), pSrc+aml_bytepos(srcPos), 1218 aml_bytelen(len)); 1219 return; 1220 } 1221 1222 /* Misaligned transfer: perform bitwise copy (slow) */ 1223 for (idx = 0; idx < len; idx++) 1224 aml_setbit(pDst, idx + dstPos, aml_tstbit(pSrc, idx + srcPos)); 1225 } 1226 1227 /* 1228 * @@@: External API 1229 * 1230 * evaluate an AML node 1231 * Returns a copy of the value in res (must be freed by user) 1232 */ 1233 1234 void 1235 aml_walknodes(struct aml_node *node, int mode, 1236 int (*nodecb)(struct aml_node *, void *), void *arg) 1237 { 1238 struct aml_node *child; 1239 1240 if (node == NULL) 1241 return; 1242 if (mode == AML_WALK_PRE) 1243 if (nodecb(node, arg)) 1244 return; 1245 SIMPLEQ_FOREACH(child, &node->son, sib) 1246 aml_walknodes(child, mode, nodecb, arg); 1247 if (mode == AML_WALK_POST) 1248 nodecb(node, arg); 1249 } 1250 1251 int 1252 aml_find_node(struct aml_node *node, const char *name, 1253 int (*cbproc)(struct aml_node *, void *arg), void *arg) 1254 { 1255 const char *nn; 1256 int st = 0; 1257 1258 while (node) { 1259 if ((nn = node->name) != NULL) { 1260 if (*nn == AMLOP_ROOTCHAR) nn++; 1261 while (*nn == AMLOP_PARENTPREFIX) nn++; 1262 if (!strcmp(name, nn)) 1263 st = cbproc(node, arg); 1264 } 1265 /* Only recurse if cbproc() wants us to */ 1266 if (!st) 1267 aml_find_node(SIMPLEQ_FIRST(&node->son), name, cbproc, arg); 1268 node = SIMPLEQ_NEXT(node, sib); 1269 } 1270 return st; 1271 } 1272 1273 /* 1274 * @@@: Parser functions 1275 */ 1276 uint8_t *aml_parsename(struct aml_node *, uint8_t *, struct aml_value **, int); 1277 uint8_t *aml_parseend(struct aml_scope *scope); 1278 int aml_parselength(struct aml_scope *); 1279 int aml_parseopcode(struct aml_scope *); 1280 1281 /* Get AML Opcode */ 1282 int 1283 aml_parseopcode(struct aml_scope *scope) 1284 { 1285 int opcode = (scope->pos[0]); 1286 int twocode = (scope->pos[0]<<8) + scope->pos[1]; 1287 1288 /* Check if this is an embedded name */ 1289 switch (opcode) { 1290 case AMLOP_ROOTCHAR: 1291 case AMLOP_PARENTPREFIX: 1292 case AMLOP_MULTINAMEPREFIX: 1293 case AMLOP_DUALNAMEPREFIX: 1294 case AMLOP_NAMECHAR: 1295 return AMLOP_NAMECHAR; 1296 } 1297 if (opcode >= 'A' && opcode <= 'Z') 1298 return AMLOP_NAMECHAR; 1299 if (twocode == AMLOP_LNOTEQUAL || twocode == AMLOP_LLESSEQUAL || 1300 twocode == AMLOP_LGREATEREQUAL || opcode == AMLOP_EXTPREFIX) { 1301 scope->pos += 2; 1302 return twocode; 1303 } 1304 scope->pos += 1; 1305 return opcode; 1306 } 1307 1308 /* Decode embedded AML Namestring */ 1309 uint8_t * 1310 aml_parsename(struct aml_node *inode, uint8_t *pos, struct aml_value **rval, int create) 1311 { 1312 struct aml_node *relnode, *node = inode; 1313 uint8_t *start = pos; 1314 int i; 1315 1316 if (*pos == AMLOP_ROOTCHAR) { 1317 pos++; 1318 node = &aml_root; 1319 } 1320 while (*pos == AMLOP_PARENTPREFIX) { 1321 pos++; 1322 if ((node = node->parent) == NULL) 1323 node = &aml_root; 1324 } 1325 switch (*pos) { 1326 case 0x00: 1327 pos++; 1328 break; 1329 case AMLOP_MULTINAMEPREFIX: 1330 for (i=0; i<pos[1]; i++) 1331 node = __aml_search(node, pos+2+i*AML_NAMESEG_LEN, 1332 create); 1333 pos += 2+i*AML_NAMESEG_LEN; 1334 break; 1335 case AMLOP_DUALNAMEPREFIX: 1336 node = __aml_search(node, pos+1, create); 1337 node = __aml_search(node, pos+1+AML_NAMESEG_LEN, create); 1338 pos += 1+2*AML_NAMESEG_LEN; 1339 break; 1340 default: 1341 /* If Relative Search (pos == start), recursively go up root */ 1342 relnode = node; 1343 do { 1344 node = __aml_search(relnode, pos, create); 1345 relnode = relnode->parent; 1346 } while (!node && pos == start && relnode); 1347 pos += AML_NAMESEG_LEN; 1348 break; 1349 } 1350 if (node) { 1351 *rval = node->value; 1352 1353 /* Dereference ALIAS here */ 1354 if ((*rval)->type == AML_OBJTYPE_OBJREF && 1355 (*rval)->v_objref.type == AMLOP_ALIAS) { 1356 dnprintf(10, "deref alias: %s\n", aml_nodename(node)); 1357 *rval = (*rval)->v_objref.ref; 1358 } 1359 aml_addref(*rval, 0); 1360 1361 dnprintf(10, "parsename: %s %x\n", aml_nodename(node), 1362 (*rval)->type); 1363 } else { 1364 *rval = aml_allocvalue(AML_OBJTYPE_NAMEREF, 0, start); 1365 1366 dnprintf(10, "%s:%s not found\n", aml_nodename(inode), 1367 aml_getname(start)); 1368 } 1369 1370 return pos; 1371 } 1372 1373 /* Decode AML Length field 1374 * AML Length field is encoded: 1375 * byte0 byte1 byte2 byte3 1376 * 00xxxxxx : if upper bits == 00, length = xxxxxx 1377 * 01--xxxx yyyyyyyy : if upper bits == 01, length = yyyyyyyyxxxx 1378 * 10--xxxx yyyyyyyy zzzzzzzz : if upper bits == 10, length = zzzzzzzzyyyyyyyyxxxx 1379 * 11--xxxx yyyyyyyy zzzzzzzz wwwwwwww : if upper bits == 11, length = wwwwwwwwzzzzzzzzyyyyyyyyxxxx 1380 */ 1381 int 1382 aml_parselength(struct aml_scope *scope) 1383 { 1384 int len; 1385 uint8_t lcode; 1386 1387 lcode = *(scope->pos++); 1388 if (lcode <= 0x3F) 1389 return lcode; 1390 1391 /* lcode >= 0x40, multibyte length, get first byte of extended length */ 1392 len = lcode & 0xF; 1393 len += *(scope->pos++) << 4L; 1394 if (lcode >= 0x80) 1395 len += *(scope->pos++) << 12L; 1396 if (lcode >= 0xC0) 1397 len += *(scope->pos++) << 20L; 1398 return len; 1399 } 1400 1401 /* Get address of end of scope; based on current address */ 1402 uint8_t * 1403 aml_parseend(struct aml_scope *scope) 1404 { 1405 uint8_t *pos = scope->pos; 1406 int len; 1407 1408 len = aml_parselength(scope); 1409 if (pos+len > scope->end) { 1410 dnprintf(10, 1411 "Bad scope... runover pos:%.4x new end:%.4x scope " 1412 "end:%.4x\n", aml_pc(pos), aml_pc(pos+len), 1413 aml_pc(scope->end)); 1414 pos = scope->end; 1415 } 1416 return pos+len; 1417 } 1418 1419 /* 1420 * @@@: Opcode utility functions 1421 */ 1422 1423 /* 1424 * @@@: Opcode functions 1425 */ 1426 1427 int odp; 1428 1429 const char hext[] = "0123456789ABCDEF"; 1430 1431 const char * 1432 aml_eisaid(u_int32_t pid) 1433 { 1434 static char id[8]; 1435 1436 id[0] = '@' + ((pid >> 2) & 0x1F); 1437 id[1] = '@' + ((pid << 3) & 0x18) + ((pid >> 13) & 0x7); 1438 id[2] = '@' + ((pid >> 8) & 0x1F); 1439 id[3] = hext[(pid >> 20) & 0xF]; 1440 id[4] = hext[(pid >> 16) & 0xF]; 1441 id[5] = hext[(pid >> 28) & 0xF]; 1442 id[6] = hext[(pid >> 24) & 0xF]; 1443 id[7] = 0; 1444 return id; 1445 } 1446 1447 /* 1448 * @@@: Default Object creation 1449 */ 1450 static char osstring[] = "Macrosift Windogs MT"; 1451 struct aml_defval { 1452 const char *name; 1453 int type; 1454 int64_t ival; 1455 const void *bval; 1456 struct aml_value **gval; 1457 } aml_defobj[] = { 1458 { "_OS_", AML_OBJTYPE_STRING, -1, osstring }, 1459 { "_REV", AML_OBJTYPE_INTEGER, 2, NULL }, 1460 { "_GL", AML_OBJTYPE_MUTEX, 1, NULL, &aml_global_lock }, 1461 { "_OSI", AML_OBJTYPE_METHOD, 1, aml_callosi }, 1462 1463 /* Create default scopes */ 1464 { "_GPE" }, 1465 { "_PR_" }, 1466 { "_SB_" }, 1467 { "_TZ_" }, 1468 { "_SI_" }, 1469 1470 { NULL } 1471 }; 1472 1473 /* _OSI Default Method: 1474 * Returns True if string argument matches list of known OS strings 1475 * We return True for Windows to fake out nasty bad AML 1476 */ 1477 char *aml_valid_osi[] = { 1478 "Windows 2000", 1479 "Windows 2001", 1480 "Windows 2001.1", 1481 "Windows 2001 SP0", 1482 "Windows 2001 SP1", 1483 "Windows 2001 SP2", 1484 "Windows 2001 SP3", 1485 "Windows 2001 SP4", 1486 "Windows 2006", 1487 "Windows 2009", 1488 NULL 1489 }; 1490 1491 struct aml_value * 1492 aml_callosi(struct aml_scope *scope, struct aml_value *val) 1493 { 1494 int idx, result=0; 1495 struct aml_value *fa; 1496 1497 fa = aml_getstack(scope, AMLOP_ARG0); 1498 for (idx=0; !result && aml_valid_osi[idx] != NULL; idx++) { 1499 dnprintf(10,"osi: %s,%s\n", fa->v_string, aml_valid_osi[idx]); 1500 result = !strcmp(fa->v_string, aml_valid_osi[idx]); 1501 } 1502 dnprintf(10,"@@ OSI found: %x\n", result); 1503 return aml_allocvalue(AML_OBJTYPE_INTEGER, result, NULL); 1504 } 1505 1506 void 1507 aml_create_defaultobjects(void) 1508 { 1509 struct aml_value *tmp; 1510 struct aml_defval *def; 1511 1512 #ifdef ACPI_MEMDEBUG 1513 LIST_INIT(&acpi_memhead); 1514 #endif 1515 1516 osstring[1] = 'i'; 1517 osstring[6] = 'o'; 1518 osstring[15] = 'w'; 1519 osstring[18] = 'N'; 1520 1521 SIMPLEQ_INIT(&aml_root.son); 1522 strlcpy(aml_root.name, "\\", sizeof(aml_root.name)); 1523 aml_root.value = aml_allocvalue(0, 0, NULL); 1524 aml_root.value->node = &aml_root; 1525 1526 for (def = aml_defobj; def->name; def++) { 1527 /* Allocate object value + add to namespace */ 1528 aml_parsename(&aml_root, (uint8_t *)def->name, &tmp, 1); 1529 _aml_setvalue(tmp, def->type, def->ival, def->bval); 1530 if (def->gval) { 1531 /* Set root object pointer */ 1532 *def->gval = tmp; 1533 } 1534 aml_delref(&tmp, 0); 1535 } 1536 } 1537 1538 #ifdef ACPI_DEBUG 1539 int 1540 aml_print_resource(union acpi_resource *crs, void *arg) 1541 { 1542 int typ = AML_CRSTYPE(crs); 1543 1544 switch (typ) { 1545 case LR_EXTIRQ: 1546 printf("extirq\tflags:%.2x len:%.2x irq:%.4x\n", 1547 crs->lr_extirq.flags, crs->lr_extirq.irq_count, 1548 letoh32(crs->lr_extirq.irq[0])); 1549 break; 1550 case SR_IRQ: 1551 printf("irq\t%.4x %.2x\n", letoh16(crs->sr_irq.irq_mask), 1552 crs->sr_irq.irq_flags); 1553 break; 1554 case SR_DMA: 1555 printf("dma\t%.2x %.2x\n", crs->sr_dma.channel, 1556 crs->sr_dma.flags); 1557 break; 1558 case SR_IOPORT: 1559 printf("ioport\tflags:%.2x _min:%.4x _max:%.4x _aln:%.2x _len:%.2x\n", 1560 crs->sr_ioport.flags, crs->sr_ioport._min, 1561 crs->sr_ioport._max, crs->sr_ioport._aln, 1562 crs->sr_ioport._len); 1563 break; 1564 case SR_STARTDEP: 1565 printf("startdep\n"); 1566 break; 1567 case SR_ENDDEP: 1568 printf("enddep\n"); 1569 break; 1570 case LR_WORD: 1571 printf("word\ttype:%.2x flags:%.2x tflag:%.2x gra:%.4x min:%.4x max:%.4x tra:%.4x len:%.4x\n", 1572 crs->lr_word.type, crs->lr_word.flags, crs->lr_word.tflags, 1573 crs->lr_word._gra, crs->lr_word._min, crs->lr_word._max, 1574 crs->lr_word._tra, crs->lr_word._len); 1575 break; 1576 case LR_DWORD: 1577 printf("dword\ttype:%.2x flags:%.2x tflag:%.2x gra:%.8x min:%.8x max:%.8x tra:%.8x len:%.8x\n", 1578 crs->lr_dword.type, crs->lr_dword.flags, crs->lr_dword.tflags, 1579 crs->lr_dword._gra, crs->lr_dword._min, crs->lr_dword._max, 1580 crs->lr_dword._tra, crs->lr_dword._len); 1581 break; 1582 case LR_QWORD: 1583 printf("dword\ttype:%.2x flags:%.2x tflag:%.2x gra:%.16llx min:%.16llx max:%.16llx tra:%.16llx len:%.16llx\n", 1584 crs->lr_qword.type, crs->lr_qword.flags, crs->lr_qword.tflags, 1585 crs->lr_qword._gra, crs->lr_qword._min, crs->lr_qword._max, 1586 crs->lr_qword._tra, crs->lr_qword._len); 1587 break; 1588 default: 1589 printf("unknown type: %x\n", typ); 1590 break; 1591 } 1592 return (0); 1593 } 1594 #endif /* ACPI_DEBUG */ 1595 1596 union acpi_resource *aml_mapresource(union acpi_resource *); 1597 1598 union acpi_resource * 1599 aml_mapresource(union acpi_resource *crs) 1600 { 1601 static union acpi_resource map; 1602 int rlen; 1603 1604 rlen = AML_CRSLEN(crs); 1605 if (rlen >= sizeof(map)) 1606 return crs; 1607 1608 memset(&map, 0, sizeof(map)); 1609 memcpy(&map, crs, rlen); 1610 1611 return ↦ 1612 } 1613 1614 int 1615 aml_parse_resource(struct aml_value *res, 1616 int (*crs_enum)(union acpi_resource *, void *), void *arg) 1617 { 1618 int off, rlen; 1619 union acpi_resource *crs; 1620 1621 if (res->type != AML_OBJTYPE_BUFFER || res->length < 5) 1622 return (-1); 1623 for (off = 0; off < res->length; off += rlen) { 1624 crs = (union acpi_resource *)(res->v_buffer+off); 1625 1626 rlen = AML_CRSLEN(crs); 1627 if (crs->hdr.typecode == 0x79 || !rlen) 1628 break; 1629 1630 crs = aml_mapresource(crs); 1631 #ifdef ACPI_DEBUG 1632 aml_print_resource(crs, NULL); 1633 #endif 1634 crs_enum(crs, arg); 1635 } 1636 1637 return (0); 1638 } 1639 1640 void 1641 aml_foreachpkg(struct aml_value *pkg, int start, 1642 void (*fn)(struct aml_value *, void *), void *arg) 1643 { 1644 int idx; 1645 1646 if (pkg->type != AML_OBJTYPE_PACKAGE) 1647 return; 1648 for (idx=start; idx<pkg->length; idx++) 1649 fn(pkg->v_package[idx], arg); 1650 } 1651 1652 /* 1653 * Walk nodes and perform fixups for nameref 1654 */ 1655 int aml_fixup_node(struct aml_node *, void *); 1656 1657 int aml_fixup_node(struct aml_node *node, void *arg) 1658 { 1659 struct aml_value *val = arg; 1660 int i; 1661 1662 if (node->value == NULL) 1663 return (0); 1664 if (arg == NULL) 1665 aml_fixup_node(node, node->value); 1666 else if (val->type == AML_OBJTYPE_NAMEREF) { 1667 node = aml_searchname(node, val->v_nameref); 1668 if (node && node->value) { 1669 _aml_setvalue(val, AML_OBJTYPE_OBJREF, AMLOP_NAMECHAR, 1670 node->value); 1671 } 1672 } else if (val->type == AML_OBJTYPE_PACKAGE) { 1673 for (i = 0; i < val->length; i++) 1674 aml_fixup_node(node, val->v_package[i]); 1675 } 1676 return (0); 1677 } 1678 1679 void 1680 aml_postparse(void) 1681 { 1682 aml_walknodes(&aml_root, AML_WALK_PRE, aml_fixup_node, NULL); 1683 } 1684 1685 #ifndef SMALL_KERNEL 1686 const char * 1687 aml_val_to_string(const struct aml_value *val) 1688 { 1689 static char buffer[256]; 1690 1691 int len; 1692 1693 switch (val->type) { 1694 case AML_OBJTYPE_BUFFER: 1695 len = val->length; 1696 if (len >= sizeof(buffer)) 1697 len = sizeof(buffer) - 1; 1698 memcpy(buffer, val->v_buffer, len); 1699 buffer[len] = 0; 1700 break; 1701 case AML_OBJTYPE_STRING: 1702 strlcpy(buffer, val->v_string, sizeof(buffer)); 1703 break; 1704 case AML_OBJTYPE_INTEGER: 1705 snprintf(buffer, sizeof(buffer), "%llx", val->v_integer); 1706 break; 1707 default: 1708 snprintf(buffer, sizeof(buffer), 1709 "Failed to convert type %d to string!", val->type); 1710 }; 1711 1712 return (buffer); 1713 } 1714 #endif /* SMALL_KERNEL */ 1715 1716 int aml_error; 1717 1718 struct aml_value *aml_gettgt(struct aml_value *, int); 1719 struct aml_value *aml_eval(struct aml_scope *, struct aml_value *, int, int, 1720 struct aml_value *); 1721 struct aml_value *aml_parsesimple(struct aml_scope *, char, 1722 struct aml_value *); 1723 struct aml_value *aml_parse(struct aml_scope *, int, const char *); 1724 struct aml_value *aml_seterror(struct aml_scope *, const char *, ...); 1725 1726 struct aml_scope *aml_findscope(struct aml_scope *, int, int); 1727 struct aml_scope *aml_pushscope(struct aml_scope *, struct aml_value *, 1728 struct aml_node *, int); 1729 struct aml_scope *aml_popscope(struct aml_scope *); 1730 1731 void aml_showstack(struct aml_scope *); 1732 struct aml_value *aml_convert(struct aml_value *, int, int); 1733 1734 int aml_matchtest(int64_t, int64_t, int); 1735 int aml_match(struct aml_value *, int, int, int, int, int); 1736 1737 int aml_compare(struct aml_value *, struct aml_value *, int); 1738 struct aml_value *aml_concat(struct aml_value *, struct aml_value *); 1739 struct aml_value *aml_concatres(struct aml_value *, struct aml_value *); 1740 struct aml_value *aml_mid(struct aml_value *, int, int); 1741 int aml_ccrlen(union acpi_resource *, void *); 1742 1743 void aml_store(struct aml_scope *, struct aml_value *, int64_t, 1744 struct aml_value *); 1745 1746 /* 1747 * Reference Count functions 1748 */ 1749 void 1750 aml_addref(struct aml_value *val, const char *lbl) 1751 { 1752 if (val == NULL) 1753 return; 1754 dnprintf(50, "XAddRef: %p %s:[%s] %d\n", 1755 val, lbl, 1756 val->node ? aml_nodename(val->node) : "INTERNAL", 1757 val->refcnt); 1758 val->refcnt++; 1759 } 1760 1761 /* Decrease reference counter */ 1762 void 1763 aml_delref(struct aml_value **pv, const char *lbl) 1764 { 1765 struct aml_value *val; 1766 1767 if (pv == NULL || *pv == NULL) 1768 return; 1769 val = *pv; 1770 val->refcnt--; 1771 if (val->refcnt == 0) { 1772 dnprintf(50, "XDelRef: %p %s %2d [%s] %s\n", 1773 val, lbl, 1774 val->refcnt, 1775 val->node ? aml_nodename(val->node) : "INTERNAL", 1776 val->refcnt ? "" : "---------------- FREEING"); 1777 1778 aml_freevalue(val); 1779 acpi_os_free(val); 1780 *pv = NULL; 1781 } 1782 } 1783 1784 /* Walk list of parent scopes until we find one of 'type' 1785 * If endscope is set, mark all intermediate scopes as invalid (used for Method/While) */ 1786 struct aml_scope * 1787 aml_findscope(struct aml_scope *scope, int type, int endscope) 1788 { 1789 while (scope) { 1790 switch (endscope) { 1791 case AMLOP_RETURN: 1792 scope->pos = scope->end; 1793 if (scope->type == AMLOP_WHILE) 1794 scope->pos = NULL; 1795 break; 1796 case AMLOP_CONTINUE: 1797 scope->pos = scope->end; 1798 break; 1799 case AMLOP_BREAK: 1800 scope->pos = scope->end; 1801 if (scope->type == type) 1802 scope->parent->pos = scope->end; 1803 break; 1804 } 1805 if (scope->type == type) 1806 break; 1807 scope = scope->parent; 1808 } 1809 return scope; 1810 } 1811 1812 struct aml_value * 1813 aml_getstack(struct aml_scope *scope, int opcode) 1814 { 1815 struct aml_value *sp; 1816 1817 sp = NULL; 1818 scope = aml_findscope(scope, AMLOP_METHOD, 0); 1819 if (scope == NULL) 1820 return NULL; 1821 if (opcode >= AMLOP_LOCAL0 && opcode <= AMLOP_LOCAL7) { 1822 if (scope->locals == NULL) 1823 scope->locals = aml_allocvalue(AML_OBJTYPE_PACKAGE, 8, NULL); 1824 sp = scope->locals->v_package[opcode - AMLOP_LOCAL0]; 1825 sp->stack = opcode; 1826 } else if (opcode >= AMLOP_ARG0 && opcode <= AMLOP_ARG6) { 1827 if (scope->args == NULL) 1828 scope->args = aml_allocvalue(AML_OBJTYPE_PACKAGE, 7, NULL); 1829 sp = scope->args->v_package[opcode - AMLOP_ARG0]; 1830 if (sp->type == AML_OBJTYPE_OBJREF) 1831 sp = sp->v_objref.ref; 1832 } 1833 return sp; 1834 } 1835 1836 #ifdef ACPI_DEBUG 1837 /* Dump AML Stack */ 1838 void 1839 aml_showstack(struct aml_scope *scope) 1840 { 1841 struct aml_value *sp; 1842 int idx; 1843 1844 dnprintf(10, "===== Stack %s:%s\n", aml_nodename(scope->node), 1845 aml_mnem(scope->type, 0)); 1846 for (idx=0; scope->args && idx<7; idx++) { 1847 sp = aml_getstack(scope, AMLOP_ARG0+idx); 1848 if (sp && sp->type) { 1849 dnprintf(10," Arg%d: ", idx); 1850 aml_showvalue(sp, 10); 1851 } 1852 } 1853 for (idx=0; scope->locals && idx<8; idx++) { 1854 sp = aml_getstack(scope, AMLOP_LOCAL0+idx); 1855 if (sp && sp->type) { 1856 dnprintf(10," Local%d: ", idx); 1857 aml_showvalue(sp, 10); 1858 } 1859 } 1860 } 1861 #endif 1862 1863 /* Create a new scope object */ 1864 struct aml_scope * 1865 aml_pushscope(struct aml_scope *parent, struct aml_value *range, 1866 struct aml_node *node, int type) 1867 { 1868 struct aml_scope *scope; 1869 uint8_t *start, *end; 1870 1871 if (range->type == AML_OBJTYPE_METHOD) { 1872 start = range->v_method.start; 1873 end = range->v_method.end; 1874 } else { 1875 start = range->v_buffer; 1876 end = start + range->length; 1877 if (start == end) 1878 return NULL; 1879 } 1880 scope = acpi_os_malloc(sizeof(struct aml_scope)); 1881 if (scope == NULL) 1882 return NULL; 1883 1884 scope->node = node; 1885 scope->start = start; 1886 scope->end = end; 1887 scope->pos = scope->start; 1888 scope->parent = parent; 1889 scope->type = type; 1890 scope->sc = acpi_softc; 1891 1892 if (parent) 1893 scope->depth = parent->depth+1; 1894 1895 aml_lastscope = scope; 1896 1897 return scope; 1898 } 1899 1900 /* Free a scope object and any children */ 1901 struct aml_scope * 1902 aml_popscope(struct aml_scope *scope) 1903 { 1904 struct aml_scope *nscope; 1905 1906 if (scope == NULL) 1907 return NULL; 1908 1909 nscope = scope->parent; 1910 1911 if (scope->type == AMLOP_METHOD) 1912 aml_delchildren(scope->node); 1913 if (scope->locals) { 1914 aml_freevalue(scope->locals); 1915 acpi_os_free(scope->locals); 1916 scope->locals = NULL; 1917 } 1918 if (scope->args) { 1919 aml_freevalue(scope->args); 1920 acpi_os_free(scope->args); 1921 scope->args = NULL; 1922 } 1923 acpi_os_free(scope); 1924 aml_lastscope = nscope; 1925 1926 return nscope; 1927 } 1928 1929 /* Test AMLOP_MATCH codes */ 1930 int 1931 aml_matchtest(int64_t a, int64_t b, int op) 1932 { 1933 switch (op) { 1934 case AML_MATCH_TR: 1935 return (1); 1936 case AML_MATCH_EQ: 1937 return (a == b); 1938 case AML_MATCH_LT: 1939 return (a < b); 1940 case AML_MATCH_LE: 1941 return (a <= b); 1942 case AML_MATCH_GE: 1943 return (a >= b); 1944 case AML_MATCH_GT: 1945 return (a > b); 1946 } 1947 return (0); 1948 } 1949 1950 /* Search a package for a matching value */ 1951 int 1952 aml_match(struct aml_value *pkg, int index, 1953 int op1, int v1, 1954 int op2, int v2) 1955 { 1956 struct aml_value *tmp; 1957 int flag; 1958 1959 while (index < pkg->length) { 1960 /* Convert package value to integer */ 1961 tmp = aml_convert(pkg->v_package[index], 1962 AML_OBJTYPE_INTEGER, -1); 1963 1964 /* Perform test */ 1965 flag = aml_matchtest(tmp->v_integer, v1, op1) && 1966 aml_matchtest(tmp->v_integer, v2, op2); 1967 aml_delref(&tmp, "xmatch"); 1968 1969 if (flag) 1970 return index; 1971 index++; 1972 } 1973 return -1; 1974 } 1975 1976 /* 1977 * Conversion routines 1978 */ 1979 int64_t 1980 aml_hextoint(const char *str) 1981 { 1982 int64_t v = 0; 1983 char c; 1984 1985 while (*str) { 1986 if (*str >= '0' && *str <= '9') 1987 c = *(str++) - '0'; 1988 else if (*str >= 'a' && *str <= 'f') 1989 c = *(str++) - 'a' + 10; 1990 else if (*str >= 'A' && *str <= 'F') 1991 c = *(str++) - 'A' + 10; 1992 else 1993 break; 1994 v = (v << 4) + c; 1995 } 1996 return v; 1997 1998 } 1999 2000 struct aml_value * 2001 aml_convert(struct aml_value *a, int ctype, int clen) 2002 { 2003 struct aml_value *c = NULL; 2004 2005 /* Object is already this type */ 2006 if (clen == -1) 2007 clen = a->length; 2008 if (a->type == ctype) { 2009 aml_addref(a, "XConvert"); 2010 return a; 2011 } 2012 switch (ctype) { 2013 case AML_OBJTYPE_BUFFER: 2014 dnprintf(10,"convert to buffer\n"); 2015 switch (a->type) { 2016 case AML_OBJTYPE_INTEGER: 2017 c = aml_allocvalue(AML_OBJTYPE_BUFFER, a->length, 2018 &a->v_integer); 2019 break; 2020 case AML_OBJTYPE_STRING: 2021 c = aml_allocvalue(AML_OBJTYPE_BUFFER, a->length, 2022 a->v_string); 2023 break; 2024 } 2025 break; 2026 case AML_OBJTYPE_INTEGER: 2027 dnprintf(10,"convert to integer : %x\n", a->type); 2028 switch (a->type) { 2029 case AML_OBJTYPE_BUFFER: 2030 c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); 2031 memcpy(&c->v_integer, a->v_buffer, 2032 min(a->length, c->length)); 2033 break; 2034 case AML_OBJTYPE_STRING: 2035 c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); 2036 c->v_integer = aml_hextoint(a->v_string); 2037 break; 2038 case AML_OBJTYPE_UNINITIALIZED: 2039 c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); 2040 break; 2041 } 2042 break; 2043 case AML_OBJTYPE_STRING: 2044 case AML_OBJTYPE_HEXSTRING: 2045 case AML_OBJTYPE_DECSTRING: 2046 dnprintf(10,"convert to string\n"); 2047 switch (a->type) { 2048 case AML_OBJTYPE_INTEGER: 2049 c = aml_allocvalue(AML_OBJTYPE_STRING, 20, NULL); 2050 snprintf(c->v_string, c->length, (ctype == AML_OBJTYPE_HEXSTRING) ? 2051 "0x%llx" : "%lld", a->v_integer); 2052 break; 2053 case AML_OBJTYPE_BUFFER: 2054 c = aml_allocvalue(AML_OBJTYPE_STRING, a->length, 2055 a->v_buffer); 2056 break; 2057 case AML_OBJTYPE_STRING: 2058 aml_addref(a, "XConvert"); 2059 return a; 2060 } 2061 break; 2062 } 2063 if (c == NULL) { 2064 #ifndef SMALL_KERNEL 2065 aml_showvalue(a, 0); 2066 #endif 2067 aml_die("Could not convert %x to %x\n", a->type, ctype); 2068 } 2069 return c; 2070 } 2071 2072 int 2073 aml_compare(struct aml_value *a1, struct aml_value *a2, int opcode) 2074 { 2075 int rc = 0; 2076 2077 /* Convert A2 to type of A1 */ 2078 a2 = aml_convert(a2, a1->type, -1); 2079 if (a1->type == AML_OBJTYPE_INTEGER) 2080 rc = aml_evalexpr(a1->v_integer, a2->v_integer, opcode); 2081 else { 2082 /* Perform String/Buffer comparison */ 2083 rc = memcmp(a1->v_buffer, a2->v_buffer, 2084 min(a1->length, a2->length)); 2085 if (rc == 0) { 2086 /* If buffers match, which one is longer */ 2087 rc = a1->length - a2->length; 2088 } 2089 /* Perform comparison against zero */ 2090 rc = aml_evalexpr(rc, 0, opcode); 2091 } 2092 /* Either deletes temp buffer, or decrease refcnt on original A2 */ 2093 aml_delref(&a2, "xcompare"); 2094 return rc; 2095 } 2096 2097 /* Concatenate two objects, returning pointer to new object */ 2098 struct aml_value * 2099 aml_concat(struct aml_value *a1, struct aml_value *a2) 2100 { 2101 struct aml_value *c = NULL; 2102 2103 /* Convert arg2 to type of arg1 */ 2104 a2 = aml_convert(a2, a1->type, -1); 2105 switch (a1->type) { 2106 case AML_OBJTYPE_INTEGER: 2107 c = aml_allocvalue(AML_OBJTYPE_BUFFER, 2108 a1->length + a2->length, NULL); 2109 memcpy(c->v_buffer, &a1->v_integer, a1->length); 2110 memcpy(c->v_buffer+a1->length, &a2->v_integer, a2->length); 2111 break; 2112 case AML_OBJTYPE_BUFFER: 2113 c = aml_allocvalue(AML_OBJTYPE_BUFFER, 2114 a1->length + a2->length, NULL); 2115 memcpy(c->v_buffer, a1->v_buffer, a1->length); 2116 memcpy(c->v_buffer+a1->length, a2->v_buffer, a2->length); 2117 break; 2118 case AML_OBJTYPE_STRING: 2119 c = aml_allocvalue(AML_OBJTYPE_STRING, 2120 a1->length + a2->length, NULL); 2121 memcpy(c->v_string, a1->v_string, a1->length); 2122 memcpy(c->v_string+a1->length, a2->v_string, a2->length); 2123 break; 2124 default: 2125 aml_die("concat type mismatch %d != %d\n", a1->type, a2->type); 2126 break; 2127 } 2128 /* Either deletes temp buffer, or decrease refcnt on original A2 */ 2129 aml_delref(&a2, "xconcat"); 2130 return c; 2131 } 2132 2133 /* Calculate length of Resource Template */ 2134 int 2135 aml_ccrlen(union acpi_resource *rs, void *arg) 2136 { 2137 int *plen = arg; 2138 2139 *plen += AML_CRSLEN(rs); 2140 return (0); 2141 } 2142 2143 /* Concatenate resource templates, returning pointer to new object */ 2144 struct aml_value * 2145 aml_concatres(struct aml_value *a1, struct aml_value *a2) 2146 { 2147 struct aml_value *c; 2148 int l1 = 0, l2 = 0, l3 = 2; 2149 uint8_t a3[] = { 0x79, 0x00 }; 2150 2151 if (a1->type != AML_OBJTYPE_BUFFER || a2->type != AML_OBJTYPE_BUFFER) 2152 aml_die("concatres: not buffers\n"); 2153 2154 /* Walk a1, a2, get length minus end tags, concatenate buffers, add end tag */ 2155 aml_parse_resource(a1, aml_ccrlen, &l1); 2156 aml_parse_resource(a2, aml_ccrlen, &l2); 2157 2158 /* Concatenate buffers, add end tag */ 2159 c = aml_allocvalue(AML_OBJTYPE_BUFFER, l1+l2+l3, NULL); 2160 memcpy(c->v_buffer, a1->v_buffer, l1); 2161 memcpy(c->v_buffer+l1, a2->v_buffer, l2); 2162 memcpy(c->v_buffer+l1+l2, a3, l3); 2163 2164 return c; 2165 } 2166 2167 /* Extract substring from string or buffer */ 2168 struct aml_value * 2169 aml_mid(struct aml_value *src, int index, int length) 2170 { 2171 if (index > src->length) 2172 index = src->length; 2173 if ((index + length) > src->length) 2174 length = src->length - index; 2175 return aml_allocvalue(src->type, length, src->v_buffer + index); 2176 } 2177 2178 /* 2179 * Field I/O utility functions 2180 */ 2181 void aml_createfield(struct aml_value *, int, struct aml_value *, int, int, 2182 struct aml_value *, int, int); 2183 void aml_parsefieldlist(struct aml_scope *, int, int, 2184 struct aml_value *, struct aml_value *, int); 2185 2186 #define GAS_PCI_CFG_SPACE_UNEVAL 0xCC 2187 2188 int 2189 aml_evalhid(struct aml_node *node, struct aml_value *val) 2190 { 2191 if (aml_evalname(acpi_softc, node, "_HID", 0, NULL, val)) 2192 return (-1); 2193 2194 /* Integer _HID: convert to EISA ID */ 2195 if (val->type == AML_OBJTYPE_INTEGER) 2196 _aml_setvalue(val, AML_OBJTYPE_STRING, -1, aml_eisaid(val->v_integer)); 2197 return (0); 2198 } 2199 2200 void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int); 2201 void aml_rwgas(struct aml_value *, int, int, struct aml_value *, int, int); 2202 2203 /* Get PCI address for opregion objects */ 2204 int 2205 aml_rdpciaddr(struct aml_node *pcidev, union amlpci_t *addr) 2206 { 2207 int64_t res; 2208 2209 if (aml_evalinteger(acpi_softc, pcidev, "_ADR", 0, NULL, &res) == 0) { 2210 addr->fun = res & 0xFFFF; 2211 addr->dev = res >> 16; 2212 } 2213 while (pcidev != NULL) { 2214 /* HID device (PCI or PCIE root): eval _BBN */ 2215 if (__aml_search(pcidev, "_HID", 0)) { 2216 if (aml_evalinteger(acpi_softc, pcidev, "_BBN", 0, NULL, &res) == 0) { 2217 addr->bus = res; 2218 break; 2219 } 2220 } 2221 pcidev = pcidev->parent; 2222 } 2223 return (0); 2224 } 2225 2226 /* Read/Write from opregion object */ 2227 void 2228 aml_rwgas(struct aml_value *rgn, int bpos, int blen, struct aml_value *val, int mode, int flag) 2229 { 2230 struct aml_value tmp; 2231 union amlpci_t pi; 2232 void *tbit, *vbit; 2233 int slen, type, sz; 2234 2235 dnprintf(10," %5s %.2x %.8llx %.4x [%s]\n", 2236 mode == ACPI_IOREAD ? "read" : "write", 2237 rgn->v_opregion.iospace, 2238 rgn->v_opregion.iobase + (bpos >> 3), 2239 blen, aml_nodename(rgn->node)); 2240 memset(&tmp, 0, sizeof(tmp)); 2241 pi.addr = rgn->v_opregion.iobase + (bpos >> 3); 2242 if (rgn->v_opregion.iospace == GAS_PCI_CFG_SPACE) 2243 { 2244 /* Get PCI Root Address for this opregion */ 2245 aml_rdpciaddr(rgn->node->parent, &pi); 2246 } 2247 2248 /* Get field access size */ 2249 switch (AML_FIELD_ACCESS(flag)) { 2250 case AML_FIELD_WORDACC: 2251 sz = 2; 2252 break; 2253 case AML_FIELD_DWORDACC: 2254 sz = 4; 2255 break; 2256 case AML_FIELD_QWORDACC: 2257 sz = 8; 2258 break; 2259 default: 2260 sz = 1; 2261 break; 2262 } 2263 2264 tbit = &tmp.v_integer; 2265 vbit = &val->v_integer; 2266 slen = (blen + 7) >> 3; 2267 type = rgn->v_opregion.iospace; 2268 2269 /* Allocate temporary storage */ 2270 if (blen > aml_intlen) { 2271 if (mode == ACPI_IOREAD) { 2272 /* Read from a large field: create buffer */ 2273 _aml_setvalue(val, AML_OBJTYPE_BUFFER, slen, 0); 2274 } else { 2275 /* Write to a large field.. create or convert buffer */ 2276 val = aml_convert(val, AML_OBJTYPE_BUFFER, -1); 2277 } 2278 _aml_setvalue(&tmp, AML_OBJTYPE_BUFFER, slen, 0); 2279 tbit = tmp.v_buffer; 2280 vbit = val->v_buffer; 2281 } else if (mode == ACPI_IOREAD) { 2282 /* Read from a short field.. initialize integer */ 2283 _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); 2284 } else { 2285 /* Write to a short field.. convert to integer */ 2286 val = aml_convert(val, AML_OBJTYPE_INTEGER, -1); 2287 } 2288 2289 if (mode == ACPI_IOREAD) { 2290 /* Read bits from opregion */ 2291 acpi_gasio(acpi_softc, ACPI_IOREAD, type, pi.addr, sz, slen, tbit); 2292 aml_bufcpy(vbit, 0, tbit, bpos & 7, blen); 2293 } else { 2294 /* Write bits to opregion */ 2295 if (val->length < slen) { 2296 dnprintf(0,"writetooshort: %d %d %s\n", val->length, slen, aml_nodename(rgn->node)); 2297 slen = val->length; 2298 } 2299 if (AML_FIELD_UPDATE(flag) == AML_FIELD_PRESERVE && ((bpos|blen) & 7)) { 2300 /* If not aligned and preserve, read existing value */ 2301 acpi_gasio(acpi_softc, ACPI_IOREAD, type, pi.addr, sz, slen, tbit); 2302 } else if (AML_FIELD_UPDATE(flag) == AML_FIELD_WRITEASONES) { 2303 memset(tbit, 0xFF, tmp.length); 2304 } 2305 /* Copy target bits, then write to region */ 2306 aml_bufcpy(tbit, bpos & 7, vbit, 0, blen); 2307 acpi_gasio(acpi_softc, ACPI_IOWRITE, type, pi.addr, sz, slen, tbit); 2308 2309 aml_delref(&val, "fld.write"); 2310 } 2311 aml_freevalue(&tmp); 2312 } 2313 2314 void 2315 aml_rwfield(struct aml_value *fld, int bpos, int blen, struct aml_value *val, int mode) 2316 { 2317 struct aml_value tmp, *ref1, *ref2; 2318 2319 ref2 = fld->v_field.ref2; 2320 ref1 = fld->v_field.ref1; 2321 if (blen > fld->v_field.bitlen) 2322 blen = fld->v_field.bitlen; 2323 2324 aml_lockfield(NULL, fld); 2325 memset(&tmp, 0, sizeof(tmp)); 2326 aml_addref(&tmp, "fld.write"); 2327 if (fld->v_field.type == AMLOP_INDEXFIELD) { 2328 _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, fld->v_field.ref3, 0); 2329 aml_rwfield(ref2, 0, aml_intlen, &tmp, ACPI_IOWRITE); 2330 aml_rwfield(ref1, fld->v_field.bitpos, fld->v_field.bitlen, val, mode); 2331 } else if (fld->v_field.type == AMLOP_BANKFIELD) { 2332 _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, fld->v_field.ref3, 0); 2333 aml_rwfield(ref2, 0, aml_intlen, &tmp, ACPI_IOWRITE); 2334 aml_rwgas(ref1, fld->v_field.bitpos, fld->v_field.bitlen, val, mode, fld->v_field.flags); 2335 } else if (fld->v_field.type == AMLOP_FIELD) { 2336 aml_rwgas(ref1, fld->v_field.bitpos+bpos, blen, val, mode, fld->v_field.flags); 2337 } else if (mode == ACPI_IOREAD) { 2338 /* bufferfield:read */ 2339 _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); 2340 aml_bufcpy(&val->v_integer, 0, ref1->v_buffer, fld->v_field.bitpos, fld->v_field.bitlen); 2341 } else { 2342 /* bufferfield:write */ 2343 val = aml_convert(val, AML_OBJTYPE_INTEGER, -1); 2344 aml_bufcpy(ref1->v_buffer, fld->v_field.bitpos, &val->v_integer, 0, fld->v_field.bitlen); 2345 aml_delref(&val, "wrbuffld"); 2346 } 2347 aml_unlockfield(NULL, fld); 2348 } 2349 2350 /* Create Field Object data index 2351 * AMLOP_FIELD n:OpRegion NULL 2352 * AMLOP_INDEXFIELD n:Field n:Field 2353 * AMLOP_BANKFIELD n:OpRegion n:Field 2354 * AMLOP_CREATEFIELD t:Buffer NULL 2355 * AMLOP_CREATEBITFIELD t:Buffer NULL 2356 * AMLOP_CREATEBYTEFIELD t:Buffer NULL 2357 * AMLOP_CREATEWORDFIELD t:Buffer NULL 2358 * AMLOP_CREATEDWORDFIELD t:Buffer NULL 2359 * AMLOP_CREATEQWORDFIELD t:Buffer NULL 2360 * AMLOP_INDEX t:Buffer NULL 2361 */ 2362 void 2363 aml_createfield(struct aml_value *field, int opcode, 2364 struct aml_value *data, int bpos, int blen, 2365 struct aml_value *index, int indexval, int flags) 2366 { 2367 dnprintf(10, "## %s(%s): %s %.4x-%.4x\n", 2368 aml_mnem(opcode, 0), 2369 blen > aml_intlen ? "BUF" : "INT", 2370 aml_nodename(field->node), bpos, blen); 2371 if (index) { 2372 dnprintf(10, " index:%s:%.2x\n", aml_nodename(index->node), 2373 indexval); 2374 } 2375 dnprintf(10, " data:%s\n", aml_nodename(data->node)); 2376 field->type = (opcode == AMLOP_FIELD || 2377 opcode == AMLOP_INDEXFIELD || 2378 opcode == AMLOP_BANKFIELD) ? 2379 AML_OBJTYPE_FIELDUNIT : 2380 AML_OBJTYPE_BUFFERFIELD; 2381 if (opcode == AMLOP_INDEXFIELD) { 2382 indexval = bpos >> 3; 2383 bpos &= 7; 2384 } 2385 2386 if (field->type == AML_OBJTYPE_BUFFERFIELD && 2387 data->type != AML_OBJTYPE_BUFFER) 2388 data = aml_convert(data, AML_OBJTYPE_BUFFER, -1); 2389 2390 field->v_field.type = opcode; 2391 field->v_field.bitpos = bpos; 2392 field->v_field.bitlen = blen; 2393 field->v_field.ref3 = indexval; 2394 field->v_field.ref2 = index; 2395 field->v_field.ref1 = data; 2396 field->v_field.flags = flags; 2397 2398 /* Increase reference count */ 2399 aml_addref(data, "Field.Data"); 2400 aml_addref(index, "Field.Index"); 2401 } 2402 2403 /* Parse Field/IndexField/BankField scope */ 2404 void 2405 aml_parsefieldlist(struct aml_scope *mscope, int opcode, int flags, 2406 struct aml_value *data, struct aml_value *index, int indexval) 2407 { 2408 struct aml_value *rv; 2409 int bpos, blen; 2410 2411 if (mscope == NULL) 2412 return; 2413 bpos = 0; 2414 while (mscope->pos < mscope->end) { 2415 switch (*mscope->pos) { 2416 case 0x00: // reserved, length 2417 mscope->pos++; 2418 blen = aml_parselength(mscope); 2419 break; 2420 case 0x01: // flags 2421 mscope->pos += 3; 2422 blen = 0; 2423 break; 2424 default: // 4-byte name, length 2425 mscope->pos = aml_parsename(mscope->node, mscope->pos, 2426 &rv, 1); 2427 blen = aml_parselength(mscope); 2428 aml_createfield(rv, opcode, data, bpos, blen, index, 2429 indexval, flags); 2430 aml_delref(&rv, 0); 2431 break; 2432 } 2433 bpos += blen; 2434 } 2435 aml_popscope(mscope); 2436 } 2437 2438 /* 2439 * Mutex/Event utility functions 2440 */ 2441 int acpi_mutex_acquire(struct aml_scope *, struct aml_value *, int); 2442 void acpi_mutex_release(struct aml_scope *, struct aml_value *); 2443 int acpi_event_wait(struct aml_scope *, struct aml_value *, int); 2444 void acpi_event_signal(struct aml_scope *, struct aml_value *); 2445 void acpi_event_reset(struct aml_scope *, struct aml_value *); 2446 2447 int 2448 acpi_mutex_acquire(struct aml_scope *scope, struct aml_value *mtx, 2449 int timeout) 2450 { 2451 int err; 2452 2453 if (mtx->v_mtx.owner == NULL || scope == mtx->v_mtx.owner) { 2454 /* We are now the owner */ 2455 mtx->v_mtx.owner = scope; 2456 if (mtx == aml_global_lock) { 2457 dnprintf(10,"LOCKING GLOBAL\n"); 2458 err = acpi_acquire_global_lock(&acpi_softc->sc_facs->global_lock); 2459 } 2460 dnprintf(5,"%s acquires mutex %s\n", scope->node->name, 2461 mtx->node->name); 2462 return (0); 2463 } else if (timeout == 0) { 2464 return (-1); 2465 } 2466 /* Wait for mutex */ 2467 return (0); 2468 } 2469 2470 void 2471 acpi_mutex_release(struct aml_scope *scope, struct aml_value *mtx) 2472 { 2473 int err; 2474 2475 if (mtx == aml_global_lock) { 2476 dnprintf(10,"UNLOCKING GLOBAL\n"); 2477 err=acpi_release_global_lock(&acpi_softc->sc_facs->global_lock); 2478 } 2479 dnprintf(5, "%s releases mutex %s\n", scope->node->name, 2480 mtx->node->name); 2481 mtx->v_mtx.owner = NULL; 2482 /* Wakeup waiters */ 2483 } 2484 2485 int 2486 acpi_event_wait(struct aml_scope *scope, struct aml_value *evt, int timeout) 2487 { 2488 /* Wait for event to occur; do work in meantime */ 2489 evt->v_evt.state = 0; 2490 while (!evt->v_evt.state) { 2491 if (!acpi_dotask(acpi_softc) && !cold) 2492 tsleep(evt, PWAIT, "acpievt", 1); 2493 else 2494 delay(100); 2495 } 2496 if (evt->v_evt.state == 1) { 2497 /* Object is signaled */ 2498 return (0); 2499 } else if (timeout == 0) { 2500 /* Zero timeout */ 2501 return (-1); 2502 } 2503 /* Wait for timeout or signal */ 2504 return (0); 2505 } 2506 2507 void 2508 acpi_event_signal(struct aml_scope *scope, struct aml_value *evt) 2509 { 2510 evt->v_evt.state = 1; 2511 /* Wakeup waiters */ 2512 } 2513 2514 void 2515 acpi_event_reset(struct aml_scope *scope, struct aml_value *evt) 2516 { 2517 evt->v_evt.state = 0; 2518 } 2519 2520 /* Store result value into an object */ 2521 void 2522 aml_store(struct aml_scope *scope, struct aml_value *lhs , int64_t ival, 2523 struct aml_value *rhs) 2524 { 2525 struct aml_value tmp; 2526 int mlen; 2527 2528 /* Already set */ 2529 if (lhs == rhs || lhs == NULL || lhs->type == AML_OBJTYPE_NOTARGET) { 2530 return; 2531 } 2532 memset(&tmp, 0, sizeof(tmp)); 2533 tmp.refcnt=99; 2534 if (rhs == NULL) { 2535 rhs = _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, ival, NULL); 2536 } 2537 if (rhs->type == AML_OBJTYPE_BUFFERFIELD || 2538 rhs->type == AML_OBJTYPE_FIELDUNIT) { 2539 aml_rwfield(rhs, 0, rhs->v_field.bitlen, &tmp, ACPI_IOREAD); 2540 rhs = &tmp; 2541 } 2542 /* Store to LocalX: free value */ 2543 if (lhs->stack >= AMLOP_LOCAL0 && lhs->stack <= AMLOP_LOCAL7) 2544 aml_freevalue(lhs); 2545 2546 lhs = aml_gettgt(lhs, AMLOP_STORE); 2547 switch (lhs->type) { 2548 case AML_OBJTYPE_UNINITIALIZED: 2549 aml_copyvalue(lhs, rhs); 2550 break; 2551 case AML_OBJTYPE_BUFFERFIELD: 2552 case AML_OBJTYPE_FIELDUNIT: 2553 aml_rwfield(lhs, 0, lhs->v_field.bitlen, rhs, ACPI_IOWRITE); 2554 break; 2555 case AML_OBJTYPE_DEBUGOBJ: 2556 break; 2557 case AML_OBJTYPE_INTEGER: 2558 rhs = aml_convert(rhs, lhs->type, -1); 2559 lhs->v_integer = rhs->v_integer; 2560 aml_delref(&rhs, "store.int"); 2561 break; 2562 case AML_OBJTYPE_BUFFER: 2563 case AML_OBJTYPE_STRING: 2564 rhs = aml_convert(rhs, lhs->type, -1); 2565 if (lhs->length < rhs->length) { 2566 dnprintf(10,"Overrun! %d,%d\n", lhs->length, rhs->length); 2567 aml_freevalue(lhs); 2568 _aml_setvalue(lhs, rhs->type, rhs->length, NULL); 2569 } 2570 mlen = min(lhs->length, rhs->length); 2571 memset(lhs->v_buffer, 0x00, lhs->length); 2572 memcpy(lhs->v_buffer, rhs->v_buffer, mlen); 2573 aml_delref(&rhs, "store.bufstr"); 2574 break; 2575 case AML_OBJTYPE_PACKAGE: 2576 /* Convert to LHS type, copy into LHS */ 2577 if (rhs->type != AML_OBJTYPE_PACKAGE) { 2578 aml_die("Copy non-package into package?"); 2579 } 2580 aml_freevalue(lhs); 2581 aml_copyvalue(lhs, rhs); 2582 break; 2583 default: 2584 aml_die("Store to default type! %x\n", lhs->type); 2585 break; 2586 } 2587 aml_freevalue(&tmp); 2588 } 2589 2590 #ifdef DDB 2591 /* Disassembler routines */ 2592 void aml_disprintf(void *arg, const char *fmt, ...); 2593 2594 void 2595 aml_disprintf(void *arg, const char *fmt, ...) 2596 { 2597 va_list ap; 2598 2599 va_start(ap, fmt); 2600 vprintf(fmt, ap); 2601 va_end(ap); 2602 } 2603 2604 void 2605 aml_disasm(struct aml_scope *scope, int lvl, 2606 void (*dbprintf)(void *, const char *, ...), 2607 void *arg) 2608 { 2609 int pc, opcode; 2610 struct aml_opcode *htab; 2611 uint64_t ival; 2612 struct aml_value *rv, tmp; 2613 uint8_t *end = NULL; 2614 struct aml_scope ms; 2615 char *ch; 2616 char mch[64]; 2617 2618 if (dbprintf == NULL) 2619 dbprintf = aml_disprintf; 2620 2621 pc = aml_pc(scope->pos); 2622 opcode = aml_parseopcode(scope); 2623 htab = aml_findopcode(opcode); 2624 2625 /* Display address + indent */ 2626 if (lvl <= 0x7FFF) { 2627 dbprintf(arg, "%.4x ", pc); 2628 for (pc=0; pc<lvl; pc++) { 2629 dbprintf(arg, " "); 2630 } 2631 } 2632 ch = NULL; 2633 switch (opcode) { 2634 case AMLOP_NAMECHAR: 2635 scope->pos = aml_parsename(scope->node, scope->pos, &rv, 0); 2636 if (rv->type == AML_OBJTYPE_NAMEREF) { 2637 ch = "@@@"; 2638 aml_delref(&rv, "disasm"); 2639 break; 2640 } 2641 /* if this is a method, get arguments */ 2642 strlcpy(mch, aml_nodename(rv->node), sizeof(mch)); 2643 if (rv->type == AML_OBJTYPE_METHOD) { 2644 strlcat(mch, "(", sizeof(mch)); 2645 for (ival=0; ival<AML_METHOD_ARGCOUNT(rv->v_method.flags); ival++) { 2646 strlcat(mch, ival ? ", %z" : "%z", 2647 sizeof(mch)); 2648 } 2649 strlcat(mch, ")", sizeof(mch)); 2650 } 2651 aml_delref(&rv, ""); 2652 ch = mch; 2653 break; 2654 2655 case AMLOP_ZERO: 2656 case AMLOP_ONE: 2657 case AMLOP_ONES: 2658 case AMLOP_LOCAL0: 2659 case AMLOP_LOCAL1: 2660 case AMLOP_LOCAL2: 2661 case AMLOP_LOCAL3: 2662 case AMLOP_LOCAL4: 2663 case AMLOP_LOCAL5: 2664 case AMLOP_LOCAL6: 2665 case AMLOP_LOCAL7: 2666 case AMLOP_ARG0: 2667 case AMLOP_ARG1: 2668 case AMLOP_ARG2: 2669 case AMLOP_ARG3: 2670 case AMLOP_ARG4: 2671 case AMLOP_ARG5: 2672 case AMLOP_ARG6: 2673 case AMLOP_NOP: 2674 case AMLOP_REVISION: 2675 case AMLOP_DEBUG: 2676 case AMLOP_CONTINUE: 2677 case AMLOP_BREAKPOINT: 2678 case AMLOP_BREAK: 2679 ch="%m"; 2680 break; 2681 case AMLOP_BYTEPREFIX: 2682 ch="%b"; 2683 break; 2684 case AMLOP_WORDPREFIX: 2685 ch="%w"; 2686 break; 2687 case AMLOP_DWORDPREFIX: 2688 ch="%d"; 2689 break; 2690 case AMLOP_QWORDPREFIX: 2691 ch="%q"; 2692 break; 2693 case AMLOP_STRINGPREFIX: 2694 ch="%a"; 2695 break; 2696 2697 case AMLOP_INCREMENT: 2698 case AMLOP_DECREMENT: 2699 case AMLOP_LNOT: 2700 case AMLOP_SIZEOF: 2701 case AMLOP_DEREFOF: 2702 case AMLOP_REFOF: 2703 case AMLOP_OBJECTTYPE: 2704 case AMLOP_UNLOAD: 2705 case AMLOP_RELEASE: 2706 case AMLOP_SIGNAL: 2707 case AMLOP_RESET: 2708 case AMLOP_STALL: 2709 case AMLOP_SLEEP: 2710 case AMLOP_RETURN: 2711 ch="%m(%n)"; 2712 break; 2713 case AMLOP_OR: 2714 case AMLOP_ADD: 2715 case AMLOP_AND: 2716 case AMLOP_NAND: 2717 case AMLOP_XOR: 2718 case AMLOP_SHL: 2719 case AMLOP_SHR: 2720 case AMLOP_NOR: 2721 case AMLOP_MOD: 2722 case AMLOP_SUBTRACT: 2723 case AMLOP_MULTIPLY: 2724 case AMLOP_INDEX: 2725 case AMLOP_CONCAT: 2726 case AMLOP_CONCATRES: 2727 case AMLOP_TOSTRING: 2728 ch="%m(%n, %n, %n)"; 2729 break; 2730 case AMLOP_CREATEBYTEFIELD: 2731 case AMLOP_CREATEWORDFIELD: 2732 case AMLOP_CREATEDWORDFIELD: 2733 case AMLOP_CREATEQWORDFIELD: 2734 case AMLOP_CREATEBITFIELD: 2735 ch="%m(%n, %n, %N)"; 2736 break; 2737 case AMLOP_CREATEFIELD: 2738 ch="%m(%n, %n, %n, %N)"; 2739 break; 2740 case AMLOP_DIVIDE: 2741 case AMLOP_MID: 2742 ch="%m(%n, %n, %n, %n)"; 2743 break; 2744 case AMLOP_LAND: 2745 case AMLOP_LOR: 2746 case AMLOP_LNOTEQUAL: 2747 case AMLOP_LLESSEQUAL: 2748 case AMLOP_LLESS: 2749 case AMLOP_LEQUAL: 2750 case AMLOP_LGREATEREQUAL: 2751 case AMLOP_LGREATER: 2752 case AMLOP_NOT: 2753 case AMLOP_FINDSETLEFTBIT: 2754 case AMLOP_FINDSETRIGHTBIT: 2755 case AMLOP_TOINTEGER: 2756 case AMLOP_TOBUFFER: 2757 case AMLOP_TOHEXSTRING: 2758 case AMLOP_TODECSTRING: 2759 case AMLOP_FROMBCD: 2760 case AMLOP_TOBCD: 2761 case AMLOP_WAIT: 2762 case AMLOP_LOAD: 2763 case AMLOP_STORE: 2764 case AMLOP_NOTIFY: 2765 case AMLOP_COPYOBJECT: 2766 ch="%m(%n, %n)"; 2767 break; 2768 case AMLOP_ACQUIRE: 2769 ch = "%m(%n, %w)"; 2770 break; 2771 case AMLOP_CONDREFOF: 2772 ch="%m(%R, %n)"; 2773 break; 2774 case AMLOP_ALIAS: 2775 ch="%m(%n, %N)"; 2776 break; 2777 case AMLOP_NAME: 2778 ch="%m(%N, %n)"; 2779 break; 2780 case AMLOP_EVENT: 2781 ch="%m(%N)"; 2782 break; 2783 case AMLOP_MUTEX: 2784 ch = "%m(%N, %b)"; 2785 break; 2786 case AMLOP_OPREGION: 2787 ch = "%m(%N, %b, %n, %n)"; 2788 break; 2789 case AMLOP_DATAREGION: 2790 ch="%m(%N, %n, %n, %n)"; 2791 break; 2792 case AMLOP_FATAL: 2793 ch = "%m(%b, %d, %n)"; 2794 break; 2795 case AMLOP_IF: 2796 case AMLOP_WHILE: 2797 case AMLOP_SCOPE: 2798 case AMLOP_THERMALZONE: 2799 case AMLOP_VARPACKAGE: 2800 end = aml_parseend(scope); 2801 ch = "%m(%n) {\n%T}"; 2802 break; 2803 case AMLOP_DEVICE: 2804 end = aml_parseend(scope); 2805 ch = "%m(%N) {\n%T}"; 2806 break; 2807 case AMLOP_POWERRSRC: 2808 end = aml_parseend(scope); 2809 ch = "%m(%N, %b, %w) {\n%T}"; 2810 break; 2811 case AMLOP_PROCESSOR: 2812 end = aml_parseend(scope); 2813 ch = "%m(%N, %b, %d, %b) {\n%T}"; 2814 break; 2815 case AMLOP_METHOD: 2816 end = aml_parseend(scope); 2817 ch = "%m(%N, %b) {\n%T}"; 2818 break; 2819 case AMLOP_PACKAGE: 2820 end = aml_parseend(scope); 2821 ch = "%m(%b) {\n%T}"; 2822 break; 2823 case AMLOP_ELSE: 2824 end = aml_parseend(scope); 2825 ch = "%m {\n%T}"; 2826 break; 2827 case AMLOP_BUFFER: 2828 end = aml_parseend(scope); 2829 ch = "%m(%n) { %B }"; 2830 break; 2831 case AMLOP_INDEXFIELD: 2832 end = aml_parseend(scope); 2833 ch = "%m(%n, %n, %b) {\n%F}"; 2834 break; 2835 case AMLOP_BANKFIELD: 2836 end = aml_parseend(scope); 2837 ch = "%m(%n, %n, %n, %b) {\n%F}"; 2838 break; 2839 case AMLOP_FIELD: 2840 end = aml_parseend(scope); 2841 ch = "%m(%n, %b) {\n%F}"; 2842 break; 2843 case AMLOP_MATCH: 2844 ch = "%m(%n, %b, %n, %b, %n, %n)"; 2845 break; 2846 case AMLOP_LOADTABLE: 2847 ch = "%m(%n, %n, %n, %n, %n, %n)"; 2848 break; 2849 default: 2850 aml_die("opcode = %x\n", opcode); 2851 break; 2852 } 2853 2854 /* Parse printable buffer args */ 2855 while (ch && *ch) { 2856 char c; 2857 2858 if (*ch != '%') { 2859 dbprintf(arg,"%c", *(ch++)); 2860 continue; 2861 } 2862 c = *(++ch); 2863 switch (c) { 2864 case 'b': 2865 case 'w': 2866 case 'd': 2867 case 'q': 2868 /* Parse simple object: don't allocate */ 2869 aml_parsesimple(scope, c, &tmp); 2870 dbprintf(arg,"0x%llx", tmp.v_integer); 2871 break; 2872 case 'a': 2873 dbprintf(arg, "\'%s\'", scope->pos); 2874 scope->pos += strlen(scope->pos)+1; 2875 break; 2876 case 'N': 2877 /* Create Name */ 2878 rv = aml_parsesimple(scope, c, NULL); 2879 dbprintf(arg,aml_nodename(rv->node)); 2880 break; 2881 case 'm': 2882 /* display mnemonic */ 2883 dbprintf(arg,htab->mnem); 2884 break; 2885 case 'R': 2886 /* Search name */ 2887 printf("%s", aml_getname(scope->pos)); 2888 scope->pos = aml_parsename(scope->node, scope->pos, 2889 &rv, 0); 2890 aml_delref(&rv, 0); 2891 break; 2892 case 'z': 2893 case 'n': 2894 /* generic arg: recurse */ 2895 aml_disasm(scope, lvl | 0x8000, dbprintf, arg); 2896 break; 2897 case 'B': 2898 /* Buffer */ 2899 scope->pos = end; 2900 break; 2901 case 'F': 2902 /* Scope: Field List */ 2903 memset(&ms, 0, sizeof(ms)); 2904 ms.node = scope->node; 2905 ms.start = scope->pos; 2906 ms.end = end; 2907 ms.pos = ms.start; 2908 ms.type = AMLOP_FIELD; 2909 2910 while (ms.pos < ms.end) { 2911 if (*ms.pos == 0x00) { 2912 ms.pos++; 2913 aml_parselength(&ms); 2914 } else if (*ms.pos == 0x01) { 2915 ms.pos+=3; 2916 } else { 2917 ms.pos = aml_parsename(ms.node, 2918 ms.pos, &rv, 1); 2919 aml_parselength(&ms); 2920 dbprintf(arg," %s\n", 2921 aml_nodename(rv->node)); 2922 aml_delref(&rv, 0); 2923 } 2924 } 2925 2926 /* Display address and closing bracket */ 2927 dbprintf(arg,"%.4x ", aml_pc(scope->pos)); 2928 for (pc=0; pc<(lvl & 0x7FFF); pc++) { 2929 dbprintf(arg," "); 2930 } 2931 scope->pos = end; 2932 break; 2933 case 'T': 2934 /* Scope: Termlist */ 2935 memset(&ms, 0, sizeof(ms)); 2936 ms.node = scope->node; 2937 ms.start = scope->pos; 2938 ms.end = end; 2939 ms.pos = ms.start; 2940 ms.type = AMLOP_SCOPE; 2941 2942 while (ms.pos < ms.end) { 2943 aml_disasm(&ms, (lvl + 1) & 0x7FFF, 2944 dbprintf, arg); 2945 } 2946 2947 /* Display address and closing bracket */ 2948 dbprintf(arg,"%.4x ", aml_pc(scope->pos)); 2949 for (pc=0; pc<(lvl & 0x7FFF); pc++) { 2950 dbprintf(arg," "); 2951 } 2952 scope->pos = end; 2953 break; 2954 } 2955 ch++; 2956 } 2957 if (lvl <= 0x7FFF) { 2958 dbprintf(arg,"\n"); 2959 } 2960 } 2961 #endif /* DDB */ 2962 2963 int aml_busy; 2964 2965 /* Evaluate method or buffervalue objects */ 2966 struct aml_value * 2967 aml_eval(struct aml_scope *scope, struct aml_value *my_ret, int ret_type, 2968 int argc, struct aml_value *argv) 2969 { 2970 struct aml_value *tmp = my_ret; 2971 struct aml_scope *ms; 2972 int idx; 2973 2974 switch (tmp->type) { 2975 case AML_OBJTYPE_NAMEREF: 2976 my_ret = aml_seterror(scope, "Undefined name: %s", 2977 aml_getname(my_ret->v_nameref)); 2978 break; 2979 case AML_OBJTYPE_METHOD: 2980 dnprintf(10,"\n--== Eval Method [%s, %d args] to %c ==--\n", 2981 aml_nodename(tmp->node), 2982 AML_METHOD_ARGCOUNT(tmp->v_method.flags), 2983 ret_type); 2984 ms = aml_pushscope(scope, tmp, tmp->node, AMLOP_METHOD); 2985 2986 /* Parse method arguments */ 2987 for (idx=0; idx<AML_METHOD_ARGCOUNT(tmp->v_method.flags); idx++) { 2988 struct aml_value *sp; 2989 2990 sp = aml_getstack(ms, AMLOP_ARG0+idx); 2991 if (argv) { 2992 aml_copyvalue(sp, &argv[idx]); 2993 } else { 2994 _aml_setvalue(sp, AML_OBJTYPE_OBJREF, AMLOP_ARG0 + idx, 0); 2995 sp->v_objref.ref = aml_parse(scope, 't', "ARGX"); 2996 } 2997 } 2998 #ifdef ACPI_DEBUG 2999 aml_showstack(ms); 3000 #endif 3001 3002 /* Evaluate method scope */ 3003 aml_root.start = tmp->v_method.base; 3004 if (tmp->v_method.fneval != NULL) { 3005 my_ret = tmp->v_method.fneval(ms, NULL); 3006 } else { 3007 aml_parse(ms, 'T', "METHEVAL"); 3008 my_ret = ms->retv; 3009 } 3010 dnprintf(10,"\n--==Finished evaluating method: %s %c\n", 3011 aml_nodename(tmp->node), ret_type); 3012 #ifdef ACPI_DEBUG 3013 aml_showvalue(my_ret, 0); 3014 aml_showstack(ms); 3015 #endif 3016 aml_popscope(ms); 3017 break; 3018 case AML_OBJTYPE_BUFFERFIELD: 3019 case AML_OBJTYPE_FIELDUNIT: 3020 my_ret = aml_allocvalue(0,0,NULL); 3021 dnprintf(20,"quick: Convert Bufferfield to %c 0x%x\n", 3022 ret_type, my_ret); 3023 aml_rwfield(tmp, 0, tmp->v_field.bitlen, my_ret, ACPI_IOREAD); 3024 break; 3025 } 3026 if (ret_type == 'i' && my_ret && my_ret->type != AML_OBJTYPE_INTEGER) { 3027 #ifndef SMALL_KERNEL 3028 aml_showvalue(my_ret, 8-100); 3029 #endif 3030 aml_die("Not Integer"); 3031 } 3032 return my_ret; 3033 } 3034 3035 /* 3036 * The following opcodes produce return values 3037 * TOSTRING -> Str 3038 * TOHEXSTR -> Str 3039 * TODECSTR -> Str 3040 * STRINGPFX -> Str 3041 * BUFFER -> Buf 3042 * CONCATRES -> Buf 3043 * TOBUFFER -> Buf 3044 * MID -> Buf|Str 3045 * CONCAT -> Buf|Str 3046 * PACKAGE -> Pkg 3047 * VARPACKAGE -> Pkg 3048 * LOCALx -> Obj 3049 * ARGx -> Obj 3050 * NAMECHAR -> Obj 3051 * REFOF -> ObjRef 3052 * INDEX -> ObjRef 3053 * DEREFOF -> DataRefObj 3054 * COPYOBJECT -> DataRefObj 3055 * STORE -> DataRefObj 3056 3057 * ZERO -> Int 3058 * ONE -> Int 3059 * ONES -> Int 3060 * REVISION -> Int 3061 * B/W/D/Q -> Int 3062 * OR -> Int 3063 * AND -> Int 3064 * ADD -> Int 3065 * NAND -> Int 3066 * XOR -> Int 3067 * SHL -> Int 3068 * SHR -> Int 3069 * NOR -> Int 3070 * MOD -> Int 3071 * SUBTRACT -> Int 3072 * MULTIPLY -> Int 3073 * DIVIDE -> Int 3074 * NOT -> Int 3075 * TOBCD -> Int 3076 * FROMBCD -> Int 3077 * FSLEFTBIT -> Int 3078 * FSRIGHTBIT -> Int 3079 * INCREMENT -> Int 3080 * DECREMENT -> Int 3081 * TOINTEGER -> Int 3082 * MATCH -> Int 3083 * SIZEOF -> Int 3084 * OBJECTTYPE -> Int 3085 * TIMER -> Int 3086 3087 * CONDREFOF -> Bool 3088 * ACQUIRE -> Bool 3089 * WAIT -> Bool 3090 * LNOT -> Bool 3091 * LAND -> Bool 3092 * LOR -> Bool 3093 * LLESS -> Bool 3094 * LEQUAL -> Bool 3095 * LGREATER -> Bool 3096 * LNOTEQUAL -> Bool 3097 * LLESSEQUAL -> Bool 3098 * LGREATEREQ -> Bool 3099 3100 * LOADTABLE -> DDB 3101 * DEBUG -> Debug 3102 3103 * The following opcodes do not generate a return value: 3104 * NOP 3105 * BREAKPOINT 3106 * RELEASE 3107 * RESET 3108 * SIGNAL 3109 * NAME 3110 * ALIAS 3111 * OPREGION 3112 * DATAREGION 3113 * EVENT 3114 * MUTEX 3115 * SCOPE 3116 * DEVICE 3117 * THERMALZONE 3118 * POWERRSRC 3119 * PROCESSOR 3120 * METHOD 3121 * CREATEFIELD 3122 * CREATEBITFIELD 3123 * CREATEBYTEFIELD 3124 * CREATEWORDFIELD 3125 * CREATEDWORDFIELD 3126 * CREATEQWORDFIELD 3127 * FIELD 3128 * INDEXFIELD 3129 * BANKFIELD 3130 * STALL 3131 * SLEEP 3132 * NOTIFY 3133 * FATAL 3134 * LOAD 3135 * UNLOAD 3136 * IF 3137 * ELSE 3138 * WHILE 3139 * BREAK 3140 * CONTINUE 3141 */ 3142 3143 /* Parse a simple object from AML Bytestream */ 3144 struct aml_value * 3145 aml_parsesimple(struct aml_scope *scope, char ch, struct aml_value *rv) 3146 { 3147 if (rv == NULL) 3148 rv = aml_allocvalue(0,0,NULL); 3149 switch (ch) { 3150 case AML_ARG_REVISION: 3151 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, AML_REVISION, NULL); 3152 break; 3153 case AML_ARG_DEBUG: 3154 _aml_setvalue(rv, AML_OBJTYPE_DEBUGOBJ, 0, NULL); 3155 break; 3156 case AML_ARG_BYTE: 3157 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3158 aml_get8(scope->pos), NULL); 3159 scope->pos += 1; 3160 break; 3161 case AML_ARG_WORD: 3162 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3163 aml_get16(scope->pos), NULL); 3164 scope->pos += 2; 3165 break; 3166 case AML_ARG_DWORD: 3167 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3168 aml_get32(scope->pos), NULL); 3169 scope->pos += 4; 3170 break; 3171 case AML_ARG_QWORD: 3172 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3173 aml_get64(scope->pos), NULL); 3174 scope->pos += 8; 3175 break; 3176 case AML_ARG_STRING: 3177 _aml_setvalue(rv, AML_OBJTYPE_STRING, -1, scope->pos); 3178 scope->pos += rv->length+1; 3179 break; 3180 } 3181 return rv; 3182 } 3183 3184 /* 3185 * Main Opcode Parser/Evaluator 3186 * 3187 * ret_type is expected type for return value 3188 * 'o' = Data Object (Int/Str/Buf/Pkg/Name) 3189 * 'i' = Integer 3190 * 't' = TermArg (Int/Str/Buf/Pkg) 3191 * 'r' = Target (NamedObj/Local/Arg/Null) 3192 * 'S' = SuperName (NamedObj/Local/Arg) 3193 * 'T' = TermList 3194 */ 3195 #define aml_debugger(x) 3196 3197 int maxdp; 3198 3199 struct aml_value * 3200 aml_gettgt(struct aml_value *val, int opcode) 3201 { 3202 while (val && val->type == AML_OBJTYPE_OBJREF) { 3203 val = val->v_objref.ref; 3204 } 3205 return val; 3206 } 3207 3208 struct aml_value * 3209 aml_seterror(struct aml_scope *scope, const char *fmt, ...) 3210 { 3211 va_list ap; 3212 3213 va_start(ap, fmt); 3214 printf("### AML PARSE ERROR (0x%x): ", aml_pc(scope->pos)); 3215 vprintf(fmt, ap); 3216 printf("\n"); 3217 va_end(ap); 3218 3219 while (scope) { 3220 scope->pos = scope->end; 3221 scope = scope->parent; 3222 } 3223 aml_error++; 3224 return aml_allocvalue(AML_OBJTYPE_INTEGER, 0, 0); 3225 } 3226 3227 /* Load new SSDT scope from memory address */ 3228 struct aml_scope * 3229 aml_load(struct acpi_softc *sc, struct aml_scope *scope, 3230 struct aml_value *rgn, struct aml_value *ddb) 3231 { 3232 struct acpi_q *entry; 3233 struct acpi_dsdt *p_ssdt; 3234 struct aml_value tmp; 3235 3236 ddb->type = AML_OBJTYPE_DDBHANDLE; 3237 ddb->v_integer = 0; 3238 3239 memset(&tmp, 0, sizeof(tmp)); 3240 if (rgn->type != AML_OBJTYPE_OPREGION || 3241 rgn->v_opregion.iospace != GAS_SYSTEM_MEMORY) 3242 goto fail; 3243 3244 /* Load SSDT from memory */ 3245 entry = acpi_maptable(sc, rgn->v_opregion.iobase, "SSDT", NULL, NULL, 1); 3246 if (entry == NULL) 3247 goto fail; 3248 3249 dnprintf(10, "%s: loaded SSDT %s @ %llx\n", sc->sc_dev.dv_xname, 3250 aml_nodename(rgn->node), rgn->v_opregion.iobase); 3251 ddb->v_integer = entry->q_id; 3252 3253 p_ssdt = entry->q_table; 3254 tmp.v_buffer = p_ssdt->aml; 3255 tmp.length = p_ssdt->hdr_length - sizeof(p_ssdt->hdr); 3256 3257 return aml_pushscope(scope, &tmp, scope->node, 3258 AMLOP_LOAD); 3259 fail: 3260 printf("%s: unable to load %s\n", sc->sc_dev.dv_xname, 3261 aml_nodename(rgn->node)); 3262 return NULL; 3263 } 3264 3265 struct aml_value * 3266 aml_parse(struct aml_scope *scope, int ret_type, const char *stype) 3267 { 3268 int opcode, idx, pc; 3269 struct aml_opcode *htab; 3270 struct aml_value *opargs[8], *my_ret, *rv; 3271 struct aml_scope *mscope, *iscope; 3272 uint8_t *start, *end; 3273 const char *ch; 3274 int64_t ival; 3275 3276 my_ret = NULL; 3277 if (scope == NULL || scope->pos >= scope->end) { 3278 return NULL; 3279 } 3280 if (odp++ > 125) 3281 panic("depth"); 3282 if (odp > maxdp) { 3283 maxdp = odp; 3284 dnprintf(10, "max depth: %d\n", maxdp); 3285 } 3286 end = NULL; 3287 iscope = scope; 3288 start: 3289 /* --== Stage 0: Get Opcode ==-- */ 3290 start = scope->pos; 3291 pc = aml_pc(scope->pos); 3292 aml_debugger(scope); 3293 3294 opcode = aml_parseopcode(scope); 3295 htab = aml_findopcode(opcode); 3296 if (htab == NULL) { 3297 /* No opcode handler */ 3298 aml_die("Unknown opcode: %.4x @ %.4x", opcode, pc); 3299 } 3300 dnprintf(18,"%.4x %s\n", pc, aml_mnem(opcode, scope->pos)); 3301 3302 /* --== Stage 1: Process opcode arguments ==-- */ 3303 memset(opargs, 0, sizeof(opargs)); 3304 idx = 0; 3305 for (ch = htab->args; *ch; ch++) { 3306 rv = NULL; 3307 switch (*ch) { 3308 case AML_ARG_OBJLEN: 3309 end = aml_parseend(scope); 3310 break; 3311 case AML_ARG_IFELSE: 3312 /* Special Case: IF-ELSE:piTbpT or IF:piT */ 3313 ch = (*end == AMLOP_ELSE && end < scope->end) ? 3314 "-TbpT" : "-T"; 3315 break; 3316 3317 /* Complex arguments */ 3318 case 's': 3319 case 'S': 3320 case AML_ARG_TARGET: 3321 case AML_ARG_TERMOBJ: 3322 case AML_ARG_INTEGER: 3323 if (*ch == 'r' && *scope->pos == AMLOP_ZERO) { 3324 /* Special case: NULL Target */ 3325 rv = aml_allocvalue(AML_OBJTYPE_NOTARGET, 0, NULL); 3326 scope->pos++; 3327 } 3328 else { 3329 rv = aml_parse(scope, *ch, htab->mnem); 3330 if (rv == NULL || aml_error) 3331 goto parse_error; 3332 } 3333 break; 3334 3335 /* Simple arguments */ 3336 case AML_ARG_BUFFER: 3337 case AML_ARG_METHOD: 3338 case AML_ARG_FIELDLIST: 3339 case AML_ARG_TERMOBJLIST: 3340 rv = aml_allocvalue(AML_OBJTYPE_SCOPE, 0, NULL); 3341 rv->v_buffer = scope->pos; 3342 rv->length = end - scope->pos; 3343 scope->pos = end; 3344 break; 3345 case AML_ARG_CONST: 3346 rv = aml_allocvalue(AML_OBJTYPE_INTEGER, 3347 (char)opcode, NULL); 3348 break; 3349 case AML_ARG_CREATENAME: 3350 scope->pos = aml_parsename(scope->node, scope->pos, 3351 &rv, 1); 3352 break; 3353 case AML_ARG_SEARCHNAME: 3354 scope->pos = aml_parsename(scope->node, scope->pos, 3355 &rv, 0); 3356 break; 3357 case AML_ARG_BYTE: 3358 case AML_ARG_WORD: 3359 case AML_ARG_DWORD: 3360 case AML_ARG_QWORD: 3361 case AML_ARG_DEBUG: 3362 case AML_ARG_STRING: 3363 case AML_ARG_REVISION: 3364 rv = aml_parsesimple(scope, *ch, NULL); 3365 break; 3366 case AML_ARG_STKLOCAL: 3367 case AML_ARG_STKARG: 3368 rv = aml_getstack(scope, opcode); 3369 break; 3370 default: 3371 aml_die("Unknown arg type: %c\n", *ch); 3372 break; 3373 } 3374 if (rv != NULL) 3375 opargs[idx++] = rv; 3376 } 3377 3378 /* --== Stage 2: Process opcode ==-- */ 3379 ival = 0; 3380 my_ret = NULL; 3381 mscope = NULL; 3382 switch (opcode) { 3383 case AMLOP_NOP: 3384 case AMLOP_BREAKPOINT: 3385 break; 3386 case AMLOP_LOCAL0: 3387 case AMLOP_LOCAL1: 3388 case AMLOP_LOCAL2: 3389 case AMLOP_LOCAL3: 3390 case AMLOP_LOCAL4: 3391 case AMLOP_LOCAL5: 3392 case AMLOP_LOCAL6: 3393 case AMLOP_LOCAL7: 3394 case AMLOP_ARG0: 3395 case AMLOP_ARG1: 3396 case AMLOP_ARG2: 3397 case AMLOP_ARG3: 3398 case AMLOP_ARG4: 3399 case AMLOP_ARG5: 3400 case AMLOP_ARG6: 3401 my_ret = opargs[0]; 3402 aml_addref(my_ret, htab->mnem); 3403 break; 3404 case AMLOP_NAMECHAR: 3405 /* opargs[0] = named object (node != NULL), or nameref */ 3406 my_ret = opargs[0]; 3407 if (scope->type == AMLOP_PACKAGE) { 3408 /* Special case for package */ 3409 if (my_ret->type == AML_OBJTYPE_NAMEREF) 3410 my_ret = aml_allocvalue(AML_OBJTYPE_STRING, -1, 3411 aml_getname(my_ret->v_nameref)); 3412 else if (my_ret->node) 3413 my_ret = aml_allocvalue(AML_OBJTYPE_STRING, -1, 3414 aml_nodename(my_ret->node)); 3415 break; 3416 } 3417 if (my_ret->type == AML_OBJTYPE_OBJREF) { 3418 my_ret = my_ret->v_objref.ref; 3419 aml_addref(my_ret, "de-alias"); 3420 } 3421 if (ret_type == 'i' || ret_type == 't' || ret_type == 'T') { 3422 /* Return TermArg or Integer: Evaluate object */ 3423 my_ret = aml_eval(scope, my_ret, ret_type, 0, NULL); 3424 } else if (my_ret->type == AML_OBJTYPE_METHOD) { 3425 /* This should only happen with CondRef */ 3426 dnprintf(12,"non-termarg method : %s\n", stype); 3427 aml_addref(my_ret, "zoom"); 3428 } 3429 break; 3430 3431 case AMLOP_ZERO: 3432 case AMLOP_ONE: 3433 case AMLOP_ONES: 3434 case AMLOP_DEBUG: 3435 case AMLOP_REVISION: 3436 case AMLOP_BYTEPREFIX: 3437 case AMLOP_WORDPREFIX: 3438 case AMLOP_DWORDPREFIX: 3439 case AMLOP_QWORDPREFIX: 3440 case AMLOP_STRINGPREFIX: 3441 my_ret = opargs[0]; 3442 break; 3443 3444 case AMLOP_BUFFER: 3445 /* Buffer: iB => Buffer */ 3446 my_ret = aml_allocvalue(AML_OBJTYPE_BUFFER, 3447 opargs[0]->v_integer, NULL); 3448 memcpy(my_ret->v_buffer, opargs[1]->v_buffer, 3449 opargs[1]->length); 3450 break; 3451 case AMLOP_PACKAGE: 3452 case AMLOP_VARPACKAGE: 3453 /* Package/VarPackage: bT/iT => Package */ 3454 my_ret = aml_allocvalue(AML_OBJTYPE_PACKAGE, 3455 opargs[0]->v_integer, 0); 3456 mscope = aml_pushscope(scope, opargs[1], scope->node, 3457 AMLOP_PACKAGE); 3458 3459 /* Recursively parse package contents */ 3460 for (idx=0; idx<my_ret->length; idx++) { 3461 rv = aml_parse(mscope, 'o', "Package"); 3462 if (rv != NULL) { 3463 aml_delref(&my_ret->v_package[idx], "pkginit"); 3464 my_ret->v_package[idx] = rv; 3465 } 3466 } 3467 aml_popscope(mscope); 3468 mscope = NULL; 3469 break; 3470 3471 /* Math/Logical operations */ 3472 case AMLOP_OR: 3473 case AMLOP_ADD: 3474 case AMLOP_AND: 3475 case AMLOP_NAND: 3476 case AMLOP_XOR: 3477 case AMLOP_SHL: 3478 case AMLOP_SHR: 3479 case AMLOP_NOR: 3480 case AMLOP_MOD: 3481 case AMLOP_SUBTRACT: 3482 case AMLOP_MULTIPLY: 3483 /* XXX: iir => I */ 3484 ival = aml_evalexpr(opargs[0]->v_integer, 3485 opargs[1]->v_integer, opcode); 3486 aml_store(scope, opargs[2], ival, NULL); 3487 break; 3488 case AMLOP_DIVIDE: 3489 /* Divide: iirr => I */ 3490 if (opargs[1]->v_integer == 0) { 3491 my_ret = aml_seterror(scope, "Divide by Zero!"); 3492 break; 3493 } 3494 ival = aml_evalexpr(opargs[0]->v_integer, 3495 opargs[1]->v_integer, AMLOP_MOD); 3496 aml_store(scope, opargs[2], ival, NULL); 3497 3498 ival = aml_evalexpr(opargs[0]->v_integer, 3499 opargs[1]->v_integer, AMLOP_DIVIDE); 3500 aml_store(scope, opargs[3], ival, NULL); 3501 break; 3502 case AMLOP_NOT: 3503 case AMLOP_TOBCD: 3504 case AMLOP_FROMBCD: 3505 case AMLOP_FINDSETLEFTBIT: 3506 case AMLOP_FINDSETRIGHTBIT: 3507 /* XXX: ir => I */ 3508 ival = aml_evalexpr(opargs[0]->v_integer, 0, opcode); 3509 aml_store(scope, opargs[1], ival, NULL); 3510 break; 3511 case AMLOP_INCREMENT: 3512 case AMLOP_DECREMENT: 3513 /* Inc/Dec: S => I */ 3514 my_ret = aml_eval(scope, opargs[0], AML_ARG_INTEGER, 0, NULL); 3515 ival = aml_evalexpr(my_ret->v_integer, 1, opcode); 3516 aml_store(scope, opargs[0], ival, NULL); 3517 break; 3518 case AMLOP_LNOT: 3519 /* LNot: i => Bool */ 3520 ival = aml_evalexpr(opargs[0]->v_integer, 0, opcode); 3521 break; 3522 case AMLOP_LOR: 3523 case AMLOP_LAND: 3524 /* XXX: ii => Bool */ 3525 ival = aml_evalexpr(opargs[0]->v_integer, 3526 opargs[1]->v_integer, opcode); 3527 break; 3528 case AMLOP_LLESS: 3529 case AMLOP_LEQUAL: 3530 case AMLOP_LGREATER: 3531 case AMLOP_LNOTEQUAL: 3532 case AMLOP_LLESSEQUAL: 3533 case AMLOP_LGREATEREQUAL: 3534 /* XXX: tt => Bool */ 3535 ival = aml_compare(opargs[0], opargs[1], opcode); 3536 break; 3537 3538 /* Reference/Store operations */ 3539 case AMLOP_CONDREFOF: 3540 /* CondRef: rr => I */ 3541 ival = 0; 3542 if (opargs[0]->node != NULL) { 3543 /* Create Object Reference */ 3544 rv = aml_allocvalue(AML_OBJTYPE_OBJREF, opcode, 3545 opargs[0]); 3546 aml_addref(opargs[0], "CondRef"); 3547 aml_store(scope, opargs[1], 0, rv); 3548 aml_delref(&rv, 0); 3549 3550 /* Mark that we found it */ 3551 ival = -1; 3552 } 3553 break; 3554 case AMLOP_REFOF: 3555 /* RefOf: r => ObjRef */ 3556 my_ret = aml_allocvalue(AML_OBJTYPE_OBJREF, opcode, opargs[0]); 3557 aml_addref(my_ret->v_objref.ref, "RefOf"); 3558 break; 3559 case AMLOP_INDEX: 3560 /* Index: tir => ObjRef */ 3561 idx = opargs[1]->v_integer; 3562 if (idx >= opargs[0]->length || idx < 0) { 3563 #ifndef SMALL_KERNEL 3564 aml_showvalue(opargs[0], 0); 3565 #endif 3566 aml_die("Index out of bounds %d/%d\n", idx, 3567 opargs[0]->length); 3568 } 3569 switch (opargs[0]->type) { 3570 case AML_OBJTYPE_PACKAGE: 3571 /* Don't set opargs[0] to NULL */ 3572 if (ret_type == 't' || ret_type == 'i' || ret_type == 'T') { 3573 my_ret = opargs[0]->v_package[idx]; 3574 aml_addref(my_ret, "Index.Package"); 3575 } else { 3576 my_ret = aml_allocvalue(AML_OBJTYPE_OBJREF, AMLOP_PACKAGE, 3577 opargs[0]->v_package[idx]); 3578 aml_addref(my_ret->v_objref.ref, 3579 "Index.Package"); 3580 } 3581 break; 3582 case AML_OBJTYPE_BUFFER: 3583 case AML_OBJTYPE_STRING: 3584 case AML_OBJTYPE_INTEGER: 3585 rv = aml_convert(opargs[0], AML_OBJTYPE_BUFFER, -1); 3586 if (ret_type == 't' || ret_type == 'i' || ret_type == 'T') { 3587 dnprintf(12,"Index.Buf Term: %d = %x\n", 3588 idx, rv->v_buffer[idx]); 3589 ival = rv->v_buffer[idx]; 3590 } else { 3591 dnprintf(12, "Index.Buf Targ\n"); 3592 my_ret = aml_allocvalue(0,0,NULL); 3593 aml_createfield(my_ret, AMLOP_INDEX, rv, 3594 8 * idx, 8, NULL, 0, AML_FIELD_BYTEACC); 3595 } 3596 aml_delref(&rv, "Index.BufStr"); 3597 break; 3598 default: 3599 aml_die("Unknown index : %x\n", opargs[0]->type); 3600 break; 3601 } 3602 aml_store(scope, opargs[2], ival, my_ret); 3603 break; 3604 case AMLOP_DEREFOF: 3605 /* DerefOf: t:ObjRef => DataRefObj */ 3606 if (opargs[0]->type == AML_OBJTYPE_OBJREF) { 3607 my_ret = opargs[0]->v_objref.ref; 3608 aml_addref(my_ret, "DerefOf"); 3609 } else { 3610 my_ret = opargs[0]; 3611 //aml_addref(my_ret, "DerefOf"); 3612 } 3613 break; 3614 case AMLOP_COPYOBJECT: 3615 /* CopyObject: t:DataRefObj, s:implename => DataRefObj */ 3616 my_ret = opargs[0]; 3617 aml_freevalue(opargs[1]); 3618 aml_copyvalue(opargs[1], opargs[0]); 3619 break; 3620 case AMLOP_STORE: 3621 /* Store: t:DataRefObj, S:upername => DataRefObj */ 3622 my_ret = opargs[0]; 3623 aml_store(scope, opargs[1], 0, opargs[0]); 3624 break; 3625 3626 /* Conversion */ 3627 case AMLOP_TOINTEGER: 3628 /* Source:CData, Result => Integer */ 3629 my_ret = aml_convert(opargs[0], AML_OBJTYPE_INTEGER, -1); 3630 aml_store(scope, opargs[1], 0, my_ret); 3631 break; 3632 case AMLOP_TOBUFFER: 3633 /* Source:CData, Result => Buffer */ 3634 my_ret = aml_convert(opargs[0], AML_OBJTYPE_BUFFER, -1); 3635 aml_store(scope, opargs[1], 0, my_ret); 3636 break; 3637 case AMLOP_TOHEXSTRING: 3638 /* Source:CData, Result => String */ 3639 my_ret = aml_convert(opargs[0], AML_OBJTYPE_HEXSTRING, -1); 3640 aml_store(scope, opargs[1], 0, my_ret); 3641 break; 3642 case AMLOP_TODECSTRING: 3643 /* Source:CData, Result => String */ 3644 my_ret = aml_convert(opargs[0], AML_OBJTYPE_DECSTRING, -1); 3645 aml_store(scope, opargs[1], 0, my_ret); 3646 break; 3647 case AMLOP_TOSTRING: 3648 /* Source:B, Length:I, Result => String */ 3649 my_ret = aml_convert(opargs[0], AML_OBJTYPE_STRING, 3650 opargs[1]->v_integer); 3651 aml_store(scope, opargs[2], 0, my_ret); 3652 break; 3653 case AMLOP_CONCAT: 3654 /* Source1:CData, Source2:CData, Result => CData */ 3655 my_ret = aml_concat(opargs[0], opargs[1]); 3656 aml_store(scope, opargs[2], 0, my_ret); 3657 break; 3658 case AMLOP_CONCATRES: 3659 /* Concat two resource buffers: buf1, buf2, result => Buffer */ 3660 my_ret = aml_concatres(opargs[0], opargs[1]); 3661 aml_store(scope, opargs[2], 0, my_ret); 3662 break; 3663 case AMLOP_MID: 3664 /* Source:BS, Index:I, Length:I, Result => BS */ 3665 my_ret = aml_mid(opargs[0], opargs[1]->v_integer, 3666 opargs[2]->v_integer); 3667 aml_store(scope, opargs[3], 0, my_ret); 3668 break; 3669 case AMLOP_MATCH: 3670 /* Match: Pkg, Op1, Val1, Op2, Val2, Index */ 3671 ival = aml_match(opargs[0], opargs[5]->v_integer, 3672 opargs[1]->v_integer, opargs[2]->v_integer, 3673 opargs[3]->v_integer, opargs[4]->v_integer); 3674 break; 3675 case AMLOP_SIZEOF: 3676 /* Sizeof: S => i */ 3677 rv = aml_gettgt(opargs[0], opcode); 3678 ival = rv->length; 3679 break; 3680 case AMLOP_OBJECTTYPE: 3681 /* ObjectType: S => i */ 3682 rv = aml_gettgt(opargs[0], opcode); 3683 ival = rv->type; 3684 break; 3685 3686 /* Mutex/Event handlers */ 3687 case AMLOP_ACQUIRE: 3688 /* Acquire: Sw => Bool */ 3689 rv = aml_gettgt(opargs[0], opcode); 3690 ival = acpi_mutex_acquire(scope, rv, 3691 opargs[1]->v_integer); 3692 break; 3693 case AMLOP_RELEASE: 3694 /* Release: S */ 3695 rv = aml_gettgt(opargs[0], opcode); 3696 acpi_mutex_release(scope, rv); 3697 break; 3698 case AMLOP_WAIT: 3699 /* Wait: Si => Bool */ 3700 rv = aml_gettgt(opargs[0], opcode); 3701 ival = acpi_event_wait(scope, rv, 3702 opargs[1]->v_integer); 3703 break; 3704 case AMLOP_RESET: 3705 /* Reset: S */ 3706 rv = aml_gettgt(opargs[0], opcode); 3707 acpi_event_reset(scope, rv); 3708 break; 3709 case AMLOP_SIGNAL: 3710 /* Signal: S */ 3711 rv = aml_gettgt(opargs[0], opcode); 3712 acpi_event_signal(scope, rv); 3713 break; 3714 3715 /* Named objects */ 3716 case AMLOP_NAME: 3717 /* Name: Nt */ 3718 rv = opargs[0]; 3719 aml_freevalue(rv); 3720 aml_copyvalue(rv, opargs[1]); 3721 break; 3722 case AMLOP_ALIAS: 3723 /* Alias: nN */ 3724 rv = _aml_setvalue(opargs[1], AML_OBJTYPE_OBJREF, opcode, 0); 3725 rv->v_objref.ref = aml_gettgt(opargs[0], opcode); 3726 aml_addref(rv->v_objref.ref, "Alias"); 3727 break; 3728 case AMLOP_OPREGION: 3729 /* OpRegion: Nbii */ 3730 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_OPREGION, 0, 0); 3731 rv->v_opregion.iospace = opargs[1]->v_integer; 3732 rv->v_opregion.iobase = opargs[2]->v_integer; 3733 rv->v_opregion.iolen = opargs[3]->v_integer; 3734 rv->v_opregion.flag = 0; 3735 break; 3736 case AMLOP_DATAREGION: 3737 /* DataTableRegion: N,t:SigStr,t:OemIDStr,t:OemTableIDStr */ 3738 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_OPREGION, 0, 0); 3739 rv->v_opregion.iospace = GAS_SYSTEM_MEMORY; 3740 rv->v_opregion.iobase = 0; 3741 rv->v_opregion.iolen = 0; 3742 aml_die("AML-DataTableRegion\n"); 3743 break; 3744 case AMLOP_EVENT: 3745 /* Event: N */ 3746 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_EVENT, 0, 0); 3747 rv->v_integer = 0; 3748 break; 3749 case AMLOP_MUTEX: 3750 /* Mutex: Nw */ 3751 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_MUTEX, 0, 0); 3752 rv->v_mtx.synclvl = opargs[1]->v_integer; 3753 break; 3754 case AMLOP_SCOPE: 3755 /* Scope: NT */ 3756 rv = opargs[0]; 3757 if (rv->type == AML_OBJTYPE_NAMEREF) { 3758 printf("Undefined scope: %s\n", aml_getname(rv->v_nameref)); 3759 break; 3760 } 3761 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 3762 break; 3763 case AMLOP_DEVICE: 3764 /* Device: NT */ 3765 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_DEVICE, 0, 0); 3766 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 3767 break; 3768 case AMLOP_THERMALZONE: 3769 /* ThermalZone: NT */ 3770 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_THERMZONE, 0, 0); 3771 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 3772 break; 3773 case AMLOP_POWERRSRC: 3774 /* PowerRsrc: NbwT */ 3775 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_POWERRSRC, 0, 0); 3776 rv->v_powerrsrc.pwr_level = opargs[1]->v_integer; 3777 rv->v_powerrsrc.pwr_order = opargs[2]->v_integer; 3778 mscope = aml_pushscope(scope, opargs[3], rv->node, opcode); 3779 break; 3780 case AMLOP_PROCESSOR: 3781 /* Processor: NbdbT */ 3782 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_PROCESSOR, 0, 0); 3783 rv->v_processor.proc_id = opargs[1]->v_integer; 3784 rv->v_processor.proc_addr = opargs[2]->v_integer; 3785 rv->v_processor.proc_len = opargs[3]->v_integer; 3786 mscope = aml_pushscope(scope, opargs[4], rv->node, opcode); 3787 break; 3788 case AMLOP_METHOD: 3789 /* Method: NbM */ 3790 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_METHOD, 0, 0); 3791 rv->v_method.flags = opargs[1]->v_integer; 3792 rv->v_method.start = opargs[2]->v_buffer; 3793 rv->v_method.end = rv->v_method.start + opargs[2]->length; 3794 rv->v_method.base = aml_root.start; 3795 break; 3796 3797 /* Field objects */ 3798 case AMLOP_CREATEFIELD: 3799 /* Source:B, BitIndex:I, NumBits:I, FieldName */ 3800 rv = _aml_setvalue(opargs[3], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3801 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer, 3802 opargs[2]->v_integer, NULL, 0, 0); 3803 break; 3804 case AMLOP_CREATEBITFIELD: 3805 /* Source:B, BitIndex:I, FieldName */ 3806 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3807 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer, 3808 1, NULL, 0, 0); 3809 break; 3810 case AMLOP_CREATEBYTEFIELD: 3811 /* Source:B, ByteIndex:I, FieldName */ 3812 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3813 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 3814 8, NULL, 0, AML_FIELD_BYTEACC); 3815 break; 3816 case AMLOP_CREATEWORDFIELD: 3817 /* Source:B, ByteIndex:I, FieldName */ 3818 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3819 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 3820 16, NULL, 0, AML_FIELD_WORDACC); 3821 break; 3822 case AMLOP_CREATEDWORDFIELD: 3823 /* Source:B, ByteIndex:I, FieldName */ 3824 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3825 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 3826 32, NULL, 0, AML_FIELD_DWORDACC); 3827 break; 3828 case AMLOP_CREATEQWORDFIELD: 3829 /* Source:B, ByteIndex:I, FieldName */ 3830 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3831 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 3832 64, NULL, 0, AML_FIELD_QWORDACC); 3833 break; 3834 case AMLOP_FIELD: 3835 /* Field: n:OpRegion, b:Flags, F:ieldlist */ 3836 mscope = aml_pushscope(scope, opargs[2], scope->node, opcode); 3837 aml_parsefieldlist(mscope, opcode, opargs[1]->v_integer, 3838 opargs[0], NULL, 0); 3839 mscope = NULL; 3840 break; 3841 case AMLOP_INDEXFIELD: 3842 /* IndexField: n:Index, n:Data, b:Flags, F:ieldlist */ 3843 mscope = aml_pushscope(scope, opargs[3], scope->node, opcode); 3844 aml_parsefieldlist(mscope, opcode, opargs[2]->v_integer, 3845 opargs[1], opargs[0], 0); 3846 mscope = NULL; 3847 break; 3848 case AMLOP_BANKFIELD: 3849 /* BankField: n:OpRegion, n:Field, i:Bank, b:Flags, F:ieldlist */ 3850 mscope = aml_pushscope(scope, opargs[4], scope->node, opcode); 3851 aml_parsefieldlist(mscope, opcode, opargs[3]->v_integer, 3852 opargs[0], opargs[1], opargs[2]->v_integer); 3853 mscope = NULL; 3854 break; 3855 3856 /* Misc functions */ 3857 case AMLOP_STALL: 3858 /* Stall: i */ 3859 acpi_stall(opargs[0]->v_integer); 3860 break; 3861 case AMLOP_SLEEP: 3862 /* Sleep: i */ 3863 acpi_sleep(opargs[0]->v_integer, "amlsleep"); 3864 break; 3865 case AMLOP_NOTIFY: 3866 /* Notify: Si */ 3867 rv = aml_gettgt(opargs[0], opcode); 3868 dnprintf(50,"Notifying: %s %x\n", 3869 aml_nodename(rv->node), 3870 opargs[1]->v_integer); 3871 aml_notify(rv->node, opargs[1]->v_integer); 3872 break; 3873 case AMLOP_TIMER: 3874 /* Timer: => i */ 3875 ival = 0xDEADBEEF; 3876 break; 3877 case AMLOP_FATAL: 3878 /* Fatal: bdi */ 3879 aml_die("AML FATAL ERROR: %x,%x,%x\n", 3880 opargs[0]->v_integer, opargs[1]->v_integer, 3881 opargs[2]->v_integer); 3882 break; 3883 case AMLOP_LOADTABLE: 3884 /* LoadTable(Sig:Str, OEMID:Str, OEMTable:Str, [RootPath:Str], [ParmPath:Str], 3885 [ParmData:DataRefObj]) => DDBHandle */ 3886 aml_die("LoadTable"); 3887 break; 3888 case AMLOP_LOAD: 3889 /* Load(Object:NameString, DDBHandle:SuperName) */ 3890 mscope = aml_load(acpi_softc, scope, opargs[0], opargs[1]); 3891 break; 3892 case AMLOP_UNLOAD: 3893 /* DDBHandle */ 3894 aml_die("Unload"); 3895 break; 3896 3897 /* Control Flow */ 3898 case AMLOP_IF: 3899 /* Arguments: iT or iTbT */ 3900 if (opargs[0]->v_integer) { 3901 dnprintf(10,"parse-if @ %.4x\n", pc); 3902 mscope = aml_pushscope(scope, opargs[1], scope->node, 3903 AMLOP_IF); 3904 } else if (opargs[3] != NULL) { 3905 dnprintf(10,"parse-else @ %.4x\n", pc); 3906 mscope = aml_pushscope(scope, opargs[3], scope->node, 3907 AMLOP_ELSE); 3908 } 3909 break; 3910 case AMLOP_WHILE: 3911 if (opargs[0]->v_integer) { 3912 /* Set parent position to start of WHILE */ 3913 scope->pos = start; 3914 mscope = aml_pushscope(scope, opargs[1], scope->node, 3915 AMLOP_WHILE); 3916 } 3917 break; 3918 case AMLOP_BREAK: 3919 /* Break: Find While Scope parent, mark type as null */ 3920 aml_findscope(scope, AMLOP_WHILE, AMLOP_BREAK); 3921 break; 3922 case AMLOP_CONTINUE: 3923 /* Find Scope.. mark all objects as invalid on way to root */ 3924 aml_findscope(scope, AMLOP_WHILE, AMLOP_CONTINUE); 3925 break; 3926 case AMLOP_RETURN: 3927 mscope = aml_findscope(scope, AMLOP_METHOD, AMLOP_RETURN); 3928 if (mscope->retv) { 3929 aml_die("already allocated\n"); 3930 } 3931 mscope->retv = aml_allocvalue(0,0,NULL); 3932 aml_copyvalue(mscope->retv, opargs[0]); 3933 mscope = NULL; 3934 break; 3935 default: 3936 /* may be set direct result */ 3937 aml_die("Unknown opcode: %x:%s\n", opcode, htab->mnem); 3938 break; 3939 } 3940 if (mscope != NULL) { 3941 /* Change our scope to new scope */ 3942 scope = mscope; 3943 } 3944 if ((ret_type == 'i' || ret_type == 't') && my_ret == NULL) { 3945 dnprintf(10,"quick: %.4x [%s] alloc return integer = 0x%llx\n", 3946 pc, htab->mnem, ival); 3947 my_ret = aml_allocvalue(AML_OBJTYPE_INTEGER, ival, NULL); 3948 } 3949 if (ret_type == 'i' && my_ret && my_ret->type != AML_OBJTYPE_INTEGER) { 3950 dnprintf(10,"quick: %.4x convert to integer %s -> %s\n", 3951 pc, htab->mnem, stype); 3952 my_ret = aml_convert(my_ret, AML_OBJTYPE_INTEGER, -1); 3953 } 3954 if (my_ret != NULL) { 3955 /* Display result */ 3956 dnprintf(20,"quick: %.4x %18s %c %.4x\n", pc, stype, 3957 ret_type, my_ret->stack); 3958 } 3959 3960 /* End opcode: display/free arguments */ 3961 parse_error: 3962 for (idx=0; idx<8; idx++) { 3963 if (opargs[idx] == my_ret) 3964 opargs[idx] = NULL; 3965 aml_delref(&opargs[idx], "oparg"); 3966 } 3967 3968 /* If parsing whole scope and not done, start again */ 3969 if (ret_type == 'T') { 3970 aml_delref(&my_ret, "scope.loop"); 3971 while (scope->pos >= scope->end && scope != iscope) { 3972 /* Pop intermediate scope */ 3973 scope = aml_popscope(scope); 3974 } 3975 if (scope->pos && scope->pos < scope->end) 3976 goto start; 3977 } 3978 3979 odp--; 3980 dnprintf(50, ">>return [%s] %s %c %p\n", aml_nodename(scope->node), 3981 stype, ret_type, my_ret); 3982 3983 return my_ret; 3984 } 3985 3986 int 3987 acpi_parse_aml(struct acpi_softc *sc, u_int8_t *start, u_int32_t length) 3988 { 3989 struct aml_scope *scope; 3990 struct aml_value res; 3991 3992 aml_root.start = start; 3993 memset(&res, 0, sizeof(res)); 3994 res.type = AML_OBJTYPE_SCOPE; 3995 res.length = length; 3996 res.v_buffer = start; 3997 3998 /* Push toplevel scope, parse AML */ 3999 aml_error = 0; 4000 scope = aml_pushscope(NULL, &res, &aml_root, AMLOP_SCOPE); 4001 aml_busy++; 4002 aml_parse(scope, 'T', "TopLevel"); 4003 aml_busy--; 4004 aml_popscope(scope); 4005 4006 if (aml_error) { 4007 printf("error in acpi_parse_aml\n"); 4008 return -1; 4009 } 4010 return (0); 4011 } 4012 4013 /* 4014 * @@@: External API 4015 * 4016 * evaluate an AML node 4017 * Returns a copy of the value in res (must be freed by user) 4018 */ 4019 int 4020 aml_evalnode(struct acpi_softc *sc, struct aml_node *node, 4021 int argc, struct aml_value *argv, struct aml_value *res) 4022 { 4023 struct aml_value *xres; 4024 4025 if (res) 4026 memset(res, 0, sizeof(*res)); 4027 if (node == NULL || node->value == NULL) 4028 return (ACPI_E_BADVALUE); 4029 dnprintf(12,"EVALNODE: %s %d\n", aml_nodename(node), acpi_nalloc); 4030 4031 aml_error = 0; 4032 xres = aml_eval(NULL, node->value, 't', argc, argv); 4033 if (xres) { 4034 if (res) 4035 aml_copyvalue(res, xres); 4036 if (xres != node->value) 4037 aml_delref(&xres, "evalnode"); 4038 } 4039 if (aml_error) { 4040 printf("error evaluating: %s\n", aml_nodename(node)); 4041 return (-1); 4042 } 4043 return (0); 4044 } 4045 4046 /* 4047 * evaluate an AML name 4048 * Returns a copy of the value in res (must be freed by user) 4049 */ 4050 int 4051 aml_evalname(struct acpi_softc *sc, struct aml_node *parent, const char *name, 4052 int argc, struct aml_value *argv, struct aml_value *res) 4053 { 4054 parent = aml_searchname(parent, name); 4055 return aml_evalnode(sc, parent, argc, argv, res); 4056 } 4057 4058 /* 4059 * evaluate an AML integer object 4060 */ 4061 int 4062 aml_evalinteger(struct acpi_softc *sc, struct aml_node *parent, 4063 const char *name, int argc, struct aml_value *argv, int64_t *ival) 4064 { 4065 struct aml_value res; 4066 int rc; 4067 4068 parent = aml_searchname(parent, name); 4069 rc = aml_evalnode(sc, parent, argc, argv, &res); 4070 if (rc == 0) { 4071 *ival = aml_val2int(&res); 4072 aml_freevalue(&res); 4073 } 4074 return rc; 4075 } 4076 4077 /* 4078 * Search for an AML name in namespace.. root only 4079 */ 4080 struct aml_node * 4081 aml_searchname(struct aml_node *root, const void *vname) 4082 { 4083 char *name = (char *)vname; 4084 char nseg[AML_NAMESEG_LEN + 1]; 4085 int i; 4086 4087 dnprintf(25,"Searchname: %s:%s = ", aml_nodename(root), vname); 4088 if (*name == AMLOP_ROOTCHAR) { 4089 root = &aml_root; 4090 name++; 4091 } 4092 while (*name != 0) { 4093 /* Ugh.. we can have short names here: append '_' */ 4094 strlcpy(nseg, "____", sizeof(nseg)); 4095 for (i=0; i < AML_NAMESEG_LEN && *name && *name != '.'; i++) 4096 nseg[i] = *name++; 4097 if (*name == '.') 4098 name++; 4099 root = __aml_search(root, nseg, 0); 4100 } 4101 dnprintf(25,"%p %s\n", root, aml_nodename(root)); 4102 return root; 4103 } 4104 4105 /* 4106 * Search for relative name 4107 */ 4108 struct aml_node * 4109 aml_searchrel(struct aml_node *root, const void *vname) 4110 { 4111 struct aml_node *res; 4112 4113 while (root) { 4114 res = aml_searchname(root, vname); 4115 if (res != NULL) 4116 return res; 4117 root = root->parent; 4118 } 4119 return NULL; 4120 } 4121 4122 #ifndef SMALL_KERNEL 4123 4124 void 4125 acpi_getdevlist(struct acpi_devlist_head *list, struct aml_node *root, 4126 struct aml_value *pkg, int off) 4127 { 4128 struct acpi_devlist *dl; 4129 struct aml_node *node; 4130 int idx; 4131 4132 for (idx=off; idx<pkg->length; idx++) { 4133 node = aml_searchname(root, pkg->v_package[idx]->v_string); 4134 if (node) { 4135 dl = acpi_os_malloc(sizeof(*dl)); 4136 if (dl) { 4137 dl->dev_node = node; 4138 TAILQ_INSERT_TAIL(list, dl, dev_link); 4139 } 4140 } 4141 } 4142 } 4143 4144 void 4145 acpi_freedevlist(struct acpi_devlist_head *list) 4146 { 4147 struct acpi_devlist *dl; 4148 4149 while ((dl = TAILQ_FIRST(list)) != NULL) { 4150 TAILQ_REMOVE(list, dl, dev_link); 4151 acpi_os_free(dl); 4152 } 4153 } 4154 #endif /* SMALL_KERNEL */ 4155