linux/drivers/acpi/acpica/utalloc.c
<<
>>
Prefs
   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
  15ACPI_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 ******************************************************************************/
  31void *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
  62acpi_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
 183acpi_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
 250acpi_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
 290acpi_status
 291acpi_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