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. #
$(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 $@ + $(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.
Index: lib/lar.c =================================================================== --- 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); return 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.
Regards, Carl-Daniel