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 - 2022, 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 acpi_status acpi_ut_create_caches(void) 63 { 64 acpi_status status; 65 66 /* Object Caches, for frequently used objects */ 67 68 status = 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), 79 ACPI_MAX_STATE_CACHE_DEPTH, 80 &acpi_gbl_state_cache); 81 if (ACPI_FAILURE(status)) { 82 return (status); 83 } 84 85 status = 86 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 if (ACPI_FAILURE(status)) { 91 return (status); 92 } 93 94 status = 95 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 if (ACPI_FAILURE(status)) { 100 return (status); 101 } 102 103 status = 104 acpi_os_create_cache("Acpi-Operand", 105 sizeof(union acpi_operand_object), 106 ACPI_MAX_OBJECT_CACHE_DEPTH, 107 &acpi_gbl_operand_cache); 108 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 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 (void)acpi_os_delete_cache(acpi_gbl_namespace_cache); 195 acpi_gbl_namespace_cache = NULL; 196 197 (void)acpi_os_delete_cache(acpi_gbl_state_cache); 198 acpi_gbl_state_cache = NULL; 199 200 (void)acpi_os_delete_cache(acpi_gbl_operand_cache); 201 acpi_gbl_operand_cache = NULL; 202 203 (void)acpi_os_delete_cache(acpi_gbl_ps_node_cache); 204 acpi_gbl_ps_node_cache = NULL; 205 206 (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache); 207 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 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 acpi_status acpi_ut_validate_buffer(struct acpi_buffer *buffer) 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 261 if ((buffer->length == ACPI_NO_BUFFER) || 262 (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 if (!buffer->pointer) { 270 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 acpi_ut_initialize_buffer(struct acpi_buffer *buffer, acpi_size required_length) 292 { 293 acpi_size input_buffer_length; 294 295 /* Parameter validation */ 296 297 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 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) { 313 case ACPI_NO_BUFFER: 314 315 /* Return the exception (and the required buffer length) */ 316 317 return (AE_BUFFER_OVERFLOW); 318 319 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 buffer->pointer = acpi_os_allocate(required_length); 328 break; 329 330 case ACPI_ALLOCATE_LOCAL_BUFFER: 331 332 /* Allocate a new buffer with local interface to allow tracking */ 333 334 buffer->pointer = ACPI_ALLOCATE(required_length); 335 break; 336 337 default: 338 339 /* Existing buffer: Validate the size of the buffer */ 340 341 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 if (!buffer->pointer) { 350 return (AE_NO_MEMORY); 351 } 352 353 /* Have a valid buffer, clear it */ 354 355 memset(buffer->pointer, 0, required_length); 356 return (AE_OK); 357 } 358