Mac Build Scripts

From FreekiWiki
Revision as of 22:59, 19 November 2007 by Tonyr (talk | contribs) (delete Replicate Disk to Disk, obsolete)
Jump to navigation Jump to search

Generate fdisk script

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