2
* Copyright (C) 2010 VMware, Inc. All Rights Reserved.
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.
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.
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.
19
FILE_LICENCE ( GPL2_OR_LATER );
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>
32
/** iPXE download protocol GUID */
33
static EFI_GUID ipxe_download_protocol_guid
34
= IPXE_DOWNLOAD_PROTOCOL_GUID;
36
/** A single in-progress file */
37
struct efi_download_file {
38
/** Data transfer interface that provides downloaded data */
39
struct interface xfer;
41
/** Current file position */
45
IPXE_DOWNLOAD_DATA_CALLBACK data_callback;
47
/** Finish callback */
48
IPXE_DOWNLOAD_FINISH_CALLBACK finish_callback;
50
/** Callback context */
57
* Transfer finished or was aborted
59
* @v file Data transfer file
60
* @v rc Reason for close
62
static void efi_download_close ( struct efi_download_file *file, int rc ) {
64
file->finish_callback ( file->context, EFIRC ( rc ) );
66
intf_shutdown ( &file->xfer, rc );
72
* Process received data
74
* @v file Data transfer file
76
* @v meta Data transfer metadata
77
* @ret rc Return status code
79
static int efi_download_deliver_iob ( struct efi_download_file *file,
80
struct io_buffer *iobuf,
81
struct xfer_metadata *meta ) {
83
size_t len = iob_len ( iobuf );
86
/* Calculate new buffer position */
87
if ( meta->flags & XFER_FL_ABS_OFFSET )
89
file->pos += meta->offset;
91
/* Call out to the data handler */
92
if ( ( efirc = file->data_callback ( file->context, iobuf->data,
93
len, file->pos ) ) != 0 ) {
98
/* Update current buffer position */
109
/** Data transfer interface operations */
110
static struct interface_operation efi_xfer_operations[] = {
111
INTF_OP ( xfer_deliver, struct efi_download_file *, efi_download_deliver_iob ),
112
INTF_OP ( intf_close, struct efi_download_file *, efi_download_close ),
115
/** EFI download data transfer interface descriptor */
116
static struct interface_descriptor efi_download_file_xfer_desc =
117
INTF_DESC ( struct efi_download_file, xfer, efi_xfer_operations );
120
* Start downloading a file, and register callback functions to handle the
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
131
static EFI_STATUS EFIAPI
132
efi_download_start ( IPXE_DOWNLOAD_PROTOCOL *This __unused,
134
IPXE_DOWNLOAD_DATA_CALLBACK DataCallback,
135
IPXE_DOWNLOAD_FINISH_CALLBACK FinishCallback,
137
IPXE_DOWNLOAD_FILE *File ) {
138
struct efi_download_file *file;
141
file = malloc ( sizeof ( struct efi_download_file ) );
142
if ( file == NULL ) {
143
return EFI_OUT_OF_RESOURCES;
146
intf_init ( &file->xfer, &efi_download_file_xfer_desc, NULL );
147
rc = xfer_open ( &file->xfer, LOCATION_URI_STRING, Url );
155
file->data_callback = DataCallback;
156
file->finish_callback = FinishCallback;
157
file->context = Context;
163
* Forcibly abort downloading a file that is currently in progress.
165
* It is not safe to call this function after the Finish callback has executed.
167
* @v This iPXE Download Protocol instance
168
* @v File Token obtained from Start
169
* @v Status Reason for aborting the download
170
* @ret Status EFI status code
172
static EFI_STATUS EFIAPI
173
efi_download_abort ( IPXE_DOWNLOAD_PROTOCOL *This __unused,
174
IPXE_DOWNLOAD_FILE File,
175
EFI_STATUS Status ) {
176
struct efi_download_file *file = File;
178
efi_download_close ( file, -EEFI ( Status ) );
183
* Poll for more data from iPXE. This function will invoke the registered
184
* callbacks if data is available or if downloads complete.
186
* @v This iPXE Download Protocol instance
187
* @ret Status EFI status code
189
static EFI_STATUS EFIAPI
190
efi_download_poll ( IPXE_DOWNLOAD_PROTOCOL *This __unused ) {
195
/** Publicly exposed iPXE download protocol */
196
static IPXE_DOWNLOAD_PROTOCOL ipxe_download_protocol_interface = {
197
.Start = efi_download_start,
198
.Abort = efi_download_abort,
199
.Poll = efi_download_poll
203
* Install iPXE download protocol
205
* @v handle EFI handle
206
* @ret rc Return status code
208
int efi_download_install ( EFI_HANDLE handle ) {
209
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
213
efirc = bs->InstallMultipleProtocolInterfaces (
215
&ipxe_download_protocol_guid,
216
&ipxe_download_protocol_interface,
219
rc = -EEFI ( efirc );
220
DBG ( "Could not install download protocol: %s\n",
229
* Uninstall iPXE download protocol
231
* @v handle EFI handle
233
void efi_download_uninstall ( EFI_HANDLE handle ) {
234
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
236
bs->UninstallMultipleProtocolInterfaces (
238
&ipxe_download_protocol_guid,
239
&ipxe_download_protocol_interface, NULL );