1 /******************************************************************************* 2 * 3 * Module Name: dmbuffer - AML disassembler, buffer and string support 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 45 #include "acpi.h" 46 #include "accommon.h" 47 #include "acdisasm.h" 48 #include "acparser.h" 49 #include "amlcode.h" 50 #include "acinterp.h" 51 52 53 #ifdef ACPI_DISASSEMBLER 54 55 #define _COMPONENT ACPI_CA_DEBUGGER 56 ACPI_MODULE_NAME ("dmbuffer") 57 58 /* Local prototypes */ 59 60 static void 61 AcpiDmUnicode ( 62 ACPI_PARSE_OBJECT *Op); 63 64 static void 65 AcpiDmGetHardwareIdType ( 66 ACPI_PARSE_OBJECT *Op); 67 68 static void 69 AcpiDmPldBuffer ( 70 UINT32 Level, 71 UINT8 *ByteData, 72 UINT32 ByteCount); 73 74 #define ACPI_BUFFER_BYTES_PER_LINE 8 75 76 77 /******************************************************************************* 78 * 79 * FUNCTION: AcpiDmDisasmByteList 80 * 81 * PARAMETERS: Level - Current source code indentation level 82 * ByteData - Pointer to the byte list 83 * ByteCount - Length of the byte list 84 * 85 * RETURN: None 86 * 87 * DESCRIPTION: Dump an AML "ByteList" in Hex format. 8 bytes per line, prefixed 88 * with the hex buffer offset. 89 * 90 ******************************************************************************/ 91 92 void 93 AcpiDmDisasmByteList ( 94 UINT32 Level, 95 UINT8 *ByteData, 96 UINT32 ByteCount) 97 { 98 UINT32 i; 99 UINT32 j; 100 UINT32 CurrentIndex; 101 UINT8 BufChar; 102 103 104 if (!ByteCount) 105 { 106 return; 107 } 108 109 for (i = 0; i < ByteCount; i += ACPI_BUFFER_BYTES_PER_LINE) 110 { 111 /* Line indent and offset prefix for each new line */ 112 113 AcpiDmIndent (Level); 114 if (ByteCount > ACPI_BUFFER_BYTES_PER_LINE) 115 { 116 AcpiOsPrintf ("/* %04X */ ", i); 117 } 118 119 /* Dump the actual hex values */ 120 121 for (j = 0; j < ACPI_BUFFER_BYTES_PER_LINE; j++) 122 { 123 CurrentIndex = i + j; 124 if (CurrentIndex >= ByteCount) 125 { 126 /* Dump fill spaces */ 127 128 AcpiOsPrintf (" "); 129 continue; 130 } 131 132 AcpiOsPrintf (" 0x%2.2X", ByteData[CurrentIndex]); 133 134 /* Add comma if there are more bytes to display */ 135 136 if (CurrentIndex < (ByteCount - 1)) 137 { 138 AcpiOsPrintf (","); 139 } 140 else 141 { 142 AcpiOsPrintf (" "); 143 } 144 } 145 146 /* Dump the ASCII equivalents within a comment */ 147 148 AcpiOsPrintf (" /* "); 149 for (j = 0; j < ACPI_BUFFER_BYTES_PER_LINE; j++) 150 { 151 CurrentIndex = i + j; 152 if (CurrentIndex >= ByteCount) 153 { 154 break; 155 } 156 157 BufChar = ByteData[CurrentIndex]; 158 if (ACPI_IS_PRINT (BufChar)) 159 { 160 AcpiOsPrintf ("%c", BufChar); 161 } 162 else 163 { 164 AcpiOsPrintf ("."); 165 } 166 } 167 168 /* Finished with this line */ 169 170 AcpiOsPrintf (" */\n"); 171 } 172 } 173 174 175 /******************************************************************************* 176 * 177 * FUNCTION: AcpiDmByteList 178 * 179 * PARAMETERS: Info - Parse tree walk info 180 * Op - Byte list op 181 * 182 * RETURN: None 183 * 184 * DESCRIPTION: Dump a buffer byte list, handling the various types of buffers. 185 * Buffer type must be already set in the Op DisasmOpcode. 186 * 187 ******************************************************************************/ 188 189 void 190 AcpiDmByteList ( 191 ACPI_OP_WALK_INFO *Info, 192 ACPI_PARSE_OBJECT *Op) 193 { 194 UINT8 *ByteData; 195 UINT32 ByteCount; 196 197 198 ByteData = Op->Named.Data; 199 ByteCount = (UINT32) Op->Common.Value.Integer; 200 201 /* 202 * The byte list belongs to a buffer, and can be produced by either 203 * a ResourceTemplate, Unicode, quoted string, or a plain byte list. 204 */ 205 switch (Op->Common.Parent->Common.DisasmOpcode) 206 { 207 case ACPI_DASM_RESOURCE: 208 209 AcpiDmResourceTemplate (Info, Op->Common.Parent, ByteData, ByteCount); 210 break; 211 212 case ACPI_DASM_STRING: 213 214 AcpiDmIndent (Info->Level); 215 AcpiUtPrintString ((char *) ByteData, ACPI_UINT16_MAX); 216 AcpiOsPrintf ("\n"); 217 break; 218 219 case ACPI_DASM_UNICODE: 220 221 AcpiDmUnicode (Op); 222 break; 223 224 case ACPI_DASM_PLD_METHOD: 225 226 AcpiDmDisasmByteList (Info->Level, ByteData, ByteCount); 227 AcpiDmPldBuffer (Info->Level, ByteData, ByteCount); 228 break; 229 230 case ACPI_DASM_BUFFER: 231 default: 232 /* 233 * Not a resource, string, or unicode string. 234 * Just dump the buffer 235 */ 236 AcpiDmDisasmByteList (Info->Level, ByteData, ByteCount); 237 break; 238 } 239 } 240 241 242 /******************************************************************************* 243 * 244 * FUNCTION: AcpiDmIsUnicodeBuffer 245 * 246 * PARAMETERS: Op - Buffer Object to be examined 247 * 248 * RETURN: TRUE if buffer contains a UNICODE string 249 * 250 * DESCRIPTION: Determine if a buffer Op contains a Unicode string 251 * 252 ******************************************************************************/ 253 254 BOOLEAN 255 AcpiDmIsUnicodeBuffer ( 256 ACPI_PARSE_OBJECT *Op) 257 { 258 UINT8 *ByteData; 259 UINT32 ByteCount; 260 UINT32 WordCount; 261 ACPI_PARSE_OBJECT *SizeOp; 262 ACPI_PARSE_OBJECT *NextOp; 263 UINT32 i; 264 265 266 /* Buffer size is the buffer argument */ 267 268 SizeOp = Op->Common.Value.Arg; 269 270 /* Next, the initializer byte list to examine */ 271 272 NextOp = SizeOp->Common.Next; 273 if (!NextOp) 274 { 275 return (FALSE); 276 } 277 278 /* Extract the byte list info */ 279 280 ByteData = NextOp->Named.Data; 281 ByteCount = (UINT32) NextOp->Common.Value.Integer; 282 WordCount = ACPI_DIV_2 (ByteCount); 283 284 /* 285 * Unicode string must have an even number of bytes and last 286 * word must be zero 287 */ 288 if ((!ByteCount) || 289 (ByteCount < 4) || 290 (ByteCount & 1) || 291 ((UINT16 *) (void *) ByteData)[WordCount - 1] != 0) 292 { 293 return (FALSE); 294 } 295 296 /* For each word, 1st byte must be ascii, 2nd byte must be zero */ 297 298 for (i = 0; i < (ByteCount - 2); i += 2) 299 { 300 if ((!ACPI_IS_PRINT (ByteData[i])) || 301 (ByteData[(ACPI_SIZE) i + 1] != 0)) 302 { 303 return (FALSE); 304 } 305 } 306 307 /* Ignore the Size argument in the disassembly of this buffer op */ 308 309 SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 310 return (TRUE); 311 } 312 313 314 /******************************************************************************* 315 * 316 * FUNCTION: AcpiDmIsStringBuffer 317 * 318 * PARAMETERS: Op - Buffer Object to be examined 319 * 320 * RETURN: TRUE if buffer contains a ASCII string, FALSE otherwise 321 * 322 * DESCRIPTION: Determine if a buffer Op contains a ASCII string 323 * 324 ******************************************************************************/ 325 326 BOOLEAN 327 AcpiDmIsStringBuffer ( 328 ACPI_PARSE_OBJECT *Op) 329 { 330 UINT8 *ByteData; 331 UINT32 ByteCount; 332 ACPI_PARSE_OBJECT *SizeOp; 333 ACPI_PARSE_OBJECT *NextOp; 334 UINT32 i; 335 336 337 /* Buffer size is the buffer argument */ 338 339 SizeOp = Op->Common.Value.Arg; 340 341 /* Next, the initializer byte list to examine */ 342 343 NextOp = SizeOp->Common.Next; 344 if (!NextOp) 345 { 346 return (FALSE); 347 } 348 349 /* Extract the byte list info */ 350 351 ByteData = NextOp->Named.Data; 352 ByteCount = (UINT32) NextOp->Common.Value.Integer; 353 354 /* Last byte must be the null terminator */ 355 356 if ((!ByteCount) || 357 (ByteCount < 2) || 358 (ByteData[ByteCount-1] != 0)) 359 { 360 return (FALSE); 361 } 362 363 for (i = 0; i < (ByteCount - 1); i++) 364 { 365 /* TBD: allow some escapes (non-ascii chars). 366 * they will be handled in the string output routine 367 */ 368 369 if (!ACPI_IS_PRINT (ByteData[i])) 370 { 371 return (FALSE); 372 } 373 } 374 375 return (TRUE); 376 } 377 378 379 /******************************************************************************* 380 * 381 * FUNCTION: AcpiDmIsPldBuffer 382 * 383 * PARAMETERS: Op - Buffer Object to be examined 384 * 385 * RETURN: TRUE if buffer contains a ASCII string, FALSE otherwise 386 * 387 * DESCRIPTION: Determine if a buffer Op contains a _PLD structure 388 * 389 ******************************************************************************/ 390 391 BOOLEAN 392 AcpiDmIsPldBuffer ( 393 ACPI_PARSE_OBJECT *Op) 394 { 395 ACPI_NAMESPACE_NODE *Node; 396 ACPI_PARSE_OBJECT *ParentOp; 397 398 399 ParentOp = Op->Common.Parent; 400 if (!ParentOp) 401 { 402 return (FALSE); 403 } 404 405 /* Check for form: Name(_PLD, Buffer() {}). Not legal, however */ 406 407 if (ParentOp->Common.AmlOpcode == AML_NAME_OP) 408 { 409 Node = ParentOp->Common.Node; 410 411 if (ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__PLD)) 412 { 413 return (TRUE); 414 } 415 416 return (FALSE); 417 } 418 419 /* Check for proper form: Name(_PLD, Package() {Buffer() {}}) */ 420 421 if (ParentOp->Common.AmlOpcode == AML_PACKAGE_OP) 422 { 423 ParentOp = ParentOp->Common.Parent; 424 if (!ParentOp) 425 { 426 return (FALSE); 427 } 428 429 if (ParentOp->Common.AmlOpcode == AML_NAME_OP) 430 { 431 Node = ParentOp->Common.Node; 432 433 if (ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__PLD)) 434 { 435 return (TRUE); 436 } 437 } 438 } 439 440 return (FALSE); 441 } 442 443 444 /******************************************************************************* 445 * 446 * FUNCTION: AcpiDmPldBuffer 447 * 448 * PARAMETERS: Level - Current source code indentation level 449 * ByteData - Pointer to the byte list 450 * ByteCount - Length of the byte list 451 * 452 * RETURN: None 453 * 454 * DESCRIPTION: Dump and format the contents of a _PLD buffer object 455 * 456 ******************************************************************************/ 457 458 #define ACPI_PLD_OUTPUT08 "%*.s/* %18s : %-6.2X */\n", ACPI_MUL_4 (Level), " " 459 #define ACPI_PLD_OUTPUT16 "%*.s/* %18s : %-6.4X */\n", ACPI_MUL_4 (Level), " " 460 #define ACPI_PLD_OUTPUT24 "%*.s/* %18s : %-6.6X */\n", ACPI_MUL_4 (Level), " " 461 462 static void 463 AcpiDmPldBuffer ( 464 UINT32 Level, 465 UINT8 *ByteData, 466 UINT32 ByteCount) 467 { 468 ACPI_PLD_INFO *PldInfo; 469 ACPI_STATUS Status; 470 471 472 /* Check for valid byte count */ 473 474 if (ByteCount < ACPI_PLD_REV1_BUFFER_SIZE) 475 { 476 return; 477 } 478 479 /* Convert _PLD buffer to local _PLD struct */ 480 481 Status = AcpiDecodePldBuffer (ByteData, ByteCount, &PldInfo); 482 if (ACPI_FAILURE (Status)) 483 { 484 return; 485 } 486 487 /* First 32-bit dword */ 488 489 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "Revision", PldInfo->Revision); 490 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "IgnoreColor", PldInfo->IgnoreColor); 491 AcpiOsPrintf (ACPI_PLD_OUTPUT24,"Color", PldInfo->Color); 492 493 /* Second 32-bit dword */ 494 495 AcpiOsPrintf (ACPI_PLD_OUTPUT16,"Width", PldInfo->Width); 496 AcpiOsPrintf (ACPI_PLD_OUTPUT16,"Height", PldInfo->Height); 497 498 /* Third 32-bit dword */ 499 500 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "UserVisible", PldInfo->UserVisible); 501 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "Dock", PldInfo->Dock); 502 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "Lid", PldInfo->Lid); 503 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "Panel", PldInfo->Panel); 504 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "VerticalPosition", PldInfo->VerticalPosition); 505 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "HorizontalPosition", PldInfo->HorizontalPosition); 506 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "Shape", PldInfo->Shape); 507 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "GroupOrientation", PldInfo->GroupOrientation); 508 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "GroupToken", PldInfo->GroupToken); 509 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "GroupPosition", PldInfo->GroupPosition); 510 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "Bay", PldInfo->Bay); 511 512 /* Fourth 32-bit dword */ 513 514 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "Ejectable", PldInfo->Ejectable); 515 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "OspmEjectRequired", PldInfo->OspmEjectRequired); 516 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "CabinetNumber", PldInfo->CabinetNumber); 517 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "CardCageNumber", PldInfo->CardCageNumber); 518 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "Reference", PldInfo->Reference); 519 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "Rotation", PldInfo->Rotation); 520 AcpiOsPrintf (ACPI_PLD_OUTPUT08, "Order", PldInfo->Order); 521 522 /* Fifth 32-bit dword */ 523 524 if (ByteCount >= ACPI_PLD_REV1_BUFFER_SIZE) 525 { 526 AcpiOsPrintf (ACPI_PLD_OUTPUT16,"VerticalOffset", PldInfo->VerticalOffset); 527 AcpiOsPrintf (ACPI_PLD_OUTPUT16,"HorizontalOffset", PldInfo->HorizontalOffset); 528 } 529 530 ACPI_FREE (PldInfo); 531 } 532 533 534 /******************************************************************************* 535 * 536 * FUNCTION: AcpiDmUnicode 537 * 538 * PARAMETERS: Op - Byte List op containing Unicode string 539 * 540 * RETURN: None 541 * 542 * DESCRIPTION: Dump Unicode string as a standard ASCII string. (Remove 543 * the extra zero bytes). 544 * 545 ******************************************************************************/ 546 547 static void 548 AcpiDmUnicode ( 549 ACPI_PARSE_OBJECT *Op) 550 { 551 UINT16 *WordData; 552 UINT32 WordCount; 553 UINT32 i; 554 555 556 /* Extract the buffer info as a WORD buffer */ 557 558 WordData = ACPI_CAST_PTR (UINT16, Op->Named.Data); 559 WordCount = ACPI_DIV_2 (((UINT32) Op->Common.Value.Integer)); 560 561 /* Write every other byte as an ASCII character */ 562 563 AcpiOsPrintf ("\""); 564 for (i = 0; i < (WordCount - 1); i++) 565 { 566 AcpiOsPrintf ("%c", (int) WordData[i]); 567 } 568 569 AcpiOsPrintf ("\")"); 570 } 571 572 573 /******************************************************************************* 574 * 575 * FUNCTION: AcpiDmGetHardwareIdType 576 * 577 * PARAMETERS: Op - Op to be examined 578 * 579 * RETURN: None 580 * 581 * DESCRIPTION: Determine the type of the argument to a _HID or _CID 582 * 1) Strings are allowed 583 * 2) If Integer, determine if it is a valid EISAID 584 * 585 ******************************************************************************/ 586 587 static void 588 AcpiDmGetHardwareIdType ( 589 ACPI_PARSE_OBJECT *Op) 590 { 591 UINT32 BigEndianId; 592 UINT32 Prefix[3]; 593 UINT32 i; 594 595 596 switch (Op->Common.AmlOpcode) 597 { 598 case AML_STRING_OP: 599 600 /* Mark this string as an _HID/_CID string */ 601 602 Op->Common.DisasmOpcode = ACPI_DASM_HID_STRING; 603 break; 604 605 case AML_WORD_OP: 606 case AML_DWORD_OP: 607 608 /* Determine if a Word/Dword is a valid encoded EISAID */ 609 610 /* Swap from little-endian to big-endian to simplify conversion */ 611 612 BigEndianId = AcpiUtDwordByteSwap ((UINT32) Op->Common.Value.Integer); 613 614 /* Create the 3 leading ASCII letters */ 615 616 Prefix[0] = ((BigEndianId >> 26) & 0x1F) + 0x40; 617 Prefix[1] = ((BigEndianId >> 21) & 0x1F) + 0x40; 618 Prefix[2] = ((BigEndianId >> 16) & 0x1F) + 0x40; 619 620 /* Verify that all 3 are ascii and alpha */ 621 622 for (i = 0; i < 3; i++) 623 { 624 if (!ACPI_IS_ASCII (Prefix[i]) || 625 !ACPI_IS_ALPHA (Prefix[i])) 626 { 627 return; 628 } 629 } 630 631 /* Mark this node as convertable to an EISA ID string */ 632 633 Op->Common.DisasmOpcode = ACPI_DASM_EISAID; 634 break; 635 636 default: 637 break; 638 } 639 } 640 641 642 /******************************************************************************* 643 * 644 * FUNCTION: AcpiDmCheckForHardwareId 645 * 646 * PARAMETERS: Op - Op to be examined 647 * 648 * RETURN: None 649 * 650 * DESCRIPTION: Determine if a Name() Op is a _HID/_CID. 651 * 652 ******************************************************************************/ 653 654 void 655 AcpiDmCheckForHardwareId ( 656 ACPI_PARSE_OBJECT *Op) 657 { 658 UINT32 Name; 659 ACPI_PARSE_OBJECT *NextOp; 660 661 662 /* Get the NameSegment */ 663 664 Name = AcpiPsGetName (Op); 665 if (!Name) 666 { 667 return; 668 } 669 670 NextOp = AcpiPsGetDepthNext (NULL, Op); 671 if (!NextOp) 672 { 673 return; 674 } 675 676 /* Check for _HID - has one argument */ 677 678 if (ACPI_COMPARE_NAME (&Name, METHOD_NAME__HID)) 679 { 680 AcpiDmGetHardwareIdType (NextOp); 681 return; 682 } 683 684 /* Exit if not _CID */ 685 686 if (!ACPI_COMPARE_NAME (&Name, METHOD_NAME__CID)) 687 { 688 return; 689 } 690 691 /* _CID can contain a single argument or a package */ 692 693 if (NextOp->Common.AmlOpcode != AML_PACKAGE_OP) 694 { 695 AcpiDmGetHardwareIdType (NextOp); 696 return; 697 } 698 699 /* _CID with Package: get the package length, check all elements */ 700 701 NextOp = AcpiPsGetDepthNext (NULL, NextOp); 702 703 /* Don't need to use the length, just walk the peer list */ 704 705 NextOp = NextOp->Common.Next; 706 while (NextOp) 707 { 708 AcpiDmGetHardwareIdType (NextOp); 709 NextOp = NextOp->Common.Next; 710 } 711 } 712 713 714 /******************************************************************************* 715 * 716 * FUNCTION: AcpiDmDecompressEisaId 717 * 718 * PARAMETERS: EncodedId - Raw encoded EISA ID. 719 * 720 * RETURN: None 721 * 722 * DESCRIPTION: Convert an encoded EISAID back to the original ASCII String 723 * and emit the correct ASL statement. If the ID is known, emit 724 * a description of the ID as a comment. 725 * 726 ******************************************************************************/ 727 728 void 729 AcpiDmDecompressEisaId ( 730 UINT32 EncodedId) 731 { 732 char IdBuffer[ACPI_EISAID_STRING_SIZE]; 733 const AH_DEVICE_ID *Info; 734 735 736 /* Convert EISAID to a string an emit the statement */ 737 738 AcpiExEisaIdToString (IdBuffer, EncodedId); 739 AcpiOsPrintf ("EisaId (\"%s\")", IdBuffer); 740 741 /* If we know about the ID, emit the description */ 742 743 Info = AcpiAhMatchHardwareId (IdBuffer); 744 if (Info) 745 { 746 AcpiOsPrintf (" /* %s */", Info->Description); 747 } 748 } 749 750 #endif 751