| #ifndef COMPILER_H | |
| #define COMPILER_H | |
| /* | |
| * Doxygen can't cope with some of the more esoteric areas of C, so we | |
| * make its life simpler. | |
| * | |
| */ | |
| #ifdef DOXYGEN | |
| #define __attribute__(x) | |
| #endif | |
| /** @file | |
| * | |
| * Global compiler definitions. | |
| * | |
| * This file is implicitly included by every @c .c file in Etherboot. | |
| * It defines global macros such as DBG(). | |
| * | |
| * We arrange for each object to export the symbol @c obj_OBJECT | |
| * (where @c OBJECT is the object name, e.g. @c rtl8139) as a global | |
| * symbol, so that the linker can drag in selected object files from | |
| * the library using <tt> -u obj_OBJECT </tt>. | |
| * | |
| */ | |
| /* Force visibility of all symbols to "hidden", i.e. inform gcc that | |
| * all symbol references resolve strictly within our final binary. | |
| * This avoids unnecessary PLT/GOT entries on x86_64. | |
| * | |
| * This is a stronger claim than specifying "-fvisibility=hidden", | |
| * since it also affects symbols marked with "extern". | |
| */ | |
| #ifndef ASSEMBLY | |
| #if __GNUC__ >= 4 | |
| #pragma GCC visibility push(hidden) | |
| #endif | |
| #endif /* ASSEMBLY */ | |
| #undef _S1 | |
| #undef _S2 | |
| #undef _C1 | |
| #undef _C2 | |
| /** Concatenate non-expanded arguments */ | |
| #define _C1( x, y ) x ## y | |
| /** Concatenate expanded arguments */ | |
| #define _C2( x, y ) _C1 ( x, y ) | |
| /** Stringify non-expanded argument */ | |
| #define _S1( x ) #x | |
| /** Stringify expanded argument */ | |
| #define _S2( x ) _S1 ( x ) | |
| /* Assembler section types */ | |
| #ifdef ASSEMBLY | |
| #define PROGBITS _C2 ( ASM_TCHAR, progbits ) | |
| #define NOBITS _C2 ( ASM_TCHAR, nobits ) | |
| #else | |
| #define PROGBITS_OPS _S2 ( ASM_TCHAR_OPS ) "progbits" | |
| #define PROGBITS _S2 ( ASM_TCHAR ) "progbits" | |
| #define NOBITS_OPS _S2 ( ASM_TCHAR_OPS ) "nobits" | |
| #define NOBITS _S2 ( ASM_TCHAR ) "nobits" | |
| #endif | |
| /** | |
| * @defgroup symmacros Macros to provide or require explicit symbols | |
| * @{ | |
| */ | |
| /** | |
| * Provide a symbol within this object file | |
| * | |
| * @v symbol Symbol name | |
| */ | |
| #ifdef ASSEMBLY | |
| #define PROVIDE_SYMBOL( symbol ) \ | |
| .section ".provided", "a", NOBITS ; \ | |
| .hidden symbol ; \ | |
| .globl symbol ; \ | |
| symbol: ; \ | |
| .previous | |
| #else | |
| #define PROVIDE_SYMBOL( symbol ) \ | |
| char symbol[0] \ | |
| __attribute__ (( section ( ".provided" ) )) | |
| #endif | |
| /** | |
| * Request a symbol | |
| * | |
| * @v symbol Symbol name | |
| * | |
| * Request a symbol to be included within the link. If the symbol | |
| * cannot be found, the link will succeed anyway. | |
| */ | |
| #ifdef ASSEMBLY | |
| #define REQUEST_SYMBOL( symbol ) \ | |
| .equ __request_ ## symbol, symbol | |
| #else | |
| #define REQUEST_SYMBOL( symbol ) \ | |
| __asm__ ( ".equ __request_" #symbol ", " #symbol ) | |
| #endif | |
| /** | |
| * Require a symbol | |
| * | |
| * @v symbol Symbol name | |
| * | |
| * Require a symbol to be included within the link. If the symbol | |
| * cannot be found, the link will fail. | |
| * | |
| * To use this macro within a file, you must also specify the file's | |
| * "requiring symbol" using the REQUIRING_SYMBOL() or | |
| * PROVIDE_REQUIRING_SYMBOL() macros. | |
| */ | |
| #ifdef ASSEMBLY | |
| #define REQUIRE_SYMBOL( symbol ) \ | |
| .reloc __requiring_symbol__, RELOC_TYPE_NONE, symbol | |
| #else | |
| #define REQUIRE_SYMBOL( symbol ) \ | |
| __asm__ ( ".reloc __requiring_symbol__, " \ | |
| _S2 ( RELOC_TYPE_NONE ) ", " #symbol ) | |
| #endif | |
| /** | |
| * Specify the file's requiring symbol | |
| * | |
| * @v symbol Symbol name | |
| * | |
| * REQUIRE_SYMBOL() works by defining a dummy relocation record | |
| * against a nominated "requiring symbol". The presence of the | |
| * nominated requiring symbol will drag in all of the symbols | |
| * specified using REQUIRE_SYMBOL(). | |
| */ | |
| #ifdef ASSEMBLY | |
| #define REQUIRING_SYMBOL( symbol ) \ | |
| .equ __requiring_symbol__, symbol | |
| #else | |
| #define REQUIRING_SYMBOL( symbol ) \ | |
| __asm__ ( ".equ __requiring_symbol__, " #symbol ) | |
| #endif | |
| /** | |
| * Provide a file's requiring symbol | |
| * | |
| * If the file contains no symbols that can be used as the requiring | |
| * symbol, you can provide a dummy one-byte-long symbol using | |
| * PROVIDE_REQUIRING_SYMBOL(). | |
| */ | |
| #ifdef ASSEMBLY | |
| #define PROVIDE_REQUIRING_SYMBOL() \ | |
| .section ".tbl.requiring_symbols", "a", PROGBITS ; \ | |
| __requiring_symbol__: .byte 0 ; \ | |
| .size __requiring_symbol__, . - __requiring_symbol__ ; \ | |
| .previous | |
| #else | |
| #define PROVIDE_REQUIRING_SYMBOL() \ | |
| __asm__ ( ".section \".tbl.requiring_symbols\", " \ | |
| " \"a\", " PROGBITS "\n" \ | |
| "__requiring_symbol__:\t.byte 0\n" \ | |
| ".size __requiring_symbol__, " \ | |
| " . - __requiring_symbol__\n" \ | |
| ".previous" ) | |
| #endif | |
| /** @} */ | |
| /** | |
| * @defgroup ipxenote Macros to provide ELF notes | |
| * @{ | |
| */ | |
| /* Construct an iPXE-specific ELF note */ | |
| #define IPXE_NOTE( type ) \ | |
| __asm__ ( ".section \".note.ipxe\", \"\", " \ | |
| _S2 ( ASM_TCHAR ) "note\n\t" \ | |
| /* Owner name length */ \ | |
| ".long 4\n\t" \ | |
| /* Content length */ \ | |
| ".long 0\n\t" \ | |
| /* Type */ \ | |
| ".long " _S2 ( _C2 ( IPXE_NOTE_, type ) ) \ | |
| "\n\t" \ | |
| /* Owner name */ \ | |
| ".ascii \"iPXE\"\n\t" \ | |
| ".previous\n\t" ) | |
| /** Build will use a disk-based console log, if present */ | |
| #define IPXE_NOTE_DISKLOG 0x18aed109 | |
| /** @} */ | |
| /** | |
| * @defgroup objmacros Macros to provide or require explicit objects | |
| * @{ | |
| */ | |
| #define PREFIX_OBJECT( _prefix ) _C2 ( _prefix, OBJECT ) | |
| #define OBJECT_SYMBOL PREFIX_OBJECT ( obj_ ) | |
| /** Always provide the symbol for the current object (defined by -DOBJECT) */ | |
| PROVIDE_SYMBOL ( OBJECT_SYMBOL ); | |
| /** | |
| * Request an object | |
| * | |
| * @v object Object name | |
| * | |
| * Request an object to be included within the link. If the object | |
| * cannot be found, the link will succeed anyway. | |
| */ | |
| #define REQUEST_OBJECT( object ) REQUEST_SYMBOL ( obj_ ## object ) | |
| /** | |
| * Require an object | |
| * | |
| * @v object Object name | |
| * | |
| * Require an object to be included within the link. If the object | |
| * cannot be found, the link will fail. | |
| * | |
| * To use this macro within a file, you must also specify the file's | |
| * "requiring symbol" using the REQUIRING_SYMBOL() or | |
| * PROVIDE_REQUIRING_SYMBOL() macros. | |
| */ | |
| #define REQUIRE_OBJECT( object ) REQUIRE_SYMBOL ( obj_ ## object ) | |
| /** @} */ | |
| /** Select file identifier for errno.h (if used) */ | |
| #define ERRFILE PREFIX_OBJECT ( ERRFILE_ ) | |
| #ifndef ASSEMBLY | |
| /** Declare a function as weak (use *before* the definition) | |
| * | |
| * Due to a bug in at least GCC 4.4.4 and earlier, weak symbols may be | |
| * inlined if they have hidden visibility (see above for why hidden | |
| * visibility is used). This results in the non-weak symbol never | |
| * being used, so explicitly mark the function as noinline to prevent | |
| * inlining. | |
| */ | |
| #define __weak __attribute__ (( weak, noinline )) | |
| #endif | |
| /** @defgroup dbg Debugging infrastructure | |
| * @{ | |
| */ | |
| /** @def DBG | |
| * | |
| * Print a debugging message. | |
| * | |
| * The debug level is set at build time by specifying the @c DEBUG= | |
| * parameter on the @c make command line. For example, to enable | |
| * debugging for the PCI bus functions (in pci.c) in a @c .dsk image | |
| * for the @c rtl8139 card, you could use the command line | |
| * | |
| * @code | |
| * | |
| * make bin/rtl8139.dsk DEBUG=pci | |
| * | |
| * @endcode | |
| * | |
| * This will enable the debugging statements (DBG()) in pci.c. If | |
| * debugging is not enabled, DBG() statements will be ignored. | |
| * | |
| * You can enable debugging in several objects simultaneously by | |
| * separating them with commas, as in | |
| * | |
| * @code | |
| * | |
| * make bin/rtl8139.dsk DEBUG=pci,buffer,heap | |
| * | |
| * @endcode | |
| * | |
| * You can increase the debugging level for an object by specifying it | |
| * with @c :N, where @c N is the level, as in | |
| * | |
| * @code | |
| * | |
| * make bin/rtl8139.dsk DEBUG=pci,buffer:2,heap | |
| * | |
| * @endcode | |
| * | |
| * which would enable debugging for the PCI, buffer-handling and | |
| * heap-allocation code, with the buffer-handling code at level 2. | |
| * | |
| */ | |
| #ifndef DBGLVL_MAX | |
| #define NDEBUG | |
| #define DBGLVL_MAX 0 | |
| #endif | |
| #ifndef DBGLVL_DFLT | |
| #define DBGLVL_DFLT DBGLVL_MAX | |
| #endif | |
| #ifndef ASSEMBLY | |
| /** printf() for debugging */ | |
| extern void __attribute__ (( format ( printf, 1, 2 ) )) | |
| dbg_printf ( const char *fmt, ... ); | |
| extern void dbg_autocolourise ( unsigned long id ); | |
| extern void dbg_decolourise ( void ); | |
| extern void dbg_hex_dump_da ( unsigned long dispaddr, | |
| const void *data, unsigned long len ); | |
| extern void dbg_md5_da ( unsigned long dispaddr, | |
| const void *data, unsigned long len ); | |
| extern void dbg_pause ( void ); | |
| extern void dbg_more ( void ); | |
| /* Allow for selective disabling of enabled debug levels */ | |
| #define __debug_disable( object ) _C2 ( __debug_disable_, object ) | |
| char __debug_disable(OBJECT) = ( DBGLVL_MAX & ~DBGLVL_DFLT ); | |
| #define DBG_DISABLE_OBJECT( object, level ) do { \ | |
| extern char __debug_disable(object); \ | |
| __debug_disable(object) |= (level); \ | |
| } while ( 0 ) | |
| #define DBG_ENABLE_OBJECT( object, level ) do { \ | |
| extern char __debug_disable(object); \ | |
| __debug_disable(object) &= ~(level); \ | |
| } while ( 0 ) | |
| #if DBGLVL_MAX | |
| #define DBGLVL ( DBGLVL_MAX & ~__debug_disable(OBJECT) ) | |
| #define DBG_DISABLE( level ) do { \ | |
| __debug_disable(OBJECT) |= ( (level) & DBGLVL_MAX ); \ | |
| } while ( 0 ) | |
| #define DBG_ENABLE( level ) do { \ | |
| __debug_disable(OBJECT) &= ~( (level) & DBGLVL_MAX ); \ | |
| } while ( 0 ) | |
| #else | |
| #define DBGLVL 0 | |
| #define DBG_DISABLE( level ) do { } while ( 0 ) | |
| #define DBG_ENABLE( level ) do { } while ( 0 ) | |
| #endif | |
| #define DBGLVL_LOG 1 | |
| #define DBG_LOG ( DBGLVL & DBGLVL_LOG ) | |
| #define DBGLVL_EXTRA 2 | |
| #define DBG_EXTRA ( DBGLVL & DBGLVL_EXTRA ) | |
| #define DBGLVL_PROFILE 4 | |
| #define DBG_PROFILE ( DBGLVL & DBGLVL_PROFILE ) | |
| #define DBGLVL_IO 8 | |
| #define DBG_IO ( DBGLVL & DBGLVL_IO ) | |
| /** | |
| * Print debugging message if we are at a certain debug level | |
| * | |
| * @v level Debug level | |
| * @v ... printf() argument list | |
| */ | |
| #define DBG_IF( level, ... ) do { \ | |
| if ( DBG_ ## level ) { \ | |
| dbg_printf ( __VA_ARGS__ ); \ | |
| } \ | |
| } while ( 0 ) | |
| /** | |
| * Print a hex dump if we are at a certain debug level | |
| * | |
| * @v level Debug level | |
| * @v dispaddr Display address | |
| * @v data Data to print | |
| * @v len Length of data | |
| */ | |
| #define DBG_HDA_IF( level, dispaddr, data, len ) do { \ | |
| if ( DBG_ ## level ) { \ | |
| union { \ | |
| unsigned long ul; \ | |
| typeof ( dispaddr ) raw; \ | |
| } da; \ | |
| da.ul = 0; \ | |
| da.raw = dispaddr; \ | |
| dbg_hex_dump_da ( da.ul, data, len ); \ | |
| } \ | |
| } while ( 0 ) | |
| /** | |
| * Print a hex dump if we are at a certain debug level | |
| * | |
| * @v level Debug level | |
| * @v data Data to print | |
| * @v len Length of data | |
| */ | |
| #define DBG_HD_IF( level, data, len ) do { \ | |
| const void *_data = data; \ | |
| DBG_HDA_IF ( level, _data, _data, len ); \ | |
| } while ( 0 ) | |
| /** | |
| * Print an MD5 checksum if we are at a certain debug level | |
| * | |
| * @v level Debug level | |
| * @v dispaddr Display address | |
| * @v data Data to print | |
| * @v len Length of data | |
| */ | |
| #define DBG_MD5A_IF( level, dispaddr, data, len ) do { \ | |
| if ( DBG_ ## level ) { \ | |
| union { \ | |
| unsigned long ul; \ | |
| typeof ( dispaddr ) raw; \ | |
| } da; \ | |
| da.ul = 0; \ | |
| da.raw = dispaddr; \ | |
| dbg_md5_da ( da.ul, data, len ); \ | |
| } \ | |
| } while ( 0 ) | |
| /** | |
| * Print an MD5 checksum if we are at a certain debug level | |
| * | |
| * @v level Debug level | |
| * @v data Data to print | |
| * @v len Length of data | |
| */ | |
| #define DBG_MD5_IF( level, data, len ) do { \ | |
| const void *_data = data; \ | |
| DBG_MD5A_IF ( level, _data, _data, len ); \ | |
| } while ( 0 ) | |
| /** | |
| * Prompt for key press if we are at a certain debug level | |
| * | |
| * @v level Debug level | |
| */ | |
| #define DBG_PAUSE_IF( level, ... ) do { \ | |
| if ( DBG_ ## level ) { \ | |
| dbg_pause(); \ | |
| } \ | |
| } while ( 0 ) | |
| /** | |
| * Prompt for more output data if we are at a certain debug level | |
| * | |
| * @v level Debug level | |
| */ | |
| #define DBG_MORE_IF( level, ... ) do { \ | |
| if ( DBG_ ## level ) { \ | |
| dbg_more(); \ | |
| } \ | |
| } while ( 0 ) | |
| /** | |
| * Select colour for debug messages if we are at a certain debug level | |
| * | |
| * @v level Debug level | |
| * @v id Message stream ID | |
| */ | |
| #define DBG_AC_IF( level, id ) do { \ | |
| if ( DBG_ ## level ) { \ | |
| union { \ | |
| unsigned long ul; \ | |
| typeof ( id ) raw; \ | |
| } dbg_stream; \ | |
| dbg_stream.ul = 0; \ | |
| dbg_stream.raw = id; \ | |
| dbg_autocolourise ( dbg_stream.ul ); \ | |
| } \ | |
| } while ( 0 ) | |
| /** | |
| * Revert colour for debug messages if we are at a certain debug level | |
| * | |
| * @v level Debug level | |
| */ | |
| #define DBG_DC_IF( level ) do { \ | |
| if ( DBG_ ## level ) { \ | |
| dbg_decolourise(); \ | |
| } \ | |
| } while ( 0 ) | |
| /* Autocolourising versions of the DBGxxx_IF() macros */ | |
| #define DBGC_IF( level, id, ... ) do { \ | |
| DBG_AC_IF ( level, id ); \ | |
| DBG_IF ( level, __VA_ARGS__ ); \ | |
| DBG_DC_IF ( level ); \ | |
| } while ( 0 ) | |
| #define DBGC_HDA_IF( level, id, ... ) do { \ | |
| DBG_AC_IF ( level, id ); \ | |
| DBG_HDA_IF ( level, __VA_ARGS__ ); \ | |
| DBG_DC_IF ( level ); \ | |
| } while ( 0 ) | |
| #define DBGC_HD_IF( level, id, ... ) do { \ | |
| DBG_AC_IF ( level, id ); \ | |
| DBG_HD_IF ( level, __VA_ARGS__ ); \ | |
| DBG_DC_IF ( level ); \ | |
| } while ( 0 ) | |
| #define DBGC_MD5A_IF( level, id, ... ) do { \ | |
| DBG_AC_IF ( level, id ); \ | |
| DBG_MD5A_IF ( level, __VA_ARGS__ ); \ | |
| DBG_DC_IF ( level ); \ | |
| } while ( 0 ) | |
| #define DBGC_MD5_IF( level, id, ... ) do { \ | |
| DBG_AC_IF ( level, id ); \ | |
| DBG_MD5_IF ( level, __VA_ARGS__ ); \ | |
| DBG_DC_IF ( level ); \ | |
| } while ( 0 ) | |
| #define DBGC_PAUSE_IF( level, id ) do { \ | |
| DBG_AC_IF ( level, id ); \ | |
| DBG_PAUSE_IF ( level ); \ | |
| DBG_DC_IF ( level ); \ | |
| } while ( 0 ) | |
| #define DBGC_MORE_IF( level, id ) do { \ | |
| DBG_AC_IF ( level, id ); \ | |
| DBG_MORE_IF ( level ); \ | |
| DBG_DC_IF ( level ); \ | |
| } while ( 0 ) | |
| /* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( LOG, ... )*/ | |
| #define DBG( ... ) DBG_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBG_HDA( ... ) DBG_HDA_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBG_HD( ... ) DBG_HD_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBG_MD5A( ... ) DBG_MD5A_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBG_MD5( ... ) DBG_MD5_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBG_PAUSE( ... ) DBG_PAUSE_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBG_MORE( ... ) DBG_MORE_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBGC( ... ) DBGC_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBGC_HDA( ... ) DBGC_HDA_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBGC_HD( ... ) DBGC_HD_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBGC_MD5A( ... ) DBGC_MD5A_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBGC_MD5( ... ) DBGC_MD5_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBGC_PAUSE( ... ) DBGC_PAUSE_IF ( LOG, ##__VA_ARGS__ ) | |
| #define DBGC_MORE( ... ) DBGC_MORE_IF ( LOG, ##__VA_ARGS__ ) | |
| /* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( EXTRA, ... )*/ | |
| #define DBG2( ... ) DBG_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBG2_HDA( ... ) DBG_HDA_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBG2_HD( ... ) DBG_HD_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBG2_MD5A( ... ) DBG_MD5A_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBG2_MD5( ... ) DBG_MD5_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBG2_PAUSE( ... ) DBG_PAUSE_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBG2_MORE( ... ) DBG_MORE_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBGC2( ... ) DBGC_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBGC2_HDA( ... ) DBGC_HDA_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBGC2_HD( ... ) DBGC_HD_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBGC2_MD5A( ... ) DBGC_MD5A_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBGC2_MD5( ... ) DBGC_MD5_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBGC2_PAUSE( ... ) DBGC_PAUSE_IF ( EXTRA, ##__VA_ARGS__ ) | |
| #define DBGC2_MORE( ... ) DBGC_MORE_IF ( EXTRA, ##__VA_ARGS__ ) | |
| /* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( PROFILE, ... )*/ | |
| #define DBGP( ... ) DBG_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGP_HDA( ... ) DBG_HDA_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGP_HD( ... ) DBG_HD_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGP_MD5A( ... ) DBG_MD5A_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGP_MD5( ... ) DBG_MD5_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGP_PAUSE( ... ) DBG_PAUSE_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGP_MORE( ... ) DBG_MORE_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGCP( ... ) DBGC_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGCP_HDA( ... ) DBGC_HDA_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGCP_HD( ... ) DBGC_HD_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGCP_MD5A( ... ) DBGC_MD5A_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGCP_MD5( ... ) DBGC_MD5_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGCP_PAUSE( ... ) DBGC_PAUSE_IF ( PROFILE, ##__VA_ARGS__ ) | |
| #define DBGCP_MORE( ... ) DBGC_MORE_IF ( PROFILE, ##__VA_ARGS__ ) | |
| /* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( IO, ... )*/ | |
| #define DBGIO( ... ) DBG_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGIO_HDA( ... ) DBG_HDA_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGIO_HD( ... ) DBG_HD_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGIO_MD5A( ... ) DBG_MD5A_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGIO_MD5( ... ) DBG_MD5_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGIO_PAUSE( ... ) DBG_PAUSE_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGIO_MORE( ... ) DBG_MORE_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGCIO( ... ) DBGC_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGCIO_HDA( ... ) DBGC_HDA_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGCIO_HD( ... ) DBGC_HD_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGCIO_MD5A( ... ) DBGC_MD5A_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGCIO_MD5( ... ) DBGC_MD5_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGCIO_PAUSE( ... ) DBGC_PAUSE_IF ( IO, ##__VA_ARGS__ ) | |
| #define DBGCIO_MORE( ... ) DBGC_MORE_IF ( IO, ##__VA_ARGS__ ) | |
| #endif /* ASSEMBLY */ | |
| /** @} */ | |
| /** @defgroup attrs Miscellaneous attributes | |
| * @{ | |
| */ | |
| #ifndef ASSEMBLY | |
| /** Declare a variable or data structure as unused. */ | |
| #define __unused __attribute__ (( unused )) | |
| /** | |
| * Declare a function as pure - i.e. without side effects | |
| */ | |
| #define __pure __attribute__ (( pure )) | |
| /** | |
| * Declare a function as const - i.e. it does not access global memory | |
| * (including dereferencing pointers passed to it) at all. | |
| * Must also not call any non-const functions. | |
| */ | |
| #define __const __attribute__ (( const )) | |
| /** | |
| * Declare a function's pointer parameters as non-null - i.e. force | |
| * compiler to check pointers at compile time and enable possible | |
| * optimizations based on that fact | |
| */ | |
| #define __nonnull __attribute__ (( nonnull )) | |
| /** | |
| * Declare a pointer returned by a function as a unique memory address | |
| * as returned by malloc-type functions. | |
| */ | |
| #define __malloc __attribute__ (( malloc )) | |
| /** | |
| * Declare a function as used. | |
| * | |
| * Necessary only if the function is called only from assembler code. | |
| */ | |
| #define __used __attribute__ (( used )) | |
| /** Declare a data structure to be aligned with 16-byte alignment */ | |
| #define __aligned __attribute__ (( aligned ( 16 ) )) | |
| /** Declare a function to be always inline */ | |
| #define __always_inline __attribute__ (( always_inline )) | |
| /* Force all inline functions to not be instrumented | |
| * | |
| * This is required to cope with what seems to be a long-standing gcc | |
| * bug, in which -finstrument-functions will cause instances of | |
| * inlined functions to be reported as further calls to the | |
| * *containing* function. This makes instrumentation very difficult | |
| * to use. | |
| * | |
| * Work around this problem by adding the no_instrument_function | |
| * attribute to all inlined functions. | |
| */ | |
| #define inline inline __attribute__ (( no_instrument_function )) | |
| #endif /* ASSEMBLY */ | |
| /** @} */ | |
| /** | |
| * Optimisation barrier | |
| */ | |
| #ifndef ASSEMBLY | |
| #define barrier() __asm__ __volatile__ ( "" : : : "memory" ) | |
| #endif /* ASSEMBLY */ | |
| /** | |
| * Array size | |
| */ | |
| #ifndef ASSEMBLY | |
| #define ARRAY_SIZE(array) ( sizeof (array) / sizeof ( (array)[0] ) ) | |
| #endif /* ASSEMBLY */ | |
| /** @defgroup abs Absolute symbols | |
| * @{ | |
| */ | |
| #ifndef ASSEMBLY | |
| /** Declare an absolute symbol (e.g. a value defined by a linker script) | |
| * | |
| * Use as e.g.: | |
| * | |
| * extern int ABS_SYMBOL ( _my_symbol ); | |
| * | |
| */ | |
| #define ABS_SYMBOL( name ) name[] | |
| /** Get value of an absolute symbol for use in a static initializer | |
| * | |
| * Use as e.g.: | |
| * | |
| * extern int ABS_SYMBOL ( _my_symbol ); | |
| * static int my_symbol = ABS_VALUE_INIT ( _my_symbol ); | |
| * | |
| * Note that the declared type must be at least as large as a pointer | |
| * type, since the compiler sees the absolute symbol as being an | |
| * address. | |
| */ | |
| #define ABS_VALUE_INIT( name ) ( ( typeof ( name[0] ) ) name ) | |
| /** Get value of an absolute symbol | |
| * | |
| * In a position-dependent executable, where all addresses are fixed | |
| * at link time, we can use the standard technique as documented by | |
| * GNU ld, e.g.: | |
| * | |
| * extern char _my_symbol[]; | |
| * | |
| * printf ( "Absolute symbol value is %x\n", ( ( int ) _my_symbol ) ); | |
| * | |
| * This technique may not work in a position-independent executable. | |
| * When dynamic relocations are applied, the runtime addresses will no | |
| * longer be equal to the link-time addresses. If the code to obtain | |
| * the address of _my_symbol uses PC-relative addressing, then it | |
| * will calculate the runtime "address" of the absolute symbol, which | |
| * will no longer be equal the the link-time "address" (i.e. the | |
| * correct value) of the absolute symbol. | |
| * | |
| * We can work around this by instead declaring a static variable to | |
| * contain the absolute value, and returning the contents of this | |
| * static variable: | |
| * | |
| * extern char _my_symbol[]; | |
| * static void * volatile my_symbol = _my_symbol; | |
| * | |
| * printf ( "Absolute symbol value is %x\n", ( ( int ) my_symbol ) ); | |
| * | |
| * The value of the static variable cannot possibly use PC-relative | |
| * addressing (since there is no applicable program counter for | |
| * non-code), and so will instead be filled in with the correct | |
| * absolute value at link time. (No dynamic relocation will be | |
| * generated that might change its value, since the symbol providing | |
| * the value is an absolute symbol.) | |
| * | |
| * This second technique will work for both position-dependent and | |
| * position-independent code, but incurs the unnecssary overhead of an | |
| * additional static variable in position-dependent code. The | |
| * ABS_VALUE() macro abstracts away these differences, using the most | |
| * efficient available technique. Use as e.g.: | |
| * | |
| * extern int ABS_SYMBOL ( _my_symbol ); | |
| * #define my_symbol ABS_VALUE ( _my_symbol ) | |
| * | |
| * printf ( "Absolute symbol value is %x\n", my_symbol ); | |
| * | |
| * The ABS_VALUE() macro uses the (otherwise redundant) type declared | |
| * on the ABS_SYMBOL() array to automatically determine the correct | |
| * type for the ABS_VALUE() expression. | |
| * | |
| * Unlike ABS_VALUE_INIT(), there is no restriction that the type must | |
| * be at least as large as a pointer type. | |
| */ | |
| #ifndef __pie__ | |
| #define ABS_VALUE( name ) ( ( typeof ( name[0] ) ) ( intptr_t ) name ) | |
| #else | |
| #define ABS_VALUE( name ) ( { \ | |
| static void * volatile static_ ## name = name; \ | |
| ( ( typeof ( name[0] ) ) ( intptr_t ) static_ ## name ); \ | |
| } ) | |
| #endif | |
| #endif /* ASSEMBLY */ | |
| /** @} */ | |
| /** | |
| * @defgroup licences Licence declarations | |
| * | |
| * For reasons that are partly historical, various different files | |
| * within the iPXE codebase have differing licences. | |
| * | |
| * @{ | |
| */ | |
| /** Declare a file as being in the public domain | |
| * | |
| * This licence declaration is applicable when a file states itself to | |
| * be in the public domain. | |
| */ | |
| #define FILE_LICENCE_PUBLIC_DOMAIN \ | |
| PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__public_domain__ ) ) | |
| /** Declare a file as being under version 2 (or later) of the GNU GPL | |
| * | |
| * This licence declaration is applicable when a file states itself to | |
| * be licensed under the GNU GPL; "either version 2 of the License, or | |
| * (at your option) any later version". | |
| */ | |
| #define FILE_LICENCE_GPL2_OR_LATER \ | |
| PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__gpl2_or_later__ ) ) | |
| /** Declare a file as being under version 2 of the GNU GPL | |
| * | |
| * This licence declaration is applicable when a file states itself to | |
| * be licensed under version 2 of the GPL, and does not include the | |
| * "or, at your option, any later version" clause. | |
| */ | |
| #define FILE_LICENCE_GPL2_ONLY \ | |
| PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__gpl2_only__ ) ) | |
| /** Declare a file as being under any version of the GNU GPL | |
| * | |
| * This licence declaration is applicable when a file states itself to | |
| * be licensed under the GPL, but does not specify a version. | |
| * | |
| * According to section 9 of the GPLv2, "If the Program does not | |
| * specify a version number of this License, you may choose any | |
| * version ever published by the Free Software Foundation". | |
| */ | |
| #define FILE_LICENCE_GPL_ANY \ | |
| PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__gpl_any__ ) ) | |
| /** Declare a file as being under the three-clause BSD licence | |
| * | |
| * This licence declaration is applicable when a file states itself to | |
| * be licensed under terms allowing redistribution in source and | |
| * binary forms (with or without modification) provided that: | |
| * | |
| * redistributions of source code retain the copyright notice, | |
| * list of conditions and any attached disclaimers | |
| * | |
| * redistributions in binary form reproduce the copyright notice, | |
| * list of conditions and any attached disclaimers in the | |
| * documentation and/or other materials provided with the | |
| * distribution | |
| * | |
| * the name of the author is not used to endorse or promote | |
| * products derived from the software without specific prior | |
| * written permission | |
| * | |
| * It is not necessary for the file to explicitly state that it is | |
| * under a "BSD" licence; only that the licensing terms be | |
| * functionally equivalent to the standard three-clause BSD licence. | |
| */ | |
| #define FILE_LICENCE_BSD3 \ | |
| PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__bsd3__ ) ) | |
| /** Declare a file as being under the two-clause BSD licence | |
| * | |
| * This licence declaration is applicable when a file states itself to | |
| * be licensed under terms allowing redistribution in source and | |
| * binary forms (with or without modification) provided that: | |
| * | |
| * redistributions of source code retain the copyright notice, | |
| * list of conditions and any attached disclaimers | |
| * | |
| * redistributions in binary form reproduce the copyright notice, | |
| * list of conditions and any attached disclaimers in the | |
| * documentation and/or other materials provided with the | |
| * distribution | |
| * | |
| * It is not necessary for the file to explicitly state that it is | |
| * under a "BSD" licence; only that the licensing terms be | |
| * functionally equivalent to the standard two-clause BSD licence. | |
| */ | |
| #define FILE_LICENCE_BSD2 \ | |
| PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__bsd2__ ) ) | |
| /** Declare a file as being under the two-clause BSD plus patent licence | |
| * | |
| * This licence declaration is applicable when a file states itself to | |
| * be licensed under terms allowing redistribution in source and | |
| * binary forms (with or without modification) provided that: | |
| * | |
| * redistributions of source code retain the copyright notice, | |
| * list of conditions and any attached disclaimers | |
| * | |
| * redistributions in binary form reproduce the copyright notice, | |
| * list of conditions and any attached disclaimers in the | |
| * documentation and/or other materials provided with the | |
| * distribution | |
| * | |
| * and in addition states that | |
| * | |
| * Subject to the terms and conditions of this license, each | |
| * copyright holder and contributor hereby grants to those | |
| * receiving rights under this license a perpetual, worldwide, | |
| * non-exclusive, no-charge, royalty-free, irrevocable (except for | |
| * failure to satisfy the conditions of this license) patent | |
| * license to make, have made, use, offer to sell, sell, import, | |
| * and otherwise transfer this software, where such license | |
| * applies only to those patent claims, already acquired or | |
| * hereafter acquired, licensable by such copyright holder or | |
| * contributor that are necessarily infringed by: | |
| * | |
| * their Contribution(s) (the licensed copyrights of copyright | |
| * holders and non-copyrightable additions of contributors, in | |
| * source or binary form) alone; or | |
| * | |
| * combination of their Contribution(s) with the work of | |
| * authorship to which such Contribution(s) was added by such | |
| * copyright holder or contributor, if, at the time the | |
| * Contribution is added, such addition causes such combination | |
| * to be necessarily infringed. The patent license shall not | |
| * apply to any other combinations which include the | |
| * Contribution. | |
| * | |
| * It is not necessary for the file to explicitly state that it is | |
| * under a "BSD" licence; only that the licensing terms be | |
| * functionally equivalent to the standard two-clause BSD licence with | |
| * patent grant. | |
| */ | |
| #define FILE_LICENCE_BSD2_PATENT \ | |
| PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__bsd2_patent__ ) ) | |
| /** Declare a file as being under the one-clause MIT-style licence | |
| * | |
| * This licence declaration is applicable when a file states itself to | |
| * be licensed under terms allowing redistribution for any purpose | |
| * with or without fee, provided that the copyright notice and | |
| * permission notice appear in all copies. | |
| */ | |
| #define FILE_LICENCE_MIT \ | |
| PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__mit__ ) ) | |
| /** Declare a file as being under GPLv2+ or UBDL | |
| * | |
| * This licence declaration is applicable when a file states itself to | |
| * be licensed under the GNU GPL; "either version 2 of the License, or | |
| * (at your option) any later version" and also states that it may be | |
| * distributed under the terms of the Unmodified Binary Distribution | |
| * Licence (as given in the file COPYING.UBDL). | |
| */ | |
| #define FILE_LICENCE_GPL2_OR_LATER_OR_UBDL \ | |
| PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__gpl2_or_later_or_ubdl__ ) ) | |
| /** Declare a particular licence as applying to a file */ | |
| #define FILE_LICENCE( _licence ) FILE_LICENCE_ ## _licence | |
| /** @} */ | |
| /* This file itself is under GPLv2+/UBDL */ | |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | |
| /** | |
| * @defgroup secboot UEFI Secure Boot restrictions | |
| * | |
| * Not all files within the iPXE codebase are allowed to be included | |
| * in UEFI Secure Boot signed builds. | |
| * | |
| * Files that are permitted in a UEFI Secure Boot build are subject to | |
| * stricter code review requirements. In particular, contributions | |
| * from third parties may not be marked as permitted unless they have | |
| * passed an approved security review. | |
| * | |
| * @{ | |
| */ | |
| /** Declare a file as being permitted in a UEFI Secure Boot build */ | |
| #define FILE_SECBOOT_PERMITTED \ | |
| PROVIDE_SYMBOL ( PREFIX_OBJECT ( __secboot__permitted__ ) ) | |
| /** Declare a file as being forbidden in a UEFI Secure Boot build */ | |
| #define FILE_SECBOOT_FORBIDDEN \ | |
| PROVIDE_SYMBOL ( PREFIX_OBJECT ( __secboot__forbidden__ ) ) | |
| /** Declare a file's UEFI Secure Boot permission status */ | |
| #define FILE_SECBOOT( _status ) FILE_SECBOOT_ ## _status | |
| /** @} */ | |
| /* This file itself is permitted in a Secure Boot build */ | |
| FILE_SECBOOT ( PERMITTED ); | |
| #include <bits/compiler.h> | |
| #endif /* COMPILER_H */ |