Root/
| |
---|---|
Source at commit 2740 created 8 years 11 months ago. By ifabio, sync with trunk. | |
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 = 0, lengthEncoding = 0;␊ |
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 = 0;␊ |
436 | U32 lengthEncoding = 0;␊ |
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 = 0;␊ |
489 | U32 lengthEncoding = 0;␊ |
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 | (void)current; // Silent a warning reported by the clang static analizer . ␊ |
509 | ␉␊ |
510 | #if DEBUG_ACPI_DECODE␊ |
511 | DBG( "Found CPU object: ");␊ |
512 | dprint_namespace(&new_ns);␊ |
513 | DBG( " id = 0x%x pmbase = 0x%x\n", id, pmbase);␊ |
514 | #endif␊ |
515 | add_processor(&new_ns, id, pmbase);␊ |
516 | ␊ |
517 | return new_end;␊ |
518 | }␊ |
519 | ␊ |
520 | static U8 *parse_acpi_namedobj(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
521 | {␊ |
522 | DBG( "Beginning namedobj: 0x%02x at memory location %p\n", *current, current);␊ |
523 | switch (*current) {␊ |
524 | case AML_EXT_OP_PREFIX:␊ |
525 | {␊ |
526 | if (*(current + 1) == AML_MUTEX_OP) {␊ |
527 | struct acpi_namespace new_ns;␊ |
528 | ␊ |
529 | current += 2;␊ |
530 | current = parse_acpi_namestring(ns, &new_ns, current, end);␊ |
531 | #if DEBUG_ACPI_DECODE␊ |
532 | DBG( "Mutex: ");␊ |
533 | dprint_namespace(&new_ns);␊ |
534 | DBG( "\n");␊ |
535 | #endif␊ |
536 | current++; /* SyncFlags */␊ |
537 | } else if (*(current + 1) == AML_OPREGION_OP) {␊ |
538 | struct acpi_namespace new_ns;␊ |
539 | ␊ |
540 | current += 2;␊ |
541 | DBG( "OpRegion at memory location %p\n", current);␊ |
542 | current = parse_acpi_namestring(ns, &new_ns, current, end);␊ |
543 | #if DEBUG_ACPI_DECODE␊ |
544 | DBG( "OpRegion name: ");␊ |
545 | dprint_namespace(&new_ns);␊ |
546 | DBG( "\n");␊ |
547 | #endif␊ |
548 | current++;␊ |
549 | current = parse_acpi_termarg(ns, current, end);␊ |
550 | current = parse_acpi_termarg(ns, current, end);␊ |
551 | #if DEBUG_ACPI_DECODE␊ |
552 | DBG( "End OpRegion: ");␊ |
553 | dprint_namespace(&new_ns);␊ |
554 | DBG( "\n");␊ |
555 | #endif␊ |
556 | } else if (*(current + 1) == AML_FIELD_OP) {␊ |
557 | U32 pkglen = 0;␊ |
558 | U32 lengthEncoding = 0;␊ |
559 | ␊ |
560 | current += 2;␊ |
561 | DBG( "FieldOp at memory location %p\n", current);␊ |
562 | parsePackageLength(current, &pkglen, &lengthEncoding);␊ |
563 | current += pkglen;␊ |
564 | } else if (*(current + 1) == AML_DEVICE_OP) {␊ |
565 | U8 *new_end;␊ |
566 | U32 pkglen = 0;␊ |
567 | U32 lengthEncoding = 0;␊ |
568 | struct acpi_namespace new_ns;␊ |
569 | ␊ |
570 | current += 2;␊ |
571 | new_end = current;␊ |
572 | DBG( "DeviceOp at memory location %p\n", current);␊ |
573 | parsePackageLength(current, &pkglen, &lengthEncoding);␊ |
574 | current += lengthEncoding;␊ |
575 | new_end += pkglen;␊ |
576 | current = parse_acpi_namestring(ns, &new_ns, current, new_end);␊ |
577 | #if DEBUG_ACPI_DECODE␊ |
578 | DBG( "DeviceOp name: ");␊ |
579 | dprint_namespace(&new_ns);␊ |
580 | DBG( "\n");␊ |
581 | #endif␊ |
582 | ␊ |
583 | parse_acpi_objectlist(&new_ns, current, new_end);␊ |
584 | current = new_end;␊ |
585 | } else if (*(current + 1) == AML_PROCESSOR_OP) {␊ |
586 | current += 2;␊ |
587 | current = parse_acpi_processor(ns, current, end);␊ |
588 | } else if (*(current + 1) == AML_INDEXFIELD_OP) {␊ |
589 | U8 *new_end;␊ |
590 | U32 pkglen = 0;␊ |
591 | U32 lengthEncoding = 0;␊ |
592 | struct acpi_namespace new_ns;␊ |
593 | ␊ |
594 | current += 2;␊ |
595 | new_end = current;␊ |
596 | DBG( "IndexFieldOp at memory location %p\n", current);␊ |
597 | parsePackageLength(current, &pkglen, &lengthEncoding);␊ |
598 | current += lengthEncoding;␊ |
599 | new_end += pkglen;␊ |
600 | current = parse_acpi_namestring(ns, &new_ns, current, new_end);␊ |
601 | #if DEBUG_ACPI_DECODE␊ |
602 | DBG( "IndexFieldOp name: ");␊ |
603 | dprint_namespace(&new_ns);␊ |
604 | DBG( "\n");␊ |
605 | #endif␊ |
606 | parse_acpi_objectlist(&new_ns, current, new_end);␊ |
607 | current = new_end;␊ |
608 | }␊ |
609 | break;␊ |
610 | }␊ |
611 | case AML_METHOD_OP:␊ |
612 | {␊ |
613 | current++;␊ |
614 | current = parse_acpi_method(ns, current, end);␊ |
615 | break;␊ |
616 | }␊ |
617 | default:␊ |
618 | break;␊ |
619 | }␊ |
620 | return current;␊ |
621 | }␊ |
622 | ␊ |
623 | static U8 *parse_acpi_type1opcode(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
624 | {␊ |
625 | DBG( "Beginning type1opcode: 0x%02x at memory location %p\n", *current, current);␊ |
626 | switch (*current) {␊ |
627 | case AML_IF_OP:␊ |
628 | {␊ |
629 | U8 *new_end;␊ |
630 | U32 pkgLen = 0;␊ |
631 | U32 lengthEncoding = 0;␊ |
632 | ␊ |
633 | DBG( "Found IfOp\n");␊ |
634 | current++;␊ |
635 | parsePackageLength(current, &pkgLen, &lengthEncoding);␊ |
636 | new_end = current + pkgLen;␊ |
637 | current += lengthEncoding;␊ |
638 | ␊ |
639 | current = parse_acpi_termarg(ns, current, new_end);␊ |
640 | parse_acpi_termlist(ns, current, new_end);␊ |
641 | current = new_end;␊ |
642 | break;␊ |
643 | }␊ |
644 | case AML_ELSE_OP:␊ |
645 | {␊ |
646 | U8 *new_end;␊ |
647 | U32 pkgLen = 0;␊ |
648 | U32 lengthEncoding = 0;␊ |
649 | ␊ |
650 | DBG( "Found ElseOp\n");␊ |
651 | current++;␊ |
652 | parsePackageLength(current, &pkgLen, &lengthEncoding);␊ |
653 | new_end = current + pkgLen;␊ |
654 | current += lengthEncoding;␊ |
655 | ␊ |
656 | parse_acpi_termlist(ns, current, new_end);␊ |
657 | current = new_end;␊ |
658 | break;␊ |
659 | }␊ |
660 | case AML_RETURN_OP:␊ |
661 | {␊ |
662 | DBG( "Found ReturnOp\n");␊ |
663 | current++;␊ |
664 | current = parse_acpi_termarg(ns, current, end);␊ |
665 | break;␊ |
666 | }␊ |
667 | default:␊ |
668 | break;␊ |
669 | }␊ |
670 | return current;␊ |
671 | }␊ |
672 | ␊ |
673 | static U8 *parse_acpi_type2opcode(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
674 | {␊ |
675 | U8 *temp = current;␊ |
676 | ␊ |
677 | DBG( "Beginning type2opcode: 0x%02x at memory location %p\n", *current, current);␊ |
678 | ␊ |
679 | current = parse_acpi_package(ns, current, end);␊ |
680 | if (current != temp)␊ |
681 | return current;␊ |
682 | ␊ |
683 | switch (*current) {␊ |
684 | case AML_LNOT_OP:␊ |
685 | current++;␊ |
686 | DBG( "Found logical not operator\n");␊ |
687 | current = parse_acpi_termarg(ns, current, end);␊ |
688 | break;␊ |
689 | ␊ |
690 | case AML_LAND_OP:␊ |
691 | case AML_LOR_OP:␊ |
692 | case AML_LEQUAL_OP:␊ |
693 | case AML_LGREATER_OP:␊ |
694 | case AML_LLESS_OP:␊ |
695 | DBG( "Found logical binary operator: %c\n", "&|!=><"[*current - AML_LAND_OP]);␊ |
696 | current++;␊ |
697 | current = parse_acpi_termarg(ns, current, end);␊ |
698 | current = parse_acpi_termarg(ns, current, end);␊ |
699 | break;␊ |
700 | ␊ |
701 | case AML_EXT_OP_PREFIX:␊ |
702 | {␊ |
703 | if (*(current + 1) == AML_COND_REF_OF_OP) {␊ |
704 | DBG( "Found CondRefOf\n");␊ |
705 | current += 2;␊ |
706 | current = parse_acpi_supername(ns, current, end);␊ |
707 | current = parse_acpi_target(ns, current, end);␊ |
708 | }␊ |
709 | break;␊ |
710 | }␊ |
711 | case AML_STORE_OP:␊ |
712 | {␊ |
713 | DBG( "Found StoreOp\n");␊ |
714 | current++;␊ |
715 | current = parse_acpi_termarg(ns, current, end);␊ |
716 | current = parse_acpi_supername(ns, current, end);␊ |
717 | break;␊ |
718 | }␊ |
719 | default:␊ |
720 | {␊ |
721 | current = parse_acpi_namestring(ns, NULL, current, end);␊ |
722 | if (current == temp)␊ |
723 | break;␊ |
724 | current = parse_acpi_termarglist(ns, current, end);␊ |
725 | }␊ |
726 | }␊ |
727 | return current;␊ |
728 | }␊ |
729 | ␊ |
730 | static U8 *parse_acpi_package(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
731 | {␊ |
732 | (void)ns;␊ |
733 | (void)end;␊ |
734 | if (*current == AML_PACKAGE_OP) {␊ |
735 | U32 pkglen = 0;␊ |
736 | U32 lengthEncoding = 0;␊ |
737 | ␊ |
738 | DBG( "Found PackageOp\n");␊ |
739 | current++;␊ |
740 | parsePackageLength(current, &pkglen, &lengthEncoding);␊ |
741 | current += pkglen;␊ |
742 | }␊ |
743 | return current;␊ |
744 | }␊ |
745 | ␊ |
746 | static U8 *parse_acpi_dataobject(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
747 | {␊ |
748 | U8 *temp = current;␊ |
749 | ␊ |
750 | current = parse_acpi_computationaldata(ns, current, end);␊ |
751 | if (current != temp)␊ |
752 | return current;␊ |
753 | ␊ |
754 | current = parse_acpi_package(ns, current, end);␊ |
755 | if (current != temp)␊ |
756 | return current;␊ |
757 | ␊ |
758 | return current;␊ |
759 | }␊ |
760 | ␊ |
761 | static U8 *parse_acpi_termarg(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
762 | {␊ |
763 | U8 *temp = current;␊ |
764 | ␊ |
765 | DBG( "Beginning termarg: 0x%02x at memory location %p\n", *current, current);␊ |
766 | ␊ |
767 | current = parse_acpi_type2opcode(ns, current, end);␊ |
768 | if (current != temp)␊ |
769 | return current;␊ |
770 | ␊ |
771 | current = parse_acpi_dataobject(ns, current, end);␊ |
772 | if (current != temp)␊ |
773 | return current;␊ |
774 | ␊ |
775 | current = parse_acpi_argobj(ns, current, end);␊ |
776 | if (current != temp)␊ |
777 | return current;␊ |
778 | ␊ |
779 | current = parse_acpi_localobj(ns, current, end);␊ |
780 | if (current != temp)␊ |
781 | return current;␊ |
782 | ␊ |
783 | return current;␊ |
784 | }␊ |
785 | ␊ |
786 | static U8 *parse_acpi_namespacemodifierobj(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
787 | {␊ |
788 | DBG( "Beginning namespacemodifierobj: 0x%02x at memory location %p\n", *current, current);␊ |
789 | switch (*current) {␊ |
790 | case AML_SCOPE_OP:␊ |
791 | {␊ |
792 | U8 *new_end;␊ |
793 | struct acpi_namespace new_ns;␊ |
794 | U32 scopeLen = 0;␊ |
795 | U32 lengthEncoding = 0;␊ |
796 | ␊ |
797 | current++;␊ |
798 | parsePackageLength(current, &scopeLen, &lengthEncoding);␊ |
799 | new_end = current + scopeLen;␊ |
800 | ␊ |
801 | current = parse_acpi_namestring(ns, &new_ns, current + lengthEncoding, new_end);␊ |
802 | #if DEBUG_ACPI_DECODE␊ |
803 | DBG( "Found Scope: ");␊ |
804 | dprint_namespace(&new_ns);␊ |
805 | DBG( "\n");␊ |
806 | #endif␊ |
807 | parse_acpi_termlist(&new_ns, current, new_end);␊ |
808 | #if DEBUG_ACPI_DECODE␊ |
809 | DBG( "End Scope: ");␊ |
810 | dprint_namespace(&new_ns);␊ |
811 | DBG( "\n");␊ |
812 | #endif␊ |
813 | current = new_end;␊ |
814 | break;␊ |
815 | }␊ |
816 | case AML_NAME_OP:␊ |
817 | current++;␊ |
818 | current = parse_acpi_namestring(ns, NULL, current, end);␊ |
819 | current = parse_acpi_datarefobject(ns, current, end);␊ |
820 | break;␊ |
821 | case AML_ALIAS_OP:␊ |
822 | current++;␊ |
823 | current = parse_acpi_namestring(ns, NULL, current, end);␊ |
824 | current = parse_acpi_namestring(ns, NULL, current, end);␊ |
825 | break;␊ |
826 | default:␊ |
827 | break;␊ |
828 | }␊ |
829 | return current;␊ |
830 | }␊ |
831 | ␊ |
832 | static U8 *parse_acpi_objectlist(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
833 | {␊ |
834 | DBG( "Beginning objectlist: 0x%02x at memory location %p end=%p\n", *current, current, end);␊ |
835 | while (current < end) {␊ |
836 | U8 *temp = current;␊ |
837 | ␊ |
838 | DBG( "New iteration of objectlist: 0x%02x at memory location %p end=%p\n", *current, current, end);␊ |
839 | ␊ |
840 | current = parse_acpi_namespacemodifierobj(ns, current, end);␊ |
841 | if (current != temp)␊ |
842 | continue;␊ |
843 | ␊ |
844 | current = parse_acpi_namedobj(ns, current, end);␊ |
845 | if (current != temp)␊ |
846 | continue;␊ |
847 | ␊ |
848 | if (current == temp) {␊ |
849 | DBG( "Unhandled object in object list: 0x%02x at memory location %p\n", *current, current);␊ |
850 | #if DEBUG_ACPI_DECODE␊ |
851 | DBG( "namespace: ");␊ |
852 | dprint_namespace(ns);␊ |
853 | DBG( "\n");␊ |
854 | #endif␊ |
855 | break;␊ |
856 | }␊ |
857 | }␊ |
858 | DBG( "Ending objectlist: 0x%02x at memory location %p\n", *current, current);␊ |
859 | return current;␊ |
860 | }␊ |
861 | ␊ |
862 | static U8 *parse_acpi_termarglist(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
863 | {␊ |
864 | DBG( "Beginning termarglist: 0x%02x at memory location %p\n", *current, current);␊ |
865 | while (current < end) {␊ |
866 | U8 *temp = current;␊ |
867 | ␊ |
868 | current = parse_acpi_termarg(ns, current, end);␊ |
869 | if (current == temp) {␊ |
870 | DBG( "Unhandled item in term arg list: 0x%02x at memory location %p\n", *current, current);␊ |
871 | #if DEBUG_ACPI_DECODE␊ |
872 | DBG( "namespace: ");␊ |
873 | dprint_namespace(ns);␊ |
874 | DBG( "\n");␊ |
875 | #endif␊ |
876 | break;␊ |
877 | }␊ |
878 | }␊ |
879 | return current;␊ |
880 | }␊ |
881 | ␊ |
882 | void parse_acpi_termlist(const struct acpi_namespace *ns, U8 * current, U8 * end)␊ |
883 | {␊ |
884 | while (current < end) {␊ |
885 | U8 *temp = current;␊ |
886 | ␊ |
887 | DBG( "Beginning new term in term list: 0x%02x at memory location %p\n", *current, current);␊ |
888 | ␊ |
889 | current = parse_acpi_namespacemodifierobj(ns, current, end);␊ |
890 | if (current != temp)␊ |
891 | continue;␊ |
892 | ␊ |
893 | current = parse_acpi_namedobj(ns, current, end);␊ |
894 | if (current != temp)␊ |
895 | continue;␊ |
896 | ␊ |
897 | current = parse_acpi_type1opcode(ns, current, end);␊ |
898 | if (current != temp)␊ |
899 | continue;␊ |
900 | ␊ |
901 | current = parse_acpi_type2opcode(ns, current, end);␊ |
902 | if (current != temp)␊ |
903 | continue;␊ |
904 | ␊ |
905 | switch (*current) {␊ |
906 | default:␊ |
907 | {␊ |
908 | DBG( "Unhandled item in term list: 0x%02x at memory location %p\n", *current, current);␊ |
909 | #if DEBUG_ACPI_DECODE␊ |
910 | DBG( "namespace: ");␊ |
911 | dprint_namespace(ns);␊ |
912 | DBG( "\n");␊ |
913 | #endif␊ |
914 | return;␊ |
915 | }␊ |
916 | }␊ |
917 | }␊ |
918 | }␊ |
919 |