mirror of
https://github.com/xcat2/xNBA.git
synced 2024-11-29 12:49:49 +00:00
Quick hack to get AoE back in to the tree, on a par with the current
iSCSI hack.
This commit is contained in:
parent
a6a1052096
commit
43013da9bf
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <gpxe/async.h>
|
||||
#include <gpxe/aoe.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* AoE ATA device
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Issue ATA command via AoE device
|
||||
*
|
||||
* @v ata ATA device
|
||||
* @v command ATA command
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int aoe_command ( struct ata_device *ata,
|
||||
struct ata_command *command ) {
|
||||
struct aoe_device *aoedev
|
||||
= container_of ( ata, struct aoe_device, ata );
|
||||
struct async async;
|
||||
|
||||
return async_block ( &async, aoe_issue ( &aoedev->aoe, command,
|
||||
&async ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise AoE device
|
||||
*
|
||||
* @v aoedev AoE device
|
||||
*/
|
||||
int init_aoedev ( struct aoe_device *aoedev ) {
|
||||
aoedev->ata.command = aoe_command;
|
||||
aoe_open ( &aoedev->aoe );
|
||||
return init_atadev ( &aoedev->ata );
|
||||
}
|
@ -81,6 +81,9 @@ struct aoehdr {
|
||||
|
||||
/** An AoE session */
|
||||
struct aoe_session {
|
||||
/** Reference counter */
|
||||
struct refcnt refcnt;
|
||||
|
||||
/** List of all AoE sessions */
|
||||
struct list_head list;
|
||||
|
||||
@ -103,8 +106,8 @@ struct aoe_session {
|
||||
unsigned int status;
|
||||
/** Byte offset within command's data buffer */
|
||||
unsigned int command_offset;
|
||||
/** Asynchronous operation for this command */
|
||||
struct async async;
|
||||
/** Return status code for command */
|
||||
int rc;
|
||||
|
||||
/** Retransmission timer */
|
||||
struct retry_timer timer;
|
||||
@ -116,20 +119,8 @@ struct aoe_session {
|
||||
/** Maximum number of sectors per packet */
|
||||
#define AOE_MAX_COUNT 2
|
||||
|
||||
extern void aoe_open ( struct aoe_session *aoe );
|
||||
extern void aoe_close ( struct aoe_session *aoe );
|
||||
extern int aoe_issue ( struct aoe_session *aoe,
|
||||
struct ata_command *command,
|
||||
struct async *parent );
|
||||
|
||||
/** An AoE device */
|
||||
struct aoe_device {
|
||||
/** ATA device interface */
|
||||
struct ata_device ata;
|
||||
/** AoE protocol instance */
|
||||
struct aoe_session aoe;
|
||||
};
|
||||
|
||||
extern int init_aoedev ( struct aoe_device *aoedev );
|
||||
extern void aoe_detach ( struct ata_device *ata );
|
||||
extern int aoe_attach ( struct ata_device *ata, struct net_device *netdev,
|
||||
const char *root_path );
|
||||
|
||||
#endif /* _GPXE_AOE_H */
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <gpxe/blockdev.h>
|
||||
#include <gpxe/uaccess.h>
|
||||
#include <gpxe/refcnt.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
@ -195,6 +196,8 @@ struct ata_device {
|
||||
*/
|
||||
int ( * command ) ( struct ata_device *ata,
|
||||
struct ata_command *command );
|
||||
/** Backing device */
|
||||
struct refcnt *backend;
|
||||
};
|
||||
|
||||
extern int init_atadev ( struct ata_device *ata );
|
||||
|
6
src/include/usr/aoeboot.h
Normal file
6
src/include/usr/aoeboot.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _USR_AOEBOOT_H
|
||||
#define _USR_AOEBOOT_H
|
||||
|
||||
extern int aoeboot ( const char *root_path );
|
||||
|
||||
#endif /* _USR_AOEBOOT_H */
|
130
src/net/aoe.c
130
src/net/aoe.c
@ -19,6 +19,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <byteswap.h>
|
||||
@ -29,7 +30,7 @@
|
||||
#include <gpxe/uaccess.h>
|
||||
#include <gpxe/ata.h>
|
||||
#include <gpxe/netdevice.h>
|
||||
#include <gpxe/async.h>
|
||||
#include <gpxe/process.h>
|
||||
#include <gpxe/aoe.h>
|
||||
|
||||
/** @file
|
||||
@ -43,6 +44,14 @@ struct net_protocol aoe_protocol;
|
||||
/** List of all AoE sessions */
|
||||
static LIST_HEAD ( aoe_sessions );
|
||||
|
||||
static void aoe_free ( struct refcnt *refcnt ) {
|
||||
struct aoe_session *aoe =
|
||||
container_of ( refcnt, struct aoe_session, refcnt );
|
||||
|
||||
netdev_put ( aoe->netdev );
|
||||
free ( aoe );
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark current AoE command complete
|
||||
*
|
||||
@ -55,8 +64,8 @@ static void aoe_done ( struct aoe_session *aoe, int rc ) {
|
||||
aoe->command->cb.cmd_stat = aoe->status;
|
||||
aoe->command = NULL;
|
||||
|
||||
/* Mark async operation as complete */
|
||||
async_done ( &aoe->async, rc );
|
||||
/* Mark operation as complete */
|
||||
aoe->rc = rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,46 +274,99 @@ struct net_protocol aoe_protocol __net_protocol = {
|
||||
.rx = aoe_rx,
|
||||
};
|
||||
|
||||
/**
|
||||
* Open AoE session
|
||||
*
|
||||
* @v aoe AoE session
|
||||
*/
|
||||
void aoe_open ( struct aoe_session *aoe ) {
|
||||
memcpy ( aoe->target, ethernet_protocol.ll_broadcast,
|
||||
sizeof ( aoe->target ) );
|
||||
aoe->tag = AOE_TAG_MAGIC;
|
||||
aoe->timer.expired = aoe_timer_expired;
|
||||
list_add ( &aoe->list, &aoe_sessions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Close AoE session
|
||||
*
|
||||
* @v aoe AoE session
|
||||
*/
|
||||
void aoe_close ( struct aoe_session *aoe ) {
|
||||
list_del ( &aoe->list );
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue ATA command via an open AoE session
|
||||
*
|
||||
* @v aoe AoE session
|
||||
* @v ata ATA device
|
||||
* @v command ATA command
|
||||
* @v parent Parent asynchronous operation
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* Only one command may be issued concurrently per session. This call
|
||||
* is non-blocking; use async_wait() to wait for the command to
|
||||
* complete.
|
||||
*/
|
||||
int aoe_issue ( struct aoe_session *aoe, struct ata_command *command,
|
||||
struct async *parent ) {
|
||||
static int aoe_command ( struct ata_device *ata,
|
||||
struct ata_command *command ) {
|
||||
struct aoe_session *aoe =
|
||||
container_of ( ata->backend, struct aoe_session, refcnt );
|
||||
int rc;
|
||||
|
||||
aoe->command = command;
|
||||
aoe->status = 0;
|
||||
aoe->command_offset = 0;
|
||||
aoe_send_command ( aoe );
|
||||
async_init ( &aoe->async, &default_async_operations, parent );
|
||||
|
||||
aoe->rc = -EINPROGRESS;
|
||||
while ( aoe->rc == -EINPROGRESS )
|
||||
step();
|
||||
rc = aoe->rc;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int aoe_detached_command ( struct ata_device *ata __unused,
|
||||
struct ata_command *command __unused ) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
void aoe_detach ( struct ata_device *ata ) {
|
||||
struct aoe_session *aoe =
|
||||
container_of ( ata->backend, struct aoe_session, refcnt );
|
||||
|
||||
stop_timer ( &aoe->timer );
|
||||
ata->command = aoe_detached_command;
|
||||
list_del ( &aoe->list );
|
||||
ref_put ( ata->backend );
|
||||
ata->backend = NULL;
|
||||
}
|
||||
|
||||
static int aoe_parse_root_path ( struct aoe_session *aoe,
|
||||
const char *root_path ) {
|
||||
char *ptr;
|
||||
|
||||
if ( strncmp ( root_path, "aoe:", 4 ) != 0 )
|
||||
return -EINVAL;
|
||||
ptr = ( ( char * ) root_path + 4 );
|
||||
|
||||
if ( *ptr++ != 'e' )
|
||||
return -EINVAL;
|
||||
|
||||
aoe->major = strtoul ( ptr, &ptr, 10 );
|
||||
if ( *ptr++ != '.' )
|
||||
return -EINVAL;
|
||||
|
||||
aoe->minor = strtoul ( ptr, &ptr, 10 );
|
||||
if ( *ptr )
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aoe_attach ( struct ata_device *ata, struct net_device *netdev,
|
||||
const char *root_path ) {
|
||||
struct aoe_session *aoe;
|
||||
int rc;
|
||||
|
||||
/* Allocate and initialise structure */
|
||||
aoe = zalloc ( sizeof ( *aoe ) );
|
||||
if ( ! aoe )
|
||||
return -ENOMEM;
|
||||
aoe->refcnt.free = aoe_free;
|
||||
aoe->netdev = netdev_get ( netdev );
|
||||
memcpy ( aoe->target, ethernet_protocol.ll_broadcast,
|
||||
sizeof ( aoe->target ) );
|
||||
aoe->tag = AOE_TAG_MAGIC;
|
||||
aoe->timer.expired = aoe_timer_expired;
|
||||
|
||||
/* Parse root path */
|
||||
if ( ( rc = aoe_parse_root_path ( aoe, root_path ) ) != 0 )
|
||||
goto err;
|
||||
|
||||
/* Attach parent interface, transfer reference to connection
|
||||
* list, and return
|
||||
*/
|
||||
ata->backend = ref_get ( &aoe->refcnt );
|
||||
ata->command = aoe_command;
|
||||
list_add ( &aoe->list, &aoe_sessions );
|
||||
return 0;
|
||||
|
||||
err:
|
||||
ref_put ( &aoe->refcnt );
|
||||
return rc;
|
||||
}
|
||||
|
@ -1,71 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <console.h>
|
||||
#include <gpxe/netdevice.h>
|
||||
#include <gpxe/aoe.h>
|
||||
#include <int13.h>
|
||||
|
||||
static struct aoe_device test_aoedev = {
|
||||
.aoe = {
|
||||
.major = 0,
|
||||
.minor = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static int aoe_parse ( const char *aoename, struct aoe_session *aoe ) {
|
||||
char *ptr = ( ( char * ) aoename );
|
||||
|
||||
if ( *ptr++ != 'e' )
|
||||
return -EINVAL;
|
||||
|
||||
aoe->major = strtoul ( ptr, &ptr, 10 );
|
||||
if ( *ptr++ != '.' )
|
||||
return -EINVAL;
|
||||
|
||||
aoe->minor = strtoul ( ptr, &ptr, 10 );
|
||||
if ( *ptr )
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_aoeboot ( struct net_device *netdev, const char *aoename,
|
||||
unsigned int drivenum ) {
|
||||
struct int13_drive drive;
|
||||
int rc;
|
||||
|
||||
printf ( "Attempting to boot from AoE device %s via %s\n",
|
||||
aoename, netdev->name );
|
||||
|
||||
if ( ( rc = aoe_parse ( aoename, &test_aoedev.aoe ) ) != 0 ) {
|
||||
printf ( "Invalid AoE device name \"%s\"\n", aoename );
|
||||
return rc;
|
||||
}
|
||||
|
||||
printf ( "Initialising AoE device e%d.%d\n",
|
||||
test_aoedev.aoe.major, test_aoedev.aoe.minor );
|
||||
test_aoedev.aoe.netdev = netdev;
|
||||
if ( ( rc = init_aoedev ( &test_aoedev ) ) != 0 ) {
|
||||
printf ( "Could not reach AoE device e%d.%d\n",
|
||||
test_aoedev.aoe.major, test_aoedev.aoe.minor );
|
||||
return rc;
|
||||
}
|
||||
|
||||
memset ( &drive, 0, sizeof ( drive ) );
|
||||
drive.drive = drivenum;
|
||||
drive.blockdev = &test_aoedev.ata.blockdev;
|
||||
register_int13_drive ( &drive );
|
||||
printf ( "Registered AoE device e%d.%d as BIOS drive %#02x\n",
|
||||
test_aoedev.aoe.major, test_aoedev.aoe.minor, 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 );
|
||||
|
||||
return rc;
|
||||
}
|
67
src/usr/aoeboot.c
Normal file
67
src/usr/aoeboot.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <gpxe/aoe.h>
|
||||
#include <gpxe/ata.h>
|
||||
#include <gpxe/netdevice.h>
|
||||
#include <gpxe/dhcp.h>
|
||||
#include <int13.h>
|
||||
#include <usr/aoeboot.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 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user