On 20.11.2007 14:14, Stefan Reinauer wrote:
- Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net [071120 11:46]:
The reason is similar for all of them: include/console.h specifies
void post_code(u8 value);
include/post_code.h specifies (because _SHARED is defined)
void stage0_post_code(u8 value) ; void (*post_code)(u8 value) = stage0_post_code;
Of course these definitions do conflict.
This issue seems trivial. include/console.h must not define a prototype for post_code. I wonder how that double definition sneaked.
Because simply deleting it causes compilation problems somewhere else?
- The conflicting post_code() definitions above are not alone, the same
happens for printk.
How so? I could not find a printk prototype in any other file. Where's the bad part?
Maybe I mixed that up with the multiple printk definitions below.
- If you remove post_code() from include/console.h everywhere
post_code() is shared, you encounter the next problem: If two files with _SHARED are linked together, each of them will contain the assignment (*post_code)=stage0_post_code, resulting in linker errors because a symbol appears twice.
This is interesting. I never had any of these problems and I have been testing that code quite a bit. What distribution and what toolchain are you using?
openSUSE 10.3 (i386) gcc (GCC) 4.2.1 (SUSE Linux) GNU ld (GNU Binutils) 2.17.50.20070726-14 (SUSE Linux)
- Even if you manage to avoid all the problems above, a new problem
arises: We have to build a LAR archive in one continuous flow because we can't extract the location of the stage0 symbols from an existing bootblock in a LAR archive and thus can't link initram and stage2 against an existing bootblock. Because of that, we never can do partial BIOS updates, which defeats the whole purpose of LAR.
Wait: You can not change the toolchain nor the version of the bootblock in between. This is only a rather small limitation. But its not very elegant, I agree.
My point was: For a given bootblock, we can't build the rest of the ROM based on the bootblock alone because it has been stripped of symbols.
Which is why I suggested a function pointer array with defined function pointers at fixed, defined offsets. Yes. This means we have to define an interface, something the Linux guys really hate.
I see no way around a function pointer array. However, we could avoid the fixed offsets if we use the same technology the Linux kernel uses for its symbol tables.
The Amiga did a very similar thing. All functions in a shared library would be available through a function pointer array. The callable functions would be defined through the library version. So a program could always react on finding a too old or not-existing library sanely instead of just spitting out a linker error like our unix/elf based systems do these days.
That's probably overkill.
Suggestions for solving the problems mentioned above:
- Always wrap shared function definitions in SHARED macros.
yes. this is how it should be done.
Can you prepare a patch?
- Make sure the assignment "ret (*func)(args) attr= stage0_##func"
happens only once per final linked object.
agreed.
That will get messy. Maybe move the assignment to a separate object which is linked to the final object?
- Include a .map file of shared stage0 functions in the LAR.
My first thought. but the map file is not sufficient for linking with those symbols. You need the object file for that. Which is bad.
Can we recreate an object file from the map file? Or can we avoid stripping all symbols from stage0/1?
Regards, Carl-Daniel