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