Mac Build Scripts

From FreekiWiki
Revision as of 15:37, 23 September 2007 by Tonyr (talk | contribs) (→‎shrink_initrd.sh: added some comments)
Jump to navigation Jump to search

Generate fdisk script

This script takes a raw device argument like /dev/hda and writes out a set of commands that can be fed to fdisk to automatically define a partition table for a Mac. The commands are written to a file named fdisk.script, but that can be changed to stdout, if this script needs to called from another script, for example. It is currently only tested for G3 towers, and needs more work and testing


#!/bin/sh
#
# create a set of input commands for fdisk to use to partition a blank
# drive for Macintosh machines.
#
# Partitions are created in the same order that an Ubuntu installation creates
# them: 
#   1. partition map
#   2. boot partition
#   3. linux partition
#   4. swap partition
# The partition map is automatically created with length 63.  The boot
# partition start block (64) and size (1954) are known (from the Ubuntu model). 
# The swap partition size is fixed arbitrary size, chosen to support 512Mb
# of ram and to allow the swap and linux partition lengths to be even.
 
 scriptName="fdisk.script"
 
 genScript () {
     # generate and write the commands, creating the script file
     #
  
     local target scriptName
 
     # initialize partition table, answer disk length query, and show the result
     echo i > $scriptName
     echo "" >>  $scriptName
     echo p >> $scriptName
     
     # create a boot partition with explicit partition size/type, and show result
     echo C >> $scriptName
     echo $bootstart >> $scriptName
     echo $bootlen >> $scriptName
     echo untitled >> $scriptName
     echo Apple_Bootstrap >> $scriptName
     echo p >> $scriptName
    
     # create a linux native partition, and show result
     echo c >> $scriptName
     echo $linuxstart >> $scriptName
     echo $linuxlen >> $scriptName
     echo c >> $scriptName
     echo p >> $scriptName
     
     # create the swap partition. and show result
     echo $swapstart >> $scriptName
     echo $swaplen >> $scriptName
     echo swap >> $scriptName
     echo p >> $scriptName
    
     # write out the partition map and confirm
     echo w >> $scriptName
     echo "" >> $scriptName
    
     # we done partishin' now
     echo q >> $scriptName
}
    
# first of all, best be root to do this
if [ $(whoami) != 'root' ]; then
    echo "You must be root to run this script; try using sudo"
    exit 1
fi

# need one argument
# target device
if [ -z $1 ]; then
    echo "no target specified"
    exit 2
else
    target=$1
fi

# target device has to exist
hdparm -g $target > /dev/null 2>&1
status=$?
if [ $status -ne 0 ]; then
    echo "device $target does not seem to exist"
    exit 3
fi

# target device must have no partitions
n_partitions=$(( $(fdisk -l $target | grep $target | wc -l) ))
if [ $n_partitions -ne 0 ]; then
    echo "There appear to be existing partitions on $target"
    echo "Quitting"
    exit 4
fi

# length of target drive
## get the hd geometry (hdparm), from that get (awk) the line that has 
## "sectors" in it, and spit out the number of sectors from that line 
## (sixth field); then remove (cut) the ',' from the end of the number;
## The hd length used for partition length calculations is actually one
## less that the true disk length, since block zero is ignored.
hdlen=$(hdparm -g $target | awk '/sector/ {print $6}' | cut -d ',' -f 1)
hdlen=$(($hdlen - 1))

# starts and lengths for boot, linux and swap partitions
#
# known values
mapstart=1
maplen=63
bootlen=1954
swaplen=1494848

#calculated values
bootstart=$(($mapstart + $maplen))
linuxstart=$(($bootstart + $bootlen))
linuxlen=$(($hdlen-($maplen + $bootlen + $swaplen)))
swapstart=$(($linuxstart+$linuxlen))

# debug
#echo "target=           $target"
#echo "hdlen=            $hdlen"
#echo "bootstart=        $bootstart"
#echo "bootlen=          $bootlen"
#echo "linuxstart=       $linuxstart"
#echo "linuxlen=         $linuxlen"
#echo "swapstart=        $swapstart"
#echo "swaplen=          $swaplen"
#calclen=$((63+$bootlen+$linuxlen+$swaplen))
#echo "calculated hdlen= $calclen"

genScript
exit 0

Replicate Mac Ubuntu Disk: Disk to Disk

This script is in-work.

The current version assumes a configuration that has three drives: a boot drive, a replication source and a replication target. It's not really practical solution unless the boot drive is the CD, and the media a bootable CD with all of the necessary software. I'm thinking customized rescue type CD, like the finnix (knoppix based) I currently use in Mac Build. Another possibility would be a netboot configuration (unknown PPC implementation at this point).

The current version is not completely tested as of 26feb07.


#!/bin/sh
#
# usage:
#       copyMacDisk [-t macType] source-device  target-device
#       -t macType     tweak the relevant files for the target environment
#
# Replicate a Mac Ubuntu disk onto a 'clean' disk; this script assumes
#   that the source is a fully installed disk device in its own right and not
#   the host on which this script is running.  The target device is expected
#   to be a 'clean' disk with no partition map.
#   [There is an alternate implentation in my mind's eye that has the
#   entire rooted file system, or install image, in a directory or partition
#   of it's own on the host machine - tr]
#
# 1. Take two arguments, a source device and a target device, and possibly
#    an option specifying the target platform
# 2. Verify that the source device has a Mac Ubuntu installation
# 3. Verify that the target device is a 'clean' disk
# 4. Create partitions on the target device
# 5. Create an ext3 filesystem on the linux partition of the target device
# 6. Use dd to copy the source boot partition to the target boot partition
#    [There is an alternative: use 'mkofboot' to create an populate the
#    target boot partition. In that case this step woujldn't happen until
#    until after fstab and yaboot.conf are modified.]
# 7. Use rsync to copy the source linux image to the target linux partition
# 8. modify fstab and yaboot.conf files for target machine environment
#    [see step 6]

errExit () {
# expect an error number and message string
# show the message, exit with the error number as exit status
    local errno msg
    errno=$1
    msg=$2
    echo $msg
    exit $errno
}

genScript () {
# expect a filename string as an argument;
# create an fdisk script file with the argument filename, overwriting 
# existing file of same name
    local scriptName
    scriptName=$1

    # length of target drive
    ## get the hd geometry (hdparm), from that get (awk) the line that has 
    ## "sectors" in it, and spit out the number of sectors from that line 
    ## (sixth field); then remove (cut) the ',' from the end of the number;
    ## The hd length used for partition length calculations is actually one
    ## less that the true disk length, since block zero is ignored.
    hdlen=$(hdparm -g /dev/$target | awk '/sector/ {print $6}' | cut -d ',' -f 1)
    hdlen=$(($hdlen - 1))
    
    # starts and lengths for boot, linux and swap partitions
    #
    # known values
    mapstart=1
    maplen=63
    bootlen=1954
    swaplen=1494848
    
    #calculated values
    bootstart=$(($mapstart + $maplen))
    linuxstart=$(($bootstart + $bootlen))
    linuxlen=$(($hdlen-($maplen + $bootlen + $swaplen)))
    swapstart=$(($linuxstart+$linuxlen))

    # generate and write the commands, creating the script file
    #
    # initialize partition table, answer disk length query, and show the result
    echo i > $scriptName
    echo "" >>  $scriptName
    echo p >> $scriptName
    
    # create a boot partition with explicit partition size/type, and show result
    echo C >> $scriptName
    echo $bootstart >> $scriptName
    echo $bootlen >> $scriptName
    echo untitled >> $scriptName
    echo Apple_Bootstrap >> $scriptName
    echo p >> $scriptName
    
    # create a linux native partition, and show result
    echo c >> $scriptName
    echo $linuxstart >> $scriptName
    echo $linuxlen >> $scriptName
    echo c >> $scriptName
    echo p >> $scriptName
    
    # create the swap partition. and show result
    echo $swapstart >> $scriptName
    echo $swaplen >> $scriptName
    echo swap >> $scriptName
    echo p >> $scriptName
    
    # write out the partition map and confirm
    echo w >> $scriptName
    echo "" >> $scriptName
    
    # we done partishin' now
    echo q >> $scriptName
}

