From 89349d7fad252f0b36be4a764369e6dd40a2e692 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 3 Jul 2007 23:09:56 +0100 Subject: [PATCH] Separated out initialisation functions from startup/shutdown functions. --- src/arch/i386/core/cpu.c | 2 - src/arch/i386/core/gdbsym.c | 4 +- src/arch/i386/core/i386_timer.c | 4 +- src/arch/i386/core/video_subr.c | 4 +- src/arch/i386/firmware/pcbios/hidemem.c | 11 ++- src/arch/i386/image/bzimage.c | 2 +- src/arch/i386/image/eltorito.c | 2 +- src/arch/i386/image/multiboot.c | 2 +- src/arch/i386/image/nbi.c | 2 +- src/core/heap.c | 27 ------ src/core/init.c | 124 +++++++++++++++++++----- src/core/main.c | 34 +------ src/core/malloc.c | 24 +++++ src/core/process.c | 8 +- src/core/serial.c | 18 +++- src/include/console.h | 14 +-- src/include/gpxe/heap.h | 15 --- src/include/gpxe/hidemem.h | 2 - src/include/gpxe/init.h | 85 +++++++++------- src/include/gpxe/process.h | 1 - src/include/gpxe/shutdown.h | 10 -- src/interface/pxe/pxe_preboot.c | 38 +++----- src/proto/nfs.c | 4 +- 23 files changed, 241 insertions(+), 196 deletions(-) delete mode 100644 src/core/heap.c delete mode 100644 src/include/gpxe/heap.h delete mode 100644 src/include/gpxe/shutdown.h diff --git a/src/arch/i386/core/cpu.c b/src/arch/i386/core/cpu.c index b43ee425..cbef6a1a 100644 --- a/src/arch/i386/core/cpu.c +++ b/src/arch/i386/core/cpu.c @@ -85,6 +85,4 @@ void cpu_setup(void) identify_cpu(&cpu_info); } -INIT_FN ( INIT_CPU, cpu_setup, NULL ); - #endif /* CONFIG_X86_64 */ diff --git a/src/arch/i386/core/gdbsym.c b/src/arch/i386/core/gdbsym.c index 1e0cadec..2da1a1bd 100644 --- a/src/arch/i386/core/gdbsym.c +++ b/src/arch/i386/core/gdbsym.c @@ -28,4 +28,6 @@ static void gdb_symbol_line ( void ) { getkey(); } -INIT_FN ( INIT_GDBSYM, gdb_symbol_line, NULL ); +struct startup_fn gdb_startup_fn __startup_fn ( STARTUP_NORMAL ) = { + .startup = gdb_symbol_line, +}; diff --git a/src/arch/i386/core/i386_timer.c b/src/arch/i386/core/i386_timer.c index 4764e21e..a87b4056 100644 --- a/src/arch/i386/core/i386_timer.c +++ b/src/arch/i386/core/i386_timer.c @@ -191,4 +191,6 @@ int timer2_running(void) #endif /* RTC_CURRTICKS */ -INIT_FN ( INIT_TIMERS, setup_timers, NULL ); +struct init_fn timer_init_fn __init_fn ( INIT_NORMAL ) = { + .initialise = setup_timers, +}; diff --git a/src/arch/i386/core/video_subr.c b/src/arch/i386/core/video_subr.c index cb7d1785..bf82cc61 100644 --- a/src/arch/i386/core/video_subr.c +++ b/src/arch/i386/core/video_subr.c @@ -99,4 +99,6 @@ struct console_driver vga_console __console_driver = { .disabled = 1, }; -INIT_FN ( INIT_CONSOLE, video_init, NULL ); +struct init_fn video_init_fn __init_fn ( INIT_EARLY ) = { + .initialise = video_init, +}; diff --git a/src/arch/i386/firmware/pcbios/hidemem.c b/src/arch/i386/firmware/pcbios/hidemem.c index c372246c..9a6dab84 100644 --- a/src/arch/i386/firmware/pcbios/hidemem.c +++ b/src/arch/i386/firmware/pcbios/hidemem.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /** Alignment for hidden memory regions */ @@ -110,7 +111,7 @@ void hide_basemem ( void ) { * Installs an INT 15 handler to edit Etherboot out of the memory map * returned by the BIOS. */ -void hide_etherboot ( void ) { +static void hide_etherboot ( void ) { /* Initialise the hidden regions */ hide_text(); @@ -127,7 +128,7 @@ void hide_etherboot ( void ) { * Uninstalls the INT 15 handler installed by hide_etherboot(), if * possible. */ -void unhide_etherboot ( void ) { +static void unhide_etherboot ( void ) { /* If we have more than one hooked interrupt at this point, it * means that some other vector is still hooked, in which case @@ -147,3 +148,9 @@ void unhide_etherboot ( void ) { unhook_bios_interrupt ( 0x15, ( unsigned int ) int15, &int15_vector ); } + +/** Hide Etherboot startup function */ +struct startup_fn hide_etherboot_startup_fn __startup_fn ( EARLY_STARTUP ) = { + .startup = hide_etherboot, + .shutdown = unhide_etherboot, +}; diff --git a/src/arch/i386/image/bzimage.c b/src/arch/i386/image/bzimage.c index 41262e19..f023fcf1 100644 --- a/src/arch/i386/image/bzimage.c +++ b/src/arch/i386/image/bzimage.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include struct image_type bzimage_image_type __image_type ( PROBE_NORMAL ); diff --git a/src/arch/i386/image/eltorito.c b/src/arch/i386/image/eltorito.c index 456a5100..53e25ca5 100644 --- a/src/arch/i386/image/eltorito.c +++ b/src/arch/i386/image/eltorito.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #define ISO9660_BLKSIZE 2048 #define ELTORITO_VOL_DESC_OFFSET ( 17 * ISO9660_BLKSIZE ) diff --git a/src/arch/i386/image/multiboot.c b/src/arch/i386/image/multiboot.c index a59927c8..71202460 100644 --- a/src/arch/i386/image/multiboot.c +++ b/src/arch/i386/image/multiboot.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT ); diff --git a/src/arch/i386/image/nbi.c b/src/arch/i386/image/nbi.c index 6084b21b..3a66e9cb 100644 --- a/src/arch/i386/image/nbi.c +++ b/src/arch/i386/image/nbi.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/core/heap.c b/src/core/heap.c deleted file mode 100644 index 4a84fc26..00000000 --- a/src/core/heap.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include - -/** - * @file - * - * Heap - * - */ - -/** - * Heap size - * - * Currently fixed at 128kB. - */ -#define HEAP_SIZE ( 128 * 1024 ) - -/** The heap itself */ -char heap[HEAP_SIZE] __attribute__ (( aligned ( __alignof__(void *) ))); - -/** - * Initialise the heap - * - */ -void init_heap ( void ) { - mpopulate ( heap, sizeof ( heap ) ); -} diff --git a/src/core/init.c b/src/core/init.c index 61570fd1..ed91bf36 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -1,37 +1,117 @@ -/************************************************************************** - * call_{init,reset,exit}_fns () - * - * Call the various initialisation and exit functions. We use a - * function table so that we don't end up dragging in an object just - * because we call its initialisation function. - ************************************************************************** +/* + * Copyright (C) 2007 Michael Brown . + * + * 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 #include +/** @file + * + * Initialisation, startup and shutdown routines + * + */ + +/** Registered initialisation functions */ static struct init_fn init_fns[0] - __table_start ( struct init_fn, init_fn ); + __table_start ( struct init_fn, init_fns ); static struct init_fn init_fns_end[0] - __table_end ( struct init_fn, init_fn ); + __table_end ( struct init_fn, init_fns ); -void call_init_fns ( void ) { +/** Registered startup/shutdown functions */ +static struct startup_fn startup_fns[0] + __table_start ( struct startup_fn, startup_fns ); +static struct startup_fn startup_fns_end[0] + __table_end ( struct startup_fn, startup_fns ); + +/** "startup() has been called" flag */ +static int started = 0; + +/** + * Initialise gPXE + * + * This function performs the one-time-only and irreversible + * initialisation steps, such as initialising the heap. It must be + * called before (almost) any other function. + * + * There is, by definition, no counterpart to this function on the + * shutdown path. + */ +void initialise ( void ) { struct init_fn *init_fn; - for ( init_fn = init_fns; init_fn < init_fns_end ; init_fn++ ) { - if ( init_fn->init ) - init_fn->init (); + /* Call registered initialisation functions */ + for ( init_fn = init_fns ; init_fn < init_fns_end ; init_fn++ ) { + init_fn->initialise (); } } -void call_exit_fns ( void ) { - struct init_fn *init_fn; +/** + * Start up gPXE + * + * This function performs the repeatable initialisation steps, such as + * probing devices. You may call startup() and shutdown() multiple + * times (as is done via the PXE API when PXENV_START_UNDI is used). + */ +void startup ( void ) { + struct startup_fn *startup_fn; - /* - * Exit functions are called in reverse order to - * initialisation functions. + if ( started ) + return; + + /* Call registered startup functions */ + for ( startup_fn = startup_fns ; startup_fn < startup_fns_end ; + startup_fn++ ) { + if ( startup_fn->startup ) + startup_fn->startup(); + } + + /* Probe for all devices. Treated separately because nothing + * else will drag in device.o */ - for ( init_fn = init_fns_end - 1; init_fn >= init_fns ; init_fn-- ) { - if ( init_fn->exit ) - init_fn->exit (); - } + probe_devices(); + + started = 1; +} + +/** + * Shut down gPXE + * + * 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 ) { + 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(); + } + + started = 0; } diff --git a/src/core/main.c b/src/core/main.c index 5b01df9c..09dccc76 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1,5 +1,5 @@ /************************************************************************** -Etherboot - Network Bootstrap Program +gPXE - Network Bootstrap Program Literature dealing with the network protocols: ARP - RFC826 @@ -14,42 +14,11 @@ Literature dealing with the network protocols: **************************************************************************/ -#include #include -#include -#include #include #include -#include -#include #include -/** - * Start up Etherboot - * - * Call this function only once, before doing (almost) anything else. - */ -static void startup ( void ) { - init_heap(); - init_processes(); - - hide_etherboot(); - call_init_fns(); - probe_devices(); -} - -/** - * Shut down Etherboot - * - * Call this function only once, before either exiting main() or - * starting up a non-returnable image. - */ -void shutdown ( void ) { - remove_devices(); - call_exit_fns(); - unhide_etherboot(); -} - /** * Main entry point * @@ -57,6 +26,7 @@ void shutdown ( void ) { */ int main ( void ) { + initialise(); startup(); /* Try autobooting if we're not going straight to the shell */ diff --git a/src/core/malloc.c b/src/core/malloc.c index bf94592c..2d892f42 100644 --- a/src/core/malloc.c +++ b/src/core/malloc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include /** @file @@ -72,6 +73,16 @@ static LIST_HEAD ( free_blocks ); /** Total amount of free memory */ size_t freemem; +/** + * Heap size + * + * Currently fixed at 128kB. + */ +#define HEAP_SIZE ( 128 * 1024 ) + +/** The heap itself */ +static char heap[HEAP_SIZE] __attribute__ (( aligned ( __alignof__(void *) ))); + /** * Allocate a memory block * @@ -342,6 +353,19 @@ void mpopulate ( void *start, size_t len ) { free_memblock ( start, ( len & ~( MIN_MEMBLOCK_SIZE - 1 ) ) ); } +/** + * Initialise the heap + * + */ +static void init_heap ( void ) { + mpopulate ( heap, sizeof ( heap ) ); +} + +/** Memory allocator initialisation function */ +struct init_fn heap_init_fn __init_fn ( INIT_EARLY ) = { + .initialise = init_heap, +}; + #if 0 #include /** diff --git a/src/core/process.c b/src/core/process.c index bd35e614..9d9ca6a6 100644 --- a/src/core/process.c +++ b/src/core/process.c @@ -17,6 +17,7 @@ */ #include +#include #include /** @file @@ -83,10 +84,15 @@ void step ( void ) { * Initialise processes * */ -void init_processes ( void ) { +static void init_processes ( void ) { struct process *process; for ( process = processes ; process < processes_end ; process++ ) { process_add ( process ); } } + +/** Process initialiser */ +struct init_fn process_init_fn __init_fn ( INIT_NORMAL ) = { + .initialise = init_processes, +}; diff --git a/src/core/serial.c b/src/core/serial.c index 3e4543bb..f325bc45 100644 --- a/src/core/serial.c +++ b/src/core/serial.c @@ -225,7 +225,7 @@ static void serial_init ( void ) { /* * void serial_fini(void); * Cleanup our use of the serial port, in particular flush the - * output buffer so we don't accidentially loose characters. + * output buffer so we don't accidentially lose characters. */ static void serial_fini ( void ) { int i, status; @@ -250,5 +250,19 @@ struct console_driver serial_console __console_driver = { .disabled = 1, }; -INIT_FN ( INIT_CONSOLE, serial_init, serial_fini ); +/** Serial console startup function */ +struct startup_fn serial_startup_fn __startup_fn ( STARTUP_NORMAL ) = { + .startup = serial_init, + .shutdown = serial_fini, +}; +/** + * Serial console initialisation function + * + * Initialise console early on so that it is available to capture + * early debug messages. It is safe to call serial_init() multiple + * times. + */ +struct init_fn serial_init_fn __init_fn ( INIT_EARLY ) = { + .initialise = serial_init, +}; diff --git a/src/include/console.h b/src/include/console.h index fd1382b4..9addd526 100644 --- a/src/include/console.h +++ b/src/include/console.h @@ -21,19 +21,19 @@ * Must be made part of the console drivers table by using * #__console_driver. * - * @note Consoles that cannot be used before their INIT_FN() has - * completed should set #disabled=1 initially. This allows other - * console devices to still be used to print out early debugging - * messages. + * @note Consoles that cannot be used before their initialisation + * function has completed should set #disabled=1 initially. This + * allows other console devices to still be used to print out early + * debugging messages. * */ struct console_driver { /** Console is disabled. * * The console's putchar(), putline(), getchar() and iskey() - * methods will not be called while #disabled==1. Typically the - * console's initialisation functions (called via INIT_FN()) - * will set #disabled=0 upon completion. + * methods will not be called while #disabled==1. Typically + * the console's initialisation functions will set #disabled=0 + * upon completion. * */ int disabled; diff --git a/src/include/gpxe/heap.h b/src/include/gpxe/heap.h deleted file mode 100644 index f2793751..00000000 --- a/src/include/gpxe/heap.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _GPXE_HEAP_H -#define _GPXE_HEAP_H - -/** - * @file - * - * Heap - * - */ - -extern char heap[]; - -extern void init_heap ( void ); - -#endif /* _GPXE_HEAP_H */ diff --git a/src/include/gpxe/hidemem.h b/src/include/gpxe/hidemem.h index db867f1c..547f8881 100644 --- a/src/include/gpxe/hidemem.h +++ b/src/include/gpxe/hidemem.h @@ -17,8 +17,6 @@ enum hidemem_region_id { EXTMEM, }; -extern void hide_etherboot(); -extern void unhide_etherboot(); extern void hide_region ( unsigned int region_id, physaddr_t start, physaddr_t end ); diff --git a/src/include/gpxe/init.h b/src/include/gpxe/init.h index b5e2f864..a5caa3e0 100644 --- a/src/include/gpxe/init.h +++ b/src/include/gpxe/init.h @@ -3,36 +3,57 @@ #include -/* - * In order to avoid having objects dragged in just because main() - * calls their initialisation function, we allow each object to - * specify that it has a function that must be called to initialise - * that object. The function call_init_fns() will call all the - * included objects' initialisation functions. +/** + * An initialisation function * - * Objects that require initialisation should include init.h and - * register the initialisation function using INIT_FN(). - * - * Objects may register up to three functions: init, reset and exit. - * init gets called only once, at the point that Etherboot is - * initialised (before the call to main()). reset gets called between - * each boot attempt. exit gets called only once, just before the - * loaded OS starts up (or just before Etherboot exits, if it exits, - * or when the PXE NBP calls UNDI_SHUTDOWN, if it's a PXE NBP). - * - * The syntax is: - * INIT_FN ( init_order, init_function, reset_function, exit_function ); - * where init_order is an ordering taken from the list below. Any - * function may be left as NULL. + * Initialisation functions are called exactly once, as part of the + * call to initialise(). + */ +struct init_fn { + void ( * initialise ) ( void ); +}; + +/** Declare an initialisation functon */ +#define __init_fn( init_order ) \ + __table ( struct init_fn, init_fns, init_order ) + +/** @defgroup initfn_order Initialisation function ordering + * @{ */ -/* An entry in the initialisation function table */ +#define INIT_EARLY 01 /**< Early initialisation */ +#define INIT_NORMAL 02 /**< Normal initialisation */ -struct init_fn { - void ( *init ) ( void ); - void ( *exit ) ( void ); +/** @} */ + +/** + * A startup/shutdown function + * + * Startup and shutdown functions may be called multiple times, as + * part of the calls to startup() and shutdown(). + */ +struct startup_fn { + void ( * startup ) ( void ); + void ( * shutdown ) ( void ); }; +/** Declare a startup/shutdown function */ +#define __startup_fn( startup_order ) \ + __table ( struct startup_fn, startup_fns, startup_order ) + +/** @defgroup startfn_order Startup/shutdown function ordering + * + * Shutdown functions are called in the reverse order to startup + * functions. + * + * @{ + */ + +#define STARTUP_EARLY 01 /**< Early startup */ +#define STARTUP_NORMAL 02 /**< Normal startup */ + +/** @} */ + /* Use double digits to avoid problems with "10" < "9" on alphabetic sort */ #define INIT_CONSOLE 02 #define INIT_GDBSYM 03 @@ -40,19 +61,9 @@ struct init_fn { #define INIT_TIMERS 05 #define INIT_LOADBUF 08 #define INIT_PCMCIA 09 -#define INIT_RPC 11 -/* Macro for creating an initialisation function table entry */ -#define INIT_FN( init_order, init_func, exit_func ) \ - struct init_fn PREFIX_OBJECT(init_fn__) \ - __table ( struct init_fn, init_fn, init_order ) = { \ - .init = init_func, \ - .exit = exit_func, \ - }; - -/* Function prototypes */ - -void call_init_fns ( void ); -void call_exit_fns ( void ); +extern void initialise ( void ); +extern void startup ( void ); +extern void shutdown ( void ); #endif /* _GPXE_INIT_H */ diff --git a/src/include/gpxe/process.h b/src/include/gpxe/process.h index 595787c0..8d9b109a 100644 --- a/src/include/gpxe/process.h +++ b/src/include/gpxe/process.h @@ -34,7 +34,6 @@ struct process { extern void process_add ( struct process *process ); extern void process_del ( struct process *process ); extern void step ( void ); -extern void init_processes ( void ); /** * Initialise process without adding to process list diff --git a/src/include/gpxe/shutdown.h b/src/include/gpxe/shutdown.h deleted file mode 100644 index 45102931..00000000 --- a/src/include/gpxe/shutdown.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _GPXE_SHUTDOWN_H -#define _GPXE_SHUTDOWN_H - -/** - * Shut down before exit - */ - -extern void shutdown ( void ); - -#endif /* _GPXE_SHUTDOWN_H */ diff --git a/src/interface/pxe/pxe_preboot.c b/src/interface/pxe/pxe_preboot.c index a74e58af..b2ae5372 100644 --- a/src/interface/pxe/pxe_preboot.c +++ b/src/interface/pxe/pxe_preboot.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "pxe.h" #include "pxe_call.h" @@ -54,26 +55,6 @@ static char *pxe_ris_filename = NULL; PXENV_EXIT_t pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK *unload_stack ) { DBG ( "PXENV_UNLOAD_STACK" ); -#if 0 - /* We need to call cleanup() at some point. The network card - * has already been disabled by ENSURE_CAN_UNLOAD(), but for - * the sake of completeness we should call the console_fini() - * etc. that are part of cleanup(). - * - * There seems to be a lack of consensus on which is the final - * PXE API call to make, but it's a fairly safe bet that all - * the potential shutdown sequences will include a call to - * PXENV_UNLOAD_STACK at some point, so we may as well do it - * here. - */ - cleanup(); - - if ( ! success ) { - unload_stack->Status = PXENV_STATUS_KEEP_ALL; - return PXENV_EXIT_FAILURE; - } -#endif - unload_stack->Status = PXENV_STATUS_SUCCESS; return PXENV_EXIT_SUCCESS; } @@ -209,6 +190,9 @@ PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) { DBG ( "PXENV_START_UNDI %04x:%04x:%04x", start_undi->AX, start_undi->BX, start_undi->DX ); + /* Probe for devices, etc. */ + startup(); + /* Determine bus type and location */ isapnp_read_port = start_undi->DX; isapnp_csn = start_undi->BX; @@ -252,12 +236,14 @@ PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) { PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ) { DBG ( "PXENV_STOP_UNDI" ); -#if 0 - if ( ! ensure_pxe_state(CAN_UNLOAD) ) { - stop_undi->Status = PXENV_STATUS_KEEP_UNDI; - return PXENV_EXIT_FAILURE; - } -#endif + /* Unhook INT 1A */ + pxe_unhook_int1a(); + + /* Clear PXE net device */ + pxe_set_netdev ( NULL ); + + /* Prepare for unload */ + shutdown(); stop_undi->Status = PXENV_STATUS_SUCCESS; return PXENV_EXIT_SUCCESS; diff --git a/src/proto/nfs.c b/src/proto/nfs.c index e21503c2..668948af 100644 --- a/src/proto/nfs.c +++ b/src/proto/nfs.c @@ -32,7 +32,7 @@ static unsigned long rpc_id; /************************************************************************** RPC_INIT - set up the ID counter to something fairly random **************************************************************************/ -static void rpc_init(void) +void rpc_init(void) { unsigned long t; @@ -608,8 +608,6 @@ nfssymlink: return 1; } -INIT_FN ( INIT_RPC, rpc_init, nfs_reset ); - struct protocol nfs_protocol __protocol = { .name = "nfs", .default_port = SUNRPC_PORT,