cbfstool: autocreate trampoline

Add the code necessary to create the linux trampoline blob.
Don't enforce this for the in-coreboot build or use objcopy
to produce linux_trampoline.o as it is a bit trickier to get
all the details right than I had hoped:
 - you have to know the elf architecture of the host machine
 - you might have to have more tools (xxd, perl, etc) installed

Change-Id: I9b7877c58d90f9fb21d16e0061a31e19fffa2470
Signed-off-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Reviewed-on: https://review.coreboot.org/12505
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Stefan Reinauer 2015-11-20 17:58:59 +01:00
parent cbce4de976
commit 0316e1a69f
3 changed files with 159 additions and 160 deletions

View File

@ -4,6 +4,7 @@ objutil ?= $(top)/util
CONFIG_FMD_GENPARSER := y
HOSTCC ?= $(CC)
OBJCOPY ?= objcopy
.PHONY: all
all: $(objutil)/cbfstool/cbfstool \
@ -17,6 +18,18 @@ clean:
$(RM) $(objutil)/cbfstool/fmaptool $(fmapobj)
$(RM) $(objutil)/cbfstool/rmodtool $(rmodobj)
linux_trampoline.c: linux_trampoline.S
rm -f linux_trampoline.c
$(CC) -m32 -o linux_trampoline linux_trampoline.S -ffreestanding -nostdlib -nostdinc -Wl,--defsym=_start=0
$(OBJCOPY) -Obinary -j .data linux_trampoline trampoline
echo "/* This file is automatically generated. Do not manually change */" > trampoline.c
xxd -c 16 -i trampoline >> trampoline.c
perl -pi -e 's,unsigned int.*$$,,g;s,unsigned char,const unsigned char,g' trampoline.c
echo "const void * const trampoline_start = &trampoline;" >> trampoline.c
echo "const unsigned long trampoline_size = sizeof trampoline;" >> trampoline.c
mv trampoline.c linux_trampoline.c
rm linux_trampoline trampoline
.SILENT:
include Makefile.inc

View File

@ -0,0 +1,133 @@
/*
* linux_trampoline
*
* Copyright (C) 2013 Patrick Georgi <patrick@georgi-clan.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/* NOTE: THIS CODE MUST REMAIN POSITION INDEPENDENT
* IT SHOULDN'T USE THE STACK
* AND IN GENERAL EXPECT NOTHING BUT RAM TO WORK
*/
.code32
.data
#include "linux_trampoline.h"
#define HEADER_SIG 0x4f49424c // LBIO little endian
#define CB_TAG_FORWARD 0x11
#define CB_TAG_MEMORY 0x1
#define CB_TAG_FRAMEBUFFER 0x12
#define E820_NR_OFFSET 0x1e8
#define LINUX_ENTRY_OFFSET 0x214
#define E820_OFFSET 0x2d0
.trampoline_start:
cld
xor %edx, %edx
mov $0, %ecx
.headerSearch:
mov $0x10000, %ebx
add %ecx, %ebx
mov (%ecx), %eax
cmp $HEADER_SIG, %eax
je .headerSearchDone // found the header
add $16, %ecx
cmp %ecx, %ebx
jne .headerSearch
.headerSearchDone:
cmp %ecx, %ebx // reached the end == not found anything?
je 2f // give up
// we assume the checksum is okay, no test
mov 4(%ecx), %ebx
add %ecx, %ebx // ebx = cb_header + header_bytes
mov 20(%ecx), %ecx // ecx = table_entries
.tableScan:
cmp $CB_TAG_FORWARD, (%ebx)
jne .testMemory
/* forward tag: assume 32bit pointer */
mov 8(%ebx), %ecx
jmp .headerSearch
.testMemory:
cmp $CB_TAG_MEMORY, (%ebx)
jne .testFramebuffer
/* memory tag: copy e820 map and entry count. also determine alt_mem_k */
mov 4(%ebx), %eax
sub $8, %eax
shr $2, %eax /* eax = number of dwords of e820 data */
cmp $(32 * 5), %eax /* linux wants at most 32 entries of 5 dwords */
jng 1f
mov $(32 * 5), %eax /* only copy 32 entries */
1:
mov %eax, %esi
mov $5, %edi
div %edi
mov %eax, (LINUX_PARAM_LOC + E820_NR_OFFSET)
mov %esi, %eax
xchg %eax, %ecx
lea 8(%ebx), %esi /* e820 data source */
mov $(LINUX_PARAM_LOC + E820_OFFSET), %edi
rep movsl
xchg %eax, %ecx
jmp .endScan
.testFramebuffer:
cmp $CB_TAG_FRAMEBUFFER, (%ebx)
jne .endScan
/* TODO: handle framebuffer tag */
.endScan:
add 4(%ebx), %ebx
dec %ecx
jnz .tableScan
/* Setup basic code and data segment selectors for Linux
**
** Flat code segment descriptor:
** selector: 0x10
** base : 0x00000000
** limit : 0xFFFFFFFF
** type : code, execute, read
**
** Flat data segment descriptor:
** selector: 0x18
** base : 0x00000000
** limit : 0xFFFFFFFF
** type : data, read/write
**
** Use TRAMPOLINE_ENTRY_LOC as a scratchpad.
*/
mov $TRAMPOLINE_ENTRY_LOC, %eax
sgdt (%eax)
mov 2(%eax), %ebx
movl $0x0000ffff, 16(%ebx)
movl $0x00cf9b00, 20(%ebx)
movl $0x0000ffff, 24(%ebx)
movl $0x00cf9300, 28(%ebx)
/* finally: jump to kernel */
mov $LINUX_PARAM_LOC, %esi
jmp *(LINUX_PARAM_LOC + LINUX_ENTRY_OFFSET)
2:
hlt
jmp 2b
.trampoline_end:

