Mac Build Scripts
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: Host to Disk
This script uses a bootpartition image and a copy of the root filesystem, both resident on the host in directory /root, to clone a Mac Ubuntu hard drive. Still needs boot partition mods for correct UUIDs (ybin or mkofboot), and fstab replacement. (The current working version is #genMacDisk.sh)
#!/bin/sh # # usage: # copyMacDisk [-t macType] source-device target-device # -t macType tweak the relevant files for the target environment # # Replicate a Mac Ubuntu disk onto a 'clean' disk; this script assumes # that the source is a fully installed disk device in its own right and not # the host on which this script is running. The target device is expected # to be a 'clean' disk with no partition map. # [There is an alternate implentation in my mind's eye that has the # entire rooted file system, or install image, in a directory or partition # of it's own on the host machine - tr] # # 1. Take two arguments, a source device and a target device, and possibly # an option specifying the target platform # 2. Verify that the source device has a Mac Ubuntu installation # 3. Verify that the target device is a 'clean' disk # 4. Create partitions on the target device # 5. Create an ext3 filesystem on the linux partition of the target device # 6. Use dd to copy the source boot partition to the target boot partition # [There is an alternative: use 'mkofboot' to create an populate the # target boot partition. In that case this step woujldn't happen until # until after fstab and yaboot.conf are modified.] # 7. Use rsync to copy the source linux image to the target linux partition # 8. modify fstab and yaboot.conf files for target machine environment # [see step 6] errExit () { # expect an error number and message string # show the message, exit with the error number as exit status local errno msg errno=$1 msg=$2 echo $msg exit $errno } genScript () { # expect a filename string as an argument; # create an fdisk script file with the argument filename, overwriting # existing file of same name local scriptName scriptName=$1 # length of target drive ## get the hd geometry (hdparm), from that get (awk) the line that has ## "sectors" in it, and spit out the number of sectors from that line ## (sixth field); then remove (cut) the ',' from the end of the number; ## The hd length used for partition length calculations is actually one ## less that the true disk length, since block zero is ignored. hdlen=$(hdparm -g /dev/$target | awk '/sector/ {print $6}' | cut -d ',' -f 1) hdlen=$(($hdlen - 1)) # starts and lengths for boot, linux and swap partitions # # known values mapstart=1 maplen=63 bootlen=1954 swaplen=1494848 #calculated values bootstart=$(($mapstart + $maplen)) linuxstart=$(($bootstart + $bootlen)) linuxlen=$(($hdlen-($maplen + $bootlen + $swaplen))) swapstart=$(($linuxstart+$linuxlen)) # generate and write the commands, creating the script file # # initialize partition table, answer disk length query, and show the result echo i > $scriptName echo "" >> $scriptName echo p >> $scriptName # create a boot partition with explicit partition size/type, and show result echo C >> $scriptName echo $bootstart >> $scriptName echo $bootlen >> $scriptName echo untitled >> $scriptName echo Apple_Bootstrap >> $scriptName echo p >> $scriptName # create a linux native partition, and show result echo c >> $scriptName echo $linuxstart >> $scriptName echo $linuxlen >> $scriptName echo untitled >> $scriptName echo p >> $scriptName # create the swap partition. and show result echo c >> $scriptName echo $swapstart >> $scriptName echo $swaplen >> $scriptName echo swap >> $scriptName echo p >> $scriptName # write out the partition map and confirm echo w >> $scriptName echo yes >> $scriptName # we done partishin' now echo q >> $scriptName } genYbConf () { # expect a boot-device string formatted as an OF device-tree name; # write a candidate yaboot.conf file using target platform values for boot device, # boot partition and linux root partition. local bootdev bootdev=$1 echo '## yaboot.conf generated by the Ubuntu installer' > $ybconfName echo '##' >> $ybconfName echo '## run: "man yaboot.conf" for details. Do not make changes until you have!!' >> $ybconfName echo '## see also: /usr/share/doc/yaboot/examples for example configurations.' >> $ybconfName echo '##' >> $ybconfName echo '## For a dual-boot menu, add one or more of:' >> $ybconfName echo '## bsd=/dev/hdaX, macos=/dev/hdaY, macosx=/dev/hdaZ' >> $ybconfName echo >> $ybconfName echo "boot=${actualbootpart}" >> $ybconfName echo "device=${bootdev}" >> $ybconfName echo 'partition=3' >> $ybconfName echo "root=${actuallinuxpart}" >> $ybconfName echo 'timeout=50' >> $ybconfName echo 'install=/usr/lib/yaboot/yaboot' >> $ybconfName echo 'magicboot=/usr/lib/yaboot/ofboot' >> $ybconfName echo 'enablecdboot' >> $ybconfName echo >> $ybconfName echo 'image=/boot/vmlinux' >> $ybconfName echo ' label=Linux' >> $ybconfName echo ' read-only' >> $ybconfName echo ' initrd=/boot/initrd.img' >> $ybconfName echo ' append="quiet splash"' >> $ybconfName echo >> $ybconfName echo 'image=/boot/vmlinux.old' >> $ybconfName echo ' label=old' >> $ybconfName echo ' read-only' >> $ybconfName echo ' initrd=/boot/initrd.img.old' >> $ybconfName echo ' append="quiet splash"' >> $ybconfName } genFstab () { # expect linux partition uuid and swap partition UUIDs as arguments; # write a candidate /etc/fstab file using the target platform values for # swap partition device name and uuid, and linux root partition device # name and uuid. local linuxuuid swapuuid linuxuuid=$1 swapuuid=$2 echo '# /etc/fstab: static file system information.' > $fstabName echo '#' >> $fstabName echo '# <file system> <mount point> <type> <options> <dump> <pass>' >> $fstabName echo 'proc /proc proc defaults 0 0' >> $fstabName echo "# $actuallinuxpart" >> $fstabName echo "UUID=$linuxuuid / ext3 defaults,errors=remount-ro 0 1" >> $fstabName echo "# $actualswappart" >> $fstabName echo "UUID=$swapuuid none swap sw 0 0" >> $fstabName echo "$actualcdrom /media/cdrom0 udf,iso9660 user,noauto 0 0" >> $fstabName } usage () { # print error message and exit errExit 2 "usage: copyMacDisk [-t macType] srcdev targetdev" } getArgs () { # parse command line options and arguments # set values for globals: src, target, macType while getopts t: f; do case $f in t) case $OPTARG in imac) macType=$OPTARG;; g3) macType=$OPTARG;; g4) macType=$OPTARG;; g4q) macType=$OPTARG;; *) errExit 1 "unrecognized target machine type $OPTARG";; esac;; *) usage;; esac done shift `expr $OPTIND - 1` if [ $# -lt 2 ]; then usage else src=$(basename $1) target=$(basename $2) fi } verifySource () { # expect a device name (e.g. hda) as argument; # test for presence of partition map, and three partitions: boot, linux, swap # fail/exit if any of these is not there local src src=$1 # test: exactly four partitions; successful fdisk has one extra match n_partitions=$(( $(fdisk -l /dev/$src | grep $src | wc -l) )) if [ $n_partitions -ne 5 ]; then errExit 3 "error: $src does not contain 4 partitions" fi # test: partition 1 is partition map part1=$(fdisk -l /dev/$src | grep ${src}1) if [ -z "$part1" ]; then errExit 4 "error: no partition map found on $src" else if [ -z "`echo $part1 | grep -i map`" ]; then errExit 4 "error: no partition map found on $src" fi fi # test: partition 2 is boot partition part2=$(fdisk -l /dev/$src | grep ${src}2) if [ -z "$part2" ]; then errExit 5 "error: no boot partition found on $src" else if [ -z "`echo $part2 | grep -i bootstrap`" ]; then errExit 5 "error: no boot partition found on $src" fi fi # test: partition 3 is linux partition part3=$(fdisk -l /dev/$src | grep ${src}3) if [ -z "$part3" ]; then errExit 6 "error: no linux partition found on $src" else if [ -z "`echo $part3 | grep -i native`" ]; then errExit 6 "error: no linux partition found on $src" fi fi # test: partition 4 is swap partition part4=$(fdisk -l /dev/$src | grep ${src}4) if [ -z "$part4" ]; then errExit 7 "error: no swap partition found on $src" else if [ -z "`echo $part4 | grep -i swap`" ]; then errExit 7 "error: no swap partition found on $src" fi fi } verifyTarget () { # expect a device name argument; # the device is expected to be a 'clean' drive with no partition map # fail/exit if device does not exist (hdpar failure) or has partitions. local target target=$1 # target device has to exist hdparm -g /dev/$target > /dev/null 2>&1 status=$? if [ $status -ne 0 ]; then errExit 8 "error: device $target does not seem to exist" fi # target device must have no partitions n_partitions=$(( $(fdisk -l /dev/$target | grep $target | wc -l) )) if [ $n_partitions -ne 0 ]; then errExit 9 "error: there appear to be existing partitions on $target" fi } createPartitions () { # expect no arguments; # create an fdisk script, run it, verify that the target linux partition # was created and create an ext3 filesystem on it. # run the fdisk script genScript $script fdisk /dev/$target < $script # create an ext3 partition on target linux partition ## make sure it's there n_partitions=$(( $(fdisk -l /dev/$target | grep $targetlinuxpart | wc -l) )) if [ $n_partitions -ne 1 ]; then errExit 10 "error: no linux partition $targetlinuxpart for fs creation" fi mkfs.ext3 $targetlinuxpart # rumor has it that 'mkswap' creates a new UUID mkswap $targetswappart } setupForCopy () { # verify/create all the necessary mount points using global values # create mount points as necessary ## linux src if [ ! -d /mnt/$(basename ${srclinuxpart}) ]; then mkdir /mnt/$(basename ${srclinuxpart}) fi ## linux target if [ ! -d /mnt/$(basename ${targetlinuxpart}) ]; then mkdir /mnt/$(basename ${targetlinuxpart}) fi ## boot target if [ ! -d /mnt/$(basename ${targetbootpart}) ]; then mkdir /mnt/$(basename ${targetbootpart}) fi # mount source and target linux partitions # mount -t ext3 /dev/$(basename ${srclinuxpart}) /mnt/$(basename ${srclinuxpart}) # status=$? # if [ $status -ne 0 ]; then # errExit 11 "error: mount src linux partition failed: /dev/${srclinuxpart} to /mnt/${srclinuxpart}" # fi mount -t ext3 -o rw /dev/$(basename ${targetlinuxpart}) /mnt/$(basename ${targetlinuxpart}) status=$? if [ $status -ne 0 ]; then errExit 12 "error: mount target linux partition failed: /dev/${targetlinuxpart} to /mnt/${targetlinuxpart}" fi } copyPartitions () { # expect no arguments; # using global partition names, copy boot partition with dd, and copy # linux install image with rsync; verify boot partition by mounting it # as an hfs filesystem # dd source boot partition to target boot partition # dd if=/dev/${srcbootpart} of=/dev/${targetbootpart} dd if=/root/bootpart.img of=/dev/$(basename ${targetbootpart}) # verify boot partition copy mount -t hfs /dev/$(basename ${targetbootpart}) /mnt/$(basename ${targetbootpart}) status=$? if [ $status -ne 0 ]; then errExit 13 "error: mount target boot partition failed: /dev/${targetbootpart} to /mnt/${targetbootpart}" else umount /mnt/$(basename ${targetbootpart}) fi # rsync linux source root to linux target # rsync -a /mnt/${src}/ /mnt/${targetlinuxpart}/ rsync -av /root/rootdir/ /mnt/$(basename ${targetlinuxpart})/ status=$? if [ $status -ne 0 ]; then errExit 14 "error: linux partition copy failed" else umount /mnt/$(basename ${targetlinuxpart}) fi } tweakFilesForTargetMachine () { # expect a platform selector as an argument; # select an OF device-tree definition for the target platform boot-device, # and capture the UUIDs of the target drive's linux and swap partitions; # use those values to generate yaboot.conf and fstab files. local macType macType=$1 # echo "target machine is $macType" # OF path to target boot partition. This must be explicit, since the # assumption is that this host is not, in general, the target case $mactype in imac) bootDevice="/pci@f2000000/mac-io@17/ata-4@1f000/disk@0:";; g3) bootDevice="/pci@80000000/pci-bridge@d/pci-ata@1/@0/disk@0:";; g4) bootDevice="/pci@f2000000/pci-bridge@d/mac-io@7/ata-4@1f000/disk@0:";; g4q) bootDevice="/pci@f2000000/mac-io@17/ata-4@1f000/disk@0:";; *) bootDevice="hd:";; esac # UUID of targetlinux and targetswap partitions linuxuuid=$(vol_id ${targetlinuxpart} | grep -i uuid | cut -d'=' -f2) swapuuid=$(vol_id ${targetswappart} | grep -i uuid | cut -d'=' -f2) genYbConf $bootDevice genFstab $linuxuuid $swapuuid } ########################### # main # ########################### # first of all, best be root to do this if [ $(whoami) != 'root' ]; then errExit 1 "You must be root to run this script; try using sudo" fi # var defs script="/tmp/fdisk.script" ybconfName="/tmp/yaboot.conf" fstabName="/tmp/fstab" bootpart=2 linuxpart=3 swappart=4 getArgs $@ srcbootpart=/dev/${src}${bootpart} srcswappart=/dev/${src}${swappart} targetbootpart=/dev/${target}${bootpart} targetswappart=/dev/${target}${swappart} srclinuxpart=/dev/${src}${linuxpart} targetlinuxpart=/dev/${target}${linuxpart} case $macType in imac) actuallinuxpart=/dev/hda3 ; actualswappart=/dev/hda4 ; actualbootpart=/dev/hda2 ; actualcdrom=/dev/hdb ;; g3) actuallinuxpart=/dev/hdc3 ; actualswappart=/dev/hdc4 ; actualbootpart=/dev/hdc2 ; actualcdrom=/dev/hda ;; g4) actuallinuxpart=/dev/hda3 ; actualswappart=/dev/hda4 ; actualbootpart=/dev/hda2 ; actualcdrom=/dev/hdc ;; g4q) actuallinuxpart=/dev/hda3 ; actualswappart=/dev/hda4 ; actualbootpart=/dev/hda2 ; actualcdrom=/dev/hdc ;; *) actuallinuxpart=/dev/hda3 ; actualswappart=/dev/hda4 ; actualbootpart=/dev/hda2 ; actualcdrom=/dev/hdc ;; esac verifySource ${src} verifyTarget ${target} createPartitions setupForCopy copyPartitions if [ $macType ]; then tweakFilesForTargetMachine $macType fi exit 0
genMacDisk.sh
This should be the current working version, if I have been diligent with updates. Theyaboot.conf and fstab modifiers have been added.
#!/bin/sh # # usage: # genMacDisk [-t macType] source-device target-device # -t macType tweak the relevant files for the target environment # # Replicate a Mac Ubuntu disk onto a 'clean' disk; this script assumes # that the source is a complete installation in a single directory, # /root/rootdir/, and a boot partition image in /root/bootpart.img. The # target device is expected to be a 'clean' disk with no partition map. # # 1. Take one argument, a target device, and an option specifying the # target platform # 2. Verify that the target device is a 'clean' disk # 3. Create partitions on the target device # 4. Create an ext3 filesystem on the linux partition of the target device # 5. Use dd to copy the source boot partition to the target boot partition # [There is an alternative: use 'mkofboot' to create an populate the # target boo:t partition. In that case this step wouldn't happen until # until after fstab and yaboot.conf are modified.] # 6. Use rsync to copy the source linux installation directory to the target # linux partition # 7. modify fstab and yaboot.conf files for target machine environment # [see step 6] errExit () { # expect an error number and message string # show the message, exit with the error number as exit status local errno msg errno=$1 msg=$2 echo $msg exit $errno } genScript () { # expect a filename string as an argument; # create an fdisk script file with the argument filename, overwriting # existing file of same name local scriptName scriptName=$1 # length of target drive ## get the hd geometry (hdparm), from that get (awk) the line that has ## "sectors" in it, and spit out the number of sectors from that line ## (sixth field); then remove (cut) the ',' from the end of the number; ## The hd length used for partition length calculations is actually one ## less that the true disk length, since block zero is ignored. hdlen=$(hdparm -g /dev/$target | awk '/sector/ {print $6}' | cut -d ',' -f 1) hdlen=$(($hdlen - 1)) # starts and lengths for boot, linux and swap partitions # # known values mapstart=1 maplen=63 bootlen=1954 swaplen=1494848 #calculated values bootstart=$(($mapstart + $maplen)) linuxstart=$(($bootstart + $bootlen)) linuxlen=$(($hdlen-($maplen + $bootlen + $swaplen))) swapstart=$(($linuxstart+$linuxlen)) # generate and write the commands, creating the script file # # initialize partition table, answer disk length query, and show the result echo i > $scriptName echo "" >> $scriptName echo p >> $scriptName # create a boot partition with explicit partition size/type, and show result echo C >> $scriptName echo $bootstart >> $scriptName echo $bootlen >> $scriptName echo untitled >> $scriptName echo Apple_Bootstrap >> $scriptName echo p >> $scriptName # create a linux native partition, and show result echo c >> $scriptName echo $linuxstart >> $scriptName echo $linuxlen >> $scriptName echo untitled >> $scriptName echo p >> $scriptName # create the swap partition. and show result echo c >> $scriptName echo $swapstart >> $scriptName echo $swaplen >> $scriptName echo swap >> $scriptName echo p >> $scriptName # write out the partition map and confirm echo w >> $scriptName echo yes >> $scriptName # we done partishin' now echo q >> $scriptName } genYbConf () { # expect a boot-device string formatted as an OF device-tree name; # write a candidate yaboot.conf file using target platform values for boot device, # boot partition and linux root partition. local bootdev bootdev=$1 echo '## yaboot.conf generated by the Ubuntu installer' > $ybconfName echo '##' >> $ybconfName echo '## run: "man yaboot.conf" for details. Do not make changes until you have!!' >> $ybconfName echo '## see also: /usr/share/doc/yaboot/examples for example configurations.' >> $ybconfName echo '##' >> $ybconfName echo '## For a dual-boot menu, add one or more of:' >> $ybconfName echo '## bsd=/dev/hdaX, macos=/dev/hdaY, macosx=/dev/hdaZ' >> $ybconfName echo >> $ybconfName echo "boot=${actualbootpart}" >> $ybconfName echo "device=${bootdev}" >> $ybconfName echo 'partition=3' >> $ybconfName echo "root=${actuallinuxpart}" >> $ybconfName echo 'timeout=50' >> $ybconfName echo 'install=/usr/lib/yaboot/yaboot' >> $ybconfName echo 'magicboot=/usr/lib/yaboot/ofboot' >> $ybconfName echo 'enablecdboot' >> $ybconfName echo >> $ybconfName echo 'image=/boot/vmlinux' >> $ybconfName echo ' label=Linux' >> $ybconfName echo ' read-only' >> $ybconfName echo ' initrd=/boot/initrd.img' >> $ybconfName echo ' append="quiet splash"' >> $ybconfName echo >> $ybconfName echo 'image=/boot/vmlinux.old' >> $ybconfName echo ' label=old' >> $ybconfName echo ' read-only' >> $ybconfName echo ' initrd=/boot/initrd.img.old' >> $ybconfName echo ' append="quiet splash"' >> $ybconfName } genFstab () { # expect linux partition uuid and swap partition UUIDs as arguments; # write a candidate /etc/fstab file using the target platform values for # swap partition device name and uuid, and linux root partition device # name and uuid. local linuxuuid swapuuid linuxuuid=$1 swapuuid=$2 echo '# /etc/fstab: static file system information.' > $fstabName echo '#' >> $fstabName echo '# <file system> <mount point> <type> <options> <dump> <pass>' >> $fstabName echo 'proc /proc proc defaults 0 0' >> $fstabName echo "# $actuallinuxpart" >> $fstabName echo "UUID=$linuxuuid / ext3 defaults,errors=remount-ro 0 1" >> $fstabName echo "# $actualswappart" >> $fstabName echo "UUID=$swapuuid none swap sw 0 0" >> $fstabName echo "$actualcdrom /media/cdrom0 udf,iso9660 user,noauto 0 0" >> $fstabName } usage () { # print error message and exit errExit 2 "usage: copyMacDisk [-t macType] srcdev targetdev" } getArgs () { # parse command line options and arguments # set values for globals: src, target, macType while getopts t: f; do case $f in t) case $OPTARG in imac) macType=$OPTARG;; g3) macType=$OPTARG;; g4) macType=$OPTARG;; g4q) macType=$OPTARG;; *) errExit 1 "unrecognized target machine type $OPTARG";; esac;; *) usage;; esac done shift `expr $OPTIND - 1` if [ $# -lt 1 ]; then usage else target=$(basename $1) fi } verifyTarget () { # expect a device name argument; # the device is expected to be a 'clean' drive with no partition map # fail/exit if device does not exist (hdpar failure) or has partitions. local target target=$1 # target device has to exist hdparm -g /dev/$target > /dev/null 2>&1 status=$? if [ $status -ne 0 ]; then errExit 8 "error: device $target does not seem to exist" fi # target device must have no partitions n_partitions=$(( $(fdisk -l /dev/$target | grep $target | wc -l) )) if [ $n_partitions -ne 0 ]; then errExit 9 "error: there appear to be existing partitions on $target" fi } createPartitions () { # expect no arguments; # create an fdisk script, run it, verify that the target linux partition # was created and create an ext3 filesystem on it. # run the fdisk script genScript $script fdisk /dev/$target < $script # create an ext3 partition on target linux partition ## make sure it's there n_partitions=$(( $(fdisk -l /dev/$target | grep $targetlinuxpart | wc -l) )) if [ $n_partitions -ne 1 ]; then errExit 10 "error: no linux partition $targetlinuxpart for fs creation" fi mkfs.ext3 $targetlinuxpart # rumor has it that 'mkswap' creates a new UUID mkswap $targetswappart } setupForCopy () { # verify/create all the necessary mount points using global values # create mount points as necessary ## linux target if [ ! -d /mnt/$(basename ${targetlinuxpart}) ]; then mkdir /mnt/$(basename ${targetlinuxpart}) fi ## boot target if [ ! -d /mnt/$(basename ${targetbootpart}) ]; then mkdir /mnt/$(basename ${targetbootpart}) fi # mount target linux partition mount -t ext3 -o rw /dev/$(basename ${targetlinuxpart}) /mnt/$(basename ${targetlinuxpart}) status=$? if [ $status -ne 0 ]; then errExit 12 "error: mount target linux partition failed: /dev/${targetlinuxpart} to /mnt/${targetlinuxpart}" fi } copyPartitions () { # expect no arguments; # using global partition names, copy boot partition with dd, and copy # linux install image with rsync; verify boot partition by mounting it # as an hfs filesystem # dd source boot partition image to target boot partition dd if=${bootpartImg} of=/dev/$(basename ${targetbootpart}) # verify boot partition copy mount -t hfs /dev/$(basename ${targetbootpart}) /mnt/$(basename ${targetbootpart}) status=$? if [ $status -ne 0 ]; then errExit 13 "error: mount target boot partition failed: /dev/${targetbootpart} to /mnt/${targetbootpart}" else umount /mnt/$(basename ${targetbootpart}) fi # rsync linux source root directory to linux target partition rsync -av ${linuxImg}/ /mnt/$(basename ${targetlinuxpart})/ status=$? if [ $status -ne 0 ]; then errExit 14 "error: linux partition copy failed" else umount /mnt/$(basename ${targetlinuxpart}) fi } tweakFilesForTargetMachine () { # expect a platform selector as an argument; # select an OF device-tree definition for the target platform boot-device, # and capture the UUIDs of the target drive's linux and swap partitions; # use those values to generate yaboot.conf and fstab files. local macType macType=$1 # echo "target machine is $macType" # OF path to target boot partition. This must be explicit, since the # assumption is that this host is not, in general, the target case $mactype in imac) bootDevice="/pci@f2000000/mac-io@17/ata-4@1f000/disk@0:";; g3) bootDevice="/pci@80000000/pci-bridge@d/pci-ata@1/@0/disk@0:";; g4) bootDevice="/pci@f2000000/pci-bridge@d/mac-io@7/ata-4@1f000/disk@0:";; g4q) bootDevice="/pci@f2000000/mac-io@17/ata-4@1f000/disk@0:";; *) bootDevice="hd:";; esac # UUID of targetlinux and targetswap partitions linuxuuid=$(vol_id ${targetlinuxpart} | grep -i uuid | cut -d'=' -f2) swapuuid=$(vol_id ${targetswappart} | grep -i uuid | cut -d'=' -f2) genYbConf $bootDevice genFstab $linuxuuid $swapuuid mount -t ext3 -o rw /dev/$(basename ${targetlinuxpart}) /mnt/$(basename ${targetlinuxpart}) cp $ybconfName /mnt/$(basename ${targetlinuxpart})/etc/yaboot.conf cp $fstabName /mnt/$(basename ${targetlinuxpart})/etc/fstab mkofboot -b /dev/$(basename ${targetbootpart}) -o $bootDevice -C /mnt/$(basename ${targetlinuxpart})/etc/yaboot.conf --nonvram status=$? if [ $status -ne 0 ]; then errExit 15 "error: failed to update boot partition" fi } ########################### # main # ########################### # first of all, best be root to do this if [ $(whoami) != 'root' ]; then errExit 1 "You must be root to run this script; try using sudo" fi # var defs linuxImg=/root/rootdir bootpartImg=/root/bootpart.img script="/tmp/fdisk.script" ybconfName="/tmp/yaboot.conf" fstabName="/tmp/fstab" bootpart=2 linuxpart=3 swappart=4 getArgs $@ targetbootpart=/dev/${target}${bootpart} targetswappart=/dev/${target}${swappart} targetlinuxpart=/dev/${target}${linuxpart} case $macType in imac) actuallinuxpart=/dev/hda3 ; actualswappart=/dev/hda4 ; actualbootpart=/dev/hda2 ; actualcdrom=/dev/hdb ;; g3) actuallinuxpart=/dev/hdc3 ; actualswappart=/dev/hdc4 ; actualbootpart=/dev/hdc2 ; actualcdrom=/dev/hda ;; g4) actuallinuxpart=/dev/hda3 ; actualswappart=/dev/hda4 ; actualbootpart=/dev/hda2 ; actualcdrom=/dev/hdc ;; g4q) actuallinuxpart=/dev/hda3 ; actualswappart=/dev/hda4 ; actualbootpart=/dev/hda2 ; actualcdrom=/dev/hdc ;; *) actuallinuxpart=/dev/hda3 ; actualswappart=/dev/hda4 ; actualbootpart=/dev/hda2 ; actualcdrom=/dev/hdc ;; esac verifyTarget ${target} createPartitions setupForCopy copyPartitions if [ $macType ]; then tweakFilesForTargetMachine $macType fi exit 0
shrink_initrd.sh
Net install for powerpc currently requires that the file initrd.gz, distributed with the netinstall files, be reduced in size and mutated from a compressed cpio archive to a cramfs filesystem. The comments in the script pretty much tell the story.
#!/bin/bash # # in case you want to know too much about why things aren't working: #set -x #set -v # # The goal here is to translate 'initrd.gz', a gzipped cpio archive, # to CRAMFS version of the same thing, while reducing the size of the # resulting file to something under 6MB. The reasons for doing so # are discussed elsewhere. See, for example, # http://wiki.freegeek.org/index.php?title=User:Tonyr/Journal/Apr07&action=edit§ion=9 # and other related entries. # # The file to be translated is one of the netboot files in Ubuntu distributions. The files # for the Ubuntu Feisty(7.04) release are available at # http://archive.ubuntu.com/ubuntu/dists/feisty/main/installer-powerpc/current/images/powerpc/netboot # The files for Edgy(6.10) and Gutsy(7.10 pre-release) are also available. # # This script expects one argument, a filename, which is expected to be an initrd file # in one of the formats 'gzipped cpio archive', 'cpio archive', or CRAMFS. The directory # structure is extracted, a purely subjective set of files is removed from the resulting # direcortory tree, and that result is re-compressed into both gzipped cpio and CRAMFS # forms, which are placed in the same directory as the original input file. # (As of 18Sep07, the CRAMFS extraction is not implemented, but a commented-out # section of code suggests the process for that.) # # usage: shrink_initrd.sh file_pathname # # input: a compressed initial ram file system in gzipped cpio format or # CRAMFS format # output: newinitrd.gz, a smaller gzipped cpio archive version of the input # newinitrd.img, a CRAMFS version of the same # (in the same directory as the original input file) # # The input filename may be in either relative or absolute pathname form. # So, what are we gonna do? # 1. extract the initrd file system image from its compressed form # 2. remove enough extraneous files to allow a rebuilt initrd image # to be smaller than 6MB. # 3. generate a CRAMFS initrd image and a gzipped cpio archive from # the reduced initrd files system # # housekeeping functions function cleanup { echo "cleaning up..." rm -rf $DIR exit } function cleanup_on_interrupt { echo "cleaning up..." rm -rf $DIR rm -rf $NEW_INITRD_GZ rm -rf $NEW_INITRD_IMG exit } # leave no trace upon external interruption trap cleanup_on_interrupt SIGHUP SIGINT SIGTERM # I suggest running this as root if [ $(whoami) != root ]; then echo "I suggest running this script as root, like, y'know, with sudo" exit fi # best have a file argument if [ $# -lt 1 ] ; then echo "usage: shrink <initrd_file_name>" exit fi # now let's define some useful file names; # the new image files will show up in the same directory as the # original image. INITRD_FILE=$1 INITRD_FILE_DIR=$(dirname $INITRD_FILE) # at various points down the road we're gonna wanna know where we started HERE=$(pwd) # I'd really like the new file names to be absolute if [ "${INITRD_FILE_DIR:0:1}" != "/" ]; then INITRD_FILE_DIR=$HERE/$INITRD_FILE_DIR fi NEW_INITRD_GZ="$INITRD_FILE_DIR/newinitrd.gz" NEW_INITRD_IMG="$INITRD_FILE_DIR/newinitrd.img" # and mkcramfs must be available if [ "$(which mkcramfs)" = "" ]; then echo "no cramfs tools found, try installing package cramfsprogs" exit fi # file argument should at least be a regular file if [ ! -f $1 ]; then echo "cannot find regular file $INITRD_FILE" exit else echo "processing file $INITRD_FILE" fi # It should be either a cpio archive, a gzipped cpio archive, # or a CRAMFS image ftype=none fdesc=$(file $INITRD_FILE) if echo "$fdesc" | grep -q gzip; then fdesc=$(file -z $INITRD_FILE) if echo "$fdesc" | grep -q "cpio archive" ; then ftype=zcpio fi elif echo "$fdesc" | grep -q "Linux Compressed ROM File System"; then ftype=cramfs elif echo "$fdesc" | grep -q "cpio archive"; then ftype=cpio fi # hmmm...the input file is not what we were expecting if [ $ftype = none ]; then echo "$INITRD_FILE does not appear to be cpio or cramfs" exit fi # report the input file size echo -n "compressed size before: " du -s $INITRD_FILE # now make a temporary directory to hold the initrd directory tree INITRD_DIR=initrd_$$ DIR=/tmp/$INITRD_DIR mkdir $DIR # and extract the initrd directory tree to the temp directory case $ftype in cpio) echo "extracting file $INITRD_FILE to $DIR" cat $INITRD_FILE | (cd $DIR; cpio -i ) ;; zcpio) echo "extracting gzipped cpio file $INITRD_FILE to $DIR" gunzip -c $INITRD_FILE | (cd $DIR; cpio -i ) ;; cramfs) echo "cramfs extraction not implemented yet"; cleanup ## well, here's a guess about how to do this # mkdir /mnt/tmpcramfs # mount -t cramfs -o loop $INITRD_FILE /mnt/tmpcramfs # cd /mnt/tmpcramfs # find . -depth -print | cpio -p --make-directories $DIR # umount /mnt/tmpcramfs # cd $HERE ;; esac # I'm assuming that the files I'm interested in are in sub-directories # of the lib/modules/<kernel-version> directory in the initrd tree. # This is not a definitive test, as it only looks for ANY directory # in the expected location. There is probably a better way, but it is my # observation that the <kernel-version> will be the version at major # release time, not necessarily the actual (updated?) kernel version. kver=$(ls $DIR/lib/modules) if [ "$kver" = "" ]; then echo "oops, there doesn't seem to be a kernel version modules directory" cleanup exit fi # ok, so now we have a reasonable expectation of doing something useful: # removing some files named in a list. I selected the items on this list in # a purely subjective manner, anything that seemed irrelevant to the task at # hand, namely, netboot installation of PPC Ubuntu on Macs in the MacBuild # area at FreeGeek. Any usefulness beyond that is serendipity. On the other # hand, you can modify this list to suit your own needs. # # For my purposes, what is left is the sungem driver and some other drivers # whose name starts with 'sun' and the tulip drivers for the DEC controllers. file=( \ lib/firmware/$kver/atmel_at76c502_3com.bin \ lib/firmware/$kver/atmel_at76c502_3com-wpa.bin \ lib/firmware/$kver/atmel_at76c502.bin \ lib/firmware/$kver/atmel_at76c502d.bin \ lib/firmware/$kver/atmel_at76c502d-wpa.bin \ lib/firmware/$kver/atmel_at76c502e.bin \ lib/firmware/$kver/atmel_at76c502e-wpa.bin \ lib/firmware/$kver/atmel_at76c502-wpa.bin \ lib/firmware/$kver/atmel_at76c503-i3861.bin \ lib/firmware/$kver/atmel_at76c503-i3863.bin \ lib/firmware/$kver/atmel_at76c503-rfmd-0.90.2-140.bin \ lib/firmware/$kver/atmel_at76c503-rfmd-acc.bin \ lib/firmware/$kver/atmel_at76c503-rfmd.bin \ lib/firmware/$kver/atmel_at76c504_2958-wpa.bin \ lib/firmware/$kver/atmel_at76c504a_2958-wpa.bin \ lib/firmware/$kver/atmel_at76c504.bin \ lib/firmware/$kver/atmel_at76c504c-wpa.bin \ lib/firmware/$kver/atmel_at76c505a-rfmd2958.bin \ lib/firmware/$kver/atmel_at76c505-rfmd2958.bin \ lib/firmware/$kver/atmel_at76c505-rfmd.bin \ lib/firmware/$kver/atmel_at76c506.bin \ lib/firmware/$kver/atmel_at76c506-wpa.bin \ lib/firmware/$kver/ipw2100-1.3.fw \ lib/firmware/$kver/ipw2100-1.3-i.fw \ lib/firmware/$kver/ipw2100-1.3-p.fw \ lib/firmware/$kver/ipw2200-bss.fw \ lib/firmware/$kver/ipw2200-ibss.fw \ lib/firmware/$kver/ipw2200-sniffer.fw \ lib/modules/$kver/kernel/drivers/net/3c59x.ko \ lib/modules/$kver/kernel/drivers/net/8139cp.ko \ lib/modules/$kver/kernel/drivers/net/8139too.ko \ lib/modules/$kver/kernel/drivers/net/8390.ko \ lib/modules/$kver/kernel/drivers/net/amd8111e.ko \ lib/modules/$kver/kernel/drivers/net/appletalk \ lib/modules/$kver/kernel/drivers/net/arcnet \ lib/modules/$kver/kernel/drivers/net/b44.ko \ lib/modules/$kver/kernel/drivers/net/bmac.ko \ lib/modules/$kver/kernel/drivers/net/bnx2.ko \ lib/modules/$kver/kernel/drivers/net/bonding \ lib/modules/$kver/kernel/drivers/net/cassini.ko \ lib/modules/$kver/kernel/drivers/net/de600.ko \ lib/modules/$kver/kernel/drivers/net/de620.ko \ lib/modules/$kver/kernel/drivers/net/defxx.ko \ lib/modules/$kver/kernel/drivers/net/dl2k.ko \ lib/modules/$kver/kernel/drivers/net/e1000 \ lib/modules/$kver/kernel/drivers/net/e100.ko \ lib/modules/$kver/kernel/drivers/net/eepro100.ko \ lib/modules/$kver/kernel/drivers/net/epic100.ko \ lib/modules/$kver/kernel/drivers/net/eql.ko \ lib/modules/$kver/kernel/drivers/net/fealnx.ko \ lib/modules/$kver/kernel/drivers/net/forcedeth.ko \ lib/modules/$kver/kernel/drivers/net/hamachi.ko \ lib/modules/$kver/kernel/drivers/net/hp100.ko \ lib/modules/$kver/kernel/drivers/net/ixgb \ lib/modules/$kver/kernel/drivers/net/mace.ko \ lib/modules/$kver/kernel/drivers/net/mii.ko \ lib/modules/$kver/kernel/drivers/net/mv643xx_eth.ko \ lib/modules/$kver/kernel/drivers/net/natsemi.ko \ lib/modules/$kver/kernel/drivers/net/ne2k-pci.ko \ lib/modules/$kver/kernel/drivers/net/ns83820.ko \ lib/modules/$kver/kernel/drivers/net/pcmcia \ lib/modules/$kver/kernel/drivers/net/pcnet32.ko \ lib/modules/$kver/kernel/drivers/net/r8169.ko \ lib/modules/$kver/kernel/drivers/net/rrunner.ko \ lib/modules/$kver/kernel/drivers/net/s2io.ko \ lib/modules/$kver/kernel/drivers/net/shaper.ko \ lib/modules/$kver/kernel/drivers/net/sis190.ko \ lib/modules/$kver/kernel/drivers/net/sis900.ko \ lib/modules/$kver/kernel/drivers/net/sk98lin \ lib/modules/$kver/kernel/drivers/net/skfp \ lib/modules/$kver/kernel/drivers/net/skge.ko \ lib/modules/$kver/kernel/drivers/net/sky2.ko \ lib/modules/$kver/kernel/drivers/net/starfire.ko \ lib/modules/$kver/kernel/drivers/net/tg3.ko \ lib/modules/$kver/kernel/drivers/net/tlan.ko \ lib/modules/$kver/kernel/drivers/net/tokenring \ lib/modules/$kver/kernel/drivers/net/tun.ko \ lib/modules/$kver/kernel/drivers/net/typhoon.ko \ lib/modules/$kver/kernel/drivers/net/via-rhine.ko \ lib/modules/$kver/kernel/drivers/net/via-velocity.ko \ lib/modules/$kver/kernel/drivers/net/wireless/airo_cs.ko \ lib/modules/$kver/kernel/drivers/net/wireless/airo.ko \ lib/modules/$kver/kernel/drivers/net/wireless/airport.ko \ lib/modules/$kver/kernel/drivers/net/wireless/atmel_cs.ko \ lib/modules/$kver/kernel/drivers/net/wireless/atmel.ko \ lib/modules/$kver/kernel/drivers/net/wireless/atmel_pci.ko \ lib/modules/$kver/kernel/drivers/net/wireless/ipw2100.ko \ lib/modules/$kver/kernel/drivers/net/wireless/ipw2200.ko \ lib/modules/$kver/kernel/drivers/net/wireless/netwave_cs.ko \ lib/modules/$kver/kernel/drivers/net/wireless/ray_cs.ko \ lib/modules/$kver/kernel/drivers/net/wireless/strip.ko \ lib/modules/$kver/kernel/drivers/net/wireless/wavelan_cs.ko \ lib/modules/$kver/kernel/drivers/net/wireless/wl3501_cs.ko \ lib/modules/$kver/kernel/drivers/net/yellowfin.ko ) # how big is the actual data before removals? echo -n "raw size before: " du -s $DIR # let's crank through the list now, obliterating as we go for i in $( seq 0 $((${#file[@]} - 1))); do rm -rf $DIR/${file[$i]} # echo $DIR/${file[$i]} done # how big is the actual data after removals? echo -n "raw size after: " du -s $DIR # now recompress the result with gzip... cd $DIR echo "making new gzipped initrd in $NEW_INITRD_GZ" find . -depth -print | cpio -oc | gzip -c > $NEW_INITRD_GZ chown ${SUDO_USER}.adm $NEW_INITRD_GZ # how big is the compressed cpio file after removals? echo -n "gzip compressed size after: " du -s $NEW_INITRD_GZ # ...and with mkcramfs echo "making new cramfs initrd in $NEW_INITRD_IMG" mkcramfs $DIR $NEW_INITRD_IMG # I'm not gonna leave the resulting files owned by root, but who should own them? chown ${SUDO_USER}.adm $NEW_INITRD_IMG # and how big is the compressed cramfs file after removals? echo -n "cramfs compressed size after: " du -s $NEW_INITRD_IMG cleanup