summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/cachedhcp.c75
-rw-r--r--src/core/image.c11
-rw-r--r--src/core/main.c3
-rw-r--r--src/core/mp.c67
-rw-r--r--src/core/null_mp.c37
-rw-r--r--src/core/settings.c107
6 files changed, 284 insertions, 16 deletions
diff --git a/src/core/cachedhcp.c b/src/core/cachedhcp.c
index 57226e16..04945e64 100644
--- a/src/core/cachedhcp.c
+++ b/src/core/cachedhcp.c
@@ -46,11 +46,20 @@ struct cached_dhcp_packet {
struct dhcp_packet *dhcppkt;
/** VLAN tag (if applicable) */
unsigned int vlan;
+ /** Flags */
+ unsigned int flags;
};
+/** Cached DHCP packet should be retained */
+#define CACHEDHCP_RETAIN 0x0001
+
+/** Cached DHCP packet has been used */
+#define CACHEDHCP_USED 0x0002
+
/** Cached DHCPACK */
struct cached_dhcp_packet cached_dhcpack = {
.name = DHCP_SETTINGS_NAME,
+ .flags = CACHEDHCP_RETAIN,
};
/** Cached ProxyDHCPOFFER */
@@ -101,8 +110,8 @@ static int cachedhcp_apply ( struct cached_dhcp_packet *cache,
size_t ll_addr_len;
int rc;
- /* Do nothing if cache is empty */
- if ( ! cache->dhcppkt )
+ /* Do nothing if cache is empty or already in use */
+ if ( ( ! cache->dhcppkt ) || ( cache->flags & CACHEDHCP_USED ) )
return 0;
chaddr = cache->dhcppkt->dhcphdr->chaddr;
@@ -169,8 +178,12 @@ static int cachedhcp_apply ( struct cached_dhcp_packet *cache,
return rc;
}
- /* Free cached DHCP packet */
- cachedhcp_free ( cache );
+ /* Mark as used */
+ cache->flags |= CACHEDHCP_USED;
+
+ /* Free cached DHCP packet, if applicable */
+ if ( ! ( cache->flags & CACHEDHCP_RETAIN ) )
+ cachedhcp_free ( cache );
return 0;
}
@@ -246,10 +259,10 @@ int cachedhcp_record ( struct cached_dhcp_packet *cache, unsigned int vlan,
}
/**
- * Cached DHCP packet startup function
+ * Cached DHCP packet early startup function
*
*/
-static void cachedhcp_startup ( void ) {
+static void cachedhcp_startup_early ( void ) {
/* Apply cached ProxyDHCPOFFER, if any */
cachedhcp_apply ( &cached_proxydhcp, NULL );
@@ -258,6 +271,20 @@ static void cachedhcp_startup ( void ) {
/* Apply cached PXEBSACK, if any */
cachedhcp_apply ( &cached_pxebs, NULL );
cachedhcp_free ( &cached_pxebs );
+}
+
+/**
+ * Cache DHCP packet late startup function
+ *
+ */
+static void cachedhcp_startup_late ( void ) {
+
+ /* Clear retention flag */
+ cached_dhcpack.flags &= ~CACHEDHCP_RETAIN;
+
+ /* Free cached DHCPACK, if used by a network device */
+ if ( cached_dhcpack.flags & CACHEDHCP_USED )
+ cachedhcp_free ( &cached_dhcpack );
/* Report unclaimed DHCPACK, if any. Do not free yet, since
* it may still be claimed by a dynamically created device
@@ -284,10 +311,16 @@ static void cachedhcp_shutdown ( int booting __unused ) {
cachedhcp_free ( &cached_dhcpack );
}
-/** Cached DHCPACK startup function */
-struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_LATE ) = {
- .name = "cachedhcp",
- .startup = cachedhcp_startup,
+/** Cached DHCP packet early startup function */
+struct startup_fn cachedhcp_early_fn __startup_fn ( STARTUP_EARLY ) = {
+ .name = "cachedhcp1",
+ .startup = cachedhcp_startup_early,
+};
+
+/** Cached DHCP packet late startup function */
+struct startup_fn cachedhcp_late_fn __startup_fn ( STARTUP_LATE ) = {
+ .name = "cachedhcp2",
+ .startup = cachedhcp_startup_late,
.shutdown = cachedhcp_shutdown,
};
@@ -309,3 +342,25 @@ struct net_driver cachedhcp_driver __net_driver = {
.name = "cachedhcp",
.probe = cachedhcp_probe,
};
+
+/**
+ * Recycle cached DHCPACK
+ *
+ * @v netdev Network device
+ * @v priv Private data
+ */
+void cachedhcp_recycle ( struct net_device *netdev ) {
+ struct cached_dhcp_packet *cache = &cached_dhcpack;
+ struct settings *settings;
+
+ /* Return DHCPACK to cache, if applicable */
+ settings = find_child_settings ( netdev_settings ( netdev ),
+ cache->name );
+ if ( cache->dhcppkt && ( settings == &cache->dhcppkt->settings ) ) {
+ DBGC ( colour, "CACHEDHCP %s recycled from %s\n",
+ cache->name, netdev->name );
+ assert ( cache->flags & CACHEDHCP_USED );
+ unregister_settings ( settings );
+ cache->flags &= ~CACHEDHCP_USED;
+ }
+}
diff --git a/src/core/image.c b/src/core/image.c
index 3e65b5ed..bf0e4f75 100644
--- a/src/core/image.c
+++ b/src/core/image.c
@@ -134,10 +134,13 @@ int image_set_uri ( struct image *image, struct uri *uri ) {
int rc;
/* Set name, if image does not already have one */
- if ( uri->path && ( ! ( image->name && image->name[0] ) ) ) {
- name = basename ( ( char * ) uri->path );
- if ( ( rc = image_set_name ( image, name ) ) != 0 )
- return rc;
+ if ( ! ( image->name && image->name[0] ) ) {
+ name = ( uri->path ? uri->path : uri->opaque );
+ if ( name ) {
+ name = basename ( ( char * ) name );
+ if ( ( rc = image_set_name ( image, name ) ) != 0 )
+ return rc;
+ }
}
/* Update image URI */
diff --git a/src/core/main.c b/src/core/main.c
index 638dea9c..3db83649 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -32,9 +32,8 @@ __asmcall int main ( void ) {
initialise();
/* Some devices take an unreasonably long time to initialise */
- printf ( "%s initialising devices...", product_short_name );
+ printf ( "%s initialising devices...\n", product_short_name );
startup();
- printf ( "ok\n" );
/* Attempt to boot */
if ( ( rc = ipxe ( NULL ) ) != 0 )
diff --git a/src/core/mp.c b/src/core/mp.c
new file mode 100644
index 00000000..146d70a6
--- /dev/null
+++ b/src/core/mp.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/** @file
+ *
+ * Multiprocessor functions
+ *
+ */
+
+#include <ipxe/timer.h>
+#include <ipxe/mp.h>
+
+/** Time to wait for application processors */
+#define MP_MAX_CPUID_WAIT_MS 10
+
+/**
+ * Get boot CPU identifier
+ *
+ * @ret id Boot CPU identifier
+ */
+unsigned int mp_boot_cpuid ( void ) {
+ unsigned int max = 0;
+
+ /* Update maximum to accommodate boot processor */
+ mp_exec_boot ( mp_update_max_cpuid, &max );
+ DBGC ( &mp_call, "MP boot processor ID is %#x\n", max );
+
+ return max;
+}
+
+/**
+ * Get maximum CPU identifier
+ *
+ * @ret max Maximum CPU identifier
+ */
+unsigned int mp_max_cpuid ( void ) {
+ unsigned int max = mp_boot_cpuid();
+
+ /* Update maximum to accommodate application processors */
+ mp_start_all ( mp_update_max_cpuid, &max );
+ mdelay ( MP_MAX_CPUID_WAIT_MS );
+ DBGC ( &mp_call, "MP observed maximum CPU ID is %#x\n", max );
+
+ return max;
+}
diff --git a/src/core/null_mp.c b/src/core/null_mp.c
new file mode 100644
index 00000000..0fa69303
--- /dev/null
+++ b/src/core/null_mp.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/**
+ * @file
+ *
+ * Null multiprocessor API
+ *
+ */
+
+#include <ipxe/mp.h>
+
+PROVIDE_MPAPI_INLINE ( null, mp_address );
+PROVIDE_MPAPI_INLINE ( null, mp_exec_boot );
+PROVIDE_MPAPI_INLINE ( null, mp_start_all );
diff --git a/src/core/settings.c b/src/core/settings.c
index bece1afe..aa4bbae2 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -2698,6 +2698,113 @@ struct builtin_setting unixtime_builtin_setting __builtin_setting = {
};
/**
+ * Fetch current working URI-related setting
+ *
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @v rel Relative URI string
+ * @ret len Length of setting data, or negative error
+ */
+static int cwuri_fetch_uri ( void *data, size_t len, const char *rel ) {
+ struct uri *reluri;
+ struct uri *uri;
+ char *uristring;
+ int ret;
+
+ /* Check that current working URI is set */
+ if ( ! cwuri ) {
+ ret = -ENOENT;
+ goto err_unset;
+ }
+
+ /* Construct relative URI */
+ reluri = parse_uri ( rel );
+ if ( ! reluri ) {
+ ret = -ENOMEM;
+ goto err_parse;
+ }
+
+ /* Construct resolved URI */
+ uri = resolve_uri ( cwuri, reluri );
+ if ( ! uri ) {
+ ret = -ENOMEM;
+ goto err_resolve;
+ }
+
+ /* Format URI string into allocated buffer (with NUL) */
+ uristring = format_uri_alloc ( uri );
+ if ( ! uristring ) {
+ ret = -ENOMEM;
+ goto err_format;
+ }
+
+ /* Copy URI string to buffer */
+ strncpy ( data, uristring, len );
+ ret = strlen ( uristring );
+
+ free ( uristring );
+ err_format:
+ uri_put ( uri );
+ err_resolve:
+ uri_put ( reluri );
+ err_parse:
+ err_unset:
+ return ret;
+}
+
+/**
+ * Fetch current working URI setting
+ *
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int cwuri_fetch ( void *data, size_t len ) {
+
+ return cwuri_fetch_uri ( data, len, "" );
+}
+
+/**
+ * Fetch current working directory URI setting
+ *
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int cwduri_fetch ( void *data, size_t len ) {
+
+ return cwuri_fetch_uri ( data, len, "." );
+}
+
+/** Current working URI setting */
+const struct setting cwuri_setting __setting ( SETTING_MISC, cwuri ) = {
+ .name = "cwuri",
+ .description = "Current working URI",
+ .type = &setting_type_string,
+ .scope = &builtin_scope,
+};
+
+/** Current working directory URI setting */
+const struct setting cwduri_setting __setting ( SETTING_MISC, cwduri ) = {
+ .name = "cwduri",
+ .description = "Current working directory URI",
+ .type = &setting_type_string,
+ .scope = &builtin_scope,
+};
+
+/** Current working URI built-in setting */
+struct builtin_setting cwuri_builtin_setting __builtin_setting = {
+ .setting = &cwuri_setting,
+ .fetch = cwuri_fetch,
+};
+
+/** Current working directory URI built-in setting */
+struct builtin_setting cwduri_builtin_setting __builtin_setting = {
+ .setting = &cwduri_setting,
+ .fetch = cwduri_fetch,
+};
+
+/**
* Fetch built-in setting
*
* @v settings Settings block