Logo Search packages:      
Sourcecode: efilinux version File versions

malloc.c

/*
 * Copyright (c) 2011, Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer
 *      in the documentation and/or other materials provided with the
 *      distribution.
 *    * Neither the name of Intel Corporation nor the names of its
 *      contributors may be used to endorse or promote products
 *      derived from this software without specific prior written
 *      permission.
 *
 * 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 MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, 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 DAMAGE.
 */

#include <efi.h>
#include <efilib.h>
#include "efilinux.h"

/**
 * emalloc - Allocate memory with a strict alignment requirement
 * @size: size in bytes of the requested allocation
 * @align: the required alignment of the allocation
 * @addr: a pointer to the allocated address on success
 *
 * If we cannot satisfy @align we return 0.
 */
EFI_STATUS emalloc(UINTN size, UINTN align, EFI_PHYSICAL_ADDRESS *addr)
{
      UINTN map_size, map_key, desc_size;
      EFI_MEMORY_DESCRIPTOR *map_buf;
      UINTN d, map_end;
      UINT32 desc_version;
      EFI_STATUS err;
      UINTN nr_pages = EFI_SIZE_TO_PAGES(size);

      err = memory_map(&map_buf, &map_size, &map_key,
                   &desc_size, &desc_version);
      if (err != EFI_SUCCESS)
            goto fail;

      d = (UINTN)map_buf;
      map_end = (UINTN)map_buf + map_size;

      for (; d < map_end; d += desc_size) {
            EFI_MEMORY_DESCRIPTOR *desc;
            EFI_PHYSICAL_ADDRESS start, end, aligned;

            desc = (EFI_MEMORY_DESCRIPTOR *)d;
            if (desc->Type != EfiConventionalMemory)
                  continue;

            if (desc->NumberOfPages < nr_pages)
                  continue;

            start = desc->PhysicalStart;
            end = start + (desc->NumberOfPages << EFI_PAGE_SHIFT);

            /* Low-memory is super-precious! */
            if (end <= 1 << 20)
                  continue;
            if (start < 1 << 20) {
                  size -= (1 << 20) - start;
                  start = (1 << 20);
            }

            aligned = (start + align -1) & ~(align -1);

            if ((aligned + size) <= end) {
                  err = allocate_pages(AllocateAddress, EfiLoaderData,
                                   nr_pages, &aligned);
                  if (err == EFI_SUCCESS) {
                        *addr = aligned;
                        break;
                  }
            }
      }

      if (d == map_end)
            err = EFI_OUT_OF_RESOURCES;

      free_pool(map_buf);
fail:
      return err;
}

/**
 * efree - Return memory allocated with emalloc
 * @memory: the address of the emalloc() allocation
 * @size: the size of the allocation
 */
void efree(EFI_PHYSICAL_ADDRESS memory, UINTN size)
{
      UINTN nr_pages = EFI_SIZE_TO_PAGES(size);

      free_pages(memory, nr_pages);
}

/**
 * malloc - Allocate memory from the EfiLoaderData pool
 * @size: size in bytes of the requested allocation
 *
 * Return a pointer to an allocation of @size bytes of type
 * EfiLoaderData.
 */
void *malloc(UINTN size)
{
      EFI_STATUS err;
      void *buffer;

      err = allocate_pool(EfiLoaderData, size, &buffer);
      if (err != EFI_SUCCESS)
            buffer = NULL;

      return buffer;
}

/**
 * free - Release memory to the EfiLoaderData pool
 * @buffer: pointer to the malloc() allocation to free
 */
void free(void *buffer)
{
      free_pool(buffer);
}

Generated by  Doxygen 1.6.0   Back to index