Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[sfrench/cifs-2.6.git] / drivers / acpi / acpica / exstorob.c
1 /******************************************************************************
2  *
3  * Module Name: exstorob - AML object store support, store to object
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2018, 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/acpi.h>
45 #include "accommon.h"
46 #include "acinterp.h"
47
48 #define _COMPONENT          ACPI_EXECUTER
49 ACPI_MODULE_NAME("exstorob")
50
51 /*******************************************************************************
52  *
53  * FUNCTION:    acpi_ex_store_buffer_to_buffer
54  *
55  * PARAMETERS:  source_desc         - Source object to copy
56  *              target_desc         - Destination object of the copy
57  *
58  * RETURN:      Status
59  *
60  * DESCRIPTION: Copy a buffer object to another buffer object.
61  *
62  ******************************************************************************/
63 acpi_status
64 acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
65                                union acpi_operand_object *target_desc)
66 {
67         u32 length;
68         u8 *buffer;
69
70         ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc);
71
72         /* If Source and Target are the same, just return */
73
74         if (source_desc == target_desc) {
75                 return_ACPI_STATUS(AE_OK);
76         }
77
78         /* We know that source_desc is a buffer by now */
79
80         buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer);
81         length = source_desc->buffer.length;
82
83         /*
84          * If target is a buffer of length zero or is a static buffer,
85          * allocate a new buffer of the proper length
86          */
87         if ((target_desc->buffer.length == 0) ||
88             (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
89                 target_desc->buffer.pointer = ACPI_ALLOCATE(length);
90                 if (!target_desc->buffer.pointer) {
91                         return_ACPI_STATUS(AE_NO_MEMORY);
92                 }
93
94                 target_desc->buffer.length = length;
95         }
96
97         /* Copy source buffer to target buffer */
98
99         if (length <= target_desc->buffer.length) {
100
101                 /* Clear existing buffer and copy in the new one */
102
103                 memset(target_desc->buffer.pointer, 0,
104                        target_desc->buffer.length);
105                 memcpy(target_desc->buffer.pointer, buffer, length);
106
107 #ifdef ACPI_OBSOLETE_BEHAVIOR
108                 /*
109                  * NOTE: ACPI versions up to 3.0 specified that the buffer must be
110                  * truncated if the string is smaller than the buffer. However, "other"
111                  * implementations of ACPI never did this and thus became the defacto
112                  * standard. ACPI 3.0A changes this behavior such that the buffer
113                  * is no longer truncated.
114                  */
115
116                 /*
117                  * OBSOLETE BEHAVIOR:
118                  * If the original source was a string, we must truncate the buffer,
119                  * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
120                  * copy must not truncate the original buffer.
121                  */
122                 if (original_src_type == ACPI_TYPE_STRING) {
123
124                         /* Set the new length of the target */
125
126                         target_desc->buffer.length = length;
127                 }
128 #endif
129         } else {
130                 /* Truncate the source, copy only what will fit */
131
132                 memcpy(target_desc->buffer.pointer, buffer,
133                        target_desc->buffer.length);
134
135                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
136                                   "Truncating source buffer from %X to %X\n",
137                                   length, target_desc->buffer.length));
138         }
139
140         /* Copy flags */
141
142         target_desc->buffer.flags = source_desc->buffer.flags;
143         target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
144         return_ACPI_STATUS(AE_OK);
145 }
146
147 /*******************************************************************************
148  *
149  * FUNCTION:    acpi_ex_store_string_to_string
150  *
151  * PARAMETERS:  source_desc         - Source object to copy
152  *              target_desc         - Destination object of the copy
153  *
154  * RETURN:      Status
155  *
156  * DESCRIPTION: Copy a String object to another String object
157  *
158  ******************************************************************************/
159
160 acpi_status
161 acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
162                                union acpi_operand_object *target_desc)
163 {
164         u32 length;
165         u8 *buffer;
166
167         ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc);
168
169         /* If Source and Target are the same, just return */
170
171         if (source_desc == target_desc) {
172                 return_ACPI_STATUS(AE_OK);
173         }
174
175         /* We know that source_desc is a string by now */
176
177         buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer);
178         length = source_desc->string.length;
179
180         /*
181          * Replace existing string value if it will fit and the string
182          * pointer is not a static pointer (part of an ACPI table)
183          */
184         if ((length < target_desc->string.length) &&
185             (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
186                 /*
187                  * String will fit in existing non-static buffer.
188                  * Clear old string and copy in the new one
189                  */
190                 memset(target_desc->string.pointer, 0,
191                        (acpi_size)target_desc->string.length + 1);
192                 memcpy(target_desc->string.pointer, buffer, length);
193         } else {
194                 /*
195                  * Free the current buffer, then allocate a new buffer
196                  * large enough to hold the value
197                  */
198                 if (target_desc->string.pointer &&
199                     (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
200
201                         /* Only free if not a pointer into the DSDT */
202
203                         ACPI_FREE(target_desc->string.pointer);
204                 }
205
206                 target_desc->string.pointer =
207                     ACPI_ALLOCATE_ZEROED((acpi_size)length + 1);
208
209                 if (!target_desc->string.pointer) {
210                         return_ACPI_STATUS(AE_NO_MEMORY);
211                 }
212
213                 target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
214                 memcpy(target_desc->string.pointer, buffer, length);
215         }
216
217         /* Set the new target length */
218
219         target_desc->string.length = length;
220         return_ACPI_STATUS(AE_OK);
221 }