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>
This commit is contained in:
parent
8bbadded83
commit
c9cae530e5
@ -10,15 +10,16 @@
|
|||||||
#include "cbfs.h"
|
#include "cbfs.h"
|
||||||
#include "rmodule.h"
|
#include "rmodule.h"
|
||||||
|
|
||||||
/* Checks if program segment contains the ignored section */
|
/* Checks if program segment contains the ignored sections */
|
||||||
static int is_phdr_ignored(Elf64_Phdr *phdr, Elf64_Shdr *shdr)
|
static int is_phdr_ignored(Elf64_Phdr *phdr, Elf64_Shdr **shdrs)
|
||||||
{
|
{
|
||||||
/* If no ignored section, return false. */
|
/* If no ignored section, return false. */
|
||||||
if (shdr == NULL)
|
if (shdrs == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Elf64_Addr sh_start = shdr->sh_addr;
|
while (*shdrs) {
|
||||||
Elf64_Addr sh_end = shdr->sh_addr + shdr->sh_size;
|
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_start = phdr->p_vaddr;
|
||||||
Elf64_Addr ph_end = phdr->p_vaddr + phdr->p_memsz;
|
Elf64_Addr ph_end = phdr->p_vaddr + phdr->p_memsz;
|
||||||
|
|
||||||
@ -34,23 +35,41 @@ static int is_phdr_ignored(Elf64_Phdr *phdr, Elf64_Shdr *shdr)
|
|||||||
ERROR("Conflicting sections in segment\n");
|
ERROR("Conflicting sections in segment\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
shdrs++;
|
||||||
|
}
|
||||||
|
|
||||||
/* Program header doesn't need to be ignored. */
|
/* Program header doesn't need to be ignored. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find section header based on ignored section name */
|
/* Sections to be ignored are comma separated */
|
||||||
static Elf64_Shdr *find_ignored_section_header(struct parsed_elf *pelf,
|
static bool is_ignored_sections(const char *section_name,
|
||||||
const char *ignore_section)
|
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;
|
int i;
|
||||||
const char *shstrtab;
|
const char *shstrtab;
|
||||||
|
Elf64_Shdr **headers = NULL;
|
||||||
|
size_t size = 1;
|
||||||
|
|
||||||
/* No section needs to be ignored */
|
/* No section needs to be ignored */
|
||||||
if (ignore_section == NULL)
|
if (ignore_sections == NULL)
|
||||||
return 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 */
|
/* Get pointer to string table */
|
||||||
shstrtab = buffer_get(pelf->strtabs[pelf->ehdr.e_shstrndx]);
|
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];
|
shdr = &pelf->shdr[i];
|
||||||
section_name = &shstrtab[shdr->sh_name];
|
section_name = &shstrtab[shdr->sh_name];
|
||||||
|
|
||||||
/* If section name matches ignored string, return shdr */
|
/* If section name matches ignored string, add to list */
|
||||||
if (strcmp(section_name, ignore_section) == 0)
|
if (is_ignored_sections(section_name, ignore_sections)) {
|
||||||
return shdr;
|
headers = realloc(headers, sizeof(*headers) * ++size);
|
||||||
|
if (!headers) {
|
||||||
|
ERROR("Memory allocation failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
headers[size - 2] = shdr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No section matches ignore string */
|
if (headers)
|
||||||
return NULL;
|
headers[size - 1] = NULL;
|
||||||
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fill_cbfs_stageheader(struct cbfs_file_attr_stageheader *stageheader,
|
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;
|
struct parsed_elf pelf;
|
||||||
Elf64_Phdr *phdr;
|
Elf64_Phdr *phdr;
|
||||||
Elf64_Ehdr *ehdr;
|
Elf64_Ehdr *ehdr;
|
||||||
Elf64_Shdr *shdr_ignored;
|
Elf64_Shdr **shdrs_ignored;
|
||||||
Elf64_Addr virt_to_phys;
|
Elf64_Addr virt_to_phys;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
@ -116,17 +142,17 @@ int parse_elf_to_stage(const struct buffer *input, struct buffer *output,
|
|||||||
ehdr = &pelf.ehdr;
|
ehdr = &pelf.ehdr;
|
||||||
phdr = &pelf.phdr[0];
|
phdr = &pelf.phdr[0];
|
||||||
|
|
||||||
/* Find the section header corresponding to ignored-section */
|
/* Find the section headers corresponding to ignored-sections */
|
||||||
shdr_ignored = find_ignored_section_header(&pelf, ignore_section);
|
shdrs_ignored = find_ignored_sections_header(&pelf, ignore_section);
|
||||||
|
|
||||||
if (ignore_section && (shdr_ignored == NULL))
|
if (ignore_section && (shdrs_ignored == NULL))
|
||||||
WARN("Ignore section not found\n");
|
WARN("Ignore section(s) not found\n");
|
||||||
|
|
||||||
headers = ehdr->e_phnum;
|
headers = ehdr->e_phnum;
|
||||||
|
|
||||||
/* Ignore the program header containing ignored section */
|
/* Ignore the program header containing ignored section */
|
||||||
for (i = 0; i < headers; i++) {
|
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;
|
phdr[i].p_type = PT_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,8 +243,7 @@ err:
|
|||||||
|
|
||||||
struct xip_context {
|
struct xip_context {
|
||||||
struct rmod_context rmodctx;
|
struct rmod_context rmodctx;
|
||||||
size_t ignored_section_idx;
|
Elf64_Shdr **ignored_sections;
|
||||||
Elf64_Shdr *ignored_section;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int rmod_filter(struct reloc_filter *f, const Elf64_Rela *r)
|
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;
|
struct parsed_elf *pelf;
|
||||||
Elf64_Sym *sym;
|
Elf64_Sym *sym;
|
||||||
struct xip_context *xipctx;
|
struct xip_context *xipctx;
|
||||||
|
Elf64_Shdr **sections;
|
||||||
|
|
||||||
xipctx = f->context;
|
xipctx = f->context;
|
||||||
pelf = &xipctx->rmodctx.pelf;
|
pelf = &xipctx->rmodctx.pelf;
|
||||||
|
|
||||||
/* Allow everything through if there isn't an ignored section. */
|
/* Allow everything through if there isn't an ignored section. */
|
||||||
if (xipctx->ignored_section == NULL)
|
if (xipctx->ignored_sections == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
reloc_type = ELF64_R_TYPE(r->r_info);
|
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];
|
sym = &pelf->syms[symbol_index];
|
||||||
|
|
||||||
/* Nothing to filter. Relocation is not being applied to the
|
/* Nothing to filter. Relocation is not being applied to the
|
||||||
* ignored section. */
|
* ignored sections. */
|
||||||
if (sym->st_shndx != xipctx->ignored_section_idx)
|
for (sections = xipctx->ignored_sections; *sections; sections++)
|
||||||
|
if (sym->st_shndx == *sections - pelf->shdr)
|
||||||
|
break;
|
||||||
|
if (!*sections)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* If there is any relocation to the ignored section that isn't
|
/* 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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Relocation referencing ignored section. Don't emit it. */
|
/* Relocation referencing ignored sections. Don't emit it. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_elf_to_xip_stage(const struct buffer *input, struct buffer *output,
|
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 cbfs_file_attr_stageheader *stageheader)
|
||||||
{
|
{
|
||||||
struct xip_context xipctx;
|
struct xip_context xipctx;
|
||||||
@ -273,7 +302,6 @@ int parse_elf_to_xip_stage(const struct buffer *input, struct buffer *output,
|
|||||||
Elf64_Xword i;
|
Elf64_Xword i;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
xipctx.ignored_section_idx = 0;
|
|
||||||
rmodctx = &xipctx.rmodctx;
|
rmodctx = &xipctx.rmodctx;
|
||||||
pelf = &rmodctx->pelf;
|
pelf = &rmodctx->pelf;
|
||||||
|
|
||||||
@ -287,12 +315,8 @@ int parse_elf_to_xip_stage(const struct buffer *input, struct buffer *output,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
xipctx.ignored_section =
|
xipctx.ignored_sections =
|
||||||
find_ignored_section_header(pelf, ignore_section);
|
find_ignored_sections_header(pelf, ignore_sections);
|
||||||
|
|
||||||
if (xipctx.ignored_section != NULL)
|
|
||||||
xipctx.ignored_section_idx =
|
|
||||||
xipctx.ignored_section - pelf->shdr;
|
|
||||||
|
|
||||||
filter.filter = rmod_filter;
|
filter.filter = rmod_filter;
|
||||||
filter.context = &xipctx;
|
filter.context = &xipctx;
|
||||||
|
@ -46,7 +46,7 @@ static struct param {
|
|||||||
const char *region_name;
|
const char *region_name;
|
||||||
const char *source_region;
|
const char *source_region;
|
||||||
const char *bootblock;
|
const char *bootblock;
|
||||||
const char *ignore_section;
|
const char *ignore_sections;
|
||||||
const char *ucode_region;
|
const char *ucode_region;
|
||||||
uint64_t u64val;
|
uint64_t u64val;
|
||||||
uint32_t type;
|
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);
|
uint32_t host_space_address = convert_addr_space(param.image_region, *offset);
|
||||||
assert(IS_HOST_SPACE_ADDRESS(host_space_address));
|
assert(IS_HOST_SPACE_ADDRESS(host_space_address));
|
||||||
ret = parse_elf_to_xip_stage(buffer, &output, host_space_address,
|
ret = parse_elf_to_xip_stage(buffer, &output, host_space_address,
|
||||||
param.ignore_section, stageheader);
|
param.ignore_sections, stageheader);
|
||||||
} else {
|
} else {
|
||||||
ret = parse_elf_to_stage(buffer, &output, param.ignore_section,
|
ret = parse_elf_to_stage(buffer, &output, param.ignore_sections,
|
||||||
stageheader);
|
stageheader);
|
||||||
}
|
}
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
@ -1968,7 +1968,8 @@ static void usage(char *name)
|
|||||||
" (linux specific: [-C cmdline] [-I initrd]) "
|
" (linux specific: [-C cmdline] [-I initrd]) "
|
||||||
"Add a payload to the ROM\n"
|
"Add a payload to the ROM\n"
|
||||||
" add-stage [-r image,regions] -f FILE -n NAME [-A hash] \\\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"
|
" [-a alignment] [-Q|--pow2page] \\\n"
|
||||||
" [-y|--xip] [--ibb] \\\n"
|
" [-y|--xip] [--ibb] \\\n"
|
||||||
" [--ext-win-base win-base --ext-win-size win-size] "
|
" [--ext-win-base win-base --ext-win-size win-size] "
|
||||||
@ -2271,7 +2272,7 @@ int main(int argc, char **argv)
|
|||||||
param.cmdline = optarg;
|
param.cmdline = optarg;
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
param.ignore_section = optarg;
|
param.ignore_sections = optarg;
|
||||||
break;
|
break;
|
||||||
case 'y':
|
case 'y':
|
||||||
param.stage_xip = true;
|
param.stage_xip = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user