Change "Boot:" prompt option parsing to be more in line with the default

(no prompt) behaviour - it is now possible to "boot net:dhcp -a" and then
say "disk" at the "Boot:" prompt - result should be equivalent to "boot disk",
but the ofwboot was loaded from the network.
While there fix a few minor errors, and one significant: if the "a" partition
should not start at the beginning of the disk, the previous code failed
to read a disklabel. Use the "c" partition now to find the disklabel now
always.
This commit is contained in:
martin 2007-09-16 23:12:31 +00:00
parent 8b937dec65
commit e3218c4391
3 changed files with 150 additions and 87 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: boot.c,v 1.14 2007/06/05 08:52:20 martin Exp $ */
/* $NetBSD: boot.c,v 1.15 2007/09/16 23:12:31 martin Exp $ */
/*
* Copyright (c) 1997, 1999 Eduardo E. Horvath. All rights reserved.
@ -111,10 +111,12 @@ prom2boot(char *dev)
#endif
static int
bootoptions(const char *ap, char *kernel, char *options)
bootoptions(const char *ap, char *loaddev, char *kernel, char *options)
{
int v = 0;
const char *cp;
const char *start1 = NULL, *end1 = NULL, *start2 = NULL, *end2 = NULL;
const char *path;
char partition;
*kernel = '\0';
*options = '\0';
@ -127,18 +129,53 @@ bootoptions(const char *ap, char *kernel, char *options)
ap++;
}
cp = ap;
if (*ap != '-') {
start1 = ap;
while (*ap != '\0' && *ap != ' ') {
ap++;
}
memcpy(kernel, cp, (ap - cp));
kernel[ap - cp] = '\0';
end1 = ap;
while (*ap != '\0' && *ap == ' ') {
ap++;
}
if (*ap != '-') {
start2 = ap;
while (*ap != '\0' && *ap != ' ') {
ap++;
}
end2 = ap;
while (*ap != '\0' && *ap == ' ') {
ap++;
}
}
}
if (end2 == start2) {
start2 = end2 = NULL;
}
if (end1 == start1) {
start1 = end1 = NULL;
}
if (start1 == NULL) {
/* only options */
} else if (start2 == NULL) {
memcpy(kernel, start1, (end1 - start1));
kernel[end1 - start1] = '\0';
path = filename(kernel, &partition);
if (path && path != kernel) {
/* copy device part */
memcpy(loaddev, kernel, path-kernel);
loaddev[path-kernel] = '\0';
/* and kernel path */
strcpy(kernel, path);
}
} else {
memcpy(loaddev, start1, (end1-start1));
loaddev[end1-start1] = '\0';
memcpy(kernel, start2, (end2 - start2));
kernel[end2 - start2] = '\0';
}
strcpy(options, ap);
@ -160,7 +197,8 @@ bootoptions(const char *ap, char *kernel, char *options)
debug = 1;
}
DPRINTF(("bootoptions: kernel='%s', options='%s'\n", kernel, options));
DPRINTF(("bootoptions: device='%s', kernel='%s', options='%s'\n",
loaddev, kernel, options));
return (v);
}
@ -318,6 +356,23 @@ start_kernel(char *kernel, char *bootline, void *ofw)
(void)printf("Failed to load '%s'.\n", kernel);
}
static void
help(void)
{
printf( "enter a special command\n"
" halt\n"
" exit\n"
" to return to OpenFirmware\n"
" ?\n"
" help\n"
" to display this message\n"
"or a boot specification:\n"
" [device] [kernel] [options]\n"
"\n"
"for example:\n"
" disk:a netbsd -s\n");
}
void
main(void *ofw)
{
@ -331,12 +386,11 @@ main(void *ofw)
prom_init();
printf("\r>> %s, Revision %s\n", bootprog_name, bootprog_rev);
printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
DPRINTF((">> (%s, %s)\n", bootprog_maker, bootprog_date));
/* Figure boot arguments */
boothowto = bootoptions(prom_getbootargs(), kernel, bootline);
strncpy(bootdev, prom_getbootpath(), sizeof(bootdev) - 1);
strncpy(bootline, prom_getbootargs(), sizeof(bootline) - 1);
boothowto = bootoptions(prom_getbootargs(), bootdev, kernel, bootline);
for (;; *kernel = '\0') {
if (boothowto & RB_ASKNAME) {
@ -345,12 +399,19 @@ main(void *ofw)
printf("Boot: ");
gets(cmdline);
boothowto = bootoptions(cmdline, kernel, bootline);
boothowto |= RB_ASKNAME;
if (!strcmp(kernel,"exit") || !strcmp(kernel,"halt")) {
if (!strcmp(cmdline,"exit") ||
!strcmp(cmdline,"halt")) {
prom_halt();
} else if (!strcmp(cmdline, "?") ||
!strcmp(cmdline, "help")) {
help();
continue;
}
boothowto = bootoptions(cmdline, bootdev, kernel,
bootline);
boothowto |= RB_ASKNAME;
i = 0;
}
if (*kernel == '\0') {

View File

@ -1,4 +1,4 @@
/* $NetBSD: boot.h,v 1.2 2007/06/05 08:52:20 martin Exp $ */
/* $NetBSD: boot.h,v 1.3 2007/09/16 23:12:32 martin Exp $ */
/*-
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@ -72,4 +72,7 @@ extern u_int get_cpuid(void);
#define LOADFILE_MMU_ALLOCATOR 0x2
extern void loadfile_set_allocator(int);
/* ofdev.c */
char *filename(char*, char*);
#endif /* _BOOT_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ofdev.c,v 1.14 2007/09/14 09:26:46 martin Exp $ */
/* $NetBSD: ofdev.c,v 1.15 2007/09/16 23:12:32 martin Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@ -53,6 +53,7 @@
#include <machine/promlib.h>
#include "ofdev.h"
#include "boot.h"
extern char bootdev[];
@ -63,7 +64,7 @@ extern char bootdev[];
*
*/
static char *
char *
filename(char *str, char *ppart)
{
char *cp, *lp;
@ -81,10 +82,8 @@ filename(char *str, char *ppart)
*cp = 0;
/* ...look whether there is a device with this name */
dhandle = prom_finddevice(str);
#ifdef NOTDEF_DEBUG
printf("filename: prom_finddevice(%s) returned %x\n",
str, dhandle);
#endif
DPRINTF(("filename: prom_finddevice(%s) returned %x\n",
str, dhandle));
*cp = savec;
if (dhandle == -1) {
/*
@ -93,10 +92,8 @@ filename(char *str, char *ppart)
*/
if (!strcmp(devtype, "block")) {
/* search for arguments */
#ifdef NOTDEF_DEBUG
printf("filename: hunting for arguments "
"in %s\n", str);
#endif
DPRINTF(("filename: hunting for arguments "
"in %s\n", str));
for (cp = lp; ; ) {
cp--;
if (cp < str ||
@ -113,16 +110,12 @@ filename(char *str, char *ppart)
*--cp = '\0';
}
}
#ifdef NOTDEF_DEBUG
printf("filename: found %s\n",lp);
#endif
DPRINTF(("filename: found %s\n",lp));
return lp;
} else if (_prom_getprop(dhandle, "device_type", devtype, sizeof devtype) < 0)
devtype[0] = 0;
}
#ifdef NOTDEF_DEBUG
printf("filename: not found\n",lp);
#endif
DPRINTF(("filename: not found\n",lp));
return 0;
}
@ -296,9 +289,7 @@ disklabel_sun_to_bsd(char *cp, struct disklabel *lp)
npp = &lp->d_partitions[i];
npp->p_offset = spp->sdkp_cyloffset * secpercyl;
npp->p_size = spp->sdkp_nsectors;
#ifdef NOTDEF_DEBUG
printf("partition %d start %x size %x\n", i, (int)npp->p_offset, (int)npp->p_size);
#endif
DPRINTF(("partition %d start %x size %x\n", i, (int)npp->p_offset, (int)npp->p_size));
if (npp->p_size == 0) {
npp->p_fstype = FS_UNUSED;
} else {
@ -317,9 +308,7 @@ disklabel_sun_to_bsd(char *cp, struct disklabel *lp)
lp->d_checksum = 0;
lp->d_checksum = dkcksum(lp);
#ifdef NOTDEF_DEBUG
printf("disklabel_sun_to_bsd: success!\n");
#endif
DPRINTF(("disklabel_sun_to_bsd: success!\n"));
return (NULL);
}
@ -357,9 +346,7 @@ search_label(struct of_dev *devp, u_long off, char *buf,
if (dkcksum(dlp))
return ("NetBSD disk label corrupted");
*lp = *dlp;
#ifdef NOTDEF_DEBUG
printf("search_label: found NetBSD label\n");
#endif
DPRINTF(("search_label: found NetBSD label\n"));
return (NULL);
}
@ -384,18 +371,16 @@ devopen(struct open_file *of, const char *name, char **file)
struct disklabel label;
} b;
struct disklabel label;
int handle, part;
int handle, part, try = 0;
size_t read;
char *errmsg = NULL;
char *errmsg = NULL, *pp, savedpart = 0;
int error = 0;
if (ofdev.handle != -1)
panic("devopen");
if (of->f_flags != F_READ)
return EPERM;
#ifdef NOTDEF_DEBUG
printf("devopen: you want %s\n", name);
#endif
DPRINTF(("devopen: you want %s\n", name));
strcpy(fname, name);
cp = filename(fname, &partition);
if (cp) {
@ -417,46 +402,58 @@ devopen(struct open_file *of, const char *name, char **file)
if (b.buf[0] != '/')
strcat(opened_name, "/");
strcat(opened_name, b.buf);
#ifdef NOTDEF_DEBUG
printf("devopen: trying %s\n", fname);
#endif
DPRINTF(("devopen: trying %s\n", fname));
if ((handle = prom_finddevice(fname)) == -1)
return ENOENT;
#ifdef NOTDEF_DEBUG
printf("devopen: found %s\n", fname);
#endif
DPRINTF(("devopen: found %s\n", fname));
if (_prom_getprop(handle, "name", b.buf, sizeof b.buf) < 0)
return ENXIO;
#ifdef NOTDEF_DEBUG
printf("devopen: %s is called %s\n", fname, b.buf);
#endif
DPRINTF(("devopen: %s is called %s\n", fname, b.buf));
floppyboot = !strcmp(b.buf, "floppy");
if (_prom_getprop(handle, "device_type", b.buf, sizeof b.buf) < 0)
return ENXIO;
#ifdef NOTDEF_DEBUG
printf("devopen: %s is a %s device\n", fname, b.buf);
#endif
#ifdef NOTDEF_DEBUG
printf("devopen: opening %s\n", fname);
#endif
DPRINTF(("devopen: %s is a %s device\n", fname, b.buf));
if (!strcmp(b.buf, "block")) {
pp = strrchr(fname, ':');
if (pp && pp[1] >= 'a' && pp[1] <= 'f' && pp[2] == 0) {
savedpart = pp[1];
} else {
savedpart = 'a';
pp = fname + strlen(fname);
pp[0] = ':';
pp[2] = '\0';
}
pp[1] = 'c';
DPRINTF(("devopen: replacing by whole disk device %s\n",
fname));
}
open_again:
DPRINTF(("devopen: opening %s\n", fname));
if ((handle = prom_open(fname)) == -1) {
#ifdef NOTDEF_DEBUG
printf("devopen: open of %s failed\n", fname);
#endif
DPRINTF(("devopen: open of %s failed\n", fname));
if (pp && savedpart) {
if (try == 0) {
pp[0] = '\0';
try = 1;
} else {
pp[0] = ':';
pp[1] = savedpart;
pp = NULL;
savedpart = '\0';
}
goto open_again;
}
return ENXIO;
}
#ifdef NOTDEF_DEBUG
printf("devopen: %s is now open\n", fname);
#endif
DPRINTF(("devopen: %s is now open\n", fname));
bzero(&ofdev, sizeof ofdev);
ofdev.handle = handle;
if (!strcmp(b.buf, "block")) {
ofdev.type = OFDEV_DISK;
ofdev.bsize = DEV_BSIZE;
/* First try to find a disklabel without MBR partitions */
#ifdef NOTDEF_DEBUG
printf("devopen: trying to read disklabel\n");
#endif
DPRINTF(("devopen: trying to read disklabel\n"));
if (strategy(&ofdev, F_READ,
LABELSECTOR, DEV_BSIZE, b.buf, &read) != 0
|| read != DEV_BSIZE
@ -473,27 +470,33 @@ devopen(struct open_file *of, const char *name, char **file)
}
if (error == ERDLAB) {
if (partition)
/* User specified a parititon, but there is none */
goto bad;
/* No, label, just use complete disk */
ofdev.partoff = 0;
if (pp && savedpart) {
pp[1] = savedpart;
prom_close(handle);
if ((handle = prom_open(fname)) == -1) {
DPRINTF(("devopen: open of %s failed\n",
fname));
return ENXIO;
}
ofdev.handle = handle;
DPRINTF(("devopen: back to original device %s\n",
fname));
}
} else {
part = partition ? partition - 'a' : 0;
ofdev.partoff = label.d_partitions[part].p_offset;
#ifdef NOTDEF_DEBUG
printf("devopen: setting partition %d offset %x\n",
part, ofdev.partoff);
#endif
DPRINTF(("devopen: setting partition %d offset %x\n",
part, ofdev.partoff));
if (label.d_partitions[part].p_fstype == FS_RAID) {
ofdev.partoff += RF_PROTECTED_SECTORS;
#ifdef NOTDEF_DEBUG
printf("devopen: found RAID partition, "
"adjusting offset to %x\n", ofdev.partoff);
#endif
DPRINTF(("devopen: found RAID partition, "
"adjusting offset to %x\n", ofdev.partoff));
}
}
nfsys = 0;
of->f_dev = ofdevsw;
of->f_devdata = &ofdev;
#ifdef SPARC_BOOT_UFS
@ -503,9 +506,7 @@ devopen(struct open_file *of, const char *name, char **file)
bcopy(&file_system_cd9660, &file_system[nfsys++],
sizeof file_system[0]);
#endif
#ifdef NOTDEF_DEBUG
printf("devopen: return 0\n");
#endif
DPRINTF(("devopen: return 0\n"));
return 0;
}
#ifdef NETBOOT
@ -522,9 +523,7 @@ devopen(struct open_file *of, const char *name, char **file)
#endif
error = EFTYPE;
bad:
#ifdef NOTDEF_DEBUG
printf("devopen: error %d, cannot open device\n", error);
#endif
DPRINTF(("devopen: error %d, cannot open device\n", error));
prom_close(handle);
ofdev.handle = -1;
return error;