xref: /freebsd/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c (revision 93e779a26c651610ac6e7986d67ecc9ed2cadcbf)
1 /*******************************************************************************
2  *
3  * Module Name: dmbuffer - AML disassembler, buffer and string support
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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 #include <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/acutils.h>
47 #include <contrib/dev/acpica/include/acdisasm.h>
48 #include <contrib/dev/acpica/include/acparser.h>
49 #include <contrib/dev/acpica/include/amlcode.h>
50 #include <contrib/dev/acpica/include/acinterp.h>
51 
52 
53 #define _COMPONENT          ACPI_CA_DEBUGGER
54         ACPI_MODULE_NAME    ("dmbuffer")
55 
56 /* Local prototypes */
57 
58 static void
59 AcpiDmUuid (
60     ACPI_PARSE_OBJECT       *Op);
61 
62 static void
63 AcpiDmUnicode (
64     ACPI_PARSE_OBJECT       *Op);
65 
66 static void
67 AcpiDmGetHardwareIdType (
68     ACPI_PARSE_OBJECT       *Op);
69 
70 static void
71 AcpiDmPldBuffer (
72     UINT32                  Level,
73     UINT8                   *ByteData,
74     UINT32                  ByteCount);
75 
76 
77 #define ACPI_BUFFER_BYTES_PER_LINE      8
78 
79 
80 /* Strings for ToPld */
81 
82 static char *DmPanelList[] =
83 {
84     "TOP",
85     "BOTTOM",
86     "LEFT",
87     "RIGHT",
88     "FRONT",
89     "BACK",
90     "UNKNOWN",
91     NULL
92 };
93 
94 static char *DmVerticalPositionList[] =
95 {
96     "UPPER",
97     "CENTER",
98     "LOWER",
99     NULL
100 };
101 
102 static char *DmHorizontalPositionList[] =
103 {
104     "LEFT",
105     "CENTER",
106     "RIGHT",
107     NULL
108 };
109 
110 static char *DmShapeList[] =
111 {
112     "ROUND",
113     "OVAL",
114     "SQUARE",
115     "VERTICALRECTANGLE",
116     "HORIZONTALRECTANGLE",
117     "VERTICALTRAPEZOID",
118     "HORIZONTALTRAPEZOID",
119     "UNKNOWN",
120     "CHAMFERED",
121     NULL
122 };
123 
124 
125 /*******************************************************************************
126  *
127  * FUNCTION:    AcpiDmDisasmByteList
128  *
129  * PARAMETERS:  Level               - Current source code indentation level
130  *              ByteData            - Pointer to the byte list
131  *              ByteCount           - Length of the byte list
132  *
133  * RETURN:      None
134  *
135  * DESCRIPTION: Dump an AML "ByteList" in Hex format. 8 bytes per line, prefixed
136  *              with the hex buffer offset.
137  *
138  ******************************************************************************/
139 
140 void
141 AcpiDmDisasmByteList (
142     UINT32                  Level,
143     UINT8                   *ByteData,
144     UINT32                  ByteCount)
145 {
146     UINT32                  i;
147     UINT32                  j;
148     UINT32                  CurrentIndex;
149     UINT8                   BufChar;
150 
151 
152     if (!ByteCount)
153     {
154         return;
155     }
156 
157     for (i = 0; i < ByteCount; i += ACPI_BUFFER_BYTES_PER_LINE)
158     {
159         /* Line indent and offset prefix for each new line */
160 
161         AcpiDmIndent (Level);
162         if (ByteCount > ACPI_BUFFER_BYTES_PER_LINE)
163         {
164             AcpiOsPrintf ("/* %04X */ ", i);
165         }
166 
167         /* Dump the actual hex values */
168 
169         for (j = 0; j < ACPI_BUFFER_BYTES_PER_LINE; j++)
170         {
171             CurrentIndex = i + j;
172             if (CurrentIndex >= ByteCount)
173             {
174                 /* Dump fill spaces */
175 
176                 AcpiOsPrintf ("      ");
177                 continue;
178             }
179 
180             AcpiOsPrintf (" 0x%2.2X", ByteData[CurrentIndex]);
181 
182             /* Add comma if there are more bytes to display */
183 
184             if (CurrentIndex < (ByteCount - 1))
185             {
186                 AcpiOsPrintf (",");
187             }
188             else
189             {
190                 AcpiOsPrintf (" ");
191             }
192         }
193 
194         /* Dump the ASCII equivalents within a comment */
195 
196         AcpiOsPrintf ("  /* ");
197         for (j = 0; j < ACPI_BUFFER_BYTES_PER_LINE; j++)
198         {
199             CurrentIndex = i + j;
200             if (CurrentIndex >= ByteCount)
201             {
202                 break;
203             }
204 
205             BufChar = ByteData[CurrentIndex];
206             if (isprint (BufChar))
207             {
208                 AcpiOsPrintf ("%c", BufChar);
209             }
210             else
211             {
212                 AcpiOsPrintf (".");
213             }
214         }
215 
216         /* Finished with this line */
217 
218         AcpiOsPrintf (" */\n");
219     }
220 }
221 
222 
223 /*******************************************************************************
224  *
225  * FUNCTION:    AcpiDmByteList
226  *
227  * PARAMETERS:  Info            - Parse tree walk info
228  *              Op              - Byte list op
229  *
230  * RETURN:      None
231  *
232  * DESCRIPTION: Dump a buffer byte list, handling the various types of buffers.
233  *              Buffer type must be already set in the Op DisasmOpcode.
234  *
235  ******************************************************************************/
236 
237 void
238 AcpiDmByteList (
239     ACPI_OP_WALK_INFO       *Info,
240     ACPI_PARSE_OBJECT       *Op)
241 {
242     UINT8                   *ByteData;
243     UINT32                  ByteCount;
244 
245 
246     ByteData = Op->Named.Data;
247     ByteCount = (UINT32) Op->Common.Value.Integer;
248 
249     /*
250      * The byte list belongs to a buffer, and can be produced by either
251      * a ResourceTemplate, Unicode, quoted string, or a plain byte list.
252      */
253     switch (Op->Common.Parent->Common.DisasmOpcode)
254     {
255     case ACPI_DASM_RESOURCE:
256 
257         AcpiDmResourceTemplate (Info, Op->Common.Parent, ByteData, ByteCount);
258         break;
259 
260     case ACPI_DASM_STRING:
261 
262         AcpiDmIndent (Info->Level);
263         AcpiUtPrintString ((char *) ByteData, ACPI_UINT16_MAX);
264         AcpiOsPrintf ("\n");
265         break;
266 
267     case ACPI_DASM_UUID:
268 
269         AcpiDmUuid (Op);
270         break;
271 
272     case ACPI_DASM_UNICODE:
273 
274         AcpiDmUnicode (Op);
275         break;
276 
277     case ACPI_DASM_PLD_METHOD:
278 #if 0
279         AcpiDmDisasmByteList (Info->Level, ByteData, ByteCount);
280 #endif
281         AcpiDmPldBuffer (Info->Level, ByteData, ByteCount);
282         break;
283 
284     case ACPI_DASM_BUFFER:
285     default:
286         /*
287          * Not a resource, string, or unicode string.
288          * Just dump the buffer
289          */
290         AcpiDmDisasmByteList (Info->Level, ByteData, ByteCount);
291         break;
292     }
293 }
294 
295 
296 /*******************************************************************************
297  *
298  * FUNCTION:    AcpiDmIsUuidBuffer
299  *
300  * PARAMETERS:  Op              - Buffer Object to be examined
301  *
302  * RETURN:      TRUE if buffer contains a UUID
303  *
304  * DESCRIPTION: Determine if a buffer Op contains a UUID
305  *
306  * To help determine whether the buffer is a UUID versus a raw data buffer,
307  * there a are a couple bytes we can look at:
308  *
309  *    xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
310  *
311  * The variant covered by the UUID specification is indicated by the two most
312  * significant bits of N being 1 0 (i.e., the hexadecimal N will always be
313  * 8, 9, A, or B).
314  *
315  * The variant covered by the UUID specification has five versions. For this
316  * variant, the four bits of M indicates the UUID version (i.e., the
317  * hexadecimal M will be either 1, 2, 3, 4, or 5).
318  *
319  ******************************************************************************/
320 
321 BOOLEAN
322 AcpiDmIsUuidBuffer (
323     ACPI_PARSE_OBJECT       *Op)
324 {
325     UINT8                   *ByteData;
326     UINT32                  ByteCount;
327     ACPI_PARSE_OBJECT       *SizeOp;
328     ACPI_PARSE_OBJECT       *NextOp;
329 
330 
331     /* Buffer size is the buffer argument */
332 
333     SizeOp = Op->Common.Value.Arg;
334 
335     /* Next, the initializer byte list to examine */
336 
337     NextOp = SizeOp->Common.Next;
338     if (!NextOp)
339     {
340         return (FALSE);
341     }
342 
343     /* Extract the byte list info */
344 
345     ByteData = NextOp->Named.Data;
346     ByteCount = (UINT32) NextOp->Common.Value.Integer;
347 
348     /* Byte count must be exactly 16 */
349 
350     if (ByteCount != UUID_BUFFER_LENGTH)
351     {
352         return (FALSE);
353     }
354 
355     /* Check for valid "M" and "N" values (see function header above) */
356 
357     if (((ByteData[7] & 0xF0) == 0x00) || /* M={1,2,3,4,5} */
358         ((ByteData[7] & 0xF0) > 0x50)  ||
359         ((ByteData[8] & 0xF0) < 0x80)  || /* N={8,9,A,B} */
360         ((ByteData[8] & 0xF0) > 0xB0))
361     {
362         return (FALSE);
363     }
364 
365     /* Ignore the Size argument in the disassembly of this buffer op */
366 
367     SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
368     return (TRUE);
369 }
370 
371 
372 /*******************************************************************************
373  *
374  * FUNCTION:    AcpiDmUuid
375  *
376  * PARAMETERS:  Op              - Byte List op containing a UUID
377  *
378  * RETURN:      None
379  *
380  * DESCRIPTION: Dump a buffer containing a UUID as a standard ASCII string.
381  *
382  * Output Format:
383  * In its canonical form, the UUID is represented by a string containing 32
384  * lowercase hexadecimal digits, displayed in 5 groups separated by hyphens.
385  * The complete form is 8-4-4-4-12 for a total of 36 characters (32
386  * alphanumeric characters representing hex digits and 4 hyphens). In bytes,
387  * 4-2-2-2-6. Example:
388  *
389  *    ToUUID ("107ededd-d381-4fd7-8da9-08e9a6c79644")
390  *
391  ******************************************************************************/
392 
393 static void
394 AcpiDmUuid (
395     ACPI_PARSE_OBJECT       *Op)
396 {
397     UINT8                   *Data;
398     const char              *Description;
399 
400 
401     Data = ACPI_CAST_PTR (UINT8, Op->Named.Data);
402 
403     /* Emit the 36-byte UUID string in the proper format/order */
404 
405     AcpiOsPrintf (
406         "\"%2.2x%2.2x%2.2x%2.2x-"
407         "%2.2x%2.2x-"
408         "%2.2x%2.2x-"
409         "%2.2x%2.2x-"
410         "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\")",
411         Data[3], Data[2], Data[1], Data[0],
412         Data[5], Data[4],
413         Data[7], Data[6],
414         Data[8], Data[9],
415         Data[10], Data[11], Data[12], Data[13], Data[14], Data[15]);
416 
417     /* Dump the UUID description string if available */
418 
419     Description = AcpiAhMatchUuid (Data);
420     if (Description)
421     {
422         AcpiOsPrintf (" /* %s */", Description);
423     }
424 }
425 
426 
427 /*******************************************************************************
428  *
429  * FUNCTION:    AcpiDmIsUnicodeBuffer
430  *
431  * PARAMETERS:  Op              - Buffer Object to be examined
432  *
433  * RETURN:      TRUE if buffer contains a UNICODE string
434  *
435  * DESCRIPTION: Determine if a buffer Op contains a Unicode string
436  *
437  ******************************************************************************/
438 
439 BOOLEAN
440 AcpiDmIsUnicodeBuffer (
441     ACPI_PARSE_OBJECT       *Op)
442 {
443     UINT8                   *ByteData;
444     UINT32                  ByteCount;
445     UINT32                  WordCount;
446     ACPI_PARSE_OBJECT       *SizeOp;
447     ACPI_PARSE_OBJECT       *NextOp;
448     UINT32                  i;
449 
450 
451     /* Buffer size is the buffer argument */
452 
453     SizeOp = Op->Common.Value.Arg;
454 
455     /* Next, the initializer byte list to examine */
456 
457     NextOp = SizeOp->Common.Next;
458     if (!NextOp)
459     {
460         return (FALSE);
461     }
462 
463     /* Extract the byte list info */
464 
465     ByteData = NextOp->Named.Data;
466     ByteCount = (UINT32) NextOp->Common.Value.Integer;
467     WordCount = ACPI_DIV_2 (ByteCount);
468 
469     /*
470      * Unicode string must have an even number of bytes and last
471      * word must be zero
472      */
473     if ((!ByteCount)     ||
474          (ByteCount < 4) ||
475          (ByteCount & 1) ||
476         ((UINT16 *) (void *) ByteData)[WordCount - 1] != 0)
477     {
478         return (FALSE);
479     }
480 
481     /* For each word, 1st byte must be ascii (1-0x7F), 2nd byte must be zero */
482 
483     for (i = 0; i < (ByteCount - 2); i += 2)
484     {
485         if ((ByteData[i] == 0) ||
486             (ByteData[i] > 0x7F) ||
487             (ByteData[(ACPI_SIZE) i + 1] != 0))
488         {
489             return (FALSE);
490         }
491     }
492 
493     /* Ignore the Size argument in the disassembly of this buffer op */
494 
495     SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
496     return (TRUE);
497 }
498 
499 
500 /*******************************************************************************
501  *
502  * FUNCTION:    AcpiDmIsStringBuffer
503  *
504  * PARAMETERS:  Op              - Buffer Object to be examined
505  *
506  * RETURN:      TRUE if buffer contains a ASCII string, FALSE otherwise
507  *
508  * DESCRIPTION: Determine if a buffer Op contains a ASCII string
509  *
510  ******************************************************************************/
511 
512 BOOLEAN
513 AcpiDmIsStringBuffer (
514     ACPI_PARSE_OBJECT       *Op)
515 {
516     UINT8                   *ByteData;
517     UINT32                  ByteCount;
518     ACPI_PARSE_OBJECT       *SizeOp;
519     ACPI_PARSE_OBJECT       *NextOp;
520     UINT32                  i;
521 
522 
523     /* Buffer size is the buffer argument */
524 
525     SizeOp = Op->Common.Value.Arg;
526 
527     /* Next, the initializer byte list to examine */
528 
529     NextOp = SizeOp->Common.Next;
530     if (!NextOp)
531     {
532         return (FALSE);
533     }
534 
535     /* Extract the byte list info */
536 
537     ByteData = NextOp->Named.Data;
538     ByteCount = (UINT32) NextOp->Common.Value.Integer;
539 
540     /* Last byte must be the null terminator */
541 
542     if ((!ByteCount)     ||
543          (ByteCount < 2) ||
544          (ByteData[ByteCount-1] != 0))
545     {
546         return (FALSE);
547     }
548 
549     for (i = 0; i < (ByteCount - 1); i++)
550     {
551         /* TBD: allow some escapes (non-ascii chars).
552          * they will be handled in the string output routine
553          */
554 
555         if (!isprint (ByteData[i]))
556         {
557             return (FALSE);
558         }
559     }
560 
561     return (TRUE);
562 }
563 
564 
565 /*******************************************************************************
566  *
567  * FUNCTION:    AcpiDmIsPldBuffer
568  *
569  * PARAMETERS:  Op                  - Buffer Object to be examined
570  *
571  * RETURN:      TRUE if buffer contains a ASCII string, FALSE otherwise
572  *
573  * DESCRIPTION: Determine if a buffer Op contains a _PLD structure
574  *
575  ******************************************************************************/
576 
577 BOOLEAN
578 AcpiDmIsPldBuffer (
579     ACPI_PARSE_OBJECT       *Op)
580 {
581     ACPI_NAMESPACE_NODE     *Node;
582     ACPI_PARSE_OBJECT       *SizeOp;
583     ACPI_PARSE_OBJECT       *ParentOp;
584 
585 
586     /* Buffer size is the buffer argument */
587 
588     SizeOp = Op->Common.Value.Arg;
589 
590     ParentOp = Op->Common.Parent;
591     if (!ParentOp)
592     {
593         return (FALSE);
594     }
595 
596     /* Check for form: Name(_PLD, Buffer() {}). Not legal, however */
597 
598     if (ParentOp->Common.AmlOpcode == AML_NAME_OP)
599     {
600         Node = ParentOp->Common.Node;
601 
602         if (ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__PLD))
603         {
604             /* Ignore the Size argument in the disassembly of this buffer op */
605 
606             SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
607             return (TRUE);
608         }
609 
610         return (FALSE);
611     }
612 
613     /* Check for proper form: Name(_PLD, Package() {Buffer() {}}) */
614 
615     if (ParentOp->Common.AmlOpcode == AML_PACKAGE_OP)
616     {
617         ParentOp = ParentOp->Common.Parent;
618         if (!ParentOp)
619         {
620             return (FALSE);
621         }
622 
623         if (ParentOp->Common.AmlOpcode == AML_NAME_OP)
624         {
625             Node = ParentOp->Common.Node;
626 
627             if (ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__PLD))
628             {
629                 /* Ignore the Size argument in the disassembly of this buffer op */
630 
631                 SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
632                 return (TRUE);
633             }
634         }
635     }
636 
637     return (FALSE);
638 }
639 
640 
641 /*******************************************************************************
642  *
643  * FUNCTION:    AcpiDmFindNameByIndex
644  *
645  * PARAMETERS:  Index               - Index of array to check
646  *              List                - Array to reference
647  *
648  * RETURN:      String from List or empty string
649  *
650  * DESCRIPTION: Finds and returns the char string located at the given index
651  *              position in List.
652  *
653  ******************************************************************************/
654 
655 static char *
656 AcpiDmFindNameByIndex (
657     UINT64                  Index,
658     char                    **List)
659 {
660     char                     *Str;
661     UINT32                   i;
662 
663 
664     /* Bounds check */
665 
666     Str = List[0];
667     i = 0;
668 
669     while(Str)
670     {
671         i++;
672         Str = List[i];
673     }
674 
675     if (Index >= i)
676     {
677         /* TBD: Add error msg */
678 
679         return ("");
680     }
681 
682     return (List[Index]);
683 }
684 
685 
686 /*******************************************************************************
687  *
688  * FUNCTION:    AcpiDmPldBuffer
689  *
690  * PARAMETERS:  Level               - Current source code indentation level
691  *              ByteData            - Pointer to the byte list
692  *              ByteCount           - Length of the byte list
693  *
694  * RETURN:      None
695  *
696  * DESCRIPTION: Dump and format the contents of a _PLD buffer object
697  *
698  ******************************************************************************/
699 
700 #define ACPI_PLD_OUTPUT08   "%*.s%-18s = 0x%X,\n", ACPI_MUL_4 (Level), " "
701 #define ACPI_PLD_OUTPUT08P  "%*.s%-18s = 0x%X)\n", ACPI_MUL_4 (Level), " "
702 #define ACPI_PLD_OUTPUT16   "%*.s%-18s = 0x%X,\n", ACPI_MUL_4 (Level), " "
703 #define ACPI_PLD_OUTPUT16P  "%*.s%-18s = 0x%X)\n", ACPI_MUL_4 (Level), " "
704 #define ACPI_PLD_OUTPUT24   "%*.s%-18s = 0x%X,\n", ACPI_MUL_4 (Level), " "
705 #define ACPI_PLD_OUTPUTSTR  "%*.s%-18s = \"%s\",\n", ACPI_MUL_4 (Level), " "
706 
707 static void
708 AcpiDmPldBuffer (
709     UINT32                  Level,
710     UINT8                   *ByteData,
711     UINT32                  ByteCount)
712 {
713     ACPI_PLD_INFO           *PldInfo;
714     ACPI_STATUS             Status;
715 
716 
717     /* Check for valid byte count */
718 
719     if (ByteCount < ACPI_PLD_REV1_BUFFER_SIZE)
720     {
721         return;
722     }
723 
724     /* Convert _PLD buffer to local _PLD struct */
725 
726     Status = AcpiDecodePldBuffer (ByteData, ByteCount, &PldInfo);
727     if (ACPI_FAILURE (Status))
728     {
729         return;
730     }
731 
732     AcpiOsPrintf ("\n");
733 
734     /* First 32-bit dword */
735 
736     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Revision", PldInfo->Revision);
737     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_IgnoreColor", PldInfo->IgnoreColor);
738     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Red", PldInfo->Red);
739     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Green", PldInfo->Green);
740     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Blue", PldInfo->Blue);
741 
742     /* Second 32-bit dword */
743 
744     AcpiOsPrintf (ACPI_PLD_OUTPUT16,  "PLD_Width", PldInfo->Width);
745     AcpiOsPrintf (ACPI_PLD_OUTPUT16,  "PLD_Height", PldInfo->Height);
746 
747     /* Third 32-bit dword */
748 
749     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_UserVisible", PldInfo->UserVisible);
750     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Dock", PldInfo->Dock);
751     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Lid", PldInfo->Lid);
752     AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_Panel",
753         AcpiDmFindNameByIndex(PldInfo->Panel, DmPanelList));
754     AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_VerticalPosition",
755         AcpiDmFindNameByIndex(PldInfo->VerticalPosition, DmVerticalPositionList));
756     AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_HorizontalPosition",
757         AcpiDmFindNameByIndex(PldInfo->HorizontalPosition, DmHorizontalPositionList));
758     AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_Shape",
759         AcpiDmFindNameByIndex(PldInfo->Shape, DmShapeList));
760     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_GroupOrientation", PldInfo->GroupOrientation);
761     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_GroupToken", PldInfo->GroupToken);
762     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_GroupPosition", PldInfo->GroupPosition);
763     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Bay", PldInfo->Bay);
764 
765     /* Fourth 32-bit dword */
766 
767     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Ejectable", PldInfo->Ejectable);
768     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_EjectRequired", PldInfo->OspmEjectRequired);
769     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_CabinetNumber", PldInfo->CabinetNumber);
770     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_CardCageNumber", PldInfo->CardCageNumber);
771     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Reference", PldInfo->Reference);
772     AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Rotation", PldInfo->Rotation);
773 
774     if (ByteCount >= ACPI_PLD_REV2_BUFFER_SIZE)
775     {
776         AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Order", PldInfo->Order);
777 
778         /* Fifth 32-bit dword */
779 
780         AcpiOsPrintf (ACPI_PLD_OUTPUT16,  "PLD_VerticalOffset", PldInfo->VerticalOffset);
781         AcpiOsPrintf (ACPI_PLD_OUTPUT16P, "PLD_HorizontalOffset", PldInfo->HorizontalOffset);
782     }
783     else /* Rev 1 buffer */
784     {
785         AcpiOsPrintf (ACPI_PLD_OUTPUT08P, "PLD_Order", PldInfo->Order);
786     }
787 
788     ACPI_FREE (PldInfo);
789 }
790 
791 
792 /*******************************************************************************
793  *
794  * FUNCTION:    AcpiDmUnicode
795  *
796  * PARAMETERS:  Op              - Byte List op containing Unicode string
797  *
798  * RETURN:      None
799  *
800  * DESCRIPTION: Dump Unicode string as a standard ASCII string. (Remove
801  *              the extra zero bytes).
802  *
803  ******************************************************************************/
804 
805 static void
806 AcpiDmUnicode (
807     ACPI_PARSE_OBJECT       *Op)
808 {
809     UINT16                  *WordData;
810     UINT32                  WordCount;
811     UINT32                  i;
812     int                     OutputValue;
813 
814 
815     /* Extract the buffer info as a WORD buffer */
816 
817     WordData = ACPI_CAST_PTR (UINT16, Op->Named.Data);
818     WordCount = ACPI_DIV_2 (((UINT32) Op->Common.Value.Integer));
819 
820     /* Write every other byte as an ASCII character */
821 
822     AcpiOsPrintf ("\"");
823     for (i = 0; i < (WordCount - 1); i++)
824     {
825         OutputValue = (int) WordData[i];
826 
827         /* Handle values that must be escaped */
828 
829         if ((OutputValue == '\"') ||
830             (OutputValue == '\\'))
831         {
832             AcpiOsPrintf ("\\%c", OutputValue);
833         }
834         else if (!isprint (OutputValue))
835         {
836             AcpiOsPrintf ("\\x%2.2X", OutputValue);
837         }
838         else
839         {
840             AcpiOsPrintf ("%c", OutputValue);
841         }
842     }
843 
844     AcpiOsPrintf ("\")");
845 }
846 
847 
848 /*******************************************************************************
849  *
850  * FUNCTION:    AcpiDmGetHardwareIdType
851  *
852  * PARAMETERS:  Op              - Op to be examined
853  *
854  * RETURN:      None
855  *
856  * DESCRIPTION: Determine the type of the argument to a _HID or _CID
857  *              1) Strings are allowed
858  *              2) If Integer, determine if it is a valid EISAID
859  *
860  ******************************************************************************/
861 
862 static void
863 AcpiDmGetHardwareIdType (
864     ACPI_PARSE_OBJECT       *Op)
865 {
866     UINT32                  BigEndianId;
867     UINT32                  Prefix[3];
868     UINT32                  i;
869 
870 
871     switch (Op->Common.AmlOpcode)
872     {
873     case AML_STRING_OP:
874 
875         /* Mark this string as an _HID/_CID string */
876 
877         Op->Common.DisasmOpcode = ACPI_DASM_HID_STRING;
878         break;
879 
880     case AML_WORD_OP:
881     case AML_DWORD_OP:
882 
883         /* Determine if a Word/Dword is a valid encoded EISAID */
884 
885         /* Swap from little-endian to big-endian to simplify conversion */
886 
887         BigEndianId = AcpiUtDwordByteSwap ((UINT32) Op->Common.Value.Integer);
888 
889         /* Create the 3 leading ASCII letters */
890 
891         Prefix[0] = ((BigEndianId >> 26) & 0x1F) + 0x40;
892         Prefix[1] = ((BigEndianId >> 21) & 0x1F) + 0x40;
893         Prefix[2] = ((BigEndianId >> 16) & 0x1F) + 0x40;
894 
895         /* Verify that all 3 are ascii and alpha */
896 
897         for (i = 0; i < 3; i++)
898         {
899             if (!ACPI_IS_ASCII (Prefix[i]) ||
900                 !isalpha (Prefix[i]))
901             {
902                 return;
903             }
904         }
905 
906         /* Mark this node as convertable to an EISA ID string */
907 
908         Op->Common.DisasmOpcode = ACPI_DASM_EISAID;
909         break;
910 
911     default:
912         break;
913     }
914 }
915 
916 
917 /*******************************************************************************
918  *
919  * FUNCTION:    AcpiDmCheckForHardwareId
920  *
921  * PARAMETERS:  Op              - Op to be examined
922  *
923  * RETURN:      None
924  *
925  * DESCRIPTION: Determine if a Name() Op is a _HID/_CID.
926  *
927  ******************************************************************************/
928 
929 void
930 AcpiDmCheckForHardwareId (
931     ACPI_PARSE_OBJECT       *Op)
932 {
933     UINT32                  Name;
934     ACPI_PARSE_OBJECT       *NextOp;
935 
936 
937     /* Get the NameSegment */
938 
939     Name = AcpiPsGetName (Op);
940     if (!Name)
941     {
942         return;
943     }
944 
945     NextOp = AcpiPsGetDepthNext (NULL, Op);
946     if (!NextOp)
947     {
948         return;
949     }
950 
951     /* Check for _HID - has one argument */
952 
953     if (ACPI_COMPARE_NAME (&Name, METHOD_NAME__HID))
954     {
955         AcpiDmGetHardwareIdType (NextOp);
956         return;
957     }
958 
959     /* Exit if not _CID */
960 
961     if (!ACPI_COMPARE_NAME (&Name, METHOD_NAME__CID))
962     {
963         return;
964     }
965 
966     /* _CID can contain a single argument or a package */
967 
968     if (NextOp->Common.AmlOpcode != AML_PACKAGE_OP)
969     {
970         AcpiDmGetHardwareIdType (NextOp);
971         return;
972     }
973 
974     /* _CID with Package: get the package length, check all elements */
975 
976     NextOp = AcpiPsGetDepthNext (NULL, NextOp);
977     if (!NextOp)
978     {
979         return;
980     }
981 
982     /* Don't need to use the length, just walk the peer list */
983 
984     NextOp = NextOp->Common.Next;
985     while (NextOp)
986     {
987         AcpiDmGetHardwareIdType (NextOp);
988         NextOp = NextOp->Common.Next;
989     }
990 }
991 
992 
993 /*******************************************************************************
994  *
995  * FUNCTION:    AcpiDmDecompressEisaId
996  *
997  * PARAMETERS:  EncodedId       - Raw encoded EISA ID.
998  *
999  * RETURN:      None
1000  *
1001  * DESCRIPTION: Convert an encoded EISAID back to the original ASCII String
1002  *              and emit the correct ASL statement. If the ID is known, emit
1003  *              a description of the ID as a comment.
1004  *
1005  ******************************************************************************/
1006 
1007 void
1008 AcpiDmDecompressEisaId (
1009     UINT32                  EncodedId)
1010 {
1011     char                    IdBuffer[ACPI_EISAID_STRING_SIZE];
1012     const AH_DEVICE_ID      *Info;
1013 
1014 
1015     /* Convert EISAID to a string an emit the statement */
1016 
1017     AcpiExEisaIdToString (IdBuffer, EncodedId);
1018     AcpiOsPrintf ("EisaId (\"%s\")", IdBuffer);
1019 
1020     /* If we know about the ID, emit the description */
1021 
1022     Info = AcpiAhMatchHardwareId (IdBuffer);
1023     if (Info)
1024     {
1025         AcpiOsPrintf (" /* %s */", Info->Description);
1026     }
1027 }
1028