genYbConf () {
# expect a boot-device string formatted as an OF device-tree name;
# write a candidate yaboot.conf file using target platform values for boot device,
# boot partition and linux root partition.
    local bootdev
    bootdev=$1

    echo '## yaboot.conf generated by the Ubuntu installer' > $ybconfName
    echo '##' >> $ybconfName
    echo '## run: "man yaboot.conf" for details. Do not make changes until you have!!' >> $ybconfName
    echo '## see also: /usr/share/doc/yaboot/examples for example configurations.' >> $ybconfName
    echo '##' >> $ybconfName
    echo '## For a dual-boot menu, add one or more of:' >> $ybconfName
    echo '## bsd=/dev/hdaX, macos=/dev/hdaY, macosx=/dev/hdaZ' >> $ybconfName
    echo  >> $ybconfName
    echo "boot=${actualbootpart}" >> $ybconfName
    echo "device=${bootdev}" >> $ybconfName
    echo 'partition=3' >> $ybconfName
    echo "root=${actuallinuxpart}" >> $ybconfName
    echo 'timeout=50' >> $ybconfName
    echo 'install=/usr/lib/yaboot/yaboot' >> $ybconfName
    echo 'magicboot=/usr/lib/yaboot/ofboot' >> $ybconfName
    echo 'enablecdboot' >> $ybconfName
    echo  >> $ybconfName
    echo 'image=/boot/vmlinux' >> $ybconfName
    echo '        label=Linux' >> $ybconfName
    echo '        read-only' >> $ybconfName
    echo '        initrd=/boot/initrd.img' >> $ybconfName
    echo '        append="quiet splash"' >> $ybconfName
    echo  >> $ybconfName
    echo 'image=/boot/vmlinux.old' >> $ybconfName
    echo '        label=old' >> $ybconfName
    echo '        read-only' >> $ybconfName
    echo '        initrd=/boot/initrd.img.old' >> $ybconfName
    echo '        append="quiet splash"' >> $ybconfName
}

genFstab () {
# expect linux partition uuid and swap partition UUIDs as arguments;
# write a candidate /etc/fstab file using the target platform values for
# swap partition device name and uuid, and linux root partition device
# name and uuid.
    local linuxuuid swapuuid
    linuxuuid=$1
    swapuuid=$2

    echo '# /etc/fstab: static file system information.' > $fstabName
    echo '#' >> $fstabName
    echo '# <file system> <mount point>   <type>  <options>       <dump>  <pass>' >> $fstabName
    echo 'proc            /proc           proc    defaults        0       0' >> $fstabName
    echo "# $actuallinuxpart" >> $fstabName
    echo "UUID=$linuxuuid /               ext3    defaults,errors=remount-ro 0       1" >> $fstabName
    echo "# $actualswappart" >> $fstabName
    echo "UUID=$swapuuid none            swap    sw              0       0" >> $fstabName
    echo "$actualcdrom        /media/cdrom0   udf,iso9660 user,noauto     0       0" >> $fstabName
}

usage () {
# print error message and exit
    errExit 2 "usage: copyMacDisk [-t macType] srcdev targetdev"
}

getArgs () {
# parse command line options and arguments
# set values for globals: src, target, macType
    while getopts t: f; do
        case $f in
        t)  case $OPTARG in
               imac) macType=$OPTARG;;
               g3)   macType=$OPTARG;;
               g4)   macType=$OPTARG;;
               *)    errExit 1 "unrecognized target machine type $OPTARG";;
            esac;;
        *)  usage;;
        esac
    done
    shift `expr $OPTIND - 1`

    if [ $# -lt 2 ]; then
        usage
    else
        src=$(basename $1)
        target=$(basename $2)
    fi
}

verifySource () {
# expect a device name (e.g. hda) as argument;
# test for presence of partition map, and three partitions: boot, linux, swap
# fail/exit if any of these is not there
    local src
    src=$1
    # test: exactly four partitions; successful fdisk has one extra match
    n_partitions=$(( $(fdisk -l /dev/$src | grep $src | wc -l) ))
    if [ $n_partitions -ne 5 ]; then
        errExit 3 "error: $src does not contain 4 partitions"
    fi

    # test: partition 1 is partition map
    part1=$(fdisk -l /dev/$src | grep ${src}1)
    if [ -z "$part1" ]; then
        errExit 4 "error: no partition map found on $src"
    else
        if [ -z "`echo $part1 | grep -i map`" ]; then
            errExit 4 "error: no partition map found on $src"
        fi
    fi

    # test: partition 2 is boot partition
    part2=$(fdisk -l /dev/$src | grep ${src}2)
    if [ -z "$part2" ]; then
        errExit 5 "error: no boot partition found on $src"
    else
        if [ -z "`echo $part2 | grep -i bootstrap`" ]; then
            errExit 5 "error: no boot partition found on $src"
        fi
    fi

    # test: partition 3 is linux partition
    part3=$(fdisk -l /dev/$src | grep ${src}3)
    if [ -z "$part3" ]; then
        errExit 6 "error: no linux partition found on $src"
    else
        if [ -z "`echo $part3 | grep -i native`" ]; then
            errExit 6 "error: no linux partition found on $src"
        fi
    fi

    # test: partition 4 is swap partition
    part4=$(fdisk -l /dev/$src | grep ${src}4)
    if [ -z "$part4" ]; then
        errExit 7 "error: no swap partition found on $src"
    else
        if [ -z "`echo $part4 | grep -i swap`" ]; then
            errExit 7 "error: no swap partition found on $src"
        fi
    fi
}

verifyTarget () {
# expect a device name argument;
# the device is expected to be a 'clean' drive with no partition map
# fail/exit if device does not exist (hdpar failure) or has partitions.
    local target
    target=$1
    # target device has to exist
    hdparm -g $target > /dev/null 2>&1
    status=$?
    if [ $status -ne 0 ]; then
        errExit 8 "error: device $target does not seem to exist"
    fi

    # target device must have no partitions
    n_partitions=$(( $(fdisk -l /dev/$target | grep $target | wc -l) ))
    if [ $n_partitions -ne 0 ]; then
        errExit 9 "error: there appear to be existing partitions on $target"
    fi
}

createPartitions () {
# expect no arguments;
# create an fdisk script, run it, verify that the target linux partition 
# was created and create an ext3 filesystem on it.

    # run the fdisk script
    genScript $script
    fdisk /dev/$target < $script
    # create an ext3 partition on target linux partition
    ## make sure it's there
    n_partitions=$(( $(fdisk -l /dev/$target | grep $targetlinuxpartition | wc -l) ))
    if [ $n_partitions -ne 1 ]; then
        errExit 10 "error: no linux partition $target for fs creation"
    fi
    mkfs.ext3 $targetlinuxpart
}

setupForCopy () {
# verify/create all the necessary mount points using global values
    # create mount points as necessary
    ## linux src
    if [ ! -d /mnt/${srclinuxpart} ]; then
        mkdir /mnt/${srclinuxpart}
    fi
    ## linux target
    if [ ! -d /mnt/${targetlinuxpart} ]; then
        mkdir /mnt/${targetlinuxpart}
    fi
    ## boot target
    if [ ! -d /mnt/${targetbootpart} ]; then
        mkdir /mnt/${targetbootpart}
    fi

    # mount source and target linux partitions
    mount -t ext3 /dev/${srclinuxpart} /mnt/${srclinuxpart}
    status=$?
    if [ $status -ne 0 ]; then
        errExit 11 "error: mount src linux partition failed: /dev/${srclinuxpart} to /mnt/${srclinuxpart}"
    fi
    mount -t ext3 /dev/${targetlinuxpart} /mnt/${targetlinuxpart}
    if [ $status -ne 0 ]; then
        errExit 12 "error: mount target linux partition failed: /dev/${targetlinuxpart} to /mnt/${targetlinuxpart}"
    fi
}

