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