Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 Sep 2005 15:21:10 -0400
From:      Jung-uk Kim <jkim@FreeBSD.org>
To:        freebsd-current@FreeBSD.org
Subject:   [PATCH] boot loader fixes #2
Message-ID:  <200509081521.14258.jkim@FreeBSD.org>
In-Reply-To: <200509011507.23432.jkim@FreeBSD.org>
References:  <200509011507.23432.jkim@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--Boundary-00=_q8IIDFjkx3aIz92
Content-Type: text/plain;
  charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

This is the second iteration of the previous patch.

http://docs.freebsd.org/cgi/mid.cgi?200509011507.23432.jkim

This one removes the redundant bound checks that I added, and fixes a 
new parsing bug that I introduced (blush, blush...).

New things in this version:

7.  Do not modify boot device until everything's good.  Previously any 
failed attempt could modify default device.

8.  Print 'FreeBSD/amd64 boot' banner on amd64 instead of 
'FreeBSD/i386 boot'.  It was confusing many users who have multiple 
drives and/or slices for a while now.  Also print slice information.  
For example,

	FreeBSD/amd64 boot
	Default: 0:ad0(0,3,a)/boot/loader
	boot:

9.  Remove 'compatibility slice', which has been broken for more than 
two years but I haven't seen a single complaint. ;-) This function 
can be revived by defining BOOT2_COMPAT_SLICE.  In that case, 
supposedly it does the correct things now (not tested).

10. Slice 4 is allowed to boot again.

Both 10 and 11 were broken from Rev 1.58.

11. Add '\n' before error messages.

