X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=qemu%2Froms%2Fipxe%2Fsrc%2Finclude%2Fipxe%2Ftables.h;fp=qemu%2Froms%2Fipxe%2Fsrc%2Finclude%2Fipxe%2Ftables.h;h=e35ce822016e7b22ab6fc0db2be12668e09992c1;hb=e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb;hp=0000000000000000000000000000000000000000;hpb=9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00;p=kvmfornfv.git diff --git a/qemu/roms/ipxe/src/include/ipxe/tables.h b/qemu/roms/ipxe/src/include/ipxe/tables.h new file mode 100644 index 000000000..e35ce8220 --- /dev/null +++ b/qemu/roms/ipxe/src/include/ipxe/tables.h @@ -0,0 +1,518 @@ +#ifndef _IPXE_TABLES_H +#define _IPXE_TABLES_H + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @page ifdef_harmful #ifdef considered harmful + * + * Overuse of @c #ifdef has long been a problem in Etherboot. + * Etherboot provides a rich array of features, but all these features + * take up valuable space in a ROM image. The traditional solution to + * this problem has been for each feature to have its own @c #ifdef + * option, allowing the feature to be compiled in only if desired. + * + * The problem with this is that it becomes impossible to compile, let + * alone test, all possible versions of Etherboot. Code that is not + * typically used tends to suffer from bit-rot over time. It becomes + * extremely difficult to predict which combinations of compile-time + * options will result in code that can even compile and link + * correctly. + * + * To solve this problem, we have adopted a new approach from + * Etherboot 5.5 onwards. @c #ifdef is now "considered harmful", and + * its use should be minimised. Separate features should be + * implemented in separate @c .c files, and should \b always be + * compiled (i.e. they should \b not be guarded with a @c #ifdef @c + * MY_PET_FEATURE statement). By making (almost) all code always + * compile, we avoid the problem of bit-rot in rarely-used code. + * + * The file config.h, in combination with the @c make command line, + * specifies the objects that will be included in any particular build + * of Etherboot. For example, suppose that config.h includes the line + * + * @code + * + * #define CONSOLE_SERIAL + * #define DOWNLOAD_PROTO_TFTP + * + * @endcode + * + * When a particular Etherboot image (e.g. @c bin/rtl8139.zdsk) is + * built, the options specified in config.h are used to drag in the + * relevant objects at link-time. For the above example, serial.o and + * tftp.o would be linked in. + * + * There remains one problem to solve: how do these objects get used? + * Traditionally, we had code such as + * + * @code + * + * #ifdef CONSOLE_SERIAL + * serial_init(); + * #endif + * + * @endcode + * + * in main.c, but this reintroduces @c #ifdef and so is a Bad Idea. + * We cannot simply remove the @c #ifdef and make it + * + * @code + * + * serial_init(); + * + * @endcode + * + * because then serial.o would end up always being linked in. + * + * The solution is to use @link tables.h linker tables @endlink. + * + */ + +/** @file + * + * Linker tables + * + * Read @ref ifdef_harmful first for some background on the motivation + * for using linker tables. + * + * This file provides macros for dealing with linker-generated tables + * of fixed-size symbols. We make fairly extensive use of these in + * order to avoid @c #ifdef spaghetti and/or linker symbol pollution. + * For example, instead of having code such as + * + * @code + * + * #ifdef CONSOLE_SERIAL + * serial_init(); + * #endif + * + * @endcode + * + * we make serial.c generate an entry in the initialisation function + * table, and then have a function call_init_fns() that simply calls + * all functions present in this table. If and only if serial.o gets + * linked in, then its initialisation function will be called. We + * avoid linker symbol pollution (i.e. always dragging in serial.o + * just because of a call to serial_init()) and we also avoid @c + * #ifdef spaghetti (having to conditionalise every reference to + * functions in serial.c). + * + * The linker script takes care of assembling the tables for us. All + * our table sections have names of the format @c .tbl.NAME.NN where + * @c NAME designates the data structure stored in the table (e.g. @c + * init_fns) and @c NN is a two-digit decimal number used to impose an + * ordering upon the tables if required. @c NN=00 is reserved for the + * symbol indicating "table start", and @c NN=99 is reserved for the + * symbol indicating "table end". + * + * As an example, suppose that we want to create a "frobnicator" + * feature framework, and allow for several independent modules to + * provide frobnicating services. Then we would create a frob.h + * header file containing e.g. + * + * @code + * + * struct frobnicator { + * const char *name; // Name of the frobnicator + * void ( *frob ) ( void ); // The frobnicating function itself + * }; + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * #define __frobnicator __table_entry ( FROBNICATORS, 01 ) + * + * @endcode + * + * Any module providing frobnicating services would look something + * like + * + * @code + * + * #include "frob.h" + * + * static void my_frob ( void ) { + * // Do my frobnicating + * ... + * } + * + * struct frob my_frobnicator __frobnicator = { + * .name = "my_frob", + * .frob = my_frob, + * }; + * + * @endcode + * + * The central frobnicator code (frob.c) would use the frobnicating + * modules as follows + * + * @code + * + * #include "frob.h" + * + * // Call all linked-in frobnicators + * void frob_all ( void ) { + * struct frob *frob; + * + * for_each_table ( frob, FROBNICATORS ) { + * printf ( "Calling frobnicator \"%s\"\n", frob->name ); + * frob->frob (); + * } + * } + * + * @endcode + * + * See init.h and init.c for a real-life example. + * + */ + +#ifdef DOXYGEN +#define __attribute__( x ) +#endif + +/** + * Declare a linker table + * + * @v type Data type + * @v name Table name + * @ret table Linker table + */ +#define __table( type, name ) ( type, name ) + +/** + * Get linker table data type + * + * @v table Linker table + * @ret type Data type + */ +#define __table_type( table ) __table_extract_type table +#define __table_extract_type( type, name ) type + +/** + * Get linker table name + * + * @v table Linker table + * @ret name Table name + */ +#define __table_name( table ) __table_extract_name table +#define __table_extract_name( type, name ) name + +/** + * Get linker table section name + * + * @v table Linker table + * @v idx Sub-table index + * @ret section Section name + */ +#define __table_section( table, idx ) \ + ".tbl." __table_name ( table ) "." __table_str ( idx ) +#define __table_str( x ) #x + +/** + * Get linker table alignment + * + * @v table Linker table + * @ret align Alignment + */ +#define __table_alignment( table ) __alignof__ ( __table_type ( table ) ) + +/** + * Declare a linker table entry + * + * @v table Linker table + * @v idx Sub-table index + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * #define __frobnicator __table_entry ( FROBNICATORS, 01 ) + * + * struct frobnicator my_frob __frobnicator = { + * ... + * }; + * + * @endcode + */ +#define __table_entry( table, idx ) \ + __attribute__ (( __section__ ( __table_section ( table, idx ) ),\ + __aligned__ ( __table_alignment ( table ) ) )) + +/** + * Get start of linker table entries + * + * @v table Linker table + * @v idx Sub-table index + * @ret entries Start of entries + */ +#define __table_entries( table, idx ) ( { \ + static __table_type ( table ) __table_entries[0] \ + __table_entry ( table, idx ) \ + __attribute__ (( unused )); \ + __table_entries; } ) + +/** + * Get start of linker table + * + * @v table Linker table + * @ret start Start of linker table + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * struct frobnicator *frobs = table_start ( FROBNICATORS ); + * + * @endcode + */ +#define table_start( table ) __table_entries ( table, 00 ) + +/** + * Get end of linker table + * + * @v table Linker table + * @ret end End of linker table + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * struct frobnicator *frobs_end = table_end ( FROBNICATORS ); + * + * @endcode + */ +#define table_end( table ) __table_entries ( table, 99 ) + +/** + * Get number of entries in linker table + * + * @v table Linker table + * @ret num_entries Number of entries in linker table + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * unsigned int num_frobs = table_num_entries ( FROBNICATORS ); + * + * @endcode + * + */ +#define table_num_entries( table ) \ + ( ( unsigned int ) ( table_end ( table ) - \ + table_start ( table ) ) ) + +/** + * Get index of entry within linker table + * + * @v table Linker table + * @v entry Table entry + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * #define __frobnicator __table_entry ( FROBNICATORS, 01 ) + * + * struct frobnicator my_frob __frobnicator = { + * ... + * }; + * + * unsigned int my_frob_idx = table_index ( FROBNICATORS, &my_frob ); + * + * @endcode + */ +#define table_index( table, entry ) \ + ( ( unsigned int ) ( (entry) - table_start ( table ) ) ) + +/** + * Iterate through all entries within a linker table + * + * @v pointer Entry pointer + * @v table Linker table + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * struct frobnicator *frob; + * + * for_each_table_entry ( frob, FROBNICATORS ) { + * ... + * } + * + * @endcode + * + */ +#define for_each_table_entry( pointer, table ) \ + for ( pointer = table_start ( table ) ; \ + pointer < table_end ( table ) ; \ + pointer++ ) + +/** + * Iterate through all remaining entries within a linker table + * + * @v pointer Entry pointer, preset to most recent entry + * @v table Linker table + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * #define __frobnicator __table_entry ( FROBNICATORS, 01 ) + * + * struct frob my_frobnicator __frobnicator; + * struct frobnicator *frob; + * + * frob = &my_frobnicator; + * for_each_table_entry_continue ( frob, FROBNICATORS ) { + * ... + * } + * + * @endcode + * + */ +#define for_each_table_entry_continue( pointer, table ) \ + for ( pointer++ ; \ + pointer < table_end ( table ) ; \ + pointer++ ) + +/** + * Iterate through all entries within a linker table in reverse order + * + * @v pointer Entry pointer + * @v table Linker table + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * struct frobnicator *frob; + * + * for_each_table_entry_reverse ( frob, FROBNICATORS ) { + * ... + * } + * + * @endcode + * + */ +#define for_each_table_entry_reverse( pointer, table ) \ + for ( pointer = ( table_end ( table ) - 1 ) ; \ + pointer >= table_start ( table ) ; \ + pointer-- ) + +/** + * Iterate through all remaining entries within a linker table in reverse order + * + * @v pointer Entry pointer, preset to most recent entry + * @v table Linker table + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * #define __frobnicator __table_entry ( FROBNICATORS, 01 ) + * + * struct frob my_frobnicator __frobnicator; + * struct frobnicator *frob; + * + * frob = &my_frobnicator; + * for_each_table_entry_continue_reverse ( frob, FROBNICATORS ) { + * ... + * } + * + * @endcode + * + */ +#define for_each_table_entry_continue_reverse( pointer, table ) \ + for ( pointer-- ; \ + pointer >= table_start ( table ) ; \ + pointer-- ) + +/****************************************************************************** + * + * Intel's C compiler chokes on several of the constructs used in this + * file. The workarounds are ugly, so we use them only for an icc + * build. + * + */ +#define ICC_ALIGN_HACK_FACTOR 128 +#ifdef __ICC + +/* + * icc miscompiles zero-length arrays by inserting padding to a length + * of two array elements. We therefore have to generate the + * __table_entries() symbols by hand in asm. + * + */ +#undef __table_entries +#define __table_entries( table, idx ) ( { \ + extern __table_type ( table ) \ + __table_temp_sym ( idx, __LINE__ ) [] \ + __table_entry ( table, idx ) \ + asm ( __table_entries_sym ( table, idx ) ); \ + __asm__ ( ".ifndef %c0\n\t" \ + ".section " __table_section ( table, idx ) "\n\t" \ + ".align %c1\n\t" \ + "\n%c0:\n\t" \ + ".previous\n\t" \ + ".endif\n\t" \ + : : "i" ( __table_temp_sym ( idx, __LINE__ ) ), \ + "i" ( __table_alignment ( table ) ) ); \ + __table_temp_sym ( idx, __LINE__ ); } ) +#define __table_entries_sym( table, idx ) \ + "__tbl_" __table_name ( table ) "_" #idx +#define __table_temp_sym( a, b ) \ + ___table_temp_sym( __table_, a, _, b ) +#define ___table_temp_sym( a, b, c, d ) a ## b ## c ## d + +/* + * icc ignores __attribute__ (( aligned (x) )) when it is used to + * decrease the compiler's default choice of alignment (which may be + * higher than the alignment actually required by the structure). We + * work around this by forcing the alignment to a large multiple of + * the required value (so that we are never attempting to decrease the + * default alignment) and then postprocessing the object file to + * reduce the alignment back down to the "real" value. + * + */ +#undef __table_alignment +#define __table_alignment( table ) \ + ( ICC_ALIGN_HACK_FACTOR * __alignof__ ( __table_type ( table ) ) ) + +/* + * Because of the alignment hack, we must ensure that the compiler + * never tries to place multiple objects within the same section, + * otherwise the assembler will insert padding to the (incorrect) + * alignment boundary. Do this by appending the line number to table + * section names. + * + * Note that we don't need to worry about padding between array + * elements, since the alignment is declared on the variable (i.e. the + * whole array) rather than on the type (i.e. on all individual array + * elements). + */ +#undef __table_section +#define __table_section( table, idx ) \ + ".tbl." __table_name ( table ) "." __table_str ( idx ) \ + "." __table_xstr ( __LINE__ ) +#define __table_xstr( x ) __table_str ( x ) + +#endif /* __ICC */ + +#endif /* _IPXE_TABLES_H */