Difference between revisions of "Mac Build Scripts"

From FreekiWiki
Jump to navigation Jump to search
(genMacDisk section)
(→‎genMacDisk.sh: good uuid retrieval; mkofboot updates boot partition)
Line 1,006: Line 1,006:
  
 
------------------------------------------------------------
 
------------------------------------------------------------
#!/bin/sh
+
  #!/bin/sh
#
+
  #
# usage:
+
  # usage:
#      genMacDisk [-t macType] source-device  target-device
+
  #      genMacDisk [-t macType] source-device  target-device
#      -t macType    tweak the relevant files for the target environment
+
  #      -t macType    tweak the relevant files for the target environment
#
+
  #
# Replicate a Mac Ubuntu disk onto a 'clean' disk; this script assumes
+
  # Replicate a Mac Ubuntu disk onto a 'clean' disk; this script assumes
#  that the source is a complete installation in a single directory,  
+
  #  that the source is a complete installation in a single directory,  
#  /root/rootdir/, and a boot partition image in /root/bootpart.img.  The
+
  #  /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.
+
  #  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  
+
  # 1. Take one argument, a target device, and an option specifying the  
#    target platform
+
  #    target platform
# 2. Verify that the target device is a 'clean' disk
+
  # 2. Verify that the target device is a 'clean' disk
# 3. Create partitions on the target device
+
  # 3. Create partitions on the target device
# 4. Create an ext3 filesystem on the linux partition of 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
+
  # 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
+
  #    [There is an alternative: use 'mkofboot' to create an populate the
#    target boot partition. In that case this step wouldn't happen until
+
  #    target boo:t partition. In that case this step wouldn't happen until
#    until after fstab and yaboot.conf are modified.]
+
  #    until after fstab and yaboot.conf are modified.]
# 6. Use rsync to copy the source linux installation directory to the target
+
  # 6. Use rsync to copy the source linux installation directory to the target
#    linux partition
+
  #    linux partition
# 7. modify fstab and yaboot.conf files for target machine environment
+
  # 7. modify fstab and yaboot.conf files for target machine environment
#    [see step 6]
+
  #    [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
+
  errExit () {
    linuxuuid=$(vol_id ${targetlinuxpart} | grep -i uuid | cut -d'=' -f2)
+
  # expect an error number and message string
    swapuuid=$(vol_id ${targetswappart} | grep -i uuid | cut -d'=' -f2)
+
  # show the message, exit with the error number as exit status
+
      local errno msg
    genYbConf $bootDevice
+
      errno=$1
    genFstab $linuxuuid $swapuuid
+
      msg=$2
}
+
      echo $msg
+
      exit $errno
###########################
+
  }
# main                    #
+
 
###########################
+
  genScript () {
# first of all, best be root to do this
+
  # expect a filename string as an argument;
if [ $(whoami) != 'root' ]; then
+
  # create an fdisk script file with the argument filename, overwriting
    errExit 1 "You must be root to run this script; try using sudo"
+
  # existing file of same name
fi
+
      local scriptName
+
      scriptName=$1
# var defs
+
 
linuxImg=/root/rootdir
+
      # length of target drive
bootpartImg=/root/bootpart.img
+
      ## get the hd geometry (hdparm), from that get (awk) the line that has
script="/tmp/fdisk.script"
+
      ## "sectors" in it, and spit out the number of sectors from that line
ybconfName="/tmp/yaboot.conf"
+
      ## (sixth field); then remove (cut) the ',' from the end of the number;
fstabName="/tmp/fstab"
+
      ## The hd length used for partition length calculations is actually one
bootpart=2
+
      ## less that the true disk length, since block zero is ignored.
linuxpart=3
+
      hdlen=$(hdparm -g /dev/$target | awk '/sector/ {print $6}' | cut -d ',' -f 1)
swappart=4
+
      hdlen=$(($hdlen - 1))
getArgs $@
+
     
targetbootpart=/dev/${target}${bootpart}
+
      # starts and lengths for boot, linux and swap partitions
targetswappart=/dev/${target}${swappart}
+
      #
targetlinuxpart=/dev/${target}${linuxpart}
+
      # known values
case $macType in
+
      mapstart=1
    imac) actuallinuxpart=/dev/hda3 ;
+
      maplen=63
          actualswappart=/dev/hda4 ;
+
      bootlen=1954
          actualbootpart=/dev/hda2 ;
+
      swaplen=1494848
          actualcdrom=/dev/hdb ;;
+
     
    g3)  actuallinuxpart=/dev/hdc3 ;
+
      #calculated values
          actualswappart=/dev/hdc4 ;
+
      bootstart=$(($mapstart + $maplen))
          actualbootpart=/dev/hdc2 ;
+
      linuxstart=$(($bootstart + $bootlen))
          actualcdrom=/dev/hda ;;
+
      linuxlen=$(($hdlen-($maplen + $bootlen + $swaplen)))
    g4)  actuallinuxpart=/dev/hda3 ;
+
      swapstart=$(($linuxstart+$linuxlen))
          actualswappart=/dev/hda4 ;
+
 
          actualbootpart=/dev/hda2 ;
+
      # generate and write the commands, creating the script file
          actualcdrom=/dec/hdc ;;
+
      #
    g4q)  actuallinuxpart=/dev/hda3 ;
+
      # initialize partition table, answer disk length query, and show the result
          actualswappart=/dev/hda4 ;
+
      echo i > $scriptName
          actualbootpart=/dev/hda2 ;
+
      echo "" >>  $scriptName
          actualcdrom=/dec/hdc ;;
+
      echo p >> $scriptName
    *)    actuallinuxpart=/dev/hda3 ;
+
     
          actualswappart=/dev/hda4 ;
+
      # create a boot partition with explicit partition size/type, and show result
          actualbootpart=/dev/hda2 ;
+
      echo C >> $scriptName
          actualcdrom=/dev/hdc ;;
+
      echo $bootstart >> $scriptName
esac
+
      echo $bootlen >> $scriptName
+
      echo untitled >> $scriptName
verifyTarget ${target}
+
      echo Apple_Bootstrap >> $scriptName
createPartitions
+
      echo p >> $scriptName
setupForCopy
+
     
copyPartitions
+
      # create a linux native partition, and show result
if [ $macType ]; then  
+
      echo c >> $scriptName
    tweakFilesForTargetMachine $macType
+
      echo $linuxstart >> $scriptName
fi
+
      echo $linuxlen >> $scriptName
exit 0
+
      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=/dec/hdc ;;
 +
      g4q)  actuallinuxpart=/dev/hda3 ;
 +
            actualswappart=/dev/hda4 ;
 +
            actualbootpart=/dev/hda2 ;
 +
            actualcdrom=/dec/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
 +
 
 
------------------------------------------------------------
 
------------------------------------------------------------
  
 
[[Category:Macintosh]]
 
[[Category:Macintosh]]

Revision as of 17:14, 28 February 2007

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=/dec/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=/dec/hdc ;;
    g4q)  actuallinuxpart=/dev/hda3 ;
          actualswappart=/dev/hda4 ;
          actualbootpart=/dev/hda2 ;
          actualcdrom=/dec/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=/dec/hdc ;;
     g4q)  actuallinuxpart=/dev/hda3 ;
           actualswappart=/dev/hda4 ;
           actualbootpart=/dev/hda2 ;
           actualcdrom=/dec/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