boot.c revision 1.3 1 1.3 he /* $NetBSD: boot.c,v 1.3 2005/06/09 16:02:19 he Exp $ */
2 1.1 tsutsui
3 1.1 tsutsui /*-
4 1.1 tsutsui * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 1.1 tsutsui * All rights reserved.
6 1.1 tsutsui *
7 1.1 tsutsui * This code is derived from software contributed to The NetBSD Foundation
8 1.1 tsutsui * by Jonathan Stone, Michael Hitch and Simon Burge.
9 1.1 tsutsui *
10 1.1 tsutsui * Redistribution and use in source and binary forms, with or without
11 1.1 tsutsui * modification, are permitted provided that the following conditions
12 1.1 tsutsui * are met:
13 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright
14 1.1 tsutsui * notice, this list of conditions and the following disclaimer.
15 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the
17 1.1 tsutsui * documentation and/or other materials provided with the distribution.
18 1.1 tsutsui * 3. All advertising materials mentioning features or use of this software
19 1.1 tsutsui * must display the following acknowledgement:
20 1.1 tsutsui * This product includes software developed by the NetBSD
21 1.1 tsutsui * Foundation, Inc. and its contributors.
22 1.1 tsutsui * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 tsutsui * contributors may be used to endorse or promote products derived
24 1.1 tsutsui * from this software without specific prior written permission.
25 1.1 tsutsui *
26 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 tsutsui * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 tsutsui * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 tsutsui * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 tsutsui * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 tsutsui * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 tsutsui * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 tsutsui * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 tsutsui * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 tsutsui * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 tsutsui * POSSIBILITY OF SUCH DAMAGE.
37 1.1 tsutsui */
38 1.1 tsutsui
39 1.1 tsutsui /*
40 1.1 tsutsui * Copyright (c) 1992, 1993
41 1.1 tsutsui * The Regents of the University of California. All rights reserved.
42 1.1 tsutsui *
43 1.1 tsutsui * This code is derived from software contributed to Berkeley by
44 1.1 tsutsui * Ralph Campbell.
45 1.1 tsutsui *
46 1.1 tsutsui * Redistribution and use in source and binary forms, with or without
47 1.1 tsutsui * modification, are permitted provided that the following conditions
48 1.1 tsutsui * are met:
49 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright
50 1.1 tsutsui * notice, this list of conditions and the following disclaimer.
51 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright
52 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the
53 1.1 tsutsui * documentation and/or other materials provided with the distribution.
54 1.1 tsutsui * 3. Neither the name of the University nor the names of its contributors
55 1.1 tsutsui * may be used to endorse or promote products derived from this software
56 1.1 tsutsui * without specific prior written permission.
57 1.1 tsutsui *
58 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 1.1 tsutsui * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 1.1 tsutsui * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 1.1 tsutsui * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 1.1 tsutsui * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 1.1 tsutsui * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 1.1 tsutsui * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 1.1 tsutsui * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 1.1 tsutsui * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 1.1 tsutsui * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 1.1 tsutsui * SUCH DAMAGE.
69 1.1 tsutsui *
70 1.1 tsutsui * @(#)boot.c 8.1 (Berkeley) 6/10/93
71 1.1 tsutsui */
72 1.1 tsutsui
73 1.1 tsutsui #include <lib/libsa/stand.h>
74 1.1 tsutsui #include <lib/libsa/loadfile.h>
75 1.1 tsutsui #include <lib/libkern/libkern.h>
76 1.1 tsutsui
77 1.1 tsutsui #include <sys/param.h>
78 1.1 tsutsui #include <sys/exec.h>
79 1.1 tsutsui #include <sys/exec_elf.h>
80 1.1 tsutsui #include <sys/boot_flag.h>
81 1.1 tsutsui
82 1.1 tsutsui #include <dev/arcbios/arcbios.h>
83 1.1 tsutsui
84 1.1 tsutsui #include "common.h"
85 1.1 tsutsui #include "bootinfo.h"
86 1.1 tsutsui
87 1.1 tsutsui #ifdef BOOT_DEBUG
88 1.1 tsutsui #define DPRINTF if (debug) printf
89 1.1 tsutsui #else
90 1.1 tsutsui #define DPRINTF while (/*CONSTCOND*/0) printf
91 1.1 tsutsui #endif
92 1.1 tsutsui
93 1.1 tsutsui /*
94 1.1 tsutsui * We won't go overboard with gzip'd kernel names. After all we can
95 1.1 tsutsui * still boot a gzip'd kernel called "netbsd.arc" - it doesn't need
96 1.1 tsutsui * the .gz suffix.
97 1.1 tsutsui *
98 1.1 tsutsui * For arcane reasons, the first byte of the first element of this struct will
99 1.1 tsutsui * contain a zero. We therefore start from one.
100 1.1 tsutsui */
101 1.1 tsutsui
102 1.1 tsutsui char *kernelnames[] = {
103 1.1 tsutsui "placekeeper",
104 1.2 thorpej "netbsd.arc",
105 1.1 tsutsui "netbsd",
106 1.1 tsutsui "netbsd.gz",
107 1.1 tsutsui "netbsd.bak",
108 1.1 tsutsui "netbsd.old",
109 1.1 tsutsui "onetbsd",
110 1.1 tsutsui "gennetbsd",
111 1.1 tsutsui NULL
112 1.1 tsutsui };
113 1.1 tsutsui
114 1.1 tsutsui static int debug = 0;
115 1.1 tsutsui static char **environment;
116 1.1 tsutsui
117 1.1 tsutsui /* Storage must be static. */
118 1.1 tsutsui struct btinfo_symtab bi_syms;
119 1.1 tsutsui struct btinfo_bootpath bi_bpath;
120 1.1 tsutsui
121 1.1 tsutsui extern const struct arcbios_fv *ARCBIOS;
122 1.1 tsutsui
123 1.1 tsutsui int main(int, char **);
124 1.1 tsutsui static char *firmware_getenv(char *);
125 1.1 tsutsui
126 1.1 tsutsui /*
127 1.1 tsutsui * This gets arguments from the ARCS monitor, calls ARCS routines to open
128 1.1 tsutsui * and load the program to boot, then transfers execution to the new program.
129 1.1 tsutsui *
130 1.1 tsutsui * argv[0] will be the ARCS path to the bootloader (i.e.,
131 1.1 tsutsui * "scsi(0)disk(2)rdisk(0)partition(1)\boot").
132 1.1 tsutsui *
133 1.1 tsutsui * argv[1] through argv[n] will contain arguments passed from the PROM, if any.
134 1.1 tsutsui */
135 1.1 tsutsui
136 1.1 tsutsui int
137 1.1 tsutsui main(int argc, char **argv)
138 1.1 tsutsui {
139 1.3 he const char *kernel = NULL;
140 1.3 he const char *bootpath = NULL;
141 1.1 tsutsui char bootfile[PATH_MAX];
142 1.1 tsutsui void (*entry)(int, char *[], int, void *);
143 1.1 tsutsui u_long marks[MARK_MAX];
144 1.1 tsutsui int win = 0;
145 1.1 tsutsui int i;
146 1.1 tsutsui int ch;
147 1.1 tsutsui
148 1.1 tsutsui /* print a banner */
149 1.1 tsutsui printf("\n");
150 1.1 tsutsui printf("%s Bootstrap, Revision %s\n", bootprog_name, bootprog_rev);
151 1.1 tsutsui printf("(%s, %s)\n", bootprog_maker, bootprog_date);
152 1.1 tsutsui
153 1.1 tsutsui memset(marks, 0, sizeof marks);
154 1.1 tsutsui
155 1.1 tsutsui /* initialise bootinfo structure early */
156 1.1 tsutsui bi_init();
157 1.1 tsutsui
158 1.1 tsutsui #ifdef BOOT_DEBUG
159 1.1 tsutsui for (i = 0; i < argc; i++)
160 1.1 tsutsui printf("argv[%d] = %s\n", i, argv[i]);
161 1.1 tsutsui #endif
162 1.1 tsutsui
163 1.1 tsutsui /* Parse arguments, if present. */
164 1.1 tsutsui while ((ch = getopt(argc, argv, "v")) != -1) {
165 1.1 tsutsui switch (ch) {
166 1.1 tsutsui case 'v':
167 1.1 tsutsui debug = 1;
168 1.1 tsutsui break;
169 1.1 tsutsui }
170 1.1 tsutsui }
171 1.1 tsutsui
172 1.1 tsutsui environment = &argv[1];
173 1.1 tsutsui
174 1.1 tsutsui bootpath = firmware_getenv("OSLoadPartition");
175 1.1 tsutsui if (bootpath == NULL)
176 1.1 tsutsui bootpath =
177 1.1 tsutsui (*ARCBIOS->GetEnvironmentVariable)("OSLoadPartition");
178 1.1 tsutsui
179 1.1 tsutsui if (bootpath == NULL) {
180 1.1 tsutsui /* XXX need to actually do the fixup */
181 1.1 tsutsui printf("OSLoadPartition is not specified.\n");
182 1.1 tsutsui return 0;
183 1.1 tsutsui }
184 1.1 tsutsui DPRINTF("bootpath = %s\n", bootpath);
185 1.1 tsutsui
186 1.1 tsutsui /*
187 1.1 tsutsui * Grab OSLoadFilename from ARCS.
188 1.1 tsutsui */
189 1.1 tsutsui
190 1.1 tsutsui kernel = firmware_getenv("OSLoadFilename");
191 1.1 tsutsui if (kernel == NULL)
192 1.1 tsutsui kernel = (*ARCBIOS->GetEnvironmentVariable)("OSLoadFilename");
193 1.1 tsutsui
194 1.1 tsutsui DPRINTF("kernel = %s\n", kernel ? kernel : "<null>");
195 1.1 tsutsui
196 1.1 tsutsui /*
197 1.1 tsutsui * The first arg is assumed to contain the name of the kernel to boot,
198 1.1 tsutsui * if it a) does not start with a hyphen and b) does not contain
199 1.1 tsutsui * an equals sign.
200 1.1 tsutsui */
201 1.1 tsutsui
202 1.1 tsutsui for (i = 1; i < argc; i++) {
203 1.1 tsutsui if (((strchr(argv[i], '=')) == NULL) && (argv[i][0] != '-')) {
204 1.1 tsutsui kernel = argv[i];
205 1.1 tsutsui break;
206 1.1 tsutsui }
207 1.1 tsutsui }
208 1.1 tsutsui
209 1.1 tsutsui if (kernel != NULL) {
210 1.1 tsutsui /*
211 1.1 tsutsui * if the name contains parenthesis, we assume that it
212 1.1 tsutsui * contains the bootpath and ignore anything passed through
213 1.1 tsutsui * the environment
214 1.1 tsutsui */
215 1.1 tsutsui if (strchr(kernel, '('))
216 1.1 tsutsui win = loadfile(kernel, marks, LOAD_KERNEL);
217 1.1 tsutsui else {
218 1.1 tsutsui strcpy(bootfile, bootpath);
219 1.1 tsutsui strcat(bootfile, kernel);
220 1.1 tsutsui win = loadfile(bootfile, marks, LOAD_KERNEL);
221 1.1 tsutsui }
222 1.1 tsutsui
223 1.1 tsutsui } else {
224 1.1 tsutsui i = 1;
225 1.1 tsutsui while (kernelnames[i] != NULL) {
226 1.1 tsutsui strcpy(bootfile, bootpath);
227 1.1 tsutsui strcat(bootfile, kernelnames[i]);
228 1.1 tsutsui kernel = kernelnames[i];
229 1.1 tsutsui win = loadfile(bootfile, marks, LOAD_KERNEL);
230 1.1 tsutsui if (win != -1)
231 1.1 tsutsui break;
232 1.1 tsutsui i++;
233 1.1 tsutsui }
234 1.1 tsutsui
235 1.1 tsutsui }
236 1.1 tsutsui
237 1.1 tsutsui if (win < 0) {
238 1.1 tsutsui printf("Boot failed! Halting...\n");
239 1.1 tsutsui (void)getchar();
240 1.1 tsutsui return 0;
241 1.1 tsutsui }
242 1.1 tsutsui
243 1.1 tsutsui #if 0
244 1.1 tsutsui strncpy(bi_bpath.bootpath, kernel, BTINFO_BOOTPATH_LEN);
245 1.1 tsutsui bi_add(&bi_bpath, BTINFO_BOOTPATH);
246 1.1 tsutsui
247 1.1 tsutsui bi_syms.nsym = marks[MARK_NSYM];
248 1.1 tsutsui bi_syms.ssym = marks[MARK_SYM];
249 1.1 tsutsui bi_syms.esym = marks[MARK_END];
250 1.1 tsutsui bi_add(&bi_syms, BTINFO_SYMTAB);
251 1.1 tsutsui #endif
252 1.1 tsutsui entry = (void *)marks[MARK_ENTRY];
253 1.1 tsutsui
254 1.1 tsutsui if (debug) {
255 1.1 tsutsui printf("Starting at %p\n\n", entry);
256 1.1 tsutsui printf("nsym 0x%lx ssym 0x%lx esym 0x%lx\n", marks[MARK_NSYM],
257 1.1 tsutsui marks[MARK_SYM], marks[MARK_END]);
258 1.1 tsutsui }
259 1.1 tsutsui (*entry)(argc, argv, 0 /* BOOTINFO_MAGIC */, NULL);
260 1.1 tsutsui
261 1.1 tsutsui printf("Kernel returned! Halting...\n");
262 1.1 tsutsui return 0;
263 1.1 tsutsui }
264 1.1 tsutsui
265 1.1 tsutsui char *
266 1.1 tsutsui firmware_getenv(char *envname)
267 1.1 tsutsui {
268 1.1 tsutsui char **env;
269 1.1 tsutsui int len;
270 1.1 tsutsui
271 1.1 tsutsui len = strlen(envname);
272 1.1 tsutsui
273 1.1 tsutsui for (env = environment; env[0]; env++) {
274 1.1 tsutsui if (strncasecmp(envname, env[0], len) == 0 &&
275 1.1 tsutsui env[0][len] == '=') {
276 1.1 tsutsui return &env[0][len + 1];
277 1.1 tsutsui }
278 1.1 tsutsui }
279 1.1 tsutsui return NULL;
280 1.1 tsutsui }
281 1.1 tsutsui
282 1.1 tsutsui void
283 1.1 tsutsui _rtt(void)
284 1.1 tsutsui {
285 1.1 tsutsui
286 1.1 tsutsui (*ARCBIOS->Halt)();
287 1.1 tsutsui }
288