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