Deleted Added
full compact
boot2.c (40307) boot2.c (40314)
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}