convert bootable freebsd or linux iso to bootable flash image

Luigi Rizzo rizzo at iet.unipi.it
Tue Nov 25 14:42:10 PST 2008


I have updated my iso2flash.sh script so that now it can
convert both FreeBSD _and_ linux ISO images to flash images.
For the latter, it uses a FAT filesystem, and puts a linux
loader with syslinux, for which you can find a port at

http://info.iet.unipi.it/~luigi/FreeBSD/index.html#syslinux-port

Below is the updated code for iso2flash.sh

------------------- cut here --------------------------------

#!/bin/sh
# $Id: iso2flash.sh 897 2008-11-25 22:41:00Z luigi $
# convert an ISO image to flash image
# The type of filesystem depends on the content, but can be forced
# manually.
#
# based on picobsd tricks.
# Requires makefs, bsdlabel, sed and dd
# The linux image uses mtools and syslinux, see
# 	http://info.iet.unipi.it/~luigi/FreeBSD/#syslinux-port
# see http://www.allbootdisks.com/download/iso.html

MAKEFS=makefs
MKLABEL=bsdlabel
BSDTAR=tar

# Create a linux disk starting from an ISO. Use a FAT media
# and syslinux to format it. Add some intelligence to figure
# out where the kernel is and what options it needs.

make_linux_image() {	# src_tree dest_image
    local tree=$1
    local img=$2
    local size=$(( $3 + 1000 ))		# size in kb
    local x=$(( 1 + $size / 128 ))	# 128k units, good for dd
    # if you have an old newfs_msdos...
    local OPTS=" -h 16 -u 64 -S 512 -s $(( 2 * ${size} )) -o 0"
    [ -f ${img} ] && { chmod u+w ${img}; rm ${img} ; }
    dd if=/dev/zero bs=128k count=$x of=${img}	# create blank file
    newfs_msdos ${OPTS} ${img}				# format msdos
    syslinux ${img}			# add linux bootcode

    # Try to identify where the kernel is
    local boot=`find $tree -name boot`
    if [ x"${boot}" != x -a -d "${boot}" ] ; then
	echo "moving boot code"
	chmod u+w ${boot} ${boot}/*
	mv ${boot}/* $tree
	[ -f ${tree}/syslinux.cfg ] || mv ${tree}/isolinux.cfg ${tree}/syslinux.cfg
    fi
    if [ -d ${tree}/isolinux ] ; then
	# systemrescuecd
	local sys=${tree}/syslinux
	echo moving files... 
	[ -d ${sys} ] || mkdir -p ${sys}
	chmod -R u+w ${tree}/isolinux
	mv ${tree}/isolinux/* ${sys}
	[ -f ${sys}/syslinux.cfg ] || mv ${sys}/isolinux.cfg ${sys}/syslinux.cfg
    fi
    if [ -f ${tree}/syslinux.cfg ] ; then
    elif [ -f ${tree}/syslinux/syslinux.cfg ] ; then
    elif [ -f ${tree}/linux ] ; then
    elif [ -f ${tree}/CE_BZ ] ; then
	# splashtop / expressgate
	echo "default ce_bz" > ${tree}/syslinux.cfg
    else
	boot=`cd ${tree}; find . -name boot.img`
	if [ x"${boot}" != x -a -f "${tree}/${boot}" ] ; then
	    cp -p /usr/local/share/syslinux/memdisk $tree
	    ( echo "default memdisk"; 
		echo "append initrd=${boot}" ) > $tree/syslinux.cfg
	fi
    fi
    mcopy -i ${img} -s ${tree}/* ::/		# copy the tree
    mdir -/ -i  ${img} ::			# show the results
}

# to add freedos code:
    #perl sys-freedos.pl --disk=${img} --heads=16 --sectors=64 --offset=0 # --lb
    #dd if=mbrfat.bin bs=90 iseek=1 oseek=1 of=${img} conv=notrunc

# Create a FreeBSD image.
make_freebsd_image() {	# tree imagefile size
    local tree=$1
    local imagefile=$2
    local boot1=${tree}/boot/boot1
    local boot2=${tree}/boot/boot2

    echo "convert tree $tree image $img"
    ${MAKEFS} -t ffs -o bsize=4096 -o fsize=512 \
        -f 50 ${imagefile} ${tree}
    ${MKLABEL} -w -f ${imagefile} auto # write a label
    # copy partition c: into a: with some sed magic
    ${MKLABEL} -f ${imagefile} | sed -e '/  c:/{p;s/c:/a:/;}' | \
        ${MKLABEL} -R -f ${imagefile} /dev/stdin

    # dump the primary and secondary boot (primary is 512 bytes)
    dd if=${boot1} of=${imagefile} conv=notrunc 2>/dev/null
    # XXX secondary starts after the 0x114 = dec 276 bytes of the label
    # so we skip 276 from the source, and 276+512=788 from dst
    # the old style blocks used 512 and 1024 respectively
    dd if=${boot2} iseek=1 ibs=276 2> /dev/null | \
        dd of=${imagefile} oseek=1 obs=788 conv=notrunc 2>/dev/null
}

extract_image() {	# extract image to a tree
    [ -f $1 ] || return
    local tmp="${tree}.tree"
    echo "Extract files from ${tree} into $tmp "
    (chmod -R +w $tmp; rm -rf $tmp )
    mkdir -p $tmp
    ls -la $tmp
    (cd $tmp && ${BSDTAR} xf $tree )
    ls -la $tmp
    tree=$tmp
}

guess_type() {
    echo guess type
    imgtype="error"	# default
    [ -f $tree/boot/loader -a -f $tree/boot/loader.rc ] && { imgtype="bsd"; return ; }
    local a=`find $tree -name isolinux`
    [ x"$a" != x -a -d $a ] && { imgtype="linux"; return ; }
}

# option processing
while [ x"$*" != x ] ; do
    case x"$1" in
    x-t )	# type
	shift
	imgtype=$1
	;;
    *)
	break
	;;
    esac
    shift
done

tree=`realpath $1`
image=`realpath $2`
echo "type <$imgtype> tree <$tree> image <$image>"

extract_image $tree
set `du -sk $tree`
size=$1
echo "image size is $size kb"

while true ; do
    case x"$imgtype" in
    *[Bb][Ss][Dd] )
	make_freebsd_image $tree $image $size
	;;
    *[Ll][Ii][Nn][Uu][Xx] )
	make_linux_image $tree $image $size
	;;
    xerror)
	echo "Image type not found, giving up"
	;;
    * )
	guess_type
	continue
	;;
    esac
    break
done
[ -d "$tmp" ] && (chmod -R u+w $tmp && rm -rf $tmp)
#---------------------- end of file -------------------------------


More information about the freebsd-hackers mailing list