1N/A#!/bin/sh
1N/A# MaKe a Bootable IMAGE --- 1.44, 2.88 and El Torito no-emulation mode
1N/A# C) 2001,2002,2003 Thierry Laronde <tlaronde@polynum.org>
1N/A# C) 2001,2002,2003 Robert Millan <robertmh@gnu.org>
1N/A
1N/A
1N/A# This program is free software; you can redistribute it and/or modify
1N/A# it under the terms of the GNU General Public License as published by
1N/A# the Free Software Foundation; either version 2, or (at your option)
1N/A# any later version.
1N/A#
1N/A# This program is distributed in the hope that it will be useful,
1N/A# but WITHOUT ANY WARRANTY; without even the implied warranty of
1N/A# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1N/A# GNU General Public License for more details.
1N/A#
1N/A# You should have received a copy of the GNU General Public License
1N/A# along with this program; if not, you can either send email to this
1N/A# program's maintainer or write to: The Free Software Foundation,
1N/A# Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
1N/A
1N/A# $Id: mkbimage,v 1.19 2004/07/21 14:43:04 robertmh Exp $
1N/A
1N/A# Global variables
1N/Atarfile=
1N/Adir=
1N/Afs= #file system type
1N/Adecompress=
1N/Aimage_type=
1N/Auname=`uname -s`
1N/APATH=/usr/sbin:$PATH
1N/A
1N/A# You can set GRUB_PATH if you need to use a specially located GRUB.
1N/A# This MUST end by a '/'!
1N/A
1N/A
1N/A#----------------------------DON'T CHANGE: INTERNALS
1N/A
1N/Ablock_size=512
1N/Acylinders=
1N/Aheads=
1N/Asectors=
1N/Acyl_size=
1N/Atype_option=
1N/Ageo_option=
1N/Aimage=
1N/Abk_120=$((2 * 15 * 80))
1N/Abk_144=$((2 * 18 * 80))
1N/Abk_288=$((2 * 36 * 80))
1N/Abk_160=$((2 * 20 * 80))
1N/Abk_168=$((2 * 21 * 80))
1N/Abk_174=$((2 * 21 * 83))
1N/Alo_options=
1N/Adevice_map=
1N/Amkfs_options=
1N/Adebug=
1N/Astage2_os_name=
1N/A
1N/A# Name by which this script was invoked.
1N/Aprogram=`echo "$0" | sed -e 's/[^\/]*\///g'`
1N/Aversion_number='$Revision: 1.19 $'
1N/A
1N/Ausage="
1N/AUsage: $program [-hVF] [-t TYPE] [-d DIRECTORY] [-s FS_TYPE] -f TAR_FILE
1N/AMake a Bootable IMAGE using GRUB as a bootloader
1N/A
1N/AOptions:
1N/A Actions:
1N/A -d DIRECTORY [default CWD]
1N/A Directory where the boot.image and the partition subdirectories
1N/A are/will be created
1N/A -f TAR_FILE
1N/A Name of the tar file containing the filesystem to install. Can
1N/A be a pure tar file [.tar] or a compressed tar file
1N/A [.tar.gz|.tar.bz2]
1N/A -s FS_TYPE
1N/A Type of the file system to create on the virtual disk. Choices
1N/A are:
1N/A ext2 on GNU [default is ext2]
1N/A ext2, minix or msdos on GNU/Linux [default is ext2]
1N/A
1N/A -t TYPE
1N/A Type of the image to create. Choices are '1.20', '1.44', '1.60',
1N/A '1.68', '1.74', '2.88' or 'hd' [default is hd]
1N/A -F
1N/A Force to set the set_dpt flag (unnecessary 99% of the time! Be
1N/A careful!
1N/A Informations:
1N/A -D
1N/A turn Debugging on [xtrace]
1N/A -h|--help
1N/A display this Help and exit
1N/A -V|--version
1N/A display Version information and exit
1N/A
1N/ACopyright (c) 2001,2002,2003 Thierry Laronde <tlaronde@polynum.org>.
1N/ACopyright (c) 2001,2002 Robert Millan <zeratul2@wanadoo.es>.
1N/AGPLed."
1N/A
1N/Aversion="mkbimage $version_number
1N/A
1N/AWritten by Thierry Laronde and Robert Millan.
1N/A
1N/ACopyright (c) 2001,2002,2003 Thierry Laronde <tlaronde@polynum.org>.
1N/ACopyright (c) 2001,2002,2003 Robert Millan <zeratul2@wanadoo.es>.
1N/A
1N/AThis is free software under the GPL version 2 or later; see the source for
1N/Acopying conditions. There is NO warranty, not even for MERCHANTABILITY or
1N/AFITNESS FOR A PARTICULAR PURPOSE."
1N/A
1N/A# Functions
1N/A
1N/Aerror ()
1N/A{
1N/A case $1 in
1N/A bug) echo "This is a bug!";
1N/A echo "$usage";;
1N/A option) echo "Unknow option"; echo "$usage";;
1N/A missing_argument) echo "You must give an argument to the option!";
1N/A echo "$usage";;
1N/A missing_option) echo "You must indicate at least one option!";
1N/A echo "$usage";;
1N/A must_be_root) echo "You must be root! (or install e2tools/mtools)";;
1N/A unknown_fs) if [ $uname = Linux ];
1N/A then echo "The GNU/Linux supported fs are: ext2, minix or msdos!";
1N/A elif [ $uname = GNU ];
1N/A then echo "The GNU supported fs is ext2!";
1N/A fi;;
1N/A unknown_format) echo "The tar file must be .tar|.tar.gz|.tar.bz2!";;
1N/A wont_fit) echo "The files won't fit on the selected type of media!";;
1N/A wrong_directory) echo "Directory inexistant or not given!";
1N/A echo "$usage";;
1N/A wrong_file) echo "File inexistant or empty!";
1N/A echo "$usage";;
1N/A wrong_type) echo "The type specified is not a valid one!";
1N/A echo "$usage";;
1N/A esac
1N/A exit 1
1N/A}
1N/A
1N/A# create a filesystem of type $fs in $image with offset $offset
1N/Amkbimage_mkfs ()
1N/A{
1N/A case $offset in
1N/A 0) lo_options="";;
1N/A *) lo_options="-o $offset";;
1N/A esac
1N/A
1N/A if [ "$offset" = "0" ] ; then
1N/A mkfs.$fs -F $image
1N/A elif [ `id -u` = "0" ] ; then
1N/A losetup $lo_options /dev/loop1 $image
1N/A mkfs.$fs /dev/loop1
1N/A losetup -d /dev/loop1
1N/A else
1N/A error must_be_root
1N/A fi
1N/A}
1N/A
1N/A# copy ${image}1/* to ${image}:/, assuming ${image} contains a filesystem
1N/A# of type $fs in offset $offset
1N/Amkbimage_cp ()
1N/A{
1N/A case $offset in
1N/A 0) lo_options="";;
1N/A *) lo_options="-o $offset";;
1N/A esac
1N/A case $fs in
1N/A ext2)
1N/A cp="e2cp";
1N/A mkdir="e2mkdir";;
1N/A vfat)
1N/A cp="mcopy";
1N/A mkdir="mmd";;
1N/A *)
1N/A cp="";
1N/A mkdir="";;
1N/A esac
1N/A
1N/A if [ "$offset" = 0 ] && which $cp > /dev/null ; then
1N/A for dir in $(cd ${image}1 && find -type d) ; do
1N/A $mkdir ${image}:$dir
1N/A done
1N/A for file in $(cd ${image}1 && find -type f) ; do
1N/A $cp ${image}1/$file ${image}:$file
1N/A done
1N/A elif [ "`id -u`" = "0" ] ; then
1N/A losetup $lo_options /dev/loop1 $image
1N/A mkdir ${image}.mnt
1N/A mount -t $fs /dev/loop1 ${image}.mnt
1N/A cp -a ${image}1/* ${image}.mnt/ && sync
1N/A umount ${image}.mnt
1N/A rmdir ${image}.mnt
1N/A losetup -d /dev/loop1
1N/A else
1N/A error must_be_root
1N/A fi
1N/A}
1N/A
1N/A#**********************************************************************
1N/A# MAIN PROGRAM *
1N/A#**********************************************************************
1N/A
1N/A#---------------------- Getting the options
1N/A
1N/A[ $# -eq 0 ] && error missing_option;
1N/A
1N/Awhile [ $# -gt 0 ]; do
1N/A case "$1" in
1N/A -d) shift;
1N/A dir="$1";
1N/A [ ! -d "$1" ] && error wrong_directory;;
1N/A -f) shift;
1N/A tarfile="$1";
1N/A [ -z "$tarfile" ] && error missing_argument;;
1N/A -s) shift;
1N/A fs="$1";;
1N/A -t) shift;
1N/A image_type="$1";;
1N/A -F) geo_option="-F";;
1N/A -D) debug="-v";
1N/A set -x;;
1N/A -h|--help) echo "$usage"; exit 0;;
1N/A -V|--version) echo "$version"; exit 0;;
1N/A *) error option ;;
1N/A esac
1N/Ashift
1N/Adone
1N/A#---------------------- Sanity checks
1N/A[ ! "$tarfile" ] && error missing_argument;
1N/A[ ! -s "$tarfile" ] && error wrong_file;
1N/A
1N/Aif [ ! "$image_type" ]; then
1N/A image_type=hd;
1N/Aelif [ "$image_type" != "1.20" ] && [ "$image_type" != "1.44" ] \
1N/A && [ "$image_type" != "1.60" ] && [ "$image_type" != "1.68" ] \
1N/A && [ "$image_type" != "2.88" ] && [ "$image_type" != "1.74" ] \
1N/A && [ "$image_type" != "hd" ] && [ "$image_type" != "1.60" ] ; then
1N/A error wrong_type ;
1N/Afi
1N/A
1N/A[ ! "$fs" ] && fs=ext2
1N/A
1N/A# Carlo Contavalli reported that I [TL] have forgotten to specify the
1N/A# partition ID for sfdisk to correctly fill the partition table (ext2 is the
1N/A# default on Linux, so this worked in this case...). This is fixed below.
1N/Acase "$fs" in
1N/A ext2) mkfs_options="-m 0";
1N/A part_id="83";; # This is the default
1N/A# ufs) if [ $uname = Linux ];
1N/A# then error unknown_fs;
1N/A# fi;;
1N/A minix) if [ $uname = GNU ];
1N/A then error unknown_fs;
1N/A else
1N/A mkfs_options="-v"; # Minix version 2
1N/A part_id="81";
1N/A fi;;
1N/A msdos) if [ $uname = GNU ];
1N/A then error unknown_fs;
1N/A else
1N/A mkfs_options="-f 1 -F 12"; # the smallest...
1N/A part_id="1";
1N/A fi;;
1N/A *) error unknown_fs;;
1N/Aesac
1N/A
1N/A# What type of tar file has been given ?
1N/A
1N/Asuffix=`echo "$tarfile" | sed -n 's/^.*\.\([targbz2]\{2,3\}\)$/\1/p'`
1N/Acase "$suffix" in
1N/A tar) decompress="cat";;
1N/A gz) decompress="gunzip -c";;
1N/A bz2) decompress="bunzip2 -c";;
1N/A *) error unknown_format;;
1N/Aesac
1N/A#---------------------- Initializations
1N/A
1N/A[ ! "$dir" ] && dir=`pwd`
1N/A
1N/Aimage=$dir/$image_type.image
1N/Adevice_map=$dir/device.map
1N/A
1N/A# First, find the size of the tar file in block_size.
1N/Afile_size=`$decompress $tarfile | wc -c | tr -d ' '`
1N/Afile_size=$(($file_size / $block_size + 1))
1N/A
1N/A# Increase in order to be sure that with a fs there will be enough
1N/A# room (trying 110%)
1N/Afile_size=$(($file_size + $file_size / 10))
1N/A
1N/Acase "$image_type" in
1N/A hd) heads=16;
1N/A sectors=63;
1N/A cyl_size=$((16 * 63));
1N/A # Create the minimum number of cylinders. At the moment, we leave
1N/A # some space by rounding everything up by adding 1 cylinder, plus
1N/A # another one for MBR + reserved track.
1N/A cylinders=$(($file_size / $cyl_size + 2));;
1N/A 1.20) [ $file_size -ge $bk_120 ] && error wont_fit;
1N/A heads=2;
1N/A sectors=15;
1N/A cyl_size=$((2 * 15));
1N/A cylinders=80;;
1N/A 1.44) [ $file_size -ge $bk_144 ] && error wont_fit;
1N/A heads=2;
1N/A sectors=18;
1N/A cyl_size=$((2 * 18));
1N/A cylinders=80;;
1N/A 1.60) [ $file_size -ge $bk_160 ] && error wont_fit;
1N/A heads=2;
1N/A sectors=20;
1N/A cyl_size=$((2 * 20));
1N/A cylinders=80;
1N/A geo_option="-F";;
1N/A 1.68) [ $file_size -ge $bk_168 ] && error wont_fit;
1N/A heads=2;
1N/A sectors=21;
1N/A cyl_size=$((2 * 21));
1N/A cylinders=80;;
1N/A 1.74) [ $file_size -ge $bk_174 ] && error wont_fit;
1N/A heads=2;
1N/A sectors=21;
1N/A cyl_size=$((2 * 21));
1N/A cylinders=83;;
1N/A 2.88) [ $file_size -ge $bk_288 ] && error wont_fit;
1N/A heads=2;
1N/A sectors=36;
1N/A cyl_size=$((2 * 36));
1N/A cylinders=80;;
1N/A *) error bug;;
1N/Aesac
1N/A
1N/Atype_option="-t $image_type"
1N/A
1N/A# We start by creating a virtual disk which size is the number of
1N/A# cylinders of $cyl_size mandatory to put the files stocked in the $tarfile
1N/A# Create the empty virtual disk
1N/Add if=/dev/zero of=$image bs=$block_size count=$(($cyl_size * $cylinders))
1N/A
1N/A# We then format the virtual disk
1N/A# NOTE: the El Torito specification wants only one partition. So we
1N/A# create the first, and the remaining 3 entries are empty.
1N/A
1N/Aif [ "$image_type" = "hd" ]; then
1N/A sfdisk -C $cylinders -H $heads -S $sectors -D $image<<EOT
1N/A,,$part_id,*,0,1,1
1N/A
1N/A
1N/AEOT
1N/A offset="$(($sectors * $block_size))"
1N/A type_option=
1N/Aelse
1N/A offset="0"
1N/Afi
1N/A
1N/A# It's time now to create the filesystem on the first partition.
1N/Amkbimage_mkfs
1N/A
1N/A# then untar the files
1N/A[ ! -e ${image}1 ] || { echo "${image}1 exists, please remove it first"; exit 1;}
1N/Amkdir -p ${image}1
1N/A$decompress $tarfile | tar -C ${image}1 $debug -xf -
1N/A
1N/A# copy the untarred files into the filesystem image
1N/Amkbimage_cp
1N/A
1N/A#We verify that the stage2 exists and we search the name
1N/Astage2_os_name=`find ${image}1 -name stage2 -type f`
1N/A
1N/A[ -r "$stage2_os_name" ] || { echo "I can't find stage2!"; exit 1;}
1N/A
1N/A#------------------------- GRUB stuff
1N/Aif [ "$image_type" = "hd" ]; then
1N/A device='(hd0)'
1N/A root='(hd0,0)'
1N/Aelse
1N/A device='(fd0)'
1N/A root='(fd0)'
1N/Afi
1N/A
1N/Acat<<EOT >$device_map
1N/A$device ${image}
1N/AEOT
1N/A
1N/A${GRUB_PATH}grub --device-map=$device_map --batch<<EOT
1N/Ageometry $device $cylinders $heads $sectors
1N/Aroot $root
1N/Asetup $device
1N/Ageometry $geo_option -w $type_option $device $cylinders $heads $sectors
1N/AEOT
1N/A
1N/Aecho "-------------------WHAT'S NEXT?-------------------------------------"
1N/Aecho
1N/A
1N/Acat <<EOF
1N/AIf you have created an image aimed to a floppy, then something like:
1N/A
1N/Add if=<type>.image of=/dev/fd0[u<size>] bs=512
1N/A
1N/Awill be more than enough... if you have formated the floppy correctly
1N/Ausing \`superformat' to be found in \`fdutils' package.
1N/A
1N/AFor El Torito floppy emulation :
1N/A
1N/Amkisofs -b <image> -c boot.catalog -o raw.iso <dir>
1N/A
1N/AAnd for El Torito Hard Disk emulation:
1N/A
1N/Amkisofs -b <image> -hard-disk-boot -c boot.catalog -o raw.iso <dir>
1N/A
1N/AEnjoy!
1N/AEOF
1N/A
1N/Arm -rf ${image}1
1N/A
1N/Aexit 0