main.c revision 1.8 1 /* $NetBSD: main.c,v 1.8 1997/09/17 19:39:40 drochner Exp $ */
2
3 /*
4 * Copyright (c) 1996, 1997
5 * Matthias Drochner. All rights reserved.
6 * Copyright (c) 1996, 1997
7 * Perry E. Metzger. All rights reserved.
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 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgements:
19 * This product includes software developed for the NetBSD Project
20 * by Matthias Drochner.
21 * This product includes software developed for the NetBSD Project
22 * by Perry E. Metzger.
23 * 4. The names of the authors may not be used to endorse or promote products
24 * derived from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38
39 #include <sys/reboot.h>
40
41 #include <lib/libkern/libkern.h>
42 #include <lib/libsa/stand.h>
43
44 #include <libi386.h>
45
46 extern void ls __P((char *));
47 extern int getopt __P((int, char **, const char *));
48
49 #ifdef SUPPORT_LYNX
50 extern int exec_lynx __P((const char*, int));
51 #endif
52
53 int errno;
54
55 extern char bootprog_name[], bootprog_rev[], bootprog_date[],
56 bootprog_maker[];
57
58 #define MAXDEVNAME 16
59
60 static char *current_fsmode;
61 static char *default_devname;
62 static int default_unit, default_partition;
63 static char *default_filename;
64
65 void command_help __P((char *));
66 void command_ls __P((char *));
67 void command_quit __P((char *));
68 void command_boot __P((char *));
69 void command_mode __P((char *));
70
71 struct bootblk_command commands[] = {
72 { "help", command_help },
73 { "?", command_help },
74 { "ls", command_ls },
75 { "quit", command_quit },
76 { "boot", command_boot },
77 { "mode", command_mode },
78 { NULL, NULL },
79 };
80
81 int
82 parsebootfile(fname, fsmode, devname, unit, partition, file)
83 const char *fname;
84 char **fsmode; /* out */
85 char **devname; /* out */
86 unsigned int *unit, *partition; /* out */
87 const char **file; /* out */
88 {
89 const char *col, *help;
90
91 *fsmode = current_fsmode;
92 *devname = default_devname;
93 *unit = default_unit;
94 *partition = default_partition;
95 *file = default_filename;
96
97 if (fname == NULL)
98 return (0);
99
100 if ((col = strchr(fname, ':'))) { /* device given */
101 static char savedevname[MAXDEVNAME + 1];
102 int devlen;
103 unsigned int u = 0, p = 0;
104 int i = 0;
105
106 devlen = col - fname;
107 if (devlen > MAXDEVNAME)
108 return (EINVAL);
109
110 #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
111 if (!isvalidname(fname[i]))
112 return (EINVAL);
113 do {
114 savedevname[i] = fname[i];
115 i++;
116 } while (isvalidname(fname[i]));
117 savedevname[i] = '\0';
118
119 #define isnum(c) ((c) >= '0' && (c) <= '9')
120 if (i < devlen) {
121 if (!isnum(fname[i]))
122 return (EUNIT);
123 do {
124 u *= 10;
125 u += fname[i++] - '0';
126 } while (isnum(fname[i]));
127 }
128
129 #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
130 if (i < devlen) {
131 if (!isvalidpart(fname[i]))
132 return (EPART);
133 p = fname[i++] - 'a';
134 }
135 if (i != devlen)
136 return (ENXIO);
137
138 *devname = savedevname;
139 *unit = u;
140 *partition = p;
141 help = col + 1;
142 } else
143 help = fname;
144
145 if (*help)
146 *file = help;
147
148 return (0);
149 }
150
151 char *sprint_bootsel(filename)
152 const char *filename;
153 {
154 char *fsname, *devname;
155 int unit, partition;
156 const char *file;
157 static char buf[80];
158
159 if (parsebootfile(filename, &fsname, &devname, &unit,
160 &partition, &file) == 0) {
161 if (!strcmp(fsname, "dos"))
162 sprintf(buf, "dos:%s", file);
163 else if (!strcmp(fsname, "ufs"))
164 sprintf(buf, "%s%d%c:%s", devname, unit, 'a' + partition, file);
165 else goto bad;
166 return(buf);
167 }
168 bad:
169 return("(invalid)");
170 }
171
172 static void
173 bootit(filename, howto, tell)
174 const char *filename;
175 int howto, tell;
176 {
177 if (tell) {
178 printf("booting %s", sprint_bootsel(filename));
179 if (howto)
180 printf(" (howto 0x%x)", howto);
181 printf("\n");
182 }
183 #ifdef SUPPORT_LYNX
184 if(exec_netbsd(filename, 0, howto) < 0)
185 printf("boot netbsd: %s: %s\n", sprint_bootsel(filename),
186 strerror(errno));
187 else {
188 printf("boot netbsd returned\n");
189 return;
190 }
191 if (exec_lynx(filename, 0) < 0)
192 printf("boot lynx: %s: %s\n", sprint_bootsel(filename),
193 strerror(errno));
194 else
195 printf("boot lynx returned\n");
196 #else
197 if (exec_netbsd(filename, 0, howto) < 0)
198 printf("boot: %s: %s\n", sprint_bootsel(filename),
199 strerror(errno));
200 else
201 printf("boot returned\n");
202 #endif
203 }
204
205 static void
206 print_banner(void)
207 {
208 int extmem = getextmem();
209 char *s = "";
210
211 #ifdef XMS
212 if (getextmem1() == 0) {
213 if ((extmem = checkxms()) != 0)
214 s = "(xms) ";
215 }
216 #endif
217
218 printf("\n");
219 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
220 printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
221 printf(">> Memory: %d/%d %sk\n", getbasemem(), extmem, s);
222 }
223
224 void
225 usage()
226 {
227 printf("dosboot [-u] [-c <commands>] [-i] [filename [-bootopts]]\n");
228 }
229
230 int
231 main(argc, argv)
232 int argc;
233 char **argv;
234 {
235 int ch;
236 int interactive = 0;
237 int howto;
238 extern char *optarg;
239 extern int optind;
240
241 initio(CONSDEV_PC);
242 gateA20();
243
244 print_banner();
245
246 current_fsmode = "dos";
247 default_devname = "hd";
248 default_unit = 0;
249 default_partition = 0;
250 default_filename = "netbsd";
251
252 while ((ch = getopt(argc, argv, "c:iu")) != -1) {
253 switch (ch) {
254 case 'c':
255 docommand(optarg);
256 return (1);
257 break;
258 case 'i':
259 interactive = 1;
260 break;
261 case 'u':
262 current_fsmode = "ufs";
263 break;
264 default:
265 usage();
266 return (1);
267 }
268 }
269
270 if (interactive) {
271 printf("type \"?\" or \"help\" for help.\n");
272 bootmenu();
273 }
274
275 argc -= optind;
276 argv += optind;
277
278 if (argc > 2) {
279 usage();
280 return (1);
281 }
282 howto = 0;
283 if (argc > 1 && !parseopts(argv[1], &howto))
284 return (1);
285
286 bootit((argc > 0 ? argv[0] : "netbsd"), howto, 1);
287 return (1);
288 }
289
290 /* ARGSUSED */
291 void
292 command_help(arg)
293 char *arg;
294 {
295 printf("commands are:\n"
296 "boot [xdNx:][filename] [-adrs]\n"
297 " (ex. \"sd0a:netbsd.old -s\"\n"
298 "ls [path]\n"
299 "mode ufs|dos\n"
300 "help|?\n"
301 "quit\n");
302 }
303
304 void
305 command_ls(arg)
306 char *arg;
307 {
308 char *help = default_filename;
309 if (strcmp(current_fsmode, "ufs")) {
310 printf("UFS only\n");
311 return;
312 }
313 default_filename = "/";
314 ls(arg);
315 default_filename = help;
316 }
317
318 /* ARGSUSED */
319 void
320 command_quit(arg)
321 char *arg;
322 {
323 printf("Exiting... goodbye...\n");
324 exit(0);
325 }
326
327 void
328 command_boot(arg)
329 char *arg;
330 {
331 char *filename;
332 int howto;
333
334 if (parseboot(arg, &filename, &howto))
335 bootit(filename, howto, 1);
336 }
337
338 void
339 command_mode(arg)
340 char *arg;
341 {
342 if (!strcmp("dos", arg))
343 current_fsmode = "dos";
344 else if (!strcmp("ufs", arg))
345 current_fsmode = "ufs";
346 else
347 printf("invalid mode\n");
348 }
349