From aa9bb6e81b81273cf8487e49acc5afc6443142f6 Mon Sep 17 00:00:00 2001 From: Carl-Daniel Hailfinger Date: Tue, 4 Dec 2007 22:42:38 +0000 Subject: [PATCH] Absolute calls from initram were only working from the file which had _MAINOBJECT #defined. Calls from all other files ended up in nirvana because the compiler was not able to calculate the address of the wrapper for the absolute call. The linker tried, but failed miserably. Use the -combine flag and compile all of initram at once. This enables GCC to calculate the address of the abscall wrapper, resulting in working code. Segher Boessenkool thinks the patched code works only by accident because GCC has no way to specify generation of XIP code. According to him, future GCC versions or other circumstances may break the code. While this patch makes code work for now, it does NOT check whether the generated code tries to write to memory outside the stack (general writable data). That will of course fail, but I hope porters are smart enough to avoid that. Corey Osgood writes: Great work tracking this down! This is okay for now, but we need to look for a better solution in the future. Counting on porters who may or may not remember this discussion to avoid something isn't good future-proofing. Checking the ELF sections for read-write data and stopping the build with an error could make this future-proof. Signed-off-by: Carl-Daniel Hailfinger Acked-by: Corey Osgood git-svn-id: svn://coreboot.org/repository/LinuxBIOSv3@537 f3766cd6-281f-0410-b1cd-43a5c92072e9 --- Rules.make | 10 ---------- arch/x86/Makefile | 14 ++++++++------ arch/x86/stage1.c | 6 +++--- mainboard/adl/msm800sev/Makefile | 8 ++++---- mainboard/amd/norwich/Makefile | 8 ++++---- mainboard/artecgroup/dbe61/Makefile | 4 ++-- mainboard/emulation/qemu-x86/Makefile | 4 ++-- mainboard/pcengines/alix1c/Makefile | 6 +++--- 8 files changed, 26 insertions(+), 34 deletions(-) diff --git a/Rules.make b/Rules.make index 715df428e4..79744cb4b9 100644 --- a/Rules.make +++ b/Rules.make @@ -78,13 +78,3 @@ $(obj)/southbridge/%.o: $(src)/southbridge/%.c $(obj)/statictree.h $(Q)printf " CC $(subst $(shell pwd)/,,$(@))\n" $(Q)$(CC) $(INITCFLAGS) -c $< -o $@ -# -# RAM initialization code can not be linked at a specific address, -# hence it has to be executed in place (XIP) position independently. -# - -$(obj)/%_xip.o: $(src)/%.c - $(Q)mkdir -p $(dir $@) - $(Q)printf " CC $(subst $(shell pwd)/,,$(@)) (XIP)\n" - $(Q)$(CC) $(INITCFLAGS) -D_SHARED -fPIE -c $< -o $@ - diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 5a64e63f0d..6d30257812 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -36,7 +36,7 @@ SILENT := >/dev/null 2>&1 ROM_SIZE := $(shell expr $(CONFIG_LINUXBIOS_ROMSIZE_KB) \* 1024) -LARFILES := nocompress:normal/initram.o normal/stage2.o nocompress:normal/option_table +LARFILES := nocompress:normal/initram normal/stage2.o nocompress:normal/option_table ifneq ($(CONFIG_PAYLOAD_NONE),y) LARFILES += normal/payload endif @@ -57,11 +57,11 @@ ifeq ($(CONFIG_DEFAULT_COMPRESSION_NRV2B),y) COMPRESSFLAG := -C nrv2b endif -$(obj)/linuxbios.rom $(obj)/linuxbios.map: $(obj)/linuxbios.bootblock $(obj)/util/lar/lar lzma nrv2b $(obj)/linuxbios.initram.o $(obj)/linuxbios.stage2.o $(obj)/option_table +$(obj)/linuxbios.rom $(obj)/linuxbios.map: $(obj)/linuxbios.bootblock $(obj)/util/lar/lar lzma nrv2b $(obj)/linuxbios.initram $(obj)/linuxbios.stage2.o $(obj)/option_table $(Q)rm -rf $(obj)/lar.tmp $(Q)mkdir $(obj)/lar.tmp $(Q)mkdir $(obj)/lar.tmp/normal - $(Q)cp $(obj)/linuxbios.initram.o $(obj)/lar.tmp/normal/initram.o + $(Q)cp $(obj)/linuxbios.initram $(obj)/lar.tmp/normal/initram $(Q)cp $(obj)/linuxbios.stage2.o $(obj)/lar.tmp/normal/stage2.o $(Q)cp $(obj)/option_table $(obj)/lar.tmp/normal/option_table ifeq ($(CONFIG_PAYLOAD_NONE),y) @@ -232,12 +232,14 @@ $(obj)/arch/x86/geodelx/stage0.o: $(src)/arch/x86/geodelx/stage0.S $(Q)printf " AS $(subst $(shell pwd)/,,$(@))\n" $(Q)$(AS) $(obj)/arch/x86/stage0_asm.s -o $@ -$(obj)/linuxbios.initram.o $(obj)/linuxbios.initram.map: $(obj)/stage0.init $(obj)/stage0-prefixed.o $(patsubst %.o,%_xip.o,$(INITRAM_OBJ)) +$(obj)/linuxbios.initram $(obj)/linuxbios.initram.map: $(obj)/stage0.init $(obj)/stage0-prefixed.o $(INITRAM_OBJ) + $(Q)printf " CC $(subst $(shell pwd)/,,$(@)) (XIP)\n" + $(Q)$(CC) $(INITCFLAGS) -D_SHARED -fPIE -c -combine $(INITRAM_OBJ) -o $(obj)/linuxbios.initram_partiallylinked.o $(Q)# initram links against stage0 $(Q)printf " LD $(subst $(shell pwd)/,,$(@))\n" $(Q)$(LD) -Ttext 0 --entry main -N -R $(obj)/stage0-prefixed.o \ - $(patsubst %.o,%_xip.o,$(INITRAM_OBJ)) -o $(obj)/linuxbios.initram.o + $(obj)/linuxbios.initram_partiallylinked.o -o $(obj)/linuxbios.initram $(Q)printf " NM $(subst $(shell pwd)/,,$(@))\n" - $(Q)$(NM) $(obj)/linuxbios.initram.o | sort -u > $(obj)/linuxbios.initram.map + $(Q)$(NM) $(obj)/linuxbios.initram | sort -u > $(obj)/linuxbios.initram.map endif diff --git a/arch/x86/stage1.c b/arch/x86/stage1.c index e28aa38d5a..ae0d6c913c 100644 --- a/arch/x86/stage1.c +++ b/arch/x86/stage1.c @@ -137,17 +137,17 @@ void __attribute__((stdcall)) stage1_main(u32 bist) // find first initram if (check_normal_boot_flag()) { printk(BIOS_DEBUG, "Choosing normal boot.\n"); - ret = execute_in_place(&archive, "normal/initram.o/segment0"); + ret = execute_in_place(&archive, "normal/initram/segment0"); } else { printk(BIOS_DEBUG, "Choosing fallback boot.\n"); - ret = execute_in_place(&archive, "fallback/initram.o/segment0"); + ret = execute_in_place(&archive, "fallback/initram/segment0"); /* Try a normal boot if fallback doesn't exist in the lar. * TODO: There are other ways to do this. * It could be ifdef or the boot flag could be forced. */ if (ret) { printk(BIOS_DEBUG, "Fallback failed. Try normal boot\n"); - ret = execute_in_place(&archive, "normal/initram.o/segment0"); + ret = execute_in_place(&archive, "normal/initram/segment0"); } } diff --git a/mainboard/adl/msm800sev/Makefile b/mainboard/adl/msm800sev/Makefile index e20a41a59d..55eb337e01 100644 --- a/mainboard/adl/msm800sev/Makefile +++ b/mainboard/adl/msm800sev/Makefile @@ -21,10 +21,10 @@ STAGE0_MAINBOARD_OBJ := $(obj)/mainboard/$(MAINBOARDDIR)/stage1.o -INITRAM_OBJ = $(obj)/mainboard/$(MAINBOARDDIR)/initram.o \ - $(obj)/northbridge/amd/geodelx/raminit.o \ - $(obj)/southbridge/amd/cs5536/smbus_initram.o \ - $(obj)/arch/x86/geodelx/geodelx.o +INITRAM_OBJ = $(src)/mainboard/$(MAINBOARDDIR)/initram.c \ + $(src)/northbridge/amd/geodelx/raminit.c \ + $(src)/southbridge/amd/cs5536/smbus_initram.c \ + $(src)/arch/x86/geodelx/geodelx.c STAGE2_MAINBOARD_OBJ = diff --git a/mainboard/amd/norwich/Makefile b/mainboard/amd/norwich/Makefile index c91fe2df36..fba49834f1 100644 --- a/mainboard/amd/norwich/Makefile +++ b/mainboard/amd/norwich/Makefile @@ -21,10 +21,10 @@ STAGE0_MAINBOARD_OBJ := $(obj)/mainboard/$(MAINBOARDDIR)/stage1.o -INITRAM_OBJ = $(obj)/mainboard/$(MAINBOARDDIR)/initram.o \ - $(obj)/northbridge/amd/geodelx/raminit.o \ - $(obj)/southbridge/amd/cs5536/smbus_initram.o \ - $(obj)/arch/x86/geodelx/geodelx.o +INITRAM_OBJ = $(src)/mainboard/$(MAINBOARDDIR)/initram.c \ + $(src)/northbridge/amd/geodelx/raminit.c \ + $(src)/southbridge/amd/cs5536/smbus_initram.c \ + $(src)/arch/x86/geodelx/geodelx.c STAGE2_MAINBOARD_OBJ = diff --git a/mainboard/artecgroup/dbe61/Makefile b/mainboard/artecgroup/dbe61/Makefile index e44cd6f582..4c20b20131 100644 --- a/mainboard/artecgroup/dbe61/Makefile +++ b/mainboard/artecgroup/dbe61/Makefile @@ -21,8 +21,8 @@ STAGE0_MAINBOARD_OBJ := $(obj)/mainboard/$(MAINBOARDDIR)/stage1.o -INITRAM_OBJ = $(obj)/mainboard/$(MAINBOARDDIR)/initram.o \ - $(obj)/arch/x86/geodelx/geodelx.o +INITRAM_OBJ = $(src)/mainboard/$(MAINBOARDDIR)/initram.c \ + $(src)/arch/x86/geodelx/geodelx.c STAGE2_MAINBOARD_OBJ = diff --git a/mainboard/emulation/qemu-x86/Makefile b/mainboard/emulation/qemu-x86/Makefile index 548ded638f..00018a2372 100644 --- a/mainboard/emulation/qemu-x86/Makefile +++ b/mainboard/emulation/qemu-x86/Makefile @@ -28,8 +28,8 @@ STAGE0_MAINBOARD_OBJ := $(obj)/mainboard/$(MAINBOARDDIR)/stage1.o # directory and is built from what was auto.c in v2. # -INITRAM_OBJ = $(obj)/mainboard/$(MAINBOARDDIR)/initram.o \ - $(obj)/mainboard/$(MAINBOARDDIR)/initram_printktest.o +INITRAM_OBJ = $(src)/mainboard/$(MAINBOARDDIR)/initram.c \ + $(src)/mainboard/$(MAINBOARDDIR)/initram_printktest.c STAGE2_MAINBOARD_OBJ = vga.o diff --git a/mainboard/pcengines/alix1c/Makefile b/mainboard/pcengines/alix1c/Makefile index e6a2320e29..7e235327a8 100644 --- a/mainboard/pcengines/alix1c/Makefile +++ b/mainboard/pcengines/alix1c/Makefile @@ -21,9 +21,9 @@ STAGE0_MAINBOARD_OBJ := $(obj)/mainboard/$(MAINBOARDDIR)/stage1.o -INITRAM_OBJ = $(obj)/mainboard/$(MAINBOARDDIR)/initram.o \ - $(obj)/northbridge/amd/geodelx/raminit.o \ - $(obj)/arch/x86/geodelx/geodelx.o +INITRAM_OBJ = $(src)/mainboard/$(MAINBOARDDIR)/initram.c \ + $(src)/northbridge/amd/geodelx/raminit.c \ + $(src)/arch/x86/geodelx/geodelx.c STAGE2_MAINBOARD_OBJ =