text: /******************************************************************************
   *
   * Module Name: utalloc - local memory allocation routines
   *
   *****************************************************************************/
  
  /*
   * Copyright (C) 2000 - 2016, Intel Corp.
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions, and the following disclaimer,
   *    without modification.
   * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   *    substantially similar to the "NO WARRANTY" disclaimer below
   *    ("Disclaimer") and any redistribution must be conditioned upon
   *    including a substantially similar Disclaimer requirement for further
   *    binary redistribution.
   * 3. Neither the names of the above-listed copyright holders nor the names
   *    of any contributors may be used to endorse or promote products derived
   *    from this software without specific prior written permission.
   *
   * Alternatively, this software may be distributed under the terms of the
   * GNU General Public License ("GPL") version 2 as published by the Free
   * Software Foundation.
   *
   * NO WARRANTY
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGES.
   */
  
  #include <contrib/dev/acpica/include/acpi.h>
  #include <contrib/dev/acpica/include/accommon.h>
  #include <contrib/dev/acpica/include/acdebug.h>
  
  #define _COMPONENT          ACPI_UTILITIES
          ACPI_MODULE_NAME    ("utalloc")
  
  
  #if !defined (USE_NATIVE_ALLOCATE_ZEROED)
  /*******************************************************************************
   *
   * FUNCTION:    AcpiOsAllocateZeroed
   *
   * PARAMETERS:  Size                - Size of the allocation
   *
   * RETURN:      Address of the allocated memory on success, NULL on failure.
   *
   * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory.
   *              This is the default implementation. Can be overridden via the
   *              USE_NATIVE_ALLOCATE_ZEROED flag.
   *
   ******************************************************************************/
  
  void *
  AcpiOsAllocateZeroed (
      ACPI_SIZE               Size)
  {
      void                    *Allocation;
  
  
      ACPI_FUNCTION_ENTRY ();
  
  
      Allocation = AcpiOsAllocate (Size);
      if (Allocation)
      {
          /* Clear the memory block */
  
          memset (Allocation, 0, Size);
      }
  
      return (Allocation);
  }
  
  #endif /* !USE_NATIVE_ALLOCATE_ZEROED */
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiUtCreateCaches
   *
   * PARAMETERS:  None
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Create all local caches
   *
   ******************************************************************************/
  
  ACPI_STATUS
  AcpiUtCreateCaches (
      void)
  {
      ACPI_STATUS             Status;
  
  
      /* Object Caches, for frequently used objects */
  
      Status = AcpiOsCreateCache ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE),
          ACPI_MAX_NAMESPACE_CACHE_DEPTH, &AcpiGbl_NamespaceCache);
      if (ACPI_FAILURE (Status))
      {
          return (Status);
      }
  
      Status = AcpiOsCreateCache ("Acpi-State", sizeof (ACPI_GENERIC_STATE),
          ACPI_MAX_STATE_CACHE_DEPTH, &AcpiGbl_StateCache);
      if (ACPI_FAILURE (Status))
      {
          return (Status);
      }
  
      Status = AcpiOsCreateCache ("Acpi-Parse", sizeof (ACPI_PARSE_OBJ_COMMON),
          ACPI_MAX_PARSE_CACHE_DEPTH, &AcpiGbl_PsNodeCache);
      if (ACPI_FAILURE (Status))
      {
          return (Status);
      }
  
      Status = AcpiOsCreateCache ("Acpi-ParseExt", sizeof (ACPI_PARSE_OBJ_NAMED),
          ACPI_MAX_EXTPARSE_CACHE_DEPTH, &AcpiGbl_PsNodeExtCache);
      if (ACPI_FAILURE (Status))
      {
          return (Status);
      }
  
      Status = AcpiOsCreateCache ("Acpi-Operand", sizeof (ACPI_OPERAND_OBJECT),
          ACPI_MAX_OBJECT_CACHE_DEPTH, &AcpiGbl_OperandCache);
      if (ACPI_FAILURE (Status))
      {
          return (Status);
      }
  
  
  #ifdef ACPI_DBG_TRACK_ALLOCATIONS
  
      /* Memory allocation lists */
  
      Status = AcpiUtCreateList ("Acpi-Global", 0,
          &AcpiGbl_GlobalList);
      if (ACPI_FAILURE (Status))
      {
          return (Status);
      }
  
      Status = AcpiUtCreateList ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE),
          &AcpiGbl_NsNodeList);
      if (ACPI_FAILURE (Status))
      {
          return (Status);
      }
  #endif
  
      return (AE_OK);
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiUtDeleteCaches
   *
   * PARAMETERS:  None
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Purge and delete all local caches
   *
   ******************************************************************************/
  
  ACPI_STATUS
  AcpiUtDeleteCaches (
      void)
  {
  #ifdef ACPI_DBG_TRACK_ALLOCATIONS
      char                    Buffer[7];
  
  
      if (AcpiGbl_DisplayFinalMemStats)
      {
          strcpy (Buffer, "MEMORY");
          (void) AcpiDbDisplayStatistics (Buffer);
      }
  #endif
  
      (void) AcpiOsDeleteCache (AcpiGbl_NamespaceCache);
      AcpiGbl_NamespaceCache = NULL;
  
      (void) AcpiOsDeleteCache (AcpiGbl_StateCache);
      AcpiGbl_StateCache = NULL;
  
      (void) AcpiOsDeleteCache (AcpiGbl_OperandCache);
      AcpiGbl_OperandCache = NULL;
  
      (void) AcpiOsDeleteCache (AcpiGbl_PsNodeCache);
      AcpiGbl_PsNodeCache = NULL;
  
      (void) AcpiOsDeleteCache (AcpiGbl_PsNodeExtCache);
      AcpiGbl_PsNodeExtCache = NULL;
  
  
  #ifdef ACPI_DBG_TRACK_ALLOCATIONS
  
      /* Debug only - display leftover memory allocation, if any */
  
      AcpiUtDumpAllocations (ACPI_UINT32_MAX, NULL);
  
      /* Free memory lists */
  
      AcpiOsFree (AcpiGbl_GlobalList);
      AcpiGbl_GlobalList = NULL;
  
      AcpiOsFree (AcpiGbl_NsNodeList);
      AcpiGbl_NsNodeList = NULL;
  #endif
  
      return (AE_OK);
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiUtValidateBuffer
   *
   * PARAMETERS:  Buffer              - Buffer descriptor to be validated
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Perform parameter validation checks on an ACPI_BUFFER
   *
   ******************************************************************************/
  
  ACPI_STATUS
  AcpiUtValidateBuffer (
      ACPI_BUFFER             *Buffer)
  {
  
      /* Obviously, the structure pointer must be valid */
  
      if (!Buffer)
      {
          return (AE_BAD_PARAMETER);
      }
  
      /* Special semantics for the length */
  
      if ((Buffer->Length == ACPI_NO_BUFFER)              ||
          (Buffer->Length == ACPI_ALLOCATE_BUFFER)        ||
          (Buffer->Length == ACPI_ALLOCATE_LOCAL_BUFFER))
      {
          return (AE_OK);
      }
  
      /* Length is valid, the buffer pointer must be also */
  
      if (!Buffer->Pointer)
      {
          return (AE_BAD_PARAMETER);
      }
  
      return (AE_OK);
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiUtInitializeBuffer
   *
   * PARAMETERS:  Buffer              - Buffer to be validated
   *              RequiredLength      - Length needed
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Validate that the buffer is of the required length or
   *              allocate a new buffer. Returned buffer is always zeroed.
   *
   ******************************************************************************/
  
  ACPI_STATUS
  AcpiUtInitializeBuffer (
      ACPI_BUFFER             *Buffer,
      ACPI_SIZE               RequiredLength)
  {
      ACPI_SIZE               InputBufferLength;
  
  
      /* Parameter validation */
  
      if (!Buffer || !RequiredLength)
      {
          return (AE_BAD_PARAMETER);
      }
  
      /*
       * Buffer->Length is used as both an input and output parameter. Get the
       * input actual length and set the output required buffer length.
       */
      InputBufferLength = Buffer->Length;
      Buffer->Length = RequiredLength;
  
      /*
       * The input buffer length contains the actual buffer length, or the type
       * of buffer to be allocated by this routine.
       */
      switch (InputBufferLength)
      {
      case ACPI_NO_BUFFER:
  
          /* Return the exception (and the required buffer length) */
  
          return (AE_BUFFER_OVERFLOW);
  
      case ACPI_ALLOCATE_BUFFER:
          /*
           * Allocate a new buffer. We directectly call AcpiOsAllocate here to
           * purposefully bypass the (optionally enabled) internal allocation
           * tracking mechanism since we only want to track internal
           * allocations. Note: The caller should use AcpiOsFree to free this
           * buffer created via ACPI_ALLOCATE_BUFFER.
           */
          Buffer->Pointer = AcpiOsAllocate (RequiredLength);
          break;
  
      case ACPI_ALLOCATE_LOCAL_BUFFER:
  
          /* Allocate a new buffer with local interface to allow tracking */
  
          Buffer->Pointer = ACPI_ALLOCATE (RequiredLength);
          break;
  
      default:
  
          /* Existing buffer: Validate the size of the buffer */
  
          if (InputBufferLength < RequiredLength)
          {
              return (AE_BUFFER_OVERFLOW);
          }
          break;
      }
  
      /* Validate allocation from above or input buffer pointer */
  
      if (!Buffer->Pointer)
      {
          return (AE_NO_MEMORY);
      }
  
      /* Have a valid buffer, clear it */
  
      memset (Buffer->Pointer, 0, RequiredLength);
      return (AE_OK);
  }
  