Annotation of src/sys/arch/i386/stand/dosboot/main.c, Revision 1.1.1.1
1.1 perry 1: /* $NetBSD$ */
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:
40: #include <sys/reboot.h>
41:
42: #include <lib/libkern/libkern.h>
43: #include <lib/libsa/stand.h>
44:
45: #include <libi386.h>
46:
47: extern char *strerror __P((int)); /* XXX missing in stand.h */
48:
49: extern void ls __P((char*));
50: extern int getopt __P((int, char**, const char*));
51:
52: int errno;
53: static char *consdev;
54:
55: extern char version[];
56:
57: #define MAXDEVNAME 16
58:
59: static char *current_fsmode;
60: static char *default_devname;
61: static int default_unit, default_partition;
62: static char *default_filename;
63:
64: int
65: parsebootfile(fname, fsmode, devname, unit, partition, file)
66: const char *fname;
67: char **fsmode;
68: char **devname; /* out */
69: unsigned int *unit, *partition; /* out */
70: const char **file; /* out */
71: {
72: const char *col, *help;
73:
74: *fsmode = current_fsmode;
75: *devname = default_devname;
76: *unit = default_unit;
77: *partition = default_partition;
78: *file = default_filename;
79:
80: if(!fname) return(0);
81:
82: if((col = strchr(fname, ':'))) { /* device given */
83: static char savedevname[MAXDEVNAME+1];
84: int devlen;
85: unsigned int u = 0, p = 0;
86: int i = 0;
87:
88: devlen = col - fname;
89: if(devlen > MAXDEVNAME)
90: return(EINVAL);
91:
92: #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
93: if(!isvalidname(fname[i]))
94: return(EINVAL);
95: do {
96: savedevname[i] = fname[i];
97: i++;
98: } while(isvalidname(fname[i]));
99: savedevname[i] = '\0';
100:
101: #define isnum(c) ((c) >= '0' && (c) <= '9')
102: if(i < devlen) {
103: if(!isnum(fname[i]))
104: return(EUNIT);
105: do {
106: u *= 10;
107: u += fname[i++] - '0';
108: } while(isnum(fname[i]));
109: }
110:
111: #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
112: if(i < devlen) {
113: if(!isvalidpart(fname[i]))
114: return(EPART);
115: p = fname[i++] - 'a';
116: }
117:
118: if(i != devlen)
119: return(ENXIO);
120:
121: *devname = savedevname;
122: *unit = u;
123: *partition = p;
124: help = col + 1;
125: } else
126: help = fname;
127:
128: if(*help) *file = help;
129:
130: return(0);
131: }
132:
133: static void
134: print_bootsel(filename)
135: char *filename;
136: {
137: char *fsname;
138: char *devname;
139: int unit, partition;
140: const char *file;
141:
142: if(!parsebootfile(filename, &fsname, &devname, &unit, &partition, &file)) {
143: if(!strcmp(fsname, "dos"))
144: printf("booting %s\n", file);
145: else if(!strcmp(fsname, "ufs"))
146: printf("booting %s%d%c:%s\n", devname, unit,
147: 'a' + partition, file);
148: }
149: }
150:
151: static void
152: bootit(filename, howto, tell)
153: const char *filename;
154: int howto, tell;
155: {
156: if(tell)
157: print_bootsel(filename);
158:
159: if(exec_netbsd(filename, 0, howto, 0, consdev) < 0)
160: printf("boot: %s\n", strerror(errno));
161: else
162: printf("boot returned\n");
163: }
164:
165: static void helpme()
166: {
167: printf("commands are:\n"
168: "boot [xdNx:][filename] [-adrs]\n"
169: " (ex. \"sd0a:netbsd.old -s\"\n"
170: "ls [path]\n"
171: "mode ufs|dos\n"
172: "help|?\n"
173: "quit\n");
174: }
175:
176: /*
177: * chops the head from the arguments and returns the arguments if any,
178: * or possibly an empty string.
179: */
180: static char *
181: gettrailer(arg)
182: char *arg;
183: {
184: char *options;
185:
186: if ((options = strchr(arg, ' ')) == NULL)
187: options = "";
188: else
189: *options++ = '\0';
190: /* trim leading blanks */
191: while (*options && *options == ' ')
192: options++;
193:
194: return(options);
195: }
196:
197: static int
198: parseopts(opts, howto)
199: char *opts;
200: int *howto;
201: {
202: int tmpopt = 0;
203:
204: opts++; /* skip - */
205: while (*opts && *opts != ' ') {
206: tmpopt |= netbsd_opt(*opts);
207: if(tmpopt == -1) {
208: printf("-%c: unknown flag\n", *opts);
209: helpme();
210: return(0);
211: }
212: opts++;
213: }
214: *howto = tmpopt;
215: return(1);
216: }
217:
218: static int
219: parseboot(arg, filename, howto)
220: char *arg;
221: char **filename;
222: int *howto;
223: {
224: char *opts = NULL;
225:
226: *filename = 0;
227: *howto = 0;
228:
229: /* if there were no arguments */
230: if (!*arg)
231: return(1);
232:
233: /* format is... */
234: /*[[xxNx:]filename] [-adrs]*/
235:
236: /* check for just args */
237: if (arg[0] == '-'){
238: opts = arg;
239: } else { /* at least a file name */
240: *filename = arg;
241:
242: opts = gettrailer(arg);
243: if (!*opts)
244: opts = NULL;
245: else if (*opts != '-') {
246: printf("invalid arguments\n");
247: helpme();
248: return(0);
249: }
250: }
251: /* at this point, we have dealt with filenames. */
252:
253: /* now, deal with options */
254: if (opts) {
255: if (!parseopts(opts, howto))
256: return(0);
257: }
258:
259: return(1);
260: }
261:
262: static void
263: parsemode(arg, mode)
264: char *arg;
265: char **mode;
266: {
267: if(!strcmp("dos", arg))
268: *mode = "dos";
269: else if(!strcmp("ufs", arg))
270: *mode = "ufs";
271: else
272: printf("invalid mode\n");
273: }
274:
275: static void
276: docommand(arg)
277: char *arg;
278: {
279: char *options;
280:
281: options = gettrailer(arg);
282:
283: if ((strcmp("help", arg) == 0) ||
284: (strcmp("?", arg) == 0)) {
285: helpme();
286: return;
287: }
288: if (strcmp("ls", arg) == 0){
289: char *help = default_filename;
290: if(strcmp(current_fsmode, "ufs")) {
291: printf("UFS only\n");
292: return;
293: }
294: default_filename = "/";
295: ls(options);
296: default_filename = help;
297: return;
298: }
299: if (strcmp("quit", arg) == 0){
300: printf("Exiting... goodbye...\n");
301: exit(0);
302: }
303: if (strcmp("boot", arg) == 0){
304: char *filename;
305: int howto;
306: if(parseboot(options, &filename, &howto))
307: bootit(filename, howto, 1);
308: return;
309: }
310: if (strcmp("mode", arg) == 0){
311: parsemode(options, ¤t_fsmode);
312: return;
313: }
314: printf("unknown command\n");
315: helpme();
316: }
317:
318: void bootmenu()
319: {
320: printf("\ntype \"?\" or \"help\" for help.\n");
321: for(;;) {
322: char input[80];
323:
324: input[0] = '\0';
325: printf("> ");
326: gets(input);
327:
328: docommand(input);
329: }
330: }
331:
332: static void
333: print_banner(void)
334: {
335: printf("\n"
336: ">> NetBSD BOOT: %d/%d k [%s]\n",
337: getbasemem(),
338: getextmem(),
339: version);
340: }
341:
342: void usage()
343: {
344: printf("dosboot [-u] [-c <commands>] [-i] [filename [-bootopts]]\n");
345: }
346:
347: int main(argc, argv)
348: int argc;
349: char **argv;
350: {
351: int ch;
352: int interactive = 0;
353: int howto;
354: extern char *optarg;
355: extern int optind;
356:
357: consdev = initio(CONSDEV_PC);
358: gateA20();
359:
360: print_banner();
361:
362: current_fsmode = "dos";
363: default_devname = "hd";
364: default_unit = 0;
365: default_partition = 0;
366: default_filename = "netbsd";
367:
368: while((ch = getopt(argc, argv, "c:iu")) != -1) {
369: switch(ch) {
370: case 'c':
371: docommand(optarg);
372: return(1);
373: break;
374: case 'i':
375: interactive = 1;
376: break;
377: case 'u':
378: current_fsmode = "ufs";
379: break;
380: default:
381: usage();
382: return(1);
383: }
384: }
385:
386: if(interactive)
387: bootmenu();
388:
389: argc -= optind;
390: argv += optind;
391:
392: if(argc > 2) {
393: usage();
394: return(1);
395: }
396:
397: howto = 0;
398: if(argc > 1 && !parseopts(argv[1], &howto))
399: return(1);
400:
401: bootit((argc > 0 ? argv[0] : "netbsd"), howto, 1);
402: return(1);
403: }
CVSweb <webmaster@jp.NetBSD.org>