Home | History | Annotate | Download | only in gpxe
      1 #ifndef _GPXE_TABLES_H
      2 #define _GPXE_TABLES_H
      3 
      4 FILE_LICENCE ( GPL2_OR_LATER );
      5 
      6 /** @page ifdef_harmful #ifdef considered harmful
      7  *
      8  * Overuse of @c #ifdef has long been a problem in Etherboot.
      9  * Etherboot provides a rich array of features, but all these features
     10  * take up valuable space in a ROM image.  The traditional solution to
     11  * this problem has been for each feature to have its own @c #ifdef
     12  * option, allowing the feature to be compiled in only if desired.
     13  *
     14  * The problem with this is that it becomes impossible to compile, let
     15  * alone test, all possible versions of Etherboot.  Code that is not
     16  * typically used tends to suffer from bit-rot over time.  It becomes
     17  * extremely difficult to predict which combinations of compile-time
     18  * options will result in code that can even compile and link
     19  * correctly.
     20  *
     21  * To solve this problem, we have adopted a new approach from
     22  * Etherboot 5.5 onwards.  @c #ifdef is now "considered harmful", and
     23  * its use should be minimised.  Separate features should be
     24  * implemented in separate @c .c files, and should \b always be
     25  * compiled (i.e. they should \b not be guarded with a @c #ifdef @c
     26  * MY_PET_FEATURE statement).  By making (almost) all code always
     27  * compile, we avoid the problem of bit-rot in rarely-used code.
     28  *
     29  * The file config.h, in combination with the @c make command line,
     30  * specifies the objects that will be included in any particular build
     31  * of Etherboot.  For example, suppose that config.h includes the line
     32  *
     33  * @code
     34  *
     35  *   #define CONSOLE_SERIAL
     36  *   #define DOWNLOAD_PROTO_TFTP
     37  *
     38  * @endcode
     39  *
     40  * When a particular Etherboot image (e.g. @c bin/rtl8139.zdsk) is
     41  * built, the options specified in config.h are used to drag in the
     42  * relevant objects at link-time.  For the above example, serial.o and
     43  * tftp.o would be linked in.
     44  *
     45  * There remains one problem to solve: how do these objects get used?
     46  * Traditionally, we had code such as
     47  *
     48  * @code
     49  *
     50  *    #ifdef CONSOLE_SERIAL
     51  *      serial_init();
     52  *    #endif
     53  *
     54  * @endcode
     55  *
     56  * in main.c, but this reintroduces @c #ifdef and so is a Bad Idea.
     57  * We cannot simply remove the @c #ifdef and make it
     58  *
     59  * @code
     60  *
     61  *   serial_init();
     62  *
     63  * @endcode
     64  *
     65  * because then serial.o would end up always being linked in.
     66  *
     67  * The solution is to use @link tables.h linker tables @endlink.
     68  *
     69  */
     70 
     71 /** @file
     72  *
     73  * Linker tables
     74  *
     75  * Read @ref ifdef_harmful first for some background on the motivation
     76  * for using linker tables.
     77  *
     78  * This file provides macros for dealing with linker-generated tables
     79  * of fixed-size symbols.  We make fairly extensive use of these in
     80  * order to avoid @c #ifdef spaghetti and/or linker symbol pollution.
     81  * For example, instead of having code such as
     82  *
     83  * @code
     84  *
     85  *    #ifdef CONSOLE_SERIAL
     86  *      serial_init();
     87  *    #endif
     88  *
     89  * @endcode
     90  *
     91  * we make serial.c generate an entry in the initialisation function
     92  * table, and then have a function call_init_fns() that simply calls
     93  * all functions present in this table.  If and only if serial.o gets
     94  * linked in, then its initialisation function will be called.  We
     95  * avoid linker symbol pollution (i.e. always dragging in serial.o
     96  * just because of a call to serial_init()) and we also avoid @c
     97  * #ifdef spaghetti (having to conditionalise every reference to
     98  * functions in serial.c).
     99  *
    100  * The linker script takes care of assembling the tables for us.  All
    101  * our table sections have names of the format @c .tbl.NAME.NN where
    102  * @c NAME designates the data structure stored in the table (e.g. @c
    103  * init_fns) and @c NN is a two-digit decimal number used to impose an
    104  * ordering upon the tables if required.  @c NN=00 is reserved for the
    105  * symbol indicating "table start", and @c NN=99 is reserved for the
    106  * symbol indicating "table end".
    107  *
    108  * As an example, suppose that we want to create a "frobnicator"
    109  * feature framework, and allow for several independent modules to
    110  * provide frobnicating services.  Then we would create a frob.h
    111  * header file containing e.g.
    112  *
    113  * @code
    114  *
    115  *   struct frobnicator {
    116  *      const char *name;		// Name of the frobnicator
    117  *	void ( *frob ) ( void ); 	// The frobnicating function itself
    118  *   };
    119  *
    120  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
    121  *
    122  *   #define __frobnicator __table_entry ( FROBNICATORS, 01 )
    123  *
    124  * @endcode
    125  *
    126  * Any module providing frobnicating services would look something
    127  * like
    128  *
    129  * @code
    130  *
    131  *   #include "frob.h"
    132  *
    133  *   static void my_frob ( void ) {
    134  *	// Do my frobnicating
    135  *	...
    136  *   }
    137  *
    138  *   struct frob my_frobnicator __frobnicator = {
    139  *	.name = "my_frob",
    140  *	.frob = my_frob,
    141  *   };
    142  *
    143  * @endcode
    144  *
    145  * The central frobnicator code (frob.c) would use the frobnicating
    146  * modules as follows
    147  *
    148  * @code
    149  *
    150  *   #include "frob.h"
    151  *
    152  *   // Call all linked-in frobnicators
    153  *   void frob_all ( void ) {
    154  *	struct frob *frob;
    155  *
    156  *	for_each_table ( frob, FROBNICATORS ) {
    157  *         printf ( "Calling frobnicator \"%s\"\n", frob->name );
    158  *	   frob->frob ();
    159  *	}
    160  *   }
    161  *
    162  * @endcode
    163  *
    164  * See init.h and init.c for a real-life example.
    165  *
    166  */
    167 
    168 #ifdef DOXYGEN
    169 #define __attribute__( x )
    170 #endif
    171 
    172 /**
    173  * Declare a linker table
    174  *
    175  * @v type		Data type
    176  * @v name		Table name
    177  * @ret table		Linker table
    178  */
    179 #define __table( type, name ) ( type, name )
    180 
    181 /**
    182  * Get linker table data type
    183  *
    184  * @v table		Linker table
    185  * @ret type		Data type
    186  */
    187 #define __table_type( table ) __table_extract_type table
    188 #define __table_extract_type( type, name ) type
    189 
    190 /**
    191  * Get linker table name
    192  *
    193  * @v table		Linker table
    194  * @ret name		Table name
    195  */
    196 #define __table_name( table ) __table_extract_name table
    197 #define __table_extract_name( type, name ) name
    198 
    199 /**
    200  * Get linker table section name
    201  *
    202  * @v table		Linker table
    203  * @v idx		Sub-table index
    204  * @ret section		Section name
    205  */
    206 #define __table_section( table, idx ) \
    207 	".tbl." __table_name ( table ) "." __table_str ( idx )
    208 #define __table_str( x ) #x
    209 
    210 /**
    211  * Get linker table alignment
    212  *
    213  * @v table		Linker table
    214  * @ret align		Alignment
    215  */
    216 #define __table_alignment( table ) __alignof__ ( __table_type ( table ) )
    217 
    218 /**
    219  * Declare a linker table entry
    220  *
    221  * @v table		Linker table
    222  * @v idx		Sub-table index
    223  *
    224  * Example usage:
    225  *
    226  * @code
    227  *
    228  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
    229  *
    230  *   #define __frobnicator __table_entry ( FROBNICATORS, 01 )
    231  *
    232  *   struct frobnicator my_frob __frobnicator = {
    233  *      ...
    234  *   };
    235  *
    236  * @endcode
    237  */
    238 #define __table_entry( table, idx )					\
    239 	__attribute__ (( __section__ ( __table_section ( table, idx ) ),\
    240 			 __aligned__ ( __table_alignment ( table ) ) ))
    241 
    242 /**
    243  * Get start of linker table entries
    244  *
    245  * @v table		Linker table
    246  * @v idx		Sub-table index
    247  * @ret entries		Start of entries
    248  */
    249 #define __table_entries( table, idx ) ( {				\
    250 	static __table_type ( table ) __table_entries[0]		\
    251 		__table_entry ( table, idx ); 				\
    252 	__table_entries; } )
    253 
    254 /**
    255  * Get start of linker table
    256  *
    257  * @v table		Linker table
    258  * @ret start		Start of linker table
    259  *
    260  * Example usage:
    261  *
    262  * @code
    263  *
    264  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
    265  *
    266  *   struct frobnicator *frobs = table_start ( FROBNICATORS );
    267  *
    268  * @endcode
    269  */
    270 #define table_start( table ) __table_entries ( table, 00 )
    271 
    272 /**
    273  * Get end of linker table
    274  *
    275  * @v table		Linker table
    276  * @ret end		End of linker table
    277  *
    278  * Example usage:
    279  *
    280  * @code
    281  *
    282  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
    283  *
    284  *   struct frobnicator *frobs_end = table_end ( FROBNICATORS );
    285  *
    286  * @endcode
    287  */
    288 #define table_end( table ) __table_entries ( table, 99 )
    289 
    290 /**
    291  * Get number of entries in linker table
    292  *
    293  * @v table		Linker table
    294  * @ret num_entries	Number of entries in linker table
    295  *
    296  * Example usage:
    297  *
    298  * @code
    299  *
    300  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
    301  *
    302  *   unsigned int num_frobs = table_num_entries ( FROBNICATORS );
    303  *
    304  * @endcode
    305  *
    306  */
    307 #define table_num_entries( table )					\
    308 	( ( unsigned int ) ( table_end ( table ) -			\
    309 			     table_start ( table ) ) )
    310 
    311 /**
    312  * Iterate through all entries within a linker table
    313  *
    314  * @v pointer		Entry pointer
    315  * @v table		Linker table
    316  *
    317  * Example usage:
    318  *
    319  * @code
    320  *
    321  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
    322  *
    323  *   struct frobnicator *frob;
    324  *
    325  *   for_each_table_entry ( frob, FROBNICATORS ) {
    326  *     ...
    327  *   }
    328  *
    329  * @endcode
    330  *
    331  */
    332 #define for_each_table_entry( pointer, table )				\
    333 	for ( pointer = table_start ( table ) ;				\
    334 	      pointer < table_end ( table ) ;				\
    335 	      pointer++ )
    336 
    337 /**
    338  * Iterate through all entries within a linker table in reverse order
    339  *
    340  * @v pointer		Entry pointer
    341  * @v table		Linker table
    342  *
    343  * Example usage:
    344  *
    345  * @code
    346  *
    347  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
    348  *
    349  *   struct frobnicator *frob;
    350  *
    351  *   for_each_table_entry_reverse ( frob, FROBNICATORS ) {
    352  *     ...
    353  *   }
    354  *
    355  * @endcode
    356  *
    357  */
    358 #define for_each_table_entry_reverse( pointer, table )			\
    359 	for ( pointer = ( table_end ( table ) - 1 ) ;			\
    360 	      pointer >= table_start ( table ) ;			\
    361 	      pointer-- )
    362 
    363 /******************************************************************************
    364  *
    365  * Intel's C compiler chokes on several of the constructs used in this
    366  * file.  The workarounds are ugly, so we use them only for an icc
    367  * build.
    368  *
    369  */
    370 #define ICC_ALIGN_HACK_FACTOR 128
    371 #ifdef __ICC
    372 
    373 /*
    374  * icc miscompiles zero-length arrays by inserting padding to a length
    375  * of two array elements.  We therefore have to generate the
    376  * __table_entries() symbols by hand in asm.
    377  *
    378  */
    379 #undef __table_entries
    380 #define __table_entries( table, idx ) ( {				\
    381 	extern __table_type ( table )					\
    382 		__table_temp_sym ( idx, __LINE__ ) []			\
    383 		__table_entry ( table, idx ) 				\
    384 		asm ( __table_entries_sym ( table, idx ) );		\
    385 	__asm__ ( ".ifndef %c0\n\t"					\
    386 		  ".section " __table_section ( table, idx ) "\n\t"	\
    387 		  ".align %c1\n\t"					\
    388 	          "\n%c0:\n\t"						\
    389 		  ".previous\n\t" 					\
    390 		  ".endif\n\t"						\
    391 		  : : "i" ( __table_temp_sym ( idx, __LINE__ ) ),	\
    392 		      "i" ( __table_alignment ( table ) ) );		\
    393 	__table_temp_sym ( idx, __LINE__ ); } )
    394 #define __table_entries_sym( table, idx )				\
    395 	"__tbl_" __table_name ( table ) "_" #idx
    396 #define __table_temp_sym( a, b )					\
    397 	___table_temp_sym( __table_, a, _, b )
    398 #define ___table_temp_sym( a, b, c, d ) a ## b ## c ## d
    399 
    400 /*
    401  * icc ignores __attribute__ (( aligned (x) )) when it is used to
    402  * decrease the compiler's default choice of alignment (which may be
    403  * higher than the alignment actually required by the structure).  We
    404  * work around this by forcing the alignment to a large multiple of
    405  * the required value (so that we are never attempting to decrease the
    406  * default alignment) and then postprocessing the object file to
    407  * reduce the alignment back down to the "real" value.
    408  *
    409  */
    410 #undef __table_alignment
    411 #define __table_alignment( table ) \
    412 	( ICC_ALIGN_HACK_FACTOR * __alignof__ ( __table_type ( table ) ) )
    413 
    414 /*
    415  * Because of the alignment hack, we must ensure that the compiler
    416  * never tries to place multiple objects within the same section,
    417  * otherwise the assembler will insert padding to the (incorrect)
    418  * alignment boundary.  Do this by appending the line number to table
    419  * section names.
    420  *
    421  * Note that we don't need to worry about padding between array
    422  * elements, since the alignment is declared on the variable (i.e. the
    423  * whole array) rather than on the type (i.e. on all individual array
    424  * elements).
    425  */
    426 #undef __table_section
    427 #define __table_section( table, idx ) \
    428 	".tbl." __table_name ( table ) "." __table_str ( idx ) \
    429 	"." __table_xstr ( __LINE__ )
    430 #define __table_xstr( x ) __table_str ( x )
    431 
    432 #endif /* __ICC */
    433 
    434 #endif /* _GPXE_TABLES_H */
    435