1/* 2 * Copyright (c) 1998 Robert Nordier 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are freely 6 * permitted provided that the above copyright notice and this 7 * paragraph and the following disclaimer are duplicated in all 8 * such forms. 9 * 10 * This software is provided "AS IS" and without any express or 11 * implied warranties, including, without limitation, the implied 12 * warranties of merchantability and fitness for a particular 13 * purpose. 14 */ 15 16/*
| 1/* 2 * Copyright (c) 1998 Robert Nordier 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are freely 6 * permitted provided that the above copyright notice and this 7 * paragraph and the following disclaimer are duplicated in all 8 * such forms. 9 * 10 * This software is provided "AS IS" and without any express or 11 * implied warranties, including, without limitation, the implied 12 * warranties of merchantability and fitness for a particular 13 * purpose. 14 */ 15 16/*
|
17 * $Id: boot2.c,v 1.1.1.1 1998/10/12 21:16:26 rnordier Exp $
| 17 * $Id: boot2.c,v 1.2 1998/10/13 17:41:06 rnordier Exp $
|
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/dirent.h> 25#include <machine/bootinfo.h> 26 27#include <ufs/ffs/fs.h> 28#include <ufs/ufs/dinode.h> 29 30#include <stdarg.h> 31 32#include <a.out.h> 33#include <elf.h> 34 35#include <btxv86.h> 36 37#define RBX_ASKNAME 0x0 /* -a */ 38#define RBX_SINGLE 0x1 /* -s */ 39#define RBX_DFLTROOT 0x5 /* -r */ 40#define RBX_KDB 0x6 /* -d */ 41#define RBX_CONFIG 0xa /* -c */ 42#define RBX_VERBOSE 0xb /* -v */ 43#define RBX_CDROM 0xd /* -C */ 44#define RBX_GDB 0xf /* -g */ 45 46#define PATH_CONFIG "/boot.config" 47#define PATH_BOOT3 "/boot/loader" 48#define PATH_KERNEL "/kernel" 49#define PATH_HELP "boot.help" 50 51#define ARGS 0x800 52#define NOPT 8 53#define BSIZEMAX 8192 54#define NDEV 3 55#define MEM_BASE 0x12 56#define MEM_EXT 0x15 57#define V86_CY(x) ((x) & 1) 58#define V86_ZR(x) ((x) & 0x40) 59 60#define DRV_HARD 0x80 61#define DRV_MASK 0x7f 62 63#define MAJ_WD 0
| 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/dirent.h> 25#include <machine/bootinfo.h> 26 27#include <ufs/ffs/fs.h> 28#include <ufs/ufs/dinode.h> 29 30#include <stdarg.h> 31 32#include <a.out.h> 33#include <elf.h> 34 35#include <btxv86.h> 36 37#define RBX_ASKNAME 0x0 /* -a */ 38#define RBX_SINGLE 0x1 /* -s */ 39#define RBX_DFLTROOT 0x5 /* -r */ 40#define RBX_KDB 0x6 /* -d */ 41#define RBX_CONFIG 0xa /* -c */ 42#define RBX_VERBOSE 0xb /* -v */ 43#define RBX_CDROM 0xd /* -C */ 44#define RBX_GDB 0xf /* -g */ 45 46#define PATH_CONFIG "/boot.config" 47#define PATH_BOOT3 "/boot/loader" 48#define PATH_KERNEL "/kernel" 49#define PATH_HELP "boot.help" 50 51#define ARGS 0x800 52#define NOPT 8 53#define BSIZEMAX 8192 54#define NDEV 3 55#define MEM_BASE 0x12 56#define MEM_EXT 0x15 57#define V86_CY(x) ((x) & 1) 58#define V86_ZR(x) ((x) & 0x40) 59 60#define DRV_HARD 0x80 61#define DRV_MASK 0x7f 62 63#define MAJ_WD 0
|
64#define MAJ_WFD 1
| 64#define MAJ_WFD 1
|
65#define MAJ_FD 2 66#define MAJ_DA 4 67 68extern uint32_t _end; 69 70static const char optstr[NOPT] = "aCcdgrsv"; 71static const unsigned char flags[NOPT] = { 72 RBX_ASKNAME, 73 RBX_CDROM, 74 RBX_CONFIG, 75 RBX_KDB, 76 RBX_GDB, 77 RBX_DFLTROOT, 78 RBX_SINGLE, 79 RBX_VERBOSE 80}; 81 82static const char *const dev_nm[] = {"wd", " ", "fd", " ", "da"}; 83 84static struct dsk { 85 unsigned drive; 86 unsigned type; 87 unsigned unit; 88 unsigned slice; 89 unsigned part; 90 unsigned start; 91 int init; 92 int meta; 93} dsk; 94static char cmd[512]; 95static char kname[1024]; 96static char help[2048]; 97static uint32_t opts; 98static struct bootinfo bootinfo; 99static int ls; 100static uint32_t fs_off; 101 102void exit(int); 103static void load(const char *); 104static int parse(char *); 105static void readfile(const char *, void *, size_t); 106static ino_t lookup(const char *); 107static int fsfind(const char *, ino_t *); 108static ssize_t fsread(ino_t, void *, size_t); 109static int dskread(void *, unsigned, unsigned); 110static int printf(const char *,...); 111static void getstr(char *, int); 112static int putchar(int); 113static int getchar(void); 114static void *memcpy(void *, const void *, size_t); 115static int strcmp(const char *, const char *); 116static void *malloc(size_t); 117static uint32_t memsize(int); 118static uint32_t drvinfo(int); 119static int drvread(void *, unsigned, unsigned); 120static int keyhit(unsigned); 121static int putch(int); 122static int getch(void); 123 124int 125main(void) 126{ 127 int autoboot, helpon, i; 128 129 dsk.drive = *(uint8_t *)PTOV(ARGS); 130 dsk.type = dsk.drive & DRV_HARD ? MAJ_WD : MAJ_FD; 131 dsk.unit = dsk.drive & DRV_MASK; 132 dsk.slice = *(uint8_t *)PTOV(ARGS + 1) + 1; 133 bootinfo.bi_version = BOOTINFO_VERSION; 134 bootinfo.bi_size = sizeof(bootinfo); 135 bootinfo.bi_basemem = memsize(MEM_BASE); 136 bootinfo.bi_extmem = memsize(MEM_EXT); 137 bootinfo.bi_memsizes_valid++; 138 for (i = 0; i < N_BIOS_GEOM; i++) 139 bootinfo.bi_bios_geom[i] = drvinfo(i); 140 autoboot = 2; 141 helpon = 1; 142 readfile(PATH_CONFIG, cmd, sizeof(cmd)); 143 if (parse(cmd)) 144 autoboot = 0; 145 else if (!*kname) { 146 if (autoboot == 2) { 147 memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3)); 148 if (!keyhit(0x37)) { 149 load(kname); 150 autoboot = 1; 151 } 152 } 153 if (autoboot == 1) 154 memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); 155 } 156 readfile(PATH_HELP, help, sizeof(help)); 157 for (;;) { 158 printf(" \n>> FreeBSD/i386 BOOT\n" 159 "Default: %u:%s(%u,%c)%s\n" 160 "%s" 161 "boot: ", 162 dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, 163 'a' + dsk.part, kname, helpon ? help : ""); 164 if (!autoboot || keyhit(0x5a)) 165 getstr(cmd, sizeof(cmd)); 166 autoboot = helpon = 0; 167 if (parse(cmd)) 168 helpon = 1; 169 else 170 load(kname); 171 } 172} 173 174void 175exit(int x) 176{ 177} 178 179static void 180load(const char *fname) 181{ 182 union { 183 struct exec ex; 184 Elf32_Ehdr eh; 185 } hdr; 186 Elf32_Phdr ep[2]; 187 Elf32_Shdr es[2]; 188 caddr_t p; 189 ino_t ino; 190 uint32_t addr, x; 191 int fmt, i, j; 192 193 if (!(ino = lookup(fname)) && !ls) { 194 printf("No `%s'\n", fname); 195 return; 196 } 197 if (fsread(ino, &hdr, sizeof(hdr)) != sizeof(hdr)) 198 return; 199 if (N_GETMAGIC(hdr.ex) == ZMAGIC) 200 fmt = 0; 201 else if (IS_ELF(hdr.eh)) 202 fmt = 1; 203 else { 204 printf("Invalid %s\n", "format"); 205 return; 206 } 207 if (fmt == 0) { 208 addr = hdr.ex.a_entry & 0xffffff; 209 p = PTOV(addr); 210 printf("%s=0x%x ", "text", (unsigned)hdr.ex.a_text); 211 fs_off = PAGE_SIZE; 212 if (fsread(ino, p, hdr.ex.a_text) != hdr.ex.a_text) 213 return; 214 p += roundup2(hdr.ex.a_text, PAGE_SIZE); 215 printf("%s=0x%x ", "data", (unsigned)hdr.ex.a_data); 216 if (fsread(ino, p, hdr.ex.a_data) != hdr.ex.a_data) 217 return; 218 p += hdr.ex.a_data; 219 printf("%s=0x%x ", "bss", (unsigned)hdr.ex.a_bss); 220 p += roundup2(hdr.ex.a_bss, PAGE_SIZE); 221 bootinfo.bi_symtab = VTOP(p); 222 memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms)); 223 p += sizeof(hdr.ex.a_syms); 224 printf("symbols=["); 225 printf("+0x%x", (unsigned)hdr.ex.a_syms); 226 if (hdr.ex.a_syms) { 227 if (fsread(ino, p, hdr.ex.a_syms) != hdr.ex.a_syms) 228 return; 229 p += hdr.ex.a_syms; 230 if (fsread(ino, p, sizeof(int)) != sizeof(int)) 231 return; 232 x = *(uint32_t *)p; 233 p += sizeof(int); 234 x -= sizeof(int); 235 printf("+0x%x", x); 236 if (fsread(ino, p, x) != x) 237 return; 238 p += x; 239 } 240 } else { 241 fs_off = hdr.eh.e_phoff; 242 for (j = i = 0; i < hdr.eh.e_phoff && j < 2; i++) { 243 if (fsread(ino, ep + j, sizeof(ep[0])) != sizeof(ep[0])) 244 return; 245 if (ep[j].p_type == PT_LOAD) 246 j++; 247 } 248 for (i = 0; i < 2; i++) { 249 p = PTOV(ep[i].p_paddr & 0xffffff); 250 printf("%s=0x%x ", !i ? "text" : "data", ep[i].p_filesz); 251 fs_off = ep[i].p_offset; 252 if (fsread(ino, p, ep[i].p_filesz) != ep[i].p_filesz) 253 return; 254 } 255 printf("%s=0x%x ", "bss", ep[1].p_memsz - ep[1].p_filesz); 256 p += roundup2(ep[1].p_memsz, PAGE_SIZE); 257 bootinfo.bi_symtab = VTOP(p); 258 printf("symbols=["); 259 if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { 260 fs_off = hdr.eh.e_shoff + sizeof(es[0]) * 261 (hdr.eh.e_shstrndx + 1); 262 if (fsread(ino, &es, sizeof(es)) != sizeof(es)) 263 return; 264 for (i = 0; i < 2; i++) { 265 memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size)); 266 p += sizeof(es[i].sh_size); 267 printf("+0x%x", es[i].sh_size); 268 fs_off = es[i].sh_offset; 269 if (fsread(ino, p, es[i].sh_size) != es[i].sh_size) 270 return; 271 p += es[i].sh_size; 272 } 273 } 274 addr = hdr.eh.e_entry & 0xffffff; 275 } 276 bootinfo.bi_esymtab = VTOP(p); 277 printf("]\nentry=0x%x\n", addr); 278 bootinfo.bi_kernelname = VTOP(fname); 279 __exec((caddr_t)addr, RB_BOOTINFO | opts, 280 MAKEBOOTDEV(dsk.type, 0, dsk.slice, dsk.unit, dsk.part), 281 0, 0, 0, VTOP(&bootinfo)); 282} 283 284static int 285parse(char *arg) 286{ 287 char *p, *q; 288 int drv, c, i; 289 290 while ((c = *arg++)) { 291 if (c == ' ') 292 continue; 293 for (p = arg; *p && *p != '\n' && *p != ' '; p++); 294 if (*p) 295 *p++ = 0; 296 if (c == '-') 297 while ((c = *arg++)) { 298 for (i = 0; c != optstr[i]; i++) 299 if (i == NOPT - 1) 300 return -1; 301 opts |= 1 << flags[i]; 302 } 303 else { 304 for (q = arg--; *q && *q != '('; q++); 305 if (*q) { 306 drv = -1; 307 if (arg[1] == ':') { 308 if (*arg < '0' || *arg > '9') 309 return -1; 310 drv = *arg - '0'; 311 arg += 2; 312 } 313 if (q - arg != 2) 314 return -1; 315 for (i = 0; arg[0] != dev_nm[i][0] ||
| 65#define MAJ_FD 2 66#define MAJ_DA 4 67 68extern uint32_t _end; 69 70static const char optstr[NOPT] = "aCcdgrsv"; 71static const unsigned char flags[NOPT] = { 72 RBX_ASKNAME, 73 RBX_CDROM, 74 RBX_CONFIG, 75 RBX_KDB, 76 RBX_GDB, 77 RBX_DFLTROOT, 78 RBX_SINGLE, 79 RBX_VERBOSE 80}; 81 82static const char *const dev_nm[] = {"wd", " ", "fd", " ", "da"}; 83 84static struct dsk { 85 unsigned drive; 86 unsigned type; 87 unsigned unit; 88 unsigned slice; 89 unsigned part; 90 unsigned start; 91 int init; 92 int meta; 93} dsk; 94static char cmd[512]; 95static char kname[1024]; 96static char help[2048]; 97static uint32_t opts; 98static struct bootinfo bootinfo; 99static int ls; 100static uint32_t fs_off; 101 102void exit(int); 103static void load(const char *); 104static int parse(char *); 105static void readfile(const char *, void *, size_t); 106static ino_t lookup(const char *); 107static int fsfind(const char *, ino_t *); 108static ssize_t fsread(ino_t, void *, size_t); 109static int dskread(void *, unsigned, unsigned); 110static int printf(const char *,...); 111static void getstr(char *, int); 112static int putchar(int); 113static int getchar(void); 114static void *memcpy(void *, const void *, size_t); 115static int strcmp(const char *, const char *); 116static void *malloc(size_t); 117static uint32_t memsize(int); 118static uint32_t drvinfo(int); 119static int drvread(void *, unsigned, unsigned); 120static int keyhit(unsigned); 121static int putch(int); 122static int getch(void); 123 124int 125main(void) 126{ 127 int autoboot, helpon, i; 128 129 dsk.drive = *(uint8_t *)PTOV(ARGS); 130 dsk.type = dsk.drive & DRV_HARD ? MAJ_WD : MAJ_FD; 131 dsk.unit = dsk.drive & DRV_MASK; 132 dsk.slice = *(uint8_t *)PTOV(ARGS + 1) + 1; 133 bootinfo.bi_version = BOOTINFO_VERSION; 134 bootinfo.bi_size = sizeof(bootinfo); 135 bootinfo.bi_basemem = memsize(MEM_BASE); 136 bootinfo.bi_extmem = memsize(MEM_EXT); 137 bootinfo.bi_memsizes_valid++; 138 for (i = 0; i < N_BIOS_GEOM; i++) 139 bootinfo.bi_bios_geom[i] = drvinfo(i); 140 autoboot = 2; 141 helpon = 1; 142 readfile(PATH_CONFIG, cmd, sizeof(cmd)); 143 if (parse(cmd)) 144 autoboot = 0; 145 else if (!*kname) { 146 if (autoboot == 2) { 147 memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3)); 148 if (!keyhit(0x37)) { 149 load(kname); 150 autoboot = 1; 151 } 152 } 153 if (autoboot == 1) 154 memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); 155 } 156 readfile(PATH_HELP, help, sizeof(help)); 157 for (;;) { 158 printf(" \n>> FreeBSD/i386 BOOT\n" 159 "Default: %u:%s(%u,%c)%s\n" 160 "%s" 161 "boot: ", 162 dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, 163 'a' + dsk.part, kname, helpon ? help : ""); 164 if (!autoboot || keyhit(0x5a)) 165 getstr(cmd, sizeof(cmd)); 166 autoboot = helpon = 0; 167 if (parse(cmd)) 168 helpon = 1; 169 else 170 load(kname); 171 } 172} 173 174void 175exit(int x) 176{ 177} 178 179static void 180load(const char *fname) 181{ 182 union { 183 struct exec ex; 184 Elf32_Ehdr eh; 185 } hdr; 186 Elf32_Phdr ep[2]; 187 Elf32_Shdr es[2]; 188 caddr_t p; 189 ino_t ino; 190 uint32_t addr, x; 191 int fmt, i, j; 192 193 if (!(ino = lookup(fname)) && !ls) { 194 printf("No `%s'\n", fname); 195 return; 196 } 197 if (fsread(ino, &hdr, sizeof(hdr)) != sizeof(hdr)) 198 return; 199 if (N_GETMAGIC(hdr.ex) == ZMAGIC) 200 fmt = 0; 201 else if (IS_ELF(hdr.eh)) 202 fmt = 1; 203 else { 204 printf("Invalid %s\n", "format"); 205 return; 206 } 207 if (fmt == 0) { 208 addr = hdr.ex.a_entry & 0xffffff; 209 p = PTOV(addr); 210 printf("%s=0x%x ", "text", (unsigned)hdr.ex.a_text); 211 fs_off = PAGE_SIZE; 212 if (fsread(ino, p, hdr.ex.a_text) != hdr.ex.a_text) 213 return; 214 p += roundup2(hdr.ex.a_text, PAGE_SIZE); 215 printf("%s=0x%x ", "data", (unsigned)hdr.ex.a_data); 216 if (fsread(ino, p, hdr.ex.a_data) != hdr.ex.a_data) 217 return; 218 p += hdr.ex.a_data; 219 printf("%s=0x%x ", "bss", (unsigned)hdr.ex.a_bss); 220 p += roundup2(hdr.ex.a_bss, PAGE_SIZE); 221 bootinfo.bi_symtab = VTOP(p); 222 memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms)); 223 p += sizeof(hdr.ex.a_syms); 224 printf("symbols=["); 225 printf("+0x%x", (unsigned)hdr.ex.a_syms); 226 if (hdr.ex.a_syms) { 227 if (fsread(ino, p, hdr.ex.a_syms) != hdr.ex.a_syms) 228 return; 229 p += hdr.ex.a_syms; 230 if (fsread(ino, p, sizeof(int)) != sizeof(int)) 231 return; 232 x = *(uint32_t *)p; 233 p += sizeof(int); 234 x -= sizeof(int); 235 printf("+0x%x", x); 236 if (fsread(ino, p, x) != x) 237 return; 238 p += x; 239 } 240 } else { 241 fs_off = hdr.eh.e_phoff; 242 for (j = i = 0; i < hdr.eh.e_phoff && j < 2; i++) { 243 if (fsread(ino, ep + j, sizeof(ep[0])) != sizeof(ep[0])) 244 return; 245 if (ep[j].p_type == PT_LOAD) 246 j++; 247 } 248 for (i = 0; i < 2; i++) { 249 p = PTOV(ep[i].p_paddr & 0xffffff); 250 printf("%s=0x%x ", !i ? "text" : "data", ep[i].p_filesz); 251 fs_off = ep[i].p_offset; 252 if (fsread(ino, p, ep[i].p_filesz) != ep[i].p_filesz) 253 return; 254 } 255 printf("%s=0x%x ", "bss", ep[1].p_memsz - ep[1].p_filesz); 256 p += roundup2(ep[1].p_memsz, PAGE_SIZE); 257 bootinfo.bi_symtab = VTOP(p); 258 printf("symbols=["); 259 if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { 260 fs_off = hdr.eh.e_shoff + sizeof(es[0]) * 261 (hdr.eh.e_shstrndx + 1); 262 if (fsread(ino, &es, sizeof(es)) != sizeof(es)) 263 return; 264 for (i = 0; i < 2; i++) { 265 memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size)); 266 p += sizeof(es[i].sh_size); 267 printf("+0x%x", es[i].sh_size); 268 fs_off = es[i].sh_offset; 269 if (fsread(ino, p, es[i].sh_size) != es[i].sh_size) 270 return; 271 p += es[i].sh_size; 272 } 273 } 274 addr = hdr.eh.e_entry & 0xffffff; 275 } 276 bootinfo.bi_esymtab = VTOP(p); 277 printf("]\nentry=0x%x\n", addr); 278 bootinfo.bi_kernelname = VTOP(fname); 279 __exec((caddr_t)addr, RB_BOOTINFO | opts, 280 MAKEBOOTDEV(dsk.type, 0, dsk.slice, dsk.unit, dsk.part), 281 0, 0, 0, VTOP(&bootinfo)); 282} 283 284static int 285parse(char *arg) 286{ 287 char *p, *q; 288 int drv, c, i; 289 290 while ((c = *arg++)) { 291 if (c == ' ') 292 continue; 293 for (p = arg; *p && *p != '\n' && *p != ' '; p++); 294 if (*p) 295 *p++ = 0; 296 if (c == '-') 297 while ((c = *arg++)) { 298 for (i = 0; c != optstr[i]; i++) 299 if (i == NOPT - 1) 300 return -1; 301 opts |= 1 << flags[i]; 302 } 303 else { 304 for (q = arg--; *q && *q != '('; q++); 305 if (*q) { 306 drv = -1; 307 if (arg[1] == ':') { 308 if (*arg < '0' || *arg > '9') 309 return -1; 310 drv = *arg - '0'; 311 arg += 2; 312 } 313 if (q - arg != 2) 314 return -1; 315 for (i = 0; arg[0] != dev_nm[i][0] ||
|
316 arg[1] != dev_nm[i][1]; i++)
| 316 arg[1] != dev_nm[i][1]; i++)
|
317 if (i == NDEV - 1) 318 return -1; 319 dsk.type = i; 320 arg += 3; 321 if (arg[1] != ',' || *arg < '0' || *arg > '9') 322 return -1; 323 dsk.unit = *arg - '0'; 324 arg += 2;
| 317 if (i == NDEV - 1) 318 return -1; 319 dsk.type = i; 320 arg += 3; 321 if (arg[1] != ',' || *arg < '0' || *arg > '9') 322 return -1; 323 dsk.unit = *arg - '0'; 324 arg += 2;
|
| 325 dsk.slice = WHOLE_DISK_SLICE;
|
325 if (arg[1] == ',') {
| 326 if (arg[1] == ',') {
|
326 if (*arg < '0' || *arg > '4')
| 327 if (*arg < '0' || *arg > '0' + NDOSPART)
|
327 return -1; 328 if ((dsk.slice = *arg - '0')) 329 dsk.slice++; 330 arg += 2; 331 } 332 if (arg[1] != ')' || *arg < 'a' || *arg > 'p') 333 return -1; 334 dsk.part = *arg - 'a'; 335 arg += 2; 336 if (drv == -1) 337 drv = dsk.unit; 338 dsk.drive = (dsk.type == MAJ_WD || 339 dsk.type == MAJ_DA ? DRV_HARD : 0) + drv; 340 dsk.meta = 0; 341 fsread(0, NULL, 0); 342 } 343 if ((i = p - arg - !*(p - 1))) { 344 if (i >= sizeof(kname)) 345 return -1; 346 memcpy(kname, arg, i + 1); 347 } 348 } 349 arg = p; 350 } 351 return 0; 352} 353 354static void 355readfile(const char *fname, void *buf, size_t size) 356{ 357 ino_t ino; 358 359 if ((ino = lookup(fname))) 360 fsread(ino, buf, size); 361} 362 363static ino_t 364lookup(const char *path) 365{ 366 char name[MAXNAMLEN + 1]; 367 const char *s; 368 ino_t ino; 369 ssize_t n; 370 int dt; 371 372 ino = ROOTINO; 373 dt = DT_DIR; 374 for (;;) { 375 if (*path == '/') 376 path++; 377 if (!*path) 378 break; 379 for (s = path; *s && *s != '/'; s++); 380 if ((n = s - path) > MAXNAMLEN) 381 return 0; 382 ls = *path == '?' && n == 1 && !*s; 383 memcpy(name, path, n); 384 name[n] = 0; 385 if ((dt = fsfind(name, &ino)) <= 0) 386 break; 387 path = s; 388 } 389 return dt == DT_REG ? ino : 0; 390} 391 392static int 393fsfind(const char *name, ino_t * ino) 394{ 395 char buf[DEV_BSIZE]; 396 struct dirent *d; 397 char *s; 398 ssize_t n; 399 400 fs_off = 0; 401 while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0) 402 for (s = buf; s < buf + DEV_BSIZE;) { 403 d = (void *)s; 404 if (ls) 405 printf("%s ", d->d_name); 406 else if (!strcmp(name, d->d_name)) { 407 *ino = d->d_fileno; 408 return d->d_type; 409 } 410 s += d->d_reclen; 411 } 412 if (n != -1 && ls) 413 putchar('\n'); 414 return 0; 415} 416 417static ssize_t 418fsread(ino_t inode, void *buf, size_t nbyte) 419{ 420 static struct fs fs; 421 static struct dinode din; 422 static char *blkbuf; 423 static ufs_daddr_t *indbuf; 424 static ino_t inomap; 425 static ufs_daddr_t blkmap, indmap; 426 static unsigned fsblks; 427 char *s; 428 ufs_daddr_t lbn, addr; 429 size_t n, nb, off; 430 431 if (!dsk.meta) { 432 if (!blkbuf) 433 blkbuf = malloc(BSIZEMAX); 434 inomap = 0; 435 if (dskread(blkbuf, SBOFF / DEV_BSIZE, SBSIZE / DEV_BSIZE)) 436 return -1; 437 memcpy(&fs, blkbuf, sizeof(fs)); 438 if (fs.fs_magic != FS_MAGIC) { 439 printf("Not ufs\n"); 440 return -1; 441 } 442 fsblks = fs.fs_bsize >> DEV_BSHIFT; 443 dsk.meta = 1; 444 } 445 if (!inode) 446 return 0; 447 if (inomap != inode) { 448 if (dskread(blkbuf, fsbtodb(&fs, ino_to_fsba(&fs, inode)), 449 fsblks)) 450 return -1; 451 din = ((struct dinode *)blkbuf)[inode % INOPB(&fs)]; 452 inomap = inode; 453 fs_off = 0; 454 blkmap = indmap = 0; 455 } 456 s = buf; 457 if (nbyte > (n = din.di_size - fs_off)) 458 nbyte = n; 459 nb = nbyte; 460 while (nb) { 461 lbn = lblkno(&fs, fs_off); 462 if (lbn < NDADDR) 463 addr = din.di_db[lbn]; 464 else { 465 if (indmap != din.di_ib[0]) { 466 if (!indbuf) 467 indbuf = malloc(BSIZEMAX); 468 if (dskread(indbuf, fsbtodb(&fs, din.di_ib[0]), 469 fsblks)) 470 return -1; 471 indmap = din.di_ib[0]; 472 } 473 addr = indbuf[(lbn - NDADDR) % NINDIR(&fs)]; 474 } 475 n = dblksize(&fs, &din, lbn); 476 if (blkmap != addr) { 477 if (dskread(blkbuf, fsbtodb(&fs, addr), n >> DEV_BSHIFT)) 478 return -1; 479 blkmap = addr; 480 } 481 off = blkoff(&fs, fs_off); 482 n -= off; 483 if (n > nb) 484 n = nb; 485 memcpy(s, blkbuf + off, n); 486 s += n; 487 fs_off += n; 488 nb -= n; 489 } 490 return nbyte; 491} 492 493static int 494dskread(void *buf, unsigned lba, unsigned nblk) 495{ 496 static char *sec; 497 struct dos_partition *dp; 498 struct disklabel *d; 499 unsigned sl, i; 500 501 if (!dsk.meta) { 502 if (!sec) 503 sec = malloc(DEV_BSIZE); 504 dsk.start = 0;
| 328 return -1; 329 if ((dsk.slice = *arg - '0')) 330 dsk.slice++; 331 arg += 2; 332 } 333 if (arg[1] != ')' || *arg < 'a' || *arg > 'p') 334 return -1; 335 dsk.part = *arg - 'a'; 336 arg += 2; 337 if (drv == -1) 338 drv = dsk.unit; 339 dsk.drive = (dsk.type == MAJ_WD || 340 dsk.type == MAJ_DA ? DRV_HARD : 0) + drv; 341 dsk.meta = 0; 342 fsread(0, NULL, 0); 343 } 344 if ((i = p - arg - !*(p - 1))) { 345 if (i >= sizeof(kname)) 346 return -1; 347 memcpy(kname, arg, i + 1); 348 } 349 } 350 arg = p; 351 } 352 return 0; 353} 354 355static void 356readfile(const char *fname, void *buf, size_t size) 357{ 358 ino_t ino; 359 360 if ((ino = lookup(fname))) 361 fsread(ino, buf, size); 362} 363 364static ino_t 365lookup(const char *path) 366{ 367 char name[MAXNAMLEN + 1]; 368 const char *s; 369 ino_t ino; 370 ssize_t n; 371 int dt; 372 373 ino = ROOTINO; 374 dt = DT_DIR; 375 for (;;) { 376 if (*path == '/') 377 path++; 378 if (!*path) 379 break; 380 for (s = path; *s && *s != '/'; s++); 381 if ((n = s - path) > MAXNAMLEN) 382 return 0; 383 ls = *path == '?' && n == 1 && !*s; 384 memcpy(name, path, n); 385 name[n] = 0; 386 if ((dt = fsfind(name, &ino)) <= 0) 387 break; 388 path = s; 389 } 390 return dt == DT_REG ? ino : 0; 391} 392 393static int 394fsfind(const char *name, ino_t * ino) 395{ 396 char buf[DEV_BSIZE]; 397 struct dirent *d; 398 char *s; 399 ssize_t n; 400 401 fs_off = 0; 402 while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0) 403 for (s = buf; s < buf + DEV_BSIZE;) { 404 d = (void *)s; 405 if (ls) 406 printf("%s ", d->d_name); 407 else if (!strcmp(name, d->d_name)) { 408 *ino = d->d_fileno; 409 return d->d_type; 410 } 411 s += d->d_reclen; 412 } 413 if (n != -1 && ls) 414 putchar('\n'); 415 return 0; 416} 417 418static ssize_t 419fsread(ino_t inode, void *buf, size_t nbyte) 420{ 421 static struct fs fs; 422 static struct dinode din; 423 static char *blkbuf; 424 static ufs_daddr_t *indbuf; 425 static ino_t inomap; 426 static ufs_daddr_t blkmap, indmap; 427 static unsigned fsblks; 428 char *s; 429 ufs_daddr_t lbn, addr; 430 size_t n, nb, off; 431 432 if (!dsk.meta) { 433 if (!blkbuf) 434 blkbuf = malloc(BSIZEMAX); 435 inomap = 0; 436 if (dskread(blkbuf, SBOFF / DEV_BSIZE, SBSIZE / DEV_BSIZE)) 437 return -1; 438 memcpy(&fs, blkbuf, sizeof(fs)); 439 if (fs.fs_magic != FS_MAGIC) { 440 printf("Not ufs\n"); 441 return -1; 442 } 443 fsblks = fs.fs_bsize >> DEV_BSHIFT; 444 dsk.meta = 1; 445 } 446 if (!inode) 447 return 0; 448 if (inomap != inode) { 449 if (dskread(blkbuf, fsbtodb(&fs, ino_to_fsba(&fs, inode)), 450 fsblks)) 451 return -1; 452 din = ((struct dinode *)blkbuf)[inode % INOPB(&fs)]; 453 inomap = inode; 454 fs_off = 0; 455 blkmap = indmap = 0; 456 } 457 s = buf; 458 if (nbyte > (n = din.di_size - fs_off)) 459 nbyte = n; 460 nb = nbyte; 461 while (nb) { 462 lbn = lblkno(&fs, fs_off); 463 if (lbn < NDADDR) 464 addr = din.di_db[lbn]; 465 else { 466 if (indmap != din.di_ib[0]) { 467 if (!indbuf) 468 indbuf = malloc(BSIZEMAX); 469 if (dskread(indbuf, fsbtodb(&fs, din.di_ib[0]), 470 fsblks)) 471 return -1; 472 indmap = din.di_ib[0]; 473 } 474 addr = indbuf[(lbn - NDADDR) % NINDIR(&fs)]; 475 } 476 n = dblksize(&fs, &din, lbn); 477 if (blkmap != addr) { 478 if (dskread(blkbuf, fsbtodb(&fs, addr), n >> DEV_BSHIFT)) 479 return -1; 480 blkmap = addr; 481 } 482 off = blkoff(&fs, fs_off); 483 n -= off; 484 if (n > nb) 485 n = nb; 486 memcpy(s, blkbuf + off, n); 487 s += n; 488 fs_off += n; 489 nb -= n; 490 } 491 return nbyte; 492} 493 494static int 495dskread(void *buf, unsigned lba, unsigned nblk) 496{ 497 static char *sec; 498 struct dos_partition *dp; 499 struct disklabel *d; 500 unsigned sl, i; 501 502 if (!dsk.meta) { 503 if (!sec) 504 sec = malloc(DEV_BSIZE); 505 dsk.start = 0;
|
| 506 if (drvread(sec, DOSBBSECTOR, 1)) 507 return -1; 508 dp = (void *)(sec + DOSPARTOFF);
|
505 sl = dsk.slice;
| 509 sl = dsk.slice;
|
| 510 if (sl < BASE_SLICE) { 511 for (i = 0; i < NDOSPART; i++) 512 if (dp[i].dp_typ == DOSPTYP_386BSD && 513 (dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) { 514 sl = BASE_SLICE + i; 515 if (dp[i].dp_flag & 0x80 || 516 dsk.slice == COMPATIBILITY_SLICE) 517 break; 518 } 519 if (dsk.slice == WHOLE_DISK_SLICE) 520 dsk.slice = sl; 521 }
|
506 if (sl != WHOLE_DISK_SLICE) {
| 522 if (sl != WHOLE_DISK_SLICE) {
|
507 if (drvread(sec, DOSBBSECTOR, 1)) 508 return -1; 509 dp = (void *)(sec + DOSPARTOFF); 510 if (sl == COMPATIBILITY_SLICE) 511 for (i = 0; i < NDOSPART; i++) 512 if (dp[i].dp_typ == DOSPTYP_386BSD && 513 (dp[i].dp_flag & 0x80 || 514 sl == COMPATIBILITY_SLICE)) 515 sl = BASE_SLICE + i;
| |
516 if (sl != COMPATIBILITY_SLICE) 517 dp += sl - BASE_SLICE; 518 if (dp->dp_typ != DOSPTYP_386BSD) { 519 printf("Invalid %s\n", "slice"); 520 return -1; 521 } 522 dsk.start = dp->dp_start; 523 }
| 523 if (sl != COMPATIBILITY_SLICE) 524 dp += sl - BASE_SLICE; 525 if (dp->dp_typ != DOSPTYP_386BSD) { 526 printf("Invalid %s\n", "slice"); 527 return -1; 528 } 529 dsk.start = dp->dp_start; 530 }
|
524 if (drvread(sec, dsk.start + LABELSECTOR, 1))
| 531 if (drvread(sec, dsk.start + LABELSECTOR, 1))
|
525 return -1; 526 d = (void *)(sec + LABELOFFSET); 527 if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) { 528 if (dsk.part != RAW_PART) {
| 532 return -1; 533 d = (void *)(sec + LABELOFFSET); 534 if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) { 535 if (dsk.part != RAW_PART) {
|
529 printf("Invalid %s\n", "label"); 530 return -1;
| 536 printf("Invalid %s\n", "label"); 537 return -1;
|
531 } 532 } else { 533 if (!dsk.init) {
| 538 } 539 } else { 540 if (!dsk.init) {
|
534 if (d->d_type == DTYPE_SCSI)
| 541 if (d->d_type == DTYPE_SCSI)
|
535 dsk.type = MAJ_DA; 536 dsk.init++; 537 } 538 if (dsk.part >= d->d_npartitions) { 539 printf("Invalid %s\n", "partition"); 540 return -1; 541 } 542 dsk.start = d->d_partitions[dsk.part].p_offset; 543 } 544 } 545 return drvread(buf, dsk.start + lba, nblk); 546} 547 548static int 549printf(const char *fmt,...) 550{ 551 static const char digits[16] = "0123456789abcdef"; 552 va_list ap; 553 char buf[10]; 554 char *s; 555 unsigned r, u; 556 int c; 557 558 va_start(ap, fmt); 559 while ((c = *fmt++)) { 560 if (c == '%') { 561 c = *fmt++; 562 switch (c) { 563 case 'c': 564 putchar(va_arg(ap, int)); 565 continue; 566 case 's': 567 for (s = va_arg(ap, char *); *s; s++) 568 putchar(*s); 569 continue; 570 case 'u': 571 case 'x': 572 r = c == 'u' ? 10U : 16U; 573 u = va_arg(ap, unsigned); 574 s = buf; 575 do 576 *s++ = digits[u % r]; 577 while (u /= r); 578 while (--s >= buf) 579 putchar(*s); 580 continue; 581 } 582 } 583 putchar(c); 584 } 585 va_end(ap); 586 return 0; 587} 588 589static void 590getstr(char *str, int size) 591{ 592 char *s; 593 int c; 594 595 s = str; 596 do { 597 switch (c = getchar()) { 598 case '\b': 599 if (s > str) 600 s--; 601 break; 602 case '\n': 603 *s = 0; 604 break; 605 default: 606 if (s - str < size - 1) 607 *s++ = c; 608 } 609 putchar(c); 610 } while (c != '\n'); 611} 612 613static int 614putchar(int c) 615{ 616 if (c == '\n') 617 putch('\r'); 618 return putch(c); 619} 620 621static int 622getchar(void) 623{ 624 int c; 625 626 c = getch(); 627 if (c == '\r') 628 c = '\n'; 629 return c; 630} 631 632static void * 633memcpy(void *dst, const void *src, size_t size) 634{ 635 const char *s; 636 char *d; 637 638 for (d = dst, s = src; size; size--) 639 *d++ = *s++; 640 return dst; 641} 642 643static int 644strcmp(const char *s1, const char *s2) 645{ 646 for (; *s1 == *s2 && *s1; s1++, s2++); 647 return (u_char)*s1 - (u_char)*s2; 648} 649 650static void * 651malloc(size_t size) 652{ 653 static uint32_t next; 654 void *p; 655 656 if (!next) 657 next = roundup2(__base + _end, 0x10000) - __base; 658 p = (void *)next; 659 next += size; 660 return p; 661} 662 663static uint32_t 664memsize(int type) 665{ 666 v86.ctl = V86_FLAGS; 667 v86.addr = type; 668 v86.eax = 0x8800; 669 v86int(); 670 return v86.eax; 671} 672 673static uint32_t 674drvinfo(int drive) 675{ 676 v86.addr = 0x13; 677 v86.eax = 0x800; 678 v86.edx = DRV_HARD + drive; 679 v86int(); 680 if (V86_CY(v86.efl)) 681 return 0x4f010f; 682 return ((v86.ecx & 0xc0) << 18) | ((v86.ecx & 0xff00) << 8) | 683 (v86.edx & 0xff00) | (v86.ecx & 0x3f); 684} 685 686static int 687drvread(void *buf, unsigned lba, unsigned nblk) 688{ 689 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 690 v86.addr = 0x604; 691 v86.eax = nblk; 692 v86.ebx = VTOPSEG(buf) << 16 | VTOPOFF(buf); 693 v86.ecx = lba; 694 v86.edx = dsk.drive; 695 v86int(); 696 v86.ctl = V86_FLAGS; 697 if (V86_CY(v86.efl)) { 698 printf("Disk error 0x%x (lba=0x%x)\n", v86.eax >> 8 & 0xff, 699 lba); 700 return -1; 701 } 702 return 0; 703} 704 705static int 706keyhit(unsigned ticks) 707{ 708 uint32_t x; 709 710 x = 0; 711 for (;;) { 712 v86.addr = 0x16; 713 v86.eax = 0x100; 714 v86int(); 715 if (!V86_ZR(v86.efl)) 716 return 1; 717 v86.addr = 0x1a; 718 v86.eax = 0; 719 v86.edx = 0; 720 v86int(); 721 if (!x) 722 x = v86.edx; 723 else if (v86.edx < x || v86.edx > x + ticks) 724 return 0; 725 } 726} 727 728static int 729putch(int c) 730{ 731 v86.addr = 0x10; 732 v86.eax = 0xe00 | (c & 0xff); 733 v86.ebx = 0x7; 734 v86int(); 735 return c; 736} 737 738static int 739getch(void) 740{ 741 v86.addr = 0x16; 742 v86.eax = 0; 743 v86int(); 744 return v86.eax & 0xff; 745}
| 542 dsk.type = MAJ_DA; 543 dsk.init++; 544 } 545 if (dsk.part >= d->d_npartitions) { 546 printf("Invalid %s\n", "partition"); 547 return -1; 548 } 549 dsk.start = d->d_partitions[dsk.part].p_offset; 550 } 551 } 552 return drvread(buf, dsk.start + lba, nblk); 553} 554 555static int 556printf(const char *fmt,...) 557{ 558 static const char digits[16] = "0123456789abcdef"; 559 va_list ap; 560 char buf[10]; 561 char *s; 562 unsigned r, u; 563 int c; 564 565 va_start(ap, fmt); 566 while ((c = *fmt++)) { 567 if (c == '%') { 568 c = *fmt++; 569 switch (c) { 570 case 'c': 571 putchar(va_arg(ap, int)); 572 continue; 573 case 's': 574 for (s = va_arg(ap, char *); *s; s++) 575 putchar(*s); 576 continue; 577 case 'u': 578 case 'x': 579 r = c == 'u' ? 10U : 16U; 580 u = va_arg(ap, unsigned); 581 s = buf; 582 do 583 *s++ = digits[u % r]; 584 while (u /= r); 585 while (--s >= buf) 586 putchar(*s); 587 continue; 588 } 589 } 590 putchar(c); 591 } 592 va_end(ap); 593 return 0; 594} 595 596static void 597getstr(char *str, int size) 598{ 599 char *s; 600 int c; 601 602 s = str; 603 do { 604 switch (c = getchar()) { 605 case '\b': 606 if (s > str) 607 s--; 608 break; 609 case '\n': 610 *s = 0; 611 break; 612 default: 613 if (s - str < size - 1) 614 *s++ = c; 615 } 616 putchar(c); 617 } while (c != '\n'); 618} 619 620static int 621putchar(int c) 622{ 623 if (c == '\n') 624 putch('\r'); 625 return putch(c); 626} 627 628static int 629getchar(void) 630{ 631 int c; 632 633 c = getch(); 634 if (c == '\r') 635 c = '\n'; 636 return c; 637} 638 639static void * 640memcpy(void *dst, const void *src, size_t size) 641{ 642 const char *s; 643 char *d; 644 645 for (d = dst, s = src; size; size--) 646 *d++ = *s++; 647 return dst; 648} 649 650static int 651strcmp(const char *s1, const char *s2) 652{ 653 for (; *s1 == *s2 && *s1; s1++, s2++); 654 return (u_char)*s1 - (u_char)*s2; 655} 656 657static void * 658malloc(size_t size) 659{ 660 static uint32_t next; 661 void *p; 662 663 if (!next) 664 next = roundup2(__base + _end, 0x10000) - __base; 665 p = (void *)next; 666 next += size; 667 return p; 668} 669 670static uint32_t 671memsize(int type) 672{ 673 v86.ctl = V86_FLAGS; 674 v86.addr = type; 675 v86.eax = 0x8800; 676 v86int(); 677 return v86.eax; 678} 679 680static uint32_t 681drvinfo(int drive) 682{ 683 v86.addr = 0x13; 684 v86.eax = 0x800; 685 v86.edx = DRV_HARD + drive; 686 v86int(); 687 if (V86_CY(v86.efl)) 688 return 0x4f010f; 689 return ((v86.ecx & 0xc0) << 18) | ((v86.ecx & 0xff00) << 8) | 690 (v86.edx & 0xff00) | (v86.ecx & 0x3f); 691} 692 693static int 694drvread(void *buf, unsigned lba, unsigned nblk) 695{ 696 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 697 v86.addr = 0x604; 698 v86.eax = nblk; 699 v86.ebx = VTOPSEG(buf) << 16 | VTOPOFF(buf); 700 v86.ecx = lba; 701 v86.edx = dsk.drive; 702 v86int(); 703 v86.ctl = V86_FLAGS; 704 if (V86_CY(v86.efl)) { 705 printf("Disk error 0x%x (lba=0x%x)\n", v86.eax >> 8 & 0xff, 706 lba); 707 return -1; 708 } 709 return 0; 710} 711 712static int 713keyhit(unsigned ticks) 714{ 715 uint32_t x; 716 717 x = 0; 718 for (;;) { 719 v86.addr = 0x16; 720 v86.eax = 0x100; 721 v86int(); 722 if (!V86_ZR(v86.efl)) 723 return 1; 724 v86.addr = 0x1a; 725 v86.eax = 0; 726 v86.edx = 0; 727 v86int(); 728 if (!x) 729 x = v86.edx; 730 else if (v86.edx < x || v86.edx > x + ticks) 731 return 0; 732 } 733} 734 735static int 736putch(int c) 737{ 738 v86.addr = 0x10; 739 v86.eax = 0xe00 | (c & 0xff); 740 v86.ebx = 0x7; 741 v86int(); 742 return c; 743} 744 745static int 746getch(void) 747{ 748 v86.addr = 0x16; 749 v86.eax = 0; 750 v86int(); 751 return v86.eax & 0xff; 752}
|