iPXE
efi_download.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
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 St, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 FILE_LICENCE ( GPL2_OR_LATER );
20 
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <ipxe/open.h>
25 #include <ipxe/process.h>
26 #include <ipxe/iobuf.h>
27 #include <ipxe/xfer.h>
28 #include <ipxe/efi/efi.h>
29 #include <ipxe/efi/efi_snp.h>
30 #include <ipxe/efi/efi_download.h>
31 
32 /** iPXE download protocol GUID */
35 
36 /** A single in-progress file */
38  /** Data transfer interface that provides downloaded data */
39  struct interface xfer;
40 
41  /** Current file position */
42  size_t pos;
43 
44  /** Data callback */
46 
47  /** Finish callback */
49 
50  /** Callback context */
51  void *context;
52 };
53 
54 /* xfer interface */
55 
56 /**
57  * Transfer finished or was aborted
58  *
59  * @v file Data transfer file
60  * @v rc Reason for close
61  */
62 static void efi_download_close ( struct efi_download_file *file, int rc ) {
63 
64  file->finish_callback ( file->context, EFIRC ( rc ) );
65 
66  intf_shutdown ( &file->xfer, rc );
67 
69 }
70 
71 /**
72  * Process received data
73  *
74  * @v file Data transfer file
75  * @v iobuf I/O buffer
76  * @v meta Data transfer metadata
77  * @ret rc Return status code
78  */
79 static int efi_download_deliver_iob ( struct efi_download_file *file,
80  struct io_buffer *iobuf,
81  struct xfer_metadata *meta ) {
82  EFI_STATUS efirc;
83  size_t len = iob_len ( iobuf );
84  int rc;
85 
86  /* Calculate new buffer position */
87  if ( meta->flags & XFER_FL_ABS_OFFSET )
88  file->pos = 0;
89  file->pos += meta->offset;
90 
91  /* Call out to the data handler */
92  if ( ( efirc = file->data_callback ( file->context, iobuf->data,
93  len, file->pos ) ) != 0 ) {
94  rc = -EEFI ( efirc );
95  goto err_callback;
96  }
97 
98  /* Update current buffer position */
99  file->pos += len;
100 
101  /* Success */
102  rc = 0;
103 
104  err_callback:
105  free_iob ( iobuf );
106  return rc;
107 }
108 
109 /** Data transfer interface operations */
113 };
114 
115 /** EFI download data transfer interface descriptor */
118 
119 /**
120  * Start downloading a file, and register callback functions to handle the
121  * download.
122  *
123  * @v This iPXE Download Protocol instance
124  * @v Url URL to download from
125  * @v DataCallback Callback that will be invoked when data arrives
126  * @v FinishCallback Callback that will be invoked when the download ends
127  * @v Context Context passed to the Data and Finish callbacks
128  * @v File Token that can be used to abort the download
129  * @ret Status EFI status code
130  */
131 static EFI_STATUS EFIAPI
133  CHAR8 *Url,
134  IPXE_DOWNLOAD_DATA_CALLBACK DataCallback,
135  IPXE_DOWNLOAD_FINISH_CALLBACK FinishCallback,
136  VOID *Context,
137  IPXE_DOWNLOAD_FILE *File ) {
138  struct efi_download_file *file;
139  int rc;
140 
141  efi_snp_claim();
142 
143  file = malloc ( sizeof ( struct efi_download_file ) );
144  if ( file == NULL ) {
145  efi_snp_release();
146  return EFI_OUT_OF_RESOURCES;
147  }
148 
150  rc = xfer_open ( &file->xfer, LOCATION_URI_STRING, Url );
151  if ( rc ) {
152  free ( file );
153  efi_snp_release();
154  return EFIRC ( rc );
155  }
156 
157  file->pos = 0;
158  file->data_callback = DataCallback;
159  file->finish_callback = FinishCallback;
160  file->context = Context;
161  *File = file;
162  return EFI_SUCCESS;
163 }
164 
165 /**
166  * Forcibly abort downloading a file that is currently in progress.
167  *
168  * It is not safe to call this function after the Finish callback has executed.
169  *
170  * @v This iPXE Download Protocol instance
171  * @v File Token obtained from Start
172  * @v Status Reason for aborting the download
173  * @ret Status EFI status code
174  */
175 static EFI_STATUS EFIAPI
177  IPXE_DOWNLOAD_FILE File,
178  EFI_STATUS Status ) {
179  struct efi_download_file *file = File;
180 
181  efi_download_close ( file, -EEFI ( Status ) );
182  return EFI_SUCCESS;
183 }
184 
185 /**
186  * Poll for more data from iPXE. This function will invoke the registered
187  * callbacks if data is available or if downloads complete.
188  *
189  * @v This iPXE Download Protocol instance
190  * @ret Status EFI status code
191  */
192 static EFI_STATUS EFIAPI
194  step();
195  return EFI_SUCCESS;
196 }
197 
198 /** Publicly exposed iPXE download protocol */
201  .Abort = efi_download_abort,
202  .Poll = efi_download_poll
203 };
204 
205 /**
206  * Install iPXE download protocol
207  *
208  * @v handle EFI handle
209  * @ret rc Return status code
210  */
213  EFI_STATUS efirc;
214  int rc;
215 
217  &handle,
220  NULL );
221  if ( efirc ) {
222  rc = -EEFI ( efirc );
223  DBG ( "Could not install download protocol: %s\n",
224  strerror ( rc ) );
225  return rc;
226  }
227 
228  return 0;
229 }
230 
231 /**
232  * Uninstall iPXE download protocol
233  *
234  * @v handle EFI handle
235  */
238 
240  handle,
243 }
iPXE Download Protocol
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2081
An object interface operation.
Definition: interface.h:17
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:249
void efi_download_uninstall(EFI_HANDLE handle)
Uninstall iPXE download protocol.
Definition: efi_download.c:236
Data transfer metadata.
Definition: xfer.h:22
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:278
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:171
static int efi_download_deliver_iob(struct efi_download_file *file, struct io_buffer *iobuf, struct xfer_metadata *meta)
Process received data.
Definition: efi_download.c:79
IPXE_DOWNLOAD_DATA_CALLBACK data_callback
Data callback.
Definition: efi_download.c:45
The iPXE Download Protocol.
Definition: efi_download.h:143
static struct interface_operation efi_xfer_operations[]
Data transfer interface operations.
Definition: efi_download.c:110
128 bit buffer containing a unique identifier value.
Definition: Base.h:215
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition: xfer.h:47
Error codes.
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:57
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
void * context
Callback context.
Definition: efi_download.c:51
EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces
Definition: UefiSpec.h:1996
static void efi_snp_claim(void)
Claim network devices for use by iPXE.
Definition: efi_snp.h:91
A single in-progress file.
Definition: efi_download.c:37
IPXE_DOWNLOAD_FINISH_CALLBACK finish_callback
Finish callback.
Definition: efi_download.c:48
#define EFI_OUT_OF_RESOURCES
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:123
VOID * IPXE_DOWNLOAD_FILE
Token to represent a currently downloading file.
Definition: efi_download.h:34
Data transfer interfaces.
IPXE_DOWNLOAD_START Start
Definition: efi_download.h:144
void(EFIAPI * IPXE_DOWNLOAD_FINISH_CALLBACK)(IN VOID *Context, IN EFI_STATUS Status)
Callback function that is invoked when the file is finished downloading, or when a connection unexpec...
Definition: efi_download.h:78
An object interface.
Definition: interface.h:124
int meta(WINDOW *, bool)
An object interface descriptor.
Definition: interface.h:55
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
#define EFIAPI
EFI Boot Services Table.
Definition: UefiSpec.h:1917
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
Location is a URI string.
Definition: open.h:34
FILE_LICENCE(GPL2_OR_LATER)
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces
Definition: UefiSpec.h:1997
static EFI_STATUS EFIAPI efi_download_poll(IPXE_DOWNLOAD_PROTOCOL *This __unused)
Poll for more data from iPXE.
Definition: efi_download.c:193
static void efi_snp_release(void)
Release network devices for use via SNP.
Definition: efi_snp.h:99
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:194
Processes.
Data transfer interface opening.
static struct interface_descriptor efi_download_file_xfer_desc
EFI download data transfer interface descriptor.
Definition: efi_download.c:116
int xfer_open(struct interface *intf, int type,...)
Open location.
Definition: open.c:202
#define VOID
Undeclared type.
Definition: Base.h:271
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
static IPXE_DOWNLOAD_PROTOCOL ipxe_download_protocol_interface
Publicly exposed iPXE download protocol.
Definition: efi_download.c:199
EFI API.
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
size_t pos
Current file position.
Definition: efi_download.c:42
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:80
uint32_t len
Length.
Definition: ena.h:14
#define EFI_SUCCESS
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:114
char CHAR8
void * data
Start of data.
Definition: iobuf.h:48
static EFI_STATUS EFIAPI efi_download_start(IPXE_DOWNLOAD_PROTOCOL *This __unused, CHAR8 *Url, IPXE_DOWNLOAD_DATA_CALLBACK DataCallback, IPXE_DOWNLOAD_FINISH_CALLBACK FinishCallback, VOID *Context, IPXE_DOWNLOAD_FILE *File)
Start downloading a file, and register callback functions to handle the download.
Definition: efi_download.c:132
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:31
void step(void)
Single-step a single process.
Definition: process.c:98
struct interface xfer
Data transfer interface that provides downloaded data.
Definition: efi_download.c:39
#define IPXE_DOWNLOAD_PROTOCOL_GUID
Definition: efi_download.h:149
int efi_download_install(EFI_HANDLE handle)
Install iPXE download protocol.
Definition: efi_download.c:211
static void efi_download_close(struct efi_download_file *file, int rc)
Transfer finished or was aborted.
Definition: efi_download.c:62
EFI_SYSTEM_TABLE * efi_systab
iPXE EFI SNP interface
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:203
uint16_t handle
Handle.
Definition: smbios.h:16
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
EFI_STATUS(EFIAPI * IPXE_DOWNLOAD_DATA_CALLBACK)(IN VOID *Context, IN VOID *Buffer, IN UINTN BufferLength, IN UINTN FileOffset)
Callback function that is invoked when data arrives for a particular file.
Definition: efi_download.h:57
static EFI_GUID ipxe_download_protocol_guid
iPXE download protocol GUID
Definition: efi_download.c:34
#define EFIRC(rc)
Convert an iPXE status code to an EFI status code.
Definition: efi.h:163
Definition: efi.h:59
static EFI_STATUS EFIAPI efi_download_abort(IPXE_DOWNLOAD_PROTOCOL *This __unused, IPXE_DOWNLOAD_FILE File, EFI_STATUS Status)
Forcibly abort downloading a file that is currently in progress.
Definition: efi_download.c:176
A persistent I/O buffer.
Definition: iobuf.h:33