Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
#!/bin/sh
# "hddimg", by Andrew Brockman
# Version: 2008apr22 (with a header added by Edrx)
# License unclear - he sent me this by e-mail.
# http://angg.twu.net/PLURALL/hddimg.html
# http://angg.twu.net/PLURALL/hddimg
# (find-es "plurall" "hddimg")
#
clear
cylendars=20
heads=64
sectors=32
point=/media/vhd
filename=
size=
errpipe=/tmp/stderr.log
outpipe=/tmp/stdout.log
dev=/tmp/free.dev
grub=
fs=ext2

usage () {
    cat <<%%%
Usage: $0 [OPTION] imageName
Create a hdd image with a given geometry

  -h or --help       print this help

  -c=INTEGER         number of cylendars = INTEGER
  -h=INTEGER         number of heads = INTEGER
  -s=INTEGER         number of sectors per track = INTEGER

  -f=FILE_SYSTEM     create with the filesystem FILE_SYSTEM
      supported filesystems are:
         ext2
         vfat
         minix
         reiserfs

  -g                 Install grub onto image

  -m=DIR             mount into folder DIR

Note that there is a set of discrete values that each parameter can take
%%%
}

for option in "$@"; do
    case "$option" in
     -h | --help)
	usage
	exit 0 ;;
    -g)
	grub=true ;;
    -c=*)
	cylendars=`echo "$option" | sed 's/-c=//'` ;;
    -f=*)
	fs=`echo "$option" | sed 's/-f=//'` ;;
    -h=*)
	heads=`echo "$option" | sed 's/-h=//'` ;;
    -s=*)
	sectors=`echo "$option" | sed 's/-s=//'` ;;
    -m=*)
	point=`echo "$option" | sed 's/-m=//'` ;;
    -*)
	echo "Unrecognized option \`$option'" 1>&2
	usage
	exit 1
	;;
    *)
	if test "x$filename" != x; then
            echo "More than one image file?" 1>&2
            usage
            exit 1
	fi
	filename="${option}" ;;
    esac
done

size=`expr "$cylendars" "*" "$heads"`
size=`expr "$sectors" "*" "$size"`
size=`expr "$size" "/" "2"`

#check if a output file was specified
if [ "x$filename" = "x" ]; then
    echo "You must specify an output file\nType \"$0 --help\" for more help"
    exit 1
fi

#remove old image file if it exists
if [ -f $filename ]; then
    echo "Removing the old image file"
    rm $filename
fi

#create new image file
echo "Creating new image file"
dd if=/dev/zero of=$filename bs=1024 count=$size 1>$outpipe 2>$errpipe

#fdisk with specified geometry
#echo "Partitioning the new image file"
#sudo fdisk -C $cylendars -H $heads -S $sectors $filename 1>$outpipe 2>$errpipe<<%%%
#n
#p
#1
#
#
#w
#%%%

#Associate the virtual disk to a loop device
echo "Istalling raw image file into: \c"
sudo losetup -f | tee $dev 2>$errpipe
sudo losetup -o 32256 $(cat $dev) $filename 1>$outpipe 2>$errpipe

#format the image, then make an ext2 filesystem
echo "Formatting the new partition"
size=`expr "$size" "-" "16"`
sudo dd if=/dev/zero of=$(cat $dev) bs=1024 count=$size 1>$outpipe 2>$errpipe
echo "Creating file system on the new partition"
case "$fs" in
    ext2)
        sudo mke2fs -b 1024 -v $(cat $dev) $temp 1>$outpipe 2>$errpipe ;;
    vfat)
        sudo mkfs.vfat $(cat $dev) $temp 1>$outpipe 2>$errpipe ;;
#    jfs)
#        sudo mkfs.jfs $(cat $dev) $temp 1>$outpipe 2>$errpipe ;;
    minix)
        sudo mkfs.minix $(cat $dev) $temp 1>$outpipe 2>$errpipe ;;
    reiserfs)
        sudo mkfs.reiserfs $(cat $dev) $temp 1>$outpipe 2>$errpipe ;;
#    xfs)
#        sudo mkfs.xfs $(cat $dev) $temp 1>$outpipe 2>$errpipe ;;
    *)
        echo "Error formatting the image: Unknown file system type" ;;
esac

#dismount loop devices
echo "Dismounting the raw disk image"
sudo losetup -d $(cat $dev) 1>$outpipe 2>$errpipe
sudo rm $dev

