Commit | Line | Data |
---|---|---|
95857638 | 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
1da177e4 LT |
2 | /****************************************************************************** |
3 | * | |
73459f73 | 4 | * Module Name: utalloc - local memory allocation routines |
1da177e4 | 5 | * |
800ba7c5 | 6 | * Copyright (C) 2000 - 2020, Intel Corp. |
1da177e4 | 7 | * |
95857638 | 8 | *****************************************************************************/ |
1da177e4 | 9 | |
1da177e4 | 10 | #include <acpi/acpi.h> |
e2f7a777 LB |
11 | #include "accommon.h" |
12 | #include "acdebug.h" | |
1da177e4 LT |
13 | |
14 | #define _COMPONENT ACPI_UTILITIES | |
4be44fcd | 15 | ACPI_MODULE_NAME("utalloc") |
1da177e4 | 16 | |
b3c86c30 LZ |
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 | ||
4fa4616e | 42 | memset(allocation, 0, size); |
b3c86c30 LZ |
43 | } |
44 | ||
45 | return (allocation); | |
46 | } | |
47 | ||
48 | #endif /* !USE_NATIVE_ALLOCATE_ZEROED */ | |
49 | ||
44f6c012 | 50 | /******************************************************************************* |
1da177e4 | 51 | * |
73459f73 | 52 | * FUNCTION: acpi_ut_create_caches |
1da177e4 | 53 | * |
73459f73 | 54 | * PARAMETERS: None |
1da177e4 | 55 | * |
73459f73 | 56 | * RETURN: Status |
1da177e4 | 57 | * |
73459f73 | 58 | * DESCRIPTION: Create all local caches |
1da177e4 LT |
59 | * |
60 | ******************************************************************************/ | |
b3c86c30 | 61 | |
4be44fcd | 62 | acpi_status acpi_ut_create_caches(void) |
1da177e4 | 63 | { |
4be44fcd | 64 | acpi_status status; |
1da177e4 | 65 | |
73459f73 | 66 | /* Object Caches, for frequently used objects */ |
1da177e4 | 67 | |
4be44fcd | 68 | status = |
61686124 BM |
69 | acpi_os_create_cache("Acpi-Namespace", |
70 | sizeof(struct acpi_namespace_node), | |
71 | ACPI_MAX_NAMESPACE_CACHE_DEPTH, | |
72 | &acpi_gbl_namespace_cache); | |
73 | if (ACPI_FAILURE(status)) { | |
74 | return (status); | |
75 | } | |
76 | ||
77 | status = | |
78 | acpi_os_create_cache("Acpi-State", sizeof(union acpi_generic_state), | |
4be44fcd LB |
79 | ACPI_MAX_STATE_CACHE_DEPTH, |
80 | &acpi_gbl_state_cache); | |
81 | if (ACPI_FAILURE(status)) { | |
73459f73 | 82 | return (status); |
1da177e4 LT |
83 | } |
84 | ||
4be44fcd | 85 | status = |
61686124 | 86 | acpi_os_create_cache("Acpi-Parse", |
4be44fcd LB |
87 | sizeof(struct acpi_parse_obj_common), |
88 | ACPI_MAX_PARSE_CACHE_DEPTH, | |
89 | &acpi_gbl_ps_node_cache); | |
90 | if (ACPI_FAILURE(status)) { | |
73459f73 | 91 | return (status); |
1da177e4 LT |
92 | } |
93 | ||
4be44fcd | 94 | status = |
b229cf92 | 95 | acpi_os_create_cache("Acpi-ParseExt", |
4be44fcd LB |
96 | sizeof(struct acpi_parse_obj_named), |
97 | ACPI_MAX_EXTPARSE_CACHE_DEPTH, | |
98 | &acpi_gbl_ps_node_ext_cache); | |
99 | if (ACPI_FAILURE(status)) { | |
73459f73 RM |
100 | return (status); |
101 | } | |
1da177e4 | 102 | |
4be44fcd | 103 | status = |
61686124 | 104 | acpi_os_create_cache("Acpi-Operand", |
4be44fcd LB |
105 | sizeof(union acpi_operand_object), |
106 | ACPI_MAX_OBJECT_CACHE_DEPTH, | |
107 | &acpi_gbl_operand_cache); | |
108 | if (ACPI_FAILURE(status)) { | |
73459f73 RM |
109 | return (status); |
110 | } | |
9cf7adec BM |
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 | ||
4119532c BM |
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 | ||
73459f73 | 168 | return (AE_OK); |
1da177e4 LT |
169 | } |
170 | ||
44f6c012 | 171 | /******************************************************************************* |
1da177e4 | 172 | * |
73459f73 | 173 | * FUNCTION: acpi_ut_delete_caches |
1da177e4 | 174 | * |
73459f73 | 175 | * PARAMETERS: None |
1da177e4 | 176 | * |
73459f73 | 177 | * RETURN: Status |
1da177e4 | 178 | * |
73459f73 | 179 | * DESCRIPTION: Purge and delete all local caches |
1da177e4 LT |
180 | * |
181 | ******************************************************************************/ | |
182 | ||
4be44fcd | 183 | acpi_status acpi_ut_delete_caches(void) |
1da177e4 | 184 | { |
d41eb99b BM |
185 | #ifdef ACPI_DBG_TRACK_ALLOCATIONS |
186 | char buffer[7]; | |
187 | ||
188 | if (acpi_gbl_display_final_mem_stats) { | |
4fa4616e | 189 | strcpy(buffer, "MEMORY"); |
1d18c058 | 190 | (void)acpi_db_display_statistics(buffer); |
d41eb99b BM |
191 | } |
192 | #endif | |
1da177e4 | 193 | |
61686124 BM |
194 | (void)acpi_os_delete_cache(acpi_gbl_namespace_cache); |
195 | acpi_gbl_namespace_cache = NULL; | |
196 | ||
4be44fcd | 197 | (void)acpi_os_delete_cache(acpi_gbl_state_cache); |
73459f73 | 198 | acpi_gbl_state_cache = NULL; |
1da177e4 | 199 | |
4be44fcd | 200 | (void)acpi_os_delete_cache(acpi_gbl_operand_cache); |
73459f73 | 201 | acpi_gbl_operand_cache = NULL; |
1da177e4 | 202 | |
4be44fcd | 203 | (void)acpi_os_delete_cache(acpi_gbl_ps_node_cache); |
73459f73 | 204 | acpi_gbl_ps_node_cache = NULL; |
1da177e4 | 205 | |
4be44fcd | 206 | (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache); |
73459f73 | 207 | acpi_gbl_ps_node_ext_cache = NULL; |
1da177e4 | 208 | |
9cf7adec BM |
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 | ||
4119532c BM |
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 | ||
dba47d3a | 228 | acpi_os_free(acpi_gbl_global_list); |
4119532c BM |
229 | acpi_gbl_global_list = NULL; |
230 | ||
dba47d3a | 231 | acpi_os_free(acpi_gbl_ns_node_list); |
4119532c BM |
232 | acpi_gbl_ns_node_list = NULL; |
233 | #endif | |
234 | ||
73459f73 | 235 | return (AE_OK); |
1da177e4 | 236 | } |
1da177e4 LT |
237 | |
238 | /******************************************************************************* | |
239 | * | |
240 | * FUNCTION: acpi_ut_validate_buffer | |
241 | * | |
ba494bee | 242 | * PARAMETERS: buffer - Buffer descriptor to be validated |
1da177e4 LT |
243 | * |
244 | * RETURN: Status | |
245 | * | |
246 | * DESCRIPTION: Perform parameter validation checks on an struct acpi_buffer | |
247 | * | |
248 | ******************************************************************************/ | |
249 | ||
f5c1e1c5 | 250 | acpi_status acpi_ut_validate_buffer(struct acpi_buffer *buffer) |
1da177e4 LT |
251 | { |
252 | ||
253 | /* Obviously, the structure pointer must be valid */ | |
254 | ||
255 | if (!buffer) { | |
256 | return (AE_BAD_PARAMETER); | |
257 | } | |
258 | ||
259 | /* Special semantics for the length */ | |
260 | ||
4be44fcd LB |
261 | if ((buffer->length == ACPI_NO_BUFFER) || |
262 | (buffer->length == ACPI_ALLOCATE_BUFFER) || | |
263 | (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) { | |
1da177e4 LT |
264 | return (AE_OK); |
265 | } | |
266 | ||
267 | /* Length is valid, the buffer pointer must be also */ | |
268 | ||
269 | if (!buffer->pointer) { | |
270 | return (AE_BAD_PARAMETER); | |
271 | } | |
272 | ||
273 | return (AE_OK); | |
274 | } | |
275 | ||
1da177e4 LT |
276 | /******************************************************************************* |
277 | * | |
278 | * FUNCTION: acpi_ut_initialize_buffer | |
279 | * | |
ba494bee | 280 | * PARAMETERS: buffer - Buffer to be validated |
1da177e4 LT |
281 | * required_length - Length needed |
282 | * | |
283 | * RETURN: Status | |
284 | * | |
285 | * DESCRIPTION: Validate that the buffer is of the required length or | |
68e125c4 | 286 | * allocate a new buffer. Returned buffer is always zeroed. |
1da177e4 LT |
287 | * |
288 | ******************************************************************************/ | |
289 | ||
290 | acpi_status | |
f5c1e1c5 | 291 | acpi_ut_initialize_buffer(struct acpi_buffer *buffer, acpi_size required_length) |
1da177e4 | 292 | { |
68e125c4 | 293 | acpi_size input_buffer_length; |
1da177e4 | 294 | |
3c7db22a BM |
295 | /* Parameter validation */ |
296 | ||
297 | if (!buffer || !required_length) { | |
298 | return (AE_BAD_PARAMETER); | |
f88133d7 | 299 | } |
3c7db22a | 300 | |
68e125c4 BM |
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 | input_buffer_length = buffer->length; | |
306 | 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 | switch (input_buffer_length) { | |
1da177e4 LT |
313 | case ACPI_NO_BUFFER: |
314 | ||
68e125c4 | 315 | /* Return the exception (and the required buffer length) */ |
1da177e4 | 316 | |
68e125c4 | 317 | return (AE_BUFFER_OVERFLOW); |
1da177e4 | 318 | |
1da177e4 | 319 | case ACPI_ALLOCATE_BUFFER: |
bb3fec14 LZ |
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 | */ | |
4be44fcd | 327 | buffer->pointer = acpi_os_allocate(required_length); |
1da177e4 LT |
328 | break; |
329 | ||
1da177e4 LT |
330 | case ACPI_ALLOCATE_LOCAL_BUFFER: |
331 | ||
332 | /* Allocate a new buffer with local interface to allow tracking */ | |
333 | ||
68e125c4 | 334 | buffer->pointer = ACPI_ALLOCATE(required_length); |
1da177e4 LT |
335 | break; |
336 | ||
1da177e4 LT |
337 | default: |
338 | ||
339 | /* Existing buffer: Validate the size of the buffer */ | |
340 | ||
68e125c4 BM |
341 | if (input_buffer_length < required_length) { |
342 | return (AE_BUFFER_OVERFLOW); | |
1da177e4 | 343 | } |
68e125c4 BM |
344 | break; |
345 | } | |
1da177e4 | 346 | |
68e125c4 | 347 | /* Validate allocation from above or input buffer pointer */ |
1da177e4 | 348 | |
68e125c4 BM |
349 | if (!buffer->pointer) { |
350 | return (AE_NO_MEMORY); | |
1da177e4 LT |
351 | } |
352 | ||
68e125c4 BM |
353 | /* Have a valid buffer, clear it */ |
354 | ||
4fa4616e | 355 | memset(buffer->pointer, 0, required_length); |
68e125c4 | 356 | return (AE_OK); |
1da177e4 | 357 | } |