diff options
-rw-r--r-- | util/cbfstool/cbfstool.c | 29 | ||||
-rw-r--r-- | util/cbfstool/common.c | 63 | ||||
-rw-r--r-- | util/cbfstool/common.h | 1 |
3 files changed, 90 insertions, 3 deletions
diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index e1b9fca58b..507edc255e 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -29,7 +29,8 @@ typedef enum { CMD_ADD_STAGE, CMD_CREATE, CMD_LOCATE, - CMD_PRINT + CMD_PRINT, + CMD_EXTRACT, } cmd_t; struct command { @@ -244,13 +245,34 @@ static int cbfs_print(int argc, char **argv) return 0; } +static int cbfs_extract(int argc, char **argv) +{ + char *romname = argv[1]; + char *cmd = argv[2]; + void *rom = loadrom(romname); + + if (rom == NULL) { + printf("Could not load ROM image '%s'.\n", romname); + return 1; + } + + if (argc != 5) + { + printf("Error: you must specify a CBFS name and a file to dump it in.\n"); + return 1; + } + + return extract_file_from_cbfs(romname, argv[3], argv[4]); +} + struct command commands[] = { {CMD_ADD, "add", cbfs_add}, {CMD_ADD_PAYLOAD, "add-payload", cbfs_add_payload}, {CMD_ADD_STAGE, "add-stage", cbfs_add_stage}, {CMD_CREATE, "create", cbfs_create}, {CMD_LOCATE, "locate", cbfs_locate}, - {CMD_PRINT, "print", cbfs_print} + {CMD_PRINT, "print", cbfs_print}, + {CMD_EXTRACT, "extract", cbfs_extract}, }; void usage(void) @@ -266,7 +288,8 @@ void usage(void) " 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" - " print Show the contents of the ROM\n\n" + " print Show the contents of the ROM\n" + " extract NAME FILE Extracts a raw payload from ROM\n\n" "TYPEs:\n" ); print_supported_filetypes(); diff --git a/util/cbfstool/common.c b/util/cbfstool/common.c index 8478c5a492..a42585b776 100644 --- a/util/cbfstool/common.c +++ b/util/cbfstool/common.c @@ -207,6 +207,69 @@ void print_cbfs_directory(const char *filename) } } +int extract_file_from_cbfs(const char *filename, const char *payloadname, const char *outpath) +{ + // Identify the coreboot image. + printf( + "%s: %d kB, bootblocksize %d, romsize %d, offset 0x%x\nAlignment: %d bytes\n\n", + basename((char *)filename), romsize / 1024, ntohl(master_header->bootblocksize), + romsize, ntohl(master_header->offset), align); + + FILE *outfile = NULL; + uint32_t current = phys_start; + while (current < phys_end) { + if (!cbfs_file_header(current)) { + current += align; + continue; + } + + // Locate the file start struct + struct cbfs_file *thisfile = + (struct cbfs_file *)phys_to_virt(current); + // And its length + uint32_t length = ntohl(thisfile->len); + // Locate the file name + char *fname = (char *)(phys_to_virt(current) + sizeof(struct cbfs_file)); + // It's not the file we are looking for.. + if (strcmp(fname, payloadname) != 0) + { + current = + ALIGN(current + ntohl(thisfile->len) + + ntohl(thisfile->offset), align); + continue; + } + + // Else, it's our file. + printf("Found %.30s payload at 0x%x, type %.12s, size %d\n", fname, + current - phys_start, strfiletype(ntohl(thisfile->type)), + length); + + // If we are not dumping to stdout, open the out file. + outfile = fopen(outpath, "wb"); + if (!outfile) + { + printf("Could not open the file %s for writing. Aborting.\n", outpath); + return 1; + } + + if (ntohl(thisfile->type) != CBFS_COMPONENT_RAW) + { + printf("Warning: only 'raw' files are safe to extract.\n"); + } + + fwrite(((char *)thisfile) + + ntohl(thisfile->offset), length, 1, outfile); + + fclose(outfile); + printf("Successfully dumped the payload.\n"); + + // We'll only dump one file. + return 0; + } + +} + + int add_file_to_cbfs(void *content, uint32_t contentsize, uint32_t location) { uint32_t current = phys_start; diff --git a/util/cbfstool/common.h b/util/cbfstool/common.h index 8d1b4d845d..8f397d8e65 100644 --- a/util/cbfstool/common.h +++ b/util/cbfstool/common.h @@ -68,6 +68,7 @@ int create_cbfs_image(const char *romfile, uint32_t romsize, 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_location(const char *romfile, uint32_t filesize, const char *filename, uint32_t align); |