linux/drivers/acpi/acpica/exstorob.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: exstorob - AML Interpreter object store support, store to object
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2013, 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
  49ACPI_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 ******************************************************************************/
  63acpi_status
  64acpi_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                ACPI_MEMSET(target_desc->buffer.pointer, 0,
 104                            target_desc->buffer.length);
 105                ACPI_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                ACPI_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
 160acpi_status
 161acpi_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                ACPI_MEMSET(target_desc->string.pointer, 0,
 191                            (acpi_size) target_desc->string.length + 1);
 192                ACPI_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 = ACPI_ALLOCATE_ZEROED((acpi_size)
 207                                                                   length + 1);
 208                if (!target_desc->string.pointer) {
 209                        return_ACPI_STATUS(AE_NO_MEMORY);
 210                }
 211
 212                target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
 213                ACPI_MEMCPY(target_desc->string.pointer, buffer, length);
 214        }
 215
 216        /* Set the new target length */
 217
 218        target_desc->string.length = length;
 219        return_ACPI_STATUS(AE_OK);
 220}
 221