[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Disk unit mixup for bootdev in i386_dkcsum.c::dkcsumattach() - BUG & FIX
OpenBSD/i386 3.5 RELEASE BOOT 2.06
Got a final kernel quickfix to solve the bootdev mixup problem
for "config root swap generic" autoconfiguration RELEASEs
om multi-disk i386 machines.
This change to dkcsum.c tries to account for most of the
following combinations:
1. different System BIOS boot setups
2. different BOOTblock versions, without depending
on specific BOOTARG_APIVER arguments
3. boxes with mixed SCSI and IDE disks on different
channels, different controllers and
different system (PCI, ISA) buses
Since I can only test this on a machine with 3 IDE
disks on 3 IDE-channels on 2 PCI buses, it would be nice
if someone with (additional) SCSI disks could test
this patch too. I expect this to solve many of the reported
problems with generic auto-configured booting on
systems with add-on diskcontrollers.
Maybe the development team could weigh this for
possible inclusion in future releases. Todd ?
Anyway, this patch fixed my problem with following setup,
where OBSD is installed on the wd0 disk (attached to
a Promise Ultra IDE PCI add-on card), and the loaded
/bsd would fail to mount root on wd0a without it:
dkcsum: wd0 matched BIOS disk 82
wd1: no disk label
dkcsum: wd1 matched BIOS disk 80
wd2: no disk label
dkcsum: wd2 matched BIOS disk 81
Here's my diff for
sys/arch/i386/i386/dkcsum.c
*** dkcsum.c.ORG Tue Jun 3 22:31:07 2003
--- dkcsum.c Fri Jun 18 10:23:37 2004
***************
*** 62,72 ****
--- 62,79 ----
int error;
u_int32_t csum;
bios_diskinfo_t *bdi, *hit;
+ dev_t bootsbootdev;
+ dev_t altbootdev;
+ int isbootdevfixed;
/* do nothing if no diskinfo passed from /boot, or a bad length */
if (bios_diskinfo == NULL || bios_cksumlen * DEV_BSIZE > MAXBSIZE)
return;
+ bootsbootdev = bootdev;
+ altbootdev = 0;
+ isbootdevfixed = 0;
+
/*
* XXX Whatif DEV_BSIZE is changed to something else than the BIOS
* blocksize? Today, /boot doesn't cover that case so neither need
***************
*** 165,191 ****
/* Fixup bootdev if units match. This means that all of
* hd*, sd*, wd*, will be interpreted the same. Not 100%
! * backwards compatible, but sd* and wd* should be phased-
* out in the bootblocks.
*/
! if (B_UNIT(bootdev) == (hit->bios_number & 0x7F)) {
int type, ctrl, adap, part, unit;
! /* Translate to MAKEBOOTDEV() style */
type = major(bp->b_dev);
! adap = B_ADAPTOR(bootdev);
! ctrl = B_CONTROLLER(bootdev);
unit = DISKUNIT(bp->b_dev);
! part = B_PARTITION(bootdev);
bootdev = MAKEBOOTDEV(type, ctrl, adap, unit, part);
}
/* This will overwrite /boot's guess, just so you remember */
hit->bsd_dev = MAKEBOOTDEV(major(bp->b_dev), 0, 0,
DISKUNIT(bp->b_dev), RAW_PART);
hit->flags |= BDI_PICKED;
}
bp->b_flags |= B_INVAL;
brelse(bp);
}
--- 172,218 ----
/* Fixup bootdev if units match. This means that all of
* hd*, sd*, wd*, will be interpreted the same. Not 100%
! * backward compatible, but sd* and wd* should be phased-
* out in the bootblocks.
*/
! /* Support B_TYPE dependent hd unit counting bootblocks */
! /* 3.5 RELEASEd BOOT 2.06 May 2004 still is one of these ? */
! if ((B_TYPE(bootsbootdev) == B_TYPE(hit->bsd_dev)) &&
! (B_UNIT(bootsbootdev) == B_UNIT(hit->bsd_dev))) {
int type, ctrl, adap, part, unit;
! /* Rewrite, keep MAKEBOOTDEV() style */
type = major(bp->b_dev);
! adap = B_ADAPTOR(bootsbootdev);
! ctrl = B_CONTROLLER(bootsbootdev);
unit = DISKUNIT(bp->b_dev);
! part = B_PARTITION(bootsbootdev);
bootdev = MAKEBOOTDEV(type, ctrl, adap, unit, part);
+ isbootdevfixed = 1;
}
+ /* Support B_TYPE independent hd unit counting bootblocks */
+ if (B_UNIT(bootsbootdev) == (hit->bios_number & 0x7F)) {
+ int type, ctrl, adap, part, unit;
+ type = major(bp->b_dev);
+ adap = B_ADAPTOR(bootsbootdev);
+ ctrl = B_CONTROLLER(bootsbootdev);
+ unit = DISKUNIT(bp->b_dev);
+ part = B_PARTITION(bootsbootdev);
+
+ altbootdev = MAKEBOOTDEV(type, ctrl, adap, unit, part);
+ }
+
/* This will overwrite /boot's guess, just so you remember */
hit->bsd_dev = MAKEBOOTDEV(major(bp->b_dev), 0, 0,
DISKUNIT(bp->b_dev), RAW_PART);
hit->flags |= BDI_PICKED;
}
+
+ if (altbootdev && !isbootdevfixed)
+ bootdev = altbootdev;
+
bp->b_flags |= B_INVAL;
brelse(bp);
}