167754Smsmith/******************************************************************************
267754Smsmith *
3306536Sjkim * Module Name: exstorob - AML object store support, store to object
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
970243Smsmith * All rights reserved.
1067754Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2567754Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2967754Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4367754Smsmith
44193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
45193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
46193341Sjkim#include <contrib/dev/acpica/include/acinterp.h>
4767754Smsmith
4867754Smsmith
4977424Smsmith#define _COMPONENT          ACPI_EXECUTER
5091116Smsmith        ACPI_MODULE_NAME    ("exstorob")
5167754Smsmith
5267754Smsmith
5367754Smsmith/*******************************************************************************
5467754Smsmith *
5591116Smsmith * FUNCTION:    AcpiExStoreBufferToBuffer
5667754Smsmith *
5771867Smsmith * PARAMETERS:  SourceDesc          - Source object to copy
5871867Smsmith *              TargetDesc          - Destination object of the copy
5967754Smsmith *
6067754Smsmith * RETURN:      Status
6167754Smsmith *
6271867Smsmith * DESCRIPTION: Copy a buffer object to another buffer object.
6367754Smsmith *
6471867Smsmith ******************************************************************************/
6571867Smsmith
6671867SmsmithACPI_STATUS
6791116SmsmithAcpiExStoreBufferToBuffer (
6871867Smsmith    ACPI_OPERAND_OBJECT     *SourceDesc,
6971867Smsmith    ACPI_OPERAND_OBJECT     *TargetDesc)
7071867Smsmith{
7171867Smsmith    UINT32                  Length;
7271867Smsmith    UINT8                   *Buffer;
7377424Smsmith
7477424Smsmith
75167802Sjkim    ACPI_FUNCTION_TRACE_PTR (ExStoreBufferToBuffer, SourceDesc);
7682367Smsmith
7783174Smsmith
78197104Sjkim    /* If Source and Target are the same, just return */
79197104Sjkim
80197104Sjkim    if (SourceDesc == TargetDesc)
81197104Sjkim    {
82197104Sjkim        return_ACPI_STATUS (AE_OK);
83197104Sjkim    }
84197104Sjkim
85151937Sjkim    /* We know that SourceDesc is a buffer by now */
86151937Sjkim
87167802Sjkim    Buffer = ACPI_CAST_PTR (UINT8, SourceDesc->Buffer.Pointer);
8871867Smsmith    Length = SourceDesc->Buffer.Length;
8971867Smsmith
9071867Smsmith    /*
91114237Snjl     * If target is a buffer of length zero or is a static buffer,
92114237Snjl     * allocate a new buffer of the proper length
9373561Smsmith     */
94114237Snjl    if ((TargetDesc->Buffer.Length == 0) ||
95114237Snjl        (TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER))
9673561Smsmith    {
97167802Sjkim        TargetDesc->Buffer.Pointer = ACPI_ALLOCATE (Length);
9873561Smsmith        if (!TargetDesc->Buffer.Pointer)
9973561Smsmith        {
100114237Snjl            return_ACPI_STATUS (AE_NO_MEMORY);
10173561Smsmith        }
10273561Smsmith
10373561Smsmith        TargetDesc->Buffer.Length = Length;
10473561Smsmith    }
10577424Smsmith
106151937Sjkim    /* Copy source buffer to target buffer */
107151937Sjkim
10871867Smsmith    if (Length <= TargetDesc->Buffer.Length)
10971867Smsmith    {
11071867Smsmith        /* Clear existing buffer and copy in the new one */
11171867Smsmith
112306536Sjkim        memset (TargetDesc->Buffer.Pointer, 0, TargetDesc->Buffer.Length);
113306536Sjkim        memcpy (TargetDesc->Buffer.Pointer, Buffer, Length);
114151937Sjkim
115151937Sjkim#ifdef ACPI_OBSOLETE_BEHAVIOR
116151937Sjkim        /*
117151937Sjkim         * NOTE: ACPI versions up to 3.0 specified that the buffer must be
118241973Sjkim         * truncated if the string is smaller than the buffer. However, "other"
119151937Sjkim         * implementations of ACPI never did this and thus became the defacto
120151937Sjkim         * standard. ACPI 3.0A changes this behavior such that the buffer
121151937Sjkim         * is no longer truncated.
122151937Sjkim         */
123151937Sjkim
124151937Sjkim        /*
125151937Sjkim         * OBSOLETE BEHAVIOR:
126151937Sjkim         * If the original source was a string, we must truncate the buffer,
127241973Sjkim         * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
128151937Sjkim         * copy must not truncate the original buffer.
129151937Sjkim         */
130151937Sjkim        if (OriginalSrcType == ACPI_TYPE_STRING)
131151937Sjkim        {
132151937Sjkim            /* Set the new length of the target */
133151937Sjkim
134151937Sjkim            TargetDesc->Buffer.Length = Length;
135151937Sjkim        }
136151937Sjkim#endif
13771867Smsmith    }
13877424Smsmith    else
13971867Smsmith    {
140151937Sjkim        /* Truncate the source, copy only what will fit */
14171867Smsmith
142306536Sjkim        memcpy (TargetDesc->Buffer.Pointer, Buffer,
143151937Sjkim            TargetDesc->Buffer.Length);
144151937Sjkim
14582367Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
146151937Sjkim            "Truncating source buffer from %X to %X\n",
14771867Smsmith            Length, TargetDesc->Buffer.Length));
14871867Smsmith    }
14971867Smsmith
15099146Siwasaki    /* Copy flags */
15199146Siwasaki
15299146Siwasaki    TargetDesc->Buffer.Flags = SourceDesc->Buffer.Flags;
153151937Sjkim    TargetDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
154114237Snjl    return_ACPI_STATUS (AE_OK);
15571867Smsmith}
15671867Smsmith
15771867Smsmith
15871867Smsmith/*******************************************************************************
15967754Smsmith *
16091116Smsmith * FUNCTION:    AcpiExStoreStringToString
16167754Smsmith *
16271867Smsmith * PARAMETERS:  SourceDesc          - Source object to copy
16371867Smsmith *              TargetDesc          - Destination object of the copy
16467754Smsmith *
16571867Smsmith * RETURN:      Status
16671867Smsmith *
16771867Smsmith * DESCRIPTION: Copy a String object to another String object
16871867Smsmith *
16967754Smsmith ******************************************************************************/
17067754Smsmith
17167754SmsmithACPI_STATUS
17291116SmsmithAcpiExStoreStringToString (
17371867Smsmith    ACPI_OPERAND_OBJECT     *SourceDesc,
17471867Smsmith    ACPI_OPERAND_OBJECT     *TargetDesc)
17567754Smsmith{
17671867Smsmith    UINT32                  Length;
17771867Smsmith    UINT8                   *Buffer;
17867754Smsmith
17967754Smsmith
180167802Sjkim    ACPI_FUNCTION_TRACE_PTR (ExStoreStringToString, SourceDesc);
18183174Smsmith
18283174Smsmith
183197104Sjkim    /* If Source and Target are the same, just return */
184197104Sjkim
185197104Sjkim    if (SourceDesc == TargetDesc)
186197104Sjkim    {
187197104Sjkim        return_ACPI_STATUS (AE_OK);
188197104Sjkim    }
189197104Sjkim
190151937Sjkim    /* We know that SourceDesc is a string by now */
191151937Sjkim
192167802Sjkim    Buffer = ACPI_CAST_PTR (UINT8, SourceDesc->String.Pointer);
19371867Smsmith    Length = SourceDesc->String.Length;
19467754Smsmith
19567754Smsmith    /*
196114237Snjl     * Replace existing string value if it will fit and the string
197114237Snjl     * pointer is not a static pointer (part of an ACPI table)
19867754Smsmith     */
199114237Snjl    if ((Length < TargetDesc->String.Length) &&
200114237Snjl       (!(TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER)))
20167754Smsmith    {
202114237Snjl        /*
203114237Snjl         * String will fit in existing non-static buffer.
204114237Snjl         * Clear old string and copy in the new one
205104470Siwasaki         */
206306536Sjkim        memset (TargetDesc->String.Pointer, 0,
207151937Sjkim            (ACPI_SIZE) TargetDesc->String.Length + 1);
208306536Sjkim        memcpy (TargetDesc->String.Pointer, Buffer, Length);
20971867Smsmith    }
21071867Smsmith    else
21171867Smsmith    {
21267754Smsmith        /*
213104470Siwasaki         * Free the current buffer, then allocate a new buffer
21471867Smsmith         * large enough to hold the value
21567754Smsmith         */
21671867Smsmith        if (TargetDesc->String.Pointer &&
21782367Smsmith           (!(TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER)))
21867754Smsmith        {
219151937Sjkim            /* Only free if not a pointer into the DSDT */
220151937Sjkim
221167802Sjkim            ACPI_FREE (TargetDesc->String.Pointer);
22267754Smsmith        }
22367754Smsmith
224306536Sjkim        TargetDesc->String.Pointer =
225306536Sjkim            ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) Length + 1);
226306536Sjkim
22771867Smsmith        if (!TargetDesc->String.Pointer)
22867754Smsmith        {
229114237Snjl            return_ACPI_STATUS (AE_NO_MEMORY);
23067754Smsmith        }
23183174Smsmith
232114237Snjl        TargetDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
233306536Sjkim        memcpy (TargetDesc->String.Pointer, Buffer, Length);
23471867Smsmith    }
23567754Smsmith
236104470Siwasaki    /* Set the new target length */
237104470Siwasaki
238104470Siwasaki    TargetDesc->String.Length = Length;
239114237Snjl    return_ACPI_STATUS (AE_OK);
24071867Smsmith}
241