Mac Build Scripts
Revision as of 20:24, 26 February 2007 by Tonyr (talk | contribs) (→Replicate Mac Ubuntu Disk: update)
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
This script is in-work...
#!/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