summaryrefslogtreecommitdiff
path: root/common/load.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/load.c')
-rw-r--r--common/load.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/common/load.c b/common/load.c
new file mode 100644
index 0000000..cb3b41d
--- /dev/null
+++ b/common/load.c
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * load.c - pull the payload into RAM. semihosting is the whole story
+ * for now, the bios INT 13h of this loader: the host serves the file,
+ * we read it at the fixed address and let the image header place it.
+ *
+ * Copyright (C) 2026 Bradley Morgan <brads@mainlining.org>
+ */
+
+#include <string.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <debug.h>
+#include <semihosting.h>
+#include <boot.h>
+
+int tb_load_semihosting(const char *fname, uintptr_t load_addr,
+ struct tb_image *img)
+{
+ long fd, len, ret;
+
+ fd = smh_open(fname, MODE_READ | MODE_BINARY);
+ if (fd < 0)
+ return fd;
+
+ len = smh_flen(fd);
+ if (len < 0) {
+ smh_close(fd);
+ return len;
+ }
+
+ /* header first so placement is known before the big copy */
+ ret = smh_read(fd, (void *)load_addr, 64);
+ if (ret != 64) {
+ smh_close(fd);
+ return -3;
+ }
+
+ if (tb_image_setup(load_addr, img)) {
+ smh_close(fd);
+ return -4;
+ }
+
+ if (img->load != load_addr) {
+ /* the image wants to sit elsewhere, copy the header there */
+ memmove((void *)img->load, (void *)load_addr, 64);
+ }
+
+ ret = smh_read(fd, (void *)(img->load + 64), len - 64);
+ if (ret != len - 64) {
+ smh_close(fd);
+ return -5;
+ }
+
+ smh_close(fd);
+ return 0;
+}