1 /****************************************************************************** 2 * 3 * Module Name: ahdecode - Miscellaneous decoding for acpihelp utility 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2021, 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 MERCHANTABILITY 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 BOOLEAN AslGbl_VerboseErrors = TRUE; 51 52 /* Local prototypes */ 53 54 static BOOLEAN 55 AhDisplayPredefinedName ( 56 char *Name, 57 UINT32 Length); 58 59 static void 60 AhDisplayPredefinedInfo ( 61 char *Name); 62 63 static void 64 AhDoSpecialNames ( 65 char *Name); 66 67 static void 68 AhDisplayResourceName ( 69 const ACPI_PREDEFINED_INFO *ThisName); 70 71 72 /******************************************************************************* 73 * 74 * FUNCTION: AhPrintOneField 75 * 76 * PARAMETERS: Indent - Indent length for new line(s) 77 * CurrentPosition - Position on current line 78 * MaxPosition - Max allowed line length 79 * Field - Data to output 80 * 81 * RETURN: Line position after field is written 82 * 83 * DESCRIPTION: Split long lines appropriately for ease of reading. 84 * 85 ******************************************************************************/ 86 87 void 88 AhPrintOneField ( 89 UINT32 Indent, 90 UINT32 CurrentPosition, 91 UINT32 MaxPosition, 92 const char *Field) 93 { 94 UINT32 Position; 95 UINT32 TokenLength; 96 const char *This; 97 const char *Next; 98 const char *Last; 99 100 101 This = Field; 102 Position = CurrentPosition; 103 104 if (Position == 0) 105 { 106 printf ("%*s", (int) Indent, " "); 107 Position = Indent; 108 } 109 110 Last = This + strlen (This); 111 while ((Next = strpbrk (This, " "))) 112 { 113 TokenLength = Next - This; 114 Position += TokenLength; 115 116 /* Split long lines */ 117 118 if (Position > MaxPosition) 119 { 120 printf ("\n%*s", (int) Indent, " "); 121 Position = TokenLength; 122 } 123 124 printf ("%.*s ", (int) TokenLength, This); 125 This = Next + 1; 126 } 127 128 /* Handle last token on the input line */ 129 130 TokenLength = Last - This; 131 if (TokenLength > 0) 132 { 133 Position += TokenLength; 134 if (Position > MaxPosition) 135 { 136 printf ("\n%*s", (int) Indent, " "); 137 } 138 139 printf ("%s", This); 140 } 141 } 142 143 144 /******************************************************************************* 145 * 146 * FUNCTION: AhDisplayDirectives 147 * 148 * PARAMETERS: None 149 * 150 * RETURN: None 151 * 152 * DESCRIPTION: Display all iASL preprocessor directives. 153 * 154 ******************************************************************************/ 155 156 void 157 AhDisplayDirectives ( 158 void) 159 { 160 const AH_DIRECTIVE_INFO *Info; 161 162 163 printf ("iASL Preprocessor Directives\n\n"); 164 165 for (Info = Gbl_PreprocessorDirectives; Info->Name; Info++) 166 { 167 printf (" %-36s : %s\n", Info->Name, Info->Description); 168 } 169 } 170 171 172 /******************************************************************************* 173 * 174 * FUNCTION: AhFindPredefinedNames (entry point for predefined name search) 175 * 176 * PARAMETERS: NamePrefix - Name or prefix to find. Must start with 177 * an underscore. NULL means "find all" 178 * 179 * RETURN: None 180 * 181 * DESCRIPTION: Find and display all ACPI predefined names that match the 182 * input name or prefix. Includes the required number of arguments 183 * and the expected return type, if any. 184 * 185 ******************************************************************************/ 186 187 void 188 AhFindPredefinedNames ( 189 char *NamePrefix) 190 { 191 UINT32 Length; 192 BOOLEAN Found; 193 char Name[ACPI_NAMESEG_SIZE + 1]; 194 195 196 if (!NamePrefix || (*NamePrefix == '*')) 197 { 198 (void) AhDisplayPredefinedName (NULL, 0); 199 return; 200 } 201 202 Length = strlen (NamePrefix); 203 if (Length > ACPI_NAMESEG_SIZE) 204 { 205 printf ("%.8s: Predefined name must be 4 characters maximum\n", 206 NamePrefix); 207 return; 208 } 209 210 /* Construct a local name or name prefix */ 211 212 AcpiUtStrupr (NamePrefix); 213 if (*NamePrefix == '_') 214 { 215 NamePrefix++; 216 } 217 218 Name[0] = '_'; 219 AcpiUtSafeStrncpy (&Name[1], NamePrefix, 4); 220 221 /* Check for special names such as _Exx, _ACx, etc. */ 222 223 AhDoSpecialNames (Name); 224 225 /* Lookup and display the name(s) */ 226 227 Found = AhDisplayPredefinedName (Name, Length); 228 if (!Found) 229 { 230 printf ("%s, no matching predefined names\n", Name); 231 } 232 } 233 234 235 /******************************************************************************* 236 * 237 * FUNCTION: AhDoSpecialNames 238 * 239 * PARAMETERS: Name - Name or prefix to find 240 * 241 * RETURN: None 242 * 243 * DESCRIPTION: Detect and handle the "special" names such as _Exx, _ACx, etc. 244 * 245 * Current support: 246 * _EJx 247 * _Exx 248 * _Lxx 249 * _Qxx 250 * _Wxx 251 * _ACx 252 * _ALx 253 * _T_x 254 * 255 ******************************************************************************/ 256 257 static void 258 AhDoSpecialNames ( 259 char *Name) 260 { 261 262 /* 263 * Check for the special names that have one or more numeric 264 * suffixes. For example, _Lxx can have 256 different flavors, 265 * from _L00 to _LFF. 266 */ 267 switch (Name[1]) 268 { 269 case 'E': 270 if (Name[2] == 'J') 271 { 272 if (isdigit ((int) Name[3]) || (Name[3] == 'X')) 273 { 274 /* _EJx */ 275 276 Name[3] = 'x'; 277 break; 278 } 279 } 280 281 ACPI_FALLTHROUGH; 282 283 case 'L': 284 case 'Q': 285 case 'W': 286 if ((isxdigit ((int) Name[2]) && isxdigit ((int) Name[3])) 287 || 288 ((Name[2] == 'X') && (Name[3] == 'X'))) 289 { 290 /* _Exx, _Lxx, _Qxx, or _Wxx */ 291 292 Name[2] = 'x'; 293 Name[3] = 'x'; 294 } 295 break; 296 297 case 'A': 298 if ((Name[2] == 'C') || (Name[2] == 'L')) 299 { 300 if (isdigit ((int) Name[3]) || (Name[3] == 'X')) 301 { 302 /* _ACx or _ALx */ 303 304 Name[3] = 'x'; 305 } 306 } 307 break; 308 309 case 'T': 310 if (Name[2] == '_') 311 { 312 /* _T_x (Reserved for iASL compiler */ 313 314 Name[3] = 'x'; 315 } 316 break; 317 318 default: 319 break; 320 } 321 } 322 323 324 /******************************************************************************* 325 * 326 * FUNCTION: AhDisplayPredefinedName 327 * 328 * PARAMETERS: Name - Name or name prefix 329 * 330 * RETURN: TRUE if any names matched, FALSE otherwise 331 * 332 * DESCRIPTION: Display information about ACPI predefined names that match 333 * the input name or name prefix. 334 * 335 ******************************************************************************/ 336 337 static BOOLEAN 338 AhDisplayPredefinedName ( 339 char *Name, 340 UINT32 Length) 341 { 342 const AH_PREDEFINED_NAME *Info; 343 BOOLEAN Found = FALSE; 344 BOOLEAN Matched; 345 UINT32 i = 0; 346 347 348 /* Find/display all names that match the input name prefix */ 349 350 for (Info = AslPredefinedInfo; Info->Name; Info++) 351 { 352 if (!Name) 353 { 354 Found = TRUE; 355 printf ("%s: <%s>\n", Info->Name, Info->Description); 356 printf ("%*s%s\n", 6, " ", Info->Action); 357 358 AhDisplayPredefinedInfo (Info->Name); 359 i++; 360 continue; 361 } 362 363 Matched = TRUE; 364 for (i = 0; i < Length; i++) 365 { 366 if (Info->Name[i] != Name[i]) 367 { 368 Matched = FALSE; 369 break; 370 } 371 } 372 373 if (Matched) 374 { 375 Found = TRUE; 376 printf ("%s: <%s>\n", Info->Name, Info->Description); 377 printf ("%*s%s\n", 6, " ", Info->Action); 378 379 AhDisplayPredefinedInfo (Info->Name); 380 } 381 } 382 383 if (!Name) 384 { 385 printf ("\nFound %d Predefined ACPI Names\n", i); 386 } 387 return (Found); 388 } 389 390 391 /******************************************************************************* 392 * 393 * FUNCTION: AhDisplayPredefinedInfo 394 * 395 * PARAMETERS: Name - Exact 4-character ACPI name. 396 * 397 * RETURN: None 398 * 399 * DESCRIPTION: Find the name in the main ACPICA predefined info table and 400 * display the # of arguments and the return value type. 401 * 402 * Note: Resource Descriptor field names do not appear in this 403 * table -- thus, nothing will be displayed for them. 404 * 405 ******************************************************************************/ 406 407 static void 408 AhDisplayPredefinedInfo ( 409 char *Name) 410 { 411 const ACPI_PREDEFINED_INFO *ThisName; 412 413 414 /* NOTE: we check both tables always because there are some dupes */ 415 416 /* Check against the predefined methods first */ 417 418 ThisName = AcpiUtMatchPredefinedMethod (Name); 419 if (ThisName) 420 { 421 AcpiUtDisplayPredefinedMethod (Gbl_Buffer, ThisName, TRUE); 422 } 423 424 /* Check against the predefined resource descriptor names */ 425 426 ThisName = AcpiUtMatchResourceName (Name); 427 if (ThisName) 428 { 429 AhDisplayResourceName (ThisName); 430 } 431 } 432 433 434 /******************************************************************************* 435 * 436 * FUNCTION: AhDisplayResourceName 437 * 438 * PARAMETERS: ThisName - Entry in the predefined method/name table 439 * 440 * RETURN: None 441 * 442 * DESCRIPTION: Display information about a resource descriptor name. 443 * 444 ******************************************************************************/ 445 446 static void 447 AhDisplayResourceName ( 448 const ACPI_PREDEFINED_INFO *ThisName) 449 { 450 UINT32 NumTypes; 451 452 453 NumTypes = AcpiUtGetResourceBitWidth (Gbl_Buffer, 454 ThisName->Info.ArgumentList); 455 456 printf (" %4.4s resource descriptor field is %s bits wide%s\n", 457 ThisName->Info.Name, 458 Gbl_Buffer, 459 (NumTypes > 1) ? " (depending on descriptor type)" : ""); 460 } 461 462 463 /******************************************************************************* 464 * 465 * FUNCTION: AhDisplayDeviceIds 466 * 467 * PARAMETERS: Name - Device Hardware ID string. 468 * NULL means "find all" 469 * 470 * RETURN: None 471 * 472 * DESCRIPTION: Display PNP* and ACPI* device IDs. 473 * 474 ******************************************************************************/ 475 476 void 477 AhDisplayDeviceIds ( 478 char *Name) 479 { 480 const AH_DEVICE_ID *Info; 481 UINT32 Length; 482 BOOLEAN Matched; 483 UINT32 i; 484 BOOLEAN Found = FALSE; 485 486 487 /* Null input name indicates "display all" */ 488 489 if (!Name || (Name[0] == '*')) 490 { 491 printf ("ACPI and PNP Device/Hardware IDs:\n\n"); 492 for (Info = AslDeviceIds; Info->Name; Info++) 493 { 494 printf ("%8s %s\n", Info->Name, Info->Description); 495 } 496 497 return; 498 } 499 500 Length = strlen (Name); 501 if (Length > 8) 502 { 503 printf ("%.8s: Hardware ID must be 8 characters maximum\n", Name); 504 return; 505 } 506 507 /* Find/display all names that match the input name prefix */ 508 509 AcpiUtStrupr (Name); 510 for (Info = AslDeviceIds; Info->Name; Info++) 511 { 512 Matched = TRUE; 513 for (i = 0; i < Length; i++) 514 { 515 if (Info->Name[i] != Name[i]) 516 { 517 Matched = FALSE; 518 break; 519 } 520 } 521 522 if (Matched) 523 { 524 Found = TRUE; 525 printf ("%8s %s\n", Info->Name, Info->Description); 526 } 527 } 528 529 if (!Found) 530 { 531 printf ("%s, Hardware ID not found\n", Name); 532 } 533 } 534 535 536 /******************************************************************************* 537 * 538 * FUNCTION: AhDisplayUuids 539 * 540 * PARAMETERS: None 541 * 542 * RETURN: None 543 * 544 * DESCRIPTION: Display all known UUIDs. 545 * 546 ******************************************************************************/ 547 548 void 549 AhDisplayUuids ( 550 void) 551 { 552 const AH_UUID *Info; 553 554 555 printf ("ACPI-related UUIDs/GUIDs:\n"); 556 557 /* Display entire table of known ACPI-related UUIDs/GUIDs */ 558 559 for (Info = Gbl_AcpiUuids; Info->Description; Info++) 560 { 561 if (!Info->String) /* Null UUID string means group description */ 562 { 563 printf ("\n%36s\n", Info->Description); 564 } 565 else 566 { 567 printf ("%32s : %s\n", Info->Description, Info->String); 568 } 569 } 570 571 /* Help info on how UUIDs/GUIDs strings are encoded */ 572 573 printf ("\n\nByte encoding of UUID/GUID strings" 574 " into ACPI Buffer objects (use ToUUID from ASL):\n\n"); 575 576 printf ("%32s : %s\n", "Input UUID/GUID String format", 577 "aabbccdd-eeff-gghh-iijj-kkllmmnnoopp"); 578 579 printf ("%32s : %s\n", "Expected output ACPI buffer", 580 "dd,cc,bb,aa, ff,ee, hh,gg, ii,jj, kk,ll,mm,nn,oo,pp"); 581 } 582 583 584 /******************************************************************************* 585 * 586 * FUNCTION: AhDisplayTables 587 * 588 * PARAMETERS: None 589 * 590 * RETURN: None 591 * 592 * DESCRIPTION: Display all known ACPI tables 593 * 594 ******************************************************************************/ 595 596 void 597 AhDisplayTables ( 598 void) 599 { 600 const AH_TABLE *Info; 601 UINT32 i = 0; 602 603 604 printf ("Known ACPI tables:\n"); 605 606 for (Info = AcpiGbl_SupportedTables; Info->Signature; Info++) 607 { 608 printf ("%8s : %s\n", Info->Signature, Info->Description); 609 i++; 610 } 611 612 printf ("\nTotal %u ACPI tables\n\n", i); 613 } 614 615 616 /******************************************************************************* 617 * 618 * FUNCTION: AhDecodeException 619 * 620 * PARAMETERS: HexString - ACPI status string from command line, in 621 * hex. If null, display all exceptions. 622 * 623 * RETURN: None 624 * 625 * DESCRIPTION: Decode and display an ACPI_STATUS exception code. 626 * 627 ******************************************************************************/ 628 629 void 630 AhDecodeException ( 631 char *HexString) 632 { 633 const ACPI_EXCEPTION_INFO *ExceptionInfo; 634 UINT32 Status; 635 UINT32 i; 636 637 638 /* 639 * A null input string means to decode and display all known 640 * exception codes. 641 */ 642 if (!HexString) 643 { 644 printf ("All defined ACPICA exception codes:\n\n"); 645 AH_DISPLAY_EXCEPTION (0, 646 "AE_OK (No error occurred)"); 647 648 /* Display codes in each block of exception types */ 649 650 for (i = 1; (i & AE_CODE_MASK) <= AE_CODE_MAX; i += 0x1000) 651 { 652 Status = i; 653 do 654 { 655 ExceptionInfo = AcpiUtValidateException ((ACPI_STATUS) Status); 656 if (ExceptionInfo) 657 { 658 AH_DISPLAY_EXCEPTION_TEXT (Status, ExceptionInfo); 659 } 660 661 Status++; 662 663 } while (ExceptionInfo); 664 } 665 return; 666 } 667 668 /* Decode a single user-supplied exception code */ 669 670 Status = strtoul (HexString, NULL, 16); 671 if (!Status) 672 { 673 printf ("%s: Invalid hexadecimal exception code value\n", HexString); 674 return; 675 } 676 677 if (Status > ACPI_UINT16_MAX) 678 { 679 AH_DISPLAY_EXCEPTION (Status, "Invalid exception code (more than 16 bits)"); 680 return; 681 } 682 683 ExceptionInfo = AcpiUtValidateException ((ACPI_STATUS) Status); 684 if (!ExceptionInfo) 685 { 686 AH_DISPLAY_EXCEPTION (Status, "Unknown exception code"); 687 return; 688 } 689 690 AH_DISPLAY_EXCEPTION_TEXT (Status, ExceptionInfo); 691 } 692