18 */ 19 20#include <sys/param.h> 21#include <sys/reboot.h> 22#include <sys/diskslice.h> 23#include <sys/disklabel.h> 24#include <sys/diskmbr.h> 25#include <sys/dirent.h> 26#include <machine/bootinfo.h> 27#include <machine/elf.h> 28 29#include <stdarg.h> 30 31#include <a.out.h> 32 33#include <btxv86.h> 34 35#include "boot2.h" 36#include "lib.h" 37 38#define IO_KEYBOARD 1 39#define IO_SERIAL 2 40 41#define SECOND 18 /* Circa that many ticks in a second. */ 42 43#define RBX_ASKNAME 0x0 /* -a */ 44#define RBX_SINGLE 0x1 /* -s */ 45#define RBX_DFLTROOT 0x5 /* -r */ 46#define RBX_KDB 0x6 /* -d */ 47#define RBX_CONFIG 0xa /* -c */ 48#define RBX_VERBOSE 0xb /* -v */ 49#define RBX_SERIAL 0xc /* -h */ 50#define RBX_CDROM 0xd /* -C */ 51#define RBX_GDB 0xf /* -g */ 52#define RBX_MUTE 0x10 /* -m */ 53#define RBX_PAUSE 0x12 /* -p */ 54#define RBX_DUAL 0x1d /* -D */ 55#define RBX_PROBEKBD 0x1e /* -P */ 56#define RBX_NOINTR 0x1f /* -n */ 57 58#define RBX_MASK 0x2005ffff 59 60#define PATH_CONFIG "/boot.config" 61#define PATH_BOOT3 "/boot/loader" 62#define PATH_KERNEL "/kernel" 63 64#define ARGS 0x900 65#define NOPT 14 66#define NDEV 5 67#define MEM_BASE 0x12 68#define MEM_EXT 0x15 69#define V86_CY(x) ((x) & 1) 70#define V86_ZR(x) ((x) & 0x40) 71 72#define DRV_HARD 0x80 73#define DRV_MASK 0x7f 74 75#define TYPE_AD 0 76#define TYPE_WD 1 77#define TYPE_DA 2 78#define TYPE_MAXHARD TYPE_DA 79#define TYPE_WFD 3 80#define TYPE_FD 4 81 82extern uint32_t _end; 83 84static const char optstr[NOPT] = "DhaCcdgmnPprsv"; 85static const unsigned char flags[NOPT] = { 86 RBX_DUAL, 87 RBX_SERIAL, 88 RBX_ASKNAME, 89 RBX_CDROM, 90 RBX_CONFIG, 91 RBX_KDB, 92 RBX_GDB, 93 RBX_MUTE, 94 RBX_NOINTR, 95 RBX_PROBEKBD, 96 RBX_PAUSE, 97 RBX_DFLTROOT, 98 RBX_SINGLE, 99 RBX_VERBOSE 100}; 101 102static const char *const dev_nm[NDEV] = {"ad", "wd", "da", " ", "fd"}; 103static const unsigned char dev_maj[NDEV] = {30, 0, 4, 1, 2}; 104 105static struct dsk { 106 unsigned drive; 107 unsigned type; 108 unsigned unit; 109 unsigned slice; 110 unsigned part; 111 unsigned start; 112 int init; 113} dsk; 114static char cmd[512]; 115static char kname[1024]; 116static uint32_t opts = RB_BOOTINFO; 117static struct bootinfo bootinfo; 118static uint8_t ioctrl = IO_KEYBOARD; 119 120void exit(int); 121static void load(const char *); 122static int parse(char *); 123static int xfsread(ino_t, void *, size_t); 124static int dskread(void *, unsigned, unsigned); 125static int printf(const char *,...); 126static int putchar(int); 127static uint32_t memsize(int); 128static int drvread(void *, unsigned, unsigned); 129static int keyhit(unsigned); 130static int xputc(int); 131static int xgetc(int); 132static int getc(int); 133 134#if 1 135#define memcpy __builtin_memcpy 136#else 137static void memcpy(char *, const char *, int); 138static void 139memcpy(char *dst, const char *src, int len) 140{ 141 while (len--) 142 *dst++ = *src++; 143} 144#endif 145 146static inline int 147strcmp(const char *s1, const char *s2) 148{ 149 for (; *s1 == *s2 && *s1; s1++, s2++); 150 return (u_char)*s1 - (u_char)*s2; 151} 152 153#include "ufsread.c" 154 155static int 156xfsread(ino_t inode, void *buf, size_t nbyte) 157{ 158 if (fsread(inode, buf, nbyte) != nbyte) { 159 printf("Invalid %s\n", "format"); 160 return -1; 161 } 162 return 0; 163} 164 165static inline void 166getstr(char *str, int size) 167{ 168 char *s; 169 int c; 170 171 s = str; 172 for (;;) { 173 switch (c = xgetc(0)) { 174 case 0: 175 break; 176 case '\177': 177 c = '\b'; 178 case '\b': 179 if (s > str) { 180 s--; 181 putchar('\b'); 182 putchar(' '); 183 } else 184 c = 0; 185 break; 186 case '\n': 187 case '\r': 188 *s = 0; 189 return; 190 default: 191 if (s - str < size - 1) 192 *s++ = c; 193 } 194 if (c) 195 putchar(c); 196 } 197} 198 199static inline uint32_t 200drvinfo(int drive) 201{ 202 v86.addr = 0x13; 203 v86.eax = 0x800; 204 v86.edx = DRV_HARD + drive; 205 v86int(); 206 if (V86_CY(v86.efl)) 207 return 0x4f010f; 208 return ((v86.ecx & 0xc0) << 18) | ((v86.ecx & 0xff00) << 8) | 209 (v86.edx & 0xff00) | (v86.ecx & 0x3f); 210} 211 212static inline void 213putc(int c) 214{ 215 v86.addr = 0x10; 216 v86.eax = 0xe00 | (c & 0xff); 217 v86.ebx = 0x7; 218 v86int(); 219} 220 221int 222main(void) 223{ 224 int autoboot, i; 225 ino_t ino; 226 227 dmadat = (void *)(roundup2(__base + _end, 0x10000) - __base); 228 v86.ctl = V86_FLAGS; 229 dsk.drive = *(uint8_t *)PTOV(ARGS); 230 dsk.type = dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD; 231 dsk.unit = dsk.drive & DRV_MASK; 232 dsk.slice = *(uint8_t *)PTOV(ARGS + 1) + 1; 233 bootinfo.bi_version = BOOTINFO_VERSION; 234 bootinfo.bi_size = sizeof(bootinfo); 235 bootinfo.bi_basemem = 0; /* XXX will be filled by loader or kernel */ 236 bootinfo.bi_extmem = memsize(MEM_EXT); 237 bootinfo.bi_memsizes_valid++; 238 for (i = 0; i < N_BIOS_GEOM; i++) 239 bootinfo.bi_bios_geom[i] = drvinfo(i); 240 241 /* Process configuration file */ 242 243 autoboot = 1; 244 245 if ((ino = lookup(PATH_CONFIG))) 246 fsread(ino, cmd, sizeof(cmd)); 247 248 if (*cmd) { 249 printf("%s: %s", PATH_CONFIG, cmd); 250 if (parse(cmd)) 251 autoboot = 0; 252 /* Do not process this command twice */ 253 *cmd = 0; 254 } 255 256 /* 257 * Try to exec stage 3 boot loader. If interrupted by a keypress, 258 * or in case of failure, try to load a kernel directly instead. 259 */ 260 261 if (autoboot && !*kname) { 262 memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3)); 263 if (!keyhit(3*SECOND)) { 264 load(kname); 265 memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); 266 } 267 } 268 269 /* Present the user with the boot2 prompt. */ 270 271 for (;;) {
| 18 */ 19 20#include <sys/param.h> 21#include <sys/reboot.h> 22#include <sys/diskslice.h> 23#include <sys/disklabel.h> 24#include <sys/diskmbr.h> 25#include <sys/dirent.h> 26#include <machine/bootinfo.h> 27#include <machine/elf.h> 28 29#include <stdarg.h> 30 31#include <a.out.h> 32 33#include <btxv86.h> 34 35#include "boot2.h" 36#include "lib.h" 37 38#define IO_KEYBOARD 1 39#define IO_SERIAL 2 40 41#define SECOND 18 /* Circa that many ticks in a second. */ 42 43#define RBX_ASKNAME 0x0 /* -a */ 44#define RBX_SINGLE 0x1 /* -s */ 45#define RBX_DFLTROOT 0x5 /* -r */ 46#define RBX_KDB 0x6 /* -d */ 47#define RBX_CONFIG 0xa /* -c */ 48#define RBX_VERBOSE 0xb /* -v */ 49#define RBX_SERIAL 0xc /* -h */ 50#define RBX_CDROM 0xd /* -C */ 51#define RBX_GDB 0xf /* -g */ 52#define RBX_MUTE 0x10 /* -m */ 53#define RBX_PAUSE 0x12 /* -p */ 54#define RBX_DUAL 0x1d /* -D */ 55#define RBX_PROBEKBD 0x1e /* -P */ 56#define RBX_NOINTR 0x1f /* -n */ 57 58#define RBX_MASK 0x2005ffff 59 60#define PATH_CONFIG "/boot.config" 61#define PATH_BOOT3 "/boot/loader" 62#define PATH_KERNEL "/kernel" 63 64#define ARGS 0x900 65#define NOPT 14 66#define NDEV 5 67#define MEM_BASE 0x12 68#define MEM_EXT 0x15 69#define V86_CY(x) ((x) & 1) 70#define V86_ZR(x) ((x) & 0x40) 71 72#define DRV_HARD 0x80 73#define DRV_MASK 0x7f 74 75#define TYPE_AD 0 76#define TYPE_WD 1 77#define TYPE_DA 2 78#define TYPE_MAXHARD TYPE_DA 79#define TYPE_WFD 3 80#define TYPE_FD 4 81 82extern uint32_t _end; 83 84static const char optstr[NOPT] = "DhaCcdgmnPprsv"; 85static const unsigned char flags[NOPT] = { 86 RBX_DUAL, 87 RBX_SERIAL, 88 RBX_ASKNAME, 89 RBX_CDROM, 90 RBX_CONFIG, 91 RBX_KDB, 92 RBX_GDB, 93 RBX_MUTE, 94 RBX_NOINTR, 95 RBX_PROBEKBD, 96 RBX_PAUSE, 97 RBX_DFLTROOT, 98 RBX_SINGLE, 99 RBX_VERBOSE 100}; 101 102static const char *const dev_nm[NDEV] = {"ad", "wd", "da", " ", "fd"}; 103static const unsigned char dev_maj[NDEV] = {30, 0, 4, 1, 2}; 104 105static struct dsk { 106 unsigned drive; 107 unsigned type; 108 unsigned unit; 109 unsigned slice; 110 unsigned part; 111 unsigned start; 112 int init; 113} dsk; 114static char cmd[512]; 115static char kname[1024]; 116static uint32_t opts = RB_BOOTINFO; 117static struct bootinfo bootinfo; 118static uint8_t ioctrl = IO_KEYBOARD; 119 120void exit(int); 121static void load(const char *); 122static int parse(char *); 123static int xfsread(ino_t, void *, size_t); 124static int dskread(void *, unsigned, unsigned); 125static int printf(const char *,...); 126static int putchar(int); 127static uint32_t memsize(int); 128static int drvread(void *, unsigned, unsigned); 129static int keyhit(unsigned); 130static int xputc(int); 131static int xgetc(int); 132static int getc(int); 133 134#if 1 135#define memcpy __builtin_memcpy 136#else 137static void memcpy(char *, const char *, int); 138static void 139memcpy(char *dst, const char *src, int len) 140{ 141 while (len--) 142 *dst++ = *src++; 143} 144#endif 145 146static inline int 147strcmp(const char *s1, const char *s2) 148{ 149 for (; *s1 == *s2 && *s1; s1++, s2++); 150 return (u_char)*s1 - (u_char)*s2; 151} 152 153#include "ufsread.c" 154 155static int 156xfsread(ino_t inode, void *buf, size_t nbyte) 157{ 158 if (fsread(inode, buf, nbyte) != nbyte) { 159 printf("Invalid %s\n", "format"); 160 return -1; 161 } 162 return 0; 163} 164 165static inline void 166getstr(char *str, int size) 167{ 168 char *s; 169 int c; 170 171 s = str; 172 for (;;) { 173 switch (c = xgetc(0)) { 174 case 0: 175 break; 176 case '\177': 177 c = '\b'; 178 case '\b': 179 if (s > str) { 180 s--; 181 putchar('\b'); 182 putchar(' '); 183 } else 184 c = 0; 185 break; 186 case '\n': 187 case '\r': 188 *s = 0; 189 return; 190 default: 191 if (s - str < size - 1) 192 *s++ = c; 193 } 194 if (c) 195 putchar(c); 196 } 197} 198 199static inline uint32_t 200drvinfo(int drive) 201{ 202 v86.addr = 0x13; 203 v86.eax = 0x800; 204 v86.edx = DRV_HARD + drive; 205 v86int(); 206 if (V86_CY(v86.efl)) 207 return 0x4f010f; 208 return ((v86.ecx & 0xc0) << 18) | ((v86.ecx & 0xff00) << 8) | 209 (v86.edx & 0xff00) | (v86.ecx & 0x3f); 210} 211 212static inline void 213putc(int c) 214{ 215 v86.addr = 0x10; 216 v86.eax = 0xe00 | (c & 0xff); 217 v86.ebx = 0x7; 218 v86int(); 219} 220 221int 222main(void) 223{ 224 int autoboot, i; 225 ino_t ino; 226 227 dmadat = (void *)(roundup2(__base + _end, 0x10000) - __base); 228 v86.ctl = V86_FLAGS; 229 dsk.drive = *(uint8_t *)PTOV(ARGS); 230 dsk.type = dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD; 231 dsk.unit = dsk.drive & DRV_MASK; 232 dsk.slice = *(uint8_t *)PTOV(ARGS + 1) + 1; 233 bootinfo.bi_version = BOOTINFO_VERSION; 234 bootinfo.bi_size = sizeof(bootinfo); 235 bootinfo.bi_basemem = 0; /* XXX will be filled by loader or kernel */ 236 bootinfo.bi_extmem = memsize(MEM_EXT); 237 bootinfo.bi_memsizes_valid++; 238 for (i = 0; i < N_BIOS_GEOM; i++) 239 bootinfo.bi_bios_geom[i] = drvinfo(i); 240 241 /* Process configuration file */ 242 243 autoboot = 1; 244 245 if ((ino = lookup(PATH_CONFIG))) 246 fsread(ino, cmd, sizeof(cmd)); 247 248 if (*cmd) { 249 printf("%s: %s", PATH_CONFIG, cmd); 250 if (parse(cmd)) 251 autoboot = 0; 252 /* Do not process this command twice */ 253 *cmd = 0; 254 } 255 256 /* 257 * Try to exec stage 3 boot loader. If interrupted by a keypress, 258 * or in case of failure, try to load a kernel directly instead. 259 */ 260 261 if (autoboot && !*kname) { 262 memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3)); 263 if (!keyhit(3*SECOND)) { 264 load(kname); 265 memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); 266 } 267 } 268 269 /* Present the user with the boot2 prompt. */ 270 271 for (;;) {
|
273 "Default: %u:%s(%u,%c)%s\n" 274 "boot: ", 275 dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, 276 'a' + dsk.part, kname); 277 if (ioctrl & IO_SERIAL) 278 sio_flush(); 279 if (!autoboot || keyhit(5*SECOND)) 280 getstr(cmd, sizeof(cmd)); 281 else 282 putchar('\n'); 283 autoboot = 0; 284 if (parse(cmd)) 285 putchar('\a'); 286 else 287 load(kname); 288 } 289} 290 291/* XXX - Needed for btxld to link the boot2 binary; do not remove. */ 292void 293exit(int x) 294{ 295} 296 297static void 298load(const char *fname) 299{ 300 union { 301 struct exec ex; 302 Elf32_Ehdr eh; 303 } hdr; 304 Elf32_Phdr ep[2]; 305 Elf32_Shdr es[2]; 306 caddr_t p; 307 ino_t ino; 308 uint32_t addr, x; 309 int fmt, i, j; 310 311 if (!(ino = lookup(fname))) { 312 if (!ls) 313 printf("No %s\n", fname); 314 return; 315 } 316 if (xfsread(ino, &hdr, sizeof(hdr))) 317 return; 318 if (N_GETMAGIC(hdr.ex) == ZMAGIC) 319 fmt = 0; 320 else if (IS_ELF(hdr.eh)) 321 fmt = 1; 322 else { 323 printf("Invalid %s\n", "format"); 324 return; 325 } 326 if (fmt == 0) { 327 addr = hdr.ex.a_entry & 0xffffff; 328 p = PTOV(addr); 329 fs_off = PAGE_SIZE; 330 if (xfsread(ino, p, hdr.ex.a_text)) 331 return; 332 p += roundup2(hdr.ex.a_text, PAGE_SIZE); 333 if (xfsread(ino, p, hdr.ex.a_data)) 334 return; 335 p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE); 336 bootinfo.bi_symtab = VTOP(p); 337 memcpy(p, (char *)&hdr.ex.a_syms, sizeof(hdr.ex.a_syms)); 338 p += sizeof(hdr.ex.a_syms); 339 if (hdr.ex.a_syms) { 340 if (xfsread(ino, p, hdr.ex.a_syms)) 341 return; 342 p += hdr.ex.a_syms; 343 if (xfsread(ino, p, sizeof(int))) 344 return; 345 x = *(uint32_t *)p; 346 p += sizeof(int); 347 x -= sizeof(int); 348 if (xfsread(ino, p, x)) 349 return; 350 p += x; 351 } 352 } else { 353 fs_off = hdr.eh.e_phoff; 354 for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) { 355 if (xfsread(ino, ep + j, sizeof(ep[0]))) 356 return; 357 if (ep[j].p_type == PT_LOAD) 358 j++; 359 } 360 for (i = 0; i < 2; i++) { 361 p = PTOV(ep[i].p_paddr & 0xffffff); 362 fs_off = ep[i].p_offset; 363 if (xfsread(ino, p, ep[i].p_filesz)) 364 return; 365 } 366 p += roundup2(ep[1].p_memsz, PAGE_SIZE); 367 bootinfo.bi_symtab = VTOP(p); 368 if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { 369 fs_off = hdr.eh.e_shoff + sizeof(es[0]) * 370 (hdr.eh.e_shstrndx + 1); 371 if (xfsread(ino, &es, sizeof(es))) 372 return; 373 for (i = 0; i < 2; i++) { 374 memcpy(p, (char *)&es[i].sh_size, sizeof(es[i].sh_size)); 375 p += sizeof(es[i].sh_size); 376 fs_off = es[i].sh_offset; 377 if (xfsread(ino, p, es[i].sh_size)) 378 return; 379 p += es[i].sh_size; 380 } 381 } 382 addr = hdr.eh.e_entry & 0xffffff; 383 } 384 bootinfo.bi_esymtab = VTOP(p); 385 bootinfo.bi_kernelname = VTOP(fname); 386 bootinfo.bi_bios_dev = dsk.drive; 387 __exec((caddr_t)addr, opts & RBX_MASK, 388 MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part), 389 0, 0, 0, VTOP(&bootinfo)); 390} 391 392static int 393parse(char *arg) 394{ 395 char *p, *q; 396 int drv, c, i; 397 398 while ((c = *arg++)) { 399 if (c == ' ' || c == '\t' || c == '\n') 400 continue; 401 for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++); 402 if (*p) 403 *p++ = 0; 404 if (c == '-') { 405 while ((c = *arg++)) { 406 for (i = 0; c != optstr[i]; i++) 407 if (i == NOPT - 1) 408 return -1; 409 opts ^= 1 << flags[i]; 410 } 411 if (opts & 1 << RBX_PROBEKBD) { 412 i = *(uint8_t *)PTOV(0x496) & 0x10; 413 /* printf("Keyboard: %s\n", i ? "yes" : "no"); */ 414 if (!i) 415 opts |= 1 << RBX_DUAL | 1 << RBX_SERIAL; 416 opts &= ~(1 << RBX_PROBEKBD); 417 } 418 ioctrl = opts & 1 << RBX_DUAL ? (IO_SERIAL|IO_KEYBOARD) : 419 opts & 1 << RBX_SERIAL ? IO_SERIAL : IO_KEYBOARD; 420 if (ioctrl & IO_SERIAL) 421 sio_init(); 422 } else { 423 for (q = arg--; *q && *q != '('; q++); 424 if (*q) { 425 drv = -1; 426 if (arg[1] == ':') { 427 if (*arg < '0' || *arg > '9') 428 return -1; 429 drv = *arg - '0'; 430 arg += 2; 431 } 432 if (q - arg != 2) 433 return -1; 434 for (i = 0; arg[0] != dev_nm[i][0] || 435 arg[1] != dev_nm[i][1]; i++) 436 if (i == NDEV - 1) 437 return -1; 438 dsk.type = i; 439 arg += 3; 440 if (arg[1] != ',' || *arg < '0' || *arg > '9') 441 return -1; 442 dsk.unit = *arg - '0'; 443 arg += 2; 444 dsk.slice = WHOLE_DISK_SLICE; 445 if (arg[1] == ',') { 446 if (*arg < '0' || *arg > '0' + NDOSPART) 447 return -1; 448 if ((dsk.slice = *arg - '0')) 449 dsk.slice++; 450 arg += 2; 451 } 452 if (arg[1] != ')' || *arg < 'a' || *arg > 'p') 453 return -1; 454 dsk.part = *arg - 'a'; 455 arg += 2; 456 if (drv == -1) 457 drv = dsk.unit; 458 dsk.drive = (dsk.type <= TYPE_MAXHARD 459 ? DRV_HARD : 0) + drv; 460 dsk_meta = 0; 461 fsread(0, NULL, 0); 462 } 463 if ((i = p - arg - !*(p - 1))) { 464 if (i >= sizeof(kname)) 465 return -1; 466 memcpy(kname, arg, i + 1); 467 } 468 } 469 arg = p; 470 } 471 return 0; 472} 473 474static int 475dskread(void *buf, unsigned lba, unsigned nblk) 476{ 477 struct dos_partition *dp; 478 struct disklabel *d; 479 char *sec; 480 unsigned sl, i; 481 482 if (!dsk_meta) { 483 sec = dmadat->secbuf; 484 dsk.start = 0; 485 if (drvread(sec, DOSBBSECTOR, 1)) 486 return -1; 487 dp = (void *)(sec + DOSPARTOFF); 488 sl = dsk.slice; 489 if (sl < BASE_SLICE) { 490 for (i = 0; i < NDOSPART; i++) 491 if (dp[i].dp_typ == DOSPTYP_386BSD && 492 (dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) { 493 sl = BASE_SLICE + i; 494 if (dp[i].dp_flag & 0x80 || 495 dsk.slice == COMPATIBILITY_SLICE) 496 break; 497 } 498 if (dsk.slice == WHOLE_DISK_SLICE) 499 dsk.slice = sl; 500 } 501 if (sl != WHOLE_DISK_SLICE) { 502 if (sl != COMPATIBILITY_SLICE) 503 dp += sl - BASE_SLICE; 504 if (dp->dp_typ != DOSPTYP_386BSD) { 505 printf("Invalid %s\n", "slice"); 506 return -1; 507 } 508 dsk.start = dp->dp_start; 509 } 510 if (drvread(sec, dsk.start + LABELSECTOR, 1)) 511 return -1; 512 d = (void *)(sec + LABELOFFSET); 513 if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) { 514 if (dsk.part != RAW_PART) { 515 printf("Invalid %s\n", "label"); 516 return -1; 517 } 518 } else { 519 if (!dsk.init) { 520 if (d->d_type == DTYPE_SCSI) 521 dsk.type = TYPE_DA; 522 dsk.init++; 523 } 524 if (dsk.part >= d->d_npartitions || 525 !d->d_partitions[dsk.part].p_size) { 526 printf("Invalid %s\n", "partition"); 527 return -1; 528 } 529 dsk.start += d->d_partitions[dsk.part].p_offset; 530 dsk.start -= d->d_partitions[RAW_PART].p_offset; 531 } 532 } 533 return drvread(buf, dsk.start + lba, nblk); 534} 535 536static int 537printf(const char *fmt,...) 538{ 539 static const char digits[16] = "0123456789abcdef"; 540 va_list ap; 541 char buf[10]; 542 char *s; 543 unsigned r, u; 544 int c; 545 546 va_start(ap, fmt); 547 while ((c = *fmt++)) { 548 if (c == '%') { 549 c = *fmt++; 550 switch (c) { 551 case 'c': 552 putchar(va_arg(ap, int)); 553 continue; 554 case 's': 555 for (s = va_arg(ap, char *); *s; s++) 556 putchar(*s); 557 continue; 558 case 'u': 559 case 'x': 560 r = c == 'u' ? 10U : 16U; 561 u = va_arg(ap, unsigned); 562 s = buf; 563 do 564 *s++ = digits[u % r]; 565 while (u /= r); 566 while (--s >= buf) 567 putchar(*s); 568 continue; 569 } 570 } 571 putchar(c); 572 } 573 va_end(ap); 574 return 0; 575} 576 577static int 578putchar(int c) 579{ 580 if (c == '\n') 581 xputc('\r'); 582 return xputc(c); 583} 584 585static uint32_t 586memsize(int type) 587{ 588 v86.addr = type; 589 v86.eax = 0x8800; 590 v86int(); 591 return v86.eax; 592} 593 594static int 595drvread(void *buf, unsigned lba, unsigned nblk) 596{ 597 static unsigned c = 0x2d5c7c2f; 598 599 printf("%c\b", c = c << 8 | c >> 24); 600 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 601 v86.addr = XREADORG; /* call to xread in boot1 */ 602 v86.es = VTOPSEG(buf); 603 v86.eax = lba; 604 v86.ebx = VTOPOFF(buf); 605 v86.ecx = lba >> 16; 606 v86.edx = nblk << 8 | dsk.drive; 607 v86int(); 608 v86.ctl = V86_FLAGS; 609 if (V86_CY(v86.efl)) { 610 printf("Disk error 0x%x (lba=0x%x)\n", v86.eax >> 8 & 0xff, 611 lba); 612 return -1; 613 } 614 return 0; 615} 616 617static int 618keyhit(unsigned ticks) 619{ 620 uint32_t t0, t1; 621 622 if (opts & 1 << RBX_NOINTR) 623 return 0; 624 t0 = 0; 625 for (;;) { 626 if (xgetc(1)) 627 return 1; 628 t1 = *(uint32_t *)PTOV(0x46c); 629 if (!t0) 630 t0 = t1; 631 if (t1 < t0 || t1 >= t0 + ticks) 632 return 0; 633 } 634} 635 636static int 637xputc(int c) 638{ 639 if (ioctrl & IO_KEYBOARD) 640 putc(c); 641 if (ioctrl & IO_SERIAL) 642 sio_putc(c); 643 return c; 644} 645 646static int 647xgetc(int fn) 648{ 649 if (opts & 1 << RBX_NOINTR) 650 return 0; 651 for (;;) { 652 if (ioctrl & IO_KEYBOARD && getc(1)) 653 return fn ? 1 : getc(0); 654 if (ioctrl & IO_SERIAL && sio_ischar()) 655 return fn ? 1 : sio_getc(); 656 if (fn) 657 return 0; 658 } 659} 660 661static int 662getc(int fn) 663{ 664 v86.addr = 0x16; 665 v86.eax = fn << 8; 666 v86int(); 667 return fn == 0 ? v86.eax & 0xff : !V86_ZR(v86.efl); 668}
| 277 "Default: %u:%s(%u,%c)%s\n" 278 "boot: ", 279 dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, 280 'a' + dsk.part, kname); 281 if (ioctrl & IO_SERIAL) 282 sio_flush(); 283 if (!autoboot || keyhit(5*SECOND)) 284 getstr(cmd, sizeof(cmd)); 285 else 286 putchar('\n'); 287 autoboot = 0; 288 if (parse(cmd)) 289 putchar('\a'); 290 else 291 load(kname); 292 } 293} 294 295/* XXX - Needed for btxld to link the boot2 binary; do not remove. */ 296void 297exit(int x) 298{ 299} 300 301static void 302load(const char *fname) 303{ 304 union { 305 struct exec ex; 306 Elf32_Ehdr eh; 307 } hdr; 308 Elf32_Phdr ep[2]; 309 Elf32_Shdr es[2]; 310 caddr_t p; 311 ino_t ino; 312 uint32_t addr, x; 313 int fmt, i, j; 314 315 if (!(ino = lookup(fname))) { 316 if (!ls) 317 printf("No %s\n", fname); 318 return; 319 } 320 if (xfsread(ino, &hdr, sizeof(hdr))) 321 return; 322 if (N_GETMAGIC(hdr.ex) == ZMAGIC) 323 fmt = 0; 324 else if (IS_ELF(hdr.eh)) 325 fmt = 1; 326 else { 327 printf("Invalid %s\n", "format"); 328 return; 329 } 330 if (fmt == 0) { 331 addr = hdr.ex.a_entry & 0xffffff; 332 p = PTOV(addr); 333 fs_off = PAGE_SIZE; 334 if (xfsread(ino, p, hdr.ex.a_text)) 335 return; 336 p += roundup2(hdr.ex.a_text, PAGE_SIZE); 337 if (xfsread(ino, p, hdr.ex.a_data)) 338 return; 339 p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE); 340 bootinfo.bi_symtab = VTOP(p); 341 memcpy(p, (char *)&hdr.ex.a_syms, sizeof(hdr.ex.a_syms)); 342 p += sizeof(hdr.ex.a_syms); 343 if (hdr.ex.a_syms) { 344 if (xfsread(ino, p, hdr.ex.a_syms)) 345 return; 346 p += hdr.ex.a_syms; 347 if (xfsread(ino, p, sizeof(int))) 348 return; 349 x = *(uint32_t *)p; 350 p += sizeof(int); 351 x -= sizeof(int); 352 if (xfsread(ino, p, x)) 353 return; 354 p += x; 355 } 356 } else { 357 fs_off = hdr.eh.e_phoff; 358 for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) { 359 if (xfsread(ino, ep + j, sizeof(ep[0]))) 360 return; 361 if (ep[j].p_type == PT_LOAD) 362 j++; 363 } 364 for (i = 0; i < 2; i++) { 365 p = PTOV(ep[i].p_paddr & 0xffffff); 366 fs_off = ep[i].p_offset; 367 if (xfsread(ino, p, ep[i].p_filesz)) 368 return; 369 } 370 p += roundup2(ep[1].p_memsz, PAGE_SIZE); 371 bootinfo.bi_symtab = VTOP(p); 372 if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { 373 fs_off = hdr.eh.e_shoff + sizeof(es[0]) * 374 (hdr.eh.e_shstrndx + 1); 375 if (xfsread(ino, &es, sizeof(es))) 376 return; 377 for (i = 0; i < 2; i++) { 378 memcpy(p, (char *)&es[i].sh_size, sizeof(es[i].sh_size)); 379 p += sizeof(es[i].sh_size); 380 fs_off = es[i].sh_offset; 381 if (xfsread(ino, p, es[i].sh_size)) 382 return; 383 p += es[i].sh_size; 384 } 385 } 386 addr = hdr.eh.e_entry & 0xffffff; 387 } 388 bootinfo.bi_esymtab = VTOP(p); 389 bootinfo.bi_kernelname = VTOP(fname); 390 bootinfo.bi_bios_dev = dsk.drive; 391 __exec((caddr_t)addr, opts & RBX_MASK, 392 MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part), 393 0, 0, 0, VTOP(&bootinfo)); 394} 395 396static int 397parse(char *arg) 398{ 399 char *p, *q; 400 int drv, c, i; 401 402 while ((c = *arg++)) { 403 if (c == ' ' || c == '\t' || c == '\n') 404 continue; 405 for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++); 406 if (*p) 407 *p++ = 0; 408 if (c == '-') { 409 while ((c = *arg++)) { 410 for (i = 0; c != optstr[i]; i++) 411 if (i == NOPT - 1) 412 return -1; 413 opts ^= 1 << flags[i]; 414 } 415 if (opts & 1 << RBX_PROBEKBD) { 416 i = *(uint8_t *)PTOV(0x496) & 0x10; 417 /* printf("Keyboard: %s\n", i ? "yes" : "no"); */ 418 if (!i) 419 opts |= 1 << RBX_DUAL | 1 << RBX_SERIAL; 420 opts &= ~(1 << RBX_PROBEKBD); 421 } 422 ioctrl = opts & 1 << RBX_DUAL ? (IO_SERIAL|IO_KEYBOARD) : 423 opts & 1 << RBX_SERIAL ? IO_SERIAL : IO_KEYBOARD; 424 if (ioctrl & IO_SERIAL) 425 sio_init(); 426 } else { 427 for (q = arg--; *q && *q != '('; q++); 428 if (*q) { 429 drv = -1; 430 if (arg[1] == ':') { 431 if (*arg < '0' || *arg > '9') 432 return -1; 433 drv = *arg - '0'; 434 arg += 2; 435 } 436 if (q - arg != 2) 437 return -1; 438 for (i = 0; arg[0] != dev_nm[i][0] || 439 arg[1] != dev_nm[i][1]; i++) 440 if (i == NDEV - 1) 441 return -1; 442 dsk.type = i; 443 arg += 3; 444 if (arg[1] != ',' || *arg < '0' || *arg > '9') 445 return -1; 446 dsk.unit = *arg - '0'; 447 arg += 2; 448 dsk.slice = WHOLE_DISK_SLICE; 449 if (arg[1] == ',') { 450 if (*arg < '0' || *arg > '0' + NDOSPART) 451 return -1; 452 if ((dsk.slice = *arg - '0')) 453 dsk.slice++; 454 arg += 2; 455 } 456 if (arg[1] != ')' || *arg < 'a' || *arg > 'p') 457 return -1; 458 dsk.part = *arg - 'a'; 459 arg += 2; 460 if (drv == -1) 461 drv = dsk.unit; 462 dsk.drive = (dsk.type <= TYPE_MAXHARD 463 ? DRV_HARD : 0) + drv; 464 dsk_meta = 0; 465 fsread(0, NULL, 0); 466 } 467 if ((i = p - arg - !*(p - 1))) { 468 if (i >= sizeof(kname)) 469 return -1; 470 memcpy(kname, arg, i + 1); 471 } 472 } 473 arg = p; 474 } 475 return 0; 476} 477 478static int 479dskread(void *buf, unsigned lba, unsigned nblk) 480{ 481 struct dos_partition *dp; 482 struct disklabel *d; 483 char *sec; 484 unsigned sl, i; 485 486 if (!dsk_meta) { 487 sec = dmadat->secbuf; 488 dsk.start = 0; 489 if (drvread(sec, DOSBBSECTOR, 1)) 490 return -1; 491 dp = (void *)(sec + DOSPARTOFF); 492 sl = dsk.slice; 493 if (sl < BASE_SLICE) { 494 for (i = 0; i < NDOSPART; i++) 495 if (dp[i].dp_typ == DOSPTYP_386BSD && 496 (dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) { 497 sl = BASE_SLICE + i; 498 if (dp[i].dp_flag & 0x80 || 499 dsk.slice == COMPATIBILITY_SLICE) 500 break; 501 } 502 if (dsk.slice == WHOLE_DISK_SLICE) 503 dsk.slice = sl; 504 } 505 if (sl != WHOLE_DISK_SLICE) { 506 if (sl != COMPATIBILITY_SLICE) 507 dp += sl - BASE_SLICE; 508 if (dp->dp_typ != DOSPTYP_386BSD) { 509 printf("Invalid %s\n", "slice"); 510 return -1; 511 } 512 dsk.start = dp->dp_start; 513 } 514 if (drvread(sec, dsk.start + LABELSECTOR, 1)) 515 return -1; 516 d = (void *)(sec + LABELOFFSET); 517 if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) { 518 if (dsk.part != RAW_PART) { 519 printf("Invalid %s\n", "label"); 520 return -1; 521 } 522 } else { 523 if (!dsk.init) { 524 if (d->d_type == DTYPE_SCSI) 525 dsk.type = TYPE_DA; 526 dsk.init++; 527 } 528 if (dsk.part >= d->d_npartitions || 529 !d->d_partitions[dsk.part].p_size) { 530 printf("Invalid %s\n", "partition"); 531 return -1; 532 } 533 dsk.start += d->d_partitions[dsk.part].p_offset; 534 dsk.start -= d->d_partitions[RAW_PART].p_offset; 535 } 536 } 537 return drvread(buf, dsk.start + lba, nblk); 538} 539 540static int 541printf(const char *fmt,...) 542{ 543 static const char digits[16] = "0123456789abcdef"; 544 va_list ap; 545 char buf[10]; 546 char *s; 547 unsigned r, u; 548 int c; 549 550 va_start(ap, fmt); 551 while ((c = *fmt++)) { 552 if (c == '%') { 553 c = *fmt++; 554 switch (c) { 555 case 'c': 556 putchar(va_arg(ap, int)); 557 continue; 558 case 's': 559 for (s = va_arg(ap, char *); *s; s++) 560 putchar(*s); 561 continue; 562 case 'u': 563 case 'x': 564 r = c == 'u' ? 10U : 16U; 565 u = va_arg(ap, unsigned); 566 s = buf; 567 do 568 *s++ = digits[u % r]; 569 while (u /= r); 570 while (--s >= buf) 571 putchar(*s); 572 continue; 573 } 574 } 575 putchar(c); 576 } 577 va_end(ap); 578 return 0; 579} 580 581static int 582putchar(int c) 583{ 584 if (c == '\n') 585 xputc('\r'); 586 return xputc(c); 587} 588 589static uint32_t 590memsize(int type) 591{ 592 v86.addr = type; 593 v86.eax = 0x8800; 594 v86int(); 595 return v86.eax; 596} 597 598static int 599drvread(void *buf, unsigned lba, unsigned nblk) 600{ 601 static unsigned c = 0x2d5c7c2f; 602 603 printf("%c\b", c = c << 8 | c >> 24); 604 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 605 v86.addr = XREADORG; /* call to xread in boot1 */ 606 v86.es = VTOPSEG(buf); 607 v86.eax = lba; 608 v86.ebx = VTOPOFF(buf); 609 v86.ecx = lba >> 16; 610 v86.edx = nblk << 8 | dsk.drive; 611 v86int(); 612 v86.ctl = V86_FLAGS; 613 if (V86_CY(v86.efl)) { 614 printf("Disk error 0x%x (lba=0x%x)\n", v86.eax >> 8 & 0xff, 615 lba); 616 return -1; 617 } 618 return 0; 619} 620 621static int 622keyhit(unsigned ticks) 623{ 624 uint32_t t0, t1; 625 626 if (opts & 1 << RBX_NOINTR) 627 return 0; 628 t0 = 0; 629 for (;;) { 630 if (xgetc(1)) 631 return 1; 632 t1 = *(uint32_t *)PTOV(0x46c); 633 if (!t0) 634 t0 = t1; 635 if (t1 < t0 || t1 >= t0 + ticks) 636 return 0; 637 } 638} 639 640static int 641xputc(int c) 642{ 643 if (ioctrl & IO_KEYBOARD) 644 putc(c); 645 if (ioctrl & IO_SERIAL) 646 sio_putc(c); 647 return c; 648} 649 650static int 651xgetc(int fn) 652{ 653 if (opts & 1 << RBX_NOINTR) 654 return 0; 655 for (;;) { 656 if (ioctrl & IO_KEYBOARD && getc(1)) 657 return fn ? 1 : getc(0); 658 if (ioctrl & IO_SERIAL && sio_ischar()) 659 return fn ? 1 : sio_getc(); 660 if (fn) 661 return 0; 662 } 663} 664 665static int 666getc(int fn) 667{ 668 v86.addr = 0x16; 669 v86.eax = fn << 8; 670 v86int(); 671 return fn == 0 ? v86.eax & 0xff : !V86_ZR(v86.efl); 672}
|