Changeset View
Changeset View
Standalone View
Standalone View
stand/i386/boot2/boot2.c
Context not available. | |||||
static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ | static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ | ||||
static const unsigned char flags[NOPT] = { | static const unsigned char flags[NOPT] = { | ||||
RBX_DUAL, | RBX_DUAL, | ||||
RBX_SERIAL, | RBX_SERIAL, | ||||
RBX_ASKNAME, | RBX_ASKNAME, | ||||
RBX_CDROM, | RBX_CDROM, | ||||
RBX_CONFIG, | RBX_CONFIG, | ||||
RBX_KDB, | RBX_KDB, | ||||
RBX_GDB, | RBX_GDB, | ||||
RBX_MUTE, | RBX_MUTE, | ||||
RBX_NOINTR, | RBX_NOINTR, | ||||
RBX_PAUSE, | RBX_PAUSE, | ||||
RBX_QUIET, | RBX_QUIET, | ||||
RBX_DFLTROOT, | RBX_DFLTROOT, | ||||
RBX_SINGLE, | RBX_SINGLE, | ||||
RBX_VERBOSE | RBX_VERBOSE | ||||
}; | }; | ||||
static const char *const dev_nm[NDEV] = {"ad", "da", "fd"}; | static const char *const dev_nm[NDEV] = {"ad", "da", "fd"}; | ||||
static const unsigned char dev_maj[NDEV] = {30, 4, 2}; | static const unsigned char dev_maj[NDEV] = {30, 4, 2}; | ||||
static struct dsk { | static struct dsk { | ||||
unsigned drive; | unsigned drive; | ||||
unsigned type; | unsigned type; | ||||
unsigned unit; | unsigned unit; | ||||
uint8_t slice; | uint8_t slice; | ||||
uint8_t part; | uint8_t part; | ||||
unsigned start; | unsigned start; | ||||
int init; | int init; | ||||
} dsk; | } dsk; | ||||
static char cmd[512], cmddup[512], knamebuf[1024]; | static char cmd[512], cmddup[512], knamebuf[1024]; | ||||
static const char *kname; | static const char *kname; | ||||
Context not available. | |||||
static void | static void | ||||
memcpy(void *dst, const void *src, int len) | memcpy(void *dst, const void *src, int len) | ||||
{ | { | ||||
const char *s = src; | const char *s = src; | ||||
char *d = dst; | char *d = dst; | ||||
while (len--) | while (len--) | ||||
*d++ = *s++; | *d++ = *s++; | ||||
} | } | ||||
static inline int | static inline int | ||||
strcmp(const char *s1, const char *s2) | strcmp(const char *s1, const char *s2) | ||||
{ | { | ||||
for (; *s1 == *s2 && *s1; s1++, s2++); | for (; *s1 == *s2 && *s1; s1++, s2++); | ||||
return (unsigned char)*s1 - (unsigned char)*s2; | return ((unsigned char)*s1 - (unsigned char)*s2); | ||||
} | } | ||||
#define UFS_SMALL_CGBASE | #define UFS_SMALL_CGBASE | ||||
Context not available. | |||||
static int | static int | ||||
xfsread(ufs_ino_t inode, void *buf, size_t nbyte) | xfsread(ufs_ino_t inode, void *buf, size_t nbyte) | ||||
{ | { | ||||
if ((size_t)fsread(inode, buf, nbyte) != nbyte) { | if ((size_t)fsread(inode, buf, nbyte) != nbyte) { | ||||
imp: Blank line at start of function rule | |||||
printf("Invalid %s\n", "format"); | printf("Invalid %s\n", "format"); | ||||
return -1; | return (-1); | ||||
} | } | ||||
return 0; | return (0); | ||||
} | } | ||||
static inline void | static inline void | ||||
getstr(void) | getstr(void) | ||||
{ | { | ||||
char *s; | char *s; | ||||
int c; | int c; | ||||
s = cmd; | s = cmd; | ||||
for (;;) { | for (;;) { | ||||
switch (c = xgetc(0)) { | switch (c = xgetc(0)) { | ||||
case 0: | case 0: | ||||
break; | break; | ||||
case '\177': | case '\177': | ||||
case '\b': | case '\b': | ||||
if (s > cmd) { | if (s > cmd) { | ||||
s--; | s--; | ||||
printf("\b \b"); | printf("\b \b"); | ||||
} | } | ||||
break; | break; | ||||
case '\n': | case '\n': | ||||
case '\r': | case '\r': | ||||
*s = 0; | *s = 0; | ||||
return; | return; | ||||
default: | default: | ||||
if (s - cmd < sizeof(cmd) - 1) | if (s - cmd < sizeof(cmd) - 1) | ||||
*s++ = c; | *s++ = c; | ||||
putchar(c); | putchar(c); | ||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
static inline void | static inline void | ||||
putc(int c) | putc(int c) | ||||
{ | { | ||||
v86.addr = 0x10; | v86.addr = 0x10; | ||||
impUnsubmitted Not Done Inline Actionsblank line imp: blank line
| |||||
v86.eax = 0xe00 | (c & 0xff); | v86.eax = 0xe00 | (c & 0xff); | ||||
v86.ebx = 0x7; | v86.ebx = 0x7; | ||||
v86int(); | v86int(); | ||||
} | } | ||||
int | int | ||||
main(void) | main(void) | ||||
{ | { | ||||
uint8_t autoboot; | uint8_t autoboot; | ||||
ufs_ino_t ino; | ufs_ino_t ino; | ||||
size_t nbyte; | size_t nbyte; | ||||
dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base); | dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base); | ||||
v86.ctl = V86_FLAGS; | v86.ctl = V86_FLAGS; | ||||
v86.efl = PSL_RESERVED_DEFAULT | PSL_I; | v86.efl = PSL_RESERVED_DEFAULT | PSL_I; | ||||
dsk.drive = *(uint8_t *)PTOV(ARGS); | dsk.drive = *(uint8_t *)PTOV(ARGS); | ||||
dsk.type = dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD; | dsk.type = dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD; | ||||
dsk.unit = dsk.drive & DRV_MASK; | dsk.unit = dsk.drive & DRV_MASK; | ||||
dsk.slice = *(uint8_t *)PTOV(ARGS + 1) + 1; | dsk.slice = *(uint8_t *)PTOV(ARGS + 1) + 1; | ||||
bootinfo.bi_version = BOOTINFO_VERSION; | bootinfo.bi_version = BOOTINFO_VERSION; | ||||
bootinfo.bi_size = sizeof(bootinfo); | bootinfo.bi_size = sizeof(bootinfo); | ||||
/* Process configuration file */ | /* Process configuration file */ | ||||
autoboot = 1; | autoboot = 1; | ||||
if ((ino = lookup(PATH_CONFIG)) || | if ((ino = lookup(PATH_CONFIG)) || | ||||
(ino = lookup(PATH_DOTCONFIG))) { | (ino = lookup(PATH_DOTCONFIG))) { | ||||
nbyte = fsread(ino, cmd, sizeof(cmd) - 1); | nbyte = fsread(ino, cmd, sizeof(cmd) - 1); | ||||
cmd[nbyte] = '\0'; | cmd[nbyte] = '\0'; | ||||
} | |||||
if (*cmd) { | |||||
memcpy(cmddup, cmd, sizeof(cmd)); | |||||
if (parse()) | |||||
autoboot = 0; | |||||
if (!OPT_CHECK(RBX_QUIET)) | |||||
printf("%s: %s", PATH_CONFIG, cmddup); | |||||
/* Do not process this command twice */ | |||||
*cmd = 0; | |||||
} | |||||
/* | |||||
* Try to exec stage 3 boot loader. If interrupted by a keypress, | |||||
* or in case of failure, try to load a kernel directly instead. | |||||
*/ | |||||
if (!kname) { | |||||
kname = PATH_LOADER; | |||||
if (autoboot && !keyhit(3*SECOND)) { | |||||
load(); | |||||
kname = PATH_KERNEL; | |||||
} | } | ||||
} | |||||
/* Present the user with the boot2 prompt. */ | if (*cmd) { | ||||
memcpy(cmddup, cmd, sizeof(cmd)); | |||||
if (parse()) | |||||
autoboot = 0; | |||||
if (!OPT_CHECK(RBX_QUIET)) | |||||
printf("%s: %s", PATH_CONFIG, cmddup); | |||||
/* Do not process this command twice */ | |||||
*cmd = 0; | |||||
} | |||||
for (;;) { | /* | ||||
if (!autoboot || !OPT_CHECK(RBX_QUIET)) | * Try to exec stage 3 boot loader. If interrupted by a keypress, | ||||
printf("\nFreeBSD/x86 boot\n" | * or in case of failure, try to load a kernel directly instead. | ||||
"Default: %u:%s(%u,%c)%s\n" | */ | ||||
"boot: ", | |||||
dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, | if (!kname) { | ||||
'a' + dsk.part, kname); | kname = PATH_LOADER; | ||||
if (DO_SIO) | if (autoboot && !keyhit(3*SECOND)) { | ||||
sio_flush(); | load(); | ||||
if (!autoboot || keyhit(3*SECOND)) | kname = PATH_KERNEL; | ||||
getstr(); | } | ||||
else if (!autoboot || !OPT_CHECK(RBX_QUIET)) | } | ||||
putchar('\n'); | |||||
autoboot = 0; | /* Present the user with the boot2 prompt. */ | ||||
if (parse()) | |||||
putchar('\a'); | for (;;) { | ||||
else | if (!autoboot || !OPT_CHECK(RBX_QUIET)) | ||||
load(); | printf("\nFreeBSD/x86 boot\n" | ||||
} | "Default: %u:%s(%u,%c)%s\n" | ||||
"boot: ", | |||||
dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, | |||||
'a' + dsk.part, kname); | |||||
if (DO_SIO) | |||||
sio_flush(); | |||||
if (!autoboot || keyhit(3*SECOND)) | |||||
getstr(); | |||||
else if (!autoboot || !OPT_CHECK(RBX_QUIET)) | |||||
putchar('\n'); | |||||
autoboot = 0; | |||||
if (parse()) | |||||
putchar('\a'); | |||||
else | |||||
load(); | |||||
} | |||||
} | } | ||||
/* XXX - Needed for btxld to link the boot2 binary; do not remove. */ | /* XXX - Needed for btxld to link the boot2 binary; do not remove. */ | ||||
Context not available. | |||||
static void | static void | ||||
load(void) | load(void) | ||||
{ | { | ||||
union { | union { | ||||
struct exec ex; | struct exec ex; | ||||
Elf32_Ehdr eh; | Elf32_Ehdr eh; | ||||
} hdr; | } hdr; | ||||
static Elf32_Phdr ep[2]; | static Elf32_Phdr ep[2]; | ||||
static Elf32_Shdr es[2]; | static Elf32_Shdr es[2]; | ||||
caddr_t p; | caddr_t p; | ||||
ufs_ino_t ino; | ufs_ino_t ino; | ||||
uint32_t addr; | uint32_t addr; | ||||
int k; | int k; | ||||
uint8_t i, j; | uint8_t i, j; | ||||
if (!(ino = lookup(kname))) { | if (!(ino = lookup(kname))) { | ||||
if (!ls) | if (!ls) | ||||
printf("No %s\n", kname); | printf("No %s\n", kname); | ||||
return; | |||||
} | |||||
if (xfsread(ino, &hdr, sizeof(hdr))) | |||||
return; | |||||
if (N_GETMAGIC(hdr.ex) == ZMAGIC) { | |||||
addr = hdr.ex.a_entry & 0xffffff; | |||||
p = PTOV(addr); | |||||
fs_off = PAGE_SIZE; | |||||
if (xfsread(ino, p, hdr.ex.a_text)) | |||||
return; | |||||
p += roundup2(hdr.ex.a_text, PAGE_SIZE); | |||||
if (xfsread(ino, p, hdr.ex.a_data)) | |||||
return; | |||||
} else if (IS_ELF(hdr.eh)) { | |||||
fs_off = hdr.eh.e_phoff; | |||||
for (j = k = 0; k < hdr.eh.e_phnum && j < 2; k++) { | |||||
if (xfsread(ino, ep + j, sizeof(ep[0]))) | |||||
return; | return; | ||||
if (ep[j].p_type == PT_LOAD) | |||||
j++; | |||||
} | } | ||||
for (i = 0; i < 2; i++) { | if (xfsread(ino, &hdr, sizeof(hdr))) | ||||
p = PTOV(ep[i].p_paddr & 0xffffff); | |||||
fs_off = ep[i].p_offset; | |||||
if (xfsread(ino, p, ep[i].p_filesz)) | |||||
return; | return; | ||||
} | |||||
p += roundup2(ep[1].p_memsz, PAGE_SIZE); | if (N_GETMAGIC(hdr.ex) == ZMAGIC) { | ||||
bootinfo.bi_symtab = VTOP(p); | addr = hdr.ex.a_entry & 0xffffff; | ||||
if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { | p = PTOV(addr); | ||||
fs_off = hdr.eh.e_shoff + sizeof(es[0]) * | fs_off = PAGE_SIZE; | ||||
(hdr.eh.e_shstrndx + 1); | if (xfsread(ino, p, hdr.ex.a_text)) | ||||
if (xfsread(ino, &es, sizeof(es))) | return; | ||||
p += roundup2(hdr.ex.a_text, PAGE_SIZE); | |||||
if (xfsread(ino, p, hdr.ex.a_data)) | |||||
return; | |||||
} else if (IS_ELF(hdr.eh)) { | |||||
fs_off = hdr.eh.e_phoff; | |||||
for (j = k = 0; k < hdr.eh.e_phnum && j < 2; k++) { | |||||
if (xfsread(ino, ep + j, sizeof(ep[0]))) | |||||
return; | |||||
if (ep[j].p_type == PT_LOAD) | |||||
j++; | |||||
} | |||||
for (i = 0; i < 2; i++) { | |||||
p = PTOV(ep[i].p_paddr & 0xffffff); | |||||
fs_off = ep[i].p_offset; | |||||
if (xfsread(ino, p, ep[i].p_filesz)) | |||||
return; | |||||
} | |||||
p += roundup2(ep[1].p_memsz, PAGE_SIZE); | |||||
bootinfo.bi_symtab = VTOP(p); | |||||
if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { | |||||
fs_off = hdr.eh.e_shoff + sizeof(es[0]) * | |||||
(hdr.eh.e_shstrndx + 1); | |||||
if (xfsread(ino, &es, sizeof(es))) | |||||
return; | |||||
for (i = 0; i < 2; i++) { | |||||
*(Elf32_Word *)p = es[i].sh_size; | |||||
p += sizeof(es[i].sh_size); | |||||
fs_off = es[i].sh_offset; | |||||
if (xfsread(ino, p, es[i].sh_size)) | |||||
return; | |||||
p += es[i].sh_size; | |||||
} | |||||
} | |||||
addr = hdr.eh.e_entry & 0xffffff; | |||||
bootinfo.bi_esymtab = VTOP(p); | |||||
} else { | |||||
printf("Invalid %s\n", "format"); | |||||
return; | return; | ||||
for (i = 0; i < 2; i++) { | |||||
*(Elf32_Word *)p = es[i].sh_size; | |||||
p += sizeof(es[i].sh_size); | |||||
fs_off = es[i].sh_offset; | |||||
if (xfsread(ino, p, es[i].sh_size)) | |||||
return; | |||||
p += es[i].sh_size; | |||||
} | |||||
} | } | ||||
addr = hdr.eh.e_entry & 0xffffff; | |||||
bootinfo.bi_esymtab = VTOP(p); | |||||
} else { | |||||
printf("Invalid %s\n", "format"); | |||||
return; | |||||
} | |||||
bootinfo.bi_kernelname = VTOP(kname); | bootinfo.bi_kernelname = VTOP(kname); | ||||
bootinfo.bi_bios_dev = dsk.drive; | bootinfo.bi_bios_dev = dsk.drive; | ||||
__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK), | __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK), | ||||
MAKEBOOTDEV(dev_maj[dsk.type], dsk.slice, dsk.unit, dsk.part), | MAKEBOOTDEV(dev_maj[dsk.type], dsk.slice, dsk.unit, dsk.part), | ||||
0, 0, 0, VTOP(&bootinfo)); | 0, 0, 0, VTOP(&bootinfo)); | ||||
} | } | ||||
static int | static int | ||||
parse() | parse() | ||||
impUnsubmitted Not Done Inline Actionsthis, and others, need parse(void) imp: this, and others, need parse(void)
| |||||
{ | { | ||||
char *arg = cmd; | char *arg = cmd; | ||||
char *ep, *p, *q; | char *ep, *p, *q; | ||||
const char *cp; | const char *cp; | ||||
unsigned int drv; | unsigned int drv; | ||||
int c, i, j; | int c, i, j; | ||||
size_t k; | size_t k; | ||||
while ((c = *arg++)) { | while ((c = *arg++)) { | ||||
if (c == ' ' || c == '\t' || c == '\n') | if (c == ' ' || c == '\t' || c == '\n') | ||||
continue; | continue; | ||||
for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++); | for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++); | ||||
ep = p; | ep = p; | ||||
if (*p) | if (*p) | ||||
*p++ = 0; | *p++ = 0; | ||||
if (c == '-') { | if (c == '-') { | ||||
while ((c = *arg++)) { | while ((c = *arg++)) { | ||||
if (c == 'P') { | if (c == 'P') { | ||||
if (*(uint8_t *)PTOV(0x496) & 0x10) { | if (*(uint8_t *)PTOV(0x496) & 0x10) { | ||||
cp = "yes"; | cp = "yes"; | ||||
} else { | } else { | ||||
opts |= OPT_SET(RBX_DUAL) | OPT_SET(RBX_SERIAL); | opts |= OPT_SET(RBX_DUAL) | | ||||
cp = "no"; | OPT_SET(RBX_SERIAL); | ||||
} | cp = "no"; | ||||
printf("Keyboard: %s\n", cp); | } | ||||
continue; | printf("Keyboard: %s\n", cp); | ||||
continue; | |||||
#if SERIAL | #if SERIAL | ||||
} else if (c == 'S') { | } else if (c == 'S') { | ||||
j = 0; | j = 0; | ||||
while ((unsigned int)(i = *arg++ - '0') <= 9) | while (*arg <= '9') { | ||||
j = j * 10 + i; | i = (unsigned int)(*arg - '0'); | ||||
if (j > 0 && i == -'0') { | j = j * 10 + i; | ||||
comspeed = j; | arg++; | ||||
break; | } | ||||
} | if (j > 0 && i == -'0') { | ||||
/* Fall through to error below ('S' not in optstr[]). */ | comspeed = j; | ||||
break; | |||||
} | |||||
/* | |||||
* Fall through to error below | |||||
* ('S' not in optstr[]). | |||||
*/ | |||||
#endif | #endif | ||||
} | } | ||||
for (i = 0; c != optstr[i]; i++) | for (i = 0; c != optstr[i]; i++) | ||||
if (i == NOPT - 1) | if (i == NOPT - 1) | ||||
return -1; | return (-1); | ||||
opts ^= OPT_SET(flags[i]); | opts ^= OPT_SET(flags[i]); | ||||
} | } | ||||
#if SERIAL | #if SERIAL | ||||
ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) : | ioctrl = OPT_CHECK(RBX_DUAL) ? | ||||
OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD; | (IO_SERIAL|IO_KEYBOARD) : | ||||
if (DO_SIO) { | OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD; | ||||
if (sio_init(115200 / comspeed) != 0) | if (DO_SIO) { | ||||
ioctrl &= ~IO_SERIAL; | if (sio_init(115200 / comspeed) != 0) | ||||
} | ioctrl &= ~IO_SERIAL; | ||||
} | |||||
#endif | #endif | ||||
} else { | } else { | ||||
for (q = arg--; *q && *q != '('; q++); | for (q = arg--; *q && *q != '('; q++); | ||||
if (*q) { | if (*q) { | ||||
drv = -1; | drv = -1; | ||||
if (arg[1] == ':') { | if (arg[1] == ':') { | ||||
drv = *arg - '0'; | drv = *arg - '0'; | ||||
if (drv > 9) | if (drv > 9) | ||||
return (-1); | return (-1); | ||||
arg += 2; | arg += 2; | ||||
} | } | ||||
if (q - arg != 2) | if (q - arg != 2) | ||||
return -1; | return -1; | ||||
for (i = 0; arg[0] != dev_nm[i][0] || | for (i = 0; arg[0] != dev_nm[i][0] || | ||||
arg[1] != dev_nm[i][1]; i++) | arg[1] != dev_nm[i][1]; i++) | ||||
if (i == NDEV - 1) | if (i == NDEV - 1) | ||||
return -1; | return (-1); | ||||
dsk.type = i; | dsk.type = i; | ||||
arg += 3; | arg += 3; | ||||
dsk.unit = *arg - '0'; | dsk.unit = *arg - '0'; | ||||
if (arg[1] != ',' || dsk.unit > 9) | if (arg[1] != ',' || dsk.unit > 9) | ||||
return -1; | return (-1); | ||||
arg += 2; | arg += 2; | ||||
dsk.slice = WHOLE_DISK_SLICE; | dsk.slice = WHOLE_DISK_SLICE; | ||||
if (arg[1] == ',') { | if (arg[1] == ',') { | ||||
dsk.slice = *arg - '0' + 1; | dsk.slice = *arg - '0' + 1; | ||||
if (dsk.slice > NDOSPART + 1) | if (dsk.slice > NDOSPART + 1) | ||||
return -1; | return (-1); | ||||
arg += 2; | arg += 2; | ||||
} | |||||
if (arg[1] != ')') | |||||
return (-1); | |||||
dsk.part = *arg - 'a'; | |||||
if (dsk.part > 7) | |||||
return (-1); | |||||
arg += 2; | |||||
if (drv == -1) | |||||
drv = dsk.unit; | |||||
dsk.drive = (dsk.type <= TYPE_MAXHARD | |||||
? DRV_HARD : 0) + drv; | |||||
dsk_meta = 0; | |||||
} | |||||
k = ep - arg; | |||||
if (k > 0) { | |||||
if (k >= sizeof(knamebuf)) | |||||
return (-1); | |||||
memcpy(knamebuf, arg, k + 1); | |||||
kname = knamebuf; | |||||
} | |||||
} | } | ||||
if (arg[1] != ')') | arg = p; | ||||
return -1; | |||||
dsk.part = *arg - 'a'; | |||||
if (dsk.part > 7) | |||||
return (-1); | |||||
arg += 2; | |||||
if (drv == -1) | |||||
drv = dsk.unit; | |||||
dsk.drive = (dsk.type <= TYPE_MAXHARD | |||||
? DRV_HARD : 0) + drv; | |||||
dsk_meta = 0; | |||||
} | |||||
k = ep - arg; | |||||
if (k > 0) { | |||||
if (k >= sizeof(knamebuf)) | |||||
return -1; | |||||
memcpy(knamebuf, arg, k + 1); | |||||
kname = knamebuf; | |||||
} | |||||
} | } | ||||
arg = p; | return (0); | ||||
} | |||||
return 0; | |||||
} | } | ||||
static int | static int | ||||
dskread(void *buf, unsigned lba, unsigned nblk) | dskread(void *buf, unsigned lba, unsigned nblk) | ||||
{ | { | ||||
struct dos_partition *dp; | struct dos_partition *dp; | ||||
struct disklabel *d; | struct disklabel *d; | ||||
char *sec; | char *sec; | ||||
unsigned i; | unsigned i; | ||||
uint8_t sl; | uint8_t sl; | ||||
const char *reason; | const char *reason; | ||||
if (!dsk_meta) { | if (!dsk_meta) { | ||||
sec = dmadat->secbuf; | sec = dmadat->secbuf; | ||||
dsk.start = 0; | dsk.start = 0; | ||||
if (drvread(sec, DOSBBSECTOR, 1)) | if (drvread(sec, DOSBBSECTOR, 1)) | ||||
return -1; | return (-1); | ||||
dp = (void *)(sec + DOSPARTOFF); | dp = (void *)(sec + DOSPARTOFF); | ||||
sl = dsk.slice; | sl = dsk.slice; | ||||
if (sl < BASE_SLICE) { | if (sl < BASE_SLICE) { | ||||
for (i = 0; i < NDOSPART; i++) | for (i = 0; i < NDOSPART; i++) | ||||
if (dp[i].dp_typ == DOSPTYP_386BSD && | if (dp[i].dp_typ == DOSPTYP_386BSD && | ||||
(dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) { | (dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) { | ||||
sl = BASE_SLICE + i; | sl = BASE_SLICE + i; | ||||
if (dp[i].dp_flag & 0x80 || | if (dp[i].dp_flag & 0x80 || | ||||
dsk.slice == COMPATIBILITY_SLICE) | dsk.slice == COMPATIBILITY_SLICE) | ||||
break; | break; | ||||
} | |||||
if (dsk.slice == WHOLE_DISK_SLICE) | |||||
dsk.slice = sl; | |||||
} | |||||
if (sl != WHOLE_DISK_SLICE) { | |||||
if (sl != COMPATIBILITY_SLICE) | |||||
dp += sl - BASE_SLICE; | |||||
if (dp->dp_typ != DOSPTYP_386BSD) { | |||||
reason = "slice"; | |||||
goto error; | |||||
} | |||||
dsk.start = dp->dp_start; | |||||
} | |||||
if (drvread(sec, dsk.start + LABELSECTOR, 1)) | |||||
return (-1); | |||||
d = (void *)(sec + LABELOFFSET); | |||||
if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) { | |||||
if (dsk.part != RAW_PART) { | |||||
reason = "label"; | |||||
goto error; | |||||
} | |||||
} else { | |||||
if (!dsk.init) { | |||||
if (d->d_type == DTYPE_SCSI) | |||||
dsk.type = TYPE_DA; | |||||
dsk.init++; | |||||
} | |||||
if (dsk.part >= d->d_npartitions || | |||||
!d->d_partitions[dsk.part].p_size) { | |||||
reason = "partition"; | |||||
goto error; | |||||
} | |||||
dsk.start += d->d_partitions[dsk.part].p_offset; | |||||
dsk.start -= d->d_partitions[RAW_PART].p_offset; | |||||
} | } | ||||
if (dsk.slice == WHOLE_DISK_SLICE) | |||||
dsk.slice = sl; | |||||
} | |||||
if (sl != WHOLE_DISK_SLICE) { | |||||
if (sl != COMPATIBILITY_SLICE) | |||||
dp += sl - BASE_SLICE; | |||||
if (dp->dp_typ != DOSPTYP_386BSD) { | |||||
reason = "slice"; | |||||
goto error; | |||||
} | |||||
dsk.start = dp->dp_start; | |||||
} | |||||
if (drvread(sec, dsk.start + LABELSECTOR, 1)) | |||||
return -1; | |||||
d = (void *)(sec + LABELOFFSET); | |||||
if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) { | |||||
if (dsk.part != RAW_PART) { | |||||
reason = "label"; | |||||
goto error; | |||||
} | |||||
} else { | |||||
if (!dsk.init) { | |||||
if (d->d_type == DTYPE_SCSI) | |||||
dsk.type = TYPE_DA; | |||||
dsk.init++; | |||||
} | |||||
if (dsk.part >= d->d_npartitions || | |||||
!d->d_partitions[dsk.part].p_size) { | |||||
reason = "partition"; | |||||
goto error; | |||||
} | |||||
dsk.start += d->d_partitions[dsk.part].p_offset; | |||||
dsk.start -= d->d_partitions[RAW_PART].p_offset; | |||||
} | } | ||||
} | return (drvread(buf, dsk.start + lba, nblk)); | ||||
return drvread(buf, dsk.start + lba, nblk); | |||||
error: | error: | ||||
printf("Invalid %s\n", reason); | printf("Invalid %s\n", reason); | ||||
return -1; | return (-1); | ||||
} | } | ||||
static void | static void | ||||
printf(const char *fmt,...) | printf(const char *fmt,...) | ||||
{ | { | ||||
va_list ap; | va_list ap; | ||||
static char buf[10]; | static char buf[10]; | ||||
char *s; | char *s; | ||||
unsigned u; | unsigned u; | ||||
int c; | int c; | ||||
va_start(ap, fmt); | va_start(ap, fmt); | ||||
while ((c = *fmt++)) { | while ((c = *fmt++)) { | ||||
if (c == '%') { | if (c == '%') { | ||||
c = *fmt++; | c = *fmt++; | ||||
switch (c) { | switch (c) { | ||||
case 'c': | case 'c': | ||||
putchar(va_arg(ap, int)); | putchar(va_arg(ap, int)); | ||||
continue; | continue; | ||||
case 's': | case 's': | ||||
for (s = va_arg(ap, char *); *s; s++) | for (s = va_arg(ap, char *); *s; s++) | ||||
putchar(*s); | putchar(*s); | ||||
continue; | continue; | ||||
case 'u': | case 'u': | ||||
u = va_arg(ap, unsigned); | u = va_arg(ap, unsigned); | ||||
s = buf; | s = buf; | ||||
do | do | ||||
*s++ = '0' + u % 10U; | *s++ = '0' + u % 10U; | ||||
while (u /= 10U); | while (u /= 10U); | ||||
while (--s >= buf) | while (--s >= buf) | ||||
putchar(*s); | putchar(*s); | ||||
continue; | continue; | ||||
} | } | ||||
} | |||||
putchar(c); | |||||
} | } | ||||
putchar(c); | va_end(ap); | ||||
} | return; | ||||
va_end(ap); | |||||
return; | |||||
} | } | ||||
static void | static void | ||||
putchar(int c) | putchar(int c) | ||||
{ | { | ||||
if (c == '\n') | if (c == '\n') | ||||
xputc('\r'); | xputc('\r'); | ||||
xputc(c); | xputc(c); | ||||
} | } | ||||
static int | static int | ||||
drvread(void *buf, unsigned lba, unsigned nblk) | drvread(void *buf, unsigned lba, unsigned nblk) | ||||
{ | { | ||||
static unsigned c = 0x2d5c7c2f; | static unsigned c = 0x2d5c7c2f; | ||||
if (!OPT_CHECK(RBX_QUIET)) { | if (!OPT_CHECK(RBX_QUIET)) { | ||||
xputc(c = c << 8 | c >> 24); | xputc(c = c << 8 | c >> 24); | ||||
xputc('\b'); | xputc('\b'); | ||||
} | } | ||||
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; | v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; | ||||
v86.addr = XREADORG; /* call to xread in boot1 */ | v86.addr = XREADORG; /* call to xread in boot1 */ | ||||
v86.es = VTOPSEG(buf); | v86.es = VTOPSEG(buf); | ||||
v86.eax = lba; | v86.eax = lba; | ||||
v86.ebx = VTOPOFF(buf); | v86.ebx = VTOPOFF(buf); | ||||
v86.ecx = lba >> 16; | v86.ecx = lba >> 16; | ||||
v86.edx = nblk << 8 | dsk.drive; | v86.edx = nblk << 8 | dsk.drive; | ||||
v86int(); | v86int(); | ||||
v86.ctl = V86_FLAGS; | v86.ctl = V86_FLAGS; | ||||
if (V86_CY(v86.efl)) { | if (V86_CY(v86.efl)) { | ||||
printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba); | printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba); | ||||
return -1; | return (-1); | ||||
} | } | ||||
return 0; | return (0); | ||||
} | } | ||||
static int | static int | ||||
keyhit(unsigned ticks) | keyhit(unsigned ticks) | ||||
{ | { | ||||
uint32_t t0, t1; | uint32_t t0, t1; | ||||
if (OPT_CHECK(RBX_NOINTR)) | if (OPT_CHECK(RBX_NOINTR)) | ||||
return 0; | return (0); | ||||
t0 = 0; | t0 = 0; | ||||
for (;;) { | for (;;) { | ||||
if (xgetc(1)) | if (xgetc(1)) | ||||
return 1; | return (1); | ||||
t1 = *(uint32_t *)PTOV(0x46c); | t1 = *(uint32_t *)PTOV(0x46c); | ||||
if (!t0) | if (!t0) | ||||
t0 = t1; | t0 = t1; | ||||
if ((uint32_t)(t1 - t0) >= ticks) | if ((uint32_t)(t1 - t0) >= ticks) | ||||
return 0; | return (0); | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
xputc(int c) | xputc(int c) | ||||
{ | { | ||||
if (DO_KBD) | if (DO_KBD) | ||||
putc(c); | putc(c); | ||||
if (DO_SIO) | if (DO_SIO) | ||||
sio_putc(c); | sio_putc(c); | ||||
return c; | return (c); | ||||
} | } | ||||
static int | static int | ||||
getc(int fn) | getc(int fn) | ||||
{ | { | ||||
v86.addr = 0x16; | v86.addr = 0x16; | ||||
v86.eax = fn << 8; | v86.eax = fn << 8; | ||||
v86int(); | v86int(); | ||||
return fn == 0 ? v86.eax & 0xff : !V86_ZR(v86.efl); | return (fn == 0 ? v86.eax & 0xff : !V86_ZR(v86.efl)); | ||||
} | } | ||||
static int | static int | ||||
xgetc(int fn) | xgetc(int fn) | ||||
{ | { | ||||
if (OPT_CHECK(RBX_NOINTR)) | if (OPT_CHECK(RBX_NOINTR)) | ||||
return 0; | return (0); | ||||
for (;;) { | for (;;) { | ||||
if (DO_KBD && getc(1)) | if (DO_KBD && getc(1)) | ||||
return fn ? 1 : getc(0); | return (fn ? 1 : getc(0)); | ||||
if (DO_SIO && sio_ischar()) | if (DO_SIO && sio_ischar()) | ||||
return fn ? 1 : sio_getc(); | return (fn ? 1 : sio_getc()); | ||||
if (fn) | if (fn) | ||||
return 0; | return (0); | ||||
} | } | ||||
} | } | ||||
Context not available. |
Blank line at start of function rule