copyPartitions () {
# expect no arguments;
# using global partition names, copy boot partition with dd, and copy 
# linux install image with rsync; verify boot partition by mounting it
# as an hfs filesystem

    # dd source boot partition to target boot partition
    dd if=/dev/${srcbootpart} of=/dev/${targetbootpart}
    # verify boot partition copy
    mount -t hfs /dev/${targetbootpart} /mnt/${targetbootpart}
    if [ $status -ne 0 ]; then
        errExit 13 "error: mount target boot partition failed: /dev/${targetbootpart} to /mnt/${targetbootpart}"
    else
        umount /mnt/${targetbootpart}
    fi
    

    # rsync linux source root to linux target 
    rsync -a /mnt/${src}/ /mnt/${target}/
    status=$?
    if [ $status -ne 0 ]; then
        errExit 14 "error: linux partition copy failed"
    fi
}

tweakFilesForTargetMachine () {
# expect a platform selector as an argument;
# select an OF device-tree definition for the target platform boot-device,
# and capture the UUIDs of the target drive's linux and swap partitions;
# use those values to generate yaboot.conf and fstab files.
    local macType
    macType=$1
#    echo "target machine is $macType"
    
    # OF path to target boot partition.  This must be explicit, since the
    # assumption is that this host is not, in general, the target
    case $mactype in
        imac) bootDevice="/pci@f2000000/mac-io@17/ata-4@1f000/disk@0:";;
        g3)   bootDevice="hd:";;
        g4)   bootDevice="hd:";;
        *)    bootDevice="hd:";;
    esac
 
    # UUID of target and swap partitions
    linuxuuid=$(tune2fs -l /dev/${srclinuxpart} | grep -i uuid | awk '{print $3}')
    swapuuid=$(tune2fs -l /dev/${srcswappart} | grep -i uuid | awk '{print $3}')

    genYbConf $bootDevice
    genFstab $linuxuuid $swapuuid
}

###########################
# main                    #
###########################
# first of all, best be root to do this
if [ $(whoami) != 'root' ]; then
    errExit 1 "You must be root to run this script; try using sudo"
fi

# now get commandline options
# ignore -t for now; if it is ever used, its argument will be
# qualified as a legal specifier.  An illegal specifier is grounds
# for early exit.
while getopts t: f; do
    case $f in
    t)  case $OPTARG in
           imac) macType=$OPTARG;;
           g3)   macType=$OPTARG;;
           g4)   macType=$OPTARG;;
           *)    errExit 1 "unrecognized target machine type $OPTARG";;
        esac;;
    *)  usage;;
    esac
done
shift `expr $OPTIND - 1`

# var defs
script="/tmp/fdisk.script"
ybconfName="/tmp/yaboot.conf"
fstabName="/tmp/fstab"
bootpart=2
linuxpart=3
swappart=4
getArgs $@
srcbootpart=/dev/${src}${bootpart}
srcswappart=/dev/${src}${swappart}
targetbootpart=/dev/${target}${bootpart}
targetswappart=/dev/${target}${swappart}
srclinuxpart=/dev/${src}${linuxpart}
targetlinuxpart=/dev/${target}${linuxpart}
case $macType in
    imac) actuallinuxpart=/dev/hda3 ;
          actualswappart=/dev/hda4 ;
          actualbootpart=/dev/hda2 ;
          actualcdrom=/dev/hdb ;;
    g3)   actuallinuxpart=/dev/hdc3 ;
          actualswappart=/dev/hdc4 ;
          actualbootpart=/dev/hdc2 ;
          actualcdrom=/dev/hda ;;
    g4)   actuallinuxpart=/dev/hda3 ;
          actualswappart=/dev/hda4 ;
          actualbootpart=/dev/hda2 ;
          actualcdrom=/dev/hdc ;;
    *)    actuallinuxpart=/dev/hda3 ;
          actualswappart=/dev/hda4 ;
          actualbootpart=/dev/hda2 ;
          actualcdrom=/dev/hdc ;;
esac

verifySource ${src}
verifyTarget ${target}
createPartitions
setupForCopy
copyPartitions
if [ $macType ]; then 
    tweakFilesForTargetMachine $macType
fi
exit 0

Replicate Mac Ubuntu Disk: Host to Disk

This is the same script as above, but hacked to use a bootpartition image and a copy of the root filesystem, both resident on the host in directory /root. Still needs boot partition mods for correct UUIDs (ybin or mkofboot), and fstab replacement.


#!/bin/sh
#
# usage:
#       copyMacDisk [-t macType] source-device  target-device
#       -t macType     tweak the relevant files for the target environment
#
# Replicate a Mac Ubuntu disk onto a 'clean' disk; this script assumes
#   that the source is a fully installed disk device in its own right and not
#   the host on which this script is running.  The target device is expected
#   to be a 'clean' disk with no partition map.
#   [There is an alternate implentation in my mind's eye that has the
#   entire rooted file system, or install image, in a directory or partition
#   of it's own on the host machine - tr]
#
# 1. Take two arguments, a source device and a target device, and possibly
#    an option specifying the target platform
# 2. Verify that the source device has a Mac Ubuntu installation
# 3. Verify that the target device is a 'clean' disk
# 4. Create partitions on the target device
# 5. Create an ext3 filesystem on the linux partition of the target device
# 6. Use dd to copy the source boot partition to the target boot partition
#    [There is an alternative: use 'mkofboot' to create an populate the
#    target boot partition. In that case this step woujldn't happen until
#    until after fstab and yaboot.conf are modified.]
# 7. Use rsync to copy the source linux image to the target linux partition
# 8. modify fstab and yaboot.conf files for target machine environment
#    [see step 6]

errExit () {
# expect an error number and message string
# show the message, exit with the error number as exit status
    local errno msg
    errno=$1
    msg=$2
    echo $msg
    exit $errno
}

genScript () {
# expect a filename string as an argument;
# create an fdisk script file with the argument filename, overwriting 
# existing file of same name
    local scriptName
    scriptName=$1

    # length of target drive
    ## get the hd geometry (hdparm), from that get (awk) the line that has 
    ## "sectors" in it, and spit out the number of sectors from that line 
    ## (sixth field); then remove (cut) the ',' from the end of the number;
    ## The hd length used for partition length calculations is actually one
    ## less that the true disk length, since block zero is ignored.
    hdlen=$(hdparm -g /dev/$target | awk '/sector/ {print $6}' | cut -d ',' -f 1)
    hdlen=$(($hdlen - 1))
    
    # starts and lengths for boot, linux and swap partitions
    #
    # known values
    mapstart=1
    maplen=63
    bootlen=1954
    swaplen=1494848
    
    #calculated values
    bootstart=$(($mapstart + $maplen))
    linuxstart=$(($bootstart + $bootlen))
    linuxlen=$(($hdlen-($maplen + $bootlen + $swaplen)))
    swapstart=$(($linuxstart+$linuxlen))

    # generate and write the commands, creating the script file
    #
    # initialize partition table, answer disk length query, and show the result
    echo i > $scriptName
    echo "" >>  $scriptName
    echo p >> $scriptName
    
    # create a boot partition with explicit partition size/type, and show result
    echo C >> $scriptName
    echo $bootstart >> $scriptName
    echo $bootlen >> $scriptName
    echo untitled >> $scriptName
    echo Apple_Bootstrap >> $scriptName
    echo p >> $scriptName
    
    # create a linux native partition, and show result
    echo c >> $scriptName
    echo $linuxstart >> $scriptName
    echo $linuxlen >> $scriptName
    echo untitled >> $scriptName
    echo p >> $scriptName
    
    # create the swap partition. and show result
    echo c >> $scriptName
    echo $swapstart >> $scriptName
    echo $swaplen >> $scriptName
    echo swap >> $scriptName
    echo p >> $scriptName
    
    # write out the partition map and confirm
    echo w >> $scriptName
    echo yes >> $scriptName
    
    # we done partishin' now
    echo q >> $scriptName
}

