[x86_64] Add support for compilation as an x86_64 binary
authorMichael Brown <mcb30@etherboot.org>
Tue, 18 Nov 2008 22:30:37 +0000 (14:30 -0800)
committerMichael Brown <mcb30@etherboot.org>
Fri, 5 Dec 2008 00:06:27 +0000 (00:06 +0000)
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

34 files changed:
src/arch/i386/Makefile
src/arch/i386/include/bits/byteswap.h
src/arch/i386/include/bits/stdint.h
src/arch/x86/Makefile [new file with mode: 0644]
src/arch/x86/core/pcidirect.c [moved from src/arch/i386/core/pcidirect.c with 98% similarity]
src/arch/x86/core/x86_string.c [moved from src/arch/i386/core/i386_string.c with 93% similarity]
src/arch/x86/include/bits/pci_io.h [moved from src/arch/i386/include/bits/pci_io.h with 100% similarity]
src/arch/x86/include/bits/string.h [moved from src/arch/i386/include/bits/string.h with 98% similarity]
src/arch/x86/include/gpxe/efi/efix86_nap.h [moved from src/arch/i386/include/gpxe/efi/efix86_nap.h with 100% similarity]
src/arch/x86/include/gpxe/pcibios.h [moved from src/arch/i386/include/gpxe/pcibios.h with 100% similarity]
src/arch/x86/include/gpxe/pcidirect.h [moved from src/arch/i386/include/gpxe/pcidirect.h with 100% similarity]
src/arch/x86/interface/efi/efix86_nap.c [moved from src/arch/i386/interface/efi/efix86_nap.c with 100% similarity]
src/arch/x86_64/Makefile [new file with mode: 0644]
src/arch/x86_64/Makefile.efi [new file with mode: 0644]
src/arch/x86_64/include/bits/byteswap.h [new file with mode: 0644]
src/arch/x86_64/include/bits/compiler.h [new file with mode: 0644]
src/arch/x86_64/include/bits/endian.h [new file with mode: 0644]
src/arch/x86_64/include/bits/errfile.h [new file with mode: 0644]
src/arch/x86_64/include/bits/io.h [new file with mode: 0644]
src/arch/x86_64/include/bits/nap.h [new file with mode: 0644]
src/arch/x86_64/include/bits/smbios.h [new file with mode: 0644]
src/arch/x86_64/include/bits/stdint.h [new file with mode: 0644]
src/arch/x86_64/include/bits/timer.h [new file with mode: 0644]
src/arch/x86_64/include/bits/uaccess.h [new file with mode: 0644]
src/arch/x86_64/include/bits/umalloc.h [new file with mode: 0644]
src/arch/x86_64/include/gdbmach.h [new file with mode: 0644]
src/arch/x86_64/include/limits.h [new file with mode: 0644]
src/arch/x86_64/prefix/efiprefix.S [new file with mode: 0644]
src/arch/x86_64/scripts/efi.lds [new file with mode: 0644]
src/include/byteswap.h
src/include/compiler.h
src/include/gpxe/efi/ProcessorBind.h
src/include/gpxe/efi/X64/ProcessorBind.h [new file with mode: 0644]
src/util/efilink.c

index e376b48..1392bba 100644 (file)
@@ -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)
index 54b93ab..98418c2 100644 (file)
@@ -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 */
index 1c9706c..6ccf097 100644 (file)
@@ -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 (file)
index 0000000..9ac75b4
--- /dev/null
@@ -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
similarity index 98%
rename from src/arch/i386/core/pcidirect.c
rename to src/arch/x86/core/pcidirect.c
index fec2e3c..db17215 100644 (file)
@@ -16,6 +16,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <gpxe/io.h>
 #include <gpxe/pci.h>
 
 /** @file
similarity index 93%
rename from src/arch/i386/core/i386_string.c
rename to src/arch/x86/core/x86_string.c
index 9917363..c0224c7 100644 (file)
@@ -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;
similarity index 98%
rename from src/arch/i386/include/bits/string.h
rename to src/arch/x86/include/bits/string.h
index c05a7df..42ddedd 100644 (file)
@@ -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/x86_64/Makefile b/src/arch/x86_64/Makefile
new file mode 100644 (file)
index 0000000..d2c2ff5
--- /dev/null
@@ -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 (file)
index 0000000..7e07088
--- /dev/null
@@ -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 (file)
index 0000000..9ed85e8
--- /dev/null
@@ -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 (file)
index 0000000..51a7eaa
--- /dev/null
@@ -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 (file)
index 0000000..413e702
--- /dev/null
@@ -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 (file)
index 0000000..dcda26b
--- /dev/null
@@ -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 (file)
index 0000000..921fdcc
--- /dev/null
@@ -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 (file)
index 0000000..0a0c8a2
--- /dev/null
@@ -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 (file)
index 0000000..2f0118d
--- /dev/null
@@ -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 (file)
index 0000000..23bae9c
--- /dev/null
@@ -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 (file)
index 0000000..dfa6c27
--- /dev/null
@@ -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 (file)
index 0000000..4558292
--- /dev/null
@@ -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 (file)
index 0000000..12bf949
--- /dev/null
@@ -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 (file)
index 0000000..fcf8e94
--- /dev/null
@@ -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 (file)
index 0000000..8cf87b4
--- /dev/null
@@ -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 (file)
index 0000000..a3b503b
--- /dev/null
@@ -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 (file)
index 0000000..833905c
--- /dev/null
@@ -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 );
+}
index 72b5a01..6c3ced2 100644 (file)
@@ -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
index 4140a35..7b5a58d 100644 (file)
@@ -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.
index cc5a985..3dbaf1b 100644 (file)
@@ -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 (file)
index 0000000..fe6c413
--- /dev/null
@@ -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
+
index e21f4a9..17b99d2 100644 (file)
@@ -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.
                 */