summaryrefslogtreecommitdiffstats
path: root/drivers/remoteproc/remoteproc_elf_loader.c
diff options
context:
space:
mode:
authorOleksij Rempel <linux@rempel-privat.de>2019-09-23 11:55:27 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-09-26 08:42:52 +0200
commit22763dab152cb38c0912fe688f564a54aeaaea88 (patch)
tree81252e6e25da91896de155d875c3badb67335299 /drivers/remoteproc/remoteproc_elf_loader.c
parentf114b0479a2217c19cdf77a5aeeeb2a329255ff0 (diff)
downloadbarebox-22763dab152cb38c0912fe688f564a54aeaaea88.tar.gz
barebox-22763dab152cb38c0912fe688f564a54aeaaea88.tar.xz
port reduced version of remoteproc framework from linux
I tested it on phytec imx7 board with remoteproc ELF image previously used on Linux. Linux would load this image, create appropriate resource (if defined in image) and boot it. The barebox version is only loading image and boot it. Currently barebox version do not extract resources defined by rproc ELF image. On this early stage it is hard to say, if it is needed. Previously there was an attempt to port bootaux command from u-boot. Porting of remoteproc framework is my attempt to lead this topic in to the (IMO) right direction. To start remoteproc image, firmwareload command should be used: firmwareload /mnt/tftp/rproc-imx-rproc-fw Since firmwareload already support multiple targets, it is possible to specify which exact cortex m4 CPU should be started (if multiple CPU are present). This example shows the list of available firmware targets: barebox@Phytec i.MX7 phyBOARD-Zeta:/ firmwareload -l firmware programming handlers: name: model: soc:imx7d-rp0@0.of Signed-off-by: Oleksij Rempel <linux@rempel-privat.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/remoteproc/remoteproc_elf_loader.c')
-rw-r--r--drivers/remoteproc/remoteproc_elf_loader.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
new file mode 100644
index 0000000000..45d52db5c1
--- /dev/null
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Remote Processor Framework Elf loader
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * Brian Swetland <swetland@google.com>
+ * Mark Grosen <mgrosen@ti.com>
+ * Fernando Guzman Lugo <fernando.lugo@ti.com>
+ * Suman Anna <s-anna@ti.com>
+ * Robert Tivy <rtivy@ti.com>
+ * Armando Uribe De Leon <x0095078@ti.com>
+ * Sjur Brændeland <sjur.brandeland@stericsson.com>
+ */
+
+#include <common.h>
+#include <elf.h>
+#include <linux/remoteproc.h>
+
+#include "remoteproc_internal.h"
+
+int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
+{
+ struct device_d *dev = &rproc->dev;
+ struct elf32_hdr *ehdr;
+ struct elf32_phdr *phdr;
+ int i, ret = 0;
+ const u8 *elf_data = fw->data;
+
+ ehdr = (struct elf32_hdr *)elf_data;
+ phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
+
+ /* go through the available ELF segments */
+ for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
+ u32 da = phdr->p_paddr;
+ u32 memsz = phdr->p_memsz;
+ u32 filesz = phdr->p_filesz;
+ u32 offset = phdr->p_offset;
+ void *ptr;
+
+ if (phdr->p_type != PT_LOAD)
+ continue;
+
+ dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
+ phdr->p_type, da, memsz, filesz);
+
+ if (filesz > memsz) {
+ dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
+ filesz, memsz);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (offset + filesz > fw->size) {
+ dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
+ offset + filesz, fw->size);
+ ret = -EINVAL;
+ break;
+ }
+
+ /* grab the kernel address for this device address */
+ ptr = rproc_da_to_va(rproc, da, memsz);
+ if (!ptr) {
+ dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
+ ret = -EINVAL;
+ break;
+ }
+
+ /* put the segment where the remote processor expects it */
+ if (phdr->p_filesz)
+ memcpy(ptr, elf_data + phdr->p_offset, filesz);
+
+ /*
+ * Zero out remaining memory for this segment.
+ *
+ * This isn't strictly required since dma_alloc_coherent already
+ * did this for us. albeit harmless, we may consider removing
+ * this.
+ */
+ if (memsz > filesz)
+ memset(ptr + filesz, 0, memsz - filesz);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(rproc_elf_load_segments);