diff options
| author | Holger Lubitz | 2007-08-02 00:13:40 +0200 |
|---|---|---|
| committer | Holger Lubitz | 2007-08-02 00:13:40 +0200 |
| commit | 58f5565eb04f08c51b4f123930294c3d033e3a8e (patch) | |
| tree | 6df9ba9712544bad49f991006471f7e6c6511f84 /src/usr | |
| parent | make bcopy use memmove (diff) | |
| parent | Initrd concatenation now working (diff) | |
| download | ipxe-58f5565eb04f08c51b4f123930294c3d033e3a8e.tar.gz ipxe-58f5565eb04f08c51b4f123930294c3d033e3a8e.tar.xz ipxe-58f5565eb04f08c51b4f123930294c3d033e3a8e.zip | |
Merge branch 'master' into strings
Diffstat (limited to 'src/usr')
| -rw-r--r-- | src/usr/aoeboot.c | 104 | ||||
| -rw-r--r-- | src/usr/autoboot.c | 13 | ||||
| -rw-r--r-- | src/usr/iscsiboot.c | 24 |
3 files changed, 136 insertions, 5 deletions
diff --git a/src/usr/aoeboot.c b/src/usr/aoeboot.c new file mode 100644 index 000000000..ffc17a1c7 --- /dev/null +++ b/src/usr/aoeboot.c @@ -0,0 +1,104 @@ +#include <stdint.h> +#include <string.h> +#include <stdio.h> +#include <byteswap.h> +#include <gpxe/aoe.h> +#include <gpxe/ata.h> +#include <gpxe/netdevice.h> +#include <gpxe/dhcp.h> +#include <gpxe/abft.h> +#include <int13.h> +#include <usr/aoeboot.h> + +/** + * AoE boot information block + * + * Must be placed at 40:f0. + * + * This structure needs to be replaced by an ACPI table or similar. + */ +struct aoe_boot_info { + /** Must be 0x01 */ + uint8_t one; + /** Client MAC address */ + uint8_t client[ETH_ALEN]; + /** Server MAC address */ + uint8_t server[ETH_ALEN]; + /** Shelf number */ + uint16_t shelf; + /** Slot number */ + uint8_t slot; +} __attribute__ (( packed )); + +/** + * Guess boot network device + * + * @ret netdev Boot network device + */ +static struct net_device * guess_boot_netdev ( void ) { + struct net_device *boot_netdev; + + /* Just use the first network device */ + for_each_netdev ( boot_netdev ) { + return boot_netdev; + } + + return NULL; +} + +int aoeboot ( const char *root_path ) { + struct ata_device ata; + struct int13_drive drive; + int rc; + + memset ( &ata, 0, sizeof ( ata ) ); + memset ( &drive, 0, sizeof ( drive ) ); + + printf ( "AoE booting from %s\n", root_path ); + + /* FIXME: ugly, ugly hack */ + struct net_device *netdev = guess_boot_netdev(); + + if ( ( rc = aoe_attach ( &ata, netdev, root_path ) ) != 0 ) { + printf ( "Could not attach AoE device: %s\n", + strerror ( rc ) ); + goto error_attach; + } + if ( ( rc = init_atadev ( &ata ) ) != 0 ) { + printf ( "Could not initialise AoE device: %s\n", + strerror ( rc ) ); + goto error_init; + } + + /* FIXME: ugly, ugly hack */ + struct aoe_session *aoe = + container_of ( ata.backend, struct aoe_session, refcnt ); + struct aoe_boot_info boot_info; + boot_info.one = 0x01; + memcpy ( boot_info.client, netdev->ll_addr, + sizeof ( boot_info.client ) ); + memcpy ( boot_info.server, aoe->target, + sizeof ( boot_info.server ) ); + boot_info.shelf = htons ( aoe->major ); + boot_info.slot = aoe->minor; + copy_to_real ( 0x40, 0xf0, &boot_info, sizeof ( boot_info ) ); + + abft_fill_data ( aoe ); + + drive.drive = find_global_dhcp_num_option ( DHCP_EB_BIOS_DRIVE ); + drive.blockdev = &ata.blockdev; + + register_int13_drive ( &drive ); + printf ( "Registered as BIOS drive %#02x\n", drive.drive ); + printf ( "Booting from BIOS drive %#02x\n", drive.drive ); + rc = int13_boot ( drive.drive ); + printf ( "Boot failed\n" ); + + printf ( "Unregistering BIOS drive %#02x\n", drive.drive ); + unregister_int13_drive ( &drive ); + + error_init: + aoe_detach ( &ata ); + error_attach: + return rc; +} diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index 97b9a4067..53283d18c 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -27,6 +27,7 @@ #include <usr/dhcpmgmt.h> #include <usr/imgmgmt.h> #include <usr/iscsiboot.h> +#include <usr/aoeboot.h> #include <usr/autoboot.h> /** @file @@ -88,13 +89,15 @@ static int boot_filename ( const char *filename ) { * @ret rc Return status code */ static int boot_root_path ( const char *root_path ) { - int rc; /* Quick hack */ - if ( ( rc = iscsiboot ( root_path ) ) != 0 ) - return rc; + if ( strncmp ( root_path, "iscsi:", 6 ) == 0 ) { + return iscsiboot ( root_path ); + } else if ( strncmp ( root_path, "aoe:", 4 ) == 0 ) { + return aoeboot ( root_path ); + } - return 0; + return -ENOTSUP; } /** @@ -103,7 +106,7 @@ static int boot_root_path ( const char *root_path ) { * @v netdev Network device * @ret rc Return status code */ -int netboot ( struct net_device *netdev ) { +static int netboot ( struct net_device *netdev ) { char buf[256]; int rc; diff --git a/src/usr/iscsiboot.c b/src/usr/iscsiboot.c index f3910f149..a7caebaf6 100644 --- a/src/usr/iscsiboot.c +++ b/src/usr/iscsiboot.c @@ -3,9 +3,27 @@ #include <stdio.h> #include <gpxe/iscsi.h> #include <gpxe/dhcp.h> +#include <gpxe/netdevice.h> +#include <gpxe/ibft.h> #include <int13.h> #include <usr/iscsiboot.h> +/** + * Guess boot network device + * + * @ret netdev Boot network device + */ +static struct net_device * guess_boot_netdev ( void ) { + struct net_device *boot_netdev; + + /* Just use the first network device */ + for_each_netdev ( boot_netdev ) { + return boot_netdev; + } + + return NULL; +} + int iscsiboot ( const char *root_path ) { struct scsi_device scsi; struct int13_drive drive; @@ -30,6 +48,12 @@ int iscsiboot ( const char *root_path ) { drive.drive = find_global_dhcp_num_option ( DHCP_EB_BIOS_DRIVE ); drive.blockdev = &scsi.blockdev; + /* FIXME: ugly, ugly hack */ + struct net_device *netdev = guess_boot_netdev(); + struct iscsi_session *iscsi = + container_of ( scsi.backend, struct iscsi_session, refcnt ); + ibft_fill_data ( netdev, iscsi ); + register_int13_drive ( &drive ); printf ( "Registered as BIOS drive %#02x\n", drive.drive ); printf ( "Booting from BIOS drive %#02x\n", drive.drive ); |
