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