Noé Rubinstein (noe.rubinstein@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/284
-gerrit
commit 23e7b952e792935986aade22e8d84692e3714329 Author: Noe Rubinstein nrubinstein@avencall.com Date: Tue Sep 27 14:59:12 2011 +0200
cbfstool: Optionally specify offsets to commands
This enables placing components in specific parts of the ROM while leaving the calculation of their precise location to CBFStool. This can be used, for example, with flashrom's layout feature.
We plan to use it to provide a more robust fallback mechanism than the one already provided by Coreboot, restricting the fallback to a part of the ROM which is write-protected during runtime.
Change-Id: I7403f37e2f20306ea113879d12a9fcec175063d8 Signed-off-by: Noe Rubinstein nrubinstein@avencall.com --- src/arch/x86/Kconfig | 6 +++ src/arch/x86/Makefile.bootblock.inc | 4 +- util/cbfstool/cbfstool.c | 54 ++++++++++++++++++----- util/cbfstool/common.c | 79 ++++++++++++++++++++++++++++++++--- util/cbfstool/common.h | 6 ++- 5 files changed, 129 insertions(+), 20 deletions(-)
diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig index f98cf5b..c4ece2a 100644 --- a/src/arch/x86/Kconfig +++ b/src/arch/x86/Kconfig @@ -55,6 +55,12 @@ config X86_BOOTBLOCK_NORMAL
endchoice
+ +config ROMSTAGE_OFFSET + hex "Romstage offset in ROM: " + depends on TINY_BOOTBLOCK + default '0x0' + config BOOTBLOCK_SOURCE string default "bootblock_simple.c" if X86_BOOTBLOCK_SIMPLE diff --git a/src/arch/x86/Makefile.bootblock.inc b/src/arch/x86/Makefile.bootblock.inc index 806afea..dd0d76e 100644 --- a/src/arch/x86/Makefile.bootblock.inc +++ b/src/arch/x86/Makefile.bootblock.inc @@ -80,7 +80,9 @@ $(obj)/coreboot.romstage: $(obj)/coreboot.pre1 $$(romstage-objs) $(obj)/romstage $(CC) -nostdlib -nostartfiles -static -o $(obj)/romstage.elf -L$(obj) -T $(obj)/romstage/ldscript.ld $(romstage-objs) $(OBJCOPY) -O binary $(obj)/romstage.elf $(obj)/romstage.bin printf "CONFIG_ROMBASE = 0x" > $(obj)/location.ld - $(CBFSTOOL) $(obj)/coreboot.pre1 locate $(obj)/romstage.bin $(CONFIG_CBFS_PREFIX)/romstage $(CONFIG_XIP_ROM_SIZE) > $(obj)/location.txt + $(CBFSTOOL) $(obj)/coreboot.pre1 locate $(obj)/romstage.bin \ + $(CONFIG_CBFS_PREFIX)/romstage $(CONFIG_XIP_ROM_SIZE) \ + $(CONFIG_ROMSTAGE_OFFSET) > $(obj)/location.txt cat $(obj)/location.txt >> $(obj)/location.ld printf ';\nAUTO_XIP_ROM_BASE = CONFIG_ROMBASE & ~(CONFIG_XIP_ROM_SIZE - 1);\n' >> $(obj)/location.ld $(CC) -nostdlib -nostartfiles -static -o $(obj)/romstage.elf -L$(obj) -T $(obj)/romstage/ldscript.ld $(romstage-objs) diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 4c28c29..530712b 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -78,7 +78,11 @@ static int cbfs_add(int argc, char **argv) else type = strtoul(argv[5], NULL, 0); if (argc > 6) { - base = strtoul(argv[6], NULL, 0); + if (*argv[6] == '+') + base = cbfs_find_location(rom, filesize, filename, + strtoul(argv[6]+1, NULL, 0)); + else + base = strtoul(argv[6], NULL, 0); } cbfsfile = create_cbfs_file(cbfsname, filedata, &filesize, type, &base); if (add_file_to_cbfs(cbfsfile, filesize, base)) @@ -118,15 +122,20 @@ static int cbfs_add_payload(int argc, char **argv) void *cbfsfile = NULL;
comp_algo algo = CBFS_COMPRESS_NONE; - if (argc > 5) { - if (argv[5][0] == 'l') + if (argc > 5 && argv[5][0] == 'l') algo = CBFS_COMPRESS_LZMA; - } - if (argc > 6) { - base = strtoul(argv[6], NULL, 0); - } + + unsigned char *payload; filesize = parse_elf_to_payload(filedata, &payload, algo); + + if (argc > 6) + if (*argv[6] == '+') + base = cbfs_find_location(rom, filesize, filename, + strtoul(argv[6]+1, NULL, 0)); + else + base = strtoul(argv[6], NULL, 0); + cbfsfile = create_cbfs_file(cbfsname, payload, &filesize, CBFS_COMPONENT_PAYLOAD, &base); @@ -171,11 +180,27 @@ static int cbfs_add_stage(int argc, char **argv) if (argv[5][0] == 'l') algo = CBFS_COMPRESS_LZMA; } - if (argc > 6) { - base = strtoul(argv[6], NULL, 0); - } unsigned char *stage; + + /* Careful here: + * + * - when the location is specified exactly, we want parse_elf_to_stage + * to use this information for the romstage to execute correctly. See + * src/arch/x86/Makefile.bootblock.inc + * + * - the +offset syntax can only be used when parse_elf_to_stage + * doesn't need this information + */ + + if (argc > 6 && *argv[6] != '+') + base = strtoul(argv[6], NULL, 0); + filesize = parse_elf_to_stage(filedata, &stage, algo, &base); + + if (argc > 6 && *argv[6] == '+') + base = cbfs_find_location(rom, filesize, filename, + strtoul(argv[6]+1, NULL, 0)); + cbfsfile = create_cbfs_file(cbfsname, stage, &filesize, CBFS_COMPONENT_STAGE, &base); @@ -225,8 +250,12 @@ static int cbfs_locate(int argc, char **argv) uint32_t filesize = getfilesize(file); const char *filename = argv[4]; int align = strtoul(argv[5], NULL, 0); + uint32_t offset = argc > 6 ? strtoul(argv[6], NULL, 0) : 0; + uint32_t loc = cbfs_find_stage_location(romname, filesize, filename, align, + offset);
- printf("%x\n", cbfs_find_location(romname, filesize, filename, align)); + printf("%x\n", loc); + fprintf(stderr, "%x\n", loc); return 0; }
@@ -287,7 +316,8 @@ void usage(void) " add-payload FILE NAME [COMP] [base] Add a payload to the ROM\n" " add-stage FILE NAME [COMP] [base] Add a stage to the ROM\n" " create SIZE BOOTBLOCK [ALIGN] Create a ROM file\n" - " locate FILE NAME ALIGN Find a place for a file of that size\n" + " locate FILE NAME ALIGN OFFSET Find a place for a file of that size\n" + " OFFSET is relative to the ROM start.\n" " print Show the contents of the ROM\n" " extract NAME FILE Extracts a raw payload from ROM\n" "\n" diff --git a/util/cbfstool/common.c b/util/cbfstool/common.c index cbf0757..09fe5bb 100644 --- a/util/cbfstool/common.c +++ b/util/cbfstool/common.c @@ -436,8 +436,9 @@ static int in_segment(int addr, int size, int gran) return ((addr & ~(gran - 1)) == ((addr + size) & ~(gran - 1))); }
-uint32_t cbfs_find_location(const char *romfile, uint32_t filesize, - const char *filename, uint32_t alignment) +uint32_t cbfs_find_stage_location(const char *romfile, uint32_t filesize, + const char *filename, uint32_t alignment, + uint32_t offset) { void *rom = loadrom(romfile); int filename_size = strlen(filename); @@ -447,6 +448,13 @@ uint32_t cbfs_find_location(const char *romfile, uint32_t filesize, 16) + sizeof(struct cbfs_stage); int totalsize = headersize + filesize;
+ if (offset > phys_end - phys_start) { + fprintf(stderr, "Offset outside of ROM boundaries\n"); + exit(1); + } + + if (offset) offset = ALIGN(phys_start + offset, align); + uint32_t current = phys_start; while (current < phys_end) { if (!cbfs_file_header(current)) { @@ -458,10 +466,19 @@ uint32_t cbfs_find_location(const char *romfile, uint32_t filesize,
uint32_t top = current + ntohl(thisfile->len) + ntohl(thisfile->offset); - if (((ntohl(thisfile->type) == 0x0) - || (ntohl(thisfile->type) == 0xffffffff)) - && (ntohl(thisfile->len) + ntohl(thisfile->offset) >= - totalsize)) { + + uint32_t off_rel = 0; + if (current < offset && offset <= top) { + off_rel = offset - current; + current = offset; + } + + if (current >= offset + && ((ntohl(thisfile->type) == 0x0) + || (ntohl(thisfile->type) == 0xffffffff)) + && (ntohl(thisfile->len) + ntohl(thisfile->offset) + - off_rel >= totalsize)) { + if (in_segment (current + headersize, filesize, alignment)) return current + headersize; @@ -485,3 +502,53 @@ uint32_t cbfs_find_location(const char *romfile, uint32_t filesize, } return 0; } + +uint32_t cbfs_find_location(const char *romfile, uint32_t filesize, + const char *filename, uint32_t offset) +{ + void *rom = loadrom(romfile); + int filename_size = strlen(filename); + + int headersize = + sizeof(struct cbfs_file) + ALIGN(filename_size + 1, 16); + + int totalsize = headersize + filesize; + + if (offset > phys_end - phys_start) { + fprintf(stderr, "Offset outside of ROM boundaries\n"); + exit(1); + } + + if (offset) offset = ALIGN(phys_start + offset, align); + + uint32_t current = phys_start; + while (current < phys_end) { + if (!cbfs_file_header(current)) { + current += align; + continue; + } + struct cbfs_file *thisfile = + (struct cbfs_file *)phys_to_virt(current); + + uint32_t top = + current + ntohl(thisfile->len) + ntohl(thisfile->offset); + + uint32_t off_rel = 0; + if (current < offset && offset <= top) { + off_rel = offset - current; + current = offset; + } + + if (current >= offset + && ((ntohl(thisfile->type) == 0x0) + || (ntohl(thisfile->type) == 0xffffffff)) + && (ntohl(thisfile->len) + ntohl(thisfile->offset) + - off_rel >= totalsize)) + return current + headersize; + + current = ALIGN(current + (ntohl(thisfile->len) + + ntohl(thisfile->offset) - off_rel), + align); + } + return 0; +} diff --git a/util/cbfstool/common.h b/util/cbfstool/common.h index 8f397d8..b5aea46 100644 --- a/util/cbfstool/common.h +++ b/util/cbfstool/common.h @@ -70,8 +70,12 @@ int add_file_to_cbfs(void *content, uint32_t contentsize, uint32_t location); void print_cbfs_directory(const char *filename); int extract_file_from_cbfs(const char *filename, const char *payloadname, const char *outpath);
+uint32_t cbfs_find_stage_location(const char *romfile, uint32_t filesize, + const char *filename, uint32_t alignment, + uint32_t offset); + uint32_t cbfs_find_location(const char *romfile, uint32_t filesize, - const char *filename, uint32_t align); + const char *filename, uint32_t offset);
void print_supported_filetypes(void);