iPXE
Defines | Functions
efi_umalloc.c File Reference

iPXE user memory allocation API for EFI More...

#include <string.h>
#include <errno.h>
#include <assert.h>
#include <ipxe/umalloc.h>
#include <ipxe/efi/efi.h>

Go to the source code of this file.

Defines

#define UNOWHERE   ( ~UNULL )
 Equivalent of NOWHERE for user pointers.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static userptr_t efi_urealloc (userptr_t old_ptr, size_t new_size)
 Reallocate external memory.
 PROVIDE_UMALLOC (efi, urealloc, efi_urealloc)

Detailed Description

iPXE user memory allocation API for EFI

Definition in file efi_umalloc.c.


Define Documentation

#define UNOWHERE   ( ~UNULL )

Equivalent of NOWHERE for user pointers.

Definition at line 39 of file efi_umalloc.c.

Referenced by efi_urealloc().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static userptr_t efi_urealloc ( userptr_t  old_ptr,
size_t  new_size 
) [static]

Reallocate external memory.

Parameters:
old_ptrMemory previously allocated by umalloc(), or UNULL
new_sizeRequested size
Return values:
new_ptrAllocated memory, or UNULL

Calling realloc() with a new size of zero is a valid way to free a memory block.

Definition at line 51 of file efi_umalloc.c.

References AllocateAnyPages, EFI_BOOT_SERVICES::AllocatePages, assert, EFI_SYSTEM_TABLE::BootServices, copy_from_user(), copy_to_user(), DBG, EEFI, EFI_PAGE_SIZE, EFI_SIZE_TO_PAGES, efi_systab, EfiBootServicesData, EFI_BOOT_SERVICES::FreePages, memcpy_user(), phys_to_user(), rc, strerror(), UNOWHERE, UNULL, and user_to_phys().

                                                                     {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        EFI_PHYSICAL_ADDRESS phys_addr;
        unsigned int new_pages, old_pages;
        userptr_t new_ptr = UNOWHERE;
        size_t old_size;
        EFI_STATUS efirc;
        int rc;

        /* Allocate new memory if necessary.  If allocation fails,
         * return without touching the old block.
         */
        if ( new_size ) {
                new_pages = ( EFI_SIZE_TO_PAGES ( new_size ) + 1 );
                if ( ( efirc = bs->AllocatePages ( AllocateAnyPages,
                                                   EfiBootServicesData,
                                                   new_pages,
                                                   &phys_addr ) ) != 0 ) {
                        rc = -EEFI ( efirc );
                        DBG ( "EFI could not allocate %d pages: %s\n",
                              new_pages, strerror ( rc ) );
                        return UNULL;
                }
                assert ( phys_addr != 0 );
                new_ptr = phys_to_user ( phys_addr + EFI_PAGE_SIZE );
                copy_to_user ( new_ptr, -EFI_PAGE_SIZE,
                               &new_size, sizeof ( new_size ) );
                DBG ( "EFI allocated %d pages at %llx\n",
                      new_pages, phys_addr );
        }

        /* Copy across relevant part of the old data region (if any),
         * then free it.  Note that at this point either (a) new_ptr
         * is valid, or (b) new_size is 0; either way, the memcpy() is
         * valid.
         */
        if ( old_ptr && ( old_ptr != UNOWHERE ) ) {
                copy_from_user ( &old_size, old_ptr, -EFI_PAGE_SIZE,
                                 sizeof ( old_size ) );
                memcpy_user ( new_ptr, 0, old_ptr, 0,
                              ( (old_size < new_size) ? old_size : new_size ));
                old_pages = ( EFI_SIZE_TO_PAGES ( old_size ) + 1 );
                phys_addr = user_to_phys ( old_ptr, -EFI_PAGE_SIZE );
                if ( ( efirc = bs->FreePages ( phys_addr, old_pages ) ) != 0 ){
                        rc = -EEFI ( efirc );
                        DBG ( "EFI could not free %d pages at %llx: %s\n",
                              old_pages, phys_addr, strerror ( rc ) );
                        /* Not fatal; we have leaked memory but successfully
                         * allocated (if asked to do so).
                         */
                }
                DBG ( "EFI freed %d pages at %llx\n", old_pages, phys_addr );
        }

        return new_ptr;
}
PROVIDE_UMALLOC ( efi  ,
urealloc  ,
efi_urealloc   
)