/** * 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 efi_urealloc ( userptr_t old_ptr, size_t new_size ) { 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; }
EFI_STATUS EFIAPI OvrFreePages( IN EFI_PHYSICAL_ADDRESS Memory, IN UINTN Pages ) { EFI_STATUS Status; Status = gOrgBS.FreePages(Memory, Pages); // PRINT("->FreePages(0x%lx, 0x%x) = %r\n", Memory, Pages, Status); return Status; }