128c506b8Sjruoho /******************************************************************************
228c506b8Sjruoho *
328c506b8Sjruoho * Module Name: utalloc - local memory allocation routines
428c506b8Sjruoho *
528c506b8Sjruoho *****************************************************************************/
628c506b8Sjruoho
7124f4c82Sjruoho /*
8*046a2985Schristos * Copyright (C) 2000 - 2023, Intel Corp.
928c506b8Sjruoho * All rights reserved.
1028c506b8Sjruoho *
11124f4c82Sjruoho * Redistribution and use in source and binary forms, with or without
12124f4c82Sjruoho * modification, are permitted provided that the following conditions
13124f4c82Sjruoho * are met:
14124f4c82Sjruoho * 1. Redistributions of source code must retain the above copyright
15124f4c82Sjruoho * notice, this list of conditions, and the following disclaimer,
16124f4c82Sjruoho * without modification.
17124f4c82Sjruoho * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18124f4c82Sjruoho * substantially similar to the "NO WARRANTY" disclaimer below
19124f4c82Sjruoho * ("Disclaimer") and any redistribution must be conditioned upon
20124f4c82Sjruoho * including a substantially similar Disclaimer requirement for further
21124f4c82Sjruoho * binary redistribution.
22124f4c82Sjruoho * 3. Neither the names of the above-listed copyright holders nor the names
23124f4c82Sjruoho * of any contributors may be used to endorse or promote products derived
24124f4c82Sjruoho * from this software without specific prior written permission.
2528c506b8Sjruoho *
26124f4c82Sjruoho * Alternatively, this software may be distributed under the terms of the
27124f4c82Sjruoho * GNU General Public License ("GPL") version 2 as published by the Free
28124f4c82Sjruoho * Software Foundation.
2928c506b8Sjruoho *
30124f4c82Sjruoho * NO WARRANTY
31124f4c82Sjruoho * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32124f4c82Sjruoho * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3346a330b4Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34124f4c82Sjruoho * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35124f4c82Sjruoho * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36124f4c82Sjruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37124f4c82Sjruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38124f4c82Sjruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39124f4c82Sjruoho * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40124f4c82Sjruoho * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41124f4c82Sjruoho * POSSIBILITY OF SUCH DAMAGES.
42124f4c82Sjruoho */
4328c506b8Sjruoho
4428c506b8Sjruoho #include "acpi.h"
4528c506b8Sjruoho #include "accommon.h"
4628c506b8Sjruoho #include "acdebug.h"
4728c506b8Sjruoho
4828c506b8Sjruoho #define _COMPONENT ACPI_UTILITIES
4928c506b8Sjruoho ACPI_MODULE_NAME ("utalloc")
5028c506b8Sjruoho
5128c506b8Sjruoho
52ff4a156dSchristos #if !defined (USE_NATIVE_ALLOCATE_ZEROED)
53ff4a156dSchristos /*******************************************************************************
54ff4a156dSchristos *
55ff4a156dSchristos * FUNCTION: AcpiOsAllocateZeroed
56ff4a156dSchristos *
57ff4a156dSchristos * PARAMETERS: Size - Size of the allocation
58ff4a156dSchristos *
59ff4a156dSchristos * RETURN: Address of the allocated memory on success, NULL on failure.
60ff4a156dSchristos *
61ff4a156dSchristos * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory.
62ff4a156dSchristos * This is the default implementation. Can be overridden via the
63ff4a156dSchristos * USE_NATIVE_ALLOCATE_ZEROED flag.
64ff4a156dSchristos *
65ff4a156dSchristos ******************************************************************************/
66ff4a156dSchristos
67ff4a156dSchristos void *
AcpiOsAllocateZeroed(ACPI_SIZE Size)68ff4a156dSchristos AcpiOsAllocateZeroed (
69ff4a156dSchristos ACPI_SIZE Size)
70ff4a156dSchristos {
71ff4a156dSchristos void *Allocation;
72ff4a156dSchristos
73ff4a156dSchristos
74ff4a156dSchristos ACPI_FUNCTION_ENTRY ();
75ff4a156dSchristos
76ff4a156dSchristos
77ff4a156dSchristos Allocation = AcpiOsAllocate (Size);
78ff4a156dSchristos if (Allocation)
79ff4a156dSchristos {
80ff4a156dSchristos /* Clear the memory block */
81ff4a156dSchristos
82c72da027Schristos memset (Allocation, 0, Size);
83ff4a156dSchristos }
84ff4a156dSchristos
85ff4a156dSchristos return (Allocation);
86ff4a156dSchristos }
87ff4a156dSchristos
88ff4a156dSchristos #endif /* !USE_NATIVE_ALLOCATE_ZEROED */
89ff4a156dSchristos
90ff4a156dSchristos
9128c506b8Sjruoho /*******************************************************************************
9228c506b8Sjruoho *
9328c506b8Sjruoho * FUNCTION: AcpiUtCreateCaches
9428c506b8Sjruoho *
9528c506b8Sjruoho * PARAMETERS: None
9628c506b8Sjruoho *
9728c506b8Sjruoho * RETURN: Status
9828c506b8Sjruoho *
9928c506b8Sjruoho * DESCRIPTION: Create all local caches
10028c506b8Sjruoho *
10128c506b8Sjruoho ******************************************************************************/
10228c506b8Sjruoho
10328c506b8Sjruoho ACPI_STATUS
AcpiUtCreateCaches(void)10428c506b8Sjruoho AcpiUtCreateCaches (
10528c506b8Sjruoho void)
10628c506b8Sjruoho {
10728c506b8Sjruoho ACPI_STATUS Status;
10828c506b8Sjruoho
10928c506b8Sjruoho
11028c506b8Sjruoho /* Object Caches, for frequently used objects */
11128c506b8Sjruoho
11228c506b8Sjruoho Status = AcpiOsCreateCache ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE),
11328c506b8Sjruoho ACPI_MAX_NAMESPACE_CACHE_DEPTH, &AcpiGbl_NamespaceCache);
11428c506b8Sjruoho if (ACPI_FAILURE (Status))
11528c506b8Sjruoho {
11628c506b8Sjruoho return (Status);
11728c506b8Sjruoho }
11828c506b8Sjruoho
11928c506b8Sjruoho Status = AcpiOsCreateCache ("Acpi-State", sizeof (ACPI_GENERIC_STATE),
12028c506b8Sjruoho ACPI_MAX_STATE_CACHE_DEPTH, &AcpiGbl_StateCache);
12128c506b8Sjruoho if (ACPI_FAILURE (Status))
12228c506b8Sjruoho {
12328c506b8Sjruoho return (Status);
12428c506b8Sjruoho }
12528c506b8Sjruoho
12628c506b8Sjruoho Status = AcpiOsCreateCache ("Acpi-Parse", sizeof (ACPI_PARSE_OBJ_COMMON),
12728c506b8Sjruoho ACPI_MAX_PARSE_CACHE_DEPTH, &AcpiGbl_PsNodeCache);
12828c506b8Sjruoho if (ACPI_FAILURE (Status))
12928c506b8Sjruoho {
13028c506b8Sjruoho return (Status);
13128c506b8Sjruoho }
13228c506b8Sjruoho
13328c506b8Sjruoho Status = AcpiOsCreateCache ("Acpi-ParseExt", sizeof (ACPI_PARSE_OBJ_NAMED),
13428c506b8Sjruoho ACPI_MAX_EXTPARSE_CACHE_DEPTH, &AcpiGbl_PsNodeExtCache);
13528c506b8Sjruoho if (ACPI_FAILURE (Status))
13628c506b8Sjruoho {
13728c506b8Sjruoho return (Status);
13828c506b8Sjruoho }
13928c506b8Sjruoho
14028c506b8Sjruoho Status = AcpiOsCreateCache ("Acpi-Operand", sizeof (ACPI_OPERAND_OBJECT),
14128c506b8Sjruoho ACPI_MAX_OBJECT_CACHE_DEPTH, &AcpiGbl_OperandCache);
14228c506b8Sjruoho if (ACPI_FAILURE (Status))
14328c506b8Sjruoho {
14428c506b8Sjruoho return (Status);
14528c506b8Sjruoho }
14628c506b8Sjruoho
147835858a6Schristos #ifdef ACPI_ASL_COMPILER
148835858a6Schristos /*
149835858a6Schristos * For use with the ASL-/ASL+ option. This cache keeps track of regular
150835858a6Schristos * 0xA9 0x01 comments.
151835858a6Schristos */
152835858a6Schristos Status = AcpiOsCreateCache ("Acpi-Comment", sizeof (ACPI_COMMENT_NODE),
153835858a6Schristos ACPI_MAX_COMMENT_CACHE_DEPTH, &AcpiGbl_RegCommentCache);
154835858a6Schristos if (ACPI_FAILURE (Status))
155835858a6Schristos {
156835858a6Schristos return (Status);
157835858a6Schristos }
158835858a6Schristos
159835858a6Schristos /*
160835858a6Schristos * This cache keeps track of the starting addresses of where the comments
161835858a6Schristos * lie. This helps prevent duplication of comments.
162835858a6Schristos */
163835858a6Schristos Status = AcpiOsCreateCache ("Acpi-Comment-Addr", sizeof (ACPI_COMMENT_ADDR_NODE),
164835858a6Schristos ACPI_MAX_COMMENT_CACHE_DEPTH, &AcpiGbl_CommentAddrCache);
165835858a6Schristos if (ACPI_FAILURE (Status))
166835858a6Schristos {
167835858a6Schristos return (Status);
168835858a6Schristos }
169835858a6Schristos
170835858a6Schristos /*
171835858a6Schristos * This cache will be used for nodes that represent files.
172835858a6Schristos */
173835858a6Schristos Status = AcpiOsCreateCache ("Acpi-File", sizeof (ACPI_FILE_NODE),
174835858a6Schristos ACPI_MAX_COMMENT_CACHE_DEPTH, &AcpiGbl_FileCache);
175835858a6Schristos if (ACPI_FAILURE (Status))
176835858a6Schristos {
177835858a6Schristos return (Status);
178835858a6Schristos }
179835858a6Schristos #endif
180835858a6Schristos
18128c506b8Sjruoho
18228c506b8Sjruoho #ifdef ACPI_DBG_TRACK_ALLOCATIONS
18328c506b8Sjruoho
18428c506b8Sjruoho /* Memory allocation lists */
18528c506b8Sjruoho
18628c506b8Sjruoho Status = AcpiUtCreateList ("Acpi-Global", 0,
18728c506b8Sjruoho &AcpiGbl_GlobalList);
18828c506b8Sjruoho if (ACPI_FAILURE (Status))
18928c506b8Sjruoho {
19028c506b8Sjruoho return (Status);
19128c506b8Sjruoho }
19228c506b8Sjruoho
19328c506b8Sjruoho Status = AcpiUtCreateList ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE),
19428c506b8Sjruoho &AcpiGbl_NsNodeList);
19528c506b8Sjruoho if (ACPI_FAILURE (Status))
19628c506b8Sjruoho {
19728c506b8Sjruoho return (Status);
19828c506b8Sjruoho }
19928c506b8Sjruoho #endif
20028c506b8Sjruoho
20128c506b8Sjruoho return (AE_OK);
20228c506b8Sjruoho }
20328c506b8Sjruoho
20428c506b8Sjruoho
20528c506b8Sjruoho /*******************************************************************************
20628c506b8Sjruoho *
20728c506b8Sjruoho * FUNCTION: AcpiUtDeleteCaches
20828c506b8Sjruoho *
20928c506b8Sjruoho * PARAMETERS: None
21028c506b8Sjruoho *
21128c506b8Sjruoho * RETURN: Status
21228c506b8Sjruoho *
21328c506b8Sjruoho * DESCRIPTION: Purge and delete all local caches
21428c506b8Sjruoho *
21528c506b8Sjruoho ******************************************************************************/
21628c506b8Sjruoho
21728c506b8Sjruoho ACPI_STATUS
AcpiUtDeleteCaches(void)21828c506b8Sjruoho AcpiUtDeleteCaches (
21928c506b8Sjruoho void)
22028c506b8Sjruoho {
22128c506b8Sjruoho #ifdef ACPI_DBG_TRACK_ALLOCATIONS
22228c506b8Sjruoho char Buffer[7];
22328c506b8Sjruoho
22471e38f1dSchristos
22528c506b8Sjruoho if (AcpiGbl_DisplayFinalMemStats)
22628c506b8Sjruoho {
227c72da027Schristos strcpy (Buffer, "MEMORY");
22828c506b8Sjruoho (void) AcpiDbDisplayStatistics (Buffer);
22928c506b8Sjruoho }
23028c506b8Sjruoho #endif
23128c506b8Sjruoho
23228c506b8Sjruoho (void) AcpiOsDeleteCache (AcpiGbl_NamespaceCache);
23328c506b8Sjruoho AcpiGbl_NamespaceCache = NULL;
23428c506b8Sjruoho
23528c506b8Sjruoho (void) AcpiOsDeleteCache (AcpiGbl_StateCache);
23628c506b8Sjruoho AcpiGbl_StateCache = NULL;
23728c506b8Sjruoho
23828c506b8Sjruoho (void) AcpiOsDeleteCache (AcpiGbl_OperandCache);
23928c506b8Sjruoho AcpiGbl_OperandCache = NULL;
24028c506b8Sjruoho
24128c506b8Sjruoho (void) AcpiOsDeleteCache (AcpiGbl_PsNodeCache);
24228c506b8Sjruoho AcpiGbl_PsNodeCache = NULL;
24328c506b8Sjruoho
24428c506b8Sjruoho (void) AcpiOsDeleteCache (AcpiGbl_PsNodeExtCache);
24528c506b8Sjruoho AcpiGbl_PsNodeExtCache = NULL;
24628c506b8Sjruoho
247835858a6Schristos #ifdef ACPI_ASL_COMPILER
248835858a6Schristos (void) AcpiOsDeleteCache (AcpiGbl_RegCommentCache);
249835858a6Schristos AcpiGbl_RegCommentCache = NULL;
250835858a6Schristos
251835858a6Schristos (void) AcpiOsDeleteCache (AcpiGbl_CommentAddrCache);
252835858a6Schristos AcpiGbl_CommentAddrCache = NULL;
253835858a6Schristos
254835858a6Schristos (void) AcpiOsDeleteCache (AcpiGbl_FileCache);
255835858a6Schristos AcpiGbl_FileCache = NULL;
256835858a6Schristos #endif
25728c506b8Sjruoho
25828c506b8Sjruoho #ifdef ACPI_DBG_TRACK_ALLOCATIONS
25928c506b8Sjruoho
26028c506b8Sjruoho /* Debug only - display leftover memory allocation, if any */
26128c506b8Sjruoho
26228c506b8Sjruoho AcpiUtDumpAllocations (ACPI_UINT32_MAX, NULL);
26328c506b8Sjruoho
26428c506b8Sjruoho /* Free memory lists */
26528c506b8Sjruoho
26628c506b8Sjruoho AcpiOsFree (AcpiGbl_GlobalList);
26728c506b8Sjruoho AcpiGbl_GlobalList = NULL;
26828c506b8Sjruoho
26928c506b8Sjruoho AcpiOsFree (AcpiGbl_NsNodeList);
27028c506b8Sjruoho AcpiGbl_NsNodeList = NULL;
27128c506b8Sjruoho #endif
27228c506b8Sjruoho
27328c506b8Sjruoho return (AE_OK);
27428c506b8Sjruoho }
27528c506b8Sjruoho
27628c506b8Sjruoho
27728c506b8Sjruoho /*******************************************************************************
27828c506b8Sjruoho *
27928c506b8Sjruoho * FUNCTION: AcpiUtValidateBuffer
28028c506b8Sjruoho *
28128c506b8Sjruoho * PARAMETERS: Buffer - Buffer descriptor to be validated
28228c506b8Sjruoho *
28328c506b8Sjruoho * RETURN: Status
28428c506b8Sjruoho *
28528c506b8Sjruoho * DESCRIPTION: Perform parameter validation checks on an ACPI_BUFFER
28628c506b8Sjruoho *
28728c506b8Sjruoho ******************************************************************************/
28828c506b8Sjruoho
28928c506b8Sjruoho ACPI_STATUS
AcpiUtValidateBuffer(ACPI_BUFFER * Buffer)29028c506b8Sjruoho AcpiUtValidateBuffer (
29128c506b8Sjruoho ACPI_BUFFER *Buffer)
29228c506b8Sjruoho {
29328c506b8Sjruoho
29428c506b8Sjruoho /* Obviously, the structure pointer must be valid */
29528c506b8Sjruoho
29628c506b8Sjruoho if (!Buffer)
29728c506b8Sjruoho {
29828c506b8Sjruoho return (AE_BAD_PARAMETER);
29928c506b8Sjruoho }
30028c506b8Sjruoho
30128c506b8Sjruoho /* Special semantics for the length */
30228c506b8Sjruoho
30328c506b8Sjruoho if ((Buffer->Length == ACPI_NO_BUFFER) ||
30428c506b8Sjruoho (Buffer->Length == ACPI_ALLOCATE_BUFFER) ||
30528c506b8Sjruoho (Buffer->Length == ACPI_ALLOCATE_LOCAL_BUFFER))
30628c506b8Sjruoho {
30728c506b8Sjruoho return (AE_OK);
30828c506b8Sjruoho }
30928c506b8Sjruoho
31028c506b8Sjruoho /* Length is valid, the buffer pointer must be also */
31128c506b8Sjruoho
31228c506b8Sjruoho if (!Buffer->Pointer)
31328c506b8Sjruoho {
31428c506b8Sjruoho return (AE_BAD_PARAMETER);
31528c506b8Sjruoho }
31628c506b8Sjruoho
31728c506b8Sjruoho return (AE_OK);
31828c506b8Sjruoho }
31928c506b8Sjruoho
32028c506b8Sjruoho
32128c506b8Sjruoho /*******************************************************************************
32228c506b8Sjruoho *
32328c506b8Sjruoho * FUNCTION: AcpiUtInitializeBuffer
32428c506b8Sjruoho *
32528c506b8Sjruoho * PARAMETERS: Buffer - Buffer to be validated
32628c506b8Sjruoho * RequiredLength - Length needed
32728c506b8Sjruoho *
32828c506b8Sjruoho * RETURN: Status
32928c506b8Sjruoho *
33028c506b8Sjruoho * DESCRIPTION: Validate that the buffer is of the required length or
33128c506b8Sjruoho * allocate a new buffer. Returned buffer is always zeroed.
33228c506b8Sjruoho *
33328c506b8Sjruoho ******************************************************************************/
33428c506b8Sjruoho
33528c506b8Sjruoho ACPI_STATUS
AcpiUtInitializeBuffer(ACPI_BUFFER * Buffer,ACPI_SIZE RequiredLength)33628c506b8Sjruoho AcpiUtInitializeBuffer (
33728c506b8Sjruoho ACPI_BUFFER *Buffer,
33828c506b8Sjruoho ACPI_SIZE RequiredLength)
33928c506b8Sjruoho {
34028c506b8Sjruoho ACPI_SIZE InputBufferLength;
34128c506b8Sjruoho
34228c506b8Sjruoho
34328c506b8Sjruoho /* Parameter validation */
34428c506b8Sjruoho
34528c506b8Sjruoho if (!Buffer || !RequiredLength)
34628c506b8Sjruoho {
34728c506b8Sjruoho return (AE_BAD_PARAMETER);
34828c506b8Sjruoho }
34928c506b8Sjruoho
35028c506b8Sjruoho /*
35128c506b8Sjruoho * Buffer->Length is used as both an input and output parameter. Get the
35228c506b8Sjruoho * input actual length and set the output required buffer length.
35328c506b8Sjruoho */
35428c506b8Sjruoho InputBufferLength = Buffer->Length;
35528c506b8Sjruoho Buffer->Length = RequiredLength;
35628c506b8Sjruoho
35728c506b8Sjruoho /*
35828c506b8Sjruoho * The input buffer length contains the actual buffer length, or the type
35928c506b8Sjruoho * of buffer to be allocated by this routine.
36028c506b8Sjruoho */
36128c506b8Sjruoho switch (InputBufferLength)
36228c506b8Sjruoho {
36328c506b8Sjruoho case ACPI_NO_BUFFER:
36428c506b8Sjruoho
36528c506b8Sjruoho /* Return the exception (and the required buffer length) */
36628c506b8Sjruoho
36728c506b8Sjruoho return (AE_BUFFER_OVERFLOW);
36828c506b8Sjruoho
36928c506b8Sjruoho case ACPI_ALLOCATE_BUFFER:
370ff4a156dSchristos /*
371ff4a156dSchristos * Allocate a new buffer. We directectly call AcpiOsAllocate here to
372ff4a156dSchristos * purposefully bypass the (optionally enabled) internal allocation
373ff4a156dSchristos * tracking mechanism since we only want to track internal
374ff4a156dSchristos * allocations. Note: The caller should use AcpiOsFree to free this
375ff4a156dSchristos * buffer created via ACPI_ALLOCATE_BUFFER.
376ff4a156dSchristos */
37728c506b8Sjruoho Buffer->Pointer = AcpiOsAllocate (RequiredLength);
37828c506b8Sjruoho break;
37928c506b8Sjruoho
38028c506b8Sjruoho case ACPI_ALLOCATE_LOCAL_BUFFER:
38128c506b8Sjruoho
38228c506b8Sjruoho /* Allocate a new buffer with local interface to allow tracking */
38328c506b8Sjruoho
38428c506b8Sjruoho Buffer->Pointer = ACPI_ALLOCATE (RequiredLength);
38528c506b8Sjruoho break;
38628c506b8Sjruoho
38728c506b8Sjruoho default:
38828c506b8Sjruoho
38928c506b8Sjruoho /* Existing buffer: Validate the size of the buffer */
39028c506b8Sjruoho
39128c506b8Sjruoho if (InputBufferLength < RequiredLength)
39228c506b8Sjruoho {
39328c506b8Sjruoho return (AE_BUFFER_OVERFLOW);
39428c506b8Sjruoho }
39528c506b8Sjruoho break;
39628c506b8Sjruoho }
39728c506b8Sjruoho
39828c506b8Sjruoho /* Validate allocation from above or input buffer pointer */
39928c506b8Sjruoho
40028c506b8Sjruoho if (!Buffer->Pointer)
40128c506b8Sjruoho {
40228c506b8Sjruoho return (AE_NO_MEMORY);
40328c506b8Sjruoho }
40428c506b8Sjruoho
40528c506b8Sjruoho /* Have a valid buffer, clear it */
40628c506b8Sjruoho
407c72da027Schristos memset (Buffer->Pointer, 0, RequiredLength);
40828c506b8Sjruoho return (AE_OK);
40928c506b8Sjruoho }
410