diff --git a/src/Makefile b/src/Makefile index 181537ea..0591bb01 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,3 +1,7 @@ +# Location to place generated files +# +BIN := bin + # Initialise variables that get added to throughout the various Makefiles # MAKEDEPS := Makefile .toolcheck .echocheck @@ -9,34 +13,34 @@ ROMS := MEDIA := NON_AUTO_MEDIA := -# Grab the central Config file. +# Locations of utilities # -MAKEDEPS += Config -include Config - -# Location to place generated files -# -BIN := bin - -# If no architecture is specified in Config or on the command-line, -# use that of the build machine. -# -ifndef ARCH -ARCH := $(shell uname -m | sed -e s,i[3456789]86,i386,) -endif - -# handle x86_64 like i386, but set -m32 option for 32bit code only -ifeq ($(ARCH),x86_64) -ARCH := i386 -CFLAGS += -m32 -ASFLAGS += --32 -LDFLAGS += -m elf_i386 -endif - -# Drag in architecture-specific Config -# -MAKEDEPS += arch/$(ARCH)/Config -include arch/$(ARCH)/Config +HOST_CC := gcc +RM := rm -f +TOUCH := touch +MKDIR := mkdir +CP := cp +ECHO := echo +PRINTF := printf +PERL := /usr/bin/perl +CC := $(CROSS_COMPILE)gcc +CPP := $(CROSS_COMPILE)gcc -E -Wp,-Wall +AS := $(CROSS_COMPILE)as +LD := $(CROSS_COMPILE)ld +SIZE := $(CROSS_COMPILE)size +AR := $(CROSS_COMPILE)ar +RANLIB := $(CROSS_COMPILE)ranlib +OBJCOPY := $(CROSS_COMPILE)objcopy +NM := $(CROSS_COMPILE)nm +OBJDUMP := $(CROSS_COMPILE)objdump +PARSEROM := $(PERL) ./util/parserom.pl +MAKEROM := $(PERL) ./util/makerom.pl +MKCONFIG := $(PERL) ./util/mkconfig.pl +SYMCHECK := $(PERL) ./util/symcheck.pl +SORTOBJDUMP := $(PERL) ./util/sortobjdump.pl +NRV2B := ./util/nrv2b +ZBIN := ./util/zbin +DOXYGEN := doxygen # If invoked with no build target, print out a helpfully suggestive # message. @@ -64,34 +68,28 @@ noargs : blib $(BIN)/NIC $(BIN)/gpxe.dsk $(BIN)/gpxe.iso $(BIN)/gpxe.usb @$(ECHO) @$(ECHO) '===========================================================' -# Locations of utilities +# Grab the central Config file. # -HOST_CC ?= gcc -CPP ?= gcc -E -Wp,-Wall -RM ?= rm -f -TOUCH ?= touch -MKDIR ?= mkdir -CP ?= cp -ECHO ?= echo -PRINTF ?= printf -PERL ?= /usr/bin/perl -CC ?= $(CROSS_COMPILE)gcc -AS ?= $(CROSS_COMPILE)as -LD ?= $(CROSS_COMPILE)ld -SIZE ?= $(CROSS_COMPILE)size -AR ?= $(CROSS_COMPILE)ar -RANLIB ?= $(CROSS_COMPILE)ranlib -OBJCOPY ?= $(CROSS_COMPILE)objcopy -NM ?= $(CROSS_COMPILE)nm -OBJDUMP ?= $(CROSS_COMPILE)objdump -PARSEROM ?= $(PERL) ./util/parserom.pl -MAKEROM ?= $(PERL) ./util/makerom.pl -MKCONFIG ?= $(PERL) ./util/mkconfig.pl -SYMCHECK ?= $(PERL) ./util/symcheck.pl -SORTOBJDUMP ?= $(PERL) ./util/sortobjdump.pl -NRV2B ?= ./util/nrv2b -ZBIN ?= ./util/zbin -DOXYGEN ?= doxygen +MAKEDEPS += Config +include Config + +# If no architecture is specified in Config or on the command-line, +# use that of the build machine. +# +ARCH ?= $(shell uname -m | sed -e s,i[3456789]86,i386,) + +# handle x86_64 like i386, but set -m32 option for 32bit code only +ifeq ($(ARCH),x86_64) +ARCH := i386 +CFLAGS += -m32 +ASFLAGS += --32 +LDFLAGS += -m elf_i386 +endif + +# Drag in architecture-specific Config +# +MAKEDEPS += arch/$(ARCH)/Config +include arch/$(ARCH)/Config # Common flags # @@ -103,6 +101,10 @@ CFLAGS += $(EXTRA_CFLAGS) ASFLAGS += $(EXTRA_ASFLAGS) LDFLAGS += $(EXTRA_LDFLAGS) +# Embedded image, if present +# +EMBEDDED_IMAGE ?= /dev/null + ifneq ($(NO_WERROR),1) CFLAGS += -Werror endif diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index 1e97ee62..d4ae8e31 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -214,6 +214,14 @@ drivers : roms : @$(ECHO) $(ROMS) +# Embedded binary +$(BIN)/embedimg.bin: $(EMBEDDED_IMAGE) + $(QM)$(ECHO) " [COPY] $@" + $(Q)$(CP) -f $(EMBEDDED_IMAGE) $@ + +$(BIN)/embed.o: $(BIN)/embedimg.bin +CFLAGS_embed = -DEMBEDIMG=\"$(BIN)/embedimg.bin\" + # Generate the NIC file from the parsed source files. The NIC file is # only for rom-o-matic. # @@ -356,6 +364,9 @@ $(BIN)/%.tmp : $(BLIB) $(MAKEDEPS) $(LDSCRIPT) -Map $(BIN)/$*.tmp.map $(Q)$(OBJDUMP) -ht $@ | $(SORTOBJDUMP) >> $(BIN)/$*.tmp.map +# Keep intermediate object file (useful for debugging) +.SECONDARY : $(BIN)/%.tmp + # Show a linker map for the specified target # $(BIN)/%.map : $(BIN)/%.tmp diff --git a/src/core/downloader.c b/src/core/downloader.c index 3726c6e1..0a443db2 100644 --- a/src/core/downloader.c +++ b/src/core/downloader.c @@ -96,6 +96,9 @@ static int downloader_ensure_size ( struct downloader *downloader, if ( len <= downloader->image->len ) return 0; + DBGC ( downloader, "Downloader %p extending to %zd bytes\n", + downloader, len ); + /* Extend buffer */ new_buffer = urealloc ( downloader->image->data, len ); if ( ! new_buffer ) { @@ -141,68 +144,44 @@ static struct job_interface_operations downloader_job_operations = { * */ -/** - * Handle seek() event received via data transfer interface - * - * @v xfer Downloader data transfer interface - * @v pos New position - * @ret rc Return status code - */ -static int downloader_xfer_seek ( struct xfer_interface *xfer, off_t offset, - int whence ) { - struct downloader *downloader = - container_of ( xfer, struct downloader, xfer ); - off_t new_pos; - int rc; - - /* Calculate new buffer position */ - switch ( whence ) { - case SEEK_SET: - new_pos = offset; - break; - case SEEK_CUR: - new_pos = ( downloader->pos + offset ); - break; - default: - assert ( 0 ); - return -EINVAL; - } - - /* Ensure that we have enough buffer space for this buffer position */ - if ( ( rc = downloader_ensure_size ( downloader, new_pos ) ) != 0 ) - return rc; - downloader->pos = new_pos; - - return 0; -} - /** * Handle deliver_raw() event received via data transfer interface * * @v xfer Downloader data transfer interface - * @v data Data buffer - * @v len Length of data buffer + * @v iobuf Datagram I/O buffer + * @v meta Data transfer metadata * @ret rc Return status code */ -static int downloader_xfer_deliver_raw ( struct xfer_interface *xfer, - const void *data, size_t len ) { +static int downloader_xfer_deliver_iob ( struct xfer_interface *xfer, + struct io_buffer *iobuf, + struct xfer_metadata *meta ) { struct downloader *downloader = container_of ( xfer, struct downloader, xfer ); + size_t len; size_t max; int rc; + /* Calculate new buffer position */ + if ( meta->whence != SEEK_CUR ) + downloader->pos = 0; + downloader->pos += meta->offset; + /* Ensure that we have enough buffer space for this data */ + len = iob_len ( iobuf ); max = ( downloader->pos + len ); if ( ( rc = downloader_ensure_size ( downloader, max ) ) != 0 ) - return rc; + goto done; /* Copy data to buffer */ - copy_to_user ( downloader->image->data, downloader->pos, data, len ); + copy_to_user ( downloader->image->data, downloader->pos, + iobuf->data, len ); /* Update current buffer position */ downloader->pos += len; - return 0; + done: + free_iob ( iobuf ); + return rc; } /** @@ -227,10 +206,10 @@ static void downloader_xfer_close ( struct xfer_interface *xfer, int rc ) { static struct xfer_interface_operations downloader_xfer_operations = { .close = downloader_xfer_close, .vredirect = xfer_vopen, - .seek = downloader_xfer_seek, .window = unlimited_xfer_window, - .deliver_iob = xfer_deliver_as_raw, - .deliver_raw = downloader_xfer_deliver_raw, + .alloc_iob = default_xfer_alloc_iob, + .deliver_iob = downloader_xfer_deliver_iob, + .deliver_raw = xfer_deliver_as_iob, }; /**************************************************************************** diff --git a/src/core/filter.c b/src/core/filter.c index 51ec5c4b..f9ebe7cf 100644 --- a/src/core/filter.c +++ b/src/core/filter.c @@ -44,12 +44,6 @@ int filter_vredirect ( struct xfer_interface *xfer, int type, return xfer_vredirect ( other, type, args ); } -int filter_seek ( struct xfer_interface *xfer, off_t offset, int whence ) { - struct xfer_interface *other = filter_other_half ( xfer ); - - return xfer_seek ( other, offset, whence ); -} - size_t filter_window ( struct xfer_interface *xfer ) { struct xfer_interface *other = filter_other_half ( xfer ); diff --git a/src/core/hw.c b/src/core/hw.c index 3502dbfb..65604ee0 100644 --- a/src/core/hw.c +++ b/src/core/hw.c @@ -36,8 +36,8 @@ static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) { static struct xfer_interface_operations hw_xfer_operations = { .close = hw_xfer_close, .vredirect = ignore_xfer_vredirect, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, + .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, .deliver_raw = ignore_xfer_deliver_raw, }; diff --git a/src/core/posix_io.c b/src/core/posix_io.c index 27c72100..2e3781ad 100644 --- a/src/core/posix_io.c +++ b/src/core/posix_io.c @@ -103,39 +103,12 @@ static void posix_file_xfer_close ( struct xfer_interface *xfer, int rc ) { posix_file_finished ( file, rc ); } -/** - * Handle seek() event - * - * @v xfer POSIX file data transfer interface - * @v pos New position - * @ret rc Return status code - */ -static int posix_file_xfer_seek ( struct xfer_interface *xfer, off_t offset, - int whence ) { - struct posix_file *file = - container_of ( xfer, struct posix_file, xfer ); - - switch ( whence ) { - case SEEK_SET: - file->pos = offset; - break; - case SEEK_CUR: - file->pos += offset; - break; - } - - if ( file->filesize < file->pos ) - file->filesize = file->pos; - - return 0; -} - /** * Handle deliver_iob() event * * @v xfer POSIX file data transfer interface * @v iobuf I/O buffer - * @v meta Data transfer metadata, or NULL + * @v meta Data transfer metadata * @ret rc Return status code */ static int @@ -145,6 +118,13 @@ posix_file_xfer_deliver_iob ( struct xfer_interface *xfer, struct posix_file *file = container_of ( xfer, struct posix_file, xfer ); + /* Keep track of file position solely for the filesize */ + if ( meta->whence != SEEK_CUR ) + file->pos = 0; + file->pos += meta->offset; + if ( file->filesize < file->pos ) + file->filesize = file->pos; + list_add_tail ( &iobuf->list, &file->data ); return 0; } @@ -153,7 +133,6 @@ posix_file_xfer_deliver_iob ( struct xfer_interface *xfer, static struct xfer_interface_operations posix_file_xfer_operations = { .close = posix_file_xfer_close, .vredirect = xfer_vopen, - .seek = posix_file_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = posix_file_xfer_deliver_iob, diff --git a/src/core/resolv.c b/src/core/resolv.c index 808ab657..f4a587f1 100644 --- a/src/core/resolv.c +++ b/src/core/resolv.c @@ -312,7 +312,6 @@ struct named_socket { static struct xfer_interface_operations named_xfer_ops = { .close = ignore_xfer_close, .vredirect = ignore_xfer_vredirect, - .seek = ignore_xfer_seek, .window = no_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, diff --git a/src/core/xfer.c b/src/core/xfer.c index 3add057b..e8503476 100644 --- a/src/core/xfer.c +++ b/src/core/xfer.c @@ -85,31 +85,6 @@ int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) { return rc; } -/** - * Seek to position - * - * @v xfer Data transfer interface - * @v offset Offset to new position - * @v whence Basis for new position - * @ret rc Return status code - */ -int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) { - struct xfer_interface *dest = xfer_get_dest ( xfer ); - int rc; - - DBGC ( xfer, "XFER %p->%p seek %s+%ld\n", xfer, dest, - whence_text ( whence ), offset ); - - rc = dest->op->seek ( dest, offset, whence ); - - if ( rc != 0 ) { - DBGC ( xfer, "XFER %p<-%p seek: %s\n", xfer, dest, - strerror ( rc ) ); - } - xfer_put ( dest ); - return rc; -} - /** * Check flow control window * @@ -153,7 +128,7 @@ struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) { * * @v xfer Data transfer interface * @v iobuf Datagram I/O buffer - * @v meta Data transfer metadata, or NULL + * @v meta Data transfer metadata * @ret rc Return status code */ int xfer_deliver_iob_meta ( struct xfer_interface *xfer, @@ -184,7 +159,8 @@ int xfer_deliver_iob_meta ( struct xfer_interface *xfer, */ int xfer_deliver_iob ( struct xfer_interface *xfer, struct io_buffer *iobuf ) { - return xfer_deliver_iob_meta ( xfer, iobuf, NULL ); + static struct xfer_metadata dummy_metadata; + return xfer_deliver_iob_meta ( xfer, iobuf, &dummy_metadata ); } /** @@ -253,6 +229,31 @@ int xfer_printf ( struct xfer_interface *xfer, const char *format, ... ) { return rc; } +/** + * Seek to position + * + * @v xfer Data transfer interface + * @v offset Offset to new position + * @v whence Basis for new position + * @ret rc Return status code + */ +int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) { + struct io_buffer *iobuf; + struct xfer_metadata meta = { + .offset = offset, + .whence = whence, + }; + + DBGC ( xfer, "XFER %p seek %s+%ld\n", xfer, + whence_text ( whence ), offset ); + + /* Allocate and send a zero-length data buffer */ + iobuf = xfer_alloc_iob ( xfer, 0 ); + if ( ! iobuf ) + return -ENOMEM; + return xfer_deliver_iob_meta ( xfer, iobuf, &meta ); +} + /**************************************************************************** * * Helper methods @@ -286,19 +287,6 @@ int ignore_xfer_vredirect ( struct xfer_interface *xfer __unused, return 0; } -/** - * Ignore seek() event - * - * @v xfer Data transfer interface - * @v offset Offset to new position - * @v whence Basis for new position - * @ret rc Return status code - */ -int ignore_xfer_seek ( struct xfer_interface *xfer __unused, - off_t offset __unused, int whence __unused ) { - return 0; -} - /** * Unlimited flow control window * @@ -401,7 +389,6 @@ int ignore_xfer_deliver_raw ( struct xfer_interface *xfer, struct xfer_interface_operations null_xfer_ops = { .close = ignore_xfer_close, .vredirect = ignore_xfer_vredirect, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, diff --git a/src/image/embed.S b/src/image/embed.S new file mode 100644 index 00000000..4541bfdc --- /dev/null +++ b/src/image/embed.S @@ -0,0 +1,7 @@ + .section ".data", "aw" + .balign 4 + .globl _embedded_image_start +_embedded_image_start: + .incbin EMBEDIMG + .globl _embedded_image_end +_embedded_image_end: diff --git a/src/image/embedded.c b/src/image/embedded.c new file mode 100644 index 00000000..e2782a43 --- /dev/null +++ b/src/image/embedded.c @@ -0,0 +1,49 @@ +/** @file + * + * Take a possible embedded image and put it in a struct image + * data structure. + */ + +#include +#include +#include +#include +#include +#include + +extern char _embedded_image_start[], _embedded_image_end[]; + +struct image *embedded_image(void) +{ + static int reclaimed = 0; + struct image *image; + size_t eisize = _embedded_image_end - _embedded_image_start; + + if ( !eisize ) + return NULL; /* No embedded image */ + + if ( reclaimed ) + return NULL; /* Already reclaimed */ + + printf("Embedded image: %d bytes at %p\n", + eisize, _embedded_image_start); + + image = alloc_image(); + if (!image) + return NULL; + + image->len = eisize; + image->data = umalloc(eisize); + if (image->data == UNULL) { + image_put(image); + return image = NULL; + } + copy_to_user(image->data, 0, _embedded_image_start, eisize); + + /* Reclaim embedded image memory */ + reclaimed = 1; + mpopulate(_embedded_image_start, eisize); + + return image; +} + diff --git a/src/include/gpxe/embedded.h b/src/include/gpxe/embedded.h new file mode 100644 index 00000000..ec457055 --- /dev/null +++ b/src/include/gpxe/embedded.h @@ -0,0 +1,9 @@ +#ifndef _GPXE_EMBEDDED_H +#define _GPXE_EMBEDDED_H + +#include + +struct image *embedded_image(void); + +#endif + diff --git a/src/include/gpxe/filter.h b/src/include/gpxe/filter.h index 3943a9e1..126f6347 100644 --- a/src/include/gpxe/filter.h +++ b/src/include/gpxe/filter.h @@ -41,8 +41,6 @@ filter_other_half ( struct xfer_interface *xfer ) { extern void filter_close ( struct xfer_interface *xfer, int rc ); extern int filter_vredirect ( struct xfer_interface *xfer, int type, va_list args ); -extern int filter_seek ( struct xfer_interface *xfer, off_t offset, - int whence ); extern size_t filter_window ( struct xfer_interface *xfer ); extern struct io_buffer * filter_alloc_iob ( struct xfer_interface *xfer, size_t len ); diff --git a/src/include/gpxe/xfer.h b/src/include/gpxe/xfer.h index 68c1169e..c75fa002 100644 --- a/src/include/gpxe/xfer.h +++ b/src/include/gpxe/xfer.h @@ -32,17 +32,6 @@ struct xfer_interface_operations { */ int ( * vredirect ) ( struct xfer_interface *xfer, int type, va_list args ); - /** Seek to position - * - * @v xfer Data transfer interface - * @v offset Offset to new position - * @v whence Basis for new position - * @ret rc Return status code - * - * @c whence must be one of @c SEEK_SET or @c SEEK_CUR. - */ - int ( * seek ) ( struct xfer_interface *xfer, off_t offset, - int whence ); /** Check flow control window * * @v xfer Data transfer interface @@ -71,7 +60,7 @@ struct xfer_interface_operations { * * @v xfer Data transfer interface * @v iobuf Datagram I/O buffer - * @v meta Data transfer metadata, or NULL + * @v meta Data transfer metadata * @ret rc Return status code * * A data transfer interface that wishes to support only raw @@ -104,8 +93,21 @@ struct xfer_interface { struct xfer_interface_operations *op; }; +/** Basis positions for seek() events */ +enum seek_whence { + SEEK_CUR = 0, + SEEK_SET, +}; + /** Data transfer metadata */ struct xfer_metadata { + /** Position of data within stream */ + off_t offset; + /** Basis for data position + * + * Must be one of @c SEEK_CUR or @c SEEK_SET. + */ + int whence; /** Source socket address, or NULL */ struct sockaddr *src; /** Destination socket address, or NULL */ @@ -114,12 +116,6 @@ struct xfer_metadata { struct net_device *netdev; }; -/** Basis positions for seek() events */ -enum seek_whence { - SEEK_SET = 0, - SEEK_CUR, -}; - /** * Describe seek basis * @@ -128,8 +124,8 @@ enum seek_whence { static inline __attribute__ (( always_inline )) const char * whence_text ( int whence ) { switch ( whence ) { - case SEEK_SET: return "SET"; case SEEK_CUR: return "CUR"; + case SEEK_SET: return "SET"; default: return "INVALID"; } } @@ -141,7 +137,6 @@ extern void xfer_close ( struct xfer_interface *xfer, int rc ); extern int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ); extern int xfer_redirect ( struct xfer_interface *xfer, int type, ... ); -extern int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ); extern size_t xfer_window ( struct xfer_interface *xfer ); extern struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ); @@ -156,12 +151,11 @@ extern int xfer_vprintf ( struct xfer_interface *xfer, const char *format, va_list args ); extern int xfer_printf ( struct xfer_interface *xfer, const char *format, ... ); +extern int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ); extern void ignore_xfer_close ( struct xfer_interface *xfer, int rc ); extern int ignore_xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ); -extern int ignore_xfer_seek ( struct xfer_interface *xfer, off_t offset, - int whence ); extern size_t unlimited_xfer_window ( struct xfer_interface *xfer ); extern size_t no_xfer_window ( struct xfer_interface *xfer ); extern struct io_buffer * default_xfer_alloc_iob ( struct xfer_interface *xfer, diff --git a/src/interface/pxe/pxe_udp.c b/src/interface/pxe/pxe_udp.c index 745366f2..0d6d1b74 100644 --- a/src/interface/pxe/pxe_udp.c +++ b/src/interface/pxe/pxe_udp.c @@ -103,7 +103,6 @@ static int pxe_udp_deliver_iob ( struct xfer_interface *xfer, static struct xfer_interface_operations pxe_udp_xfer_operations = { .close = ignore_xfer_close, .vredirect = ignore_xfer_vredirect, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = pxe_udp_deliver_iob, diff --git a/src/net/tcp.c b/src/net/tcp.c index 2b9a97b0..d6b44b02 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -1022,7 +1022,6 @@ static int tcp_xfer_deliver_iob ( struct xfer_interface *xfer, static struct xfer_interface_operations tcp_xfer_operations = { .close = tcp_xfer_close, .vredirect = ignore_xfer_vredirect, - .seek = ignore_xfer_seek, .window = tcp_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = tcp_xfer_deliver_iob, diff --git a/src/net/tcp/ftp.c b/src/net/tcp/ftp.c index 0e4d969f..ffb2fbff 100644 --- a/src/net/tcp/ftp.c +++ b/src/net/tcp/ftp.c @@ -299,7 +299,6 @@ static int ftp_control_deliver_raw ( struct xfer_interface *control, static struct xfer_interface_operations ftp_control_operations = { .close = ftp_control_close, .vredirect = xfer_vopen, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, @@ -364,7 +363,6 @@ static int ftp_data_deliver_iob ( struct xfer_interface *data, static struct xfer_interface_operations ftp_data_operations = { .close = ftp_data_closed, .vredirect = xfer_vopen, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = ftp_data_deliver_iob, @@ -397,7 +395,6 @@ static void ftp_xfer_closed ( struct xfer_interface *xfer, int rc ) { static struct xfer_interface_operations ftp_xfer_operations = { .close = ftp_xfer_closed, .vredirect = ignore_xfer_vredirect, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, diff --git a/src/net/tcp/http.c b/src/net/tcp/http.c index 2a5450ed..db92e9eb 100644 --- a/src/net/tcp/http.c +++ b/src/net/tcp/http.c @@ -426,7 +426,6 @@ static void http_socket_close ( struct xfer_interface *socket, int rc ) { static struct xfer_interface_operations http_socket_operations = { .close = http_socket_close, .vredirect = xfer_vopen, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = http_socket_deliver_iob, @@ -453,7 +452,6 @@ static void http_xfer_close ( struct xfer_interface *xfer, int rc ) { static struct xfer_interface_operations http_xfer_operations = { .close = http_xfer_close, .vredirect = ignore_xfer_vredirect, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c index 2416089a..ff1478e4 100644 --- a/src/net/tcp/iscsi.c +++ b/src/net/tcp/iscsi.c @@ -684,7 +684,7 @@ static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi, /* Process challenge an octet at a time */ for ( ; ( value[0] && value[1] ) ; value += 2 ) { memcpy ( buf, value, 2 ); - buf[3] = 0; + buf[2] = 0; byte = strtoul ( buf, &endp, 16 ); if ( *endp != '\0' ) { DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge " @@ -1322,7 +1322,6 @@ static int iscsi_vredirect ( struct xfer_interface *socket, int type, static struct xfer_interface_operations iscsi_socket_operations = { .close = iscsi_socket_close, .vredirect = iscsi_vredirect, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, diff --git a/src/net/tls.c b/src/net/tls.c index f67bdd46..834686fb 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -1460,7 +1460,6 @@ static int tls_plainstream_deliver_raw ( struct xfer_interface *xfer, static struct xfer_interface_operations tls_plainstream_operations = { .close = tls_plainstream_close, .vredirect = ignore_xfer_vredirect, - .seek = filter_seek, .window = tls_plainstream_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, @@ -1600,7 +1599,6 @@ static int tls_cipherstream_deliver_raw ( struct xfer_interface *xfer, static struct xfer_interface_operations tls_cipherstream_operations = { .close = tls_cipherstream_close, .vredirect = xfer_vopen, - .seek = filter_seek, .window = filter_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, diff --git a/src/net/udp.c b/src/net/udp.c index eb241496..89a5b868 100644 --- a/src/net/udp.c +++ b/src/net/udp.c @@ -415,7 +415,6 @@ static int udp_xfer_deliver_iob ( struct xfer_interface *xfer, static struct xfer_interface_operations udp_xfer_operations = { .close = udp_xfer_close, .vredirect = ignore_xfer_vredirect, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = udp_alloc_iob, .deliver_iob = udp_xfer_deliver_iob, diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index 2fdb943c..2521f9ac 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -368,11 +368,11 @@ static size_t dhcp_field_len ( const void *data, size_t max_len ) { * @v max_len Field length * @v tag DHCP option tag, or 0 * - * If @c tag is non-zero, the field will be treated as a - * NUL-terminated string representing the value of the specified DHCP - * option. If @c tag is zero, the field will be treated as a block of - * DHCP options, and simply appended to the existing options in the - * option block. + * If @c tag is non-zero (and the field is not empty), the field will + * be treated as a NUL-terminated string representing the value of the + * specified DHCP option. If @c tag is zero, the field will be + * treated as a block of DHCP options, and simply appended to the + * existing options in the option block. * * The caller must ensure that there is enough space in the options * block to perform the merge. @@ -385,7 +385,9 @@ static void merge_dhcp_field ( struct dhcp_option_block *options, struct dhcp_option *end; if ( tag ) { - set_dhcp_option ( options, tag, data, strlen ( data ) ); + len = strlen ( data ); + if ( len ) + set_dhcp_option ( options, tag, data, len ); } else { len = dhcp_field_len ( data, max_len ); dest = ( options->data + options->len - 1 ); @@ -925,8 +927,8 @@ static int dhcp_deliver_raw ( struct xfer_interface *xfer, static struct xfer_interface_operations dhcp_xfer_operations = { .close = ignore_xfer_close, .vredirect = xfer_vopen, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, + .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, .deliver_raw = dhcp_deliver_raw, }; diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c index f32b2e05..d82d124b 100644 --- a/src/net/udp/dns.c +++ b/src/net/udp/dns.c @@ -435,7 +435,6 @@ static void dns_xfer_close ( struct xfer_interface *socket, int rc ) { static struct xfer_interface_operations dns_socket_operations = { .close = dns_xfer_close, .vredirect = xfer_vopen, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, diff --git a/src/net/udp/tftp.c b/src/net/udp/tftp.c index d5f02a08..e9698004 100644 --- a/src/net/udp/tftp.c +++ b/src/net/udp/tftp.c @@ -703,6 +703,7 @@ static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) { static int tftp_rx_data ( struct tftp_request *tftp, struct io_buffer *iobuf ) { struct tftp_data *data = iobuf->data; + struct xfer_metadata meta; int block; off_t offset; size_t data_len; @@ -729,8 +730,10 @@ static int tftp_rx_data ( struct tftp_request *tftp, } /* Deliver data */ - xfer_seek ( &tftp->xfer, offset, SEEK_SET ); - rc = xfer_deliver_iob ( &tftp->xfer, iobuf ); + memset ( &meta, 0, sizeof ( meta ) ); + meta.whence = SEEK_SET; + meta.offset = offset; + rc = xfer_deliver_iob_meta ( &tftp->xfer, iobuf, &meta ); iobuf = NULL; if ( rc != 0 ) { DBGC ( tftp, "TFTP %p could not deliver data: %s\n", @@ -909,7 +912,6 @@ static int tftp_socket_deliver_iob ( struct xfer_interface *socket, static struct xfer_interface_operations tftp_socket_operations = { .close = ignore_xfer_close, .vredirect = xfer_vopen, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = tftp_socket_deliver_iob, @@ -937,7 +939,6 @@ static int tftp_mc_socket_deliver_iob ( struct xfer_interface *mc_socket, static struct xfer_interface_operations tftp_mc_socket_operations = { .close = ignore_xfer_close, .vredirect = xfer_vopen, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = tftp_mc_socket_deliver_iob, @@ -964,7 +965,6 @@ static void tftp_xfer_close ( struct xfer_interface *xfer, int rc ) { static struct xfer_interface_operations tftp_xfer_operations = { .close = tftp_xfer_close, .vredirect = ignore_xfer_vredirect, - .seek = ignore_xfer_seek, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index 91836978..c3b07e9a 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,30 @@ static struct net_device * find_boot_netdev ( void ) { return NULL; } +/** + * Boot embedded image + * + * @ret rc Return status code + */ +static int boot_embedded_image ( void ) { + struct image *image; + int rc; + + image = embedded_image(); + if ( !image ) + return ENOENT; + + if ( ( rc = imgload ( image ) ) != 0 ) { + printf ( "Could not load embedded image: %s\n", + strerror ( rc ) ); + } else if ( ( rc = imgexec ( image ) ) != 0 ) { + printf ( "Could not boot embedded image: %s\n", + strerror ( rc ) ); + } + image_put ( image ); + return rc; +} + /** * Boot using filename * @@ -115,6 +140,11 @@ static int netboot ( struct net_device *netdev ) { return rc; route(); + /* Try to boot an embedded image if we have one */ + rc = boot_embedded_image (); + if ( rc != ENOENT ) + return rc; + /* Try to download and boot whatever we are given as a filename */ dhcp_snprintf ( buf, sizeof ( buf ), find_global_dhcp_option ( DHCP_BOOTFILE_NAME ) );