xref: /netbsd-src/sys/external/bsd/acpica/dist/tools/acpihelp/ahdecode.c (revision 1b9578b8c2c1f848eeb16dabbfd7d1f0d9fdefbd)
1 /******************************************************************************
2  *
3  * Module Name: ahdecode - Operator/Opcode decoding for acpihelp utility
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 #include "acpihelp.h"
45 
46 #define ACPI_CREATE_PREDEFINED_TABLE
47 #include "acpredef.h"
48 
49 static char         Gbl_Buffer[64];
50 static const char   *AcpiRtypeNames[] =
51 {
52     "/Integer",
53     "/String",
54     "/Buffer",
55     "/Package",
56     "/Reference",
57 };
58 
59 
60 /* Local prototypes */
61 
62 static BOOLEAN
63 AhDisplayPredefinedName (
64     char                    *Name,
65     UINT32                  Length);
66 
67 static void
68 AhDisplayPredefinedInfo (
69     char                    *Name);
70 
71 static void
72 AhGetExpectedTypes (
73     char                    *Buffer,
74     UINT32                  ExpectedBtypes);
75 
76 static void
77 AhDisplayAmlOpcode (
78     const AH_AML_OPCODE     *Op);
79 
80 static void
81 AhDisplayAslOperator (
82     const AH_ASL_OPERATOR   *Op);
83 
84 static void
85 AhDisplayAslKeyword (
86     const AH_ASL_KEYWORD    *Op);
87 
88 static void
89 AhPrintOneField (
90     UINT32                  Indent,
91     UINT32                  CurrentPosition,
92     UINT32                  MaxPosition,
93     const char              *Field);
94 
95 
96 /*******************************************************************************
97  *
98  * FUNCTION:    AhFindPredefinedNames (entry point for predefined name search)
99  *
100  * PARAMETERS:  NamePrefix          - Name or prefix to find. Must start with
101  *                                    an underscore. NULL means "find all"
102  *
103  * RETURN:      None
104  *
105  * DESCRIPTION: Find and display all ACPI predefined names that match the
106  *              input name or prefix. Includes the required number of arguments
107  *              and the expected return type, if any.
108  *
109  ******************************************************************************/
110 
111 void
112 AhFindPredefinedNames (
113     char                    *NamePrefix)
114 {
115     UINT32                  Length;
116     BOOLEAN                 Found;
117     char                    Name[9];
118 
119 
120     if (!NamePrefix)
121     {
122         Found = AhDisplayPredefinedName (Name, 0);
123         return;
124     }
125 
126     /* Contruct a local name or name prefix */
127 
128     AhStrupr (NamePrefix);
129     if (*NamePrefix == '_')
130     {
131         NamePrefix++;
132     }
133 
134     Name[0] = '_';
135     strncpy (&Name[1], NamePrefix, 7);
136 
137     Length = strlen (Name);
138     if (Length > 4)
139     {
140         printf ("%.8s: Predefined name must be 4 characters maximum\n", Name);
141         return;
142     }
143 
144     Found = AhDisplayPredefinedName (Name, Length);
145     if (!Found)
146     {
147         printf ("%s, no matching predefined names\n", Name);
148     }
149 }
150 
151 
152 /*******************************************************************************
153  *
154  * FUNCTION:    AhDisplayPredefinedName
155  *
156  * PARAMETERS:  Name                - Name or name prefix
157  *
158  * RETURN:      TRUE if any names matched, FALSE otherwise
159  *
160  * DESCRIPTION: Display information about ACPI predefined names that match
161  *              the input name or name prefix.
162  *
163  ******************************************************************************/
164 
165 static BOOLEAN
166 AhDisplayPredefinedName (
167     char                    *Name,
168     UINT32                  Length)
169 {
170     const AH_PREDEFINED_NAME    *Info;
171     BOOLEAN                     Found = FALSE;
172     BOOLEAN                     Matched;
173     UINT32                      i;
174 
175 
176     /* Find/display all names that match the input name prefix */
177 
178     for (Info = AslPredefinedInfo; Info->Name; Info++)
179     {
180         if (!Name)
181         {
182             Found = TRUE;
183             printf ("%s: <%s>\n", Info->Name, Info->Description);
184             printf ("%*s%s\n", 6, " ", Info->Action);
185 
186             AhDisplayPredefinedInfo (Info->Name);
187             continue;
188         }
189 
190         Matched = TRUE;
191         for (i = 0; i < Length; i++)
192         {
193             if (Info->Name[i] != Name[i])
194             {
195                 Matched = FALSE;
196                 break;
197             }
198         }
199 
200         if (Matched)
201         {
202             Found = TRUE;
203             printf ("%s: <%s>\n", Info->Name, Info->Description);
204             printf ("%*s%s\n", 6, " ", Info->Action);
205 
206             AhDisplayPredefinedInfo (Info->Name);
207         }
208     }
209 
210     return (Found);
211 }
212 
213 
214 /*******************************************************************************
215  *
216  * FUNCTION:    AhDisplayPredefinedInfo
217  *
218  * PARAMETERS:  Name                - Exact 4-character ACPI name.
219  *
220  * RETURN:      None
221  *
222  * DESCRIPTION: Find the name in the main ACPICA predefined info table and
223  *              display the # of arguments and the return value type.
224  *
225  *              Note: Resource Descriptor field names do not appear in this
226  *              table -- thus, nothing will be displayed for them.
227  *
228  ******************************************************************************/
229 
230 static void
231 AhDisplayPredefinedInfo (
232     char                    *Name)
233 {
234     const ACPI_PREDEFINED_INFO  *ThisName;
235     BOOLEAN                     Matched;
236     UINT32                      i;
237 
238 
239     /* Find/display only the exact input name */
240 
241     for (ThisName = PredefinedNames; ThisName->Info.Name[0]; ThisName++)
242     {
243         Matched = TRUE;
244         for (i = 0; i < ACPI_NAME_SIZE; i++)
245         {
246             if (ThisName->Info.Name[i] != Name[i])
247             {
248                 Matched = FALSE;
249                 break;
250             }
251         }
252 
253         if (Matched)
254         {
255             AhGetExpectedTypes (Gbl_Buffer, ThisName->Info.ExpectedBtypes);
256 
257             printf ("%*s%4.4s has %u arguments, returns: %s\n",
258                 6, " ", ThisName->Info.Name, ThisName->Info.ParamCount,
259                 ThisName->Info.ExpectedBtypes ? Gbl_Buffer : "-Nothing-");
260             return;
261         }
262 
263         if (ThisName->Info.ExpectedBtypes & ACPI_RTYPE_PACKAGE)
264         {
265             ThisName++;
266         }
267     }
268 }
269 
270 
271 /*******************************************************************************
272  *
273  * FUNCTION:    AhGetExpectedTypes
274  *
275  * PARAMETERS:  Buffer              - Where the formatted string is returned
276  *              ExpectedBTypes      - Bitfield of expected data types
277  *
278  * RETURN:      Formatted string in Buffer.
279  *
280  * DESCRIPTION: Format the expected object types into a printable string.
281  *
282  ******************************************************************************/
283 
284 static void
285 AhGetExpectedTypes (
286     char                    *Buffer,
287     UINT32                  ExpectedBtypes)
288 {
289     UINT32                  ThisRtype;
290     UINT32                  i;
291     UINT32                  j;
292 
293 
294     j = 1;
295     Buffer[0] = 0;
296     ThisRtype = ACPI_RTYPE_INTEGER;
297 
298     for (i = 0; i < ACPI_NUM_RTYPES; i++)
299     {
300         /* If one of the expected types, concatenate the name of this type */
301 
302         if (ExpectedBtypes & ThisRtype)
303         {
304             strcat (Buffer, &AcpiRtypeNames[i][j]);
305             j = 0;              /* Use name separator from now on */
306         }
307         ThisRtype <<= 1;    /* Next Rtype */
308     }
309 }
310 
311 
312 /*******************************************************************************
313  *
314  * FUNCTION:    AhFindAmlOpcode (entry point for AML opcode name search)
315  *
316  * PARAMETERS:  Name                - Name or prefix for an AML opcode.
317  *                                    NULL means "find all"
318  *
319  * RETURN:      None
320  *
321  * DESCRIPTION: Find all AML opcodes that match the input Name or name
322  *              prefix.
323  *
324  ******************************************************************************/
325 
326 void
327 AhFindAmlOpcode (
328     char                    *Name)
329 {
330     const AH_AML_OPCODE     *Op;
331     BOOLEAN                 Found = FALSE;
332 
333 
334     AhStrupr (Name);
335 
336     /* Find/display all opcode names that match the input name prefix */
337 
338     for (Op = AmlOpcodeInfo; Op->OpcodeString; Op++)
339     {
340         if (!Op->OpcodeName) /* Unused opcodes */
341         {
342             continue;
343         }
344 
345         if (!Name)
346         {
347             AhDisplayAmlOpcode (Op);
348             Found = TRUE;
349             continue;
350         }
351 
352         /* Upper case the opcode name before substring compare */
353 
354         strcpy (Gbl_Buffer, Op->OpcodeName);
355         AhStrupr (Gbl_Buffer);
356 
357         if (strstr (Gbl_Buffer, Name) == Gbl_Buffer)
358         {
359             AhDisplayAmlOpcode (Op);
360             Found = TRUE;
361         }
362     }
363 
364     if (!Found)
365     {
366         printf ("%s, no matching AML operators\n", Name);
367     }
368 }
369 
370 
371 /*******************************************************************************
372  *
373  * FUNCTION:    AhDecodeAmlOpcode (entry point for AML opcode search)
374  *
375  * PARAMETERS:  OpcodeString        - String version of AML opcode
376  *
377  * RETURN:      None
378  *
379  * DESCRIPTION: Display information about the input AML opcode
380  *
381  ******************************************************************************/
382 
383 void
384 AhDecodeAmlOpcode (
385     char                    *OpcodeString)
386 {
387     const AH_AML_OPCODE     *Op;
388     UINT32                  Opcode;
389     BOOLEAN                 Found = FALSE;
390     UINT8                   Prefix;
391 
392 
393     if (!OpcodeString)
394     {
395         AhFindAmlOpcode (NULL);
396         return;
397     }
398 
399     Opcode = ACPI_STRTOUL (OpcodeString, NULL, 16);
400     if (Opcode > ACPI_UINT16_MAX)
401     {
402         printf ("Invalid opcode (more than 16 bits)\n");
403         return;
404     }
405 
406     /* Only valid opcode extension is 0x5B */
407 
408     Prefix = (Opcode & 0x0000FF00) >> 8;
409     if (Prefix && (Prefix != 0x5B))
410     {
411         printf ("Invalid opcode (invalid extension prefix 0x%X)\n",
412             Prefix);
413         return;
414     }
415 
416     /* Find/Display the opcode. May fall within an opcode range */
417 
418     for (Op = AmlOpcodeInfo; Op->OpcodeString; Op++)
419     {
420         if ((Opcode >= Op->OpcodeRangeStart) &&
421             (Opcode <= Op->OpcodeRangeEnd))
422         {
423             AhDisplayAmlOpcode (Op);
424             Found = TRUE;
425         }
426     }
427 }
428 
429 
430 /*******************************************************************************
431  *
432  * FUNCTION:    AhDisplayAmlOpcode
433  *
434  * PARAMETERS:  Op                  - An opcode info struct
435  *
436  * RETURN:      None
437  *
438  * DESCRIPTION: Display the contents of an AML opcode information struct
439  *
440  ******************************************************************************/
441 
442 static void
443 AhDisplayAmlOpcode (
444     const AH_AML_OPCODE     *Op)
445 {
446 
447     if (!Op->OpcodeName)
448     {
449         printf ("%18s: Opcode=%-9s\n", "Reserved opcode", Op->OpcodeString);
450         return;
451     }
452 
453     /* Opcode name and value(s) */
454 
455     printf ("%18s: Opcode=%-9s Type (%s)",
456         Op->OpcodeName, Op->OpcodeString, Op->Type);
457 
458     /* Optional fixed/static arguments */
459 
460     if (Op->FixedArguments)
461     {
462         printf (" FixedArgs (");
463         AhPrintOneField (37, 36 + 7 + strlen (Op->Type) + 12,
464             AH_MAX_AML_LINE_LENGTH, Op->FixedArguments);
465         printf (")");
466     }
467 
468     /* Optional variable-length argument list */
469 
470     if (Op->VariableArguments)
471     {
472         if (Op->FixedArguments)
473         {
474             printf ("\n%*s", 36, " ");
475         }
476         printf (" VariableArgs (");
477         AhPrintOneField (37, 15, AH_MAX_AML_LINE_LENGTH, Op->VariableArguments);
478         printf (")");
479     }
480     printf ("\n");
481 
482     /* Grammar specification */
483 
484     if (Op->Grammar)
485     {
486         AhPrintOneField (37, 0, AH_MAX_AML_LINE_LENGTH, Op->Grammar);
487         printf ("\n");
488     }
489 }
490 
491 
492 /*******************************************************************************
493  *
494  * FUNCTION:    AhFindAslKeywords (entry point for ASL keyword search)
495  *
496  * PARAMETERS:  Name                - Name or prefix for an ASL keyword.
497  *                                    NULL means "find all"
498  *
499  * RETURN:      None
500  *
501  * DESCRIPTION: Find all ASL keywords that match the input Name or name
502  *              prefix.
503  *
504  ******************************************************************************/
505 
506 void
507 AhFindAslKeywords (
508     char                    *Name)
509 {
510     const AH_ASL_KEYWORD    *Keyword;
511     BOOLEAN                 Found = FALSE;
512 
513 
514     AhStrupr (Name);
515 
516     for (Keyword = AslKeywordInfo; Keyword->Name; Keyword++)
517     {
518         if (!Name)
519         {
520             AhDisplayAslKeyword (Keyword);
521             Found = TRUE;
522             continue;
523         }
524 
525         /* Upper case the operator name before substring compare */
526 
527         strcpy (Gbl_Buffer, Keyword->Name);
528         AhStrupr (Gbl_Buffer);
529 
530         if (strstr (Gbl_Buffer, Name) == Gbl_Buffer)
531         {
532             AhDisplayAslKeyword (Keyword);
533             Found = TRUE;
534         }
535     }
536 
537     if (!Found)
538     {
539         printf ("%s, no matching ASL keywords\n", Name);
540     }
541 }
542 
543 
544 /*******************************************************************************
545  *
546  * FUNCTION:    AhDisplayAslKeyword
547  *
548  * PARAMETERS:  Op                  - Pointer to ASL keyword with syntax info
549  *
550  * RETURN:      None
551  *
552  * DESCRIPTION: Format and display syntax info for an ASL keyword. Splits
553  *              long lines appropriately for reading.
554  *
555  ******************************************************************************/
556 
557 static void
558 AhDisplayAslKeyword (
559     const AH_ASL_KEYWORD    *Op)
560 {
561 
562     /* ASL keyword name and description */
563 
564     printf ("%20s: %s\n", Op->Name, Op->Description);
565     if (!Op->KeywordList)
566     {
567         return;
568     }
569 
570     /* List of actual keywords */
571 
572     AhPrintOneField (22, 0, AH_MAX_ASL_LINE_LENGTH, Op->KeywordList);
573     printf ("\n");
574 }
575 
576 
577 /*******************************************************************************
578  *
579  * FUNCTION:    AhFindAslOperators (entry point for ASL operator search)
580  *
581  * PARAMETERS:  Name                - Name or prefix for an ASL operator.
582  *                                    NULL means "find all"
583  *
584  * RETURN:      None
585  *
586  * DESCRIPTION: Find all ASL operators that match the input Name or name
587  *              prefix.
588  *
589  ******************************************************************************/
590 
591 void
592 AhFindAslOperators (
593     char                    *Name)
594 {
595     const AH_ASL_OPERATOR   *Operator;
596     BOOLEAN                 Found = FALSE;
597 
598 
599     AhStrupr (Name);
600 
601     /* Find/display all names that match the input name prefix */
602 
603     for (Operator = AslOperatorInfo; Operator->Name; Operator++)
604     {
605         if (!Name)
606         {
607             AhDisplayAslOperator (Operator);
608             Found = TRUE;
609             continue;
610         }
611 
612         /* Upper case the operator name before substring compare */
613 
614         strcpy (Gbl_Buffer, Operator->Name);
615         AhStrupr (Gbl_Buffer);
616 
617         if (strstr (Gbl_Buffer, Name) == Gbl_Buffer)
618         {
619             AhDisplayAslOperator (Operator);
620             Found = TRUE;
621         }
622     }
623 
624     if (!Found)
625     {
626         printf ("%s, no matching ASL operators\n", Name);
627     }
628 }
629 
630 
631 /*******************************************************************************
632  *
633  * FUNCTION:    AhDisplayAslOperator
634  *
635  * PARAMETERS:  Op                  - Pointer to ASL operator with syntax info
636  *
637  * RETURN:      None
638  *
639  * DESCRIPTION: Format and display syntax info for an ASL operator. Splits
640  *              long lines appropriately for reading.
641  *
642  ******************************************************************************/
643 
644 static void
645 AhDisplayAslOperator (
646     const AH_ASL_OPERATOR   *Op)
647 {
648 
649     /* ASL operator name and description */
650 
651     printf ("%16s: %s\n", Op->Name, Op->Description);
652     if (!Op->Syntax)
653     {
654         return;
655     }
656 
657     /* Syntax for the operator */
658 
659     AhPrintOneField (18, 0, AH_MAX_ASL_LINE_LENGTH, Op->Syntax);
660     printf ("\n");
661 }
662 
663 
664 /*******************************************************************************
665  *
666  * FUNCTION:    AhPrintOneField
667  *
668  * PARAMETERS:  Indent              - Indent length for new line(s)
669  *              CurrentPosition     - Position on current line
670  *              MaxPosition         - Max allowed line length
671  *              Field               - Data to output
672  *
673  * RETURN:      Line position after field is written
674  *
675  * DESCRIPTION: Split long lines appropriately for ease of reading.
676  *
677  ******************************************************************************/
678 
679 static void
680 AhPrintOneField (
681     UINT32                  Indent,
682     UINT32                  CurrentPosition,
683     UINT32                  MaxPosition,
684     const char              *Field)
685 {
686     UINT32                  Position;
687     UINT32                  TokenLength;
688     const char              *This;
689     const char              *Next;
690     const char              *Last;
691 
692 
693     This = Field;
694     Position = CurrentPosition;
695 
696     if (Position == 0)
697     {
698         printf ("%*s", (int) Indent, " ");
699         Position = Indent;
700     }
701 
702     Last = This + strlen (This);
703     while ((Next = strpbrk (This, " ")))
704     {
705         TokenLength = Next - This;
706         Position += TokenLength;
707 
708         /* Split long lines */
709 
710         if (Position > MaxPosition)
711         {
712             printf ("\n%*s", (int) Indent, " ");
713             Position = TokenLength;
714         }
715 
716         printf ("%.*s ", (int) TokenLength, This);
717         This = Next + 1;
718     }
719 
720     /* Handle last token on the input line */
721 
722     TokenLength = Last - This;
723     if (TokenLength > 0)
724     {
725         Position += TokenLength;
726         if (Position > MaxPosition)
727         {
728             printf ("\n%*s", (int) Indent, " ");
729         }
730         printf ("%s", This);
731     }
732 }
733