summaryrefslogtreecommitdiffstats
path: root/src/usr/autoboot.c
diff options
context:
space:
mode:
authorMichael Brown2010-09-03 17:11:51 +0200
committerMichael Brown2010-09-14 21:37:15 +0200
commit220495f8bf2222e1dc1aa7db554d23997b545546 (patch)
treef04aa0d123a0b643fc41e178db81cfe63ba913bf /src/usr/autoboot.c
parent[hermon] Use correct alignment for doorbell records (diff)
downloadipxe-220495f8bf2222e1dc1aa7db554d23997b545546.tar.gz
ipxe-220495f8bf2222e1dc1aa7db554d23997b545546.tar.xz
ipxe-220495f8bf2222e1dc1aa7db554d23997b545546.zip
[block] Replace gPXE block-device API with an iPXE asynchronous interface
The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/usr/autoboot.c')
-rw-r--r--src/usr/autoboot.c70
1 files changed, 62 insertions, 8 deletions
diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c
index 48d1fa60..0421dc43 100644
--- a/src/usr/autoboot.c
+++ b/src/usr/autoboot.c
@@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/image.h>
#include <ipxe/sanboot.h>
#include <ipxe/uri.h>
+#include <ipxe/init.h>
#include <usr/ifmgmt.h>
#include <usr/route.h>
#include <usr/dhcpmgmt.h>
@@ -109,6 +110,14 @@ int boot_next_server_and_filename ( struct in_addr next_server,
return rc;
}
+/** The "keep-san" setting */
+struct setting keep_san_setting __setting = {
+ .name = "keep-san",
+ .description = "Preserve SAN connection",
+ .tag = DHCP_EB_KEEP_SAN,
+ .type = &setting_type_int8,
+};
+
/**
* Boot using root path
*
@@ -116,17 +125,62 @@ int boot_next_server_and_filename ( struct in_addr next_server,
* @ret rc Return status code
*/
int boot_root_path ( const char *root_path ) {
- struct sanboot_protocol *sanboot;
+ struct uri *uri;
+ int drive;
+ int rc;
- /* Quick hack */
- for_each_table_entry ( sanboot, SANBOOT_PROTOCOLS ) {
- if ( strncmp ( root_path, sanboot->prefix,
- strlen ( sanboot->prefix ) ) == 0 ) {
- return sanboot->boot ( root_path );
- }
+ /* Parse URI */
+ uri = parse_uri ( root_path );
+ if ( ! uri ) {
+ printf ( "Could not parse \"%s\"\n", root_path );
+ rc = -ENOMEM;
+ goto err_parse_uri;
}
- return -ENOTSUP;
+ /* Hook SAN device */
+ if ( ( drive = san_hook ( uri, 0 ) ) < 0 ) {
+ rc = drive;
+ printf ( "Could not open SAN device: %s\n",
+ strerror ( rc ) );
+ goto err_open;
+ }
+ printf ( "Registered as SAN device %#02x\n", drive );
+
+ /* Describe SAN device */
+ if ( ( rc = san_describe ( drive ) ) != 0 ) {
+ printf ( "Could not describe SAN device %#02x: %s\n",
+ drive, strerror ( rc ) );
+ goto err_describe;
+ }
+
+ printf ( "Booting from SAN device %#02x\n", drive );
+ rc = san_boot ( drive );
+ printf ( "Boot from SAN device %#02x failed: %s\n",
+ drive, strerror ( rc ) );
+
+ /* Leave drive registered, if instructed to do so */
+ if ( fetch_intz_setting ( NULL, &keep_san_setting ) != 0 ) {
+ printf ( "Preserving connection to SAN device %#02x\n",
+ drive );
+ shutdown_exit_flags |= SHUTDOWN_KEEP_DEVICES;
+ goto err_keep_san;
+ }
+
+ /* Unhook SAN deivce */
+ printf ( "Unregistering SAN device %#02x\n", drive );
+ san_unhook ( drive );
+
+ /* Drop URI reference */
+ uri_put ( uri );
+
+ return 0;
+
+ err_keep_san:
+ err_describe:
+ err_open:
+ uri_put ( uri );
+ err_parse_uri:
+ return rc;
}
/**