|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2008 Michael Brown <[email protected]>. ! 3: * ! 4: * This program is free software; you can redistribute it and/or ! 5: * modify it under the terms of the GNU General Public License as ! 6: * published by the Free Software Foundation; either version 2 of the ! 7: * License, or any later version. ! 8: * ! 9: * This program is distributed in the hope that it will be useful, but ! 10: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 12: * General Public License for more details. ! 13: * ! 14: * You should have received a copy of the GNU General Public License ! 15: * along with this program; if not, write to the Free Software ! 16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: #include <assert.h> ! 22: #include <ipxe/umalloc.h> ! 23: #include <ipxe/efi/efi.h> ! 24: ! 25: /** @file ! 26: * ! 27: * iPXE user memory allocation API for EFI ! 28: * ! 29: */ ! 30: ! 31: /** Equivalent of NOWHERE for user pointers */ ! 32: #define UNOWHERE ( ~UNULL ) ! 33: ! 34: /** ! 35: * Reallocate external memory ! 36: * ! 37: * @v old_ptr Memory previously allocated by umalloc(), or UNULL ! 38: * @v new_size Requested size ! 39: * @ret new_ptr Allocated memory, or UNULL ! 40: * ! 41: * Calling realloc() with a new size of zero is a valid way to free a ! 42: * memory block. ! 43: */ ! 44: static userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) { ! 45: EFI_BOOT_SERVICES *bs = efi_systab->BootServices; ! 46: EFI_PHYSICAL_ADDRESS phys_addr; ! 47: unsigned int new_pages, old_pages; ! 48: userptr_t new_ptr = UNOWHERE; ! 49: size_t old_size; ! 50: EFI_STATUS efirc; ! 51: ! 52: /* Allocate new memory if necessary. If allocation fails, ! 53: * return without touching the old block. ! 54: */ ! 55: if ( new_size ) { ! 56: new_pages = ( EFI_SIZE_TO_PAGES ( new_size ) + 1 ); ! 57: if ( ( efirc = bs->AllocatePages ( AllocateAnyPages, ! 58: EfiBootServicesData, ! 59: new_pages, ! 60: &phys_addr ) ) != 0 ) { ! 61: DBG ( "EFI could not allocate %d pages: %s\n", ! 62: new_pages, efi_strerror ( efirc ) ); ! 63: return UNULL; ! 64: } ! 65: assert ( phys_addr != 0 ); ! 66: new_ptr = phys_to_user ( phys_addr + EFI_PAGE_SIZE ); ! 67: copy_to_user ( new_ptr, -EFI_PAGE_SIZE, ! 68: &new_size, sizeof ( new_size ) ); ! 69: DBG ( "EFI allocated %d pages at %llx\n", ! 70: new_pages, phys_addr ); ! 71: } ! 72: ! 73: /* Copy across relevant part of the old data region (if any), ! 74: * then free it. Note that at this point either (a) new_ptr ! 75: * is valid, or (b) new_size is 0; either way, the memcpy() is ! 76: * valid. ! 77: */ ! 78: if ( old_ptr && ( old_ptr != UNOWHERE ) ) { ! 79: copy_from_user ( &old_size, old_ptr, -EFI_PAGE_SIZE, ! 80: sizeof ( old_size ) ); ! 81: memcpy_user ( new_ptr, 0, old_ptr, 0, ! 82: ( (old_size < new_size) ? old_size : new_size )); ! 83: old_pages = ( EFI_SIZE_TO_PAGES ( old_size ) + 1 ); ! 84: phys_addr = user_to_phys ( old_ptr, -EFI_PAGE_SIZE ); ! 85: if ( ( efirc = bs->FreePages ( phys_addr, old_pages ) ) != 0 ){ ! 86: DBG ( "EFI could not free %d pages at %llx: %s\n", ! 87: old_pages, phys_addr, efi_strerror ( efirc ) ); ! 88: /* Not fatal; we have leaked memory but successfully ! 89: * allocated (if asked to do so). ! 90: */ ! 91: } ! 92: DBG ( "EFI freed %d pages at %llx\n", old_pages, phys_addr ); ! 93: } ! 94: ! 95: return new_ptr; ! 96: } ! 97: ! 98: PROVIDE_UMALLOC ( efi, urealloc, efi_urealloc );
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.