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