1 | /*␊ |
2 | Copyright (c) 2010, Intel Corporation␊ |
3 | All rights reserved.␊ |
4 | ␊ |
5 | Redistribution and use in source and binary forms, with or without␊ |
6 | modification, are permitted provided that the following conditions are met:␊ |
7 | ␊ |
8 | * Redistributions of source code must retain the above copyright notice,␊ |
9 | this list of conditions and the following disclaimer.␊ |
10 | * Redistributions in binary form must reproduce the above copyright notice,␊ |
11 | this list of conditions and the following disclaimer in the documentation␊ |
12 | and/or other materials provided with the distribution.␊ |
13 | * Neither the name of Intel Corporation nor the names of its contributors␊ |
14 | may be used to endorse or promote products derived from this software␊ |
15 | without specific prior written permission.␊ |
16 | ␊ |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND␊ |
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED␊ |
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE␊ |
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR␊ |
21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES␊ |
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;␊ |
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON␊ |
24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT␊ |
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS␊ |
26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.␊ |
27 | */␊ |
28 | ␊ |
29 | #include "acpi.h"␊ |
30 | #include "acpidecode.h"␊ |
31 | ␊ |
32 | #define DEBUG_ACPI_DECODE 0␊ |
33 | ␊ |
34 | #if DEBUG_ACPI_DECODE==1␊ |
35 | #include "libsaio.h"␊ |
36 | #define DBG(x...) printf(x)␊ |
37 | #else␊ |
38 | #define DBG(x...)␊ |
39 | #endif␊ |
40 | ␊ |
41 | static U8 *parse_acpi_dataobject(const struct acpi_namespace *ns, U8 * current, U8 * end);␊ |
42 | static U8 *parse_acpi_package(const struct acpi_namespace *ns, U8 * current, U8 * end);␊ |
43 | static U8 *parse_acpi_termarg(const struct acpi_namespace *ns, U8 * current, U8 * end);␊ |
44 | static U8 *parse_acpi_termarglist(const struct acpi_namespace *ns, U8 * current, U8 * end);␊ |
45 | static U8 *parse_acpi_objectlist(const struct acpi_namespace *ns, U8 * current, U8 * end);␊ |
46 | U8* UIDPointer = (U8*)0;␊ |
47 | ␊ |
48 | void *decodeTableHeader(void *current, ACPI_TABLE_HEADER ** tableHeader)␊ |
49 | {␊ |
50 | *tableHeader = current;␊ |
51 | current = *tableHeader + 1;␊ |
52 | return current;␊ |
53 | }␊ |
54 | void dprint_nameseg(U32 i)␊ |
55 | {␊ |
56 | DBG("%c%c%c%c",␊ |
57 | (int)(i & 0x000000ff),␊ |
58 | (int)((i & 0x0000ff00) >> 8),␊ |
59 | (int)((i & 0x00ff0000) >> 16),␊ |
60 | (int)(i >> 24));␊ |
61 | }␊ |
62 | ␊ |
63 | #if DEBUG_ACPI_DECODE␊ |
64 | static void dprint_namespace(const struct acpi_namespace *ns)␊ |
65 | {␊ |
66 | U32 i;␊ |
67 | DBG( "\\");␊ |
68 | for (i = 0; i < ns->depth; i++) {␊ |
69 | if (i != 0)␊ |
70 | DBG( ".");␊ |
71 | dprint_nameseg(ns->nameseg[i]);␊ |
72 | }␊ |
73 | }␊ |
74 | #endif␊ |
75 | ␊ |
76 | static void parsePackageLength(U8 * current, U32 * length, U32 * lengthEncoding)␊ |
77 | {␊ |
78 | U32 i;␊ |
79 | U8 len0 = *current;␊ |
80 | U8 numBytes = len0 >> 6;␊ |
81 | U32 total = 0;␊ |
82 | ␊ |
83 | for (i = numBytes; i > 0; i--) {␊ |
84 | total <<= 8;␊ |
85 | total |= current[i];␊ |
86 | }␊ |
87 | ␊ |
88 | total <<= 4;␊ |
89 | total |= len0 & 0x3f;␊ |
90 | *length = total;␊ |
91 | *lengthEncoding = numBytes + 1;␊ |
92 | DBG("Package length=0x%02x\n", *length);␊ |
93 | }␊ |
94 | ␊ |
95 | #if UNUSED␊ |
96 | static bool ns_match(struct acpi_namespace *ns1, struct acpi_namespace *ns2)␊ |
97 | {␊ |
98 | U32 i;␊ |
99 | if (ns1->depth != ns2->depth)␊ |
100 | return false;␊ |
101 | ␊ |
102 | for (i = 0; i < ns1->depth; i++)␊ |
103 | if (ns1->nameseg[i] != ns2->nameseg[i])␊ |
104 | return false;␊ |
105 | ␊ |
106 | return true;␊ |
107 | }␊ |
108 | ␊ |
109 | U32 acpi_ns_found;␊ |
110 | #endif␊ |
111 | ␊ |
112 | static U8 *parse_acpi_namestring(const struct acpi_namespace *ns_context, struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
113 | {␊ |
114 | U8 *temp = current;␊ |
115 | struct acpi_namespace dummy_ns;␊ |
116 | ␊ |
117 | (void)end;␊ |
118 | ␊ |
119 | if (!ns)␊ |
120 | ns = &dummy_ns;␊ |
121 | *ns = *ns_context;␊ |
122 | ␊ |
123 | if (*current == AML_ROOT_PREFIX) {␊ |
124 | ns->depth = 0;␊ |
125 | current++;␊ |
126 | } else␊ |
127 | while (*current == AML_PARENT_PREFIX) {␊ |
128 | if (ns->depth == 0) {␊ |
129 | DBG( "Attempt to use parent prefix with no namespace left\n");␊ |
130 | return temp;␊ |
131 | }␊ |
132 | current++;␊ |
133 | ns->depth--;␊ |
134 | }␊ |
135 | ␊ |
136 | switch (*current) {␊ |
137 | case AML_DUAL_NAME_PREFIX:␊ |
138 | if (ns->depth + 2 > ACPI_NAMESPACE_MAX_DEPTH) {␊ |
139 | DBG( "Namespace got too deep\n");␊ |
140 | return temp;␊ |
141 | }␊ |
142 | current++;␊ |
143 | ns->nameseg[ns->depth++] = *(U32 *) current;␊ |
144 | current += 4;␊ |
145 | ns->nameseg[ns->depth++] = *(U32 *) current;␊ |
146 | current += 4;␊ |
147 | break;␊ |
148 | case AML_MULTI_NAME_PREFIX:␊ |
149 | {␊ |
150 | U8 nameseg_count;␊ |
151 | current++;␊ |
152 | nameseg_count = *current++;␊ |
153 | if (ns->depth + nameseg_count > ACPI_NAMESPACE_MAX_DEPTH) {␊ |
154 | DBG( "Namespace got too deep\n");␊ |
155 | return temp;␊ |
156 | }␊ |
157 | while (nameseg_count--) {␊ |
158 | ns->nameseg[ns->depth++] = *(U32 *) current;␊ |
159 | current += 4;␊ |
160 | }␊ |
161 | break;␊ |
162 | }␊ |
163 | case AML_NULL_NAME:␊ |
164 | current++;␊ |
165 | break;␊ |
166 | default:␊ |
167 | if (*current != '_' && (*current < 'A' || *current > 'Z')) {␊ |
168 | DBG( "Invalid nameseg lead character: 0x%02x\n", *current);␊ |
169 | return temp;␊ |
170 | }␊ |
171 | if (ns->depth + 1 > ACPI_NAMESPACE_MAX_DEPTH) {␊ |
172 | DBG( "Namespace got too deep\n");␊ |
173 | return temp;␊ |
174 | }␊ |
175 | ns->nameseg[ns->depth++] = *(U32 *) current;␊ |
176 | current += 4;␊ |
177 | break;␊ |
178 | }␊ |
179 | #if DEBUG_ACPI_DECODE␊ |
180 | DBG( "Found NameString: ");␊ |
181 | dprint_namespace(ns);␊ |
182 | DBG("\n");␊ |
183 | #endif␊ |
184 | ␉if (ns->nameseg[1] == NAMESEG("PCI0") && ns->nameseg[2] == NAMESEG("_UID")) {␊ |
185 | ␉␉UIDPointer = current;␊ |
186 | ␉}␊ |
187 | ␉␊ |
188 | #if UNUSED␉␊ |
189 | if (!acpi_ns_found) {␊ |
190 | U32 index;␊ |
191 | ␊ |
192 | for (index = 0; index < acpi_processor_count; index++)␊ |
193 | if (ns_match(ns, &acpi_processors[index].ns)) {␊ |
194 | acpi_ns_found = 1;␊ |
195 | break;␊ |
196 | }␊ |
197 | }␊ |
198 | #endif␊ |
199 | return current;␊ |
200 | }␊ |
201 | ␊ |
202 | static U8 *parse_acpi_buffer(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
203 | {␊ |
204 | U32 pkglen, lengthEncoding;␊ |
205 | (void)ns;␊ |
206 | (void)end;␊ |
207 | if (*current != AML_BUFFER_OP)␊ |
208 | return current;␊ |
209 | current++;␊ |
210 | parsePackageLength(current, &pkglen, &lengthEncoding);␊ |
211 | current += pkglen;␊ |
212 | return current;␊ |
213 | }␊ |
214 | ␊ |
215 | static U8 *parse_acpi_computationaldata(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
216 | {␊ |
217 | U8 *temp = current;␊ |
218 | ␊ |
219 | current = parse_acpi_buffer(ns, current, end);␊ |
220 | if (current != temp)␊ |
221 | return current;␊ |
222 | ␊ |
223 | switch (*current) {␊ |
224 | case AML_BYTE_OP:␊ |
225 | DBG("Found ByteOp\n");␊ |
226 | current += 1 + 1;␊ |
227 | break;␊ |
228 | case AML_WORD_OP:␊ |
229 | DBG( "Found WordOp\n");␊ |
230 | current += 1 + 2;␊ |
231 | break;␊ |
232 | case AML_DWORD_OP:␊ |
233 | DBG("Found DwordOp\n");␊ |
234 | current += 1 + 4;␊ |
235 | break;␊ |
236 | case AML_QWORD_OP:␊ |
237 | DBG( "Found QwordOp\n");␊ |
238 | current += 1 + 8;␊ |
239 | break;␊ |
240 | case AML_STRING_OP:␊ |
241 | DBG( "Found StringOp: \"");␊ |
242 | current++;␊ |
243 | while (*current)␊ |
244 | #if DEBUG_ACPI_DECODE␊ |
245 | if (*current < ' ' || *current > 0x7e)␊ |
246 | printf( "\\x%02x", *current++);␊ |
247 | else␊ |
248 | printf( "%c", *current++);␊ |
249 | #else␊ |
250 | current++;␊ |
251 | #endif␊ |
252 | current++; /* Skip the \0 */␊ |
253 | DBG( "\"\n");␊ |
254 | break;␊ |
255 | case AML_ZERO_OP:␊ |
256 | DBG( "Found ZeroOp\n");␊ |
257 | current += 1;␊ |
258 | break;␊ |
259 | case AML_ONE_OP:␊ |
260 | DBG( "Found OneOp\n");␊ |
261 | current += 1;␊ |
262 | break;␊ |
263 | case AML_ONES_OP:␊ |
264 | DBG( "Found OneOp\n");␊ |
265 | current += 1;␊ |
266 | break;␊ |
267 | case AML_EXT_OP_PREFIX:␊ |
268 | if (*(current + 1) == AML_REVISION_OP)␊ |
269 | current += 2;␊ |
270 | default:␊ |
271 | break;␊ |
272 | }␊ |
273 | ␊ |
274 | return current;␊ |
275 | }␊ |
276 | ␊ |
277 | static U8 *parse_acpi_argobj(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
278 | {␊ |
279 | (void)ns;␊ |
280 | (void)end;␊ |
281 | switch (*current) {␊ |
282 | case AML_ARG0_OP:␊ |
283 | DBG( "Found Arg0Op\n");␊ |
284 | current++;␊ |
285 | break;␊ |
286 | case AML_ARG1_OP:␊ |
287 | DBG( "Found Arg1Op\n");␊ |
288 | current++;␊ |
289 | break;␊ |
290 | case AML_ARG2_OP:␊ |
291 | DBG( "Found Arg2Op\n");␊ |
292 | current++;␊ |
293 | break;␊ |
294 | case AML_ARG3_OP:␊ |
295 | DBG( "Found Arg3Op\n");␊ |
296 | current++;␊ |
297 | break;␊ |
298 | case AML_ARG4_OP:␊ |
299 | DBG( "Found Arg4Op\n");␊ |
300 | current++;␊ |
301 | break;␊ |
302 | case AML_ARG5_OP:␊ |
303 | DBG( "Found Arg5Op\n");␊ |
304 | current++;␊ |
305 | break;␊ |
306 | case AML_ARG6_OP:␊ |
307 | DBG( "Found Arg6Op\n");␊ |
308 | current++;␊ |
309 | break;␊ |
310 | default:␊ |
311 | break;␊ |
312 | }␊ |
313 | return current;␊ |
314 | }␊ |
315 | ␊ |
316 | static U8 *parse_acpi_localobj(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
317 | {␊ |
318 | (void)ns;␊ |
319 | (void)end;␊ |
320 | switch (*current) {␊ |
321 | case AML_LOCAL0_OP:␊ |
322 | DBG( "Found Local0Op\n");␊ |
323 | current++;␊ |
324 | break;␊ |
325 | case AML_LOCAL1_OP:␊ |
326 | DBG( "Found Local1Op\n");␊ |
327 | current++;␊ |
328 | break;␊ |
329 | case AML_LOCAL2_OP:␊ |
330 | DBG( "Found Local2Op\n");␊ |
331 | current++;␊ |
332 | break;␊ |
333 | case AML_LOCAL3_OP:␊ |
334 | DBG("Found Local3Op\n");␊ |
335 | current++;␊ |
336 | break;␊ |
337 | case AML_LOCAL4_OP:␊ |
338 | DBG( "Found Local4Op\n");␊ |
339 | current++;␊ |
340 | break;␊ |
341 | case AML_LOCAL5_OP:␊ |
342 | DBG( "Found Local5Op\n");␊ |
343 | current++;␊ |
344 | break;␊ |
345 | case AML_LOCAL6_OP:␊ |
346 | DBG( "Found Local6Op\n");␊ |
347 | current++;␊ |
348 | break;␊ |
349 | case AML_LOCAL7_OP:␊ |
350 | DBG( "Found Local7Op\n");␊ |
351 | current++;␊ |
352 | break;␊ |
353 | default:␊ |
354 | break;␊ |
355 | }␊ |
356 | return current;␊ |
357 | }␊ |
358 | ␊ |
359 | static U8 *parse_acpi_debugobj(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
360 | {␊ |
361 | (void)ns;␊ |
362 | (void)end;␊ |
363 | if ((*current == AML_EXT_OP_PREFIX) && (*(current + 1) == AML_DEBUG_OP)) {␊ |
364 | current += 2;␊ |
365 | DBG( "Found DebugOp\n");␊ |
366 | }␊ |
367 | ␊ |
368 | return current;␊ |
369 | }␊ |
370 | ␊ |
371 | static U8 *parse_acpi_datarefobject(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
372 | {␊ |
373 | U8 *temp = current;␊ |
374 | ␊ |
375 | DBG( "Beginning datarefobject: 0x%02x at memory location %p\n", *current, current);␊ |
376 | current = parse_acpi_dataobject(ns, current, end);␊ |
377 | if (current != temp)␊ |
378 | return current;␊ |
379 | ␊ |
380 | return current;␊ |
381 | }␊ |
382 | ␊ |
383 | static U8 *parse_acpi_simplename(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
384 | {␊ |
385 | U8 *temp = current;␊ |
386 | ␊ |
387 | current = parse_acpi_namestring(ns, NULL, current, end);␊ |
388 | if (current != temp)␊ |
389 | return current;␊ |
390 | ␊ |
391 | current = parse_acpi_argobj(ns, current, end);␊ |
392 | if (current != temp)␊ |
393 | return current;␊ |
394 | ␊ |
395 | current = parse_acpi_localobj(ns, current, end);␊ |
396 | if (current != temp)␊ |
397 | return current;␊ |
398 | ␊ |
399 | return current;␊ |
400 | }␊ |
401 | ␊ |
402 | static U8 *parse_acpi_supername(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
403 | {␊ |
404 | U8 *temp = current;␊ |
405 | ␊ |
406 | current = parse_acpi_simplename(ns, current, end);␊ |
407 | if (current != temp)␊ |
408 | return current;␊ |
409 | ␊ |
410 | current = parse_acpi_debugobj(ns, current, end);␊ |
411 | if (current != temp)␊ |
412 | return current;␊ |
413 | ␊ |
414 | return current;␊ |
415 | }␊ |
416 | ␊ |
417 | static U8 *parse_acpi_target(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
418 | {␊ |
419 | U8 *temp = current;␊ |
420 | ␊ |
421 | current = parse_acpi_supername(ns, current, end);␊ |
422 | if (current != temp)␊ |
423 | return current;␊ |
424 | ␊ |
425 | if (*current == AML_NULL_NAME)␊ |
426 | current++;␊ |
427 | ␊ |
428 | return current;␊ |
429 | }␊ |
430 | ␊ |
431 | static U8 *parse_acpi_method(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
432 | {␊ |
433 | U8 *new_end = current;␊ |
434 | U8 *temp;␊ |
435 | U32 pkglen;␊ |
436 | U32 lengthEncoding;␊ |
437 | struct acpi_namespace new_ns;␊ |
438 | ␊ |
439 | (void)end;␊ |
440 | ␊ |
441 | parsePackageLength(current, &pkglen, &lengthEncoding);␊ |
442 | current += lengthEncoding;␊ |
443 | new_end += pkglen;␊ |
444 | ␊ |
445 | temp = current;␊ |
446 | current = parse_acpi_namestring(ns, &new_ns, current, new_end);␊ |
447 | if (current == temp)␊ |
448 | return new_end;␊ |
449 | ␉␊ |
450 | #if DEBUG_ACPI_DECODE␊ |
451 | DBG( "Found Method: ");␊ |
452 | dprint_namespace(&new_ns);␊ |
453 | DBG( "\n");␊ |
454 | #endif␊ |
455 | // U8 methodFlags␊ |
456 | current++;␊ |
457 | ␊ |
458 | parse_acpi_termlist(&new_ns, current, new_end);␊ |
459 | ␊ |
460 | #if DEBUG_ACPI_DECODE␊ |
461 | DBG( "End of Method: ");␊ |
462 | dprint_namespace(&new_ns);␊ |
463 | DBG( "\n");␊ |
464 | #endif␊ |
465 | ␊ |
466 | return new_end;␊ |
467 | }␊ |
468 | ␊ |
469 | U32 acpi_processor_count;␊ |
470 | struct acpi_processor acpi_processors[CPU_MAP_LIMIT];␊ |
471 | ␊ |
472 | static void add_processor(const struct acpi_namespace *ns, U8 id, U32 pmbase)␊ |
473 | {␊ |
474 | if (acpi_processor_count == CPU_MAP_LIMIT) {␊ |
475 | DBG( "No more room for ACPI processor structures\n");␊ |
476 | return;␊ |
477 | }␊ |
478 | acpi_processors[acpi_processor_count].ns = *ns;␊ |
479 | acpi_processors[acpi_processor_count].id = id;␊ |
480 | acpi_processors[acpi_processor_count].pmbase = pmbase;␊ |
481 | acpi_processor_count++;␊ |
482 | }␊ |
483 | ␊ |
484 | static U8 *parse_acpi_processor(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
485 | {␊ |
486 | U8 *new_end = current;␊ |
487 | U8 *temp;␊ |
488 | U32 pkglen;␊ |
489 | U32 lengthEncoding;␊ |
490 | struct acpi_namespace new_ns;␊ |
491 | U8 id;␊ |
492 | U32 pmbase;␊ |
493 | ␊ |
494 | (void)end;␊ |
495 | ␊ |
496 | parsePackageLength(current, &pkglen, &lengthEncoding);␊ |
497 | current += lengthEncoding;␊ |
498 | new_end += pkglen;␊ |
499 | ␊ |
500 | temp = current;␊ |
501 | current = parse_acpi_namestring(ns, &new_ns, current, new_end);␊ |
502 | if (current == temp)␊ |
503 | return new_end;␊ |
504 | ␊ |
505 | id = *current++;␊ |
506 | pmbase = *(U32 *) current;␊ |
507 | current += 4;␊ |
508 | ␉␊ |
509 | #if DEBUG_ACPI_DECODE␊ |
510 | DBG( "Found CPU object: ");␊ |
511 | dprint_namespace(&new_ns);␊ |
512 | DBG( " id = 0x%x pmbase = 0x%x\n", id, pmbase);␊ |
513 | #endif␊ |
514 | add_processor(&new_ns, id, pmbase);␊ |
515 | ␊ |
516 | return new_end;␊ |
517 | }␊ |
518 | ␊ |
519 | static U8 *parse_acpi_namedobj(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
520 | {␊ |
521 | DBG( "Beginning namedobj: 0x%02x at memory location %p\n", *current, current);␊ |
522 | switch (*current) {␊ |
523 | case AML_EXT_OP_PREFIX:␊ |
524 | {␊ |
525 | if (*(current + 1) == AML_MUTEX_OP) {␊ |
526 | struct acpi_namespace new_ns;␊ |
527 | ␊ |
528 | current += 2;␊ |
529 | current = parse_acpi_namestring(ns, &new_ns, current, end);␊ |
530 | #if DEBUG_ACPI_DECODE␊ |
531 | DBG( "Mutex: ");␊ |
532 | dprint_namespace(&new_ns);␊ |
533 | DBG( "\n");␊ |
534 | #endif␊ |
535 | current++; /* SyncFlags */␊ |
536 | } else if (*(current + 1) == AML_OPREGION_OP) {␊ |
537 | struct acpi_namespace new_ns;␊ |
538 | ␊ |
539 | current += 2;␊ |
540 | DBG( "OpRegion at memory location %p\n", current);␊ |
541 | current = parse_acpi_namestring(ns, &new_ns, current, end);␊ |
542 | #if DEBUG_ACPI_DECODE␊ |
543 | DBG( "OpRegion name: ");␊ |
544 | dprint_namespace(&new_ns);␊ |
545 | DBG( "\n");␊ |
546 | #endif␊ |
547 | current++;␊ |
548 | current = parse_acpi_termarg(ns, current, end);␊ |
549 | current = parse_acpi_termarg(ns, current, end);␊ |
550 | #if DEBUG_ACPI_DECODE␊ |
551 | DBG( "End OpRegion: ");␊ |
552 | dprint_namespace(&new_ns);␊ |
553 | DBG( "\n");␊ |
554 | #endif␊ |
555 | } else if (*(current + 1) == AML_FIELD_OP) {␊ |
556 | U32 pkglen;␊ |
557 | U32 lengthEncoding;␊ |
558 | ␊ |
559 | current += 2;␊ |
560 | DBG( "FieldOp at memory location %p\n", current);␊ |
561 | parsePackageLength(current, &pkglen, &lengthEncoding);␊ |
562 | current += pkglen;␊ |
563 | } else if (*(current + 1) == AML_DEVICE_OP) {␊ |
564 | U8 *new_end;␊ |
565 | U32 pkglen;␊ |
566 | U32 lengthEncoding;␊ |
567 | struct acpi_namespace new_ns;␊ |
568 | ␊ |
569 | current += 2;␊ |
570 | new_end = current;␊ |
571 | DBG( "DeviceOp at memory location %p\n", current);␊ |
572 | parsePackageLength(current, &pkglen, &lengthEncoding);␊ |
573 | current += lengthEncoding;␊ |
574 | new_end += pkglen;␊ |
575 | current = parse_acpi_namestring(ns, &new_ns, current, new_end);␊ |
576 | #if DEBUG_ACPI_DECODE␊ |
577 | DBG( "DeviceOp name: ");␊ |
578 | dprint_namespace(&new_ns);␊ |
579 | DBG( "\n");␊ |
580 | #endif␊ |
581 | ␊ |
582 | current = parse_acpi_objectlist(&new_ns, current, new_end);␊ |
583 | current = new_end;␊ |
584 | } else if (*(current + 1) == AML_PROCESSOR_OP) {␊ |
585 | current += 2;␊ |
586 | current = parse_acpi_processor(ns, current, end);␊ |
587 | } else if (*(current + 1) == AML_INDEXFIELD_OP) {␊ |
588 | U8 *new_end;␊ |
589 | U32 pkglen;␊ |
590 | U32 lengthEncoding;␊ |
591 | struct acpi_namespace new_ns;␊ |
592 | ␊ |
593 | current += 2;␊ |
594 | new_end = current;␊ |
595 | DBG( "IndexFieldOp at memory location %p\n", current);␊ |
596 | parsePackageLength(current, &pkglen, &lengthEncoding);␊ |
597 | current += lengthEncoding;␊ |
598 | new_end += pkglen;␊ |
599 | current = parse_acpi_namestring(ns, &new_ns, current, new_end);␊ |
600 | #if DEBUG_ACPI_DECODE␊ |
601 | DBG( "IndexFieldOp name: ");␊ |
602 | dprint_namespace(&new_ns);␊ |
603 | DBG( "\n");␊ |
604 | #endif␊ |
605 | current = parse_acpi_objectlist(&new_ns, current, new_end);␊ |
606 | current = new_end;␊ |
607 | }␊ |
608 | break;␊ |
609 | }␊ |
610 | case AML_METHOD_OP:␊ |
611 | {␊ |
612 | current++;␊ |
613 | current = parse_acpi_method(ns, current, end);␊ |
614 | break;␊ |
615 | }␊ |
616 | default:␊ |
617 | break;␊ |
618 | }␊ |
619 | return current;␊ |
620 | }␊ |
621 | ␊ |
622 | static U8 *parse_acpi_type1opcode(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
623 | {␊ |
624 | DBG( "Beginning type1opcode: 0x%02x at memory location %p\n", *current, current);␊ |
625 | switch (*current) {␊ |
626 | case AML_IF_OP:␊ |
627 | {␊ |
628 | U8 *new_end;␊ |
629 | U32 pkgLen;␊ |
630 | U32 lengthEncoding;␊ |
631 | ␊ |
632 | DBG( "Found IfOp\n");␊ |
633 | current++;␊ |
634 | parsePackageLength(current, &pkgLen, &lengthEncoding);␊ |
635 | new_end = current + pkgLen;␊ |
636 | current += lengthEncoding;␊ |
637 | ␊ |
638 | current = parse_acpi_termarg(ns, current, new_end);␊ |
639 | parse_acpi_termlist(ns, current, new_end);␊ |
640 | current = new_end;␊ |
641 | break;␊ |
642 | }␊ |
643 | case AML_ELSE_OP:␊ |
644 | {␊ |
645 | U8 *new_end;␊ |
646 | U32 pkgLen;␊ |
647 | U32 lengthEncoding;␊ |
648 | ␊ |
649 | DBG( "Found ElseOp\n");␊ |
650 | current++;␊ |
651 | parsePackageLength(current, &pkgLen, &lengthEncoding);␊ |
652 | new_end = current + pkgLen;␊ |
653 | current += lengthEncoding;␊ |
654 | ␊ |
655 | parse_acpi_termlist(ns, current, new_end);␊ |
656 | current = new_end;␊ |
657 | break;␊ |
658 | }␊ |
659 | case AML_RETURN_OP:␊ |
660 | {␊ |
661 | DBG( "Found ReturnOp\n");␊ |
662 | current++;␊ |
663 | current = parse_acpi_termarg(ns, current, end);␊ |
664 | break;␊ |
665 | }␊ |
666 | default:␊ |
667 | break;␊ |
668 | }␊ |
669 | return current;␊ |
670 | }␊ |
671 | ␊ |
672 | static U8 *parse_acpi_type2opcode(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
673 | {␊ |
674 | U8 *temp = current;␊ |
675 | ␊ |
676 | DBG( "Beginning type2opcode: 0x%02x at memory location %p\n", *current, current);␊ |
677 | ␊ |
678 | current = parse_acpi_package(ns, current, end);␊ |
679 | if (current != temp)␊ |
680 | return current;␊ |
681 | ␊ |
682 | switch (*current) {␊ |
683 | case AML_LNOT_OP:␊ |
684 | current++;␊ |
685 | DBG( "Found logical not operator\n");␊ |
686 | current = parse_acpi_termarg(ns, current, end);␊ |
687 | break;␊ |
688 | ␊ |
689 | case AML_LAND_OP:␊ |
690 | case AML_LOR_OP:␊ |
691 | case AML_LEQUAL_OP:␊ |
692 | case AML_LGREATER_OP:␊ |
693 | case AML_LLESS_OP:␊ |
694 | DBG( "Found logical binary operator: %c\n", "&|!=><"[*current - AML_LAND_OP]);␊ |
695 | current++;␊ |
696 | current = parse_acpi_termarg(ns, current, end);␊ |
697 | current = parse_acpi_termarg(ns, current, end);␊ |
698 | break;␊ |
699 | ␊ |
700 | case AML_EXT_OP_PREFIX:␊ |
701 | {␊ |
702 | if (*(current + 1) == AML_COND_REF_OF_OP) {␊ |
703 | DBG( "Found CondRefOf\n");␊ |
704 | current += 2;␊ |
705 | current = parse_acpi_supername(ns, current, end);␊ |
706 | current = parse_acpi_target(ns, current, end);␊ |
707 | }␊ |
708 | break;␊ |
709 | }␊ |
710 | case AML_STORE_OP:␊ |
711 | {␊ |
712 | DBG( "Found StoreOp\n");␊ |
713 | current++;␊ |
714 | current = parse_acpi_termarg(ns, current, end);␊ |
715 | current = parse_acpi_supername(ns, current, end);␊ |
716 | break;␊ |
717 | }␊ |
718 | default:␊ |
719 | {␊ |
720 | current = parse_acpi_namestring(ns, NULL, current, end);␊ |
721 | if (current == temp)␊ |
722 | break;␊ |
723 | current = parse_acpi_termarglist(ns, current, end);␊ |
724 | }␊ |
725 | }␊ |
726 | return current;␊ |
727 | }␊ |
728 | ␊ |
729 | static U8 *parse_acpi_package(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
730 | {␊ |
731 | (void)ns;␊ |
732 | (void)end;␊ |
733 | if (*current == AML_PACKAGE_OP) {␊ |
734 | U32 pkglen;␊ |
735 | U32 lengthEncoding;␊ |
736 | ␊ |
737 | DBG( "Found PackageOp\n");␊ |
738 | current++;␊ |
739 | parsePackageLength(current, &pkglen, &lengthEncoding);␊ |
740 | current += pkglen;␊ |
741 | }␊ |
742 | return current;␊ |
743 | }␊ |
744 | ␊ |
745 | static U8 *parse_acpi_dataobject(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
746 | {␊ |
747 | U8 *temp = current;␊ |
748 | ␊ |
749 | current = parse_acpi_computationaldata(ns, current, end);␊ |
750 | if (current != temp)␊ |
751 | return current;␊ |
752 | ␊ |
753 | current = parse_acpi_package(ns, current, end);␊ |
754 | if (current != temp)␊ |
755 | return current;␊ |
756 | ␊ |
757 | return current;␊ |
758 | }␊ |
759 | ␊ |
760 | static U8 *parse_acpi_termarg(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
761 | {␊ |
762 | U8 *temp = current;␊ |
763 | ␊ |
764 | DBG( "Beginning termarg: 0x%02x at memory location %p\n", *current, current);␊ |
765 | ␊ |
766 | current = parse_acpi_type2opcode(ns, current, end);␊ |
767 | if (current != temp)␊ |
768 | return current;␊ |
769 | ␊ |
770 | current = parse_acpi_dataobject(ns, current, end);␊ |
771 | if (current != temp)␊ |
772 | return current;␊ |
773 | ␊ |
774 | current = parse_acpi_argobj(ns, current, end);␊ |
775 | if (current != temp)␊ |
776 | return current;␊ |
777 | ␊ |
778 | current = parse_acpi_localobj(ns, current, end);␊ |
779 | if (current != temp)␊ |
780 | return current;␊ |
781 | ␊ |
782 | return current;␊ |
783 | }␊ |
784 | ␊ |
785 | static U8 *parse_acpi_namespacemodifierobj(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
786 | {␊ |
787 | DBG( "Beginning namespacemodifierobj: 0x%02x at memory location %p\n", *current, current);␊ |
788 | switch (*current) {␊ |
789 | case AML_SCOPE_OP:␊ |
790 | {␊ |
791 | U8 *new_end;␊ |
792 | struct acpi_namespace new_ns;␊ |
793 | U32 scopeLen;␊ |
794 | U32 lengthEncoding;␊ |
795 | ␊ |
796 | current++;␊ |
797 | parsePackageLength(current, &scopeLen, &lengthEncoding);␊ |
798 | new_end = current + scopeLen;␊ |
799 | ␊ |
800 | current = parse_acpi_namestring(ns, &new_ns, current + lengthEncoding, new_end);␊ |
801 | #if DEBUG_ACPI_DECODE␊ |
802 | DBG( "Found Scope: ");␊ |
803 | dprint_namespace(&new_ns);␊ |
804 | DBG( "\n");␊ |
805 | #endif␊ |
806 | parse_acpi_termlist(&new_ns, current, new_end);␊ |
807 | #if DEBUG_ACPI_DECODE␊ |
808 | DBG( "End Scope: ");␊ |
809 | dprint_namespace(&new_ns);␊ |
810 | DBG( "\n");␊ |
811 | #endif␊ |
812 | current = new_end;␊ |
813 | break;␊ |
814 | }␊ |
815 | case AML_NAME_OP:␊ |
816 | current++;␊ |
817 | current = parse_acpi_namestring(ns, NULL, current, end);␊ |
818 | current = parse_acpi_datarefobject(ns, current, end);␊ |
819 | break;␊ |
820 | case AML_ALIAS_OP:␊ |
821 | current++;␊ |
822 | current = parse_acpi_namestring(ns, NULL, current, end);␊ |
823 | current = parse_acpi_namestring(ns, NULL, current, end);␊ |
824 | break;␊ |
825 | default:␊ |
826 | break;␊ |
827 | }␊ |
828 | return current;␊ |
829 | }␊ |
830 | ␊ |
831 | static U8 *parse_acpi_objectlist(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
832 | {␊ |
833 | DBG( "Beginning objectlist: 0x%02x at memory location %p end=%p\n", *current, current, end);␊ |
834 | while (current < end) {␊ |
835 | U8 *temp = current;␊ |
836 | ␊ |
837 | DBG( "New iteration of objectlist: 0x%02x at memory location %p end=%p\n", *current, current, end);␊ |
838 | ␊ |
839 | current = parse_acpi_namespacemodifierobj(ns, current, end);␊ |
840 | if (current != temp)␊ |
841 | continue;␊ |
842 | ␊ |
843 | current = parse_acpi_namedobj(ns, current, end);␊ |
844 | if (current != temp)␊ |
845 | continue;␊ |
846 | ␊ |
847 | if (current == temp) {␊ |
848 | DBG( "Unhandled object in object list: 0x%02x at memory location %p\n", *current, current);␊ |
849 | #if DEBUG_ACPI_DECODE␊ |
850 | DBG( "namespace: ");␊ |
851 | dprint_namespace(ns);␊ |
852 | DBG( "\n");␊ |
853 | #endif␊ |
854 | break;␊ |
855 | }␊ |
856 | }␊ |
857 | DBG( "Ending objectlist: 0x%02x at memory location %p\n", *current, current);␊ |
858 | return current;␊ |
859 | }␊ |
860 | ␊ |
861 | static U8 *parse_acpi_termarglist(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
862 | {␊ |
863 | DBG( "Beginning termarglist: 0x%02x at memory location %p\n", *current, current);␊ |
864 | while (current < end) {␊ |
865 | U8 *temp = current;␊ |
866 | ␊ |
867 | current = parse_acpi_termarg(ns, current, end);␊ |
868 | if (current == temp) {␊ |
869 | DBG( "Unhandled item in term arg list: 0x%02x at memory location %p\n", *current, current);␊ |
870 | #if DEBUG_ACPI_DECODE␊ |
871 | DBG( "namespace: ");␊ |
872 | dprint_namespace(ns);␊ |
873 | DBG( "\n");␊ |
874 | #endif␊ |
875 | break;␊ |
876 | }␊ |
877 | }␊ |
878 | return current;␊ |
879 | }␊ |
880 | ␊ |
881 | void parse_acpi_termlist(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
882 | {␊ |
883 | while (current < end) {␊ |
884 | U8 *temp = current;␊ |
885 | ␊ |
886 | DBG( "Beginning new term in term list: 0x%02x at memory location %p\n", *current, current);␊ |
887 | ␊ |
888 | current = parse_acpi_namespacemodifierobj(ns, current, end);␊ |
889 | if (current != temp)␊ |
890 | continue;␊ |
891 | ␊ |
892 | current = parse_acpi_namedobj(ns, current, end);␊ |
893 | if (current != temp)␊ |
894 | continue;␊ |
895 | ␊ |
896 | current = parse_acpi_type1opcode(ns, current, end);␊ |
897 | if (current != temp)␊ |
898 | continue;␊ |
899 | ␊ |
900 | current = parse_acpi_type2opcode(ns, current, end);␊ |
901 | if (current != temp)␊ |
902 | continue;␊ |
903 | ␊ |
904 | switch (*current) {␊ |
905 | default:␊ |
906 | {␊ |
907 | DBG( "Unhandled item in term list: 0x%02x at memory location %p\n", *current, current);␊ |
908 | #if DEBUG_ACPI_DECODE␊ |
909 | DBG( "namespace: ");␊ |
910 | dprint_namespace(ns);␊ |
911 | DBG( "\n");␊ |
912 | #endif␊ |
913 | return;␊ |
914 | }␊ |
915 | }␊ |
916 | }␊ |
917 | }␊ |
918 | |