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