1 /******************************************************************************
2  *
3  * Module Name: exstorob - AML object store support, store to object
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2020, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acinterp.h"
47 
48 
49 #define _COMPONENT          ACPI_EXECUTER
50         ACPI_MODULE_NAME    ("exstorob")
51 
52 
53 /*******************************************************************************
54  *
55  * FUNCTION:    AcpiExStoreBufferToBuffer
56  *
57  * PARAMETERS:  SourceDesc          - Source object to copy
58  *              TargetDesc          - Destination object of the copy
59  *
60  * RETURN:      Status
61  *
62  * DESCRIPTION: Copy a buffer object to another buffer object.
63  *
64  ******************************************************************************/
65 
66 ACPI_STATUS
67 AcpiExStoreBufferToBuffer (
68     ACPI_OPERAND_OBJECT     *SourceDesc,
69     ACPI_OPERAND_OBJECT     *TargetDesc)
70 {
71     UINT32                  Length;
72     UINT8                   *Buffer;
73 
74 
75     ACPI_FUNCTION_TRACE_PTR (ExStoreBufferToBuffer, SourceDesc);
76 
77 
78     /* If Source and Target are the same, just return */
79 
80     if (SourceDesc == TargetDesc)
81     {
82         return_ACPI_STATUS (AE_OK);
83     }
84 
85     /* We know that SourceDesc is a buffer by now */
86 
87     Buffer = ACPI_CAST_PTR (UINT8, SourceDesc->Buffer.Pointer);
88     Length = SourceDesc->Buffer.Length;
89 
90     /*
91      * If target is a buffer of length zero or is a static buffer,
92      * allocate a new buffer of the proper length
93      */
94     if ((TargetDesc->Buffer.Length == 0) ||
95         (TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER))
96     {
97         TargetDesc->Buffer.Pointer = ACPI_ALLOCATE (Length);
98         if (!TargetDesc->Buffer.Pointer)
99         {
100             return_ACPI_STATUS (AE_NO_MEMORY);
101         }
102 
103         TargetDesc->Buffer.Length = Length;
104     }
105 
106     /* Copy source buffer to target buffer */
107 
108     if (Length <= TargetDesc->Buffer.Length)
109     {
110         /* Clear existing buffer and copy in the new one */
111 
112         memset (TargetDesc->Buffer.Pointer, 0, TargetDesc->Buffer.Length);
113         memcpy (TargetDesc->Buffer.Pointer, Buffer, Length);
114 
115 #ifdef ACPI_OBSOLETE_BEHAVIOR
116         /*
117          * NOTE: ACPI versions up to 3.0 specified that the buffer must be
118          * truncated if the string is smaller than the buffer. However, "other"
119          * implementations of ACPI never did this and thus became the defacto
120          * standard. ACPI 3.0A changes this behavior such that the buffer
121          * is no longer truncated.
122          */
123 
124         /*
125          * OBSOLETE BEHAVIOR:
126          * If the original source was a string, we must truncate the buffer,
127          * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
128          * copy must not truncate the original buffer.
129          */
130         if (OriginalSrcType == ACPI_TYPE_STRING)
131         {
132             /* Set the new length of the target */
133 
134             TargetDesc->Buffer.Length = Length;
135         }
136 #endif
137     }
138     else
139     {
140         /* Truncate the source, copy only what will fit */
141 
142         memcpy (TargetDesc->Buffer.Pointer, Buffer,
143             TargetDesc->Buffer.Length);
144 
145         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
146             "Truncating source buffer from %X to %X\n",
147             Length, TargetDesc->Buffer.Length));
148     }
149 
150     /* Copy flags */
151 
152     TargetDesc->Buffer.Flags = SourceDesc->Buffer.Flags;
153     TargetDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
154     return_ACPI_STATUS (AE_OK);
155 }
156 
157 
158 /*******************************************************************************
159  *
160  * FUNCTION:    AcpiExStoreStringToString
161  *
162  * PARAMETERS:  SourceDesc          - Source object to copy
163  *              TargetDesc          - Destination object of the copy
164  *
165  * RETURN:      Status
166  *
167  * DESCRIPTION: Copy a String object to another String object
168  *
169  ******************************************************************************/
170 
171 ACPI_STATUS
172 AcpiExStoreStringToString (
173     ACPI_OPERAND_OBJECT     *SourceDesc,
174     ACPI_OPERAND_OBJECT     *TargetDesc)
175 {
176     UINT32                  Length;
177     UINT8                   *Buffer;
178 
179 
180     ACPI_FUNCTION_TRACE_PTR (ExStoreStringToString, SourceDesc);
181 
182 
183     /* If Source and Target are the same, just return */
184 
185     if (SourceDesc == TargetDesc)
186     {
187         return_ACPI_STATUS (AE_OK);
188     }
189 
190     /* We know that SourceDesc is a string by now */
191 
192     Buffer = ACPI_CAST_PTR (UINT8, SourceDesc->String.Pointer);
193     Length = SourceDesc->String.Length;
194 
195     /*
196      * Replace existing string value if it will fit and the string
197      * pointer is not a static pointer (part of an ACPI table)
198      */
199     if ((Length < TargetDesc->String.Length) &&
200        (!(TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER)))
201     {
202         /*
203          * String will fit in existing non-static buffer.
204          * Clear old string and copy in the new one
205          */
206         memset (TargetDesc->String.Pointer, 0,
207             (ACPI_SIZE) TargetDesc->String.Length + 1);
208         memcpy (TargetDesc->String.Pointer, Buffer, Length);
209     }
210     else
211     {
212         /*
213          * Free the current buffer, then allocate a new buffer
214          * large enough to hold the value
215          */
216         if (TargetDesc->String.Pointer &&
217            (!(TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER)))
218         {
219             /* Only free if not a pointer into the DSDT */
220 
221             ACPI_FREE (TargetDesc->String.Pointer);
222         }
223 
224         TargetDesc->String.Pointer =
225             ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) Length + 1);
226 
227         if (!TargetDesc->String.Pointer)
228         {
229             return_ACPI_STATUS (AE_NO_MEMORY);
230         }
231 
232         TargetDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
233         memcpy (TargetDesc->String.Pointer, Buffer, Length);
234     }
235 
236     /* Set the new target length */
237 
238     TargetDesc->String.Length = Length;
239     return_ACPI_STATUS (AE_OK);
240 }
241