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