Re: Installed 5.2RC from CDROM, fails to boot in manager

From: Bruce Evans <bde_at_zeta.org.au>
Date: Mon, 5 Jan 2004 00:23:46 +1100 (EST)
On Fri, 2 Jan 2004, Doug White wrote:

> On Thu, 1 Jan 2004, Clint Olsen wrote:
>
> > On Jan 01, Kevin Oberman wrote:
> > >
> > > Try re-writing the MBR. Use the fixit disk (ISO-2) to bring up th live
> > > system. Then enter the command: boot0cfg -o packet -B ad0
> > >
> > > There are other options you might want to use, but this should work.
> > > (Read the man page.)
> >
> > Thanks for the suggestion.  Incidentally, I did finally get the darn system
> > to boot, but I had to allow fdisk to determine the slices itself.  I
> > checked my old 4.7 machine, and apparently I didn't pay much attention, but
> > it also made 2 unused slices at each ends of the disk with the FreeBSD
> > slice in the middle.  I'd sure like to know why the blank slice is required
> > at the end of the disk...

A blank slice is not required.  Only one slice is required for FreeBSD[1-4]
to be able to determine the geometry, but it must end on a cylinder boundary
as explained in the next paragraph.  (Note that this is a boundary for
virtual cylinder except possibly on 10-20 year old drives.  The BIOS has
its own idea of cylinders, and this is mostly unrelated to both physical
cylinders and the manufacturer's virtual cylinders.  For me, it's always
just whatever I configure the BIOS to.)

> Cylinder alignment.
>
> FreeBSD's fdisk has always had a heck of a time getting disk geometry to
> jive with the BIOS.  The best way to avoid this sort of problem is to
> write the initial partition table with DOS FDISK by creating a dos
> partition that you delete in FreeBSD later.  Since DOS FDISK is using BIOS
> vectors to figure out geometry and such, it get it right as far as the
> BIOS is concerned and thats what matters to boot0.

This seems to have been "fixed" by GEOM in -current.  FreeBSD fdisk now
apparently almost always gets the geometry wrong by not even looking at
the existing partitions, so creating a partition using DOS FDISK doesn't
help.  E.g., for fdisk(8):

Correct output with a de-GEOMed kernel (same as for a pre-GEOM kernel
and a RELENG_4 kernel):
% ******* Working on device /dev/ad0 *******
% parameters extracted from in-core disklabel are:
% cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
%
% parameters to be used for BIOS calculations are:
% cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
%
% Media sector size is 512
% Warning: BIOS sector numbering starts with sector 1
% Information from DOS bootblock is:
% The data for partition 1 is:
% sysid 11 (0x0b),(DOS or Windows 95 with 32 bit FAT)
%     start 63, size 2104452 (1027 Meg), flag 0
% 	beg: cyl 0/ head 1/ sector 1;
% 	end: cyl 130/ head 254/ sector 63
% ...

Here "heads=255" and "sectors/track=63" in the "parameters extracted
from in-core disklabel" are the firmware number of heads and sectors/track
adjusted to match the numbers in the partition table.  For current
model ATA drives, the firmware numbers are always heads=16 and
sectors/track=63 (this is from a standardisation of manufacturers's
virtual cylinders).  The above is for an old 6.4GB drive.  The drive
is still new enough to have H=16 and S=63.  However, it was partitioned
when virtual cylinders with H=255 and S=63 was the most common BIOS
configuration and the partitioning uses this.  This is reflected in
the ending head and sector values for the partition shown (and other
partitions, but they all have the same ending head and sector values,
as they must to avoid ambiguity).  The kernel essentially just converts
'head 254 / sector 63" to H=255 S=63.

The "parameters to be used for BIOS calculations" are just copies of
the "parameters extracted from in-core disklabel".  The parameters
actually have nothing to do with the in-core disk label except that
they were stored there in FreeBSD[1-4].  Now they aren't even extracted
from there, except as a fallback in my version of fdisk(8).  They are
determined using the DIOCGFWHEADS and DIOCFWSECTORS ioctls.  My version
falls back to reading the disk label if these ioctls fail, so that it
works with old kernels.

Broken output with a -current kernel:
% ******* Working on device /dev/ad0 *******
% parameters extracted from in-core disklabel are:
% cylinders=13328 heads=15 sectors/track=63 (945 blks/cyl)
%
% Figures below won't work with BIOS for partitions not in cyl 1
% parameters to be used for BIOS calculations are:
% cylinders=13328 heads=15 sectors/track=63 (945 blks/cyl)
%
% Media sector size is 512
% Warning: BIOS sector numbering starts with sector 1
% Information from DOS bootblock is:
% The data for partition 1 is:
% sysid 11 (0x0b),(DOS or Windows 95 with 32 bit FAT)
%     start 63, size 2104452 (1027 Meg), flag 0
% 	beg: cyl 0/ head 1/ sector 1;
% 	end: cyl 130/ head 254/ sector 63

