PKGDIR		?= ../..
L4DIR		?= $(PKGDIR)/../..

DEFAULT_RELOC_arm   := 0x01400000
DEFAULT_RELOC_x86   := 0x002d0000
DEFAULT_RELOC_amd64 := 0x002d0000

include $(L4DIR)/mk/Makeconf
-include $(OBJ_DIR)/Makeconf.local

SYSTEMS		:= x86 amd64 arm
ifeq ($(BUILD_ARCH),arm)
# ARM always uses single image mode
ENTRY		:= auto-build-entry
endif


PRIVATE_INCDIR	 = $(SRC_DIR) $(SRC_DIR)/ARCH-$(ARCH)

# special include directories only needed for <l4/sys/kernel.h>
PRIVATE_INCDIR_init_kip_v2.o      = $(OBJ_BASE)/include/$(ARCH)/l4v2 \
                                    $(DROPS_STDDIR)/include/$(ARCH)/l4v2
PRIVATE_INCDIR_init_arm_kip.o     = $(OBJ_BASE)/include/$(ARCH)/l4v2 \
                                    $(DROPS_STDDIR)/include/$(ARCH)/l4v2

TARGET		:= bootstrap
TARGET_BIN	 = $(TARGET)
MODE		 = tiny

SUPPORT_CC_arm-sa1000     := support_sa1000.cc
SUPPORT_CC_arm-pxa        := support_pxa.cc
SUPPORT_CC_arm-integrator := support_integrator.cc
SUPPORT_CC_arm-rv         := support_rv.cc

SRC_C		+= exec.c module.c patch.c
SRC_CC		+= region.cc startup.cc init_kip_v2.cc init_kip_v4.cc \
                   libc_support+.cc

SRC_CC_x86	+= support_x86.cc
SRC_CC_amd64	+= support_x86.cc
SRC_C_x86	+= serial.c base_critical.c
SRC_C_amd64	+= serial.c base_critical.c
SRC_CC_arm     	+= $(SUPPORT_CC_arm-$(ARM_PLATFORM_TYPE))

OPTS		 = -g -Os $(CARCHFLAGS_$(ARCH)) $(CARCHFLAGS_$(ARCH)_$(CPU))

MOD_ADDR         = 0x02000000
SRC_S		:= crt0.S
ifeq ($(ARCH),arm)
ifeq ($(ARM_PLATFORM_TYPE),)
$(error For ARM architecture builds, ARM_PLATFORM_TYPE must be set to some valid platform name)
endif
DRV_LIBS	+= -larm_uart
CPPFLAGS	+= -DARCH_arm_$(ARM_PLATFORM_TYPE)
endif
CRT0		 =
LDSCRIPT	 = bootstrap.ld
LDNMAGIC	 =

-include $(SRC_DIR)/Makeconf.$(ARM_PLATFORM_TYPE)

vpath serial.c        $(SRC_DIR)/ARCH-x86
vpath bootstrap.ld.in $(SRC_DIR)/ARCH-$(ARCH)
vpath crt0.S	      $(SRC_DIR)/ARCH-$(ARCH)

MODULE_PATH     ?= $(OBJ_BASE)/bin/$(SYSTEM)/$(BUILD_ABI)
MODULE_LIST     ?= $(SRC_DIR)/modules.list

# can be overwritten by Makeconf.local
COMPRESS	?= 0
LOADER_MBI	?= 0
REALMODE_LOADING ?= 0
RML		?= 0

ifneq ($(REALMODE_LOADING)$(RML),00)
REALMODE_LOADING := 1
endif

ifeq ($(ARCH),arm)
LOADER_MBI	 := 1
CPPFLAGS         += -DSINGLE_SECTION
endif


# convenience
ifneq ($(E),)
ENTRY		:= $(E)
endif

ifneq ($(ENTRY),)
TARGET		:= bootstrap.image
INSTALL_TARGET	+= bootstrap_$(ENTRY) bootstrap.image
bootstrap_$(ENTRY): bootstrap.stripped
	$(VERBOSE)ln -f $< $@
endif

ifneq ($(REALMODE_LOADING),0)
LOADER_MBI	 = 1
CPPFLAGS	+= -DREALMODE_LOADING -DSINGLE_SECTION
# don't install bootstrap_$(ENTRY)
INSTALL_TARGET	 = bootstrap.load
endif

