diff options
author | Gabe Black <gabeblack@google.com> | 2011-05-23 17:54:29 -0700 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2011-08-29 10:39:14 -0700 |
commit | f961aa5af3fa2d12fb1d273a17694bde4b64d6a0 (patch) | |
tree | c199c63704ba39ab88fa1a4c0c935d533a365bd2 /arch/x86 | |
parent | 309f8df51fc941523974b4b691686bba914583b5 (diff) |
Fix how the location of the realmode and bios blobs are calculated.
There are two blobs embedded into the u-boot image which are linked to run at
an address which is different from where they actually end up in the ROM, one
called "realmode" and one called "bios". There are realmode_setup and
bios_setup functions which prepare those blobs by copying them into the
location they're supposed to run from, among other things.
During u-boot relocation from ROM to RAM, the text and a few data segments are
copied over. The realmode and bios sections are not copied, and so the only
place they can be read from is their original location in the ROM. Looking
specifically at the bios blob, there are symbols defined in the linker script
called __bios_start and __bios_size which are defined to be the start and size
of the blob in the ROM.
In the bios_setup function, there seem to be two mistakes happening. First,
the offset from ROM to RAM is being added to __bios_start which implies that
this code expects to use the copy moved to RAM. No such copy is made, so that's
wrong. More subtly, when u-boot relocates itself, it goes through all of the
relocations stored in .rel.dyn and fixes them up. This has the effect of
transforming the __bios_start reference in bios_setup so that it refers to the
version in RAM (if one existed) instead of the one in ROM. To correct for that,
the offset actually needs to be subtracted out again to translate the address
back into the ROM.
The net effect is that for both blobs, a + needs to be changed to a -.
BUG=chrome-os-partner:3905
TEST=Built coreboot u-boot.
Signed-off-by: Gabe Black <gabeblack@google.com>
Change-Id: I7480ddfe4c4d67b012b92850438145fbf47ca376
Reviewed-on: http://gerrit.chromium.org/gerrit/2157
Reviewed-by: Stefan Reinauer <reinauer@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Gabe Black <gabeblack@chromium.org>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/lib/bios_setup.c | 6 | ||||
-rw-r--r-- | arch/x86/lib/realmode.c | 6 |
2 files changed, 10 insertions, 2 deletions
diff --git a/arch/x86/lib/bios_setup.c b/arch/x86/lib/bios_setup.c index 6949b35069b..5837fde6ee4 100644 --- a/arch/x86/lib/bios_setup.c +++ b/arch/x86/lib/bios_setup.c @@ -140,7 +140,11 @@ static void setvector(int vector, u16 segment, void *handler) int bios_setup(void) { - ulong bios_start = (ulong)&__bios_start + gd->reloc_off; + /* + * The BIOS section is not relocated and still in the ROM. The + * __bios_start symbol was adjusted, though, so adjust it back. + */ + ulong bios_start = (ulong)&__bios_start - gd->reloc_off; ulong bios_size = (ulong)&__bios_size; static int done=0; diff --git a/arch/x86/lib/realmode.c b/arch/x86/lib/realmode.c index d244cfabed8..43f0e9a5b8e 100644 --- a/arch/x86/lib/realmode.c +++ b/arch/x86/lib/realmode.c @@ -34,7 +34,11 @@ extern char realmode_enter; int realmode_setup(void) { - ulong realmode_start = (ulong)&__realmode_start + gd->reloc_off; + /* + * The realmode section is not relocated and still in the ROM. The + * __realmode_start symbol was adjusted, though, so adjust it back. + */ + ulong realmode_start = (ulong)&__realmode_start - gd->reloc_off; ulong realmode_size = (ulong)&__realmode_size; /* copy the realmode switch code */ |