Unfortunately, the patch virtually exhausts all the space left for 
boot2. :-(

Please test and let me know,

Thanks,

Jung-uk Kim

* Note: Bigger boot block is required for more fixes.

http://docs.freebsd.org/cgi/mid.cgi?200509081418.47794.jkim

In fact, keyboard probing is quite broken on many BIOSes.

http://docs.freebsd.org/cgi/mid.cgi?200305091456.40582.jkim
http://docs.freebsd.org/cgi/mid.cgi?200305131427.20811.jkim

If I had more space, I could do the correct thing in C. :-(

* Note: '-S' or '-S0' option is only good for the BIOS which 
initializes serial port correctly.  Your mileage may vary.

--Boundary-00=_q8IIDFjkx3aIz92
Content-Type: text/x-diff;
  charset="iso-2022-jp";
  name="boot2.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="boot2.diff"

Index: src/sys/boot/common/ufsread.c
===================================================================
RCS file: /home/ncvs/src/sys/boot/common/ufsread.c,v
retrieving revision 1.14
diff -u -r1.14 ufsread.c
--- src/sys/boot/common/ufsread.c	30 Jan 2005 14:58:00 -0000	1.14
+++ src/sys/boot/common/ufsread.c	8 Sep 2005 18:34:04 -0000
@@ -139,7 +139,7 @@
 		memcpy(name, path, n);
 		name[n] = 0;
 		if (dt != DT_DIR) {
-			printf("%s: not a directory.\n", name);
+			printf("\n%s: not a directory.\n", name);
 			return (0);
 		}
 		if ((dt = fsfind(name, &ino)) <= 0)
@@ -209,7 +209,7 @@
 				break;
 		}
 		if (sblock_try[n] == -1) {
-			printf("Not ufs\n");
+			printf("\nNot ufs\n");
 			return -1;
 		}
 		dsk_meta++;
Index: src/sys/boot/i386/boot0/Makefile
===================================================================
RCS file: /home/ncvs/src/sys/boot/i386/boot0/Makefile,v
retrieving revision 1.32
diff -u -r1.32 Makefile
--- src/sys/boot/i386/boot0/Makefile	25 Apr 2005 17:41:35 -0000	1.32
+++ src/sys/boot/i386/boot0/Makefile	1 Sep 2005 17:12:16 -0000
@@ -45,6 +45,8 @@
 BOOT_BOOT0_COMCONSOLE_SPEED=	"1 << 5 + 3"
 .elif ${BOOT_COMCONSOLE_SPEED} == 110
 BOOT_BOOT0_COMCONSOLE_SPEED=	"0 << 5 + 3"
+.elif ${BOOT_COMCONSOLE_SPEED} == 0
+BOOT_BOOT0_COMCONSOLE_SPEED=	0
 .else
 BOOT_BOOT0_COMCONSOLE_SPEED=	"7 << 5 + 3"
 .endif
Index: src/sys/boot/i386/boot2/Makefile
===================================================================
RCS file: /home/ncvs/src/sys/boot/i386/boot2/Makefile,v
retrieving revision 1.59
diff -u -r1.59 Makefile
--- src/sys/boot/i386/boot2/Makefile	15 Jul 2005 12:22:14 -0000	1.59
+++ src/sys/boot/i386/boot2/Makefile	8 Sep 2005 18:34:04 -0000
@@ -23,12 +23,12 @@
 CFLAGS=	-Os \
 	-fno-guess-branch-probability \
 	-fomit-frame-pointer \
-	-fno-unit-at-a-time \
 	-mno-align-long-strings \
 	-mrtd \
 	-mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 \
 	-D${BOOT2_UFS} \
 	-DFLAGS=${BOOT_BOOT1_FLAGS} \
+	-DMARCH=\"${MACHINE_ARCH}\" \
 	-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
 	-DSIOFMT=${B2SIOFMT} \
 	-DSIOSPD=${BOOT_COMCONSOLE_SPEED} \
Index: src/sys/boot/i386/boot2/boot2.c
===================================================================
RCS file: /home/ncvs/src/sys/boot/i386/boot2/boot2.c,v
retrieving revision 1.74
diff -u -r1.74 boot2.c
--- src/sys/boot/i386/boot2/boot2.c	18 Aug 2005 00:42:45 -0000	1.74
+++ src/sys/boot/i386/boot2/boot2.c	8 Sep 2005 18:34:05 -0000
@@ -63,6 +63,7 @@
 #define RBX_NOINTR	0x1c	/* -n */
 /* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */
 #define RBX_DUAL	0x1d	/* -D */
+/* 0x1e is RBX_PROBEKBD (-P).  No longer needed here. */
 /* 0x1f is reserved for log2(RB_BOOTINFO). */
 
 /* pass: -a, -s, -r, -d, -c, -v, -h, -C, -g, -m, -p, -D */
@@ -73,7 +74,7 @@
 #define PATH_KERNEL	"/boot/kernel/kernel"
 
 #define ARGS		0x900
-#define NOPT		12
+#define NOPT		11
 #define NDEV		3
 #define MEM_BASE	0x12
 #define MEM_EXT 	0x15
@@ -90,13 +91,26 @@
 
 extern uint32_t _end;
 
-static const char optstr[NOPT] = "DhaCgmnprsv"; /* Also 'P', 'S' */
+static const char optstr[NOPT] = {
+    'a',	/* RBX_ASKNAME */
+    'C',	/* RBX_CDROM */
+    'D',	/* RBX_DUAL */
+    'g',	/* RBX_GDB */
+    'h',	/* RBX_SERIAL */
+    'm',	/* RBX_MUTE */
+    'n',	/* RBX_NOINTR */
+    'p',	/* RBX_PAUSE */
+    'r',	/* RBX_DFLTROOT */
+    's',	/* RBX_SINGLE */
+    'v'		/* RBX_VERBOSE */
+};
+
 static const unsigned char flags[NOPT] = {
-    RBX_DUAL,
-    RBX_SERIAL,
     RBX_ASKNAME,
     RBX_CDROM,
+    RBX_DUAL,
     RBX_GDB,
+    RBX_SERIAL,
     RBX_MUTE,
     RBX_NOINTR,
     RBX_PAUSE,
@@ -138,8 +152,8 @@
 static int xgetc(int);
 static int getc(int);
 
-static void memcpy(void *, const void *, int);
-static void
+void memcpy(void *, const void *, int);
+void
 memcpy(void *dst, const void *src, int len)
 {
     const char *s = src;
@@ -162,7 +176,7 @@
 xfsread(ino_t inode, void *buf, size_t nbyte)
 {
     if ((size_t)fsread(inode, buf, nbyte) != nbyte) {
-	printf("Invalid %s\n", "format");
+	printf("\nInvalid %s\n", "format");
 	return -1;
     }
     return 0;
@@ -221,6 +235,9 @@
 {
     int autoboot;
     ino_t ino;
+#ifndef BOOT2_COMPAT_SLICE
+    static char slice[] = "1,";
+#endif
 
     dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
     v86.ctl = V86_FLAGS;
@@ -245,8 +262,6 @@
 	if (parse())
 	    autoboot = 0;
 	printf("%s: %s", PATH_CONFIG, cmd);
-	/* Do not process this command twice */
-	*cmd = 0;
     }
 
     /*
@@ -265,11 +280,22 @@
     /* Present the user with the boot2 prompt. */
 
     for (;;) {
-	printf("\nFreeBSD/i386 boot\n"
+	/* Do not process previous command twice */
+	*cmd = '\0';
+#ifdef BOOT2_COMPAT_SLICE
+	printf("\nFreeBSD/" MARCH " boot\n"
 	       "Default: %u:%s(%u,%c)%s\n"
 	       "boot: ",
 	       dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit,
 	       'a' + dsk.part, kname);
+#else
+	*slice = (dsk.slice == WHOLE_DISK_SLICE ? '\0' : '0' + dsk.slice - 1);
+	printf("\nFreeBSD/" MARCH " boot\n"
+	       "Default: %u:%s(%u,%s%c)%s\n"
+	       "boot: ",
+	       dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit,
+	       slice, 'a' + dsk.part, kname);
+#endif
 	if (ioctrl & IO_SERIAL)
 	    sio_flush();
 	if (!autoboot || keyhit(5*SECOND))
@@ -306,7 +332,7 @@
 
     if (!(ino = lookup(kname))) {
 	if (!ls)
-	    printf("No %s\n", kname);
+	    printf("\nNo %s\n", kname);
 	return;
     }
     if (xfsread(ino, &hdr, sizeof(hdr)))
@@ -316,7 +342,7 @@
     else if (IS_ELF(hdr.eh))
 	fmt = 1;
     else {
-	printf("Invalid %s\n", "format");
+	printf("\nInvalid %s\n", "format");
 	return;
     }
     if (fmt == 0) {
@@ -388,51 +414,60 @@
 static int
 parse()
 {
-    char *arg = cmd;
-    char *ep, *p, *q;
-    const char *cp;
-    unsigned int drv;
-    int c, i, j;
+    char *arg;
+    char *p, *q;
+    unsigned drv, unit, slice, part;
+    int i, j;
 
-    while ((c = *arg++)) {
-	if (c == ' ' || c == '\t' || c == '\n')
+    for (arg = cmd; *arg; arg++) {
+	if (*arg == ' ' || *arg == '\t' || *arg == '\n')
 	    continue;
-	for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
-	ep = p;
+	for (p = arg; *p != '\n' && *p != ' ' && *p != '\t'; p++)
+	    if (!*p) {
+		/* Do not process previous command twice */
+		p[1] = '\0';
+		break;
+	    }
 	if (*p)
-	    *p++ = 0;
-	if (c == '-') {
-	    while ((c = *arg++)) {
-		if (c == 'P') {
-		    if (*(uint8_t *)PTOV(0x496) & 0x10) {
-			cp = "yes";
-		    } else {
+	    *p = '\0';
+	if (*arg == '-') {
+	    for (q = arg + 1; *q; q++) {
+		if (*q == 'P') {
+		    if (!(*(uint8_t *)PTOV(0x496) & 0x10)) {
 			opts |= 1 << RBX_DUAL | 1 << RBX_SERIAL;
-			cp = "no";
+			printf("\nNo %s\n", "atkbd");
 		    }
-		    printf("Keyboard: %s\n", cp);
-		    continue;
-		} else if (c == 'S') {
-		    j = 0;
-		    while ((unsigned int)(i = *arg++ - '0') <= 9)
-			j = j * 10 + i;
-		    if (j > 0 && i == -'0') {
+		} else if (*q == 'S') {
+		    for (i = 1, j = 0; q[i] >= '0' && q[i] <= '9'; i++)
+			j = j * 10 + q[i] - '0';
+#if defined(UFS1_ONLY) || defined(UFS2_ONLY)
+		    switch(j) {
+		    case 0:	/* do not change speed */
+		    case 110:	case 150:   case 300:	case 1200:
+		    case 2400:	case 4800:  case 9600:	case 19200:
+		    case 38400:	case 57600: case 115200:
 			comspeed = j;
 			break;
+		    default:	/* invalid speed */
+			return -1;
 		    }
-		    /* Fall through to error below ('S' not in optstr[]). */
+#else
+		    comspeed = j;
+#endif
+		    q += i - 1;
+		} else {
+		    for (i = 0; *q != optstr[i]; i++)
+			if (i == NOPT - 1)
+			    return -1;
+		    opts ^= 1 << flags[i];
 		}
-		for (i = 0; c != optstr[i]; i++)
-		    if (i == NOPT - 1)
-			return -1;
-		opts ^= 1 << flags[i];
 	    }
 	    ioctrl = opts & 1 << RBX_DUAL ? (IO_SERIAL|IO_KEYBOARD) :
 		     opts & 1 << RBX_SERIAL ? IO_SERIAL : IO_KEYBOARD;
-	    if (ioctrl & IO_SERIAL)
-	        sio_init(115200 / comspeed);
+	    if (comspeed && (ioctrl & IO_SERIAL))
+		sio_init(115200 / comspeed);
 	} else {
-	    for (q = arg--; *q && *q != '('; q++);
+	    for (q = arg; *q && *q != '('; q++);
 	    if (*q) {
 		drv = -1;
 		if (arg[1] == ':') {
@@ -447,32 +482,42 @@
 			    arg[1] != dev_nm[i][1]; i++)
 		    if (i == NDEV - 1)
 			return -1;
-		dsk.type = i;
 		arg += 3;
-		dsk.unit = *arg - '0';
-		if (arg[1] != ',' || dsk.unit > 9)
+		unit = *arg - '0';
+		if (arg[1] != ',' || unit > 9)
 		    return -1;
 		arg += 2;
-		dsk.slice = WHOLE_DISK_SLICE;
+		slice = WHOLE_DISK_SLICE;
 		if (arg[1] == ',') {
-		    dsk.slice = *arg - '0' + 1;
-		    if (dsk.slice > NDOSPART)
+		    slice = *arg - '0';
+#ifdef BOOT2_COMPAT_SLICE
+		    if (slice > NDOSPART)
+			return -1;
+		    if (slice != COMPATIBILITY_SLICE)
+			slice++;
+#else
+		    if (slice == COMPATIBILITY_SLICE || slice > NDOSPART)
 			return -1;
+		    slice++;
+#endif
 		    arg += 2;
 		}
 		if (arg[1] != ')')
 		    return -1;
-		dsk.part = *arg - 'a';
-		if (dsk.part > 7)
-		    return (-1);
+		part = *arg - 'a';
+		if (part >= MAXPARTITIONS)
+		    return -1;
 		arg += 2;
 		if (drv == -1)
-		    drv = dsk.unit;
-		dsk.drive = (dsk.type <= TYPE_MAXHARD
-			     ? DRV_HARD : 0) + drv;
+		    drv = unit;
+		dsk.drive = (i <= TYPE_MAXHARD ? DRV_HARD : 0) + drv;
+		dsk.type = i;
+		dsk.unit = unit;
+		dsk.slice = slice;
+		dsk.part = part;
 		dsk_meta = 0;
 	    }
-	    if ((i = ep - arg)) {
+	    if ((i = p - arg)) {
 		if ((size_t)i >= sizeof(kname))
 		    return -1;
 		memcpy(kname, arg, i + 1);
@@ -503,18 +548,24 @@
 		if (dp[i].dp_typ == DOSPTYP_386BSD &&
 		    (dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) {
 		    sl = BASE_SLICE + i;
+#ifdef BOOT2_COMPAT_SLICE
 		    if (dp[i].dp_flag & 0x80 ||
 			dsk.slice == COMPATIBILITY_SLICE)
+#else
+		    if (dp[i].dp_flag & 0x80)
+#endif
 			break;
 		}
 	    if (dsk.slice == WHOLE_DISK_SLICE)
 		dsk.slice = sl;
 	}
 	if (sl != WHOLE_DISK_SLICE) {
+#ifdef BOOT2_COMPAT_SLICE
 	    if (sl != COMPATIBILITY_SLICE)
+#endif
 		dp += sl - BASE_SLICE;
 	    if (dp->dp_typ != DOSPTYP_386BSD) {
-		printf("Invalid %s\n", "slice");
+		printf("\nInvalid %s\n", "slice");
 		return -1;
 	    }
 	    dsk.start = dp->dp_start;
@@ -524,7 +575,7 @@
 	d = (void *)(sec + LABELOFFSET);
 	if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) {
 	    if (dsk.part != RAW_PART) {
-		printf("Invalid %s\n", "label");
+		printf("\nInvalid %s\n", "label");
 		return -1;
 	    }
 	} else {
@@ -535,7 +586,7 @@
 	    }
 	    if (dsk.part >= d->d_npartitions ||
 		!d->d_partitions[dsk.part].p_size) {
-		printf("Invalid %s\n", "partition");
+		printf("\nInvalid %s\n", "partition");
 		return -1;
 	    }
 	    dsk.start += d->d_partitions[dsk.part].p_offset;
Index: src/sys/boot/i386/libi386/comconsole.c
===================================================================
RCS file: /home/ncvs/src/sys/boot/i386/libi386/comconsole.c,v
retrieving revision 1.11
diff -u -r1.11 comconsole.c
--- src/sys/boot/i386/libi386/comconsole.c	18 Aug 2005 01:39:43 -0000	1.11
+++ src/sys/boot/i386/libi386/comconsole.c	1 Sep 2005 17:12:16 -0000
@@ -96,6 +96,8 @@
 	    if (speed > 0)
 		comc_curspeed = speed;
 	}
+	if (comc_curspeed == 0)
+	    comc_curspeed = comc_getspeed();
 
 	sprintf(speedbuf, "%d", comc_curspeed);
 	unsetenv("comconsole_speed");
@@ -145,7 +147,7 @@
 {
     int speed;
 
-    if (value == NULL || (speed = comc_parsespeed(value)) <= 0) {
+    if (value == NULL || (speed = comc_parsespeed(value)) < 0) {
 	printf("Invalid speed\n");
 	return (CMD_ERROR);
     }
@@ -162,6 +164,8 @@
 comc_setup(int speed)
 {
 
+    if (speed == 0)
+	return;
     comc_curspeed = speed;
 
     outb(COMPORT + com_cfcr, CFCR_DLAB | COMC_FMT);
@@ -182,7 +186,7 @@
     int speed;
 
     speed = strtol(speedstr, &p, 0);
-    if (p == speedstr || *p != '\0' || speed <= 0)
+    if (p == speedstr || *p != '\0' || speed < 0)
 	return (-1);
 
     return (speed);

--Boundary-00=_q8IIDFjkx3aIz92--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200509081521.14258.jkim>