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