ifneq ($(LOADER_MBI),0)
SRC_CC		+= loader_mbi.cc
MOD_ADDR	 = 0x00150000
CPPFLAGS	+= -DLOADER_MBI
endif

ifneq ($(COMPRESS),0)
SRC_C		+= uncompress.c gunzip.c
CPPFLAGS	+= -DCOMPRESS
else
CPPFLAGS	+= -DPLACE_MODULES_AT_MODADDR
endif

ifneq ($(RAM_SIZE_MB),)
CPPFLAGS	+= -DRAM_SIZE_MB=$(RAM_SIZE_MB)
endif

ifeq ($(ARCH),arm)
BOOTSTRAP_RAW	:= bootstrap.raw
endif

ifeq ($(ARCH),amd64)
all:: libc32.a bootstrap32
INSTALL_TARGET	:= bootstrap32
TARGET_BIN	:= bootstrap32
endif

include $(L4DIR)/mk/prog.mk

CXXFLAGS += -fno-rtti -fno-exceptions
CXXFLAGS += $(call checkcxx,-fno-threadsafe-statics)

ifneq ($(SYSTEM),)
 ifneq ($(ENTRY),)
  ifeq ($(filter clean cleanall,$(MAKECMDGOALS)),)
    BUILD_DUMMY := $(shell SEARCHPATH=$(BOOTSTRAP_SEARCH_PATH):$(MODULE_PATH) \
                           CROSS_COMPILE=$(SYSTEM_TARGET) \
			   OPT_ARCH=$(ARCH) \
			   OPT_COMPRESS=$(COMPRESS) \
                           $(SRC_DIR)/build.pl $(MODULE_LIST) $(ENTRY) 2>&1 | tee build.log 1>&2 \
                     || echo X-build-failed-X)
    ifeq ($(BUILD_DUMMY),X-build-failed-X)
     $(error Processing of module list failed!)
    else
     BUILD_DUMMY := $(shell echo $(BUILD_DUMMY))
    endif
    # mod.make.inc is generated by build.pl
    include mod.make.inc
  endif

  OBJS_bootstrap.image += $(MODULE_OBJECT_FILES)
  CPPFLAGS             += -DIMAGE_MODE
  BOOTSTRAP_LD_dep     := mod.make.inc
  STARTUP_C_dep        := mod.make.inc
 endif
endif

CPPFLAGS	+= -DMODADDR=$(MOD_ADDR)

L4LIBS		 = $(DRV_LIBS) -lcxx_base -lcxx_io

LIBCLIBS	 = -nostdlib $(GCCLDNOSTDLIB) -ll4util -luc_c $(GCCLIB)

SRC_C		+= $(LIBC_SUPPORT_C_$(ARCH)) \
		   $(LIBC_SUPPORT_C_$(ARCH)-$(ARM_PLATFORM_TYPE))

ifneq ($(SYSTEM),)

all:: $(BOOTSTRAP_RAW) bootstrap.stripped

# image for use with pxelinux
bootstrap.load: $(TARGET_BIN) bootsect.o.img setup.o.img
	@$(GEN_MESSAGE)
	$(VERBOSE)objcopy -O binary -R .note -R .comment -S $< $<.load.bin
	$(VERBOSE)cat bootsect.o.img setup.o.img $<.load.bin > $@

bootsect.o.img: ARCH-x86/bootsect.S Makefile
	@$(GEN_MESSAGE)
	$(VERBOSE)$(CC) -traditional -nostdinc -nostdlib -c $<
	$(VERBOSE)$(LD) -m elf_i386 -Ttext 0x0 -o $@ -s --oformat binary \
	  bootsect.o
	$(VERBOSE)chmod -x $@

setup.o.img: ARCH-x86/setup.S Makefile
	@$(GEN_MESSAGE)
	$(VERBOSE)$(CC) -traditional -nostdinc -nostdlib -DARCH_$(ARCH) -c $<
	$(VERBOSE)$(LD) -m elf_i386 -Ttext 0x0 -o $@ -s --oformat binary \
	  -e begtext setup.o
	$(VERBOSE)dd if=/dev/zero bs=1 count=$$((3072 - `wc -c < setup.o.img`)) >> setup.o.img 2> /dev/null
	$(VERBOSE)chmod -x $@

