Skip to content

Commit

Permalink
use -nostdlib everywhere and improve ARCH detection
Browse files Browse the repository at this point in the history
  • Loading branch information
pbatard committed Apr 18, 2016
1 parent 92bef53 commit 8a7d8af
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 53 deletions.
123 changes: 76 additions & 47 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,49 +1,77 @@
TARGET = x64
SUBSYSTEM = 10 # 10 = EFI application

ifeq ($(TARGET),x64)
ARCH = x86_64
GCC_ARCH = x86_64
QEMU_ARCH = x86_64
CROSS_COMPILE = $(GCC_ARCH)-w64-mingw32-
EP_PREFIX =
CFLAGS = -m64 -mno-red-zone
LDFLAGS = -Wl,-dll -Wl,--subsystem,$(SUBSYSTEM) -nostdlib
else ifeq ($(TARGET),ia32)
ARCH = ia32
GCC_ARCH = i686
QEMU_ARCH = i386
CROSS_COMPILE = $(GCC_ARCH)-w64-mingw32-
EP_PREFIX = _
CFLAGS = -m32 -mno-red-zone
# Can't use -nostdlib as we're missing an implementation of __umoddi3
# and __udivdi3, required by ia32/math.c and present in libgcc.a
LDFLAGS = -Wl,-dll -Wl,--subsystem,$(SUBSYSTEM)
else ifeq ($(TARGET),arm)
ARCH = arm
GCC_ARCH = arm
QEMU_ARCH = arm
CROSS_COMPILE = $(GCC_ARCH)-linux-gnueabihf-
EP_PREFIX =
CFLAGS = -marm -fpic -fshort-wchar
LDFLAGS = -Wl,--no-wchar-size-warning -Wl,--subsystem,$(SUBSYSTEM) -nostdlib
ARCH = x64
SUBSYSTEM = 10 # 10 = EFI application

# Try to auto-detect the target ARCH
ifeq ($(shell uname -o),Msys)
IS_MINGW32 = $(findstring MINGW32,$(shell uname -s))
IS_MINGW64 = $(findstring MINGW64,$(shell uname -s))
ifeq ($(IS_MINGW32),MINGW32)
ARCH = ia32
endif
ifeq ($(IS_MINGW64),MINGW64)
ARCH = x64
endif
else
ifeq ($(shell uname -m),x86_64)
ARCH = x64
else ifeq ($(shell uname -m),arm)
ARCH = arm
CROSS_COMPILE =
else
ARCH = ia32
endif
endif

# Set parameters according to our platform
ifeq ($(SYSTEMROOT),)
QEMU = qemu-system-$(QEMU_ARCH) -nographic
# Auto-detect the host arch for MinGW
ifeq ($(shell uname -m),x86_64)
MINGW_HOST = w64
else
MINGW_HOST = w32
endif

ifeq ($(ARCH),x64)
GNUEFI_ARCH = x86_64
GCC_ARCH = x86_64
QEMU_ARCH = x86_64
CROSS_COMPILE = $(GCC_ARCH)-$(MINGW_HOST)-mingw32-
EP_PREFIX =
CFLAGS = -m64 -mno-red-zone
LDFLAGS = -Wl,-dll
else ifeq ($(ARCH),ia32)
GNUEFI_ARCH = ia32
GCC_ARCH = i686
QEMU_ARCH = i386
CROSS_COMPILE = $(GCC_ARCH)-$(MINGW_HOST)-mingw32-
EP_PREFIX = _
CFLAGS = -m32 -mno-red-zone
LDFLAGS = -Wl,-dll
else ifeq ($(ARCH),arm)
GNUEFI_ARCH = arm
GCC_ARCH = arm
QEMU_ARCH = arm
CROSS_COMPILE = $(GCC_ARCH)-linux-gnueabi-
EP_PREFIX =
CFLAGS = -marm -fpic -fshort-wchar
LDFLAGS = -Wl,--no-wchar-size-warning
endif
OVMF_ARCH = $(shell echo $(ARCH) | tr a-z A-Z)

# SYSTEMROOT is only defined on Windows systems
ifneq ($(SYSTEMROOT),)
QEMU = "/c/Program Files/qemu/qemu-system-$(QEMU_ARCH)w.exe"
# MinGW on Windows doesn't use (tuple)-ar but (tuple)-gcc-ar
# so we remove the cross compiler tuple altogether
CROSS_COMPILE =
else
QEMU = qemu-system-$(QEMU_ARCH) -nographic
endif
OVMF_ARCH = $(shell echo $(TARGET) | tr a-z A-Z)
GNUEFI_PATH = $(CURDIR)/gnu-efi
GNUEFI_DIR = $(CURDIR)/gnu-efi

CC := $(CROSS_COMPILE)gcc
CFLAGS += -fno-stack-protector -Wshadow -Wall -Wunused -Werror-implicit-function-declaration
CFLAGS += -I$(GNUEFI_PATH)/inc -I$(GNUEFI_PATH)/inc/$(ARCH) -I$(GNUEFI_PATH)/inc/protocol
LDFLAGS+= -shared -e $(EP_PREFIX)EfiMain
LIBS := -L$(GNUEFI_PATH)/$(ARCH)/lib -lefi
CFLAGS += -I$(GNUEFI_DIR)/inc -I$(GNUEFI_DIR)/inc/$(GNUEFI_ARCH) -I$(GNUEFI_DIR)/inc/protocol
LDFLAGS+= -Wl,--subsystem,$(SUBSYSTEM) -nostdlib -shared -e $(EP_PREFIX)EfiMain
LIBS := -L$(GNUEFI_DIR)/$(GNUEFI_ARCH)/lib -lefi

