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