diff options
author | Michael Brown <mcb30@etherboot.org> | 2008-11-18 14:30:37 -0800 |
---|---|---|
committer | Michael Brown <mcb30@etherboot.org> | 2008-12-05 00:06:27 +0000 |
commit | ce0a0ccf5c2b99be684f13a9418d1556bae5f0ed (patch) | |
tree | 965c86dafc3fbdca8e46ee22b94387242cc0e288 /src | |
parent | b0d2c9a4d5b5dd669a845127a37ba08440e2820b (diff) | |
download | ipxe-ce0a0ccf5c2b99be684f13a9418d1556bae5f0ed.tar.gz |
[x86_64] Add support for compilation as an x86_64 binary
Currently the only supported platform for x86_64 is EFI.
Building an EFI64 gPXE requires a version of gcc that supports
__attribute__((ms_abi)). This currently means a development build of
gcc; the feature should be present when gcc 4.4 is released.
In the meantime; you can grab a suitable gcc tree from
git://git.etherboot.org/scm/people/mcb30/gcc/.git
Diffstat (limited to 'src')
34 files changed, 997 insertions, 51 deletions
diff --git a/src/arch/i386/Makefile b/src/arch/i386/Makefile index e376b4811..1392bbac7 100644 --- a/src/arch/i386/Makefile +++ b/src/arch/i386/Makefile @@ -68,7 +68,6 @@ SRCDIRS += arch/i386/drivers/net SRCDIRS += arch/i386/interface/pcbios SRCDIRS += arch/i386/interface/pxe SRCDIRS += arch/i386/interface/syslinux -SRCDIRS += arch/i386/interface/efi # The various xxx_loader.c files are #included into core/loader.c and # should not be compiled directly. @@ -82,6 +81,11 @@ NON_AUTO_SRCS += arch/i386/core/wince_loader.c OBJS_unnrv2b = unnrv2b unnrv2b16 CFLAGS_unnrv2b16 = -DCODE16 +# Include common x86 Makefile +# +MAKEDEPS += arch/x86/Makefile +include arch/x86/Makefile + # Include platform-specific Makefile # MAKEDEPS += arch/i386/Makefile.$(PLATFORM) diff --git a/src/arch/i386/include/bits/byteswap.h b/src/arch/i386/include/bits/byteswap.h index 54b93ab90..98418c29d 100644 --- a/src/arch/i386/include/bits/byteswap.h +++ b/src/arch/i386/include/bits/byteswap.h @@ -2,7 +2,7 @@ #define ETHERBOOT_BITS_BYTESWAP_H static inline __attribute__ ((always_inline, const)) uint16_t -__i386_bswap_16(uint16_t x) +__bswap_variable_16(uint16_t x) { __asm__("xchgb %b0,%h0\n\t" : "=q" (x) @@ -11,7 +11,7 @@ __i386_bswap_16(uint16_t x) } static inline __attribute__ ((always_inline, const)) uint32_t -__i386_bswap_32(uint32_t x) +__bswap_variable_32(uint32_t x) { __asm__("xchgb %b0,%h0\n\t" "rorl $16,%0\n\t" @@ -22,7 +22,7 @@ __i386_bswap_32(uint32_t x) } static inline __attribute__ ((always_inline, const)) uint64_t -__i386_bswap_64(uint64_t x) +__bswap_variable_64(uint64_t x) { union { uint64_t qword; @@ -30,47 +30,12 @@ __i386_bswap_64(uint64_t x) } u; u.qword = x; - u.dword[0] = __i386_bswap_32(u.dword[0]); - u.dword[1] = __i386_bswap_32(u.dword[1]); + u.dword[0] = __bswap_variable_32(u.dword[0]); + u.dword[1] = __bswap_variable_32(u.dword[1]); __asm__("xchgl %0,%1" : "=r" ( u.dword[0] ), "=r" ( u.dword[1] ) : "0" ( u.dword[0] ), "1" ( u.dword[1] ) ); return u.qword; } -#define __bswap_constant_16(x) \ - ((uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \ - (((uint16_t)(x) & 0xff00) >> 8))) - -#define __bswap_constant_32(x) \ - ((uint32_t)((((uint32_t)(x) & 0x000000ffU) << 24) | \ - (((uint32_t)(x) & 0x0000ff00U) << 8) | \ - (((uint32_t)(x) & 0x00ff0000U) >> 8) | \ - (((uint32_t)(x) & 0xff000000U) >> 24))) - -#define __bswap_constant_64(x) \ - ((uint64_t)((((uint64_t)(x) & 0x00000000000000ffULL) << 56) | \ - (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \ - (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \ - (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \ - (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \ - (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \ - (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \ - (((uint64_t)(x) & 0xff00000000000000ULL) >> 56))) - -#define __bswap_16(x) \ - ((uint16_t)(__builtin_constant_p(x) ? \ - __bswap_constant_16(x) : \ - __i386_bswap_16(x))) - -#define __bswap_32(x) \ - ((uint32_t)(__builtin_constant_p(x) ? \ - __bswap_constant_32(x) : \ - __i386_bswap_32(x))) - -#define __bswap_64(x) \ - ((uint64_t)(__builtin_constant_p(x) ? \ - __bswap_constant_64(x) : \ - __i386_bswap_64(x))) - #endif /* ETHERBOOT_BITS_BYTESWAP_H */ diff --git a/src/arch/i386/include/bits/stdint.h b/src/arch/i386/include/bits/stdint.h index 1c9706c14..6ccf09717 100644 --- a/src/arch/i386/include/bits/stdint.h +++ b/src/arch/i386/include/bits/stdint.h @@ -1,8 +1,8 @@ #ifndef _BITS_STDINT_H #define _BITS_STDINT_H -typedef typeof(sizeof(int)) size_t; -typedef signed long ssize_t; +typedef unsigned int size_t; +typedef signed int ssize_t; typedef signed long off_t; typedef unsigned char uint8_t; diff --git a/src/arch/x86/Makefile b/src/arch/x86/Makefile new file mode 100644 index 000000000..9ac75b456 --- /dev/null +++ b/src/arch/x86/Makefile @@ -0,0 +1,8 @@ +# Include common x86 headers +# +CFLAGS += -Iarch/x86/include + +# x86-specific directories containing source files +# +SRCDIRS += arch/x86/core +SRCDIRS += arch/x86/interface/efi diff --git a/src/arch/i386/core/pcidirect.c b/src/arch/x86/core/pcidirect.c index fec2e3c18..db17215e4 100644 --- a/src/arch/i386/core/pcidirect.c +++ b/src/arch/x86/core/pcidirect.c @@ -16,6 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <gpxe/io.h> #include <gpxe/pci.h> /** @file diff --git a/src/arch/i386/core/i386_string.c b/src/arch/x86/core/x86_string.c index 9917363a6..c0224c7a9 100644 --- a/src/arch/i386/core/i386_string.c +++ b/src/arch/x86/core/x86_string.c @@ -32,9 +32,7 @@ * @v len Length * @ret dest Destination address */ -__attribute__ (( regparm ( 3 ) )) void * __memcpy ( void *dest, - const void *src, - size_t len ) { +void * __memcpy ( void *dest, const void *src, size_t len ) { void *edi = dest; const void *esi = src; int discard_ecx; diff --git a/src/arch/i386/include/bits/pci_io.h b/src/arch/x86/include/bits/pci_io.h index 0fbb439db..0fbb439db 100644 --- a/src/arch/i386/include/bits/pci_io.h +++ b/src/arch/x86/include/bits/pci_io.h diff --git a/src/arch/i386/include/bits/string.h b/src/arch/x86/include/bits/string.h index c05a7df84..42ddeddf1 100644 --- a/src/arch/i386/include/bits/string.h +++ b/src/arch/x86/include/bits/string.h @@ -23,9 +23,7 @@ #define __HAVE_ARCH_MEMCPY -extern __attribute__ (( regparm ( 3 ) )) void * __memcpy ( void *dest, - const void *src, - size_t len ); +extern void * __memcpy ( void *dest, const void *src, size_t len ); #if 0 static inline __attribute__ (( always_inline )) void * diff --git a/src/arch/i386/include/gpxe/efi/efix86_nap.h b/src/arch/x86/include/gpxe/efi/efix86_nap.h index 91424c547..91424c547 100644 --- a/src/arch/i386/include/gpxe/efi/efix86_nap.h +++ b/src/arch/x86/include/gpxe/efi/efix86_nap.h diff --git a/src/arch/i386/include/gpxe/pcibios.h b/src/arch/x86/include/gpxe/pcibios.h index b86f5abd4..b86f5abd4 100644 --- a/src/arch/i386/include/gpxe/pcibios.h +++ b/src/arch/x86/include/gpxe/pcibios.h diff --git a/src/arch/i386/include/gpxe/pcidirect.h b/src/arch/x86/include/gpxe/pcidirect.h index fe433c6f2..fe433c6f2 100644 --- a/src/arch/i386/include/gpxe/pcidirect.h +++ b/src/arch/x86/include/gpxe/pcidirect.h diff --git a/src/arch/i386/interface/efi/efix86_nap.c b/src/arch/x86/interface/efi/efix86_nap.c index 45e99a685..45e99a685 100644 --- a/src/arch/i386/interface/efi/efix86_nap.c +++ b/src/arch/x86/interface/efi/efix86_nap.c diff --git a/src/arch/x86_64/Makefile b/src/arch/x86_64/Makefile new file mode 100644 index 000000000..d2c2ff53d --- /dev/null +++ b/src/arch/x86_64/Makefile @@ -0,0 +1,41 @@ +# Code size reduction. +# +CFLAGS += -fstrength-reduce -fomit-frame-pointer + +# Code size reduction. gcc3 needs a different syntax to gcc2 if you +# want to avoid spurious warnings. +# +CFLAGS += -falign-jumps=1 -falign-loops=1 -falign-functions=1 + +# Use %rip-relative addressing wherever possible. +# +CFLAGS += -fpie + +# Force 64-bit code +# +CFLAGS += -m64 +ASFLAGS += --64 +LDFLAGS += -m elf_x86_64 + +# EFI requires -fshort-wchar, and nothing else currently uses wchar_t +# +CFLAGS += -fshort-wchar + +# We need to undefine the default macro "i386" when compiling .S +# files, otherwise ".arch i386" translates to ".arch 1"... +# +CFLAGS += -Ui386 + +# x86_64-specific directories containing source files +# +SRCDIRS += arch/x86_64/prefix + +# Include common x86 Makefile +# +MAKEDEPS += arch/x86/Makefile +include arch/x86/Makefile + +# Include platform-specific Makefile +# +MAKEDEPS += arch/x86_64/Makefile.$(PLATFORM) +include arch/x86_64/Makefile.$(PLATFORM) diff --git a/src/arch/x86_64/Makefile.efi b/src/arch/x86_64/Makefile.efi new file mode 100644 index 000000000..7e07088de --- /dev/null +++ b/src/arch/x86_64/Makefile.efi @@ -0,0 +1,28 @@ +# -*- makefile -*- : Force emacs to use Makefile mode + +# EFI probably doesn't guarantee us a red zone, so let's not rely on it. +# +CFLAGS += -mno-red-zone + +# The EFI linker script +# +LDSCRIPT = arch/x86_64/scripts/efi.lds + +# Use a relocatable link; we perform final relocations in the efilink utility. +# +LDFLAGS += -r -d -S + +# Media types. +# +NON_AUTO_MEDIA += efi + +# Rule for building EFI files +# +$(BIN)/%.efi.tmp-reloc : $(BIN)/%.efi.tmp $(EFILINK) + $(QM)$(ECHO) " [EFILINK] $@" + $(Q)$(LD) -e 0 -o /dev/null $< # Check for unresolved symbols + $(Q)$(EFILINK) $< $@ + +$(BIN)/%.efi : $(BIN)/%.efi.tmp-reloc + $(QM)$(ECHO) " [FINISH] $@" + $(Q)$(OBJCOPY) -Obinary $< $@ diff --git a/src/arch/x86_64/include/bits/byteswap.h b/src/arch/x86_64/include/bits/byteswap.h new file mode 100644 index 000000000..9ed85e8f8 --- /dev/null +++ b/src/arch/x86_64/include/bits/byteswap.h @@ -0,0 +1,22 @@ +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H + +static inline __attribute__ (( always_inline, const )) uint16_t +__bswap_variable_16 ( uint16_t x ) { + __asm__ ( "xchgb %b0,%h0" : "=Q" ( x ) : "0" ( x ) ); + return x; +} + +static inline __attribute__ (( always_inline, const )) uint32_t +__bswap_variable_32 ( uint32_t x ) { + __asm__ ( "bswapl %k0" : "=r" ( x ) : "0" ( x ) ); + return x; +} + +static inline __attribute__ (( always_inline, const )) uint64_t +__bswap_variable_64 ( uint64_t x ) { + __asm__ ( "bswapq %q0" : "=r" ( x ) : "0" ( x ) ); + return x; +} + +#endif /* _BITS_BYTESWAP_H */ diff --git a/src/arch/x86_64/include/bits/compiler.h b/src/arch/x86_64/include/bits/compiler.h new file mode 100644 index 000000000..51a7eaae2 --- /dev/null +++ b/src/arch/x86_64/include/bits/compiler.h @@ -0,0 +1,14 @@ +#ifndef _BITS_COMPILER_H +#define _BITS_COMPILER_H + +#ifndef ASSEMBLY + +/** Declare a function with standard calling conventions */ +#define __asmcall __attribute__ (( regparm(0) )) + +/** Declare a function with libgcc implicit linkage */ +#define __libgcc + +#endif /* ASSEMBLY */ + +#endif /* _BITS_COMPILER_H */ diff --git a/src/arch/x86_64/include/bits/endian.h b/src/arch/x86_64/include/bits/endian.h new file mode 100644 index 000000000..413e702db --- /dev/null +++ b/src/arch/x86_64/include/bits/endian.h @@ -0,0 +1,6 @@ +#ifndef ETHERBOOT_BITS_ENDIAN_H +#define ETHERBOOT_BITS_ENDIAN_H + +#define __BYTE_ORDER __LITTLE_ENDIAN + +#endif /* ETHERBOOT_BITS_ENDIAN_H */ diff --git a/src/arch/x86_64/include/bits/errfile.h b/src/arch/x86_64/include/bits/errfile.h new file mode 100644 index 000000000..dcda26ba4 --- /dev/null +++ b/src/arch/x86_64/include/bits/errfile.h @@ -0,0 +1,11 @@ +#ifndef _BITS_ERRFILE_H +#define _BITS_ERRFILE_H + +/** + * @addtogroup errfile Error file identifiers + * @{ + */ + +/** @} */ + +#endif /* _BITS_ERRFILE_H */ diff --git a/src/arch/x86_64/include/bits/io.h b/src/arch/x86_64/include/bits/io.h new file mode 100644 index 000000000..921fdcc05 --- /dev/null +++ b/src/arch/x86_64/include/bits/io.h @@ -0,0 +1,10 @@ +#ifndef _BITS_IO_H +#define _BITS_IO_H + +/** @file + * + * x86_64-specific I/O API implementations + * + */ + +#endif /* _BITS_IO_H */ diff --git a/src/arch/x86_64/include/bits/nap.h b/src/arch/x86_64/include/bits/nap.h new file mode 100644 index 000000000..0a0c8a246 --- /dev/null +++ b/src/arch/x86_64/include/bits/nap.h @@ -0,0 +1,12 @@ +#ifndef _BITS_NAP_H +#define _BITS_NAP_H + +/** @file + * + * x86_64-specific CPU sleeping API implementations + * + */ + +#include <gpxe/efi/efix86_nap.h> + +#endif /* _BITS_MAP_H */ diff --git a/src/arch/x86_64/include/bits/smbios.h b/src/arch/x86_64/include/bits/smbios.h new file mode 100644 index 000000000..2f0118d02 --- /dev/null +++ b/src/arch/x86_64/include/bits/smbios.h @@ -0,0 +1,10 @@ +#ifndef _BITS_SMBIOS_H +#define _BITS_SMBIOS_H + +/** @file + * + * i386-specific SMBIOS API implementations + * + */ + +#endif /* _BITS_SMBIOS_H */ diff --git a/src/arch/x86_64/include/bits/stdint.h b/src/arch/x86_64/include/bits/stdint.h new file mode 100644 index 000000000..23bae9c46 --- /dev/null +++ b/src/arch/x86_64/include/bits/stdint.h @@ -0,0 +1,21 @@ +#ifndef _BITS_STDINT_H +#define _BITS_STDINT_H + +typedef unsigned long size_t; +typedef signed long ssize_t; +typedef signed long off_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; +typedef signed long long int64_t; + +typedef unsigned long physaddr_t; +typedef unsigned long intptr_t; + +#endif /* _BITS_STDINT_H */ diff --git a/src/arch/x86_64/include/bits/timer.h b/src/arch/x86_64/include/bits/timer.h new file mode 100644 index 000000000..dfa6c270c --- /dev/null +++ b/src/arch/x86_64/include/bits/timer.h @@ -0,0 +1,10 @@ +#ifndef _BITS_TIMER_H +#define _BITS_TIMER_H + +/** @file + * + * x86_64-specific timer API implementations + * + */ + +#endif /* _BITS_TIMER_H */ diff --git a/src/arch/x86_64/include/bits/uaccess.h b/src/arch/x86_64/include/bits/uaccess.h new file mode 100644 index 000000000..455829242 --- /dev/null +++ b/src/arch/x86_64/include/bits/uaccess.h @@ -0,0 +1,10 @@ +#ifndef _BITS_UACCESS_H +#define _BITS_UACCESS_H + +/** @file + * + * x86_64-specific user access API implementations + * + */ + +#endif /* _BITS_UACCESS_H */ diff --git a/src/arch/x86_64/include/bits/umalloc.h b/src/arch/x86_64/include/bits/umalloc.h new file mode 100644 index 000000000..12bf949d1 --- /dev/null +++ b/src/arch/x86_64/include/bits/umalloc.h @@ -0,0 +1,10 @@ +#ifndef _BITS_UMALLOC_H +#define _BITS_UMALLOC_H + +/** @file + * + * x86_64-specific user memory allocation API implementations + * + */ + +#endif /* _BITS_UMALLOC_H */ diff --git a/src/arch/x86_64/include/gdbmach.h b/src/arch/x86_64/include/gdbmach.h new file mode 100644 index 000000000..fcf8e94e6 --- /dev/null +++ b/src/arch/x86_64/include/gdbmach.h @@ -0,0 +1,51 @@ +#ifndef GDBMACH_H +#define GDBMACH_H + +/** @file + * + * GDB architecture specifics + * + * This file declares functions for manipulating the machine state and + * debugging context. + * + */ + +#include <stdint.h> + +typedef unsigned long gdbreg_t; + +/* The register snapshot, this must be in sync with interrupt handler and the + * GDB protocol. */ +enum { + // STUB: don't expect this to work! + GDBMACH_EIP, + GDBMACH_EFLAGS, + GDBMACH_NREGS, + GDBMACH_SIZEOF_REGS = GDBMACH_NREGS * sizeof ( gdbreg_t ) +}; + +/* Breakpoint types */ +enum { + GDBMACH_BPMEM, + GDBMACH_BPHW, + GDBMACH_WATCH, + GDBMACH_RWATCH, + GDBMACH_AWATCH, +}; + +static inline void gdbmach_set_pc ( gdbreg_t *regs, gdbreg_t pc ) { + regs [ GDBMACH_EIP ] = pc; +} + +static inline void gdbmach_set_single_step ( gdbreg_t *regs, int step ) { + regs [ GDBMACH_EFLAGS ] &= ~( 1 << 8 ); /* Trace Flag (TF) */ + regs [ GDBMACH_EFLAGS ] |= ( step << 8 ); +} + +static inline void gdbmach_breakpoint ( void ) { + __asm__ __volatile__ ( "int $3\n" ); +} + +extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len, int enable ); + +#endif /* GDBMACH_H */ diff --git a/src/arch/x86_64/include/limits.h b/src/arch/x86_64/include/limits.h new file mode 100644 index 000000000..8cf87b471 --- /dev/null +++ b/src/arch/x86_64/include/limits.h @@ -0,0 +1,59 @@ +#ifndef LIMITS_H +#define LIMITS_H 1 + +/* Number of bits in a `char' */ +#define CHAR_BIT 8 + +/* Minimum and maximum values a `signed char' can hold */ +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 + +/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */ +#define UCHAR_MAX 255 + +/* Minimum and maximum values a `char' can hold */ +#define CHAR_MIN SCHAR_MIN +#define CHAR_MAX SCHAR_MAX + +/* Minimum and maximum values a `signed short int' can hold */ +#define SHRT_MIN (-32768) +#define SHRT_MAX 32767 + +/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */ +#define USHRT_MAX 65535 + + +/* Minimum and maximum values a `signed int' can hold */ +#define INT_MIN (-INT_MAX - 1) +#define INT_MAX 2147483647 + +/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ +#define UINT_MAX 4294967295U + + +/* Minimum and maximum values a `signed int' can hold */ +#define INT_MAX 2147483647 +#define INT_MIN (-INT_MAX - 1) + + +/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ +#define UINT_MAX 4294967295U + + +/* Minimum and maximum values a `signed long' can hold */ +#define LONG_MAX 9223372036854775807L +#define LONG_MIN (-LONG_MAX - 1L) + +/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */ +#define ULONG_MAX 18446744073709551615UL + +/* Minimum and maximum values a `signed long long' can hold */ +#define LLONG_MAX 9223372036854775807LL +#define LLONG_MIN (-LONG_MAX - 1LL) + + +/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */ +#define ULLONG_MAX 18446744073709551615ULL + + +#endif /* LIMITS_H */ diff --git a/src/arch/x86_64/prefix/efiprefix.S b/src/arch/x86_64/prefix/efiprefix.S new file mode 100644 index 000000000..a3b503b82 --- /dev/null +++ b/src/arch/x86_64/prefix/efiprefix.S @@ -0,0 +1,174 @@ + .text + .code32 + .arch i386 + .section ".prefix", "a", @progbits + .org 0x00 + + /* DOS (.com) header + * + * EFI executables seem to leave most of this empty + */ +mzhdr: + .ascii "MZ" /* Magic number */ + .word 0 /* Bytes on last page of file */ + .word 0 /* Pages in file */ + .word 0 /* Relocations */ + .word 0 /* Size of header in paragraphs */ + .word 0 /* Minimum extra paragraphs needed */ + .word 0 /* Maximum extra paragraphs needed */ + .word 0 /* Initial (relative) SS value */ + .word 0 /* Initial SP value */ + .word 0 /* "Checksum" */ + .word 0 /* Initial IP value */ + .word 0 /* Initial (relative) CS value */ + .word 0 /* File address of relocation table */ + .word 0 /* Ovesrlay number */ + .word 0, 0, 0, 0 /* Reserved words */ + .word 0 /* OEM identifier (for e_oeminfo) */ + .word 0 /* OEM information; e_oemid specific */ + .word 0, 0, 0, 0, 0 /* Reserved words */ + .word 0, 0, 0, 0, 0 /* Reserved words */ + .long pehdr_lma /* File address of new exe header */ + .size mzhdr, . - mzhdr + + /* PE header */ + .org 0xc0 /* For compatibility with MS toolchain */ +pehdr: + .ascii "PE\0\0" /* Magic number */ + .word 0x8664 /* CPU architecture: x86_64 */ + .word num_pe_sections /* Number of sections */ + .long 0x10d1a884 /* Timestamp */ + .long 0 /* Symbol table */ + .long 0 /* Number of symbols */ + .word opthdr_size /* Size of optional header */ + .word 0x2002 /* Characteristics */ + .size pehdr, . - pehdr + .equ pehdr_lma, pehdr - mzhdr + + /* "Optional" header */ +opthdr: + .word 0x020b /* Magic number */ + .byte 0 /* Linker major version number */ + .byte 0 /* Linker minor version number */ + .long _text_filesz /* Size of text section */ + .long _data_filesz /* Size of data section */ + .long _bss_filesz /* Size of bss section */ + .long efi_entry_lma /* Entry point */ + .long _text_lma /* Text section start RVA */ + .quad 0 /* Image base address */ + .long _max_align /* Section alignment */ + .long _max_align /* File alignment */ + .word 0 /* Operating system major version number */ + .word 0 /* Operating system minor version number */ + .word 0 /* Image major version number */ + .word 0 /* Image minor version number */ + .word 0 /* Subsystem major version number */ + .word 0 /* Subsystem minor version number */ + .long 0 /* Reserved */ + .long _filesz /* Total image size */ + .long _prefix_filesz /* Total header size */ + .long 0 /* "Checksum" */ + .word 0x0a /* Subsystem: EFI */ + .word 0 /* DLL characteristics */ + .quad 0 /* Size of stack reserve */ + .quad 0 /* Size of stack commit */ + .quad 0 /* Size of heap reserve */ + .quad 0 /* Size of heap commit */ + .long 0 /* Loader flags */ + .long 16 /* Number of data directory entries */ + .long 0, 0 /* Export directory */ + .long 0, 0 /* Import directory */ + .long 0, 0 /* Resource directory */ + .long 0, 0 /* Exception directory */ + .long 0, 0 /* Security directory */ + .long _reloc_lma, _reloc_filesz /* Base relocation directory */ + .long debugdir_lma, debugdir_size /* Debug directory */ + .long 0, 0 /* Description directory */ + .long 0, 0 /* Special directory */ + .long 0, 0 /* Thread storage directory */ + .long 0, 0 /* Load configuration directory */ + .long 0, 0 /* Bound import directory */ + .long 0, 0 /* Import address table directory */ + .long 0, 0 /* Delay import directory */ + .long 0, 0 /* Reserved */ + .long 0, 0 /* Reserved */ + .size opthdr, . - opthdr + .equ opthdr_size, . - opthdr + + /* PE sections */ +pe_sections: +text_section: + .asciz ".text" /* Section name */ + .align 8 + .long _text_filesz /* Section size */ + .long _text_lma /* Relative Virtual Address */ + .long _text_filesz /* Section size (rounded up) */ + .long _text_lma /* Pointer to raw data */ + .long 0 /* Link-time relocations */ + .long 0 /* Line numbers */ + .word 0 /* Number of link-time relocations */ + .word 0 /* Number of line numbers */ + .long 0x68000020 /* Characteristics */ +rodata_section: + .asciz ".rodata" /* Section name */ + .align 8 + .long _rodata_filesz /* Section size */ + .long _rodata_lma /* Relative Virtual Address */ + .long _rodata_filesz /* Section size (rounded up) */ + .long _rodata_lma /* Pointer to raw data */ + .long 0 /* Link-time relocations */ + .long 0 /* Line numbers */ + .word 0 /* Number of link-time relocations */ + .word 0 /* Number of line numbers */ + .long 0x48000040 /* Characteristics */ +data_section: + .asciz ".data" /* Section name */ + .align 8 + .long _data_filesz /* Section size */ + .long _data_lma /* Relative Virtual Address */ + .long _data_filesz /* Section size (rounded up) */ + .long _data_lma /* Pointer to raw data */ + .long 0 /* Link-time relocations */ + .long 0 /* Line numbers */ + .word 0 /* Number of link-time relocations */ + .word 0 /* Number of line numbers */ + .long 0xc8000040 /* Characteristics */ +reloc_section: + .asciz ".reloc" /* Section name */ + .align 8 + .long _reloc_filesz /* Section size */ + .long _reloc_lma /* Relative Virtual Address */ + .long _reloc_filesz /* Section size (rounded up) */ + .long _reloc_lma /* Pointer to raw data */ + .long 0 /* Link-time relocations */ + .long 0 /* Line numbers */ + .word 0 /* Number of link-time relocations */ + .word 0 /* Number of line numbers */ + .long 0x42000040 /* Characteristics */ + +pe_sections_end: + .size pe_sections, . - pe_sections + .equ num_pe_sections, ( ( . - pe_sections ) / 0x28 ) + + /* Debug directory */ + .section ".rodata" + .globl debugdir +debugdir: + .long 0 /* Characteristics */ + .long 0x10d1a884 /* Timestamp */ + .word 0 /* Major version */ + .word 0 /* Minor version */ + .long 0x02 /* RSDS? */ + .long codeview_rsds_size /* Size of data */ + .long codeview_rsds_lma /* RVA */ + .long codeview_rsds_lma /* File offset */ + .size debugdir, . - debugdir + .equ debugdir_size, . - debugdir + /* Codeview structure */ + .globl codeview_rsds +codeview_rsds: + .ascii "RSDS" /* Magic number */ + .long 0, 0, 0, 0, 0 /* Unused by EFI */ + .asciz "efiprefix.pdb" + .size codeview_rsds, . - codeview_rsds + .equ codeview_rsds_size, . - codeview_rsds diff --git a/src/arch/x86_64/scripts/efi.lds b/src/arch/x86_64/scripts/efi.lds new file mode 100644 index 000000000..833905c93 --- /dev/null +++ b/src/arch/x86_64/scripts/efi.lds @@ -0,0 +1,180 @@ +/* -*- sh -*- */ + +/* + * Linker script for EFI images + * + */ + +EXTERN ( efi_entry ) + +SECTIONS { + + /* The file starts at a virtual address of zero, and sections are + * contiguous. Each section is aligned to at least _max_align, + * which defaults to 32. Load addresses are equal to virtual + * addresses. + */ + + . = 0; + _max_align = 32; + + /* + * The prefix + * + */ + + .prefix : { + _prefix = .; + *(.prefix) + *(.prefix.*) + _mprefix = .; + } .bss.prefix (NOLOAD) : { + _eprefix = .; + } + _prefix_filesz = ABSOLUTE ( _mprefix - _prefix ); + _prefix_memsz = ABSOLUTE ( _eprefix - _prefix ); + + /* + * The text section + * + */ + + . = ALIGN ( _max_align ); + .text : { + _text = .; + *(.text) + *(.text.*) + _mtext = .; + } .bss.text (NOLOAD) : { + _etext = .; + } + _text_filesz = ABSOLUTE ( _mtext - _text ); + _text_memsz = ABSOLUTE ( _etext - _text ); + + /* + * The rodata section + * + */ + + . = ALIGN ( _max_align ); + .rodata : { + _rodata = .; + *(.rodata) + *(.rodata.*) + _mrodata = .; + } .bss.rodata (NOLOAD) : { + _erodata = .; + } + _rodata_filesz = ABSOLUTE ( _mrodata - _rodata ); + _rodata_memsz = ABSOLUTE ( _erodata - _rodata ); + + /* + * The data section + * + */ + + . = ALIGN ( _max_align ); + .data : { + _data = .; + *(.data) + *(.data.*) + *(SORT(.tbl.*)) /* Various tables. See include/tables.h */ + /* EFI seems to not support proper bss sections */ + *(.bss) + *(.bss.*) + *(COMMON) + *(.stack) + *(.stack.*) + _mdata = .; + } .bss.data (NOLOAD) : { + _edata = .; + } + _data_filesz = ABSOLUTE ( _mdata - _data ); + _data_memsz = ABSOLUTE ( _edata - _data ); + + /* + * The bss section + * + */ + + . = ALIGN ( _max_align ); + .bss : { + _bss = .; + /* EFI seems to not support proper bss sections */ + _mbss = .; + } .bss.bss (NOLOAD) : { + _ebss = .; + } + _bss_filesz = ABSOLUTE ( _mbss - _bss ); + _bss_memsz = ABSOLUTE ( _ebss - _bss ); + + /* + * The reloc section + * + */ + + . = ALIGN ( _max_align ); + .reloc : { + _reloc = .; + /* Provide some dummy contents to force ld to include this + * section. It will be created by the efilink utility. + */ + BYTE(0); + _mreloc = .; + } .bss.reloc (NOLOAD) : { + _ereloc = .; + } + _reloc_filesz = ABSOLUTE ( _mreloc - _reloc ); + _reloc_memsz = ABSOLUTE ( _ereloc - _reloc ); + + _filesz = ABSOLUTE ( . ); + + /* + * Weak symbols that need zero values if not otherwise defined + * + */ + + .weak 0x0 : { + _weak = .; + *(.weak) + _eweak = .; + } + _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" ); + + /* + * Dispose of the comment and note sections to make the link map + * easier to read + * + */ + + /DISCARD/ : { + *(.comment) + *(.comment.*) + *(.note) + *(.note.*) + *(.eh_frame) + *(.eh_frame.*) + *(.rel) + *(.rel.*) + } + + /* + * Load address calculations. + * + */ + + _prefix_lma = ABSOLUTE ( _prefix ); + _text_lma = ABSOLUTE ( _text ); + _rodata_lma = ABSOLUTE ( _rodata ); + _data_lma = ABSOLUTE ( _data ); + _bss_lma = ABSOLUTE ( _bss ); + _reloc_lma = ABSOLUTE ( _reloc ); + + /* + * Load addresses required by the prefix + * + */ + efi_entry_lma = ABSOLUTE ( efi_entry ); + debugdir_lma = ABSOLUTE ( debugdir ); + codeview_rsds_lma = ABSOLUTE ( codeview_rsds ); +} diff --git a/src/include/byteswap.h b/src/include/byteswap.h index 72b5a01db..6c3ced25f 100644 --- a/src/include/byteswap.h +++ b/src/include/byteswap.h @@ -4,6 +4,41 @@ #include "endian.h" #include "bits/byteswap.h" +#define __bswap_constant_16(x) \ + ((uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \ + (((uint16_t)(x) & 0xff00) >> 8))) + +#define __bswap_constant_32(x) \ + ((uint32_t)((((uint32_t)(x) & 0x000000ffU) << 24) | \ + (((uint32_t)(x) & 0x0000ff00U) << 8) | \ + (((uint32_t)(x) & 0x00ff0000U) >> 8) | \ + (((uint32_t)(x) & 0xff000000U) >> 24))) + +#define __bswap_constant_64(x) \ + ((uint64_t)((((uint64_t)(x) & 0x00000000000000ffULL) << 56) | \ + (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \ + (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \ + (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \ + (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \ + (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \ + (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \ + (((uint64_t)(x) & 0xff00000000000000ULL) >> 56))) + +#define __bswap_16(x) \ + ((uint16_t)(__builtin_constant_p(x) ? \ + __bswap_constant_16(x) : \ + __bswap_variable_16(x))) + +#define __bswap_32(x) \ + ((uint32_t)(__builtin_constant_p(x) ? \ + __bswap_constant_32(x) : \ + __bswap_variable_32(x))) + +#define __bswap_64(x) \ + ((uint64_t)(__builtin_constant_p(x) ? \ + __bswap_constant_64(x) : \ + __bswap_variable_64(x))) + #if __BYTE_ORDER == __LITTLE_ENDIAN #include "little_bswap.h" #endif diff --git a/src/include/compiler.h b/src/include/compiler.h index 4140a3563..7b5a58d62 100644 --- a/src/include/compiler.h +++ b/src/include/compiler.h @@ -59,6 +59,15 @@ __asm__ ( ".equ\t" OBJECT_SYMBOL_STR ", 0" ); #define REQUIRE_OBJECT(object) \ __asm__ ( ".equ\tneed_" #object ", obj_" #object ); +/* 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". + */ +#pragma GCC visibility push(hidden) + /** @def DBG * * Print a debugging message. diff --git a/src/include/gpxe/efi/ProcessorBind.h b/src/include/gpxe/efi/ProcessorBind.h index cc5a9852e..3dbaf1b8f 100644 --- a/src/include/gpxe/efi/ProcessorBind.h +++ b/src/include/gpxe/efi/ProcessorBind.h @@ -8,3 +8,7 @@ #if __i386__ #include <gpxe/efi/Ia32/ProcessorBind.h> #endif + +#if __x86_64__ +#include <gpxe/efi/X64/ProcessorBind.h> +#endif diff --git a/src/include/gpxe/efi/X64/ProcessorBind.h b/src/include/gpxe/efi/X64/ProcessorBind.h new file mode 100644 index 000000000..fe6c413be --- /dev/null +++ b/src/include/gpxe/efi/X64/ProcessorBind.h @@ -0,0 +1,247 @@ +/** @file + Processor or Compiler specific defines and types x64 (Intel(r) EM64T, AMD64). + + Copyright (c) 2006, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +/// +/// Define the processor type so other code can make processor based choices +/// +#define MDE_CPU_X64 + + +// +// Make sure we are useing the correct packing rules per EFI specification +// +#ifndef __GNUC__ +#pragma pack() +#endif + + +#if __INTEL_COMPILER +// +// Disable ICC's remark #869: "Parameter" was never referenced warning. +// This is legal ANSI C code so we disable the remark that is turned on with -Wall +// +#pragma warning ( disable : 869 ) + +// +// Disable ICC's remark #1418: external function definition with no prior declaration. +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 1418 ) + +// +// Disable ICC's remark #1419: external declaration in primary source file +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 1419 ) + +#endif + + +#if _MSC_EXTENSIONS + +// +// Disable warning that make it impossible to compile at /W4 +// This only works for Microsoft* tools +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + +// +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning +// +#pragma warning ( disable : 4127 ) + +// +// This warning is caused by functions defined but not used. For precompiled header only. +// +#pragma warning ( disable : 4505 ) + +// +// This warning is caused by empty (after preprocessing) souce file. For precompiled header only. +// +#pragma warning ( disable : 4206 ) + +#endif + + +#if !defined(__GNUC__) && (__STDC_VERSION__ < 199901L) + // + // No ANSI C 2000 stdint.h integer width declarations, so define equivalents + // + + #if _MSC_EXTENSIONS + + + // + // use Microsoft C complier dependent interger width types + // + typedef unsigned __int64 UINT64; + typedef __int64 INT64; + typedef unsigned __int32 UINT32; + typedef __int32 INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #else + #ifdef _EFI_P64 + // + // P64 - is Intel Itanium(TM) speak for pointers being 64-bit and longs and ints + // are 32-bits + // + typedef unsigned long long UINT64; + typedef long long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short CHAR16; + typedef unsigned short UINT16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #else + // + // Assume LP64 - longs and pointers are 64-bit. Ints are 32-bit. + // + typedef unsigned long UINT64; + typedef long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #endif + #endif + + #define UINT8_MAX 0xff + +#else + // + // Use ANSI C 2000 stdint.h integer width declarations + // + #include <stdint.h> + typedef uint8_t BOOLEAN; + typedef int8_t INT8; + typedef uint8_t UINT8; + typedef int16_t INT16; + typedef uint16_t UINT16; + typedef int32_t INT32; + typedef uint32_t UINT32; + typedef int64_t INT64; + typedef uint64_t UINT64; + typedef char CHAR8; + typedef uint16_t CHAR16; + +#endif + +typedef UINT64 UINTN; +typedef INT64 INTN; + + +// +// Processor specific defines +// +#define MAX_BIT 0x8000000000000000ULL +#define MAX_2_BITS 0xC000000000000000ULL + +// +// Maximum legal X64 address +// +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL + +// +// The stack alignment required for X64 +// +#define CPU_STACK_ALIGNMENT 16 + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify thier member functions with EFIAPI. +// +#if _MSC_EXTENSIONS + /// + /// Define the standard calling convention reguardless of optimization level. + /// __cdecl is Microsoft* specific C extension. + /// + #define EFIAPI __cdecl +#elif __GNUC__ + /// + /// Define the standard calling convention reguardless of optimization level. + /// The GCC support assumes a GCC compiler that supports the EFI ABI. The EFI + /// ABI is much closer to the x64 Microsoft* ABI than standard x64 (x86-64) + /// GCC ABI. Thus a standard x64 (x86-64) GCC compiler can not be used for + /// x64. Warning the assembly code in the MDE x64 does not follow the correct + /// ABI for the standard x64 (x86-64) GCC. + /// + #define EFIAPI __attribute__((ms_abi)) +#else + /// + /// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI + /// is the standard. + /// + #define EFIAPI +#endif + +// +// The Microsoft* C compiler can removed references to unreferenced data items +// if the /OPT:REF linker option is used. We defined a macro as this is a +// a non standard extension +// +#if _MSC_EXTENSIONS + #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany) +#else + #define GLOBAL_REMOVE_IF_UNREFERENCED +#endif + +// +// For symbol name in GNU assembly code, an extra "_" is necessary +// +#if __GNUC__ + #if defined(linux) + #define ASM_PFX(name) name + #else + #define ASM_PFX(name) _##name + #endif +#endif + +#define FUNCTION_ENTRY_POINT(p) (p) + +#endif + diff --git a/src/util/efilink.c b/src/util/efilink.c index e21f4a901..17b99d293 100644 --- a/src/util/efilink.c +++ b/src/util/efilink.c @@ -56,6 +56,9 @@ static void generate_pe_reloc ( struct pe_relocs **pe_reltab, start_rva = ( rva & ~0xfff ); reloc = ( rva & 0xfff ); switch ( size ) { + case 8: + reloc |= 0xa000; + break; case 4: reloc |= 0x3000; break; @@ -385,13 +388,18 @@ static void process_reloc ( asection *section, arelent *rel, /* Skip absolute symbols; the symbol value won't * change when the object is loaded. */ - } else if ( strcmp ( howto->name, "R_386_32" ) == 0 ) { + } else if ( strcmp ( howto->name, "R_X86_64_64" ) == 0 ) { + /* Generate an 8-byte PE relocation */ + generate_pe_reloc ( pe_reltab, offset, 8 ); + } else if ( ( strcmp ( howto->name, "R_386_32" ) == 0 ) || + ( strcmp ( howto->name, "R_X86_64_32" ) == 0 ) ) { /* Generate a 4-byte PE relocation */ generate_pe_reloc ( pe_reltab, offset, 4 ); } else if ( strcmp ( howto->name, "R_386_16" ) == 0 ) { /* Generate a 2-byte PE relocation */ generate_pe_reloc ( pe_reltab, offset, 2 ); - } else if ( strcmp ( howto->name, "R_386_PC32" ) == 0 ) { + } else if ( ( strcmp ( howto->name, "R_386_PC32" ) == 0 ) || + ( strcmp ( howto->name, "R_X86_64_PC32" ) == 0 ) ) { /* Skip PC-relative relocations; all relative offsets * remain unaltered when the object is loaded. */ |