From 6ed0ba1e93f99edef7a62c3670b4ec61103e0ae9 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Mon, 29 Apr 2024 10:04:59 +0200
Subject: cbfstool: Read XIP stage alignment requirements from ELF
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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>
---
 util/cbfstool/cbfstool.c   | 23 +++++++++++++----------
 util/cbfstool/elfheaders.c |  5 ++++-
 util/cbfstool/elfparsing.h |  6 +++---
 3 files changed, 20 insertions(+), 14 deletions(-)

(limited to 'util')

diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c
index 88bf22b649..f81c133bf1 100644
--- a/util/cbfstool/cbfstool.c
+++ b/util/cbfstool/cbfstool.c
@@ -1156,23 +1156,26 @@ static int cbfstool_convert_mkstage(struct buffer *buffer, uint32_t *offset,
 	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 39faff209d..5bcac15e4a 100644
--- a/util/cbfstool/elfheaders.c
+++ b/util/cbfstool/elfheaders.c
@@ -1434,12 +1434,13 @@ int elf_writer_add_rel(struct elf_writer *ew, const char *sym, Elf64_Addr addr)
 	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 @@ int elf_program_file_size(const struct buffer *input, size_t *file_size)
 		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 d207f45fc4..b80a3b1083 100644
--- a/util/cbfstool/elfparsing.h
+++ b/util/cbfstool/elfparsing.h
@@ -114,9 +114,9 @@ int elf_writer_add_rel(struct elf_writer *ew, const char *sym, Elf64_Addr addr);
 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 */
-- 
cgit v1.2.3