genYbConf () {
# expect a boot-device string formatted as an OF device-tree name;
# write a candidate yaboot.conf file using target platform values for boot device,
# boot partition and linux root partition.
    local bootdev
    bootdev=$1

    echo '## yaboot.conf generated by the Ubuntu installer' > $ybconfName
    echo '##' >> $ybconfName
    echo '## run: "man yaboot.conf" for details. Do not make changes until you have!!' >> $ybconfName
    echo '## see also: /usr/share/doc/yaboot/examples for example configurations.' >> $ybconfName
    echo '##' >> $ybconfName
    echo '## For a dual-boot menu, add one or more of:' >> $ybconfName
    echo '## bsd=/dev/hdaX, macos=/dev/hdaY, macosx=/dev/hdaZ' >> $ybconfName
    echo  >> $ybconfName
    echo "boot=${actualbootpart}" >> $ybconfName
    echo "device=${bootdev}" >> $ybconfName
    echo 'partition=3' >> $ybconfName
    echo "root=${actuallinuxpart}" >> $ybconfName
    echo 'timeout=50' >> $ybconfName
    echo 'install=/usr/lib/yaboot/yaboot' >> $ybconfName
    echo 'magicboot=/usr/lib/yaboot/ofboot' >> $ybconfName
    echo 'enablecdboot' >> $ybconfName
    echo  >> $ybconfName
    echo 'image=/boot/vmlinux' >> $ybconfName
    echo '        label=Linux' >> $ybconfName
    echo '        read-only' >> $ybconfName
    echo '        initrd=/boot/initrd.img' >> $ybconfName
    echo '        append="quiet splash"' >> $ybconfName
    echo  >> $ybconfName
    echo 'image=/boot/vmlinux.old' >> $ybconfName
    echo '        label=old' >> $ybconfName
    echo '        read-only' >> $ybconfName
    echo '        initrd=/boot/initrd.img.old' >> $ybconfName
    echo '        append="quiet splash"' >> $ybconfName
}

genFstab () {
# expect linux partition uuid and swap partition UUIDs as arguments;
# write a candidate /etc/fstab file using the target platform values for
# swap partition device name and uuid, and linux root partition device
# name and uuid.
    local linuxuuid swapuuid
    linuxuuid=$1
    swapuuid=$2

    echo '# /etc/fstab: static file system information.' > $fstabName
    echo '#' >> $fstabName
    echo '# <file system> <mount point>   <type>  <options>       <dump>  <pass>' >> $fstabName
    echo 'proc            /proc           proc    defaults        0       0' >> $fstabName
    echo "# $actuallinuxpart" >> $fstabName
    echo "UUID=$linuxuuid /               ext3    defaults,errors=remount-ro 0       1" >> $fstabName
    echo "# $actualswappart" >> $fstabName
    echo "UUID=$swapuuid none            swap    sw              0       0" >> $fstabName
    echo "$actualcdrom        /media/cdrom0   udf,iso9660 user,noauto     0       0" >> $fstabName
}

usage () {
# print error message and exit
    errExit 2 "usage: copyMacDisk [-t macType] srcdev targetdev"
}

getArgs () {
# parse command line options and arguments
# set values for globals: src, target, macType
    while getopts t: f; do
        case $f in
        t)  case $OPTARG in
               imac) macType=$OPTARG;;
               g3)   macType=$OPTARG;;
               g4)   macType=$OPTARG;;
               g4q)  macType=$OPTARG;;
               *)    errExit 1 "unrecognized target machine type $OPTARG";;
            esac;;
        *)  usage;;
        esac
    done
    shift `expr $OPTIND - 1`

    if [ $# -lt 2 ]; then
        usage
    else
        src=$(basename $1)
        target=$(basename $2)
    fi
}

verifySource () {
# expect a device name (e.g. hda) as argument;
# test for presence of partition map, and three partitions: boot, linux, swap
# fail/exit if any of these is not there
    local src
    src=$1
    # test: exactly four partitions; successful fdisk has one extra match
    n_partitions=$(( $(fdisk -l /dev/$src | grep $src | wc -l) ))
    if [ $n_partitions -ne 5 ]; then
        errExit 3 "error: $src does not contain 4 partitions"
    fi

    # test: partition 1 is partition map
    part1=$(fdisk -l /dev/$src | grep ${src}1)
    if [ -z "$part1" ]; then
        errExit 4 "error: no partition map found on $src"
    else
        if [ -z "`echo $part1 | grep -i map`" ]; then
            errExit 4 "error: no partition map found on $src"
        fi
    fi

    # test: partition 2 is boot partition
    part2=$(fdisk -l /dev/$src | grep ${src}2)
    if [ -z "$part2" ]; then
        errExit 5 "error: no boot partition found on $src"
    else
        if [ -z "`echo $part2 | grep -i bootstrap`" ]; then
            errExit 5 "error: no boot partition found on $src"
        fi
    fi

    # test: partition 3 is linux partition
    part3=$(fdisk -l /dev/$src | grep ${src}3)
    if [ -z "$part3" ]; then
        errExit 6 "error: no linux partition found on $src"
    else
        if [ -z "`echo $part3 | grep -i native`" ]; then
            errExit 6 "error: no linux partition found on $src"
        fi
    fi

    # test: partition 4 is swap partition
    part4=$(fdisk -l /dev/$src | grep ${src}4)
    if [ -z "$part4" ]; then
        errExit 7 "error: no swap partition found on $src"
    else
        if [ -z "`echo $part4 | grep -i swap`" ]; then
            errExit 7 "error: no swap partition found on $src"
        fi
    fi
}

verifyTarget () {
# expect a device name argument;
# the device is expected to be a 'clean' drive with no partition map
# fail/exit if device does not exist (hdpar failure) or has partitions.
    local target
    target=$1
    # target device has to exist
    hdparm -g /dev/$target > /dev/null 2>&1
    status=$?
    if [ $status -ne 0 ]; then
        errExit 8 "error: device $target does not seem to exist"
    fi

    # target device must have no partitions
    n_partitions=$(( $(fdisk -l /dev/$target | grep $target | wc -l) ))
    if [ $n_partitions -ne 0 ]; then
        errExit 9 "error: there appear to be existing partitions on $target"
    fi
}

createPartitions () {
# expect no arguments;
# create an fdisk script, run it, verify that the target linux partition 
# was created and create an ext3 filesystem on it.

    # run the fdisk script
    genScript $script
    fdisk /dev/$target < $script
    # create an ext3 partition on target linux partition
    ## make sure it's there
    n_partitions=$(( $(fdisk -l /dev/$target | grep $targetlinuxpart | wc -l) ))
    if [ $n_partitions -ne 1 ]; then
        errExit 10 "error: no linux partition $targetlinuxpart for fs creation"
    fi
    mkfs.ext3 $targetlinuxpart
    # rumor has it that 'mkswap' creates a new UUID
    mkswap $targetswappart
}

setupForCopy () {
# verify/create all the necessary mount points using global values
    # create mount points as necessary
    ## linux src
    if [ ! -d /mnt/$(basename ${srclinuxpart}) ]; then
        mkdir /mnt/$(basename ${srclinuxpart})
    fi
    ## linux target
    if [ ! -d /mnt/$(basename ${targetlinuxpart}) ]; then
        mkdir /mnt/$(basename ${targetlinuxpart})
    fi
    ## boot target
    if [ ! -d /mnt/$(basename ${targetbootpart}) ]; then
        mkdir /mnt/$(basename ${targetbootpart})
    fi

    # mount source and target linux partitions
#    mount -t ext3 /dev/$(basename ${srclinuxpart}) /mnt/$(basename ${srclinuxpart})
#    status=$?
#    if [ $status -ne 0 ]; then
#        errExit 11 "error: mount src linux partition failed: /dev/${srclinuxpart} to /mnt/${srclinuxpart}"
#    fi  
    mount -t ext3 -o rw /dev/$(basename ${targetlinuxpart}) /mnt/$(basename ${targetlinuxpart})
    status=$?
    if [ $status -ne 0 ]; then
        errExit 12 "error: mount target linux partition failed: /dev/${targetlinuxpart} to /mnt/${targetlinuxpart}"
    fi
}

copyPartitions () {
# expect no arguments;
# using global partition names, copy boot partition with dd, and copy 
# linux install image with rsync; verify boot partition by mounting it
# as an hfs filesystem

    # dd source boot partition to target boot partition
#    dd if=/dev/${srcbootpart} of=/dev/${targetbootpart}
    dd if=/root/bootpart.img of=/dev/$(basename ${targetbootpart})
    # verify boot partition copy
    mount -t hfs /dev/$(basename ${targetbootpart}) /mnt/$(basename ${targetbootpart})
    status=$?
    if [ $status -ne 0 ]; then
        errExit 13 "error: mount target boot partition failed: /dev/${targetbootpart} to /mnt/${targetbootpart}"
    else
        umount /mnt/$(basename ${targetbootpart})
    fi
    

    # rsync linux source root to linux target 
#    rsync -a /mnt/${src}/ /mnt/${targetlinuxpart}/
    rsync -av /root/rootdir/ /mnt/$(basename ${targetlinuxpart})/
    status=$?
    if [ $status -ne 0 ]; then
        errExit 14 "error: linux partition copy failed"
    else
        umount /mnt/$(basename ${targetlinuxpart})
    fi
}

