NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-hp300/54455 (hp300 ISO should be encapsulated in LIF to be bootable)



The following reply was made to PR port-hp300/54455; it has been noted by GNATS.

From: Izumi Tsutsui <tsutsui%ceres.dti.ne.jp@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: netbsd-bugs%netbsd.org@localhost, tsutsui%ceres.dti.ne.jp@localhost
Subject: Re: port-hp300/54455 (hp300 ISO should be encapsulated in LIF to be
	 bootable)
Date: Fri, 17 May 2024 02:43:40 +0900

 I've managed to get working hp300 installcd.
 
 I wrote:
 > Synopsis: hp300 ISO should be encapsulated in LIF to be bootable
  :
 > - concept confirmed (using a different approach from OpenBSD/hp300)
 >   https://www.youtube.com/watch?v=seHEeoup6P0
 >  - prepare a new uboot binary without LIF volume but only LIF file header
 >    (four bytes entry address and four bytes file size at the top)
 
 This is not necessary, we can just add size of LIF volume and directory
 (8192 bytes) to a block number in LIF directory entry as extra offset.
 
 >  - put the uboot binary for CD on in a boot ISO by makefs(8)
 >   - in ISO9660 all blocks for each file are contiguously allocated
 >     so we can directly specify it in the LIF directory entry
 >     without a boot partition
 
 See attached diffs below.
 
 >  - prepare LIF volume and directory entry in the boot ISO
 >  - write a block number of the uboot in the ISO image to
 >    a directory entry in the LIF header
 
 It turns out current installboot(8) already has these support.
 
 > - needs to implement host tools to prepare necessary data in a boot ISO
 >  - hp300/stand/mkboot option to add only LIF file header (no LIF volume)
 
 This is not necessary, as noted above.
 
 >  - installboot support to detect block and length of a file in ISO9660 fs
 >    as src/distrib/cdrom/macppc_installboot does
 
 See the attached diffs.
 
 I've also pushed all commits with full logs to my github:
  https://github.com/tsutsui/netbsd-src/compare/689d5906...tsutsui:netbsd-src:tsutsui-hp300-cdboot-rebase
 
 - sys/arch/hp300/stand/mkboot/Makefile
  - enable SUPPORT_CD
 
 - sys/fs/cd9660
  - make cd9660_util.c usable with cd9660_extern.h from userland
 
 - tools/Makefile.nbincludes
  - install cd9660 sys headers for tools installboot build
    (XXX: should we install these ones into /usr/include/fs ?)
 
 - usr.sbin/installboot
  - add cd9660 support to -t option
  - make arch/hp300.c use it to make CD ISO bootable
 
 - distrib/hp300/cdroms/installcd/Makefile
  - install RAMDISK kernel and bootloader for hp300 installcd
 
 - distrib/cdrom/macppc_installboot
  - sync with usr.sbin/installboot/cd9660.c, for future merge
 
 ---
 diff --git a/distrib/cdrom/macppc_installboot/Makefile b/distrib/cdrom/macppc_installboot/Makefile
 index dcc9df2aa9c5..4bb078685c9d 100644
 --- a/distrib/cdrom/macppc_installboot/Makefile
 +++ b/distrib/cdrom/macppc_installboot/Makefile
 @@ -16,6 +16,7 @@ HOST_CPPFLAGS+=	-I. -I${.CURDIR}
  	${HOST_INSTALL_DIR} fs/cd9660
  	${HOST_LN} -s ${NETBSDSRCDIR}/sys/fs/unicode.h fs
  	${HOST_LN} -s ${NETBSDSRCDIR}/sys/fs/cd9660/iso.h fs/cd9660
 +	${HOST_LN} -s ${NETBSDSRCDIR}/sys/fs/cd9660/cd9660_extern.h fs/cd9660
  .endif
  
  cleandir distclean: cleaninc
 diff --git a/distrib/cdrom/macppc_installboot/cd9660.c b/distrib/cdrom/macppc_installboot/cd9660.c
 index 02d1c9232a6e..008a5cec1822 100644
 --- a/distrib/cdrom/macppc_installboot/cd9660.c
 +++ b/distrib/cdrom/macppc_installboot/cd9660.c
 @@ -51,6 +51,7 @@ __RCSID("$NetBSD: cd9660.c,v 1.4 2014/09/27 15:21:40 tsutsui Exp $");
  #include <dirent.h>
  
  #include <fs/cd9660/iso.h>
 +#include <fs/cd9660/cd9660_extern.h>
  
  #include "installboot.h"
  
 @@ -87,7 +88,7 @@ cd9660_match(ib_params *params)
  		return 0;
  	}
  
 -	blocksize = isonum_723((char *)ipd.logical_block_size);
 +	blocksize = isonum_723((u_char *)ipd.logical_block_size);
  	if (blocksize != ISO_DEFAULT_BLOCK_SIZE) {
  		warnx("Invalid blocksize %d in `%s'",
  		    blocksize, params->filesystem);
 @@ -104,10 +105,11 @@ int
  cd9660_findstage2(ib_params *params, uint32_t *maxblk, ib_block *blocks)
  {
  	uint8_t buf[ISO_DEFAULT_BLOCK_SIZE];
 -	char name[MAXNAMLEN];
 -	char *ofwboot;
 +	char name[ISO_MAXNAMLEN];
 +	char *stage2;
  	off_t loc;
 -	int rv, blocksize, found, i;
 +	int rv, blocksize, found;
 +	u_int i;
  	struct iso_primary_descriptor ipd;
  	struct iso_directory_record *idr;
  
 @@ -122,20 +124,20 @@ cd9660_findstage2(ib_params *params, uint32_t *maxblk, ib_block *blocks)
  #endif
  
  	/* The secondary bootstrap must be clearly in /. */
 -	strlcpy(name, params->stage2, MAXNAMLEN);
 -	ofwboot = name;
 -	if (ofwboot[0] == '/')
 -		ofwboot++;
 -	if (strchr(ofwboot, '/') != NULL) {
 +	strlcpy(name, params->stage2, ISO_MAXNAMLEN);
 +	stage2 = name;
 +	if (stage2[0] == '/')
 +		stage2++;
 +	if (strchr(stage2, '/') != NULL) {
  		warnx("The secondary bootstrap `%s' must be in / "
  		    "on filesystem `%s'", params->stage2, params->filesystem);
  		return 0;
  	}
 -	if (strchr(ofwboot, '.') == NULL) {
 +	if (strchr(stage2, '.') == NULL) {
  		/*
  		 * XXX should fix isofncmp()?
  		 */
 -		strlcat(ofwboot, ".", MAXNAMLEN);
 +		strlcat(name, ".", ISO_MAXNAMLEN);
  	}
  
  	rv = pread(params->fsfd, &ipd, sizeof(ipd),
 @@ -148,7 +150,7 @@ cd9660_findstage2(ib_params *params, uint32_t *maxblk, ib_block *blocks)
  		   params->filesystem);
  		return 0;
  	}
 -	blocksize = isonum_723((char *)ipd.logical_block_size);
 +	blocksize = isonum_723((u_char *)ipd.logical_block_size);
  
  	idr = (void *)ipd.root_directory_record;
  	loc = (off_t)isonum_733(idr->extent) * blocksize;
 @@ -205,13 +207,12 @@ cd9660_findstage2(ib_params *params, uint32_t *maxblk, ib_block *blocks)
  			printf("\n");
  		}
  #endif
 -		if (isofncmp(ofwboot, strlen(ofwboot),
 -		    idr->name, isonum_711(idr->name_len), 0) == 0) {
 +		if (isofncmp((u_char *)stage2, strlen(stage2),
 +		    (u_char *)idr->name,
 +		    isonum_711((u_char *)idr->name_len), 0) == 0) {
  			found = 1;
  			/* ISO filesystem always has contiguous file blocks */
  			blocks[0].block = (int64_t)isonum_733(idr->extent);
 -			/* XXX bootxx assumes blocksize is 512 */
 -			blocks[0].block *= blocksize / 512;
  			blocks[0].blocksize =
  			    roundup(isonum_733(idr->size), blocksize);
  			*maxblk = 1;
 diff --git a/distrib/cdrom/macppc_installboot/installboot.c b/distrib/cdrom/macppc_installboot/installboot.c
 index e3af92bb8988..56da84961b8b 100644
 --- a/distrib/cdrom/macppc_installboot/installboot.c
 +++ b/distrib/cdrom/macppc_installboot/installboot.c
 @@ -47,6 +47,12 @@ static	void usage(void);
  
  static	ib_params	installboot_params;
  
 +static	struct ib_fs cd9660_fstype = {
 +	.name = "cd9660",
 +	.match = cd9660_match,
 +	.findstage2 = cd9660_findstage2
 +};
 +
  int
  main(int argc, char **argv)
  {
 @@ -59,6 +65,7 @@ main(int argc, char **argv)
  	uint32_t nblk, maxblk, blk_i;
  	int rv;
  	ib_block *blocks;
 +	uint64_t block;
  
  	setprogname(argv[0]);
  	params = &installboot_params;
 @@ -70,11 +77,16 @@ main(int argc, char **argv)
  		usage();
  
  	params->filesystem = argv[1];
 +	params->fstype = &cd9660_fstype;
  
  	if ((params->fsfd = open(params->filesystem, O_RDWR, 0600)) == -1)
  		err(1, "Opening file system `%s' read", params->filesystem);
  	if (fstat(params->fsfd, &params->fsstat) == -1)
  		err(1, "Examining file system `%s'", params->filesystem);
 +	if (!params->fstype->match(params))
 +		errx(1, "File system `%s' is not of type %s",
 +		    params->filesystem, params->fstype->name);
 +
  #ifdef DEBUG
  	printf("file system: %s, %ld bytes\n",
  	    params->filesystem, (long)params->fsstat.st_size);
 @@ -87,7 +99,7 @@ main(int argc, char **argv)
  	if (pread(params->fsfd, &pme, sizeof pme, BSIZE * 2) != sizeof(pme))
  		err(1, "read pme from file system `%s'", params->filesystem);
  
 -	if (strcmp(pme.pmPartName, "NetBSD_BootBlock"))
 +	if (strcmp((char *)pme.pmPartName, "NetBSD_BootBlock"))
  		err(1, "invalid partition map in file system `%s'",
  		    params->filesystem);
  
 @@ -167,14 +179,16 @@ main(int argc, char **argv)
  	}
  
  	nblk = maxblk;
 -	if (!cd9660_findstage2(params, &nblk, blocks)) {
 +	if (!params->fstype->findstage2(params, &nblk, blocks)) {
  		exit(1);
  	}
  
  	bbinfop->bbi_block_count = htobe32(nblk);
  	bbinfop->bbi_block_size = htobe32(blocks[0].blocksize);
  	for (blk_i = 0; blk_i < nblk; blk_i++) {
 -		bbinfop->bbi_block_table[blk_i] = htobe32(blocks[blk_i].block);
 +		/* XXX bootxx assumes blocksize is 512 */
 +		block = blocks[blk_i].block * (params->fstype->blocksize / 512);
 +		bbinfop->bbi_block_table[blk_i] = htobe32(block);
  		if (blocks[blk_i].blocksize < blocks[0].blocksize &&
  		    blk_i + 1 != nblk) {
  			warnx("Secondary bootstrap `%s' blocks do not have "
 diff --git a/distrib/cdrom/macppc_installboot/installboot.h b/distrib/cdrom/macppc_installboot/installboot.h
 index 1875e300cc04..57d8ae09502f 100644
 --- a/distrib/cdrom/macppc_installboot/installboot.h
 +++ b/distrib/cdrom/macppc_installboot/installboot.h
 @@ -43,10 +43,6 @@
  #include <sys/stat.h>
  #include <stdint.h>
  
 -#ifndef MAXNAMLEN
 -#define MAXNAMLEN	511
 -#endif
 -
  typedef enum {
  				/* flags from global options */
  	IB_VERBOSE =	1<<0,		/* verbose operation */
 @@ -135,7 +131,4 @@ struct bbinfo_params {
  int		cd9660_match(ib_params *);
  int		cd9660_findstage2(ib_params *, uint32_t *, ib_block *);
  
 -int isofncmp(const u_char *, size_t, const u_char *, size_t, int);
 -void isofntrans(const u_char *, int, u_char *, u_short *, int, int, int, int);
 -
  #endif	/* _INSTALLBOOT_H */
 diff --git a/distrib/hp300/cdroms/installcd/Makefile b/distrib/hp300/cdroms/installcd/Makefile
 index 96c9b1dfd1ec..7417897242a5 100644
 --- a/distrib/hp300/cdroms/installcd/Makefile
 +++ b/distrib/hp300/cdroms/installcd/Makefile
 @@ -3,4 +3,18 @@ CDBASE=		hp300cd			# gives ${CDBASE}.iso
  CDRELEASE=	true			# include $RELEASEDIR/$RELEASEMACHINEDIR
  CDRELEASE_NODEBUG=	true
  
 +CDKERNELS=	netbsd-RAMDISK.gz netbsd
 +CDINSTKERNEL=	../../instkernel
 +
 +SYS_UBOOT=	SYS_UBOOT
 +BOOTDIR=	${DESTDIR}/usr/mdec/rbootd
 +
 +# make the CD bootable
 +prepare_md_post:
 +	${INSTALL} ${COPY} -m 0644 ${BOOTDIR}/${SYS_UBOOT} cdrom
 +
 +image_md_post:
 +	${TOOL_INSTALLBOOT} -m ${MACHINE} \
 +	    ${CDIMAGE} ${BOOTDIR}/${SYS_UBOOT} /${SYS_UBOOT}
 +
  .include "${.CURDIR}/../../../common/Makefile.bootcd"
 diff --git a/sys/arch/hp300/stand/uboot/Makefile b/sys/arch/hp300/stand/uboot/Makefile
 index 6d0a833e2b77..3fe3a8882e39 100644
 --- a/sys/arch/hp300/stand/uboot/Makefile
 +++ b/sys/arch/hp300/stand/uboot/Makefile
 @@ -6,6 +6,7 @@ NEWVERSWHAT=	"Primary Boot"
  
  CPPFLAGS+=	-DSUPPORT_ETHERNET -DSUPPORT_TAPE -DSUPPORT_DISK
  CPPFLAGS+=	-DSUPPORT_UFS2
 +CPPFLAGS+=	-DSUPPORT_CD
  
  LINKS=	${BINDIR}/${PROG} ${BINDIR}/rdboot
  LINKS+=	${BINDIR}/${PROG} ${BINDIR}/bootrd
 diff --git a/sys/fs/cd9660/cd9660_extern.h b/sys/fs/cd9660/cd9660_extern.h
 index f58436bdb322..1276eac9a587 100644
 --- a/sys/fs/cd9660/cd9660_extern.h
 +++ b/sys/fs/cd9660/cd9660_extern.h
 @@ -105,10 +105,11 @@ extern int (**cd9660_vnodeop_p)(void *);
  extern int (**cd9660_specop_p)(void *);
  extern int (**cd9660_fifoop_p)(void *);
  
 +ino_t isodirino(struct iso_directory_record *, struct iso_mnt *);
 +#endif /* _KERNEL */
 +
  int isochar(const u_char *, const u_char *, int, u_int16_t *);
  int isofncmp(const u_char *, size_t, const u_char *, size_t, int);
  void isofntrans(const u_char *, int, u_char *, u_short *, int, int, int, int);
 -ino_t isodirino(struct iso_directory_record *, struct iso_mnt *);
 -#endif /* _KERNEL */
  
  #endif /* _ISOFS_CD9660_CD9660_EXTERN_H_ */
 diff --git a/sys/fs/cd9660/cd9660_util.c b/sys/fs/cd9660/cd9660_util.c
 index 3915ab1409bb..3d827e390926 100644
 --- a/sys/fs/cd9660/cd9660_util.c
 +++ b/sys/fs/cd9660/cd9660_util.c
 @@ -66,11 +66,7 @@ __KERNEL_RCSID(0, "$NetBSD: cd9660_util.c,v 1.14 2016/03/09 20:18:17 christos Ex
  #endif
  
  #include <fs/cd9660/iso.h>
 -#ifdef _KERNEL
  #include <fs/cd9660/cd9660_extern.h>
 -#else
 -static int isochar(const u_char *, const u_char *, int, uint16_t *);
 -#endif
  
  #include <fs/unicode.h>
  
 diff --git a/tools/Makefile.nbincludes b/tools/Makefile.nbincludes
 index efff65fe8411..71d4e8baa8ab 100644
 --- a/tools/Makefile.nbincludes
 +++ b/tools/Makefile.nbincludes
 @@ -6,12 +6,15 @@ _ARCHDIR:=	${.PARSEDIR}/../sys/arch
  _INCDIR:=	${.PARSEDIR}/../include
  _SYSDIR:=	${.PARSEDIR}/../sys/sys
  _UFSDIR:=	${.PARSEDIR}/../sys/ufs
 +_FSDIR:=	${.PARSEDIR}/../sys/fs
  _SUBDIR!=	cd ${_ARCHDIR} && ${MAKE} -V SUBDIR
  
  .if make(depend) || make(all) || make(dependall) || make(install)
  # There's no need to run these commands for "make cleandir" or "make obj",
  # and TOOL_SED will not yet have been built.
  _UFS_INCS!=	cd ${_UFSDIR} && find ffs ufs -name '*.h'
 +_FS_INCS!=	cd ${_FSDIR} && find cd9660 -name '*.h'
 +_FS_INCS+=	unicode.h
  _ARCH_INCS!=	${TOOL_SED} -e 's/^\#.*//' ${.PARSEDIR}/headerlist
  .endif
  
 @@ -34,6 +37,8 @@ beforedepend:
  	${HOST_INSTALL_DIR} ${TOOLDIR}/include/nbinclude
  	${HOST_INSTALL_DIR} ${TOOLDIR}/include/nbinclude/sys
  	${HOST_INSTALL_DIR} ${TOOLDIR}/include/nbinclude/ufs
 +	${HOST_INSTALL_DIR} ${TOOLDIR}/include/nbinclude/fs
 +	${HOST_INSTALL_DIR} ${TOOLDIR}/include/nbinclude/fs/cd9660
  	cd ${_ARCHDIR} && \
  	    ${TOOL_PAX} -s /include\\/// -rw ${_ARCH_INCS} \
  	    ${TOOLDIR}/include/nbinclude
 @@ -43,5 +48,7 @@ beforedepend:
  	    ${TOOL_PAX} -rw ${_SYSINCS} ${TOOLDIR}/include/nbinclude/sys
  	cd ${_UFSDIR} && \
  	    ${TOOL_PAX} -rw ${_UFS_INCS} ${TOOLDIR}/include/nbinclude/ufs
 +	cd ${_FSDIR} && \
 +	    ${TOOL_PAX} -rw ${_FS_INCS} ${TOOLDIR}/include/nbinclude/fs
  	cd ${TOOLDIR}/include/nbinclude && rm -f machine && \
  	    ${HOST_INSTALL_SYMLINK} ${MACHINE} machine
 diff --git a/usr.sbin/installboot/Makefile b/usr.sbin/installboot/Makefile
 index e31285b7776a..324ae24bddb9 100644
 --- a/usr.sbin/installboot/Makefile
 +++ b/usr.sbin/installboot/Makefile
 @@ -69,9 +69,29 @@ SRCS+= ffs_bswap.c
  #SRCS+= ext2fs.c ext2fs_bswap.c
  .endif
  
 +.if !empty(ARCH_FILES:C/(hp300|macppc)/cd9660/:Mcd9660.c)
 +SRCS+= cd9660.c cd9660_util.c
 +
 +.if !make(obj) && !make(clean) && !make(cleandir)
 +.BEGIN:
 +	-rm -rf fs
 +	${HOST_INSTALL_DIR} fs
 +	${HOST_INSTALL_DIR} fs/cd9660
 +	${HOST_LN} -s ${NETBSDSRCDIR}/sys/fs/unicode.h fs
 +	${HOST_LN} -s ${NETBSDSRCDIR}/sys/fs/cd9660/iso.h fs/cd9660
 +	${HOST_LN} -s ${NETBSDSRCDIR}/sys/fs/cd9660/cd9660_extern.h fs/cd9660
 +.endif
 +
 +cleandir distclean: cleaninc
 +
 +cleaninc:
 +	-rm -rf fs
 +.endif
 +
  UFSSRC=		${NETBSDSRCDIR}/sys/ufs
 +CD9660SRC=	${NETBSDSRCDIR}/sys/fs/cd9660
  CPPFLAGS+=	-I${.CURDIR} -I.
 -.PATH:		${.CURDIR}/arch ${UFSSRC}/ffs ${UFSSRC}/ext2fs
 +.PATH:		${.CURDIR}/arch ${UFSSRC}/ffs ${UFSSRC}/ext2fs ${CD9660SRC}
  
  .if !defined(HOSTPROGNAME)
  .for f in i386 macppc
 diff --git a/usr.sbin/installboot/arch/hp300.c b/usr.sbin/installboot/arch/hp300.c
 index 118caa2c78c9..56cf9de18f07 100644
 --- a/usr.sbin/installboot/arch/hp300.c
 +++ b/usr.sbin/installboot/arch/hp300.c
 @@ -62,6 +62,9 @@ __RCSID("$NetBSD: hp300.c,v 1.18 2024/05/11 22:10:27 tsutsui Exp $");
  
  #include "installboot.h"
  
 +#define HP300_MAXBLOCKS	1	/* Only contiguous blocks are expected. */
 +#define LIF_VOLDIRSIZE	1024	/* size of LIF volume header and directory */
 +
  static int hp300_setboot(ib_params *);
  
  struct ib_mach ib_mach_hp300 = {
 @@ -77,6 +80,7 @@ hp300_setboot(ib_params *params)
  {
  	int		retval;
  	uint8_t		*bootstrap;
 +	size_t		bootstrap_size;
  	ssize_t		rv;
  	struct partition *boot;
  	struct hp300_lifdir *lifdir;
 @@ -84,6 +88,8 @@ hp300_setboot(ib_params *params)
  	int		i;
  	unsigned int	secsize = HP300_SECTSIZE;
  	uint64_t	boot_size, boot_offset;
 +	uint32_t	nblk;
 +	ib_block	*blocks;
  	struct disklabel *label;
  
  	assert(params != NULL);
 @@ -101,7 +107,62 @@ hp300_setboot(ib_params *params)
  		goto done;
  	}
  
 -	if (params->flags & IB_APPEND) {
 +	if (params->stage2 != NULL) {
 +		/*
 +		 * Use contiguous blocks of SYS_BOOT in the target filesystem
 +		 * (assuming ISO9660) for a LIF directory entry used
 +		 * by BOOTROM on bootstrap.
 +		 */
 +		if (strcmp(params->fstype->name, "cd9660") != 0) {
 +			warn("Target filesystem `%s' is unexpected",
 +			    params->fstype->name);
 +		}
 +
 +		if (S_ISREG(params->fsstat.st_mode)) {
 +			if (fsync(params->fsfd) == -1)
 +				warn("Synchronising file system `%s'",
 +				    params->filesystem);
 +		} else {
 +			/* Don't allow real file systems for sanity */
 +			warnx("`%s' must be a regular file to append "
 +			    "a bootstrap", params->filesystem);
 +			goto done;
 +		}
 +
 +		/* Allocate space for our block list. */
 +		nblk = HP300_MAXBLOCKS;
 +		blocks = malloc(sizeof(*blocks) * nblk);
 +		if (blocks == NULL) {
 +			warn("Allocating %lu bytes for block list",
 +			    (unsigned long)sizeof(*blocks) * nblk);
 +			goto done;
 +		}
 +
 +		/* Check the block of for the SYS_UBOOT in the target fs */
 +		if (!params->fstype->findstage2(params, &nblk, blocks))
 +			goto done;
 +
 +		if (nblk == 0) {
 +			warnx("Secondary bootstrap `%s' is empty",
 +			    params->stage2);
 +			goto done;
 +		} else if (nblk > 1) {
 +			warnx("Secondary bootstrap `%s' doesn't have "
 +			    "contiguous blocks", params->stage2);
 +			goto done;
 +		}
 +
 +		boot_offset = blocks[0].block * params->fstype->blocksize;
 +		/* need to read only LIF volume and directories */
 +		bootstrap_size = LIF_VOLDIRSIZE;
 +
 +		if ((params->flags & IB_VERBOSE) != 0) {
 +			printf("Bootstrap `%s' found at offset %lu in `%s'\n",
 +			    params->stage2, (unsigned long)boot_offset,
 +			    params->filesystem);
 +		}
 +
 +	} else if (params->flags & IB_APPEND) {
  		if (!S_ISREG(params->fsstat.st_mode)) {
  			warnx(
  		    "`%s' must be a regular file to append a bootstrap",
 @@ -157,11 +218,24 @@ hp300_setboot(ib_params *params)
  		}
  	}
  
 -	bootstrap = mmap(NULL, params->s1stat.st_size, PROT_READ | PROT_WRITE,
 -			    MAP_PRIVATE, params->s1fd, 0);
 -	if (bootstrap == MAP_FAILED) {
 -		warn("mmapping `%s'", params->stage1);
 -		goto done;
 +	if (params->stage2 != NULL) {
 +		/* Use bootstrap file in the target filesystem. */
 +		bootstrap = mmap(NULL, bootstrap_size,
 +		    PROT_READ | PROT_WRITE, MAP_PRIVATE, params->fsfd,
 +		    boot_offset);
 +		if (bootstrap == MAP_FAILED) {
 +			warn("mmapping `%s'", params->filesystem);
 +			goto done;
 +		}
 +	} else {
 +		/* Use bootstrap specified as stage1. */
 +		bootstrap_size = params->s1stat.st_size;
 +		bootstrap = mmap(NULL, bootstrap_size,
 +		    PROT_READ | PROT_WRITE, MAP_PRIVATE, params->s1fd, 0);
 +		if (bootstrap == MAP_FAILED) {
 +			warn("mmapping `%s'", params->stage1);
 +			goto done;
 +		}
  	}
  
  	/* Relocate files, sanity check LIF directory on the way */
 @@ -187,8 +261,8 @@ hp300_setboot(ib_params *params)
  	}
  
  	/* Write LIF volume header and directory to sectors 0 and 1 */
 -	rv = pwrite(params->fsfd, bootstrap, 1024, 0);
 -	if (rv != 1024) {
 +	rv = pwrite(params->fsfd, bootstrap, LIF_VOLDIRSIZE, 0);
 +	if (rv != LIF_VOLDIRSIZE) {
  		if (rv == -1)
  			warn("Writing `%s'", params->filesystem);
  		else
 @@ -196,6 +270,15 @@ hp300_setboot(ib_params *params)
  		goto done;
  	}
  
 +	if (params->stage2 != NULL) {
 +		/*
 +		 * Bootstrap in the target filesystem is used.
 +		 * No need to write bootstrap to BOOT partition.
 +		 */
 +		retval = 1;
 +		goto done;
 +	}
 +
  	/* Write files to BOOT partition */
  	offset = boot_offset <= HP300_SECTSIZE * 16 ? HP300_SECTSIZE * 16 : 0;
  	i = roundup(params->s1stat.st_size, secsize) - offset;
 @@ -216,6 +299,6 @@ hp300_setboot(ib_params *params)
  	if (label != NULL)
  		free(label);
  	if (bootstrap != MAP_FAILED)
 -		munmap(bootstrap, params->s1stat.st_size);
 +		munmap(bootstrap, bootstrap_size);
  	return retval;
  }
 diff --git a/usr.sbin/installboot/cd9660.c b/usr.sbin/installboot/cd9660.c
 new file mode 100644
 index 000000000000..6cb682d1c5e2
 --- /dev/null
 +++ b/usr.sbin/installboot/cd9660.c
 @@ -0,0 +1,234 @@
 +/*	$NetBSD$	*/
 +
 +/*-
 + * Copyright (c) 2005 Izumi Tsutsui.  All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. Redistributions in binary form must reproduce the above copyright
 + *    notice, this list of conditions and the following disclaimer in the
 + *    documentation and/or other materials provided with the distribution.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +#if HAVE_NBTOOL_CONFIG_H
 +#include "nbtool_config.h"
 +#endif
 +
 +#include <sys/cdefs.h>
 +#if defined(__RCSID) && !defined(__lint)
 +__RCSID("$NetBSD$");
 +#endif	/* !__lint */
 +
 +#include <sys/param.h>
 +
 +#if !HAVE_NBTOOL_CONFIG_H
 +#include <sys/mount.h>
 +#endif
 +
 +#include <assert.h>
 +#include <err.h>
 +#include <errno.h>
 +#include <fcntl.h>
 +#include <stdarg.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <unistd.h>
 +#include <dirent.h>
 +
 +#include <fs/cd9660/iso.h>
 +#include <fs/cd9660/cd9660_extern.h>
 +
 +#include "installboot.h"
 +
 +#define roundup(x, y)	((((x)+((y)-1))/(y))*(y))
 +#define MAXLEN		16
 +
 +
 +int
 +cd9660_match(ib_params *params)
 +{
 +	int rv, blocksize;
 +	struct iso_primary_descriptor ipd;
 +
 +	assert(params != NULL);
 +	assert(params->fstype != NULL);
 +	assert(params->fsfd != -1);
 +
 +	rv = pread(params->fsfd, &ipd, sizeof(ipd),
 +	    ISO_DEFAULT_BLOCK_SIZE * 16);
 +	if (rv == -1) {
 +		warn("Reading primary descriptor in `%s'", params->filesystem);
 +		return 0;
 +	} else if (rv != sizeof(ipd)) {
 +		warnx("Reading primary descriptor in `%s': short read",
 +		   params->filesystem);
 +		return 0;
 +	}
 +
 +	if (ipd.type[0] != ISO_VD_PRIMARY ||
 +	    strncmp(ipd.id, ISO_STANDARD_ID, sizeof(ipd.id)) != 0 ||
 +	    ipd.version[0] != 1) {
 +		warnx("Filesystem `%s' is not ISO9660 format",
 +		   params->filesystem);
 +		return 0;
 +	}
 +
 +	blocksize = isonum_723((u_char *)ipd.logical_block_size);
 +	if (blocksize != ISO_DEFAULT_BLOCK_SIZE) {
 +		warnx("Invalid blocksize %d in `%s'",
 +		    blocksize, params->filesystem);
 +		return 0;
 +	}
 +
 +	params->fstype->blocksize = blocksize;
 +	params->fstype->needswap = 0;
 +
 +	return 1;
 +}
 +
 +int
 +cd9660_findstage2(ib_params *params, uint32_t *maxblk, ib_block *blocks)
 +{
 +	uint8_t buf[ISO_DEFAULT_BLOCK_SIZE];
 +	char name[ISO_MAXNAMLEN];
 +	char *stage2;
 +	off_t loc;
 +	int rv, blocksize, found;
 +	u_int i;
 +	struct iso_primary_descriptor ipd;
 +	struct iso_directory_record *idr;
 +
 +	assert(params != NULL);
 +	assert(params->stage2 != NULL);
 +	assert(maxblk != NULL);
 +	assert(blocks != NULL);
 +
 +#if 0
 +	if (params->flags & IB_STAGE2START)
 +		return hardcode_stage2(params, maxblk, blocks);
 +#endif
 +
 +	/* The secondary bootstrap must be clearly in /. */
 +	strlcpy(name, params->stage2, ISO_MAXNAMLEN);
 +	stage2 = name;
 +	if (stage2[0] == '/')
 +		stage2++;
 +	if (strchr(stage2, '/') != NULL) {
 +		warnx("The secondary bootstrap `%s' must be in / "
 +		    "on filesystem `%s'", params->stage2, params->filesystem);
 +		return 0;
 +	}
 +	if (strchr(stage2, '.') == NULL) {
 +		/*
 +		 * XXX should fix isofncmp()?
 +		 */
 +		strlcat(name, ".", ISO_MAXNAMLEN);
 +	}
 +
 +	rv = pread(params->fsfd, &ipd, sizeof(ipd),
 +	    ISO_DEFAULT_BLOCK_SIZE * 16);
 +	if (rv == -1) {
 +		warn("Reading primary descriptor in `%s'", params->filesystem);
 +		return 0;
 +	} else if (rv != sizeof(ipd)) {
 +		warnx("Reading primary descriptor in `%s': short read",
 +		   params->filesystem);
 +		return 0;
 +	}
 +	blocksize = isonum_723((u_char *)ipd.logical_block_size);
 +
 +	idr = (void *)ipd.root_directory_record;
 +	loc = (off_t)isonum_733(idr->extent) * blocksize;
 +	rv = pread(params->fsfd, buf, blocksize, loc);
 +	if (rv == -1) {
 +		warn("Reading root directory record in `%s'",
 +		    params->filesystem);
 +		return 0;
 +	} else if (rv != sizeof(ipd)) {
 +		warnx("Reading root directory record in `%s': short read",
 +		   params->filesystem);
 +		return 0;
 +	}
 +
 +	found = 0;
 +	for (i = 0; i < blocksize - sizeof(struct iso_directory_record);
 +	    i += (u_char)idr->length[0]) {
 +		idr = (void *)&buf[i];
 +
 +#ifdef DEBUG
 +		printf("i = %d, idr->length[0] = %3d\n",
 +		    i, (u_char)idr->length[0]);
 +#endif
 +		/* check end of entries */
 +		if (idr->length[0] == 0) {
 +#ifdef DEBUG
 +		printf("end of entries\n");
 +#endif
 +			break;
 +		}
 +
 +		if (idr->flags[0] & 2) {
 +			/* skip directory entries */
 +#ifdef DEBUG
 +			printf("skip directory entry\n");
 +#endif
 +			continue;
 +		}
 +		if (idr->name_len[0] == 1 &&
 +		    (idr->name[0] == 0 || idr->name[0] == 1)) {
 +			/* skip "." and ".." */
 +#ifdef DEBUG
 +			printf("skip dot dot\n");
 +#endif
 +			continue;
 +		}
 +#ifdef DEBUG
 +		{
 +			int j;
 +
 +			printf("filename:");
 +			for (j = 0; j < isonum_711(idr->name_len); j++)
 +				printf("%c", idr->name[j]);
 +			printf("\n");
 +		}
 +#endif
 +		if (isofncmp((u_char *)stage2, strlen(stage2),
 +		    (u_char *)idr->name,
 +		    isonum_711((u_char *)idr->name_len), 0) == 0) {
 +			found = 1;
 +			/* ISO filesystem always has contiguous file blocks */
 +			blocks[0].block = (int64_t)isonum_733(idr->extent);
 +			blocks[0].blocksize =
 +			    roundup(isonum_733(idr->size), blocksize);
 +			*maxblk = 1;
 +#ifdef DEBUG
 +			printf("block = %ld, blocksize = %ld\n",
 +			    (long)blocks[0].block, blocks[0].blocksize);
 +#endif
 +			break;
 +		}
 +	}
 +
 +	if (found == 0) {
 +		warnx("Can't find secondary bootstrap `%s' in filesystem `%s'",
 +		    params->stage2, params->filesystem);
 +		return 0;
 +	}
 +
 +	return 1;
 +}
 diff --git a/usr.sbin/installboot/fstypes.c b/usr.sbin/installboot/fstypes.c
 index 1b77f974fc5d..4bb720be6b5a 100644
 --- a/usr.sbin/installboot/fstypes.c
 +++ b/usr.sbin/installboot/fstypes.c
 @@ -48,11 +48,31 @@ __RCSID("$NetBSD: fstypes.c,v 1.13 2010/01/14 16:27:49 tsutsui Exp $");
  
  struct ib_fs fstypes[] = {
  #ifndef NO_STAGE2
 -	{ .name = "ffs",  .match = ffs_match,	.findstage2 = ffs_findstage2	},
 -	{ .name = "raid", .match = raid_match,	.findstage2 = ffs_findstage2	},
 -	{ .name = "raw",  .match = raw_match,	.findstage2 = raw_findstage2	},
 +	{
 +		.name = "ffs",
 +		.match = ffs_match,
 +		.findstage2 = ffs_findstage2
 +	},
 +	{
 +		.name = "raid",
 +		.match = raid_match,
 +		.findstage2 = ffs_findstage2
 +	},
 +	{
 +		.name = "cd9660",
 +		.match = cd9660_match,
 +		.findstage2 = cd9660_findstage2
 +	},
 +	/* raw_match() always matches, so raw should be at the end. */
 +	{
 +		.name = "raw",
 +		.match = raw_match,
 +		.findstage2 = raw_findstage2
 +	},
  #endif
 -	{ .name = NULL, }
 +	{
 +		.name = NULL
 +	}
  };
  
  #ifndef NO_STAGE2
 diff --git a/usr.sbin/installboot/installboot.8 b/usr.sbin/installboot/installboot.8
 index b6eaf75fc974..71a4871eae1c 100644
 --- a/usr.sbin/installboot/installboot.8
 +++ b/usr.sbin/installboot/installboot.8
 @@ -32,7 +32,7 @@
  .\" Usage: \*(UB
  .ds UB U\(hyBoot
  .
 -.Dd December 25, 2023
 +.Dd May 12, 2024
  .Dt INSTALLBOOT 8
  .Os
  .Sh NAME
 @@ -479,6 +479,9 @@ Fast File System.
  .It Ic raid
  Mirrored RAIDframe File System.
  .
 +.It Ic cd9660
 +ISO 9660 File System.
 +.
  .It Ic raw
  .Dq Raw
  image.
 diff --git a/usr.sbin/installboot/installboot.h b/usr.sbin/installboot/installboot.h
 index 468670c6fb14..b9e65b9a1660 100644
 --- a/usr.sbin/installboot/installboot.h
 +++ b/usr.sbin/installboot/installboot.h
 @@ -171,15 +171,23 @@ int		shared_bbinfo_clearboot(ib_params *, struct bbinfo_params *,
  int		shared_bbinfo_setboot(ib_params *, struct bbinfo_params *,
  		    int (*)(ib_params *, struct bbinfo_params *, uint8_t *));
  
 -	/* fstypes.c */
 -int		hardcode_stage2(ib_params *, uint32_t *, ib_block *);
 +	/* cd9660.c */
 +int		cd9660_match(ib_params *);
 +int		cd9660_findstage2(ib_params *, uint32_t *, ib_block *);
 +
 +	/* ext2fs.c */
 +int		ext2fs_match(ib_params *);
 +int		ext2fs_findstage2(ib_params *, uint32_t *, ib_block *);
 +
 +	/* ffs.c */
  int		ffs_match(ib_params *);
  int		ffs_findstage2(ib_params *, uint32_t *, ib_block *);
  int		raid_match(ib_params *);
 +
 +	/* fstypes.c */
 +int		hardcode_stage2(ib_params *, uint32_t *, ib_block *);
  int		raw_match(ib_params *);
  int		raw_findstage2(ib_params *, uint32_t *, ib_block *);
 -int		ext2fs_match(ib_params *);
 -int		ext2fs_findstage2(ib_params *, uint32_t *, ib_block *);
  
  	/* machines.c */
  extern struct ib_mach ib_mach_alpha;
 
 
 ---
 Izumi Tsutsui
 


Home | Main Index | Thread Index | Old Index