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