tweakFilesForTargetMachine () {
# expect a platform selector as an argument;
# select an OF device-tree definition for the target platform boot-device,
# and capture the UUIDs of the target drive's linux and swap partitions;
# use those values to generate yaboot.conf and fstab files.
    local macType
    macType=$1
#    echo "target machine is $macType"
    
    # OF path to target boot partition.  This must be explicit, since the
    # assumption is that this host is not, in general, the target
    case $mactype in
        imac) bootDevice="/pci@f2000000/mac-io@17/ata-4@1f000/disk@0:";;
        g3)   bootDevice="/pci@80000000/pci-bridge@d/pci-ata@1/@0/disk@0:";;
        g4)   bootDevice="/pci@f2000000/pci-bridge@d/mac-io@7/ata-4@1f000/disk@0:";;
        g4q)  bootDevice="/pci@f2000000/mac-io@17/ata-4@1f000/disk@0:";;
        *)    bootDevice="hd:";;
    esac
 
    # UUID of targetlinux and targetswap partitions
    linuxuuid=$(vol_id ${targetlinuxpart} | grep -i uuid | cut -d'=' -f2)
    swapuuid=$(vol_id ${targetswappart} | grep -i uuid | cut -d'=' -f2)

    genYbConf $bootDevice
    genFstab $linuxuuid $swapuuid
}

###########################
# main                    #
###########################
# first of all, best be root to do this
if [ $(whoami) != 'root' ]; then
    errExit 1 "You must be root to run this script; try using sudo"
fi

# var defs
script="/tmp/fdisk.script"
ybconfName="/tmp/yaboot.conf"
fstabName="/tmp/fstab"
bootpart=2
linuxpart=3
swappart=4
getArgs $@
srcbootpart=/dev/${src}${bootpart}
srcswappart=/dev/${src}${swappart}
targetbootpart=/dev/${target}${bootpart}
targetswappart=/dev/${target}${swappart}
srclinuxpart=/dev/${src}${linuxpart}
targetlinuxpart=/dev/${target}${linuxpart}
case $macType in
    imac) actuallinuxpart=/dev/hda3 ;
          actualswappart=/dev/hda4 ;
          actualbootpart=/dev/hda2 ;
          actualcdrom=/dev/hdb ;;
    g3)   actuallinuxpart=/dev/hdc3 ;
          actualswappart=/dev/hdc4 ;
          actualbootpart=/dev/hdc2 ;
          actualcdrom=/dev/hda ;;
    g4)   actuallinuxpart=/dev/hda3 ;
          actualswappart=/dev/hda4 ;
          actualbootpart=/dev/hda2 ;
          actualcdrom=/dev/hdc ;;
    g4q)  actuallinuxpart=/dev/hda3 ;
          actualswappart=/dev/hda4 ;
          actualbootpart=/dev/hda2 ;
          actualcdrom=/dev/hdc ;;
    *)    actuallinuxpart=/dev/hda3 ;
          actualswappart=/dev/hda4 ;
          actualbootpart=/dev/hda2 ;
          actualcdrom=/dev/hdc ;;
esac

verifySource ${src}
verifyTarget ${target}
createPartitions
setupForCopy
copyPartitions
if [ $macType ]; then 
    tweakFilesForTargetMachine $macType
fi
exit 0

genMacDisk.sh

