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