1 /******************************************************************************
   2  *
   3  * Module Name: aslopcode - AML opcode generation
   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 "aslcompiler.h"
  46 #include "aslcompiler.y.h"
  47 #include "amlcode.h"
  48 
  49 #define _COMPONENT          ACPI_COMPILER
  50         ACPI_MODULE_NAME    ("aslopcodes")
  51 
  52 
  53 /* Local prototypes */
  54 
  55 static void
  56 OpcDoAccessAs (
  57     ACPI_PARSE_OBJECT       *Op);
  58 
  59 static void
  60 OpcDoConnection (
  61     ACPI_PARSE_OBJECT       *Op);
  62 
  63 static void
  64 OpcDoUnicode (
  65     ACPI_PARSE_OBJECT       *Op);
  66 
  67 static void
  68 OpcDoEisaId (
  69     ACPI_PARSE_OBJECT       *Op);
  70 
  71 static void
  72 OpcDoUuId (
  73     ACPI_PARSE_OBJECT       *Op);
  74 
  75 
  76 /*******************************************************************************
  77  *
  78  * FUNCTION:    OpcAmlOpcodeUpdateWalk
  79  *
  80  * PARAMETERS:  ASL_WALK_CALLBACK
  81  *
  82  * RETURN:      Status
  83  *
  84  * DESCRIPTION: Opcode update walk, ascending callback
  85  *
  86  ******************************************************************************/
  87 
  88 ACPI_STATUS
  89 OpcAmlOpcodeUpdateWalk (
  90     ACPI_PARSE_OBJECT       *Op,
  91     UINT32                  Level,
  92     void                    *Context)
  93 {
  94 
  95     /*
  96      * Handle the Package() case where the actual opcode cannot be determined
  97      * until the PackageLength operand has been folded and minimized.
  98      * (PackageOp versus VarPackageOp)
  99      *
 100      * This is (as of ACPI 3.0) the only case where the AML opcode can change
 101      * based upon the value of a parameter.
 102      *
 103      * The parser always inserts a VarPackage opcode, which can possibly be
 104      * optimized to a Package opcode.
 105      */
 106     if (Op->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)
 107     {
 108         OpnDoPackage (Op);
 109     }
 110 
 111     return (AE_OK);
 112 }
 113 
 114 
 115 /*******************************************************************************
 116  *
 117  * FUNCTION:    OpcAmlOpcodeWalk
 118  *
 119  * PARAMETERS:  ASL_WALK_CALLBACK
 120  *
 121  * RETURN:      Status
 122  *
 123  * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML
 124  *              operands.
 125  *
 126  ******************************************************************************/
 127 
 128 ACPI_STATUS
 129 OpcAmlOpcodeWalk (
 130     ACPI_PARSE_OBJECT       *Op,
 131     UINT32                  Level,
 132     void                    *Context)
 133 {
 134 
 135     TotalParseNodes++;
 136 
 137     OpcGenerateAmlOpcode (Op);
 138     OpnGenerateAmlOperands (Op);
 139     return (AE_OK);
 140 }
 141 
 142 
 143 /*******************************************************************************
 144  *
 145  * FUNCTION:    OpcGetIntegerWidth
 146  *
 147  * PARAMETERS:  Op          - DEFINITION BLOCK op
 148  *
 149  * RETURN:      none
 150  *
 151  * DESCRIPTION: Extract integer width from the table revision
 152  *
 153  ******************************************************************************/
 154 
 155 void
 156 OpcGetIntegerWidth (
 157     ACPI_PARSE_OBJECT       *Op)
 158 {
 159     ACPI_PARSE_OBJECT       *Child;
 160 
 161 
 162     if (!Op)
 163     {
 164         return;
 165     }
 166 
 167     if (Gbl_RevisionOverride)
 168     {
 169         AcpiUtSetIntegerWidth (Gbl_RevisionOverride);
 170     }
 171     else
 172     {
 173         Child = Op->Asl.Child;
 174         Child = Child->Asl.Next;
 175         Child = Child->Asl.Next;
 176 
 177         /* Use the revision to set the integer width */
 178 
 179         AcpiUtSetIntegerWidth ((UINT8) Child->Asl.Value.Integer);
 180     }
 181 }
 182 
 183 
 184 /*******************************************************************************
 185  *
 186  * FUNCTION:    OpcSetOptimalIntegerSize
 187  *
 188  * PARAMETERS:  Op        - A parse tree node
 189  *
 190  * RETURN:      Integer width, in bytes. Also sets the node AML opcode to the
 191  *              optimal integer AML prefix opcode.
 192  *
 193  * DESCRIPTION: Determine the optimal AML encoding of an integer. All leading
 194  *              zeros can be truncated to squeeze the integer into the
 195  *              minimal number of AML bytes.
 196  *
 197  ******************************************************************************/
 198 
 199 UINT32
 200 OpcSetOptimalIntegerSize (
 201     ACPI_PARSE_OBJECT       *Op)
 202 {
 203 
 204 #if 0
 205     /*
 206      * TBD: - we don't want to optimize integers in the block header, but the
 207      * code below does not work correctly.
 208      */
 209     if (Op->Asl.Parent &&
 210         Op->Asl.Parent->Asl.Parent &&
 211        (Op->Asl.Parent->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK))
 212     {
 213         return (0);
 214     }
 215 #endif
 216 
 217     /*
 218      * Check for the special AML integers first - Zero, One, Ones.
 219      * These are single-byte opcodes that are the smallest possible
 220      * representation of an integer.
 221      *
 222      * This optimization is optional.
 223      */
 224     if (Gbl_IntegerOptimizationFlag)
 225     {
 226         switch (Op->Asl.Value.Integer)
 227         {
 228         case 0:
 229 
 230             Op->Asl.AmlOpcode = AML_ZERO_OP;
 231             AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
 232                 Op, "Zero");
 233             return (1);
 234 
 235         case 1:
 236 
 237             Op->Asl.AmlOpcode = AML_ONE_OP;
 238             AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
 239                 Op, "One");
 240             return (1);
 241 
 242         case ACPI_UINT32_MAX:
 243 
 244             /* Check for table integer width (32 or 64) */
 245 
 246             if (AcpiGbl_IntegerByteWidth == 4)
 247             {
 248                 Op->Asl.AmlOpcode = AML_ONES_OP;
 249                 AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
 250                     Op, "Ones");
 251                 return (1);
 252             }
 253             break;
 254 
 255         case ACPI_UINT64_MAX:
 256 
 257             /* Check for table integer width (32 or 64) */
 258 
 259             if (AcpiGbl_IntegerByteWidth == 8)
 260             {
 261                 Op->Asl.AmlOpcode = AML_ONES_OP;
 262                 AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
 263                     Op, "Ones");
 264                 return (1);
 265             }
 266             break;
 267 
 268         default:
 269 
 270             break;
 271         }
 272     }
 273 
 274     /* Find the best fit using the various AML integer prefixes */
 275 
 276     if (Op->Asl.Value.Integer <= ACPI_UINT8_MAX)
 277     {
 278         Op->Asl.AmlOpcode = AML_BYTE_OP;
 279         return (1);
 280     }
 281     if (Op->Asl.Value.Integer <= ACPI_UINT16_MAX)
 282     {
 283         Op->Asl.AmlOpcode = AML_WORD_OP;
 284         return (2);
 285     }
 286     if (Op->Asl.Value.Integer <= ACPI_UINT32_MAX)
 287     {
 288         Op->Asl.AmlOpcode = AML_DWORD_OP;
 289         return (4);
 290     }
 291     else
 292     {
 293         if (AcpiGbl_IntegerByteWidth == 4)
 294         {
 295             AslError (ASL_WARNING, ASL_MSG_INTEGER_LENGTH,
 296                 Op, NULL);
 297 
 298             if (!Gbl_IgnoreErrors)
 299             {
 300                 /* Truncate the integer to 32-bit */
 301                 Op->Asl.AmlOpcode = AML_DWORD_OP;
 302                 return (4);
 303             }
 304         }
 305 
 306         Op->Asl.AmlOpcode = AML_QWORD_OP;
 307         return (8);
 308     }
 309 }
 310 
 311 
 312 /*******************************************************************************
 313  *
 314  * FUNCTION:    OpcDoAccessAs
 315  *
 316  * PARAMETERS:  Op        - Parse node
 317  *
 318  * RETURN:      None
 319  *
 320  * DESCRIPTION: Implement the ACCESS_AS ASL keyword.
 321  *
 322  ******************************************************************************/
 323 
 324 static void
 325 OpcDoAccessAs (
 326     ACPI_PARSE_OBJECT       *Op)
 327 {
 328     ACPI_PARSE_OBJECT       *TypeOp;
 329     ACPI_PARSE_OBJECT       *AttribOp;
 330     ACPI_PARSE_OBJECT       *LengthOp;
 331     UINT8                   Attribute;
 332 
 333 
 334     Op->Asl.AmlOpcodeLength = 1;
 335     TypeOp = Op->Asl.Child;
 336 
 337     /* First child is the access type */
 338 
 339     TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
 340     TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
 341 
 342     /* Second child is the optional access attribute */
 343 
 344     AttribOp = TypeOp->Asl.Next;
 345     if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
 346     {
 347         AttribOp->Asl.Value.Integer = 0;
 348     }
 349     AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
 350     AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
 351 
 352     /* Only a few AccessAttributes support AccessLength */
 353 
 354     Attribute = (UINT8) AttribOp->Asl.Value.Integer;
 355     if ((Attribute != AML_FIELD_ATTRIB_MULTIBYTE) &&
 356         (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) &&
 357         (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS))
 358     {
 359         return;
 360     }
 361 
 362     Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP;
 363 
 364     /*
 365      * Child of Attributes is the AccessLength (required for Multibyte,
 366      * RawBytes, RawProcess.)
 367      */
 368     LengthOp = AttribOp->Asl.Child;
 369     if (!LengthOp)
 370     {
 371         return;
 372     }
 373 
 374     /* TBD: probably can remove */
 375 
 376     if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
 377     {
 378         LengthOp->Asl.Value.Integer = 16;
 379     }
 380 
 381     LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
 382     LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
 383 }
 384 
 385 
 386 /*******************************************************************************
 387  *
 388  * FUNCTION:    OpcDoConnection
 389  *
 390  * PARAMETERS:  Op        - Parse node
 391  *
 392  * RETURN:      None
 393  *
 394  * DESCRIPTION: Implement the Connection ASL keyword.
 395  *
 396  ******************************************************************************/
 397 
 398 static void
 399 OpcDoConnection (
 400     ACPI_PARSE_OBJECT       *Op)
 401 {
 402     ASL_RESOURCE_NODE       *Rnode;
 403     ACPI_PARSE_OBJECT       *BufferOp;
 404     ACPI_PARSE_OBJECT       *BufferLengthOp;
 405     ACPI_PARSE_OBJECT       *BufferDataOp;
 406     UINT8                   State;
 407 
 408 
 409     Op->Asl.AmlOpcodeLength = 1;
 410 
 411     if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)
 412     {
 413         return;
 414     }
 415 
 416     BufferOp = Op->Asl.Child;
 417     BufferLengthOp = BufferOp->Asl.Child;
 418     BufferDataOp = BufferLengthOp->Asl.Next;
 419 
 420     State = ACPI_RSTATE_NORMAL;
 421     Rnode = RsDoOneResourceDescriptor (BufferDataOp->Asl.Next, 0, &State);
 422     if (!Rnode)
 423     {
 424         return; /* error */
 425     }
 426 
 427     /*
 428      * Transform the nodes into the following
 429      *
 430      * Op           -> AML_BUFFER_OP
 431      * First Child  -> BufferLength
 432      * Second Child -> Descriptor Buffer (raw byte data)
 433      */
 434     BufferOp->Asl.ParseOpcode         = PARSEOP_BUFFER;
 435     BufferOp->Asl.AmlOpcode           = AML_BUFFER_OP;
 436     BufferOp->Asl.CompileFlags        = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
 437     UtSetParseOpName (BufferOp);
 438 
 439     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
 440     BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength;
 441     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
 442     UtSetParseOpName (BufferLengthOp);
 443 
 444     BufferDataOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
 445     BufferDataOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
 446     BufferDataOp->Asl.AmlOpcodeLength     = 0;
 447     BufferDataOp->Asl.AmlLength           = Rnode->BufferLength;
 448     BufferDataOp->Asl.Value.Buffer        = (UINT8 *) Rnode;
 449     UtSetParseOpName (BufferDataOp);
 450 }
 451 
 452 
 453 /*******************************************************************************
 454  *
 455  * FUNCTION:    OpcDoUnicode
 456  *
 457  * PARAMETERS:  Op        - Parse node
 458  *
 459  * RETURN:      None
 460  *
 461  * DESCRIPTION: Implement the UNICODE ASL "macro".  Convert the input string
 462  *              to a unicode buffer. There is no Unicode AML opcode.
 463  *
 464  * Note:  The Unicode string is 16 bits per character, no leading signature,
 465  *        with a 16-bit terminating NULL.
 466  *
 467  ******************************************************************************/
 468 
 469 static void
 470 OpcDoUnicode (
 471     ACPI_PARSE_OBJECT       *Op)
 472 {
 473     ACPI_PARSE_OBJECT       *InitializerOp;
 474     UINT32                  Length;
 475     UINT32                  Count;
 476     UINT32                  i;
 477     UINT8                   *AsciiString;
 478     UINT16                  *UnicodeString;
 479     ACPI_PARSE_OBJECT       *BufferLengthOp;
 480 
 481 
 482     /* Change op into a buffer object */
 483 
 484     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
 485     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
 486     UtSetParseOpName (Op);
 487 
 488     /* Buffer Length is first, followed by the string */
 489 
 490     BufferLengthOp = Op->Asl.Child;
 491     InitializerOp = BufferLengthOp->Asl.Next;
 492 
 493     AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;
 494 
 495     /* Create a new buffer for the Unicode string */
 496 
 497     Count = strlen (InitializerOp->Asl.Value.String) + 1;
 498     Length = Count * sizeof (UINT16);
 499     UnicodeString = UtLocalCalloc (Length);
 500 
 501     /* Convert to Unicode string (including null terminator) */
 502 
 503     for (i = 0; i < Count; i++)
 504     {
 505         UnicodeString[i] = (UINT16) AsciiString[i];
 506     }
 507 
 508     /*
 509      * Just set the buffer size node to be the buffer length, regardless
 510      * of whether it was previously an integer or a default_arg placeholder
 511      */
 512     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
 513     BufferLengthOp->Asl.AmlOpcode     = AML_DWORD_OP;
 514     BufferLengthOp->Asl.Value.Integer = Length;
 515     UtSetParseOpName (BufferLengthOp);
 516 
 517     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
 518 
 519     /* The Unicode string is a raw data buffer */
 520 
 521     InitializerOp->Asl.Value.Buffer   = (UINT8 *) UnicodeString;
 522     InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
 523     InitializerOp->Asl.AmlLength      = Length;
 524     InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
 525     InitializerOp->Asl.Child          = NULL;
 526     UtSetParseOpName (InitializerOp);
 527 }
 528 
 529 
 530 /*******************************************************************************
 531  *
 532  * FUNCTION:    OpcDoEisaId
 533  *
 534  * PARAMETERS:  Op        - Parse node
 535  *
 536  * RETURN:      None
 537  *
 538  * DESCRIPTION: Convert a string EISA ID to numeric representation. See the
 539  *              Pnp BIOS Specification for details. Here is an excerpt:
 540  *
 541  *              A seven character ASCII representation of the product
 542  *              identifier compressed into a 32-bit identifier. The seven
 543  *              character ID consists of a three character manufacturer code,
 544  *              a three character hexadecimal product identifier, and a one
 545  *              character hexadecimal revision number. The manufacturer code
 546  *              is a 3 uppercase character code that is compressed into 3 5-bit
 547  *              values as follows:
 548  *                  1) Find hex ASCII value for each letter
 549  *                  2) Subtract 40h from each ASCII value
 550  *                  3) Retain 5 least significant bits for each letter by
 551  *                     discarding upper 3 bits because they are always 0.
 552  *                  4) Compressed code = concatenate 0 and the 3 5-bit values
 553  *
 554  *              The format of the compressed product identifier is as follows:
 555  *              Byte 0: Bit 7       - Reserved (0)
 556  *                      Bits 6-2:   - 1st character of compressed mfg code
 557  *                      Bits 1-0    - Upper 2 bits of 2nd character of mfg code
 558  *              Byte 1: Bits 7-5    - Lower 3 bits of 2nd character of mfg code
 559  *                      Bits 4-0    - 3rd character of mfg code
 560  *              Byte 2: Bits 7-4    - 1st hex digit of product number
 561  *                      Bits 3-0    - 2nd hex digit of product number
 562  *              Byte 3: Bits 7-4    - 3st hex digit of product number
 563  *                      Bits 3-0    - Hex digit of the revision number
 564  *
 565  ******************************************************************************/
 566 
 567 static void
 568 OpcDoEisaId (
 569     ACPI_PARSE_OBJECT       *Op)
 570 {
 571     UINT32                  EisaId = 0;
 572     UINT32                  BigEndianId;
 573     char                    *InString;
 574     ACPI_STATUS             Status = AE_OK;
 575     UINT32                  i;
 576 
 577 
 578     InString = (char *) Op->Asl.Value.String;
 579 
 580     /*
 581      * The EISAID string must be exactly 7 characters and of the form
 582      * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
 583      */
 584     if (ACPI_STRLEN (InString) != 7)
 585     {
 586         Status = AE_BAD_PARAMETER;
 587     }
 588     else
 589     {
 590         /* Check all 7 characters for correct format */
 591 
 592         for (i = 0; i < 7; i++)
 593         {
 594             /* First 3 characters must be uppercase letters */
 595 
 596             if (i < 3)
 597             {
 598                 if (!isupper ((int) InString[i]))
 599                 {
 600                     Status = AE_BAD_PARAMETER;
 601                 }
 602             }
 603 
 604             /* Last 4 characters must be hex digits */
 605 
 606             else if (!isxdigit ((int) InString[i]))
 607             {
 608                 Status = AE_BAD_PARAMETER;
 609             }
 610         }
 611     }
 612 
 613     if (ACPI_FAILURE (Status))
 614     {
 615         AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
 616     }
 617     else
 618     {
 619         /* Create ID big-endian first (bits are contiguous) */
 620 
 621         BigEndianId =
 622             (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
 623             (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
 624             (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |
 625 
 626             (UtHexCharToValue (InString[3])) << 12 |
 627             (UtHexCharToValue (InString[4])) << 8  |
 628             (UtHexCharToValue (InString[5])) << 4  |
 629              UtHexCharToValue (InString[6]);
 630 
 631         /* Swap to little-endian to get final ID (see function header) */
 632 
 633         EisaId = AcpiUtDwordByteSwap (BigEndianId);
 634     }
 635 
 636     /*
 637      * Morph the Op into an integer, regardless of whether there
 638      * was an error in the EISAID string
 639      */
 640     Op->Asl.Value.Integer = EisaId;
 641 
 642     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
 643     Op->Asl.ParseOpcode = PARSEOP_INTEGER;
 644     (void) OpcSetOptimalIntegerSize (Op);
 645 
 646     /* Op is now an integer */
 647 
 648     UtSetParseOpName (Op);
 649 }
 650 
 651 
 652 /*******************************************************************************
 653  *
 654  * FUNCTION:    OpcDoUuId
 655  *
 656  * PARAMETERS:  Op        - Parse node
 657  *
 658  * RETURN:      None
 659  *
 660  * DESCRIPTION: Convert UUID string to 16-byte buffer
 661  *
 662  ******************************************************************************/
 663 
 664 static void
 665 OpcDoUuId (
 666     ACPI_PARSE_OBJECT       *Op)
 667 {
 668     char                    *InString;
 669     char                    *Buffer;
 670     ACPI_STATUS             Status = AE_OK;
 671     ACPI_PARSE_OBJECT       *NewOp;
 672 
 673 
 674     InString = (char *) Op->Asl.Value.String;
 675     Buffer = UtLocalCalloc (16);
 676 
 677     Status = AuValidateUuid (InString);
 678     if (ACPI_FAILURE (Status))
 679     {
 680         AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
 681     }
 682     else
 683     {
 684         (void) AuConvertStringToUuid (InString, Buffer);
 685     }
 686 
 687     /* Change Op to a Buffer */
 688 
 689     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
 690     Op->Common.AmlOpcode = AML_BUFFER_OP;
 691 
 692     /* Disable further optimization */
 693 
 694     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
 695     UtSetParseOpName (Op);
 696 
 697     /* Child node is the buffer length */
 698 
 699     NewOp = TrAllocateNode (PARSEOP_INTEGER);
 700 
 701     NewOp->Asl.AmlOpcode     = AML_BYTE_OP;
 702     NewOp->Asl.Value.Integer = 16;
 703     NewOp->Asl.Parent        = Op;
 704 
 705     Op->Asl.Child = NewOp;
 706     Op = NewOp;
 707 
 708     /* Peer to the child is the raw buffer data */
 709 
 710     NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
 711     NewOp->Asl.AmlOpcode     = AML_RAW_DATA_BUFFER;
 712     NewOp->Asl.AmlLength     = 16;
 713     NewOp->Asl.Value.String  = (char *) Buffer;
 714     NewOp->Asl.Parent        = Op->Asl.Parent;
 715 
 716     Op->Asl.Next = NewOp;
 717 }
 718 
 719 
 720 /*******************************************************************************
 721  *
 722  * FUNCTION:    OpcGenerateAmlOpcode
 723  *
 724  * PARAMETERS:  Op        - Parse node
 725  *
 726  * RETURN:      None
 727  *
 728  * DESCRIPTION: Generate the AML opcode associated with the node and its
 729  *              parse (lex/flex) keyword opcode. Essentially implements
 730  *              a mapping between the parse opcodes and the actual AML opcodes.
 731  *
 732  ******************************************************************************/
 733 
 734 void
 735 OpcGenerateAmlOpcode (
 736     ACPI_PARSE_OBJECT       *Op)
 737 {
 738 
 739     UINT16                  Index;
 740 
 741 
 742     Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
 743 
 744     Op->Asl.AmlOpcode     = AslKeywordMapping[Index].AmlOpcode;
 745     Op->Asl.AcpiBtype     = AslKeywordMapping[Index].AcpiBtype;
 746     Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
 747 
 748     if (!Op->Asl.Value.Integer)
 749     {
 750         Op->Asl.Value.Integer = AslKeywordMapping[Index].Value;
 751     }
 752 
 753     /* Special handling for some opcodes */
 754 
 755     switch (Op->Asl.ParseOpcode)
 756     {
 757     case PARSEOP_INTEGER:
 758         /*
 759          * Set the opcode based on the size of the integer
 760          */
 761         (void) OpcSetOptimalIntegerSize (Op);
 762         break;
 763 
 764     case PARSEOP_OFFSET:
 765 
 766         Op->Asl.AmlOpcodeLength = 1;
 767         break;
 768 
 769     case PARSEOP_ACCESSAS:
 770 
 771         OpcDoAccessAs (Op);
 772         break;
 773 
 774     case PARSEOP_CONNECTION:
 775 
 776         OpcDoConnection (Op);
 777         break;
 778 
 779     case PARSEOP_EISAID:
 780 
 781         OpcDoEisaId (Op);
 782         break;
 783 
 784     case PARSEOP_TOUUID:
 785 
 786         OpcDoUuId (Op);
 787         break;
 788 
 789     case PARSEOP_UNICODE:
 790 
 791         OpcDoUnicode (Op);
 792         break;
 793 
 794     case PARSEOP_INCLUDE:
 795 
 796         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
 797         Gbl_HasIncludeFiles = TRUE;
 798         break;
 799 
 800     case PARSEOP_EXTERNAL:
 801 
 802         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
 803         Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
 804         break;
 805 
 806     case PARSEOP_TIMER:
 807 
 808         if (AcpiGbl_IntegerBitWidth == 32)
 809         {
 810             AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
 811         }
 812         break;
 813 
 814     default:
 815 
 816         /* Nothing to do for other opcodes */
 817 
 818         break;
 819     }
 820 
 821     return;
 822 }