OVMF_ZIP = OVMF-$(OVMF_ARCH)-r15214.zip

Expand All @@ -56,7 +84,7 @@ GCCMINOR := $(shell $(CC) -dumpversion | cut -f2 -d.)
GCCMACHINE := $(shell $(CC) -dumpmachine)
GCCNEWENOUGH := $(shell ( [ $(GCCVERSION) -gt "4" ] \
|| ( [ $(GCCVERSION) -eq "4" ] \
&& [ $(GCCMINOR) -ge "7" ] ) ) \
&& [ $(GCCMINOR) -ge "7" ] ) ) \
&& echo 1)
ifneq ($(GCCNEWENOUGH),1)
$(error You need GCC 4.7 or later)
Expand All @@ -70,10 +98,10 @@ endif
.PHONY: all clean superclean
all: boot.efi

$(GNUEFI_PATH)/$(ARCH)/lib/libefi.a:
$(MAKE) -C$(GNUEFI_PATH) CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH) lib
$(GNUEFI_DIR)/$(GNUEFI_ARCH)/lib/libefi.a:
$(MAKE) -C$(GNUEFI_DIR) CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(GNUEFI_ARCH) lib

%.efi: %.o $(GNUEFI_PATH)/$(ARCH)/lib/libefi.a
%.efi: %.o $(GNUEFI_DIR)/$(GNUEFI_ARCH)/lib/libefi.a
@echo [LD] $(notdir $@)
@$(CC) $(LDFLAGS) $< -o $@ $(LIBS)

Expand All @@ -82,18 +110,18 @@ $(GNUEFI_PATH)/$(ARCH)/lib/libefi.a:
@$(CC) $(CFLAGS) -ffreestanding -c $<

qemu: CFLAGS += -D_DEBUG
qemu: boot.efi OVMF_$(OVMF_ARCH).fd ntfs.vhd image/efi/boot/boot$(TARGET).efi image/efi/rufus/ntfs_$(TARGET).efi
qemu: boot.efi OVMF_$(OVMF_ARCH).fd ntfs.vhd image/efi/boot/boot$(ARCH).efi image/efi/rufus/ntfs_$(ARCH).efi
$(QEMU) -bios ./OVMF_$(OVMF_ARCH).fd -net none -hda fat:image -hdb ntfs.vhd

image/efi/boot/boot$(TARGET).efi: boot.efi
image/efi/boot/boot$(ARCH).efi: boot.efi
mkdir -p image/efi/boot
cp -f $< $@

# NTFS driver
ntfs_$(TARGET).efi:
wget http://efi.akeo.ie/downloads/efifs-0.8/$(ARCH)/ntfs_$(TARGET).efi
ntfs_$(ARCH).efi:
wget http://efi.akeo.ie/downloads/efifs-0.8/$(ARCH)/ntfs_$(ARCH).efi

image/efi/rufus/ntfs_$(TARGET).efi: ntfs_$(TARGET).efi
image/efi/rufus/ntfs_$(ARCH).efi: ntfs_$(ARCH).efi
mkdir -p image/efi/rufus
cp -f $< $@

Expand All @@ -111,9 +139,10 @@ OVMF_$(OVMF_ARCH).fd:
rm $(OVMF_ZIP)

clean:
$(MAKE) -C$(GNUEFI_DIR) clean
rm -f boot.efi *.o
rm -rf image

superclean: clean
$(MAKE) -C$(GNUEFI_PATH) clean
$(MAKE) -C$(GNUEFI_DIR) clean
rm -f *.fd ntfs.vhd ntfs_*.efi
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,14 @@ git submodule update
If using Visual Studio, just press `F5` to have the application compiled and
launched in the QEMU emulator.

If using MinGW, issue: `make TARGET=<arch>` where `<arch>` is one of `ia32`
or `x64`. You can also debug through QEMU with MinGW by adding `qemu` to your
`make` invocation. Be mindful however that this turns the special `_DEBUG`
mode on, and you should run make without invoking `qemu` to produce proper
release binaries.
If using gcc, you should be able to simply issue `make`. If needed you can also
issue something like `make ARCH=<arch> CROSS_COMPILE=<tuple>` where `<arch>` is
one of `ia32`, `x64` or `arm` and tuple is the one for your cross-compiler (e.g.
`arm-linux-gnueabihf-`).

You can also debug through QEMU by specifying `qemu` to your `make` invocation.
Be mindful however that this turns the special `_DEBUG` mode on, and you should
run make without invoking `qemu` to produce proper release binaries.

## Download and installation

Expand Down
2 changes: 1 addition & 1 deletion gnu-efi
Submodule gnu-efi updated from b5b6a8 to 78e4df

0 comments on commit 8a7d8af

Please sign in to comment.