The same hacked script as above, but cleaned up somewhat. Still without yaboot.conf and fstab modifiers.



 #!/bin/sh
 #
 # usage:
 #       genMacDisk [-t macType] source-device  target-device
 #       -t macType     tweak the relevant files for the target environment
 #
 # Replicate a Mac Ubuntu disk onto a 'clean' disk; this script assumes
 #   that the source is a complete installation in a single directory, 
 #   /root/rootdir/, and a boot partition image in /root/bootpart.img.  The
 #   target device is expected to be a 'clean' disk with no partition map.
 #
 # 1. Take one argument, a target device, and an option specifying the 
 #    target platform
 # 2. Verify that the target device is a 'clean' disk
 # 3. Create partitions on the target device
 # 4. Create an ext3 filesystem on the linux partition of the target device
 # 5. Use dd to copy the source boot partition to the target boot partition
 #    [There is an alternative: use 'mkofboot' to create an populate the
 #    target boo:t partition. In that case this step wouldn't happen until
 #    until after fstab and yaboot.conf are modified.]
 # 6. Use rsync to copy the source linux installation directory to the target
 #    linux partition
 # 7. modify fstab and yaboot.conf files for target machine environment
 #    [see step 6]
 
 errExit () {
 # expect an error number and message string
 # show the message, exit with the error number as exit status
     local errno msg
     errno=$1
     msg=$2
     echo $msg
     exit $errno
 }
 
 genScript () {
 # expect a filename string as an argument;
 # create an fdisk script file with the argument filename, overwriting 
 # existing file of same name
     local scriptName
     scriptName=$1
 
     # length of target drive
     ## get the hd geometry (hdparm), from that get (awk) the line that has 
     ## "sectors" in it, and spit out the number of sectors from that line 
     ## (sixth field); then remove (cut) the ',' from the end of the number;
     ## The hd length used for partition length calculations is actually one
     ## less that the true disk length, since block zero is ignored.
     hdlen=$(hdparm -g /dev/$target | awk '/sector/ {print $6}' | cut -d ',' -f 1)
     hdlen=$(($hdlen - 1))
     
     # starts and lengths for boot, linux and swap partitions
     #
     # known values
     mapstart=1
     maplen=63
     bootlen=1954
     swaplen=1494848
     
     #calculated values
     bootstart=$(($mapstart + $maplen))
     linuxstart=$(($bootstart + $bootlen))
     linuxlen=$(($hdlen-($maplen + $bootlen + $swaplen)))
     swapstart=$(($linuxstart+$linuxlen))
 
     # generate and write the commands, creating the script file
     #
     # initialize partition table, answer disk length query, and show the result
     echo i > $scriptName
     echo "" >>  $scriptName
     echo p >> $scriptName
     
     # create a boot partition with explicit partition size/type, and show result
     echo C >> $scriptName
     echo $bootstart >> $scriptName
     echo $bootlen >> $scriptName
     echo untitled >> $scriptName
     echo Apple_Bootstrap >> $scriptName
     echo p >> $scriptName
     
     # create a linux native partition, and show result
     echo c >> $scriptName
     echo $linuxstart >> $scriptName
     echo $linuxlen >> $scriptName
     echo untitled >> $scriptName
     echo p >> $scriptName
     
     # create the swap partition. and show result
     echo c >> $scriptName
     echo $swapstart >> $scriptName
     echo $swaplen >> $scriptName
     echo swap >> $scriptName
     echo p >> $scriptName
     
     # write out the partition map and confirm
     echo w >> $scriptName
     echo yes >> $scriptName
     
     # we done partishin' now
     echo q >> $scriptName
 }
 
 genYbConf () {
 # expect a boot-device string formatted as an OF device-tree name;
 # write a candidate yaboot.conf file using target platform values for boot device,
 # boot partition and linux root partition.
     local bootdev
     bootdev=$1
 
     echo '## yaboot.conf generated by the Ubuntu installer' > $ybconfName
     echo '##' >> $ybconfName
     echo '## run: "man yaboot.conf" for details. Do not make changes until you have!!' >> $ybconfName
     echo '## see also: /usr/share/doc/yaboot/examples for example configurations.' >> $ybconfName
     echo '##' >> $ybconfName
     echo '## For a dual-boot menu, add one or more of:' >> $ybconfName
     echo '## bsd=/dev/hdaX, macos=/dev/hdaY, macosx=/dev/hdaZ' >> $ybconfName
     echo  >> $ybconfName
     echo "boot=${actualbootpart}" >> $ybconfName
     echo "device=${bootdev}" >> $ybconfName
     echo 'partition=3' >> $ybconfName
     echo "root=${actuallinuxpart}" >> $ybconfName
     echo 'timeout=50' >> $ybconfName
     echo 'install=/usr/lib/yaboot/yaboot' >> $ybconfName
     echo 'magicboot=/usr/lib/yaboot/ofboot' >> $ybconfName
     echo 'enablecdboot' >> $ybconfName
     echo  >> $ybconfName
     echo 'image=/boot/vmlinux' >> $ybconfName
     echo '        label=Linux' >> $ybconfName
     echo '        read-only' >> $ybconfName
     echo '        initrd=/boot/initrd.img' >> $ybconfName
     echo '        append="quiet splash"' >> $ybconfName
     echo  >> $ybconfName
     echo 'image=/boot/vmlinux.old' >> $ybconfName
     echo '        label=old' >> $ybconfName
     echo '        read-only' >> $ybconfName
     echo '        initrd=/boot/initrd.img.old' >> $ybconfName
     echo '        append="quiet splash"' >> $ybconfName
 }
 
 genFstab () {
 # expect linux partition uuid and swap partition UUIDs as arguments;
 # write a candidate /etc/fstab file using the target platform values for
 # swap partition device name and uuid, and linux root partition device
 # name and uuid.
     local linuxuuid swapuuid
     linuxuuid=$1
     swapuuid=$2
 
     echo '# /etc/fstab: static file system information.' > $fstabName
     echo '#' >> $fstabName
     echo '# <file system> <mount point>   <type>  <options>       <dump>  <pass>' >> $fstabName
     echo 'proc            /proc           proc    defaults        0       0' >> $fstabName
     echo "# $actuallinuxpart" >> $fstabName
     echo "UUID=$linuxuuid /               ext3    defaults,errors=remount-ro 0       1" >> $fstabName
     echo "# $actualswappart" >> $fstabName
     echo "UUID=$swapuuid none            swap    sw              0       0" >> $fstabName
     echo "$actualcdrom        /media/cdrom0   udf,iso9660 user,noauto     0       0" >> $fstabName
 }
 
 usage () {
 # print error message and exit
     errExit 2 "usage: copyMacDisk [-t macType] srcdev targetdev"
 }
 
 getArgs () {
 # parse command line options and arguments
 # set values for globals: src, target, macType
     while getopts t: f; do
         case $f in
         t)  case $OPTARG in
                imac) macType=$OPTARG;;
                g3)   macType=$OPTARG;;
                g4)   macType=$OPTARG;;
                g4q)  macType=$OPTARG;;
                *)    errExit 1 "unrecognized target machine type $OPTARG";;
             esac;;
         *)  usage;;
         esac
     done
     shift `expr $OPTIND - 1`
 
     if [ $# -lt 1 ]; then
         usage
     else
         target=$(basename $1)
     fi
 }
 
 verifyTarget () {
 # expect a device name argument;
 # the device is expected to be a 'clean' drive with no partition map
 # fail/exit if device does not exist (hdpar failure) or has partitions.
     local target
     target=$1
     # target device has to exist
     hdparm -g /dev/$target > /dev/null 2>&1
     status=$?
     if [ $status -ne 0 ]; then
         errExit 8 "error: device $target does not seem to exist"
     fi
 
     # target device must have no partitions
     n_partitions=$(( $(fdisk -l /dev/$target | grep $target | wc -l) ))
     if [ $n_partitions -ne 0 ]; then
         errExit 9 "error: there appear to be existing partitions on $target"
     fi
 }
 
 createPartitions () {
 # expect no arguments;
 # create an fdisk script, run it, verify that the target linux partition 
 # was created and create an ext3 filesystem on it.
 
     # run the fdisk script
     genScript $script
     fdisk /dev/$target < $script
     # create an ext3 partition on target linux partition
     ## make sure it's there
     n_partitions=$(( $(fdisk -l /dev/$target | grep $targetlinuxpart | wc -l) ))
     if [ $n_partitions -ne 1 ]; then
         errExit 10 "error: no linux partition $targetlinuxpart for fs creation"
     fi
     mkfs.ext3 $targetlinuxpart
     # rumor has it that 'mkswap' creates a new UUID
     mkswap $targetswappart
 }
 
 setupForCopy () {
 # verify/create all the necessary mount points using global values
     # create mount points as necessary
     ## linux target
     if [ ! -d /mnt/$(basename ${targetlinuxpart}) ]; then
         mkdir /mnt/$(basename ${targetlinuxpart})
     fi
     ## boot target
     if [ ! -d /mnt/$(basename ${targetbootpart}) ]; then
         mkdir /mnt/$(basename ${targetbootpart})
     fi
 
     # mount target linux partition
     mount -t ext3 -o rw /dev/$(basename ${targetlinuxpart}) /mnt/$(basename ${targetlinuxpart})
     status=$?
     if [ $status -ne 0 ]; then
         errExit 12 "error: mount target linux partition failed: /dev/${targetlinuxpart} to /mnt/${targetlinuxpart}"
     fi
 }
 
 copyPartitions () {
 # expect no arguments;
 # using global partition names, copy boot partition with dd, and copy 
 # linux install image with rsync; verify boot partition by mounting it
 # as an hfs filesystem
 
     # dd source boot partition image to target boot partition
     dd if=${bootpartImg} of=/dev/$(basename ${targetbootpart})
     # verify boot partition copy
     mount -t hfs /dev/$(basename ${targetbootpart}) /mnt/$(basename ${targetbootpart})
     status=$?
     if [ $status -ne 0 ]; then
         errExit 13 "error: mount target boot partition failed: /dev/${targetbootpart} to /mnt/${targetbootpart}"
     else
         umount /mnt/$(basename ${targetbootpart})
     fi
     
 
     # rsync linux source root directory to linux target partition
     rsync -av ${linuxImg}/ /mnt/$(basename ${targetlinuxpart})/
     status=$?
     if [ $status -ne 0 ]; then
         errExit 14 "error: linux partition copy failed"
     else
         umount /mnt/$(basename ${targetlinuxpart})
     fi
 }
 
 tweakFilesForTargetMachine () {
 # expect a platform selector as an argument;
 # select an OF device-tree definition for the target platform boot-device,
 # and capture the UUIDs of the target drive's linux and swap partitions;
 # use those values to generate yaboot.conf and fstab files.
     local macType
     macType=$1
 #    echo "target machine is $macType"
     
     # OF path to target boot partition.  This must be explicit, since the
     # assumption is that this host is not, in general, the target
     case $mactype in
         imac) bootDevice="/pci@f2000000/mac-io@17/ata-4@1f000/disk@0:";;
         g3)   bootDevice="/pci@80000000/pci-bridge@d/pci-ata@1/@0/disk@0:";;
         g4)   bootDevice="/pci@f2000000/pci-bridge@d/mac-io@7/ata-4@1f000/disk@0:";;
         g4q)  bootDevice="/pci@f2000000/mac-io@17/ata-4@1f000/disk@0:";;
         *)    bootDevice="hd:";;
     esac
  
     # UUID of targetlinux and targetswap partitions
     linuxuuid=$(vol_id ${targetlinuxpart} | grep -i uuid | cut -d'=' -f2)
     swapuuid=$(vol_id ${targetswappart} | grep -i uuid | cut -d'=' -f2)
 
     genYbConf $bootDevice
     genFstab $linuxuuid $swapuuid
 
     mount -t ext3 -o rw /dev/$(basename ${targetlinuxpart}) /mnt/$(basename ${targetlinuxpart})
     cp $ybconfName /mnt/$(basename ${targetlinuxpart})/etc/yaboot.conf
     cp $fstabName /mnt/$(basename ${targetlinuxpart})/etc/fstab
     mkofboot -b /dev/$(basename ${targetbootpart}) -o $bootDevice -C /mnt/$(basename ${targetlinuxpart})/etc/yaboot.conf --nonvram
     status=$?
     if [ $status -ne 0 ]; then
         errExit 15 "error: failed to update boot partition"
     fi
 }
 
 ###########################
 # main                    #
 ###########################
 # first of all, best be root to do this
 if [ $(whoami) != 'root' ]; then
     errExit 1 "You must be root to run this script; try using sudo"
 fi
 
 # var defs
 linuxImg=/root/rootdir
 bootpartImg=/root/bootpart.img
 script="/tmp/fdisk.script"
 ybconfName="/tmp/yaboot.conf"
 fstabName="/tmp/fstab"
 bootpart=2
 linuxpart=3
 swappart=4
 getArgs $@
 targetbootpart=/dev/${target}${bootpart}
 targetswappart=/dev/${target}${swappart}
 targetlinuxpart=/dev/${target}${linuxpart}
 case $macType in
     imac) actuallinuxpart=/dev/hda3 ;
           actualswappart=/dev/hda4 ;
           actualbootpart=/dev/hda2 ;
           actualcdrom=/dev/hdb ;;
     g3)   actuallinuxpart=/dev/hdc3 ;
           actualswappart=/dev/hdc4 ;
           actualbootpart=/dev/hdc2 ;
           actualcdrom=/dev/hda ;;
     g4)   actuallinuxpart=/dev/hda3 ;
           actualswappart=/dev/hda4 ;
           actualbootpart=/dev/hda2 ;
           actualcdrom=/dev/hdc ;;
     g4q)  actuallinuxpart=/dev/hda3 ;
           actualswappart=/dev/hda4 ;
           actualbootpart=/dev/hda2 ;
           actualcdrom=/dev/hdc ;;
     *)    actuallinuxpart=/dev/hda3 ;
           actualswappart=/dev/hda4 ;
           actualbootpart=/dev/hda2 ;
           actualcdrom=/dev/hdc ;;
 esac
 
 verifyTarget ${target}
 createPartitions
 setupForCopy
 copyPartitions
 if [ $macType ]; then 
     tweakFilesForTargetMachine $macType
 fi
 exit 0


