1274357Sjkim/****************************************************************************** 2274357Sjkim * 3274357Sjkim * Module Name: aslprintf - ASL Printf/Fprintf macro support 4274357Sjkim * 5274357Sjkim *****************************************************************************/ 6274357Sjkim 7274357Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9274357Sjkim * All rights reserved. 10274357Sjkim * 11274357Sjkim * Redistribution and use in source and binary forms, with or without 12274357Sjkim * modification, are permitted provided that the following conditions 13274357Sjkim * are met: 14274357Sjkim * 1. Redistributions of source code must retain the above copyright 15274357Sjkim * notice, this list of conditions, and the following disclaimer, 16274357Sjkim * without modification. 17274357Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18274357Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19274357Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20274357Sjkim * including a substantially similar Disclaimer requirement for further 21274357Sjkim * binary redistribution. 22274357Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23274357Sjkim * of any contributors may be used to endorse or promote products derived 24274357Sjkim * from this software without specific prior written permission. 25274357Sjkim * 26274357Sjkim * Alternatively, this software may be distributed under the terms of the 27274357Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28274357Sjkim * Software Foundation. 29274357Sjkim * 30274357Sjkim * NO WARRANTY 31274357Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32274357Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33274357Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34274357Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35274357Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36274357Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37274357Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38274357Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39274357Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40274357Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41274357Sjkim * POSSIBILITY OF SUCH DAMAGES. 42274357Sjkim */ 43274357Sjkim 44278970Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 45274357Sjkim#include "aslcompiler.y.h" 46278970Sjkim#include <contrib/dev/acpica/include/amlcode.h> 47274357Sjkim 48274357Sjkim#define _COMPONENT ACPI_COMPILER 49274357Sjkim ACPI_MODULE_NAME ("aslprintf") 50274357Sjkim 51274357Sjkim 52274357Sjkim/* Local prototypes */ 53274357Sjkim 54274357Sjkimstatic void 55274357SjkimOpcCreateConcatenateNode ( 56274357Sjkim ACPI_PARSE_OBJECT *Op, 57274357Sjkim ACPI_PARSE_OBJECT *Node); 58274357Sjkim 59274357Sjkimstatic void 60274357SjkimOpcParsePrintf ( 61274357Sjkim ACPI_PARSE_OBJECT *Op, 62274357Sjkim ACPI_PARSE_OBJECT *DestOp); 63274357Sjkim 64274357Sjkim 65274357Sjkim/******************************************************************************* 66274357Sjkim * 67274357Sjkim * FUNCTION: OpcDoPrintf 68274357Sjkim * 69274357Sjkim * PARAMETERS: Op - printf parse node 70274357Sjkim * 71274357Sjkim * RETURN: None 72274357Sjkim * 73274357Sjkim * DESCRIPTION: Convert printf macro to a Store(..., Debug) AML operation. 74274357Sjkim * 75274357Sjkim ******************************************************************************/ 76274357Sjkim 77274357Sjkimvoid 78274357SjkimOpcDoPrintf ( 79274357Sjkim ACPI_PARSE_OBJECT *Op) 80274357Sjkim{ 81274357Sjkim ACPI_PARSE_OBJECT *DestOp; 82274357Sjkim 83274357Sjkim 84274357Sjkim /* Store destination is the Debug op */ 85274357Sjkim 86274357Sjkim DestOp = TrAllocateNode (PARSEOP_DEBUG); 87274357Sjkim DestOp->Asl.AmlOpcode = AML_DEBUG_OP; 88274357Sjkim DestOp->Asl.Parent = Op; 89274357Sjkim DestOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber; 90274357Sjkim 91274357Sjkim OpcParsePrintf (Op, DestOp); 92274357Sjkim} 93274357Sjkim 94274357Sjkim 95274357Sjkim/******************************************************************************* 96274357Sjkim * 97274357Sjkim * FUNCTION: OpcDoFprintf 98274357Sjkim * 99274357Sjkim * PARAMETERS: Op - fprintf parse node 100274357Sjkim * 101274357Sjkim * RETURN: None 102274357Sjkim * 103274357Sjkim * DESCRIPTION: Convert fprintf macro to a Store AML operation. 104274357Sjkim * 105274357Sjkim ******************************************************************************/ 106274357Sjkim 107274357Sjkimvoid 108274357SjkimOpcDoFprintf ( 109274357Sjkim ACPI_PARSE_OBJECT *Op) 110274357Sjkim{ 111274357Sjkim ACPI_PARSE_OBJECT *DestOp; 112274357Sjkim 113274357Sjkim 114274357Sjkim /* Store destination is the first argument of fprintf */ 115274357Sjkim 116274357Sjkim DestOp = Op->Asl.Child; 117274357Sjkim Op->Asl.Child = DestOp->Asl.Next; 118274357Sjkim DestOp->Asl.Next = NULL; 119274357Sjkim 120274357Sjkim OpcParsePrintf (Op, DestOp); 121274357Sjkim} 122274357Sjkim 123274357Sjkim 124274357Sjkim/******************************************************************************* 125274357Sjkim * 126274357Sjkim * FUNCTION: OpcParsePrintf 127274357Sjkim * 128274357Sjkim * PARAMETERS: Op - Printf parse node 129274357Sjkim * DestOp - Destination of Store operation 130274357Sjkim * 131274357Sjkim * RETURN: None 132274357Sjkim * 133274357Sjkim * DESCRIPTION: Convert printf macro to a Store AML operation. The printf 134274357Sjkim * macro parse tree is layed out as follows: 135274357Sjkim * 136274357Sjkim * Op - printf parse op 137274357Sjkim * Op->Child - Format string 138274357Sjkim * Op->Next - Format string arguments 139274357Sjkim * 140274357Sjkim ******************************************************************************/ 141274357Sjkim 142274357Sjkimstatic void 143274357SjkimOpcParsePrintf ( 144274357Sjkim ACPI_PARSE_OBJECT *Op, 145274357Sjkim ACPI_PARSE_OBJECT *DestOp) 146274357Sjkim{ 147274357Sjkim char *Format; 148274357Sjkim char *StartPosition = NULL; 149274357Sjkim ACPI_PARSE_OBJECT *ArgNode; 150274357Sjkim ACPI_PARSE_OBJECT *NextNode; 151274357Sjkim UINT32 StringLength = 0; 152274357Sjkim char *NewString; 153274357Sjkim BOOLEAN StringToProcess = FALSE; 154274357Sjkim ACPI_PARSE_OBJECT *NewOp; 155274357Sjkim 156274357Sjkim 157274357Sjkim /* Get format string */ 158274357Sjkim 159274357Sjkim Format = ACPI_CAST_PTR (char, Op->Asl.Child->Asl.Value.String); 160274357Sjkim ArgNode = Op->Asl.Child->Asl.Next; 161274357Sjkim 162274357Sjkim /* 163274357Sjkim * Detach argument list so that we can use a NULL check to distinguish 164274357Sjkim * the first concatenation operation we need to make 165274357Sjkim */ 166274357Sjkim Op->Asl.Child = NULL; 167274357Sjkim 168274357Sjkim for (; *Format; ++Format) 169274357Sjkim { 170274357Sjkim if (*Format != '%') 171274357Sjkim { 172274357Sjkim if (!StringToProcess) 173274357Sjkim { 174274357Sjkim /* Mark the beginning of a string */ 175274357Sjkim 176274357Sjkim StartPosition = Format; 177274357Sjkim StringToProcess = TRUE; 178274357Sjkim } 179274357Sjkim 180274357Sjkim ++StringLength; 181274357Sjkim continue; 182274357Sjkim } 183274357Sjkim 184274357Sjkim /* Save string, if any, to new string object and concat it */ 185274357Sjkim 186274357Sjkim if (StringToProcess) 187274357Sjkim { 188274357Sjkim NewString = UtStringCacheCalloc (StringLength + 1); 189306536Sjkim strncpy (NewString, StartPosition, StringLength); 190274357Sjkim 191274357Sjkim NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL); 192274357Sjkim NewOp->Asl.Value.String = NewString; 193274357Sjkim NewOp->Asl.AmlOpcode = AML_STRING_OP; 194274357Sjkim NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING; 195274357Sjkim NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber; 196274357Sjkim 197274357Sjkim OpcCreateConcatenateNode(Op, NewOp); 198274357Sjkim 199274357Sjkim StringLength = 0; 200274357Sjkim StringToProcess = FALSE; 201274357Sjkim } 202274357Sjkim 203274357Sjkim ++Format; 204274357Sjkim 205274357Sjkim /* 206274357Sjkim * We have a format parameter and will need an argument to go 207274357Sjkim * with it 208274357Sjkim */ 209274357Sjkim if (!ArgNode || 210274357Sjkim ArgNode->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 211274357Sjkim { 212274357Sjkim AslError(ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, NULL); 213274357Sjkim return; 214274357Sjkim } 215274357Sjkim 216274357Sjkim /* 217274357Sjkim * We do not support sub-specifiers of printf (flags, width, 218274357Sjkim * precision, length). For specifiers we only support %x/%X for 219274357Sjkim * hex or %s for strings. Also, %o for generic "acpi object". 220274357Sjkim */ 221274357Sjkim switch (*Format) 222274357Sjkim { 223274357Sjkim case 's': 224274357Sjkim 225274357Sjkim if (ArgNode->Asl.ParseOpcode != PARSEOP_STRING_LITERAL) 226274357Sjkim { 227274357Sjkim AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgNode, 228274357Sjkim "String required"); 229274357Sjkim return; 230274357Sjkim } 231274357Sjkim 232274357Sjkim NextNode = ArgNode->Asl.Next; 233274357Sjkim ArgNode->Asl.Next = NULL; 234274357Sjkim OpcCreateConcatenateNode(Op, ArgNode); 235274357Sjkim ArgNode = NextNode; 236274357Sjkim continue; 237274357Sjkim 238274357Sjkim case 'X': 239274357Sjkim case 'x': 240274357Sjkim case 'o': 241274357Sjkim 242274357Sjkim NextNode = ArgNode->Asl.Next; 243274357Sjkim ArgNode->Asl.Next = NULL; 244274357Sjkim 245274357Sjkim /* 246274357Sjkim * Append an empty string if the first argument is 247274357Sjkim * not a string. This will implicitly conver the 2nd 248274357Sjkim * concat source to a string per the ACPI specification. 249274357Sjkim */ 250274357Sjkim if (!Op->Asl.Child) 251274357Sjkim { 252274357Sjkim NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL); 253274357Sjkim NewOp->Asl.Value.String = ""; 254274357Sjkim NewOp->Asl.AmlOpcode = AML_STRING_OP; 255274357Sjkim NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING; 256274357Sjkim NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber; 257274357Sjkim 258274357Sjkim OpcCreateConcatenateNode(Op, NewOp); 259274357Sjkim } 260274357Sjkim 261274357Sjkim OpcCreateConcatenateNode(Op, ArgNode); 262274357Sjkim ArgNode = NextNode; 263274357Sjkim break; 264274357Sjkim 265274357Sjkim default: 266274357Sjkim 267274357Sjkim AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Op, 268274357Sjkim "Unrecognized format specifier"); 269274357Sjkim continue; 270274357Sjkim } 271274357Sjkim } 272274357Sjkim 273274357Sjkim /* Process any remaining string */ 274274357Sjkim 275274357Sjkim if (StringToProcess) 276274357Sjkim { 277274357Sjkim NewString = UtStringCacheCalloc (StringLength + 1); 278306536Sjkim strncpy (NewString, StartPosition, StringLength); 279274357Sjkim 280274357Sjkim NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL); 281274357Sjkim NewOp->Asl.Value.String = NewString; 282274357Sjkim NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING; 283274357Sjkim NewOp->Asl.AmlOpcode = AML_STRING_OP; 284274357Sjkim NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber; 285274357Sjkim 286274357Sjkim OpcCreateConcatenateNode(Op, NewOp); 287274357Sjkim } 288274357Sjkim 289274357Sjkim /* 290274357Sjkim * If we get here and there's no child node then Format 291274357Sjkim * was an empty string. Just make a no op. 292274357Sjkim */ 293274357Sjkim if (!Op->Asl.Child) 294274357Sjkim { 295274357Sjkim Op->Asl.ParseOpcode = PARSEOP_NOOP; 296274357Sjkim AslError(ASL_WARNING, ASL_MSG_NULL_STRING, Op, 297274357Sjkim "Converted to NOOP"); 298274357Sjkim return; 299274357Sjkim } 300274357Sjkim 301274357Sjkim /* Check for erroneous extra arguments */ 302274357Sjkim 303274357Sjkim if (ArgNode && 304274357Sjkim ArgNode->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 305274357Sjkim { 306274357Sjkim AslError(ASL_WARNING, ASL_MSG_ARG_COUNT_HI, ArgNode, 307274357Sjkim "Extra arguments ignored"); 308274357Sjkim } 309274357Sjkim 310274357Sjkim /* Change Op to a Store */ 311274357Sjkim 312274357Sjkim Op->Asl.ParseOpcode = PARSEOP_STORE; 313274357Sjkim Op->Common.AmlOpcode = AML_STORE_OP; 314274357Sjkim Op->Asl.CompileFlags = 0; 315274357Sjkim 316274357Sjkim /* Disable further optimization */ 317274357Sjkim 318274357Sjkim Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST; 319274357Sjkim UtSetParseOpName (Op); 320274357Sjkim 321274357Sjkim /* Set Store destination */ 322274357Sjkim 323274357Sjkim Op->Asl.Child->Asl.Next = DestOp; 324274357Sjkim} 325274357Sjkim 326274357Sjkim 327274357Sjkim/******************************************************************************* 328274357Sjkim * 329274357Sjkim * FUNCTION: OpcCreateConcatenateNode 330274357Sjkim * 331274357Sjkim * PARAMETERS: Op - Parse node 332274357Sjkim * Node - Parse node to be concatenated 333274357Sjkim * 334274357Sjkim * RETURN: None 335274357Sjkim * 336274357Sjkim * DESCRIPTION: Make Node the child of Op. If child node already exists, then 337274357Sjkim * concat child with Node and makes concat node the child of Op. 338274357Sjkim * 339274357Sjkim ******************************************************************************/ 340274357Sjkim 341274357Sjkimstatic void 342274357SjkimOpcCreateConcatenateNode ( 343274357Sjkim ACPI_PARSE_OBJECT *Op, 344274357Sjkim ACPI_PARSE_OBJECT *Node) 345274357Sjkim{ 346274357Sjkim ACPI_PARSE_OBJECT *NewConcatOp; 347274357Sjkim 348274357Sjkim 349274357Sjkim if (!Op->Asl.Child) 350274357Sjkim { 351274357Sjkim Op->Asl.Child = Node; 352274357Sjkim Node->Asl.Parent = Op; 353274357Sjkim return; 354274357Sjkim } 355274357Sjkim 356274357Sjkim NewConcatOp = TrAllocateNode (PARSEOP_CONCATENATE); 357274357Sjkim NewConcatOp->Asl.AmlOpcode = AML_CONCAT_OP; 358274357Sjkim NewConcatOp->Asl.AcpiBtype = 0x7; 359274357Sjkim NewConcatOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber; 360274357Sjkim 361274357Sjkim /* First arg is child of Op*/ 362274357Sjkim 363274357Sjkim NewConcatOp->Asl.Child = Op->Asl.Child; 364274357Sjkim Op->Asl.Child->Asl.Parent = NewConcatOp; 365274357Sjkim 366274357Sjkim /* Second arg is Node */ 367274357Sjkim 368274357Sjkim NewConcatOp->Asl.Child->Asl.Next = Node; 369274357Sjkim Node->Asl.Parent = NewConcatOp; 370274357Sjkim 371274357Sjkim /* Third arg is Zero (not used) */ 372274357Sjkim 373274357Sjkim NewConcatOp->Asl.Child->Asl.Next->Asl.Next = 374274357Sjkim TrAllocateNode (PARSEOP_ZERO); 375274357Sjkim NewConcatOp->Asl.Child->Asl.Next->Asl.Next->Asl.Parent = 376274357Sjkim NewConcatOp; 377274357Sjkim 378274357Sjkim Op->Asl.Child = NewConcatOp; 379274357Sjkim NewConcatOp->Asl.Parent = Op; 380274357Sjkim} 381