diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/base16.c | 15 | ||||
-rw-r--r-- | src/core/cachedhcp.c | 3 | ||||
-rw-r--r-- | src/core/dummy_sanboot.c | 8 | ||||
-rw-r--r-- | src/core/interface.c | 1 | ||||
-rw-r--r-- | src/core/null_sanboot.c | 2 | ||||
-rw-r--r-- | src/core/parseopt.c | 39 | ||||
-rw-r--r-- | src/core/random.c | 8 | ||||
-rw-r--r-- | src/core/sanboot.c | 78 | ||||
-rw-r--r-- | src/core/settings.c | 33 | ||||
-rw-r--r-- | src/core/uuid.c | 28 | ||||
-rw-r--r-- | src/core/xfer.c | 3 |
11 files changed, 173 insertions, 45 deletions
diff --git a/src/core/base16.c b/src/core/base16.c index f9e0f336..47e35f41 100644 --- a/src/core/base16.c +++ b/src/core/base16.c @@ -78,12 +78,23 @@ int hex_decode ( char separator, const char *encoded, void *data, size_t len ) { unsigned int count = 0; unsigned int sixteens; unsigned int units; + int optional; + /* Strip out optionality flag from separator character */ + optional = ( separator & HEX_DECODE_OPTIONAL ); + separator &= ~HEX_DECODE_OPTIONAL; + + /* Decode string */ while ( *encoded ) { /* Check separator, if applicable */ - if ( count && separator && ( ( *(encoded++) != separator ) ) ) - return -EINVAL; + if ( count && separator ) { + if ( *encoded == separator ) { + encoded++; + } else if ( ! optional ) { + return -EINVAL; + } + } /* Extract digits. Note that either digit may be NUL, * which would be interpreted as an invalid value by diff --git a/src/core/cachedhcp.c b/src/core/cachedhcp.c index 60213f02..57226e16 100644 --- a/src/core/cachedhcp.c +++ b/src/core/cachedhcp.c @@ -295,9 +295,10 @@ struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_LATE ) = { * Apply cached DHCPACK to network device, if applicable * * @v netdev Network device + * @v priv Private data * @ret rc Return status code */ -static int cachedhcp_probe ( struct net_device *netdev ) { +static int cachedhcp_probe ( struct net_device *netdev, void *priv __unused ) { /* Apply cached DHCPACK to network device, if applicable */ return cachedhcp_apply ( &cached_dhcpack, netdev ); diff --git a/src/core/dummy_sanboot.c b/src/core/dummy_sanboot.c index e6293099..e22998da 100644 --- a/src/core/dummy_sanboot.c +++ b/src/core/dummy_sanboot.c @@ -55,7 +55,7 @@ static int dummy_san_hook ( unsigned int drive, struct uri **uris, /* Register SAN device */ if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) { - DBGC ( sandev, "SAN %#02x could not register: %s\n", + DBGC ( sandev->drive, "SAN %#02x could not register: %s\n", sandev->drive, strerror ( rc ) ); goto err_register; } @@ -80,7 +80,7 @@ static void dummy_san_unhook ( unsigned int drive ) { /* Find drive */ sandev = sandev_find ( drive ); if ( ! sandev ) { - DBG ( "SAN %#02x does not exist\n", drive ); + DBGC ( drive, "SAN %#02x does not exist\n", drive ); return; } @@ -95,11 +95,11 @@ static void dummy_san_unhook ( unsigned int drive ) { * Boot from dummy SAN device * * @v drive Drive number - * @v filename Filename (or NULL to use default) + * @v config Boot configuration parameters * @ret rc Return status code */ static int dummy_san_boot ( unsigned int drive __unused, - const char *filename __unused ) { + struct san_boot_config *config __unused ) { return -EOPNOTSUPP; } diff --git a/src/core/interface.c b/src/core/interface.c index 34a4180a..ea060689 100644 --- a/src/core/interface.c +++ b/src/core/interface.c @@ -285,6 +285,7 @@ void intf_shutdown ( struct interface *intf, int rc ) { intf_nullify ( intf ); /* Transfer destination to temporary interface */ + intf_temp_init ( &tmp, intf ); tmp.dest = intf->dest; intf->dest = &null_intf; diff --git a/src/core/null_sanboot.c b/src/core/null_sanboot.c index 7c0680f5..2340cd2a 100644 --- a/src/core/null_sanboot.c +++ b/src/core/null_sanboot.c @@ -38,7 +38,7 @@ static void null_san_unhook ( unsigned int drive __unused ) { } static int null_san_boot ( unsigned int drive __unused, - const char *filename __unused ) { + struct san_boot_config *config __unused ) { return -EOPNOTSUPP; } diff --git a/src/core/parseopt.c b/src/core/parseopt.c index 1dbfc7ae..8410e6e9 100644 --- a/src/core/parseopt.c +++ b/src/core/parseopt.c @@ -28,13 +28,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <ctype.h> #include <errno.h> #include <getopt.h> +#include <ipxe/uuid.h> #include <ipxe/netdevice.h> #include <ipxe/menu.h> #include <ipxe/settings.h> #include <ipxe/params.h> #include <ipxe/timer.h> +#include <ipxe/keys.h> #include <ipxe/parseopt.h> #include <config/branding.h> @@ -123,6 +126,29 @@ int parse_timeout ( char *text, unsigned long *value ) { } /** + * Parse UUID + * + * @v text Text + * @ret uuid UUID value + * @ret rc Return status code + */ +int parse_uuid ( char *text, struct uuid_option *uuid ) { + int rc; + + /* Sanity check */ + assert ( text != NULL ); + + /* Parse UUID */ + if ( ( rc = uuid_aton ( text, &uuid->buf ) ) != 0 ) { + printf ( "\"%s\": invalid UUID\n", text ); + return rc; + } + uuid->value = &uuid->buf; + + return 0; +} + +/** * Parse network device name * * @v text Text @@ -213,6 +239,7 @@ int parse_flag ( char *text __unused, int *flag ) { * @ret rc Return status code */ int parse_key ( char *text, unsigned int *key ) { + int rc; /* Interpret single characters as being a literal key character */ if ( text[0] && ! text[1] ) { @@ -221,7 +248,17 @@ int parse_key ( char *text, unsigned int *key ) { } /* Otherwise, interpret as an integer */ - return parse_integer ( text, key ); + if ( ( rc = parse_integer ( text, key ) ) < 0 ) + return rc; + + /* For backwards compatibility with existing scripts, treat + * integers between the ASCII range and special key range as + * being relative special key values. + */ + if ( ( ! isascii ( *key ) ) && ( *key < KEY_MIN ) ) + *key += KEY_MIN; + + return 0; } /** diff --git a/src/core/random.c b/src/core/random.c index 975a03cf..e3251964 100644 --- a/src/core/random.c +++ b/src/core/random.c @@ -6,8 +6,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +#include <stddef.h> #include <stdlib.h> -#include <ipxe/timer.h> +#include <time.h> static int32_t rnd_seed = 0; @@ -30,8 +31,9 @@ void srandom ( unsigned int seed ) { long int random ( void ) { int32_t q; - if ( ! rnd_seed ) /* Initialize linear congruential generator */ - srandom ( currticks() ); + /* Initialize linear congruential generator */ + if ( ! rnd_seed ) + srandom ( time ( NULL ) ); /* simplified version of the LCG given in Bruce Schneier's "Applied Cryptography" */ diff --git a/src/core/sanboot.c b/src/core/sanboot.c index cabc4843..e49a3f92 100644 --- a/src/core/sanboot.c +++ b/src/core/sanboot.c @@ -45,16 +45,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <ipxe/sanboot.h> /** - * Default SAN drive number - * - * The drive number is a meaningful concept only in a BIOS - * environment, where it represents the INT13 drive number (0x80 for - * the first hard disk). We retain it in other environments to allow - * for a simple way for iPXE commands to refer to SAN drives. - */ -#define SAN_DEFAULT_DRIVE 0x80 - -/** * Timeout for block device commands (in ticks) * * Underlying devices should ideally never become totally stuck. @@ -108,6 +98,22 @@ struct san_device * sandev_find ( unsigned int drive ) { } /** + * Find next SAN device by drive number + * + * @v drive Minimum drive number + * @ret sandev SAN device, or NULL + */ +struct san_device * sandev_next ( unsigned int drive ) { + struct san_device *sandev; + + list_for_each_entry ( sandev, &san_devices, list ) { + if ( sandev->drive >= drive ) + return sandev; + } + return NULL; +} + +/** * Free SAN device * * @v refcnt Reference count @@ -197,7 +203,7 @@ static int sanpath_open ( struct san_path *sanpath ) { /* Open interface */ if ( ( rc = xfer_open_uri ( &sanpath->block, sanpath->uri ) ) != 0 ) { - DBGC ( sandev, "SAN %#02x.%d could not (re)open URI: " + DBGC ( sandev->drive, "SAN %#02x.%d could not (re)open URI: " "%s\n", sandev->drive, sanpath->index, strerror ( rc ) ); return rc; } @@ -265,7 +271,7 @@ static void sanpath_block_close ( struct san_path *sanpath, int rc ) { /* Any closure is an error from our point of view */ if ( rc == 0 ) rc = -ENOTCONN; - DBGC ( sandev, "SAN %#02x.%d closed: %s\n", + DBGC ( sandev->drive, "SAN %#02x.%d closed: %s\n", sandev->drive, sanpath->index, strerror ( rc ) ); /* Close path */ @@ -307,11 +313,11 @@ static void sanpath_step ( struct san_path *sanpath ) { /* Mark as active path or close as applicable */ if ( ! sandev->active ) { - DBGC ( sandev, "SAN %#02x.%d is active\n", + DBGC ( sandev->drive, "SAN %#02x.%d is active\n", sandev->drive, sanpath->index ); sandev->active = sanpath; } else { - DBGC ( sandev, "SAN %#02x.%d is available\n", + DBGC ( sandev->drive, "SAN %#02x.%d is available\n", sandev->drive, sanpath->index ); sanpath_close ( sanpath, 0 ); } @@ -398,8 +404,9 @@ int sandev_reopen ( struct san_device *sandev ) { rc = sanpath->path_rc; break; } - DBGC ( sandev, "SAN %#02x never became available: %s\n", - sandev->drive, strerror ( rc ) ); + DBGC ( sandev->drive, "SAN %#02x never became " + "available: %s\n", sandev->drive, + strerror ( rc ) ); goto err_none; } } @@ -453,8 +460,9 @@ static int sandev_command_rw ( struct san_device *sandev, if ( ( rc = params->rw.block_rw ( &sanpath->block, &sandev->command, params->rw.lba, params->rw.count, params->rw.buffer, len ) ) != 0 ) { - DBGC ( sandev, "SAN %#02x.%d could not initiate read/write: " - "%s\n", sandev->drive, sanpath->index, strerror ( rc ) ); + DBGC ( sandev->drive, "SAN %#02x.%d could not initiate " + "read/write: %s\n", sandev->drive, sanpath->index, + strerror ( rc ) ); return rc; } @@ -480,8 +488,9 @@ sandev_command_read_capacity ( struct san_device *sandev, /* Initiate read capacity command */ if ( ( rc = block_read_capacity ( &sanpath->block, &sandev->command ) ) != 0 ) { - DBGC ( sandev, "SAN %#02x.%d could not initiate read capacity: " - "%s\n", sandev->drive, sanpath->index, strerror ( rc ) ); + DBGC ( sandev->drive, "SAN %#02x.%d could not initiate read " + "capacity: %s\n", sandev->drive, sanpath->index, + strerror ( rc ) ); return rc; } @@ -565,7 +574,7 @@ sandev_command ( struct san_device *sandev, int sandev_reset ( struct san_device *sandev ) { int rc; - DBGC ( sandev, "SAN %#02x reset\n", sandev->drive ); + DBGC ( sandev->drive, "SAN %#02x reset\n", sandev->drive ); /* Close and reopen underlying block device */ if ( ( rc = sandev_reopen ( sandev ) ) != 0 ) @@ -698,8 +707,8 @@ static int sandev_describe ( struct san_device *sandev ) { if ( ! desc ) continue; if ( ( rc = desc->model->complete ( desc ) ) != 0 ) { - DBGC ( sandev, "SAN %#02x.%d could not be " - "described: %s\n", sandev->drive, + DBGC ( sandev->drive, "SAN %#02x.%d could not " + "be described: %s\n", sandev->drive, sanpath->index, strerror ( rc ) ); return rc; } @@ -792,8 +801,8 @@ static int sandev_parse_iso9660 ( struct san_device *sandev ) { /* Read primary volume descriptor */ if ( ( rc = sandev_read ( sandev, lba, count, virt_to_user ( scratch ) ) ) != 0 ) { - DBGC ( sandev, "SAN %#02x could not read ISO9660 primary" - "volume descriptor: %s\n", + DBGC ( sandev->drive, "SAN %#02x could not read ISO9660 " + "primary volume descriptor: %s\n", sandev->drive, strerror ( rc ) ); goto err_rw; } @@ -801,8 +810,8 @@ static int sandev_parse_iso9660 ( struct san_device *sandev ) { /* Configure as CD-ROM if applicable */ if ( memcmp ( &scratch->primary.fixed, &primary_check, sizeof ( primary_check ) ) == 0 ) { - DBGC ( sandev, "SAN %#02x contains an ISO9660 filesystem; " - "treating as CD-ROM\n", sandev->drive ); + DBGC ( sandev->drive, "SAN %#02x contains an ISO9660 " + "filesystem; treating as CD-ROM\n", sandev->drive ); sandev->blksize_shift = blksize_shift; sandev->is_cdrom = 1; } @@ -867,11 +876,12 @@ struct san_device * alloc_sandev ( struct uri **uris, unsigned int count, */ int register_sandev ( struct san_device *sandev, unsigned int drive, unsigned int flags ) { + struct san_device *before; int rc; /* Check that drive number is not in use */ if ( sandev_find ( drive ) != NULL ) { - DBGC ( sandev, "SAN %#02x is already in use\n", drive ); + DBGC ( sandev->drive, "SAN %#02x is already in use\n", drive ); rc = -EADDRINUSE; goto err_in_use; } @@ -900,9 +910,13 @@ int register_sandev ( struct san_device *sandev, unsigned int drive, if ( ( rc = sandev_parse_iso9660 ( sandev ) ) != 0 ) goto err_iso9660; - /* Add to list of SAN devices */ - list_add_tail ( &sandev->list, &san_devices ); - DBGC ( sandev, "SAN %#02x registered\n", sandev->drive ); + /* Add to list of SAN devices, in drive order */ + for_each_sandev ( before ) { + if ( before->drive > sandev->drive ) + break; + } + list_add_tail ( &sandev->list, &before->list ); + DBGC ( sandev->drive, "SAN %#02x registered\n", sandev->drive ); return 0; @@ -936,7 +950,7 @@ void unregister_sandev ( struct san_device *sandev ) { /* Remove ACPI descriptors */ sandev_undescribe ( sandev ); - DBGC ( sandev, "SAN %#02x unregistered\n", sandev->drive ); + DBGC ( sandev->drive, "SAN %#02x unregistered\n", sandev->drive ); } /** The "san-drive" setting */ diff --git a/src/core/settings.c b/src/core/settings.c index da075baa..4593876f 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -2195,6 +2195,37 @@ const struct setting_type setting_type_base64 __setting_type = { }; /** + * Parse UUID/GUID setting value + * + * @v type Setting type + * @v value Formatted setting value + * @v buf Buffer to contain raw value + * @v len Length of buffer + * @v size Integer size, in bytes + * @ret len Length of raw value, or negative error + */ +static int parse_uuid_setting ( const struct setting_type *type, + const char *value, void *buf, size_t len ) { + union uuid uuid; + int rc; + + /* Parse UUID */ + if ( ( rc = uuid_aton ( value, &uuid ) ) != 0 ) + return rc; + + /* Mangle GUID byte ordering */ + if ( type == &setting_type_guid ) + uuid_mangle ( &uuid ); + + /* Copy value */ + if ( len > sizeof ( uuid ) ) + len = sizeof ( uuid ); + memcpy ( buf, uuid.raw, len ); + + return ( sizeof ( uuid ) ); +} + +/** * Format UUID/GUID setting value * * @v type Setting type @@ -2227,12 +2258,14 @@ static int format_uuid_setting ( const struct setting_type *type, /** UUID setting type */ const struct setting_type setting_type_uuid __setting_type = { .name = "uuid", + .parse = parse_uuid_setting, .format = format_uuid_setting, }; /** GUID setting type */ const struct setting_type setting_type_guid __setting_type = { .name = "guid", + .parse = parse_uuid_setting, .format = format_uuid_setting, }; diff --git a/src/core/uuid.c b/src/core/uuid.c index c43d4216..b6600af7 100644 --- a/src/core/uuid.c +++ b/src/core/uuid.c @@ -25,7 +25,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <stdint.h> #include <stdio.h> +#include <errno.h> #include <byteswap.h> +#include <ipxe/base16.h> #include <ipxe/uuid.h> /** @file @@ -53,3 +55,29 @@ const char * uuid_ntoa ( const union uuid *uuid ) { uuid->canonical.e[4], uuid->canonical.e[5] ); return buf; } + +/** + * Parse UUID + * + * @v string UUID string + * @v uuid UUID to fill in + * @ret rc Return status code + */ +int uuid_aton ( const char *string, union uuid *uuid ) { + int len; + int rc; + + /* Decode as hex string with optional '-' separator */ + len = hex_decode ( ( '-' | HEX_DECODE_OPTIONAL ), string, uuid->raw, + sizeof ( *uuid ) ); + if ( len < 0 ) { + rc = len; + return rc; + } + + /* Check length */ + if ( len != sizeof ( *uuid ) ) + return -EINVAL; + + return 0; +} diff --git a/src/core/xfer.c b/src/core/xfer.c index 0faf3292..269359e1 100644 --- a/src/core/xfer.c +++ b/src/core/xfer.c @@ -60,7 +60,7 @@ static struct xfer_metadata dummy_metadata; * @ret rc Return status code */ int xfer_vredirect ( struct interface *intf, int type, va_list args ) { - struct interface tmp = INTF_INIT ( null_intf_desc ); + struct interface tmp; struct interface *dest; xfer_vredirect_TYPE ( void * ) *op = intf_get_dest_op_no_passthru ( intf, xfer_vredirect, &dest ); @@ -85,6 +85,7 @@ int xfer_vredirect ( struct interface *intf, int type, va_list args ) { * If redirection fails, then send intf_close() to the * parent interface. */ + intf_temp_init ( &tmp, intf ); intf_plug ( &tmp, dest ); rc = xfer_vreopen ( dest, type, args ); if ( rc == 0 ) { |