| 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 - 2025, 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(s: target_desc->buffer.pointer, c: 0, | 
|---|
| 70 | n: target_desc->buffer.length); | 
|---|
| 71 | memcpy(to: target_desc->buffer.pointer, from: buffer, len: 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(to: target_desc->buffer.pointer, from: buffer, | 
|---|
| 99 | len: 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(s: target_desc->string.pointer, c: 0, | 
|---|
| 157 | n: (acpi_size)target_desc->string.length + 1); | 
|---|
| 158 | memcpy(to: target_desc->string.pointer, from: buffer, len: 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(to: target_desc->string.pointer, from: buffer, len: length); | 
|---|
| 181 | } | 
|---|
| 182 |  | 
|---|
| 183 | /* Set the new target length */ | 
|---|
| 184 |  | 
|---|
| 185 | target_desc->string.length = length; | 
|---|
| 186 | return_ACPI_STATUS(AE_OK); | 
|---|
| 187 | } | 
|---|
| 188 |  | 
|---|