mkbootimage: add elf_use_ph patch by mwojcik

This commit is contained in:
2026-02-14 18:11:58 +08:00
parent 6cfb6fd1fc
commit bd466202d4
2 changed files with 221 additions and 1 deletions

View File

@@ -59,7 +59,8 @@
};
propagatedBuildInputs = [pkgs.libelf pkgs.pcre];
patchPhase = ''
patches = [ ./mkbootimage-elf-use-ph.diff ];
postPatch = ''
substituteInPlace Makefile --replace "git rev-parse --short HEAD" "echo nix"
'';
installPhase = ''

219
mkbootimage-elf-use-ph.diff Normal file
View File

@@ -0,0 +1,219 @@
diff --git a/src/bif.c b/src/bif.c
index f3e0615..e2caec9 100644
--- a/src/bif.c
+++ b/src/bif.c
@@ -332,8 +332,9 @@ static error bif_parse_file(lexer_t *lex, bif_cfg_t *cfg, bif_node_t *node) {
node->load = 0;
node->offset = 0;
node->bootloader = 0;
+ node->elf_use_ph = 0;
node->fsbl_config = 0;
- node->pmufw_image = 0;
+ node->pmufw_image = 0;
node->exception_level = BOOTROM_PART_ATTR_EXC_LVL_EL0;
node->partition_owner = BOOTROM_PART_ATTR_OWNER_FSBL;
node->destination_cpu = BOOTROM_PART_ATTR_DEST_CPU_NONE;
@@ -462,6 +463,11 @@ error bif_node_set_attr(
return SUCCESS;
}
+ if (strcmp(attr_name, "elf_use_ph") == 0) {
+ node->elf_use_ph = 0xFF;
+ return SUCCESS;
+ }
+
if (strcmp(attr_name, "partition_owner") == 0) {
if (!value) {
perrorf(lex, "the \"%s\" attribute requires an argument\n", attr_name);
diff --git a/src/bif.h b/src/bif.h
index f76b13e..cf73670 100644
--- a/src/bif.h
+++ b/src/bif.h
@@ -40,6 +40,7 @@ typedef struct bif_node_t {
uint32_t load;
uint32_t offset;
uint32_t partition_owner;
+ uint8_t elf_use_ph; /* boolean */
/* supported zynqmp attributes */
uint8_t fsbl_config; /* boolean */
diff --git a/src/bootrom.c b/src/bootrom.c
index 4b6ee25..af90570 100644
--- a/src/bootrom.c
+++ b/src/bootrom.c
@@ -187,7 +187,8 @@ error append_file_to_image(uint32_t *addr,
img_size,
&elf_nbits,
&elf_load,
- &elf_entry);
+ &elf_entry,
+ node.elf_use_ph);
if (err) {
errorf("ELF file reading failed\n");
@@ -372,7 +373,8 @@ error create_boot_image(uint32_t *img_ptr,
&pmufw_img_size,
&pmufw_img_nbits,
&pmufw_img_load,
- &pmufw_img_entry);
+ &pmufw_img_entry,
+ bif_cfg->nodes[i].elf_use_ph);
if (err) {
errorf("failed to parse ELF file: %s\n", bif_cfg->nodes[i].fname);
return ERROR_BOOTROM_ELF;
diff --git a/src/file/elf.c b/src/file/elf.c
index 410fed6..4fd7ded 100644
--- a/src/file/elf.c
+++ b/src/file/elf.c
@@ -34,11 +34,75 @@
#include <gelf.h>
#include <unistd.h>
+static error elf_create_image_from_ph(Elf *elf, uint32_t start_addr, uint8_t *out_buf) {
+ size_t n_phdrs;
+
+ if(elf_getphdrnum(elf, &n_phdrs) != 0) {
+ printf("elf_getphdrnum failed\n");
+ return ERROR_BOOTROM_ELF;
+ }
+ size_t file_size;
+ uint8_t *raw_data = elf_rawfile(elf, &file_size);
+ if (raw_data == NULL) {
+ return ERROR_BOOTROM_ELF;
+ }
+ for (size_t i = 0; i < n_phdrs; ++i) {
+ GElf_Phdr phdr;
+ if (gelf_getphdr(elf, i, &phdr) == NULL) {
+ printf("gelf_getphdr returned no address\n");
+ continue;
+ }
+ if (phdr.p_type == PT_LOAD) {
+ // loadable, get the data
+ if (phdr.p_offset + phdr.p_filesz > file_size) {
+ // somehow offset is further than the whole file size
+ return ERROR_BOOTROM_ELF;
+ }
+ if (phdr.p_filesz > 0) {
+ uint8_t *segment_data = raw_data + phdr.p_offset;
+ size_t segment_size = phdr.p_filesz;
+
+ memcpy(out_buf + phdr.p_paddr - start_addr,
+ segment_data,
+ segment_size);
+ }
+ }
+ }
+ return SUCCESS;
+}
+
static bool elf_is_loadable_section(const GElf_Shdr *elf_shdr) {
return elf_shdr->sh_type != SHT_NOBITS && (elf_shdr->sh_flags & SHF_ALLOC) &&
elf_shdr->sh_size != 0;
}
+static error elf_get_startaddr_endaddr_from_ph(Elf *elf, uint32_t *start_addr, uint32_t *end_addr) {
+ size_t n_phdrs;
+ *start_addr = -1;
+ *end_addr = 0;
+
+ if (elf_getphdrnum(elf, &n_phdrs) != 0) {
+ return ERROR_BOOTROM_ELF;
+ }
+
+ for (size_t i = 0; i < n_phdrs; ++i) {
+ GElf_Phdr phdr;
+ if (gelf_getphdr(elf, i, &phdr) == NULL) {
+ continue;
+ }
+ if (phdr.p_type == PT_LOAD) {
+ if (*start_addr > phdr.p_paddr) {
+ *start_addr = phdr.p_paddr;
+ }
+
+ if (phdr.p_paddr + phdr.p_filesz > *end_addr) {
+ *end_addr = phdr.p_paddr + phdr.p_filesz;
+ }
+ }
+ }
+ return SUCCESS;
+}
+
static error elf_get_startaddr_endaddr(Elf *elf, uint32_t *start_addr, uint32_t *end_addr) {
Elf_Scn *elf_scn = NULL;
GElf_Shdr elf_shdr;
@@ -95,7 +159,8 @@ error elf_append(void *addr,
uint32_t *img_size,
uint8_t *elf_nbits,
uint32_t *elf_load,
- uint32_t *elf_entry) {
+ uint32_t *elf_entry,
+ uint8_t elf_use_ph) {
error err;
int fd_elf;
Elf *elf;
@@ -124,10 +189,18 @@ error elf_append(void *addr,
return ERROR_BOOTROM_ELF;
}
- if ((err = elf_get_startaddr_endaddr(elf, &start_addr, &end_addr))) {
- elf_end(elf);
- close(fd_elf);
- return err;
+ if (elf_use_ph) {
+ if ((err = elf_get_startaddr_endaddr_from_ph(elf, &start_addr, &end_addr))) {
+ elf_end(elf);
+ close(fd_elf);
+ return err;
+ }
+ } else {
+ if ((err = elf_get_startaddr_endaddr(elf, &start_addr, &end_addr))) {
+ elf_end(elf);
+ close(fd_elf);
+ return err;
+ }
}
if (end_addr - start_addr > img_max_size) {
@@ -138,10 +211,18 @@ error elf_append(void *addr,
memset(addr, 0, end_addr - start_addr);
- if ((err = elf_create_image(elf, start_addr, addr))) {
- elf_end(elf);
- close(fd_elf);
- return err;
+ if (elf_use_ph) {
+ if ((err = elf_create_image_from_ph(elf, start_addr, addr))) {
+ elf_end(elf);
+ close(fd_elf);
+ return err;
+ }
+ } else {
+ if ((err = elf_create_image(elf, start_addr, addr))) {
+ elf_end(elf);
+ close(fd_elf);
+ return err;
+ }
}
if (gelf_getehdr(elf, &elf_ehdr) != &elf_ehdr) {
@@ -159,4 +240,4 @@ error elf_append(void *addr,
close(fd_elf);
return SUCCESS;
-}
+}
\ No newline at end of file
diff --git a/src/file/elf.h b/src/file/elf.h
index 062616e..88d27ff 100644
--- a/src/file/elf.h
+++ b/src/file/elf.h
@@ -9,6 +9,7 @@ error elf_append(void *addr,
uint32_t *img_size,
uint8_t *elf_nbits,
uint32_t *elf_load,
- uint32_t *elf_entry);
+ uint32_t *elf_entry,
+ uint8_t elf_use_ph);
#endif