iPXE
downloader.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
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., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <syslog.h>
29 #include <ipxe/iobuf.h>
30 #include <ipxe/xfer.h>
31 #include <ipxe/open.h>
32 #include <ipxe/job.h>
33 #include <ipxe/uaccess.h>
34 #include <ipxe/umalloc.h>
35 #include <ipxe/image.h>
36 #include <ipxe/xferbuf.h>
37 #include <ipxe/downloader.h>
38 
39 /** @file
40  *
41  * Image downloader
42  *
43  */
44 
45 /** A downloader */
46 struct downloader {
47  /** Reference count for this object */
48  struct refcnt refcnt;
49 
50  /** Job control interface */
51  struct interface job;
52  /** Data transfer interface */
53  struct interface xfer;
54 
55  /** Image to contain downloaded file */
56  struct image *image;
57  /** Data transfer buffer */
59 };
60 
61 /**
62  * Free downloader object
63  *
64  * @v refcnt Downloader reference counter
65  */
66 static void downloader_free ( struct refcnt *refcnt ) {
67  struct downloader *downloader =
68  container_of ( refcnt, struct downloader, refcnt );
69 
71  free ( downloader );
72 }
73 
74 /**
75  * Terminate download
76  *
77  * @v downloader Downloader
78  * @v rc Reason for termination
79  */
80 static void downloader_finished ( struct downloader *downloader, int rc ) {
81 
82  /* Log download status */
83  if ( rc == 0 ) {
84  syslog ( LOG_NOTICE, "Downloaded \"%s\"\n",
85  downloader->image->name );
86  } else {
87  syslog ( LOG_ERR, "Download of \"%s\" failed: %s\n",
88  downloader->image->name, strerror ( rc ) );
89  }
90 
91  /* Update image length */
93 
94  /* Shut down interfaces */
97 }
98 
99 /****************************************************************************
100  *
101  * Job control interface
102  *
103  */
104 
105 /**
106  * Report progress of download job
107  *
108  * @v downloader Downloader
109  * @v progress Progress report to fill in
110  * @ret ongoing_rc Ongoing job status code (if known)
111  */
113  struct job_progress *progress ) {
114  int rc;
115 
116  /* Allow data transfer to provide an accurate description */
117  if ( ( rc = job_progress ( &downloader->xfer, progress ) ) != 0 )
118  return rc;
119 
120  /* This is not entirely accurate, since downloaded data may
121  * arrive out of order (e.g. with multicast protocols), but
122  * it's a reasonable first approximation.
123  */
124  if ( ! progress->total ) {
125  progress->completed = downloader->buffer.pos;
126  progress->total = downloader->buffer.len;
127  }
128 
129  return 0;
130 }
131 
132 /****************************************************************************
133  *
134  * Data transfer interface
135  *
136  */
137 
138 /**
139  * Handle received data
140  *
141  * @v downloader Downloader
142  * @v iobuf Datagram I/O buffer
143  * @v meta Data transfer metadata
144  * @ret rc Return status code
145  */
147  struct io_buffer *iobuf,
148  struct xfer_metadata *meta ) {
149  int rc;
150 
151  /* Add data to buffer */
152  if ( ( rc = xferbuf_deliver ( &downloader->buffer, iob_disown ( iobuf ),
153  meta ) ) != 0 )
154  goto err_deliver;
155 
156  return 0;
157 
158  err_deliver:
160  return rc;
161 }
162 
163 /**
164  * Get underlying data transfer buffer
165  *
166  * @v downloader Downloader
167  * @ret xferbuf Data transfer buffer, or NULL on error
168  */
169 static struct xfer_buffer *
171 
172  /* Provide direct access to underlying data transfer buffer */
173  return &downloader->buffer;
174 }
175 
176 /**
177  * Redirect data transfer interface
178  *
179  * @v downloader Downloader
180  * @v type New location type
181  * @v args Remaining arguments depend upon location type
182  * @ret rc Return status code
183  */
184 static int downloader_vredirect ( struct downloader *downloader, int type,
185  va_list args ) {
186  va_list tmp;
187  struct uri *uri;
188  int rc;
189 
190  /* Intercept redirects to a LOCATION_URI and update the image URI */
191  if ( type == LOCATION_URI ) {
192 
193  /* Extract URI argument */
194  va_copy ( tmp, args );
195  uri = va_arg ( tmp, struct uri * );
196  va_end ( tmp );
197 
198  /* Set image URI */
199  if ( ( rc = image_set_uri ( downloader->image, uri ) ) != 0 )
200  goto err;
201  }
202 
203  /* Redirect to new location */
204  if ( ( rc = xfer_vreopen ( &downloader->xfer, type, args ) ) != 0 )
205  goto err;
206 
207  return 0;
208 
209  err:
211  return rc;
212 }
213 
214 /** Downloader data transfer interface operations */
220 };
221 
222 /** Downloader data transfer interface descriptor */
225 
226 /****************************************************************************
227  *
228  * Job control interface
229  *
230  */
231 
232 /** Downloader job control interface operations */
236 };
237 
238 /** Downloader job control interface descriptor */
240  INTF_DESC ( struct downloader, job, downloader_job_op );
241 
242 /****************************************************************************
243  *
244  * Instantiator
245  *
246  */
247 
248 /**
249  * Instantiate a downloader
250  *
251  * @v job Job control interface
252  * @v image Image to fill with downloaded file
253  * @ret rc Return status code
254  *
255  * Instantiates a downloader object to download the content of the
256  * specified image from its URI.
257  */
258 int create_downloader ( struct interface *job, struct image *image ) {
259  struct downloader *downloader;
260  int rc;
261 
262  /* Allocate and initialise structure */
263  downloader = zalloc ( sizeof ( *downloader ) );
264  if ( ! downloader )
265  return -ENOMEM;
268  &downloader->refcnt );
270  &downloader->refcnt );
272  xferbuf_umalloc_init ( &downloader->buffer, &image->data );
273 
274  /* Instantiate child objects and attach to our interfaces */
275  if ( ( rc = xfer_open_uri ( &downloader->xfer, image->uri ) ) != 0 )
276  goto err;
277 
278  /* Attach parent interface, mortalise self, and return */
280  ref_put ( &downloader->refcnt );
281  return 0;
282 
283  err:
285  ref_put ( &downloader->refcnt );
286  return rc;
287 }
An object interface operation.
Definition: interface.h:17
static struct xfer_buffer * downloader_buffer(struct downloader *downloader)
Get underlying data transfer buffer.
Definition: downloader.c:170
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:244
int xferbuf_deliver(struct xfer_buffer *xferbuf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Add received data to data transfer buffer.
Definition: xferbuf.c:152
#define va_end(ap)
Definition: stdarg.h:9
Data transfer metadata.
Definition: xfer.h:22
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:273
userptr_t data
Raw file image.
Definition: image.h:41
int image_set_uri(struct image *image, struct uri *uri)
Set image URI.
Definition: image.c:119
struct image * image
Image to contain downloaded file.
Definition: downloader.c:56
Location is a URI.
Definition: open.h:27
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
Error codes.
A data transfer buffer.
Definition: xferbuf.h:19
I/O buffers.
uint8_t type
Type.
Definition: ena.h:16
int xfer_open_uri(struct interface *intf, struct uri *uri)
Open URI.
Definition: open.c:66
static struct image * image_get(struct image *image)
Increment reference count on an image.
Definition: image.h:196
static struct interface_descriptor downloader_xfer_desc
Downloader data transfer interface descriptor.
Definition: downloader.c:223
int xfer_vredirect(struct interface *intf, int type, va_list args)
Send redirection event.
Definition: xfer.c:62
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:102
Image downloader.
size_t pos
Current offset within data.
Definition: xferbuf.h:25
#define va_copy(dest, src)
Definition: stdarg.h:10
An executable image.
Definition: image.h:24
#define LOG_ERR
Error: error conditions.
Definition: syslog.h:35
struct interface job
Job control interface.
Definition: downloader.c:51
Access to external ("user") memory.
Data transfer interfaces.
A reference counter.
Definition: refcnt.h:26
size_t len
Size of data.
Definition: xferbuf.h:23
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:208
static void downloader_finished(struct downloader *downloader, int rc)
Terminate download.
Definition: downloader.c:80
#define va_arg(ap, type)
Definition: stdarg.h:8
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
An object interface.
Definition: interface.h:109
Executable images.
unsigned long total
Total operation size.
Definition: job.h:30
unsigned long completed
Amount of operation completed so far.
Definition: job.h:23
int create_downloader(struct interface *job, struct image *image)
Instantiate a downloader.
Definition: downloader.c:258
int meta(WINDOW *, bool)
An object interface descriptor.
Definition: interface.h:40
System logger.
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
A downloader.
Definition: downloader.c:46
size_t len
Length of raw file image.
Definition: image.h:43
Job progress.
Definition: job.h:15
uint8_t * tmp
Definition: entropy.h:156
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
User memory allocation.
struct uri * uri
URI of image.
Definition: image.h:32
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:193
static void image_put(struct image *image)
Decrement reference count on an image.
Definition: image.h:206
Data transfer interface opening.
struct interface xfer
Data transfer interface.
Definition: downloader.c:53
int xfer_vreopen(struct interface *intf, int type, va_list args)
Reopen location.
Definition: open.c:223
Job control interfaces.
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:65
static int downloader_progress(struct downloader *downloader, struct job_progress *progress)
Report progress of download job.
Definition: downloader.c:112
static struct interface_operation downloader_xfer_operations[]
Downloader data transfer interface operations.
Definition: downloader.c:215
struct refcnt refcnt
Reference count for this object.
Definition: downloader.c:48
__builtin_va_list va_list
Definition: stdarg.h:6
struct xfer_buffer buffer
Data transfer buffer.
Definition: downloader.c:58
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static int downloader_deliver(struct downloader *downloader, struct io_buffer *iobuf, struct xfer_metadata *meta)
Handle received data.
Definition: downloader.c:146
#define syslog(priority, fmt,...)
Write message to system log.
Definition: syslog.h:93
A Uniform Resource Identifier.
Definition: uri.h:50
static struct interface_operation downloader_job_op[]
Downloader job control interface operations.
Definition: downloader.c:233
static struct interface_descriptor downloader_job_desc
Downloader job control interface descriptor.
Definition: downloader.c:239
static void downloader_free(struct refcnt *refcnt)
Free downloader object.
Definition: downloader.c:66
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:173
char * name
Name.
Definition: image.h:34
#define LOG_NOTICE
Notice: normal but significant conditions.
Definition: syslog.h:41
static int downloader_vredirect(struct downloader *downloader, int type, va_list args)
Redirect data transfer interface.
Definition: downloader.c:184
Data transfer buffer.
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
A persistent I/O buffer.
Definition: iobuf.h:32