You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tables.h 12KB

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