[LinuxBIOS] v3: an interesting problem with initram
c-d.hailfinger.devel.2006 at gmx.net
Mon Nov 26 15:24:38 CET 2007
On 26.11.2007 08:24, ron minnich wrote:
> Initram is being set up as follows:
> 08048074 T spd_read_byte
> 080480e0 T main
> 08048145 T __i686.get_pc_thunk.bx
> note that spd_read_byte is first. And it's entered first and that's
> bad, as main is supposed to be entered. I tried the simple thing of
> reordering the functions in the file, and that did not do it.
Try this in combination with having main first in the file:
--- Rules.make (Revision 518)
+++ Rules.make (Arbeitskopie)
@@ -81,10 +81,11 @@
# RAM initialization code can not be linked at a specific address,
# hence it has to be executed in place position independently.
+# -fno-toplevel-reorder is here to work around a linker bug.
$(Q)mkdir -p $(dir $@)
$(Q)printf " CC $(subst $(shell pwd)/,,$(@)) (XIP)\n"
- $(Q)$(CC) $(INITCFLAGS) -D_SHARED -fPIE -c $< -o $@
+ $(Q)$(CC) $(INITCFLAGS) -fno-toplevel-reorder -save-temps -D_SHARED -fPIE -c $< -o $@
While the problem we see is not a gcc bug, this can help to workaround
the bug partially.
> So, why is spd_read_byte first in the file, and how do we fix it?
> Because the call from the rom code is going to spd_read_byte, not
> main, and I'm stuck :-)
Linking build/linuxbios.initram.o gives us code which is still correct
and contains all necessary sections and has the right entry point.
Then we invoke
objcopy -O binary build/linuxbios.initram.o build/linuxbios.initram
and that objcopy leaves us with a binary object. Where exactly in that
binary object do we store the entry point?
Exactly. Nowhere. So LAR has no place to get the entry point. However,
lib/lar.c also does not care about the entry point for execution at all
if you call run_file() or execute_in_place(), it simply starts execution
at the beginning of the LAR member. That works as long as main() happens
to be exactly at the start of the binary object. Badbadbad.
This patch should clarify what happens.
--- lib/lar.c (Revision 518)
+++ lib/lar.c (Arbeitskopie)
@@ -232,6 +232,8 @@
* Given a file name in the LAR , search for it, and load it into memory,
* using the passed-in pointer as the address; jump to the file.
* If the passed-in pointer is (void *)-1, then execute the file in place.
+ * BIG FAT WARNING: run_file uses the beginning of the file as entry point
+ * and does NOT care about the entry member of the LAR header!
* @param archive A descriptor for current archive.
* @param filename filename to find
* @param where pointer to where to load the data
@@ -265,7 +267,7 @@
where = result.start;
- printk(BIOS_SPEW, "where is %p\n", where);
+ printk(BIOS_SPEW, "where is %p, not honoring entry point specified in archive\n", where);
ret = run_address(where);
printk(BIOS_SPEW, "run_file returns with %d\n", ret);
We now have two choices:
* make sure main() is always at the start of the binary object both for
initram and stage2 or
* honor the entry point specified in the LAR header.
I vote for the second choice, but that means we can't feed the lar
utility binary objects anymore without additional "entry" parameters.
More information about the coreboot