jordan.crouse at amd.com
Sat Oct 6 00:28:07 CEST 2007
(This is a long e-mail. I apologize, but I feel this is important to
This week I've been working with LinuxBIOSv3 to try to get over the XIP
initram problem. For those that tuning in late, here's the recap:
There are some symbols that we use that we want to define once, and
use in different segments (such as printk). This is very easy to do
for segments that are loaded and run at a particular location in memory,
by passing in the symbol list from stage0 to LD through the -R command
line option, from which LD figures the right relative offsets.
The problem is, this is only easy if you know where your code is
executing, and pass the appropriate fu into LD. For most systems,
we need to run at least the initram segment in place on the ROM which
are not always located at a known location - there can be multiple
initram blocks, and LAR can put them anywhere it wishes. Needless to
say, this breaks things badly when we try to call functions in the bootblock
with a relative offset that walks into the weeds.
So my quest this week was to try to find a list of solutions that we
can consider as a group. The only criteria I had for a solution is that
it needed to maintain the independence of the individual segments (i.e. -
I couldn't just cheat and link the bootblock and initram together). Any
other legitimate solution was on the table, though obviously, the more
simple and obvious the better. Here's what I came up with:
Solution 1 - fixed locations
the -R trick to LD works for the XIP modules too, assuming that you link it
at the right address where it will execute in the ROM. The very simplest way
to do this would be to define fixed locations for the initram(s) and feed
those in to to LD (through a platform configuration). This would be
remotely similar to v2.
CONS: Completely breaks the LAR model, wastes ROM space, and really breaks
the whole v3 concept.
Solution 2 - relink the image
Like above, we use -R to pass in the symbols from stage0.
we link the image at an arbitrary address (say, 0x0), and
build it into the LAR. We can then ask LAR where it put the segment,
and then relink the segment at that address, and replace it in the LAR.
There may be other things we can do with LAR to make this easier - perhaps
just pass in the sizes of the segments to LAR and have it return the offsets
without actually constructing an archive, perhaps?
PROS: Fits in the v3 model
CONS: Complex, and relies on some scripts to do the right thing with LAR.
Also, its confusing to relink twice.
Solution 3 - postlinker
Again, we use -R to pass in the symbols from stage0 and link the segment
to 0x0. But instead of re-linking when we learn the address, we run
a special utility that will read the relocation tables in the ELF and
update the addresses in the ELF. This should be somewhat more lightweight
then re-linking. The same problems with LAR still exist here -
the key is finding out the address we need to link to.
PROS: Fits into the v3 model, less complex then relinking
CONS: Finding the address from LAR will be a challenge. Plus its another
custom utility to maintain.
Solution 3.5 - postlinker + symbol table
One CON for all of these is that each solution requires us to have the
stage0.o ELF file laying around. To me, that sort of defeats the purpose
of independence. So the 4th option is similar to the 3rd (and suffers from
the same problems), but instead of using -R to pass the symbols to LD
during the link stage, we leave the shared symbols undefined. Then,
we grab a list of shared symbols from stage0.o (which could easily be
a "published" list, and feed that into the custom script from above, which
could fill in the undefined shared symbols.
PROS: One could build an initram completely separate from
stage0 (which is the goal).
CONS: An extra stage of abstraction to get the symbol table. It would be
difficult to ensure that the symbol table matches the current bootblock.
Finding the address from the LAR remains a challenge. Custom utility.
I vote for #3 and possibly #4. I've spent some time writing the very
custom app described above, and I used it with a little manual
trickery to make the Geode boot through the initram stage (I'll send it
out in a separate e-mail). Figuring out the right address from LAR
will be the tricky part - for that i really don't have a good idea (I
build the lar with the un-modified initram, listed the lar, figured out the
address, ran my tool, and re-lared the new initram. I don't recommend
that method - too much possibility for failure).
So, why am I telling you this? Because I think the time is ripe for a
discussion - we know what needs to be done code wise, and we have a list
of options at our disposal, but the most important thing we need is
consensus. I don't want this to be some crazy scheme cooked up late at
night and snuck into the code base when nobody is looking.
Systems Software Development Engineer
Advanced Micro Devices, Inc.
More information about the coreboot