View File

@ -1,164 +1,17 @@
/*
* linux_trampoline
*
* Copyright (C) 2013 Patrick Georgi <patrick@georgi-clan.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#if 0
/* NOTE: THIS CODE MUST REMAIN POSITION INDEPENDENT
* IT SHOULDN'T USE THE STACK
* AND IN GENERAL EXPECT NOTHING BUT RAM TO WORK
*/
.code32
.data
#include "linux_trampoline.h"
#define HEADER_SIG 0x4f49424c // LBIO little endian
#define CB_TAG_FORWARD 0x11
#define CB_TAG_MEMORY 0x1
#define CB_TAG_FRAMEBUFFER 0x12
#define E820_NR_OFFSET 0x1e8
#define LINUX_ENTRY_OFFSET 0x214
#define E820_OFFSET 0x2d0
.trampoline_start:
cld
xor %edx, %edx
mov $0, %ecx
.headerSearch:
mov $0x10000, %ebx
add %ecx, %ebx
mov (%ecx), %eax
cmp $HEADER_SIG, %eax
je .headerSearchDone // found the header
add $16, %ecx
cmp %ecx, %ebx
jne .headerSearch
.headerSearchDone:
cmp %ecx, %ebx // reached the end == not found anything?
je 2f // give up
// we assume the checksum is okay, no test
mov 4(%ecx), %ebx
add %ecx, %ebx // ebx = cb_header + header_bytes
mov 20(%ecx), %ecx // ecx = table_entries
.tableScan:
cmp $CB_TAG_FORWARD, (%ebx)
jne .testMemory
/* forward tag: assume 32bit pointer */
mov 8(%ebx), %ecx
jmp .headerSearch
.testMemory:
cmp $CB_TAG_MEMORY, (%ebx)
jne .testFramebuffer
/* memory tag: copy e820 map and entry count. also determine alt_mem_k */
mov 4(%ebx), %eax
sub $8, %eax
shr $2, %eax /* eax = number of dwords of e820 data */
cmp $(32 * 5), %eax /* linux wants at most 32 entries of 5 dwords */
jng 1f
mov $(32 * 5), %eax /* only copy 32 entries */
1:
mov %eax, %esi
mov $5, %edi
div %edi
mov %eax, (LINUX_PARAM_LOC + E820_NR_OFFSET)
mov %esi, %eax
xchg %eax, %ecx
lea 8(%ebx), %esi /* e820 data source */
mov $(LINUX_PARAM_LOC + E820_OFFSET), %edi
rep movsl
xchg %eax, %ecx
jmp .endScan
.testFramebuffer:
cmp $CB_TAG_FRAMEBUFFER, (%ebx)
jne .endScan
/* TODO: handle framebuffer tag */
.endScan:
add 4(%ebx), %ebx
dec %ecx
jnz .tableScan
/* Setup basic code and data segment selectors for Linux
**
** Flat code segment descriptor:
** selector: 0x10
** base : 0x00000000
** limit : 0xFFFFFFFF
** type : code, execute, read
**
** Flat data segment descriptor:
** selector: 0x18
** base : 0x00000000
** limit : 0xFFFFFFFF
** type : data, read/write
**
** Use TRAMPOLINE_ENTRY_LOC as a scratchpad.
*/
mov $TRAMPOLINE_ENTRY_LOC, %eax
sgdt (%eax)
mov 2(%eax), %ebx
movl $0x0000ffff, 16(%ebx)
movl $0x00cf9b00, 20(%ebx)
movl $0x0000ffff, 24(%ebx)
movl $0x00cf9300, 28(%ebx)
/* finally: jump to kernel */
mov $LINUX_PARAM_LOC, %esi
jmp *(LINUX_PARAM_LOC + LINUX_ENTRY_OFFSET)
2:
hlt
jmp 2b
.trampoline_end:
.global trampoline_start, trampoline_size
trampoline_start:
.long .trampoline_start
trampoline_size:
.long .trampoline_end - .trampoline_start
#endif
/* The code above is hand-crafted to fit various contraints.
* To simplify porting, the below matches the above.
* When changing any code in here, compile the above as a .S
* file, objcopy it to binary and paste the result below (minus
* the last 8 bytes which are trampoline_start and trampoline_size).
*/
/* This file is automatically generated. Do not manually change */
const unsigned char trampoline[] = {
0xfc, 0x31, 0xd2, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x01, 0x00, 0x01, 0xcb, 0x8b,
0x01, 0x3d, 0x4c, 0x42, 0x49, 0x4f, 0x74, 0x07, 0x83, 0xc1, 0x10, 0x39, 0xcb, 0x75, 0xe9, 0x39,
0xcb, 0x0f, 0x84, 0x85, 0x00, 0x00, 0x00, 0x8b, 0x59, 0x04, 0x01, 0xcb, 0x8b, 0x49, 0x14, 0x83,
0x3b, 0x11, 0x75, 0x05, 0x8b, 0x4b, 0x08, 0xeb, 0xcf, 0x83, 0x3b, 0x01, 0x75, 0x33, 0x8b, 0x43,
0x04, 0x83, 0xe8, 0x08, 0xc1, 0xe8, 0x02, 0x3d, 0xa0, 0x00, 0x00, 0x00, 0x7e, 0x05, 0xb8, 0xa0,
0x00, 0x00, 0x00, 0x89, 0xc6, 0xbf, 0x05, 0x00, 0x00, 0x00, 0xf7, 0xf7, 0xa3, 0xe8, 0x01, 0x09,
0x00, 0x89, 0xf0, 0x91, 0x8d, 0x73, 0x08, 0xbf, 0xd0, 0x02, 0x09, 0x00, 0xf3, 0xa5, 0x91, 0xeb,
0x05, 0x83, 0x3b, 0x12, 0x75, 0x00, 0x03, 0x5b, 0x04, 0x49, 0x75, 0xb3, 0xb8, 0x00, 0x00, 0x04,
0x00, 0x0f, 0x01, 0x00, 0x8b, 0x58, 0x02, 0xc7, 0x43, 0x10, 0xff, 0xff, 0x00, 0x00, 0xc7, 0x43,
0x14, 0x00, 0x9b, 0xcf, 0x00, 0xc7, 0x43, 0x18, 0xff, 0xff, 0x00, 0x00, 0xc7, 0x43, 0x1c, 0x00,
0x93, 0xcf, 0x00, 0xbe, 0x00, 0x00, 0x09, 0x00, 0xff, 0x25, 0x14, 0x02, 0x09, 0x00, 0xf4, 0xeb,
0xfd
0xfc, 0x31, 0xd2, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x01, 0x00, 0x01, 0xcb, 0x8b,
0x01, 0x3d, 0x4c, 0x42, 0x49, 0x4f, 0x74, 0x07, 0x83, 0xc1, 0x10, 0x39, 0xcb, 0x75, 0xe9, 0x39,
0xcb, 0x0f, 0x84, 0x87, 0x00, 0x00, 0x00, 0x8b, 0x59, 0x04, 0x01, 0xcb, 0x8b, 0x49, 0x14, 0x83,
0x3b, 0x11, 0x75, 0x05, 0x8b, 0x4b, 0x08, 0xeb, 0xcf, 0x83, 0x3b, 0x01, 0x75, 0x33, 0x8b, 0x43,
0x04, 0x83, 0xe8, 0x08, 0xc1, 0xe8, 0x02, 0x3d, 0xa0, 0x00, 0x00, 0x00, 0x7e, 0x05, 0xb8, 0xa0,
0x00, 0x00, 0x00, 0x89, 0xc6, 0xbf, 0x05, 0x00, 0x00, 0x00, 0xf7, 0xf7, 0xa3, 0xe8, 0x01, 0x09,
0x00, 0x89, 0xf0, 0x91, 0x8d, 0x73, 0x08, 0xbf, 0xd0, 0x02, 0x09, 0x00, 0xf3, 0xa5, 0x91, 0xeb,
0x05, 0x83, 0x3b, 0x12, 0x75, 0x00, 0x03, 0x5b, 0x04, 0x49, 0x75, 0xb3, 0xb8, 0x00, 0x00, 0x04,
0x00, 0x0f, 0x01, 0x00, 0x8b, 0x58, 0x02, 0xc7, 0x43, 0x10, 0xff, 0xff, 0x00, 0x00, 0xc7, 0x43,
0x14, 0x00, 0x9b, 0xcf, 0x00, 0xc7, 0x43, 0x18, 0xff, 0xff, 0x00, 0x00, 0xc7, 0x43, 0x1c, 0x00,
0x93, 0xcf, 0x00, 0xbe, 0x00, 0x00, 0x09, 0x00, 0xff, 0x25, 0x14, 0x02, 0x09, 0x00, 0xf4, 0xeb,
0xfd
};
const void * const trampoline_start = &trampoline;