xref: /netbsd-src/sys/arch/hpcmips/stand/lcboot/main.c (revision 85e3fbd2ebdea4c043943e3fc74aae69c997bc76)
1 /* $NetBSD: main.c,v 1.7 2016/06/11 06:29:24 dholland Exp $ */
2 
3 /*
4  * Copyright (c) 2003 Naoto Shimazaki.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY NAOTO SHIMAZAKI AND CONTRIBUTORS ``AS IS''
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE NAOTO OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * Boot loader for L-Card+
31  *
32  * ROM Map
33  * -------
34  * ROM1
35  * BFFF FFFF	------------------------------
36  *
37  *		reserved
38  *
39  * BF80 0000	------------------------------
40  *
41  * ROM0
42  * BFFF FFFF	------------------------------
43  *
44  *		user storage (max 2Mbytes)
45  *
46  * BFE0 0000	------------------------------
47  *
48  *		reserved
49  *
50  * BFD4 0000	------------------------------
51  *
52  *		boot params
53  *
54  * BFD2 0000	------------------------------
55  *
56  *		second boot loader (mirror image)
57  *		or Linux Kernel
58  *
59  * BFD0 0000	------------------------------
60  *
61  *		first boot loader (L-Card+ original loader)
62  *
63  *		reset vector
64  * BFC0 0000	------------------------------
65  *
66  *		gziped kernel image (max 4Mbytes)
67  *
68  * BF80 0000	------------------------------
69  *
70  *
71  *
72  * RAM Map
73  * -------
74  *
75  * 80FF FFFF	------------------------------
76  *		ROM ICE work
77  * 80FF FE00	------------------------------
78  *		ROM ICE stack
79  * 80FF FDA8	------------------------------
80  *
81  *
82  *
83  *		kernel
84  * 8004 0000	------------------------------
85  *		kernel stack (growing to lower)
86  *
87  *
88  *		boot loader heap (growing to upper)
89  *		boot loader text & data (at exec time)
90  * 8000 1000	------------------------------
91  *		vector table
92  * 8000 0000	------------------------------
93  *
94  *		virtual memory space
95  *
96  * 0000 0000	------------------------------
97  *
98  *
99  *
100  * ROMCS0 <-> ROMCS3 mapping
101  *
102  *  ROMCS0        ROMCS3
103  * BE7F FFFF <-> BFFF FFFF
104  * BE40 0000 <-> BFC0 0000	reset vector
105  * BE00 0000 <-> BF80 0000
106  *
107  *
108  */
109 #include <sys/cdefs.h>
110 __KERNEL_RCSID(0, "$NetBSD: main.c,v 1.7 2016/06/11 06:29:24 dholland Exp $");
111 
112 #include <lib/libsa/stand.h>
113 
114 #include <lib/libsa/loadfile.h>
115 #include <lib/libkern/libkern.h>
116 
117 #include <hpcmips/vr/vripreg.h>
118 #include <hpcmips/vr/cmureg.h>
119 #include <hpcmips/vr/vr4181giureg.h>
120 
121 #include "extern.h"
122 #include "i28f128reg.h"
123 
124 /* XXX */
125 #define ISABRGCTL	0x00
126 #define ISABRGSTS	0x02
127 #define XISACTL		0x04
128 
129 #define BOOTTIMEOUT	9	/* must less than 10 */
130 #define LINEBUFLEN	80
131 
132 extern const char bootprog_rev[];
133 extern const char bootprog_name[];
134 
135 static void command_help(char *opt);
136 static void command_dump(char *opt);
137 static void command_boot(char *opt);
138 static void command_load(char *opt);
139 static void command_fill(char *opt);
140 static void command_write(char *opt);
141 static void command_option(char *subcmd);
142 static void opt_subcmd_print(char *opt);
143 static void opt_subcmd_read(char *opt);
144 static void opt_subcmd_write(char *opt);
145 static void opt_subcmd_path(char *opt);
146 static void opt_subcmd_bootp(char *opt);
147 static void opt_subcmd_ip(char *opt);
148 
149 
150 struct boot_option	bootopts;
151 
152 static struct bootmenu_command commands[] = {
153 	{ "?",		command_help },
154 	{ "h",		command_help },
155 	{ "d",		command_dump },
156 	{ "b",		command_boot },
157 	{ "l",		command_load },
158 	{ "f",		command_fill },
159 	{ "w",		command_write },
160 	{ "o",		command_option },
161 	{ NULL,		NULL },
162 };
163 
164 static struct bootmenu_command opt_subcommands[] = {
165 	{ "p",		opt_subcmd_print },
166 	{ "r",		opt_subcmd_read },
167 	{ "w",		opt_subcmd_write },
168 	{ "path",	opt_subcmd_path },
169 	{ "bootp",	opt_subcmd_bootp },
170 	{ "ip",		opt_subcmd_ip },
171 	{ NULL,		NULL },
172 };
173 
174 static void
print_banner(void)175 print_banner(void)
176 {
177 	printf("\n");
178 	printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
179 #if 0
180 	printf(">> Memory: %d/%d k\n", getbasemem(), getextmem());
181 #endif
182 }
183 
184 static void
init_devices(void)185 init_devices(void)
186 {
187 	/* Init RTC */
188 	REGWRITE_2(VRETIMEH, 0, 0);
189 	REGWRITE_2(VRETIMEM, 0, 0);
190 	REGWRITE_2(VRETIMEL, 0, 0);
191 
192 
193 	/*
194 	 * CLKSPEEDREG	0x6012
195 	 *	DIV	DIV2 mode
196 	 *	CLKSP	18 (0x12)
197 	 *	PClock (CPU clock)		65.536MHz
198 	 *		PClock = (18.432MHz / CLKSP) x 64
199 	 *		       = (18.432MHz / 18) x 64
200 	 *		       = 65.536MHz
201 	 *	TClock (peripheral clock)	32.768MHz
202 	 *		TClock = PClock / DIV
203 	 *		       = 65.536MHz / 2
204 	 *		       = 32.768MHz
205 	 */
206 
207 	/*
208 	 * setup ISA BUS clock freqency
209 	 *
210 	 * set PCLK (internal peripheral clock) to 32.768MHz (TClock / 1)
211 	 * set External ISA bus clock to 10.922MHz (TClock / 3)
212 	 */
213 	REGWRITE_2(VR4181_ISABRG_ADDR, ISABRGCTL, 0x0003);
214 	REGWRITE_2(VR4181_ISABRG_ADDR, XISACTL, 0x0401);
215 
216 	/*
217 	 * setup peripheral's clock supply
218 	 *
219 	 * CSU: disable
220 	 * AIU: enable (AIU, ADU, ADU18M)
221 	 * PIU: disable
222 	 * SIU: enable (SIU18M)
223 	 */
224 	REGWRITE_2(VR4181_CMU_ADDR, 0, CMUMASK_SIU | CMUMASK_AIU);
225 
226 	/*
227 	 * setup GPIO
228 	 */
229 #if 0
230 	/* L-Card+ generic setup */
231 	/*
232 	 * pin   mode	comment
233 	 * GP0 : GPI	not used
234 	 * GP1 : GPI	not used
235 	 * GP2 : GPO	LED6 (0: on  1: off)
236 	 * GP3 : PCS0	chip select for CS8900A Lan controller
237 	 * GP4 : GPI	IRQ input from CS8900A
238 	 * GP5 : GPI	not used
239 	 * GP6 : GPI	not used
240 	 * GP7 : GPI	reserved by TANBAC TB0193
241 	 */
242 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PIOD_L_REG_W, 0xffff);
243 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE0_REG_W,
244 		   GP3_PCS0 | GP2_GPO);
245 	/*
246 	 * pin   mode	comment
247 	 * GP8 : GPO	LED5 (0: on  1: off)
248 	 * GP9 : GPI	CD2
249 	 * GP10: GPI	CD1
250 	 * GP11: GPI	not used
251 	 * GP12: GPI	not used
252 	 * GP13: GPI	not used
253 	 * GP14: GPI	not used
254 	 * GP15: GPI	not used
255 	 */
256 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE1_REG_W, GP8_GPO);
257 	/*
258 	 * pin   mode	comment
259 	 * GP16: IORD	ISA bus
260 	 * GP17: IOWR	ISA bus
261 	 * GP18: IORDY	ISA bus
262 	 * GP19: GPI	not used
263 	 * GP20: GPI	not used
264 	 * GP21: RESET	resets CS8900A
265 	 * GP22: ROMCS0	ROM chip select
266 	 * GP23: ROMCS1	ROM chip select
267 	 */
268 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE2_REG_W,
269 		   GP23_ROMCS1 | GP22_ROMCS0 | GP21_RESET
270 		   | GP18_IORDY | GP17_IOWR | GP16_IORD);
271 	/*
272 	 * GP24: ROMCS2	ROM chip select
273 	 * GP25: RxD1	SIU1
274 	 * GP26: TxD1	SIU1
275 	 * GP27: RTS1	SIU1
276 	 * GP28: CTS1	SIU1
277 	 * GP29: GPI	LED3
278 	 * GP30: GPI	reserved by TANBAC TB0193
279 	 * GP31: GPI	LED4
280 	 */
281 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE3_REG_W,
282 		   GP30_GPI
283 		   | GP28_CTS1 | GP27_RTS1 | GP26_TxD1 | GP25_RxD1
284 		   | GP24_ROMCS2);
285 #else
286 	/* e-care node specific setup */
287 	/*
288 	 * pin   mode	comment
289 	 * GP0 : GPO	ECNRTC_RST
290 	 * GP1 : GPO	ECNRTC_CLK
291 	 * GP2 : GPO	LED6 (0: on  1: off)
292 	 * GP3 : PCS0	chip select for CS8900A Lan controller
293 	 * GP4 : GPI	IRQ input from CS8900A
294 	 * GP5 : GPO	ECNRTC_DIR
295 	 * GP6 : GPO	ECNRTC_OUT
296 	 * GP7 : GPI	reserved by TANBAC TB0193
297 	 */
298 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PIOD_L_REG_W, 0xffff);
299 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE0_REG_W,
300 		   GP6_GPO | GP5_GPO | GP3_PCS0
301 		   | GP2_GPO | GP1_GPO | GP0_GPO);
302 
303 	/*
304 	 * pin   mode	comment
305 	 * GP8 : GPO	LED5 (0: on  1: off)
306 	 * GP9 : GPI	CD2
307 	 * GP10: GPI	CD1
308 	 * GP11: GPI	not used
309 	 * GP12: GPI	ECNRTC_IN
310 	 * GP13: GPI	not used
311 	 * GP14: GPI	not used
312 	 * GP15: GPI	not used
313 	 */
314 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE1_REG_W,
315 		   GP12_GPI | GP8_GPO);
316 
317 	/*
318 	 * pin   mode	comment
319 	 * GP16: IORD	ISA bus
320 	 * GP17: IOWR	ISA bus
321 	 * GP18: IORDY	ISA bus
322 	 * GP19: GPI	not used
323 	 * GP20: GPI	not used
324 	 * GP21: RESET	resets CS8900A
325 	 * GP22: ROMCS0	ROM chip select
326 	 * GP23: ROMCS1	ROM chip select
327 	 */
328 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE2_REG_W,
329 		   GP23_ROMCS1 | GP22_ROMCS0 | GP21_RESET
330 		   | GP18_IORDY | GP17_IOWR | GP16_IORD);
331 	/*
332 	 * GP24: ROMCS2	ROM chip select
333 	 * GP25: RxD1	SIU1
334 	 * GP26: TxD1	SIU1
335 	 * GP27: RTS1	SIU1
336 	 * GP28: CTS1	SIU1
337 	 * GP29: GPI	LED3
338 	 * GP30: GPI	reserved by TANBAC TB0193
339 	 * GP31: GPI	LED4
340 	 */
341 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE3_REG_W,
342 		   GP30_GPI
343 		   | GP28_CTS1 | GP27_RTS1 | GP26_TxD1 | GP25_RxD1
344 		   | GP24_ROMCS2);
345 #endif
346 
347 #if 0
348 	/*
349 	 * setup interrupt
350 	 *
351 	 * I4TYP:  falling edge trigger
352 	 * GIMSK4: unmask
353 	 * GIEN4:  enable
354 	 * other:  unused, mask, disable
355 	 */
356 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_INTTYP_L_REG_W,
357 		   I4TYP_HIGH_LEVEL);
358 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_INTMASK_REG_W,
359 		   0xffffU & ~GIMSK4);
360 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_INTEN_REG_W, GIEN4);
361 #endif
362 
363 	/*
364 	 * programmable chip select
365 	 *
366 	 * PCS0 is used to select CS8900A Ethernet controller
367 	 * on TB0193
368 	 *
369 	 * PCS0:
370 	 *	0x14010000 - 0x14010fff
371 	 *	I/O access, 16bit cycle, both of read/write
372 	 * PCS1: unused
373 	 */
374 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PCS0STRA_REG_W, 0x0000);
375 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PCS0STPA_REG_W, 0x0fff);
376 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PCS0HIA_REG_W, 0x1401);
377 	REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PCSMODE_REG_W,
378 		   PCS0MIOB_IO | PCS0DSIZE_16BIT | PCS0MD_READWRITE);
379 }
380 
381 /*
382  * chops the head from the arguments and returns the arguments if any,
383  * or possibly an empty string.
384  */
385 static char *
get_next_arg(char * arg)386 get_next_arg(char *arg)
387 {
388 	char *opt;
389 
390 	if ((opt = strchr(arg, ' ')) == NULL) {
391 		opt = "";
392 	} else {
393 		*opt++ = '\0';
394 	}
395 
396         /* trim leading blanks */
397 	while (*opt == ' ')
398 		opt++;
399 
400 	return opt;
401 }
402 
403 static void
command_help(char * opt)404 command_help(char *opt)
405 {
406 	printf("commands are:\n"
407 	       "boot:\tb\n"
408 	       "dump:\td addr [addr]\n"
409 	       "fill:\tf addr addr char\n"
410 	       "load:\tl [offset] (with following S-Record)\n"
411 	       "write:\tw dst src len\n"
412 	       "option:\to subcommand [params]\n"
413 	       "help:\th|?\n"
414 	       "\n"
415 	       "option subcommands are:\n"
416 	       "print:\to p\n"
417 	       "read:\to r\n"
418 	       "write:\to w\n"
419 	       "path:\to path pathname\n"
420 	       "bootp:\to bootp yes|no\n"
421 	       "ip:\to ip remote local netmask gateway\n"
422 		);
423 }
424 
425 static void
bad_param(void)426 bad_param(void)
427 {
428 	printf("bad param\n");
429 	command_help(NULL);
430 }
431 
432 static const u_int8_t print_cnv[] = {
433 	'0', '1', '2', '3', '4', '5', '6', '7',
434 	'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
435 
436 static void
printhexul(u_int32_t n)437 printhexul(u_int32_t n)
438 {
439 	int	i;
440 
441 	for (i = 28; i >= 0; i -= 4)
442 		putchar(print_cnv[(n >> i) & 0x0f]);
443 }
444 
445 static void
printhexuc(u_int8_t n)446 printhexuc(u_int8_t n)
447 {
448 	int	i;
449 
450 	for (i = 4; i >= 0; i -= 4)
451 		putchar(print_cnv[(n >> i) & 0x0f]);
452 }
453 
454 static void
command_dump(char * opt)455 command_dump(char *opt)
456 {
457 	char		*endptr;
458 	const char	*p;
459 	const char	*line_fence;
460 	const char	*limit;
461 
462 	p = (const char *) strtoul(opt, &endptr, 16);
463 	if (opt == endptr) {
464 		bad_param();
465 		return;
466 	}
467 
468 	opt = get_next_arg(opt);
469 	limit = (const char *) strtoul(opt, &endptr, 16);
470 	if (opt == endptr) {
471 		limit = p + 256;
472 	}
473 
474 	for (;;) {
475 		printhexul((u_int32_t) p);
476 		putchar(' ');
477 		line_fence = p + 16;
478 		while (p < line_fence) {
479 			printhexuc(*p++);
480 			putchar(' ');
481 			if (p >= limit) {
482 				putchar('\n');
483 				return;
484 			}
485 		}
486 		putchar('\n');
487 		if (ISKEY) {
488 			if (getchar() == '\x03')
489 				break;
490 		}
491 	}
492 }
493 
494 static void
command_boot(char * opt)495 command_boot(char *opt)
496 {
497 	u_long	marks[MARK_MAX];
498 
499 	marks[MARK_START] = 0;
500 	if (loadfile(bootopts.b_pathname, marks, LOAD_KERNEL)) {
501 		printf("loadfile failed\n");
502 		return;
503 	}
504 	start_netbsd();
505 	/* no return */
506 }
507 
508 /*
509  * loading S-Record
510  */
511 static int
load_srec(char * offset)512 load_srec(char *offset)
513 {
514 	char		s2lbuf[9];
515 	char		c;
516 	char		rectype;
517 	u_int32_t	reclen;
518 	u_int32_t	reclen_bk;
519 	u_int32_t	recaddr;
520 	char		*endptr;
521 	char		*p;
522 	u_int32_t	sum;
523 	int		err = 0;
524 
525 	for (;;) {
526 		/*
527 		 * the first step is to read a S-Record.
528 		 */
529 		if ((c = getchar()) != 'S')
530 			goto out;
531 
532 		rectype = getchar();
533 
534 		s2lbuf[0] = getchar();
535 		s2lbuf[1] = getchar();
536 		s2lbuf[2] = '\0';
537 		reclen_bk = reclen = strtoul(s2lbuf, &endptr, 16);
538 		if (endptr != &s2lbuf[2])
539 			goto out;
540 		sum = reclen;
541 
542 		p = s2lbuf;
543 
544 		switch (rectype) {
545 		case '0':
546 			/* just ignore */
547 			do {
548 				c = getchar();
549 			} while (c != '\r' && c != '\n');
550 			continue;
551 
552 		case '3':
553 			*p++ = getchar();
554 			*p++ = getchar();
555 			reclen--;
556 			/* FALLTHRU */
557 		case '2':
558 			*p++ = getchar();
559 			*p++ = getchar();
560 			reclen--;
561 			/* FALLTHRU */
562 		case '1':
563 			*p++ = getchar();
564 			*p++ = getchar();
565 			*p++ = getchar();
566 			*p++ = getchar();
567 			*p = '\0';
568 			reclen -= 2;
569 
570 			recaddr = strtoul(s2lbuf, &endptr, 16);
571 			if (endptr != p)
572 				goto out;
573 			sum += (recaddr >> 24) & 0xff;
574 			sum += (recaddr >> 16) & 0xff;
575 			sum += (recaddr >> 8) & 0xff;
576 			sum += recaddr & 0xff;
577 
578 			p = offset + recaddr;
579 			/*
580 			 * XXX
581 			 * address range is must be chaked here!
582 			 */
583 			reclen--;
584 			s2lbuf[2] = '\0';
585 			while (reclen > 0) {
586 				s2lbuf[0] = getchar();
587 				s2lbuf[1] = getchar();
588 				*p = (u_int8_t) strtoul(s2lbuf, &endptr, 16);
589 				if (endptr != &s2lbuf[2])
590 					goto out;
591 				sum += *p++;
592 				reclen--;
593 			}
594 			break;
595 
596 		case '7':
597 		case '8':
598 		case '9':
599 			goto out2;
600 
601 		default:
602 			goto out;
603 		}
604 
605 		s2lbuf[0] = getchar();
606 		s2lbuf[1] = getchar();
607 		s2lbuf[2] = '\0';
608 		sum += (strtoul(s2lbuf, &endptr, 16) & 0xff);
609 		sum &= 0xff;
610 		if (sum != 0xff) {
611 			printf("checksum error\n");
612 			err = 1;
613 			goto out2;
614 		}
615 
616 		c = getchar();
617 		if (c != '\r' && c != '\n')
618 			goto out;
619 	}
620 	/* never reach */
621 	return 1;
622 
623 out:
624 	printf("invalid S-Record\n");
625 	err = 1;
626 
627 out2:
628 	do {
629 		c = getchar();
630 	} while (c != '\r' && c != '\n');
631 
632 	return err;
633 }
634 
635 static void
command_load(char * opt)636 command_load(char *opt)
637 {
638 	char	*endptr;
639 	char	*offset;
640 
641 	offset = (char *) strtoul(opt, &endptr, 16);
642 	if (opt == endptr)
643 		offset = 0;
644 	load_srec(offset);
645 }
646 
647 static void
command_fill(char * opt)648 command_fill(char *opt)
649 {
650 	char	*endptr;
651 	char	*p;
652 	char	*limit;
653 	int	c;
654 
655 	p = (char *) strtoul(opt, &endptr, 16);
656 	if (opt == endptr) {
657 		bad_param();
658 		return;
659 	}
660 
661 	opt = get_next_arg(opt);
662 	limit = (char *) strtoul(opt, &endptr, 16);
663 	if (opt == endptr) {
664 		bad_param();
665 		return;
666 	}
667 
668 	opt = get_next_arg(opt);
669 	c = strtoul(opt, &endptr, 16);
670 	if (opt == endptr)
671 		c = '\0';
672 
673 	memset(p, c, limit - p);
674 }
675 
676 static void
check_write_verify_flash(u_int32_t src,u_int32_t dst,size_t len)677 check_write_verify_flash(u_int32_t src, u_int32_t dst, size_t len)
678 {
679 	int		status;
680 
681 	if ((dst & I28F128_BLOCK_MASK) != 0) {
682 		printf("dst addr must be aligned to block boundary (0x%x)\n",
683 		       I28F128_BLOCK_SIZE);
684 		return;
685 	}
686 
687 	if (i28f128_probe((void *) dst)) {
688 		printf("dst addr is not a intel 28F128\n");
689 	} else {
690 		printf("intel 28F128 detected\n");
691 	}
692 
693 	if ((status = i28f128_region_write((void *) dst, (void *) src, len))
694 	    != 0) {
695 		printf("write mem to flash failed status = %x\n", status);
696 		return;
697 	}
698 
699 	printf("verifying...");
700 	if (memcmp((void *) dst, (void *) src, len)) {
701 		printf("verify error\n");
702 		return;
703 	}
704 	printf("ok\n");
705 
706 	printf("writing memory to flash succeeded\n");
707 }
708 
709 static void
command_write(char * opt)710 command_write(char *opt)
711 {
712 	char		*endptr;
713 	u_int32_t	src;
714 	u_int32_t	dst;
715 	size_t		len;
716 
717 	dst = strtoul(opt, &endptr, 16);
718 	if (opt == endptr)
719 		goto out;
720 
721 	opt = get_next_arg(opt);
722 	src = strtoul(opt, &endptr, 16);
723 	if (opt == endptr)
724 		goto out;
725 
726 	opt = get_next_arg(opt);
727 	len = strtoul(opt, &endptr, 16);
728 	if (opt == endptr)
729 		goto out;
730 
731 	check_write_verify_flash(src, dst, len);
732 	return;
733 
734 out:
735 	bad_param();
736 	return;
737 }
738 
739 static void
command_option(char * subcmd)740 command_option(char *subcmd)
741 {
742 	char	*opt;
743 	int	i;
744 
745 	opt = get_next_arg(subcmd);
746 
747 	/* dispatch subcommand */
748 	for (i = 0; opt_subcommands[i].c_name != NULL; i++) {
749 		if (strcmp(subcmd, opt_subcommands[i].c_name) == 0) {
750 			opt_subcommands[i].c_fn(opt);
751 			break;
752 		}
753 	}
754 	if (opt_subcommands[i].c_name == NULL) {
755 		printf("unknown option subcommand\n");
756 		command_help(NULL);
757 	}
758 }
759 
760 static void
opt_subcmd_print(char * opt)761 opt_subcmd_print(char *opt)
762 {
763 	printf("boot options:\n"
764 	       "magic:\t\t%s\n"
765 	       "pathname:\t`%s'\n"
766 	       "bootp:\t\t%s\n",
767 	       bootopts.b_magic == BOOTOPT_MAGIC ? "ok" : "bad",
768 	       bootopts.b_pathname,
769 	       bootopts.b_flags & B_F_USE_BOOTP ? "yes" : "no");
770 	printf("remote IP:\t%s\n", inet_ntoa(bootopts.b_remote_ip));
771 	printf("local IP:\t%s\n", inet_ntoa(bootopts.b_local_ip));
772 	printf("netmask:\t%s\n", intoa(bootopts.b_netmask));
773 	printf("gateway IP:\t%s\n", inet_ntoa(bootopts.b_gate_ip));
774 }
775 
776 static void
opt_subcmd_read(char * opt)777 opt_subcmd_read(char *opt)
778 {
779 	bootopts = *((struct boot_option *) BOOTOPTS_BASE);
780 	if (bootopts.b_magic != BOOTOPT_MAGIC)
781 		bootopts.b_pathname[0] = '\0';
782 }
783 
784 static void
opt_subcmd_write(char * opt)785 opt_subcmd_write(char *opt)
786 {
787 	bootopts.b_magic = BOOTOPT_MAGIC;
788 
789 	check_write_verify_flash((u_int32_t) &bootopts, BOOTOPTS_BASE,
790 				 sizeof bootopts);
791 }
792 
793 static void
opt_subcmd_path(char * opt)794 opt_subcmd_path(char *opt)
795 {
796 	strlcpy(bootopts.b_pathname, opt, sizeof bootopts.b_pathname);
797 }
798 
799 static void
opt_subcmd_bootp(char * opt)800 opt_subcmd_bootp(char *opt)
801 {
802 	if (strcmp(opt, "yes") == 0) {
803 		bootopts.b_flags |= B_F_USE_BOOTP;
804 	} else if (strcmp(opt, "no") == 0) {
805 		bootopts.b_flags &= ~B_F_USE_BOOTP;
806 	} else {
807 		bad_param();
808 	}
809 }
810 
811 static void
opt_subcmd_ip(char * opt)812 opt_subcmd_ip(char *opt)
813 {
814 	bootopts.b_remote_ip.s_addr = inet_addr(opt);
815 	opt = get_next_arg(opt);
816 	bootopts.b_local_ip.s_addr = inet_addr(opt);
817 	opt = get_next_arg(opt);
818 	bootopts.b_netmask = inet_addr(opt);
819 	opt = get_next_arg(opt);
820 	bootopts.b_gate_ip.s_addr = inet_addr(opt);
821 }
822 
823 static void
bootmenu(void)824 bootmenu(void)
825 {
826 	char	input[LINEBUFLEN];
827 	char	*cmd;
828 	char	*opt;
829 	int	i;
830 
831 	for (;;) {
832 
833 		/* input a line */
834 		input[0] = '\0';
835 		printf("> ");
836 		kgets(input, sizeof(input));
837 		cmd = input;
838 
839 		/* skip leading whitespace. */
840 		while(*cmd == ' ')
841 			cmd++;
842 
843 		if(*cmd) {
844 			/* here, some command entered */
845 
846 			opt = get_next_arg(cmd);
847 
848 			/* dispatch command */
849 			for (i = 0; commands[i].c_name != NULL; i++) {
850 				if (strcmp(cmd, commands[i].c_name) == 0) {
851 					commands[i].c_fn(opt);
852 					break;
853 				}
854 			}
855 			if (commands[i].c_name == NULL) {
856 				printf("unknown command\n");
857 				command_help(NULL);
858 			}
859 		}
860 
861 	}
862 }
863 
864 static char
awaitkey(void)865 awaitkey(void)
866 {
867 	int	i;
868 	int	j;
869 	char	c = 0;
870 
871 	while (ISKEY)
872 		getchar();
873 
874 	for (i = BOOTTIMEOUT; i > 0; i--) {
875 		printf("%d\b", i);
876 		for (j = 0; j < 1000000; j++) {
877 			if (ISKEY) {
878 				while (ISKEY)
879 					c = getchar();
880 				goto out;
881 			}
882 		}
883 	}
884 
885 out:
886 	printf("0\n");
887 	return(c);
888 }
889 
890 __dead void
_rtt(void)891 _rtt(void)
892 {
893 	for (;;)
894 		;
895 }
896 
897 int
main(void)898 main(void)
899 {
900 	char	c;
901 
902 	init_devices();
903 
904 	comcninit();
905 
906 	opt_subcmd_read(NULL);
907 
908 	print_banner();
909 
910 	c = awaitkey();
911 	if (c != '\r' && c != '\n' && c != '\0') {
912 		printf("type \"?\" or \"h\" for help.\n");
913 		bootmenu(); /* does not return */
914 	}
915 
916 	command_boot(NULL);
917 	/*
918 	 * command_boot() returns only if it failed to boot.
919 	 * we enter to boot menu in this case.
920 	 */
921 	bootmenu();
922 
923 	return 0;
924 }
925