From c13e4bf3e16080993fb42399327501201c4f9f13 Mon Sep 17 00:00:00 2001 From: Hung-Te Lin Date: Tue, 29 Jan 2013 15:22:11 +0800 Subject: cbfstool: Use cbfs_image API for "add-*" (add-payload, add-stage, ...) commands. add-payload, add-stage, and add-flat-binary are now all using cbfs_image API. To test: cbfstool coreboot.rom add-stage -f FILE -n fallback/romstage -b 0xXXXX cbfstool coreboot.rom add-payload -f FILE -n fallback/pyload And compare with old cbfstool. Verified to boot on ARM(snow) and X86(qemu-i386). Change-Id: If65cb495c476ef6f9d90c778531f0c3caf178281 Signed-off-by: Hung-Te Lin Reviewed-on: http://review.coreboot.org/2220 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- util/cbfstool/cbfs-mkpayload.c | 72 ++++++------- util/cbfstool/cbfs-mkstage.c | 32 +++--- util/cbfstool/cbfstool.c | 240 ++++++++++------------------------------- util/cbfstool/common.h | 16 +-- 4 files changed, 115 insertions(+), 245 deletions(-) diff --git a/util/cbfstool/cbfs-mkpayload.c b/util/cbfstool/cbfs-mkpayload.c index 060e9ee283..302d50637d 100644 --- a/util/cbfstool/cbfs-mkpayload.c +++ b/util/cbfstool/cbfs-mkpayload.c @@ -27,15 +27,14 @@ #include "cbfs.h" #include "elf.h" -int parse_elf_to_payload(unsigned char *input, unsigned char **output, - comp_algo algo) +int parse_elf_to_payload(const struct buffer *input, + struct buffer *output, comp_algo algo) { Elf32_Phdr *phdr; - Elf32_Ehdr *ehdr = (Elf32_Ehdr *) input; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)input->data; Elf32_Shdr *shdr; char *header; char *strtab; - unsigned char *sptr; int headers; int segments = 1; int isize = 0, osize = 0; @@ -43,12 +42,14 @@ int parse_elf_to_payload(unsigned char *input, unsigned char **output, struct cbfs_payload_segment *segs; int i; - if(!iself(input)){ + if(!iself((unsigned char *)input->data)){ ERROR("The payload file is not in ELF format!\n"); return -1; } - if (!((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) && + // The tool may work in architecture-independent way. + if (arch != CBFS_ARCHITECTURE_UNKNOWN && + !((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) && !((ehdr->e_machine == EM_386) && (arch == CBFS_ARCHITECTURE_X86))) { ERROR("The payload file has the wrong architecture\n"); return -1; @@ -58,6 +59,7 @@ int parse_elf_to_payload(unsigned char *input, unsigned char **output, if (!compress) return -1; + DEBUG("start: parse_elf_to_payload\n"); headers = ehdr->e_phnum; header = (char *)ehdr; @@ -104,15 +106,14 @@ int parse_elf_to_payload(unsigned char *input, unsigned char **output, } /* Allocate a block of memory to store the data in */ + if (buffer_create(output, (segments * sizeof(*segs)) + isize, + input->name) != 0) + return -1; + memset(output->data, 0, output->size); - sptr = - calloc((segments * sizeof(struct cbfs_payload_segment)) + isize, 1); doffset = (segments * sizeof(struct cbfs_payload_segment)); - if (sptr == NULL) - goto err; - - segs = (struct cbfs_payload_segment *)sptr; + segs = (struct cbfs_payload_segment *)output->data; segments = 0; for (i = 0; i < ehdr->e_shnum; i++) { @@ -132,7 +133,7 @@ int parse_elf_to_payload(unsigned char *input, unsigned char **output, segs[segments].len = (unsigned int)shdr[i].sh_size; segs[segments].offset = doffset; - memcpy((unsigned long *)(sptr + doffset), + memcpy((unsigned long *)(output->data + doffset), &header[shdr[i].sh_offset], shdr[i].sh_size); doffset += segs[segments].len; @@ -172,7 +173,7 @@ int parse_elf_to_payload(unsigned char *input, unsigned char **output, int len; compress((char *)&header[phdr[i].p_offset], - phdr[i].p_filesz, (char *)(sptr + doffset), &len); + phdr[i].p_filesz, output->data + doffset, &len); segs[segments].len = htonl(len); /* If the compressed section is larger, then use the @@ -182,7 +183,7 @@ int parse_elf_to_payload(unsigned char *input, unsigned char **output, segs[segments].compression = 0; segs[segments].len = htonl(phdr[i].p_filesz); - memcpy((char *)(sptr + doffset), + memcpy(output->data + doffset, &header[phdr[i].p_offset], phdr[i].p_filesz); } @@ -193,24 +194,19 @@ int parse_elf_to_payload(unsigned char *input, unsigned char **output, } segs[segments].type = PAYLOAD_SEGMENT_ENTRY; - segs[segments++].load_addr = (uint64_t)htonll(ehdr->e_entry); - - *output = sptr; + segs[segments++].load_addr = htonll(ehdr->e_entry); - return (segments * sizeof(struct cbfs_payload_segment)) + osize; - - err: - return -1; + output->size = (segments * sizeof(struct cbfs_payload_segment)) + osize; + return 0; } -int parse_flat_binary_to_payload(unsigned char *input, unsigned char **output, - int32_t input_size, +int parse_flat_binary_to_payload(const struct buffer *input, + struct buffer *output, uint32_t loadaddress, uint32_t entrypoint, comp_algo algo) { comp_func_ptr compress; - unsigned char *payload; struct cbfs_payload_segment *segs; int doffset, len = 0; @@ -219,39 +215,35 @@ int parse_flat_binary_to_payload(unsigned char *input, unsigned char **output, return -1; DEBUG("start: parse_flat_binary_to_payload\n"); - - /* FIXME compressed file size might be bigger than original file and - * causing buffer overflow. */ - payload = calloc((2 * sizeof(struct cbfs_payload_segment)) + input_size, 1); - if (payload == NULL) { - ERROR("Could not allocate memory.\n"); + if (buffer_create(output, (2 * sizeof(*segs) + input->size), + input->name) != 0) return -1; - } + memset(output->data, 0, output->size); - segs = (struct cbfs_payload_segment *)payload; + segs = (struct cbfs_payload_segment *)output->data; doffset = (2 * sizeof(*segs)); /* Prepare code segment */ segs[0].type = PAYLOAD_SEGMENT_CODE; segs[0].load_addr = htonll(loadaddress); - segs[0].mem_len = htonl(input_size); + segs[0].mem_len = htonl(input->size); segs[0].offset = htonl(doffset); - compress((char*)input, input_size, (char*)payload + doffset, &len); + compress(input->data, input->size, output->data + doffset, &len); segs[0].compression = htonl(algo); segs[0].len = htonl(len); - if ((unsigned int)len >= input_size) { + if ((unsigned int)len >= input->size) { WARN("Compressing data would make it bigger - disabled.\n"); segs[0].compression = 0; - segs[0].len = htonl(input_size); - memcpy(payload + doffset, input, input_size); + segs[0].len = htonl(input->size); + memcpy(output->data + doffset, input->data, input->size); } /* prepare entry point segment */ segs[1].type = PAYLOAD_SEGMENT_ENTRY; segs[1].load_addr = htonll(entrypoint); - *output = payload; + output->size = doffset + ntohl(segs[0].len); - return doffset + ntohl(segs[0].len); + return 0; } diff --git a/util/cbfstool/cbfs-mkstage.c b/util/cbfstool/cbfs-mkstage.c index 4374bdadf5..4008367d9d 100644 --- a/util/cbfstool/cbfs-mkstage.c +++ b/util/cbfstool/cbfs-mkstage.c @@ -44,13 +44,12 @@ static unsigned int swap32(unsigned int x) unsigned int (*elf32_to_native) (unsigned int) = idemp; /* returns size of result, or -1 if error */ -int parse_elf_to_stage(unsigned char *input, unsigned char **output, - comp_algo algo, uint32_t * location) +int parse_elf_to_stage(const struct buffer *input, struct buffer *output, + comp_algo algo, uint32_t *location) { Elf32_Phdr *phdr; - Elf32_Ehdr *ehdr = (Elf32_Ehdr *) input; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)input->data; char *header, *buffer; - unsigned char *out; int headers; int i; @@ -63,12 +62,15 @@ int parse_elf_to_stage(unsigned char *input, unsigned char **output, if (!compress) return -1; - if (!iself(input)) { + DEBUG("start: parse_elf_to_stage(location=0x%x)\n", *location); + if (!iself((unsigned char *)input->data)) { ERROR("The stage file is not in ELF format!\n"); return -1; } - if (!((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) && + // The tool may work in architecture-independent way. + if (arch != CBFS_ARCHITECTURE_UNKNOWN && + !((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) && !((ehdr->e_machine == EM_386) && (arch == CBFS_ARCHITECTURE_X86))) { ERROR("The stage file has the wrong architecture\n"); return -1; @@ -162,28 +164,26 @@ int parse_elf_to_stage(unsigned char *input, unsigned char **output, } /* Now make the output buffer */ - out = calloc(sizeof(struct cbfs_stage) + data_end - data_start, 1); - - if (out == NULL) { + if (buffer_create(output, sizeof(*stage) + data_end - data_start, + input->name) != 0) { ERROR("Unable to allocate memory: %m\n"); return -1; } + memset(output->data, 0, output->size); - stage = (struct cbfs_stage *)out; + stage = (struct cbfs_stage *)output->data; stage->load = data_start; /* FIXME: htonll */ stage->memlen = mem_end - data_start; stage->compression = algo; stage->entry = ehdr->e_entry; /* FIXME: htonll */ - compress(buffer, data_end - data_start, - (char *)(out + sizeof(struct cbfs_stage)), (int *)&stage->len); - + compress(buffer, data_end - data_start, (output->data + sizeof(*stage)), + (int *)&stage->len); free(buffer); - *output = out; - if (*location) *location -= sizeof(struct cbfs_stage); - return sizeof(struct cbfs_stage) + stage->len; + output->size = sizeof(*stage) + stage->len; + return 0; } diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 28ca15fe05..3881628e26 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -58,7 +58,7 @@ static struct param { .algo = CBFS_COMPRESS_NONE, }; -typedef int (*convert_buffer_t)(struct buffer *buffer); +typedef int (*convert_buffer_t)(struct buffer *buffer, uint32_t *offset); static int cbfs_add_component(const char *cbfs_name, const char *filename, @@ -89,7 +89,7 @@ static int cbfs_add_component(const char *cbfs_name, return 1; } - if (convert && convert(&buffer) != 0) { + if (convert && convert(&buffer, &offset) != 0) { ERROR("Failed to parse file '%s'.\n", filename); buffer_delete(&buffer); return 1; @@ -126,6 +126,42 @@ static int cbfs_add_component(const char *cbfs_name, return 0; } +static int cbfstool_convert_mkstage(struct buffer *buffer, uint32_t *offset) { + struct buffer output; + if (parse_elf_to_stage(buffer, &output, param.algo, offset) != 0) + return -1; + buffer_delete(buffer); + // direct assign, no dupe. + memcpy(buffer, &output, sizeof(*buffer)); + return 0; +} + +static int cbfstool_convert_mkpayload(struct buffer *buffer, uint32_t *offset) { + struct buffer output; + if (parse_elf_to_payload(buffer, &output, param.algo) != 0) + return -1; + buffer_delete(buffer); + // direct assign, no dupe. + memcpy(buffer, &output, sizeof(*buffer)); + return 0; +} + +static int cbfstool_convert_mkflatpayload(struct buffer *buffer, + uint32_t *offset) { + struct buffer output; + if (parse_flat_binary_to_payload(buffer, &output, + param.loadaddress, + param.entrypoint, + param.algo) != 0) { + return -1; + } + buffer_delete(buffer); + // direct assign, no dupe. + memcpy(buffer, &output, sizeof(*buffer)); + return 0; +} + + static int cbfs_add(void) { return cbfs_add_component(param.cbfs_name, @@ -136,204 +172,44 @@ static int cbfs_add(void) NULL); } -static int cbfs_add_payload(void) +static int cbfs_add_stage(void) { - uint32_t filesize = 0; - void *rom, *filedata, *cbfsfile; - unsigned char *payload; - - if (!param.filename) { - ERROR("You need to specify -f/--filename.\n"); - return 1; - } - - if (!param.name) { - ERROR("You need to specify -n/--name.\n"); - return 1; - } - - rom = loadrom(param.cbfs_name); - if (rom == NULL) { - ERROR("Could not load ROM image '%s'.\n", - param.cbfs_name); - return 1; - } - - filedata = loadfile(param.filename, &filesize, 0, SEEK_SET); - if (filedata == NULL) { - ERROR("Could not load file '%s'.\n", - param.filename); - free(rom); - return 1; - } - - filesize = parse_elf_to_payload(filedata, &payload, param.algo); - if (filesize <= 0) { - ERROR("Adding payload '%s' failed.\n", - param.filename); - free(rom); - return 1; - } - - cbfsfile = create_cbfs_file(param.name, payload, &filesize, - CBFS_COMPONENT_PAYLOAD, ¶m.baseaddress); - - free(filedata); - free(payload); - - if (add_file_to_cbfs(cbfsfile, filesize, param.baseaddress)) { - ERROR("Adding payload '%s' failed.\n", - param.filename); - free(cbfsfile); - free(rom); - return 1; - } - - if (writerom(param.cbfs_name, rom, romsize)) { - free(cbfsfile); - free(rom); - return 1; - } - - free(cbfsfile); - free(rom); - return 0; + return cbfs_add_component(param.cbfs_name, + param.filename, + param.name, + CBFS_COMPONENT_STAGE, + param.baseaddress, + cbfstool_convert_mkstage); } -static int cbfs_add_stage(void) +static int cbfs_add_payload(void) { - uint32_t filesize = 0; - void *rom, *filedata, *cbfsfile; - unsigned char *stage; - - if (!param.filename) { - ERROR("You need to specify -f/--filename.\n"); - return 1; - } - - if (!param.name) { - ERROR("You need to specify -n/--name.\n"); - return 1; - } - - rom = loadrom(param.cbfs_name); - if (rom == NULL) { - ERROR("Could not load ROM image '%s'.\n", - param.cbfs_name); - return 1; - } - - filedata = loadfile(param.filename, &filesize, 0, SEEK_SET); - if (filedata == NULL) { - ERROR("Could not load file '%s'.\n", - param.filename); - free(rom); - return 1; - } - - filesize = parse_elf_to_stage(filedata, &stage, param.algo, ¶m.baseaddress); - - cbfsfile = create_cbfs_file(param.name, stage, &filesize, - CBFS_COMPONENT_STAGE, ¶m.baseaddress); - - free(filedata); - free(stage); - - if (add_file_to_cbfs(cbfsfile, filesize, param.baseaddress)) { - ERROR("Adding stage '%s' failed.\n", - param.filename); - free(cbfsfile); - free(rom); - return 1; - } - - if (writerom(param.cbfs_name, rom, romsize)) { - free(cbfsfile); - free(rom); - return 1; - } - - free(cbfsfile); - free(rom); - return 0; + return cbfs_add_component(param.cbfs_name, + param.filename, + param.name, + CBFS_COMPONENT_PAYLOAD, + param.baseaddress, + cbfstool_convert_mkpayload); } static int cbfs_add_flat_binary(void) { - uint32_t filesize = 0; - void *rom, *filedata, *cbfsfile; - unsigned char *payload; - - if (!param.filename) { - ERROR("You need to specify -f/--filename.\n"); - return 1; - } - - if (!param.name) { - ERROR("You need to specify -n/--name.\n"); - return 1; - } - if (param.loadaddress == 0) { ERROR("You need to specify a valid " "-l/--load-address.\n"); return 1; } - if (param.entrypoint == 0) { ERROR("You need to specify a valid " "-e/--entry-point.\n"); return 1; } - - rom = loadrom(param.cbfs_name); - if (rom == NULL) { - ERROR("Could not load ROM image '%s'.\n", - param.cbfs_name); - return 1; - } - - filedata = loadfile(param.filename, &filesize, 0, SEEK_SET); - if (filedata == NULL) { - ERROR("Could not load file '%s'.\n", - param.filename); - free(rom); - return 1; - } - - filesize = parse_flat_binary_to_payload(filedata, &payload, - filesize, - param.loadaddress, - param.entrypoint, - param.algo); - free(filedata); - - if ((int)filesize <= 0) { - ERROR("Adding payload '%s' failed.\n", - param.filename); - free(rom); - return 1; - } - cbfsfile = create_cbfs_file(param.name, payload, &filesize, - CBFS_COMPONENT_PAYLOAD, ¶m.baseaddress); - - free(payload); - if (add_file_to_cbfs(cbfsfile, filesize, param.baseaddress)) { - ERROR("Adding payload '%s' failed.\n", - param.filename); - free(cbfsfile); - free(rom); - return 1; - } - if (writerom(param.cbfs_name, rom, romsize)) { - free(cbfsfile); - free(rom); - return 1; - } - - free(cbfsfile); - free(rom); - return 0; + return cbfs_add_component(param.cbfs_name, + param.filename, + param.name, + CBFS_COMPONENT_PAYLOAD, + param.baseaddress, + cbfstool_convert_mkflatpayload); } static int cbfs_remove(void) diff --git a/util/cbfstool/common.h b/util/cbfstool/common.h index a859e103f2..16c04c9c8e 100644 --- a/util/cbfstool/common.h +++ b/util/cbfstool/common.h @@ -98,14 +98,16 @@ comp_func_ptr compression_function(comp_algo algo); uint64_t intfiletype(const char *name); /* cbfs-mkpayload.c */ -int parse_elf_to_payload(unsigned char *input, unsigned char **output, - comp_algo algo); -int parse_flat_binary_to_payload(unsigned char *input, unsigned char **output, - int32_t input_size, uint32_t loadaddress, - uint32_t entrypoint, comp_algo algo); +int parse_elf_to_payload(const struct buffer *input, + struct buffer *output, comp_algo algo); +int parse_flat_binary_to_payload(const struct buffer *input, + struct buffer *output, + uint32_t loadaddress, + uint32_t entrypoint, + comp_algo algo); /* cbfs-mkstage.c */ -int parse_elf_to_stage(unsigned char *input, unsigned char **output, - comp_algo algo, uint32_t * location); +int parse_elf_to_stage(const struct buffer *input, struct buffer *output, + comp_algo algo, uint32_t *location); void *create_cbfs_file(const char *filename, void *data, uint32_t * datasize, uint32_t type, uint32_t * location); -- cgit v1.2.3