1 /* $NetBSD: main.c,v 1.3.2.3 2004/09/21 13:16:12 skrll Exp $ */
4 * Copyright (c) 2003 Naoto Shimazaki.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
30 * Boot loader for L-Card+
35 * BFFF FFFF ------------------------------
39 * BF80 0000 ------------------------------
42 * BFFF FFFF ------------------------------
44 * user storage (max 2Mbytes)
46 * BFE0 0000 ------------------------------
50 * BFD4 0000 ------------------------------
54 * BFD2 0000 ------------------------------
56 * second boot loader (mirror image)
59 * BFD0 0000 ------------------------------
61 * first boot loader (L-Card+ original loader)
64 * BFC0 0000 ------------------------------
66 * gziped kernel image (max 4Mbytes)
68 * BF80 0000 ------------------------------
75 * 80FF FFFF ------------------------------
77 * 80FF FE00 ------------------------------
79 * 80FF FDA8 ------------------------------
84 * 8004 0000 ------------------------------
85 * kernel stack (growing to lower)
88 * boot loader heap (growing to upper)
89 * boot loader text & data (at exec time)
90 * 8000 1000 ------------------------------
92 * 8000 0000 ------------------------------
94 * virtual memory space
96 * 0000 0000 ------------------------------
100 * ROMCS0 <-> ROMCS3 mapping
103 * BE7F FFFF <-> BFFF FFFF
104 * BE40 0000 <-> BFC0 0000 reset vector
105 * BE00 0000 <-> BF80 0000
109 #include <sys/cdefs.h>
110 __KERNEL_RCSID(0, "$NetBSD: main.c,v 1.3.2.3 2004/09/21 13:16:12 skrll Exp $");
112 #include <lib/libsa/stand.h>
114 #include <lib/libsa/loadfile.h>
115 #include <lib/libkern/libkern.h>
117 #include <hpcmips/vr/vripreg.h>
118 #include <hpcmips/vr/cmureg.h>
119 #include <hpcmips/vr/vr4181giureg.h>
122 #include "i28f128reg.h"
125 #define ISABRGCTL 0x00
126 #define ISABRGSTS 0x02
129 #define BOOTTIMEOUT 9 /* must less than 10 */
130 #define LINEBUFLEN 80
132 extern const char bootprog_rev
[];
133 extern const char bootprog_name
[];
134 extern const char bootprog_date
[];
135 extern const char bootprog_maker
[];
137 static void command_help(char *opt
);
138 static void command_dump(char *opt
);
139 static void command_boot(char *opt
);
140 static void command_load(char *opt
);
141 static void command_fill(char *opt
);
142 static void command_write(char *opt
);
143 static void command_option(char *subcmd
);
144 static void opt_subcmd_print(char *opt
);
145 static void opt_subcmd_read(char *opt
);
146 static void opt_subcmd_write(char *opt
);
147 static void opt_subcmd_path(char *opt
);
148 static void opt_subcmd_bootp(char *opt
);
149 static void opt_subcmd_ip(char *opt
);
152 struct boot_option bootopts
;
154 static struct bootmenu_command commands
[] = {
155 { "?", command_help
},
156 { "h", command_help
},
157 { "d", command_dump
},
158 { "b", command_boot
},
159 { "l", command_load
},
160 { "f", command_fill
},
161 { "w", command_write
},
162 { "o", command_option
},
166 static struct bootmenu_command opt_subcommands
[] = {
167 { "p", opt_subcmd_print
},
168 { "r", opt_subcmd_read
},
169 { "w", opt_subcmd_write
},
170 { "path", opt_subcmd_path
},
171 { "bootp", opt_subcmd_bootp
},
172 { "ip", opt_subcmd_ip
},
180 printf(">> %s, Revision %s\n", bootprog_name
, bootprog_rev
);
181 printf(">> (%s, %s)\n", bootprog_maker
, bootprog_date
);
183 printf(">> Memory: %d/%d k\n", getbasemem(), getextmem());
191 REGWRITE_2(VRETIMEH
, 0, 0);
192 REGWRITE_2(VRETIMEM
, 0, 0);
193 REGWRITE_2(VRETIMEL
, 0, 0);
200 * PClock (CPU clock) 65.536MHz
201 * PClock = (18.432MHz / CLKSP) x 64
202 * = (18.432MHz / 18) x 64
204 * TClock (peripheral clock) 32.768MHz
205 * TClock = PClock / DIV
211 * setup ISA BUS clock freqency
213 * set PCLK (internal peripheral clock) to 32.768MHz (TClock / 1)
214 * set External ISA bus clock to 10.922MHz (TClock / 3)
216 REGWRITE_2(VR4181_ISABRG_ADDR
, ISABRGCTL
, 0x0003);
217 REGWRITE_2(VR4181_ISABRG_ADDR
, XISACTL
, 0x0401);
220 * setup peripheral's clock supply
223 * AIU: enable (AIU, ADU, ADU18M)
225 * SIU: enable (SIU18M)
227 REGWRITE_2(VR4181_CMU_ADDR
, 0, CMUMASK_SIU
| CMUMASK_AIU
);
233 /* L-Card+ generic setup */
238 * GP2 : GPO LED6 (0: on 1: off)
239 * GP3 : PCS0 chip select for CS8900A Lan controller
240 * GP4 : GPI IRQ input from CS8900A
243 * GP7 : GPI reserved by TANBAC TB0193
245 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_PIOD_L_REG_W
, 0xffff);
246 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_MODE0_REG_W
,
250 * GP8 : GPO LED5 (0: on 1: off)
259 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_MODE1_REG_W
, GP8_GPO
);
264 * GP18: IORDY ISA bus
267 * GP21: RESET resets CS8900A
268 * GP22: ROMCS0 ROM chip select
269 * GP23: ROMCS1 ROM chip select
271 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_MODE2_REG_W
,
272 GP23_ROMCS1
| GP22_ROMCS0
| GP21_RESET
273 | GP18_IORDY
| GP17_IOWR
| GP16_IORD
);
275 * GP24: ROMCS2 ROM chip select
281 * GP30: GPI reserved by TANBAC TB0193
284 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_MODE3_REG_W
,
286 | GP28_CTS1
| GP27_RTS1
| GP26_TxD1
| GP25_RxD1
289 /* e-care node specific setup */
292 * GP0 : GPO ECNRTC_RST
293 * GP1 : GPO ECNRTC_CLK
294 * GP2 : GPO LED6 (0: on 1: off)
295 * GP3 : PCS0 chip select for CS8900A Lan controller
296 * GP4 : GPI IRQ input from CS8900A
297 * GP5 : GPO ECNRTC_DIR
298 * GP6 : GPO ECNRTC_OUT
299 * GP7 : GPI reserved by TANBAC TB0193
301 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_PIOD_L_REG_W
, 0xffff);
302 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_MODE0_REG_W
,
303 GP6_GPO
| GP5_GPO
| GP3_PCS0
304 | GP2_GPO
| GP1_GPO
| GP0_GPO
);
308 * GP8 : GPO LED5 (0: on 1: off)
312 * GP12: GPI ECNRTC_IN
317 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_MODE1_REG_W
,
324 * GP18: IORDY ISA bus
327 * GP21: RESET resets CS8900A
328 * GP22: ROMCS0 ROM chip select
329 * GP23: ROMCS1 ROM chip select
331 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_MODE2_REG_W
,
332 GP23_ROMCS1
| GP22_ROMCS0
| GP21_RESET
333 | GP18_IORDY
| GP17_IOWR
| GP16_IORD
);
335 * GP24: ROMCS2 ROM chip select
341 * GP30: GPI reserved by TANBAC TB0193
344 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_MODE3_REG_W
,
346 | GP28_CTS1
| GP27_RTS1
| GP26_TxD1
| GP25_RxD1
354 * I4TYP: falling edge trigger
357 * other: unused, mask, disable
359 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_INTTYP_L_REG_W
,
361 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_INTMASK_REG_W
,
363 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_INTEN_REG_W
, GIEN4
);
367 * programmable chip select
369 * PCS0 is used to select CS8900A Ethernet controller
373 * 0x14010000 - 0x14010fff
374 * I/O access, 16bit cycle, both of read/write
377 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_PCS0STRA_REG_W
, 0x0000);
378 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_PCS0STPA_REG_W
, 0x0fff);
379 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_PCS0HIA_REG_W
, 0x1401);
380 REGWRITE_2(VR4181_GIU81_ADDR
, VR4181GIU_PCSMODE_REG_W
,
381 PCS0MIOB_IO
| PCS0DSIZE_16BIT
| PCS0MD_READWRITE
);
385 * chops the head from the arguments and returns the arguments if any,
386 * or possibly an empty string.
389 get_next_arg(char *arg
)
393 if ((opt
= strchr(arg
, ' ')) == NULL
) {
399 /* trim leading blanks */
407 command_help(char *opt
)
409 printf("commands are:\n"
411 "dump:\td addr [addr]\n"
412 "fill:\tf addr addr char\n"
413 "load:\tl [offset] (with following S-Record)\n"
414 "write:\tw dst src len\n"
415 "option:\to subcommand [params]\n"
418 "option subcommands are:\n"
422 "path:\to path pathname\n"
423 "bootp:\to bootp yes|no\n"
424 "ip:\to ip remote local netmask gateway\n"
431 printf("bad param\n");
435 static const u_int8_t print_cnv
[] = {
436 '0', '1', '2', '3', '4', '5', '6', '7',
437 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
440 printhexul(u_int32_t n
)
444 for (i
= 28; i
>= 0; i
-= 4)
445 putchar(print_cnv
[(n
>> i
) & 0x0f]);
449 printhexuc(u_int8_t n
)
453 for (i
= 4; i
>= 0; i
-= 4)
454 putchar(print_cnv
[(n
>> i
) & 0x0f]);
458 command_dump(char *opt
)
462 const char *line_fence
;
465 p
= (const char *) strtoul(opt
, &endptr
, 16);
471 opt
= get_next_arg(opt
);
472 limit
= (const char *) strtoul(opt
, &endptr
, 16);
478 printhexul((u_int32_t
) p
);
481 while (p
< line_fence
) {
491 if (getchar() == '\x03')
498 command_boot(char *opt
)
500 u_long marks
[MARK_MAX
];
502 marks
[MARK_START
] = 0;
503 if (loadfile(bootopts
.b_pathname
, marks
, LOAD_KERNEL
)) {
504 printf("loadfile failed\n");
515 load_srec(char *offset
)
530 * the first step is to read a S-Record.
532 if ((c
= getchar()) != 'S')
537 s2lbuf
[0] = getchar();
538 s2lbuf
[1] = getchar();
540 reclen_bk
= reclen
= strtoul(s2lbuf
, &endptr
, 16);
541 if (endptr
!= &s2lbuf
[2])
552 } while (c
!= '\r' && c
!= '\n');
573 recaddr
= strtoul(s2lbuf
, &endptr
, 16);
576 sum
+= (recaddr
>> 24) & 0xff;
577 sum
+= (recaddr
>> 16) & 0xff;
578 sum
+= (recaddr
>> 8) & 0xff;
579 sum
+= recaddr
& 0xff;
581 p
= offset
+ recaddr
;
584 * address range is must be chaked here!
589 s2lbuf
[0] = getchar();
590 s2lbuf
[1] = getchar();
591 *p
= (u_int8_t
) strtoul(s2lbuf
, &endptr
, 16);
592 if (endptr
!= &s2lbuf
[2])
608 s2lbuf
[0] = getchar();
609 s2lbuf
[1] = getchar();
611 sum
+= (strtoul(s2lbuf
, &endptr
, 16) & 0xff);
614 printf("checksum error\n");
620 if (c
!= '\r' && c
!= '\n')
627 printf("invalid S-Record\n");
633 } while (c
!= '\r' && c
!= '\n');
639 command_load(char *opt
)
644 offset
= (char *) strtoul(opt
, &endptr
, 16);
651 command_fill(char *opt
)
658 p
= (char *) strtoul(opt
, &endptr
, 16);
664 opt
= get_next_arg(opt
);
665 limit
= (char *) strtoul(opt
, &endptr
, 16);
671 opt
= get_next_arg(opt
);
672 c
= strtoul(opt
, &endptr
, 16);
676 memset(p
, c
, limit
- p
);
680 check_write_verify_flash(u_int32_t src
, u_int32_t dst
, size_t len
)
684 if ((dst
& I28F128_BLOCK_MASK
) != 0) {
685 printf("dst addr must be aligned to block boundary (0x%x)\n",
690 if (i28f128_probe((void *) dst
)) {
691 printf("dst addr is not a intel 28F128\n");
693 printf("intel 28F128 detected\n");
696 if ((status
= i28f128_region_write((void *) dst
, (void *) src
, len
))
698 printf("write mem to flash failed status = %x\n", status
);
702 printf("verifying...");
703 if (memcmp((void *) dst
, (void *) src
, len
)) {
704 printf("verify error\n");
709 printf("writing memory to flash succeeded\n");
713 command_write(char *opt
)
720 dst
= strtoul(opt
, &endptr
, 16);
724 opt
= get_next_arg(opt
);
725 src
= strtoul(opt
, &endptr
, 16);
729 opt
= get_next_arg(opt
);
730 len
= strtoul(opt
, &endptr
, 16);
734 check_write_verify_flash(src
, dst
, len
);
743 command_option(char *subcmd
)
748 opt
= get_next_arg(subcmd
);
750 /* dispatch subcommand */
751 for (i
= 0; opt_subcommands
[i
].c_name
!= NULL
; i
++) {
752 if (strcmp(subcmd
, opt_subcommands
[i
].c_name
) == 0) {
753 opt_subcommands
[i
].c_fn(opt
);
757 if (opt_subcommands
[i
].c_name
== NULL
) {
758 printf("unknown option subcommand\n");
764 opt_subcmd_print(char *opt
)
766 printf("boot options:\n"
770 bootopts
.b_magic
== BOOTOPT_MAGIC
? "ok" : "bad",
772 bootopts
.b_flags
& B_F_USE_BOOTP
? "yes" : "no");
773 printf("remote IP:\t%s\n", inet_ntoa(bootopts
.b_remote_ip
));
774 printf("local IP:\t%s\n", inet_ntoa(bootopts
.b_local_ip
));
775 printf("netmask:\t%s\n", intoa(bootopts
.b_netmask
));
776 printf("gateway IP:\t%s\n", inet_ntoa(bootopts
.b_gate_ip
));
780 opt_subcmd_read(char *opt
)
782 bootopts
= *((struct boot_option
*) BOOTOPTS_BASE
);
783 if (bootopts
.b_magic
!= BOOTOPT_MAGIC
)
784 bootopts
.b_pathname
[0] = '\0';
788 opt_subcmd_write(char *opt
)
790 bootopts
.b_magic
= BOOTOPT_MAGIC
;
792 check_write_verify_flash((u_int32_t
) &bootopts
, BOOTOPTS_BASE
,
797 opt_subcmd_path(char *opt
)
799 strlcpy(bootopts
.b_pathname
, opt
, sizeof bootopts
.b_pathname
);
803 opt_subcmd_bootp(char *opt
)
805 if (strcmp(opt
, "yes") == 0) {
806 bootopts
.b_flags
|= B_F_USE_BOOTP
;
807 } else if (strcmp(opt
, "no") == 0) {
808 bootopts
.b_flags
&= ~B_F_USE_BOOTP
;
815 opt_subcmd_ip(char *opt
)
817 bootopts
.b_remote_ip
.s_addr
= inet_addr(opt
);
818 opt
= get_next_arg(opt
);
819 bootopts
.b_local_ip
.s_addr
= inet_addr(opt
);
820 opt
= get_next_arg(opt
);
821 bootopts
.b_netmask
= inet_addr(opt
);
822 opt
= get_next_arg(opt
);
823 bootopts
.b_gate_ip
.s_addr
= inet_addr(opt
);
829 char input
[LINEBUFLEN
];
842 /* skip leading whitespace. */
847 /* here, some command entered */
849 opt
= get_next_arg(cmd
);
851 /* dispatch command */
852 for (i
= 0; commands
[i
].c_name
!= NULL
; i
++) {
853 if (strcmp(cmd
, commands
[i
].c_name
) == 0) {
854 commands
[i
].c_fn(opt
);
858 if (commands
[i
].c_name
== NULL
) {
859 printf("unknown command\n");
877 for (i
= BOOTTIMEOUT
; i
> 0; i
--) {
879 for (j
= 0; j
< 1000000; j
++) {
909 opt_subcmd_read(NULL
);
914 if (c
!= '\r' && c
!= '\n' && c
!= '\0') {
915 printf("type \"?\" or \"h\" for help.\n");
916 bootmenu(); /* does not return */
921 * command_boot() returns only if it failed to boot.
922 * we enter to boot menu in this case.