In -current/GEOM the DIOCGFWHEADS and DIOCFWSECTORS ioctls apparently
return the actual FW (firmware) values.  These are not useful in fdisk,
and fdisk doesn't know how to find correct ones, so the geometry is
just wrong.  If there are no partitions, then fdisk has no way to
determine the geometry (you have to type it in or risk using the
firmware geometry).  If there is a partition that ends on a cylinder
boundary according to the BIOS's idea of the geometry, then fdisk could
determine the geometry in they same way that the kernel used to, but
it shouldn't have to.  The code for this was intentionally put in the
kernel so that all fdisk-like programs don't need to duplicate it.

I don't use sysinstall(8), so I don't know exactly what its internal
fdisk does, but it seems to be even more broken in this area.  E.g., in
disks.c:

% static void
% print_chunks(Disk *d, int u)
% {
%     int row;
%     int i;
%     int sz;
%     char *szstr;
%
%     szstr = (u == UNIT_GIG ? "GB" : (u == UNIT_MEG ? "MB" :
% 	(u == UNIT_KILO ? "KB" : "ST")));
%
%     for (i = Total = 0; chunk_info[i]; i++)
% 	Total += chunk_info[i]->size;
% #ifdef PC98
%     if (d->bios_cyl >= 65536 || d->bios_hd > 16 || d->bios_sect >= 256) {
% #else
%     if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) {
% #endif

This sanity check is completely insane.  It is guaranteed not to be satisfied
by any drive larger than 33 disk-manufacturers-GB in the !PC98 case, and
by any drive larger than 137 d-m-GB in the PC98 case.  Thus it is guaranteed
not to be satisfied by any new drive that you can reasonbly buy in the !PC98
case, and by 160GB+ drives in the PC98 case.  In RELENG_4, not accepting
d_bios_hd values up to 255 is a bug since the kernel-determined geometry
will often have such values.  In -current, a "firmware" value of 16 for
d_bios_hd would maje the d_bios_hd check pass but ensure that the
d_bios_cyl check fails for all current model drives.  A limit of 65536
on d_bios_cyl is just wrong for drives larger than 137GB.  (137GB was a
hardware limit for ATA drives until recently.  I don't know how BIOSes
support drives larger than this.)

% 	dialog_clear_norefresh();
% 	msgConfirm("WARNING:  A geometry of %lu/%lu/%lu for %s is incorrect.  Using\n"
% 		   "a more likely geometry.  If this geometry is incorrect or you\n"
% 		   "are unsure as to whether or not it's correct, please consult\n"
% 		   "the Hardware Guide in the Documentation submenu or use the\n"
% 		   "(G)eometry command to change it now.\n\n"
% 		   "Remember: you need to enter whatever your BIOS thinks the\n"
% 		   "geometry is!  For IDE, it's what you were told in the BIOS\n"
% 		   "setup. For SCSI, it's the translation mode your controller is\n"
% 		   "using.  Do NOT use a ``physical geometry''.",
% 	  d->bios_cyl, d->bios_hd, d->bios_sect, d->name);

Since the sanity check is insane, the user is almost always presented with
the above alarming message.

% 	Sanitize_Bios_Geom(d);

This function is mostly insane, but ends up doing something reasonable for
large drives (it almost always considers the geometry to be insane, then
adjusts it to a sane geometry (but one that is insane according to the
above check):

    C = (size / H / S)
	(sure to be > 65536 if the drive is larger than 137GN)
	(but C is mostly irrelevant for fdisk)
    H = 255
    S = initial value (usually 63)

%     }

I usually have no problems with this stuff, but recently created some
bad partition tables by swapping disks into a new system.  The disks
had been partitioned with H=255/C=63 and the BIOS configuration was
"AUTO" for both motherboards.  The first motherboard (ASUS A7V266-E)
got this right, but the second motherboard (ASUS A7N8X-E) somehow
got a geometry of H=240/C=63.  Creating partitions using WinXP
actually used the BIOS geometry and made a mess.  The second motherboard
had to be changed to something like "Large" mode to get H=255.  The
first motherboard has a very nice set of options for configuring
geometries: { LBA, Large, Normal, Match Partition Table, Manual }.
("Manual" gives the old configuration method where you can set
everything.  "Match Partition Table" gives exactly what FreeBSD fdisk
used to do.  Many disk BIOSes do this, but I haven't seen an option
to configure it before.)  The second motherboard had a not so nice
set of options for configuring geometries IIRC.

Bruce
Received on Sun Jan 04 2004 - 04:24:06 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:36 UTC