1 /******************************************************************************* 2 * 3 * Module Name: dmbuffer - AML disassembler, buffer and string support 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, 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 <contrib/dev/acpica/include/acpi.h> 46 #include <contrib/dev/acpica/include/accommon.h> 47 #include <contrib/dev/acpica/include/acdisasm.h> 48 #include <contrib/dev/acpica/include/acparser.h> 49 #include <contrib/dev/acpica/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_UINT8_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 /* 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 528 AcpiOsPrintf ("\""); 529 530 /* Write every other byte as an ASCII character */ 531 532 for (i = 0; i < (WordCount - 1); i++) 533 { 534 AcpiOsPrintf ("%c", (int) WordData[i]); 535 } 536 537 AcpiOsPrintf ("\")"); 538 } 539 540 541 /******************************************************************************* 542 * 543 * FUNCTION: AcpiDmIsEisaIdElement 544 * 545 * PARAMETERS: Op - Op to be examined 546 * 547 * RETURN: None 548 * 549 * DESCRIPTION: Determine if an Op (argument to _HID or _CID) can be converted 550 * to an EISA ID. 551 * 552 ******************************************************************************/ 553 554 static void 555 AcpiDmIsEisaIdElement ( 556 ACPI_PARSE_OBJECT *Op) 557 { 558 UINT32 BigEndianId; 559 UINT32 Prefix[3]; 560 UINT32 i; 561 562 563 /* The parameter must be either a word or a dword */ 564 565 if ((Op->Common.AmlOpcode != AML_DWORD_OP) && 566 (Op->Common.AmlOpcode != AML_WORD_OP)) 567 { 568 return; 569 } 570 571 /* Swap from little-endian to big-endian to simplify conversion */ 572 573 BigEndianId = AcpiUtDwordByteSwap ((UINT32) Op->Common.Value.Integer); 574 575 /* Create the 3 leading ASCII letters */ 576 577 Prefix[0] = ((BigEndianId >> 26) & 0x1F) + 0x40; 578 Prefix[1] = ((BigEndianId >> 21) & 0x1F) + 0x40; 579 Prefix[2] = ((BigEndianId >> 16) & 0x1F) + 0x40; 580 581 /* Verify that all 3 are ascii and alpha */ 582 583 for (i = 0; i < 3; i++) 584 { 585 if (!ACPI_IS_ASCII (Prefix[i]) || 586 !ACPI_IS_ALPHA (Prefix[i])) 587 { 588 return; 589 } 590 } 591 592 /* OK - mark this node as convertable to an EISA ID */ 593 594 Op->Common.DisasmOpcode = ACPI_DASM_EISAID; 595 } 596 597 598 /******************************************************************************* 599 * 600 * FUNCTION: AcpiDmIsEisaId 601 * 602 * PARAMETERS: Op - Op to be examined 603 * 604 * RETURN: None 605 * 606 * DESCRIPTION: Determine if a Name() Op can be converted to an EisaId. 607 * 608 ******************************************************************************/ 609 610 void 611 AcpiDmIsEisaId ( 612 ACPI_PARSE_OBJECT *Op) 613 { 614 UINT32 Name; 615 ACPI_PARSE_OBJECT *NextOp; 616 617 618 /* Get the NameSegment */ 619 620 Name = AcpiPsGetName (Op); 621 if (!Name) 622 { 623 return; 624 } 625 626 NextOp = AcpiPsGetDepthNext (NULL, Op); 627 if (!NextOp) 628 { 629 return; 630 } 631 632 /* Check for _HID - has one argument */ 633 634 if (ACPI_COMPARE_NAME (&Name, METHOD_NAME__HID)) 635 { 636 AcpiDmIsEisaIdElement (NextOp); 637 return; 638 } 639 640 /* Exit if not _CID */ 641 642 if (!ACPI_COMPARE_NAME (&Name, METHOD_NAME__CID)) 643 { 644 return; 645 } 646 647 /* _CID can contain a single argument or a package */ 648 649 if (NextOp->Common.AmlOpcode != AML_PACKAGE_OP) 650 { 651 AcpiDmIsEisaIdElement (NextOp); 652 return; 653 } 654 655 /* _CID with Package: get the package length */ 656 657 NextOp = AcpiPsGetDepthNext (NULL, NextOp); 658 659 /* Don't need to use the length, just walk the peer list */ 660 661 NextOp = NextOp->Common.Next; 662 while (NextOp) 663 { 664 AcpiDmIsEisaIdElement (NextOp); 665 NextOp = NextOp->Common.Next; 666 } 667 } 668 669 670 /******************************************************************************* 671 * 672 * FUNCTION: AcpiDmEisaId 673 * 674 * PARAMETERS: EncodedId - Raw encoded EISA ID. 675 * 676 * RETURN: None 677 * 678 * DESCRIPTION: Convert an encoded EISAID back to the original ASCII String. 679 * 680 ******************************************************************************/ 681 682 void 683 AcpiDmEisaId ( 684 UINT32 EncodedId) 685 { 686 UINT32 BigEndianId; 687 688 689 /* Swap from little-endian to big-endian to simplify conversion */ 690 691 BigEndianId = AcpiUtDwordByteSwap (EncodedId); 692 693 694 /* Split to form "AAANNNN" string */ 695 696 AcpiOsPrintf ("EisaId (\"%c%c%c%4.4X\")", 697 698 /* Three Alpha characters (AAA), 5 bits each */ 699 700 (int) ((BigEndianId >> 26) & 0x1F) + 0x40, 701 (int) ((BigEndianId >> 21) & 0x1F) + 0x40, 702 (int) ((BigEndianId >> 16) & 0x1F) + 0x40, 703 704 /* Numeric part (NNNN) is simply the lower 16 bits */ 705 706 (UINT32) (BigEndianId & 0xFFFF)); 707 } 708 709 #endif 710