dmbuffer.c revision 1.1.1.2.4.2 1 /*******************************************************************************
2 *
3 * Module Name: dmbuffer - AML disassembler, buffer and string support
4 *
5 ******************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2011, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45 #include "acpi.h"
46 #include "accommon.h"
47 #include "acdisasm.h"
48 #include "acparser.h"
49 #include "amlcode.h"
50
51
52 #ifdef ACPI_DISASSEMBLER
53
54 #define _COMPONENT ACPI_CA_DEBUGGER
55 ACPI_MODULE_NAME ("dmbuffer")
56
57 /* Local prototypes */
58
59 static void
60 AcpiDmUnicode (
61 ACPI_PARSE_OBJECT *Op);
62
63 static void
64 AcpiDmIsEisaIdElement (
65 ACPI_PARSE_OBJECT *Op);
66
67
68 /*******************************************************************************
69 *
70 * FUNCTION: AcpiDmDisasmByteList
71 *
72 * PARAMETERS: Level - Current source code indentation level
73 * ByteData - Pointer to the byte list
74 * ByteCount - Length of the byte list
75 *
76 * RETURN: None
77 *
78 * DESCRIPTION: Dump an AML "ByteList" in Hex format. 8 bytes per line, prefixed
79 * with the hex buffer offset.
80 *
81 ******************************************************************************/
82
83 void
84 AcpiDmDisasmByteList (
85 UINT32 Level,
86 UINT8 *ByteData,
87 UINT32 ByteCount)
88 {
89 UINT32 i;
90
91
92 if (!ByteCount)
93 {
94 return;
95 }
96
97 /* Dump the byte list */
98
99 for (i = 0; i < ByteCount; i++)
100 {
101 /* New line every 8 bytes */
102
103 if (((i % 8) == 0) && (i < ByteCount))
104 {
105 if (i > 0)
106 {
107 AcpiOsPrintf ("\n");
108 }
109
110 AcpiDmIndent (Level);
111 if (ByteCount > 7)
112 {
113 AcpiOsPrintf ("/* %04X */ ", i);
114 }
115 }
116
117 AcpiOsPrintf ("0x%2.2X", (UINT32) ByteData[i]);
118
119 /* Add comma if there are more bytes to display */
120
121 if (i < (ByteCount -1))
122 {
123 AcpiOsPrintf (", ");
124 }
125 }
126
127 if (Level)
128 {
129 AcpiOsPrintf ("\n");
130 }
131 }
132
133
134 /*******************************************************************************
135 *
136 * FUNCTION: AcpiDmByteList
137 *
138 * PARAMETERS: Info - Parse tree walk info
139 * Op - Byte list op
140 *
141 * RETURN: None
142 *
143 * DESCRIPTION: Dump a buffer byte list, handling the various types of buffers.
144 * Buffer type must be already set in the Op DisasmOpcode.
145 *
146 ******************************************************************************/
147
148 void
149 AcpiDmByteList (
150 ACPI_OP_WALK_INFO *Info,
151 ACPI_PARSE_OBJECT *Op)
152 {
153 UINT8 *ByteData;
154 UINT32 ByteCount;
155
156
157 ByteData = Op->Named.Data;
158 ByteCount = (UINT32) Op->Common.Value.Integer;
159
160 /*
161 * The byte list belongs to a buffer, and can be produced by either
162 * a ResourceTemplate, Unicode, quoted string, or a plain byte list.
163 */
164 switch (Op->Common.Parent->Common.DisasmOpcode)
165 {
166 case ACPI_DASM_RESOURCE:
167
168 AcpiDmResourceTemplate (Info, Op->Common.Parent, ByteData, ByteCount);
169 break;
170
171 case ACPI_DASM_STRING:
172
173 AcpiDmIndent (Info->Level);
174 AcpiUtPrintString ((char *) ByteData, ACPI_UINT8_MAX);
175 AcpiOsPrintf ("\n");
176 break;
177
178 case ACPI_DASM_UNICODE:
179
180 AcpiDmUnicode (Op);
181 break;
182
183 case ACPI_DASM_BUFFER:
184 default:
185
186 /*
187 * Not a resource, string, or unicode string.
188 * Just dump the buffer
189 */
190 AcpiDmDisasmByteList (Info->Level, ByteData, ByteCount);
191 break;
192 }
193 }
194
195
196 /*******************************************************************************
197 *
198 * FUNCTION: AcpiDmIsUnicodeBuffer
199 *
200 * PARAMETERS: Op - Buffer Object to be examined
201 *
202 * RETURN: TRUE if buffer contains a UNICODE string
203 *
204 * DESCRIPTION: Determine if a buffer Op contains a Unicode string
205 *
206 ******************************************************************************/
207
208 BOOLEAN
209 AcpiDmIsUnicodeBuffer (
210 ACPI_PARSE_OBJECT *Op)
211 {
212 UINT8 *ByteData;
213 UINT32 ByteCount;
214 UINT32 WordCount;
215 ACPI_PARSE_OBJECT *SizeOp;
216 ACPI_PARSE_OBJECT *NextOp;
217 UINT32 i;
218
219
220 /* Buffer size is the buffer argument */
221
222 SizeOp = Op->Common.Value.Arg;
223
224 /* Next, the initializer byte list to examine */
225
226 NextOp = SizeOp->Common.Next;
227 if (!NextOp)
228 {
229 return (FALSE);
230 }
231
232 /* Extract the byte list info */
233
234 ByteData = NextOp->Named.Data;
235 ByteCount = (UINT32) NextOp->Common.Value.Integer;
236 WordCount = ACPI_DIV_2 (ByteCount);
237
238 /*
239 * Unicode string must have an even number of bytes and last
240 * word must be zero
241 */
242 if ((!ByteCount) ||
243 (ByteCount < 4) ||
244 (ByteCount & 1) ||
245 ((UINT16 *) (void *) ByteData)[WordCount - 1] != 0)
246 {
247 return (FALSE);
248 }
249
250 /* For each word, 1st byte must be ascii, 2nd byte must be zero */
251
252 for (i = 0; i < (ByteCount - 2); i += 2)
253 {
254 if ((!ACPI_IS_PRINT (ByteData[i])) ||
255 (ByteData[(ACPI_SIZE) i + 1] != 0))
256 {
257 return (FALSE);
258 }
259 }
260
261 /* Ignore the Size argument in the disassembly of this buffer op */
262
263 SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
264 return (TRUE);
265 }
266
267
268 /*******************************************************************************
269 *
270 * FUNCTION: AcpiDmIsStringBuffer
271 *
272 * PARAMETERS: Op - Buffer Object to be examined
273 *
274 * RETURN: TRUE if buffer contains a ASCII string, FALSE otherwise
275 *
276 * DESCRIPTION: Determine if a buffer Op contains a ASCII string
277 *
278 ******************************************************************************/
279
280 BOOLEAN
281 AcpiDmIsStringBuffer (
282 ACPI_PARSE_OBJECT *Op)
283 {
284 UINT8 *ByteData;
285 UINT32 ByteCount;
286 ACPI_PARSE_OBJECT *SizeOp;
287 ACPI_PARSE_OBJECT *NextOp;
288 UINT32 i;
289
290
291 /* Buffer size is the buffer argument */
292
293 SizeOp = Op->Common.Value.Arg;
294
295 /* Next, the initializer byte list to examine */
296
297 NextOp = SizeOp->Common.Next;
298 if (!NextOp)
299 {
300 return (FALSE);
301 }
302
303 /* Extract the byte list info */
304
305 ByteData = NextOp->Named.Data;
306 ByteCount = (UINT32) NextOp->Common.Value.Integer;
307
308 /* Last byte must be the null terminator */
309
310 if ((!ByteCount) ||
311 (ByteCount < 2) ||
312 (ByteData[ByteCount-1] != 0))
313 {
314 return (FALSE);
315 }
316
317 for (i = 0; i < (ByteCount - 1); i++)
318 {
319 /* TBD: allow some escapes (non-ascii chars).
320 * they will be handled in the string output routine
321 */
322
323 if (!ACPI_IS_PRINT (ByteData[i]))
324 {
325 return (FALSE);
326 }
327 }
328
329 return (TRUE);
330 }
331
332
333 /*******************************************************************************
334 *
335 * FUNCTION: AcpiDmUnicode
336 *
337 * PARAMETERS: Op - Byte List op containing Unicode string
338 *
339 * RETURN: None
340 *
341 * DESCRIPTION: Dump Unicode string as a standard ASCII string. (Remove
342 * the extra zero bytes).
343 *
344 ******************************************************************************/
345
346 static void
347 AcpiDmUnicode (
348 ACPI_PARSE_OBJECT *Op)
349 {
350 UINT16 *WordData;
351 UINT32 WordCount;
352 UINT32 i;
353
354
355 /* Extract the buffer info as a WORD buffer */
356
357 WordData = ACPI_CAST_PTR (UINT16, Op->Named.Data);
358 WordCount = ACPI_DIV_2 (((UINT32) Op->Common.Value.Integer));
359
360
361 AcpiOsPrintf ("\"");
362
363 /* Write every other byte as an ASCII character */
364
365 for (i = 0; i < (WordCount - 1); i++)
366 {
367 AcpiOsPrintf ("%c", (int) WordData[i]);
368 }
369
370 AcpiOsPrintf ("\")");
371 }
372
373
374 /*******************************************************************************
375 *
376 * FUNCTION: AcpiDmIsEisaIdElement
377 *
378 * PARAMETERS: Op - Op to be examined
379 *
380 * RETURN: None
381 *
382 * DESCRIPTION: Determine if an Op (argument to _HID or _CID) can be converted
383 * to an EISA ID.
384 *
385 ******************************************************************************/
386
387 static void
388 AcpiDmIsEisaIdElement (
389 ACPI_PARSE_OBJECT *Op)
390 {
391 UINT32 BigEndianId;
392 UINT32 Prefix[3];
393 UINT32 i;
394
395
396 /* The parameter must be either a word or a dword */
397
398 if ((Op->Common.AmlOpcode != AML_DWORD_OP) &&
399 (Op->Common.AmlOpcode != AML_WORD_OP))
400 {
401 return;
402 }
403
404 /* Swap from little-endian to big-endian to simplify conversion */
405
406 BigEndianId = AcpiUtDwordByteSwap ((UINT32) Op->Common.Value.Integer);
407
408 /* Create the 3 leading ASCII letters */
409
410 Prefix[0] = ((BigEndianId >> 26) & 0x1F) + 0x40;
411 Prefix[1] = ((BigEndianId >> 21) & 0x1F) + 0x40;
412 Prefix[2] = ((BigEndianId >> 16) & 0x1F) + 0x40;
413
414 /* Verify that all 3 are ascii and alpha */
415
416 for (i = 0; i < 3; i++)
417 {
418 if (!ACPI_IS_ASCII (Prefix[i]) ||
419 !ACPI_IS_ALPHA (Prefix[i]))
420 {
421 return;
422 }
423 }
424
425 /* OK - mark this node as convertable to an EISA ID */
426
427 Op->Common.DisasmOpcode = ACPI_DASM_EISAID;
428 }
429
430
431 /*******************************************************************************
432 *
433 * FUNCTION: AcpiDmIsEisaId
434 *
435 * PARAMETERS: Op - Op to be examined
436 *
437 * RETURN: None
438 *
439 * DESCRIPTION: Determine if a Name() Op can be converted to an EisaId.
440 *
441 ******************************************************************************/
442
443 void
444 AcpiDmIsEisaId (
445 ACPI_PARSE_OBJECT *Op)
446 {
447 UINT32 Name;
448 ACPI_PARSE_OBJECT *NextOp;
449
450
451 /* Get the NameSegment */
452
453 Name = AcpiPsGetName (Op);
454 if (!Name)
455 {
456 return;
457 }
458
459 NextOp = AcpiPsGetDepthNext (NULL, Op);
460 if (!NextOp)
461 {
462 return;
463 }
464
465 /* Check for _HID - has one argument */
466
467 if (ACPI_COMPARE_NAME (&Name, METHOD_NAME__HID))
468 {
469 AcpiDmIsEisaIdElement (NextOp);
470 return;
471 }
472
473 /* Exit if not _CID */
474
475 if (!ACPI_COMPARE_NAME (&Name, METHOD_NAME__CID))
476 {
477 return;
478 }
479
480 /* _CID can contain a single argument or a package */
481
482 if (NextOp->Common.AmlOpcode != AML_PACKAGE_OP)
483 {
484 AcpiDmIsEisaIdElement (NextOp);
485 return;
486 }
487
488 /* _CID with Package: get the package length */
489
490 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
491
492 /* Don't need to use the length, just walk the peer list */
493
494 NextOp = NextOp->Common.Next;
495 while (NextOp)
496 {
497 AcpiDmIsEisaIdElement (NextOp);
498 NextOp = NextOp->Common.Next;
499 }
500 }
501
502
503 /*******************************************************************************
504 *
505 * FUNCTION: AcpiDmEisaId
506 *
507 * PARAMETERS: EncodedId - Raw encoded EISA ID.
508 *
509 * RETURN: None
510 *
511 * DESCRIPTION: Convert an encoded EISAID back to the original ASCII String.
512 *
513 ******************************************************************************/
514
515 void
516 AcpiDmEisaId (
517 UINT32 EncodedId)
518 {
519 UINT32 BigEndianId;
520
521
522 /* Swap from little-endian to big-endian to simplify conversion */
523
524 BigEndianId = AcpiUtDwordByteSwap (EncodedId);
525
526
527 /* Split to form "AAANNNN" string */
528
529 AcpiOsPrintf ("EisaId (\"%c%c%c%4.4X\")",
530
531 /* Three Alpha characters (AAA), 5 bits each */
532
533 (int) ((BigEndianId >> 26) & 0x1F) + 0x40,
534 (int) ((BigEndianId >> 21) & 0x1F) + 0x40,
535 (int) ((BigEndianId >> 16) & 0x1F) + 0x40,
536
537 /* Numeric part (NNNN) is simply the lower 16 bits */
538
539 (UINT32) (BigEndianId & 0xFFFF));
540 }
541
542 #endif
543