Bug Summary

File:dev/acpi/dsdt.c
Warning:line 4324, column 24
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

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