forked from M-Labs/zynq-rs
220 lines
6.2 KiB
Diff
220 lines
6.2 KiB
Diff
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
|