00001 #ifndef _GPXE_TABLES_H 00002 #define _GPXE_TABLES_H 00003 00004 FILE_LICENCE ( GPL2_OR_LATER ); 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 __table_entries; } ) 00253 00254 /** 00255 * Get start of linker table 00256 * 00257 * @v table Linker table 00258 * @ret start Start of linker table 00259 * 00260 * Example usage: 00261 * 00262 * @code 00263 * 00264 * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) 00265 * 00266 * struct frobnicator *frobs = table_start ( FROBNICATORS ); 00267 * 00268 * @endcode 00269 */ 00270 #define table_start( table ) __table_entries ( table, 00 ) 00271 00272 /** 00273 * Get end of linker table 00274 * 00275 * @v table Linker table 00276 * @ret end End of linker table 00277 * 00278 * Example usage: 00279 * 00280 * @code 00281 * 00282 * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) 00283 * 00284 * struct frobnicator *frobs_end = table_end ( FROBNICATORS ); 00285 * 00286 * @endcode 00287 */ 00288 #define table_end( table ) __table_entries ( table, 99 ) 00289 00290 /** 00291 * Get number of entries in linker table 00292 * 00293 * @v table Linker table 00294 * @ret num_entries Number of entries in linker table 00295 * 00296 * Example usage: 00297 * 00298 * @code 00299 * 00300 * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) 00301 * 00302 * unsigned int num_frobs = table_num_entries ( FROBNICATORS ); 00303 * 00304 * @endcode 00305 * 00306 */ 00307 #define table_num_entries( table ) \ 00308 ( ( unsigned int ) ( table_end ( table ) - \ 00309 table_start ( table ) ) ) 00310 00311 /** 00312 * Iterate through all entries within a linker table 00313 * 00314 * @v pointer Entry pointer 00315 * @v table Linker table 00316 * 00317 * Example usage: 00318 * 00319 * @code 00320 * 00321 * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) 00322 * 00323 * struct frobnicator *frob; 00324 * 00325 * for_each_table_entry ( frob, FROBNICATORS ) { 00326 * ... 00327 * } 00328 * 00329 * @endcode 00330 * 00331 */ 00332 #define for_each_table_entry( pointer, table ) \ 00333 for ( pointer = table_start ( table ) ; \ 00334 pointer < table_end ( table ) ; \ 00335 pointer++ ) 00336 00337 /** 00338 * Iterate through all entries within a linker table in reverse order 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_reverse ( frob, FROBNICATORS ) { 00352 * ... 00353 * } 00354 * 00355 * @endcode 00356 * 00357 */ 00358 #define for_each_table_entry_reverse( pointer, table ) \ 00359 for ( pointer = ( table_end ( table ) - 1 ) ; \ 00360 pointer >= table_start ( table ) ; \ 00361 pointer-- ) 00362 00363 /****************************************************************************** 00364 * 00365 * Intel's C compiler chokes on several of the constructs used in this 00366 * file. The workarounds are ugly, so we use them only for an icc 00367 * build. 00368 * 00369 */ 00370 #define ICC_ALIGN_HACK_FACTOR 128 00371 #ifdef __ICC 00372 00373 /* 00374 * icc miscompiles zero-length arrays by inserting padding to a length 00375 * of two array elements. We therefore have to generate the 00376 * __table_entries() symbols by hand in asm. 00377 * 00378 */ 00379 #undef __table_entries 00380 #define __table_entries( table, idx ) ( { \ 00381 extern __table_type ( table ) \ 00382 __table_temp_sym ( idx, __LINE__ ) [] \ 00383 __table_entry ( table, idx ) \ 00384 asm ( __table_entries_sym ( table, idx ) ); \ 00385 __asm__ ( ".ifndef %c0\n\t" \ 00386 ".section " __table_section ( table, idx ) "\n\t" \ 00387 ".align %c1\n\t" \ 00388 "\n%c0:\n\t" \ 00389 ".previous\n\t" \ 00390 ".endif\n\t" \ 00391 : : "i" ( __table_temp_sym ( idx, __LINE__ ) ), \ 00392 "i" ( __table_alignment ( table ) ) ); \ 00393 __table_temp_sym ( idx, __LINE__ ); } ) 00394 #define __table_entries_sym( table, idx ) \ 00395 "__tbl_" __table_name ( table ) "_" #idx 00396 #define __table_temp_sym( a, b ) \ 00397 ___table_temp_sym( __table_, a, _, b ) 00398 #define ___table_temp_sym( a, b, c, d ) a ## b ## c ## d 00399 00400 /* 00401 * icc ignores __attribute__ (( aligned (x) )) when it is used to 00402 * decrease the compiler's default choice of alignment (which may be 00403 * higher than the alignment actually required by the structure). We 00404 * work around this by forcing the alignment to a large multiple of 00405 * the required value (so that we are never attempting to decrease the 00406 * default alignment) and then postprocessing the object file to 00407 * reduce the alignment back down to the "real" value. 00408 * 00409 */ 00410 #undef __table_alignment 00411 #define __table_alignment( table ) \ 00412 ( ICC_ALIGN_HACK_FACTOR * __alignof__ ( __table_type ( table ) ) ) 00413 00414 /* 00415 * Because of the alignment hack, we must ensure that the compiler 00416 * never tries to place multiple objects within the same section, 00417 * otherwise the assembler will insert padding to the (incorrect) 00418 * alignment boundary. Do this by appending the line number to table 00419 * section names. 00420 * 00421 * Note that we don't need to worry about padding between array 00422 * elements, since the alignment is declared on the variable (i.e. the 00423 * whole array) rather than on the type (i.e. on all individual array 00424 * elements). 00425 */ 00426 #undef __table_section 00427 #define __table_section( table, idx ) \ 00428 ".tbl." __table_name ( table ) "." __table_str ( idx ) \ 00429 "." __table_xstr ( __LINE__ ) 00430 #define __table_xstr( x ) __table_str ( x ) 00431 00432 #endif /* __ICC */ 00433 00434 #endif /* _GPXE_TABLES_H */
1.5.7.1