summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/base16.c15
-rw-r--r--src/core/cachedhcp.c3
-rw-r--r--src/core/dummy_sanboot.c8
-rw-r--r--src/core/interface.c1
-rw-r--r--src/core/null_sanboot.c2
-rw-r--r--src/core/parseopt.c39
-rw-r--r--src/core/random.c8
-rw-r--r--src/core/sanboot.c78
-rw-r--r--src/core/settings.c33
-rw-r--r--src/core/uuid.c28
-rw-r--r--src/core/xfer.c3
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 ) {