svn commit: r194241 - head/lib/libdisk

Bruce Evans brde at
Tue Jun 16 01:13:02 UTC 2009

On Mon, 15 Jun 2009, Ulf Lilleengen wrote:

> Marcel Moolenaar wrote:
>> On Jun 15, 2009, at 9:18 AM, Ulf Lilleengen wrote:
>>> Author: lulf
>>> Date: Mon Jun 15 16:18:24 2009
>>> New Revision: 194241
>>> URL:
>>> Log:
>>>  - Relax sanitazion requirements in libdisk, as a previous commit
>>> enabling this
>>>    sanitization broke sysinstall on some disks.  This was due to the
>>> disks
>>>    reporting a geometry that was incorrectly sanitized by sysinstall.
>>> This makes
>>>    the sanitization consistent with fdisk.
>> *snip*
>>> +    if (disk->bios_hd > 256)
>>>         sane = 0;
>> The number of heads cannot exceed 255. There are only 8-bits
>> in which the number of heads is stored. This also applies to
>> PC98, BTW.

No, the number of heads can be 256 except in certain broken APIs and
BIOSes.  The broken APIs don't include fdisk tables, since the maximum
number of heads isn't stored.  Only the maximum head number is stored.
Head numbers are 0-based, so their maximum is 1 less than the number
of heads.  The maximum head number of 255 fits in the 8 bits in an
fdisk table.

Most of the original int 0x13 BIOS interfaces are similar.  E.g., AH = 8
(read drive parameters) returns the maximum for each CHS value.  C and
H values are 0-based, so their max is one less than their number.
S values are bogusly 1-based, so their max is the same as their total.
AH = 2 (read sectors) and AH = 3 (write sectors) naturally pass the
(current) head number (in an 8-bit register), so they never need to
represent 256 in the 8-bit register.

The only broken API that I remember the int 0x41 and 0x46 pseudo-interrupts.
These may be only de-facto (I can't find them in the Phoenix BIOS book
copyright 1987-1991), but before about 1990 the int 0x13 AH=8 interface
was often not implemented and int 0x41 and int 0x46 worked better.  The
IDT entry for ints 0x41 and 0x46 contains a pointer to a table with the
following data (0x41 for hard disk 0 and 0x46 for hard disk 1): from
the header file for Minix "wini" disk drivers:

/* BIOS table layout. */
typedef char wn_biosdrive[16];
#define WN_CYLINDERS(t)		(* (unsigned short *) (&(t)[0x0]))
#define WN_HEADS(t)		(* (unsigned char *)  (&(t)[0x2]))
#define WN_PRECOMP(t)		(* (unsigned short *) (&(t)[0x5]))
#define WN_CTLBYTE(t)		(* (unsigned char *)  (&(t)[0x8]))
#define WN_LANDINGZONE(t)	(* (unsigned short *) (&(t)[0xc]))
#define WN_SECTORS(t)		(* (unsigned char *)  (&(t)[0xe]))

Many or most 1990's BIOSes present precisely this table for you to edit
in their setup.  They present many possibilities for obselete (even in
1990's) disks from arrays of this table in ROM, and at least 1 modifiable
table per disk in CMOS.

Since the head number is for the number of heads, and the table entry
for it has type unsigned char, 256 heads does't fit, it becomes 0.
Non-broken software would unwrap 0 back to 0 256 and just work, but
having 256 (virtual) heads is not very useful so configuring it
should be avoided.

Apparently, some newer BIOSes know that they are non-broken here (or
maybe for cylinder numbers), and default to larger numbers.  Such
defaults should still be avoided in case you want to move the disk
to a machine with a BIOS that doesn't support them.

I once tried to standardize on the maximum possible number of heads
(256), but had to switch to 255 when 256 failed on only some machines.
I still use 255 on all machines.  With 2000's BIOSes this requires
ignoring BIOS defaults and/or selecting so-called LBA mode in BIOS
configurations.  FreeBSD doesn't know the BIOS defaults anyway; it
gives different defaults (except in my version) which I ignore.

Many 2000's BIOSes produce defaults for the number of sectors that can't
possibly work in fdisk tables since they significantly exceed 63.
Selecting LBA mode always avoids this for me (LBA CHS = xxx/255/63).
I don't know how misconfigurations from this are usually avoided.

> Aha, so I should fix fdisk too then. Thanks.

Please don't break fdisk too.  There must be a way to set valid but
dangerous values, or theoretically invalid but practically working
values, if they are representable and are needed for compatibility.


More information about the svn-src-all mailing list