|  | @@ -33,7 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
		
	
		
			
			| 33 | 33 |  #include <ipxe/uaccess.h>
 | 
		
	
		
			
			| 34 | 34 |  #include <ipxe/umalloc.h>
 | 
		
	
		
			
			| 35 | 35 |  #include <ipxe/image.h>
 | 
		
	
		
			
			| 36 |  | -#include <ipxe/profile.h>
 | 
		
	
		
			
			|  | 36 | +#include <ipxe/xferbuf.h>
 | 
		
	
		
			
			| 37 | 37 |  #include <ipxe/downloader.h>
 | 
		
	
		
			
			| 38 | 38 |  
 | 
		
	
		
			
			| 39 | 39 |  /** @file
 | 
		
	
	
		
			
			|  | @@ -42,14 +42,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
		
	
		
			
			| 42 | 42 |   *
 | 
		
	
		
			
			| 43 | 43 |   */
 | 
		
	
		
			
			| 44 | 44 |  
 | 
		
	
		
			
			| 45 |  | -/** Receive profiler */
 | 
		
	
		
			
			| 46 |  | -static struct profiler downloader_rx_profiler __profiler =
 | 
		
	
		
			
			| 47 |  | -	{ .name = "downloader.rx" };
 | 
		
	
		
			
			| 48 |  | -
 | 
		
	
		
			
			| 49 |  | -/** Data copy profiler */
 | 
		
	
		
			
			| 50 |  | -static struct profiler downloader_copy_profiler __profiler =
 | 
		
	
		
			
			| 51 |  | -	{ .name = "downloader.copy" };
 | 
		
	
		
			
			| 52 |  | -
 | 
		
	
		
			
			| 53 | 45 |  /** A downloader */
 | 
		
	
		
			
			| 54 | 46 |  struct downloader {
 | 
		
	
		
			
			| 55 | 47 |  	/** Reference count for this object */
 | 
		
	
	
		
			
			|  | @@ -62,8 +54,8 @@ struct downloader {
 | 
		
	
		
			
			| 62 | 54 |  
 | 
		
	
		
			
			| 63 | 55 |  	/** Image to contain downloaded file */
 | 
		
	
		
			
			| 64 | 56 |  	struct image *image;
 | 
		
	
		
			
			| 65 |  | -	/** Current position within image buffer */
 | 
		
	
		
			
			| 66 |  | -	size_t pos;
 | 
		
	
		
			
			|  | 57 | +	/** Data transfer buffer */
 | 
		
	
		
			
			|  | 58 | +	struct xfer_buffer buffer;
 | 
		
	
		
			
			| 67 | 59 |  };
 | 
		
	
		
			
			| 68 | 60 |  
 | 
		
	
		
			
			| 69 | 61 |  /**
 | 
		
	
	
		
			
			|  | @@ -96,42 +88,14 @@ static void downloader_finished ( struct downloader *downloader, int rc ) {
 | 
		
	
		
			
			| 96 | 88 |  			 downloader->image->name, strerror ( rc ) );
 | 
		
	
		
			
			| 97 | 89 |  	}
 | 
		
	
		
			
			| 98 | 90 |  
 | 
		
	
		
			
			|  | 91 | +	/* Update image length */
 | 
		
	
		
			
			|  | 92 | +	downloader->image->len = downloader->buffer.len;
 | 
		
	
		
			
			|  | 93 | +
 | 
		
	
		
			
			| 99 | 94 |  	/* Shut down interfaces */
 | 
		
	
		
			
			| 100 | 95 |  	intf_shutdown ( &downloader->xfer, rc );
 | 
		
	
		
			
			| 101 | 96 |  	intf_shutdown ( &downloader->job, rc );
 | 
		
	
		
			
			| 102 | 97 |  }
 | 
		
	
		
			
			| 103 | 98 |  
 | 
		
	
		
			
			| 104 |  | -/**
 | 
		
	
		
			
			| 105 |  | - * Ensure that download buffer is large enough for the specified size
 | 
		
	
		
			
			| 106 |  | - *
 | 
		
	
		
			
			| 107 |  | - * @v downloader	Downloader
 | 
		
	
		
			
			| 108 |  | - * @v len		Required minimum size
 | 
		
	
		
			
			| 109 |  | - * @ret rc		Return status code
 | 
		
	
		
			
			| 110 |  | - */
 | 
		
	
		
			
			| 111 |  | -static int downloader_ensure_size ( struct downloader *downloader,
 | 
		
	
		
			
			| 112 |  | -				    size_t len ) {
 | 
		
	
		
			
			| 113 |  | -	userptr_t new_buffer;
 | 
		
	
		
			
			| 114 |  | -
 | 
		
	
		
			
			| 115 |  | -	/* If buffer is already large enough, do nothing */
 | 
		
	
		
			
			| 116 |  | -	if ( len <= downloader->image->len )
 | 
		
	
		
			
			| 117 |  | -		return 0;
 | 
		
	
		
			
			| 118 |  | -
 | 
		
	
		
			
			| 119 |  | -	DBGC ( downloader, "Downloader %p extending to %zd bytes\n",
 | 
		
	
		
			
			| 120 |  | -	       downloader, len );
 | 
		
	
		
			
			| 121 |  | -
 | 
		
	
		
			
			| 122 |  | -	/* Extend buffer */
 | 
		
	
		
			
			| 123 |  | -	new_buffer = urealloc ( downloader->image->data, len );
 | 
		
	
		
			
			| 124 |  | -	if ( ! new_buffer ) {
 | 
		
	
		
			
			| 125 |  | -		DBGC ( downloader, "Downloader %p could not extend buffer to "
 | 
		
	
		
			
			| 126 |  | -		       "%zd bytes\n", downloader, len );
 | 
		
	
		
			
			| 127 |  | -		return -ENOSPC;
 | 
		
	
		
			
			| 128 |  | -	}
 | 
		
	
		
			
			| 129 |  | -	downloader->image->data = new_buffer;
 | 
		
	
		
			
			| 130 |  | -	downloader->image->len = len;
 | 
		
	
		
			
			| 131 |  | -
 | 
		
	
		
			
			| 132 |  | -	return 0;
 | 
		
	
		
			
			| 133 |  | -}
 | 
		
	
		
			
			| 134 |  | -
 | 
		
	
		
			
			| 135 | 99 |  /****************************************************************************
 | 
		
	
		
			
			| 136 | 100 |   *
 | 
		
	
		
			
			| 137 | 101 |   * Job control interface
 | 
		
	
	
		
			
			|  | @@ -152,8 +116,8 @@ static int downloader_progress ( struct downloader *downloader,
 | 
		
	
		
			
			| 152 | 116 |  	 * arrive out of order (e.g. with multicast protocols), but
 | 
		
	
		
			
			| 153 | 117 |  	 * it's a reasonable first approximation.
 | 
		
	
		
			
			| 154 | 118 |  	 */
 | 
		
	
		
			
			| 155 |  | -	progress->completed = downloader->pos;
 | 
		
	
		
			
			| 156 |  | -	progress->total = downloader->image->len;
 | 
		
	
		
			
			|  | 119 | +	progress->completed = downloader->buffer.pos;
 | 
		
	
		
			
			|  | 120 | +	progress->total = downloader->buffer.len;
 | 
		
	
		
			
			| 157 | 121 |  
 | 
		
	
		
			
			| 158 | 122 |  	return 0;
 | 
		
	
		
			
			| 159 | 123 |  }
 | 
		
	
	
		
			
			|  | @@ -175,38 +139,17 @@ static int downloader_progress ( struct downloader *downloader,
 | 
		
	
		
			
			| 175 | 139 |  static int downloader_xfer_deliver ( struct downloader *downloader,
 | 
		
	
		
			
			| 176 | 140 |  				     struct io_buffer *iobuf,
 | 
		
	
		
			
			| 177 | 141 |  				     struct xfer_metadata *meta ) {
 | 
		
	
		
			
			| 178 |  | -	size_t len;
 | 
		
	
		
			
			| 179 |  | -	size_t max;
 | 
		
	
		
			
			| 180 | 142 |  	int rc;
 | 
		
	
		
			
			| 181 | 143 |  
 | 
		
	
		
			
			| 182 |  | -	/* Start profiling */
 | 
		
	
		
			
			| 183 |  | -	profile_start ( &downloader_rx_profiler );
 | 
		
	
		
			
			| 184 |  | -
 | 
		
	
		
			
			| 185 |  | -	/* Calculate new buffer position */
 | 
		
	
		
			
			| 186 |  | -	if ( meta->flags & XFER_FL_ABS_OFFSET )
 | 
		
	
		
			
			| 187 |  | -		downloader->pos = 0;
 | 
		
	
		
			
			| 188 |  | -	downloader->pos += meta->offset;
 | 
		
	
		
			
			| 189 |  | -
 | 
		
	
		
			
			| 190 |  | -	/* Ensure that we have enough buffer space for this data */
 | 
		
	
		
			
			| 191 |  | -	len = iob_len ( iobuf );
 | 
		
	
		
			
			| 192 |  | -	max = ( downloader->pos + len );
 | 
		
	
		
			
			| 193 |  | -	if ( ( rc = downloader_ensure_size ( downloader, max ) ) != 0 )
 | 
		
	
		
			
			| 194 |  | -		goto done;
 | 
		
	
		
			
			| 195 |  | -
 | 
		
	
		
			
			| 196 |  | -	/* Copy data to buffer */
 | 
		
	
		
			
			| 197 |  | -	profile_start ( &downloader_copy_profiler );
 | 
		
	
		
			
			| 198 |  | -	copy_to_user ( downloader->image->data, downloader->pos,
 | 
		
	
		
			
			| 199 |  | -		       iobuf->data, len );
 | 
		
	
		
			
			| 200 |  | -	profile_stop ( &downloader_copy_profiler );
 | 
		
	
		
			
			| 201 |  | -
 | 
		
	
		
			
			| 202 |  | -	/* Update current buffer position */
 | 
		
	
		
			
			| 203 |  | -	downloader->pos += len;
 | 
		
	
		
			
			| 204 |  | -
 | 
		
	
		
			
			| 205 |  | - done:
 | 
		
	
		
			
			| 206 |  | -	free_iob ( iobuf );
 | 
		
	
		
			
			| 207 |  | -	if ( rc != 0 )
 | 
		
	
		
			
			| 208 |  | -		downloader_finished ( downloader, rc );
 | 
		
	
		
			
			| 209 |  | -	profile_stop ( &downloader_rx_profiler );
 | 
		
	
		
			
			|  | 144 | +	/* Add data to buffer */
 | 
		
	
		
			
			|  | 145 | +	if ( ( rc = xferbuf_deliver ( &downloader->buffer, iob_disown ( iobuf ),
 | 
		
	
		
			
			|  | 146 | +				      meta ) ) != 0 )
 | 
		
	
		
			
			|  | 147 | +		goto err_deliver;
 | 
		
	
		
			
			|  | 148 | +
 | 
		
	
		
			
			|  | 149 | +	return 0;
 | 
		
	
		
			
			|  | 150 | +
 | 
		
	
		
			
			|  | 151 | + err_deliver:
 | 
		
	
		
			
			|  | 152 | +	downloader_finished ( downloader, rc );
 | 
		
	
		
			
			| 210 | 153 |  	return rc;
 | 
		
	
		
			
			| 211 | 154 |  }
 | 
		
	
		
			
			| 212 | 155 |  
 | 
		
	
	
		
			
			|  | @@ -266,6 +209,7 @@ int create_downloader ( struct interface *job, struct image *image ) {
 | 
		
	
		
			
			| 266 | 209 |  	intf_init ( &downloader->xfer, &downloader_xfer_desc,
 | 
		
	
		
			
			| 267 | 210 |  		    &downloader->refcnt );
 | 
		
	
		
			
			| 268 | 211 |  	downloader->image = image_get ( image );
 | 
		
	
		
			
			|  | 212 | +	xferbuf_umalloc_init ( &downloader->buffer, &image->data );
 | 
		
	
		
			
			| 269 | 213 |  
 | 
		
	
		
			
			| 270 | 214 |  	/* Instantiate child objects and attach to our interfaces */
 | 
		
	
		
			
			| 271 | 215 |  	if ( ( rc = xfer_open_uri ( &downloader->xfer, image->uri ) ) != 0 )
 |