xref: /openbsd-src/sys/arch/armv7/stand/efiboot/exec.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: exec.c,v 1.8 2016/06/21 15:39:51 kettenis Exp $	*/
2 
3 /*
4  * Copyright (c) 2006, 2016 Mark Kettenis
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/reboot.h>
21 #include <dev/cons.h>
22 
23 #include <lib/libkern/libkern.h>
24 #include <lib/libsa/loadfile.h>
25 #include <sys/exec_elf.h>
26 
27 #include <efi.h>
28 #include <stand/boot/cmd.h>
29 
30 #include "efiboot.h"
31 #include "libsa.h"
32 
33 typedef void (*startfuncp)(void *, void *, void *) __attribute__ ((noreturn));
34 
35 void
36 run_loadfile(u_long *marks, int howto)
37 {
38 	Elf_Ehdr *elf = (Elf_Ehdr *)marks[MARK_SYM];
39 	Elf_Shdr *shp = (Elf_Shdr *)(marks[MARK_SYM] + elf->e_shoff);
40 	u_long esym = marks[MARK_END] & 0x0fffffff;
41 	u_long offset = 0;
42 	char args[256];
43 	char *cp;
44 	void *fdt;
45 	uint32_t board_id;
46 	int i;
47 
48 	/*
49 	 * Tell locore.S where the symbol table ends by setting
50 	 * 'esym', which should be the first word in the .data
51 	 * section.
52 	 */
53 	for (i = 0; i < elf->e_shnum; i++) {
54 		/* XXX Assume .data is the first writable segment. */
55 		if (shp[i].sh_flags & SHF_WRITE) {
56 			/* XXX We have to store the virtual address. */
57 			esym |= shp[i].sh_addr & 0xf0000000;
58 			*(u_long *)(LOADADDR(shp[i].sh_addr)) = esym;
59 			break;
60 		}
61 	}
62 
63 	snprintf(args, sizeof(args) - 8, "%s:%s", cmd.bootdev, cmd.image);
64 	cp = args + strlen(args);
65 
66 	*cp++ = ' ';
67 	*cp = '-';
68         if (howto & RB_ASKNAME)
69                 *++cp = 'a';
70         if (howto & RB_CONFIG)
71                 *++cp = 'c';
72         if (howto & RB_SINGLE)
73                 *++cp = 's';
74         if (howto & RB_KDB)
75                 *++cp = 'd';
76         if (*cp == '-')
77 		*--cp = 0;
78 	else
79 		*++cp = 0;
80 
81 	fdt = efi_makebootargs(args, &board_id);
82 
83 	efi_cleanup();
84 
85 	(*(startfuncp)(marks[MARK_ENTRY]))(NULL, (void *)board_id, fdt);
86 
87 	/* NOTREACHED */
88 }
89