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