1 /******************************************************************************
   2  *
   3  * Module Name: ahdecode - Operator/Opcode decoding for acpihelp utility
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 #define ACPI_CREATE_PREDEFINED_TABLE
  45 #define ACPI_CREATE_RESOURCE_TABLE
  46 
  47 #include "acpihelp.h"
  48 #include "acpredef.h"
  49 
  50 
  51 /* Device IDs defined in the ACPI specification */
  52 
  53 static const AH_DEVICE_ID  AhDeviceIds[] =
  54 {
  55     {"PNP0A05",     "Generic Container Device"},
  56     {"PNP0A06",     "Generic Container Device"},
  57     {"PNP0C08",     "ACPI core hardware"},
  58     {"PNP0C09",     "Embedded Controller Device"},
  59     {"PNP0C0A",     "Control Method Battery"},
  60     {"PNP0C0B",     "Fan"},
  61     {"PNP0C0C",     "Power Button Device"},
  62     {"PNP0C0D",     "Lid Device"},
  63     {"PNP0C0E",     "Sleep Button Device"},
  64     {"PNP0C0F",     "PCI Interrupt Link Device"},
  65     {"PNP0C80",     "Memory Device"},
  66 
  67     {"ACPI0001",    "SMBus 1.0 Host Controller"},
  68     {"ACPI0002",    "Smart Battery Subsystem"},
  69     {"ACPI0003",    "Power Source Device"},
  70     {"ACPI0004",    "Module Device"},
  71     {"ACPI0005",    "SMBus 2.0 Host Controller"},
  72     {"ACPI0006",    "GPE Block Device"},
  73     {"ACPI0007",    "Processor Device"},
  74     {"ACPI0008",    "Ambient Light Sensor Device"},
  75     {"ACPI0009",    "I/O xAPIC Device"},
  76     {"ACPI000A",    "I/O APIC Device"},
  77     {"ACPI000B",    "I/O SAPIC Device"},
  78     {"ACPI000C",    "Processor Aggregator Device"},
  79     {"ACPI000D",    "Power Meter Device"},
  80     {"ACPI000E",    "Time/Alarm Device"},
  81     {"ACPI000F",    "User Presence Detection Device"},
  82 
  83     {NULL, NULL}
  84 };
  85 
  86 #define AH_DISPLAY_EXCEPTION(Status, Name) \
  87     printf ("%.4X: %s\n", Status, Name)
  88 
  89 #define AH_DISPLAY_EXCEPTION_TEXT(Status, Exception) \
  90     printf ("%.4X: %-28s (%s)\n", Status, Exception->Name, Exception->Description)
  91 
  92 #define BUFFER_LENGTH           128
  93 #define LINE_BUFFER_LENGTH      512
  94 
  95 static char         Gbl_Buffer[BUFFER_LENGTH];
  96 static char         Gbl_LineBuffer[LINE_BUFFER_LENGTH];
  97 
  98 /* Local prototypes */
  99 
 100 static BOOLEAN
 101 AhDisplayPredefinedName (
 102     char                    *Name,
 103     UINT32                  Length);
 104 
 105 static void
 106 AhDisplayPredefinedInfo (
 107     char                    *Name);
 108 
 109 static void
 110 AhDisplayResourceName (
 111     const ACPI_PREDEFINED_INFO  *ThisName);
 112 
 113 static void
 114 AhDisplayAmlOpcode (
 115     const AH_AML_OPCODE     *Op);
 116 
 117 static void
 118 AhDisplayAslOperator (
 119     const AH_ASL_OPERATOR   *Op);
 120 
 121 static void
 122 AhDisplayOperatorKeywords (
 123     const AH_ASL_OPERATOR   *Op);
 124 
 125 static void
 126 AhDisplayAslKeyword (
 127     const AH_ASL_KEYWORD    *Op);
 128 
 129 static void
 130 AhPrintOneField (
 131     UINT32                  Indent,
 132     UINT32                  CurrentPosition,
 133     UINT32                  MaxPosition,
 134     const char              *Field);
 135 
 136 
 137 /*******************************************************************************
 138  *
 139  * FUNCTION:    AhFindPredefinedNames (entry point for predefined name search)
 140  *
 141  * PARAMETERS:  NamePrefix          - Name or prefix to find. Must start with
 142  *                                    an underscore. NULL means "find all"
 143  *
 144  * RETURN:      None
 145  *
 146  * DESCRIPTION: Find and display all ACPI predefined names that match the
 147  *              input name or prefix. Includes the required number of arguments
 148  *              and the expected return type, if any.
 149  *
 150  ******************************************************************************/
 151 
 152 void
 153 AhFindPredefinedNames (
 154     char                    *NamePrefix)
 155 {
 156     UINT32                  Length;
 157     BOOLEAN                 Found;
 158     char                    Name[9];
 159 
 160 
 161     if (!NamePrefix)
 162     {
 163         Found = AhDisplayPredefinedName (Name, 0);
 164         return;
 165     }
 166 
 167     /* Contruct a local name or name prefix */
 168 
 169     AhStrupr (NamePrefix);
 170     if (*NamePrefix == '_')
 171     {
 172         NamePrefix++;
 173     }
 174 
 175     Name[0] = '_';
 176     strncpy (&Name[1], NamePrefix, 7);
 177 
 178     Length = strlen (Name);
 179     if (Length > 4)
 180     {
 181         printf ("%.8s: Predefined name must be 4 characters maximum\n", Name);
 182         return;
 183     }
 184 
 185     Found = AhDisplayPredefinedName (Name, Length);
 186     if (!Found)
 187     {
 188         printf ("%s, no matching predefined names\n", Name);
 189     }
 190 }
 191 
 192 
 193 /*******************************************************************************
 194  *
 195  * FUNCTION:    AhDisplayPredefinedName
 196  *
 197  * PARAMETERS:  Name                - Name or name prefix
 198  *
 199  * RETURN:      TRUE if any names matched, FALSE otherwise
 200  *
 201  * DESCRIPTION: Display information about ACPI predefined names that match
 202  *              the input name or name prefix.
 203  *
 204  ******************************************************************************/
 205 
 206 static BOOLEAN
 207 AhDisplayPredefinedName (
 208     char                    *Name,
 209     UINT32                  Length)
 210 {
 211     const AH_PREDEFINED_NAME    *Info;
 212     BOOLEAN                     Found = FALSE;
 213     BOOLEAN                     Matched;
 214     UINT32                      i;
 215 
 216 
 217     /* Find/display all names that match the input name prefix */
 218 
 219     for (Info = AslPredefinedInfo; Info->Name; Info++)
 220     {
 221         if (!Name)
 222         {
 223             Found = TRUE;
 224             printf ("%s: <%s>\n", Info->Name, Info->Description);
 225             printf ("%*s%s\n", 6, " ", Info->Action);
 226 
 227             AhDisplayPredefinedInfo (Info->Name);
 228             continue;
 229         }
 230 
 231         Matched = TRUE;
 232         for (i = 0; i < Length; i++)
 233         {
 234             if (Info->Name[i] != Name[i])
 235             {
 236                 Matched = FALSE;
 237                 break;
 238             }
 239         }
 240 
 241         if (Matched)
 242         {
 243             Found = TRUE;
 244             printf ("%s: <%s>\n", Info->Name, Info->Description);
 245             printf ("%*s%s\n", 6, " ", Info->Action);
 246 
 247             AhDisplayPredefinedInfo (Info->Name);
 248         }
 249     }
 250 
 251     return (Found);
 252 }
 253 
 254 
 255 /*******************************************************************************
 256  *
 257  * FUNCTION:    AhDisplayPredefinedInfo
 258  *
 259  * PARAMETERS:  Name                - Exact 4-character ACPI name.
 260  *
 261  * RETURN:      None
 262  *
 263  * DESCRIPTION: Find the name in the main ACPICA predefined info table and
 264  *              display the # of arguments and the return value type.
 265  *
 266  *              Note: Resource Descriptor field names do not appear in this
 267  *              table -- thus, nothing will be displayed for them.
 268  *
 269  ******************************************************************************/
 270 
 271 static void
 272 AhDisplayPredefinedInfo (
 273     char                        *Name)
 274 {
 275     const ACPI_PREDEFINED_INFO  *ThisName;
 276 
 277 
 278     /* NOTE: we check both tables always because there are some dupes */
 279 
 280     /* Check against the predefine methods first */
 281 
 282     ThisName = AcpiUtMatchPredefinedMethod (Name);
 283     if (ThisName)
 284     {
 285         AcpiUtDisplayPredefinedMethod (Gbl_Buffer, ThisName, TRUE);
 286     }
 287 
 288     /* Check against the predefined resource descriptor names */
 289 
 290     ThisName = AcpiUtMatchResourceName (Name);
 291     if (ThisName)
 292     {
 293         AhDisplayResourceName (ThisName);
 294     }
 295 }
 296 
 297 
 298 /*******************************************************************************
 299  *
 300  * FUNCTION:    AhDisplayResourceName
 301  *
 302  * PARAMETERS:  ThisName            - Entry in the predefined method/name table
 303  *
 304  * RETURN:      None
 305  *
 306  * DESCRIPTION: Display information about a resource descriptor name.
 307  *
 308  ******************************************************************************/
 309 
 310 static void
 311 AhDisplayResourceName (
 312     const ACPI_PREDEFINED_INFO  *ThisName)
 313 {
 314     UINT32                      NumTypes;
 315 
 316 
 317     NumTypes = AcpiUtGetResourceBitWidth (Gbl_Buffer,
 318         ThisName->Info.ArgumentList);
 319 
 320     printf ("      %4.4s resource descriptor field is %s bits wide%s\n",
 321         ThisName->Info.Name,
 322         Gbl_Buffer,
 323         (NumTypes > 1) ? " (depending on descriptor type)" : "");
 324 }
 325 
 326 
 327 /*******************************************************************************
 328  *
 329  * FUNCTION:    AhFindAmlOpcode (entry point for AML opcode name search)
 330  *
 331  * PARAMETERS:  Name                - Name or prefix for an AML opcode.
 332  *                                    NULL means "find all"
 333  *
 334  * RETURN:      None
 335  *
 336  * DESCRIPTION: Find all AML opcodes that match the input Name or name
 337  *              prefix.
 338  *
 339  ******************************************************************************/
 340 
 341 void
 342 AhFindAmlOpcode (
 343     char                    *Name)
 344 {
 345     const AH_AML_OPCODE     *Op;
 346     BOOLEAN                 Found = FALSE;
 347 
 348 
 349     AhStrupr (Name);
 350 
 351     /* Find/display all opcode names that match the input name prefix */
 352 
 353     for (Op = AmlOpcodeInfo; Op->OpcodeString; Op++)
 354     {
 355         if (!Op->OpcodeName) /* Unused opcodes */
 356         {
 357             continue;
 358         }
 359 
 360         if (!Name)
 361         {
 362             AhDisplayAmlOpcode (Op);
 363             Found = TRUE;
 364             continue;
 365         }
 366 
 367         /* Upper case the opcode name before substring compare */
 368 
 369         strcpy (Gbl_Buffer, Op->OpcodeName);
 370         AhStrupr (Gbl_Buffer);
 371 
 372         if (strstr (Gbl_Buffer, Name) == Gbl_Buffer)
 373         {
 374             AhDisplayAmlOpcode (Op);
 375             Found = TRUE;
 376         }
 377     }
 378 
 379     if (!Found)
 380     {
 381         printf ("%s, no matching AML operators\n", Name);
 382     }
 383 }
 384 
 385 
 386 /*******************************************************************************
 387  *
 388  * FUNCTION:    AhDecodeAmlOpcode (entry point for AML opcode search)
 389  *
 390  * PARAMETERS:  OpcodeString        - String version of AML opcode
 391  *
 392  * RETURN:      None
 393  *
 394  * DESCRIPTION: Display information about the input AML opcode
 395  *
 396  ******************************************************************************/
 397 
 398 void
 399 AhDecodeAmlOpcode (
 400     char                    *OpcodeString)
 401 {
 402     const AH_AML_OPCODE     *Op;
 403     UINT32                  Opcode;
 404     UINT8                   Prefix;
 405 
 406 
 407     if (!OpcodeString)
 408     {
 409         AhFindAmlOpcode (NULL);
 410         return;
 411     }
 412 
 413     Opcode = ACPI_STRTOUL (OpcodeString, NULL, 16);
 414     if (Opcode > ACPI_UINT16_MAX)
 415     {
 416         printf ("Invalid opcode (more than 16 bits)\n");
 417         return;
 418     }
 419 
 420     /* Only valid opcode extension is 0x5B */
 421 
 422     Prefix = (Opcode & 0x0000FF00) >> 8;
 423     if (Prefix && (Prefix != 0x5B))
 424     {
 425         printf ("Invalid opcode (invalid extension prefix 0x%X)\n",
 426             Prefix);
 427         return;
 428     }
 429 
 430     /* Find/Display the opcode. May fall within an opcode range */
 431 
 432     for (Op = AmlOpcodeInfo; Op->OpcodeString; Op++)
 433     {
 434         if ((Opcode >= Op->OpcodeRangeStart) &&
 435             (Opcode <= Op->OpcodeRangeEnd))
 436         {
 437             AhDisplayAmlOpcode (Op);
 438         }
 439     }
 440 }
 441 
 442 
 443 /*******************************************************************************
 444  *
 445  * FUNCTION:    AhDisplayAmlOpcode
 446  *
 447  * PARAMETERS:  Op                  - An opcode info struct
 448  *
 449  * RETURN:      None
 450  *
 451  * DESCRIPTION: Display the contents of an AML opcode information struct
 452  *
 453  ******************************************************************************/
 454 
 455 static void
 456 AhDisplayAmlOpcode (
 457     const AH_AML_OPCODE     *Op)
 458 {
 459 
 460     if (!Op->OpcodeName)
 461     {
 462         printf ("%18s: Opcode=%-9s\n", "Reserved opcode", Op->OpcodeString);
 463         return;
 464     }
 465 
 466     /* Opcode name and value(s) */
 467 
 468     printf ("%18s: Opcode=%-9s Type (%s)",
 469         Op->OpcodeName, Op->OpcodeString, Op->Type);
 470 
 471     /* Optional fixed/static arguments */
 472 
 473     if (Op->FixedArguments)
 474     {
 475         printf (" FixedArgs (");
 476         AhPrintOneField (37, 36 + 7 + strlen (Op->Type) + 12,
 477             AH_MAX_AML_LINE_LENGTH, Op->FixedArguments);
 478         printf (")");
 479     }
 480 
 481     /* Optional variable-length argument list */
 482 
 483     if (Op->VariableArguments)
 484     {
 485         if (Op->FixedArguments)
 486         {
 487             printf ("\n%*s", 36, " ");
 488         }
 489         printf (" VariableArgs (");
 490         AhPrintOneField (37, 15, AH_MAX_AML_LINE_LENGTH, Op->VariableArguments);
 491         printf (")");
 492     }
 493     printf ("\n");
 494 
 495     /* Grammar specification */
 496 
 497     if (Op->Grammar)
 498     {
 499         AhPrintOneField (37, 0, AH_MAX_AML_LINE_LENGTH, Op->Grammar);
 500         printf ("\n");
 501     }
 502 }
 503 
 504 
 505 /*******************************************************************************
 506  *
 507  * FUNCTION:    AhFindAslKeywords (entry point for ASL keyword search)
 508  *
 509  * PARAMETERS:  Name                - Name or prefix for an ASL keyword.
 510  *                                    NULL means "find all"
 511  *
 512  * RETURN:      None
 513  *
 514  * DESCRIPTION: Find all ASL keywords that match the input Name or name
 515  *              prefix.
 516  *
 517  ******************************************************************************/
 518 
 519 void
 520 AhFindAslKeywords (
 521     char                    *Name)
 522 {
 523     const AH_ASL_KEYWORD    *Keyword;
 524     BOOLEAN                 Found = FALSE;
 525 
 526 
 527     AhStrupr (Name);
 528 
 529     for (Keyword = AslKeywordInfo; Keyword->Name; Keyword++)
 530     {
 531         if (!Name)
 532         {
 533             AhDisplayAslKeyword (Keyword);
 534             Found = TRUE;
 535             continue;
 536         }
 537 
 538         /* Upper case the operator name before substring compare */
 539 
 540         strcpy (Gbl_Buffer, Keyword->Name);
 541         AhStrupr (Gbl_Buffer);
 542 
 543         if (strstr (Gbl_Buffer, Name) == Gbl_Buffer)
 544         {
 545             AhDisplayAslKeyword (Keyword);
 546             Found = TRUE;
 547         }
 548     }
 549 
 550     if (!Found)
 551     {
 552         printf ("%s, no matching ASL keywords\n", Name);
 553     }
 554 }
 555 
 556 
 557 /*******************************************************************************
 558  *
 559  * FUNCTION:    AhDisplayAslKeyword
 560  *
 561  * PARAMETERS:  Op                  - Pointer to ASL keyword with syntax info
 562  *
 563  * RETURN:      None
 564  *
 565  * DESCRIPTION: Format and display syntax info for an ASL keyword. Splits
 566  *              long lines appropriately for reading.
 567  *
 568  ******************************************************************************/
 569 
 570 static void
 571 AhDisplayAslKeyword (
 572     const AH_ASL_KEYWORD    *Op)
 573 {
 574 
 575     /* ASL keyword name and description */
 576 
 577     printf ("%22s: %s\n", Op->Name, Op->Description);
 578     if (!Op->KeywordList)
 579     {
 580         return;
 581     }
 582 
 583     /* List of actual keywords */
 584 
 585     AhPrintOneField (24, 0, AH_MAX_ASL_LINE_LENGTH, Op->KeywordList);
 586     printf ("\n");
 587 }
 588 
 589 
 590 /*******************************************************************************
 591  *
 592  * FUNCTION:    AhFindAslOperators (entry point for ASL operator search)
 593  *
 594  * PARAMETERS:  Name                - Name or prefix for an ASL operator.
 595  *                                    NULL means "find all"
 596  *
 597  * RETURN:      None
 598  *
 599  * DESCRIPTION: Find all ASL operators that match the input Name or name
 600  *              prefix.
 601  *
 602  ******************************************************************************/
 603 
 604 void
 605 AhFindAslOperators (
 606     char                    *Name)
 607 {
 608     const AH_ASL_OPERATOR   *Operator;
 609     BOOLEAN                 Found = FALSE;
 610 
 611 
 612     AhStrupr (Name);
 613 
 614     /* Find/display all names that match the input name prefix */
 615 
 616     for (Operator = AslOperatorInfo; Operator->Name; Operator++)
 617     {
 618         if (!Name)
 619         {
 620             AhDisplayAslOperator (Operator);
 621             Found = TRUE;
 622             continue;
 623         }
 624 
 625         /* Upper case the operator name before substring compare */
 626 
 627         strcpy (Gbl_Buffer, Operator->Name);
 628         AhStrupr (Gbl_Buffer);
 629 
 630         if (strstr (Gbl_Buffer, Name) == Gbl_Buffer)
 631         {
 632             AhDisplayAslOperator (Operator);
 633             Found = TRUE;
 634         }
 635     }
 636 
 637     if (!Found)
 638     {
 639         printf ("%s, no matching ASL operators\n", Name);
 640     }
 641 }
 642 
 643 
 644 /*******************************************************************************
 645  *
 646  * FUNCTION:    AhDisplayAslOperator
 647  *
 648  * PARAMETERS:  Op                  - Pointer to ASL operator with syntax info
 649  *
 650  * RETURN:      None
 651  *
 652  * DESCRIPTION: Format and display syntax info for an ASL operator. Splits
 653  *              long lines appropriately for reading.
 654  *
 655  ******************************************************************************/
 656 
 657 static void
 658 AhDisplayAslOperator (
 659     const AH_ASL_OPERATOR   *Op)
 660 {
 661 
 662     /* ASL operator name and description */
 663 
 664     printf ("%16s: %s\n", Op->Name, Op->Description);
 665     if (!Op->Syntax)
 666     {
 667         return;
 668     }
 669 
 670     /* Syntax for the operator */
 671 
 672     AhPrintOneField (18, 0, AH_MAX_ASL_LINE_LENGTH, Op->Syntax);
 673     printf ("\n");
 674 
 675     AhDisplayOperatorKeywords (Op);
 676     printf ("\n");
 677 }
 678 
 679 
 680 /*******************************************************************************
 681  *
 682  * FUNCTION:    AhDisplayOperatorKeywords
 683  *
 684  * PARAMETERS:  Op                  - Pointer to ASL keyword with syntax info
 685  *
 686  * RETURN:      None
 687  *
 688  * DESCRIPTION: Display any/all keywords that are associated with the ASL
 689  *              operator.
 690  *
 691  ******************************************************************************/
 692 
 693 static void
 694 AhDisplayOperatorKeywords (
 695     const AH_ASL_OPERATOR   *Op)
 696 {
 697     char                    *Token;
 698     char                    *Separators = "(){}, ";
 699     BOOLEAN                 FirstKeyword = TRUE;
 700 
 701 
 702     if (!Op || !Op->Syntax)
 703     {
 704         return;
 705     }
 706 
 707     /*
 708      * Find all parameters that have the word "keyword" within, and then
 709      * display the info about that keyword
 710      */
 711     strcpy (Gbl_LineBuffer, Op->Syntax);
 712     Token = strtok (Gbl_LineBuffer, Separators);
 713     while (Token)
 714     {
 715         if (strstr (Token, "Keyword"))
 716         {
 717             if (FirstKeyword)
 718             {
 719                 printf ("\n");
 720                 FirstKeyword = FALSE;
 721             }
 722 
 723             /* Found a keyword, display keyword information */
 724 
 725             AhFindAslKeywords (Token);
 726         }
 727 
 728         Token = strtok (NULL, Separators);
 729     }
 730 }
 731 
 732 
 733 /*******************************************************************************
 734  *
 735  * FUNCTION:    AhPrintOneField
 736  *
 737  * PARAMETERS:  Indent              - Indent length for new line(s)
 738  *              CurrentPosition     - Position on current line
 739  *              MaxPosition         - Max allowed line length
 740  *              Field               - Data to output
 741  *
 742  * RETURN:      Line position after field is written
 743  *
 744  * DESCRIPTION: Split long lines appropriately for ease of reading.
 745  *
 746  ******************************************************************************/
 747 
 748 static void
 749 AhPrintOneField (
 750     UINT32                  Indent,
 751     UINT32                  CurrentPosition,
 752     UINT32                  MaxPosition,
 753     const char              *Field)
 754 {
 755     UINT32                  Position;
 756     UINT32                  TokenLength;
 757     const char              *This;
 758     const char              *Next;
 759     const char              *Last;
 760 
 761 
 762     This = Field;
 763     Position = CurrentPosition;
 764 
 765     if (Position == 0)
 766     {
 767         printf ("%*s", (int) Indent, " ");
 768         Position = Indent;
 769     }
 770 
 771     Last = This + strlen (This);
 772     while ((Next = strpbrk (This, " ")))
 773     {
 774         TokenLength = Next - This;
 775         Position += TokenLength;
 776 
 777         /* Split long lines */
 778 
 779         if (Position > MaxPosition)
 780         {
 781             printf ("\n%*s", (int) Indent, " ");
 782             Position = TokenLength;
 783         }
 784 
 785         printf ("%.*s ", (int) TokenLength, This);
 786         This = Next + 1;
 787     }
 788 
 789     /* Handle last token on the input line */
 790 
 791     TokenLength = Last - This;
 792     if (TokenLength > 0)
 793     {
 794         Position += TokenLength;
 795         if (Position > MaxPosition)
 796         {
 797             printf ("\n%*s", (int) Indent, " ");
 798         }
 799         printf ("%s", This);
 800     }
 801 }
 802 
 803 
 804 /*******************************************************************************
 805  *
 806  * FUNCTION:    AhDisplayDeviceIds
 807  *
 808  * PARAMETERS:  None
 809  *
 810  * RETURN:      None
 811  *
 812  * DESCRIPTION: Display all PNP* and ACPI* device IDs defined in the ACPI spec.
 813  *
 814  ******************************************************************************/
 815 
 816 void
 817 AhDisplayDeviceIds (
 818     void)
 819 {
 820     const AH_DEVICE_ID      *DeviceId = AhDeviceIds;
 821 
 822 
 823     printf ("ACPI and PNP Device IDs defined in the ACPI specification:\n\n");
 824     while (DeviceId->Name)
 825     {
 826         printf ("%8s   %s\n", DeviceId->Name, DeviceId->Description);
 827         DeviceId++;
 828     }
 829 }
 830 
 831 
 832 /*******************************************************************************
 833  *
 834  * FUNCTION:    AhDecodeException
 835  *
 836  * PARAMETERS:  HexString           - ACPI status string from command line, in
 837  *                                    hex. If null, display all exceptions.
 838  *
 839  * RETURN:      None
 840  *
 841  * DESCRIPTION: Decode and display an ACPI_STATUS exception code.
 842  *
 843  ******************************************************************************/
 844 
 845 void
 846 AhDecodeException (
 847     char                    *HexString)
 848 {
 849     const ACPI_EXCEPTION_INFO   *ExceptionInfo;
 850     UINT32                      Status;
 851     UINT32                      i;
 852 
 853 
 854     /*
 855      * A null input string means to decode and display all known
 856      * exception codes.
 857      */
 858     if (!HexString)
 859     {
 860         printf ("All defined ACPICA exception codes:\n\n");
 861         AH_DISPLAY_EXCEPTION (0, "AE_OK                        (No error occurred)");
 862 
 863         /* Display codes in each block of exception types */
 864 
 865         for (i = 1; (i & AE_CODE_MASK) <= AE_CODE_MAX; i += 0x1000)
 866         {
 867             Status = i;
 868             do
 869             {
 870                 ExceptionInfo = AcpiUtValidateException ((ACPI_STATUS) Status);
 871                 if (ExceptionInfo)
 872                 {
 873                     AH_DISPLAY_EXCEPTION_TEXT (Status, ExceptionInfo);
 874                 }
 875                 Status++;
 876 
 877             } while (ExceptionInfo);
 878         }
 879         return;
 880     }
 881 
 882     /* Decode a single user-supplied exception code */
 883 
 884     Status = ACPI_STRTOUL (HexString, NULL, 16);
 885     if (!Status)
 886     {
 887         printf ("%s: Invalid hexadecimal exception code value\n", HexString);
 888         return;
 889     }
 890 
 891     if (Status > ACPI_UINT16_MAX)
 892     {
 893         AH_DISPLAY_EXCEPTION (Status, "Invalid exception code (more than 16 bits)");
 894         return;
 895     }
 896 
 897     ExceptionInfo = AcpiUtValidateException ((ACPI_STATUS) Status);
 898     if (!ExceptionInfo)
 899     {
 900         AH_DISPLAY_EXCEPTION (Status, "Unknown exception code");
 901         return;
 902     }
 903 
 904     AH_DISPLAY_EXCEPTION_TEXT (Status, ExceptionInfo);
 905 }