Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[iSCSI] Support Windows Server 2008 direct iSCSI installation
Add yet another ugly hack to iscsiboot.c, this time to allow the user to
inhibit the shutdown/removal of the iSCSI INT13 device (and the network
devices, since they are required for the iSCSI device to function).

On the plus side, the fact that shutdown() now takes flags to
differentiate between shutdown-for-exit and shutdown-for-boot means that
another ugly hack (to allow returning via the PXE stack on BIOSes that
have broken INT 18 calls) will be easier.

I feel dirty.
  • Loading branch information
Michael Brown committed Jul 17, 2008
1 parent 4e033c7 commit 03c80c1
Show file tree
Hide file tree
Showing 18 changed files with 115 additions and 51 deletions.
2 changes: 1 addition & 1 deletion src/arch/i386/firmware/pcbios/hidemem.c
Expand Up @@ -128,7 +128,7 @@ static void hide_etherboot ( void ) {
* Uninstalls the INT 15 handler installed by hide_etherboot(), if
* possible.
*/
static void unhide_etherboot ( void ) {
static void unhide_etherboot ( int flags __unused ) {

/* If we have more than one hooked interrupt at this point, it
* means that some other vector is still hooked, in which case
Expand Down
2 changes: 1 addition & 1 deletion src/arch/i386/image/bzimage.c
Expand Up @@ -348,7 +348,7 @@ static int bzimage_exec ( struct image *image ) {
sizeof ( bzhdr ) );

/* Prepare for exiting */
shutdown();
shutdown ( SHUTDOWN_BOOT );

DBGC ( image, "bzImage %p jumping to RM kernel at %04x:0000 "
"(stack %04x:%04zx)\n", image,
Expand Down
2 changes: 1 addition & 1 deletion src/arch/i386/image/elfboot.c
Expand Up @@ -46,7 +46,7 @@ static int elfboot_exec ( struct image *image ) {
/* An ELF image has no callback interface, so we need to shut
* down before invoking it.
*/
shutdown();
shutdown ( SHUTDOWN_BOOT );

/* Jump to OS with flat physical addressing */
__asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" )
Expand Down
2 changes: 1 addition & 1 deletion src/arch/i386/image/multiboot.c
Expand Up @@ -277,7 +277,7 @@ static int multiboot_exec ( struct image *image ) {
/* Multiboot images may not return and have no callback
* interface, so shut everything down prior to booting the OS.
*/
shutdown();
shutdown ( SHUTDOWN_BOOT );

/* Jump to OS with flat physical addressing */
__asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" )
Expand Down
2 changes: 1 addition & 1 deletion src/arch/i386/image/nbi.c
Expand Up @@ -429,7 +429,7 @@ static int nbi_exec ( struct image *image ) {
/* Shut down now if NBI image will not return */
may_return = NBI_PROGRAM_RETURNS ( imgheader.flags );
if ( ! may_return )
shutdown();
shutdown ( SHUTDOWN_BOOT );

/* Execute NBI image */
if ( NBI_LINEAR_EXEC_ADDR ( imgheader.flags ) ) {
Expand Down
7 changes: 7 additions & 0 deletions src/core/config.c
Expand Up @@ -205,3 +205,10 @@ REQUIRE_OBJECT ( gdbidt );
REQUIRE_OBJECT ( gdbudp );
REQUIRE_OBJECT ( gdbstub_cmd );
#endif

/*
* Drag in objects that are always required, but not dragged in via
* symbol dependencies.
*
*/
REQUIRE_OBJECT ( device );
18 changes: 13 additions & 5 deletions src/core/device.c
Expand Up @@ -20,6 +20,7 @@
#include <gpxe/list.h>
#include <gpxe/tables.h>
#include <gpxe/device.h>
#include <gpxe/init.h>

/**
* @file
Expand Down Expand Up @@ -68,13 +69,11 @@ static void rootdev_remove ( struct root_device *rootdev ) {
/**
* Probe all devices
*
* @ret rc Return status code
*
* This initiates probing for all devices in the system. After this
* call, the device hierarchy will be populated, and all hardware
* should be ready to use.
*/
int probe_devices ( void ) {
static void probe_devices ( void ) {
struct root_device *rootdev;
int rc;

Expand All @@ -84,19 +83,28 @@ int probe_devices ( void ) {
if ( ( rc = rootdev_probe ( rootdev ) ) != 0 )
list_del ( &rootdev->dev.siblings );
}
return 0;
}

/**
* Remove all devices
*
*/
void remove_devices ( void ) {
static void remove_devices ( int flags ) {
struct root_device *rootdev;
struct root_device *tmp;

if ( flags & SHUTDOWN_KEEP_DEVICES ) {
DBG ( "Refusing to remove devices on shutdown\n" );
return;
}

list_for_each_entry_safe ( rootdev, tmp, &devices, dev.siblings ) {
rootdev_remove ( rootdev );
list_del ( &rootdev->dev.siblings );
}
}

struct startup_fn startup_devices __startup_fn ( STARTUP_NORMAL ) = {
.startup = probe_devices,
.shutdown = remove_devices,
};
14 changes: 4 additions & 10 deletions src/core/init.c
Expand Up @@ -79,38 +79,32 @@ void startup ( void ) {
startup_fn->startup();
}

/* Probe for all devices. Treated separately because nothing
* else will drag in device.o
*/
probe_devices();

started = 1;
}

/**
* Shut down gPXE
*
* @v flags Shutdown behaviour flags
*
* This function reverses the actions of startup(), and leaves gPXE in
* a state ready to be removed from memory. You may call startup()
* again after calling shutdown().
* Call this function only once, before either exiting main() or
* starting up a non-returnable image.
*/
void shutdown ( void ) {
void shutdown ( int flags ) {
struct startup_fn *startup_fn;

if ( ! started )
return;

/* Remove all devices */
remove_devices();

/* Call registered shutdown functions (in reverse order) */
for ( startup_fn = startup_fns_end - 1 ; startup_fn >= startup_fns ;
startup_fn-- ) {
if ( startup_fn->shutdown )
startup_fn->shutdown();
startup_fn->shutdown ( flags );
}

started = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/core/main.c
Expand Up @@ -62,7 +62,7 @@ __cdecl int main ( void ) {
shell();
}

shutdown();
shutdown ( SHUTDOWN_EXIT | shutdown_exit_flags );

return 0;
}
4 changes: 2 additions & 2 deletions src/core/serial.c
Expand Up @@ -224,7 +224,7 @@ static void serial_init ( void ) {
* Cleanup our use of the serial port, in particular flush the
* output buffer so we don't accidentially lose characters.
*/
static void serial_fini ( void ) {
static void serial_fini ( int flags __unused ) {
int i, status;
/* Flush the output buffer to avoid dropping characters,
* if we are reinitializing the serial port.
Expand All @@ -247,6 +247,6 @@ struct init_fn serial_init_fn __init_fn ( INIT_SERIAL ) = {
};

/** Serial driver startup function */
struct startup_fn serial_startup_fn __startup_fn ( STARTUP_NORMAL ) = {
struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = {
.shutdown = serial_fini,
};
3 changes: 0 additions & 3 deletions src/include/gpxe/device.h
Expand Up @@ -105,7 +105,4 @@ struct root_driver {
/** Declare a root device */
#define __root_device __table ( struct root_device, root_devices, 01 )

extern int probe_devices ( void );
extern void remove_devices ( void );

#endif /* _GPXE_DEVICE_H */
15 changes: 12 additions & 3 deletions src/include/gpxe/dhcp.h
Expand Up @@ -164,23 +164,32 @@ struct dhcp_packet;
* priority of multiple option blocks (e.g. options from non-volatile
* storage versus options from a DHCP server).
*/
#define DHCP_EB_PRIORITY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 1 )
#define DHCP_EB_PRIORITY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x01 )

/** "Your" IP address
*
* This option is used internally to contain the value of the "yiaddr"
* field, in order to provide a consistent approach to storing and
* processing options. It should never be present in a DHCP packet.
*/
#define DHCP_EB_YIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 2 )
#define DHCP_EB_YIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x02 )

/** "Server" IP address
*
* This option is used internally to contain the value of the "siaddr"
* field, in order to provide a consistent approach to storing and
* processing options. It should never be present in a DHCP packet.
*/
#define DHCP_EB_SIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 3 )
#define DHCP_EB_SIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x03 )

/** Keep SAN drive registered
*
* If set to a non-zero value, gPXE will not detach any SAN drive
* after failing to boot from it. (This option is required in order
* to perform a Windows Server 2008 installation direct to an iSCSI
* target.)
*/
#define DHCP_EB_KEEP_SAN DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x08 )

/*
* Tags in the range 0x10-0x7f are reserved for feature markers
Expand Down
1 change: 1 addition & 0 deletions src/include/gpxe/errfile.h
Expand Up @@ -155,6 +155,7 @@
#define ERRFILE_ibft ( ERRFILE_OTHER | 0x000c0000 )
#define ERRFILE_tls ( ERRFILE_OTHER | 0x000d0000 )
#define ERRFILE_ifmgmt ( ERRFILE_OTHER | 0x000e0000 )
#define ERRFILE_iscsiboot ( ERRFILE_OTHER | 0x000f0000 )

/** @} */

Expand Down
14 changes: 12 additions & 2 deletions src/include/gpxe/init.h
Expand Up @@ -28,6 +28,16 @@ struct init_fn {

/** @} */

/** Shutdown flags */
enum shutdown_flags {
/** Shutdown is in order to exit (return to gPXE's caller) */
SHUTDOWN_EXIT = 0x0001,
/** Shutdown is in order to boot an OS */
SHUTDOWN_BOOT = 0x0002,
/** Do not remove devices */
SHUTDOWN_KEEP_DEVICES = 0x0004,
};

/**
* A startup/shutdown function
*
Expand All @@ -36,7 +46,7 @@ struct init_fn {
*/
struct startup_fn {
void ( * startup ) ( void );
void ( * shutdown ) ( void );
void ( * shutdown ) ( int flags );
};

/** Declare a startup/shutdown function */
Expand All @@ -58,6 +68,6 @@ struct startup_fn {

extern void initialise ( void );
extern void startup ( void );
extern void shutdown ( void );
extern void shutdown ( int flags );

#endif /* _GPXE_INIT_H */
2 changes: 2 additions & 0 deletions src/include/usr/autoboot.h
Expand Up @@ -7,6 +7,8 @@
*
*/

extern int shutdown_exit_flags;

extern void autoboot ( void );
extern int boot_root_path ( const char *root_path );

Expand Down
2 changes: 1 addition & 1 deletion src/interface/pxe/pxe_preboot.c
Expand Up @@ -318,7 +318,7 @@ PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ) {
pxe_set_netdev ( NULL );

/* Prepare for unload */
shutdown();
shutdown ( SHUTDOWN_BOOT );

stop_undi->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
Expand Down
3 changes: 3 additions & 0 deletions src/usr/autoboot.c
Expand Up @@ -41,6 +41,9 @@
/** Time to wait for link-up */
#define LINK_WAIT_MS 15000

/** Shutdown flags for exit */
int shutdown_exit_flags = 0;

/**
* Identify the boot network device
*
Expand Down

0 comments on commit 03c80c1

Please sign in to comment.