Subject: Re: bootable 3.0_BETA CD-ROM image
To: None <port-sgimips@NetBSD.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-sgimips
Date: 09/12/2005 03:06:15
In article <050911055036.M0121068@mirage.ceres.dti.ne.jp>
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;
}
---