Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: utalloc - local memory allocation routines
5 : : *
6 : : * Copyright (C) 2000 - 2020, Intel Corp.
7 : : *
8 : : *****************************************************************************/
9 : :
10 : : #include <acpi/acpi.h>
11 : : #include "accommon.h"
12 : : #include "acdebug.h"
13 : :
14 : : #define _COMPONENT ACPI_UTILITIES
15 : : ACPI_MODULE_NAME("utalloc")
16 : :
17 : : #if !defined (USE_NATIVE_ALLOCATE_ZEROED)
18 : : /*******************************************************************************
19 : : *
20 : : * FUNCTION: acpi_os_allocate_zeroed
21 : : *
22 : : * PARAMETERS: size - Size of the allocation
23 : : *
24 : : * RETURN: Address of the allocated memory on success, NULL on failure.
25 : : *
26 : : * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory.
27 : : * This is the default implementation. Can be overridden via the
28 : : * USE_NATIVE_ALLOCATE_ZEROED flag.
29 : : *
30 : : ******************************************************************************/
31 : : void *acpi_os_allocate_zeroed(acpi_size size)
32 : : {
33 : : void *allocation;
34 : :
35 : : ACPI_FUNCTION_ENTRY();
36 : :
37 : : allocation = acpi_os_allocate(size);
38 : : if (allocation) {
39 : :
40 : : /* Clear the memory block */
41 : :
42 : : memset(allocation, 0, size);
43 : : }
44 : :
45 : : return (allocation);
46 : : }
47 : :
48 : : #endif /* !USE_NATIVE_ALLOCATE_ZEROED */
49 : :
50 : : /*******************************************************************************
51 : : *
52 : : * FUNCTION: acpi_ut_create_caches
53 : : *
54 : : * PARAMETERS: None
55 : : *
56 : : * RETURN: Status
57 : : *
58 : : * DESCRIPTION: Create all local caches
59 : : *
60 : : ******************************************************************************/
61 : :
62 : 30 : acpi_status acpi_ut_create_caches(void)
63 : : {
64 : 30 : acpi_status status;
65 : :
66 : : /* Object Caches, for frequently used objects */
67 : :
68 : 30 : status =
69 : 30 : acpi_os_create_cache("Acpi-Namespace",
70 : : sizeof(struct acpi_namespace_node),
71 : : ACPI_MAX_NAMESPACE_CACHE_DEPTH,
72 : : &acpi_gbl_namespace_cache);
73 [ + - ]: 30 : if (ACPI_FAILURE(status)) {
74 : : return (status);
75 : : }
76 : :
77 : 30 : status =
78 : 30 : acpi_os_create_cache("Acpi-State", sizeof(union acpi_generic_state),
79 : : ACPI_MAX_STATE_CACHE_DEPTH,
80 : : &acpi_gbl_state_cache);
81 [ + - ]: 30 : if (ACPI_FAILURE(status)) {
82 : : return (status);
83 : : }
84 : :
85 : 30 : status =
86 : 30 : acpi_os_create_cache("Acpi-Parse",
87 : : sizeof(struct acpi_parse_obj_common),
88 : : ACPI_MAX_PARSE_CACHE_DEPTH,
89 : : &acpi_gbl_ps_node_cache);
90 [ + - ]: 30 : if (ACPI_FAILURE(status)) {
91 : : return (status);
92 : : }
93 : :
94 : 30 : status =
95 : 30 : acpi_os_create_cache("Acpi-ParseExt",
96 : : sizeof(struct acpi_parse_obj_named),
97 : : ACPI_MAX_EXTPARSE_CACHE_DEPTH,
98 : : &acpi_gbl_ps_node_ext_cache);
99 [ + - ]: 30 : if (ACPI_FAILURE(status)) {
100 : : return (status);
101 : : }
102 : :
103 : 30 : status =
104 : 30 : acpi_os_create_cache("Acpi-Operand",
105 : : sizeof(union acpi_operand_object),
106 : : ACPI_MAX_OBJECT_CACHE_DEPTH,
107 : : &acpi_gbl_operand_cache);
108 : 30 : if (ACPI_FAILURE(status)) {
109 : : return (status);
110 : : }
111 : : #ifdef ACPI_ASL_COMPILER
112 : : /*
113 : : * For use with the ASL-/ASL+ option. This cache keeps track of regular
114 : : * 0xA9 0x01 comments.
115 : : */
116 : : status =
117 : : acpi_os_create_cache("Acpi-Comment",
118 : : sizeof(struct acpi_comment_node),
119 : : ACPI_MAX_COMMENT_CACHE_DEPTH,
120 : : &acpi_gbl_reg_comment_cache);
121 : : if (ACPI_FAILURE(status)) {
122 : : return (status);
123 : : }
124 : :
125 : : /*
126 : : * This cache keeps track of the starting addresses of where the comments
127 : : * lie. This helps prevent duplication of comments.
128 : : */
129 : : status =
130 : : acpi_os_create_cache("Acpi-Comment-Addr",
131 : : sizeof(struct acpi_comment_addr_node),
132 : : ACPI_MAX_COMMENT_CACHE_DEPTH,
133 : : &acpi_gbl_comment_addr_cache);
134 : : if (ACPI_FAILURE(status)) {
135 : : return (status);
136 : : }
137 : :
138 : : /*
139 : : * This cache will be used for nodes that represent files.
140 : : */
141 : : status =
142 : : acpi_os_create_cache("Acpi-File", sizeof(struct acpi_file_node),
143 : : ACPI_MAX_COMMENT_CACHE_DEPTH,
144 : : &acpi_gbl_file_cache);
145 : : if (ACPI_FAILURE(status)) {
146 : : return (status);
147 : : }
148 : : #endif
149 : :
150 : : #ifdef ACPI_DBG_TRACK_ALLOCATIONS
151 : :
152 : : /* Memory allocation lists */
153 : :
154 : : status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list);
155 : : if (ACPI_FAILURE(status)) {
156 : : return (status);
157 : : }
158 : :
159 : : status =
160 : : acpi_ut_create_list("Acpi-Namespace",
161 : : sizeof(struct acpi_namespace_node),
162 : : &acpi_gbl_ns_node_list);
163 : : if (ACPI_FAILURE(status)) {
164 : : return (status);
165 : : }
166 : : #endif
167 : :
168 : : return (AE_OK);
169 : : }
170 : :
171 : : /*******************************************************************************
172 : : *
173 : : * FUNCTION: acpi_ut_delete_caches
174 : : *
175 : : * PARAMETERS: None
176 : : *
177 : : * RETURN: Status
178 : : *
179 : : * DESCRIPTION: Purge and delete all local caches
180 : : *
181 : : ******************************************************************************/
182 : :
183 : 0 : acpi_status acpi_ut_delete_caches(void)
184 : : {
185 : : #ifdef ACPI_DBG_TRACK_ALLOCATIONS
186 : : char buffer[7];
187 : :
188 : : if (acpi_gbl_display_final_mem_stats) {
189 : : strcpy(buffer, "MEMORY");
190 : : (void)acpi_db_display_statistics(buffer);
191 : : }
192 : : #endif
193 : :
194 : 0 : (void)acpi_os_delete_cache(acpi_gbl_namespace_cache);
195 : 0 : acpi_gbl_namespace_cache = NULL;
196 : :
197 : 0 : (void)acpi_os_delete_cache(acpi_gbl_state_cache);
198 : 0 : acpi_gbl_state_cache = NULL;
199 : :
200 : 0 : (void)acpi_os_delete_cache(acpi_gbl_operand_cache);
201 : 0 : acpi_gbl_operand_cache = NULL;
202 : :
203 : 0 : (void)acpi_os_delete_cache(acpi_gbl_ps_node_cache);
204 : 0 : acpi_gbl_ps_node_cache = NULL;
205 : :
206 : 0 : (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache);
207 : 0 : acpi_gbl_ps_node_ext_cache = NULL;
208 : :
209 : : #ifdef ACPI_ASL_COMPILER
210 : : (void)acpi_os_delete_cache(acpi_gbl_reg_comment_cache);
211 : : acpi_gbl_reg_comment_cache = NULL;
212 : :
213 : : (void)acpi_os_delete_cache(acpi_gbl_comment_addr_cache);
214 : : acpi_gbl_comment_addr_cache = NULL;
215 : :
216 : : (void)acpi_os_delete_cache(acpi_gbl_file_cache);
217 : : acpi_gbl_file_cache = NULL;
218 : : #endif
219 : :
220 : : #ifdef ACPI_DBG_TRACK_ALLOCATIONS
221 : :
222 : : /* Debug only - display leftover memory allocation, if any */
223 : :
224 : : acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL);
225 : :
226 : : /* Free memory lists */
227 : :
228 : : acpi_os_free(acpi_gbl_global_list);
229 : : acpi_gbl_global_list = NULL;
230 : :
231 : : acpi_os_free(acpi_gbl_ns_node_list);
232 : : acpi_gbl_ns_node_list = NULL;
233 : : #endif
234 : :
235 : 0 : return (AE_OK);
236 : : }
237 : :
238 : : /*******************************************************************************
239 : : *
240 : : * FUNCTION: acpi_ut_validate_buffer
241 : : *
242 : : * PARAMETERS: buffer - Buffer descriptor to be validated
243 : : *
244 : : * RETURN: Status
245 : : *
246 : : * DESCRIPTION: Perform parameter validation checks on an struct acpi_buffer
247 : : *
248 : : ******************************************************************************/
249 : :
250 : 3504 : acpi_status acpi_ut_validate_buffer(struct acpi_buffer *buffer)
251 : : {
252 : :
253 : : /* Obviously, the structure pointer must be valid */
254 : :
255 [ + - ]: 3504 : if (!buffer) {
256 : : return (AE_BAD_PARAMETER);
257 : : }
258 : :
259 : : /* Special semantics for the length */
260 : :
261 : 3504 : if ((buffer->length == ACPI_NO_BUFFER) ||
262 [ + + ]: 3504 : (buffer->length == ACPI_ALLOCATE_BUFFER) ||
263 : : (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) {
264 : : return (AE_OK);
265 : : }
266 : :
267 : : /* Length is valid, the buffer pointer must be also */
268 : :
269 [ - + ]: 1710 : if (!buffer->pointer) {
270 : 0 : return (AE_BAD_PARAMETER);
271 : : }
272 : :
273 : : return (AE_OK);
274 : : }
275 : :
276 : : /*******************************************************************************
277 : : *
278 : : * FUNCTION: acpi_ut_initialize_buffer
279 : : *
280 : : * PARAMETERS: buffer - Buffer to be validated
281 : : * required_length - Length needed
282 : : *
283 : : * RETURN: Status
284 : : *
285 : : * DESCRIPTION: Validate that the buffer is of the required length or
286 : : * allocate a new buffer. Returned buffer is always zeroed.
287 : : *
288 : : ******************************************************************************/
289 : :
290 : : acpi_status
291 : 21906 : acpi_ut_initialize_buffer(struct acpi_buffer *buffer, acpi_size required_length)
292 : : {
293 : 21906 : acpi_size input_buffer_length;
294 : :
295 : : /* Parameter validation */
296 : :
297 [ + - ]: 21906 : if (!buffer || !required_length) {
298 : : return (AE_BAD_PARAMETER);
299 : : }
300 : :
301 : : /*
302 : : * Buffer->Length is used as both an input and output parameter. Get the
303 : : * input actual length and set the output required buffer length.
304 : : */
305 : 21906 : input_buffer_length = buffer->length;
306 : 21906 : buffer->length = required_length;
307 : :
308 : : /*
309 : : * The input buffer length contains the actual buffer length, or the type
310 : : * of buffer to be allocated by this routine.
311 : : */
312 [ + + + - ]: 21906 : switch (input_buffer_length) {
313 : : case ACPI_NO_BUFFER:
314 : :
315 : : /* Return the exception (and the required buffer length) */
316 : :
317 : : return (AE_BUFFER_OVERFLOW);
318 : :
319 : 1854 : case ACPI_ALLOCATE_BUFFER:
320 : : /*
321 : : * Allocate a new buffer. We directectly call acpi_os_allocate here to
322 : : * purposefully bypass the (optionally enabled) internal allocation
323 : : * tracking mechanism since we only want to track internal
324 : : * allocations. Note: The caller should use acpi_os_free to free this
325 : : * buffer created via ACPI_ALLOCATE_BUFFER.
326 : : */
327 : 1854 : buffer->pointer = acpi_os_allocate(required_length);
328 : 1854 : break;
329 : :
330 : 1230 : case ACPI_ALLOCATE_LOCAL_BUFFER:
331 : :
332 : : /* Allocate a new buffer with local interface to allow tracking */
333 : :
334 : 1230 : buffer->pointer = ACPI_ALLOCATE(required_length);
335 : 1230 : break;
336 : :
337 : 18822 : default:
338 : :
339 : : /* Existing buffer: Validate the size of the buffer */
340 : :
341 [ + - ]: 18822 : if (input_buffer_length < required_length) {
342 : : return (AE_BUFFER_OVERFLOW);
343 : : }
344 : : break;
345 : : }
346 : :
347 : : /* Validate allocation from above or input buffer pointer */
348 : :
349 [ + - ]: 21906 : if (!buffer->pointer) {
350 : : return (AE_NO_MEMORY);
351 : : }
352 : :
353 : : /* Have a valid buffer, clear it */
354 : :
355 : 21906 : memset(buffer->pointer, 0, required_length);
356 : 21906 : return (AE_OK);
357 : : }
|