1 /******************************************************************************
   2  *
   3  * Module Name: utalloc - local memory allocation routines
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 #define __UTALLOC_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acdebug.h"
  49 
  50 #define _COMPONENT          ACPI_UTILITIES
  51         ACPI_MODULE_NAME    ("utalloc")
  52 
  53 
  54 #if !defined (USE_NATIVE_ALLOCATE_ZEROED)
  55 /*******************************************************************************
  56  *
  57  * FUNCTION:    AcpiOsAllocateZeroed
  58  *
  59  * PARAMETERS:  Size                - Size of the allocation
  60  *
  61  * RETURN:      Address of the allocated memory on success, NULL on failure.
  62  *
  63  * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory.
  64  *              This is the default implementation. Can be overridden via the
  65  *              USE_NATIVE_ALLOCATE_ZEROED flag.
  66  *
  67  ******************************************************************************/
  68 
  69 void *
  70 AcpiOsAllocateZeroed (
  71     ACPI_SIZE               Size)
  72 {
  73     void                    *Allocation;
  74 
  75 
  76     ACPI_FUNCTION_ENTRY ();
  77 
  78 
  79     Allocation = AcpiOsAllocate (Size);
  80     if (Allocation)
  81     {
  82         /* Clear the memory block */
  83 
  84         ACPI_MEMSET (Allocation, 0, Size);
  85     }
  86 
  87     return (Allocation);
  88 }
  89 
  90 #endif /* !USE_NATIVE_ALLOCATE_ZEROED */
  91 
  92 
  93 /*******************************************************************************
  94  *
  95  * FUNCTION:    AcpiUtCreateCaches
  96  *
  97  * PARAMETERS:  None
  98  *
  99  * RETURN:      Status
 100  *
 101  * DESCRIPTION: Create all local caches
 102  *
 103  ******************************************************************************/
 104 
 105 ACPI_STATUS
 106 AcpiUtCreateCaches (
 107     void)
 108 {
 109     ACPI_STATUS             Status;
 110 
 111 
 112     /* Object Caches, for frequently used objects */
 113 
 114     Status = AcpiOsCreateCache ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE),
 115                 ACPI_MAX_NAMESPACE_CACHE_DEPTH, &AcpiGbl_NamespaceCache);
 116     if (ACPI_FAILURE (Status))
 117     {
 118         return (Status);
 119     }
 120 
 121     Status = AcpiOsCreateCache ("Acpi-State", sizeof (ACPI_GENERIC_STATE),
 122                 ACPI_MAX_STATE_CACHE_DEPTH, &AcpiGbl_StateCache);
 123     if (ACPI_FAILURE (Status))
 124     {
 125         return (Status);
 126     }
 127 
 128     Status = AcpiOsCreateCache ("Acpi-Parse", sizeof (ACPI_PARSE_OBJ_COMMON),
 129                 ACPI_MAX_PARSE_CACHE_DEPTH, &AcpiGbl_PsNodeCache);
 130     if (ACPI_FAILURE (Status))
 131     {
 132         return (Status);
 133     }
 134 
 135     Status = AcpiOsCreateCache ("Acpi-ParseExt", sizeof (ACPI_PARSE_OBJ_NAMED),
 136                 ACPI_MAX_EXTPARSE_CACHE_DEPTH, &AcpiGbl_PsNodeExtCache);
 137     if (ACPI_FAILURE (Status))
 138     {
 139         return (Status);
 140     }
 141 
 142     Status = AcpiOsCreateCache ("Acpi-Operand", sizeof (ACPI_OPERAND_OBJECT),
 143                 ACPI_MAX_OBJECT_CACHE_DEPTH, &AcpiGbl_OperandCache);
 144     if (ACPI_FAILURE (Status))
 145     {
 146         return (Status);
 147     }
 148 
 149 
 150 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 151 
 152     /* Memory allocation lists */
 153 
 154     Status = AcpiUtCreateList ("Acpi-Global", 0,
 155                 &AcpiGbl_GlobalList);
 156     if (ACPI_FAILURE (Status))
 157     {
 158         return (Status);
 159     }
 160 
 161     Status = AcpiUtCreateList ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE),
 162                 &AcpiGbl_NsNodeList);
 163     if (ACPI_FAILURE (Status))
 164     {
 165         return (Status);
 166     }
 167 #endif
 168 
 169     return (AE_OK);
 170 }
 171 
 172 
 173 /*******************************************************************************
 174  *
 175  * FUNCTION:    AcpiUtDeleteCaches
 176  *
 177  * PARAMETERS:  None
 178  *
 179  * RETURN:      Status
 180  *
 181  * DESCRIPTION: Purge and delete all local caches
 182  *
 183  ******************************************************************************/
 184 
 185 ACPI_STATUS
 186 AcpiUtDeleteCaches (
 187     void)
 188 {
 189 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 190     char                    Buffer[7];
 191 
 192     if (AcpiGbl_DisplayFinalMemStats)
 193     {
 194         ACPI_STRCPY (Buffer, "MEMORY");
 195         (void) AcpiDbDisplayStatistics (Buffer);
 196     }
 197 #endif
 198 
 199     (void) AcpiOsDeleteCache (AcpiGbl_NamespaceCache);
 200     AcpiGbl_NamespaceCache = NULL;
 201 
 202     (void) AcpiOsDeleteCache (AcpiGbl_StateCache);
 203     AcpiGbl_StateCache = NULL;
 204 
 205     (void) AcpiOsDeleteCache (AcpiGbl_OperandCache);
 206     AcpiGbl_OperandCache = NULL;
 207 
 208     (void) AcpiOsDeleteCache (AcpiGbl_PsNodeCache);
 209     AcpiGbl_PsNodeCache = NULL;
 210 
 211     (void) AcpiOsDeleteCache (AcpiGbl_PsNodeExtCache);
 212     AcpiGbl_PsNodeExtCache = NULL;
 213 
 214 
 215 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 216 
 217     /* Debug only - display leftover memory allocation, if any */
 218 
 219     AcpiUtDumpAllocations (ACPI_UINT32_MAX, NULL);
 220 
 221     /* Free memory lists */
 222 
 223     AcpiOsFree (AcpiGbl_GlobalList);
 224     AcpiGbl_GlobalList = NULL;
 225 
 226     AcpiOsFree (AcpiGbl_NsNodeList);
 227     AcpiGbl_NsNodeList = NULL;
 228 #endif
 229 
 230     return (AE_OK);
 231 }
 232 
 233 
 234 /*******************************************************************************
 235  *
 236  * FUNCTION:    AcpiUtValidateBuffer
 237  *
 238  * PARAMETERS:  Buffer              - Buffer descriptor to be validated
 239  *
 240  * RETURN:      Status
 241  *
 242  * DESCRIPTION: Perform parameter validation checks on an ACPI_BUFFER
 243  *
 244  ******************************************************************************/
 245 
 246 ACPI_STATUS
 247 AcpiUtValidateBuffer (
 248     ACPI_BUFFER             *Buffer)
 249 {
 250 
 251     /* Obviously, the structure pointer must be valid */
 252 
 253     if (!Buffer)
 254     {
 255         return (AE_BAD_PARAMETER);
 256     }
 257 
 258     /* Special semantics for the length */
 259 
 260     if ((Buffer->Length == ACPI_NO_BUFFER)              ||
 261         (Buffer->Length == ACPI_ALLOCATE_BUFFER)        ||
 262         (Buffer->Length == ACPI_ALLOCATE_LOCAL_BUFFER))
 263     {
 264         return (AE_OK);
 265     }
 266 
 267     /* Length is valid, the buffer pointer must be also */
 268 
 269     if (!Buffer->Pointer)
 270     {
 271         return (AE_BAD_PARAMETER);
 272     }
 273 
 274     return (AE_OK);
 275 }
 276 
 277 
 278 /*******************************************************************************
 279  *
 280  * FUNCTION:    AcpiUtInitializeBuffer
 281  *
 282  * PARAMETERS:  Buffer              - Buffer to be validated
 283  *              RequiredLength      - Length needed
 284  *
 285  * RETURN:      Status
 286  *
 287  * DESCRIPTION: Validate that the buffer is of the required length or
 288  *              allocate a new buffer. Returned buffer is always zeroed.
 289  *
 290  ******************************************************************************/
 291 
 292 ACPI_STATUS
 293 AcpiUtInitializeBuffer (
 294     ACPI_BUFFER             *Buffer,
 295     ACPI_SIZE               RequiredLength)
 296 {
 297     ACPI_SIZE               InputBufferLength;
 298 
 299 
 300     /* Parameter validation */
 301 
 302     if (!Buffer || !RequiredLength)
 303     {
 304         return (AE_BAD_PARAMETER);
 305     }
 306 
 307     /*
 308      * Buffer->Length is used as both an input and output parameter. Get the
 309      * input actual length and set the output required buffer length.
 310      */
 311     InputBufferLength = Buffer->Length;
 312     Buffer->Length = RequiredLength;
 313 
 314     /*
 315      * The input buffer length contains the actual buffer length, or the type
 316      * of buffer to be allocated by this routine.
 317      */
 318     switch (InputBufferLength)
 319     {
 320     case ACPI_NO_BUFFER:
 321 
 322         /* Return the exception (and the required buffer length) */
 323 
 324         return (AE_BUFFER_OVERFLOW);
 325 
 326     case ACPI_ALLOCATE_BUFFER:
 327         /*
 328          * Allocate a new buffer. We directectly call AcpiOsAllocate here to
 329          * purposefully bypass the (optionally enabled) internal allocation
 330          * tracking mechanism since we only want to track internal
 331          * allocations. Note: The caller should use AcpiOsFree to free this
 332          * buffer created via ACPI_ALLOCATE_BUFFER.
 333          */
 334         Buffer->Pointer = AcpiOsAllocate (RequiredLength);
 335         break;
 336 
 337     case ACPI_ALLOCATE_LOCAL_BUFFER:
 338 
 339         /* Allocate a new buffer with local interface to allow tracking */
 340 
 341         Buffer->Pointer = ACPI_ALLOCATE (RequiredLength);
 342         break;
 343 
 344     default:
 345 
 346         /* Existing buffer: Validate the size of the buffer */
 347 
 348         if (InputBufferLength < RequiredLength)
 349         {
 350             return (AE_BUFFER_OVERFLOW);
 351         }
 352         break;
 353     }
 354 
 355     /* Validate allocation from above or input buffer pointer */
 356 
 357     if (!Buffer->Pointer)
 358     {
 359         return (AE_NO_MEMORY);
 360     }
 361 
 362     /* Have a valid buffer, clear it */
 363 
 364     ACPI_MEMSET (Buffer->Pointer, 0, RequiredLength);
 365     return (AE_OK);
 366 }