Bug #78
closed
Skylake ramstage crashes if CONFIG_RELOCATABLE_RAMSTAGE is selected
Added by Trammell Hudson about 8 years ago.
Updated over 7 years ago.
Description
As discussed on the mailing list: https://www.coreboot.org/pipermail/coreboot/2016-October/082121.html
Skylake (the Chell Chromebook) reboots following the LGDT
instruction in the ramstage entry if it is built as relocatable.
CBFS: 'Master Header Locator' located CBFS at [a00100:ffffc0)
CBFS: Locating 'fallback/ramstage'
CBFS: Found @ offset afc0 size 12e29
Decompressing stage fallback/ramstage @ 0x7abbffc0 (743408 bytes)
Loading module at 7abc0000/7abc0000 with entry 7abc0000. filesize: 0x28d88 memsize: 0xb57b0
Processing 2472 relocs. Offset value of 0x7aac0000
src/arch/x86/boot.c:223: jumping to 7abc0000
(and then it crashes, asserting LPC reset and rebooting)
Aaron Durbin suggested disabling CONFIG_RELOCATABLE_RAMSTAGE
, but CONFIG_SOC_INTEL_SKYLAKE
forces the relocatable ramstage flag. I've modified src/soc/intel/skylake/Kconfig
to not select it and now coreboot makes it all the way into the Linux payload. By adding the i915 framebuffer driver to the Linux kernel, it is able to bring up the console in a miniscule font! https://www.flickr.com/photos/osr/30026718432/in/photostream/lightbox/
I responded with these suggestions to attempt to further debug:
I don't understand that behavior at all. When you objdump -d -r -S
ramstage.debug do you see the ljmp instruction?
You can dump the ramstage relocations (with is still enabled) by changing
#define PK_ADJ_LEVEL BIOS_DEBUG
in src/lib/rmdoule.c.
The ramstage.debug looks fine:
Disassembly of section .text:
00100000 <_program>:
#else
.code32
#endif
.globl _start
_start:
cli
100000: fa cli
lgdt %cs:gdtaddr
100001: 2e 0f 01 15 1f 01 10 lgdtl %cs:0x10011f
100008: 00
100005: R_386_32 .text
#ifndef __x86_64__
ljmp $0x10, $1f
100009: ea 10 00 10 00 10 00 ljmp $0x10,$0x100010
10000a: R_386_32 .text
#endif
...
Something appears to be wrong in the relocation code -- it appears to be stuck on the first address rather than updating the other relocations.
Decompressing stage fallback/ramstage @ 0x7abbffc0 (743408 bytes)
src/lib/rmodule.c:310
src/lib/rmodule.c:314
Loading module at 7abc0000/7abc0000 with entry 7abc0000. filesize: 0x28d88 memsize: 0xb57b0
Processing 2472 relocs. Offset value of 0x7aac0000
Adjusting 7aac0000: 0x5a5a5a5a -> 0xd5065a5a
Adjusting 7aac0000: 0xd5065a5a -> 0x4fb25a5a
Adjusting 7aac0000: 0x4fb25a5a -> 0xca5e5a5a
Adjusting 7aac0000: 0xca5e5a5a -> 0x450a5a5a
Adjusting 7aac0000: 0x450a5a5a -> 0xbfb65a5a
Adjusting 7aac0000: 0xbfb65a5a -> 0x3a625a5a
Adjusting 7aac0000: 0x3a625a5a -> 0xb50e5a5a
Adjusting 7aac0000: 0xb50e5a5a -> 0x2fba5a5a
...
The SMM relocation looks fine, however:
Loading module at 00038000/00124a6c with entry 00038000. filesize: 0x160 memsize: 0x160
Processing 10 relocs. Offset value of 0x00038000
Adjusting 00038002: 0x00000024 -> 0x00038024
Adjusting 0003801d: 0x0000003c -> 0x0003803c
Adjusting 00038026: 0x00000024 -> 0x00038024
Adjusting 00038054: 0x000000d8 -> 0x000380d8
Adjusting 00038066: 0x00000160 -> 0x00038160
Adjusting 0003806d: 0x000000c0 -> 0x000380c0
Adjusting 00038075: 0x000000c4 -> 0x000380c4
Adjusting 0003807e: 0x000000d0 -> 0x000380d0
Adjusting 00038085: 0x000000cc -> 0x000380cc
Adjusting 0003808b: 0x000000c8 -> 0x000380c8
SMM Module: stub loaded at 00038000. Will call 00112e17(00000000)
Installing SMM handler to 0x7b000000
Decompressing stage fallback/ramstage @ 0x7abbffc0 (743408 bytes)
src/lib/rmodule.c:329
src/lib/rmodule.c:333
Loading module at 7abc0000/7abc0000 with entry 7abc0000. filesize: 0x28f88 memsize: 0xb57b0
Processing 2482 relocs @ 7abe8f88. Offset value of 0x7aac0000
module->location=7abc0000
module->header->module_link_start_address=00100000
7abe8f88: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
...
7abc0000: fa 2e 0f 01 15 1f 01 10 00 ea 10 00 10 00 10 00 ................
7abc0010: b8 18 00 00 00 8e d8 8e c0 8e d0 8e e0 8e e8 b0 ................
7abc0020: 13 e6 80 fc 8d 3d 00 90 12 00 b9 00 10 13 00 29 .....=.........)
7abc0030: f9 c1 e9 02 b8 ef be ad de f3 ab bc 00 10 13 00 ................
Adding hexdumps of the regions, the code appears to be correctly mapped (fa 2e 0f... are the first instructions in the .program text segment). However the .relocs section does not appear to be correctly populated in memory.
According to readelf, the .relocs should start at offset 0x02afc8 in the file, although it appears that the module->relocations offset is 0x28ff8 (i.e., directly after the .program section):
readelf -S ramstage.elf
There are 8 section headers, starting at offset 0x34:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .shstrtab STRTAB 00000000 000194 00003b 00 0 0 0
[ 2] .strtab STRTAB 00000000 001000 001000 00 0 0 1
[ 3] .symtab NULL 00000000 002000 000000 10 0 0 4
[ 4] .header PROGBITS 00000000 002000 000040 00 WAX 0 0 0
[ 5] .program PROGBITS 00000040 002040 028f88 00 WAX 0 0 0
[ 6] .relocs PROGBITS 00028fc8 02afc8 0026c8 00 WAX 0 0 0
[ 7] .empty NOBITS 0002b690 02d690 08a160 00 A 0 0 0
Oops. This is my own bug.
A while ago I added code to rmodule_copy_payload() to ensure that the SMM region was entirely zeroed, but this does not take into account the reloc section, only the code section. This needs to be re-considered:
static void rmodule_copy_payload(const struct rmodule *module)
{
const size_t mem_size = rmodule_memory_size(module);
printk(BIOS_DEBUG, "Loading module at %p/%p with entry %p. "
"filesize: 0x%x memsize: 0x%zx\n",
module->location, module->payload, rmodule_entry(module),
module->payload_size, mem_size);
// zero the excess memory if there is any
if (mem_size > module->payload_size)
{
memset((uint8_t*) module->location + module->payload_size,
0,
mem_size - module->payload_size
);
}
/* No need to copy the payload if the load location and the
* payload location are the same. */
if (module->location == module->payload)
return;
memcpy(module->location, module->payload, module->payload_size);
}
If you want to zero out memory you need to do it after the rmodule has been loaded. However, that zero'ing of memory is largely taken care of in the normal load path.
- Status changed from New to Rejected
Do I read it correctly that this bug was never upstream?
Also available in: Atom
PDF