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 
  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