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