[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-bugs
Subject:    user/947: Handle over 8G. with fdisk
From:       sigh () kuzirabekon ! econ ! nagasaki-u ! ac ! jp
Date:       1999-10-18 12:20:13
[Download RAW message or body]


>Number:         947
>Category:       user
>Synopsis:       fdisk can not handle disk over 8G. well.
>Confidential:   yes
>Severity:       non-critical
>Priority:       medium
>Responsible:    bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Oct 18 06:30:02 MDT 1999
>Last-Modified:
>Originator:     SUZUKI Hitoshi
>Organization:
sigh@net.nagasaki-u.ac.jp
Faculty of Economics, Nagasaki Univ.
>Release:        OpenBSD-current/i386
>Environment:
	System      : OpenBSD 2.6
	Architecture: OpenBSD.i386
	Machine     : i386
>Description:
There is missing entry in /usr/src/sys/arch/powerpc/include/disklabel.h
#define DOSPTYP_FAT32L	0x0c		/* 32-bit FAT, LBA-mapped */

fdisk -c, -h options argument checking is wrong.
Both minimum are 1.

To handle large disk and partiton beyond 8G.,
loosen cylinder maximum to 262144 (2^18).
Note. 18=32-(8+6)
# In   PC BIOS IDE Disk LBA mode.
# c:     10bit    16bit   N.A.
# h:      8bit     4bit   N.A.
# s:      6bit     8bit   N.A. 
# total: 24bit    28bit 32bit   

There is another extended partition id in DOS after Windows 95.
Add new entry to
/usr/src/sys/arch/{i386,arc,powerpc,alpha}/include/disklabel.h 
#define DOSPTYP_EXTENDL 0x0f		/* Extended, LBA-mapped; contains sub-partitions */

Newer bios (and some OSs) will handle DOS partition beyond 8G. as
0x0c (32-bit FAT), 0x0e (16-bit FAT), 0x0f (extended).

Be nice to partition pass 8G., now boot strap in CHS mode
has chance to boot up.

>How-To-Repeat:
	
>Fix:
Add missing entry to /usr/src/sys/arch/powerpc/include/disklabel.h
#define DOSPTYP_FAT32L	0x0c		/* 32-bit FAT, LBA-mapped */
Add new entry to
/usr/src/sys/arch/{i386,arc,powerpc,alpha}/include/disklabel.h 
#define DOSPTYP_EXTENDL 0x0f		/* Extended, LBA-mapped; contains sub-partitions */
Here is quick patch.
diff -u /usr/src/sbin/fdisk/cmd.c ./cmd.c
--- /usr/src/sbin/fdisk/cmd.c	Mon Aug 23 09:40:13 1999
+++ ./cmd.c	Mon Oct 18 19:13:21 1999
@@ -169,6 +169,8 @@
 		EDIT("BIOS Ending sector",     ASK_DEC, pp->esect, 1, maxsect, NULL);
 		/* Fix up off/size values */
 		PRT_fix_BN(disk, pp);
+		/* Fix up CHS values for LBA */
+		PRT_fix_CHS(disk, pp);
 	} else {
 		u_int m;
 
diff -u /usr/src/sbin/fdisk/disk.c ./disk.c
--- /usr/src/sbin/fdisk/disk.c	Tue Oct 28 19:06:32 1997
+++ ./disk.c	Mon Oct 18 19:06:02 1999
@@ -211,7 +211,7 @@
 	 * Or we need a mapping from biosdev -> BSD universe.
 	 */
 	if (disk->bios)
-		if (disk->real->cylinders > 1024 || disk->real->heads > 255 ||
+		if (disk->real->cylinders > 262144 || disk->real->heads > 255 ||
 		    disk->real->sectors > 63)
 			disk->real = disk->bios;
 
diff -u /usr/src/sbin/fdisk/fdisk.c ./fdisk.c
--- /usr/src/sbin/fdisk/fdisk.c	Mon Sep 14 12:54:34 1998
+++ ./fdisk.c	Mon Oct 18 20:49:21 1999
@@ -87,12 +87,12 @@
 			break;
 		case 'c':
 			c_arg = atoi(optarg);
-			if (c_arg < 0 || c_arg > 1023)
+			if (c_arg < 1 || c_arg > 262144)
 				errx(1, "Cylinder argument out of range.");
 			break;
 		case 'h':
 			h_arg = atoi(optarg);
-			if (h_arg < 0 || h_arg > 255)
+			if (h_arg < 1 || h_arg > 255)
 				errx(1, "Head argument out of range.");
 			break;
 		case 's':
@@ -117,24 +117,19 @@
 	if (c_arg | h_arg | s_arg) {
 		usermetrics = malloc(sizeof(DISK_metrics));
 		if (usermetrics != NULL) {
-			if (c_arg)
+			if (c_arg && h_arg && s_arg) {
 				usermetrics->cylinders = c_arg;
-			else
-				errx(1, "Please specify a full geometry with [-chs].");
-			if (h_arg)
 				usermetrics->heads = h_arg;
-			else
-				errx(1, "Please specify a full geometry with [-chs].");
-			if (s_arg)
 				usermetrics->sectors = s_arg;
-			else
+				usermetrics->size = c_arg * h_arg * s_arg;
+			} else
 				errx(1, "Please specify a full geometry with [-chs].");
 		}
-		usermetrics->size = c_arg * h_arg * s_arg;
 	} else
 		usermetrics = NULL;
 
 	/* Get the geometry */
+	disk.real = NULL;
 	if (DISK_getmetrics(&disk, usermetrics))
 		errx(1, "Can't get disk geometry, please use [-chs] to specify.");
 
diff -u /usr/src/sbin/fdisk/part.c ./part.c
--- /usr/src/sbin/fdisk/part.c	Fri Jul 23 22:21:38 1999
+++ ./part.c	Mon Oct 18 20:33:24 1999
@@ -137,19 +137,7 @@
 {
 	unsigned char *p = prt;
 	off_t off;
-	int need_fix_chs = 0;
 
-	/* dont check fields 0 and 4, they are flag and id, always preserved */
-	if ((p[1] == 0xff) && 
-	    (p[2] == 0xff) && 
-	    (p[3] == 0xff) && 
-	    (p[5] == 0xff) && 
-	    (p[6] == 0xff) && 
-	    (p[7] == 0xff))
-	{
-		/* CHS values invalid */
-		need_fix_chs =1;
-	}
 	partn->flag = *p++;
 	partn->shead = *p++;
 
@@ -163,15 +151,15 @@
 	partn->ecyl = ((*p << 2) & 0xFF00) | (*(p+1));
 	p += 2;
 
-	off = partn->id != DOSPTYP_EXTEND ? offset : reloff;
+	if ((partn->id == DOSPTYP_EXTEND) || (partn->id == DOSPTYP_EXTENDL))
+		off = reloff;
+	else
+		off = offset;
 
 	partn->bs = getlong(p) + off;
 	partn->ns = getlong(p+4);
 
-	if (need_fix_chs == 1) {
-		printf("warning MBR CHS values invalid, translating LBA values\n");
-		PRT_fix_CHS(disk, partn);
-	}
+	PRT_fix_CHS(disk, partn);
 }
 
 int
@@ -197,7 +185,25 @@
 	void *prt;
 {
 	unsigned char *p = prt;
-	off_t off = partn->id != DOSPTYP_EXTEND ? offset : reloff; 
+	prt_t tmp;
+	tmp.shead = (partn->shead > 1024)? 1023: partn->shead;
+	tmp.ssect = partn->ssect;
+	tmp.scyl = partn->scyl; 
+	tmp.ehead = (partn->ehead > 1024)? 1023: partn->ehead;
+	tmp.esect = partn->ssect;
+	tmp.ecyl = partn->scyl; 
+	if (!PRT_check_chs(partn) && PRT_check_chs(&tmp)) {
+		partn->shead = tmp.shead;
+		partn->ssect = tmp.ssect;
+		partn->scyl = tmp.scyl;
+		partn->ehead = tmp.ehead;
+		partn->esect = tmp.esect;
+		partn->ecyl = tmp.ecyl;
+	}
+	if ((partn->id == DOSPTYP_EXTEND) || (partn->id == DOSPTYP_EXTENDL))
+		off = reloff;
+	else
+		off = offset;
 
 	if (PRT_check_chs(partn)) {
 		*p++ = partn->flag & 0xFF;
@@ -302,6 +308,10 @@
 	head = (start / spt); start -= (head * spt);
 	sect = (start + 1);
 
+	if (cyl > 1023) {
+		cyl = 1023;
+		printf("Only LBA values are valid in starting cylinder.\n");
+	}
 	part->scyl = cyl;
 	part->shead = head;
 	part->ssect = sect;
@@ -311,6 +321,10 @@
 	head = (end / spt); end -= (head * spt);
 	sect = (end + 1);
 
+	if (cyl > 1023) {
+		cyl = 1023;
+		printf("Only LBA values are valid in ending cylinder.\n");
+	}
 	part->ecyl = cyl;
 	part->ehead = head;
 	part->esect = sect;

>Audit-Trail:
>Unformatted:

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic