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 - 2023, 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
acpi_ex_store_buffer_to_buffer(union acpi_operand_object * source_desc,union acpi_operand_object * target_desc)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
acpi_ex_store_string_to_string(union acpi_operand_object * source_desc,union acpi_operand_object * target_desc)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  }
188