# raw version without ELF, primarily useful for ARM
$(BOOTSTRAP_RAW): $(TARGET_BIN)
	@$(GEN_MESSAGE)
	$(VERBOSE)cp $< $@.tmp
	$(VERBOSE)$(OBJCOPY) -O binary $@.tmp $@
	$(VERBOSE)$(RM) $@.tmp

# stripped version of bootstrap
bootstrap.stripped: $(TARGET_BIN)
	@$(GEN_MESSAGE)
	$(VERBOSE)$(OBJCOPY) -S $< $@

endif

$(TARGET): $(LDSCRIPT) $(OBJS_$(TARGET))

startup.o: $(STARTUP_C_dep)

$(LDSCRIPT): $(LDSCRIPT).in $(SRC_DIR)/Makefile $(BOOTSTRAP_LD_dep)
	@$(GEN_MESSAGE)
	$(VERBOSE)cpp -P $(CPPFLAGS) -DLINKADDR=$(DEFAULT_RELOC_$(ARCH)) $< $@;

ifneq ($(SYSTEM),)

clean::
	$(VERBOSE)$(RM) mod.make.inc mod*.bin mbi_modules.bin $(LDSCRIPT)
	$(VERBOSE)$(RM) setup.o.img bootsect.o.img
	$(VERBOSE)$(RM) mod*.bin
	$(VERBOSE)$(RM) $(SRC32_C:.c=.o32) $(SRC32_S:.S=.o32)

cleanall::
	$(VERBOSE)$(RM) bootstrap_* bootstrap.*

endif

ifeq ($(ARCH),amd64)

vpath %.c             $(SRC_DIR)/ARCH-amd64
vpath %.S             $(SRC_DIR)/ARCH-amd64
vpath %.c             $(SRC_DIR)/ARCH-amd64/boot32
vpath %.S             $(SRC_DIR)/ARCH-amd64/boot32
vpath bootstrap.ld.in $(SRC_DIR)/ARCH-x86

SRC32_C		 = boot_cpu.c boot_kernel.c load_elf.c minilibc_support.c
SRC32_S		 = boot.S boot_idt.S
OBJ32		 = $(SRC32_S:.S=.o32) $(SRC32_C:.c=.o32)
CC32		 = $(filter-out -m64, $(CC))
CFLAGS32	:= $(filter-out -m64, $(CFLAGS)) -m32

.PHONY: libc32.a
libc32.a:
	$(VERBOSE)$(MAKE) O=$(OBJ_BASE) -C $(SRC_DIR)/ARCH-amd64/libc32

bootstrap32: $(OBJ32) bootstrap32.bin $(OBJ_DIR)/ARCH-amd64/libc32/OBJ-$(ARCH)_$(CPU)/libc32.a
	@$(LINK_MESSAGE)
	$(VERBOSE)$(CC32) -o $@ -nostdlib -static \
	  -Wl,-T,$(SRC_DIR)/ARCH-amd64/boot32/bootstrap32.ld,--gc-sections $^ -lgcc
	$(VERBOSE)chmod 755 $@

bootstrap32.bin: $(TARGET)
	@$(GEN_MESSAGE)
	$(VERBOSE)$(OBJCOPY) -S $< bootstrap64.bin
	$(VERBOSE)chmod -x bootstrap64.bin
	$(VERBOSE)$(OBJCOPY) -B i386 -I binary -O elf32-i386 bootstrap64.bin $@

%.o32: %.c
	@$(COMP_MESSAGE)
	$(VERBOSE)$(CC32) -o $@ -c $(DEPEND_FLAG) \
	  $(CPPFLAGS) $(CFLAGS32) $(call absfilename,$<)

%.o32: %.S
	@$(COMP_MESSAGE)
	$(VERBOSE)$(CC32) -o $@ -c $(DEPEND_FLAG) \
	  $(CPPFLAGS) $(CFLAGS32) $(call absfilename,$<)

clean cleanall::
	$(VERBOSE)PWD=$(call absfilename,$(SRC_DIR)/ARCH-amd64/libc32) \
	  $(MAKE) -C $(SRC_DIR)/ARCH-amd64/libc32 $@

endif
