xref: /NextBSD/sys/boot/mips/beri/loader/main.c (revision e5d2f8730c92c4abb6de986ec4e1f39a242b9868)
1 /*-
2  * Copyright (c) 2013-2014 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7  * ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 #include <sys/param.h>
35 #include <sys/linker.h>
36 #include <sys/reboot.h>
37 
38 #include <machine/bootinfo.h>
39 #include <machine/elf.h>
40 
41 #include <stand.h>
42 #include <bootstrap.h>
43 #include <loader.h>
44 #include <mips.h>
45 
46 #ifdef LOADER_USB_SUPPORT
47 #include <storage/umass_common.h>
48 #endif
49 
50 static int	__elfN(exec)(struct preloaded_file *);
51 static void	extract_currdev(struct bootinfo *);
52 
53 struct devsw *devsw[] = {
54 	&beri_cfi_disk,
55 	&beri_sdcard_disk,
56 #ifdef LOADER_USB_SUPPORT
57 	&umass_disk,
58 #endif
59 	NULL
60 };
61 
62 struct arch_switch archsw;
63 
64 struct file_format *file_formats[] = {
65 	&beri_elf,
66 	NULL
67 };
68 
69 struct fs_ops *file_system[] = {
70 #ifdef LOADER_UFS_SUPPORT
71 	&ufs_fsops,
72 #endif
73 	NULL
74 };
75 
76 struct console *consoles[] = {
77 	&altera_jtag_uart_console,
78 	NULL
79 };
80 
81 extern void	__bss_start, __bss_end;
82 extern void	__heap_start, __heap_end;
83 
84 static int
__elfN(exec)85 __elfN(exec)(struct preloaded_file *fp)
86 {
87 
88 	return (EFTYPE);
89 }
90 
91 /*
92  * Capture arguments from boot2 for later reuse when launching the kernel.
93  * Note that we choose not to maintain a pointer to boo2_bootinfop after
94  * initial argument processing: this is because we might load the kernel over
95  * the spot where boot2 was running, so we can't pass that pointer on to the
96  * kernel.  To be on the safe side, never reference it outside of the body of
97  * main(), instead preserving a copy.
98  */
99 int		 boot2_argc;
100 char		**boot2_argv;
101 char		**boot2_envv;
102 
103 struct bootinfo	boot2_bootinfo;
104 
105 int
main(int argc,char * argv[],char * envv[],struct bootinfo * bootinfop)106 main(int argc, char *argv[], char *envv[], struct bootinfo *bootinfop)
107 {
108 	struct devsw **dp;
109 
110 	/* NB: Must be sure to bzero() before using any globals. */
111 	bzero(&__bss_start, (uintptr_t)&__bss_end - (uintptr_t)&__bss_start);
112 
113 	boot2_argc = argc;
114 	boot2_argv = argv;
115 	boot2_envv = envv;
116 	boot2_bootinfo = *bootinfop;	/* Copy rather than by reference. */
117 
118 	setheap((void *)&__heap_start, (void *)&__heap_end);
119 
120 	/*
121 	 * Pick up console settings from boot2; probe console.
122 	 */
123 	if (bootinfop->bi_boot2opts & RB_MULTIPLE) {
124 		if (bootinfop->bi_boot2opts & RB_SERIAL)
125 			setenv("console", "comconsole vidconsole", 1);
126 		else
127 			setenv("console", "vidconsole comconsole", 1);
128 	} else if (bootinfop->bi_boot2opts & RB_SERIAL)
129 		setenv("console", "comconsole", 1);
130 	else if (bootinfop->bi_boot2opts & RB_MUTE)
131 		setenv("console", "nullconsole", 1);
132 	cons_probe();
133 	setenv("LINES", "24", 1);
134 
135 	printf("%s(%d, %p, %p, %p (%p))\n", __func__, argc, argv, envv,
136 	    bootinfop, (void *)bootinfop->bi_memsize);
137 
138 	/*
139 	 * Initialise devices.
140 	 */
141 	for (dp = devsw; *dp != NULL; dp++) {
142 		if ((*dp)->dv_init != NULL)
143 			(*dp)->dv_init();
144 	}
145 	extract_currdev(bootinfop);
146 
147 	printf("\n");
148 	printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
149 	printf("(%s, %s)\n", bootprog_maker, bootprog_date);
150 #if 0
151 	printf("bootpath=\"%s\"\n", bootpath);
152 #endif
153 
154 	interact(NULL);
155 	return (0);
156 }
157 
158 static void
extract_currdev(struct bootinfo * bootinfop)159 extract_currdev(struct bootinfo *bootinfop)
160 {
161 	const char *bootdev;
162 
163 	/*
164 	 * Pick up boot device information from boot2.
165 	 *
166 	 * XXXRW: Someday: device units.
167 	 */
168 	switch(bootinfop->bi_boot_dev_type) {
169 	case BOOTINFO_DEV_TYPE_DRAM:
170 		bootdev = "dram0";
171 		break;
172 
173 	case BOOTINFO_DEV_TYPE_CFI:
174 		bootdev = "cfi0";
175 		break;
176 
177 	case BOOTINFO_DEV_TYPE_SDCARD:
178 		bootdev = "sdcard0";
179 		break;
180 
181 	default:
182 		bootdev = NULL;
183 	}
184 
185 	if (bootdev != NULL) {
186 		env_setenv("currdev", EV_VOLATILE, bootdev, NULL, env_nounset);
187 		env_setenv("loaddev", EV_VOLATILE, bootdev, env_noset,
188 		    env_nounset);
189 	}
190 }
191 
192 void
abort(void)193 abort(void)
194 {
195 
196 	printf("error: loader abort\n");
197 	while (1);
198 }
199 
200 void
exit(int code)201 exit(int code)
202 {
203 
204 	printf("error: loader exit\n");
205 	while (1);
206 }
207 
208 void
longjmperror(void)209 longjmperror(void)
210 {
211 
212 	printf("error: loader longjmp error\n");
213 	while (1);
214 }
215 
216 time_t
time(time_t * tloc)217 time(time_t *tloc)
218 {
219 
220 	/* We can't provide time since UTC, so just provide time since boot. */
221 	return (cp0_count_get() / 100000000);
222 }
223 
224 /*
225  * Delay - in usecs
226  *
227  * NOTE: We are assuming that the CPU is running at 100MHz.
228  */
229 void
delay(int usecs)230 delay(int usecs)
231 {
232 	uint32_t delta;
233 	uint32_t curr;
234 	uint32_t last;
235 
236 	last = cp0_count_get();
237 	while (usecs > 0) {
238 		curr = cp0_count_get();
239 		delta = curr - last;
240 		while (usecs > 0 && delta >= 100) {
241 			usecs--;
242 			last += 100;
243 			delta -= 100;
244 		}
245 	}
246 }
247