cbfstool: Add option to ignore section in add-stage
Allow add-stage to have an optional parameter for ignoring any section. This is required to ensure proper operation of elf_to_stage in case of loadable segments with zero filesize. Change-Id: I49ad62c2a4260ab9cec173c80c0f16923fc66c79 Signed-off-by: Furquan Shaikh <furquan@google.com> Reviewed-on: http://review.coreboot.org/7304 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com>
This commit is contained in:
parent
cc6f84c411
commit
405304aca3
|
@ -28,16 +28,79 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "cbfs.h"
|
#include "cbfs.h"
|
||||||
|
|
||||||
|
/* Checks if program segment contains the ignored section */
|
||||||
|
static int is_phdr_ignored(Elf64_Phdr *phdr, Elf64_Shdr *shdr)
|
||||||
|
{
|
||||||
|
/* If no ignored section, return false. */
|
||||||
|
if (shdr == 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;
|
||||||
|
|
||||||
|
/* Return true only if section occupies whole of segment. */
|
||||||
|
if ((sh_start == ph_start) && (sh_end == ph_end)) {
|
||||||
|
DEBUG("Ignoring program segment at %p\n", (void *)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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char *shstrtab;
|
||||||
|
|
||||||
|
/* No section needs to be ignored */
|
||||||
|
if (ignore_section == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
DEBUG("Section to be ignored: %s\n", ignore_section);
|
||||||
|
|
||||||
|
/* Get pointer to string table */
|
||||||
|
shstrtab = buffer_get(pelf->strtabs[pelf->ehdr.e_shstrndx]);
|
||||||
|
|
||||||
|
for (i = 0; i < pelf->ehdr.e_shnum; i++) {
|
||||||
|
Elf64_Shdr *shdr;
|
||||||
|
const char *section_name;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No section matches ignore string */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* returns size of result, or -1 if error.
|
/* returns size of result, or -1 if error.
|
||||||
* Note that, with the new code, this function
|
* Note that, with the new code, this function
|
||||||
* works for all elf files, not just the restricted set.
|
* works for all elf files, not just the restricted set.
|
||||||
*/
|
*/
|
||||||
int parse_elf_to_stage(const struct buffer *input, struct buffer *output,
|
int parse_elf_to_stage(const struct buffer *input, struct buffer *output,
|
||||||
uint32_t arch, comp_algo algo, uint32_t *location)
|
uint32_t arch, comp_algo algo, uint32_t *location,
|
||||||
|
const char *ignore_section)
|
||||||
{
|
{
|
||||||
struct parsed_elf pelf;
|
struct parsed_elf pelf;
|
||||||
Elf64_Phdr *phdr;
|
Elf64_Phdr *phdr;
|
||||||
Elf64_Ehdr *ehdr;
|
Elf64_Ehdr *ehdr;
|
||||||
|
Elf64_Shdr *shdr_ignored;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
struct buffer outheader;
|
struct buffer outheader;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
@ -62,8 +125,20 @@ 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 */
|
||||||
|
shdr_ignored = find_ignored_section_header(&pelf, ignore_section);
|
||||||
|
|
||||||
|
if (ignore_section && (shdr_ignored == NULL))
|
||||||
|
WARN("Ignore section not found\n");
|
||||||
|
|
||||||
headers = ehdr->e_phnum;
|
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))
|
||||||
|
phdr[i].p_type = PT_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
data_start = ~0;
|
data_start = ~0;
|
||||||
data_end = 0;
|
data_end = 0;
|
||||||
mem_end = 0;
|
mem_end = 0;
|
||||||
|
|
|
@ -41,6 +41,7 @@ static struct param {
|
||||||
char *name;
|
char *name;
|
||||||
char *filename;
|
char *filename;
|
||||||
char *bootblock;
|
char *bootblock;
|
||||||
|
char *ignore_section;
|
||||||
uint64_t u64val;
|
uint64_t u64val;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t baseaddress;
|
uint32_t baseaddress;
|
||||||
|
@ -184,7 +185,7 @@ static int cbfstool_convert_mkstage(struct buffer *buffer, uint32_t *offset)
|
||||||
struct buffer output;
|
struct buffer output;
|
||||||
int ret;
|
int ret;
|
||||||
ret = parse_elf_to_stage(buffer, &output, param.arch, param.algo,
|
ret = parse_elf_to_stage(buffer, &output, param.arch, param.algo,
|
||||||
offset);
|
offset, param.ignore_section);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return -1;
|
return -1;
|
||||||
buffer_delete(buffer);
|
buffer_delete(buffer);
|
||||||
|
@ -516,7 +517,7 @@ static int cbfs_update_fit(void)
|
||||||
static const struct command commands[] = {
|
static const struct command commands[] = {
|
||||||
{"add", "f:n:t:b:vh?", cbfs_add},
|
{"add", "f:n:t:b:vh?", cbfs_add},
|
||||||
{"add-payload", "f:n:t:c:b:vh?C:I:", cbfs_add_payload},
|
{"add-payload", "f:n:t:c:b:vh?C:I:", cbfs_add_payload},
|
||||||
{"add-stage", "f:n:t:c:b:vh?", cbfs_add_stage},
|
{"add-stage", "f:n:t:c:b:S:vh?", cbfs_add_stage},
|
||||||
{"add-flat-binary", "f:n:l:e:c:b:vh?", cbfs_add_flat_binary},
|
{"add-flat-binary", "f:n:l:e:c:b:vh?", cbfs_add_flat_binary},
|
||||||
{"add-int", "i:n:b:vh?", cbfs_add_integer},
|
{"add-int", "i:n:b:vh?", cbfs_add_integer},
|
||||||
{"remove", "n:vh?", cbfs_remove},
|
{"remove", "n:vh?", cbfs_remove},
|
||||||
|
@ -546,6 +547,7 @@ static struct option long_options[] = {
|
||||||
{"empty-fits", required_argument, 0, 'x' },
|
{"empty-fits", required_argument, 0, 'x' },
|
||||||
{"initrd", required_argument, 0, 'I' },
|
{"initrd", required_argument, 0, 'I' },
|
||||||
{"cmdline", required_argument, 0, 'C' },
|
{"cmdline", required_argument, 0, 'C' },
|
||||||
|
{"ignore-sec", required_argument, 0, 'S' },
|
||||||
{"verbose", no_argument, 0, 'v' },
|
{"verbose", no_argument, 0, 'v' },
|
||||||
{"help", no_argument, 0, 'h' },
|
{"help", no_argument, 0, 'h' },
|
||||||
{NULL, 0, 0, 0 }
|
{NULL, 0, 0, 0 }
|
||||||
|
@ -566,7 +568,8 @@ static void usage(char *name)
|
||||||
" add-payload -f FILE -n NAME [-c compression] [-b base] "
|
" add-payload -f FILE -n NAME [-c compression] [-b base] "
|
||||||
"Add a payload to the ROM\n"
|
"Add a payload to the ROM\n"
|
||||||
" (linux specific: [-C cmdline] [-I initrd])\n"
|
" (linux specific: [-C cmdline] [-I initrd])\n"
|
||||||
" add-stage -f FILE -n NAME [-c compression] [-b base] "
|
" add-stage -f FILE -n NAME [-c compression] [-b base] \\\n"
|
||||||
|
" [-S section-to-ignore] "
|
||||||
"Add a stage to the ROM\n"
|
"Add a stage to the ROM\n"
|
||||||
" add-flat-binary -f FILE -n NAME -l load-address \\\n"
|
" add-flat-binary -f FILE -n NAME -l load-address \\\n"
|
||||||
" -e entry-point [-c compression] [-b base] "
|
" -e entry-point [-c compression] [-b base] "
|
||||||
|
@ -714,6 +717,9 @@ int main(int argc, char **argv)
|
||||||
case 'C':
|
case 'C':
|
||||||
param.cmdline = optarg;
|
param.cmdline = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'S':
|
||||||
|
param.ignore_section = optarg;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
case '?':
|
case '?':
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
|
|
|
@ -139,7 +139,8 @@ int parse_flat_binary_to_payload(const struct buffer *input,
|
||||||
comp_algo algo);
|
comp_algo algo);
|
||||||
/* cbfs-mkstage.c */
|
/* cbfs-mkstage.c */
|
||||||
int parse_elf_to_stage(const struct buffer *input, struct buffer *output,
|
int parse_elf_to_stage(const struct buffer *input, struct buffer *output,
|
||||||
uint32_t arch, comp_algo algo, uint32_t *location);
|
uint32_t arch, comp_algo algo, uint32_t *location,
|
||||||
|
const char *ignore_section);
|
||||||
|
|
||||||
void print_supported_filetypes(void);
|
void print_supported_filetypes(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue