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