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 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. #ifndef _IPXE_TABLES_H
  2. #define _IPXE_TABLES_H
  3. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  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. __attribute__ (( unused )); \
  242. __table_entries; } )
  243. /**
  244. * Get start of linker table
  245. *
  246. * @v table Linker table
  247. * @ret start Start of linker table
  248. *
  249. * Example usage:
  250. *
  251. * @code
  252. *
  253. * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
  254. *
  255. * struct frobnicator *frobs = table_start ( FROBNICATORS );
  256. *
  257. * @endcode
  258. */
  259. #define table_start( table ) __table_entries ( table, 00 )
  260. /**
  261. * Get end of linker table
  262. *
  263. * @v table Linker table
  264. * @ret end End of linker table
  265. *
  266. * Example usage:
  267. *
  268. * @code
  269. *
  270. * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
  271. *
  272. * struct frobnicator *frobs_end = table_end ( FROBNICATORS );
  273. *
  274. * @endcode
  275. */
  276. #define table_end( table ) __table_entries ( table, 99 )
  277. /**
  278. * Get number of entries in linker table
  279. *
  280. * @v table Linker table
  281. * @ret num_entries Number of entries in linker table
  282. *
  283. * Example usage:
  284. *
  285. * @code
  286. *
  287. * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
  288. *
  289. * unsigned int num_frobs = table_num_entries ( FROBNICATORS );
  290. *
  291. * @endcode
  292. *
  293. */
  294. #define table_num_entries( table ) \
  295. ( ( unsigned int ) ( table_end ( table ) - \
  296. table_start ( table ) ) )
  297. /**
  298. * Get index of entry within linker table
  299. *
  300. * @v table Linker table
  301. * @v entry Table entry
  302. *
  303. * Example usage:
  304. *
  305. * @code
  306. *
  307. * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
  308. *
  309. * #define __frobnicator __table_entry ( FROBNICATORS, 01 )
  310. *
  311. * struct frobnicator my_frob __frobnicator = {
  312. * ...
  313. * };
  314. *
  315. * unsigned int my_frob_idx = table_index ( FROBNICATORS, &my_frob );
  316. *
  317. * @endcode
  318. */
  319. #define table_index( table, entry ) \
  320. ( ( unsigned int ) ( (entry) - table_start ( table ) ) )
  321. /**
  322. * Iterate through all entries within a linker table
  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 ( frob, FROBNICATORS ) {
  336. * ...
  337. * }
  338. *
  339. * @endcode
  340. *
  341. */
  342. #define for_each_table_entry( pointer, table ) \
  343. for ( pointer = table_start ( table ) ; \
  344. pointer < table_end ( table ) ; \
  345. pointer++ )
  346. /**
  347. * Iterate through all remaining entries within a linker table
  348. *
  349. * @v pointer Entry pointer, preset to most recent entry
  350. * @v table Linker table
  351. *
  352. * Example usage:
  353. *
  354. * @code
  355. *
  356. * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
  357. * #define __frobnicator __table_entry ( FROBNICATORS, 01 )
  358. *
  359. * struct frob my_frobnicator __frobnicator;
  360. * struct frobnicator *frob;
  361. *
  362. * frob = &my_frobnicator;
  363. * for_each_table_entry_continue ( frob, FROBNICATORS ) {
  364. * ...
  365. * }
  366. *
  367. * @endcode
  368. *
  369. */
  370. #define for_each_table_entry_continue( pointer, table ) \
  371. for ( pointer++ ; \
  372. pointer < table_end ( table ) ; \
  373. pointer++ )
  374. /**
  375. * Iterate through all entries within a linker table in reverse order
  376. *
  377. * @v pointer Entry pointer
  378. * @v table Linker table
  379. *
  380. * Example usage:
  381. *
  382. * @code
  383. *
  384. * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
  385. *
  386. * struct frobnicator *frob;
  387. *
  388. * for_each_table_entry_reverse ( frob, FROBNICATORS ) {
  389. * ...
  390. * }
  391. *
  392. * @endcode
  393. *
  394. */
  395. #define for_each_table_entry_reverse( pointer, table ) \
  396. for ( pointer = ( table_end ( table ) - 1 ) ; \
  397. pointer >= table_start ( table ) ; \
  398. pointer-- )
  399. /**
  400. * Iterate through all remaining entries within a linker table in reverse order
  401. *
  402. * @v pointer Entry pointer, preset to most recent entry
  403. * @v table Linker table
  404. *
  405. * Example usage:
  406. *
  407. * @code
  408. *
  409. * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
  410. * #define __frobnicator __table_entry ( FROBNICATORS, 01 )
  411. *
  412. * struct frob my_frobnicator __frobnicator;
  413. * struct frobnicator *frob;
  414. *
  415. * frob = &my_frobnicator;
  416. * for_each_table_entry_continue_reverse ( frob, FROBNICATORS ) {
  417. * ...
  418. * }
  419. *
  420. * @endcode
  421. *
  422. */
  423. #define for_each_table_entry_continue_reverse( pointer, table ) \
  424. for ( pointer-- ; \
  425. pointer >= table_start ( table ) ; \
  426. pointer-- )
  427. /******************************************************************************
  428. *
  429. * Intel's C compiler chokes on several of the constructs used in this
  430. * file. The workarounds are ugly, so we use them only for an icc
  431. * build.
  432. *
  433. */
  434. #define ICC_ALIGN_HACK_FACTOR 128
  435. #ifdef __ICC
  436. /*
  437. * icc miscompiles zero-length arrays by inserting padding to a length
  438. * of two array elements. We therefore have to generate the
  439. * __table_entries() symbols by hand in asm.
  440. *
  441. */
  442. #undef __table_entries
  443. #define __table_entries( table, idx ) ( { \
  444. extern __table_type ( table ) \
  445. __table_temp_sym ( idx, __LINE__ ) [] \
  446. __table_entry ( table, idx ) \
  447. asm ( __table_entries_sym ( table, idx ) ); \
  448. __asm__ ( ".ifndef %c0\n\t" \
  449. ".section " __table_section ( table, idx ) "\n\t" \
  450. ".align %c1\n\t" \
  451. "\n%c0:\n\t" \
  452. ".previous\n\t" \
  453. ".endif\n\t" \
  454. : : "i" ( __table_temp_sym ( idx, __LINE__ ) ), \
  455. "i" ( __table_alignment ( table ) ) ); \
  456. __table_temp_sym ( idx, __LINE__ ); } )
  457. #define __table_entries_sym( table, idx ) \
  458. "__tbl_" __table_name ( table ) "_" #idx
  459. #define __table_temp_sym( a, b ) \
  460. ___table_temp_sym( __table_, a, _, b )
  461. #define ___table_temp_sym( a, b, c, d ) a ## b ## c ## d
  462. /*
  463. * icc ignores __attribute__ (( aligned (x) )) when it is used to
  464. * decrease the compiler's default choice of alignment (which may be
  465. * higher than the alignment actually required by the structure). We
  466. * work around this by forcing the alignment to a large multiple of
  467. * the required value (so that we are never attempting to decrease the
  468. * default alignment) and then postprocessing the object file to
  469. * reduce the alignment back down to the "real" value.
  470. *
  471. */
  472. #undef __table_alignment
  473. #define __table_alignment( table ) \
  474. ( ICC_ALIGN_HACK_FACTOR * __alignof__ ( __table_type ( table ) ) )
  475. /*
  476. * Because of the alignment hack, we must ensure that the compiler
  477. * never tries to place multiple objects within the same section,
  478. * otherwise the assembler will insert padding to the (incorrect)
  479. * alignment boundary. Do this by appending the line number to table
  480. * section names.
  481. *
  482. * Note that we don't need to worry about padding between array
  483. * elements, since the alignment is declared on the variable (i.e. the
  484. * whole array) rather than on the type (i.e. on all individual array
  485. * elements).
  486. */
  487. #undef __table_section
  488. #define __table_section( table, idx ) \
  489. ".tbl." __table_name ( table ) "." __table_str ( idx ) \
  490. "." __table_xstr ( __LINE__ )
  491. #define __table_xstr( x ) __table_str ( x )
  492. #endif /* __ICC */
  493. #endif /* _IPXE_TABLES_H */