From 8a9dfb1835cc7d9d6b513857a38a85e09be6ffad Mon Sep 17 00:00:00 2001 From: James Benton Date: Sat, 26 Dec 2015 18:10:38 -0800 Subject: [PATCH] Basic start of a Wii U Toolchain. --- Makefile | 26 +++++++++++++++ crt/Makefile | 24 ++++++++++++++ crt/crt0.S | 10 ++++++ include/coreinit_crt.h | 12 +++++++ include/coreinit_debug.h | 12 +++++++ include/gx2_init.h | 12 +++++++ rpl/Makefile | 25 ++++++++++++++ rpl/common/lib.c | 20 ++++++++++++ rpl/common/rules.mk | 68 +++++++++++++++++++++++++++++++++++++++ rpl/common/stub.S | 13 ++++++++ rpl/libcoreinit/Makefile | 2 ++ rpl/libcoreinit/config.h | 2 ++ rpl/libcoreinit/exports.h | 2 ++ rpl/libgx2/Makefile | 2 ++ rpl/libgx2/config.h | 2 ++ rpl/libgx2/exports.h | 1 + rules/base.mk | 54 +++++++++++++++++++++++++++++++ rules/ppc.mk | 9 ++++++ rules/rpl.ld | 66 +++++++++++++++++++++++++++++++++++++ rules/rpl.mk | 12 +++++++ 20 files changed, 374 insertions(+) create mode 100644 Makefile create mode 100644 crt/Makefile create mode 100644 crt/crt0.S create mode 100644 include/coreinit_crt.h create mode 100644 include/coreinit_debug.h create mode 100644 include/gx2_init.h create mode 100644 rpl/Makefile create mode 100644 rpl/common/lib.c create mode 100644 rpl/common/rules.mk create mode 100644 rpl/common/stub.S create mode 100644 rpl/libcoreinit/Makefile create mode 100644 rpl/libcoreinit/config.h create mode 100644 rpl/libcoreinit/exports.h create mode 100644 rpl/libgx2/Makefile create mode 100644 rpl/libgx2/config.h create mode 100644 rpl/libgx2/exports.h create mode 100644 rules/base.mk create mode 100644 rules/ppc.mk create mode 100644 rules/rpl.ld create mode 100644 rules/rpl.mk diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..70b80f18 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +WUT_ROOT := $(CURDIR) +TARGETS := crt rpl + +all: + @for dir in $(TARGETS); do \ + echo; \ + echo Entering Directory $$dir; \ + $(MAKE) --no-print-directory -C $$dir; \ + echo Leaving Directory $$dir; \ + done + +clean: + @rm -rf lib + @for dir in $(TARGETS); do \ + echo Cleaning $$dir; \ + $(MAKE) --no-print-directory -C $$dir clean; \ + done + +install: + @mkdir -p lib + @for dir in $(TARGETS); do \ + echo Installing $$dir; \ + $(MAKE) --no-print-directory -C $$dir install; \ + done + +.PHONY: all clean install diff --git a/crt/Makefile b/crt/Makefile new file mode 100644 index 00000000..a36cd38a --- /dev/null +++ b/crt/Makefile @@ -0,0 +1,24 @@ +WUT_ROOT := $(CURDIR)/.. +include $(WUT_ROOT)/rules/ppc.mk + +CFILES := $(wildcard *.c) +SFILES := $(wildcard *.S) +CRT0 := crt0.o + +STUBS := $(SFILES:.S=.o) $(CFILES:.c=.o) + +all: $(STUBS) $(CRT0) + +clean: + @echo "[RM] $(notdir $(CRT0))" + @rm -f $(STUBS) $(CRT0) + +install: all + @mkdir -p $(WUT_ROOT)/lib + @cp -f *.o $(WUT_ROOT)/lib + +%.o: %.S + @echo "[CC] $(notdir $<)" + @$(CC) $(CFLAGS) -c $< -o $@ + +.PHONY: all clean diff --git a/crt/crt0.S b/crt/crt0.S new file mode 100644 index 00000000..3b8a2b1e --- /dev/null +++ b/crt/crt0.S @@ -0,0 +1,10 @@ +.extern main +.extern _Exit +.global _start +_start: + bl main + b _Exit + +.global __eabi +__eabi: + blr diff --git a/include/coreinit_crt.h b/include/coreinit_crt.h new file mode 100644 index 00000000..49d77064 --- /dev/null +++ b/include/coreinit_crt.h @@ -0,0 +1,12 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void +_Exit(); + +#ifdef __cplusplus +} +#endif diff --git a/include/coreinit_debug.h b/include/coreinit_debug.h new file mode 100644 index 00000000..661a6274 --- /dev/null +++ b/include/coreinit_debug.h @@ -0,0 +1,12 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void +OSFatal(const char *msg); + +#ifdef __cplusplus +} +#endif diff --git a/include/gx2_init.h b/include/gx2_init.h new file mode 100644 index 00000000..0c66194f --- /dev/null +++ b/include/gx2_init.h @@ -0,0 +1,12 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void +GX2Init(); + +#ifdef __cplusplus +} +#endif diff --git a/rpl/Makefile b/rpl/Makefile new file mode 100644 index 00000000..b4f05006 --- /dev/null +++ b/rpl/Makefile @@ -0,0 +1,25 @@ +WUT_ROOT := $(CURDIR)/.. +TARGETS := libcoreinit libgx2 + +all: + @for dir in $(TARGETS); do \ + echo; \ + echo Entering Directory $$dir; \ + $(MAKE) --no-print-directory -C $$dir; \ + echo Leaving Directory $$dir; \ + done + +clean: + @for dir in $(TARGETS); do \ + echo Cleaning $$dir; \ + $(MAKE) --no-print-directory -C $$dir clean; \ + done + +install: all + @mkdir -p $(WUT_ROOT)/lib + @for dir in $(TARGETS); do \ + echo Installing $$dir; \ + cp $$dir/*.a $(WUT_ROOT)/lib; \ + done + +.PHONY: all install clean diff --git a/rpl/common/lib.c b/rpl/common/lib.c new file mode 100644 index 00000000..cd27204e --- /dev/null +++ b/rpl/common/lib.c @@ -0,0 +1,20 @@ +#include "config.h" + +typedef struct { + const char* name; + const void* fstub; +} __attribute__((__packed__)) rpl_header; + +static const void* fstub[0] __attribute__((section(".data.rplFuncStubs"))); +static const const char name[] __attribute__((section(".rodata.rplNames"))) = LIBRARY_NAME; + +static rpl_header header __attribute__((section(".lib.rplLibs"))) = { + name, + fstub, +}; + +#define EXPORT(name) \ + extern void* name; \ + const void* name##_stub __attribute__((section(".data.rplFuncStubs"))) = &name; \ + +#include "exports.h" diff --git a/rpl/common/rules.mk b/rpl/common/rules.mk new file mode 100644 index 00000000..22f2978d --- /dev/null +++ b/rpl/common/rules.mk @@ -0,0 +1,68 @@ +.SUFFIXES: + +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCE := ../common . +INCLUDE := . +DATA := data +LIBS := + +ifneq ($(BUILD),$(notdir $(CURDIR))) +WUT_ROOT := $(CURDIR)/../.. +else +WUT_ROOT := $(CURDIR)/../../.. +endif +include $(WUT_ROOT)/rules/ppc.mk + +LD := $(PREFIX)ld +RPLCFLAGS := -Wno-unused-variable -fPIC -fpic -fno-builtin +CFLAGS += -O2 -Wall -std=c11 $(RPLCFLAGS) +ODEPS := stub.o lib.o + +ifneq ($(BUILD),$(notdir $(CURDIR))) + +export OUTPUT := $(CURDIR)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCE),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) +export BUILDDIR := $(CURDIR)/$(BUILD) +export DEPSDIR := $(BUILDDIR) + +CFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.c))) +CXXFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.S))) + +export OFILES := $(CFILES:.c=.o) \ + $(CXXFILES:.cpp=.o) \ + $(SFILES:.S=.o) + +export INCLUDES := $(foreach dir,$(INCLUDE),-I$(CURDIR)/$(dir)) \ + -I$(CURDIR)/$(BUILD) + +.PHONY: $(BUILD) clean + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +clean: + @echo "[RM] $(notdir $(OUTPUT))" + @rm -rf $(BUILD) $(OUTPUT).elf $(OUTPUT).a + +else + +DEPENDS := $(OFILES:.o=.d) +OFILES := $(filter-out $(ODEPS),$(OFILES)) + +$(OUTPUT).a: rpl.o $(OFILES) + +lib.o: lib.c + @echo "[CC] $(notdir $<)" + @$(CC) $(DEPSOPTIONS) $(RPLCFLAGS) -S $(INCLUDES) $< -o lib.S + @$(CC) $(DEPSOPTIONS) $(RPLCFLAGS) -c lib.S -o $@ + +rpl.o: $(ODEPS) + @$(LD) $(LDFLAGS) -r $(ODEPS) -o $@ + +-include $(DEPENDS) + +endif diff --git a/rpl/common/stub.S b/rpl/common/stub.S new file mode 100644 index 00000000..7d0e4b44 --- /dev/null +++ b/rpl/common/stub.S @@ -0,0 +1,13 @@ +#include "config.h" + +#define EXPORT(name) \ +.align 2; \ +.section ".rplTramp.text","ax"; \ + .global name; \ + name: \ + li %r0, 0; \ + oris %r0, %r0, 0; \ + mtctr %r0; \ + bctr; \ + +#include "exports.h" diff --git a/rpl/libcoreinit/Makefile b/rpl/libcoreinit/Makefile new file mode 100644 index 00000000..0db6a682 --- /dev/null +++ b/rpl/libcoreinit/Makefile @@ -0,0 +1,2 @@ +-include ../common/rules.mk +-include ../../common/rules.mk diff --git a/rpl/libcoreinit/config.h b/rpl/libcoreinit/config.h new file mode 100644 index 00000000..009754bb --- /dev/null +++ b/rpl/libcoreinit/config.h @@ -0,0 +1,2 @@ +#define LIBRARY_NAME "coreinit.rpl" +#define LIBRARY_SYMBOL coreinit diff --git a/rpl/libcoreinit/exports.h b/rpl/libcoreinit/exports.h new file mode 100644 index 00000000..7a6d1a0a --- /dev/null +++ b/rpl/libcoreinit/exports.h @@ -0,0 +1,2 @@ +EXPORT(_Exit); +EXPORT(OSFatal); \ No newline at end of file diff --git a/rpl/libgx2/Makefile b/rpl/libgx2/Makefile new file mode 100644 index 00000000..0db6a682 --- /dev/null +++ b/rpl/libgx2/Makefile @@ -0,0 +1,2 @@ +-include ../common/rules.mk +-include ../../common/rules.mk diff --git a/rpl/libgx2/config.h b/rpl/libgx2/config.h new file mode 100644 index 00000000..26aad313 --- /dev/null +++ b/rpl/libgx2/config.h @@ -0,0 +1,2 @@ +#define LIBRARY_NAME "gx2.rpl" +#define LIBRARY_SYMBOL gx2 diff --git a/rpl/libgx2/exports.h b/rpl/libgx2/exports.h new file mode 100644 index 00000000..e0c195c7 --- /dev/null +++ b/rpl/libgx2/exports.h @@ -0,0 +1 @@ +EXPORT(GX2Init); \ No newline at end of file diff --git a/rules/base.mk b/rules/base.mk new file mode 100644 index 00000000..adf82f21 --- /dev/null +++ b/rules/base.mk @@ -0,0 +1,54 @@ +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please ensure DEVKITPRO is in your environment.") +endif + +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please ensure DEVKITPPC is in your environment.") +endif + +export PORTLIBS := $(DEVKITPRO)/portlibs/ppc +export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH) + +PREFIX := powerpc-eabi- +OBJCOPY := $(PREFIX)objcopy +AR := $(PREFIX)ar +AS := $(PREFIX)gcc +CC := $(PREFIX)gcc +CXX := $(PREFIX)g++ +STRIP := $(PREFIX)strip + +ifeq ($(findstring $(PREFIX),$(LD)),) +LD := $(CC) +endif + +DEPSOPTIONS = -MMD -MP -MF $(DEPSDIR)/$*.d + +ifdef VERBOSE +DEPSOPTIONS += -v +endif + +%.o: %.c + @echo "[CC] $(notdir $<)" + @$(CC) $(DEPSOPTIONS) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +%.o: %.cpp + @echo "[CXX] $(notdir $<)" + @$(CXX) $(DEPSOPTIONS) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ + +%.o: %.s + @echo "[CC] $(notdir $<)" + @$(AS) $(DEPSOPTIONS) -x assembler-with-cpp $(ASFLAGS) $(INCLUDES) -c $< -o $@ + +%.o: %.S + @echo "[CC] $(notdir $<)" + @$(AS) $(DEPSOPTIONS) -x assembler-with-cpp $(ASFLAGS) $(INCLUDES) -c $< -o $@ + +%.a: + @echo "[AR] $(notdir $@)" + @$(AR) -rcs $@ $^ + +%.elf: + @echo "[LD] $(notdir $@)" + @echo "[LD] $(LIBPATHS)" + @echo "[LD] $(LDFLAGS)" + @$(LD) -v $^ $(LIBPATHS) $(LIBS) $(LDFLAGS) -o $@ diff --git a/rules/ppc.mk b/rules/ppc.mk new file mode 100644 index 00000000..91f2809e --- /dev/null +++ b/rules/ppc.mk @@ -0,0 +1,9 @@ +LIBPATHS := -L$(WUT_ROOT)/lib +CFLAGS := -I$(WUT_ROOT)/include -fno-builtin -ffreestanding +CXXFLAGS := $(CFLAGS) +LDFLAGS := -nostdlib -nostartfiles -T $(WUT_ROOT)/rules/rpl.ld + +include $(WUT_ROOT)/rules/base.mk + +%.rpx: %.elf + @$(STRIP) $< -o $(BUILDDIR)/$(notdir $<) diff --git a/rules/rpl.ld b/rules/rpl.ld new file mode 100644 index 00000000..5d205ae9 --- /dev/null +++ b/rules/rpl.ld @@ -0,0 +1,66 @@ +OUTPUT_FORMAT("elf32-powerpc") +OUTPUT_ARCH(powerpc:common) + +ENTRY(_start) + +MEMORY { + system (rw) : ORIGIN = 0x01000000, LENGTH = 32M + code (rwx) : ORIGIN = 0x02000000, LENGTH = 224M + data (rw) : ORIGIN = 0x10000000, LENGTH = 800M +} + +PHDRS { +} + +SECTIONS { + . = ORIGIN(code); + + /* Standard code section */ + .text . : { *(.text .stub .text.*) } + + /* + * Trampolines for each RPL function, have the same symbol name of + * than the function they should import. + * + * There will be 2 relocations in each trampoline pointing to the + * function stub inside the .data.rplFuncStubs, we can edit these + * relocation entries to use the RPL import during conversion to RPL. + * + * li r0, func_stub@lo -> .data.rplFuncStubs + * oris r0, func_stub@hi -> .data.rplFuncStubs + * mtctr r0 + * bctr + */ + .rplTramp.text . : { + *(.rplTramp.text) + *(SORT(.rplTramp.text.*)) + } + + /* Standard data sections */ + . = ORIGIN(data); + + .rodata . : { *(.rodata .rodata.*) } + .data . : { *(.data) } + .bss . : { *(.bss) } + + /* System stuff is for our elf2rpl converter to go through */ + . = ORIGIN(system); + + /* + * Contains the name of RPLs, referenced by .lib.rplLibs + */ + .rodata.rplNames . : { KEEP (*(.rodata.rplNames)) } + + /* + * List of RPL libraries to import, in format: + * uint32_t nameAddress -> .rodata.rplNames + * uint32_t firstFuncEntry -> .data.rplFuncStubs + */ + .lib.rplLibs . : { KEEP (*(.lib.rplLibs)) } + + /* + * List of functions an RPL exports, in format: + * uint32_t trampAddress + */ + .data.rplFuncStubs . : { KEEP (*(.data.rplFuncStubs)) } +} diff --git a/rules/rpl.mk b/rules/rpl.mk new file mode 100644 index 00000000..08a3f8d2 --- /dev/null +++ b/rules/rpl.mk @@ -0,0 +1,12 @@ +LIBPATHS := -L$(WUT_ROOT)/lib +CFLAGS := -I$(WUT_ROOT)/include -fno-builtin -ffreestanding +CXXFLAGS := $(CFLAGS) +LDFLAGS := -nostdlib -nostartfiles $(WUT_ROOT)/lib/crt0.o -T $(WUT_ROOT)/rules/rpl.ld + +include $(WUT_ROOT)/rules/base.mk + +%.rpx: %.elf + @$(STRIP) $< -o $(BUILDDIR)/$(notdir $<) + +%.rpl: %.elf + @$(STRIP) $< -o $(BUILDDIR)/$(notdir $<)