195b482a8SLen Brown 295b482a8SLen Brown /****************************************************************************** 395b482a8SLen Brown * 495b482a8SLen Brown * Module Name: exstorob - AML Interpreter object store support, store to object 595b482a8SLen Brown * 695b482a8SLen Brown *****************************************************************************/ 795b482a8SLen Brown 895b482a8SLen Brown /* 977848130SBob Moore * Copyright (C) 2000 - 2012, Intel Corp. 1095b482a8SLen Brown * All rights reserved. 1195b482a8SLen Brown * 1295b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 1395b482a8SLen Brown * modification, are permitted provided that the following conditions 1495b482a8SLen Brown * are met: 1595b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 1695b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 1795b482a8SLen Brown * without modification. 1895b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1995b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 2095b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 2195b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 2295b482a8SLen Brown * binary redistribution. 2395b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 2495b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 2595b482a8SLen Brown * from this software without specific prior written permission. 2695b482a8SLen Brown * 2795b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 2895b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 2995b482a8SLen Brown * Software Foundation. 3095b482a8SLen Brown * 3195b482a8SLen Brown * NO WARRANTY 3295b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3395b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3495b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3595b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3695b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3795b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3895b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3995b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4095b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4195b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4295b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 4395b482a8SLen Brown */ 4495b482a8SLen Brown 4595b482a8SLen Brown #include <acpi/acpi.h> 46e2f7a777SLen Brown #include "accommon.h" 47e2f7a777SLen Brown #include "acinterp.h" 4895b482a8SLen Brown 4995b482a8SLen Brown #define _COMPONENT ACPI_EXECUTER 5095b482a8SLen Brown ACPI_MODULE_NAME("exstorob") 5195b482a8SLen Brown 5295b482a8SLen Brown /******************************************************************************* 5395b482a8SLen Brown * 5495b482a8SLen Brown * FUNCTION: acpi_ex_store_buffer_to_buffer 5595b482a8SLen Brown * 5695b482a8SLen Brown * PARAMETERS: source_desc - Source object to copy 5795b482a8SLen Brown * target_desc - Destination object of the copy 5895b482a8SLen Brown * 5995b482a8SLen Brown * RETURN: Status 6095b482a8SLen Brown * 6195b482a8SLen Brown * DESCRIPTION: Copy a buffer object to another buffer object. 6295b482a8SLen Brown * 6395b482a8SLen Brown ******************************************************************************/ 6495b482a8SLen Brown acpi_status 6595b482a8SLen Brown acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, 6695b482a8SLen Brown union acpi_operand_object *target_desc) 6795b482a8SLen Brown { 6895b482a8SLen Brown u32 length; 6995b482a8SLen Brown u8 *buffer; 7095b482a8SLen Brown 7195b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc); 7295b482a8SLen Brown 73b0de22bdSLin Ming /* If Source and Target are the same, just return */ 74b0de22bdSLin Ming 75b0de22bdSLin Ming if (source_desc == target_desc) { 76b0de22bdSLin Ming return_ACPI_STATUS(AE_OK); 77b0de22bdSLin Ming } 78b0de22bdSLin Ming 7995b482a8SLen Brown /* We know that source_desc is a buffer by now */ 8095b482a8SLen Brown 8195b482a8SLen Brown buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer); 8295b482a8SLen Brown length = source_desc->buffer.length; 8395b482a8SLen Brown 8495b482a8SLen Brown /* 8595b482a8SLen Brown * If target is a buffer of length zero or is a static buffer, 8695b482a8SLen Brown * allocate a new buffer of the proper length 8795b482a8SLen Brown */ 8895b482a8SLen Brown if ((target_desc->buffer.length == 0) || 8995b482a8SLen Brown (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) { 9095b482a8SLen Brown target_desc->buffer.pointer = ACPI_ALLOCATE(length); 9195b482a8SLen Brown if (!target_desc->buffer.pointer) { 9295b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 9395b482a8SLen Brown } 9495b482a8SLen Brown 9595b482a8SLen Brown target_desc->buffer.length = length; 9695b482a8SLen Brown } 9795b482a8SLen Brown 9895b482a8SLen Brown /* Copy source buffer to target buffer */ 9995b482a8SLen Brown 10095b482a8SLen Brown if (length <= target_desc->buffer.length) { 10195b482a8SLen Brown 10295b482a8SLen Brown /* Clear existing buffer and copy in the new one */ 10395b482a8SLen Brown 10495b482a8SLen Brown ACPI_MEMSET(target_desc->buffer.pointer, 0, 10595b482a8SLen Brown target_desc->buffer.length); 10695b482a8SLen Brown ACPI_MEMCPY(target_desc->buffer.pointer, buffer, length); 10795b482a8SLen Brown 10895b482a8SLen Brown #ifdef ACPI_OBSOLETE_BEHAVIOR 10995b482a8SLen Brown /* 11095b482a8SLen Brown * NOTE: ACPI versions up to 3.0 specified that the buffer must be 11195b482a8SLen Brown * truncated if the string is smaller than the buffer. However, "other" 11295b482a8SLen Brown * implementations of ACPI never did this and thus became the defacto 113*ba494beeSBob Moore * standard. ACPI 3.0A changes this behavior such that the buffer 11495b482a8SLen Brown * is no longer truncated. 11595b482a8SLen Brown */ 11695b482a8SLen Brown 11795b482a8SLen Brown /* 11895b482a8SLen Brown * OBSOLETE BEHAVIOR: 11995b482a8SLen Brown * If the original source was a string, we must truncate the buffer, 12095b482a8SLen Brown * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer 12195b482a8SLen Brown * copy must not truncate the original buffer. 12295b482a8SLen Brown */ 12395b482a8SLen Brown if (original_src_type == ACPI_TYPE_STRING) { 12495b482a8SLen Brown 12595b482a8SLen Brown /* Set the new length of the target */ 12695b482a8SLen Brown 12795b482a8SLen Brown target_desc->buffer.length = length; 12895b482a8SLen Brown } 12995b482a8SLen Brown #endif 13095b482a8SLen Brown } else { 13195b482a8SLen Brown /* Truncate the source, copy only what will fit */ 13295b482a8SLen Brown 13395b482a8SLen Brown ACPI_MEMCPY(target_desc->buffer.pointer, buffer, 13495b482a8SLen Brown target_desc->buffer.length); 13595b482a8SLen Brown 13695b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 13795b482a8SLen Brown "Truncating source buffer from %X to %X\n", 13895b482a8SLen Brown length, target_desc->buffer.length)); 13995b482a8SLen Brown } 14095b482a8SLen Brown 14195b482a8SLen Brown /* Copy flags */ 14295b482a8SLen Brown 14395b482a8SLen Brown target_desc->buffer.flags = source_desc->buffer.flags; 14495b482a8SLen Brown target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; 14595b482a8SLen Brown return_ACPI_STATUS(AE_OK); 14695b482a8SLen Brown } 14795b482a8SLen Brown 14895b482a8SLen Brown /******************************************************************************* 14995b482a8SLen Brown * 15095b482a8SLen Brown * FUNCTION: acpi_ex_store_string_to_string 15195b482a8SLen Brown * 15295b482a8SLen Brown * PARAMETERS: source_desc - Source object to copy 15395b482a8SLen Brown * target_desc - Destination object of the copy 15495b482a8SLen Brown * 15595b482a8SLen Brown * RETURN: Status 15695b482a8SLen Brown * 15795b482a8SLen Brown * DESCRIPTION: Copy a String object to another String object 15895b482a8SLen Brown * 15995b482a8SLen Brown ******************************************************************************/ 16095b482a8SLen Brown 16195b482a8SLen Brown acpi_status 16295b482a8SLen Brown acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, 16395b482a8SLen Brown union acpi_operand_object *target_desc) 16495b482a8SLen Brown { 16595b482a8SLen Brown u32 length; 16695b482a8SLen Brown u8 *buffer; 16795b482a8SLen Brown 16895b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc); 16995b482a8SLen Brown 170b0de22bdSLin Ming /* If Source and Target are the same, just return */ 171b0de22bdSLin Ming 172b0de22bdSLin Ming if (source_desc == target_desc) { 173b0de22bdSLin Ming return_ACPI_STATUS(AE_OK); 174b0de22bdSLin Ming } 175b0de22bdSLin Ming 17695b482a8SLen Brown /* We know that source_desc is a string by now */ 17795b482a8SLen Brown 17895b482a8SLen Brown buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer); 17995b482a8SLen Brown length = source_desc->string.length; 18095b482a8SLen Brown 18195b482a8SLen Brown /* 18295b482a8SLen Brown * Replace existing string value if it will fit and the string 18395b482a8SLen Brown * pointer is not a static pointer (part of an ACPI table) 18495b482a8SLen Brown */ 18595b482a8SLen Brown if ((length < target_desc->string.length) && 18695b482a8SLen Brown (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { 18795b482a8SLen Brown /* 18895b482a8SLen Brown * String will fit in existing non-static buffer. 18995b482a8SLen Brown * Clear old string and copy in the new one 19095b482a8SLen Brown */ 19195b482a8SLen Brown ACPI_MEMSET(target_desc->string.pointer, 0, 19295b482a8SLen Brown (acpi_size) target_desc->string.length + 1); 19395b482a8SLen Brown ACPI_MEMCPY(target_desc->string.pointer, buffer, length); 19495b482a8SLen Brown } else { 19595b482a8SLen Brown /* 19695b482a8SLen Brown * Free the current buffer, then allocate a new buffer 19795b482a8SLen Brown * large enough to hold the value 19895b482a8SLen Brown */ 19995b482a8SLen Brown if (target_desc->string.pointer && 20095b482a8SLen Brown (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { 20195b482a8SLen Brown 20295b482a8SLen Brown /* Only free if not a pointer into the DSDT */ 20395b482a8SLen Brown 20495b482a8SLen Brown ACPI_FREE(target_desc->string.pointer); 20595b482a8SLen Brown } 20695b482a8SLen Brown 20795b482a8SLen Brown target_desc->string.pointer = ACPI_ALLOCATE_ZEROED((acpi_size) 20895b482a8SLen Brown length + 1); 20995b482a8SLen Brown if (!target_desc->string.pointer) { 21095b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 21195b482a8SLen Brown } 21295b482a8SLen Brown 21395b482a8SLen Brown target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; 21495b482a8SLen Brown ACPI_MEMCPY(target_desc->string.pointer, buffer, length); 21595b482a8SLen Brown } 21695b482a8SLen Brown 21795b482a8SLen Brown /* Set the new target length */ 21895b482a8SLen Brown 21995b482a8SLen Brown target_desc->string.length = length; 22095b482a8SLen Brown return_ACPI_STATUS(AE_OK); 22195b482a8SLen Brown } 222