#check and see if we want grub
if test "x$grub" = "x"; then
    echo "Finished creating the image file, would you like to mount it now? [y] \c"
    option=
    read option
    if [ "$option" = "y" ] || [ "x$option" = "x" ]; then
        echo "Mounting the image file"
        sudo mount -o loop,offset=32256 $filename $point 1>$outpipe 2>$errpipe
    fi

    exit 1
fi

#mount the image
test -d "$point" || sudo mkdir "$point" 1>$outpipe 2>$errpipe
sudo umount $point 1>$outpipe 2>$errpipe
echo "Mounting the new partion to \"$point\""
sudo mount -o loop,offset=32256 $filename $point 1>$outpipe 2>$errpipe

####################################################################
#GRUB instalation
echo "Installing grub"
bootdir=${point}/boot
grubdir=${bootdir}/grub
pkglibdir=/usr/lib/grub/x86-pc

echo "Making directory: \"$bootdir\""
sudo mkdir "$bootdir" 1>$outpipe 2>$errpipe
sudo chmod 777 "$bootdir" 1>$outpipe 2>$errpipe 

echo "Making directory: \"$grubdir\""
sudo mkdir "$grubdir" 1>$outpipe 2>$errpipe
sudo chmod 777 "$grubdir" 1>$outpipe 2>$errpipe 

echo "Copying grub files into \"$grubdir\""
for file in \
    ${pkglibdir}/stage1 ${pkglibdir}/stage2 ${pkglibdir}/*stage1_5; do
    sudo cp -f $file $grubdir 1>$outpipe 2>$errpipe
done

sudo chmod 777 $grubdir/* 1>$outpipe 2>$errpipe

echo "Creating menu.lst"
#sudo touch "$grubdir/menu.lst"
echo "
default 0
timeout 0

title		Media Center
root		(hd0,0)
kernel		/boot/osloader/mbloader
module		/system/kernel" 1>$outpipe

sudo cp $outpipe $grubdir/menu.lst 1>$outpipe 2>$errpipe
sudo chmod 777 $grubdir/menu.lst 1>$outpipe 2>$errpipe

sudo umount $point 1>$outpipe 2>$errpipe

sudo losetup -f | tee $dev 1>$outpipe 2>$errpipe
sudo losetup $(cat $dev) $filename 1>$outpipe 2>$errpipe

echo "Copying the grub boot files"
sudo dd if=$pkglibdir/stage1 of=$(cat $dev) bs=512 count=1 1>$outpipe 2>$errpipe
case "$fs" in
    ext2)
        sudo dd if=$pkglibdir/e2fs_stage1_5 of=$(cat $dev) bs=512 seek=1 1>$outpipe 2>$errpipe ;;
    vfat)
        sudo dd if=$pkglibdir/fat_stage1_5 of=$(cat $dev) bs=512 seek=1 1>$outpipe 2>$errpipe ;;
#    jfs)
#        sudo dd if=$pkglibdir/jfs_stage1_5 of=$(cat $dev) bs=512 seek=1 1>$outpipe 2>$errpipe ;;
    minix)
        sudo dd if=$pkglibdir/minix_stage1_5 of=$(cat $dev) bs=512 seek=1 1>$outpipe 2>$errpipe ;;
    reiserfs)
        sudo dd if=$pkglibdir/reiserfs_stage1_5 of=$(cat $dev) bs=512 seek=1 1>$outpipe 2>$errpipe ;;
#    xfs)
#        sudo dd if=$pkglibdir/xfs_stage1_5 of=$(cat $dev) bs=512 seek=1 1>$outpipe 2>$errpipe ;;
    *)
        echo "Error copying GRUB stage 1.5: Unknown file system type" ;;
esac

size=`expr "$cylendars" "*" "$heads"`
size=`expr "$sectors" "*" "$size"`
size=`expr "$size" "-" "63"`

partsize=/tmp/partsize
asciidump=asciidump
$asciidump $size $partsize

sudo dd if=$partsize of=$(cat $dev) bs=2w obs=1 count=1 seek=458 1>$outpipe 2>$errpipe

sudo losetup -d $(cat $dev) 1>$outpipe 2>$errpipe

echo "Finished creating the image file, would you like to mount it now? [y] \c"
option=
read option
if [ "$option" = "y" ] || [ "x$option" = "x" ]; then
    echo "Mounting the image file"
    sudo mount -o loop,offset=32256 $filename $point 1>$outpipe 2>$errpipe
fi

sudo rm $partsize
sudo rm $errpipe
sudo rm $outpipe
sudo rm $dev