summaryrefslogtreecommitdiff
path: root/util/cbfstool
diff options
context:
space:
mode:
authorJeremy Compostella <jeremy.compostella@intel.com>2023-08-30 10:25:33 -0700
committerJulius Werner <jwerner@chromium.org>2023-09-14 21:01:48 +0000
commitc9cae530e5ac54c5b3639d0d555966ca5cad65ff (patch)
tree32d56be8b587deff5db0c3fb8a8f6ac991ec9a41 /util/cbfstool
parent8bbadded831e50ec2fa3808c8f1f39345d9dee8d (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.c118
-rw-r--r--util/cbfstool/cbfstool.c11
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;