Merge tag 'drm-misc-next-2018-04-26' of git://anongit.freedesktop.org/drm/drm-misc...
[sfrench/cifs-2.6.git] / drivers / acpi / acpica / exstorob.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: exstorob - AML object store support, store to object
5  *
6  * Copyright (C) 2000 - 2018, Intel Corp.
7  *
8  *****************************************************************************/
9
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acinterp.h"
13
14 #define _COMPONENT          ACPI_EXECUTER
15 ACPI_MODULE_NAME("exstorob")
16
17 /*******************************************************************************
18  *
19  * FUNCTION:    acpi_ex_store_buffer_to_buffer
20  *
21  * PARAMETERS:  source_desc         - Source object to copy
22  *              target_desc         - Destination object of the copy
23  *
24  * RETURN:      Status
25  *
26  * DESCRIPTION: Copy a buffer object to another buffer object.
27  *
28  ******************************************************************************/
29 acpi_status
30 acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
31                                union acpi_operand_object *target_desc)
32 {
33         u32 length;
34         u8 *buffer;
35
36         ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc);
37
38         /* If Source and Target are the same, just return */
39
40         if (source_desc == target_desc) {
41                 return_ACPI_STATUS(AE_OK);
42         }
43
44         /* We know that source_desc is a buffer by now */
45
46         buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer);
47         length = source_desc->buffer.length;
48
49         /*
50          * If target is a buffer of length zero or is a static buffer,
51          * allocate a new buffer of the proper length
52          */
53         if ((target_desc->buffer.length == 0) ||
54             (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
55                 target_desc->buffer.pointer = ACPI_ALLOCATE(length);
56                 if (!target_desc->buffer.pointer) {
57                         return_ACPI_STATUS(AE_NO_MEMORY);
58                 }
59
60                 target_desc->buffer.length = length;
61         }
62
63         /* Copy source buffer to target buffer */
64
65         if (length <= target_desc->buffer.length) {
66
67                 /* Clear existing buffer and copy in the new one */
68
69                 memset(target_desc->buffer.pointer, 0,
70                        target_desc->buffer.length);
71                 memcpy(target_desc->buffer.pointer, buffer, length);
72
73 #ifdef ACPI_OBSOLETE_BEHAVIOR
74                 /*
75                  * NOTE: ACPI versions up to 3.0 specified that the buffer must be
76                  * truncated if the string is smaller than the buffer. However, "other"
77                  * implementations of ACPI never did this and thus became the defacto
78                  * standard. ACPI 3.0A changes this behavior such that the buffer
79                  * is no longer truncated.
80                  */
81
82                 /*
83                  * OBSOLETE BEHAVIOR:
84                  * If the original source was a string, we must truncate the buffer,
85                  * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
86                  * copy must not truncate the original buffer.
87                  */
88                 if (original_src_type == ACPI_TYPE_STRING) {
89
90                         /* Set the new length of the target */
91
92                         target_desc->buffer.length = length;
93                 }
94 #endif
95         } else {
96                 /* Truncate the source, copy only what will fit */
97
98                 memcpy(target_desc->buffer.pointer, buffer,
99                        target_desc->buffer.length);
100
101                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
102                                   "Truncating source buffer from %X to %X\n",
103                                   length, target_desc->buffer.length));
104         }
105
106         /* Copy flags */
107
108         target_desc->buffer.flags = source_desc->buffer.flags;
109         target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
110         return_ACPI_STATUS(AE_OK);
111 }
112
113 /*******************************************************************************
114  *
115  * FUNCTION:    acpi_ex_store_string_to_string
116  *
117  * PARAMETERS:  source_desc         - Source object to copy
118  *              target_desc         - Destination object of the copy
119  *
120  * RETURN:      Status
121  *
122  * DESCRIPTION: Copy a String object to another String object
123  *
124  ******************************************************************************/
125
126 acpi_status
127 acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
128                                union acpi_operand_object *target_desc)
129 {
130         u32 length;
131         u8 *buffer;
132
133         ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc);
134
135         /* If Source and Target are the same, just return */
136
137         if (source_desc == target_desc) {
138                 return_ACPI_STATUS(AE_OK);
139         }
140
141         /* We know that source_desc is a string by now */
142
143         buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer);
144         length = source_desc->string.length;
145
146         /*
147          * Replace existing string value if it will fit and the string
148          * pointer is not a static pointer (part of an ACPI table)
149          */
150         if ((length < target_desc->string.length) &&
151             (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
152                 /*
153                  * String will fit in existing non-static buffer.
154                  * Clear old string and copy in the new one
155                  */
156                 memset(target_desc->string.pointer, 0,
157                        (acpi_size)target_desc->string.length + 1);
158                 memcpy(target_desc->string.pointer, buffer, length);
159         } else {
160                 /*
161                  * Free the current buffer, then allocate a new buffer
162                  * large enough to hold the value
163                  */
164                 if (target_desc->string.pointer &&
165                     (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
166
167                         /* Only free if not a pointer into the DSDT */
168
169                         ACPI_FREE(target_desc->string.pointer);
170                 }
171
172                 target_desc->string.pointer =
173                     ACPI_ALLOCATE_ZEROED((acpi_size)length + 1);
174
175                 if (!target_desc->string.pointer) {
176                         return_ACPI_STATUS(AE_NO_MEMORY);
177                 }
178
179                 target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
180                 memcpy(target_desc->string.pointer, buffer, length);
181         }
182
183         /* Set the new target length */
184
185         target_desc->string.length = length;
186         return_ACPI_STATUS(AE_OK);
187 }