1f8146b88SJung-uk Kim /****************************************************************************** 2f8146b88SJung-uk Kim * 3f8146b88SJung-uk Kim * Module Name: exconcat - Concatenate-type AML operators 4f8146b88SJung-uk Kim * 5f8146b88SJung-uk Kim *****************************************************************************/ 6f8146b88SJung-uk Kim 7f8146b88SJung-uk Kim /* 8f8146b88SJung-uk Kim * Copyright (C) 2000 - 2016, Intel Corp. 9f8146b88SJung-uk Kim * All rights reserved. 10f8146b88SJung-uk Kim * 11f8146b88SJung-uk Kim * Redistribution and use in source and binary forms, with or without 12f8146b88SJung-uk Kim * modification, are permitted provided that the following conditions 13f8146b88SJung-uk Kim * are met: 14f8146b88SJung-uk Kim * 1. Redistributions of source code must retain the above copyright 15f8146b88SJung-uk Kim * notice, this list of conditions, and the following disclaimer, 16f8146b88SJung-uk Kim * without modification. 17f8146b88SJung-uk Kim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18f8146b88SJung-uk Kim * substantially similar to the "NO WARRANTY" disclaimer below 19f8146b88SJung-uk Kim * ("Disclaimer") and any redistribution must be conditioned upon 20f8146b88SJung-uk Kim * including a substantially similar Disclaimer requirement for further 21f8146b88SJung-uk Kim * binary redistribution. 22f8146b88SJung-uk Kim * 3. Neither the names of the above-listed copyright holders nor the names 23f8146b88SJung-uk Kim * of any contributors may be used to endorse or promote products derived 24f8146b88SJung-uk Kim * from this software without specific prior written permission. 25f8146b88SJung-uk Kim * 26f8146b88SJung-uk Kim * Alternatively, this software may be distributed under the terms of the 27f8146b88SJung-uk Kim * GNU General Public License ("GPL") version 2 as published by the Free 28f8146b88SJung-uk Kim * Software Foundation. 29f8146b88SJung-uk Kim * 30f8146b88SJung-uk Kim * NO WARRANTY 31f8146b88SJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32f8146b88SJung-uk Kim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33f8146b88SJung-uk Kim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34f8146b88SJung-uk Kim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35f8146b88SJung-uk Kim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36f8146b88SJung-uk Kim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37f8146b88SJung-uk Kim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38f8146b88SJung-uk Kim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39f8146b88SJung-uk Kim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40f8146b88SJung-uk Kim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41f8146b88SJung-uk Kim * POSSIBILITY OF SUCH DAMAGES. 42f8146b88SJung-uk Kim */ 43f8146b88SJung-uk Kim 44f8146b88SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h> 45f8146b88SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h> 46f8146b88SJung-uk Kim #include <contrib/dev/acpica/include/acinterp.h> 47f8146b88SJung-uk Kim #include <contrib/dev/acpica/include/amlresrc.h> 48f8146b88SJung-uk Kim 49f8146b88SJung-uk Kim 50f8146b88SJung-uk Kim #define _COMPONENT ACPI_EXECUTER 51f8146b88SJung-uk Kim ACPI_MODULE_NAME ("exconcat") 52f8146b88SJung-uk Kim 53f8146b88SJung-uk Kim /* Local Prototypes */ 54f8146b88SJung-uk Kim 55f8146b88SJung-uk Kim static ACPI_STATUS 56f8146b88SJung-uk Kim AcpiExConvertToObjectTypeString ( 57f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc, 58f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT **ResultDesc); 59f8146b88SJung-uk Kim 60f8146b88SJung-uk Kim 61f8146b88SJung-uk Kim /******************************************************************************* 62f8146b88SJung-uk Kim * 63f8146b88SJung-uk Kim * FUNCTION: AcpiExDoConcatenate 64f8146b88SJung-uk Kim * 65f8146b88SJung-uk Kim * PARAMETERS: Operand0 - First source object 66f8146b88SJung-uk Kim * Operand1 - Second source object 67f8146b88SJung-uk Kim * ActualReturnDesc - Where to place the return object 68f8146b88SJung-uk Kim * WalkState - Current walk state 69f8146b88SJung-uk Kim * 70f8146b88SJung-uk Kim * RETURN: Status 71f8146b88SJung-uk Kim * 72f8146b88SJung-uk Kim * DESCRIPTION: Concatenate two objects with the ACPI-defined conversion 73f8146b88SJung-uk Kim * rules as necessary. 74f8146b88SJung-uk Kim * NOTE: 75f8146b88SJung-uk Kim * Per the ACPI spec (up to 6.1), Concatenate only supports Integer, 76f8146b88SJung-uk Kim * String, and Buffer objects. However, we support all objects here 77f8146b88SJung-uk Kim * as an extension. This improves the usefulness of both Concatenate 78f8146b88SJung-uk Kim * and the Printf/Fprintf macros. The extension returns a string 79f8146b88SJung-uk Kim * describing the object type for the other objects. 80f8146b88SJung-uk Kim * 02/2016. 81f8146b88SJung-uk Kim * 82f8146b88SJung-uk Kim ******************************************************************************/ 83f8146b88SJung-uk Kim 84f8146b88SJung-uk Kim ACPI_STATUS 85f8146b88SJung-uk Kim AcpiExDoConcatenate ( 86f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *Operand0, 87f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *Operand1, 88f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT **ActualReturnDesc, 89f8146b88SJung-uk Kim ACPI_WALK_STATE *WalkState) 90f8146b88SJung-uk Kim { 91f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *LocalOperand0 = Operand0; 92f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; 93f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *TempOperand1 = NULL; 94f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *ReturnDesc; 95f8146b88SJung-uk Kim char *Buffer; 96f8146b88SJung-uk Kim ACPI_OBJECT_TYPE Operand0Type; 97f8146b88SJung-uk Kim ACPI_OBJECT_TYPE Operand1Type; 98f8146b88SJung-uk Kim ACPI_STATUS Status; 99f8146b88SJung-uk Kim 100f8146b88SJung-uk Kim 101f8146b88SJung-uk Kim ACPI_FUNCTION_TRACE (ExDoConcatenate); 102f8146b88SJung-uk Kim 103f8146b88SJung-uk Kim 104f8146b88SJung-uk Kim /* Operand 0 preprocessing */ 105f8146b88SJung-uk Kim 106f8146b88SJung-uk Kim switch (Operand0->Common.Type) 107f8146b88SJung-uk Kim { 108f8146b88SJung-uk Kim case ACPI_TYPE_INTEGER: 109f8146b88SJung-uk Kim case ACPI_TYPE_STRING: 110f8146b88SJung-uk Kim case ACPI_TYPE_BUFFER: 111f8146b88SJung-uk Kim 112f8146b88SJung-uk Kim Operand0Type = Operand0->Common.Type; 113f8146b88SJung-uk Kim break; 114f8146b88SJung-uk Kim 115f8146b88SJung-uk Kim default: 116f8146b88SJung-uk Kim 117f8146b88SJung-uk Kim /* For all other types, get the "object type" string */ 118f8146b88SJung-uk Kim 119f8146b88SJung-uk Kim Status = AcpiExConvertToObjectTypeString ( 120f8146b88SJung-uk Kim Operand0, &LocalOperand0); 121f8146b88SJung-uk Kim if (ACPI_FAILURE (Status)) 122f8146b88SJung-uk Kim { 123f8146b88SJung-uk Kim goto Cleanup; 124f8146b88SJung-uk Kim } 125f8146b88SJung-uk Kim 126f8146b88SJung-uk Kim Operand0Type = ACPI_TYPE_STRING; 127f8146b88SJung-uk Kim break; 128f8146b88SJung-uk Kim } 129f8146b88SJung-uk Kim 130f8146b88SJung-uk Kim /* Operand 1 preprocessing */ 131f8146b88SJung-uk Kim 132f8146b88SJung-uk Kim switch (Operand1->Common.Type) 133f8146b88SJung-uk Kim { 134f8146b88SJung-uk Kim case ACPI_TYPE_INTEGER: 135f8146b88SJung-uk Kim case ACPI_TYPE_STRING: 136f8146b88SJung-uk Kim case ACPI_TYPE_BUFFER: 137f8146b88SJung-uk Kim 138f8146b88SJung-uk Kim Operand1Type = Operand1->Common.Type; 139f8146b88SJung-uk Kim break; 140f8146b88SJung-uk Kim 141f8146b88SJung-uk Kim default: 142f8146b88SJung-uk Kim 143f8146b88SJung-uk Kim /* For all other types, get the "object type" string */ 144f8146b88SJung-uk Kim 145f8146b88SJung-uk Kim Status = AcpiExConvertToObjectTypeString ( 146f8146b88SJung-uk Kim Operand1, &LocalOperand1); 147f8146b88SJung-uk Kim if (ACPI_FAILURE (Status)) 148f8146b88SJung-uk Kim { 149f8146b88SJung-uk Kim goto Cleanup; 150f8146b88SJung-uk Kim } 151f8146b88SJung-uk Kim 152f8146b88SJung-uk Kim Operand1Type = ACPI_TYPE_STRING; 153f8146b88SJung-uk Kim break; 154f8146b88SJung-uk Kim } 155f8146b88SJung-uk Kim 156f8146b88SJung-uk Kim /* 157f8146b88SJung-uk Kim * Convert the second operand if necessary. The first operand (0) 158f8146b88SJung-uk Kim * determines the type of the second operand (1) (See the Data Types 159f8146b88SJung-uk Kim * section of the ACPI specification). Both object types are 160f8146b88SJung-uk Kim * guaranteed to be either Integer/String/Buffer by the operand 161f8146b88SJung-uk Kim * resolution mechanism. 162f8146b88SJung-uk Kim */ 163f8146b88SJung-uk Kim switch (Operand0Type) 164f8146b88SJung-uk Kim { 165f8146b88SJung-uk Kim case ACPI_TYPE_INTEGER: 166f8146b88SJung-uk Kim 167*493deb39SJung-uk Kim Status = AcpiExConvertToInteger (LocalOperand1, &TempOperand1, 168*493deb39SJung-uk Kim ACPI_STRTOUL_BASE16); 169f8146b88SJung-uk Kim break; 170f8146b88SJung-uk Kim 171f8146b88SJung-uk Kim case ACPI_TYPE_BUFFER: 172f8146b88SJung-uk Kim 173f8146b88SJung-uk Kim Status = AcpiExConvertToBuffer (LocalOperand1, &TempOperand1); 174f8146b88SJung-uk Kim break; 175f8146b88SJung-uk Kim 176f8146b88SJung-uk Kim case ACPI_TYPE_STRING: 177f8146b88SJung-uk Kim 178f8146b88SJung-uk Kim switch (Operand1Type) 179f8146b88SJung-uk Kim { 180f8146b88SJung-uk Kim case ACPI_TYPE_INTEGER: 181f8146b88SJung-uk Kim case ACPI_TYPE_STRING: 182f8146b88SJung-uk Kim case ACPI_TYPE_BUFFER: 183f8146b88SJung-uk Kim 184f8146b88SJung-uk Kim /* Other types have already been converted to string */ 185f8146b88SJung-uk Kim 186f8146b88SJung-uk Kim Status = AcpiExConvertToString ( 187f8146b88SJung-uk Kim LocalOperand1, &TempOperand1, ACPI_IMPLICIT_CONVERT_HEX); 188f8146b88SJung-uk Kim break; 189f8146b88SJung-uk Kim 190f8146b88SJung-uk Kim default: 191f8146b88SJung-uk Kim 192f8146b88SJung-uk Kim Status = AE_OK; 193f8146b88SJung-uk Kim break; 194f8146b88SJung-uk Kim } 195f8146b88SJung-uk Kim break; 196f8146b88SJung-uk Kim 197f8146b88SJung-uk Kim default: 198f8146b88SJung-uk Kim 199f8146b88SJung-uk Kim ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", 200f8146b88SJung-uk Kim Operand0->Common.Type)); 201f8146b88SJung-uk Kim Status = AE_AML_INTERNAL; 202f8146b88SJung-uk Kim } 203f8146b88SJung-uk Kim 204f8146b88SJung-uk Kim if (ACPI_FAILURE (Status)) 205f8146b88SJung-uk Kim { 206f8146b88SJung-uk Kim goto Cleanup; 207f8146b88SJung-uk Kim } 208f8146b88SJung-uk Kim 209f8146b88SJung-uk Kim /* Take care with any newly created operand objects */ 210f8146b88SJung-uk Kim 211f8146b88SJung-uk Kim if ((LocalOperand1 != Operand1) && 212f8146b88SJung-uk Kim (LocalOperand1 != TempOperand1)) 213f8146b88SJung-uk Kim { 214f8146b88SJung-uk Kim AcpiUtRemoveReference (LocalOperand1); 215f8146b88SJung-uk Kim } 216f8146b88SJung-uk Kim 217f8146b88SJung-uk Kim LocalOperand1 = TempOperand1; 218f8146b88SJung-uk Kim 219f8146b88SJung-uk Kim /* 220f8146b88SJung-uk Kim * Both operands are now known to be the same object type 221f8146b88SJung-uk Kim * (Both are Integer, String, or Buffer), and we can now perform 222f8146b88SJung-uk Kim * the concatenation. 223f8146b88SJung-uk Kim * 224f8146b88SJung-uk Kim * There are three cases to handle, as per the ACPI spec: 225f8146b88SJung-uk Kim * 226f8146b88SJung-uk Kim * 1) Two Integers concatenated to produce a new Buffer 227f8146b88SJung-uk Kim * 2) Two Strings concatenated to produce a new String 228f8146b88SJung-uk Kim * 3) Two Buffers concatenated to produce a new Buffer 229f8146b88SJung-uk Kim */ 230f8146b88SJung-uk Kim switch (Operand0Type) 231f8146b88SJung-uk Kim { 232f8146b88SJung-uk Kim case ACPI_TYPE_INTEGER: 233f8146b88SJung-uk Kim 234f8146b88SJung-uk Kim /* Result of two Integers is a Buffer */ 235f8146b88SJung-uk Kim /* Need enough buffer space for two integers */ 236f8146b88SJung-uk Kim 237f8146b88SJung-uk Kim ReturnDesc = AcpiUtCreateBufferObject ( 238f8146b88SJung-uk Kim (ACPI_SIZE) ACPI_MUL_2 (AcpiGbl_IntegerByteWidth)); 239f8146b88SJung-uk Kim if (!ReturnDesc) 240f8146b88SJung-uk Kim { 241f8146b88SJung-uk Kim Status = AE_NO_MEMORY; 242f8146b88SJung-uk Kim goto Cleanup; 243f8146b88SJung-uk Kim } 244f8146b88SJung-uk Kim 245f8146b88SJung-uk Kim Buffer = (char *) ReturnDesc->Buffer.Pointer; 246f8146b88SJung-uk Kim 247f8146b88SJung-uk Kim /* Copy the first integer, LSB first */ 248f8146b88SJung-uk Kim 249f8146b88SJung-uk Kim memcpy (Buffer, &Operand0->Integer.Value, 250f8146b88SJung-uk Kim AcpiGbl_IntegerByteWidth); 251f8146b88SJung-uk Kim 252f8146b88SJung-uk Kim /* Copy the second integer (LSB first) after the first */ 253f8146b88SJung-uk Kim 254f8146b88SJung-uk Kim memcpy (Buffer + AcpiGbl_IntegerByteWidth, 255f8146b88SJung-uk Kim &LocalOperand1->Integer.Value, AcpiGbl_IntegerByteWidth); 256f8146b88SJung-uk Kim break; 257f8146b88SJung-uk Kim 258f8146b88SJung-uk Kim case ACPI_TYPE_STRING: 259f8146b88SJung-uk Kim 260f8146b88SJung-uk Kim /* Result of two Strings is a String */ 261f8146b88SJung-uk Kim 262f8146b88SJung-uk Kim ReturnDesc = AcpiUtCreateStringObject ( 263f8146b88SJung-uk Kim ((ACPI_SIZE) LocalOperand0->String.Length + 264f8146b88SJung-uk Kim LocalOperand1->String.Length)); 265f8146b88SJung-uk Kim if (!ReturnDesc) 266f8146b88SJung-uk Kim { 267f8146b88SJung-uk Kim Status = AE_NO_MEMORY; 268f8146b88SJung-uk Kim goto Cleanup; 269f8146b88SJung-uk Kim } 270f8146b88SJung-uk Kim 271f8146b88SJung-uk Kim Buffer = ReturnDesc->String.Pointer; 272f8146b88SJung-uk Kim 273f8146b88SJung-uk Kim /* Concatenate the strings */ 274f8146b88SJung-uk Kim 275f8146b88SJung-uk Kim strcpy (Buffer, LocalOperand0->String.Pointer); 276f8146b88SJung-uk Kim strcat (Buffer, LocalOperand1->String.Pointer); 277f8146b88SJung-uk Kim break; 278f8146b88SJung-uk Kim 279f8146b88SJung-uk Kim case ACPI_TYPE_BUFFER: 280f8146b88SJung-uk Kim 281f8146b88SJung-uk Kim /* Result of two Buffers is a Buffer */ 282f8146b88SJung-uk Kim 283f8146b88SJung-uk Kim ReturnDesc = AcpiUtCreateBufferObject ( 284f8146b88SJung-uk Kim ((ACPI_SIZE) Operand0->Buffer.Length + 285f8146b88SJung-uk Kim LocalOperand1->Buffer.Length)); 286f8146b88SJung-uk Kim if (!ReturnDesc) 287f8146b88SJung-uk Kim { 288f8146b88SJung-uk Kim Status = AE_NO_MEMORY; 289f8146b88SJung-uk Kim goto Cleanup; 290f8146b88SJung-uk Kim } 291f8146b88SJung-uk Kim 292f8146b88SJung-uk Kim Buffer = (char *) ReturnDesc->Buffer.Pointer; 293f8146b88SJung-uk Kim 294f8146b88SJung-uk Kim /* Concatenate the buffers */ 295f8146b88SJung-uk Kim 296f8146b88SJung-uk Kim memcpy (Buffer, Operand0->Buffer.Pointer, 297f8146b88SJung-uk Kim Operand0->Buffer.Length); 298f8146b88SJung-uk Kim memcpy (Buffer + Operand0->Buffer.Length, 299f8146b88SJung-uk Kim LocalOperand1->Buffer.Pointer, 300f8146b88SJung-uk Kim LocalOperand1->Buffer.Length); 301f8146b88SJung-uk Kim break; 302f8146b88SJung-uk Kim 303f8146b88SJung-uk Kim default: 304f8146b88SJung-uk Kim 305f8146b88SJung-uk Kim /* Invalid object type, should not happen here */ 306f8146b88SJung-uk Kim 307f8146b88SJung-uk Kim ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", 308f8146b88SJung-uk Kim Operand0->Common.Type)); 309f8146b88SJung-uk Kim Status = AE_AML_INTERNAL; 310f8146b88SJung-uk Kim goto Cleanup; 311f8146b88SJung-uk Kim } 312f8146b88SJung-uk Kim 313f8146b88SJung-uk Kim *ActualReturnDesc = ReturnDesc; 314f8146b88SJung-uk Kim 315f8146b88SJung-uk Kim Cleanup: 316f8146b88SJung-uk Kim if (LocalOperand0 != Operand0) 317f8146b88SJung-uk Kim { 318f8146b88SJung-uk Kim AcpiUtRemoveReference (LocalOperand0); 319f8146b88SJung-uk Kim } 320f8146b88SJung-uk Kim 321f8146b88SJung-uk Kim if (LocalOperand1 != Operand1) 322f8146b88SJung-uk Kim { 323f8146b88SJung-uk Kim AcpiUtRemoveReference (LocalOperand1); 324f8146b88SJung-uk Kim } 325f8146b88SJung-uk Kim 326f8146b88SJung-uk Kim return_ACPI_STATUS (Status); 327f8146b88SJung-uk Kim } 328f8146b88SJung-uk Kim 329f8146b88SJung-uk Kim 330f8146b88SJung-uk Kim /******************************************************************************* 331f8146b88SJung-uk Kim * 332f8146b88SJung-uk Kim * FUNCTION: AcpiExConvertToObjectTypeString 333f8146b88SJung-uk Kim * 334f8146b88SJung-uk Kim * PARAMETERS: ObjDesc - Object to be converted 335f8146b88SJung-uk Kim * ReturnDesc - Where to place the return object 336f8146b88SJung-uk Kim * 337f8146b88SJung-uk Kim * RETURN: Status 338f8146b88SJung-uk Kim * 339f8146b88SJung-uk Kim * DESCRIPTION: Convert an object of arbitrary type to a string object that 340f8146b88SJung-uk Kim * contains the namestring for the object. Used for the 341f8146b88SJung-uk Kim * concatenate operator. 342f8146b88SJung-uk Kim * 343f8146b88SJung-uk Kim ******************************************************************************/ 344f8146b88SJung-uk Kim 345f8146b88SJung-uk Kim static ACPI_STATUS 346f8146b88SJung-uk Kim AcpiExConvertToObjectTypeString ( 347f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc, 348f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT **ResultDesc) 349f8146b88SJung-uk Kim { 350f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *ReturnDesc; 351f8146b88SJung-uk Kim const char *TypeString; 352f8146b88SJung-uk Kim 353f8146b88SJung-uk Kim 354f8146b88SJung-uk Kim TypeString = AcpiUtGetTypeName (ObjDesc->Common.Type); 355f8146b88SJung-uk Kim 356f8146b88SJung-uk Kim ReturnDesc = AcpiUtCreateStringObject ( 357f8146b88SJung-uk Kim ((ACPI_SIZE) strlen (TypeString) + 9)); /* 9 For "[ Object]" */ 358f8146b88SJung-uk Kim if (!ReturnDesc) 359f8146b88SJung-uk Kim { 360f8146b88SJung-uk Kim return (AE_NO_MEMORY); 361f8146b88SJung-uk Kim } 362f8146b88SJung-uk Kim 363f8146b88SJung-uk Kim strcpy (ReturnDesc->String.Pointer, "["); 364f8146b88SJung-uk Kim strcat (ReturnDesc->String.Pointer, TypeString); 365f8146b88SJung-uk Kim strcat (ReturnDesc->String.Pointer, " Object]"); 366f8146b88SJung-uk Kim 367f8146b88SJung-uk Kim *ResultDesc = ReturnDesc; 368f8146b88SJung-uk Kim return (AE_OK); 369f8146b88SJung-uk Kim } 370f8146b88SJung-uk Kim 371f8146b88SJung-uk Kim 372f8146b88SJung-uk Kim /******************************************************************************* 373f8146b88SJung-uk Kim * 374f8146b88SJung-uk Kim * FUNCTION: AcpiExConcatTemplate 375f8146b88SJung-uk Kim * 376f8146b88SJung-uk Kim * PARAMETERS: Operand0 - First source object 377f8146b88SJung-uk Kim * Operand1 - Second source object 378f8146b88SJung-uk Kim * ActualReturnDesc - Where to place the return object 379f8146b88SJung-uk Kim * WalkState - Current walk state 380f8146b88SJung-uk Kim * 381f8146b88SJung-uk Kim * RETURN: Status 382f8146b88SJung-uk Kim * 383f8146b88SJung-uk Kim * DESCRIPTION: Concatenate two resource templates 384f8146b88SJung-uk Kim * 385f8146b88SJung-uk Kim ******************************************************************************/ 386f8146b88SJung-uk Kim 387f8146b88SJung-uk Kim ACPI_STATUS 388f8146b88SJung-uk Kim AcpiExConcatTemplate ( 389f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *Operand0, 390f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *Operand1, 391f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT **ActualReturnDesc, 392f8146b88SJung-uk Kim ACPI_WALK_STATE *WalkState) 393f8146b88SJung-uk Kim { 394f8146b88SJung-uk Kim ACPI_STATUS Status; 395f8146b88SJung-uk Kim ACPI_OPERAND_OBJECT *ReturnDesc; 396f8146b88SJung-uk Kim UINT8 *NewBuf; 397f8146b88SJung-uk Kim UINT8 *EndTag; 398f8146b88SJung-uk Kim ACPI_SIZE Length0; 399f8146b88SJung-uk Kim ACPI_SIZE Length1; 400f8146b88SJung-uk Kim ACPI_SIZE NewLength; 401f8146b88SJung-uk Kim 402f8146b88SJung-uk Kim 403f8146b88SJung-uk Kim ACPI_FUNCTION_TRACE (ExConcatTemplate); 404f8146b88SJung-uk Kim 405f8146b88SJung-uk Kim 406f8146b88SJung-uk Kim /* 407f8146b88SJung-uk Kim * Find the EndTag descriptor in each resource template. 408f8146b88SJung-uk Kim * Note1: returned pointers point TO the EndTag, not past it. 409f8146b88SJung-uk Kim * Note2: zero-length buffers are allowed; treated like one EndTag 410f8146b88SJung-uk Kim */ 411f8146b88SJung-uk Kim 412f8146b88SJung-uk Kim /* Get the length of the first resource template */ 413f8146b88SJung-uk Kim 414f8146b88SJung-uk Kim Status = AcpiUtGetResourceEndTag (Operand0, &EndTag); 415f8146b88SJung-uk Kim if (ACPI_FAILURE (Status)) 416f8146b88SJung-uk Kim { 417f8146b88SJung-uk Kim return_ACPI_STATUS (Status); 418f8146b88SJung-uk Kim } 419f8146b88SJung-uk Kim 420f8146b88SJung-uk Kim Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer); 421f8146b88SJung-uk Kim 422f8146b88SJung-uk Kim /* Get the length of the second resource template */ 423f8146b88SJung-uk Kim 424f8146b88SJung-uk Kim Status = AcpiUtGetResourceEndTag (Operand1, &EndTag); 425f8146b88SJung-uk Kim if (ACPI_FAILURE (Status)) 426f8146b88SJung-uk Kim { 427f8146b88SJung-uk Kim return_ACPI_STATUS (Status); 428f8146b88SJung-uk Kim } 429f8146b88SJung-uk Kim 430f8146b88SJung-uk Kim Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer); 431f8146b88SJung-uk Kim 432f8146b88SJung-uk Kim /* Combine both lengths, minimum size will be 2 for EndTag */ 433f8146b88SJung-uk Kim 434f8146b88SJung-uk Kim NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG); 435f8146b88SJung-uk Kim 436f8146b88SJung-uk Kim /* Create a new buffer object for the result (with one EndTag) */ 437f8146b88SJung-uk Kim 438f8146b88SJung-uk Kim ReturnDesc = AcpiUtCreateBufferObject (NewLength); 439f8146b88SJung-uk Kim if (!ReturnDesc) 440f8146b88SJung-uk Kim { 441f8146b88SJung-uk Kim return_ACPI_STATUS (AE_NO_MEMORY); 442f8146b88SJung-uk Kim } 443f8146b88SJung-uk Kim 444f8146b88SJung-uk Kim /* 445f8146b88SJung-uk Kim * Copy the templates to the new buffer, 0 first, then 1 follows. One 446f8146b88SJung-uk Kim * EndTag descriptor is copied from Operand1. 447f8146b88SJung-uk Kim */ 448f8146b88SJung-uk Kim NewBuf = ReturnDesc->Buffer.Pointer; 449f8146b88SJung-uk Kim memcpy (NewBuf, Operand0->Buffer.Pointer, Length0); 450f8146b88SJung-uk Kim memcpy (NewBuf + Length0, Operand1->Buffer.Pointer, Length1); 451f8146b88SJung-uk Kim 452f8146b88SJung-uk Kim /* Insert EndTag and set the checksum to zero, means "ignore checksum" */ 453f8146b88SJung-uk Kim 454f8146b88SJung-uk Kim NewBuf[NewLength - 1] = 0; 455f8146b88SJung-uk Kim NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1; 456f8146b88SJung-uk Kim 457f8146b88SJung-uk Kim /* Return the completed resource template */ 458f8146b88SJung-uk Kim 459f8146b88SJung-uk Kim *ActualReturnDesc = ReturnDesc; 460f8146b88SJung-uk Kim return_ACPI_STATUS (AE_OK); 461f8146b88SJung-uk Kim } 462