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