shrink_initrd.sh

#!/bin/bash
#
# in case you want to know too much about why things aren't working:
#set -x
#set -v

# 
# The goal here is to translate 'initrd.gz', a gzipped cpio archive,
# to CRAMFS version of the same thing, while reducing the size of the
# resulting file to something under 6MB.  The reasons for doing so
# are discussed elsewhere.  See, for example,
#  http://wiki.freegeek.org/index.php?title=User:Tonyr/Journal/Apr07&action=edit&section=9
# and other related entries.
#
# The file to be translated is one of the netboot files in Ubuntu distributions. The files
# for the Ubuntu Feisty(7.04) release are available at
#  http://archive.ubuntu.com/ubuntu/dists/feisty/main/installer-powerpc/current/images/powerpc/netboot
#  The files for Edgy(6.10) and Gutsy(7.10 pre-release) are also available.
#
# This script expects one argument, a filename, which is expected to be an initrd file
# in one of the formats 'gzipped cpio archive', 'cpio archive', or CRAMFS.  The directory
# structure is extracted, a purely subjective set of files is removed from the resulting
# direcortory tree, and that result is re-compressed into both gzipped cpio and CRAMFS
# forms, which are placed in the same directory as the original input file.
# (As of 18Sep07, the CRAMFS extraction is not implemented, but a commented-out
# section of code suggests the process for that.)
#
# usage:  shrink_initrd.sh file_pathname
#
# input:  a compressed initial ram file system in gzipped cpio format or
#         CRAMFS format
# output: newinitrd.gz, a smaller gzipped cpio archive version of the input 
#         newinitrd.img, a CRAMFS version of the same
#           (in the same directory as the original input file)
#
# The input filename may be in either relative or absolute pathname form. 
# So, what are we gonna do?  
# 1. extract the initrd file system image from its compressed form
# 2. remove enough extraneous files to allow a rebuilt initrd image
#    to be smaller than 6MB.
# 3. generate a CRAMFS initrd image and a gzipped cpio archive from
#    the reduced initrd files system
#

# housekeeping functions
function cleanup {
  echo "cleaning up..."
  rm -rf $DIR
  exit
}

function cleanup_on_interrupt {
  echo "cleaning up..."
  rm -rf $DIR
  rm -rf $NEW_INITRD_GZ
  rm -rf $NEW_INITRD_IMG
  exit
}

# leave no trace upon external interruption
trap cleanup_on_interrupt SIGHUP SIGINT SIGTERM

# I suggest running this as root
if [ $(whoami) != root ]; then
  echo "I suggest running this script as root, like, y'know, with sudo"
  exit
fi

# best have a file argument
if [ $# -lt 1 ] ; then
  echo "usage: shrink <initrd_file_name>"
  exit
fi

# now let's define some useful file names;
# the new image files will show up in the same directory as the
# original image.
INITRD_FILE=$1
INITRD_FILE_DIR=$(dirname $INITRD_FILE)
# at various points down the road we're gonna wanna know where we started
HERE=$(pwd)
# I'd really like the new file names to be absolute
if [ "${INITRD_FILE_DIR:0:1}" != "/" ]; then
 INITRD_FILE_DIR=$HERE/$INITRD_FILE_DIR
fi 
NEW_INITRD_GZ="$INITRD_FILE_DIR/newinitrd.gz"
NEW_INITRD_IMG="$INITRD_FILE_DIR/newinitrd.img"

# and mkcramfs must be available
if [ "$(which mkcramfs)" = "" ]; then
  echo "no cramfs tools found, try installing package cramfsprogs"
  exit
fi

# file argument should at least be a regular file
if [ ! -f $1 ]; then
  echo "cannot find regular file $INITRD_FILE"
  exit
else
  echo "processing file $INITRD_FILE"
fi

# It should be either a cpio archive, a gzipped cpio archive,
# or a CRAMFS image
ftype=none
fdesc=$(file $INITRD_FILE)
if echo "$fdesc" | grep -q gzip; then
  fdesc=$(file -z $INITRD_FILE)
  if echo "$fdesc" | grep -q "cpio archive" ; then
    ftype=zcpio
  fi
elif echo "$fdesc" | grep -q "Linux Compressed ROM File System"; then
  ftype=cramfs
elif echo "$fdesc" | grep -q "cpio archive"; then
  ftype=cpio
fi

# hmmm...the input file is not what we were expecting
if [ $ftype = none ]; then
  echo "$INITRD_FILE does not appear to be cpio or cramfs"
  exit
fi

# report the input file size
echo -n "compressed size before: "
du -s $INITRD_FILE

# now make a temporary directory to hold the initrd directory tree
INITRD_DIR=initrd_$$
DIR=/tmp/$INITRD_DIR
mkdir $DIR

# and extract the initrd directory tree to the temp directory
case $ftype in
  cpio) 
    echo "extracting file $INITRD_FILE to $DIR"
    cat $INITRD_FILE | (cd $DIR; cpio -i )
    ;;
  zcpio)
    echo "extracting gzipped cpio file $INITRD_FILE to $DIR"
    gunzip -c $INITRD_FILE | (cd $DIR; cpio -i )
    ;;
  cramfs)
    echo "cramfs extraction not implemented yet";
    cleanup
    ## well, here's a guess about how to do this
    # mkdir /mnt/tmpcramfs
    # mount -t cramfs -o loop $INITRD_FILE /mnt/tmpcramfs
    # cd /mnt/tmpcramfs
    # find . -depth -print | cpio -p --make-directories $DIR
    # umount /mnt/tmpcramfs
    # cd $HERE
    ;;
esac

# I'm assuming that the files I'm interested in are in sub-directories
# of the lib/modules/<kernel-version> directory in the initrd tree.  
# This is not a definitive test, as it only looks for ANY directory
# in the expected location.  There is probably a better way, but it is my
# observation that the <kernel-version> will be the version at major
# release time, not necessarily the actual (updated?) kernel version.
kver=$(ls $DIR/lib/modules)
if [ "$kver" = "" ]; then
  echo "oops, there doesn't seem to be a kernel version modules directory"
  cleanup
  exit
fi

