Julius Werner has submitted this change. ( https://review.coreboot.org/c/coreboot/+/82102?usp=email )
Change subject: cbfstool: Read XIP stage alignment requirements from ELF ......................................................................
cbfstool: Read XIP stage alignment requirements from ELF
On x86_64 romstage can contain page tables and a page table pointer which have an larger alignment requirement of 4096. Instead of hardcoding it, read if from the ELF phdrs.
Change-Id: I94e4a4209b7441ecb2966a1342c3d46625771bb8 Signed-off-by: Arthur Heymans arthur@aheymans.xyz Reviewed-on: https://review.coreboot.org/c/coreboot/+/82102 Reviewed-by: Shuo Liu shuo.liu@intel.com Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Jérémy Compostella jeremy.compostella@intel.com Reviewed-by: Julius Werner jwerner@chromium.org --- M Makefile.mk M util/cbfstool/cbfstool.c M util/cbfstool/elfheaders.c M util/cbfstool/elfparsing.h 4 files changed, 20 insertions(+), 23 deletions(-)
Approvals: Shuo Liu: Looks good to me, but someone else must approve Jérémy Compostella: Looks good to me, but someone else must approve Julius Werner: Looks good to me, approved build bot (Jenkins): Verified
diff --git a/Makefile.mk b/Makefile.mk index e642ac7..3cfd97c 100644 --- a/Makefile.mk +++ b/Makefile.mk @@ -1276,15 +1276,6 @@ $(CONFIG_CBFS_PREFIX)/romstage-options := -b 0 endif ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32)$(CONFIG_ARCH_ROMSTAGE_X86_64),y) -# Use a 64 byte alignment to provide a minimum alignment -# requirement for the overall romstage. While the first object within -# romstage could have a 4 byte minimum alignment that doesn't mean the linker -# won't decide the entire section should be aligned to a larger value. In the -# future cbfstool should add XIP files proper and honor the alignment -# requirements of the program segment. -# -# Make sure that segment for .car.data is ignored while adding romstage. -$(CONFIG_CBFS_PREFIX)/romstage-align := 64 ifeq ($(CONFIG_NO_XIP_EARLY_STAGES),y) $(CONFIG_CBFS_PREFIX)/romstage-options := -S ".car.data" else diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 88bf22b..f81c133 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -1156,23 +1156,26 @@ struct cbfs_file *header) { struct buffer output; - size_t data_size; int ret;
- if (elf_program_file_size(buffer, &data_size) < 0) { - ERROR("Could not obtain ELF size\n"); - return 1; - } - /* * We need a final location for XIP parsing, so we need to call do_cbfs_locate() early * here. That is okay because XIP stages may not be compressed, so their size cannot * change anymore at a later point. */ - if (param.stage_xip && - do_cbfs_locate(offset, data_size)) { - ERROR("Could not find location for stage.\n"); - return 1; + if (param.stage_xip) { + size_t data_size, alignment; + if (elf_program_file_size_align(buffer, &data_size, &alignment) < 0) { + ERROR("Could not obtain ELF size & alignment\n"); + return 1; + } + + param.alignment = MAX(alignment, param.alignment); + + if (do_cbfs_locate(offset, data_size)) { + ERROR("Could not find location for stage.\n"); + return 1; + } }
struct cbfs_file_attr_stageheader *stageheader = (void *) diff --git a/util/cbfstool/elfheaders.c b/util/cbfstool/elfheaders.c index 39faff2..5bcac15 100644 --- a/util/cbfstool/elfheaders.c +++ b/util/cbfstool/elfheaders.c @@ -1434,12 +1434,13 @@ return add_rel(rel_sec, &rel); }
-int elf_program_file_size(const struct buffer *input, size_t *file_size) +int elf_program_file_size_align(const struct buffer *input, size_t *file_size, size_t *align) { Elf64_Ehdr ehdr; Elf64_Phdr *phdr; int i; size_t loadable_file_size = 0; + size_t align_size = 0;
if (elf_headers(input, &ehdr, &phdr, NULL)) return -1; @@ -1448,9 +1449,11 @@ if (phdr[i].p_type != PT_LOAD) continue; loadable_file_size += phdr[i].p_filesz; + align_size = MAX(align_size, phdr[i].p_align); }
*file_size = loadable_file_size; + *align = align_size;
free(phdr);
diff --git a/util/cbfstool/elfparsing.h b/util/cbfstool/elfparsing.h index d207f45..b80a3b1 100644 --- a/util/cbfstool/elfparsing.h +++ b/util/cbfstool/elfparsing.h @@ -114,9 +114,9 @@ int elf_writer_serialize(struct elf_writer *ew, struct buffer *out);
/* - * Calculate the loadable program's file size footprint. Returns < 0 on error, - * 0 on success. + * Calculate the loadable program's file size footprint and alignment requirements. + * Returns < 0 on error, 0 on success. */ -int elf_program_file_size(const struct buffer *input, size_t *file_size); +int elf_program_file_size_align(const struct buffer *input, size_t *file_size, size_t *align);
#endif /* ELFPARSING_H */