iPXE
tables.h
Go to the documentation of this file.
00001 #ifndef _IPXE_TABLES_H
00002 #define _IPXE_TABLES_H
00003 
00004 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00005 
00006 /** @page ifdef_harmful #ifdef considered harmful
00007  *
00008  * Overuse of @c #ifdef has long been a problem in Etherboot.
00009  * Etherboot provides a rich array of features, but all these features
00010  * take up valuable space in a ROM image.  The traditional solution to
00011  * this problem has been for each feature to have its own @c #ifdef
00012  * option, allowing the feature to be compiled in only if desired.
00013  *
00014  * The problem with this is that it becomes impossible to compile, let
00015  * alone test, all possible versions of Etherboot.  Code that is not
00016  * typically used tends to suffer from bit-rot over time.  It becomes
00017  * extremely difficult to predict which combinations of compile-time
00018  * options will result in code that can even compile and link
00019  * correctly.
00020  *
00021  * To solve this problem, we have adopted a new approach from
00022  * Etherboot 5.5 onwards.  @c #ifdef is now "considered harmful", and
00023  * its use should be minimised.  Separate features should be
00024  * implemented in separate @c .c files, and should \b always be
00025  * compiled (i.e. they should \b not be guarded with a @c #ifdef @c
00026  * MY_PET_FEATURE statement).  By making (almost) all code always
00027  * compile, we avoid the problem of bit-rot in rarely-used code.
00028  *
00029  * The file config.h, in combination with the @c make command line,
00030  * specifies the objects that will be included in any particular build
00031  * of Etherboot.  For example, suppose that config.h includes the line
00032  *
00033  * @code
00034  *
00035  *   #define CONSOLE_SERIAL
00036  *   #define DOWNLOAD_PROTO_TFTP
00037  *
00038  * @endcode
00039  *
00040  * When a particular Etherboot image (e.g. @c bin/rtl8139.zdsk) is
00041  * built, the options specified in config.h are used to drag in the
00042  * relevant objects at link-time.  For the above example, serial.o and
00043  * tftp.o would be linked in.
00044  *
00045  * There remains one problem to solve: how do these objects get used?
00046  * Traditionally, we had code such as
00047  *
00048  * @code
00049  *
00050  *    #ifdef CONSOLE_SERIAL
00051  *      serial_init();
00052  *    #endif
00053  *
00054  * @endcode
00055  *
00056  * in main.c, but this reintroduces @c #ifdef and so is a Bad Idea.
00057  * We cannot simply remove the @c #ifdef and make it
00058  *
00059  * @code
00060  *
00061  *   serial_init();
00062  *
00063  * @endcode
00064  *
00065  * because then serial.o would end up always being linked in.
00066  *
00067  * The solution is to use @link tables.h linker tables @endlink.
00068  *
00069  */
00070 
00071 /** @file
00072  *
00073  * Linker tables
00074  *
00075  * Read @ref ifdef_harmful first for some background on the motivation
00076  * for using linker tables.
00077  *
00078  * This file provides macros for dealing with linker-generated tables
00079  * of fixed-size symbols.  We make fairly extensive use of these in
00080  * order to avoid @c #ifdef spaghetti and/or linker symbol pollution.
00081  * For example, instead of having code such as
00082  *
00083  * @code
00084  *
00085  *    #ifdef CONSOLE_SERIAL
00086  *      serial_init();
00087  *    #endif
00088  *
00089  * @endcode
00090  *
00091  * we make serial.c generate an entry in the initialisation function
00092  * table, and then have a function call_init_fns() that simply calls
00093  * all functions present in this table.  If and only if serial.o gets
00094  * linked in, then its initialisation function will be called.  We
00095  * avoid linker symbol pollution (i.e. always dragging in serial.o
00096  * just because of a call to serial_init()) and we also avoid @c
00097  * #ifdef spaghetti (having to conditionalise every reference to
00098  * functions in serial.c).
00099  *
00100  * The linker script takes care of assembling the tables for us.  All
00101  * our table sections have names of the format @c .tbl.NAME.NN where
00102  * @c NAME designates the data structure stored in the table (e.g. @c
00103  * init_fns) and @c NN is a two-digit decimal number used to impose an
00104  * ordering upon the tables if required.  @c NN=00 is reserved for the
00105  * symbol indicating "table start", and @c NN=99 is reserved for the
00106  * symbol indicating "table end".
00107  *
00108  * As an example, suppose that we want to create a "frobnicator"
00109  * feature framework, and allow for several independent modules to
00110  * provide frobnicating services.  Then we would create a frob.h
00111  * header file containing e.g.
00112  *
00113  * @code
00114  *
00115  *   struct frobnicator {
00116  *      const char *name;               // Name of the frobnicator
00117  *      void ( *frob ) ( void );        // The frobnicating function itself
00118  *   };
00119  *
00120  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
00121  *
00122  *   #define __frobnicator __table_entry ( FROBNICATORS, 01 )
00123  *
00124  * @endcode
00125  *
00126  * Any module providing frobnicating services would look something
00127  * like
00128  *
00129  * @code
00130  *
00131  *   #include "frob.h"
00132  *
00133  *   static void my_frob ( void ) {
00134  *      // Do my frobnicating
00135  *      ...
00136  *   }
00137  *
00138  *   struct frob my_frobnicator __frobnicator = {
00139  *      .name = "my_frob",
00140  *      .frob = my_frob,
00141  *   };
00142  *
00143  * @endcode
00144  *
00145  * The central frobnicator code (frob.c) would use the frobnicating
00146  * modules as follows
00147  *
00148  * @code
00149  *
00150  *   #include "frob.h"
00151  *
00152  *   // Call all linked-in frobnicators
00153  *   void frob_all ( void ) {
00154  *      struct frob *frob;
00155  *
00156  *      for_each_table ( frob, FROBNICATORS ) {
00157  *         printf ( "Calling frobnicator \"%s\"\n", frob->name );
00158  *         frob->frob ();
00159  *      }
00160  *   }
00161  *
00162  * @endcode
00163  *
00164  * See init.h and init.c for a real-life example.
00165  *
00166  */
00167 
00168 #ifdef DOXYGEN
00169 #define __attribute__( x )
00170 #endif
00171 
00172 /**
00173  * Declare a linker table
00174  *
00175  * @v type              Data type
00176  * @v name              Table name
00177  * @ret table           Linker table
00178  */
00179 #define __table( type, name ) ( type, name )
00180 
00181 /**
00182  * Get linker table data type
00183  *
00184  * @v table             Linker table
00185  * @ret type            Data type
00186  */
00187 #define __table_type( table ) __table_extract_type table
00188 #define __table_extract_type( type, name ) type
00189 
00190 /**
00191  * Get linker table name
00192  *
00193  * @v table             Linker table
00194  * @ret name            Table name
00195  */
00196 #define __table_name( table ) __table_extract_name table
00197 #define __table_extract_name( type, name ) name
00198 
00199 /**
00200  * Get linker table section name
00201  *
00202  * @v table             Linker table
00203  * @v idx               Sub-table index
00204  * @ret section         Section name
00205  */
00206 #define __table_section( table, idx ) \
00207         ".tbl." __table_name ( table ) "." __table_str ( idx )
00208 #define __table_str( x ) #x
00209 
00210 /**
00211  * Get linker table alignment
00212  *
00213  * @v table             Linker table
00214  * @ret align           Alignment
00215  */
00216 #define __table_alignment( table ) __alignof__ ( __table_type ( table ) )
00217 
00218 /**
00219  * Declare a linker table entry
00220  *
00221  * @v table             Linker table
00222  * @v idx               Sub-table index
00223  *
00224  * Example usage:
00225  *
00226  * @code
00227  *
00228  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
00229  *
00230  *   #define __frobnicator __table_entry ( FROBNICATORS, 01 )
00231  *
00232  *   struct frobnicator my_frob __frobnicator = {
00233  *      ...
00234  *   };
00235  *
00236  * @endcode
00237  */
00238 #define __table_entry( table, idx )                                     \
00239         __attribute__ (( __section__ ( __table_section ( table, idx ) ),\
00240                          __aligned__ ( __table_alignment ( table ) ) ))
00241 
00242 /**
00243  * Get start of linker table entries
00244  *
00245  * @v table             Linker table
00246  * @v idx               Sub-table index
00247  * @ret entries         Start of entries
00248  */
00249 #define __table_entries( table, idx ) ( {                               \
00250         static __table_type ( table ) __table_entries[0]                \
00251                 __table_entry ( table, idx )                            \
00252                 __attribute__ (( unused ));                             \
00253         __table_entries; } )
00254 
00255 /**
00256  * Get start of linker table
00257  *
00258  * @v table             Linker table
00259  * @ret start           Start of linker table
00260  *
00261  * Example usage:
00262  *
00263  * @code
00264  *
00265  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
00266  *
00267  *   struct frobnicator *frobs = table_start ( FROBNICATORS );
00268  *
00269  * @endcode
00270  */
00271 #define table_start( table ) __table_entries ( table, 00 )
00272 
00273 /**
00274  * Get end of linker table
00275  *
00276  * @v table             Linker table
00277  * @ret end             End of linker table
00278  *
00279  * Example usage:
00280  *
00281  * @code
00282  *
00283  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
00284  *
00285  *   struct frobnicator *frobs_end = table_end ( FROBNICATORS );
00286  *
00287  * @endcode
00288  */
00289 #define table_end( table ) __table_entries ( table, 99 )
00290 
00291 /**
00292  * Get number of entries in linker table
00293  *
00294  * @v table             Linker table
00295  * @ret num_entries     Number of entries in linker table
00296  *
00297  * Example usage:
00298  *
00299  * @code
00300  *
00301  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
00302  *
00303  *   unsigned int num_frobs = table_num_entries ( FROBNICATORS );
00304  *
00305  * @endcode
00306  *
00307  */
00308 #define table_num_entries( table )                                      \
00309         ( ( unsigned int ) ( table_end ( table ) -                      \
00310                              table_start ( table ) ) )
00311 
00312 /**
00313  * Get index of entry within linker table
00314  *
00315  * @v table             Linker table
00316  * @v entry             Table entry
00317  *
00318  * Example usage:
00319  *
00320  * @code
00321  *
00322  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
00323  *
00324  *   #define __frobnicator __table_entry ( FROBNICATORS, 01 )
00325  *
00326  *   struct frobnicator my_frob __frobnicator = {
00327  *      ...
00328  *   };
00329  *
00330  *   unsigned int my_frob_idx = table_index ( FROBNICATORS, &my_frob );
00331  *
00332  * @endcode
00333  */
00334 #define table_index( table, entry )                                     \
00335         ( ( unsigned int ) ( (entry) - table_start ( table ) ) )
00336 
00337 /**
00338  * Iterate through all entries within a linker table
00339  *
00340  * @v pointer           Entry pointer
00341  * @v table             Linker table
00342  *
00343  * Example usage:
00344  *
00345  * @code
00346  *
00347  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
00348  *
00349  *   struct frobnicator *frob;
00350  *
00351  *   for_each_table_entry ( frob, FROBNICATORS ) {
00352  *     ...
00353  *   }
00354  *
00355  * @endcode
00356  *
00357  */
00358 #define for_each_table_entry( pointer, table )                          \
00359         for ( pointer = table_start ( table ) ;                         \
00360               pointer < table_end ( table ) ;                           \
00361               pointer++ )
00362 
00363 /**
00364  * Iterate through all remaining entries within a linker table
00365  *
00366  * @v pointer           Entry pointer, preset to most recent entry
00367  * @v table             Linker table
00368  *
00369  * Example usage:
00370  *
00371  * @code
00372  *
00373  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
00374  *   #define __frobnicator __table_entry ( FROBNICATORS, 01 )
00375  *
00376  *   struct frob my_frobnicator __frobnicator;
00377  *   struct frobnicator *frob;
00378  *
00379  *   frob = &my_frobnicator;
00380  *   for_each_table_entry_continue ( frob, FROBNICATORS ) {
00381  *     ...
00382  *   }
00383  *
00384  * @endcode
00385  *
00386  */
00387 #define for_each_table_entry_continue( pointer, table )                 \
00388         for ( pointer++ ;                                               \
00389               pointer < table_end ( table ) ;                           \
00390               pointer++ )
00391 
00392 /**
00393  * Iterate through all entries within a linker table in reverse order
00394  *
00395  * @v pointer           Entry pointer
00396  * @v table             Linker table
00397  *
00398  * Example usage:
00399  *
00400  * @code
00401  *
00402  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
00403  *
00404  *   struct frobnicator *frob;
00405  *
00406  *   for_each_table_entry_reverse ( frob, FROBNICATORS ) {
00407  *     ...
00408  *   }
00409  *
00410  * @endcode
00411  *
00412  */
00413 #define for_each_table_entry_reverse( pointer, table )                  \
00414         for ( pointer = ( table_end ( table ) - 1 ) ;                   \
00415               pointer >= table_start ( table ) ;                        \
00416               pointer-- )
00417 
00418 /**
00419  * Iterate through all remaining entries within a linker table in reverse order
00420  *
00421  * @v pointer           Entry pointer, preset to most recent entry
00422  * @v table             Linker table
00423  *
00424  * Example usage:
00425  *
00426  * @code
00427  *
00428  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
00429  *   #define __frobnicator __table_entry ( FROBNICATORS, 01 )
00430  *
00431  *   struct frob my_frobnicator __frobnicator;
00432  *   struct frobnicator *frob;
00433  *
00434  *   frob = &my_frobnicator;
00435  *   for_each_table_entry_continue_reverse ( frob, FROBNICATORS ) {
00436  *     ...
00437  *   }
00438  *
00439  * @endcode
00440  *
00441  */
00442 #define for_each_table_entry_continue_reverse( pointer, table )         \
00443         for ( pointer-- ;                                               \
00444               pointer >= table_start ( table ) ;                        \
00445               pointer-- )
00446 
00447 /******************************************************************************
00448  *
00449  * Intel's C compiler chokes on several of the constructs used in this
00450  * file.  The workarounds are ugly, so we use them only for an icc
00451  * build.
00452  *
00453  */
00454 #define ICC_ALIGN_HACK_FACTOR 128
00455 #ifdef __ICC
00456 
00457 /*
00458  * icc miscompiles zero-length arrays by inserting padding to a length
00459  * of two array elements.  We therefore have to generate the
00460  * __table_entries() symbols by hand in asm.
00461  *
00462  */
00463 #undef __table_entries
00464 #define __table_entries( table, idx ) ( {                               \
00465         extern __table_type ( table )                                   \
00466                 __table_temp_sym ( idx, __LINE__ ) []                   \
00467                 __table_entry ( table, idx )                            \
00468                 asm ( __table_entries_sym ( table, idx ) );             \
00469         __asm__ ( ".ifndef %c0\n\t"                                     \
00470                   ".section " __table_section ( table, idx ) "\n\t"     \
00471                   ".align %c1\n\t"                                      \
00472                   "\n%c0:\n\t"                                          \
00473                   ".previous\n\t"                                       \
00474                   ".endif\n\t"                                          \
00475                   : : "i" ( __table_temp_sym ( idx, __LINE__ ) ),       \
00476                       "i" ( __table_alignment ( table ) ) );            \
00477         __table_temp_sym ( idx, __LINE__ ); } )
00478 #define __table_entries_sym( table, idx )                               \
00479         "__tbl_" __table_name ( table ) "_" #idx
00480 #define __table_temp_sym( a, b )                                        \
00481         ___table_temp_sym( __table_, a, _, b )
00482 #define ___table_temp_sym( a, b, c, d ) a ## b ## c ## d
00483 
00484 /*
00485  * icc ignores __attribute__ (( aligned (x) )) when it is used to
00486  * decrease the compiler's default choice of alignment (which may be
00487  * higher than the alignment actually required by the structure).  We
00488  * work around this by forcing the alignment to a large multiple of
00489  * the required value (so that we are never attempting to decrease the
00490  * default alignment) and then postprocessing the object file to
00491  * reduce the alignment back down to the "real" value.
00492  *
00493  */
00494 #undef __table_alignment
00495 #define __table_alignment( table ) \
00496         ( ICC_ALIGN_HACK_FACTOR * __alignof__ ( __table_type ( table ) ) )
00497 
00498 /*
00499  * Because of the alignment hack, we must ensure that the compiler
00500  * never tries to place multiple objects within the same section,
00501  * otherwise the assembler will insert padding to the (incorrect)
00502  * alignment boundary.  Do this by appending the line number to table
00503  * section names.
00504  *
00505  * Note that we don't need to worry about padding between array
00506  * elements, since the alignment is declared on the variable (i.e. the
00507  * whole array) rather than on the type (i.e. on all individual array
00508  * elements).
00509  */
00510 #undef __table_section
00511 #define __table_section( table, idx ) \
00512         ".tbl." __table_name ( table ) "." __table_str ( idx ) \
00513         "." __table_xstr ( __LINE__ )
00514 #define __table_xstr( x ) __table_str ( x )
00515 
00516 #endif /* __ICC */
00517 
00518 #endif /* _IPXE_TABLES_H */