1 /* $OpenBSD: dsdt.c,v 1.249 2019/10/16 01:43:50 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 "Windows 2016", 1507 "Windows 2017", 1508 "Windows 2017.2", 1509 "Windows 2018", 1510 "Windows 2018.2", 1511 "Windows 2019", 1512 NULL 1513 }; 1514 1515 struct aml_value * 1516 aml_callosi(struct aml_scope *scope, struct aml_value *val) 1517 { 1518 int idx, result=0; 1519 struct aml_value *fa; 1520 1521 fa = aml_getstack(scope, AMLOP_ARG0); 1522 1523 if (hw_vendor != NULL && 1524 (strcmp(hw_vendor, "Apple Inc.") == 0 || 1525 strcmp(hw_vendor, "Apple Computer, Inc.") == 0)) { 1526 if (strcmp(fa->v_string, "Darwin") == 0) { 1527 dnprintf(10,"osi: returning 1 for %s on %s hardware\n", 1528 fa->v_string, hw_vendor); 1529 result = 1; 1530 } else 1531 dnprintf(10,"osi: on %s hardware, but ignoring %s\n", 1532 hw_vendor, fa->v_string); 1533 1534 return aml_allocvalue(AML_OBJTYPE_INTEGER, result, NULL); 1535 } 1536 1537 for (idx=0; !result && aml_valid_osi[idx] != NULL; idx++) { 1538 dnprintf(10,"osi: %s,%s\n", fa->v_string, aml_valid_osi[idx]); 1539 result = !strcmp(fa->v_string, aml_valid_osi[idx]); 1540 } 1541 dnprintf(10,"@@ OSI found: %x\n", result); 1542 return aml_allocvalue(AML_OBJTYPE_INTEGER, result, NULL); 1543 } 1544 1545 void 1546 aml_create_defaultobjects(void) 1547 { 1548 struct aml_value *tmp; 1549 struct aml_defval *def; 1550 1551 #ifdef ACPI_MEMDEBUG 1552 LIST_INIT(&acpi_memhead); 1553 #endif 1554 1555 osstring[1] = 'i'; 1556 osstring[6] = 'o'; 1557 osstring[15] = 'w'; 1558 osstring[18] = 'N'; 1559 1560 SIMPLEQ_INIT(&aml_root.son); 1561 strlcpy(aml_root.name, "\\", sizeof(aml_root.name)); 1562 aml_root.value = aml_allocvalue(0, 0, NULL); 1563 aml_root.value->node = &aml_root; 1564 1565 for (def = aml_defobj; def->name; def++) { 1566 /* Allocate object value + add to namespace */ 1567 aml_parsename(&aml_root, (uint8_t *)def->name, &tmp, 1); 1568 _aml_setvalue(tmp, def->type, def->ival, def->bval); 1569 if (def->gval) { 1570 /* Set root object pointer */ 1571 *def->gval = tmp; 1572 } 1573 aml_delref(&tmp, 0); 1574 } 1575 } 1576 1577 #ifdef ACPI_DEBUG 1578 int 1579 aml_print_resource(union acpi_resource *crs, void *arg) 1580 { 1581 int typ = AML_CRSTYPE(crs); 1582 1583 switch (typ) { 1584 case LR_EXTIRQ: 1585 printf("extirq\tflags:%.2x len:%.2x irq:%.4x\n", 1586 crs->lr_extirq.flags, crs->lr_extirq.irq_count, 1587 letoh32(crs->lr_extirq.irq[0])); 1588 break; 1589 case SR_IRQ: 1590 printf("irq\t%.4x %.2x\n", letoh16(crs->sr_irq.irq_mask), 1591 crs->sr_irq.irq_flags); 1592 break; 1593 case SR_DMA: 1594 printf("dma\t%.2x %.2x\n", crs->sr_dma.channel, 1595 crs->sr_dma.flags); 1596 break; 1597 case SR_IOPORT: 1598 printf("ioport\tflags:%.2x _min:%.4x _max:%.4x _aln:%.2x _len:%.2x\n", 1599 crs->sr_ioport.flags, crs->sr_ioport._min, 1600 crs->sr_ioport._max, crs->sr_ioport._aln, 1601 crs->sr_ioport._len); 1602 break; 1603 case SR_STARTDEP: 1604 printf("startdep\n"); 1605 break; 1606 case SR_ENDDEP: 1607 printf("enddep\n"); 1608 break; 1609 case LR_WORD: 1610 printf("word\ttype:%.2x flags:%.2x tflag:%.2x gra:%.4x min:%.4x max:%.4x tra:%.4x len:%.4x\n", 1611 crs->lr_word.type, crs->lr_word.flags, crs->lr_word.tflags, 1612 crs->lr_word._gra, crs->lr_word._min, crs->lr_word._max, 1613 crs->lr_word._tra, crs->lr_word._len); 1614 break; 1615 case LR_DWORD: 1616 printf("dword\ttype:%.2x flags:%.2x tflag:%.2x gra:%.8x min:%.8x max:%.8x tra:%.8x len:%.8x\n", 1617 crs->lr_dword.type, crs->lr_dword.flags, crs->lr_dword.tflags, 1618 crs->lr_dword._gra, crs->lr_dword._min, crs->lr_dword._max, 1619 crs->lr_dword._tra, crs->lr_dword._len); 1620 break; 1621 case LR_QWORD: 1622 printf("dword\ttype:%.2x flags:%.2x tflag:%.2x gra:%.16llx min:%.16llx max:%.16llx tra:%.16llx len:%.16llx\n", 1623 crs->lr_qword.type, crs->lr_qword.flags, crs->lr_qword.tflags, 1624 crs->lr_qword._gra, crs->lr_qword._min, crs->lr_qword._max, 1625 crs->lr_qword._tra, crs->lr_qword._len); 1626 break; 1627 default: 1628 printf("unknown type: %x\n", typ); 1629 break; 1630 } 1631 return (0); 1632 } 1633 #endif /* ACPI_DEBUG */ 1634 1635 union acpi_resource *aml_mapresource(union acpi_resource *); 1636 1637 union acpi_resource * 1638 aml_mapresource(union acpi_resource *crs) 1639 { 1640 static union acpi_resource map; 1641 int rlen; 1642 1643 rlen = AML_CRSLEN(crs); 1644 if (rlen >= sizeof(map)) 1645 return crs; 1646 1647 memset(&map, 0, sizeof(map)); 1648 memcpy(&map, crs, rlen); 1649 1650 return ↦ 1651 } 1652 1653 int 1654 aml_parse_resource(struct aml_value *res, 1655 int (*crs_enum)(int, union acpi_resource *, void *), void *arg) 1656 { 1657 int off, rlen, crsidx; 1658 union acpi_resource *crs; 1659 1660 if (res->type != AML_OBJTYPE_BUFFER || res->length < 5) 1661 return (-1); 1662 for (off = 0, crsidx = 0; off < res->length; off += rlen, crsidx++) { 1663 crs = (union acpi_resource *)(res->v_buffer+off); 1664 1665 rlen = AML_CRSLEN(crs); 1666 if (crs->hdr.typecode == SRT_ENDTAG || !rlen) 1667 break; 1668 1669 crs = aml_mapresource(crs); 1670 #ifdef ACPI_DEBUG 1671 aml_print_resource(crs, NULL); 1672 #endif 1673 crs_enum(crsidx, crs, arg); 1674 } 1675 1676 return (0); 1677 } 1678 1679 void 1680 aml_foreachpkg(struct aml_value *pkg, int start, 1681 void (*fn)(struct aml_value *, void *), void *arg) 1682 { 1683 int idx; 1684 1685 if (pkg->type != AML_OBJTYPE_PACKAGE) 1686 return; 1687 for (idx=start; idx<pkg->length; idx++) 1688 fn(pkg->v_package[idx], arg); 1689 } 1690 1691 /* 1692 * Walk nodes and perform fixups for nameref 1693 */ 1694 int aml_fixup_node(struct aml_node *, void *); 1695 1696 int aml_fixup_node(struct aml_node *node, void *arg) 1697 { 1698 struct aml_value *val = arg; 1699 int i; 1700 1701 if (node->value == NULL) 1702 return (0); 1703 if (arg == NULL) 1704 aml_fixup_node(node, node->value); 1705 else if (val->type == AML_OBJTYPE_NAMEREF) { 1706 node = aml_searchname(node, val->v_nameref); 1707 if (node && node->value) { 1708 _aml_setvalue(val, AML_OBJTYPE_OBJREF, AMLOP_NAMECHAR, 1709 node->value); 1710 } 1711 } else if (val->type == AML_OBJTYPE_PACKAGE) { 1712 for (i = 0; i < val->length; i++) 1713 aml_fixup_node(node, val->v_package[i]); 1714 } 1715 return (0); 1716 } 1717 1718 void 1719 aml_postparse(void) 1720 { 1721 aml_walknodes(&aml_root, AML_WALK_PRE, aml_fixup_node, NULL); 1722 } 1723 1724 #ifndef SMALL_KERNEL 1725 const char * 1726 aml_val_to_string(const struct aml_value *val) 1727 { 1728 static char buffer[256]; 1729 1730 int len; 1731 1732 switch (val->type) { 1733 case AML_OBJTYPE_BUFFER: 1734 len = val->length; 1735 if (len >= sizeof(buffer)) 1736 len = sizeof(buffer) - 1; 1737 memcpy(buffer, val->v_buffer, len); 1738 buffer[len] = 0; 1739 break; 1740 case AML_OBJTYPE_STRING: 1741 strlcpy(buffer, val->v_string, sizeof(buffer)); 1742 break; 1743 case AML_OBJTYPE_INTEGER: 1744 snprintf(buffer, sizeof(buffer), "%llx", val->v_integer); 1745 break; 1746 default: 1747 snprintf(buffer, sizeof(buffer), 1748 "Failed to convert type %d to string!", val->type); 1749 }; 1750 1751 return (buffer); 1752 } 1753 #endif /* SMALL_KERNEL */ 1754 1755 int aml_error; 1756 1757 struct aml_value *aml_gettgt(struct aml_value *, int); 1758 struct aml_value *aml_eval(struct aml_scope *, struct aml_value *, int, int, 1759 struct aml_value *); 1760 struct aml_value *aml_parsesimple(struct aml_scope *, char, 1761 struct aml_value *); 1762 struct aml_value *aml_parse(struct aml_scope *, int, const char *); 1763 struct aml_value *aml_seterror(struct aml_scope *, const char *, ...); 1764 1765 struct aml_scope *aml_findscope(struct aml_scope *, int, int); 1766 struct aml_scope *aml_pushscope(struct aml_scope *, struct aml_value *, 1767 struct aml_node *, int); 1768 struct aml_scope *aml_popscope(struct aml_scope *); 1769 1770 void aml_showstack(struct aml_scope *); 1771 struct aml_value *aml_convert(struct aml_value *, int, int); 1772 1773 int aml_matchtest(int64_t, int64_t, int); 1774 int aml_match(struct aml_value *, int, int, int, int, int); 1775 1776 int aml_compare(struct aml_value *, struct aml_value *, int); 1777 struct aml_value *aml_concat(struct aml_value *, struct aml_value *); 1778 struct aml_value *aml_concatres(struct aml_value *, struct aml_value *); 1779 struct aml_value *aml_mid(struct aml_value *, int, int); 1780 int aml_ccrlen(int, union acpi_resource *, void *); 1781 1782 void aml_store(struct aml_scope *, struct aml_value *, int64_t, 1783 struct aml_value *); 1784 1785 /* 1786 * Reference Count functions 1787 */ 1788 void 1789 aml_addref(struct aml_value *val, const char *lbl) 1790 { 1791 if (val == NULL) 1792 return; 1793 dnprintf(50, "XAddRef: %p %s:[%s] %d\n", 1794 val, lbl, 1795 val->node ? aml_nodename(val->node) : "INTERNAL", 1796 val->refcnt); 1797 val->refcnt++; 1798 } 1799 1800 /* Decrease reference counter */ 1801 void 1802 aml_delref(struct aml_value **pv, const char *lbl) 1803 { 1804 struct aml_value *val; 1805 1806 if (pv == NULL || *pv == NULL) 1807 return; 1808 val = *pv; 1809 val->refcnt--; 1810 if (val->refcnt == 0) { 1811 dnprintf(50, "XDelRef: %p %s %2d [%s] %s\n", 1812 val, lbl, 1813 val->refcnt, 1814 val->node ? aml_nodename(val->node) : "INTERNAL", 1815 val->refcnt ? "" : "---------------- FREEING"); 1816 1817 aml_freevalue(val); 1818 acpi_os_free(val); 1819 *pv = NULL; 1820 } 1821 } 1822 1823 /* Walk list of parent scopes until we find one of 'type' 1824 * If endscope is set, mark all intermediate scopes as invalid (used for Method/While) */ 1825 struct aml_scope * 1826 aml_findscope(struct aml_scope *scope, int type, int endscope) 1827 { 1828 while (scope) { 1829 switch (endscope) { 1830 case AMLOP_RETURN: 1831 scope->pos = scope->end; 1832 if (scope->type == AMLOP_WHILE) 1833 scope->pos = NULL; 1834 break; 1835 case AMLOP_CONTINUE: 1836 scope->pos = scope->end; 1837 break; 1838 case AMLOP_BREAK: 1839 scope->pos = scope->end; 1840 if (scope->type == type) 1841 scope->parent->pos = scope->end; 1842 break; 1843 } 1844 if (scope->type == type) 1845 break; 1846 scope = scope->parent; 1847 } 1848 return scope; 1849 } 1850 1851 struct aml_value * 1852 aml_getstack(struct aml_scope *scope, int opcode) 1853 { 1854 struct aml_value *sp; 1855 1856 sp = NULL; 1857 scope = aml_findscope(scope, AMLOP_METHOD, 0); 1858 if (scope == NULL) 1859 return NULL; 1860 if (opcode >= AMLOP_LOCAL0 && opcode <= AMLOP_LOCAL7) { 1861 if (scope->locals == NULL) 1862 scope->locals = aml_allocvalue(AML_OBJTYPE_PACKAGE, 8, NULL); 1863 sp = scope->locals->v_package[opcode - AMLOP_LOCAL0]; 1864 sp->stack = opcode; 1865 } else if (opcode >= AMLOP_ARG0 && opcode <= AMLOP_ARG6) { 1866 if (scope->args == NULL) 1867 scope->args = aml_allocvalue(AML_OBJTYPE_PACKAGE, 7, NULL); 1868 sp = scope->args->v_package[opcode - AMLOP_ARG0]; 1869 if (sp->type == AML_OBJTYPE_OBJREF) 1870 sp = sp->v_objref.ref; 1871 } 1872 return sp; 1873 } 1874 1875 #ifdef ACPI_DEBUG 1876 /* Dump AML Stack */ 1877 void 1878 aml_showstack(struct aml_scope *scope) 1879 { 1880 struct aml_value *sp; 1881 int idx; 1882 1883 dnprintf(10, "===== Stack %s:%s\n", aml_nodename(scope->node), 1884 aml_mnem(scope->type, 0)); 1885 for (idx=0; scope->args && idx<7; idx++) { 1886 sp = aml_getstack(scope, AMLOP_ARG0+idx); 1887 if (sp && sp->type) { 1888 dnprintf(10," Arg%d: ", idx); 1889 aml_showvalue(sp); 1890 } 1891 } 1892 for (idx=0; scope->locals && idx<8; idx++) { 1893 sp = aml_getstack(scope, AMLOP_LOCAL0+idx); 1894 if (sp && sp->type) { 1895 dnprintf(10," Local%d: ", idx); 1896 aml_showvalue(sp); 1897 } 1898 } 1899 } 1900 #endif 1901 1902 /* Create a new scope object */ 1903 struct aml_scope * 1904 aml_pushscope(struct aml_scope *parent, struct aml_value *range, 1905 struct aml_node *node, int type) 1906 { 1907 struct aml_scope *scope; 1908 uint8_t *start, *end; 1909 1910 if (range->type == AML_OBJTYPE_METHOD) { 1911 start = range->v_method.start; 1912 end = range->v_method.end; 1913 } else { 1914 start = range->v_buffer; 1915 end = start + range->length; 1916 if (start == end) 1917 return NULL; 1918 } 1919 scope = acpi_os_malloc(sizeof(struct aml_scope)); 1920 if (scope == NULL) 1921 return NULL; 1922 1923 scope->node = node; 1924 scope->start = start; 1925 scope->end = end; 1926 scope->pos = scope->start; 1927 scope->parent = parent; 1928 scope->type = type; 1929 scope->sc = acpi_softc; 1930 1931 if (parent) 1932 scope->depth = parent->depth+1; 1933 1934 aml_lastscope = scope; 1935 1936 return scope; 1937 } 1938 1939 /* Free a scope object and any children */ 1940 struct aml_scope * 1941 aml_popscope(struct aml_scope *scope) 1942 { 1943 struct aml_scope *nscope; 1944 1945 if (scope == NULL) 1946 return NULL; 1947 1948 nscope = scope->parent; 1949 1950 if (scope->type == AMLOP_METHOD) 1951 aml_delchildren(scope->node); 1952 if (scope->locals) { 1953 aml_freevalue(scope->locals); 1954 acpi_os_free(scope->locals); 1955 scope->locals = NULL; 1956 } 1957 if (scope->args) { 1958 aml_freevalue(scope->args); 1959 acpi_os_free(scope->args); 1960 scope->args = NULL; 1961 } 1962 acpi_os_free(scope); 1963 aml_lastscope = nscope; 1964 1965 return nscope; 1966 } 1967 1968 /* Test AMLOP_MATCH codes */ 1969 int 1970 aml_matchtest(int64_t a, int64_t b, int op) 1971 { 1972 switch (op) { 1973 case AML_MATCH_TR: 1974 return (1); 1975 case AML_MATCH_EQ: 1976 return (a == b); 1977 case AML_MATCH_LT: 1978 return (a < b); 1979 case AML_MATCH_LE: 1980 return (a <= b); 1981 case AML_MATCH_GE: 1982 return (a >= b); 1983 case AML_MATCH_GT: 1984 return (a > b); 1985 } 1986 return (0); 1987 } 1988 1989 /* Search a package for a matching value */ 1990 int 1991 aml_match(struct aml_value *pkg, int index, 1992 int op1, int v1, 1993 int op2, int v2) 1994 { 1995 struct aml_value *tmp; 1996 int flag; 1997 1998 while (index < pkg->length) { 1999 /* Convert package value to integer */ 2000 tmp = aml_convert(pkg->v_package[index], 2001 AML_OBJTYPE_INTEGER, -1); 2002 2003 /* Perform test */ 2004 flag = aml_matchtest(tmp->v_integer, v1, op1) && 2005 aml_matchtest(tmp->v_integer, v2, op2); 2006 aml_delref(&tmp, "xmatch"); 2007 2008 if (flag) 2009 return index; 2010 index++; 2011 } 2012 return -1; 2013 } 2014 2015 /* 2016 * Conversion routines 2017 */ 2018 int64_t 2019 aml_hextoint(const char *str) 2020 { 2021 int64_t v = 0; 2022 char c; 2023 2024 while (*str) { 2025 if (*str >= '0' && *str <= '9') 2026 c = *(str++) - '0'; 2027 else if (*str >= 'a' && *str <= 'f') 2028 c = *(str++) - 'a' + 10; 2029 else if (*str >= 'A' && *str <= 'F') 2030 c = *(str++) - 'A' + 10; 2031 else 2032 break; 2033 v = (v << 4) + c; 2034 } 2035 return v; 2036 2037 } 2038 2039 struct aml_value * 2040 aml_convert(struct aml_value *a, int ctype, int clen) 2041 { 2042 struct aml_value *c = NULL; 2043 2044 /* Object is already this type */ 2045 if (clen == -1) 2046 clen = a->length; 2047 if (a->type == ctype) { 2048 aml_addref(a, "XConvert"); 2049 return a; 2050 } 2051 switch (ctype) { 2052 case AML_OBJTYPE_BUFFER: 2053 dnprintf(10,"convert to buffer\n"); 2054 switch (a->type) { 2055 case AML_OBJTYPE_INTEGER: 2056 c = aml_allocvalue(AML_OBJTYPE_BUFFER, a->length, 2057 &a->v_integer); 2058 break; 2059 case AML_OBJTYPE_STRING: 2060 c = aml_allocvalue(AML_OBJTYPE_BUFFER, a->length, 2061 a->v_string); 2062 break; 2063 } 2064 break; 2065 case AML_OBJTYPE_INTEGER: 2066 dnprintf(10,"convert to integer : %x\n", a->type); 2067 switch (a->type) { 2068 case AML_OBJTYPE_BUFFER: 2069 c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); 2070 memcpy(&c->v_integer, a->v_buffer, 2071 min(a->length, c->length)); 2072 break; 2073 case AML_OBJTYPE_STRING: 2074 c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); 2075 c->v_integer = aml_hextoint(a->v_string); 2076 break; 2077 case AML_OBJTYPE_UNINITIALIZED: 2078 c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); 2079 break; 2080 } 2081 break; 2082 case AML_OBJTYPE_STRING: 2083 case AML_OBJTYPE_HEXSTRING: 2084 case AML_OBJTYPE_DECSTRING: 2085 dnprintf(10,"convert to string\n"); 2086 switch (a->type) { 2087 case AML_OBJTYPE_INTEGER: 2088 c = aml_allocvalue(AML_OBJTYPE_STRING, 20, NULL); 2089 snprintf(c->v_string, c->length, (ctype == AML_OBJTYPE_HEXSTRING) ? 2090 "0x%llx" : "%lld", a->v_integer); 2091 break; 2092 case AML_OBJTYPE_BUFFER: 2093 c = aml_allocvalue(AML_OBJTYPE_STRING, a->length, 2094 a->v_buffer); 2095 break; 2096 case AML_OBJTYPE_STRING: 2097 aml_addref(a, "XConvert"); 2098 return a; 2099 } 2100 break; 2101 } 2102 if (c == NULL) { 2103 #ifndef SMALL_KERNEL 2104 aml_showvalue(a); 2105 #endif 2106 aml_die("Could not convert %x to %x\n", a->type, ctype); 2107 } 2108 return c; 2109 } 2110 2111 int 2112 aml_compare(struct aml_value *a1, struct aml_value *a2, int opcode) 2113 { 2114 int rc = 0; 2115 2116 /* Convert A2 to type of A1 */ 2117 a2 = aml_convert(a2, a1->type, -1); 2118 if (a1->type == AML_OBJTYPE_INTEGER) 2119 rc = aml_evalexpr(a1->v_integer, a2->v_integer, opcode); 2120 else { 2121 /* Perform String/Buffer comparison */ 2122 rc = memcmp(a1->v_buffer, a2->v_buffer, 2123 min(a1->length, a2->length)); 2124 if (rc == 0) { 2125 /* If buffers match, which one is longer */ 2126 rc = a1->length - a2->length; 2127 } 2128 /* Perform comparison against zero */ 2129 rc = aml_evalexpr(rc, 0, opcode); 2130 } 2131 /* Either deletes temp buffer, or decrease refcnt on original A2 */ 2132 aml_delref(&a2, "xcompare"); 2133 return rc; 2134 } 2135 2136 /* Concatenate two objects, returning pointer to new object */ 2137 struct aml_value * 2138 aml_concat(struct aml_value *a1, struct aml_value *a2) 2139 { 2140 struct aml_value *c = NULL; 2141 2142 /* Convert arg2 to type of arg1 */ 2143 a2 = aml_convert(a2, a1->type, -1); 2144 switch (a1->type) { 2145 case AML_OBJTYPE_INTEGER: 2146 c = aml_allocvalue(AML_OBJTYPE_BUFFER, 2147 a1->length + a2->length, NULL); 2148 memcpy(c->v_buffer, &a1->v_integer, a1->length); 2149 memcpy(c->v_buffer+a1->length, &a2->v_integer, a2->length); 2150 break; 2151 case AML_OBJTYPE_BUFFER: 2152 c = aml_allocvalue(AML_OBJTYPE_BUFFER, 2153 a1->length + a2->length, NULL); 2154 memcpy(c->v_buffer, a1->v_buffer, a1->length); 2155 memcpy(c->v_buffer+a1->length, a2->v_buffer, a2->length); 2156 break; 2157 case AML_OBJTYPE_STRING: 2158 c = aml_allocvalue(AML_OBJTYPE_STRING, 2159 a1->length + a2->length, NULL); 2160 memcpy(c->v_string, a1->v_string, a1->length); 2161 memcpy(c->v_string+a1->length, a2->v_string, a2->length); 2162 break; 2163 default: 2164 aml_die("concat type mismatch %d != %d\n", a1->type, a2->type); 2165 break; 2166 } 2167 /* Either deletes temp buffer, or decrease refcnt on original A2 */ 2168 aml_delref(&a2, "xconcat"); 2169 return c; 2170 } 2171 2172 /* Calculate length of Resource Template */ 2173 int 2174 aml_ccrlen(int crsidx, union acpi_resource *rs, void *arg) 2175 { 2176 int *plen = arg; 2177 2178 *plen += AML_CRSLEN(rs); 2179 return (0); 2180 } 2181 2182 /* Concatenate resource templates, returning pointer to new object */ 2183 struct aml_value * 2184 aml_concatres(struct aml_value *a1, struct aml_value *a2) 2185 { 2186 struct aml_value *c; 2187 int l1 = 0, l2 = 0, l3 = 2; 2188 uint8_t a3[] = { SRT_ENDTAG, 0x00 }; 2189 2190 if (a1->type != AML_OBJTYPE_BUFFER || a2->type != AML_OBJTYPE_BUFFER) 2191 aml_die("concatres: not buffers\n"); 2192 2193 /* Walk a1, a2, get length minus end tags, concatenate buffers, add end tag */ 2194 aml_parse_resource(a1, aml_ccrlen, &l1); 2195 aml_parse_resource(a2, aml_ccrlen, &l2); 2196 2197 /* Concatenate buffers, add end tag */ 2198 c = aml_allocvalue(AML_OBJTYPE_BUFFER, l1+l2+l3, NULL); 2199 memcpy(c->v_buffer, a1->v_buffer, l1); 2200 memcpy(c->v_buffer+l1, a2->v_buffer, l2); 2201 memcpy(c->v_buffer+l1+l2, a3, l3); 2202 2203 return c; 2204 } 2205 2206 /* Extract substring from string or buffer */ 2207 struct aml_value * 2208 aml_mid(struct aml_value *src, int index, int length) 2209 { 2210 if (index > src->length) 2211 index = src->length; 2212 if ((index + length) > src->length) 2213 length = src->length - index; 2214 return aml_allocvalue(src->type, length, src->v_buffer + index); 2215 } 2216 2217 /* 2218 * Field I/O utility functions 2219 */ 2220 void aml_createfield(struct aml_value *, int, struct aml_value *, int, int, 2221 struct aml_value *, int, int); 2222 void aml_parsefieldlist(struct aml_scope *, int, int, 2223 struct aml_value *, struct aml_value *, int); 2224 2225 int 2226 aml_evalhid(struct aml_node *node, struct aml_value *val) 2227 { 2228 if (aml_evalname(acpi_softc, node, "_HID", 0, NULL, val)) 2229 return (-1); 2230 2231 /* Integer _HID: convert to EISA ID */ 2232 if (val->type == AML_OBJTYPE_INTEGER) 2233 _aml_setvalue(val, AML_OBJTYPE_STRING, -1, aml_eisaid(val->v_integer)); 2234 return (0); 2235 } 2236 2237 int 2238 aml_opreg_sysmem_handler(void *cookie, int iodir, uint64_t address, int size, 2239 uint64_t *value) 2240 { 2241 return acpi_gasio(acpi_softc, iodir, GAS_SYSTEM_MEMORY, 2242 address, size, size, value); 2243 } 2244 2245 int 2246 aml_opreg_sysio_handler(void *cookie, int iodir, uint64_t address, int size, 2247 uint64_t *value) 2248 { 2249 return acpi_gasio(acpi_softc, iodir, GAS_SYSTEM_IOSPACE, 2250 address, size, size, value); 2251 } 2252 2253 int 2254 aml_opreg_pcicfg_handler(void *cookie, int iodir, uint64_t address, int size, 2255 uint64_t *value) 2256 { 2257 return acpi_gasio(acpi_softc, iodir, GAS_PCI_CFG_SPACE, 2258 address, size, size, value); 2259 } 2260 2261 int 2262 aml_opreg_ec_handler(void *cookie, int iodir, uint64_t address, int size, 2263 uint64_t *value) 2264 { 2265 return acpi_gasio(acpi_softc, iodir, GAS_EMBEDDED, 2266 address, size, size, value); 2267 } 2268 2269 struct aml_regionspace { 2270 void *cookie; 2271 int (*handler)(void *, int, uint64_t, int, uint64_t *); 2272 }; 2273 2274 struct aml_regionspace aml_regionspace[256] = { 2275 [ACPI_OPREG_SYSMEM] = { NULL, aml_opreg_sysmem_handler }, 2276 [ACPI_OPREG_SYSIO] = { NULL, aml_opreg_sysio_handler }, 2277 [ACPI_OPREG_PCICFG] = { NULL, aml_opreg_pcicfg_handler }, 2278 [ACPI_OPREG_EC] = { NULL, aml_opreg_ec_handler }, 2279 }; 2280 2281 void 2282 aml_register_regionspace(struct aml_node *node, int iospace, void *cookie, 2283 int (*handler)(void *, int, uint64_t, int, uint64_t *)) 2284 { 2285 struct aml_value arg[2]; 2286 2287 KASSERT(iospace >= 0 && iospace < 256); 2288 2289 aml_regionspace[iospace].cookie = cookie; 2290 aml_regionspace[iospace].handler = handler; 2291 2292 /* Register address space. */ 2293 memset(&arg, 0, sizeof(arg)); 2294 arg[0].type = AML_OBJTYPE_INTEGER; 2295 arg[0].v_integer = iospace; 2296 arg[1].type = AML_OBJTYPE_INTEGER; 2297 arg[1].v_integer = 1; 2298 node = aml_searchname(node, "_REG"); 2299 if (node) 2300 aml_evalnode(acpi_softc, node, 2, arg, NULL); 2301 } 2302 2303 void aml_rwgen(struct aml_value *, int, int, struct aml_value *, int, int); 2304 void aml_rwgpio(struct aml_value *, int, int, struct aml_value *, int, int); 2305 void aml_rwgsb(struct aml_value *, int, int, int, struct aml_value *, int, int); 2306 void aml_rwindexfield(struct aml_value *, struct aml_value *val, int); 2307 void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int); 2308 2309 /* Get PCI address for opregion objects */ 2310 int 2311 aml_rdpciaddr(struct aml_node *pcidev, union amlpci_t *addr) 2312 { 2313 int64_t res; 2314 2315 addr->bus = 0; 2316 addr->seg = 0; 2317 if (aml_evalinteger(acpi_softc, pcidev, "_ADR", 0, NULL, &res) == 0) { 2318 addr->fun = res & 0xFFFF; 2319 addr->dev = res >> 16; 2320 } 2321 while (pcidev != NULL) { 2322 /* HID device (PCI or PCIE root): eval _SEG and _BBN */ 2323 if (__aml_search(pcidev, "_HID", 0)) { 2324 if (aml_evalinteger(acpi_softc, pcidev, "_SEG", 2325 0, NULL, &res) == 0) { 2326 addr->seg = res; 2327 } 2328 if (aml_evalinteger(acpi_softc, pcidev, "_BBN", 2329 0, NULL, &res) == 0) { 2330 addr->bus = res; 2331 break; 2332 } 2333 } 2334 pcidev = pcidev->parent; 2335 } 2336 return (0); 2337 } 2338 2339 int 2340 acpi_genio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address, 2341 int access_size, int len, void *buffer) 2342 { 2343 struct aml_regionspace *region = &aml_regionspace[iospace]; 2344 uint8_t *pb; 2345 int reg; 2346 2347 dnprintf(50, "genio: %.2x 0x%.8llx %s\n", 2348 iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read"); 2349 2350 KASSERT((len % access_size) == 0); 2351 2352 pb = (uint8_t *)buffer; 2353 for (reg = 0; reg < len; reg += access_size) { 2354 uint64_t value; 2355 int err; 2356 2357 if (iodir == ACPI_IOREAD) { 2358 err = region->handler(region->cookie, iodir, 2359 address + reg, access_size, &value); 2360 if (err) 2361 return err; 2362 switch (access_size) { 2363 case 1: 2364 *(uint8_t *)(pb + reg) = value; 2365 break; 2366 case 2: 2367 *(uint16_t *)(pb + reg) = value; 2368 break; 2369 case 4: 2370 *(uint32_t *)(pb + reg) = value; 2371 break; 2372 default: 2373 printf("%s: invalid access size %d on read\n", 2374 __func__, access_size); 2375 return -1; 2376 } 2377 } else { 2378 switch (access_size) { 2379 case 1: 2380 value = *(uint8_t *)(pb + reg); 2381 break; 2382 case 2: 2383 value = *(uint16_t *)(pb + reg); 2384 break; 2385 case 4: 2386 value = *(uint32_t *)(pb + reg); 2387 break; 2388 default: 2389 printf("%s: invalid access size %d on write\n", 2390 __func__, access_size); 2391 return -1; 2392 } 2393 err = region->handler(region->cookie, iodir, 2394 address + reg, access_size, &value); 2395 if (err) 2396 return err; 2397 } 2398 } 2399 2400 return 0; 2401 } 2402 2403 /* Read/Write from opregion object */ 2404 void 2405 aml_rwgen(struct aml_value *rgn, int bpos, int blen, struct aml_value *val, 2406 int mode, int flag) 2407 { 2408 struct aml_value tmp; 2409 union amlpci_t pi; 2410 void *tbit, *vbit; 2411 int tlen, type, sz; 2412 2413 dnprintf(10," %5s %.2x %.8llx %.4x [%s]\n", 2414 mode == ACPI_IOREAD ? "read" : "write", 2415 rgn->v_opregion.iospace, 2416 rgn->v_opregion.iobase + (bpos >> 3), 2417 blen, aml_nodename(rgn->node)); 2418 memset(&tmp, 0, sizeof(tmp)); 2419 2420 /* Get field access size */ 2421 switch (AML_FIELD_ACCESS(flag)) { 2422 case AML_FIELD_WORDACC: 2423 sz = 2; 2424 break; 2425 case AML_FIELD_DWORDACC: 2426 sz = 4; 2427 break; 2428 case AML_FIELD_QWORDACC: 2429 sz = 8; 2430 break; 2431 default: 2432 sz = 1; 2433 break; 2434 } 2435 2436 pi.addr = (rgn->v_opregion.iobase + (bpos >> 3)) & ~(sz - 1); 2437 bpos += ((rgn->v_opregion.iobase & (sz - 1)) << 3); 2438 bpos &= ((sz << 3) - 1); 2439 2440 if (rgn->v_opregion.iospace == ACPI_OPREG_PCICFG) { 2441 /* Get PCI Root Address for this opregion */ 2442 aml_rdpciaddr(rgn->node->parent, &pi); 2443 } 2444 2445 tbit = &tmp.v_integer; 2446 vbit = &val->v_integer; 2447 tlen = roundup(bpos + blen, sz << 3); 2448 type = rgn->v_opregion.iospace; 2449 2450 if (aml_regionspace[type].handler == NULL) { 2451 printf("%s: unregistered RegionSpace 0x%x\n", __func__, type); 2452 return; 2453 } 2454 2455 /* Allocate temporary storage */ 2456 if (tlen > aml_intlen) { 2457 _aml_setvalue(&tmp, AML_OBJTYPE_BUFFER, tlen >> 3, 0); 2458 tbit = tmp.v_buffer; 2459 } 2460 2461 if (blen > aml_intlen) { 2462 if (mode == ACPI_IOREAD) { 2463 /* Read from a large field: create buffer */ 2464 _aml_setvalue(val, AML_OBJTYPE_BUFFER, (blen + 7) >> 3, 0); 2465 } else { 2466 /* Write to a large field.. create or convert buffer */ 2467 val = aml_convert(val, AML_OBJTYPE_BUFFER, -1); 2468 2469 if (blen > (val->length << 3)) 2470 blen = val->length << 3; 2471 } 2472 vbit = val->v_buffer; 2473 } else { 2474 if (mode == ACPI_IOREAD) { 2475 /* Read from a short field.. initialize integer */ 2476 _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); 2477 } else { 2478 /* Write to a short field.. convert to integer */ 2479 val = aml_convert(val, AML_OBJTYPE_INTEGER, -1); 2480 } 2481 } 2482 2483 if (mode == ACPI_IOREAD) { 2484 /* Read bits from opregion */ 2485 acpi_genio(acpi_softc, ACPI_IOREAD, type, pi.addr, 2486 sz, tlen >> 3, tbit); 2487 aml_bufcpy(vbit, 0, tbit, bpos, blen); 2488 } else { 2489 /* Write bits to opregion */ 2490 if (AML_FIELD_UPDATE(flag) == AML_FIELD_PRESERVE && 2491 (bpos != 0 || blen != tlen)) { 2492 acpi_genio(acpi_softc, ACPI_IOREAD, type, pi.addr, 2493 sz, tlen >> 3, tbit); 2494 } else if (AML_FIELD_UPDATE(flag) == AML_FIELD_WRITEASONES) { 2495 memset(tbit, 0xff, tmp.length); 2496 } 2497 /* Copy target bits, then write to region */ 2498 aml_bufcpy(tbit, bpos, vbit, 0, blen); 2499 acpi_genio(acpi_softc, ACPI_IOWRITE, type, pi.addr, 2500 sz, tlen >> 3, tbit); 2501 2502 aml_delref(&val, "fld.write"); 2503 } 2504 aml_freevalue(&tmp); 2505 } 2506 2507 void 2508 aml_rwgpio(struct aml_value *conn, int bpos, int blen, struct aml_value *val, 2509 int mode, int flag) 2510 { 2511 union acpi_resource *crs = (union acpi_resource *)conn->v_buffer; 2512 struct aml_node *node; 2513 uint16_t pin; 2514 int v = 0; 2515 2516 if (conn->type != AML_OBJTYPE_BUFFER || conn->length < 5 || 2517 AML_CRSTYPE(crs) != LR_GPIO || AML_CRSLEN(crs) > conn->length) 2518 aml_die("Invalid GpioIo"); 2519 if (bpos != 0 || blen != 1) 2520 aml_die("Invalid GpioIo access"); 2521 2522 node = aml_searchname(conn->node, 2523 (char *)&crs->pad[crs->lr_gpio.res_off]); 2524 pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off]; 2525 2526 if (node == NULL || node->gpio == NULL) 2527 aml_die("Could not find GpioIo pin"); 2528 2529 if (mode == ACPI_IOWRITE) { 2530 v = aml_val2int(val); 2531 node->gpio->write_pin(node->gpio->cookie, pin, v); 2532 } else { 2533 v = node->gpio->read_pin(node->gpio->cookie, pin); 2534 _aml_setvalue(val, AML_OBJTYPE_INTEGER, v, NULL); 2535 } 2536 } 2537 2538 #ifndef SMALL_KERNEL 2539 2540 void 2541 aml_rwgsb(struct aml_value *conn, int alen, int bpos, int blen, 2542 struct aml_value *val, int mode, int flag) 2543 { 2544 union acpi_resource *crs = (union acpi_resource *)conn->v_buffer; 2545 struct aml_node *node; 2546 i2c_tag_t tag; 2547 i2c_op_t op; 2548 i2c_addr_t addr; 2549 int cmdlen, buflen; 2550 uint8_t cmd; 2551 uint8_t *buf; 2552 int err; 2553 2554 if (conn->type != AML_OBJTYPE_BUFFER || conn->length < 5 || 2555 AML_CRSTYPE(crs) != LR_SERBUS || AML_CRSLEN(crs) > conn->length || 2556 crs->lr_i2cbus.revid != 1 || crs->lr_i2cbus.type != LR_SERBUS_I2C) 2557 aml_die("Invalid GenericSerialBus"); 2558 if (AML_FIELD_ACCESS(flag) != AML_FIELD_BUFFERACC || 2559 bpos & 0x3 || blen != 8) 2560 aml_die("Invalid GenericSerialBus access"); 2561 2562 node = aml_searchname(conn->node, 2563 (char *)&crs->lr_i2cbus.vdata[crs->lr_i2cbus.tlength - 6]); 2564 2565 if (node == NULL || node->i2c == NULL) 2566 aml_die("Could not find GenericSerialBus controller"); 2567 2568 switch (((flag >> 6) & 0x3)) { 2569 case 0: /* Normal */ 2570 switch (AML_FIELD_ATTR(flag)) { 2571 case 0x02: /* AttribQuick */ 2572 cmdlen = 0; 2573 buflen = 0; 2574 break; 2575 case 0x04: /* AttribSendReceive */ 2576 cmdlen = 0; 2577 buflen = 1; 2578 break; 2579 case 0x06: /* AttribByte */ 2580 cmdlen = 1; 2581 buflen = 1; 2582 break; 2583 case 0x08: /* AttribWord */ 2584 cmdlen = 1; 2585 buflen = 2; 2586 break; 2587 case 0x0b: /* AttribBytes */ 2588 cmdlen = 1; 2589 buflen = alen; 2590 break; 2591 case 0x0e: /* AttribRawBytes */ 2592 cmdlen = 0; 2593 buflen = alen; 2594 break; 2595 default: 2596 aml_die("unsupported access type 0x%x", flag); 2597 break; 2598 } 2599 break; 2600 case 1: /* AttribBytes */ 2601 cmdlen = 1; 2602 buflen = AML_FIELD_ATTR(flag); 2603 break; 2604 case 2: /* AttribRawBytes */ 2605 cmdlen = 0; 2606 buflen = AML_FIELD_ATTR(flag); 2607 break; 2608 default: 2609 aml_die("unsupported access type 0x%x", flag); 2610 break; 2611 } 2612 2613 if (mode == ACPI_IOREAD) { 2614 _aml_setvalue(val, AML_OBJTYPE_BUFFER, buflen + 2, NULL); 2615 op = I2C_OP_READ_WITH_STOP; 2616 } else { 2617 op = I2C_OP_WRITE_WITH_STOP; 2618 } 2619 2620 tag = node->i2c; 2621 addr = crs->lr_i2cbus._adr; 2622 cmd = bpos >> 3; 2623 buf = val->v_buffer; 2624 2625 iic_acquire_bus(tag, 0); 2626 err = iic_exec(tag, op, addr, &cmd, cmdlen, &buf[2], buflen, 0); 2627 iic_release_bus(tag, 0); 2628 2629 /* 2630 * The ACPI specification doesn't tell us what the status 2631 * codes mean beyond implying that zero means success. So use 2632 * the error returned from the transfer. All possible error 2633 * numbers should fit in a single byte. 2634 */ 2635 buf[0] = err; 2636 } 2637 2638 #endif 2639 2640 void 2641 aml_rwindexfield(struct aml_value *fld, struct aml_value *val, int mode) 2642 { 2643 struct aml_value tmp, *ref1, *ref2; 2644 void *tbit, *vbit; 2645 int vpos, bpos, blen; 2646 int indexval; 2647 int sz, len; 2648 2649 ref2 = fld->v_field.ref2; 2650 ref1 = fld->v_field.ref1; 2651 bpos = fld->v_field.bitpos; 2652 blen = fld->v_field.bitlen; 2653 2654 memset(&tmp, 0, sizeof(tmp)); 2655 tmp.refcnt = 99; 2656 2657 /* Get field access size */ 2658 switch (AML_FIELD_ACCESS(fld->v_field.flags)) { 2659 case AML_FIELD_WORDACC: 2660 sz = 2; 2661 break; 2662 case AML_FIELD_DWORDACC: 2663 sz = 4; 2664 break; 2665 case AML_FIELD_QWORDACC: 2666 sz = 8; 2667 break; 2668 default: 2669 sz = 1; 2670 break; 2671 } 2672 2673 if (blen > aml_intlen) { 2674 if (mode == ACPI_IOREAD) { 2675 /* Read from a large field: create buffer */ 2676 _aml_setvalue(val, AML_OBJTYPE_BUFFER, 2677 (blen + 7) >> 3, 0); 2678 } 2679 vbit = val->v_buffer; 2680 } else { 2681 if (mode == ACPI_IOREAD) { 2682 /* Read from a short field: initialize integer */ 2683 _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); 2684 } 2685 vbit = &val->v_integer; 2686 } 2687 tbit = &tmp.v_integer; 2688 vpos = 0; 2689 2690 indexval = (bpos >> 3) & ~(sz - 1); 2691 bpos = bpos - (indexval << 3); 2692 2693 while (blen > 0) { 2694 len = min(blen, (sz << 3) - bpos); 2695 2696 /* Write index register */ 2697 _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, indexval, 0); 2698 aml_rwfield(ref2, 0, aml_intlen, &tmp, ACPI_IOWRITE); 2699 indexval += sz; 2700 2701 /* Read/write data register */ 2702 _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, 0, 0); 2703 if (mode == ACPI_IOWRITE) 2704 aml_bufcpy(tbit, 0, vbit, vpos, len); 2705 aml_rwfield(ref1, bpos, len, &tmp, mode); 2706 if (mode == ACPI_IOREAD) 2707 aml_bufcpy(vbit, vpos, tbit, 0, len); 2708 vpos += len; 2709 blen -= len; 2710 bpos = 0; 2711 } 2712 } 2713 2714 void 2715 aml_rwfield(struct aml_value *fld, int bpos, int blen, struct aml_value *val, 2716 int mode) 2717 { 2718 struct aml_value tmp, *ref1, *ref2; 2719 2720 ref2 = fld->v_field.ref2; 2721 ref1 = fld->v_field.ref1; 2722 if (blen > fld->v_field.bitlen) 2723 blen = fld->v_field.bitlen; 2724 2725 aml_lockfield(NULL, fld); 2726 memset(&tmp, 0, sizeof(tmp)); 2727 aml_addref(&tmp, "fld.write"); 2728 if (fld->v_field.type == AMLOP_INDEXFIELD) { 2729 aml_rwindexfield(fld, val, mode); 2730 } else if (fld->v_field.type == AMLOP_BANKFIELD) { 2731 _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, fld->v_field.ref3, 0); 2732 aml_rwfield(ref2, 0, aml_intlen, &tmp, ACPI_IOWRITE); 2733 aml_rwgen(ref1, fld->v_field.bitpos, fld->v_field.bitlen, 2734 val, mode, fld->v_field.flags); 2735 } else if (fld->v_field.type == AMLOP_FIELD) { 2736 switch (ref1->v_opregion.iospace) { 2737 case ACPI_OPREG_GPIO: 2738 aml_rwgpio(ref2, bpos, blen, val, mode, 2739 fld->v_field.flags); 2740 break; 2741 #ifndef SMALL_KERNEL 2742 case ACPI_OPREG_GSB: 2743 aml_rwgsb(ref2, fld->v_field.ref3, 2744 fld->v_field.bitpos + bpos, blen, 2745 val, mode, fld->v_field.flags); 2746 break; 2747 #endif 2748 default: 2749 aml_rwgen(ref1, fld->v_field.bitpos + bpos, blen, 2750 val, mode, fld->v_field.flags); 2751 break; 2752 } 2753 } else if (mode == ACPI_IOREAD) { 2754 /* bufferfield:read */ 2755 _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); 2756 aml_bufcpy(&val->v_integer, 0, ref1->v_buffer, 2757 fld->v_field.bitpos, fld->v_field.bitlen); 2758 } else { 2759 /* bufferfield:write */ 2760 val = aml_convert(val, AML_OBJTYPE_INTEGER, -1); 2761 aml_bufcpy(ref1->v_buffer, fld->v_field.bitpos, &val->v_integer, 2762 0, fld->v_field.bitlen); 2763 aml_delref(&val, "wrbuffld"); 2764 } 2765 aml_unlockfield(NULL, fld); 2766 } 2767 2768 /* Create Field Object data index 2769 * AMLOP_FIELD n:OpRegion NULL 2770 * AMLOP_INDEXFIELD n:Field n:Field 2771 * AMLOP_BANKFIELD n:OpRegion n:Field 2772 * AMLOP_CREATEFIELD t:Buffer NULL 2773 * AMLOP_CREATEBITFIELD t:Buffer NULL 2774 * AMLOP_CREATEBYTEFIELD t:Buffer NULL 2775 * AMLOP_CREATEWORDFIELD t:Buffer NULL 2776 * AMLOP_CREATEDWORDFIELD t:Buffer NULL 2777 * AMLOP_CREATEQWORDFIELD t:Buffer NULL 2778 * AMLOP_INDEX t:Buffer NULL 2779 */ 2780 void 2781 aml_createfield(struct aml_value *field, int opcode, 2782 struct aml_value *data, int bpos, int blen, 2783 struct aml_value *index, int indexval, int flags) 2784 { 2785 dnprintf(10, "## %s(%s): %s %.4x-%.4x\n", 2786 aml_mnem(opcode, 0), 2787 blen > aml_intlen ? "BUF" : "INT", 2788 aml_nodename(field->node), bpos, blen); 2789 if (index) { 2790 dnprintf(10, " index:%s:%.2x\n", aml_nodename(index->node), 2791 indexval); 2792 } 2793 dnprintf(10, " data:%s\n", aml_nodename(data->node)); 2794 field->type = (opcode == AMLOP_FIELD || 2795 opcode == AMLOP_INDEXFIELD || 2796 opcode == AMLOP_BANKFIELD) ? 2797 AML_OBJTYPE_FIELDUNIT : 2798 AML_OBJTYPE_BUFFERFIELD; 2799 2800 if (field->type == AML_OBJTYPE_BUFFERFIELD && 2801 data->type != AML_OBJTYPE_BUFFER) 2802 data = aml_convert(data, AML_OBJTYPE_BUFFER, -1); 2803 2804 field->v_field.type = opcode; 2805 field->v_field.bitpos = bpos; 2806 field->v_field.bitlen = blen; 2807 field->v_field.ref3 = indexval; 2808 field->v_field.ref2 = index; 2809 field->v_field.ref1 = data; 2810 field->v_field.flags = flags; 2811 2812 /* Increase reference count */ 2813 aml_addref(data, "Field.Data"); 2814 aml_addref(index, "Field.Index"); 2815 } 2816 2817 /* Parse Field/IndexField/BankField scope */ 2818 void 2819 aml_parsefieldlist(struct aml_scope *mscope, int opcode, int flags, 2820 struct aml_value *data, struct aml_value *index, int indexval) 2821 { 2822 struct aml_value *conn = NULL; 2823 struct aml_value *rv; 2824 int bpos, blen; 2825 2826 if (mscope == NULL) 2827 return; 2828 bpos = 0; 2829 while (mscope->pos < mscope->end) { 2830 switch (*mscope->pos) { 2831 case 0x00: /* ReservedField */ 2832 mscope->pos++; 2833 blen = aml_parselength(mscope); 2834 break; 2835 case 0x01: /* AccessField */ 2836 mscope->pos++; 2837 blen = 0; 2838 flags = aml_get8(mscope->pos++); 2839 flags |= aml_get8(mscope->pos++) << 8; 2840 break; 2841 case 0x02: /* ConnectionField */ 2842 mscope->pos++; 2843 blen = 0; 2844 conn = aml_parse(mscope, 'o', "Connection"); 2845 if (conn == NULL) 2846 aml_die("Could not parse connection"); 2847 conn->node = mscope->node; 2848 break; 2849 case 0x03: /* ExtendedAccessField */ 2850 mscope->pos++; 2851 blen = 0; 2852 flags = aml_get8(mscope->pos++); 2853 flags |= aml_get8(mscope->pos++) << 8; 2854 indexval = aml_get8(mscope->pos++); 2855 break; 2856 default: /* NamedField */ 2857 mscope->pos = aml_parsename(mscope->node, mscope->pos, 2858 &rv, 1); 2859 blen = aml_parselength(mscope); 2860 aml_createfield(rv, opcode, data, bpos, blen, 2861 conn ? conn : index, indexval, flags); 2862 aml_delref(&rv, 0); 2863 break; 2864 } 2865 bpos += blen; 2866 } 2867 aml_popscope(mscope); 2868 } 2869 2870 /* 2871 * Mutex/Event utility functions 2872 */ 2873 int acpi_mutex_acquire(struct aml_scope *, struct aml_value *, int); 2874 void acpi_mutex_release(struct aml_scope *, struct aml_value *); 2875 int acpi_event_wait(struct aml_scope *, struct aml_value *, int); 2876 void acpi_event_signal(struct aml_scope *, struct aml_value *); 2877 void acpi_event_reset(struct aml_scope *, struct aml_value *); 2878 2879 int 2880 acpi_mutex_acquire(struct aml_scope *scope, struct aml_value *mtx, 2881 int timeout) 2882 { 2883 if (mtx->v_mtx.owner == NULL || scope == mtx->v_mtx.owner) { 2884 /* We are now the owner */ 2885 mtx->v_mtx.owner = scope; 2886 if (mtx == aml_global_lock) { 2887 dnprintf(10,"LOCKING GLOBAL\n"); 2888 acpi_glk_enter(); 2889 } 2890 dnprintf(5,"%s acquires mutex %s\n", scope->node->name, 2891 mtx->node->name); 2892 return (0); 2893 } else if (timeout == 0) { 2894 return (-1); 2895 } 2896 /* Wait for mutex */ 2897 return (0); 2898 } 2899 2900 void 2901 acpi_mutex_release(struct aml_scope *scope, struct aml_value *mtx) 2902 { 2903 if (mtx == aml_global_lock) { 2904 dnprintf(10,"UNLOCKING GLOBAL\n"); 2905 acpi_glk_leave(); 2906 } 2907 dnprintf(5, "%s releases mutex %s\n", scope->node->name, 2908 mtx->node->name); 2909 mtx->v_mtx.owner = NULL; 2910 /* Wakeup waiters */ 2911 } 2912 2913 int 2914 acpi_event_wait(struct aml_scope *scope, struct aml_value *evt, int timeout) 2915 { 2916 /* Wait for event to occur; do work in meantime */ 2917 while (evt->v_evt.state == 0 && timeout >= 0) { 2918 if (acpi_dotask(acpi_softc)) 2919 continue; 2920 if (!cold) { 2921 if (rwsleep(evt, &acpi_softc->sc_lck, PWAIT, 2922 "acpievt", 1) == EWOULDBLOCK) { 2923 if (timeout < AML_NO_TIMEOUT) 2924 timeout -= (1000 / hz); 2925 } 2926 } else { 2927 delay(1000); 2928 if (timeout < AML_NO_TIMEOUT) 2929 timeout--; 2930 } 2931 } 2932 if (evt->v_evt.state == 0) 2933 return (-1); 2934 evt->v_evt.state--; 2935 return (0); 2936 } 2937 2938 void 2939 acpi_event_signal(struct aml_scope *scope, struct aml_value *evt) 2940 { 2941 evt->v_evt.state++; 2942 if (evt->v_evt.state > 0) 2943 wakeup_one(evt); 2944 } 2945 2946 void 2947 acpi_event_reset(struct aml_scope *scope, struct aml_value *evt) 2948 { 2949 evt->v_evt.state = 0; 2950 } 2951 2952 /* Store result value into an object */ 2953 void 2954 aml_store(struct aml_scope *scope, struct aml_value *lhs , int64_t ival, 2955 struct aml_value *rhs) 2956 { 2957 struct aml_value tmp; 2958 struct aml_node *node; 2959 int mlen; 2960 2961 /* Already set */ 2962 if (lhs == rhs || lhs == NULL || lhs->type == AML_OBJTYPE_NOTARGET) { 2963 return; 2964 } 2965 memset(&tmp, 0, sizeof(tmp)); 2966 tmp.refcnt=99; 2967 if (rhs == NULL) { 2968 rhs = _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, ival, NULL); 2969 } 2970 if (rhs->type == AML_OBJTYPE_BUFFERFIELD || 2971 rhs->type == AML_OBJTYPE_FIELDUNIT) { 2972 aml_rwfield(rhs, 0, rhs->v_field.bitlen, &tmp, ACPI_IOREAD); 2973 rhs = &tmp; 2974 } 2975 /* Store to LocalX: free value */ 2976 if (lhs->stack >= AMLOP_LOCAL0 && lhs->stack <= AMLOP_LOCAL7) 2977 aml_freevalue(lhs); 2978 2979 lhs = aml_gettgt(lhs, AMLOP_STORE); 2980 switch (lhs->type) { 2981 case AML_OBJTYPE_UNINITIALIZED: 2982 aml_copyvalue(lhs, rhs); 2983 break; 2984 case AML_OBJTYPE_BUFFERFIELD: 2985 case AML_OBJTYPE_FIELDUNIT: 2986 aml_rwfield(lhs, 0, lhs->v_field.bitlen, rhs, ACPI_IOWRITE); 2987 break; 2988 case AML_OBJTYPE_DEBUGOBJ: 2989 break; 2990 case AML_OBJTYPE_INTEGER: 2991 rhs = aml_convert(rhs, lhs->type, -1); 2992 lhs->v_integer = rhs->v_integer; 2993 aml_delref(&rhs, "store.int"); 2994 break; 2995 case AML_OBJTYPE_BUFFER: 2996 case AML_OBJTYPE_STRING: 2997 rhs = aml_convert(rhs, lhs->type, -1); 2998 if (lhs->length < rhs->length) { 2999 dnprintf(10, "Overrun! %d,%d\n", 3000 lhs->length, rhs->length); 3001 aml_freevalue(lhs); 3002 _aml_setvalue(lhs, rhs->type, rhs->length, NULL); 3003 } 3004 mlen = min(lhs->length, rhs->length); 3005 memset(lhs->v_buffer, 0x00, lhs->length); 3006 memcpy(lhs->v_buffer, rhs->v_buffer, mlen); 3007 aml_delref(&rhs, "store.bufstr"); 3008 break; 3009 case AML_OBJTYPE_PACKAGE: 3010 /* Convert to LHS type, copy into LHS */ 3011 if (rhs->type != AML_OBJTYPE_PACKAGE) { 3012 aml_die("Copy non-package into package?"); 3013 } 3014 aml_freevalue(lhs); 3015 aml_copyvalue(lhs, rhs); 3016 break; 3017 case AML_OBJTYPE_NAMEREF: 3018 node = __aml_searchname(scope->node, lhs->v_nameref, 1); 3019 if (node == NULL) { 3020 aml_die("Could not create node %s", lhs->v_nameref); 3021 } 3022 aml_copyvalue(node->value, rhs); 3023 break; 3024 case AML_OBJTYPE_METHOD: 3025 /* Method override */ 3026 if (rhs->type != AML_OBJTYPE_INTEGER) { 3027 aml_die("Overriding a method with a non-int?"); 3028 } 3029 aml_freevalue(lhs); 3030 aml_copyvalue(lhs, rhs); 3031 break; 3032 default: 3033 aml_die("Store to default type! %x\n", lhs->type); 3034 break; 3035 } 3036 aml_freevalue(&tmp); 3037 } 3038 3039 #ifdef DDB 3040 /* Disassembler routines */ 3041 void aml_disprintf(void *arg, const char *fmt, ...); 3042 3043 void 3044 aml_disprintf(void *arg, const char *fmt, ...) 3045 { 3046 va_list ap; 3047 3048 va_start(ap, fmt); 3049 vprintf(fmt, ap); 3050 va_end(ap); 3051 } 3052 3053 void 3054 aml_disasm(struct aml_scope *scope, int lvl, 3055 void (*dbprintf)(void *, const char *, ...) 3056 __attribute__((__format__(__kprintf__,2,3))), 3057 void *arg) 3058 { 3059 int pc, opcode; 3060 struct aml_opcode *htab; 3061 uint64_t ival; 3062 struct aml_value *rv, tmp; 3063 uint8_t *end = NULL; 3064 struct aml_scope ms; 3065 char *ch; 3066 char mch[64]; 3067 3068 if (dbprintf == NULL) 3069 dbprintf = aml_disprintf; 3070 3071 pc = aml_pc(scope->pos); 3072 opcode = aml_parseopcode(scope); 3073 htab = aml_findopcode(opcode); 3074 3075 /* Display address + indent */ 3076 if (lvl <= 0x7FFF) { 3077 dbprintf(arg, "%.4x ", pc); 3078 for (pc=0; pc<lvl; pc++) { 3079 dbprintf(arg, " "); 3080 } 3081 } 3082 ch = NULL; 3083 switch (opcode) { 3084 case AMLOP_NAMECHAR: 3085 scope->pos = aml_parsename(scope->node, scope->pos, &rv, 0); 3086 if (rv->type == AML_OBJTYPE_NAMEREF) { 3087 ch = "@@@"; 3088 aml_delref(&rv, "disasm"); 3089 break; 3090 } 3091 /* if this is a method, get arguments */ 3092 strlcpy(mch, aml_nodename(rv->node), sizeof(mch)); 3093 if (rv->type == AML_OBJTYPE_METHOD) { 3094 strlcat(mch, "(", sizeof(mch)); 3095 for (ival=0; 3096 ival < AML_METHOD_ARGCOUNT(rv->v_method.flags); 3097 ival++) { 3098 strlcat(mch, ival ? ", %z" : "%z", 3099 sizeof(mch)); 3100 } 3101 strlcat(mch, ")", sizeof(mch)); 3102 } 3103 aml_delref(&rv, ""); 3104 ch = mch; 3105 break; 3106 3107 case AMLOP_ZERO: 3108 case AMLOP_ONE: 3109 case AMLOP_ONES: 3110 case AMLOP_LOCAL0: 3111 case AMLOP_LOCAL1: 3112 case AMLOP_LOCAL2: 3113 case AMLOP_LOCAL3: 3114 case AMLOP_LOCAL4: 3115 case AMLOP_LOCAL5: 3116 case AMLOP_LOCAL6: 3117 case AMLOP_LOCAL7: 3118 case AMLOP_ARG0: 3119 case AMLOP_ARG1: 3120 case AMLOP_ARG2: 3121 case AMLOP_ARG3: 3122 case AMLOP_ARG4: 3123 case AMLOP_ARG5: 3124 case AMLOP_ARG6: 3125 case AMLOP_NOP: 3126 case AMLOP_REVISION: 3127 case AMLOP_DEBUG: 3128 case AMLOP_CONTINUE: 3129 case AMLOP_BREAKPOINT: 3130 case AMLOP_BREAK: 3131 ch="%m"; 3132 break; 3133 case AMLOP_BYTEPREFIX: 3134 ch="%b"; 3135 break; 3136 case AMLOP_WORDPREFIX: 3137 ch="%w"; 3138 break; 3139 case AMLOP_DWORDPREFIX: 3140 ch="%d"; 3141 break; 3142 case AMLOP_QWORDPREFIX: 3143 ch="%q"; 3144 break; 3145 case AMLOP_STRINGPREFIX: 3146 ch="%a"; 3147 break; 3148 3149 case AMLOP_INCREMENT: 3150 case AMLOP_DECREMENT: 3151 case AMLOP_LNOT: 3152 case AMLOP_SIZEOF: 3153 case AMLOP_DEREFOF: 3154 case AMLOP_REFOF: 3155 case AMLOP_OBJECTTYPE: 3156 case AMLOP_UNLOAD: 3157 case AMLOP_RELEASE: 3158 case AMLOP_SIGNAL: 3159 case AMLOP_RESET: 3160 case AMLOP_STALL: 3161 case AMLOP_SLEEP: 3162 case AMLOP_RETURN: 3163 ch="%m(%n)"; 3164 break; 3165 case AMLOP_OR: 3166 case AMLOP_ADD: 3167 case AMLOP_AND: 3168 case AMLOP_NAND: 3169 case AMLOP_XOR: 3170 case AMLOP_SHL: 3171 case AMLOP_SHR: 3172 case AMLOP_NOR: 3173 case AMLOP_MOD: 3174 case AMLOP_SUBTRACT: 3175 case AMLOP_MULTIPLY: 3176 case AMLOP_INDEX: 3177 case AMLOP_CONCAT: 3178 case AMLOP_CONCATRES: 3179 case AMLOP_TOSTRING: 3180 ch="%m(%n, %n, %n)"; 3181 break; 3182 case AMLOP_CREATEBYTEFIELD: 3183 case AMLOP_CREATEWORDFIELD: 3184 case AMLOP_CREATEDWORDFIELD: 3185 case AMLOP_CREATEQWORDFIELD: 3186 case AMLOP_CREATEBITFIELD: 3187 ch="%m(%n, %n, %N)"; 3188 break; 3189 case AMLOP_CREATEFIELD: 3190 ch="%m(%n, %n, %n, %N)"; 3191 break; 3192 case AMLOP_DIVIDE: 3193 case AMLOP_MID: 3194 ch="%m(%n, %n, %n, %n)"; 3195 break; 3196 case AMLOP_LAND: 3197 case AMLOP_LOR: 3198 case AMLOP_LNOTEQUAL: 3199 case AMLOP_LLESSEQUAL: 3200 case AMLOP_LLESS: 3201 case AMLOP_LEQUAL: 3202 case AMLOP_LGREATEREQUAL: 3203 case AMLOP_LGREATER: 3204 case AMLOP_NOT: 3205 case AMLOP_FINDSETLEFTBIT: 3206 case AMLOP_FINDSETRIGHTBIT: 3207 case AMLOP_TOINTEGER: 3208 case AMLOP_TOBUFFER: 3209 case AMLOP_TOHEXSTRING: 3210 case AMLOP_TODECSTRING: 3211 case AMLOP_FROMBCD: 3212 case AMLOP_TOBCD: 3213 case AMLOP_WAIT: 3214 case AMLOP_LOAD: 3215 case AMLOP_STORE: 3216 case AMLOP_NOTIFY: 3217 case AMLOP_COPYOBJECT: 3218 ch="%m(%n, %n)"; 3219 break; 3220 case AMLOP_ACQUIRE: 3221 ch = "%m(%n, %w)"; 3222 break; 3223 case AMLOP_CONDREFOF: 3224 ch="%m(%R, %n)"; 3225 break; 3226 case AMLOP_ALIAS: 3227 ch="%m(%n, %N)"; 3228 break; 3229 case AMLOP_NAME: 3230 ch="%m(%N, %n)"; 3231 break; 3232 case AMLOP_EVENT: 3233 ch="%m(%N)"; 3234 break; 3235 case AMLOP_MUTEX: 3236 ch = "%m(%N, %b)"; 3237 break; 3238 case AMLOP_OPREGION: 3239 ch = "%m(%N, %b, %n, %n)"; 3240 break; 3241 case AMLOP_DATAREGION: 3242 ch="%m(%N, %n, %n, %n)"; 3243 break; 3244 case AMLOP_FATAL: 3245 ch = "%m(%b, %d, %n)"; 3246 break; 3247 case AMLOP_IF: 3248 case AMLOP_WHILE: 3249 case AMLOP_SCOPE: 3250 case AMLOP_THERMALZONE: 3251 case AMLOP_VARPACKAGE: 3252 end = aml_parseend(scope); 3253 ch = "%m(%n) {\n%T}"; 3254 break; 3255 case AMLOP_DEVICE: 3256 end = aml_parseend(scope); 3257 ch = "%m(%N) {\n%T}"; 3258 break; 3259 case AMLOP_POWERRSRC: 3260 end = aml_parseend(scope); 3261 ch = "%m(%N, %b, %w) {\n%T}"; 3262 break; 3263 case AMLOP_PROCESSOR: 3264 end = aml_parseend(scope); 3265 ch = "%m(%N, %b, %d, %b) {\n%T}"; 3266 break; 3267 case AMLOP_METHOD: 3268 end = aml_parseend(scope); 3269 ch = "%m(%N, %b) {\n%T}"; 3270 break; 3271 case AMLOP_PACKAGE: 3272 end = aml_parseend(scope); 3273 ch = "%m(%b) {\n%T}"; 3274 break; 3275 case AMLOP_ELSE: 3276 end = aml_parseend(scope); 3277 ch = "%m {\n%T}"; 3278 break; 3279 case AMLOP_BUFFER: 3280 end = aml_parseend(scope); 3281 ch = "%m(%n) { %B }"; 3282 break; 3283 case AMLOP_INDEXFIELD: 3284 end = aml_parseend(scope); 3285 ch = "%m(%n, %n, %b) {\n%F}"; 3286 break; 3287 case AMLOP_BANKFIELD: 3288 end = aml_parseend(scope); 3289 ch = "%m(%n, %n, %n, %b) {\n%F}"; 3290 break; 3291 case AMLOP_FIELD: 3292 end = aml_parseend(scope); 3293 ch = "%m(%n, %b) {\n%F}"; 3294 break; 3295 case AMLOP_MATCH: 3296 ch = "%m(%n, %b, %n, %b, %n, %n)"; 3297 break; 3298 case AMLOP_LOADTABLE: 3299 ch = "%m(%n, %n, %n, %n, %n, %n)"; 3300 break; 3301 default: 3302 aml_die("opcode = %x\n", opcode); 3303 break; 3304 } 3305 3306 /* Parse printable buffer args */ 3307 while (ch && *ch) { 3308 char c; 3309 3310 if (*ch != '%') { 3311 dbprintf(arg,"%c", *(ch++)); 3312 continue; 3313 } 3314 c = *(++ch); 3315 switch (c) { 3316 case 'b': 3317 case 'w': 3318 case 'd': 3319 case 'q': 3320 /* Parse simple object: don't allocate */ 3321 aml_parsesimple(scope, c, &tmp); 3322 dbprintf(arg,"0x%llx", tmp.v_integer); 3323 break; 3324 case 'a': 3325 dbprintf(arg, "\'%s\'", scope->pos); 3326 scope->pos += strlen(scope->pos)+1; 3327 break; 3328 case 'N': 3329 /* Create Name */ 3330 rv = aml_parsesimple(scope, c, NULL); 3331 dbprintf(arg, "%s", aml_nodename(rv->node)); 3332 break; 3333 case 'm': 3334 /* display mnemonic */ 3335 dbprintf(arg, "%s", htab->mnem); 3336 break; 3337 case 'R': 3338 /* Search name */ 3339 printf("%s", aml_getname(scope->pos)); 3340 scope->pos = aml_parsename(scope->node, scope->pos, 3341 &rv, 0); 3342 aml_delref(&rv, 0); 3343 break; 3344 case 'z': 3345 case 'n': 3346 /* generic arg: recurse */ 3347 aml_disasm(scope, lvl | 0x8000, dbprintf, arg); 3348 break; 3349 case 'B': 3350 /* Buffer */ 3351 scope->pos = end; 3352 break; 3353 case 'F': 3354 /* Scope: Field List */ 3355 memset(&ms, 0, sizeof(ms)); 3356 ms.node = scope->node; 3357 ms.start = scope->pos; 3358 ms.end = end; 3359 ms.pos = ms.start; 3360 ms.type = AMLOP_FIELD; 3361 3362 while (ms.pos < ms.end) { 3363 if (*ms.pos == 0x00) { 3364 ms.pos++; 3365 aml_parselength(&ms); 3366 } else if (*ms.pos == 0x01) { 3367 ms.pos+=3; 3368 } else { 3369 ms.pos = aml_parsename(ms.node, 3370 ms.pos, &rv, 1); 3371 aml_parselength(&ms); 3372 dbprintf(arg," %s\n", 3373 aml_nodename(rv->node)); 3374 aml_delref(&rv, 0); 3375 } 3376 } 3377 3378 /* Display address and closing bracket */ 3379 dbprintf(arg,"%.4x ", aml_pc(scope->pos)); 3380 for (pc=0; pc<(lvl & 0x7FFF); pc++) { 3381 dbprintf(arg," "); 3382 } 3383 scope->pos = end; 3384 break; 3385 case 'T': 3386 /* Scope: Termlist */ 3387 memset(&ms, 0, sizeof(ms)); 3388 ms.node = scope->node; 3389 ms.start = scope->pos; 3390 ms.end = end; 3391 ms.pos = ms.start; 3392 ms.type = AMLOP_SCOPE; 3393 3394 while (ms.pos < ms.end) { 3395 aml_disasm(&ms, (lvl + 1) & 0x7FFF, 3396 dbprintf, arg); 3397 } 3398 3399 /* Display address and closing bracket */ 3400 dbprintf(arg,"%.4x ", aml_pc(scope->pos)); 3401 for (pc=0; pc<(lvl & 0x7FFF); pc++) { 3402 dbprintf(arg," "); 3403 } 3404 scope->pos = end; 3405 break; 3406 } 3407 ch++; 3408 } 3409 if (lvl <= 0x7FFF) { 3410 dbprintf(arg,"\n"); 3411 } 3412 } 3413 #endif /* DDB */ 3414 3415 int aml_busy; 3416 3417 /* Evaluate method or buffervalue objects */ 3418 struct aml_value * 3419 aml_eval(struct aml_scope *scope, struct aml_value *my_ret, int ret_type, 3420 int argc, struct aml_value *argv) 3421 { 3422 struct aml_value *tmp = my_ret; 3423 struct aml_scope *ms; 3424 int idx; 3425 3426 switch (tmp->type) { 3427 case AML_OBJTYPE_NAMEREF: 3428 my_ret = aml_seterror(scope, "Undefined name: %s", 3429 aml_getname(my_ret->v_nameref)); 3430 break; 3431 case AML_OBJTYPE_METHOD: 3432 dnprintf(10,"\n--== Eval Method [%s, %d args] to %c ==--\n", 3433 aml_nodename(tmp->node), 3434 AML_METHOD_ARGCOUNT(tmp->v_method.flags), 3435 ret_type); 3436 ms = aml_pushscope(scope, tmp, tmp->node, AMLOP_METHOD); 3437 3438 /* Parse method arguments */ 3439 for (idx=0; idx<AML_METHOD_ARGCOUNT(tmp->v_method.flags); idx++) { 3440 struct aml_value *sp; 3441 3442 sp = aml_getstack(ms, AMLOP_ARG0+idx); 3443 if (argv) { 3444 aml_copyvalue(sp, &argv[idx]); 3445 } else { 3446 _aml_setvalue(sp, AML_OBJTYPE_OBJREF, AMLOP_ARG0 + idx, 0); 3447 sp->v_objref.ref = aml_parse(scope, 't', "ARGX"); 3448 } 3449 } 3450 #ifdef ACPI_DEBUG 3451 aml_showstack(ms); 3452 #endif 3453 3454 /* Evaluate method scope */ 3455 aml_root.start = tmp->v_method.base; 3456 if (tmp->v_method.fneval != NULL) { 3457 my_ret = tmp->v_method.fneval(ms, NULL); 3458 } else { 3459 aml_parse(ms, 'T', "METHEVAL"); 3460 my_ret = ms->retv; 3461 } 3462 dnprintf(10,"\n--==Finished evaluating method: %s %c\n", 3463 aml_nodename(tmp->node), ret_type); 3464 #ifdef ACPI_DEBUG 3465 aml_showvalue(my_ret); 3466 aml_showstack(ms); 3467 #endif 3468 aml_popscope(ms); 3469 break; 3470 case AML_OBJTYPE_BUFFERFIELD: 3471 case AML_OBJTYPE_FIELDUNIT: 3472 my_ret = aml_allocvalue(0,0,NULL); 3473 dnprintf(20,"quick: Convert Bufferfield to %c %p\n", 3474 ret_type, my_ret); 3475 aml_rwfield(tmp, 0, tmp->v_field.bitlen, my_ret, ACPI_IOREAD); 3476 break; 3477 } 3478 if (ret_type == 'i' && my_ret && my_ret->type != AML_OBJTYPE_INTEGER) { 3479 #ifndef SMALL_KERNEL 3480 aml_showvalue(my_ret); 3481 #endif 3482 aml_die("Not Integer"); 3483 } 3484 return my_ret; 3485 } 3486 3487 /* 3488 * The following opcodes produce return values 3489 * TOSTRING -> Str 3490 * TOHEXSTR -> Str 3491 * TODECSTR -> Str 3492 * STRINGPFX -> Str 3493 * BUFFER -> Buf 3494 * CONCATRES -> Buf 3495 * TOBUFFER -> Buf 3496 * MID -> Buf|Str 3497 * CONCAT -> Buf|Str 3498 * PACKAGE -> Pkg 3499 * VARPACKAGE -> Pkg 3500 * LOCALx -> Obj 3501 * ARGx -> Obj 3502 * NAMECHAR -> Obj 3503 * REFOF -> ObjRef 3504 * INDEX -> ObjRef 3505 * DEREFOF -> DataRefObj 3506 * COPYOBJECT -> DataRefObj 3507 * STORE -> DataRefObj 3508 3509 * ZERO -> Int 3510 * ONE -> Int 3511 * ONES -> Int 3512 * REVISION -> Int 3513 * B/W/D/Q -> Int 3514 * OR -> Int 3515 * AND -> Int 3516 * ADD -> Int 3517 * NAND -> Int 3518 * XOR -> Int 3519 * SHL -> Int 3520 * SHR -> Int 3521 * NOR -> Int 3522 * MOD -> Int 3523 * SUBTRACT -> Int 3524 * MULTIPLY -> Int 3525 * DIVIDE -> Int 3526 * NOT -> Int 3527 * TOBCD -> Int 3528 * FROMBCD -> Int 3529 * FSLEFTBIT -> Int 3530 * FSRIGHTBIT -> Int 3531 * INCREMENT -> Int 3532 * DECREMENT -> Int 3533 * TOINTEGER -> Int 3534 * MATCH -> Int 3535 * SIZEOF -> Int 3536 * OBJECTTYPE -> Int 3537 * TIMER -> Int 3538 3539 * CONDREFOF -> Bool 3540 * ACQUIRE -> Bool 3541 * WAIT -> Bool 3542 * LNOT -> Bool 3543 * LAND -> Bool 3544 * LOR -> Bool 3545 * LLESS -> Bool 3546 * LEQUAL -> Bool 3547 * LGREATER -> Bool 3548 * LNOTEQUAL -> Bool 3549 * LLESSEQUAL -> Bool 3550 * LGREATEREQ -> Bool 3551 3552 * LOADTABLE -> DDB 3553 * DEBUG -> Debug 3554 3555 * The following opcodes do not generate a return value: 3556 * NOP 3557 * BREAKPOINT 3558 * RELEASE 3559 * RESET 3560 * SIGNAL 3561 * NAME 3562 * ALIAS 3563 * OPREGION 3564 * DATAREGION 3565 * EVENT 3566 * MUTEX 3567 * SCOPE 3568 * DEVICE 3569 * THERMALZONE 3570 * POWERRSRC 3571 * PROCESSOR 3572 * METHOD 3573 * CREATEFIELD 3574 * CREATEBITFIELD 3575 * CREATEBYTEFIELD 3576 * CREATEWORDFIELD 3577 * CREATEDWORDFIELD 3578 * CREATEQWORDFIELD 3579 * FIELD 3580 * INDEXFIELD 3581 * BANKFIELD 3582 * STALL 3583 * SLEEP 3584 * NOTIFY 3585 * FATAL 3586 * LOAD 3587 * UNLOAD 3588 * IF 3589 * ELSE 3590 * WHILE 3591 * BREAK 3592 * CONTINUE 3593 */ 3594 3595 /* Parse a simple object from AML Bytestream */ 3596 struct aml_value * 3597 aml_parsesimple(struct aml_scope *scope, char ch, struct aml_value *rv) 3598 { 3599 if (rv == NULL) 3600 rv = aml_allocvalue(0,0,NULL); 3601 switch (ch) { 3602 case AML_ARG_REVISION: 3603 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, AML_REVISION, NULL); 3604 break; 3605 case AML_ARG_DEBUG: 3606 _aml_setvalue(rv, AML_OBJTYPE_DEBUGOBJ, 0, NULL); 3607 break; 3608 case AML_ARG_BYTE: 3609 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3610 aml_get8(scope->pos), NULL); 3611 scope->pos += 1; 3612 break; 3613 case AML_ARG_WORD: 3614 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3615 aml_get16(scope->pos), NULL); 3616 scope->pos += 2; 3617 break; 3618 case AML_ARG_DWORD: 3619 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3620 aml_get32(scope->pos), NULL); 3621 scope->pos += 4; 3622 break; 3623 case AML_ARG_QWORD: 3624 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3625 aml_get64(scope->pos), NULL); 3626 scope->pos += 8; 3627 break; 3628 case AML_ARG_STRING: 3629 _aml_setvalue(rv, AML_OBJTYPE_STRING, -1, scope->pos); 3630 scope->pos += rv->length+1; 3631 break; 3632 } 3633 return rv; 3634 } 3635 3636 /* 3637 * Main Opcode Parser/Evaluator 3638 * 3639 * ret_type is expected type for return value 3640 * 'o' = Data Object (Int/Str/Buf/Pkg/Name) 3641 * 'i' = Integer 3642 * 't' = TermArg (Int/Str/Buf/Pkg) 3643 * 'r' = Target (NamedObj/Local/Arg/Null) 3644 * 'S' = SuperName (NamedObj/Local/Arg) 3645 * 'T' = TermList 3646 */ 3647 #define aml_debugger(x) 3648 3649 int maxdp; 3650 3651 struct aml_value * 3652 aml_gettgt(struct aml_value *val, int opcode) 3653 { 3654 while (val && val->type == AML_OBJTYPE_OBJREF) { 3655 val = val->v_objref.ref; 3656 } 3657 return val; 3658 } 3659 3660 struct aml_value * 3661 aml_seterror(struct aml_scope *scope, const char *fmt, ...) 3662 { 3663 va_list ap; 3664 3665 va_start(ap, fmt); 3666 printf("### AML PARSE ERROR (0x%x): ", aml_pc(scope->pos)); 3667 vprintf(fmt, ap); 3668 printf("\n"); 3669 va_end(ap); 3670 3671 while (scope) { 3672 scope->pos = scope->end; 3673 scope = scope->parent; 3674 } 3675 aml_error++; 3676 return aml_allocvalue(AML_OBJTYPE_INTEGER, 0, 0); 3677 } 3678 3679 struct aml_value * 3680 aml_loadtable(struct acpi_softc *sc, const char *signature, 3681 const char *oemid, const char *oemtableid, const char *rootpath, 3682 const char *parameterpath, struct aml_value *parameterdata) 3683 { 3684 struct acpi_table_header *hdr; 3685 struct acpi_dsdt *p_dsdt; 3686 struct acpi_q *entry; 3687 3688 if (strlen(rootpath) > 0) 3689 aml_die("LoadTable: RootPathString unsupported"); 3690 if (strlen(parameterpath) > 0) 3691 aml_die("LoadTable: ParameterPathString unsupported"); 3692 3693 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 3694 hdr = entry->q_table; 3695 if (strncmp(hdr->signature, signature, 3696 sizeof(hdr->signature)) == 0 && 3697 strncmp(hdr->oemid, oemid, sizeof(hdr->oemid)) == 0 && 3698 strncmp(hdr->oemtableid, oemtableid, 3699 sizeof(hdr->oemtableid)) == 0) { 3700 p_dsdt = entry->q_table; 3701 acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length - 3702 sizeof(p_dsdt->hdr)); 3703 return aml_allocvalue(AML_OBJTYPE_DDBHANDLE, 0, 0); 3704 } 3705 } 3706 3707 return aml_allocvalue(AML_OBJTYPE_INTEGER, 0, 0); 3708 } 3709 3710 /* Load new SSDT scope from memory address */ 3711 struct aml_scope * 3712 aml_load(struct acpi_softc *sc, struct aml_scope *scope, 3713 struct aml_value *rgn, struct aml_value *ddb) 3714 { 3715 struct acpi_q *entry; 3716 struct acpi_dsdt *p_ssdt; 3717 struct aml_value tmp; 3718 3719 ddb->type = AML_OBJTYPE_DDBHANDLE; 3720 ddb->v_integer = 0; 3721 3722 memset(&tmp, 0, sizeof(tmp)); 3723 if (rgn->type != AML_OBJTYPE_OPREGION || 3724 rgn->v_opregion.iospace != GAS_SYSTEM_MEMORY) 3725 goto fail; 3726 3727 /* Load SSDT from memory */ 3728 entry = acpi_maptable(sc, rgn->v_opregion.iobase, "SSDT", NULL, NULL, 1); 3729 if (entry == NULL) 3730 goto fail; 3731 3732 dnprintf(10, "%s: loaded SSDT %s @ %llx\n", sc->sc_dev.dv_xname, 3733 aml_nodename(rgn->node), rgn->v_opregion.iobase); 3734 ddb->v_integer = entry->q_id; 3735 3736 p_ssdt = entry->q_table; 3737 tmp.v_buffer = p_ssdt->aml; 3738 tmp.length = p_ssdt->hdr_length - sizeof(p_ssdt->hdr); 3739 3740 return aml_pushscope(scope, &tmp, scope->node, 3741 AMLOP_LOAD); 3742 fail: 3743 printf("%s: unable to load %s\n", sc->sc_dev.dv_xname, 3744 aml_nodename(rgn->node)); 3745 return NULL; 3746 } 3747 3748 struct aml_value * 3749 aml_parse(struct aml_scope *scope, int ret_type, const char *stype) 3750 { 3751 int opcode, idx, pc; 3752 struct aml_opcode *htab; 3753 struct aml_value *opargs[8], *my_ret, *rv; 3754 struct aml_scope *mscope, *iscope; 3755 uint8_t *start, *end; 3756 const char *ch; 3757 int64_t ival; 3758 struct timespec ts; 3759 3760 my_ret = NULL; 3761 if (scope == NULL || scope->pos >= scope->end) { 3762 return NULL; 3763 } 3764 if (odp++ > 125) 3765 panic("depth"); 3766 if (odp > maxdp) { 3767 maxdp = odp; 3768 dnprintf(10, "max depth: %d\n", maxdp); 3769 } 3770 end = NULL; 3771 iscope = scope; 3772 start: 3773 /* --== Stage 0: Get Opcode ==-- */ 3774 start = scope->pos; 3775 pc = aml_pc(scope->pos); 3776 aml_debugger(scope); 3777 3778 opcode = aml_parseopcode(scope); 3779 htab = aml_findopcode(opcode); 3780 if (htab == NULL) { 3781 /* No opcode handler */ 3782 aml_die("Unknown opcode: %.4x @ %.4x", opcode, pc); 3783 } 3784 dnprintf(18,"%.4x %s\n", pc, aml_mnem(opcode, scope->pos)); 3785 3786 /* --== Stage 1: Process opcode arguments ==-- */ 3787 memset(opargs, 0, sizeof(opargs)); 3788 idx = 0; 3789 for (ch = htab->args; *ch; ch++) { 3790 rv = NULL; 3791 switch (*ch) { 3792 case AML_ARG_OBJLEN: 3793 end = aml_parseend(scope); 3794 break; 3795 case AML_ARG_IFELSE: 3796 /* Special Case: IF-ELSE:piTbpT or IF:piT */ 3797 ch = (*end == AMLOP_ELSE && end < scope->end) ? 3798 "-TbpT" : "-T"; 3799 break; 3800 3801 /* Complex arguments */ 3802 case 's': 3803 case 'S': 3804 case AML_ARG_TARGET: 3805 case AML_ARG_TERMOBJ: 3806 case AML_ARG_INTEGER: 3807 if (*ch == 'r' && *scope->pos == AMLOP_ZERO) { 3808 /* Special case: NULL Target */ 3809 rv = aml_allocvalue(AML_OBJTYPE_NOTARGET, 0, NULL); 3810 scope->pos++; 3811 } 3812 else { 3813 rv = aml_parse(scope, *ch, htab->mnem); 3814 if (rv == NULL || aml_error) 3815 goto parse_error; 3816 } 3817 break; 3818 3819 /* Simple arguments */ 3820 case AML_ARG_BUFFER: 3821 case AML_ARG_METHOD: 3822 case AML_ARG_FIELDLIST: 3823 case AML_ARG_TERMOBJLIST: 3824 rv = aml_allocvalue(AML_OBJTYPE_SCOPE, 0, NULL); 3825 rv->v_buffer = scope->pos; 3826 rv->length = end - scope->pos; 3827 scope->pos = end; 3828 break; 3829 case AML_ARG_CONST: 3830 rv = aml_allocvalue(AML_OBJTYPE_INTEGER, 3831 (char)opcode, NULL); 3832 break; 3833 case AML_ARG_CREATENAME: 3834 scope->pos = aml_parsename(scope->node, scope->pos, 3835 &rv, 1); 3836 break; 3837 case AML_ARG_SEARCHNAME: 3838 scope->pos = aml_parsename(scope->node, scope->pos, 3839 &rv, 0); 3840 break; 3841 case AML_ARG_BYTE: 3842 case AML_ARG_WORD: 3843 case AML_ARG_DWORD: 3844 case AML_ARG_QWORD: 3845 case AML_ARG_DEBUG: 3846 case AML_ARG_STRING: 3847 case AML_ARG_REVISION: 3848 rv = aml_parsesimple(scope, *ch, NULL); 3849 break; 3850 case AML_ARG_STKLOCAL: 3851 case AML_ARG_STKARG: 3852 rv = aml_getstack(scope, opcode); 3853 break; 3854 default: 3855 aml_die("Unknown arg type: %c\n", *ch); 3856 break; 3857 } 3858 if (rv != NULL) 3859 opargs[idx++] = rv; 3860 } 3861 3862 /* --== Stage 2: Process opcode ==-- */ 3863 ival = 0; 3864 my_ret = NULL; 3865 mscope = NULL; 3866 switch (opcode) { 3867 case AMLOP_NOP: 3868 case AMLOP_BREAKPOINT: 3869 break; 3870 case AMLOP_LOCAL0: 3871 case AMLOP_LOCAL1: 3872 case AMLOP_LOCAL2: 3873 case AMLOP_LOCAL3: 3874 case AMLOP_LOCAL4: 3875 case AMLOP_LOCAL5: 3876 case AMLOP_LOCAL6: 3877 case AMLOP_LOCAL7: 3878 case AMLOP_ARG0: 3879 case AMLOP_ARG1: 3880 case AMLOP_ARG2: 3881 case AMLOP_ARG3: 3882 case AMLOP_ARG4: 3883 case AMLOP_ARG5: 3884 case AMLOP_ARG6: 3885 my_ret = opargs[0]; 3886 aml_addref(my_ret, htab->mnem); 3887 break; 3888 case AMLOP_NAMECHAR: 3889 /* opargs[0] = named object (node != NULL), or nameref */ 3890 my_ret = opargs[0]; 3891 if (scope->type == AMLOP_PACKAGE) { 3892 /* Special case for package */ 3893 if (my_ret->type == AML_OBJTYPE_NAMEREF) 3894 my_ret = aml_allocvalue(AML_OBJTYPE_STRING, -1, 3895 aml_getname(my_ret->v_nameref)); 3896 else if (my_ret->node) 3897 my_ret = aml_allocvalue(AML_OBJTYPE_STRING, -1, 3898 aml_nodename(my_ret->node)); 3899 break; 3900 } 3901 if (my_ret->type == AML_OBJTYPE_OBJREF) { 3902 my_ret = my_ret->v_objref.ref; 3903 aml_addref(my_ret, "de-alias"); 3904 } 3905 if (ret_type == 'i' || ret_type == 't' || ret_type == 'T') { 3906 /* Return TermArg or Integer: Evaluate object */ 3907 my_ret = aml_eval(scope, my_ret, ret_type, 0, NULL); 3908 } else if (my_ret->type == AML_OBJTYPE_METHOD) { 3909 /* This should only happen with CondRef */ 3910 dnprintf(12,"non-termarg method : %s\n", stype); 3911 aml_addref(my_ret, "zoom"); 3912 } 3913 break; 3914 3915 case AMLOP_ZERO: 3916 case AMLOP_ONE: 3917 case AMLOP_ONES: 3918 case AMLOP_DEBUG: 3919 case AMLOP_REVISION: 3920 case AMLOP_BYTEPREFIX: 3921 case AMLOP_WORDPREFIX: 3922 case AMLOP_DWORDPREFIX: 3923 case AMLOP_QWORDPREFIX: 3924 case AMLOP_STRINGPREFIX: 3925 my_ret = opargs[0]; 3926 break; 3927 3928 case AMLOP_BUFFER: 3929 /* Buffer: iB => Buffer */ 3930 my_ret = aml_allocvalue(AML_OBJTYPE_BUFFER, 3931 opargs[0]->v_integer, NULL); 3932 memcpy(my_ret->v_buffer, opargs[1]->v_buffer, 3933 opargs[1]->length); 3934 break; 3935 case AMLOP_PACKAGE: 3936 case AMLOP_VARPACKAGE: 3937 /* Package/VarPackage: bT/iT => Package */ 3938 my_ret = aml_allocvalue(AML_OBJTYPE_PACKAGE, 3939 opargs[0]->v_integer, 0); 3940 mscope = aml_pushscope(scope, opargs[1], scope->node, 3941 AMLOP_PACKAGE); 3942 3943 /* Recursively parse package contents */ 3944 for (idx=0; idx<my_ret->length; idx++) { 3945 rv = aml_parse(mscope, 'o', "Package"); 3946 if (rv != NULL) { 3947 aml_delref(&my_ret->v_package[idx], "pkginit"); 3948 my_ret->v_package[idx] = rv; 3949 } 3950 } 3951 aml_popscope(mscope); 3952 mscope = NULL; 3953 break; 3954 3955 /* Math/Logical operations */ 3956 case AMLOP_OR: 3957 case AMLOP_ADD: 3958 case AMLOP_AND: 3959 case AMLOP_NAND: 3960 case AMLOP_XOR: 3961 case AMLOP_SHL: 3962 case AMLOP_SHR: 3963 case AMLOP_NOR: 3964 case AMLOP_MOD: 3965 case AMLOP_SUBTRACT: 3966 case AMLOP_MULTIPLY: 3967 /* XXX: iir => I */ 3968 ival = aml_evalexpr(opargs[0]->v_integer, 3969 opargs[1]->v_integer, opcode); 3970 aml_store(scope, opargs[2], ival, NULL); 3971 break; 3972 case AMLOP_DIVIDE: 3973 /* Divide: iirr => I */ 3974 if (opargs[1]->v_integer == 0) { 3975 my_ret = aml_seterror(scope, "Divide by Zero!"); 3976 break; 3977 } 3978 ival = aml_evalexpr(opargs[0]->v_integer, 3979 opargs[1]->v_integer, AMLOP_MOD); 3980 aml_store(scope, opargs[2], ival, NULL); 3981 3982 ival = aml_evalexpr(opargs[0]->v_integer, 3983 opargs[1]->v_integer, AMLOP_DIVIDE); 3984 aml_store(scope, opargs[3], ival, NULL); 3985 break; 3986 case AMLOP_NOT: 3987 case AMLOP_TOBCD: 3988 case AMLOP_FROMBCD: 3989 case AMLOP_FINDSETLEFTBIT: 3990 case AMLOP_FINDSETRIGHTBIT: 3991 /* XXX: ir => I */ 3992 ival = aml_evalexpr(opargs[0]->v_integer, 0, opcode); 3993 aml_store(scope, opargs[1], ival, NULL); 3994 break; 3995 case AMLOP_INCREMENT: 3996 case AMLOP_DECREMENT: 3997 /* Inc/Dec: S => I */ 3998 my_ret = aml_eval(scope, opargs[0], AML_ARG_INTEGER, 0, NULL); 3999 ival = aml_evalexpr(my_ret->v_integer, 1, opcode); 4000 aml_store(scope, opargs[0], ival, NULL); 4001 break; 4002 case AMLOP_LNOT: 4003 /* LNot: i => Bool */ 4004 ival = aml_evalexpr(opargs[0]->v_integer, 0, opcode); 4005 break; 4006 case AMLOP_LOR: 4007 case AMLOP_LAND: 4008 /* XXX: ii => Bool */ 4009 ival = aml_evalexpr(opargs[0]->v_integer, 4010 opargs[1]->v_integer, opcode); 4011 break; 4012 case AMLOP_LLESS: 4013 case AMLOP_LEQUAL: 4014 case AMLOP_LGREATER: 4015 case AMLOP_LNOTEQUAL: 4016 case AMLOP_LLESSEQUAL: 4017 case AMLOP_LGREATEREQUAL: 4018 /* XXX: tt => Bool */ 4019 ival = aml_compare(opargs[0], opargs[1], opcode); 4020 break; 4021 4022 /* Reference/Store operations */ 4023 case AMLOP_CONDREFOF: 4024 /* CondRef: rr => I */ 4025 ival = 0; 4026 if (opargs[0]->node != NULL) { 4027 /* Create Object Reference */ 4028 rv = aml_allocvalue(AML_OBJTYPE_OBJREF, opcode, 4029 opargs[0]); 4030 aml_addref(opargs[0], "CondRef"); 4031 aml_store(scope, opargs[1], 0, rv); 4032 aml_delref(&rv, 0); 4033 4034 /* Mark that we found it */ 4035 ival = -1; 4036 } 4037 break; 4038 case AMLOP_REFOF: 4039 /* RefOf: r => ObjRef */ 4040 my_ret = aml_allocvalue(AML_OBJTYPE_OBJREF, opcode, opargs[0]); 4041 aml_addref(my_ret->v_objref.ref, "RefOf"); 4042 break; 4043 case AMLOP_INDEX: 4044 /* Index: tir => ObjRef */ 4045 idx = opargs[1]->v_integer; 4046 /* Reading past the end of the array? - Ignore */ 4047 if (idx >= opargs[0]->length || idx < 0) 4048 break; 4049 switch (opargs[0]->type) { 4050 case AML_OBJTYPE_PACKAGE: 4051 /* Don't set opargs[0] to NULL */ 4052 if (ret_type == 't' || ret_type == 'i' || ret_type == 'T') { 4053 my_ret = opargs[0]->v_package[idx]; 4054 aml_addref(my_ret, "Index.Package"); 4055 } else { 4056 my_ret = aml_allocvalue(AML_OBJTYPE_OBJREF, AMLOP_PACKAGE, 4057 opargs[0]->v_package[idx]); 4058 aml_addref(my_ret->v_objref.ref, 4059 "Index.Package"); 4060 } 4061 break; 4062 case AML_OBJTYPE_BUFFER: 4063 case AML_OBJTYPE_STRING: 4064 case AML_OBJTYPE_INTEGER: 4065 rv = aml_convert(opargs[0], AML_OBJTYPE_BUFFER, -1); 4066 if (ret_type == 't' || ret_type == 'i' || ret_type == 'T') { 4067 dnprintf(12,"Index.Buf Term: %d = %x\n", 4068 idx, rv->v_buffer[idx]); 4069 ival = rv->v_buffer[idx]; 4070 } else { 4071 dnprintf(12, "Index.Buf Targ\n"); 4072 my_ret = aml_allocvalue(0,0,NULL); 4073 aml_createfield(my_ret, AMLOP_INDEX, rv, 4074 8 * idx, 8, NULL, 0, AML_FIELD_BYTEACC); 4075 } 4076 aml_delref(&rv, "Index.BufStr"); 4077 break; 4078 default: 4079 aml_die("Unknown index : %x\n", opargs[0]->type); 4080 break; 4081 } 4082 aml_store(scope, opargs[2], ival, my_ret); 4083 break; 4084 case AMLOP_DEREFOF: 4085 /* DerefOf: t:ObjRef => DataRefObj */ 4086 if (opargs[0]->type == AML_OBJTYPE_OBJREF) { 4087 my_ret = opargs[0]->v_objref.ref; 4088 aml_addref(my_ret, "DerefOf"); 4089 } else { 4090 my_ret = opargs[0]; 4091 //aml_addref(my_ret, "DerefOf"); 4092 } 4093 break; 4094 case AMLOP_COPYOBJECT: 4095 /* CopyObject: t:DataRefObj, s:implename => DataRefObj */ 4096 my_ret = opargs[0]; 4097 aml_freevalue(opargs[1]); 4098 aml_copyvalue(opargs[1], opargs[0]); 4099 break; 4100 case AMLOP_STORE: 4101 /* Store: t:DataRefObj, S:upername => DataRefObj */ 4102 my_ret = opargs[0]; 4103 aml_store(scope, opargs[1], 0, opargs[0]); 4104 break; 4105 4106 /* Conversion */ 4107 case AMLOP_TOINTEGER: 4108 /* Source:CData, Result => Integer */ 4109 my_ret = aml_convert(opargs[0], AML_OBJTYPE_INTEGER, -1); 4110 aml_store(scope, opargs[1], 0, my_ret); 4111 break; 4112 case AMLOP_TOBUFFER: 4113 /* Source:CData, Result => Buffer */ 4114 my_ret = aml_convert(opargs[0], AML_OBJTYPE_BUFFER, -1); 4115 aml_store(scope, opargs[1], 0, my_ret); 4116 break; 4117 case AMLOP_TOHEXSTRING: 4118 /* Source:CData, Result => String */ 4119 my_ret = aml_convert(opargs[0], AML_OBJTYPE_HEXSTRING, -1); 4120 aml_store(scope, opargs[1], 0, my_ret); 4121 break; 4122 case AMLOP_TODECSTRING: 4123 /* Source:CData, Result => String */ 4124 my_ret = aml_convert(opargs[0], AML_OBJTYPE_DECSTRING, -1); 4125 aml_store(scope, opargs[1], 0, my_ret); 4126 break; 4127 case AMLOP_TOSTRING: 4128 /* Source:B, Length:I, Result => String */ 4129 my_ret = aml_convert(opargs[0], AML_OBJTYPE_STRING, 4130 opargs[1]->v_integer); 4131 aml_store(scope, opargs[2], 0, my_ret); 4132 break; 4133 case AMLOP_CONCAT: 4134 /* Source1:CData, Source2:CData, Result => CData */ 4135 my_ret = aml_concat(opargs[0], opargs[1]); 4136 aml_store(scope, opargs[2], 0, my_ret); 4137 break; 4138 case AMLOP_CONCATRES: 4139 /* Concat two resource buffers: buf1, buf2, result => Buffer */ 4140 my_ret = aml_concatres(opargs[0], opargs[1]); 4141 aml_store(scope, opargs[2], 0, my_ret); 4142 break; 4143 case AMLOP_MID: 4144 /* Source:BS, Index:I, Length:I, Result => BS */ 4145 my_ret = aml_mid(opargs[0], opargs[1]->v_integer, 4146 opargs[2]->v_integer); 4147 aml_store(scope, opargs[3], 0, my_ret); 4148 break; 4149 case AMLOP_MATCH: 4150 /* Match: Pkg, Op1, Val1, Op2, Val2, Index */ 4151 ival = aml_match(opargs[0], opargs[5]->v_integer, 4152 opargs[1]->v_integer, opargs[2]->v_integer, 4153 opargs[3]->v_integer, opargs[4]->v_integer); 4154 break; 4155 case AMLOP_SIZEOF: 4156 /* Sizeof: S => i */ 4157 rv = aml_gettgt(opargs[0], opcode); 4158 ival = rv->length; 4159 break; 4160 case AMLOP_OBJECTTYPE: 4161 /* ObjectType: S => i */ 4162 rv = aml_gettgt(opargs[0], opcode); 4163 ival = rv->type; 4164 break; 4165 4166 /* Mutex/Event handlers */ 4167 case AMLOP_ACQUIRE: 4168 /* Acquire: Sw => Bool */ 4169 rv = aml_gettgt(opargs[0], opcode); 4170 ival = acpi_mutex_acquire(scope, rv, 4171 opargs[1]->v_integer); 4172 break; 4173 case AMLOP_RELEASE: 4174 /* Release: S */ 4175 rv = aml_gettgt(opargs[0], opcode); 4176 acpi_mutex_release(scope, rv); 4177 break; 4178 case AMLOP_WAIT: 4179 /* Wait: Si => Bool */ 4180 rv = aml_gettgt(opargs[0], opcode); 4181 ival = acpi_event_wait(scope, rv, 4182 opargs[1]->v_integer); 4183 break; 4184 case AMLOP_RESET: 4185 /* Reset: S */ 4186 rv = aml_gettgt(opargs[0], opcode); 4187 acpi_event_reset(scope, rv); 4188 break; 4189 case AMLOP_SIGNAL: 4190 /* Signal: S */ 4191 rv = aml_gettgt(opargs[0], opcode); 4192 acpi_event_signal(scope, rv); 4193 break; 4194 4195 /* Named objects */ 4196 case AMLOP_NAME: 4197 /* Name: Nt */ 4198 rv = opargs[0]; 4199 aml_freevalue(rv); 4200 aml_copyvalue(rv, opargs[1]); 4201 break; 4202 case AMLOP_ALIAS: 4203 /* Alias: nN */ 4204 rv = _aml_setvalue(opargs[1], AML_OBJTYPE_OBJREF, opcode, 0); 4205 rv->v_objref.ref = aml_gettgt(opargs[0], opcode); 4206 aml_addref(rv->v_objref.ref, "Alias"); 4207 break; 4208 case AMLOP_OPREGION: 4209 /* OpRegion: Nbii */ 4210 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_OPREGION, 0, 0); 4211 rv->v_opregion.iospace = opargs[1]->v_integer; 4212 rv->v_opregion.iobase = opargs[2]->v_integer; 4213 rv->v_opregion.iolen = opargs[3]->v_integer; 4214 rv->v_opregion.flag = 0; 4215 break; 4216 case AMLOP_DATAREGION: 4217 /* DataTableRegion: N,t:SigStr,t:OemIDStr,t:OemTableIDStr */ 4218 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_OPREGION, 0, 0); 4219 rv->v_opregion.iospace = GAS_SYSTEM_MEMORY; 4220 rv->v_opregion.iobase = 0; 4221 rv->v_opregion.iolen = 0; 4222 aml_die("AML-DataTableRegion\n"); 4223 break; 4224 case AMLOP_EVENT: 4225 /* Event: N */ 4226 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_EVENT, 0, 0); 4227 rv->v_evt.state = 0; 4228 break; 4229 case AMLOP_MUTEX: 4230 /* Mutex: Nw */ 4231 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_MUTEX, 0, 0); 4232 rv->v_mtx.synclvl = opargs[1]->v_integer; 4233 break; 4234 case AMLOP_SCOPE: 4235 /* Scope: NT */ 4236 rv = opargs[0]; 4237 if (rv->type == AML_OBJTYPE_NAMEREF) { 4238 printf("Undefined scope: %s\n", aml_getname(rv->v_nameref)); 4239 break; 4240 } 4241 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 4242 break; 4243 case AMLOP_DEVICE: 4244 /* Device: NT */ 4245 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_DEVICE, 0, 0); 4246 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 4247 break; 4248 case AMLOP_THERMALZONE: 4249 /* ThermalZone: NT */ 4250 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_THERMZONE, 0, 0); 4251 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 4252 break; 4253 case AMLOP_POWERRSRC: 4254 /* PowerRsrc: NbwT */ 4255 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_POWERRSRC, 0, 0); 4256 rv->v_powerrsrc.pwr_level = opargs[1]->v_integer; 4257 rv->v_powerrsrc.pwr_order = opargs[2]->v_integer; 4258 mscope = aml_pushscope(scope, opargs[3], rv->node, opcode); 4259 break; 4260 case AMLOP_PROCESSOR: 4261 /* Processor: NbdbT */ 4262 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_PROCESSOR, 0, 0); 4263 rv->v_processor.proc_id = opargs[1]->v_integer; 4264 rv->v_processor.proc_addr = opargs[2]->v_integer; 4265 rv->v_processor.proc_len = opargs[3]->v_integer; 4266 mscope = aml_pushscope(scope, opargs[4], rv->node, opcode); 4267 break; 4268 case AMLOP_METHOD: 4269 /* Method: NbM */ 4270 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_METHOD, 0, 0); 4271 rv->v_method.flags = opargs[1]->v_integer; 4272 rv->v_method.start = opargs[2]->v_buffer; 4273 rv->v_method.end = rv->v_method.start + opargs[2]->length; 4274 rv->v_method.base = aml_root.start; 4275 break; 4276 4277 /* Field objects */ 4278 case AMLOP_CREATEFIELD: 4279 /* Source:B, BitIndex:I, NumBits:I, FieldName */ 4280 rv = _aml_setvalue(opargs[3], AML_OBJTYPE_BUFFERFIELD, 0, 0); 4281 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer, 4282 opargs[2]->v_integer, NULL, 0, 0); 4283 break; 4284 case AMLOP_CREATEBITFIELD: 4285 /* Source:B, BitIndex:I, FieldName */ 4286 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 4287 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer, 4288 1, NULL, 0, 0); 4289 break; 4290 case AMLOP_CREATEBYTEFIELD: 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 8, NULL, 0, AML_FIELD_BYTEACC); 4295 break; 4296 case AMLOP_CREATEWORDFIELD: 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 16, NULL, 0, AML_FIELD_WORDACC); 4301 break; 4302 case AMLOP_CREATEDWORDFIELD: 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 32, NULL, 0, AML_FIELD_DWORDACC); 4307 break; 4308 case AMLOP_CREATEQWORDFIELD: 4309 /* Source:B, ByteIndex:I, FieldName */ 4310 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 4311 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 4312 64, NULL, 0, AML_FIELD_QWORDACC); 4313 break; 4314 case AMLOP_FIELD: 4315 /* Field: n:OpRegion, b:Flags, F:ieldlist */ 4316 mscope = aml_pushscope(scope, opargs[2], scope->node, opcode); 4317 aml_parsefieldlist(mscope, opcode, opargs[1]->v_integer, 4318 opargs[0], NULL, 0); 4319 mscope = NULL; 4320 break; 4321 case AMLOP_INDEXFIELD: 4322 /* IndexField: n:Index, n:Data, b:Flags, F:ieldlist */ 4323 mscope = aml_pushscope(scope, opargs[3], scope->node, opcode); 4324 aml_parsefieldlist(mscope, opcode, opargs[2]->v_integer, 4325 opargs[1], opargs[0], 0); 4326 mscope = NULL; 4327 break; 4328 case AMLOP_BANKFIELD: 4329 /* BankField: n:OpRegion, n:Field, i:Bank, b:Flags, F:ieldlist */ 4330 mscope = aml_pushscope(scope, opargs[4], scope->node, opcode); 4331 aml_parsefieldlist(mscope, opcode, opargs[3]->v_integer, 4332 opargs[0], opargs[1], opargs[2]->v_integer); 4333 mscope = NULL; 4334 break; 4335 4336 /* Misc functions */ 4337 case AMLOP_STALL: 4338 /* Stall: i */ 4339 acpi_stall(opargs[0]->v_integer); 4340 break; 4341 case AMLOP_SLEEP: 4342 /* Sleep: i */ 4343 acpi_sleep(opargs[0]->v_integer, "amlsleep"); 4344 break; 4345 case AMLOP_NOTIFY: 4346 /* Notify: Si */ 4347 rv = aml_gettgt(opargs[0], opcode); 4348 dnprintf(50,"Notifying: %s %llx\n", 4349 aml_nodename(rv->node), 4350 opargs[1]->v_integer); 4351 aml_notify(rv->node, opargs[1]->v_integer); 4352 break; 4353 case AMLOP_TIMER: 4354 /* Timer: => i */ 4355 nanouptime(&ts); 4356 ival = ts.tv_sec * 10000000 + ts.tv_nsec / 100; 4357 break; 4358 case AMLOP_FATAL: 4359 /* Fatal: bdi */ 4360 aml_die("AML FATAL ERROR: %x,%x,%x\n", 4361 opargs[0]->v_integer, opargs[1]->v_integer, 4362 opargs[2]->v_integer); 4363 break; 4364 case AMLOP_LOADTABLE: 4365 /* LoadTable(Sig:Str, OEMID:Str, OEMTable:Str, [RootPath:Str], [ParmPath:Str], 4366 [ParmData:DataRefObj]) => DDBHandle */ 4367 my_ret = aml_loadtable(acpi_softc, opargs[0]->v_string, 4368 opargs[1]->v_string, opargs[2]->v_string, 4369 opargs[3]->v_string, opargs[4]->v_string, opargs[5]); 4370 break; 4371 case AMLOP_LOAD: 4372 /* Load(Object:NameString, DDBHandle:SuperName) */ 4373 mscope = aml_load(acpi_softc, scope, opargs[0], opargs[1]); 4374 break; 4375 case AMLOP_UNLOAD: 4376 /* DDBHandle */ 4377 aml_die("Unload"); 4378 break; 4379 4380 /* Control Flow */ 4381 case AMLOP_IF: 4382 /* Arguments: iT or iTbT */ 4383 if (opargs[0]->v_integer) { 4384 dnprintf(10,"parse-if @ %.4x\n", pc); 4385 mscope = aml_pushscope(scope, opargs[1], scope->node, 4386 AMLOP_IF); 4387 } else if (opargs[3] != NULL) { 4388 dnprintf(10,"parse-else @ %.4x\n", pc); 4389 mscope = aml_pushscope(scope, opargs[3], scope->node, 4390 AMLOP_ELSE); 4391 } 4392 break; 4393 case AMLOP_WHILE: 4394 if (opargs[0]->v_integer) { 4395 /* Set parent position to start of WHILE */ 4396 scope->pos = start; 4397 mscope = aml_pushscope(scope, opargs[1], scope->node, 4398 AMLOP_WHILE); 4399 } 4400 break; 4401 case AMLOP_BREAK: 4402 /* Break: Find While Scope parent, mark type as null */ 4403 aml_findscope(scope, AMLOP_WHILE, AMLOP_BREAK); 4404 break; 4405 case AMLOP_CONTINUE: 4406 /* Find Scope.. mark all objects as invalid on way to root */ 4407 aml_findscope(scope, AMLOP_WHILE, AMLOP_CONTINUE); 4408 break; 4409 case AMLOP_RETURN: 4410 mscope = aml_findscope(scope, AMLOP_METHOD, AMLOP_RETURN); 4411 if (mscope->retv) { 4412 aml_die("already allocated\n"); 4413 } 4414 mscope->retv = aml_allocvalue(0,0,NULL); 4415 aml_copyvalue(mscope->retv, opargs[0]); 4416 mscope = NULL; 4417 break; 4418 default: 4419 /* may be set direct result */ 4420 aml_die("Unknown opcode: %x:%s\n", opcode, htab->mnem); 4421 break; 4422 } 4423 if (mscope != NULL) { 4424 /* Change our scope to new scope */ 4425 scope = mscope; 4426 } 4427 if ((ret_type == 'i' || ret_type == 't') && my_ret == NULL) { 4428 dnprintf(10,"quick: %.4x [%s] alloc return integer = 0x%llx\n", 4429 pc, htab->mnem, ival); 4430 my_ret = aml_allocvalue(AML_OBJTYPE_INTEGER, ival, NULL); 4431 } 4432 if (ret_type == 'i' && my_ret && my_ret->type != AML_OBJTYPE_INTEGER) { 4433 dnprintf(10,"quick: %.4x convert to integer %s -> %s\n", 4434 pc, htab->mnem, stype); 4435 my_ret = aml_convert(my_ret, AML_OBJTYPE_INTEGER, -1); 4436 } 4437 if (my_ret != NULL) { 4438 /* Display result */ 4439 dnprintf(20,"quick: %.4x %18s %c %.4x\n", pc, stype, 4440 ret_type, my_ret->stack); 4441 } 4442 4443 /* End opcode: display/free arguments */ 4444 parse_error: 4445 for (idx=0; idx<8; idx++) { 4446 if (opargs[idx] == my_ret) 4447 opargs[idx] = NULL; 4448 aml_delref(&opargs[idx], "oparg"); 4449 } 4450 4451 /* If parsing whole scope and not done, start again */ 4452 if (ret_type == 'T') { 4453 aml_delref(&my_ret, "scope.loop"); 4454 while (scope->pos >= scope->end && scope != iscope) { 4455 /* Pop intermediate scope */ 4456 scope = aml_popscope(scope); 4457 } 4458 if (scope->pos && scope->pos < scope->end) 4459 goto start; 4460 } 4461 4462 odp--; 4463 dnprintf(50, ">>return [%s] %s %c %p\n", aml_nodename(scope->node), 4464 stype, ret_type, my_ret); 4465 4466 return my_ret; 4467 } 4468 4469 int 4470 acpi_parse_aml(struct acpi_softc *sc, uint8_t *start, uint32_t length) 4471 { 4472 struct aml_scope *scope; 4473 struct aml_value res; 4474 4475 aml_root.start = start; 4476 memset(&res, 0, sizeof(res)); 4477 res.type = AML_OBJTYPE_SCOPE; 4478 res.length = length; 4479 res.v_buffer = start; 4480 4481 /* Push toplevel scope, parse AML */ 4482 aml_error = 0; 4483 scope = aml_pushscope(NULL, &res, &aml_root, AMLOP_SCOPE); 4484 aml_busy++; 4485 aml_parse(scope, 'T', "TopLevel"); 4486 aml_busy--; 4487 aml_popscope(scope); 4488 4489 if (aml_error) { 4490 printf("error in acpi_parse_aml\n"); 4491 return -1; 4492 } 4493 return (0); 4494 } 4495 4496 /* 4497 * @@@: External API 4498 * 4499 * evaluate an AML node 4500 * Returns a copy of the value in res (must be freed by user) 4501 */ 4502 int 4503 aml_evalnode(struct acpi_softc *sc, struct aml_node *node, 4504 int argc, struct aml_value *argv, struct aml_value *res) 4505 { 4506 struct aml_value *xres; 4507 4508 if (res) 4509 memset(res, 0, sizeof(*res)); 4510 if (node == NULL || node->value == NULL) 4511 return (ACPI_E_BADVALUE); 4512 dnprintf(12,"EVALNODE: %s %lx\n", aml_nodename(node), acpi_nalloc); 4513 4514 aml_error = 0; 4515 xres = aml_eval(NULL, node->value, 't', argc, argv); 4516 if (xres) { 4517 if (res) 4518 aml_copyvalue(res, xres); 4519 if (xres != node->value) 4520 aml_delref(&xres, "evalnode"); 4521 } 4522 if (aml_error) { 4523 printf("error evaluating: %s\n", aml_nodename(node)); 4524 return (-1); 4525 } 4526 return (0); 4527 } 4528 4529 int 4530 aml_node_setval(struct acpi_softc *sc, struct aml_node *node, int64_t val) 4531 { 4532 struct aml_value env; 4533 4534 if (!node) 4535 return (0); 4536 4537 memset(&env, 0, sizeof(env)); 4538 env.type = AML_OBJTYPE_INTEGER; 4539 env.v_integer = val; 4540 4541 return aml_evalnode(sc, node, 1, &env, NULL); 4542 } 4543 4544 /* 4545 * evaluate an AML name 4546 * Returns a copy of the value in res (must be freed by user) 4547 */ 4548 int 4549 aml_evalname(struct acpi_softc *sc, struct aml_node *parent, const char *name, 4550 int argc, struct aml_value *argv, struct aml_value *res) 4551 { 4552 parent = aml_searchname(parent, name); 4553 return aml_evalnode(sc, parent, argc, argv, res); 4554 } 4555 4556 /* 4557 * evaluate an AML integer object 4558 */ 4559 int 4560 aml_evalinteger(struct acpi_softc *sc, struct aml_node *parent, 4561 const char *name, int argc, struct aml_value *argv, int64_t *ival) 4562 { 4563 struct aml_value res; 4564 int rc; 4565 4566 parent = aml_searchname(parent, name); 4567 rc = aml_evalnode(sc, parent, argc, argv, &res); 4568 if (rc == 0) { 4569 *ival = aml_val2int(&res); 4570 aml_freevalue(&res); 4571 } 4572 return rc; 4573 } 4574 4575 /* 4576 * Search for an AML name in namespace.. root only 4577 */ 4578 struct aml_node * 4579 __aml_searchname(struct aml_node *root, const void *vname, int create) 4580 { 4581 char *name = (char *)vname; 4582 char nseg[AML_NAMESEG_LEN + 1]; 4583 int i; 4584 4585 dnprintf(25,"Searchname: %s:%s = ", aml_nodename(root), name); 4586 while (*name == AMLOP_ROOTCHAR) { 4587 root = &aml_root; 4588 name++; 4589 } 4590 while (*name != 0) { 4591 /* Ugh.. we can have short names here: append '_' */ 4592 strlcpy(nseg, "____", sizeof(nseg)); 4593 for (i=0; i < AML_NAMESEG_LEN && *name && *name != '.'; i++) 4594 nseg[i] = *name++; 4595 if (*name == '.') 4596 name++; 4597 root = __aml_search(root, nseg, create); 4598 } 4599 dnprintf(25,"%p %s\n", root, aml_nodename(root)); 4600 return root; 4601 } 4602 4603 struct aml_node * 4604 aml_searchname(struct aml_node *root, const void *vname) 4605 { 4606 return __aml_searchname(root, vname, 0); 4607 } 4608 4609 /* 4610 * Search for relative name 4611 */ 4612 struct aml_node * 4613 aml_searchrel(struct aml_node *root, const void *vname) 4614 { 4615 struct aml_node *res; 4616 4617 while (root) { 4618 res = aml_searchname(root, vname); 4619 if (res != NULL) 4620 return res; 4621 root = root->parent; 4622 } 4623 return NULL; 4624 } 4625 4626 #ifndef SMALL_KERNEL 4627 4628 void 4629 acpi_getdevlist(struct acpi_devlist_head *list, struct aml_node *root, 4630 struct aml_value *pkg, int off) 4631 { 4632 struct acpi_devlist *dl; 4633 struct aml_node *node; 4634 int idx; 4635 4636 for (idx=off; idx<pkg->length; idx++) { 4637 node = aml_searchname(root, pkg->v_package[idx]->v_string); 4638 if (node) { 4639 dl = acpi_os_malloc(sizeof(*dl)); 4640 if (dl) { 4641 dl->dev_node = node; 4642 TAILQ_INSERT_TAIL(list, dl, dev_link); 4643 } 4644 } 4645 } 4646 } 4647 4648 void 4649 acpi_freedevlist(struct acpi_devlist_head *list) 4650 { 4651 struct acpi_devlist *dl; 4652 4653 while ((dl = TAILQ_FIRST(list)) != NULL) { 4654 TAILQ_REMOVE(list, dl, dev_link); 4655 acpi_os_free(dl); 4656 } 4657 } 4658 #endif /* SMALL_KERNEL */ 4659