aboutsummaryrefslogtreecommitdiffstats
path: root/gpxe/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'gpxe/src/core')
-rw-r--r--gpxe/src/core/acpi.c2
-rw-r--r--gpxe/src/core/ansiesc.c2
-rw-r--r--gpxe/src/core/asprintf.c2
-rw-r--r--gpxe/src/core/base64.c2
-rw-r--r--gpxe/src/core/basename.c2
-rw-r--r--gpxe/src/core/bitmap.c2
-rw-r--r--gpxe/src/core/bitops.c2
-rw-r--r--gpxe/src/core/config.c224
-rw-r--r--gpxe/src/core/console.c11
-rw-r--r--gpxe/src/core/cpio.c2
-rw-r--r--gpxe/src/core/ctype.c48
-rw-r--r--gpxe/src/core/cwuri.c2
-rw-r--r--gpxe/src/core/debug.c3
-rw-r--r--gpxe/src/core/device.c9
-rw-r--r--gpxe/src/core/downloader.c27
-rw-r--r--gpxe/src/core/exec.c14
-rw-r--r--gpxe/src/core/filter.c2
-rw-r--r--gpxe/src/core/gdbstub.c17
-rw-r--r--gpxe/src/core/getkey.c2
-rw-r--r--gpxe/src/core/getopt.c2
-rw-r--r--gpxe/src/core/image.c10
-rw-r--r--gpxe/src/core/init.c25
-rw-r--r--gpxe/src/core/interface.c2
-rw-r--r--gpxe/src/core/iobuf.c2
-rw-r--r--gpxe/src/core/job.c10
-rw-r--r--gpxe/src/core/linebuf.c2
-rw-r--r--gpxe/src/core/main.c9
-rw-r--r--gpxe/src/core/malloc.c2
-rw-r--r--gpxe/src/core/misc.c17
-rw-r--r--gpxe/src/core/monojob.c2
-rw-r--r--gpxe/src/core/nvo.c2
-rw-r--r--gpxe/src/core/open.c41
-rw-r--r--gpxe/src/core/posix_io.c4
-rw-r--r--gpxe/src/core/process.c24
-rw-r--r--gpxe/src/core/random.c2
-rw-r--r--gpxe/src/core/refcnt.c2
-rw-r--r--gpxe/src/core/resolv.c53
-rw-r--r--gpxe/src/core/serial.c2
-rw-r--r--gpxe/src/core/settings.c500
-rw-r--r--gpxe/src/core/string.c2
-rw-r--r--gpxe/src/core/timer.c2
-rw-r--r--gpxe/src/core/uri.c165
-rw-r--r--gpxe/src/core/uuid.c2
-rw-r--r--gpxe/src/core/vsprintf.c2
-rw-r--r--gpxe/src/core/xfer.c5
45 files changed, 718 insertions, 548 deletions
diff --git a/gpxe/src/core/acpi.c b/gpxe/src/core/acpi.c
index 94b7b2a1..b65f4d48 100644
--- a/gpxe/src/core/acpi.c
+++ b/gpxe/src/core/acpi.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/acpi.h>
/** @file
diff --git a/gpxe/src/core/ansiesc.c b/gpxe/src/core/ansiesc.c
index 6b820ada..31306e2a 100644
--- a/gpxe/src/core/ansiesc.c
+++ b/gpxe/src/core/ansiesc.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <assert.h>
#include <gpxe/ansiesc.h>
diff --git a/gpxe/src/core/asprintf.c b/gpxe/src/core/asprintf.c
index 94d7e7c4..03cf45cf 100644
--- a/gpxe/src/core/asprintf.c
+++ b/gpxe/src/core/asprintf.c
@@ -4,6 +4,8 @@
#include <stdio.h>
#include <errno.h>
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* Write a formatted string to newly allocated memory.
*
diff --git a/gpxe/src/core/base64.c b/gpxe/src/core/base64.c
index e54821e3..5619ef7b 100644
--- a/gpxe/src/core/base64.c
+++ b/gpxe/src/core/base64.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <string.h>
#include <assert.h>
diff --git a/gpxe/src/core/basename.c b/gpxe/src/core/basename.c
index 7340c0d5..a481c54f 100644
--- a/gpxe/src/core/basename.c
+++ b/gpxe/src/core/basename.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
diff --git a/gpxe/src/core/bitmap.c b/gpxe/src/core/bitmap.c
index d0266471..bbe9cbaa 100644
--- a/gpxe/src/core/bitmap.c
+++ b/gpxe/src/core/bitmap.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <errno.h>
#include <gpxe/bitmap.h>
diff --git a/gpxe/src/core/bitops.c b/gpxe/src/core/bitops.c
index 53abaaea..1bca9e47 100644
--- a/gpxe/src/core/bitops.c
+++ b/gpxe/src/core/bitops.c
@@ -1,5 +1,7 @@
#include <strings.h>
+FILE_LICENCE ( GPL2_OR_LATER );
+
int __flsl ( long x ) {
unsigned long value = x;
int ls = 0;
diff --git a/gpxe/src/core/config.c b/gpxe/src/core/config.c
deleted file mode 100644
index bd0d66ec..00000000
--- a/gpxe/src/core/config.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2, or (at
- * your option) any later version.
- */
-
-#include <config/general.h>
-#include <config/console.h>
-
-/*
- * Build ID string calculations
- *
- */
-#undef XSTR
-#undef STR
-#define XSTR(s) STR(s)
-#define STR(s) #s
-
-#ifdef BUILD_SERIAL
-#include "config/.buildserial.h"
-#define BUILD_SERIAL_STR " #" XSTR(BUILD_SERIAL_NUM)
-#else
-#define BUILD_SERIAL_STR ""
-#endif
-
-#ifdef BUILD_ID
-#define BUILD_ID_STR " " BUILD_ID
-#else
-#define BUILD_ID_STR ""
-#endif
-
-#if defined(BUILD_ID) || defined(BUILD_SERIAL)
-#define BUILD_STRING " [build" BUILD_ID_STR BUILD_SERIAL_STR "]"
-#else
-#define BUILD_STRING ""
-#endif
-
-/*
- * Drag in all requested console types
- *
- */
-
-#ifdef CONSOLE_PCBIOS
-REQUIRE_OBJECT ( bios_console );
-#endif
-#ifdef CONSOLE_SERIAL
-REQUIRE_OBJECT ( serial_console );
-#endif
-#ifdef CONSOLE_DIRECT_VGA
-REQUIRE_OBJECT ( video_subr );
-#endif
-#ifdef CONSOLE_BTEXT
-REQUIRE_OBJECT ( btext );
-#endif
-#ifdef CONSOLE_PC_KBD
-REQUIRE_OBJECT ( pc_kbd );
-#endif
-#ifdef CONSOLE_SYSLOG
-REQUIRE_OBJECT ( syslog );
-#endif
-#ifdef CONSOLE_EFI
-REQUIRE_OBJECT ( efi_console );
-#endif
-
-/*
- * Drag in all requested network protocols
- *
- */
-#ifdef NET_PROTO_IPV4
-REQUIRE_OBJECT ( ipv4 );
-#endif
-
-/*
- * Drag in all requested download protocols
- *
- */
-#ifdef DOWNLOAD_PROTO_TFTP
-REQUIRE_OBJECT ( tftp );
-#endif
-#ifdef DOWNLOAD_PROTO_NFS
-REQUIRE_OBJECT ( nfs );
-#endif
-#ifdef DOWNLOAD_PROTO_HTTP
-REQUIRE_OBJECT ( http );
-#endif
-#ifdef DOWNLOAD_PROTO_HTTPS
-REQUIRE_OBJECT ( https );
-#endif
-#ifdef DOWNLOAD_PROTO_FTP
-REQUIRE_OBJECT ( ftp );
-#endif
-#ifdef DOWNLOAD_PROTO_TFTM
-REQUIRE_OBJECT ( tftm );
-#endif
-#ifdef DOWNLOAD_PROTO_SLAM
-REQUIRE_OBJECT ( slam );
-#endif
-
-/*
- * Drag in all requested SAN boot protocols
- *
- */
-#ifdef SANBOOT_PROTO_ISCSI
-REQUIRE_OBJECT ( iscsiboot );
-#endif
-#ifdef SANBOOT_PROTO_AOE
-REQUIRE_OBJECT ( aoeboot );
-#endif
-
-/*
- * Drag in all requested resolvers
- *
- */
-#ifdef DNS_RESOLVER
-REQUIRE_OBJECT ( dns );
-#endif
-#ifdef NMB_RESOLVER
-REQUIRE_OBJECT ( nmb );
-#endif
-
-/*
- * Drag in all requested image formats
- *
- */
-#ifdef IMAGE_NBI
-REQUIRE_OBJECT ( nbi );
-#endif
-#ifdef IMAGE_ELF
-REQUIRE_OBJECT ( elfboot );
-#endif
-#ifdef IMAGE_FREEBSD
-REQUIRE_OBJECT ( freebsd );
-#endif
-#ifdef IMAGE_MULTIBOOT
-REQUIRE_OBJECT ( multiboot );
-#endif
-#ifdef IMAGE_AOUT
-REQUIRE_OBJECT ( aout );
-#endif
-#ifdef IMAGE_WINCE
-REQUIRE_OBJECT ( wince );
-#endif
-#ifdef IMAGE_PXE
-REQUIRE_OBJECT ( pxe_image );
-#endif
-#ifdef IMAGE_SCRIPT
-REQUIRE_OBJECT ( script );
-#endif
-#ifdef IMAGE_BZIMAGE
-REQUIRE_OBJECT ( bzimage );
-#endif
-#ifdef IMAGE_ELTORITO
-REQUIRE_OBJECT ( eltorito );
-#endif
-#ifdef IMAGE_COMBOOT
-REQUIRE_OBJECT ( comboot );
-REQUIRE_OBJECT ( com32 );
-REQUIRE_OBJECT ( comboot_call );
-REQUIRE_OBJECT ( com32_call );
-REQUIRE_OBJECT ( com32_wrapper );
-REQUIRE_OBJECT ( comboot_resolv );
-#endif
-#ifdef IMAGE_EFI
-REQUIRE_OBJECT ( efi_image );
-#endif
-
-/*
- * Drag in all requested commands
- *
- */
-#ifdef AUTOBOOT_CMD
-REQUIRE_OBJECT ( autoboot_cmd );
-#endif
-#ifdef NVO_CMD
-REQUIRE_OBJECT ( nvo_cmd );
-#endif
-#ifdef CONFIG_CMD
-REQUIRE_OBJECT ( config_cmd );
-#endif
-#ifdef IFMGMT_CMD
-REQUIRE_OBJECT ( ifmgmt_cmd );
-#endif
-#ifdef ROUTE_CMD
-REQUIRE_OBJECT ( route_cmd );
-#endif
-#ifdef IMAGE_CMD
-REQUIRE_OBJECT ( image_cmd );
-#endif
-#ifdef DHCP_CMD
-REQUIRE_OBJECT ( dhcp_cmd );
-#endif
-#ifdef SANBOOT_CMD
-REQUIRE_OBJECT ( sanboot_cmd );
-#endif
-#ifdef LOGIN_CMD
-REQUIRE_OBJECT ( login_cmd );
-#endif
-
-/*
- * Drag in miscellaneous objects
- *
- */
-#ifdef NULL_TRAP
-REQUIRE_OBJECT ( nulltrap );
-#endif
-#ifdef GDBSERIAL
-REQUIRE_OBJECT ( gdbidt );
-REQUIRE_OBJECT ( gdbserial );
-REQUIRE_OBJECT ( gdbstub_cmd );
-#endif
-#ifdef GDBUDP
-REQUIRE_OBJECT ( gdbidt );
-REQUIRE_OBJECT ( gdbudp );
-REQUIRE_OBJECT ( gdbstub_cmd );
-#endif
-
-/*
- * Drag in objects that are always required, but not dragged in via
- * symbol dependencies.
- *
- */
-REQUIRE_OBJECT ( device );
-REQUIRE_OBJECT ( embedded );
diff --git a/gpxe/src/core/console.c b/gpxe/src/core/console.c
index c9773f71..e22d2601 100644
--- a/gpxe/src/core/console.c
+++ b/gpxe/src/core/console.c
@@ -5,10 +5,7 @@
/** @file */
-static struct console_driver console_drivers[0]
- __table_start ( struct console_driver, console );
-static struct console_driver console_drivers_end[0]
- __table_end ( struct console_driver, console );
+FILE_LICENCE ( GPL2_OR_LATER );
/**
* Write a single character to each console device.
@@ -28,8 +25,7 @@ void putchar ( int character ) {
if ( character == '\n' )
putchar ( '\r' );
- for ( console = console_drivers; console < console_drivers_end ;
- console++ ) {
+ for_each_table_entry ( console, CONSOLES ) {
if ( ( ! console->disabled ) && console->putchar )
console->putchar ( character );
}
@@ -51,8 +47,7 @@ void putchar ( int character ) {
static struct console_driver * has_input ( void ) {
struct console_driver *console;
- for ( console = console_drivers; console < console_drivers_end ;
- console++ ) {
+ for_each_table_entry ( console, CONSOLES ) {
if ( ( ! console->disabled ) && console->iskey ) {
if ( console->iskey () )
return console;
diff --git a/gpxe/src/core/cpio.c b/gpxe/src/core/cpio.c
index 7d2e8828..b303fa35 100644
--- a/gpxe/src/core/cpio.c
+++ b/gpxe/src/core/cpio.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/** @file
*
* CPIO archives
diff --git a/gpxe/src/core/ctype.c b/gpxe/src/core/ctype.c
new file mode 100644
index 00000000..6185bb2f
--- /dev/null
+++ b/gpxe/src/core/ctype.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Character types
+ *
+ */
+
+#include <ctype.h>
+
+/**
+ * Check to see if character is a space
+ *
+ * @v c Character
+ * @ret isspace Character is a space
+ */
+int isspace ( int c ) {
+ switch ( c ) {
+ case ' ' :
+ case '\f' :
+ case '\n' :
+ case '\r' :
+ case '\t' :
+ case '\v' :
+ return 1;
+ default:
+ return 0;
+ }
+}
diff --git a/gpxe/src/core/cwuri.c b/gpxe/src/core/cwuri.c
index 81fd900e..65e01b21 100644
--- a/gpxe/src/core/cwuri.c
+++ b/gpxe/src/core/cwuri.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stddef.h>
#include <gpxe/uri.h>
diff --git a/gpxe/src/core/debug.c b/gpxe/src/core/debug.c
index 500a7ac0..8f929309 100644
--- a/gpxe/src/core/debug.c
+++ b/gpxe/src/core/debug.c
@@ -36,7 +36,8 @@ static void dbg_hex_dump_da_row ( unsigned long dispaddr, const void *data,
printf ( " " );
continue;
}
- printf ( " %02x", bytes[i] );
+ printf ( "%c%02x",
+ ( ( ( i % 16 ) == 8 ) ? '-' : ' ' ), bytes[i] );
}
printf ( " : " );
for ( i = offset ; i < ( offset + 16 ) ; i++ ) {
diff --git a/gpxe/src/core/device.c b/gpxe/src/core/device.c
index 84915c2d..96ccc9ff 100644
--- a/gpxe/src/core/device.c
+++ b/gpxe/src/core/device.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <gpxe/list.h>
#include <gpxe/tables.h>
@@ -29,11 +31,6 @@
*
*/
-static struct root_device root_devices[0]
- __table_start ( struct root_device, root_devices );
-static struct root_device root_devices_end[0]
- __table_end ( struct root_device, root_devices );
-
/** Registered root devices */
static LIST_HEAD ( devices );
@@ -77,7 +74,7 @@ static void probe_devices ( void ) {
struct root_device *rootdev;
int rc;
- for ( rootdev = root_devices; rootdev < root_devices_end; rootdev++ ) {
+ for_each_table_entry ( rootdev, ROOT_DEVICES ) {
list_add ( &rootdev->dev.siblings, &devices );
INIT_LIST_HEAD ( &rootdev->dev.children );
if ( ( rc = rootdev_probe ( rootdev ) ) != 0 )
diff --git a/gpxe/src/core/downloader.c b/gpxe/src/core/downloader.c
index 0a443db2..86c144dc 100644
--- a/gpxe/src/core/downloader.c
+++ b/gpxe/src/core/downloader.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
@@ -124,18 +126,37 @@ static int downloader_ensure_size ( struct downloader *downloader,
* @v job Downloader job control interface
*/
static void downloader_job_kill ( struct job_interface *job ) {
- struct downloader *downloader =
+ struct downloader *downloader =
container_of ( job, struct downloader, job );
/* Terminate download */
downloader_finished ( downloader, -ECANCELED );
}
+/**
+ * Report progress of download job
+ *
+ * @v job Downloader job control interface
+ * @v progress Progress report to fill in
+ */
+static void downloader_job_progress ( struct job_interface *job,
+ struct job_progress *progress ) {
+ struct downloader *downloader =
+ container_of ( job, struct downloader, job );
+
+ /* This is not entirely accurate, since downloaded data may
+ * arrive out of order (e.g. with multicast protocols), but
+ * it's a reasonable first approximation.
+ */
+ progress->completed = downloader->pos;
+ progress->total = downloader->image->len;
+}
+
/** Downloader job control interface operations */
static struct job_interface_operations downloader_job_operations = {
.done = ignore_job_done,
.kill = downloader_job_kill,
- .progress = ignore_job_progress,
+ .progress = downloader_job_progress,
};
/****************************************************************************
@@ -205,7 +226,7 @@ static void downloader_xfer_close ( struct xfer_interface *xfer, int rc ) {
/** Downloader data transfer interface operations */
static struct xfer_interface_operations downloader_xfer_operations = {
.close = downloader_xfer_close,
- .vredirect = xfer_vopen,
+ .vredirect = xfer_vreopen,
.window = unlimited_xfer_window,
.alloc_iob = default_xfer_alloc_iob,
.deliver_iob = downloader_xfer_deliver_iob,
diff --git a/gpxe/src/core/exec.c b/gpxe/src/core/exec.c
index a9861b60..6c16aa44 100644
--- a/gpxe/src/core/exec.c
+++ b/gpxe/src/core/exec.c
@@ -16,10 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <ctype.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
@@ -34,11 +37,6 @@
*
*/
-static struct command commands[0]
- __table_start ( struct command, commands );
-static struct command commands_end[0]
- __table_end ( struct command, commands );
-
/* Avoid dragging in getopt.o unless a command really uses it */
int optind;
int nextchar;
@@ -78,7 +76,7 @@ int execv ( const char *command, char * const argv[] ) {
reset_getopt();
/* Hand off to command implementation */
- for ( cmd = commands ; cmd < commands_end ; cmd++ ) {
+ for_each_table_entry ( cmd, COMMANDS ) {
if ( strcmp ( command, cmd->name ) == 0 )
return cmd->exec ( argc, ( char ** ) argv );
}
@@ -173,7 +171,7 @@ static int split_args ( char *args, char * argv[] ) {
while ( 1 ) {
/* Skip over any whitespace / convert to NUL */
- while ( *args == ' ' ) {
+ while ( isspace ( *args ) ) {
if ( argv )
*args = '\0';
args++;
@@ -186,7 +184,7 @@ static int split_args ( char *args, char * argv[] ) {
argv[argc] = args;
argc++;
/* Skip to start of next whitespace, if any */
- while ( *args && ( *args != ' ' ) ) {
+ while ( *args && ! isspace ( *args ) ) {
args++;
}
}
diff --git a/gpxe/src/core/filter.c b/gpxe/src/core/filter.c
index f9ebe7cf..a8bee7dc 100644
--- a/gpxe/src/core/filter.c
+++ b/gpxe/src/core/filter.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/xfer.h>
#include <gpxe/filter.h>
diff --git a/gpxe/src/core/gdbstub.c b/gpxe/src/core/gdbstub.c
index bbed344f..c8083955 100644
--- a/gpxe/src/core/gdbstub.c
+++ b/gpxe/src/core/gdbstub.c
@@ -54,10 +54,6 @@ struct gdbstub {
int len; /* length of payload */
};
-/* Transports */
-static struct gdb_transport gdb_transport_start[0] __table_start ( struct gdb_transport, gdb_transports );
-static struct gdb_transport gdb_transport_end[0] __table_end ( struct gdb_transport, gdb_transports );
-
/* Packet parser states */
static void gdbstub_state_new ( struct gdbstub *stub, char ch );
static void gdbstub_state_data ( struct gdbstub *stub, char ch );
@@ -348,12 +344,10 @@ static void gdbstub_state_cksum2 ( struct gdbstub *stub, char ch ) {
static void gdbstub_state_wait_ack ( struct gdbstub *stub, char ch ) {
if ( ch == '+' ) {
stub->parse = gdbstub_state_new;
- } else if ( ch == '-' ) {
- gdbstub_tx_packet ( stub ); /* retransmit */
- } else if ( ch == '$' ) {
- /* GDB is reconnecting, drop our packet and listen to GDB */
- stub->trans->send ( "-", 1 );
- stub->parse = gdbstub_state_new;
+ } else {
+ /* This retransmit is very aggressive but necessary to keep
+ * in sync with GDB. */
+ gdbstub_tx_packet ( stub );
}
}
@@ -387,7 +381,8 @@ void gdbstub_handler ( int signo, gdbreg_t *regs ) {
struct gdb_transport *find_gdb_transport ( const char *name ) {
struct gdb_transport *trans;
- for ( trans = gdb_transport_start; trans < gdb_transport_end; trans++ ) {
+
+ for_each_table_entry ( trans, GDB_TRANSPORTS ) {
if ( strcmp ( trans->name, name ) == 0 ) {
return trans;
}
diff --git a/gpxe/src/core/getkey.c b/gpxe/src/core/getkey.c
index 787c9027..dbd074cc 100644
--- a/gpxe/src/core/getkey.c
+++ b/gpxe/src/core/getkey.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <ctype.h>
#include <console.h>
#include <gpxe/process.h>
diff --git a/gpxe/src/core/getopt.c b/gpxe/src/core/getopt.c
index 6de412bb..b67da0c1 100644
--- a/gpxe/src/core/getopt.c
+++ b/gpxe/src/core/getopt.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <string.h>
#include <stdio.h>
diff --git a/gpxe/src/core/image.c b/gpxe/src/core/image.c
index 277d09a9..24fe51ab 100644
--- a/gpxe/src/core/image.c
+++ b/gpxe/src/core/image.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
@@ -37,12 +39,6 @@
/** List of registered images */
struct list_head images = LIST_HEAD_INIT ( images );
-/** List of image types */
-static struct image_type image_types[0]
- __table_start ( struct image_type, image_types );
-static struct image_type image_types_end[0]
- __table_end ( struct image_type, image_types );
-
/**
* Free executable/loadable image
*
@@ -219,7 +215,7 @@ int image_autoload ( struct image *image ) {
return image_load ( image );
/* Otherwise probe for a suitable type */
- for ( type = image_types ; type < image_types_end ; type++ ) {
+ for_each_table_entry ( type, IMAGE_TYPES ) {
DBGC ( image, "IMAGE %p trying type %s\n", image, type->name );
rc = image_load_type ( image, type );
if ( image->type == NULL )
diff --git a/gpxe/src/core/init.c b/gpxe/src/core/init.c
index 50e199ce..cd0f6dcc 100644
--- a/gpxe/src/core/init.c
+++ b/gpxe/src/core/init.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/device.h>
#include <gpxe/init.h>
@@ -25,18 +27,6 @@
*
*/
-/** Registered initialisation functions */
-static struct init_fn init_fns[0]
- __table_start ( struct init_fn, init_fns );
-static struct init_fn init_fns_end[0]
- __table_end ( struct init_fn, init_fns );
-
-/** Registered startup/shutdown functions */
-static struct startup_fn startup_fns[0]
- __table_start ( struct startup_fn, startup_fns );
-static struct startup_fn startup_fns_end[0]
- __table_end ( struct startup_fn, startup_fns );
-
/** "startup() has been called" flag */
static int started = 0;
@@ -54,9 +44,8 @@ void initialise ( void ) {
struct init_fn *init_fn;
/* Call registered initialisation functions */
- for ( init_fn = init_fns ; init_fn < init_fns_end ; init_fn++ ) {
+ for_each_table_entry ( init_fn, INIT_FNS )
init_fn->initialise ();
- }
}
/**
@@ -73,8 +62,7 @@ void startup ( void ) {
return;
/* Call registered startup functions */
- for ( startup_fn = startup_fns ; startup_fn < startup_fns_end ;
- startup_fn++ ) {
+ for_each_table_entry ( startup_fn, STARTUP_FNS ) {
if ( startup_fn->startup )
startup_fn->startup();
}
@@ -90,7 +78,7 @@ void startup ( void ) {
* This function reverses the actions of startup(), and leaves gPXE in
* a state ready to be removed from memory. You may call startup()
* again after calling shutdown().
-
+ *
* Call this function only once, before either exiting main() or
* starting up a non-returnable image.
*/
@@ -101,8 +89,7 @@ void shutdown ( int flags ) {
return;
/* Call registered shutdown functions (in reverse order) */
- for ( startup_fn = startup_fns_end - 1 ; startup_fn >= startup_fns ;
- startup_fn-- ) {
+ for_each_table_entry_reverse ( startup_fn, STARTUP_FNS ) {
if ( startup_fn->shutdown )
startup_fn->shutdown ( flags );
}
diff --git a/gpxe/src/core/interface.c b/gpxe/src/core/interface.c
index 37aabfe0..43d58ed2 100644
--- a/gpxe/src/core/interface.c
+++ b/gpxe/src/core/interface.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/interface.h>
/** @file
diff --git a/gpxe/src/core/iobuf.c b/gpxe/src/core/iobuf.c
index cc4aedea..1ce7890e 100644
--- a/gpxe/src/core/iobuf.c
+++ b/gpxe/src/core/iobuf.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <errno.h>
#include <gpxe/malloc.h>
diff --git a/gpxe/src/core/job.c b/gpxe/src/core/job.c
index 6c2faf30..438064ef 100644
--- a/gpxe/src/core/job.c
+++ b/gpxe/src/core/job.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <errno.h>
#include <gpxe/job.h>
@@ -42,6 +44,14 @@ void job_kill ( struct job_interface *job ) {
job_put ( dest );
}
+void job_progress ( struct job_interface *job,
+ struct job_progress *progress ) {
+ struct job_interface *dest = job_get_dest ( job );
+
+ dest->op->progress ( dest, progress );
+ job_put ( dest );
+}
+
/****************************************************************************
*
* Helper methods
diff --git a/gpxe/src/core/linebuf.c b/gpxe/src/core/linebuf.c
index d02f37c3..221f4e1a 100644
--- a/gpxe/src/core/linebuf.c
+++ b/gpxe/src/core/linebuf.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
diff --git a/gpxe/src/core/main.c b/gpxe/src/core/main.c
index bd2428f0..d07d24c0 100644
--- a/gpxe/src/core/main.c
+++ b/gpxe/src/core/main.c
@@ -9,11 +9,11 @@ Literature dealing with the network protocols:
DHCP - RFC2131, RFC2132 (options)
TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
- NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
- IGMP - RFC1112
**************************************************************************/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdio.h>
#include <gpxe/init.h>
#include <gpxe/features.h>
@@ -27,9 +27,6 @@ Literature dealing with the network protocols:
#define BOLD "\033[1m"
#define CYAN "\033[36m"
-static struct feature features[0] __table_start ( struct feature, features );
-static struct feature features_end[0] __table_end ( struct feature, features );
-
/**
* Main entry point
*
@@ -61,7 +58,7 @@ __asmcall int main ( void ) {
NORMAL " -- Open Source Boot Firmware -- "
CYAN "http://etherboot.org" NORMAL "\n"
"Features:" );
- for ( feature = features ; feature < features_end ; feature++ )
+ for_each_table_entry ( feature, FEATURES )
printf ( " %s", feature->name );
printf ( "\n" );
diff --git a/gpxe/src/core/malloc.c b/gpxe/src/core/malloc.c
index db7f1bed..8b0bc24d 100644
--- a/gpxe/src/core/malloc.c
+++ b/gpxe/src/core/malloc.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stddef.h>
#include <stdint.h>
#include <string.h>
diff --git a/gpxe/src/core/misc.c b/gpxe/src/core/misc.c
index 1f51272d..c19591bb 100644
--- a/gpxe/src/core/misc.c
+++ b/gpxe/src/core/misc.c
@@ -2,7 +2,10 @@
MISC Support Routines
**************************************************************************/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
+#include <ctype.h>
#include <byteswap.h>
#include <gpxe/in.h>
#include <gpxe/timer.h>
@@ -30,20 +33,6 @@ int inet_aton ( const char *cp, struct in_addr *inp ) {
return 0;
}
-int isspace ( int c ) {
- switch ( c ) {
- case ' ':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- case '\v':
- return 1;
- default:
- return 0;
- }
-}
-
unsigned long strtoul ( const char *p, char **endp, int base ) {
unsigned long ret = 0;
unsigned int charval;
diff --git a/gpxe/src/core/monojob.c b/gpxe/src/core/monojob.c
index 657bfd7a..a24b559e 100644
--- a/gpxe/src/core/monojob.c
+++ b/gpxe/src/core/monojob.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <stdio.h>
#include <errno.h>
diff --git a/gpxe/src/core/nvo.c b/gpxe/src/core/nvo.c
index e5c07d98..3dbf51d3 100644
--- a/gpxe/src/core/nvo.c
+++ b/gpxe/src/core/nvo.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
diff --git a/gpxe/src/core/open.c b/gpxe/src/core/open.c
index db8d92e6..70b427ba 100644
--- a/gpxe/src/core/open.c
+++ b/gpxe/src/core/open.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdarg.h>
#include <string.h>
#include <errno.h>
@@ -30,18 +32,6 @@
*
*/
-/** Registered URI openers */
-static struct uri_opener uri_openers[0]
- __table_start ( struct uri_opener, uri_openers );
-static struct uri_opener uri_openers_end[0]
- __table_end ( struct uri_opener, uri_openers );
-
-/** Registered socket openers */
-static struct socket_opener socket_openers[0]
- __table_start ( struct socket_opener, socket_openers );
-static struct socket_opener socket_openers_end[0]
- __table_end ( struct socket_opener, socket_openers );
-
/**
* Open URI
*
@@ -63,8 +53,10 @@ int xfer_open_uri ( struct xfer_interface *xfer, struct uri *uri ) {
return -ENOMEM;
/* Find opener which supports this URI scheme */
- for ( opener = uri_openers ; opener < uri_openers_end ; opener++ ) {
+ for_each_table_entry ( opener, URI_OPENERS ) {
if ( strcmp ( resolved_uri->scheme, opener->scheme ) == 0 ) {
+ DBGC ( xfer, "XFER %p opening %s URI\n",
+ xfer, opener->scheme );
rc = opener->open ( xfer, resolved_uri );
goto done;
}
@@ -121,7 +113,7 @@ int xfer_open_socket ( struct xfer_interface *xfer, int semantics,
socket_semantics_name ( semantics ),
socket_family_name ( peer->sa_family ) );
- for ( opener = socket_openers; opener < socket_openers_end; opener++ ){
+ for_each_table_entry ( opener, SOCKET_OPENERS ) {
if ( ( opener->semantics == semantics ) &&
( opener->family == peer->sa_family ) ) {
return opener->open ( xfer, peer, local );
@@ -182,3 +174,24 @@ int xfer_open ( struct xfer_interface *xfer, int type, ... ) {
va_end ( args );
return rc;
}
+
+/**
+ * Reopen location
+ *
+ * @v xfer Data transfer interface
+ * @v type Location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ *
+ * This will close the existing connection and open a new connection
+ * using xfer_vopen(). It is intended to be used as a .vredirect
+ * method handler.
+ */
+int xfer_vreopen ( struct xfer_interface *xfer, int type, va_list args ) {
+
+ /* Close existing connection */
+ xfer_close ( xfer, 0 );
+
+ /* Open new location */
+ return xfer_vopen ( xfer, type, args );
+}
diff --git a/gpxe/src/core/posix_io.c b/gpxe/src/core/posix_io.c
index e0459bdf..e6b1a0f6 100644
--- a/gpxe/src/core/posix_io.c
+++ b/gpxe/src/core/posix_io.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <string.h>
#include <errno.h>
@@ -137,7 +139,7 @@ posix_file_xfer_deliver_iob ( struct xfer_interface *xfer,
/** POSIX file data transfer interface operations */
static struct xfer_interface_operations posix_file_xfer_operations = {
.close = posix_file_xfer_close,
- .vredirect = xfer_vopen,
+ .vredirect = xfer_vreopen,
.window = unlimited_xfer_window,
.alloc_iob = default_xfer_alloc_iob,
.deliver_iob = posix_file_xfer_deliver_iob,
diff --git a/gpxe/src/core/process.c b/gpxe/src/core/process.c
index 6a687140..9c13e020 100644
--- a/gpxe/src/core/process.c
+++ b/gpxe/src/core/process.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/list.h>
#include <gpxe/init.h>
#include <gpxe/process.h>
@@ -31,21 +33,22 @@
/** Process run queue */
static LIST_HEAD ( run_queue );
-/** Registered permanent processes */
-static struct process processes[0]
- __table_start ( struct process, processes );
-static struct process processes_end[0]
- __table_end ( struct process, processes );
-
/**
* Add process to process list
*
* @v process Process
+ *
+ * It is safe to call process_add() multiple times; further calls will
+ * have no effect.
*/
void process_add ( struct process *process ) {
- DBGC ( process, "PROCESS %p starting\n", process );
- ref_get ( process->refcnt );
- list_add_tail ( &process->list, &run_queue );
+ if ( list_empty ( &process->list ) ) {
+ DBGC ( process, "PROCESS %p starting\n", process );
+ ref_get ( process->refcnt );
+ list_add_tail ( &process->list, &run_queue );
+ } else {
+ DBGC ( process, "PROCESS %p already started\n", process );
+ }
}
/**
@@ -93,9 +96,8 @@ void step ( void ) {
static void init_processes ( void ) {
struct process *process;
- for ( process = processes ; process < processes_end ; process++ ) {
+ for_each_table_entry ( process, PERMANENT_PROCESSES )
process_add ( process );
- }
}
/** Process initialiser */
diff --git a/gpxe/src/core/random.c b/gpxe/src/core/random.c
index d34e763a..6e7374e3 100644
--- a/gpxe/src/core/random.c
+++ b/gpxe/src/core/random.c
@@ -4,6 +4,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <gpxe/timer.h>
diff --git a/gpxe/src/core/refcnt.c b/gpxe/src/core/refcnt.c
index 30bb6dea..f2286cac 100644
--- a/gpxe/src/core/refcnt.c
+++ b/gpxe/src/core/refcnt.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <gpxe/refcnt.h>
diff --git a/gpxe/src/core/resolv.c b/gpxe/src/core/resolv.c
index f4a587f1..6f01f93e 100644
--- a/gpxe/src/core/resolv.c
+++ b/gpxe/src/core/resolv.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -150,12 +152,6 @@ struct resolver numeric_resolver __resolver ( RESOLV_NUMERIC ) = {
***************************************************************************
*/
-/** Registered name resolvers */
-static struct resolver resolvers[0]
- __table_start ( struct resolver, resolvers );
-static struct resolver resolvers_end[0]
- __table_end ( struct resolver, resolvers );
-
/** A name resolution multiplexer */
struct resolv_mux {
/** Reference counter */
@@ -223,7 +219,7 @@ static void resolv_mux_done ( struct resolv_interface *resolv,
/* Attempt next child resolver, if possible */
mux->resolver++;
- if ( mux->resolver >= resolvers_end ) {
+ if ( mux->resolver >= table_end ( RESOLVERS ) ) {
DBGC ( mux, "RESOLV %p failed to resolve name\n", mux );
goto finished;
}
@@ -262,7 +258,7 @@ int resolv ( struct resolv_interface *resolv, const char *name,
return -ENOMEM;
resolv_init ( &mux->parent, &null_resolv_ops, &mux->refcnt );
resolv_init ( &mux->child, &resolv_mux_child_ops, &mux->refcnt );
- mux->resolver = resolvers;
+ mux->resolver = table_start ( RESOLVERS );
memcpy ( &mux->sa, sa, sizeof ( mux->sa ) );
memcpy ( mux->name, name, name_len );
@@ -308,9 +304,36 @@ struct named_socket {
int have_local;
};
+/**
+ * Finish using named socket
+ *
+ * @v named Named socket
+ * @v rc Reason for finish
+ */
+static void named_done ( struct named_socket *named, int rc ) {
+
+ /* Close all interfaces */
+ resolv_nullify ( &named->resolv );
+ xfer_nullify ( &named->xfer );
+ xfer_close ( &named->xfer, rc );
+}
+
+/**
+ * Handle close() event
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+static void named_xfer_close ( struct xfer_interface *xfer, int rc ) {
+ struct named_socket *named =
+ container_of ( xfer, struct named_socket, xfer );
+
+ named_done ( named, rc );
+}
+
/** Named socket opener data transfer interface operations */
static struct xfer_interface_operations named_xfer_ops = {
- .close = ignore_xfer_close,
+ .close = named_xfer_close,
.vredirect = ignore_xfer_vredirect,
.window = no_xfer_window,
.alloc_iob = default_xfer_alloc_iob,
@@ -330,10 +353,6 @@ static void named_resolv_done ( struct resolv_interface *resolv,
struct named_socket *named =
container_of ( resolv, struct named_socket, resolv );
- /* Unplug resolver and nullify data transfer interface */
- resolv_unplug ( &named->resolv );
- xfer_nullify ( &named->xfer );
-
/* Redirect if name resolution was successful */
if ( rc == 0 ) {
rc = xfer_redirect ( &named->xfer, LOCATION_SOCKET,
@@ -342,12 +361,8 @@ static void named_resolv_done ( struct resolv_interface *resolv,
&named->local : NULL ) );
}
- /* Close data transfer interface if redirection failed */
- if ( rc != 0 )
- xfer_close ( &named->xfer, rc );
-
- /* Unplug data transfer interface */
- xfer_unplug ( &named->xfer );
+ /* Terminate resolution */
+ named_done ( named, rc );
}
/** Named socket opener name resolution interface operations */
diff --git a/gpxe/src/core/serial.c b/gpxe/src/core/serial.c
index 5b3be39c..d35e89e9 100644
--- a/gpxe/src/core/serial.c
+++ b/gpxe/src/core/serial.c
@@ -11,6 +11,8 @@
* parity, 1 stop bit (8N1). This can be changed in init_serial().
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include "stddef.h"
#include <gpxe/init.h>
#include <gpxe/io.h>
diff --git a/gpxe/src/core/settings.c b/gpxe/src/core/settings.c
index f34eb664..7d83101c 100644
--- a/gpxe/src/core/settings.c
+++ b/gpxe/src/core/settings.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
@@ -37,85 +39,326 @@
*
*/
-/** Registered settings */
-static struct setting settings[0]
- __table_start ( struct setting, settings );
-static struct setting settings_end[0]
- __table_end ( struct setting, settings );
+/******************************************************************************
+ *
+ * Generic settings blocks
+ *
+ ******************************************************************************
+ */
-/** Registered setting types */
-static struct setting_type setting_types[0]
- __table_start ( struct setting_type, setting_types );
-static struct setting_type setting_types_end[0]
- __table_end ( struct setting_type, setting_types );
+/**
+ * A generic setting
+ *
+ */
+struct generic_setting {
+ /** List of generic settings */
+ struct list_head list;
+ /** Setting */
+ struct setting setting;
+ /** Size of setting name */
+ size_t name_len;
+ /** Size of setting data */
+ size_t data_len;
+};
-/** Registered settings applicators */
-static struct settings_applicator settings_applicators[0]
- __table_start ( struct settings_applicator, settings_applicators );
-static struct settings_applicator settings_applicators_end[0]
- __table_end ( struct settings_applicator, settings_applicators );
+/**
+ * Get generic setting name
+ *
+ * @v generic Generic setting
+ * @ret name Generic setting name
+ */
+static inline void * generic_setting_name ( struct generic_setting *generic ) {
+ return ( ( ( void * ) generic ) + sizeof ( *generic ) );
+}
-/******************************************************************************
+/**
+ * Get generic setting data
*
- * Registered settings blocks
+ * @v generic Generic setting
+ * @ret data Generic setting data
+ */
+static inline void * generic_setting_data ( struct generic_setting *generic ) {
+ return ( ( ( void * ) generic ) + sizeof ( *generic ) +
+ generic->name_len );
+}
+
+/**
+ * Find generic setting
*
- ******************************************************************************
+ * @v generics Generic settings block
+ * @v setting Setting to find
+ * @ret generic Generic setting, or NULL
*/
+static struct generic_setting *
+find_generic_setting ( struct generic_settings *generics,
+ struct setting *setting ) {
+ struct generic_setting *generic;
+
+ list_for_each_entry ( generic, &generics->list, list ) {
+ if ( setting_cmp ( &generic->setting, setting ) == 0 )
+ return generic;
+ }
+ return NULL;
+}
/**
- * Store value of simple setting
+ * Store value of generic setting
*
- * @v options DHCP option block
+ * @v settings Settings block
* @v setting Setting to store
* @v data Setting data, or NULL to clear setting
* @v len Length of setting data
* @ret rc Return status code
*/
-int simple_settings_store ( struct settings *settings, struct setting *setting,
- const void *data, size_t len ) {
- struct simple_settings *simple =
- container_of ( settings, struct simple_settings, settings );
- return dhcpopt_extensible_store ( &simple->dhcpopts, setting->tag,
- data, len );
+int generic_settings_store ( struct settings *settings,
+ struct setting *setting,
+ const void *data, size_t len ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *old;
+ struct generic_setting *new = NULL;
+ size_t name_len;
+
+ /* Identify existing generic setting, if any */
+ old = find_generic_setting ( generics, setting );
+
+ /* Create new generic setting, if required */
+ if ( len ) {
+ /* Allocate new generic setting */
+ name_len = ( strlen ( setting->name ) + 1 );
+ new = zalloc ( sizeof ( *new ) + name_len + len );
+ if ( ! new )
+ return -ENOMEM;
+
+ /* Populate new generic setting */
+ new->name_len = name_len;
+ new->data_len = len;
+ memcpy ( &new->setting, setting, sizeof ( new->setting ) );
+ new->setting.name = generic_setting_name ( new );
+ memcpy ( generic_setting_name ( new ),
+ setting->name, name_len );
+ memcpy ( generic_setting_data ( new ), data, len );
+ }
+
+ /* Delete existing generic setting, if any */
+ if ( old ) {
+ list_del ( &old->list );
+ free ( old );
+ }
+
+ /* Add new setting to list, if any */
+ if ( new )
+ list_add ( &new->list, &generics->list );
+
+ return 0;
}
/**
- * Fetch value of simple setting
+ * Fetch value of generic setting
*
- * @v options DHCP option block
+ * @v settings Settings block
* @v setting Setting to fetch
* @v data Buffer to fill with setting data
* @v len Length of buffer
* @ret len Length of setting data, or negative error
*/
-int simple_settings_fetch ( struct settings *settings, struct setting *setting,
- void *data, size_t len ) {
- struct simple_settings *simple =
- container_of ( settings, struct simple_settings, settings );
- return dhcpopt_fetch ( &simple->dhcpopts, setting->tag, data, len );
+int generic_settings_fetch ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *generic;
+
+ /* Find generic setting */
+ generic = find_generic_setting ( generics, setting );
+ if ( ! generic )
+ return -ENOENT;
+
+ /* Copy out generic setting data */
+ if ( len > generic->data_len )
+ len = generic->data_len;
+ memcpy ( data, generic_setting_data ( generic ), len );
+ return generic->data_len;
+}
+
+/**
+ * Clear generic settings block
+ *
+ * @v settings Settings block
+ */
+void generic_settings_clear ( struct settings *settings ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *generic;
+ struct generic_setting *tmp;
+
+ list_for_each_entry_safe ( generic, tmp, &generics->list, list ) {
+ list_del ( &generic->list );
+ free ( generic );
+ }
+ assert ( list_empty ( &generics->list ) );
}
-/** Simple settings operations */
-struct settings_operations simple_settings_operations = {
- .store = simple_settings_store,
- .fetch = simple_settings_fetch,
+/** Generic settings operations */
+struct settings_operations generic_settings_operations = {
+ .store = generic_settings_store,
+ .fetch = generic_settings_fetch,
+ .clear = generic_settings_clear,
};
-/** Root simple settings block */
-struct simple_settings simple_settings_root = {
+/******************************************************************************
+ *
+ * Registered settings blocks
+ *
+ ******************************************************************************
+ */
+
+/** Root generic settings block */
+struct generic_settings generic_settings_root = {
.settings = {
.refcnt = NULL,
.name = "",
.siblings =
- LIST_HEAD_INIT ( simple_settings_root.settings.siblings ),
+ LIST_HEAD_INIT ( generic_settings_root.settings.siblings ),
.children =
- LIST_HEAD_INIT ( simple_settings_root.settings.children ),
- .op = &simple_settings_operations,
+ LIST_HEAD_INIT ( generic_settings_root.settings.children ),
+ .op = &generic_settings_operations,
},
+ .list = LIST_HEAD_INIT ( generic_settings_root.list ),
};
/** Root settings block */
-#define settings_root simple_settings_root.settings
+#define settings_root generic_settings_root.settings
+
+/**
+ * Find child named settings block
+ *
+ * @v parent Parent settings block
+ * @v name Name within this parent
+ * @ret settings Settings block, or NULL
+ */
+static struct settings * find_child_settings ( struct settings *parent,
+ const char *name ) {
+ struct settings *settings;
+
+ /* Treat empty name as meaning "this block" */
+ if ( ! *name )
+ return parent;
+
+ /* Look for child with matching name */
+ list_for_each_entry ( settings, &parent->children, siblings ) {
+ if ( strcmp ( settings->name, name ) == 0 )
+ return settings;
+ }
+
+ return NULL;
+}
+
+/**
+ * Find or create child named settings block
+ *
+ * @v parent Parent settings block
+ * @v name Name within this parent
+ * @ret settings Settings block, or NULL
+ */
+static struct settings * autovivify_child_settings ( struct settings *parent,
+ const char *name ) {
+ struct {
+ struct generic_settings generic;
+ char name[ strlen ( name ) + 1 /* NUL */ ];
+ } *new_child;
+ struct settings *settings;
+
+ /* Return existing settings, if existent */
+ if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
+ return settings;
+
+ /* Create new generic settings block */
+ new_child = zalloc ( sizeof ( *new_child ) );
+ if ( ! new_child ) {
+ DBGC ( parent, "Settings %p could not create child %s\n",
+ parent, name );
+ return NULL;
+ }
+ memcpy ( new_child->name, name, sizeof ( new_child->name ) );
+ generic_settings_init ( &new_child->generic, NULL, new_child->name );
+ settings = &new_child->generic.settings;
+ register_settings ( settings, parent );
+ return settings;
+}
+
+/**
+ * Return settings block name (for debug only)
+ *
+ * @v settings Settings block
+ * @ret name Settings block name
+ */
+static const char * settings_name ( struct settings *settings ) {
+ static char buf[64];
+ char tmp[ sizeof ( buf ) ];
+ int count;
+
+ for ( count = 0 ; settings ; settings = settings->parent ) {
+ memcpy ( tmp, buf, sizeof ( tmp ) );
+ snprintf ( buf, sizeof ( buf ), "%s%c%s", settings->name,
+ ( count++ ? '.' : '\0' ), tmp );
+ }
+ return ( buf + 1 );
+}
+
+/**
+ * Parse settings block name
+ *
+ * @v name Name
+ * @v get_child Function to find or create child settings block
+ * @ret settings Settings block, or NULL
+ */
+static struct settings *
+parse_settings_name ( const char *name,
+ struct settings * ( * get_child ) ( struct settings *,
+ const char * ) ) {
+ struct settings *settings = &settings_root;
+ char name_copy[ strlen ( name ) + 1 ];
+ char *subname;
+ char *remainder;
+
+ /* Create modifiable copy of name */
+ memcpy ( name_copy, name, sizeof ( name_copy ) );
+ remainder = name_copy;
+
+ /* Parse each name component in turn */
+ while ( remainder ) {
+ struct net_device *netdev;
+
+ subname = remainder;
+ remainder = strchr ( subname, '.' );
+ if ( remainder )
+ *(remainder++) = '\0';
+
+ /* Special case "netX" root settings block */
+ if ( ( subname == name_copy ) && ! strcmp ( subname, "netX" ) &&
+ ( ( netdev = last_opened_netdev() ) != NULL ) )
+ settings = get_child ( settings, netdev->name );
+ else
+ settings = get_child ( settings, subname );
+
+ if ( ! settings )
+ break;
+ }
+
+ return settings;
+}
+
+/**
+ * Find named settings block
+ *
+ * @v name Name
+ * @ret settings Settings block, or NULL
+ */
+struct settings * find_settings ( const char *name ) {
+
+ return parse_settings_name ( name, find_child_settings );
+}
/**
* Apply all settings
@@ -127,8 +370,7 @@ static int apply_settings ( void ) {
int rc;
/* Call all settings applicators */
- for ( applicator = settings_applicators ;
- applicator < settings_applicators_end ; applicator++ ) {
+ for_each_table_entry ( applicator, SETTINGS_APPLICATORS ) {
if ( ( rc = applicator->apply() ) != 0 ) {
DBG ( "Could not apply settings using applicator "
"%p: %s\n", applicator, strerror ( rc ) );
@@ -199,7 +441,8 @@ int register_settings ( struct settings *settings, struct settings *parent ) {
ref_get ( parent->refcnt );
settings->parent = parent;
list_add_tail ( &settings->siblings, &parent->children );
- DBGC ( settings, "Settings %p registered\n", settings );
+ DBGC ( settings, "Settings %p (\"%s\") registered\n",
+ settings, settings_name ( settings ) );
/* Fix up settings priority */
reprioritise_settings ( settings );
@@ -217,63 +460,19 @@ int register_settings ( struct settings *settings, struct settings *parent ) {
*/
void unregister_settings ( struct settings *settings ) {
+ DBGC ( settings, "Settings %p (\"%s\") unregistered\n",
+ settings, settings_name ( settings ) );
+
/* Remove from list of settings */
ref_put ( settings->refcnt );
ref_put ( settings->parent->refcnt );
settings->parent = NULL;
list_del ( &settings->siblings );
- DBGC ( settings, "Settings %p unregistered\n", settings );
/* Apply potentially-updated settings */
apply_settings();
}
-/**
- * Find child named settings block
- *
- * @v parent Parent settings block
- * @v name Name within this parent
- * @ret settings Settings block, or NULL
- */
-struct settings * find_child_settings ( struct settings *parent,
- const char *name ) {
- struct settings *settings;
- size_t len;
-
- /* NULL parent => add to settings root */
- if ( parent == NULL )
- parent = &settings_root;
-
- /* Look for a child whose name matches the initial component */
- list_for_each_entry ( settings, &parent->children, siblings ) {
- len = strlen ( settings->name );
- if ( strncmp ( name, settings->name, len ) != 0 )
- continue;
- if ( name[len] == 0 )
- return settings;
- if ( name[len] == '.' )
- return find_child_settings ( settings,
- ( name + len + 1 ) );
- }
-
- return NULL;
-}
-
-/**
- * Find named settings block
- *
- * @v name Name
- * @ret settings Settings block, or NULL
- */
-struct settings * find_settings ( const char *name ) {
-
- /* If name is empty, use the root */
- if ( ! *name )
- return &settings_root;
-
- return find_child_settings ( &settings_root, name );
-}
-
/******************************************************************************
*
* Core settings routines
@@ -298,6 +497,10 @@ int store_setting ( struct settings *settings, struct setting *setting,
if ( ! settings )
settings = &settings_root;
+ /* Sanity check */
+ if ( ! settings->op->store )
+ return -ENOTSUP;
+
/* Store setting */
if ( ( rc = settings->op->store ( settings, setting,
data, len ) ) != 0 )
@@ -345,6 +548,10 @@ int fetch_setting ( struct settings *settings, struct setting *setting,
if ( ! settings )
settings = &settings_root;
+ /* Sanity check */
+ if ( ! settings->op->fetch )
+ return -ENOTSUP;
+
/* Try this block first */
if ( ( ret = settings->op->fetch ( settings, setting,
data, len ) ) >= 0 )
@@ -411,7 +618,7 @@ int fetch_string_setting_copy ( struct settings *settings,
struct setting *setting,
char **data ) {
int len;
- int check_len;
+ int check_len = 0;
len = fetch_setting_len ( settings, setting );
if ( len < 0 )
@@ -421,7 +628,8 @@ int fetch_string_setting_copy ( struct settings *settings,
if ( ! *data )
return -ENOMEM;
- fetch_string_setting ( settings, setting, *data, ( len + 1 ) );
+ check_len = fetch_string_setting ( settings, setting, *data,
+ ( len + 1 ) );
assert ( check_len == len );
return len;
}
@@ -504,7 +712,8 @@ int fetch_uint_setting ( struct settings *settings, struct setting *setting,
return len;
/* Mask off sign-extended bits */
- *value = ( svalue & ( -1UL >> ( sizeof ( long ) - len ) ) );
+ assert ( len <= ( int ) sizeof ( long ) );
+ *value = ( svalue & ( -1UL >> ( 8 * ( sizeof ( long ) - len ) ) ) );
return len;
}
@@ -559,6 +768,16 @@ int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
}
/**
+ * Clear settings block
+ *
+ * @v settings Settings block
+ */
+void clear_settings ( struct settings *settings ) {
+ if ( settings->op->clear )
+ settings->op->clear ( settings );
+}
+
+/**
* Compare two settings
*
* @v a Setting to compare
@@ -572,8 +791,12 @@ int setting_cmp ( struct setting *a, struct setting *b ) {
if ( a->tag && ( a->tag == b->tag ) )
return 0;
- /* Otherwise, compare the names */
- return strcmp ( a->name, b->name );
+ /* Otherwise, if the settings have names, compare them */
+ if ( a->name && b->name && a->name[0] )
+ return strcmp ( a->name, b->name );
+
+ /* Otherwise, return a non-match */
+ return ( ! 0 );
}
/******************************************************************************
@@ -614,7 +837,7 @@ int storef_setting ( struct settings *settings, struct setting *setting,
static struct setting * find_setting ( const char *name ) {
struct setting *setting;
- for ( setting = settings ; setting < settings_end ; setting++ ) {
+ for_each_table_entry ( setting, SETTINGS ) {
if ( strcmp ( name, setting->name ) == 0 )
return setting;
}
@@ -622,6 +845,26 @@ static struct setting * find_setting ( const char *name ) {
}
/**
+ * Parse setting name as tag number
+ *
+ * @v name Name
+ * @ret tag Tag number, or 0 if not a valid number
+ */
+static unsigned int parse_setting_tag ( const char *name ) {
+ char *tmp = ( ( char * ) name );
+ unsigned int tag = 0;
+
+ while ( 1 ) {
+ tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
+ if ( *tmp == 0 )
+ return tag;
+ if ( *tmp != '.' )
+ return 0;
+ tmp++;
+ }
+}
+
+/**
* Find setting type
*
* @v name Name
@@ -630,7 +873,7 @@ static struct setting * find_setting ( const char *name ) {
static struct setting_type * find_setting_type ( const char *name ) {
struct setting_type *type;
- for ( type = setting_types ; type < setting_types_end ; type++ ) {
+ for_each_table_entry ( type, SETTING_TYPES ) {
if ( strcmp ( name, type->name ) == 0 )
return type;
}
@@ -641,30 +884,38 @@ static struct setting_type * find_setting_type ( const char *name ) {
* Parse setting name
*
* @v name Name of setting
+ * @v get_child Function to find or create child settings block
* @v settings Settings block to fill in
* @v setting Setting to fill in
+ * @v tmp_name Buffer for copy of setting name
* @ret rc Return status code
*
* Interprets a name of the form
* "[settings_name/]tag_name[:type_name]" and fills in the appropriate
* fields.
+ *
+ * The @c tmp_name buffer must be large enough to hold a copy of the
+ * setting name.
*/
-static int parse_setting_name ( const char *name, struct settings **settings,
- struct setting *setting ) {
- char tmp_name[ strlen ( name ) + 1 ];
+static int
+parse_setting_name ( const char *name,
+ struct settings * ( * get_child ) ( struct settings *,
+ const char * ),
+ struct settings **settings, struct setting *setting,
+ char *tmp_name ) {
char *settings_name;
char *setting_name;
char *type_name;
struct setting *named_setting;
- char *tmp;
/* Set defaults */
*settings = &settings_root;
memset ( setting, 0, sizeof ( *setting ) );
- setting->type = &setting_type_hex;
+ setting->name = "";
+ setting->type = &setting_type_string;
/* Split name into "[settings_name/]setting_name[:type_name]" */
- memcpy ( tmp_name, name, sizeof ( tmp_name ) );
+ strcpy ( tmp_name, name );
if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
*(setting_name++) = 0;
settings_name = tmp_name;
@@ -677,7 +928,7 @@ static int parse_setting_name ( const char *name, struct settings **settings,
/* Identify settings block, if specified */
if ( settings_name ) {
- *settings = find_settings ( settings_name );
+ *settings = parse_settings_name ( settings_name, get_child );
if ( *settings == NULL ) {
DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
settings_name, name );
@@ -685,25 +936,16 @@ static int parse_setting_name ( const char *name, struct settings **settings,
}
}
- /* Identify tag number */
+ /* Identify setting */
if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
+ /* Matches a defined named setting; use that setting */
memcpy ( setting, named_setting, sizeof ( *setting ) );
- } else {
- /* Unrecognised name: try to interpret as a tag number */
- tmp = setting_name;
- while ( 1 ) {
- setting->tag = ( ( setting->tag << 8 ) |
- strtoul ( tmp, &tmp, 0 ) );
- if ( *tmp == 0 )
- break;
- if ( *tmp != '.' ) {
- DBG ( "Invalid setting \"%s\" in \"%s\"\n",
- setting_name, name );
- return -ENOENT;
- }
- tmp++;
- }
+ } else if ( ( setting->tag = parse_setting_tag ( setting_name ) ) !=0){
+ /* Is a valid numeric tag; use the tag */
setting->tag |= (*settings)->tag_magic;
+ } else {
+ /* Use the arbitrary name */
+ setting->name = setting_name;
}
/* Identify setting type, if specified */
@@ -729,9 +971,11 @@ static int parse_setting_name ( const char *name, struct settings **settings,
int storef_named_setting ( const char *name, const char *value ) {
struct settings *settings;
struct setting setting;
+ char tmp_name[ strlen ( name ) + 1 ];
int rc;
- if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
+ if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
+ &settings, &setting, tmp_name )) != 0)
return rc;
return storef_setting ( settings, &setting, value );
}
@@ -747,9 +991,11 @@ int storef_named_setting ( const char *name, const char *value ) {
int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
struct settings *settings;
struct setting setting;
+ char tmp_name[ strlen ( name ) + 1 ];
int rc;
- if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
+ if ( ( rc = parse_setting_name ( name, find_child_settings,
+ &settings, &setting, tmp_name )) != 0)
return rc;
return fetchf_setting ( settings, &setting, buf, len );
}
@@ -839,7 +1085,7 @@ static int fetchf_uristring ( struct settings *settings,
fetch_string_setting ( settings, setting, raw_buf,
sizeof ( raw_buf ) );
- return uri_encode ( raw_buf, buf, len );
+ return uri_encode ( raw_buf, buf, len, URI_FRAGMENT );
}
}
@@ -1180,7 +1426,7 @@ struct setting filename_setting __setting = {
/** Root path setting */
struct setting root_path_setting __setting = {
.name = "root-path",
- .description = "NFS/iSCSI root path",
+ .description = "iSCSI root path",
.tag = DHCP_ROOT_PATH,
.type = &setting_type_string,
};
diff --git a/gpxe/src/core/string.c b/gpxe/src/core/string.c
index 2e17bdcb..190007a4 100644
--- a/gpxe/src/core/string.c
+++ b/gpxe/src/core/string.c
@@ -10,6 +10,8 @@
* published by the Free Software Foundation.
*/
+FILE_LICENCE ( GPL2_ONLY );
+
/*
* stupid library routines.. The optimized versions should generally be found
* as inline code in <asm-xx/string.h>
diff --git a/gpxe/src/core/timer.c b/gpxe/src/core/timer.c
index d71e3da1..096d07ec 100644
--- a/gpxe/src/core/timer.c
+++ b/gpxe/src/core/timer.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <unistd.h>
/**
diff --git a/gpxe/src/core/uri.c b/gpxe/src/core/uri.c
index 7bb46da0..6a1f2e59 100644
--- a/gpxe/src/core/uri.c
+++ b/gpxe/src/core/uri.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/** @file
*
* Uniform Resource Identifiers
@@ -74,6 +76,7 @@ struct uri * parse_uri ( const char *uri_string ) {
char *tmp;
char *path = NULL;
char *authority = NULL;
+ int i;
size_t raw_len;
/* Allocate space for URI struct and a copy of the string */
@@ -83,7 +86,7 @@ struct uri * parse_uri ( const char *uri_string ) {
return NULL;
raw = ( ( ( char * ) uri ) + sizeof ( *uri ) );
- /* Zero URI struct and copy in the raw string */
+ /* Copy in the raw string */
memcpy ( raw, uri_string, raw_len );
/* Start by chopping off the fragment, if it exists */
@@ -169,6 +172,14 @@ struct uri * parse_uri ( const char *uri_string ) {
uri->port = tmp;
}
+ /* Decode fields that should be decoded */
+ for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) {
+ const char *field = uri_get_field ( uri, i );
+ if ( field && ( URI_ENCODED & ( 1 << i ) ) )
+ uri_decode ( field, ( char * ) field,
+ strlen ( field ) + 1 /* NUL */ );
+ }
+
done:
DBG ( "URI \"%s\" split into", uri_string );
dump_uri ( uri );
@@ -196,71 +207,65 @@ unsigned int uri_port ( struct uri *uri, unsigned int default_port ) {
* @v buf Buffer to fill with URI string
* @v size Size of buffer
* @v uri URI to write into buffer, or NULL
+ * @v fields Bitmask of fields to include in URI string, or URI_ALL
* @ret len Length of URI string
*/
-int unparse_uri ( char *buf, size_t size, struct uri *uri ) {
+int unparse_uri ( char *buf, size_t size, struct uri *uri,
+ unsigned int fields ) {
+ /* List of characters that typically go before certain fields */
+ static char separators[] = { /* scheme */ 0, /* opaque */ ':',
+ /* user */ 0, /* password */ ':',
+ /* host */ '@', /* port */ ':',
+ /* path */ 0, /* query */ '?',
+ /* fragment */ '#' };
int used = 0;
+ int i;
DBG ( "URI unparsing" );
dump_uri ( uri );
DBG ( "\n" );
+ /* Ensure buffer is NUL-terminated */
+ if ( size )
+ buf[0] = '\0';
+
/* Special-case NULL URI */
- if ( ! uri ) {
- if ( size )
- buf[0] = '\0';
+ if ( ! uri )
return 0;
- }
-
- /* Special-case opaque URIs */
- if ( uri->opaque ) {
- return ssnprintf ( ( buf + used ), ( size - used ),
- "%s:%s", uri->scheme, uri->opaque );
- }
- /* scheme:// */
- if ( uri->scheme ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "%s://", uri->scheme );
- }
-
- /* [user[:password]@]host[:port] */
- if ( uri->host ) {
- if ( uri->user ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "%s", uri->user );
- if ( uri->password ) {
- used += ssnprintf ( ( buf + used ),
- ( size - used ),
- ":%s", uri->password );
+ /* Iterate through requested fields */
+ for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) {
+ const char *field = uri_get_field ( uri, i );
+ char sep = separators[i];
+
+ /* Ensure `fields' only contains bits for fields that exist */
+ if ( ! field )
+ fields &= ~( 1 << i );
+
+ /* Store this field if we were asked to */
+ if ( fields & ( 1 << i ) ) {
+ /* Print :// if we're non-opaque and had a scheme */
+ if ( ( fields & URI_SCHEME_BIT ) &&
+ ( i > URI_OPAQUE ) ) {
+ used += ssnprintf ( buf + used, size - used,
+ "://" );
+ /* Only print :// once */
+ fields &= ~URI_SCHEME_BIT;
}
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "@" );
- }
- used += ssnprintf ( ( buf + used ), ( size - used ), "%s",
- uri->host );
- if ( uri->port ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- ":%s", uri->port );
- }
- }
-
- /* /path */
- if ( uri->path ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "%s", uri->path );
- }
- /* ?query */
- if ( uri->query ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "?%s", uri->query );
- }
-
- /* #fragment */
- if ( uri->fragment ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "#%s", uri->fragment );
+ /* Only print separator if an earlier field exists */
+ if ( sep && ( fields & ( ( 1 << i ) - 1 ) ) )
+ used += ssnprintf ( buf + used, size - used,
+ "%c", sep );
+
+ /* Print contents of field, possibly encoded */
+ if ( URI_ENCODED & ( 1 << i ) )
+ used += uri_encode ( field, buf + used,
+ size - used, i );
+ else
+ used += ssnprintf ( buf + used, size - used,
+ "%s", field );
+ }
}
return used;
@@ -275,10 +280,10 @@ int unparse_uri ( char *buf, size_t size, struct uri *uri ) {
* Creates a modifiable copy of a URI.
*/
struct uri * uri_dup ( struct uri *uri ) {
- size_t len = ( unparse_uri ( NULL, 0, uri ) + 1 );
+ size_t len = ( unparse_uri ( NULL, 0, uri, URI_ALL ) + 1 );
char buf[len];
- unparse_uri ( buf, len, uri );
+ unparse_uri ( buf, len, uri, URI_ALL );
return parse_uri ( buf );
}
@@ -391,16 +396,31 @@ struct uri * resolve_uri ( struct uri *base_uri,
* Test for unreserved URI characters
*
* @v c Character to test
+ * @v field Field of URI in which character lies
* @ret is_unreserved Character is an unreserved character
*/
-static int is_unreserved_uri_char ( int c ) {
+static int is_unreserved_uri_char ( int c, int field ) {
/* According to RFC3986, the unreserved character set is
*
* A-Z a-z 0-9 - _ . ~
+ *
+ * but we also pass & ; = in queries, / in paths,
+ * and everything in opaques
*/
- return ( isupper ( c ) || islower ( c ) || isdigit ( c ) ||
- ( c == '-' ) || ( c == '_' ) ||
- ( c == '.' ) || ( c == '~' ) );
+ int ok = ( isupper ( c ) || islower ( c ) || isdigit ( c ) ||
+ ( c == '-' ) || ( c == '_' ) ||
+ ( c == '.' ) || ( c == '~' ) );
+
+ if ( field == URI_QUERY )
+ ok = ok || ( c == ';' ) || ( c == '&' ) || ( c == '=' );
+
+ if ( field == URI_PATH )
+ ok = ok || ( c == '/' );
+
+ if ( field == URI_OPAQUE )
+ ok = 1;
+
+ return ok;
}
/**
@@ -409,18 +429,20 @@ static int is_unreserved_uri_char ( int c ) {
* @v raw_string String to be URI-encoded
* @v buf Buffer to contain encoded string
* @v len Length of buffer
+ * @v field Field of URI in which string lies
* @ret len Length of encoded string (excluding NUL)
*/
-size_t uri_encode ( const char *raw_string, char *buf, size_t len ) {
+size_t uri_encode ( const char *raw_string, char *buf, ssize_t len,
+ int field ) {
ssize_t remaining = len;
size_t used;
unsigned char c;
- if ( len )
+ if ( len > 0 )
buf[0] = '\0';
while ( ( c = *(raw_string++) ) ) {
- if ( is_unreserved_uri_char ( c ) ) {
+ if ( is_unreserved_uri_char ( c, field ) ) {
used = ssnprintf ( buf, remaining, "%c", c );
} else {
used = ssnprintf ( buf, remaining, "%%%02X", c );
@@ -439,17 +461,17 @@ size_t uri_encode ( const char *raw_string, char *buf, size_t len ) {
* @v buf Buffer to contain decoded string
* @v len Length of buffer
* @ret len Length of decoded string (excluding NUL)
+ *
+ * This function may be used in-place, with @a buf the same as
+ * @a encoded_string.
*/
-size_t uri_decode ( const char *encoded_string, char *buf, size_t len ) {
- ssize_t remaining = len;
+size_t uri_decode ( const char *encoded_string, char *buf, ssize_t len ) {
+ ssize_t remaining;
char hexbuf[3];
char *hexbuf_end;
unsigned char c;
- if ( len )
- buf[0] = '\0';
-
- while ( *encoded_string ) {
+ for ( remaining = len; *encoded_string; remaining-- ) {
if ( *encoded_string == '%' ) {
encoded_string++;
snprintf ( hexbuf, sizeof ( hexbuf ), "%s",
@@ -459,7 +481,12 @@ size_t uri_decode ( const char *encoded_string, char *buf, size_t len ) {
} else {
c = *(encoded_string++);
}
- ssnprintf ( buf++, remaining--, "%c", c );
+ if ( remaining > 1 )
+ *buf++ = c;
}
+
+ if ( len )
+ *buf = 0;
+
return ( len - remaining );
}
diff --git a/gpxe/src/core/uuid.c b/gpxe/src/core/uuid.c
index a3a82c68..2b67d55d 100644
--- a/gpxe/src/core/uuid.c
+++ b/gpxe/src/core/uuid.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdio.h>
#include <byteswap.h>
diff --git a/gpxe/src/core/vsprintf.c b/gpxe/src/core/vsprintf.c
index 4457fe4f..21ab2429 100644
--- a/gpxe/src/core/vsprintf.c
+++ b/gpxe/src/core/vsprintf.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stddef.h>
#include <stdarg.h>
#include <stdio.h>
diff --git a/gpxe/src/core/xfer.c b/gpxe/src/core/xfer.c
index 9ed19da2..1ec6f9d3 100644
--- a/gpxe/src/core/xfer.c
+++ b/gpxe/src/core/xfer.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <stdio.h>
#include <errno.h>
@@ -43,11 +45,14 @@ static struct xfer_metadata dummy_metadata;
*/
void xfer_close ( struct xfer_interface *xfer, int rc ) {
struct xfer_interface *dest = xfer_get_dest ( xfer );
+ struct xfer_interface_operations *op = xfer->op;
DBGC ( xfer, "XFER %p->%p close\n", xfer, dest );
xfer_unplug ( xfer );
+ xfer_nullify ( xfer );
dest->op->close ( dest, rc );
+ xfer->op = op;
xfer_put ( dest );
}