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