1 /* $OpenBSD: dsdt.c,v 1.196 2012/07/10 15:57:41 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 u_int64_t aml_evalexpr(u_int64_t, u_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 u_int64_t 1103 aml_evalexpr(u_int64_t lhs, u_int64_t rhs, int opcode) 1104 { 1105 u_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, 2229 int mode, int flag) 2230 { 2231 struct aml_value tmp; 2232 union amlpci_t pi; 2233 void *tbit, *vbit; 2234 int slen, type, sz; 2235 2236 dnprintf(10," %5s %.2x %.8llx %.4x [%s]\n", 2237 mode == ACPI_IOREAD ? "read" : "write", 2238 rgn->v_opregion.iospace, 2239 rgn->v_opregion.iobase + (bpos >> 3), 2240 blen, aml_nodename(rgn->node)); 2241 memset(&tmp, 0, sizeof(tmp)); 2242 pi.addr = rgn->v_opregion.iobase + (bpos >> 3); 2243 if (rgn->v_opregion.iospace == GAS_PCI_CFG_SPACE) 2244 { 2245 /* Get PCI Root Address for this opregion */ 2246 aml_rdpciaddr(rgn->node->parent, &pi); 2247 } 2248 2249 /* Get field access size */ 2250 switch (AML_FIELD_ACCESS(flag)) { 2251 case AML_FIELD_WORDACC: 2252 sz = 2; 2253 break; 2254 case AML_FIELD_DWORDACC: 2255 sz = 4; 2256 break; 2257 case AML_FIELD_QWORDACC: 2258 sz = 8; 2259 break; 2260 default: 2261 sz = 1; 2262 break; 2263 } 2264 2265 tbit = &tmp.v_integer; 2266 vbit = &val->v_integer; 2267 slen = (blen + 7) >> 3; 2268 type = rgn->v_opregion.iospace; 2269 2270 /* Allocate temporary storage */ 2271 if (blen > aml_intlen) { 2272 if (mode == ACPI_IOREAD) { 2273 /* Read from a large field: create buffer */ 2274 _aml_setvalue(val, AML_OBJTYPE_BUFFER, slen, 0); 2275 } else { 2276 /* Write to a large field.. create or convert buffer */ 2277 val = aml_convert(val, AML_OBJTYPE_BUFFER, -1); 2278 } 2279 _aml_setvalue(&tmp, AML_OBJTYPE_BUFFER, slen, 0); 2280 tbit = tmp.v_buffer; 2281 vbit = val->v_buffer; 2282 } else if (mode == ACPI_IOREAD) { 2283 /* Read from a short field.. initialize integer */ 2284 _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); 2285 } else { 2286 /* Write to a short field.. convert to integer */ 2287 val = aml_convert(val, AML_OBJTYPE_INTEGER, -1); 2288 } 2289 2290 if (mode == ACPI_IOREAD) { 2291 /* Read bits from opregion */ 2292 acpi_gasio(acpi_softc, ACPI_IOREAD, type, pi.addr, 2293 sz, slen, tbit); 2294 aml_bufcpy(vbit, 0, tbit, bpos & 7, blen); 2295 } else { 2296 /* Write bits to opregion */ 2297 if (val->length < slen) { 2298 dnprintf(0,"writetooshort: %d %d %s\n", 2299 val->length, slen, aml_nodename(rgn->node)); 2300 slen = val->length; 2301 } 2302 if (AML_FIELD_UPDATE(flag) == AML_FIELD_PRESERVE && 2303 ((bpos | blen) & 7)) { 2304 /* If not aligned and preserve, read existing value */ 2305 acpi_gasio(acpi_softc, ACPI_IOREAD, type, pi.addr, 2306 sz, slen, tbit); 2307 } else if (AML_FIELD_UPDATE(flag) == AML_FIELD_WRITEASONES) { 2308 memset(tbit, 0xFF, tmp.length); 2309 } 2310 /* Copy target bits, then write to region */ 2311 aml_bufcpy(tbit, bpos & 7, vbit, 0, blen); 2312 acpi_gasio(acpi_softc, ACPI_IOWRITE, type, pi.addr, 2313 sz, slen, tbit); 2314 2315 aml_delref(&val, "fld.write"); 2316 } 2317 aml_freevalue(&tmp); 2318 } 2319 2320 void 2321 aml_rwfield(struct aml_value *fld, int bpos, int blen, struct aml_value *val, 2322 int mode) 2323 { 2324 struct aml_value tmp, *ref1, *ref2; 2325 2326 ref2 = fld->v_field.ref2; 2327 ref1 = fld->v_field.ref1; 2328 if (blen > fld->v_field.bitlen) 2329 blen = fld->v_field.bitlen; 2330 2331 aml_lockfield(NULL, fld); 2332 memset(&tmp, 0, sizeof(tmp)); 2333 aml_addref(&tmp, "fld.write"); 2334 if (fld->v_field.type == AMLOP_INDEXFIELD) { 2335 _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, fld->v_field.ref3, 0); 2336 aml_rwfield(ref2, 0, aml_intlen, &tmp, ACPI_IOWRITE); 2337 aml_rwfield(ref1, fld->v_field.bitpos, fld->v_field.bitlen, 2338 val, mode); 2339 } else if (fld->v_field.type == AMLOP_BANKFIELD) { 2340 _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, fld->v_field.ref3, 0); 2341 aml_rwfield(ref2, 0, aml_intlen, &tmp, ACPI_IOWRITE); 2342 aml_rwgas(ref1, fld->v_field.bitpos, fld->v_field.bitlen, 2343 val, mode, fld->v_field.flags); 2344 } else if (fld->v_field.type == AMLOP_FIELD) { 2345 aml_rwgas(ref1, fld->v_field.bitpos + bpos, blen, val, mode, 2346 fld->v_field.flags); 2347 } else if (mode == ACPI_IOREAD) { 2348 /* bufferfield:read */ 2349 _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); 2350 aml_bufcpy(&val->v_integer, 0, ref1->v_buffer, 2351 fld->v_field.bitpos, fld->v_field.bitlen); 2352 } else { 2353 /* bufferfield:write */ 2354 val = aml_convert(val, AML_OBJTYPE_INTEGER, -1); 2355 aml_bufcpy(ref1->v_buffer, fld->v_field.bitpos, &val->v_integer, 2356 0, fld->v_field.bitlen); 2357 aml_delref(&val, "wrbuffld"); 2358 } 2359 aml_unlockfield(NULL, fld); 2360 } 2361 2362 /* Create Field Object data index 2363 * AMLOP_FIELD n:OpRegion NULL 2364 * AMLOP_INDEXFIELD n:Field n:Field 2365 * AMLOP_BANKFIELD n:OpRegion n:Field 2366 * AMLOP_CREATEFIELD t:Buffer NULL 2367 * AMLOP_CREATEBITFIELD t:Buffer NULL 2368 * AMLOP_CREATEBYTEFIELD t:Buffer NULL 2369 * AMLOP_CREATEWORDFIELD t:Buffer NULL 2370 * AMLOP_CREATEDWORDFIELD t:Buffer NULL 2371 * AMLOP_CREATEQWORDFIELD t:Buffer NULL 2372 * AMLOP_INDEX t:Buffer NULL 2373 */ 2374 void 2375 aml_createfield(struct aml_value *field, int opcode, 2376 struct aml_value *data, int bpos, int blen, 2377 struct aml_value *index, int indexval, int flags) 2378 { 2379 dnprintf(10, "## %s(%s): %s %.4x-%.4x\n", 2380 aml_mnem(opcode, 0), 2381 blen > aml_intlen ? "BUF" : "INT", 2382 aml_nodename(field->node), bpos, blen); 2383 if (index) { 2384 dnprintf(10, " index:%s:%.2x\n", aml_nodename(index->node), 2385 indexval); 2386 } 2387 dnprintf(10, " data:%s\n", aml_nodename(data->node)); 2388 field->type = (opcode == AMLOP_FIELD || 2389 opcode == AMLOP_INDEXFIELD || 2390 opcode == AMLOP_BANKFIELD) ? 2391 AML_OBJTYPE_FIELDUNIT : 2392 AML_OBJTYPE_BUFFERFIELD; 2393 if (opcode == AMLOP_INDEXFIELD) { 2394 indexval = bpos >> 3; 2395 bpos &= 7; 2396 } 2397 2398 if (field->type == AML_OBJTYPE_BUFFERFIELD && 2399 data->type != AML_OBJTYPE_BUFFER) 2400 data = aml_convert(data, AML_OBJTYPE_BUFFER, -1); 2401 2402 field->v_field.type = opcode; 2403 field->v_field.bitpos = bpos; 2404 field->v_field.bitlen = blen; 2405 field->v_field.ref3 = indexval; 2406 field->v_field.ref2 = index; 2407 field->v_field.ref1 = data; 2408 field->v_field.flags = flags; 2409 2410 /* Increase reference count */ 2411 aml_addref(data, "Field.Data"); 2412 aml_addref(index, "Field.Index"); 2413 } 2414 2415 /* Parse Field/IndexField/BankField scope */ 2416 void 2417 aml_parsefieldlist(struct aml_scope *mscope, int opcode, int flags, 2418 struct aml_value *data, struct aml_value *index, int indexval) 2419 { 2420 struct aml_value *rv; 2421 int bpos, blen; 2422 2423 if (mscope == NULL) 2424 return; 2425 bpos = 0; 2426 while (mscope->pos < mscope->end) { 2427 switch (*mscope->pos) { 2428 case 0x00: // reserved, length 2429 mscope->pos++; 2430 blen = aml_parselength(mscope); 2431 break; 2432 case 0x01: // flags 2433 mscope->pos += 3; 2434 blen = 0; 2435 break; 2436 default: // 4-byte name, length 2437 mscope->pos = aml_parsename(mscope->node, mscope->pos, 2438 &rv, 1); 2439 blen = aml_parselength(mscope); 2440 aml_createfield(rv, opcode, data, bpos, blen, index, 2441 indexval, flags); 2442 aml_delref(&rv, 0); 2443 break; 2444 } 2445 bpos += blen; 2446 } 2447 aml_popscope(mscope); 2448 } 2449 2450 /* 2451 * Mutex/Event utility functions 2452 */ 2453 int acpi_mutex_acquire(struct aml_scope *, struct aml_value *, int); 2454 void acpi_mutex_release(struct aml_scope *, struct aml_value *); 2455 int acpi_event_wait(struct aml_scope *, struct aml_value *, int); 2456 void acpi_event_signal(struct aml_scope *, struct aml_value *); 2457 void acpi_event_reset(struct aml_scope *, struct aml_value *); 2458 2459 int 2460 acpi_mutex_acquire(struct aml_scope *scope, struct aml_value *mtx, 2461 int timeout) 2462 { 2463 int err; 2464 2465 if (mtx->v_mtx.owner == NULL || scope == mtx->v_mtx.owner) { 2466 /* We are now the owner */ 2467 mtx->v_mtx.owner = scope; 2468 if (mtx == aml_global_lock) { 2469 dnprintf(10,"LOCKING GLOBAL\n"); 2470 err = acpi_acquire_global_lock(&acpi_softc->sc_facs->global_lock); 2471 } 2472 dnprintf(5,"%s acquires mutex %s\n", scope->node->name, 2473 mtx->node->name); 2474 return (0); 2475 } else if (timeout == 0) { 2476 return (-1); 2477 } 2478 /* Wait for mutex */ 2479 return (0); 2480 } 2481 2482 void 2483 acpi_mutex_release(struct aml_scope *scope, struct aml_value *mtx) 2484 { 2485 int err; 2486 2487 if (mtx == aml_global_lock) { 2488 dnprintf(10,"UNLOCKING GLOBAL\n"); 2489 err=acpi_release_global_lock(&acpi_softc->sc_facs->global_lock); 2490 } 2491 dnprintf(5, "%s releases mutex %s\n", scope->node->name, 2492 mtx->node->name); 2493 mtx->v_mtx.owner = NULL; 2494 /* Wakeup waiters */ 2495 } 2496 2497 int 2498 acpi_event_wait(struct aml_scope *scope, struct aml_value *evt, int timeout) 2499 { 2500 /* Wait for event to occur; do work in meantime */ 2501 evt->v_evt.state = 0; 2502 while (!evt->v_evt.state) { 2503 if (!acpi_dotask(acpi_softc) && !cold) 2504 tsleep(evt, PWAIT, "acpievt", 1); 2505 else 2506 delay(100); 2507 } 2508 if (evt->v_evt.state == 1) { 2509 /* Object is signaled */ 2510 return (0); 2511 } else if (timeout == 0) { 2512 /* Zero timeout */ 2513 return (-1); 2514 } 2515 /* Wait for timeout or signal */ 2516 return (0); 2517 } 2518 2519 void 2520 acpi_event_signal(struct aml_scope *scope, struct aml_value *evt) 2521 { 2522 evt->v_evt.state = 1; 2523 /* Wakeup waiters */ 2524 } 2525 2526 void 2527 acpi_event_reset(struct aml_scope *scope, struct aml_value *evt) 2528 { 2529 evt->v_evt.state = 0; 2530 } 2531 2532 /* Store result value into an object */ 2533 void 2534 aml_store(struct aml_scope *scope, struct aml_value *lhs , int64_t ival, 2535 struct aml_value *rhs) 2536 { 2537 struct aml_value tmp; 2538 int mlen; 2539 2540 /* Already set */ 2541 if (lhs == rhs || lhs == NULL || lhs->type == AML_OBJTYPE_NOTARGET) { 2542 return; 2543 } 2544 memset(&tmp, 0, sizeof(tmp)); 2545 tmp.refcnt=99; 2546 if (rhs == NULL) { 2547 rhs = _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, ival, NULL); 2548 } 2549 if (rhs->type == AML_OBJTYPE_BUFFERFIELD || 2550 rhs->type == AML_OBJTYPE_FIELDUNIT) { 2551 aml_rwfield(rhs, 0, rhs->v_field.bitlen, &tmp, ACPI_IOREAD); 2552 rhs = &tmp; 2553 } 2554 /* Store to LocalX: free value */ 2555 if (lhs->stack >= AMLOP_LOCAL0 && lhs->stack <= AMLOP_LOCAL7) 2556 aml_freevalue(lhs); 2557 2558 lhs = aml_gettgt(lhs, AMLOP_STORE); 2559 switch (lhs->type) { 2560 case AML_OBJTYPE_UNINITIALIZED: 2561 aml_copyvalue(lhs, rhs); 2562 break; 2563 case AML_OBJTYPE_BUFFERFIELD: 2564 case AML_OBJTYPE_FIELDUNIT: 2565 aml_rwfield(lhs, 0, lhs->v_field.bitlen, rhs, ACPI_IOWRITE); 2566 break; 2567 case AML_OBJTYPE_DEBUGOBJ: 2568 break; 2569 case AML_OBJTYPE_INTEGER: 2570 rhs = aml_convert(rhs, lhs->type, -1); 2571 lhs->v_integer = rhs->v_integer; 2572 aml_delref(&rhs, "store.int"); 2573 break; 2574 case AML_OBJTYPE_BUFFER: 2575 case AML_OBJTYPE_STRING: 2576 rhs = aml_convert(rhs, lhs->type, -1); 2577 if (lhs->length < rhs->length) { 2578 dnprintf(10, "Overrun! %d,%d\n", 2579 lhs->length, rhs->length); 2580 aml_freevalue(lhs); 2581 _aml_setvalue(lhs, rhs->type, rhs->length, NULL); 2582 } 2583 mlen = min(lhs->length, rhs->length); 2584 memset(lhs->v_buffer, 0x00, lhs->length); 2585 memcpy(lhs->v_buffer, rhs->v_buffer, mlen); 2586 aml_delref(&rhs, "store.bufstr"); 2587 break; 2588 case AML_OBJTYPE_PACKAGE: 2589 /* Convert to LHS type, copy into LHS */ 2590 if (rhs->type != AML_OBJTYPE_PACKAGE) { 2591 aml_die("Copy non-package into package?"); 2592 } 2593 aml_freevalue(lhs); 2594 aml_copyvalue(lhs, rhs); 2595 break; 2596 default: 2597 aml_die("Store to default type! %x\n", lhs->type); 2598 break; 2599 } 2600 aml_freevalue(&tmp); 2601 } 2602 2603 #ifdef DDB 2604 /* Disassembler routines */ 2605 void aml_disprintf(void *arg, const char *fmt, ...); 2606 2607 void 2608 aml_disprintf(void *arg, const char *fmt, ...) 2609 { 2610 va_list ap; 2611 2612 va_start(ap, fmt); 2613 vprintf(fmt, ap); 2614 va_end(ap); 2615 } 2616 2617 void 2618 aml_disasm(struct aml_scope *scope, int lvl, 2619 void (*dbprintf)(void *, const char *, ...), 2620 void *arg) 2621 { 2622 int pc, opcode; 2623 struct aml_opcode *htab; 2624 uint64_t ival; 2625 struct aml_value *rv, tmp; 2626 uint8_t *end = NULL; 2627 struct aml_scope ms; 2628 char *ch; 2629 char mch[64]; 2630 2631 if (dbprintf == NULL) 2632 dbprintf = aml_disprintf; 2633 2634 pc = aml_pc(scope->pos); 2635 opcode = aml_parseopcode(scope); 2636 htab = aml_findopcode(opcode); 2637 2638 /* Display address + indent */ 2639 if (lvl <= 0x7FFF) { 2640 dbprintf(arg, "%.4x ", pc); 2641 for (pc=0; pc<lvl; pc++) { 2642 dbprintf(arg, " "); 2643 } 2644 } 2645 ch = NULL; 2646 switch (opcode) { 2647 case AMLOP_NAMECHAR: 2648 scope->pos = aml_parsename(scope->node, scope->pos, &rv, 0); 2649 if (rv->type == AML_OBJTYPE_NAMEREF) { 2650 ch = "@@@"; 2651 aml_delref(&rv, "disasm"); 2652 break; 2653 } 2654 /* if this is a method, get arguments */ 2655 strlcpy(mch, aml_nodename(rv->node), sizeof(mch)); 2656 if (rv->type == AML_OBJTYPE_METHOD) { 2657 strlcat(mch, "(", sizeof(mch)); 2658 for (ival=0; 2659 ival < AML_METHOD_ARGCOUNT(rv->v_method.flags); 2660 ival++) { 2661 strlcat(mch, ival ? ", %z" : "%z", 2662 sizeof(mch)); 2663 } 2664 strlcat(mch, ")", sizeof(mch)); 2665 } 2666 aml_delref(&rv, ""); 2667 ch = mch; 2668 break; 2669 2670 case AMLOP_ZERO: 2671 case AMLOP_ONE: 2672 case AMLOP_ONES: 2673 case AMLOP_LOCAL0: 2674 case AMLOP_LOCAL1: 2675 case AMLOP_LOCAL2: 2676 case AMLOP_LOCAL3: 2677 case AMLOP_LOCAL4: 2678 case AMLOP_LOCAL5: 2679 case AMLOP_LOCAL6: 2680 case AMLOP_LOCAL7: 2681 case AMLOP_ARG0: 2682 case AMLOP_ARG1: 2683 case AMLOP_ARG2: 2684 case AMLOP_ARG3: 2685 case AMLOP_ARG4: 2686 case AMLOP_ARG5: 2687 case AMLOP_ARG6: 2688 case AMLOP_NOP: 2689 case AMLOP_REVISION: 2690 case AMLOP_DEBUG: 2691 case AMLOP_CONTINUE: 2692 case AMLOP_BREAKPOINT: 2693 case AMLOP_BREAK: 2694 ch="%m"; 2695 break; 2696 case AMLOP_BYTEPREFIX: 2697 ch="%b"; 2698 break; 2699 case AMLOP_WORDPREFIX: 2700 ch="%w"; 2701 break; 2702 case AMLOP_DWORDPREFIX: 2703 ch="%d"; 2704 break; 2705 case AMLOP_QWORDPREFIX: 2706 ch="%q"; 2707 break; 2708 case AMLOP_STRINGPREFIX: 2709 ch="%a"; 2710 break; 2711 2712 case AMLOP_INCREMENT: 2713 case AMLOP_DECREMENT: 2714 case AMLOP_LNOT: 2715 case AMLOP_SIZEOF: 2716 case AMLOP_DEREFOF: 2717 case AMLOP_REFOF: 2718 case AMLOP_OBJECTTYPE: 2719 case AMLOP_UNLOAD: 2720 case AMLOP_RELEASE: 2721 case AMLOP_SIGNAL: 2722 case AMLOP_RESET: 2723 case AMLOP_STALL: 2724 case AMLOP_SLEEP: 2725 case AMLOP_RETURN: 2726 ch="%m(%n)"; 2727 break; 2728 case AMLOP_OR: 2729 case AMLOP_ADD: 2730 case AMLOP_AND: 2731 case AMLOP_NAND: 2732 case AMLOP_XOR: 2733 case AMLOP_SHL: 2734 case AMLOP_SHR: 2735 case AMLOP_NOR: 2736 case AMLOP_MOD: 2737 case AMLOP_SUBTRACT: 2738 case AMLOP_MULTIPLY: 2739 case AMLOP_INDEX: 2740 case AMLOP_CONCAT: 2741 case AMLOP_CONCATRES: 2742 case AMLOP_TOSTRING: 2743 ch="%m(%n, %n, %n)"; 2744 break; 2745 case AMLOP_CREATEBYTEFIELD: 2746 case AMLOP_CREATEWORDFIELD: 2747 case AMLOP_CREATEDWORDFIELD: 2748 case AMLOP_CREATEQWORDFIELD: 2749 case AMLOP_CREATEBITFIELD: 2750 ch="%m(%n, %n, %N)"; 2751 break; 2752 case AMLOP_CREATEFIELD: 2753 ch="%m(%n, %n, %n, %N)"; 2754 break; 2755 case AMLOP_DIVIDE: 2756 case AMLOP_MID: 2757 ch="%m(%n, %n, %n, %n)"; 2758 break; 2759 case AMLOP_LAND: 2760 case AMLOP_LOR: 2761 case AMLOP_LNOTEQUAL: 2762 case AMLOP_LLESSEQUAL: 2763 case AMLOP_LLESS: 2764 case AMLOP_LEQUAL: 2765 case AMLOP_LGREATEREQUAL: 2766 case AMLOP_LGREATER: 2767 case AMLOP_NOT: 2768 case AMLOP_FINDSETLEFTBIT: 2769 case AMLOP_FINDSETRIGHTBIT: 2770 case AMLOP_TOINTEGER: 2771 case AMLOP_TOBUFFER: 2772 case AMLOP_TOHEXSTRING: 2773 case AMLOP_TODECSTRING: 2774 case AMLOP_FROMBCD: 2775 case AMLOP_TOBCD: 2776 case AMLOP_WAIT: 2777 case AMLOP_LOAD: 2778 case AMLOP_STORE: 2779 case AMLOP_NOTIFY: 2780 case AMLOP_COPYOBJECT: 2781 ch="%m(%n, %n)"; 2782 break; 2783 case AMLOP_ACQUIRE: 2784 ch = "%m(%n, %w)"; 2785 break; 2786 case AMLOP_CONDREFOF: 2787 ch="%m(%R, %n)"; 2788 break; 2789 case AMLOP_ALIAS: 2790 ch="%m(%n, %N)"; 2791 break; 2792 case AMLOP_NAME: 2793 ch="%m(%N, %n)"; 2794 break; 2795 case AMLOP_EVENT: 2796 ch="%m(%N)"; 2797 break; 2798 case AMLOP_MUTEX: 2799 ch = "%m(%N, %b)"; 2800 break; 2801 case AMLOP_OPREGION: 2802 ch = "%m(%N, %b, %n, %n)"; 2803 break; 2804 case AMLOP_DATAREGION: 2805 ch="%m(%N, %n, %n, %n)"; 2806 break; 2807 case AMLOP_FATAL: 2808 ch = "%m(%b, %d, %n)"; 2809 break; 2810 case AMLOP_IF: 2811 case AMLOP_WHILE: 2812 case AMLOP_SCOPE: 2813 case AMLOP_THERMALZONE: 2814 case AMLOP_VARPACKAGE: 2815 end = aml_parseend(scope); 2816 ch = "%m(%n) {\n%T}"; 2817 break; 2818 case AMLOP_DEVICE: 2819 end = aml_parseend(scope); 2820 ch = "%m(%N) {\n%T}"; 2821 break; 2822 case AMLOP_POWERRSRC: 2823 end = aml_parseend(scope); 2824 ch = "%m(%N, %b, %w) {\n%T}"; 2825 break; 2826 case AMLOP_PROCESSOR: 2827 end = aml_parseend(scope); 2828 ch = "%m(%N, %b, %d, %b) {\n%T}"; 2829 break; 2830 case AMLOP_METHOD: 2831 end = aml_parseend(scope); 2832 ch = "%m(%N, %b) {\n%T}"; 2833 break; 2834 case AMLOP_PACKAGE: 2835 end = aml_parseend(scope); 2836 ch = "%m(%b) {\n%T}"; 2837 break; 2838 case AMLOP_ELSE: 2839 end = aml_parseend(scope); 2840 ch = "%m {\n%T}"; 2841 break; 2842 case AMLOP_BUFFER: 2843 end = aml_parseend(scope); 2844 ch = "%m(%n) { %B }"; 2845 break; 2846 case AMLOP_INDEXFIELD: 2847 end = aml_parseend(scope); 2848 ch = "%m(%n, %n, %b) {\n%F}"; 2849 break; 2850 case AMLOP_BANKFIELD: 2851 end = aml_parseend(scope); 2852 ch = "%m(%n, %n, %n, %b) {\n%F}"; 2853 break; 2854 case AMLOP_FIELD: 2855 end = aml_parseend(scope); 2856 ch = "%m(%n, %b) {\n%F}"; 2857 break; 2858 case AMLOP_MATCH: 2859 ch = "%m(%n, %b, %n, %b, %n, %n)"; 2860 break; 2861 case AMLOP_LOADTABLE: 2862 ch = "%m(%n, %n, %n, %n, %n, %n)"; 2863 break; 2864 default: 2865 aml_die("opcode = %x\n", opcode); 2866 break; 2867 } 2868 2869 /* Parse printable buffer args */ 2870 while (ch && *ch) { 2871 char c; 2872 2873 if (*ch != '%') { 2874 dbprintf(arg,"%c", *(ch++)); 2875 continue; 2876 } 2877 c = *(++ch); 2878 switch (c) { 2879 case 'b': 2880 case 'w': 2881 case 'd': 2882 case 'q': 2883 /* Parse simple object: don't allocate */ 2884 aml_parsesimple(scope, c, &tmp); 2885 dbprintf(arg,"0x%llx", tmp.v_integer); 2886 break; 2887 case 'a': 2888 dbprintf(arg, "\'%s\'", scope->pos); 2889 scope->pos += strlen(scope->pos)+1; 2890 break; 2891 case 'N': 2892 /* Create Name */ 2893 rv = aml_parsesimple(scope, c, NULL); 2894 dbprintf(arg,aml_nodename(rv->node)); 2895 break; 2896 case 'm': 2897 /* display mnemonic */ 2898 dbprintf(arg,htab->mnem); 2899 break; 2900 case 'R': 2901 /* Search name */ 2902 printf("%s", aml_getname(scope->pos)); 2903 scope->pos = aml_parsename(scope->node, scope->pos, 2904 &rv, 0); 2905 aml_delref(&rv, 0); 2906 break; 2907 case 'z': 2908 case 'n': 2909 /* generic arg: recurse */ 2910 aml_disasm(scope, lvl | 0x8000, dbprintf, arg); 2911 break; 2912 case 'B': 2913 /* Buffer */ 2914 scope->pos = end; 2915 break; 2916 case 'F': 2917 /* Scope: Field List */ 2918 memset(&ms, 0, sizeof(ms)); 2919 ms.node = scope->node; 2920 ms.start = scope->pos; 2921 ms.end = end; 2922 ms.pos = ms.start; 2923 ms.type = AMLOP_FIELD; 2924 2925 while (ms.pos < ms.end) { 2926 if (*ms.pos == 0x00) { 2927 ms.pos++; 2928 aml_parselength(&ms); 2929 } else if (*ms.pos == 0x01) { 2930 ms.pos+=3; 2931 } else { 2932 ms.pos = aml_parsename(ms.node, 2933 ms.pos, &rv, 1); 2934 aml_parselength(&ms); 2935 dbprintf(arg," %s\n", 2936 aml_nodename(rv->node)); 2937 aml_delref(&rv, 0); 2938 } 2939 } 2940 2941 /* Display address and closing bracket */ 2942 dbprintf(arg,"%.4x ", aml_pc(scope->pos)); 2943 for (pc=0; pc<(lvl & 0x7FFF); pc++) { 2944 dbprintf(arg," "); 2945 } 2946 scope->pos = end; 2947 break; 2948 case 'T': 2949 /* Scope: Termlist */ 2950 memset(&ms, 0, sizeof(ms)); 2951 ms.node = scope->node; 2952 ms.start = scope->pos; 2953 ms.end = end; 2954 ms.pos = ms.start; 2955 ms.type = AMLOP_SCOPE; 2956 2957 while (ms.pos < ms.end) { 2958 aml_disasm(&ms, (lvl + 1) & 0x7FFF, 2959 dbprintf, arg); 2960 } 2961 2962 /* Display address and closing bracket */ 2963 dbprintf(arg,"%.4x ", aml_pc(scope->pos)); 2964 for (pc=0; pc<(lvl & 0x7FFF); pc++) { 2965 dbprintf(arg," "); 2966 } 2967 scope->pos = end; 2968 break; 2969 } 2970 ch++; 2971 } 2972 if (lvl <= 0x7FFF) { 2973 dbprintf(arg,"\n"); 2974 } 2975 } 2976 #endif /* DDB */ 2977 2978 int aml_busy; 2979 2980 /* Evaluate method or buffervalue objects */ 2981 struct aml_value * 2982 aml_eval(struct aml_scope *scope, struct aml_value *my_ret, int ret_type, 2983 int argc, struct aml_value *argv) 2984 { 2985 struct aml_value *tmp = my_ret; 2986 struct aml_scope *ms; 2987 int idx; 2988 2989 switch (tmp->type) { 2990 case AML_OBJTYPE_NAMEREF: 2991 my_ret = aml_seterror(scope, "Undefined name: %s", 2992 aml_getname(my_ret->v_nameref)); 2993 break; 2994 case AML_OBJTYPE_METHOD: 2995 dnprintf(10,"\n--== Eval Method [%s, %d args] to %c ==--\n", 2996 aml_nodename(tmp->node), 2997 AML_METHOD_ARGCOUNT(tmp->v_method.flags), 2998 ret_type); 2999 ms = aml_pushscope(scope, tmp, tmp->node, AMLOP_METHOD); 3000 3001 /* Parse method arguments */ 3002 for (idx=0; idx<AML_METHOD_ARGCOUNT(tmp->v_method.flags); idx++) { 3003 struct aml_value *sp; 3004 3005 sp = aml_getstack(ms, AMLOP_ARG0+idx); 3006 if (argv) { 3007 aml_copyvalue(sp, &argv[idx]); 3008 } else { 3009 _aml_setvalue(sp, AML_OBJTYPE_OBJREF, AMLOP_ARG0 + idx, 0); 3010 sp->v_objref.ref = aml_parse(scope, 't', "ARGX"); 3011 } 3012 } 3013 #ifdef ACPI_DEBUG 3014 aml_showstack(ms); 3015 #endif 3016 3017 /* Evaluate method scope */ 3018 aml_root.start = tmp->v_method.base; 3019 if (tmp->v_method.fneval != NULL) { 3020 my_ret = tmp->v_method.fneval(ms, NULL); 3021 } else { 3022 aml_parse(ms, 'T', "METHEVAL"); 3023 my_ret = ms->retv; 3024 } 3025 dnprintf(10,"\n--==Finished evaluating method: %s %c\n", 3026 aml_nodename(tmp->node), ret_type); 3027 #ifdef ACPI_DEBUG 3028 aml_showvalue(my_ret, 0); 3029 aml_showstack(ms); 3030 #endif 3031 aml_popscope(ms); 3032 break; 3033 case AML_OBJTYPE_BUFFERFIELD: 3034 case AML_OBJTYPE_FIELDUNIT: 3035 my_ret = aml_allocvalue(0,0,NULL); 3036 dnprintf(20,"quick: Convert Bufferfield to %c 0x%x\n", 3037 ret_type, my_ret); 3038 aml_rwfield(tmp, 0, tmp->v_field.bitlen, my_ret, ACPI_IOREAD); 3039 break; 3040 } 3041 if (ret_type == 'i' && my_ret && my_ret->type != AML_OBJTYPE_INTEGER) { 3042 #ifndef SMALL_KERNEL 3043 aml_showvalue(my_ret, 8-100); 3044 #endif 3045 aml_die("Not Integer"); 3046 } 3047 return my_ret; 3048 } 3049 3050 /* 3051 * The following opcodes produce return values 3052 * TOSTRING -> Str 3053 * TOHEXSTR -> Str 3054 * TODECSTR -> Str 3055 * STRINGPFX -> Str 3056 * BUFFER -> Buf 3057 * CONCATRES -> Buf 3058 * TOBUFFER -> Buf 3059 * MID -> Buf|Str 3060 * CONCAT -> Buf|Str 3061 * PACKAGE -> Pkg 3062 * VARPACKAGE -> Pkg 3063 * LOCALx -> Obj 3064 * ARGx -> Obj 3065 * NAMECHAR -> Obj 3066 * REFOF -> ObjRef 3067 * INDEX -> ObjRef 3068 * DEREFOF -> DataRefObj 3069 * COPYOBJECT -> DataRefObj 3070 * STORE -> DataRefObj 3071 3072 * ZERO -> Int 3073 * ONE -> Int 3074 * ONES -> Int 3075 * REVISION -> Int 3076 * B/W/D/Q -> Int 3077 * OR -> Int 3078 * AND -> Int 3079 * ADD -> Int 3080 * NAND -> Int 3081 * XOR -> Int 3082 * SHL -> Int 3083 * SHR -> Int 3084 * NOR -> Int 3085 * MOD -> Int 3086 * SUBTRACT -> Int 3087 * MULTIPLY -> Int 3088 * DIVIDE -> Int 3089 * NOT -> Int 3090 * TOBCD -> Int 3091 * FROMBCD -> Int 3092 * FSLEFTBIT -> Int 3093 * FSRIGHTBIT -> Int 3094 * INCREMENT -> Int 3095 * DECREMENT -> Int 3096 * TOINTEGER -> Int 3097 * MATCH -> Int 3098 * SIZEOF -> Int 3099 * OBJECTTYPE -> Int 3100 * TIMER -> Int 3101 3102 * CONDREFOF -> Bool 3103 * ACQUIRE -> Bool 3104 * WAIT -> Bool 3105 * LNOT -> Bool 3106 * LAND -> Bool 3107 * LOR -> Bool 3108 * LLESS -> Bool 3109 * LEQUAL -> Bool 3110 * LGREATER -> Bool 3111 * LNOTEQUAL -> Bool 3112 * LLESSEQUAL -> Bool 3113 * LGREATEREQ -> Bool 3114 3115 * LOADTABLE -> DDB 3116 * DEBUG -> Debug 3117 3118 * The following opcodes do not generate a return value: 3119 * NOP 3120 * BREAKPOINT 3121 * RELEASE 3122 * RESET 3123 * SIGNAL 3124 * NAME 3125 * ALIAS 3126 * OPREGION 3127 * DATAREGION 3128 * EVENT 3129 * MUTEX 3130 * SCOPE 3131 * DEVICE 3132 * THERMALZONE 3133 * POWERRSRC 3134 * PROCESSOR 3135 * METHOD 3136 * CREATEFIELD 3137 * CREATEBITFIELD 3138 * CREATEBYTEFIELD 3139 * CREATEWORDFIELD 3140 * CREATEDWORDFIELD 3141 * CREATEQWORDFIELD 3142 * FIELD 3143 * INDEXFIELD 3144 * BANKFIELD 3145 * STALL 3146 * SLEEP 3147 * NOTIFY 3148 * FATAL 3149 * LOAD 3150 * UNLOAD 3151 * IF 3152 * ELSE 3153 * WHILE 3154 * BREAK 3155 * CONTINUE 3156 */ 3157 3158 /* Parse a simple object from AML Bytestream */ 3159 struct aml_value * 3160 aml_parsesimple(struct aml_scope *scope, char ch, struct aml_value *rv) 3161 { 3162 if (rv == NULL) 3163 rv = aml_allocvalue(0,0,NULL); 3164 switch (ch) { 3165 case AML_ARG_REVISION: 3166 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, AML_REVISION, NULL); 3167 break; 3168 case AML_ARG_DEBUG: 3169 _aml_setvalue(rv, AML_OBJTYPE_DEBUGOBJ, 0, NULL); 3170 break; 3171 case AML_ARG_BYTE: 3172 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3173 aml_get8(scope->pos), NULL); 3174 scope->pos += 1; 3175 break; 3176 case AML_ARG_WORD: 3177 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3178 aml_get16(scope->pos), NULL); 3179 scope->pos += 2; 3180 break; 3181 case AML_ARG_DWORD: 3182 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3183 aml_get32(scope->pos), NULL); 3184 scope->pos += 4; 3185 break; 3186 case AML_ARG_QWORD: 3187 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3188 aml_get64(scope->pos), NULL); 3189 scope->pos += 8; 3190 break; 3191 case AML_ARG_STRING: 3192 _aml_setvalue(rv, AML_OBJTYPE_STRING, -1, scope->pos); 3193 scope->pos += rv->length+1; 3194 break; 3195 } 3196 return rv; 3197 } 3198 3199 /* 3200 * Main Opcode Parser/Evaluator 3201 * 3202 * ret_type is expected type for return value 3203 * 'o' = Data Object (Int/Str/Buf/Pkg/Name) 3204 * 'i' = Integer 3205 * 't' = TermArg (Int/Str/Buf/Pkg) 3206 * 'r' = Target (NamedObj/Local/Arg/Null) 3207 * 'S' = SuperName (NamedObj/Local/Arg) 3208 * 'T' = TermList 3209 */ 3210 #define aml_debugger(x) 3211 3212 int maxdp; 3213 3214 struct aml_value * 3215 aml_gettgt(struct aml_value *val, int opcode) 3216 { 3217 while (val && val->type == AML_OBJTYPE_OBJREF) { 3218 val = val->v_objref.ref; 3219 } 3220 return val; 3221 } 3222 3223 struct aml_value * 3224 aml_seterror(struct aml_scope *scope, const char *fmt, ...) 3225 { 3226 va_list ap; 3227 3228 va_start(ap, fmt); 3229 printf("### AML PARSE ERROR (0x%x): ", aml_pc(scope->pos)); 3230 vprintf(fmt, ap); 3231 printf("\n"); 3232 va_end(ap); 3233 3234 while (scope) { 3235 scope->pos = scope->end; 3236 scope = scope->parent; 3237 } 3238 aml_error++; 3239 return aml_allocvalue(AML_OBJTYPE_INTEGER, 0, 0); 3240 } 3241 3242 /* Load new SSDT scope from memory address */ 3243 struct aml_scope * 3244 aml_load(struct acpi_softc *sc, struct aml_scope *scope, 3245 struct aml_value *rgn, struct aml_value *ddb) 3246 { 3247 struct acpi_q *entry; 3248 struct acpi_dsdt *p_ssdt; 3249 struct aml_value tmp; 3250 3251 ddb->type = AML_OBJTYPE_DDBHANDLE; 3252 ddb->v_integer = 0; 3253 3254 memset(&tmp, 0, sizeof(tmp)); 3255 if (rgn->type != AML_OBJTYPE_OPREGION || 3256 rgn->v_opregion.iospace != GAS_SYSTEM_MEMORY) 3257 goto fail; 3258 3259 /* Load SSDT from memory */ 3260 entry = acpi_maptable(sc, rgn->v_opregion.iobase, "SSDT", NULL, NULL, 1); 3261 if (entry == NULL) 3262 goto fail; 3263 3264 dnprintf(10, "%s: loaded SSDT %s @ %llx\n", sc->sc_dev.dv_xname, 3265 aml_nodename(rgn->node), rgn->v_opregion.iobase); 3266 ddb->v_integer = entry->q_id; 3267 3268 p_ssdt = entry->q_table; 3269 tmp.v_buffer = p_ssdt->aml; 3270 tmp.length = p_ssdt->hdr_length - sizeof(p_ssdt->hdr); 3271 3272 return aml_pushscope(scope, &tmp, scope->node, 3273 AMLOP_LOAD); 3274 fail: 3275 printf("%s: unable to load %s\n", sc->sc_dev.dv_xname, 3276 aml_nodename(rgn->node)); 3277 return NULL; 3278 } 3279 3280 struct aml_value * 3281 aml_parse(struct aml_scope *scope, int ret_type, const char *stype) 3282 { 3283 int opcode, idx, pc; 3284 struct aml_opcode *htab; 3285 struct aml_value *opargs[8], *my_ret, *rv; 3286 struct aml_scope *mscope, *iscope; 3287 uint8_t *start, *end; 3288 const char *ch; 3289 int64_t ival; 3290 3291 my_ret = NULL; 3292 if (scope == NULL || scope->pos >= scope->end) { 3293 return NULL; 3294 } 3295 if (odp++ > 125) 3296 panic("depth"); 3297 if (odp > maxdp) { 3298 maxdp = odp; 3299 dnprintf(10, "max depth: %d\n", maxdp); 3300 } 3301 end = NULL; 3302 iscope = scope; 3303 start: 3304 /* --== Stage 0: Get Opcode ==-- */ 3305 start = scope->pos; 3306 pc = aml_pc(scope->pos); 3307 aml_debugger(scope); 3308 3309 opcode = aml_parseopcode(scope); 3310 htab = aml_findopcode(opcode); 3311 if (htab == NULL) { 3312 /* No opcode handler */ 3313 aml_die("Unknown opcode: %.4x @ %.4x", opcode, pc); 3314 } 3315 dnprintf(18,"%.4x %s\n", pc, aml_mnem(opcode, scope->pos)); 3316 3317 /* --== Stage 1: Process opcode arguments ==-- */ 3318 memset(opargs, 0, sizeof(opargs)); 3319 idx = 0; 3320 for (ch = htab->args; *ch; ch++) { 3321 rv = NULL; 3322 switch (*ch) { 3323 case AML_ARG_OBJLEN: 3324 end = aml_parseend(scope); 3325 break; 3326 case AML_ARG_IFELSE: 3327 /* Special Case: IF-ELSE:piTbpT or IF:piT */ 3328 ch = (*end == AMLOP_ELSE && end < scope->end) ? 3329 "-TbpT" : "-T"; 3330 break; 3331 3332 /* Complex arguments */ 3333 case 's': 3334 case 'S': 3335 case AML_ARG_TARGET: 3336 case AML_ARG_TERMOBJ: 3337 case AML_ARG_INTEGER: 3338 if (*ch == 'r' && *scope->pos == AMLOP_ZERO) { 3339 /* Special case: NULL Target */ 3340 rv = aml_allocvalue(AML_OBJTYPE_NOTARGET, 0, NULL); 3341 scope->pos++; 3342 } 3343 else { 3344 rv = aml_parse(scope, *ch, htab->mnem); 3345 if (rv == NULL || aml_error) 3346 goto parse_error; 3347 } 3348 break; 3349 3350 /* Simple arguments */ 3351 case AML_ARG_BUFFER: 3352 case AML_ARG_METHOD: 3353 case AML_ARG_FIELDLIST: 3354 case AML_ARG_TERMOBJLIST: 3355 rv = aml_allocvalue(AML_OBJTYPE_SCOPE, 0, NULL); 3356 rv->v_buffer = scope->pos; 3357 rv->length = end - scope->pos; 3358 scope->pos = end; 3359 break; 3360 case AML_ARG_CONST: 3361 rv = aml_allocvalue(AML_OBJTYPE_INTEGER, 3362 (char)opcode, NULL); 3363 break; 3364 case AML_ARG_CREATENAME: 3365 scope->pos = aml_parsename(scope->node, scope->pos, 3366 &rv, 1); 3367 break; 3368 case AML_ARG_SEARCHNAME: 3369 scope->pos = aml_parsename(scope->node, scope->pos, 3370 &rv, 0); 3371 break; 3372 case AML_ARG_BYTE: 3373 case AML_ARG_WORD: 3374 case AML_ARG_DWORD: 3375 case AML_ARG_QWORD: 3376 case AML_ARG_DEBUG: 3377 case AML_ARG_STRING: 3378 case AML_ARG_REVISION: 3379 rv = aml_parsesimple(scope, *ch, NULL); 3380 break; 3381 case AML_ARG_STKLOCAL: 3382 case AML_ARG_STKARG: 3383 rv = aml_getstack(scope, opcode); 3384 break; 3385 default: 3386 aml_die("Unknown arg type: %c\n", *ch); 3387 break; 3388 } 3389 if (rv != NULL) 3390 opargs[idx++] = rv; 3391 } 3392 3393 /* --== Stage 2: Process opcode ==-- */ 3394 ival = 0; 3395 my_ret = NULL; 3396 mscope = NULL; 3397 switch (opcode) { 3398 case AMLOP_NOP: 3399 case AMLOP_BREAKPOINT: 3400 break; 3401 case AMLOP_LOCAL0: 3402 case AMLOP_LOCAL1: 3403 case AMLOP_LOCAL2: 3404 case AMLOP_LOCAL3: 3405 case AMLOP_LOCAL4: 3406 case AMLOP_LOCAL5: 3407 case AMLOP_LOCAL6: 3408 case AMLOP_LOCAL7: 3409 case AMLOP_ARG0: 3410 case AMLOP_ARG1: 3411 case AMLOP_ARG2: 3412 case AMLOP_ARG3: 3413 case AMLOP_ARG4: 3414 case AMLOP_ARG5: 3415 case AMLOP_ARG6: 3416 my_ret = opargs[0]; 3417 aml_addref(my_ret, htab->mnem); 3418 break; 3419 case AMLOP_NAMECHAR: 3420 /* opargs[0] = named object (node != NULL), or nameref */ 3421 my_ret = opargs[0]; 3422 if (scope->type == AMLOP_PACKAGE) { 3423 /* Special case for package */ 3424 if (my_ret->type == AML_OBJTYPE_NAMEREF) 3425 my_ret = aml_allocvalue(AML_OBJTYPE_STRING, -1, 3426 aml_getname(my_ret->v_nameref)); 3427 else if (my_ret->node) 3428 my_ret = aml_allocvalue(AML_OBJTYPE_STRING, -1, 3429 aml_nodename(my_ret->node)); 3430 break; 3431 } 3432 if (my_ret->type == AML_OBJTYPE_OBJREF) { 3433 my_ret = my_ret->v_objref.ref; 3434 aml_addref(my_ret, "de-alias"); 3435 } 3436 if (ret_type == 'i' || ret_type == 't' || ret_type == 'T') { 3437 /* Return TermArg or Integer: Evaluate object */ 3438 my_ret = aml_eval(scope, my_ret, ret_type, 0, NULL); 3439 } else if (my_ret->type == AML_OBJTYPE_METHOD) { 3440 /* This should only happen with CondRef */ 3441 dnprintf(12,"non-termarg method : %s\n", stype); 3442 aml_addref(my_ret, "zoom"); 3443 } 3444 break; 3445 3446 case AMLOP_ZERO: 3447 case AMLOP_ONE: 3448 case AMLOP_ONES: 3449 case AMLOP_DEBUG: 3450 case AMLOP_REVISION: 3451 case AMLOP_BYTEPREFIX: 3452 case AMLOP_WORDPREFIX: 3453 case AMLOP_DWORDPREFIX: 3454 case AMLOP_QWORDPREFIX: 3455 case AMLOP_STRINGPREFIX: 3456 my_ret = opargs[0]; 3457 break; 3458 3459 case AMLOP_BUFFER: 3460 /* Buffer: iB => Buffer */ 3461 my_ret = aml_allocvalue(AML_OBJTYPE_BUFFER, 3462 opargs[0]->v_integer, NULL); 3463 memcpy(my_ret->v_buffer, opargs[1]->v_buffer, 3464 opargs[1]->length); 3465 break; 3466 case AMLOP_PACKAGE: 3467 case AMLOP_VARPACKAGE: 3468 /* Package/VarPackage: bT/iT => Package */ 3469 my_ret = aml_allocvalue(AML_OBJTYPE_PACKAGE, 3470 opargs[0]->v_integer, 0); 3471 mscope = aml_pushscope(scope, opargs[1], scope->node, 3472 AMLOP_PACKAGE); 3473 3474 /* Recursively parse package contents */ 3475 for (idx=0; idx<my_ret->length; idx++) { 3476 rv = aml_parse(mscope, 'o', "Package"); 3477 if (rv != NULL) { 3478 aml_delref(&my_ret->v_package[idx], "pkginit"); 3479 my_ret->v_package[idx] = rv; 3480 } 3481 } 3482 aml_popscope(mscope); 3483 mscope = NULL; 3484 break; 3485 3486 /* Math/Logical operations */ 3487 case AMLOP_OR: 3488 case AMLOP_ADD: 3489 case AMLOP_AND: 3490 case AMLOP_NAND: 3491 case AMLOP_XOR: 3492 case AMLOP_SHL: 3493 case AMLOP_SHR: 3494 case AMLOP_NOR: 3495 case AMLOP_MOD: 3496 case AMLOP_SUBTRACT: 3497 case AMLOP_MULTIPLY: 3498 /* XXX: iir => I */ 3499 ival = aml_evalexpr(opargs[0]->v_integer, 3500 opargs[1]->v_integer, opcode); 3501 aml_store(scope, opargs[2], ival, NULL); 3502 break; 3503 case AMLOP_DIVIDE: 3504 /* Divide: iirr => I */ 3505 if (opargs[1]->v_integer == 0) { 3506 my_ret = aml_seterror(scope, "Divide by Zero!"); 3507 break; 3508 } 3509 ival = aml_evalexpr(opargs[0]->v_integer, 3510 opargs[1]->v_integer, AMLOP_MOD); 3511 aml_store(scope, opargs[2], ival, NULL); 3512 3513 ival = aml_evalexpr(opargs[0]->v_integer, 3514 opargs[1]->v_integer, AMLOP_DIVIDE); 3515 aml_store(scope, opargs[3], ival, NULL); 3516 break; 3517 case AMLOP_NOT: 3518 case AMLOP_TOBCD: 3519 case AMLOP_FROMBCD: 3520 case AMLOP_FINDSETLEFTBIT: 3521 case AMLOP_FINDSETRIGHTBIT: 3522 /* XXX: ir => I */ 3523 ival = aml_evalexpr(opargs[0]->v_integer, 0, opcode); 3524 aml_store(scope, opargs[1], ival, NULL); 3525 break; 3526 case AMLOP_INCREMENT: 3527 case AMLOP_DECREMENT: 3528 /* Inc/Dec: S => I */ 3529 my_ret = aml_eval(scope, opargs[0], AML_ARG_INTEGER, 0, NULL); 3530 ival = aml_evalexpr(my_ret->v_integer, 1, opcode); 3531 aml_store(scope, opargs[0], ival, NULL); 3532 break; 3533 case AMLOP_LNOT: 3534 /* LNot: i => Bool */ 3535 ival = aml_evalexpr(opargs[0]->v_integer, 0, opcode); 3536 break; 3537 case AMLOP_LOR: 3538 case AMLOP_LAND: 3539 /* XXX: ii => Bool */ 3540 ival = aml_evalexpr(opargs[0]->v_integer, 3541 opargs[1]->v_integer, opcode); 3542 break; 3543 case AMLOP_LLESS: 3544 case AMLOP_LEQUAL: 3545 case AMLOP_LGREATER: 3546 case AMLOP_LNOTEQUAL: 3547 case AMLOP_LLESSEQUAL: 3548 case AMLOP_LGREATEREQUAL: 3549 /* XXX: tt => Bool */ 3550 ival = aml_compare(opargs[0], opargs[1], opcode); 3551 break; 3552 3553 /* Reference/Store operations */ 3554 case AMLOP_CONDREFOF: 3555 /* CondRef: rr => I */ 3556 ival = 0; 3557 if (opargs[0]->node != NULL) { 3558 /* Create Object Reference */ 3559 rv = aml_allocvalue(AML_OBJTYPE_OBJREF, opcode, 3560 opargs[0]); 3561 aml_addref(opargs[0], "CondRef"); 3562 aml_store(scope, opargs[1], 0, rv); 3563 aml_delref(&rv, 0); 3564 3565 /* Mark that we found it */ 3566 ival = -1; 3567 } 3568 break; 3569 case AMLOP_REFOF: 3570 /* RefOf: r => ObjRef */ 3571 my_ret = aml_allocvalue(AML_OBJTYPE_OBJREF, opcode, opargs[0]); 3572 aml_addref(my_ret->v_objref.ref, "RefOf"); 3573 break; 3574 case AMLOP_INDEX: 3575 /* Index: tir => ObjRef */ 3576 idx = opargs[1]->v_integer; 3577 if (idx >= opargs[0]->length || idx < 0) { 3578 #ifndef SMALL_KERNEL 3579 aml_showvalue(opargs[0], 0); 3580 #endif 3581 aml_die("Index out of bounds %d/%d\n", idx, 3582 opargs[0]->length); 3583 } 3584 switch (opargs[0]->type) { 3585 case AML_OBJTYPE_PACKAGE: 3586 /* Don't set opargs[0] to NULL */ 3587 if (ret_type == 't' || ret_type == 'i' || ret_type == 'T') { 3588 my_ret = opargs[0]->v_package[idx]; 3589 aml_addref(my_ret, "Index.Package"); 3590 } else { 3591 my_ret = aml_allocvalue(AML_OBJTYPE_OBJREF, AMLOP_PACKAGE, 3592 opargs[0]->v_package[idx]); 3593 aml_addref(my_ret->v_objref.ref, 3594 "Index.Package"); 3595 } 3596 break; 3597 case AML_OBJTYPE_BUFFER: 3598 case AML_OBJTYPE_STRING: 3599 case AML_OBJTYPE_INTEGER: 3600 rv = aml_convert(opargs[0], AML_OBJTYPE_BUFFER, -1); 3601 if (ret_type == 't' || ret_type == 'i' || ret_type == 'T') { 3602 dnprintf(12,"Index.Buf Term: %d = %x\n", 3603 idx, rv->v_buffer[idx]); 3604 ival = rv->v_buffer[idx]; 3605 } else { 3606 dnprintf(12, "Index.Buf Targ\n"); 3607 my_ret = aml_allocvalue(0,0,NULL); 3608 aml_createfield(my_ret, AMLOP_INDEX, rv, 3609 8 * idx, 8, NULL, 0, AML_FIELD_BYTEACC); 3610 } 3611 aml_delref(&rv, "Index.BufStr"); 3612 break; 3613 default: 3614 aml_die("Unknown index : %x\n", opargs[0]->type); 3615 break; 3616 } 3617 aml_store(scope, opargs[2], ival, my_ret); 3618 break; 3619 case AMLOP_DEREFOF: 3620 /* DerefOf: t:ObjRef => DataRefObj */ 3621 if (opargs[0]->type == AML_OBJTYPE_OBJREF) { 3622 my_ret = opargs[0]->v_objref.ref; 3623 aml_addref(my_ret, "DerefOf"); 3624 } else { 3625 my_ret = opargs[0]; 3626 //aml_addref(my_ret, "DerefOf"); 3627 } 3628 break; 3629 case AMLOP_COPYOBJECT: 3630 /* CopyObject: t:DataRefObj, s:implename => DataRefObj */ 3631 my_ret = opargs[0]; 3632 aml_freevalue(opargs[1]); 3633 aml_copyvalue(opargs[1], opargs[0]); 3634 break; 3635 case AMLOP_STORE: 3636 /* Store: t:DataRefObj, S:upername => DataRefObj */ 3637 my_ret = opargs[0]; 3638 aml_store(scope, opargs[1], 0, opargs[0]); 3639 break; 3640 3641 /* Conversion */ 3642 case AMLOP_TOINTEGER: 3643 /* Source:CData, Result => Integer */ 3644 my_ret = aml_convert(opargs[0], AML_OBJTYPE_INTEGER, -1); 3645 aml_store(scope, opargs[1], 0, my_ret); 3646 break; 3647 case AMLOP_TOBUFFER: 3648 /* Source:CData, Result => Buffer */ 3649 my_ret = aml_convert(opargs[0], AML_OBJTYPE_BUFFER, -1); 3650 aml_store(scope, opargs[1], 0, my_ret); 3651 break; 3652 case AMLOP_TOHEXSTRING: 3653 /* Source:CData, Result => String */ 3654 my_ret = aml_convert(opargs[0], AML_OBJTYPE_HEXSTRING, -1); 3655 aml_store(scope, opargs[1], 0, my_ret); 3656 break; 3657 case AMLOP_TODECSTRING: 3658 /* Source:CData, Result => String */ 3659 my_ret = aml_convert(opargs[0], AML_OBJTYPE_DECSTRING, -1); 3660 aml_store(scope, opargs[1], 0, my_ret); 3661 break; 3662 case AMLOP_TOSTRING: 3663 /* Source:B, Length:I, Result => String */ 3664 my_ret = aml_convert(opargs[0], AML_OBJTYPE_STRING, 3665 opargs[1]->v_integer); 3666 aml_store(scope, opargs[2], 0, my_ret); 3667 break; 3668 case AMLOP_CONCAT: 3669 /* Source1:CData, Source2:CData, Result => CData */ 3670 my_ret = aml_concat(opargs[0], opargs[1]); 3671 aml_store(scope, opargs[2], 0, my_ret); 3672 break; 3673 case AMLOP_CONCATRES: 3674 /* Concat two resource buffers: buf1, buf2, result => Buffer */ 3675 my_ret = aml_concatres(opargs[0], opargs[1]); 3676 aml_store(scope, opargs[2], 0, my_ret); 3677 break; 3678 case AMLOP_MID: 3679 /* Source:BS, Index:I, Length:I, Result => BS */ 3680 my_ret = aml_mid(opargs[0], opargs[1]->v_integer, 3681 opargs[2]->v_integer); 3682 aml_store(scope, opargs[3], 0, my_ret); 3683 break; 3684 case AMLOP_MATCH: 3685 /* Match: Pkg, Op1, Val1, Op2, Val2, Index */ 3686 ival = aml_match(opargs[0], opargs[5]->v_integer, 3687 opargs[1]->v_integer, opargs[2]->v_integer, 3688 opargs[3]->v_integer, opargs[4]->v_integer); 3689 break; 3690 case AMLOP_SIZEOF: 3691 /* Sizeof: S => i */ 3692 rv = aml_gettgt(opargs[0], opcode); 3693 ival = rv->length; 3694 break; 3695 case AMLOP_OBJECTTYPE: 3696 /* ObjectType: S => i */ 3697 rv = aml_gettgt(opargs[0], opcode); 3698 ival = rv->type; 3699 break; 3700 3701 /* Mutex/Event handlers */ 3702 case AMLOP_ACQUIRE: 3703 /* Acquire: Sw => Bool */ 3704 rv = aml_gettgt(opargs[0], opcode); 3705 ival = acpi_mutex_acquire(scope, rv, 3706 opargs[1]->v_integer); 3707 break; 3708 case AMLOP_RELEASE: 3709 /* Release: S */ 3710 rv = aml_gettgt(opargs[0], opcode); 3711 acpi_mutex_release(scope, rv); 3712 break; 3713 case AMLOP_WAIT: 3714 /* Wait: Si => Bool */ 3715 rv = aml_gettgt(opargs[0], opcode); 3716 ival = acpi_event_wait(scope, rv, 3717 opargs[1]->v_integer); 3718 break; 3719 case AMLOP_RESET: 3720 /* Reset: S */ 3721 rv = aml_gettgt(opargs[0], opcode); 3722 acpi_event_reset(scope, rv); 3723 break; 3724 case AMLOP_SIGNAL: 3725 /* Signal: S */ 3726 rv = aml_gettgt(opargs[0], opcode); 3727 acpi_event_signal(scope, rv); 3728 break; 3729 3730 /* Named objects */ 3731 case AMLOP_NAME: 3732 /* Name: Nt */ 3733 rv = opargs[0]; 3734 aml_freevalue(rv); 3735 aml_copyvalue(rv, opargs[1]); 3736 break; 3737 case AMLOP_ALIAS: 3738 /* Alias: nN */ 3739 rv = _aml_setvalue(opargs[1], AML_OBJTYPE_OBJREF, opcode, 0); 3740 rv->v_objref.ref = aml_gettgt(opargs[0], opcode); 3741 aml_addref(rv->v_objref.ref, "Alias"); 3742 break; 3743 case AMLOP_OPREGION: 3744 /* OpRegion: Nbii */ 3745 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_OPREGION, 0, 0); 3746 rv->v_opregion.iospace = opargs[1]->v_integer; 3747 rv->v_opregion.iobase = opargs[2]->v_integer; 3748 rv->v_opregion.iolen = opargs[3]->v_integer; 3749 rv->v_opregion.flag = 0; 3750 break; 3751 case AMLOP_DATAREGION: 3752 /* DataTableRegion: N,t:SigStr,t:OemIDStr,t:OemTableIDStr */ 3753 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_OPREGION, 0, 0); 3754 rv->v_opregion.iospace = GAS_SYSTEM_MEMORY; 3755 rv->v_opregion.iobase = 0; 3756 rv->v_opregion.iolen = 0; 3757 aml_die("AML-DataTableRegion\n"); 3758 break; 3759 case AMLOP_EVENT: 3760 /* Event: N */ 3761 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_EVENT, 0, 0); 3762 rv->v_integer = 0; 3763 break; 3764 case AMLOP_MUTEX: 3765 /* Mutex: Nw */ 3766 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_MUTEX, 0, 0); 3767 rv->v_mtx.synclvl = opargs[1]->v_integer; 3768 break; 3769 case AMLOP_SCOPE: 3770 /* Scope: NT */ 3771 rv = opargs[0]; 3772 if (rv->type == AML_OBJTYPE_NAMEREF) { 3773 printf("Undefined scope: %s\n", aml_getname(rv->v_nameref)); 3774 break; 3775 } 3776 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 3777 break; 3778 case AMLOP_DEVICE: 3779 /* Device: NT */ 3780 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_DEVICE, 0, 0); 3781 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 3782 break; 3783 case AMLOP_THERMALZONE: 3784 /* ThermalZone: NT */ 3785 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_THERMZONE, 0, 0); 3786 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 3787 break; 3788 case AMLOP_POWERRSRC: 3789 /* PowerRsrc: NbwT */ 3790 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_POWERRSRC, 0, 0); 3791 rv->v_powerrsrc.pwr_level = opargs[1]->v_integer; 3792 rv->v_powerrsrc.pwr_order = opargs[2]->v_integer; 3793 mscope = aml_pushscope(scope, opargs[3], rv->node, opcode); 3794 break; 3795 case AMLOP_PROCESSOR: 3796 /* Processor: NbdbT */ 3797 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_PROCESSOR, 0, 0); 3798 rv->v_processor.proc_id = opargs[1]->v_integer; 3799 rv->v_processor.proc_addr = opargs[2]->v_integer; 3800 rv->v_processor.proc_len = opargs[3]->v_integer; 3801 mscope = aml_pushscope(scope, opargs[4], rv->node, opcode); 3802 break; 3803 case AMLOP_METHOD: 3804 /* Method: NbM */ 3805 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_METHOD, 0, 0); 3806 rv->v_method.flags = opargs[1]->v_integer; 3807 rv->v_method.start = opargs[2]->v_buffer; 3808 rv->v_method.end = rv->v_method.start + opargs[2]->length; 3809 rv->v_method.base = aml_root.start; 3810 break; 3811 3812 /* Field objects */ 3813 case AMLOP_CREATEFIELD: 3814 /* Source:B, BitIndex:I, NumBits:I, FieldName */ 3815 rv = _aml_setvalue(opargs[3], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3816 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer, 3817 opargs[2]->v_integer, NULL, 0, 0); 3818 break; 3819 case AMLOP_CREATEBITFIELD: 3820 /* Source:B, BitIndex:I, FieldName */ 3821 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3822 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer, 3823 1, NULL, 0, 0); 3824 break; 3825 case AMLOP_CREATEBYTEFIELD: 3826 /* Source:B, ByteIndex:I, FieldName */ 3827 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3828 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 3829 8, NULL, 0, AML_FIELD_BYTEACC); 3830 break; 3831 case AMLOP_CREATEWORDFIELD: 3832 /* Source:B, ByteIndex:I, FieldName */ 3833 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3834 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 3835 16, NULL, 0, AML_FIELD_WORDACC); 3836 break; 3837 case AMLOP_CREATEDWORDFIELD: 3838 /* Source:B, ByteIndex:I, FieldName */ 3839 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3840 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 3841 32, NULL, 0, AML_FIELD_DWORDACC); 3842 break; 3843 case AMLOP_CREATEQWORDFIELD: 3844 /* Source:B, ByteIndex:I, FieldName */ 3845 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 3846 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 3847 64, NULL, 0, AML_FIELD_QWORDACC); 3848 break; 3849 case AMLOP_FIELD: 3850 /* Field: n:OpRegion, b:Flags, F:ieldlist */ 3851 mscope = aml_pushscope(scope, opargs[2], scope->node, opcode); 3852 aml_parsefieldlist(mscope, opcode, opargs[1]->v_integer, 3853 opargs[0], NULL, 0); 3854 mscope = NULL; 3855 break; 3856 case AMLOP_INDEXFIELD: 3857 /* IndexField: n:Index, n:Data, b:Flags, F:ieldlist */ 3858 mscope = aml_pushscope(scope, opargs[3], scope->node, opcode); 3859 aml_parsefieldlist(mscope, opcode, opargs[2]->v_integer, 3860 opargs[1], opargs[0], 0); 3861 mscope = NULL; 3862 break; 3863 case AMLOP_BANKFIELD: 3864 /* BankField: n:OpRegion, n:Field, i:Bank, b:Flags, F:ieldlist */ 3865 mscope = aml_pushscope(scope, opargs[4], scope->node, opcode); 3866 aml_parsefieldlist(mscope, opcode, opargs[3]->v_integer, 3867 opargs[0], opargs[1], opargs[2]->v_integer); 3868 mscope = NULL; 3869 break; 3870 3871 /* Misc functions */ 3872 case AMLOP_STALL: 3873 /* Stall: i */ 3874 acpi_stall(opargs[0]->v_integer); 3875 break; 3876 case AMLOP_SLEEP: 3877 /* Sleep: i */ 3878 acpi_sleep(opargs[0]->v_integer, "amlsleep"); 3879 break; 3880 case AMLOP_NOTIFY: 3881 /* Notify: Si */ 3882 rv = aml_gettgt(opargs[0], opcode); 3883 dnprintf(50,"Notifying: %s %x\n", 3884 aml_nodename(rv->node), 3885 opargs[1]->v_integer); 3886 aml_notify(rv->node, opargs[1]->v_integer); 3887 break; 3888 case AMLOP_TIMER: 3889 /* Timer: => i */ 3890 ival = 0xDEADBEEF; 3891 break; 3892 case AMLOP_FATAL: 3893 /* Fatal: bdi */ 3894 aml_die("AML FATAL ERROR: %x,%x,%x\n", 3895 opargs[0]->v_integer, opargs[1]->v_integer, 3896 opargs[2]->v_integer); 3897 break; 3898 case AMLOP_LOADTABLE: 3899 /* LoadTable(Sig:Str, OEMID:Str, OEMTable:Str, [RootPath:Str], [ParmPath:Str], 3900 [ParmData:DataRefObj]) => DDBHandle */ 3901 aml_die("LoadTable"); 3902 break; 3903 case AMLOP_LOAD: 3904 /* Load(Object:NameString, DDBHandle:SuperName) */ 3905 mscope = aml_load(acpi_softc, scope, opargs[0], opargs[1]); 3906 break; 3907 case AMLOP_UNLOAD: 3908 /* DDBHandle */ 3909 aml_die("Unload"); 3910 break; 3911 3912 /* Control Flow */ 3913 case AMLOP_IF: 3914 /* Arguments: iT or iTbT */ 3915 if (opargs[0]->v_integer) { 3916 dnprintf(10,"parse-if @ %.4x\n", pc); 3917 mscope = aml_pushscope(scope, opargs[1], scope->node, 3918 AMLOP_IF); 3919 } else if (opargs[3] != NULL) { 3920 dnprintf(10,"parse-else @ %.4x\n", pc); 3921 mscope = aml_pushscope(scope, opargs[3], scope->node, 3922 AMLOP_ELSE); 3923 } 3924 break; 3925 case AMLOP_WHILE: 3926 if (opargs[0]->v_integer) { 3927 /* Set parent position to start of WHILE */ 3928 scope->pos = start; 3929 mscope = aml_pushscope(scope, opargs[1], scope->node, 3930 AMLOP_WHILE); 3931 } 3932 break; 3933 case AMLOP_BREAK: 3934 /* Break: Find While Scope parent, mark type as null */ 3935 aml_findscope(scope, AMLOP_WHILE, AMLOP_BREAK); 3936 break; 3937 case AMLOP_CONTINUE: 3938 /* Find Scope.. mark all objects as invalid on way to root */ 3939 aml_findscope(scope, AMLOP_WHILE, AMLOP_CONTINUE); 3940 break; 3941 case AMLOP_RETURN: 3942 mscope = aml_findscope(scope, AMLOP_METHOD, AMLOP_RETURN); 3943 if (mscope->retv) { 3944 aml_die("already allocated\n"); 3945 } 3946 mscope->retv = aml_allocvalue(0,0,NULL); 3947 aml_copyvalue(mscope->retv, opargs[0]); 3948 mscope = NULL; 3949 break; 3950 default: 3951 /* may be set direct result */ 3952 aml_die("Unknown opcode: %x:%s\n", opcode, htab->mnem); 3953 break; 3954 } 3955 if (mscope != NULL) { 3956 /* Change our scope to new scope */ 3957 scope = mscope; 3958 } 3959 if ((ret_type == 'i' || ret_type == 't') && my_ret == NULL) { 3960 dnprintf(10,"quick: %.4x [%s] alloc return integer = 0x%llx\n", 3961 pc, htab->mnem, ival); 3962 my_ret = aml_allocvalue(AML_OBJTYPE_INTEGER, ival, NULL); 3963 } 3964 if (ret_type == 'i' && my_ret && my_ret->type != AML_OBJTYPE_INTEGER) { 3965 dnprintf(10,"quick: %.4x convert to integer %s -> %s\n", 3966 pc, htab->mnem, stype); 3967 my_ret = aml_convert(my_ret, AML_OBJTYPE_INTEGER, -1); 3968 } 3969 if (my_ret != NULL) { 3970 /* Display result */ 3971 dnprintf(20,"quick: %.4x %18s %c %.4x\n", pc, stype, 3972 ret_type, my_ret->stack); 3973 } 3974 3975 /* End opcode: display/free arguments */ 3976 parse_error: 3977 for (idx=0; idx<8; idx++) { 3978 if (opargs[idx] == my_ret) 3979 opargs[idx] = NULL; 3980 aml_delref(&opargs[idx], "oparg"); 3981 } 3982 3983 /* If parsing whole scope and not done, start again */ 3984 if (ret_type == 'T') { 3985 aml_delref(&my_ret, "scope.loop"); 3986 while (scope->pos >= scope->end && scope != iscope) { 3987 /* Pop intermediate scope */ 3988 scope = aml_popscope(scope); 3989 } 3990 if (scope->pos && scope->pos < scope->end) 3991 goto start; 3992 } 3993 3994 odp--; 3995 dnprintf(50, ">>return [%s] %s %c %p\n", aml_nodename(scope->node), 3996 stype, ret_type, my_ret); 3997 3998 return my_ret; 3999 } 4000 4001 int 4002 acpi_parse_aml(struct acpi_softc *sc, u_int8_t *start, u_int32_t length) 4003 { 4004 struct aml_scope *scope; 4005 struct aml_value res; 4006 4007 aml_root.start = start; 4008 memset(&res, 0, sizeof(res)); 4009 res.type = AML_OBJTYPE_SCOPE; 4010 res.length = length; 4011 res.v_buffer = start; 4012 4013 /* Push toplevel scope, parse AML */ 4014 aml_error = 0; 4015 scope = aml_pushscope(NULL, &res, &aml_root, AMLOP_SCOPE); 4016 aml_busy++; 4017 aml_parse(scope, 'T', "TopLevel"); 4018 aml_busy--; 4019 aml_popscope(scope); 4020 4021 if (aml_error) { 4022 printf("error in acpi_parse_aml\n"); 4023 return -1; 4024 } 4025 return (0); 4026 } 4027 4028 /* 4029 * @@@: External API 4030 * 4031 * evaluate an AML node 4032 * Returns a copy of the value in res (must be freed by user) 4033 */ 4034 int 4035 aml_evalnode(struct acpi_softc *sc, struct aml_node *node, 4036 int argc, struct aml_value *argv, struct aml_value *res) 4037 { 4038 struct aml_value *xres; 4039 4040 if (res) 4041 memset(res, 0, sizeof(*res)); 4042 if (node == NULL || node->value == NULL) 4043 return (ACPI_E_BADVALUE); 4044 dnprintf(12,"EVALNODE: %s %d\n", aml_nodename(node), acpi_nalloc); 4045 4046 aml_error = 0; 4047 xres = aml_eval(NULL, node->value, 't', argc, argv); 4048 if (xres) { 4049 if (res) 4050 aml_copyvalue(res, xres); 4051 if (xres != node->value) 4052 aml_delref(&xres, "evalnode"); 4053 } 4054 if (aml_error) { 4055 printf("error evaluating: %s\n", aml_nodename(node)); 4056 return (-1); 4057 } 4058 return (0); 4059 } 4060 4061 /* 4062 * evaluate an AML name 4063 * Returns a copy of the value in res (must be freed by user) 4064 */ 4065 int 4066 aml_evalname(struct acpi_softc *sc, struct aml_node *parent, const char *name, 4067 int argc, struct aml_value *argv, struct aml_value *res) 4068 { 4069 parent = aml_searchname(parent, name); 4070 return aml_evalnode(sc, parent, argc, argv, res); 4071 } 4072 4073 /* 4074 * evaluate an AML integer object 4075 */ 4076 int 4077 aml_evalinteger(struct acpi_softc *sc, struct aml_node *parent, 4078 const char *name, int argc, struct aml_value *argv, int64_t *ival) 4079 { 4080 struct aml_value res; 4081 int rc; 4082 4083 parent = aml_searchname(parent, name); 4084 rc = aml_evalnode(sc, parent, argc, argv, &res); 4085 if (rc == 0) { 4086 *ival = aml_val2int(&res); 4087 aml_freevalue(&res); 4088 } 4089 return rc; 4090 } 4091 4092 /* 4093 * Search for an AML name in namespace.. root only 4094 */ 4095 struct aml_node * 4096 aml_searchname(struct aml_node *root, const void *vname) 4097 { 4098 char *name = (char *)vname; 4099 char nseg[AML_NAMESEG_LEN + 1]; 4100 int i; 4101 4102 dnprintf(25,"Searchname: %s:%s = ", aml_nodename(root), vname); 4103 while (*name == AMLOP_ROOTCHAR) { 4104 root = &aml_root; 4105 name++; 4106 } 4107 while (*name != 0) { 4108 /* Ugh.. we can have short names here: append '_' */ 4109 strlcpy(nseg, "____", sizeof(nseg)); 4110 for (i=0; i < AML_NAMESEG_LEN && *name && *name != '.'; i++) 4111 nseg[i] = *name++; 4112 if (*name == '.') 4113 name++; 4114 root = __aml_search(root, nseg, 0); 4115 } 4116 dnprintf(25,"%p %s\n", root, aml_nodename(root)); 4117 return root; 4118 } 4119 4120 /* 4121 * Search for relative name 4122 */ 4123 struct aml_node * 4124 aml_searchrel(struct aml_node *root, const void *vname) 4125 { 4126 struct aml_node *res; 4127 4128 while (root) { 4129 res = aml_searchname(root, vname); 4130 if (res != NULL) 4131 return res; 4132 root = root->parent; 4133 } 4134 return NULL; 4135 } 4136 4137 #ifndef SMALL_KERNEL 4138 4139 void 4140 acpi_getdevlist(struct acpi_devlist_head *list, struct aml_node *root, 4141 struct aml_value *pkg, int off) 4142 { 4143 struct acpi_devlist *dl; 4144 struct aml_node *node; 4145 int idx; 4146 4147 for (idx=off; idx<pkg->length; idx++) { 4148 node = aml_searchname(root, pkg->v_package[idx]->v_string); 4149 if (node) { 4150 dl = acpi_os_malloc(sizeof(*dl)); 4151 if (dl) { 4152 dl->dev_node = node; 4153 TAILQ_INSERT_TAIL(list, dl, dev_link); 4154 } 4155 } 4156 } 4157 } 4158 4159 void 4160 acpi_freedevlist(struct acpi_devlist_head *list) 4161 { 4162 struct acpi_devlist *dl; 4163 4164 while ((dl = TAILQ_FIRST(list)) != NULL) { 4165 TAILQ_REMOVE(list, dl, dev_link); 4166 acpi_os_free(dl); 4167 } 4168 } 4169 #endif /* SMALL_KERNEL */ 4170