1433d6423SLionel Sambuc /******************************************************************************
2433d6423SLionel Sambuc *
3433d6423SLionel Sambuc * Module Name: utalloc - local memory allocation routines
4433d6423SLionel Sambuc *
5433d6423SLionel Sambuc *****************************************************************************/
6433d6423SLionel Sambuc
7*29492bb7SDavid van Moolenbroek /*
8*29492bb7SDavid van Moolenbroek * Copyright (C) 2000 - 2014, Intel Corp.
9433d6423SLionel Sambuc * All rights reserved.
10433d6423SLionel Sambuc *
11*29492bb7SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
12*29492bb7SDavid van Moolenbroek * modification, are permitted provided that the following conditions
13*29492bb7SDavid van Moolenbroek * are met:
14*29492bb7SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
15*29492bb7SDavid van Moolenbroek * notice, this list of conditions, and the following disclaimer,
16*29492bb7SDavid van Moolenbroek * without modification.
17*29492bb7SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*29492bb7SDavid van Moolenbroek * substantially similar to the "NO WARRANTY" disclaimer below
19*29492bb7SDavid van Moolenbroek * ("Disclaimer") and any redistribution must be conditioned upon
20*29492bb7SDavid van Moolenbroek * including a substantially similar Disclaimer requirement for further
21*29492bb7SDavid van Moolenbroek * binary redistribution.
22*29492bb7SDavid van Moolenbroek * 3. Neither the names of the above-listed copyright holders nor the names
23*29492bb7SDavid van Moolenbroek * of any contributors may be used to endorse or promote products derived
24*29492bb7SDavid van Moolenbroek * from this software without specific prior written permission.
25433d6423SLionel Sambuc *
26*29492bb7SDavid van Moolenbroek * Alternatively, this software may be distributed under the terms of the
27*29492bb7SDavid van Moolenbroek * GNU General Public License ("GPL") version 2 as published by the Free
28*29492bb7SDavid van Moolenbroek * Software Foundation.
29433d6423SLionel Sambuc *
30*29492bb7SDavid van Moolenbroek * NO WARRANTY
31*29492bb7SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*29492bb7SDavid van Moolenbroek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*29492bb7SDavid van Moolenbroek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*29492bb7SDavid van Moolenbroek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*29492bb7SDavid van Moolenbroek * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*29492bb7SDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*29492bb7SDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*29492bb7SDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*29492bb7SDavid van Moolenbroek * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*29492bb7SDavid van Moolenbroek * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*29492bb7SDavid van Moolenbroek * POSSIBILITY OF SUCH DAMAGES.
42*29492bb7SDavid van Moolenbroek */
43433d6423SLionel Sambuc
44433d6423SLionel Sambuc #include "acpi.h"
45433d6423SLionel Sambuc #include "accommon.h"
46433d6423SLionel Sambuc #include "acdebug.h"
47433d6423SLionel Sambuc
48433d6423SLionel Sambuc #define _COMPONENT ACPI_UTILITIES
49433d6423SLionel Sambuc ACPI_MODULE_NAME ("utalloc")
50433d6423SLionel Sambuc
51433d6423SLionel Sambuc
52*29492bb7SDavid van Moolenbroek #if !defined (USE_NATIVE_ALLOCATE_ZEROED)
53*29492bb7SDavid van Moolenbroek /*******************************************************************************
54*29492bb7SDavid van Moolenbroek *
55*29492bb7SDavid van Moolenbroek * FUNCTION: AcpiOsAllocateZeroed
56*29492bb7SDavid van Moolenbroek *
57*29492bb7SDavid van Moolenbroek * PARAMETERS: Size - Size of the allocation
58*29492bb7SDavid van Moolenbroek *
59*29492bb7SDavid van Moolenbroek * RETURN: Address of the allocated memory on success, NULL on failure.
60*29492bb7SDavid van Moolenbroek *
61*29492bb7SDavid van Moolenbroek * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory.
62*29492bb7SDavid van Moolenbroek * This is the default implementation. Can be overridden via the
63*29492bb7SDavid van Moolenbroek * USE_NATIVE_ALLOCATE_ZEROED flag.
64*29492bb7SDavid van Moolenbroek *
65*29492bb7SDavid van Moolenbroek ******************************************************************************/
66*29492bb7SDavid van Moolenbroek
67*29492bb7SDavid van Moolenbroek void *
AcpiOsAllocateZeroed(ACPI_SIZE Size)68*29492bb7SDavid van Moolenbroek AcpiOsAllocateZeroed (
69*29492bb7SDavid van Moolenbroek ACPI_SIZE Size)
70*29492bb7SDavid van Moolenbroek {
71*29492bb7SDavid van Moolenbroek void *Allocation;
72*29492bb7SDavid van Moolenbroek
73*29492bb7SDavid van Moolenbroek
74*29492bb7SDavid van Moolenbroek ACPI_FUNCTION_ENTRY ();
75*29492bb7SDavid van Moolenbroek
76*29492bb7SDavid van Moolenbroek
77*29492bb7SDavid van Moolenbroek Allocation = AcpiOsAllocate (Size);
78*29492bb7SDavid van Moolenbroek if (Allocation)
79*29492bb7SDavid van Moolenbroek {
80*29492bb7SDavid van Moolenbroek /* Clear the memory block */
81*29492bb7SDavid van Moolenbroek
82*29492bb7SDavid van Moolenbroek ACPI_MEMSET (Allocation, 0, Size);
83*29492bb7SDavid van Moolenbroek }
84*29492bb7SDavid van Moolenbroek
85*29492bb7SDavid van Moolenbroek return (Allocation);
86*29492bb7SDavid van Moolenbroek }
87*29492bb7SDavid van Moolenbroek
88*29492bb7SDavid van Moolenbroek #endif /* !USE_NATIVE_ALLOCATE_ZEROED */
89*29492bb7SDavid van Moolenbroek
90*29492bb7SDavid van Moolenbroek
91433d6423SLionel Sambuc /*******************************************************************************
92433d6423SLionel Sambuc *
93433d6423SLionel Sambuc * FUNCTION: AcpiUtCreateCaches
94433d6423SLionel Sambuc *
95433d6423SLionel Sambuc * PARAMETERS: None
96433d6423SLionel Sambuc *
97433d6423SLionel Sambuc * RETURN: Status
98433d6423SLionel Sambuc *
99433d6423SLionel Sambuc * DESCRIPTION: Create all local caches
100433d6423SLionel Sambuc *
101433d6423SLionel Sambuc ******************************************************************************/
102433d6423SLionel Sambuc
103433d6423SLionel Sambuc ACPI_STATUS
AcpiUtCreateCaches(void)104433d6423SLionel Sambuc AcpiUtCreateCaches (
105433d6423SLionel Sambuc void)
106433d6423SLionel Sambuc {
107433d6423SLionel Sambuc ACPI_STATUS Status;
108433d6423SLionel Sambuc
109433d6423SLionel Sambuc
110433d6423SLionel Sambuc /* Object Caches, for frequently used objects */
111433d6423SLionel Sambuc
112433d6423SLionel Sambuc Status = AcpiOsCreateCache ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE),
113433d6423SLionel Sambuc ACPI_MAX_NAMESPACE_CACHE_DEPTH, &AcpiGbl_NamespaceCache);
114433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
115433d6423SLionel Sambuc {
116433d6423SLionel Sambuc return (Status);
117433d6423SLionel Sambuc }
118433d6423SLionel Sambuc
119433d6423SLionel Sambuc Status = AcpiOsCreateCache ("Acpi-State", sizeof (ACPI_GENERIC_STATE),
120433d6423SLionel Sambuc ACPI_MAX_STATE_CACHE_DEPTH, &AcpiGbl_StateCache);
121433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
122433d6423SLionel Sambuc {
123433d6423SLionel Sambuc return (Status);
124433d6423SLionel Sambuc }
125433d6423SLionel Sambuc
126433d6423SLionel Sambuc Status = AcpiOsCreateCache ("Acpi-Parse", sizeof (ACPI_PARSE_OBJ_COMMON),
127433d6423SLionel Sambuc ACPI_MAX_PARSE_CACHE_DEPTH, &AcpiGbl_PsNodeCache);
128433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
129433d6423SLionel Sambuc {
130433d6423SLionel Sambuc return (Status);
131433d6423SLionel Sambuc }
132433d6423SLionel Sambuc
133433d6423SLionel Sambuc Status = AcpiOsCreateCache ("Acpi-ParseExt", sizeof (ACPI_PARSE_OBJ_NAMED),
134433d6423SLionel Sambuc ACPI_MAX_EXTPARSE_CACHE_DEPTH, &AcpiGbl_PsNodeExtCache);
135433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
136433d6423SLionel Sambuc {
137433d6423SLionel Sambuc return (Status);
138433d6423SLionel Sambuc }
139433d6423SLionel Sambuc
140433d6423SLionel Sambuc Status = AcpiOsCreateCache ("Acpi-Operand", sizeof (ACPI_OPERAND_OBJECT),
141433d6423SLionel Sambuc ACPI_MAX_OBJECT_CACHE_DEPTH, &AcpiGbl_OperandCache);
142433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
143433d6423SLionel Sambuc {
144433d6423SLionel Sambuc return (Status);
145433d6423SLionel Sambuc }
146433d6423SLionel Sambuc
147433d6423SLionel Sambuc
148433d6423SLionel Sambuc #ifdef ACPI_DBG_TRACK_ALLOCATIONS
149433d6423SLionel Sambuc
150433d6423SLionel Sambuc /* Memory allocation lists */
151433d6423SLionel Sambuc
152433d6423SLionel Sambuc Status = AcpiUtCreateList ("Acpi-Global", 0,
153433d6423SLionel Sambuc &AcpiGbl_GlobalList);
154433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
155433d6423SLionel Sambuc {
156433d6423SLionel Sambuc return (Status);
157433d6423SLionel Sambuc }
158433d6423SLionel Sambuc
159433d6423SLionel Sambuc Status = AcpiUtCreateList ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE),
160433d6423SLionel Sambuc &AcpiGbl_NsNodeList);
161433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
162433d6423SLionel Sambuc {
163433d6423SLionel Sambuc return (Status);
164433d6423SLionel Sambuc }
165433d6423SLionel Sambuc #endif
166433d6423SLionel Sambuc
167433d6423SLionel Sambuc return (AE_OK);
168433d6423SLionel Sambuc }
169433d6423SLionel Sambuc
170433d6423SLionel Sambuc
171433d6423SLionel Sambuc /*******************************************************************************
172433d6423SLionel Sambuc *
173433d6423SLionel Sambuc * FUNCTION: AcpiUtDeleteCaches
174433d6423SLionel Sambuc *
175433d6423SLionel Sambuc * PARAMETERS: None
176433d6423SLionel Sambuc *
177433d6423SLionel Sambuc * RETURN: Status
178433d6423SLionel Sambuc *
179433d6423SLionel Sambuc * DESCRIPTION: Purge and delete all local caches
180433d6423SLionel Sambuc *
181433d6423SLionel Sambuc ******************************************************************************/
182433d6423SLionel Sambuc
183433d6423SLionel Sambuc ACPI_STATUS
AcpiUtDeleteCaches(void)184433d6423SLionel Sambuc AcpiUtDeleteCaches (
185433d6423SLionel Sambuc void)
186433d6423SLionel Sambuc {
187433d6423SLionel Sambuc #ifdef ACPI_DBG_TRACK_ALLOCATIONS
188433d6423SLionel Sambuc char Buffer[7];
189433d6423SLionel Sambuc
190433d6423SLionel Sambuc if (AcpiGbl_DisplayFinalMemStats)
191433d6423SLionel Sambuc {
192433d6423SLionel Sambuc ACPI_STRCPY (Buffer, "MEMORY");
193433d6423SLionel Sambuc (void) AcpiDbDisplayStatistics (Buffer);
194433d6423SLionel Sambuc }
195433d6423SLionel Sambuc #endif
196433d6423SLionel Sambuc
197433d6423SLionel Sambuc (void) AcpiOsDeleteCache (AcpiGbl_NamespaceCache);
198433d6423SLionel Sambuc AcpiGbl_NamespaceCache = NULL;
199433d6423SLionel Sambuc
200433d6423SLionel Sambuc (void) AcpiOsDeleteCache (AcpiGbl_StateCache);
201433d6423SLionel Sambuc AcpiGbl_StateCache = NULL;
202433d6423SLionel Sambuc
203433d6423SLionel Sambuc (void) AcpiOsDeleteCache (AcpiGbl_OperandCache);
204433d6423SLionel Sambuc AcpiGbl_OperandCache = NULL;
205433d6423SLionel Sambuc
206433d6423SLionel Sambuc (void) AcpiOsDeleteCache (AcpiGbl_PsNodeCache);
207433d6423SLionel Sambuc AcpiGbl_PsNodeCache = NULL;
208433d6423SLionel Sambuc
209433d6423SLionel Sambuc (void) AcpiOsDeleteCache (AcpiGbl_PsNodeExtCache);
210433d6423SLionel Sambuc AcpiGbl_PsNodeExtCache = NULL;
211433d6423SLionel Sambuc
212433d6423SLionel Sambuc
213433d6423SLionel Sambuc #ifdef ACPI_DBG_TRACK_ALLOCATIONS
214433d6423SLionel Sambuc
215433d6423SLionel Sambuc /* Debug only - display leftover memory allocation, if any */
216433d6423SLionel Sambuc
217433d6423SLionel Sambuc AcpiUtDumpAllocations (ACPI_UINT32_MAX, NULL);
218433d6423SLionel Sambuc
219433d6423SLionel Sambuc /* Free memory lists */
220433d6423SLionel Sambuc
221433d6423SLionel Sambuc AcpiOsFree (AcpiGbl_GlobalList);
222433d6423SLionel Sambuc AcpiGbl_GlobalList = NULL;
223433d6423SLionel Sambuc
224433d6423SLionel Sambuc AcpiOsFree (AcpiGbl_NsNodeList);
225433d6423SLionel Sambuc AcpiGbl_NsNodeList = NULL;
226433d6423SLionel Sambuc #endif
227433d6423SLionel Sambuc
228433d6423SLionel Sambuc return (AE_OK);
229433d6423SLionel Sambuc }
230433d6423SLionel Sambuc
231433d6423SLionel Sambuc
232433d6423SLionel Sambuc /*******************************************************************************
233433d6423SLionel Sambuc *
234433d6423SLionel Sambuc * FUNCTION: AcpiUtValidateBuffer
235433d6423SLionel Sambuc *
236433d6423SLionel Sambuc * PARAMETERS: Buffer - Buffer descriptor to be validated
237433d6423SLionel Sambuc *
238433d6423SLionel Sambuc * RETURN: Status
239433d6423SLionel Sambuc *
240433d6423SLionel Sambuc * DESCRIPTION: Perform parameter validation checks on an ACPI_BUFFER
241433d6423SLionel Sambuc *
242433d6423SLionel Sambuc ******************************************************************************/
243433d6423SLionel Sambuc
244433d6423SLionel Sambuc ACPI_STATUS
AcpiUtValidateBuffer(ACPI_BUFFER * Buffer)245433d6423SLionel Sambuc AcpiUtValidateBuffer (
246433d6423SLionel Sambuc ACPI_BUFFER *Buffer)
247433d6423SLionel Sambuc {
248433d6423SLionel Sambuc
249433d6423SLionel Sambuc /* Obviously, the structure pointer must be valid */
250433d6423SLionel Sambuc
251433d6423SLionel Sambuc if (!Buffer)
252433d6423SLionel Sambuc {
253433d6423SLionel Sambuc return (AE_BAD_PARAMETER);
254433d6423SLionel Sambuc }
255433d6423SLionel Sambuc
256433d6423SLionel Sambuc /* Special semantics for the length */
257433d6423SLionel Sambuc
258433d6423SLionel Sambuc if ((Buffer->Length == ACPI_NO_BUFFER) ||
259433d6423SLionel Sambuc (Buffer->Length == ACPI_ALLOCATE_BUFFER) ||
260433d6423SLionel Sambuc (Buffer->Length == ACPI_ALLOCATE_LOCAL_BUFFER))
261433d6423SLionel Sambuc {
262433d6423SLionel Sambuc return (AE_OK);
263433d6423SLionel Sambuc }
264433d6423SLionel Sambuc
265433d6423SLionel Sambuc /* Length is valid, the buffer pointer must be also */
266433d6423SLionel Sambuc
267433d6423SLionel Sambuc if (!Buffer->Pointer)
268433d6423SLionel Sambuc {
269433d6423SLionel Sambuc return (AE_BAD_PARAMETER);
270433d6423SLionel Sambuc }
271433d6423SLionel Sambuc
272433d6423SLionel Sambuc return (AE_OK);
273433d6423SLionel Sambuc }
274433d6423SLionel Sambuc
275433d6423SLionel Sambuc
276433d6423SLionel Sambuc /*******************************************************************************
277433d6423SLionel Sambuc *
278433d6423SLionel Sambuc * FUNCTION: AcpiUtInitializeBuffer
279433d6423SLionel Sambuc *
280433d6423SLionel Sambuc * PARAMETERS: Buffer - Buffer to be validated
281433d6423SLionel Sambuc * RequiredLength - Length needed
282433d6423SLionel Sambuc *
283433d6423SLionel Sambuc * RETURN: Status
284433d6423SLionel Sambuc *
285433d6423SLionel Sambuc * DESCRIPTION: Validate that the buffer is of the required length or
286433d6423SLionel Sambuc * allocate a new buffer. Returned buffer is always zeroed.
287433d6423SLionel Sambuc *
288433d6423SLionel Sambuc ******************************************************************************/
289433d6423SLionel Sambuc
290433d6423SLionel Sambuc ACPI_STATUS
AcpiUtInitializeBuffer(ACPI_BUFFER * Buffer,ACPI_SIZE RequiredLength)291433d6423SLionel Sambuc AcpiUtInitializeBuffer (
292433d6423SLionel Sambuc ACPI_BUFFER *Buffer,
293433d6423SLionel Sambuc ACPI_SIZE RequiredLength)
294433d6423SLionel Sambuc {
295433d6423SLionel Sambuc ACPI_SIZE InputBufferLength;
296433d6423SLionel Sambuc
297433d6423SLionel Sambuc
298433d6423SLionel Sambuc /* Parameter validation */
299433d6423SLionel Sambuc
300433d6423SLionel Sambuc if (!Buffer || !RequiredLength)
301433d6423SLionel Sambuc {
302433d6423SLionel Sambuc return (AE_BAD_PARAMETER);
303433d6423SLionel Sambuc }
304433d6423SLionel Sambuc
305433d6423SLionel Sambuc /*
306433d6423SLionel Sambuc * Buffer->Length is used as both an input and output parameter. Get the
307433d6423SLionel Sambuc * input actual length and set the output required buffer length.
308433d6423SLionel Sambuc */
309433d6423SLionel Sambuc InputBufferLength = Buffer->Length;
310433d6423SLionel Sambuc Buffer->Length = RequiredLength;
311433d6423SLionel Sambuc
312433d6423SLionel Sambuc /*
313433d6423SLionel Sambuc * The input buffer length contains the actual buffer length, or the type
314433d6423SLionel Sambuc * of buffer to be allocated by this routine.
315433d6423SLionel Sambuc */
316433d6423SLionel Sambuc switch (InputBufferLength)
317433d6423SLionel Sambuc {
318433d6423SLionel Sambuc case ACPI_NO_BUFFER:
319433d6423SLionel Sambuc
320433d6423SLionel Sambuc /* Return the exception (and the required buffer length) */
321433d6423SLionel Sambuc
322433d6423SLionel Sambuc return (AE_BUFFER_OVERFLOW);
323433d6423SLionel Sambuc
324433d6423SLionel Sambuc case ACPI_ALLOCATE_BUFFER:
325*29492bb7SDavid van Moolenbroek /*
326*29492bb7SDavid van Moolenbroek * Allocate a new buffer. We directectly call AcpiOsAllocate here to
327*29492bb7SDavid van Moolenbroek * purposefully bypass the (optionally enabled) internal allocation
328*29492bb7SDavid van Moolenbroek * tracking mechanism since we only want to track internal
329*29492bb7SDavid van Moolenbroek * allocations. Note: The caller should use AcpiOsFree to free this
330*29492bb7SDavid van Moolenbroek * buffer created via ACPI_ALLOCATE_BUFFER.
331*29492bb7SDavid van Moolenbroek */
332433d6423SLionel Sambuc Buffer->Pointer = AcpiOsAllocate (RequiredLength);
333433d6423SLionel Sambuc break;
334433d6423SLionel Sambuc
335433d6423SLionel Sambuc case ACPI_ALLOCATE_LOCAL_BUFFER:
336433d6423SLionel Sambuc
337433d6423SLionel Sambuc /* Allocate a new buffer with local interface to allow tracking */
338433d6423SLionel Sambuc
339433d6423SLionel Sambuc Buffer->Pointer = ACPI_ALLOCATE (RequiredLength);
340433d6423SLionel Sambuc break;
341433d6423SLionel Sambuc
342433d6423SLionel Sambuc default:
343433d6423SLionel Sambuc
344433d6423SLionel Sambuc /* Existing buffer: Validate the size of the buffer */
345433d6423SLionel Sambuc
346433d6423SLionel Sambuc if (InputBufferLength < RequiredLength)
347433d6423SLionel Sambuc {
348433d6423SLionel Sambuc return (AE_BUFFER_OVERFLOW);
349433d6423SLionel Sambuc }
350433d6423SLionel Sambuc break;
351433d6423SLionel Sambuc }
352433d6423SLionel Sambuc
353433d6423SLionel Sambuc /* Validate allocation from above or input buffer pointer */
354433d6423SLionel Sambuc
355433d6423SLionel Sambuc if (!Buffer->Pointer)
356433d6423SLionel Sambuc {
357433d6423SLionel Sambuc return (AE_NO_MEMORY);
358433d6423SLionel Sambuc }
359433d6423SLionel Sambuc
360433d6423SLionel Sambuc /* Have a valid buffer, clear it */
361433d6423SLionel Sambuc
362433d6423SLionel Sambuc ACPI_MEMSET (Buffer->Pointer, 0, RequiredLength);
363433d6423SLionel Sambuc return (AE_OK);
364433d6423SLionel Sambuc }
365