Subject: Re: bootable 3.0_BETA CD-ROM image
To: None <>
From: Izumi Tsutsui <>
List: port-sgimips
Date: 09/12/2005 03:06:15
In article <>
I wrote:

> It's not ahc(4) specific (also happens on esiop(4)), and only occurs
> on CD-ROM which has SGI volhdr. The problem is caused by inconsistency
> of blocksize (512 or 2048) handling on ARCBIOS (volhdr), MD disklabel(9)
> and MI cd(4), but I'm still wondering how to fix/handle it properly.

(a) "resource shortage" message is caused because
    sys/dev/ic/aic7xxx_osm.c:ahc_setup_data() is called with
    xs->datalen == 0x10800 (> MAXPHYS) and bus_dmamap_load(9) fails.
    This also happens even I decrease maximum xfer size in ahc_minphys().

(b) MI cd(4) uses d_secsize in struct disklabel to determine
    blocksize of the CD media. If d_secsize is not match with
    the real blocksize (typically 2048), it causes problem (a).
    (I don't track this very well though)

(c) On mounting a normal CD-ROM, it doesn't have any native label so
    the default label created by sys/dev/scsipi/cd.c:cdgetdefaultlabel()
    is used and in this case d_secsize set to 2048 bytes by default.
    There is no problem with this value.

(d) On the other hand, the sgimips bootable CD image has an
    SGI volume header. If the disk has the header, MD readdisklabel(9)
    creates BSD disklabel from values in the volume header, and
    d_secsize in struct disklabel is taken from dp.dp_secbytes
    in struct sgi_boot_devparms.

(e) sgivol(8) utility always uses 512bytes for dp_secbytes on creating
    default volhdr. Then d_secsize in the disklabel taken from
    the bootable image is set to 512 bytes.
    This causes the problem (b) and (a).

I thought we could fix the problem if (e) was fixed, i.e. use 2048bytes
on creating volhdr for bootable image, but it causes other problems:

(f) MI cd(4) uses b_secsize to calculate a byte offset for each
    partition. So if b_secsize is changed from 512 to 2048,
    we also have to adjust p_offset values for each partitions,
    otherwise we cannot mount partitions whose offset != 0.

(g) p_offset values in struct disklabel are taken from the "first"
    member in struct sgi_boot_block (defined in <sys/bootblock.h>),
    so we have to change sgivol(8) to write ajusted values for
    2048bytes/sector disk images.

(h) But the ARCS firmware seems to ignore the dp_secbytes value.
    If the "first" (offset) values are adjusted for 2048bytes/sector,
    the ARCS fails to open the partition, so bootloaders (ip?xboot)
    can't load kernels on the partition.

I added a workaround to MD disklabel(9) handling for (f) and (h),
i.e. in disklabel_sgimips_to_bsd() and disklabel_bsd_to_sgimips()
adjust p_offset values on converting from the "first" in volhdr
if dp_secbytes (d_secsize) is 2048 (patch attached), but
I think it's a bit ugly.

There are also some minor problems:

(i) In spite of (f), MI cd(4) (and all other devices?) uses
    DEV_BSIZE (==512) to caluclate partition size.
    This means we shouldn't adjuct p_size values in
    struct disklabel even if b_secsize != 512.

(j) sgivol(8) calculates a size of partition a from a size of
    the opened device, so on creating a bootable image,
    the image has enough size on creating sgi volhdr.
    If it doesn't some files located at the end of the image
    can't be read.

(k) The CD image which has volhdr can't be mounted on other ports.
    Is it better to make volhdr size to 32Kbytes (for iso9660,
    even 8Kbytes is better for FFS?) and prepare the primary boot
    to load ip?xboot as the secondary boot from root file system?
    (I'm not sure if it's possible though)
Izumi Tsutsui

Index: sys/arch/sgimips/sgimips/disksubr.c
RCS file: /cvsroot/src/sys/arch/sgimips/sgimips/disksubr.c,v
retrieving revision 1.14
diff -u -r1.14 disksubr.c
--- sys/arch/sgimips/sgimips/disksubr.c	24 Nov 2004 21:59:32 -0000	1.14
+++ sys/arch/sgimips/sgimips/disksubr.c	11 Sep 2005 17:41:26 -0000
@@ -331,6 +331,9 @@
 		lpp = &lp->d_partitions[bp];
 		lpp->p_offset = vh->partitions[mp].first;
+		/* XXX ARCS ignores dp_secbytes on calculating offsets */
+		if (vh->dp.dp_secbytes == 2048)
+			lpp->p_offset /= 2048 / 512;
 		lpp->p_size = vh->partitions[mp].blocks;
 		lpp->p_fstype = partition_map[i].bsd_type;
 		if (lpp->p_fstype == FS_BSDFFS) {
@@ -379,6 +382,9 @@
 		lpp = &lp->d_partitions[bp];
 		vh->partitions[mp].first = lpp->p_offset;
+		/* XXX ARCS ignores dp_secbytes on calculating offsets */
+		if (lp->d_secsize == 2048)
+			vh->partitions[mp].first *= 2048 / 512;
 		vh->partitions[mp].blocks = lpp->p_size;
 		vh->partitions[mp].type = partition_map[i].mips_type;