linux/drivers/acpi/acpica/exstorob.c
<<
>>
Prefs
   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 - 2022, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include <acpi/acpi.h>
  11#include "accommon.h"
  12#include "acinterp.h"
  13
  14#define _COMPONENT          ACPI_EXECUTER
  15ACPI_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 ******************************************************************************/
  29acpi_status
  30acpi_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
 126acpi_status
 127acpi_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