cbfstool: prepare for exposing rmodule logic
The core logic of the rmodule parser is ideal for processing romstage ELF files for XIP. To that end start the work of exposing the logic from rmodule so cbfstool can take advantage of it. The properties that both need require: - Single program segment - Relocation information - Filter relocation processing BUG=chrome-os-partner:44827 BRANCH=None TEST=Built rambi. Change-Id: I176d0ae0ae1933cdf6adac67d393ba676198861a Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/11595 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
parent
a0e7738463
commit
051a181f0c
|
@ -51,13 +51,10 @@ struct rmod_context {
|
||||||
Elf64_Addr *emitted_relocs;
|
Elf64_Addr *emitted_relocs;
|
||||||
|
|
||||||
/* The following fields are addresses within the linked program. */
|
/* The following fields are addresses within the linked program. */
|
||||||
Elf64_Addr link_addr;
|
|
||||||
Elf64_Addr entry;
|
|
||||||
Elf64_Addr parameters_begin;
|
Elf64_Addr parameters_begin;
|
||||||
Elf64_Addr parameters_end;
|
Elf64_Addr parameters_end;
|
||||||
Elf64_Addr bss_begin;
|
Elf64_Addr bss_begin;
|
||||||
Elf64_Addr bss_end;
|
Elf64_Addr bss_end;
|
||||||
Elf64_Xword size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -371,7 +368,7 @@ populate_sym(struct rmod_context *ctx, const char *sym_name, Elf64_Addr *addr,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int populate_program_info(struct rmod_context *ctx)
|
static int populate_rmodule_info(struct rmod_context *ctx)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const char *strtab;
|
const char *strtab;
|
||||||
|
@ -423,15 +420,6 @@ static int populate_program_info(struct rmod_context *ctx)
|
||||||
if (populate_sym(ctx, "_ebss", &ctx->bss_end, nsyms, strtab, 0))
|
if (populate_sym(ctx, "_ebss", &ctx->bss_end, nsyms, strtab, 0))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Honor the entry point within the ELF header. */
|
|
||||||
ctx->entry = ehdr->e_entry;
|
|
||||||
|
|
||||||
/* Link address is the virtual address of the program segment. */
|
|
||||||
ctx->link_addr = ctx->phdr->p_vaddr;
|
|
||||||
|
|
||||||
/* The program size is the memsz of the program segment. */
|
|
||||||
ctx->size = ctx->phdr->p_memsz;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,7 +504,6 @@ write_elf(const struct rmod_context *ctx, const struct buffer *in,
|
||||||
|
|
||||||
/* Create ELF writer with modified entry point. */
|
/* Create ELF writer with modified entry point. */
|
||||||
memcpy(&ehdr, &ctx->pelf.ehdr, sizeof(ehdr));
|
memcpy(&ehdr, &ctx->pelf.ehdr, sizeof(ehdr));
|
||||||
ehdr.e_entry = ctx->entry;
|
|
||||||
ew = elf_writer_init(&ehdr);
|
ew = elf_writer_init(&ehdr);
|
||||||
|
|
||||||
if (ew == NULL) {
|
if (ew == NULL) {
|
||||||
|
@ -544,11 +531,11 @@ write_elf(const struct rmod_context *ctx, const struct buffer *in,
|
||||||
loc += ctx->nrelocs * sizeof(Elf32_Addr);
|
loc += ctx->nrelocs * sizeof(Elf32_Addr);
|
||||||
ctx->xdr->put32(&rmod_header, loc);
|
ctx->xdr->put32(&rmod_header, loc);
|
||||||
/* module_link_start_address */
|
/* module_link_start_address */
|
||||||
ctx->xdr->put32(&rmod_header, ctx->link_addr);
|
ctx->xdr->put32(&rmod_header, ctx->phdr->p_vaddr);
|
||||||
/* module_program_size */
|
/* module_program_size */
|
||||||
ctx->xdr->put32(&rmod_header, ctx->size);
|
ctx->xdr->put32(&rmod_header, ctx->phdr->p_memsz);
|
||||||
/* module_entry_point */
|
/* module_entry_point */
|
||||||
ctx->xdr->put32(&rmod_header, ctx->entry);
|
ctx->xdr->put32(&rmod_header, ctx->pelf.ehdr.e_entry);
|
||||||
/* parameters_begin */
|
/* parameters_begin */
|
||||||
ctx->xdr->put32(&rmod_header, ctx->parameters_begin);
|
ctx->xdr->put32(&rmod_header, ctx->parameters_begin);
|
||||||
/* parameters_end */
|
/* parameters_end */
|
||||||
|
@ -631,16 +618,15 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rmodule_create(const struct buffer *elfin, struct buffer *elfout)
|
static int rmodule_init(struct rmod_context *ctx, const struct buffer *elfin)
|
||||||
{
|
{
|
||||||
struct rmod_context ctx;
|
|
||||||
struct parsed_elf *pelf;
|
struct parsed_elf *pelf;
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
memset(&ctx, 0, sizeof(ctx));
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
pelf = &ctx.pelf;
|
pelf = &ctx->pelf;
|
||||||
|
|
||||||
if (parse_elf(elfin, pelf, ELF_PARSE_ALL)) {
|
if (parse_elf(elfin, pelf, ELF_PARSE_ALL)) {
|
||||||
ERROR("Couldn't parse ELF!\n");
|
ERROR("Couldn't parse ELF!\n");
|
||||||
|
@ -656,32 +642,52 @@ int rmodule_create(const struct buffer *elfin, struct buffer *elfout)
|
||||||
/* Determine if architecture is supported. */
|
/* Determine if architecture is supported. */
|
||||||
for (i = 0; i < ARRAY_SIZE(reloc_ops); i++) {
|
for (i = 0; i < ARRAY_SIZE(reloc_ops); i++) {
|
||||||
if (reloc_ops[i].arch == pelf->ehdr.e_machine) {
|
if (reloc_ops[i].arch == pelf->ehdr.e_machine) {
|
||||||
ctx.ops = &reloc_ops[i];
|
ctx->ops = &reloc_ops[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.ops == NULL) {
|
if (ctx->ops == NULL) {
|
||||||
ERROR("ELF is unsupported arch: %u.\n", pelf->ehdr.e_machine);
|
ERROR("ELF is unsupported arch: %u.\n", pelf->ehdr.e_machine);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the endian ops. */
|
/* Set the endian ops. */
|
||||||
if (ctx.pelf.ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
|
if (ctx->pelf.ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
|
||||||
ctx.xdr = &xdr_be;
|
ctx->xdr = &xdr_be;
|
||||||
else
|
else
|
||||||
ctx.xdr = &xdr_le;
|
ctx->xdr = &xdr_le;
|
||||||
|
|
||||||
if (find_program_segment(&ctx))
|
if (find_program_segment(ctx))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (filter_relocation_sections(&ctx))
|
if (filter_relocation_sections(ctx))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rmodule_cleanup(struct rmod_context *ctx)
|
||||||
|
{
|
||||||
|
free(ctx->emitted_relocs);
|
||||||
|
parsed_elf_destroy(&ctx->pelf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmodule_create(const struct buffer *elfin, struct buffer *elfout)
|
||||||
|
{
|
||||||
|
struct rmod_context ctx;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (rmodule_init(&ctx, elfin))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (collect_relocations(&ctx))
|
if (collect_relocations(&ctx))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (populate_program_info(&ctx))
|
if (populate_rmodule_info(&ctx))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (write_elf(&ctx, elfin, elfout))
|
if (write_elf(&ctx, elfin, elfout))
|
||||||
|
@ -690,7 +696,6 @@ int rmodule_create(const struct buffer *elfin, struct buffer *elfout)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(ctx.emitted_relocs);
|
rmodule_cleanup(&ctx);
|
||||||
parsed_elf_destroy(pelf);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue