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