summaryrefslogtreecommitdiff
path: root/sys/arch/armv7/stand/efiboot/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/armv7/stand/efiboot/exec.c')
-rw-r--r--sys/arch/armv7/stand/efiboot/exec.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/sys/arch/armv7/stand/efiboot/exec.c b/sys/arch/armv7/stand/efiboot/exec.c
new file mode 100644
index 00000000000..189eb4e4b8c
--- /dev/null
+++ b/sys/arch/armv7/stand/efiboot/exec.c
@@ -0,0 +1,142 @@
+/* $OpenBSD: exec.c,v 1.1 2016/05/14 17:55:15 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2006, 2016 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+
+#include <lib/libsa/loadfile.h>
+
+#ifdef BOOT_ELF
+#include <sys/exec_elf.h>
+#endif
+
+#include <sys/reboot.h>
+#include <stand/boot/cmd.h>
+#include <machine/bootconfig.h>
+
+#include <efi.h>
+
+extern EFI_BOOT_SERVICES *BS;
+
+typedef void (*startfuncp)(void *, void *, void *) __attribute__ ((noreturn));
+
+struct uboot_tag_header {
+ uint32_t size;
+ uint32_t tag;
+};
+struct uboot_tag_core {
+ uint32_t flags;
+ uint32_t pagesize;
+ uint32_t rootdev;
+};
+struct uboot_tag_serialnr {
+ uint32_t low;
+ uint32_t high;
+};
+struct uboot_tag_revision {
+ uint32_t rev;
+};
+struct uboot_tag_mem32 {
+ uint32_t size;
+ uint32_t start;
+};
+struct uboot_tag_cmdline {
+ char cmdline[1];
+};
+
+#define ATAG_CORE 0x54410001
+#define ATAG_MEM 0x54410002
+#define ATAG_CMDLINE 0x54410009
+#define ATAG_SERIAL 0x54410006
+#define ATAG_REVISION 0x54410007
+#define ATAG_NONE 0x00000000
+struct uboot_tag {
+ struct uboot_tag_header hdr;
+ union {
+ struct uboot_tag_core core;
+ struct uboot_tag_mem32 mem;
+ struct uboot_tag_revision rev;
+ struct uboot_tag_serialnr serialnr;
+ struct uboot_tag_cmdline cmdline;
+ } u;
+};
+
+struct uboot_tag tags[2];
+
+void
+run_loadfile(u_long *marks, int howto)
+{
+#if 0
+#ifdef BOOT_ELF
+ Elf_Ehdr *elf = (Elf_Ehdr *)marks[MARK_SYM];
+ Elf_Shdr *shp = (Elf_Shdr *)(marks[MARK_SYM] + elf->e_shoff);
+ u_long esym = marks[MARK_END];
+ char *cp;
+ int i;
+
+ /*
+ * Tell locore.S where the symbol table ends by setting
+ * 'esym', which should be the first word in the .data
+ * section.
+ */
+ for (i = 0; i < elf->e_shnum; i++) {
+ /* XXX Assume .data is the first writable segment. */
+ if (shp[i].sh_flags & SHF_WRITE) {
+ /* XXX We have to store the virtual address. */
+ esym |= shp[i].sh_addr & 0xff000000;
+ *(u_long *)(shp[i].sh_addr & 0x00ffffff) = esym;
+ break;
+ }
+ }
+#endif
+ cp = (char *)0x00200000 - MAX_BOOT_STRING - 1;
+
+#define BOOT_STRING_MAGIC 0x4f425344
+
+ *(int *)cp = BOOT_STRING_MAGIC;
+
+ cp += sizeof(int);
+ snprintf(cp, MAX_BOOT_STRING, "%s:%s -", cmd.bootdev, cmd.image);
+
+ while (*cp != '\0')
+ cp++;
+ if (howto & RB_ASKNAME)
+ *cp++ = 'a';
+ if (howto & RB_CONFIG)
+ *cp++ = 'c';
+ if (howto & RB_KDB)
+ *cp++ = 'd';
+ if (howto & RB_SINGLE)
+ *cp++ = 's';
+
+ *cp = '\0';
+
+#endif
+
+ tags[0].hdr.tag = ATAG_MEM;
+ tags[0].hdr.size = sizeof(struct uboot_tag);
+ tags[0].u.mem.start = 0x10000000;
+ tags[0].u.mem.size = 0x80000000;
+
+ memcpy((void *)0x10000000, tags, sizeof(tags));
+
+ BS->ExitBootServices(NULL, 0);
+
+ (*(startfuncp)(marks[MARK_ENTRY]))(NULL, (void *)4821, (void *)0x10000000);
+
+ /* NOTREACHED */
+}