1 1.34 riastrad /* $NetBSD: main.c,v 1.34 2022/09/22 14:27:02 riastradh Exp $ */ 2 1.1 nisimura 3 1.1 nisimura /*- 4 1.1 nisimura * Copyright (c) 2007 The NetBSD Foundation, Inc. 5 1.1 nisimura * All rights reserved. 6 1.1 nisimura * 7 1.1 nisimura * This code is derived from software contributed to The NetBSD Foundation 8 1.1 nisimura * by Tohru Nishimura. 9 1.1 nisimura * 10 1.1 nisimura * Redistribution and use in source and binary forms, with or without 11 1.1 nisimura * modification, are permitted provided that the following conditions 12 1.1 nisimura * are met: 13 1.1 nisimura * 1. Redistributions of source code must retain the above copyright 14 1.1 nisimura * notice, this list of conditions and the following disclaimer. 15 1.1 nisimura * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 nisimura * notice, this list of conditions and the following disclaimer in the 17 1.1 nisimura * documentation and/or other materials provided with the distribution. 18 1.1 nisimura * 19 1.1 nisimura * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 nisimura * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 nisimura * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 nisimura * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 nisimura * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 nisimura * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 nisimura * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 nisimura * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 nisimura * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 nisimura * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 nisimura * POSSIBILITY OF SUCH DAMAGE. 30 1.1 nisimura */ 31 1.1 nisimura 32 1.1 nisimura #include <sys/param.h> 33 1.1 nisimura #include <sys/reboot.h> 34 1.1 nisimura 35 1.1 nisimura #include <lib/libsa/stand.h> 36 1.1 nisimura #include <lib/libsa/loadfile.h> 37 1.1 nisimura #include <lib/libkern/libkern.h> 38 1.1 nisimura 39 1.1 nisimura #include <machine/bootinfo.h> 40 1.1 nisimura 41 1.1 nisimura #include "globals.h" 42 1.1 nisimura 43 1.33 rin #ifdef DEBUG 44 1.33 rin int debug = 1; 45 1.33 rin #endif 46 1.33 rin 47 1.1 nisimura static const struct bootarg { 48 1.1 nisimura const char *name; 49 1.1 nisimura int value; 50 1.1 nisimura } bootargs[] = { 51 1.1 nisimura { "multi", RB_AUTOBOOT }, 52 1.1 nisimura { "auto", RB_AUTOBOOT }, 53 1.1 nisimura { "ask", RB_ASKNAME }, 54 1.1 nisimura { "single", RB_SINGLE }, 55 1.1 nisimura { "ddb", RB_KDB }, 56 1.1 nisimura { "userconf", RB_USERCONF }, 57 1.1 nisimura { "norm", AB_NORMAL }, 58 1.1 nisimura { "quiet", AB_QUIET }, 59 1.1 nisimura { "verb", AB_VERBOSE }, 60 1.1 nisimura { "silent", AB_SILENT }, 61 1.12 phx { "debug", AB_DEBUG }, 62 1.12 phx { "altboot", -1 } 63 1.1 nisimura }; 64 1.1 nisimura 65 1.17 phx /* default PATA drive configuration is "10": single master on first channel */ 66 1.17 phx static char *drive_config = "10"; 67 1.17 phx 68 1.1 nisimura void *bootinfo; /* low memory reserved to pass bootinfo structures */ 69 1.1 nisimura int bi_size; /* BOOTINFO_MAXSIZE */ 70 1.1 nisimura char *bi_next; 71 1.1 nisimura 72 1.1 nisimura void bi_init(void *); 73 1.1 nisimura void bi_add(void *, int, int); 74 1.1 nisimura 75 1.1 nisimura struct btinfo_memory bi_mem; 76 1.1 nisimura struct btinfo_console bi_cons; 77 1.1 nisimura struct btinfo_clock bi_clk; 78 1.1 nisimura struct btinfo_prodfamily bi_fam; 79 1.27 phx struct btinfo_model bi_model; 80 1.1 nisimura struct btinfo_bootpath bi_path; 81 1.1 nisimura struct btinfo_rootdevice bi_rdev; 82 1.1 nisimura struct btinfo_net bi_net; 83 1.1 nisimura struct btinfo_modulelist *btinfo_modulelist; 84 1.1 nisimura size_t btinfo_modulelist_size; 85 1.1 nisimura 86 1.1 nisimura struct boot_module { 87 1.1 nisimura char *bm_kmod; 88 1.1 nisimura ssize_t bm_len; 89 1.1 nisimura struct boot_module *bm_next; 90 1.1 nisimura }; 91 1.1 nisimura struct boot_module *boot_modules; 92 1.1 nisimura char module_base[80]; 93 1.1 nisimura uint32_t kmodloadp; 94 1.1 nisimura int modules_enabled = 0; 95 1.1 nisimura 96 1.31 christos #define MAXMODNAME 32 97 1.23 jakllsch void module_add(const char *); 98 1.30 pgoyette void module_add_split(const char *); 99 1.23 jakllsch void module_load(const char *); 100 1.1 nisimura int module_open(struct boot_module *); 101 1.1 nisimura 102 1.7 phx void main(int, char **, char *, char *); 103 1.12 phx 104 1.4 nisimura extern char bootprog_name[], bootprog_rev[]; 105 1.12 phx extern char newaltboot[], newaltboot_end[]; 106 1.1 nisimura 107 1.6 nisimura struct pcidev lata[2]; 108 1.16 phx struct pcidev lnif[2]; 109 1.6 nisimura struct pcidev lusb[3]; 110 1.6 nisimura int nata, nnif, nusb; 111 1.6 nisimura 112 1.1 nisimura int brdtype; 113 1.1 nisimura uint32_t busclock, cpuclock; 114 1.1 nisimura 115 1.1 nisimura static int check_bootname(char *); 116 1.11 phx static int input_cmdline(char **, int); 117 1.7 phx static int parse_cmdline(char **, int, char *, char *); 118 1.7 phx static int is_space(char); 119 1.15 phx #ifdef DEBUG 120 1.15 phx static void sat_test(void); 121 1.22 phx static void findflash(void); 122 1.15 phx #endif 123 1.7 phx 124 1.12 phx #define BNAME_DEFAULT "wd0:" 125 1.7 phx #define MAX_ARGS 10 126 1.1 nisimura 127 1.1 nisimura void 128 1.7 phx main(int argc, char *argv[], char *bootargs_start, char *bootargs_end) 129 1.1 nisimura { 130 1.19 phx unsigned long marks[MARK_MAX]; 131 1.1 nisimura struct brdprop *brdprop; 132 1.7 phx char *new_argv[MAX_ARGS]; 133 1.19 phx char *bname; 134 1.12 phx ssize_t len; 135 1.19 phx int err, fd, howto, i, n; 136 1.1 nisimura 137 1.19 phx printf("\n>> %s altboot, revision %s\n", bootprog_name, bootprog_rev); 138 1.1 nisimura 139 1.1 nisimura brdprop = brd_lookup(brdtype); 140 1.3 phx printf(">> %s, cpu %u MHz, bus %u MHz, %dMB SDRAM\n", brdprop->verbose, 141 1.1 nisimura cpuclock / 1000000, busclock / 1000000, bi_mem.memsize >> 20); 142 1.1 nisimura 143 1.6 nisimura nata = pcilookup(PCI_CLASS_IDE, lata, 2); 144 1.6 nisimura if (nata == 0) 145 1.14 phx nata = pcilookup(PCI_CLASS_RAID, lata, 2); 146 1.14 phx if (nata == 0) 147 1.6 nisimura nata = pcilookup(PCI_CLASS_MISCSTORAGE, lata, 2); 148 1.8 phx if (nata == 0) 149 1.8 phx nata = pcilookup(PCI_CLASS_SCSI, lata, 2); 150 1.16 phx nnif = pcilookup(PCI_CLASS_ETH, lnif, 2); 151 1.6 nisimura nusb = pcilookup(PCI_CLASS_USB, lusb, 3); 152 1.6 nisimura 153 1.6 nisimura #ifdef DEBUG 154 1.6 nisimura if (nata == 0) 155 1.6 nisimura printf("No IDE/SATA found\n"); 156 1.6 nisimura else for (n = 0; n < nata; n++) { 157 1.6 nisimura int b, d, f, bdf, pvd; 158 1.6 nisimura bdf = lata[n].bdf; 159 1.6 nisimura pvd = lata[n].pvd; 160 1.6 nisimura pcidecomposetag(bdf, &b, &d, &f); 161 1.6 nisimura printf("%04x.%04x DSK %02d:%02d:%02d\n", 162 1.6 nisimura PCI_VENDOR(pvd), PCI_PRODUCT(pvd), b, d, f); 163 1.1 nisimura } 164 1.6 nisimura if (nnif == 0) 165 1.6 nisimura printf("no NET found\n"); 166 1.16 phx else for (n = 0; n < nnif; n++) { 167 1.6 nisimura int b, d, f, bdf, pvd; 168 1.16 phx bdf = lnif[n].bdf; 169 1.16 phx pvd = lnif[n].pvd; 170 1.6 nisimura pcidecomposetag(bdf, &b, &d, &f); 171 1.6 nisimura printf("%04x.%04x NET %02d:%02d:%02d\n", 172 1.6 nisimura PCI_VENDOR(pvd), PCI_PRODUCT(pvd), b, d, f); 173 1.6 nisimura } 174 1.6 nisimura if (nusb == 0) 175 1.6 nisimura printf("no USB found\n"); 176 1.6 nisimura else for (n = 0; n < nusb; n++) { 177 1.6 nisimura int b, d, f, bdf, pvd; 178 1.6 nisimura bdf = lusb[0].bdf; 179 1.6 nisimura pvd = lusb[0].pvd; 180 1.6 nisimura pcidecomposetag(bdf, &b, &d, &f); 181 1.6 nisimura printf("%04x.%04x USB %02d:%02d:%02d\n", 182 1.6 nisimura PCI_VENDOR(pvd), PCI_PRODUCT(pvd), b, d, f); 183 1.1 nisimura } 184 1.6 nisimura #endif 185 1.1 nisimura 186 1.1 nisimura pcisetup(); 187 1.1 nisimura pcifixup(); 188 1.1 nisimura 189 1.7 phx /* 190 1.7 phx * When argc is too big then it is probably a pointer, which could 191 1.7 phx * indicate that we were launched as a Linux kernel module using 192 1.7 phx * "bootm". 193 1.7 phx */ 194 1.7 phx if (argc > MAX_ARGS) { 195 1.13 phx if (argv != NULL) { 196 1.13 phx /* 197 1.17 phx * initrd image was loaded: 198 1.17 phx * check if it contains a valid altboot command line 199 1.13 phx */ 200 1.17 phx char *p = (char *)argv; 201 1.17 phx 202 1.17 phx if (strncmp(p, "altboot:", 8) == 0) { 203 1.17 phx *p = 0; 204 1.17 phx for (p = p + 8; *p >= ' '; p++); 205 1.17 phx argc = parse_cmdline(new_argv, MAX_ARGS, 206 1.17 phx ((char *)argv) + 8, p); 207 1.17 phx argv = new_argv; 208 1.17 phx } else 209 1.17 phx argc = 0; /* boot default */ 210 1.13 phx } else { 211 1.13 phx /* parse standard Linux bootargs */ 212 1.13 phx argc = parse_cmdline(new_argv, MAX_ARGS, 213 1.13 phx bootargs_start, bootargs_end); 214 1.13 phx argv = new_argv; 215 1.13 phx } 216 1.7 phx } 217 1.7 phx 218 1.17 phx /* look for a PATA drive configuration string under the arguments */ 219 1.17 phx for (n = 1; n < argc; n++) { 220 1.17 phx if (strncmp(argv[n], "ide:", 4) == 0 && 221 1.17 phx argv[n][4] >= '0' && argv[n][4] <= '2') { 222 1.17 phx drive_config = &argv[n][4]; 223 1.17 phx break; 224 1.17 phx } 225 1.17 phx } 226 1.17 phx 227 1.29 dholland /* initialize a disk driver */ 228 1.18 phx for (i = 0, n = 0; i < nata; i++) 229 1.18 phx n += dskdv_init(&lata[i]); 230 1.18 phx if (n == 0) 231 1.17 phx printf("IDE/SATA device driver was not found\n"); 232 1.17 phx 233 1.17 phx /* initialize a network interface */ 234 1.17 phx for (n = 0; n < nnif; n++) 235 1.17 phx if (netif_init(&lnif[n]) != 0) 236 1.17 phx break; 237 1.17 phx if (n >= nnif) 238 1.17 phx printf("no NET device driver was found\n"); 239 1.17 phx 240 1.11 phx /* wait 2s for user to enter interactive mode */ 241 1.11 phx for (n = 200; n >= 0; n--) { 242 1.11 phx if (n % 100 == 0) 243 1.19 phx printf("\rHit any key to enter interactive mode: %d", 244 1.11 phx n / 100); 245 1.11 phx if (tstchar()) { 246 1.15 phx #ifdef DEBUG 247 1.22 phx unsigned c; 248 1.22 phx 249 1.22 phx c = toupper(getchar()); 250 1.22 phx if (c == 'C') { 251 1.15 phx /* controller test terminal */ 252 1.15 phx sat_test(); 253 1.15 phx n = 200; 254 1.15 phx continue; 255 1.15 phx } 256 1.22 phx else if (c == 'F') { 257 1.22 phx /* find strings in Flash ROM */ 258 1.22 phx findflash(); 259 1.22 phx n = 200; 260 1.22 phx continue; 261 1.22 phx } 262 1.15 phx #else 263 1.11 phx (void)getchar(); 264 1.15 phx #endif 265 1.15 phx /* enter command line */ 266 1.11 phx argv = new_argv; 267 1.11 phx argc = input_cmdline(argv, MAX_ARGS); 268 1.11 phx break; 269 1.11 phx } 270 1.11 phx delay(10000); 271 1.11 phx } 272 1.11 phx putchar('\n'); 273 1.11 phx 274 1.1 nisimura howto = RB_AUTOBOOT; /* default is autoboot = 0 */ 275 1.1 nisimura 276 1.1 nisimura /* get boot options and determine bootname */ 277 1.1 nisimura for (n = 1; n < argc; n++) { 278 1.17 phx if (strncmp(argv[n], "ide:", 4) == 0) 279 1.17 phx continue; /* ignore drive configuration argument */ 280 1.17 phx 281 1.1 nisimura for (i = 0; i < sizeof(bootargs) / sizeof(bootargs[0]); i++) { 282 1.1 nisimura if (strncasecmp(argv[n], bootargs[i].name, 283 1.1 nisimura strlen(bootargs[i].name)) == 0) { 284 1.1 nisimura howto |= bootargs[i].value; 285 1.1 nisimura break; 286 1.1 nisimura } 287 1.1 nisimura } 288 1.1 nisimura if (i >= sizeof(bootargs) / sizeof(bootargs[0])) 289 1.1 nisimura break; /* break on first unknown string */ 290 1.1 nisimura } 291 1.19 phx 292 1.20 nisimura /* 293 1.20 nisimura * If no device name is given, we construct a list of drives 294 1.20 nisimura * which have valid disklabels. 295 1.20 nisimura */ 296 1.19 phx if (n >= argc) { 297 1.25 christos static const size_t blen = sizeof("wdN:"); 298 1.19 phx n = 0; 299 1.19 phx argc = 0; 300 1.25 christos argv = alloc(MAX_UNITS * (sizeof(char *) + blen)); 301 1.19 phx bname = (char *)(argv + MAX_UNITS); 302 1.19 phx for (i = 0; i < MAX_UNITS; i++) { 303 1.19 phx if (!dlabel_valid(i)) 304 1.19 phx continue; 305 1.25 christos snprintf(bname, blen, "wd%d:", i); 306 1.19 phx argv[argc++] = bname; 307 1.25 christos bname += blen; 308 1.19 phx } 309 1.19 phx /* use default drive if no valid disklabel is found */ 310 1.19 phx if (argc == 0) { 311 1.19 phx argc = 1; 312 1.19 phx argv[0] = BNAME_DEFAULT; 313 1.19 phx } 314 1.19 phx } 315 1.19 phx 316 1.20 nisimura /* try to boot off kernel from the drive list */ 317 1.19 phx while (n < argc) { 318 1.19 phx bname = argv[n++]; 319 1.19 phx 320 1.1 nisimura if (check_bootname(bname) == 0) { 321 1.1 nisimura printf("%s not a valid bootname\n", bname); 322 1.19 phx continue; 323 1.1 nisimura } 324 1.1 nisimura 325 1.19 phx if ((fd = open(bname, 0)) < 0) { 326 1.19 phx if (errno == ENOENT) 327 1.19 phx printf("\"%s\" not found\n", bi_path.bootpath); 328 1.19 phx continue; 329 1.19 phx } 330 1.19 phx printf("loading \"%s\" ", bi_path.bootpath); 331 1.19 phx marks[MARK_START] = 0; 332 1.19 phx 333 1.19 phx if (howto == -1) { 334 1.19 phx /* load another altboot binary and replace ourselves */ 335 1.19 phx len = read(fd, (void *)0x100000, 0x1000000 - 0x100000); 336 1.19 phx if (len == -1) 337 1.19 phx goto loadfail; 338 1.19 phx close(fd); 339 1.19 phx netif_shutdown_all(); 340 1.19 phx 341 1.19 phx memcpy((void *)0xf0000, newaltboot, 342 1.19 phx newaltboot_end - newaltboot); 343 1.19 phx __syncicache((void *)0xf0000, 344 1.19 phx newaltboot_end - newaltboot); 345 1.19 phx printf("Restarting...\n"); 346 1.19 phx run((void *)1, argv, (void *)0x100000, (void *)len, 347 1.19 phx (void *)0xf0000); 348 1.19 phx } 349 1.12 phx 350 1.19 phx err = fdloadfile(fd, marks, LOAD_KERNEL); 351 1.12 phx close(fd); 352 1.32 rin if (err != 0) 353 1.19 phx continue; 354 1.12 phx 355 1.19 phx printf("entry=%p, ssym=%p, esym=%p\n", 356 1.19 phx (void *)marks[MARK_ENTRY], 357 1.19 phx (void *)marks[MARK_SYM], 358 1.19 phx (void *)marks[MARK_END]); 359 1.19 phx 360 1.19 phx bootinfo = (void *)0x4000; 361 1.19 phx bi_init(bootinfo); 362 1.19 phx bi_add(&bi_cons, BTINFO_CONSOLE, sizeof(bi_cons)); 363 1.19 phx bi_add(&bi_mem, BTINFO_MEMORY, sizeof(bi_mem)); 364 1.19 phx bi_add(&bi_clk, BTINFO_CLOCK, sizeof(bi_clk)); 365 1.19 phx bi_add(&bi_path, BTINFO_BOOTPATH, sizeof(bi_path)); 366 1.19 phx bi_add(&bi_rdev, BTINFO_ROOTDEVICE, sizeof(bi_rdev)); 367 1.19 phx bi_add(&bi_fam, BTINFO_PRODFAMILY, sizeof(bi_fam)); 368 1.19 phx if (brdtype == BRD_SYNOLOGY || brdtype == BRD_DLINKDSM) { 369 1.19 phx /* need to pass this MAC address to kernel */ 370 1.19 phx bi_add(&bi_net, BTINFO_NET, sizeof(bi_net)); 371 1.19 phx } 372 1.27 phx bi_add(&bi_model, BTINFO_MODEL, sizeof(bi_model)); 373 1.10 phx 374 1.19 phx if (modules_enabled) { 375 1.21 dsl if (fsmod != NULL) 376 1.30 pgoyette module_add_split(fsmod); 377 1.19 phx kmodloadp = marks[MARK_END]; 378 1.19 phx btinfo_modulelist = NULL; 379 1.19 phx module_load(bname); 380 1.19 phx if (btinfo_modulelist != NULL && 381 1.19 phx btinfo_modulelist->num > 0) 382 1.19 phx bi_add(btinfo_modulelist, BTINFO_MODULELIST, 383 1.19 phx btinfo_modulelist_size); 384 1.19 phx } 385 1.1 nisimura 386 1.19 phx launchfixup(); 387 1.19 phx netif_shutdown_all(); 388 1.1 nisimura 389 1.19 phx __syncicache((void *)marks[MARK_ENTRY], 390 1.19 phx (u_int)marks[MARK_SYM] - (u_int)marks[MARK_ENTRY]); 391 1.19 phx 392 1.19 phx run((void *)marks[MARK_SYM], (void *)marks[MARK_END], 393 1.19 phx (void *)howto, bootinfo, (void *)marks[MARK_ENTRY]); 394 1.1 nisimura 395 1.19 phx /* should never come here */ 396 1.19 phx printf("exec returned. Restarting...\n"); 397 1.19 phx _rtt(); 398 1.19 phx } 399 1.1 nisimura loadfail: 400 1.1 nisimura printf("load failed. Restarting...\n"); 401 1.1 nisimura _rtt(); 402 1.1 nisimura } 403 1.1 nisimura 404 1.1 nisimura void 405 1.1 nisimura bi_init(void *addr) 406 1.1 nisimura { 407 1.1 nisimura struct btinfo_magic bi_magic; 408 1.1 nisimura 409 1.1 nisimura memset(addr, 0, BOOTINFO_MAXSIZE); 410 1.1 nisimura bi_next = (char *)addr; 411 1.1 nisimura bi_size = 0; 412 1.1 nisimura 413 1.1 nisimura bi_magic.magic = BOOTINFO_MAGIC; 414 1.1 nisimura bi_add(&bi_magic, BTINFO_MAGIC, sizeof(bi_magic)); 415 1.1 nisimura } 416 1.1 nisimura 417 1.1 nisimura void 418 1.1 nisimura bi_add(void *new, int type, int size) 419 1.1 nisimura { 420 1.1 nisimura struct btinfo_common *bi; 421 1.1 nisimura 422 1.1 nisimura if (bi_size + size > BOOTINFO_MAXSIZE) 423 1.1 nisimura return; /* XXX error? */ 424 1.1 nisimura 425 1.1 nisimura bi = new; 426 1.1 nisimura bi->next = size; 427 1.1 nisimura bi->type = type; 428 1.1 nisimura memcpy(bi_next, new, size); 429 1.1 nisimura bi_next += size; 430 1.1 nisimura } 431 1.1 nisimura 432 1.30 pgoyette /* 433 1.30 pgoyette * Add a /-separated list of module names to the boot list 434 1.30 pgoyette */ 435 1.31 christos void 436 1.30 pgoyette module_add_split(const char *name) 437 1.30 pgoyette { 438 1.30 pgoyette char mod_name[MAXMODNAME]; 439 1.30 pgoyette int i; 440 1.30 pgoyette const char *mp = name; 441 1.30 pgoyette char *ep; 442 1.30 pgoyette 443 1.30 pgoyette while (*mp) { /* scan list of module names */ 444 1.30 pgoyette i = MAXMODNAME; 445 1.30 pgoyette ep = mod_name; 446 1.30 pgoyette while (--i) { /* scan for end of first name */ 447 1.30 pgoyette *ep = *mp; 448 1.30 pgoyette if (*ep == '/') /* NUL-terminate the name */ 449 1.30 pgoyette *ep = '\0'; 450 1.30 pgoyette 451 1.30 pgoyette if (*ep == 0 ) { /* add non-empty name */ 452 1.30 pgoyette if (ep != mod_name) 453 1.30 pgoyette module_add(mod_name); 454 1.30 pgoyette break; 455 1.30 pgoyette } 456 1.30 pgoyette ep++; mp++; 457 1.30 pgoyette } 458 1.30 pgoyette if (*ep != 0) { 459 1.30 pgoyette printf("module name too long\n"); 460 1.30 pgoyette return; 461 1.30 pgoyette } 462 1.30 pgoyette if (*mp == '/') { /* skip separator if more */ 463 1.30 pgoyette mp++; 464 1.30 pgoyette } 465 1.30 pgoyette } 466 1.30 pgoyette } 467 1.30 pgoyette 468 1.1 nisimura void 469 1.23 jakllsch module_add(const char *name) 470 1.1 nisimura { 471 1.1 nisimura struct boot_module *bm, *bmp; 472 1.1 nisimura 473 1.1 nisimura while (*name == ' ' || *name == '\t') 474 1.1 nisimura ++name; 475 1.1 nisimura 476 1.1 nisimura bm = alloc(sizeof(struct boot_module) + strlen(name) + 1); 477 1.1 nisimura if (bm == NULL) { 478 1.24 jakllsch printf("couldn't allocate module %s\n", name); 479 1.24 jakllsch return; 480 1.1 nisimura } 481 1.1 nisimura 482 1.1 nisimura bm->bm_kmod = (char *)(bm + 1); 483 1.1 nisimura bm->bm_len = -1; 484 1.1 nisimura bm->bm_next = NULL; 485 1.1 nisimura strcpy(bm->bm_kmod, name); 486 1.1 nisimura if ((bmp = boot_modules) == NULL) 487 1.1 nisimura boot_modules = bm; 488 1.1 nisimura else { 489 1.1 nisimura while (bmp->bm_next != NULL) 490 1.1 nisimura bmp = bmp->bm_next; 491 1.1 nisimura bmp->bm_next = bm; 492 1.1 nisimura } 493 1.1 nisimura } 494 1.1 nisimura 495 1.1 nisimura #define PAGE_SIZE 4096 496 1.1 nisimura #define alignpg(x) (((x)+PAGE_SIZE-1) & ~(PAGE_SIZE-1)) 497 1.1 nisimura 498 1.1 nisimura void 499 1.24 jakllsch module_load(const char *kernel_path) 500 1.1 nisimura { 501 1.1 nisimura struct boot_module *bm; 502 1.1 nisimura struct bi_modulelist_entry *bi; 503 1.1 nisimura struct stat st; 504 1.24 jakllsch char *p; 505 1.1 nisimura int size, fd; 506 1.1 nisimura 507 1.1 nisimura strcpy(module_base, kernel_path); 508 1.1 nisimura if ((p = strchr(module_base, ':')) == NULL) 509 1.1 nisimura return; /* eeh?! */ 510 1.1 nisimura p += 1; 511 1.1 nisimura size = sizeof(module_base) - (p - module_base); 512 1.1 nisimura 513 1.1 nisimura if (netbsd_version / 1000000 % 100 == 99) { 514 1.1 nisimura /* -current */ 515 1.1 nisimura snprintf(p, size, 516 1.1 nisimura "/stand/sandpoint/%d.%d.%d/modules", 517 1.1 nisimura netbsd_version / 100000000, 518 1.1 nisimura netbsd_version / 1000000 % 100, 519 1.34 riastrad netbsd_version / 100 % 10000); 520 1.1 nisimura } 521 1.1 nisimura else if (netbsd_version != 0) { 522 1.1 nisimura /* release */ 523 1.1 nisimura snprintf(p, size, 524 1.1 nisimura "/stand/sandpoint/%d.%d/modules", 525 1.1 nisimura netbsd_version / 100000000, 526 1.1 nisimura netbsd_version / 1000000 % 100); 527 1.1 nisimura } 528 1.1 nisimura 529 1.1 nisimura /* 530 1.1 nisimura * 1st pass; determine module existence 531 1.1 nisimura */ 532 1.1 nisimura size = 0; 533 1.1 nisimura for (bm = boot_modules; bm != NULL; bm = bm->bm_next) { 534 1.1 nisimura fd = module_open(bm); 535 1.1 nisimura if (fd == -1) 536 1.1 nisimura continue; 537 1.1 nisimura if (fstat(fd, &st) == -1 || st.st_size == -1) { 538 1.1 nisimura printf("WARNING: couldn't stat %s\n", bm->bm_kmod); 539 1.1 nisimura close(fd); 540 1.1 nisimura continue; 541 1.1 nisimura } 542 1.1 nisimura bm->bm_len = (int)st.st_size; 543 1.1 nisimura close(fd); 544 1.24 jakllsch size += sizeof(struct bi_modulelist_entry); 545 1.1 nisimura } 546 1.1 nisimura if (size == 0) 547 1.1 nisimura return; 548 1.1 nisimura 549 1.1 nisimura size += sizeof(struct btinfo_modulelist); 550 1.1 nisimura btinfo_modulelist = alloc(size); 551 1.1 nisimura if (btinfo_modulelist == NULL) { 552 1.1 nisimura printf("WARNING: couldn't allocate module list\n"); 553 1.1 nisimura return; 554 1.1 nisimura } 555 1.1 nisimura btinfo_modulelist_size = size; 556 1.1 nisimura btinfo_modulelist->num = 0; 557 1.1 nisimura 558 1.1 nisimura /* 559 1.1 nisimura * 2nd pass; load modules into memory 560 1.1 nisimura */ 561 1.1 nisimura kmodloadp = alignpg(kmodloadp); 562 1.1 nisimura bi = (struct bi_modulelist_entry *)(btinfo_modulelist + 1); 563 1.1 nisimura for (bm = boot_modules; bm != NULL; bm = bm->bm_next) { 564 1.1 nisimura if (bm->bm_len == -1) 565 1.1 nisimura continue; /* already found unavailable */ 566 1.1 nisimura fd = module_open(bm); 567 1.1 nisimura printf("module \"%s\" ", bm->bm_kmod); 568 1.1 nisimura size = read(fd, (char *)kmodloadp, SSIZE_MAX); 569 1.1 nisimura if (size < bm->bm_len) 570 1.1 nisimura printf("WARNING: couldn't load"); 571 1.1 nisimura else { 572 1.26 joerg snprintf(bi->kmod, sizeof(bi->kmod), "%s", bm->bm_kmod); 573 1.1 nisimura bi->type = BI_MODULE_ELF; 574 1.1 nisimura bi->len = size; 575 1.1 nisimura bi->base = kmodloadp; 576 1.1 nisimura btinfo_modulelist->num += 1; 577 1.1 nisimura printf("loaded at 0x%08x size 0x%x", kmodloadp, size); 578 1.1 nisimura kmodloadp += alignpg(size); 579 1.1 nisimura bi += 1; 580 1.1 nisimura } 581 1.1 nisimura printf("\n"); 582 1.1 nisimura close(fd); 583 1.1 nisimura } 584 1.1 nisimura btinfo_modulelist->endpa = kmodloadp; 585 1.1 nisimura } 586 1.1 nisimura 587 1.1 nisimura int 588 1.1 nisimura module_open(struct boot_module *bm) 589 1.1 nisimura { 590 1.1 nisimura char path[80]; 591 1.1 nisimura int fd; 592 1.1 nisimura 593 1.1 nisimura snprintf(path, sizeof(path), 594 1.1 nisimura "%s/%s/%s.kmod", module_base, bm->bm_kmod, bm->bm_kmod); 595 1.1 nisimura fd = open(path, 0); 596 1.1 nisimura return fd; 597 1.1 nisimura } 598 1.1 nisimura 599 1.17 phx /* 600 1.17 phx * Return the drive configuration for the requested channel 'ch'. 601 1.17 phx * Channel 2 is the first channel of the next IDE controller. 602 1.17 phx * 0: for no drive present on channel 603 1.17 phx * 1: for master drive present on channel, no slave 604 1.17 phx * 2: for master and slave drive present 605 1.17 phx */ 606 1.17 phx int 607 1.17 phx get_drive_config(int ch) 608 1.1 nisimura { 609 1.17 phx if (drive_config != NULL) { 610 1.17 phx if (strlen(drive_config) <= ch) 611 1.17 phx return 0; /* an unspecified channel is unused */ 612 1.17 phx if (drive_config[ch] >= '0' && drive_config[ch] <= '2') 613 1.17 phx return drive_config[ch] - '0'; 614 1.17 phx } 615 1.17 phx return -1; 616 1.1 nisimura } 617 1.1 nisimura 618 1.1 nisimura void * 619 1.1 nisimura allocaligned(size_t size, size_t align) 620 1.1 nisimura { 621 1.1 nisimura uint32_t p; 622 1.1 nisimura 623 1.1 nisimura if (align-- < 2) 624 1.1 nisimura return alloc(size); 625 1.1 nisimura p = (uint32_t)alloc(size + align); 626 1.1 nisimura return (void *)((p + align) & ~align); 627 1.1 nisimura } 628 1.1 nisimura 629 1.9 phx static int hex2nibble(char c) 630 1.9 phx { 631 1.9 phx 632 1.9 phx if (c >= 'a') 633 1.9 phx c &= ~0x20; 634 1.9 phx if (c >= 'A' && c <= 'F') 635 1.9 phx c -= 'A' - ('9' + 1); 636 1.9 phx else if (c < '0' || c > '9') 637 1.9 phx return -1; 638 1.9 phx 639 1.9 phx return c - '0'; 640 1.9 phx } 641 1.9 phx 642 1.9 phx uint32_t 643 1.9 phx read_hex(const char *s) 644 1.9 phx { 645 1.9 phx int n; 646 1.9 phx uint32_t val; 647 1.9 phx 648 1.9 phx val = 0; 649 1.9 phx while ((n = hex2nibble(*s++)) >= 0) 650 1.9 phx val = (val << 4) | n; 651 1.9 phx return val; 652 1.9 phx } 653 1.9 phx 654 1.1 nisimura static int 655 1.1 nisimura check_bootname(char *s) 656 1.1 nisimura { 657 1.1 nisimura /* 658 1.1 nisimura * nfs: 659 1.1 nisimura * nfs:<bootfile> 660 1.1 nisimura * tftp: 661 1.1 nisimura * tftp:<bootfile> 662 1.1 nisimura * wd[N[P]]:<bootfile> 663 1.9 phx * mem:<address> 664 1.1 nisimura * 665 1.1 nisimura * net is a synonym of nfs. 666 1.1 nisimura */ 667 1.9 phx if (strncmp(s, "nfs:", 4) == 0 || strncmp(s, "net:", 4) == 0 || 668 1.9 phx strncmp(s, "tftp:", 5) == 0 || strncmp(s, "mem:", 4) == 0) 669 1.1 nisimura return 1; 670 1.1 nisimura if (s[0] == 'w' && s[1] == 'd') { 671 1.1 nisimura s += 2; 672 1.1 nisimura if (*s != ':' && *s >= '0' && *s <= '3') { 673 1.1 nisimura ++s; 674 1.1 nisimura if (*s != ':' && *s >= 'a' && *s <= 'p') 675 1.1 nisimura ++s; 676 1.1 nisimura } 677 1.1 nisimura return *s == ':'; 678 1.1 nisimura } 679 1.1 nisimura return 0; 680 1.1 nisimura } 681 1.7 phx 682 1.11 phx static int input_cmdline(char **argv, int maxargc) 683 1.11 phx { 684 1.11 phx char *cmdline; 685 1.11 phx 686 1.11 phx printf("\nbootargs> "); 687 1.11 phx cmdline = alloc(256); 688 1.28 dholland kgets(cmdline, 256); 689 1.11 phx 690 1.11 phx return parse_cmdline(argv, maxargc, cmdline, 691 1.11 phx cmdline + strlen(cmdline)); 692 1.11 phx } 693 1.11 phx 694 1.7 phx static int 695 1.7 phx parse_cmdline(char **argv, int maxargc, char *p, char *end) 696 1.7 phx { 697 1.7 phx int argc; 698 1.7 phx 699 1.7 phx argv[0] = ""; 700 1.7 phx for (argc = 1; argc < maxargc && p < end; argc++) { 701 1.7 phx while (is_space(*p)) 702 1.7 phx p++; 703 1.7 phx if (p >= end) 704 1.7 phx break; 705 1.7 phx argv[argc] = p; 706 1.7 phx while (!is_space(*p) && p < end) 707 1.7 phx p++; 708 1.7 phx *p++ = '\0'; 709 1.7 phx } 710 1.7 phx 711 1.7 phx return argc; 712 1.7 phx } 713 1.7 phx 714 1.7 phx static int 715 1.7 phx is_space(char c) 716 1.7 phx { 717 1.15 phx 718 1.7 phx return c > '\0' && c <= ' '; 719 1.7 phx } 720 1.15 phx 721 1.15 phx #ifdef DEBUG 722 1.15 phx static void 723 1.22 phx findflash(void) 724 1.22 phx { 725 1.22 phx char buf[256]; 726 1.22 phx int i, n; 727 1.22 phx unsigned char c, *p; 728 1.22 phx 729 1.22 phx for (;;) { 730 1.22 phx printf("\nfind> "); 731 1.28 dholland kgets(buf, sizeof(buf)); 732 1.22 phx if (tolower((unsigned)buf[0]) == 'x') 733 1.22 phx break; 734 1.22 phx for (i = 0, n = 0, c = 0; buf[i]; i++) { 735 1.22 phx c <<= 4; 736 1.22 phx c |= hex2nibble(buf[i]); 737 1.22 phx if (i & 1) 738 1.22 phx buf[n++] = c; 739 1.22 phx } 740 1.22 phx printf("Searching for:"); 741 1.22 phx for (i = 0; i < n; i++) 742 1.22 phx printf(" %02x", buf[i]); 743 1.22 phx printf("\n"); 744 1.22 phx for (p = (unsigned char *)0xff000000; 745 1.22 phx p <= (unsigned char *)(0xffffffff-n); p++) { 746 1.22 phx for (i = 0; i < n; i++) { 747 1.22 phx if (p[i] != buf[i]) 748 1.22 phx break; 749 1.22 phx } 750 1.22 phx if (i >= n) 751 1.22 phx printf("Found at %08x\n", (unsigned)p); 752 1.22 phx } 753 1.22 phx } 754 1.22 phx } 755 1.22 phx 756 1.22 phx static void 757 1.15 phx sat_test(void) 758 1.15 phx { 759 1.15 phx char buf[1024]; 760 1.15 phx int i, j, n, pos; 761 1.15 phx unsigned char c; 762 1.15 phx 763 1.15 phx putchar('\n'); 764 1.15 phx for (;;) { 765 1.15 phx do { 766 1.15 phx for (pos = 0; pos < 1024 && sat_tstch() != 0; pos++) 767 1.15 phx buf[pos] = sat_getch(); 768 1.15 phx if (pos > 1023) 769 1.15 phx break; 770 1.15 phx delay(100000); 771 1.15 phx } while (sat_tstch()); 772 1.15 phx 773 1.15 phx for (i = 0; i < pos; i += 16) { 774 1.15 phx if ((n = i + 16) > pos) 775 1.15 phx n = pos; 776 1.15 phx for (j = 0; j < n; j++) 777 1.15 phx printf("%02x ", (unsigned)buf[i + j]); 778 1.15 phx for (; j < 16; j++) 779 1.15 phx printf(" "); 780 1.15 phx putchar('\"'); 781 1.15 phx for (j = 0; j < n; j++) { 782 1.15 phx c = buf[i + j]; 783 1.15 phx putchar((c >= 0x20 && c <= 0x7e) ? c : '.'); 784 1.15 phx } 785 1.15 phx printf("\"\n"); 786 1.15 phx } 787 1.15 phx 788 1.15 phx printf("controller> "); 789 1.28 dholland kgets(buf, sizeof(buf)); 790 1.15 phx if (buf[0] == '*' && buf[1] == 'X') 791 1.15 phx break; 792 1.15 phx 793 1.15 phx if (buf[0] == '0' && tolower((unsigned)buf[1]) == 'x') { 794 1.15 phx for (i = 2, n = 0, c = 0; buf[i]; i++) { 795 1.15 phx c <<= 4; 796 1.15 phx c |= hex2nibble(buf[i]); 797 1.15 phx if (i & 1) 798 1.15 phx buf[n++] = c; 799 1.15 phx } 800 1.15 phx } else 801 1.15 phx n = strlen(buf); 802 1.15 phx 803 1.15 phx if (n > 0) 804 1.15 phx sat_write(buf, n); 805 1.15 phx } 806 1.15 phx } 807 1.15 phx #endif 808