128c506b8Sjruoho /******************************************************************************
228c506b8Sjruoho *
328c506b8Sjruoho * Module Name: aslopcode - AML opcode generation
428c506b8Sjruoho *
528c506b8Sjruoho *****************************************************************************/
628c506b8Sjruoho
7124f4c82Sjruoho /*
8*2c7d7e3cSchristos * Copyright (C) 2000 - 2023, Intel Corp.
928c506b8Sjruoho * All rights reserved.
1028c506b8Sjruoho *
11124f4c82Sjruoho * Redistribution and use in source and binary forms, with or without
12124f4c82Sjruoho * modification, are permitted provided that the following conditions
13124f4c82Sjruoho * are met:
14124f4c82Sjruoho * 1. Redistributions of source code must retain the above copyright
15124f4c82Sjruoho * notice, this list of conditions, and the following disclaimer,
16124f4c82Sjruoho * without modification.
17124f4c82Sjruoho * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18124f4c82Sjruoho * substantially similar to the "NO WARRANTY" disclaimer below
19124f4c82Sjruoho * ("Disclaimer") and any redistribution must be conditioned upon
20124f4c82Sjruoho * including a substantially similar Disclaimer requirement for further
21124f4c82Sjruoho * binary redistribution.
22124f4c82Sjruoho * 3. Neither the names of the above-listed copyright holders nor the names
23124f4c82Sjruoho * of any contributors may be used to endorse or promote products derived
24124f4c82Sjruoho * from this software without specific prior written permission.
2528c506b8Sjruoho *
26124f4c82Sjruoho * Alternatively, this software may be distributed under the terms of the
27124f4c82Sjruoho * GNU General Public License ("GPL") version 2 as published by the Free
28124f4c82Sjruoho * Software Foundation.
2928c506b8Sjruoho *
30124f4c82Sjruoho * NO WARRANTY
31124f4c82Sjruoho * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32124f4c82Sjruoho * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3398244dcfSchristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34124f4c82Sjruoho * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35124f4c82Sjruoho * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36124f4c82Sjruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37124f4c82Sjruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38124f4c82Sjruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39124f4c82Sjruoho * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40124f4c82Sjruoho * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41124f4c82Sjruoho * POSSIBILITY OF SUCH DAMAGES.
42124f4c82Sjruoho */
4328c506b8Sjruoho
4428c506b8Sjruoho #include "aslcompiler.h"
4528c506b8Sjruoho #include "aslcompiler.y.h"
4628c506b8Sjruoho #include "amlcode.h"
4728c506b8Sjruoho
4828c506b8Sjruoho #define _COMPONENT ACPI_COMPILER
4928c506b8Sjruoho ACPI_MODULE_NAME ("aslopcodes")
5028c506b8Sjruoho
5128c506b8Sjruoho
5228c506b8Sjruoho /* Local prototypes */
5328c506b8Sjruoho
5428c506b8Sjruoho static void
5528c506b8Sjruoho OpcDoAccessAs (
5628c506b8Sjruoho ACPI_PARSE_OBJECT *Op);
5728c506b8Sjruoho
5828c506b8Sjruoho static void
59ff4a156dSchristos OpcDoConnection (
60ff4a156dSchristos ACPI_PARSE_OBJECT *Op);
61ff4a156dSchristos
62ff4a156dSchristos static void
6328c506b8Sjruoho OpcDoUnicode (
6428c506b8Sjruoho ACPI_PARSE_OBJECT *Op);
6528c506b8Sjruoho
6628c506b8Sjruoho static void
6728c506b8Sjruoho OpcDoEisaId (
6828c506b8Sjruoho ACPI_PARSE_OBJECT *Op);
6928c506b8Sjruoho
7028c506b8Sjruoho static void
7128c506b8Sjruoho OpcDoUuId (
7228c506b8Sjruoho ACPI_PARSE_OBJECT *Op);
7328c506b8Sjruoho
7428c506b8Sjruoho
7528c506b8Sjruoho /*******************************************************************************
7628c506b8Sjruoho *
7728c506b8Sjruoho * FUNCTION: OpcAmlOpcodeUpdateWalk
7828c506b8Sjruoho *
7928c506b8Sjruoho * PARAMETERS: ASL_WALK_CALLBACK
8028c506b8Sjruoho *
8128c506b8Sjruoho * RETURN: Status
8228c506b8Sjruoho *
8328c506b8Sjruoho * DESCRIPTION: Opcode update walk, ascending callback
8428c506b8Sjruoho *
8528c506b8Sjruoho ******************************************************************************/
8628c506b8Sjruoho
8728c506b8Sjruoho ACPI_STATUS
OpcAmlOpcodeUpdateWalk(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)8828c506b8Sjruoho OpcAmlOpcodeUpdateWalk (
8928c506b8Sjruoho ACPI_PARSE_OBJECT *Op,
9028c506b8Sjruoho UINT32 Level,
9128c506b8Sjruoho void *Context)
9228c506b8Sjruoho {
9328c506b8Sjruoho
9428c506b8Sjruoho /*
9528c506b8Sjruoho * Handle the Package() case where the actual opcode cannot be determined
9628c506b8Sjruoho * until the PackageLength operand has been folded and minimized.
9728c506b8Sjruoho * (PackageOp versus VarPackageOp)
9828c506b8Sjruoho *
9928c506b8Sjruoho * This is (as of ACPI 3.0) the only case where the AML opcode can change
10028c506b8Sjruoho * based upon the value of a parameter.
10128c506b8Sjruoho *
10228c506b8Sjruoho * The parser always inserts a VarPackage opcode, which can possibly be
10328c506b8Sjruoho * optimized to a Package opcode.
10428c506b8Sjruoho */
10528c506b8Sjruoho if (Op->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)
10628c506b8Sjruoho {
10728c506b8Sjruoho OpnDoPackage (Op);
10828c506b8Sjruoho }
10928c506b8Sjruoho
11028c506b8Sjruoho return (AE_OK);
11128c506b8Sjruoho }
11228c506b8Sjruoho
11328c506b8Sjruoho
11428c506b8Sjruoho /*******************************************************************************
11528c506b8Sjruoho *
11628c506b8Sjruoho * FUNCTION: OpcAmlOpcodeWalk
11728c506b8Sjruoho *
11828c506b8Sjruoho * PARAMETERS: ASL_WALK_CALLBACK
11928c506b8Sjruoho *
12028c506b8Sjruoho * RETURN: Status
12128c506b8Sjruoho *
12228c506b8Sjruoho * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML
12328c506b8Sjruoho * operands.
12428c506b8Sjruoho *
12528c506b8Sjruoho ******************************************************************************/
12628c506b8Sjruoho
12728c506b8Sjruoho ACPI_STATUS
OpcAmlOpcodeWalk(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)12828c506b8Sjruoho OpcAmlOpcodeWalk (
12928c506b8Sjruoho ACPI_PARSE_OBJECT *Op,
13028c506b8Sjruoho UINT32 Level,
13128c506b8Sjruoho void *Context)
13228c506b8Sjruoho {
13328c506b8Sjruoho
1347efa3256Schristos AslGbl_TotalParseNodes++;
13528c506b8Sjruoho
13628c506b8Sjruoho OpcGenerateAmlOpcode (Op);
13728c506b8Sjruoho OpnGenerateAmlOperands (Op);
13828c506b8Sjruoho return (AE_OK);
13928c506b8Sjruoho }
14028c506b8Sjruoho
14128c506b8Sjruoho
14228c506b8Sjruoho /*******************************************************************************
14328c506b8Sjruoho *
14428c506b8Sjruoho * FUNCTION: OpcGetIntegerWidth
14528c506b8Sjruoho *
14628c506b8Sjruoho * PARAMETERS: Op - DEFINITION BLOCK op
14728c506b8Sjruoho *
14828c506b8Sjruoho * RETURN: none
14928c506b8Sjruoho *
15028c506b8Sjruoho * DESCRIPTION: Extract integer width from the table revision
15128c506b8Sjruoho *
15228c506b8Sjruoho ******************************************************************************/
15328c506b8Sjruoho
15428c506b8Sjruoho void
OpcGetIntegerWidth(ACPI_PARSE_OBJECT * Op)15528c506b8Sjruoho OpcGetIntegerWidth (
15628c506b8Sjruoho ACPI_PARSE_OBJECT *Op)
15728c506b8Sjruoho {
15828c506b8Sjruoho ACPI_PARSE_OBJECT *Child;
15928c506b8Sjruoho
16028c506b8Sjruoho
16128c506b8Sjruoho if (!Op)
16228c506b8Sjruoho {
16328c506b8Sjruoho return;
16428c506b8Sjruoho }
16528c506b8Sjruoho
1667efa3256Schristos if (AslGbl_RevisionOverride)
16728c506b8Sjruoho {
1687efa3256Schristos AcpiUtSetIntegerWidth (AslGbl_RevisionOverride);
16928c506b8Sjruoho }
17028c506b8Sjruoho else
17128c506b8Sjruoho {
17228c506b8Sjruoho Child = Op->Asl.Child;
17328c506b8Sjruoho Child = Child->Asl.Next;
17428c506b8Sjruoho Child = Child->Asl.Next;
17528c506b8Sjruoho
17628c506b8Sjruoho /* Use the revision to set the integer width */
17728c506b8Sjruoho
17828c506b8Sjruoho AcpiUtSetIntegerWidth ((UINT8) Child->Asl.Value.Integer);
17928c506b8Sjruoho }
18028c506b8Sjruoho }
18128c506b8Sjruoho
18228c506b8Sjruoho
18328c506b8Sjruoho /*******************************************************************************
18428c506b8Sjruoho *
18528c506b8Sjruoho * FUNCTION: OpcSetOptimalIntegerSize
18628c506b8Sjruoho *
18728c506b8Sjruoho * PARAMETERS: Op - A parse tree node
18828c506b8Sjruoho *
18928c506b8Sjruoho * RETURN: Integer width, in bytes. Also sets the node AML opcode to the
19028c506b8Sjruoho * optimal integer AML prefix opcode.
19128c506b8Sjruoho *
19228c506b8Sjruoho * DESCRIPTION: Determine the optimal AML encoding of an integer. All leading
19328c506b8Sjruoho * zeros can be truncated to squeeze the integer into the
19428c506b8Sjruoho * minimal number of AML bytes.
19528c506b8Sjruoho *
19628c506b8Sjruoho ******************************************************************************/
19728c506b8Sjruoho
19828c506b8Sjruoho UINT32
OpcSetOptimalIntegerSize(ACPI_PARSE_OBJECT * Op)19928c506b8Sjruoho OpcSetOptimalIntegerSize (
20028c506b8Sjruoho ACPI_PARSE_OBJECT *Op)
20128c506b8Sjruoho {
20228c506b8Sjruoho
20328c506b8Sjruoho #if 0
20428c506b8Sjruoho /*
20528c506b8Sjruoho * TBD: - we don't want to optimize integers in the block header, but the
20628c506b8Sjruoho * code below does not work correctly.
20728c506b8Sjruoho */
20828c506b8Sjruoho if (Op->Asl.Parent &&
20928c506b8Sjruoho Op->Asl.Parent->Asl.Parent &&
21081bd9c9cSchristos (Op->Asl.Parent->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK))
21128c506b8Sjruoho {
212ff4a156dSchristos return (0);
21328c506b8Sjruoho }
21428c506b8Sjruoho #endif
21528c506b8Sjruoho
21628c506b8Sjruoho /*
21728c506b8Sjruoho * Check for the special AML integers first - Zero, One, Ones.
21828c506b8Sjruoho * These are single-byte opcodes that are the smallest possible
21928c506b8Sjruoho * representation of an integer.
22028c506b8Sjruoho *
22128c506b8Sjruoho * This optimization is optional.
22228c506b8Sjruoho */
2237efa3256Schristos if (AslGbl_IntegerOptimizationFlag)
22428c506b8Sjruoho {
22528c506b8Sjruoho switch (Op->Asl.Value.Integer)
22628c506b8Sjruoho {
22728c506b8Sjruoho case 0:
22828c506b8Sjruoho
22928c506b8Sjruoho Op->Asl.AmlOpcode = AML_ZERO_OP;
23028c506b8Sjruoho AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
23128c506b8Sjruoho Op, "Zero");
232ff4a156dSchristos return (1);
23328c506b8Sjruoho
23428c506b8Sjruoho case 1:
23528c506b8Sjruoho
23628c506b8Sjruoho Op->Asl.AmlOpcode = AML_ONE_OP;
23728c506b8Sjruoho AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
23828c506b8Sjruoho Op, "One");
239ff4a156dSchristos return (1);
24028c506b8Sjruoho
24128c506b8Sjruoho case ACPI_UINT32_MAX:
24228c506b8Sjruoho
24328c506b8Sjruoho /* Check for table integer width (32 or 64) */
24428c506b8Sjruoho
24528c506b8Sjruoho if (AcpiGbl_IntegerByteWidth == 4)
24628c506b8Sjruoho {
24728c506b8Sjruoho Op->Asl.AmlOpcode = AML_ONES_OP;
24828c506b8Sjruoho AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
24928c506b8Sjruoho Op, "Ones");
250ff4a156dSchristos return (1);
25128c506b8Sjruoho }
25228c506b8Sjruoho break;
25328c506b8Sjruoho
25428c506b8Sjruoho case ACPI_UINT64_MAX:
25528c506b8Sjruoho
25628c506b8Sjruoho /* Check for table integer width (32 or 64) */
25728c506b8Sjruoho
25828c506b8Sjruoho if (AcpiGbl_IntegerByteWidth == 8)
25928c506b8Sjruoho {
26028c506b8Sjruoho Op->Asl.AmlOpcode = AML_ONES_OP;
26128c506b8Sjruoho AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
26228c506b8Sjruoho Op, "Ones");
263ff4a156dSchristos return (1);
26428c506b8Sjruoho }
26528c506b8Sjruoho break;
26628c506b8Sjruoho
26728c506b8Sjruoho default:
268ff4a156dSchristos
26928c506b8Sjruoho break;
27028c506b8Sjruoho }
27128c506b8Sjruoho }
27228c506b8Sjruoho
27328c506b8Sjruoho /* Find the best fit using the various AML integer prefixes */
27428c506b8Sjruoho
27528c506b8Sjruoho if (Op->Asl.Value.Integer <= ACPI_UINT8_MAX)
27628c506b8Sjruoho {
27728c506b8Sjruoho Op->Asl.AmlOpcode = AML_BYTE_OP;
278ff4a156dSchristos return (1);
27928c506b8Sjruoho }
28081bd9c9cSchristos
28128c506b8Sjruoho if (Op->Asl.Value.Integer <= ACPI_UINT16_MAX)
28228c506b8Sjruoho {
28328c506b8Sjruoho Op->Asl.AmlOpcode = AML_WORD_OP;
284ff4a156dSchristos return (2);
28528c506b8Sjruoho }
28681bd9c9cSchristos
28728c506b8Sjruoho if (Op->Asl.Value.Integer <= ACPI_UINT32_MAX)
28828c506b8Sjruoho {
28928c506b8Sjruoho Op->Asl.AmlOpcode = AML_DWORD_OP;
290ff4a156dSchristos return (4);
29128c506b8Sjruoho }
292660602a8Schristos else /* 64-bit integer */
29328c506b8Sjruoho {
29428c506b8Sjruoho if (AcpiGbl_IntegerByteWidth == 4)
29528c506b8Sjruoho {
29628c506b8Sjruoho AslError (ASL_WARNING, ASL_MSG_INTEGER_LENGTH,
29728c506b8Sjruoho Op, NULL);
29828c506b8Sjruoho
2997efa3256Schristos if (!AslGbl_IgnoreErrors)
30028c506b8Sjruoho {
30128c506b8Sjruoho /* Truncate the integer to 32-bit */
302660602a8Schristos
303660602a8Schristos Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
304660602a8Schristos
305660602a8Schristos /* Now set the optimal integer size */
306660602a8Schristos
307660602a8Schristos return (OpcSetOptimalIntegerSize (Op));
30828c506b8Sjruoho }
30928c506b8Sjruoho }
31028c506b8Sjruoho
31128c506b8Sjruoho Op->Asl.AmlOpcode = AML_QWORD_OP;
312ff4a156dSchristos return (8);
31328c506b8Sjruoho }
31428c506b8Sjruoho }
31528c506b8Sjruoho
31628c506b8Sjruoho
31728c506b8Sjruoho /*******************************************************************************
31828c506b8Sjruoho *
31928c506b8Sjruoho * FUNCTION: OpcDoAccessAs
32028c506b8Sjruoho *
32128c506b8Sjruoho * PARAMETERS: Op - Parse node
32228c506b8Sjruoho *
32328c506b8Sjruoho * RETURN: None
32428c506b8Sjruoho *
32528c506b8Sjruoho * DESCRIPTION: Implement the ACCESS_AS ASL keyword.
32628c506b8Sjruoho *
32728c506b8Sjruoho ******************************************************************************/
32828c506b8Sjruoho
32928c506b8Sjruoho static void
OpcDoAccessAs(ACPI_PARSE_OBJECT * Op)33028c506b8Sjruoho OpcDoAccessAs (
33128c506b8Sjruoho ACPI_PARSE_OBJECT *Op)
33228c506b8Sjruoho {
333ff4a156dSchristos ACPI_PARSE_OBJECT *TypeOp;
334ff4a156dSchristos ACPI_PARSE_OBJECT *AttribOp;
335ff4a156dSchristos ACPI_PARSE_OBJECT *LengthOp;
336ff4a156dSchristos UINT8 Attribute;
33728c506b8Sjruoho
33828c506b8Sjruoho
33928c506b8Sjruoho Op->Asl.AmlOpcodeLength = 1;
340ff4a156dSchristos TypeOp = Op->Asl.Child;
34128c506b8Sjruoho
34228c506b8Sjruoho /* First child is the access type */
34328c506b8Sjruoho
344ff4a156dSchristos TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
345ff4a156dSchristos TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
34628c506b8Sjruoho
34728c506b8Sjruoho /* Second child is the optional access attribute */
34828c506b8Sjruoho
349ff4a156dSchristos AttribOp = TypeOp->Asl.Next;
350ff4a156dSchristos if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
35128c506b8Sjruoho {
352ff4a156dSchristos AttribOp->Asl.Value.Integer = 0;
35328c506b8Sjruoho }
35481bd9c9cSchristos
355ff4a156dSchristos AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
356ff4a156dSchristos AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
357ff4a156dSchristos
358ff4a156dSchristos /* Only a few AccessAttributes support AccessLength */
359ff4a156dSchristos
360ff4a156dSchristos Attribute = (UINT8) AttribOp->Asl.Value.Integer;
3617efa3256Schristos if ((Attribute != AML_FIELD_ATTRIB_BYTES) &&
362ff4a156dSchristos (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) &&
3637efa3256Schristos (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS_BYTES))
364ff4a156dSchristos {
365ff4a156dSchristos return;
366ff4a156dSchristos }
367ff4a156dSchristos
368ff4a156dSchristos Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP;
369ff4a156dSchristos
370ff4a156dSchristos /*
371ff4a156dSchristos * Child of Attributes is the AccessLength (required for Multibyte,
372ff4a156dSchristos * RawBytes, RawProcess.)
373ff4a156dSchristos */
374ff4a156dSchristos LengthOp = AttribOp->Asl.Child;
375ff4a156dSchristos if (!LengthOp)
376ff4a156dSchristos {
377ff4a156dSchristos return;
378ff4a156dSchristos }
379ff4a156dSchristos
380ff4a156dSchristos /* TBD: probably can remove */
381ff4a156dSchristos
382ff4a156dSchristos if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
383ff4a156dSchristos {
384ff4a156dSchristos LengthOp->Asl.Value.Integer = 16;
385ff4a156dSchristos }
386ff4a156dSchristos
387ff4a156dSchristos LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
388ff4a156dSchristos LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
389ff4a156dSchristos }
390ff4a156dSchristos
391ff4a156dSchristos
392ff4a156dSchristos /*******************************************************************************
393ff4a156dSchristos *
394ff4a156dSchristos * FUNCTION: OpcDoConnection
395ff4a156dSchristos *
396ff4a156dSchristos * PARAMETERS: Op - Parse node
397ff4a156dSchristos *
398ff4a156dSchristos * RETURN: None
399ff4a156dSchristos *
400ff4a156dSchristos * DESCRIPTION: Implement the Connection ASL keyword.
401ff4a156dSchristos *
402ff4a156dSchristos ******************************************************************************/
403ff4a156dSchristos
404ff4a156dSchristos static void
OpcDoConnection(ACPI_PARSE_OBJECT * Op)405ff4a156dSchristos OpcDoConnection (
406ff4a156dSchristos ACPI_PARSE_OBJECT *Op)
407ff4a156dSchristos {
408ff4a156dSchristos ASL_RESOURCE_NODE *Rnode;
409ff4a156dSchristos ACPI_PARSE_OBJECT *BufferOp;
410ff4a156dSchristos ACPI_PARSE_OBJECT *BufferLengthOp;
411ff4a156dSchristos ACPI_PARSE_OBJECT *BufferDataOp;
412460301d4Schristos ASL_RESOURCE_INFO Info;
413ff4a156dSchristos UINT8 State;
414ff4a156dSchristos
415ff4a156dSchristos
416ff4a156dSchristos Op->Asl.AmlOpcodeLength = 1;
417ff4a156dSchristos
418ff4a156dSchristos if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)
419ff4a156dSchristos {
420ff4a156dSchristos return;
421ff4a156dSchristos }
422ff4a156dSchristos
423ff4a156dSchristos BufferOp = Op->Asl.Child;
424ff4a156dSchristos BufferLengthOp = BufferOp->Asl.Child;
425ff4a156dSchristos BufferDataOp = BufferLengthOp->Asl.Next;
426ff4a156dSchristos
427460301d4Schristos Info.DescriptorTypeOp = BufferDataOp->Asl.Next;
428460301d4Schristos Info.CurrentByteOffset = 0;
429ff4a156dSchristos State = ACPI_RSTATE_NORMAL;
430460301d4Schristos Rnode = RsDoOneResourceDescriptor (&Info, &State);
431ff4a156dSchristos if (!Rnode)
432ff4a156dSchristos {
433ff4a156dSchristos return; /* error */
434ff4a156dSchristos }
435ff4a156dSchristos
436ff4a156dSchristos /*
437ff4a156dSchristos * Transform the nodes into the following
438ff4a156dSchristos *
439ff4a156dSchristos * Op -> AML_BUFFER_OP
440ff4a156dSchristos * First Child -> BufferLength
441ff4a156dSchristos * Second Child -> Descriptor Buffer (raw byte data)
442ff4a156dSchristos */
443ff4a156dSchristos BufferOp->Asl.ParseOpcode = PARSEOP_BUFFER;
444ff4a156dSchristos BufferOp->Asl.AmlOpcode = AML_BUFFER_OP;
445ae01dbf5Schristos BufferOp->Asl.CompileFlags = OP_AML_PACKAGE | OP_IS_RESOURCE_DESC;
446ff4a156dSchristos UtSetParseOpName (BufferOp);
447ff4a156dSchristos
448ff4a156dSchristos BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
449ff4a156dSchristos BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength;
450ff4a156dSchristos (void) OpcSetOptimalIntegerSize (BufferLengthOp);
451ff4a156dSchristos UtSetParseOpName (BufferLengthOp);
452ff4a156dSchristos
453ff4a156dSchristos BufferDataOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
454ff4a156dSchristos BufferDataOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN;
455ff4a156dSchristos BufferDataOp->Asl.AmlOpcodeLength = 0;
456ff4a156dSchristos BufferDataOp->Asl.AmlLength = Rnode->BufferLength;
457ff4a156dSchristos BufferDataOp->Asl.Value.Buffer = (UINT8 *) Rnode;
458ff4a156dSchristos UtSetParseOpName (BufferDataOp);
45928c506b8Sjruoho }
46028c506b8Sjruoho
46128c506b8Sjruoho
46228c506b8Sjruoho /*******************************************************************************
46328c506b8Sjruoho *
46428c506b8Sjruoho * FUNCTION: OpcDoUnicode
46528c506b8Sjruoho *
46628c506b8Sjruoho * PARAMETERS: Op - Parse node
46728c506b8Sjruoho *
46828c506b8Sjruoho * RETURN: None
46928c506b8Sjruoho *
47028c506b8Sjruoho * DESCRIPTION: Implement the UNICODE ASL "macro". Convert the input string
47128c506b8Sjruoho * to a unicode buffer. There is no Unicode AML opcode.
47228c506b8Sjruoho *
47328c506b8Sjruoho * Note: The Unicode string is 16 bits per character, no leading signature,
47428c506b8Sjruoho * with a 16-bit terminating NULL.
47528c506b8Sjruoho *
47628c506b8Sjruoho ******************************************************************************/
47728c506b8Sjruoho
47828c506b8Sjruoho static void
OpcDoUnicode(ACPI_PARSE_OBJECT * Op)47928c506b8Sjruoho OpcDoUnicode (
48028c506b8Sjruoho ACPI_PARSE_OBJECT *Op)
48128c506b8Sjruoho {
48228c506b8Sjruoho ACPI_PARSE_OBJECT *InitializerOp;
48328c506b8Sjruoho UINT32 Length;
48428c506b8Sjruoho UINT32 Count;
48528c506b8Sjruoho UINT32 i;
48628c506b8Sjruoho UINT8 *AsciiString;
48728c506b8Sjruoho UINT16 *UnicodeString;
48828c506b8Sjruoho ACPI_PARSE_OBJECT *BufferLengthOp;
48928c506b8Sjruoho
49028c506b8Sjruoho
49128c506b8Sjruoho /* Change op into a buffer object */
49228c506b8Sjruoho
493ae01dbf5Schristos Op->Asl.CompileFlags &= ~OP_COMPILE_TIME_CONST;
49428c506b8Sjruoho Op->Asl.ParseOpcode = PARSEOP_BUFFER;
49528c506b8Sjruoho UtSetParseOpName (Op);
49628c506b8Sjruoho
49728c506b8Sjruoho /* Buffer Length is first, followed by the string */
49828c506b8Sjruoho
49928c506b8Sjruoho BufferLengthOp = Op->Asl.Child;
50028c506b8Sjruoho InitializerOp = BufferLengthOp->Asl.Next;
50128c506b8Sjruoho
50228c506b8Sjruoho AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;
50328c506b8Sjruoho
50428c506b8Sjruoho /* Create a new buffer for the Unicode string */
50528c506b8Sjruoho
50628c506b8Sjruoho Count = strlen (InitializerOp->Asl.Value.String) + 1;
50728c506b8Sjruoho Length = Count * sizeof (UINT16);
50828c506b8Sjruoho UnicodeString = UtLocalCalloc (Length);
50928c506b8Sjruoho
51028c506b8Sjruoho /* Convert to Unicode string (including null terminator) */
51128c506b8Sjruoho
51228c506b8Sjruoho for (i = 0; i < Count; i++)
51328c506b8Sjruoho {
51428c506b8Sjruoho UnicodeString[i] = (UINT16) AsciiString[i];
51528c506b8Sjruoho }
51628c506b8Sjruoho
51728c506b8Sjruoho /*
51828c506b8Sjruoho * Just set the buffer size node to be the buffer length, regardless
51928c506b8Sjruoho * of whether it was previously an integer or a default_arg placeholder
52028c506b8Sjruoho */
52128c506b8Sjruoho BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
52228c506b8Sjruoho BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
52328c506b8Sjruoho BufferLengthOp->Asl.Value.Integer = Length;
52428c506b8Sjruoho UtSetParseOpName (BufferLengthOp);
52528c506b8Sjruoho
52628c506b8Sjruoho (void) OpcSetOptimalIntegerSize (BufferLengthOp);
52728c506b8Sjruoho
52828c506b8Sjruoho /* The Unicode string is a raw data buffer */
52928c506b8Sjruoho
53028c506b8Sjruoho InitializerOp->Asl.Value.Buffer = (UINT8 *) UnicodeString;
53128c506b8Sjruoho InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
53228c506b8Sjruoho InitializerOp->Asl.AmlLength = Length;
53328c506b8Sjruoho InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
53428c506b8Sjruoho InitializerOp->Asl.Child = NULL;
53528c506b8Sjruoho UtSetParseOpName (InitializerOp);
53628c506b8Sjruoho }
53728c506b8Sjruoho
53828c506b8Sjruoho
53928c506b8Sjruoho /*******************************************************************************
54028c506b8Sjruoho *
54128c506b8Sjruoho * FUNCTION: OpcDoEisaId
54228c506b8Sjruoho *
54328c506b8Sjruoho * PARAMETERS: Op - Parse node
54428c506b8Sjruoho *
54528c506b8Sjruoho * RETURN: None
54628c506b8Sjruoho *
54728c506b8Sjruoho * DESCRIPTION: Convert a string EISA ID to numeric representation. See the
54828c506b8Sjruoho * Pnp BIOS Specification for details. Here is an excerpt:
54928c506b8Sjruoho *
55028c506b8Sjruoho * A seven character ASCII representation of the product
55128c506b8Sjruoho * identifier compressed into a 32-bit identifier. The seven
55228c506b8Sjruoho * character ID consists of a three character manufacturer code,
55328c506b8Sjruoho * a three character hexadecimal product identifier, and a one
55428c506b8Sjruoho * character hexadecimal revision number. The manufacturer code
55528c506b8Sjruoho * is a 3 uppercase character code that is compressed into 3 5-bit
55628c506b8Sjruoho * values as follows:
55728c506b8Sjruoho * 1) Find hex ASCII value for each letter
55828c506b8Sjruoho * 2) Subtract 40h from each ASCII value
559ff4a156dSchristos * 3) Retain 5 least significant bits for each letter by
56028c506b8Sjruoho * discarding upper 3 bits because they are always 0.
56128c506b8Sjruoho * 4) Compressed code = concatenate 0 and the 3 5-bit values
56228c506b8Sjruoho *
56328c506b8Sjruoho * The format of the compressed product identifier is as follows:
56428c506b8Sjruoho * Byte 0: Bit 7 - Reserved (0)
56528c506b8Sjruoho * Bits 6-2: - 1st character of compressed mfg code
56628c506b8Sjruoho * Bits 1-0 - Upper 2 bits of 2nd character of mfg code
56728c506b8Sjruoho * Byte 1: Bits 7-5 - Lower 3 bits of 2nd character of mfg code
56828c506b8Sjruoho * Bits 4-0 - 3rd character of mfg code
56928c506b8Sjruoho * Byte 2: Bits 7-4 - 1st hex digit of product number
57028c506b8Sjruoho * Bits 3-0 - 2nd hex digit of product number
57198244dcfSchristos * Byte 3: Bits 7-4 - 3rd hex digit of product number
57228c506b8Sjruoho * Bits 3-0 - Hex digit of the revision number
57328c506b8Sjruoho *
57428c506b8Sjruoho ******************************************************************************/
57528c506b8Sjruoho
57628c506b8Sjruoho static void
OpcDoEisaId(ACPI_PARSE_OBJECT * Op)57728c506b8Sjruoho OpcDoEisaId (
57828c506b8Sjruoho ACPI_PARSE_OBJECT *Op)
57928c506b8Sjruoho {
58028c506b8Sjruoho UINT32 EisaId = 0;
58128c506b8Sjruoho UINT32 BigEndianId;
58228c506b8Sjruoho char *InString;
58328c506b8Sjruoho ACPI_STATUS Status = AE_OK;
58428c506b8Sjruoho UINT32 i;
58528c506b8Sjruoho
58628c506b8Sjruoho
58728c506b8Sjruoho InString = (char *) Op->Asl.Value.String;
58828c506b8Sjruoho
58928c506b8Sjruoho /*
59028c506b8Sjruoho * The EISAID string must be exactly 7 characters and of the form
59128c506b8Sjruoho * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
59228c506b8Sjruoho */
5939b9ee194Schristos if (strlen (InString) != 7)
59428c506b8Sjruoho {
59528c506b8Sjruoho Status = AE_BAD_PARAMETER;
59628c506b8Sjruoho }
59728c506b8Sjruoho else
59828c506b8Sjruoho {
59928c506b8Sjruoho /* Check all 7 characters for correct format */
60028c506b8Sjruoho
60128c506b8Sjruoho for (i = 0; i < 7; i++)
60228c506b8Sjruoho {
60328c506b8Sjruoho /* First 3 characters must be uppercase letters */
60428c506b8Sjruoho
60528c506b8Sjruoho if (i < 3)
60628c506b8Sjruoho {
60728c506b8Sjruoho if (!isupper ((int) InString[i]))
60828c506b8Sjruoho {
60928c506b8Sjruoho Status = AE_BAD_PARAMETER;
61028c506b8Sjruoho }
61128c506b8Sjruoho }
61228c506b8Sjruoho
61328c506b8Sjruoho /* Last 4 characters must be hex digits */
61428c506b8Sjruoho
61528c506b8Sjruoho else if (!isxdigit ((int) InString[i]))
61628c506b8Sjruoho {
61728c506b8Sjruoho Status = AE_BAD_PARAMETER;
61828c506b8Sjruoho }
61928c506b8Sjruoho }
62028c506b8Sjruoho }
62128c506b8Sjruoho
62228c506b8Sjruoho if (ACPI_FAILURE (Status))
62328c506b8Sjruoho {
62428c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
62528c506b8Sjruoho }
62628c506b8Sjruoho else
62728c506b8Sjruoho {
62828c506b8Sjruoho /* Create ID big-endian first (bits are contiguous) */
62928c506b8Sjruoho
63028c506b8Sjruoho BigEndianId =
631124f4c82Sjruoho (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
632124f4c82Sjruoho (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
633124f4c82Sjruoho (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |
63428c506b8Sjruoho
635460301d4Schristos (AcpiUtAsciiCharToHex (InString[3])) << 12 |
636460301d4Schristos (AcpiUtAsciiCharToHex (InString[4])) << 8 |
637460301d4Schristos (AcpiUtAsciiCharToHex (InString[5])) << 4 |
638460301d4Schristos AcpiUtAsciiCharToHex (InString[6]);
63928c506b8Sjruoho
64028c506b8Sjruoho /* Swap to little-endian to get final ID (see function header) */
64128c506b8Sjruoho
64228c506b8Sjruoho EisaId = AcpiUtDwordByteSwap (BigEndianId);
64328c506b8Sjruoho }
64428c506b8Sjruoho
64528c506b8Sjruoho /*
64628c506b8Sjruoho * Morph the Op into an integer, regardless of whether there
64728c506b8Sjruoho * was an error in the EISAID string
64828c506b8Sjruoho */
64928c506b8Sjruoho Op->Asl.Value.Integer = EisaId;
65028c506b8Sjruoho
651ae01dbf5Schristos Op->Asl.CompileFlags &= ~OP_COMPILE_TIME_CONST;
65228c506b8Sjruoho Op->Asl.ParseOpcode = PARSEOP_INTEGER;
65328c506b8Sjruoho (void) OpcSetOptimalIntegerSize (Op);
65428c506b8Sjruoho
65528c506b8Sjruoho /* Op is now an integer */
65628c506b8Sjruoho
65728c506b8Sjruoho UtSetParseOpName (Op);
65828c506b8Sjruoho }
65928c506b8Sjruoho
66028c506b8Sjruoho
66128c506b8Sjruoho /*******************************************************************************
66228c506b8Sjruoho *
663ff4a156dSchristos * FUNCTION: OpcDoUuId
66428c506b8Sjruoho *
66528c506b8Sjruoho * PARAMETERS: Op - Parse node
66628c506b8Sjruoho *
66728c506b8Sjruoho * RETURN: None
66828c506b8Sjruoho *
66928c506b8Sjruoho * DESCRIPTION: Convert UUID string to 16-byte buffer
67028c506b8Sjruoho *
67128c506b8Sjruoho ******************************************************************************/
67228c506b8Sjruoho
67328c506b8Sjruoho static void
OpcDoUuId(ACPI_PARSE_OBJECT * Op)67428c506b8Sjruoho OpcDoUuId (
67528c506b8Sjruoho ACPI_PARSE_OBJECT *Op)
67628c506b8Sjruoho {
67728c506b8Sjruoho char *InString;
678460301d4Schristos UINT8 *Buffer;
67928c506b8Sjruoho ACPI_STATUS Status = AE_OK;
68028c506b8Sjruoho ACPI_PARSE_OBJECT *NewOp;
68128c506b8Sjruoho
68228c506b8Sjruoho
683679c17fdSchristos InString = ACPI_CAST_PTR (char, Op->Asl.Value.String);
68428c506b8Sjruoho Buffer = UtLocalCalloc (16);
68528c506b8Sjruoho
686124f4c82Sjruoho Status = AuValidateUuid (InString);
68728c506b8Sjruoho if (ACPI_FAILURE (Status))
68828c506b8Sjruoho {
68928c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
69028c506b8Sjruoho }
691124f4c82Sjruoho else
69228c506b8Sjruoho {
693b558e860Schristos /* Convert UUID string to a buffer, check for a known UUID */
694b558e860Schristos
695460301d4Schristos AcpiUtConvertStringToUuid (InString, Buffer);
696b558e860Schristos if (!AcpiAhMatchUuid (Buffer))
697b558e860Schristos {
698b558e860Schristos AslError (ASL_REMARK, ASL_MSG_UUID_NOT_FOUND, Op, NULL);
699b558e860Schristos }
70028c506b8Sjruoho }
70128c506b8Sjruoho
70228c506b8Sjruoho /* Change Op to a Buffer */
70328c506b8Sjruoho
70428c506b8Sjruoho Op->Asl.ParseOpcode = PARSEOP_BUFFER;
70528c506b8Sjruoho Op->Common.AmlOpcode = AML_BUFFER_OP;
70628c506b8Sjruoho
70728c506b8Sjruoho /* Disable further optimization */
70828c506b8Sjruoho
709ae01dbf5Schristos Op->Asl.CompileFlags &= ~OP_COMPILE_TIME_CONST;
71028c506b8Sjruoho UtSetParseOpName (Op);
71128c506b8Sjruoho
71228c506b8Sjruoho /* Child node is the buffer length */
71328c506b8Sjruoho
714ae01dbf5Schristos NewOp = TrAllocateOp (PARSEOP_INTEGER);
71528c506b8Sjruoho
71628c506b8Sjruoho NewOp->Asl.AmlOpcode = AML_BYTE_OP;
71728c506b8Sjruoho NewOp->Asl.Value.Integer = 16;
71828c506b8Sjruoho NewOp->Asl.Parent = Op;
71928c506b8Sjruoho
72028c506b8Sjruoho Op->Asl.Child = NewOp;
72128c506b8Sjruoho Op = NewOp;
72228c506b8Sjruoho
72328c506b8Sjruoho /* Peer to the child is the raw buffer data */
72428c506b8Sjruoho
725ae01dbf5Schristos NewOp = TrAllocateOp (PARSEOP_RAW_DATA);
72628c506b8Sjruoho NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
72728c506b8Sjruoho NewOp->Asl.AmlLength = 16;
728679c17fdSchristos NewOp->Asl.Value.String = ACPI_CAST_PTR (char, Buffer);
72928c506b8Sjruoho NewOp->Asl.Parent = Op->Asl.Parent;
73028c506b8Sjruoho
73128c506b8Sjruoho Op->Asl.Next = NewOp;
73228c506b8Sjruoho }
73328c506b8Sjruoho
73428c506b8Sjruoho
73528c506b8Sjruoho /*******************************************************************************
73628c506b8Sjruoho *
73728c506b8Sjruoho * FUNCTION: OpcGenerateAmlOpcode
73828c506b8Sjruoho *
73928c506b8Sjruoho * PARAMETERS: Op - Parse node
74028c506b8Sjruoho *
74128c506b8Sjruoho * RETURN: None
74228c506b8Sjruoho *
74328c506b8Sjruoho * DESCRIPTION: Generate the AML opcode associated with the node and its
74428c506b8Sjruoho * parse (lex/flex) keyword opcode. Essentially implements
74528c506b8Sjruoho * a mapping between the parse opcodes and the actual AML opcodes.
74628c506b8Sjruoho *
74728c506b8Sjruoho ******************************************************************************/
74828c506b8Sjruoho
74928c506b8Sjruoho void
OpcGenerateAmlOpcode(ACPI_PARSE_OBJECT * Op)75028c506b8Sjruoho OpcGenerateAmlOpcode (
75128c506b8Sjruoho ACPI_PARSE_OBJECT *Op)
75228c506b8Sjruoho {
75328c506b8Sjruoho UINT16 Index;
75428c506b8Sjruoho
75528c506b8Sjruoho
75628c506b8Sjruoho Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
75728c506b8Sjruoho
75828c506b8Sjruoho Op->Asl.AmlOpcode = AslKeywordMapping[Index].AmlOpcode;
75928c506b8Sjruoho Op->Asl.AcpiBtype = AslKeywordMapping[Index].AcpiBtype;
76028c506b8Sjruoho Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
76128c506b8Sjruoho
76228c506b8Sjruoho if (!Op->Asl.Value.Integer)
76328c506b8Sjruoho {
76428c506b8Sjruoho Op->Asl.Value.Integer = AslKeywordMapping[Index].Value;
76528c506b8Sjruoho }
76628c506b8Sjruoho
76728c506b8Sjruoho /* Special handling for some opcodes */
76828c506b8Sjruoho
76928c506b8Sjruoho switch (Op->Asl.ParseOpcode)
77028c506b8Sjruoho {
77128c506b8Sjruoho case PARSEOP_INTEGER:
77228c506b8Sjruoho /*
77328c506b8Sjruoho * Set the opcode based on the size of the integer
77428c506b8Sjruoho */
77528c506b8Sjruoho (void) OpcSetOptimalIntegerSize (Op);
77628c506b8Sjruoho break;
77728c506b8Sjruoho
77828c506b8Sjruoho case PARSEOP_OFFSET:
77928c506b8Sjruoho
78028c506b8Sjruoho Op->Asl.AmlOpcodeLength = 1;
78128c506b8Sjruoho break;
78228c506b8Sjruoho
78328c506b8Sjruoho case PARSEOP_ACCESSAS:
78428c506b8Sjruoho
78528c506b8Sjruoho OpcDoAccessAs (Op);
78628c506b8Sjruoho break;
78728c506b8Sjruoho
788ff4a156dSchristos case PARSEOP_CONNECTION:
789ff4a156dSchristos
790ff4a156dSchristos OpcDoConnection (Op);
791ff4a156dSchristos break;
792ff4a156dSchristos
79328c506b8Sjruoho case PARSEOP_EISAID:
79428c506b8Sjruoho
79528c506b8Sjruoho OpcDoEisaId (Op);
79628c506b8Sjruoho break;
79728c506b8Sjruoho
798679c17fdSchristos case PARSEOP_PRINTF:
799679c17fdSchristos
800679c17fdSchristos OpcDoPrintf (Op);
801679c17fdSchristos break;
802679c17fdSchristos
803679c17fdSchristos case PARSEOP_FPRINTF:
804679c17fdSchristos
805679c17fdSchristos OpcDoFprintf (Op);
806679c17fdSchristos break;
807679c17fdSchristos
808679c17fdSchristos case PARSEOP_TOPLD:
809679c17fdSchristos
810679c17fdSchristos OpcDoPld (Op);
811679c17fdSchristos break;
812679c17fdSchristos
81328c506b8Sjruoho case PARSEOP_TOUUID:
81428c506b8Sjruoho
81528c506b8Sjruoho OpcDoUuId (Op);
81628c506b8Sjruoho break;
81728c506b8Sjruoho
81828c506b8Sjruoho case PARSEOP_UNICODE:
81928c506b8Sjruoho
82028c506b8Sjruoho OpcDoUnicode (Op);
82128c506b8Sjruoho break;
82228c506b8Sjruoho
82328c506b8Sjruoho case PARSEOP_INCLUDE:
82428c506b8Sjruoho
8257efa3256Schristos AslGbl_HasIncludeFiles = TRUE;
82628c506b8Sjruoho break;
82728c506b8Sjruoho
828ff4a156dSchristos case PARSEOP_TIMER:
829ff4a156dSchristos
830ff4a156dSchristos if (AcpiGbl_IntegerBitWidth == 32)
831ff4a156dSchristos {
832ff4a156dSchristos AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
833ff4a156dSchristos }
834ff4a156dSchristos break;
835ff4a156dSchristos
83628c506b8Sjruoho default:
837ff4a156dSchristos
83828c506b8Sjruoho /* Nothing to do for other opcodes */
839ff4a156dSchristos
84028c506b8Sjruoho break;
84128c506b8Sjruoho }
84228c506b8Sjruoho
84328c506b8Sjruoho return;
84428c506b8Sjruoho }
845