diff options
Diffstat (limited to 'gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c')
-rw-r--r-- | gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c | 202 |
1 files changed, 0 insertions, 202 deletions
diff --git a/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c b/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c deleted file mode 100644 index 0645fe63..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** - * @file - * - * External memory allocation - * - */ - -#include <limits.h> -#include <errno.h> -#include <gpxe/uaccess.h> -#include <gpxe/hidemem.h> -#include <gpxe/memmap.h> -#include <gpxe/umalloc.h> - -/** Alignment of external allocated memory */ -#define EM_ALIGN ( 4 * 1024 ) - -/** Equivalent of NOWHERE for user pointers */ -#define UNOWHERE ( ~UNULL ) - -/** An external memory block */ -struct external_memory { - /** Size of this memory block (excluding this header) */ - size_t size; - /** Block is currently in use */ - int used; -}; - -/** Top of heap */ -static userptr_t top = UNULL; - -/** Bottom of heap (current lowest allocated block) */ -static userptr_t bottom = UNULL; - -/** - * Initialise external heap - * - * @ret rc Return status code - */ -static int init_eheap ( void ) { - struct memory_map memmap; - unsigned long heap_size = 0; - unsigned int i; - - DBG ( "Allocating external heap\n" ); - - get_memmap ( &memmap ); - for ( i = 0 ; i < memmap.count ; i++ ) { - struct memory_region *region = &memmap.regions[i]; - unsigned long r_start, r_end; - unsigned long r_size; - - DBG ( "Considering [%llx,%llx)\n", region->start, region->end); - - /* Truncate block to 4GB */ - if ( region->start > UINT_MAX ) { - DBG ( "...starts after 4GB\n" ); - continue; - } - r_start = region->start; - if ( region->end > UINT_MAX ) { - DBG ( "...end truncated to 4GB\n" ); - r_end = 0; /* =4GB, given the wraparound */ - } else { - r_end = region->end; - } - - /* Use largest block */ - r_size = ( r_end - r_start ); - if ( r_size > heap_size ) { - DBG ( "...new best block found\n" ); - top = bottom = phys_to_user ( r_end ); - heap_size = r_size; - } - } - - if ( ! heap_size ) { - DBG ( "No external heap available\n" ); - return -ENOMEM; - } - - DBG ( "External heap grows downwards from %lx\n", - user_to_phys ( top, 0 ) ); - return 0; -} - -/** - * Collect free blocks - * - */ -static void ecollect_free ( void ) { - struct external_memory extmem; - - /* Walk the free list and collect empty blocks */ - while ( bottom != top ) { - copy_from_user ( &extmem, bottom, -sizeof ( extmem ), - sizeof ( extmem ) ); - if ( extmem.used ) - break; - DBG ( "EXTMEM freeing [%lx,%lx)\n", user_to_phys ( bottom, 0 ), - user_to_phys ( bottom, extmem.size ) ); - bottom = userptr_add ( bottom, - ( extmem.size + sizeof ( extmem ) ) ); - } -} - -/** - * Reallocate external memory - * - * @v old_ptr Memory previously allocated by umalloc(), or UNULL - * @v new_size Requested size - * @ret new_ptr Allocated memory, or UNULL - * - * Calling realloc() with a new size of zero is a valid way to free a - * memory block. - */ -static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) { - struct external_memory extmem; - userptr_t new = ptr; - size_t align; - int rc; - - /* Initialise external memory allocator if necessary */ - if ( bottom == top ) { - if ( ( rc = init_eheap() ) != 0 ) - return UNULL; - } - - /* Get block properties into extmem */ - if ( ptr && ( ptr != UNOWHERE ) ) { - /* Determine old size */ - copy_from_user ( &extmem, ptr, -sizeof ( extmem ), - sizeof ( extmem ) ); - } else { - /* Create a zero-length block */ - ptr = bottom = userptr_add ( bottom, -sizeof ( extmem ) ); - DBG ( "EXTMEM allocating [%lx,%lx)\n", - user_to_phys ( ptr, 0 ), user_to_phys ( ptr, 0 ) ); - extmem.size = 0; - } - extmem.used = ( new_size > 0 ); - - /* Expand/shrink block if possible */ - if ( ptr == bottom ) { - /* Update block */ - new = userptr_add ( ptr, - ( new_size - extmem.size ) ); - align = ( user_to_phys ( new, 0 ) & ( EM_ALIGN - 1 ) ); - new_size += align; - new = userptr_add ( new, -align ); - DBG ( "EXTMEM expanding [%lx,%lx) to [%lx,%lx)\n", - user_to_phys ( ptr, 0 ), - user_to_phys ( ptr, extmem.size ), - user_to_phys ( new, 0 ), - user_to_phys ( new, new_size )); - memmove_user ( new, 0, ptr, 0, ( ( extmem.size < new_size ) ? - extmem.size : new_size ) ); - extmem.size = new_size; - bottom = new; - } else { - /* Cannot expand; can only pretend to shrink */ - if ( new_size > extmem.size ) { - /* Refuse to expand */ - DBG ( "EXTMEM cannot expand [%lx,%lx)\n", - user_to_phys ( ptr, 0 ), - user_to_phys ( ptr, extmem.size ) ); - return UNULL; - } - } - - /* Write back block properties */ - copy_to_user ( new, -sizeof ( extmem ), &extmem, - sizeof ( extmem ) ); - - /* Collect any free blocks and update hidden memory region */ - ecollect_free(); - hide_umalloc ( user_to_phys ( bottom, -sizeof ( extmem ) ), - user_to_phys ( top, 0 ) ); - - return ( new_size ? new : UNOWHERE ); -} - -PROVIDE_UMALLOC ( memtop, urealloc, memtop_urealloc ); |