NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
port-i386/46583: BIOS bootloader problems with partitions that start above 1TB
>Number: 46583
>Category: port-i386
>Synopsis: BIOS bootloader problems with partitions that start above 1TB
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: port-i386-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Jun 11 07:30:01 +0000 2012
>Originator: Dave Huang
>Release: NetBSD 6.99.7
>Organization:
Name: Dave Huang | Mammal, mammal / their names are called /
INet: khym%azeotrope.org@localhost | they raise a paw / the bat, the cat /
FurryMUCK: Dahan | dolphin and dog / koala bear and hog -- TMBG
Dahan: Hani G Y+C 36 Y++ L+++ W- C++ T++ A+ E+ S++ V++ F- Q+++ P+ B+ PA+ PL++
>Environment:
NetBSD/x86 BIOS Boot, Revision 5.9 (from NetBSD 6.0_BETA2)
>Description:
The x86 BIOS bootloader has an integer overflow bug that
causes it to not see MBR partitions that start above 1TB (2^31 512-byte
blocks), even though the limit on MBR partitions is 2TB.
>How-To-Repeat:
Partition a disk with MBR-style partitioning and create a
NetBSD partition with a start LBA above 2^31, install the bootloader,
copy a kernel to the partition, and attempt to boot.
For example:
Disk: /dev/rwd1d
NetBSD disklabel disk geometry:
cylinders: 3876021, heads: 16, sectors/track: 63 (1008 sectors/cylinder)
total sectors: 3907029168
BIOS disk geometry:
cylinders: 1023, heads: 255, sectors/track: 63 (16065 sectors/cylinder)
total sectors: 3907029168
Partitions aligned to 2048 sector boundaries, offset 63
Partition table:
0: NTFS, OS/2 HPFS, QNX2 or Advanced UNIX (sysid 7)
start 206848, size 3824902144 (1867628 MB, Cyls 12/223/20-238102/5/47)
1: NetBSD (sysid 169)
start 3825108992, size 81920176 (40000 MB, Cyls
238102/5/48-243201/80/63), Active
2: <UNUSED>
3: <UNUSED>
First active partition: 1
Drive serial number: 2051726421 (0x7a4adc55)
When attempting to boot, the bootloader will run, but will be unable
to find the kernel, or even the partition that the kernel is on:
booting hd0a:netbsd - starting in 0 seconds.
open netbsd: Input/output error
boot: hd0a:netbsd: Input/output error
booting hd0a:netbsd.gz
open netbsd.gz: Input/output error
boot: hd0a:netbsd.gz: Input/output error
> dev
disk hd0 size 1863 GB
[ note that no partitions are listed ]
Compiling the bootloader with -DDISK_DEBUG shows that the sector
number is overflowing a signed 32-bit int:
ptn type 7 in sector 206848
ptn type 169 in sector -469858304
read error dblk -469858303--469858286
>Fix:
Not sure whether uint32_t or daddr_t is more correct--I went with the
former, since MBR partition LBAs are 32 bits.
Index: sys/arch/i386/stand/lib/biosdisk.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/stand/lib/biosdisk.c,v
retrieving revision 1.40
diff -u -p -r1.40 biosdisk.c
--- sys/arch/i386/stand/lib/biosdisk.c 16 Jan 2012 18:47:57 -0000 1.40
+++ sys/arch/i386/stand/lib/biosdisk.c 11 Jun 2012 07:03:04 -0000
@@ -414,7 +414,7 @@ read_minix_subp(struct biosdisk *d, stru
if (readsects(&d->ll, sector, 1, d->buf, 0)) {
#ifdef DISK_DEBUG
- printf("Error reading MFS sector %d\n", sector);
+ printf("Error reading MFS sector %ld\n", (long)sector);
#endif
return EIO;
}
@@ -443,10 +443,11 @@ read_label(struct biosdisk *d)
struct disklabel dflt_lbl;
struct mbr_partition mbr[MBR_PART_COUNT];
struct partition *p;
- int sector, i;
+ uint32_t sector;
+ int i;
int error;
int typ;
- int ext_base, this_ext, next_ext;
+ uint32_t ext_base, this_ext, next_ext;
#ifdef COMPAT_386BSD_MBRPART
int sector_386bsd = -1;
#endif
@@ -471,7 +472,7 @@ read_label(struct biosdisk *d)
next_ext = 0;
if (readsects(&d->ll, this_ext, 1, d->buf, 0)) {
#ifdef DISK_DEBUG
- printf("error reading MBR sector %d\n", this_ext);
+ printf("error reading MBR sector %u\n", this_ext);
#endif
return EIO;
}
@@ -484,7 +485,7 @@ read_label(struct biosdisk *d)
continue;
sector = this_ext + mbr[i].mbrp_start;
#ifdef DISK_DEBUG
- printf("ptn type %d in sector %d\n", typ, sector);
+ printf("ptn type %d in sector %u\n", typ, sector);
#endif
if (typ == MBR_PTYPE_MINIX_14B) {
if (!read_minix_subp(d, &dflt_lbl,
>Unformatted:
Home |
Main Index |
Thread Index |
Old Index