From 843322f8982c9194daff6e9885d769390bea6928 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sat, 10 Jan 2026 22:00:59 +0000 Subject: [PATCH] elf_loader: add generic callback-based loader Change-Id: I1dd972a585bc7c805e32c9665d13e248663ccc73 --- firmware/elf_loader.c | 42 ++++++++++++++++++++++------------- firmware/include/elf_loader.h | 9 ++++++++ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/firmware/elf_loader.c b/firmware/elf_loader.c index d6fd2e71d4..d1f08f661c 100644 --- a/firmware/elf_loader.c +++ b/firmware/elf_loader.c @@ -101,17 +101,16 @@ static int elf_validate_phdr(const struct elf_phdr *phdr, return ELF_ERR_MEM_UNMAPPED; } -int elf_loadfd(int fd, - const struct elf_load_context *ctx, - void **entrypoint) +int elf_load(elf_read_callback_t read_cb, + intptr_t read_arg, + const struct elf_load_context *ctx, + void **entrypoint) { struct elf_header ehdr; struct elf_phdr phdr; - ssize_t nread; int err; - nread = read(fd, &ehdr, sizeof(ehdr)); - if (nread != (ssize_t)sizeof(ehdr)) + if (read_cb(read_arg, 0, &ehdr, sizeof(ehdr))) return ELF_ERR_IO; err = elf_validate_header(&ehdr); @@ -124,11 +123,7 @@ int elf_loadfd(int fd, for (size_t ph_index = 0; ph_index < ehdr.e_phnum; ++ph_index) { off_t ph_off = ehdr.e_phoff + (ph_index * ehdr.e_phentsize); - if (lseek(fd, ph_off, SEEK_SET) == (off_t)-1) - return ELF_ERR_IO; - - nread = read(fd, &phdr, sizeof(phdr)); - if (nread != (ssize_t)sizeof(phdr)) + if (read_cb(read_arg, ph_off, &phdr, sizeof(phdr))) return ELF_ERR_IO; err = elf_validate_phdr(&phdr, ctx); @@ -138,11 +133,7 @@ int elf_loadfd(int fd, /* Load file data to memory if needed */ if (phdr.p_filesz > 0) { - if (lseek(fd, phdr.p_offset, SEEK_SET) == (off_t)-1) - return ELF_ERR_IO; - - nread = read(fd, (void *)phdr.p_vaddr, phdr.p_filesz); - if (nread < 0 || (uint32_t)nread != phdr.p_filesz) + if (read_cb(read_arg, phdr.p_offset, (void *)phdr.p_vaddr, phdr.p_filesz)) return ELF_ERR_IO; } @@ -160,6 +151,25 @@ int elf_loadfd(int fd, return ELF_OK; } +int elf_loadfd(int fd, + const struct elf_load_context *ctx, + void **entrypoint) +{ + return elf_load(elf_read_fd_callback, fd, ctx, entrypoint); +} + +int elf_read_fd_callback(intptr_t fd, off_t pos, void *buf, size_t size) +{ + if (lseek(fd, pos, SEEK_SET) == (off_t)-1) + return -1; + + ssize_t nread = read(fd, buf, size); + if (nread < 0 || (size_t)nread != size) + return -1; + + return 0; +} + int elf_loadpath(const char *filename, const struct elf_load_context *ctx, void **entrypoint) diff --git a/firmware/include/elf_loader.h b/firmware/include/elf_loader.h index 0f30e87ab2..344a4eb4e1 100644 --- a/firmware/include/elf_loader.h +++ b/firmware/include/elf_loader.h @@ -38,6 +38,7 @@ #include #include +#include enum elf_error { @@ -83,9 +84,17 @@ struct elf_load_context size_t num_mmap; }; +typedef int (*elf_read_callback_t) (intptr_t arg, off_t pos, void *buf, size_t size); + +int elf_load(elf_read_callback_t read_cb, + intptr_t read_arg, + const struct elf_load_context *ctx, + void **entrypoint); + int elf_loadfd(int fd, const struct elf_load_context *ctx, void **entrypoint); +int elf_read_fd_callback(intptr_t fd, off_t pos, void *buf, size_t size); int elf_loadpath(const char *filename, const struct elf_load_context *ctx,