diff options
author | Jeremy Compostella <jeremy.compostella@intel.com> | 2023-08-30 10:25:33 -0700 |
---|---|---|
committer | Julius Werner <jwerner@chromium.org> | 2023-09-14 21:01:48 +0000 |
commit | c9cae530e5ac54c5b3639d0d555966ca5cad65ff (patch) | |
tree | 32d56be8b587deff5db0c3fb8a8f6ac991ec9a41 /util/cbfstool | |
parent | 8bbadded831e50ec2fa3808c8f1f39345d9dee8d (diff) |
cbfstool: Make add-stage support multiple ignore sections
For x86 eXecute-In-Place (XIP) .data section support, cbfstool need to
to skip relocation of the .data section symbols in addition to
.car.data section symbols.
To support this requirement, this patch makes the `-S` option take a
multiple section names separated by commas.
TEST=With `-S ".car.data .data"`, XIP pre-memory stages with
a `.data` section do not have any of the `.car.data` or `.data`
section symbols relocated.
Change-Id: Icf09ee5a318e37c5da94bba6c0a0f39485963d3a
Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/77560
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'util/cbfstool')
-rw-r--r-- | util/cbfstool/cbfs-mkstage.c | 118 | ||||
-rw-r--r-- | util/cbfstool/cbfstool.c | 11 |
2 files changed, 77 insertions, 52 deletions
diff --git a/util/cbfstool/cbfs-mkstage.c b/util/cbfstool/cbfs-mkstage.c index be8573861b..54150cc534 100644 --- a/util/cbfstool/cbfs-mkstage.c +++ b/util/cbfstool/cbfs-mkstage.c @@ -10,47 +10,66 @@ #include "cbfs.h" #include "rmodule.h" -/* Checks if program segment contains the ignored section */ -static int is_phdr_ignored(Elf64_Phdr *phdr, Elf64_Shdr *shdr) +/* Checks if program segment contains the ignored sections */ +static int is_phdr_ignored(Elf64_Phdr *phdr, Elf64_Shdr **shdrs) { /* If no ignored section, return false. */ - if (shdr == NULL) + if (shdrs == NULL) return 0; - Elf64_Addr sh_start = shdr->sh_addr; - Elf64_Addr sh_end = shdr->sh_addr + shdr->sh_size; - Elf64_Addr ph_start = phdr->p_vaddr; - Elf64_Addr ph_end = phdr->p_vaddr + phdr->p_memsz; + while (*shdrs) { + Elf64_Addr sh_start = (*shdrs)->sh_addr; + Elf64_Addr sh_end = (*shdrs)->sh_addr + (*shdrs)->sh_size; + Elf64_Addr ph_start = phdr->p_vaddr; + Elf64_Addr ph_end = phdr->p_vaddr + phdr->p_memsz; - /* Return true only if section occupies whole of segment. */ - if ((sh_start == ph_start) && (sh_end == ph_end)) { - DEBUG("Ignoring program segment at 0x%" PRIx64 "\n", ph_start); - return 1; - } + /* Return true only if section occupies whole of segment. */ + if ((sh_start == ph_start) && (sh_end == ph_end)) { + DEBUG("Ignoring program segment at 0x%" PRIx64 "\n", ph_start); + return 1; + } - /* If shdr intersects phdr at all, its a conflict */ - if (((sh_start >= ph_start) && (sh_start <= ph_end)) || - ((sh_end >= ph_start) && (sh_end <= ph_end))) { - ERROR("Conflicting sections in segment\n"); - exit(1); + /* If shdr intersects phdr at all, its a conflict */ + if (((sh_start >= ph_start) && (sh_start <= ph_end)) || + ((sh_end >= ph_start) && (sh_end <= ph_end))) { + ERROR("Conflicting sections in segment\n"); + exit(1); + } + shdrs++; } /* Program header doesn't need to be ignored. */ return 0; } -/* Find section header based on ignored section name */ -static Elf64_Shdr *find_ignored_section_header(struct parsed_elf *pelf, - const char *ignore_section) +/* Sections to be ignored are comma separated */ +static bool is_ignored_sections(const char *section_name, + const char *ignore_sections) +{ + const char *cur, *comma; + + for (cur = ignore_sections; (comma = strchr(cur, ',')); cur = comma + 1) + if (!strncmp(cur, section_name, comma - cur)) + return true; + return !strcmp(cur, section_name); +} + +/* Find section headers based on ignored section names. + * Returns a NULL-terminated list of section headers. + */ +static Elf64_Shdr **find_ignored_sections_header(struct parsed_elf *pelf, + const char *ignore_sections) { int i; const char *shstrtab; + Elf64_Shdr **headers = NULL; + size_t size = 1; /* No section needs to be ignored */ - if (ignore_section == NULL) + if (ignore_sections == NULL) return NULL; - DEBUG("Section to be ignored: %s\n", ignore_section); + DEBUG("Sections to be ignored: %s\n", ignore_sections); /* Get pointer to string table */ shstrtab = buffer_get(pelf->strtabs[pelf->ehdr.e_shstrndx]); @@ -62,13 +81,20 @@ static Elf64_Shdr *find_ignored_section_header(struct parsed_elf *pelf, shdr = &pelf->shdr[i]; section_name = &shstrtab[shdr->sh_name]; - /* If section name matches ignored string, return shdr */ - if (strcmp(section_name, ignore_section) == 0) - return shdr; + /* If section name matches ignored string, add to list */ + if (is_ignored_sections(section_name, ignore_sections)) { + headers = realloc(headers, sizeof(*headers) * ++size); + if (!headers) { + ERROR("Memory allocation failed\n"); + exit(1); + } + headers[size - 2] = shdr; + } } - /* No section matches ignore string */ - return NULL; + if (headers) + headers[size - 1] = NULL; + return headers; } static int fill_cbfs_stageheader(struct cbfs_file_attr_stageheader *stageheader, @@ -98,7 +124,7 @@ int parse_elf_to_stage(const struct buffer *input, struct buffer *output, struct parsed_elf pelf; Elf64_Phdr *phdr; Elf64_Ehdr *ehdr; - Elf64_Shdr *shdr_ignored; + Elf64_Shdr **shdrs_ignored; Elf64_Addr virt_to_phys; int ret = -1; @@ -116,17 +142,17 @@ int parse_elf_to_stage(const struct buffer *input, struct buffer *output, ehdr = &pelf.ehdr; phdr = &pelf.phdr[0]; - /* Find the section header corresponding to ignored-section */ - shdr_ignored = find_ignored_section_header(&pelf, ignore_section); + /* Find the section headers corresponding to ignored-sections */ + shdrs_ignored = find_ignored_sections_header(&pelf, ignore_section); - if (ignore_section && (shdr_ignored == NULL)) - WARN("Ignore section not found\n"); + if (ignore_section && (shdrs_ignored == NULL)) + WARN("Ignore section(s) not found\n"); headers = ehdr->e_phnum; /* Ignore the program header containing ignored section */ for (i = 0; i < headers; i++) { - if (is_phdr_ignored(&phdr[i], shdr_ignored)) + if (is_phdr_ignored(&phdr[i], shdrs_ignored)) phdr[i].p_type = PT_NULL; } @@ -217,8 +243,7 @@ err: struct xip_context { struct rmod_context rmodctx; - size_t ignored_section_idx; - Elf64_Shdr *ignored_section; + Elf64_Shdr **ignored_sections; }; static int rmod_filter(struct reloc_filter *f, const Elf64_Rela *r) @@ -228,12 +253,13 @@ static int rmod_filter(struct reloc_filter *f, const Elf64_Rela *r) struct parsed_elf *pelf; Elf64_Sym *sym; struct xip_context *xipctx; + Elf64_Shdr **sections; xipctx = f->context; pelf = &xipctx->rmodctx.pelf; /* Allow everything through if there isn't an ignored section. */ - if (xipctx->ignored_section == NULL) + if (xipctx->ignored_sections == NULL) return 1; reloc_type = ELF64_R_TYPE(r->r_info); @@ -241,8 +267,11 @@ static int rmod_filter(struct reloc_filter *f, const Elf64_Rela *r) sym = &pelf->syms[symbol_index]; /* Nothing to filter. Relocation is not being applied to the - * ignored section. */ - if (sym->st_shndx != xipctx->ignored_section_idx) + * ignored sections. */ + for (sections = xipctx->ignored_sections; *sections; sections++) + if (sym->st_shndx == *sections - pelf->shdr) + break; + if (!*sections) return 1; /* If there is any relocation to the ignored section that isn't @@ -255,12 +284,12 @@ static int rmod_filter(struct reloc_filter *f, const Elf64_Rela *r) return -1; } - /* Relocation referencing ignored section. Don't emit it. */ + /* Relocation referencing ignored sections. Don't emit it. */ return 0; } int parse_elf_to_xip_stage(const struct buffer *input, struct buffer *output, - uint32_t location, const char *ignore_section, + uint32_t location, const char *ignore_sections, struct cbfs_file_attr_stageheader *stageheader) { struct xip_context xipctx; @@ -273,7 +302,6 @@ int parse_elf_to_xip_stage(const struct buffer *input, struct buffer *output, Elf64_Xword i; int ret = -1; - xipctx.ignored_section_idx = 0; rmodctx = &xipctx.rmodctx; pelf = &rmodctx->pelf; @@ -287,12 +315,8 @@ int parse_elf_to_xip_stage(const struct buffer *input, struct buffer *output, goto out; } - xipctx.ignored_section = - find_ignored_section_header(pelf, ignore_section); - - if (xipctx.ignored_section != NULL) - xipctx.ignored_section_idx = - xipctx.ignored_section - pelf->shdr; + xipctx.ignored_sections = + find_ignored_sections_header(pelf, ignore_sections); filter.filter = rmod_filter; filter.context = &xipctx; diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index c825a13c72..3df7b52089 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -46,7 +46,7 @@ static struct param { const char *region_name; const char *source_region; const char *bootblock; - const char *ignore_section; + const char *ignore_sections; const char *ucode_region; uint64_t u64val; uint32_t type; @@ -1179,9 +1179,9 @@ static int cbfstool_convert_mkstage(struct buffer *buffer, uint32_t *offset, uint32_t host_space_address = convert_addr_space(param.image_region, *offset); assert(IS_HOST_SPACE_ADDRESS(host_space_address)); ret = parse_elf_to_xip_stage(buffer, &output, host_space_address, - param.ignore_section, stageheader); + param.ignore_sections, stageheader); } else { - ret = parse_elf_to_stage(buffer, &output, param.ignore_section, + ret = parse_elf_to_stage(buffer, &output, param.ignore_sections, stageheader); } if (ret != 0) @@ -1968,7 +1968,8 @@ static void usage(char *name) " (linux specific: [-C cmdline] [-I initrd]) " "Add a payload to the ROM\n" " add-stage [-r image,regions] -f FILE -n NAME [-A hash] \\\n" - " [-c compression] [-b base] [-S section-to-ignore] \\\n" + " [-c compression] [-b base] \\\n" + " [-S comma-separated-section(s)-to-ignore] \\\n" " [-a alignment] [-Q|--pow2page] \\\n" " [-y|--xip] [--ibb] \\\n" " [--ext-win-base win-base --ext-win-size win-size] " @@ -2271,7 +2272,7 @@ int main(int argc, char **argv) param.cmdline = optarg; break; case 'S': - param.ignore_section = optarg; + param.ignore_sections = optarg; break; case 'y': param.stage_xip = true; |