# ok, so now we have a reasonable expectation of doing something useful:
# removing some files named in a list.  I selected the items on this list in
# a purely subjective manner, anything that seemed irrelevant to the task at 
# hand,  namely,  netboot installation of PPC Ubuntu on Macs in the MacBuild 
# area at FreeGeek.  Any usefulness beyond that is serendipity.  On the other
# hand, you can modify this list to suit your own needs.
#
# For my purposes, what is left is the sungem driver and some other drivers
# whose name starts with 'sun' and the tulip drivers for the DEC controllers.
file=( \
lib/firmware/$kver/atmel_at76c502_3com.bin \
lib/firmware/$kver/atmel_at76c502_3com-wpa.bin \
lib/firmware/$kver/atmel_at76c502.bin \
lib/firmware/$kver/atmel_at76c502d.bin \
lib/firmware/$kver/atmel_at76c502d-wpa.bin \
lib/firmware/$kver/atmel_at76c502e.bin \
lib/firmware/$kver/atmel_at76c502e-wpa.bin \
lib/firmware/$kver/atmel_at76c502-wpa.bin \
lib/firmware/$kver/atmel_at76c503-i3861.bin \
lib/firmware/$kver/atmel_at76c503-i3863.bin \
lib/firmware/$kver/atmel_at76c503-rfmd-0.90.2-140.bin \
lib/firmware/$kver/atmel_at76c503-rfmd-acc.bin \
lib/firmware/$kver/atmel_at76c503-rfmd.bin \
lib/firmware/$kver/atmel_at76c504_2958-wpa.bin \
lib/firmware/$kver/atmel_at76c504a_2958-wpa.bin \
lib/firmware/$kver/atmel_at76c504.bin \
lib/firmware/$kver/atmel_at76c504c-wpa.bin \
lib/firmware/$kver/atmel_at76c505a-rfmd2958.bin \
lib/firmware/$kver/atmel_at76c505-rfmd2958.bin \
lib/firmware/$kver/atmel_at76c505-rfmd.bin \
lib/firmware/$kver/atmel_at76c506.bin \
lib/firmware/$kver/atmel_at76c506-wpa.bin \
lib/firmware/$kver/ipw2100-1.3.fw \
lib/firmware/$kver/ipw2100-1.3-i.fw \
lib/firmware/$kver/ipw2100-1.3-p.fw \
lib/firmware/$kver/ipw2200-bss.fw \
lib/firmware/$kver/ipw2200-ibss.fw \
lib/firmware/$kver/ipw2200-sniffer.fw \
lib/modules/$kver/kernel/drivers/net/3c59x.ko \
lib/modules/$kver/kernel/drivers/net/8139cp.ko \
lib/modules/$kver/kernel/drivers/net/8139too.ko \
lib/modules/$kver/kernel/drivers/net/8390.ko \
lib/modules/$kver/kernel/drivers/net/amd8111e.ko \
lib/modules/$kver/kernel/drivers/net/appletalk \
lib/modules/$kver/kernel/drivers/net/arcnet \
lib/modules/$kver/kernel/drivers/net/b44.ko \
lib/modules/$kver/kernel/drivers/net/bmac.ko \
lib/modules/$kver/kernel/drivers/net/bnx2.ko \
lib/modules/$kver/kernel/drivers/net/bonding \
lib/modules/$kver/kernel/drivers/net/cassini.ko \
lib/modules/$kver/kernel/drivers/net/de600.ko \
lib/modules/$kver/kernel/drivers/net/de620.ko \
lib/modules/$kver/kernel/drivers/net/defxx.ko \
lib/modules/$kver/kernel/drivers/net/dl2k.ko \
lib/modules/$kver/kernel/drivers/net/e1000 \
lib/modules/$kver/kernel/drivers/net/e100.ko \
lib/modules/$kver/kernel/drivers/net/eepro100.ko \
lib/modules/$kver/kernel/drivers/net/epic100.ko \
lib/modules/$kver/kernel/drivers/net/eql.ko \
lib/modules/$kver/kernel/drivers/net/fealnx.ko \
lib/modules/$kver/kernel/drivers/net/forcedeth.ko \
lib/modules/$kver/kernel/drivers/net/hamachi.ko \
lib/modules/$kver/kernel/drivers/net/hp100.ko \
lib/modules/$kver/kernel/drivers/net/ixgb \
lib/modules/$kver/kernel/drivers/net/mace.ko \
lib/modules/$kver/kernel/drivers/net/mii.ko \
lib/modules/$kver/kernel/drivers/net/mv643xx_eth.ko \
lib/modules/$kver/kernel/drivers/net/natsemi.ko \
lib/modules/$kver/kernel/drivers/net/ne2k-pci.ko \
lib/modules/$kver/kernel/drivers/net/ns83820.ko \
lib/modules/$kver/kernel/drivers/net/pcmcia \
lib/modules/$kver/kernel/drivers/net/pcnet32.ko \
lib/modules/$kver/kernel/drivers/net/r8169.ko \
lib/modules/$kver/kernel/drivers/net/rrunner.ko \
lib/modules/$kver/kernel/drivers/net/s2io.ko \
lib/modules/$kver/kernel/drivers/net/shaper.ko \
lib/modules/$kver/kernel/drivers/net/sis190.ko \
lib/modules/$kver/kernel/drivers/net/sis900.ko \
lib/modules/$kver/kernel/drivers/net/sk98lin \
lib/modules/$kver/kernel/drivers/net/skfp \
lib/modules/$kver/kernel/drivers/net/skge.ko \
lib/modules/$kver/kernel/drivers/net/sky2.ko \
lib/modules/$kver/kernel/drivers/net/starfire.ko \
lib/modules/$kver/kernel/drivers/net/tg3.ko \
lib/modules/$kver/kernel/drivers/net/tlan.ko \
lib/modules/$kver/kernel/drivers/net/tokenring \
lib/modules/$kver/kernel/drivers/net/tun.ko \
lib/modules/$kver/kernel/drivers/net/typhoon.ko \
lib/modules/$kver/kernel/drivers/net/via-rhine.ko \
lib/modules/$kver/kernel/drivers/net/via-velocity.ko \
lib/modules/$kver/kernel/drivers/net/wireless/airo_cs.ko \
lib/modules/$kver/kernel/drivers/net/wireless/airo.ko \
lib/modules/$kver/kernel/drivers/net/wireless/airport.ko \
lib/modules/$kver/kernel/drivers/net/wireless/atmel_cs.ko \
lib/modules/$kver/kernel/drivers/net/wireless/atmel.ko \
lib/modules/$kver/kernel/drivers/net/wireless/atmel_pci.ko \
lib/modules/$kver/kernel/drivers/net/wireless/ipw2100.ko \
lib/modules/$kver/kernel/drivers/net/wireless/ipw2200.ko \
lib/modules/$kver/kernel/drivers/net/wireless/netwave_cs.ko \
lib/modules/$kver/kernel/drivers/net/wireless/ray_cs.ko \
lib/modules/$kver/kernel/drivers/net/wireless/strip.ko \
lib/modules/$kver/kernel/drivers/net/wireless/wavelan_cs.ko \
lib/modules/$kver/kernel/drivers/net/wireless/wl3501_cs.ko \
lib/modules/$kver/kernel/drivers/net/yellowfin.ko )

# how big is the actual data before removals?
echo -n "raw size before: "
du -s $DIR
# let's crank through the list now, obliterating as we go
for i in $( seq 0 $((${#file[@]} - 1))); do
  rm -rf $DIR/${file[$i]}
#  echo $DIR/${file[$i]}
done
# how big is the actual data after removals?
echo -n "raw size after:  "
du -s $DIR

# now recompress the result with gzip...
cd $DIR
echo "making new gzipped initrd in $NEW_INITRD_GZ"
find . -depth -print | cpio -oc | gzip -c > $NEW_INITRD_GZ
chown ${SUDO_USER}.adm $NEW_INITRD_GZ
# how big is the compressed cpio file after removals?
echo -n "gzip compressed size after:   "
du -s $NEW_INITRD_GZ

# ...and with mkcramfs
echo "making new cramfs initrd in $NEW_INITRD_IMG"
mkcramfs $DIR $NEW_INITRD_IMG
# I'm not gonna leave the resulting files owned by root, but who should own them?
chown ${SUDO_USER}.adm $NEW_INITRD_IMG
# and how big is the compressed cramfs file after removals?
echo -n "cramfs compressed size after: "
du -s $NEW_INITRD_IMG

cleanup