Version 13.4.5
[livecd.git] / tools / livecd-iso-to-disk.sh
blob3e149d7ecba81ba0ce9b7fd86ba42667750277d2
1 #!/bin/bash
2 # Convert a live CD iso so that it's bootable off of a USB stick
3 # Copyright 2007 Red Hat, Inc.
4 # Jeremy Katz <katzj@redhat.com>
6 # overlay/persistence enhancements by Douglas McClendon <dmc@viros.org>
7 # GPT+MBR hybrid enhancements by Stewart Adam <s.adam@diffingo.com>
8 #
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; version 2 of the License.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU Library General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 export PATH=/sbin:/usr/sbin:$PATH
25 usage() {
26 echo "$0 [--timeout <time>] [--totaltimeout <time>] [--format] [--reset-mbr] [--noverify] [--overlay-size-mb <size>] [--home-size-mb <size>] [--unencrypted-home] [--skipcopy] [--efi] <isopath> <usbstick device>"
27 exit 1
30 cleanup() {
31 sleep 2
32 [ -d "$CDMNT" ] && umount $CDMNT && rmdir $CDMNT
33 [ -d "$USBMNT" ] && umount $USBMNT && rmdir $USBMNT
36 exitclean() {
37 echo "Cleaning up to exit..."
38 cleanup
39 exit 1
42 isdevloop() {
43 [ x"${1#/dev/loop}" != x"$1" ]
46 getdisk() {
47 DEV=$1
49 if isdevloop "$DEV"; then
50 device="$DEV"
51 return
54 p=$(udevadm info -q path -n $DEV)
55 if [ $? -gt 0 ]; then
56 echo "Error getting udev path to $DEV"
57 exitclean
59 if [ -e /sys/$p/device ]; then
60 device=$(basename /sys/$p)
61 else
62 device=$(basename $(readlink -f /sys/$p/../))
64 if [ ! -e /sys/block/$device -o ! -e /dev/$device ]; then
65 echo "Error finding block device of $DEV. Aborting!"
66 exitclean
69 device="/dev/$device"
70 # FIXME: weird dev names could mess this up I guess
71 p=/dev/$(basename $p)
72 partnum=${p##$device}
75 getpartition() {
76 DEV=$1
77 pa=$( < /proc/partitions )
78 pa=${pa##*$DEV}
79 partnum=${pa%% *}
82 resetMBR() {
83 if isdevloop "$DEV"; then
84 return
86 getdisk $1
87 # if efi, we need to use the hybrid MBR
88 if [ -n "$efi" ];then
89 if [ -f /usr/lib/syslinux/gptmbr.bin ]; then
90 cat /usr/lib/syslinux/gptmbr.bin > $device
91 elif [ -f /usr/share/syslinux/gptmbr.bin ]; then
92 cat /usr/share/syslinux/gptmbr.bin > $device
93 else
94 echo "Could not find gptmbr.bin (syslinux)"
95 exitclean
97 # Make it bootable on EFI and BIOS
98 parted -s $device set $partnum legacy_boot on
99 else
100 if [ -f /usr/lib/syslinux/mbr.bin ]; then
101 cat /usr/lib/syslinux/mbr.bin > $device
102 elif [ -f /usr/share/syslinux/mbr.bin ]; then
103 cat /usr/share/syslinux/mbr.bin > $device
104 else
105 echo "Could not find mbr.bin (syslinux)"
106 exitclean
111 checkMBR() {
112 if isdevloop "$DEV"; then
113 return 0
115 getdisk $1
117 bs=$(mktemp /tmp/bs.XXXXXX)
118 dd if=$device of=$bs bs=512 count=1 2>/dev/null || exit 2
120 mbrword=$(hexdump -n 2 $bs |head -n 1|awk {'print $2;'})
121 rm -f $bs
122 if [ "$mbrword" = "0000" ]; then
123 echo "MBR appears to be blank."
124 echo "Do you want to replace the MBR on this device?"
125 echo "Press Enter to continue or ctrl-c to abort"
126 read
127 resetMBR $1
130 return 0
133 checkPartActive() {
134 dev=$1
135 getdisk $dev
137 # if we're installing to whole-disk and not a partition, then we
138 # don't need to worry about being active
139 if [ "$dev" = "$device" ]; then
140 return
142 if isdevloop "$DEV"; then
143 return
146 if [ "$(/sbin/fdisk -l $device 2>/dev/null |grep $dev |awk {'print $2;'})" != "*" ]; then
147 echo "Partition isn't marked bootable!"
148 echo "You can mark the partition as bootable with "
149 echo " # /sbin/parted $device"
150 echo " (parted) toggle N boot"
151 echo " (parted) quit"
152 exitclean
156 checkLVM() {
157 dev=$1
159 if [ -x /sbin/pvs -a \
160 "$(/sbin/pvs -o vg_name --noheadings $dev* 2>/dev/null)" ]; then
161 echo "Device, $dev, contains a volume group and cannot be formated!"
162 echo "You can remove the volume group using vgremove."
163 exitclean
165 return 0
168 createGPTLayout() {
169 dev=$1
170 getdisk $dev
172 echo "WARNING: THIS WILL DESTROY ANY DATA ON $device!!!"
173 echo "Press Enter to continue or ctrl-c to abort"
174 read
175 umount ${device}* &> /dev/null
176 wipefs -a ${device}
177 /sbin/parted --script $device mklabel gpt
178 partinfo=$(LC_ALL=C /sbin/parted --script -m $device "unit b print" |grep ^$device:)
179 size=$(echo $partinfo |cut -d : -f 2 |sed -e 's/B$//')
180 /sbin/parted --script $device unit b mkpart '"EFI System Partition"' fat32 1048576 $(($size - 1048576)) set 1 boot on
181 # Sometimes automount can be _really_ annoying.
182 echo "Waiting for devices to settle..."
183 /sbin/udevadm settle
184 sleep 5
185 getpartition ${device#/dev/}
186 USBDEV=${device}${partnum}
187 umount $USBDEV &> /dev/null
188 /sbin/mkdosfs -n LIVE $USBDEV
189 USBLABEL="UUID=$(/sbin/blkid -s UUID -o value $USBDEV)"
192 createMSDOSLayout() {
193 dev=$1
194 getdisk $dev
196 echo "WARNING: THIS WILL DESTROY ANY DATA ON $device!!!"
197 echo "Press Enter to continue or ctrl-c to abort"
198 read
199 umount ${device}* &> /dev/null
200 wipefs -a ${device}
201 /sbin/parted --script $device mklabel msdos
202 partinfo=$(LC_ALL=C /sbin/parted --script -m $device "unit b print" |grep ^$device:)
203 size=$(echo $partinfo |cut -d : -f 2 |sed -e 's/B$//')
204 /sbin/parted --script $device unit b mkpart primary fat32 1048576 $(($size - 1048576)) set 1 boot on
205 # Sometimes automount can be _really_ annoying.
206 echo "Waiting for devices to settle..."
207 /sbin/udevadm settle
208 sleep 5
209 if ! isdevloop "$DEV"; then
210 getpartition ${device#/dev/}
211 USBDEV=${device}${partnum}
212 else
213 USBDEV=${device}
215 umount $USBDEV &> /dev/null
216 /sbin/mkdosfs -n LIVE $USBDEV
217 USBLABEL="UUID=$(/sbin/blkid -s UUID -o value $USBDEV)"
220 createEXTFSLayout() {
221 dev=$1
222 getdisk $dev
224 echo "WARNING: THIS WILL DESTROY ANY DATA ON $device!!!"
225 echo "Press Enter to continue or ctrl-c to abort"
226 read
227 umount ${device}* &> /dev/null
228 wipefs -a ${device}
229 /sbin/parted --script $device mklabel msdos
230 partinfo=$(LC_ALL=C /sbin/parted --script -m $device "unit b print" |grep ^$device:)
231 size=$(echo $partinfo |cut -d : -f 2 |sed -e 's/B$//')
232 /sbin/parted --script $device unit b mkpart primary ext2 1048576 $(($size - 1048576)) set 1 boot on
233 # Sometimes automount can be _really_ annoying.
234 echo "Waiting for devices to settle..."
235 /sbin/udevadm settle
236 sleep 5
237 getpartition ${device#/dev/}
238 USBDEV=${device}${partnum}
239 umount $USBDEV &> /dev/null
240 /sbin/mkfs.ext3 -L LIVE $USBDEV
241 USBLABEL="UUID=$(/sbin/blkid -s UUID -o value $USBDEV)"
244 checkGPT() {
245 dev=$1
246 getdisk $dev
248 if [ "$(/sbin/fdisk -l $device 2>/dev/null |grep -c GPT)" -eq "0" ]; then
249 echo "EFI boot requires a GPT partition table."
250 echo "This can be done manually or you can run with --format"
251 exitclean
254 partinfo=$(LC_ALL=C /sbin/parted --script -m $device "print" |grep ^$partnum:)
255 volname=$(echo $partinfo |cut -d : -f 6)
256 flags=$(echo $partinfo |cut -d : -f 7)
257 if [ "$volname" != "EFI System Partition" ]; then
258 echo "Partition name must be 'EFI System Partition'"
259 echo "This can be set in parted or you can run with --reset-mbr"
260 exitclean
262 if [ "$(echo $flags |grep -c boot)" = "0" ]; then
263 echo "Partition isn't marked bootable!"
264 echo "You can mark the partition as bootable with "
265 echo " # /sbin/parted $device"
266 echo " (parted) toggle N boot"
267 echo " (parted) quit"
268 exitclean
272 checkFilesystem() {
273 dev=$1
275 USBFS=$(/sbin/blkid -s TYPE -o value $dev)
276 if [ "$USBFS" != "vfat" ] && [ "$USBFS" != "msdos" ]; then
277 if [ "$USBFS" != "ext2" ] && [ "$USBFS" != "ext3" ]; then
278 echo "USB filesystem must be vfat, ext[23]"
279 exitclean
284 USBLABEL=$(/sbin/blkid -s UUID -o value $dev)
285 if [ -n "$USBLABEL" ]; then
286 USBLABEL="UUID=$USBLABEL" ;
287 else
288 USBLABEL=$(/sbin/blkid -s LABEL -o value $dev)
289 if [ -n "$USBLABEL" ]; then
290 USBLABEL="LABEL=$USBLABEL"
291 else
292 echo "Need to have a filesystem label or UUID for your USB device"
293 if [ "$USBFS" = "vfat" -o "$USBFS" = "msdos" ]; then
294 echo "Label can be set with /sbin/dosfslabel"
295 elif [ "$USBFS" = "ext2" -o "$USBFS" = "ext3" ]; then
296 echo "Label can be set with /sbin/e2label"
297 elif [ "$USBFS" = "btrfs" ]; then
298 echo "Eventually you'll be able to use /sbin/btrfs filesystem label to add a label."
300 exitclean
304 if [ "$USBFS" = "vfat" -o "$USBFS" = "msdos" ]; then
305 mountopts="-o shortname=winnt,umask=0077"
309 checkSyslinuxVersion() {
310 if [ ! -x /usr/bin/syslinux ]; then
311 echo "You need to have syslinux installed to run this script"
312 exit 1
314 if ! syslinux 2>&1 | grep -qe -d; then
315 SYSLINUXPATH=""
316 elif [ -n "$multi" ]; then
317 SYSLINUXPATH="$LIVEOS/syslinux"
318 else
319 SYSLINUXPATH="syslinux"
323 checkMounted() {
324 dev=$1
325 if grep -q "^$dev " /proc/mounts ; then
326 echo "$dev is mounted, please unmount for safety"
327 exitclean
329 if grep -q "^$dev " /proc/swaps; then
330 echo "$dev is in use as a swap device, please disable swap"
331 exitclean
335 checkint() {
336 if ! test $1 -gt 0 2>/dev/null ; then
337 usage
341 if [ $(id -u) != 0 ]; then
342 echo "You need to be root to run this script"
343 exit 1
346 detectisotype() {
347 if [ -e $CDMNT/LiveOS/squashfs.img ]; then
348 isotype=live
349 return
351 if [ -e $CDMNT/images/install.img -o $CDMNT/isolinux/initrd.img ]; then
352 imgtype=install
353 if [ -e $CDMNT/Packages ]; then
354 isotype=installer
355 else
356 isotype=netinst
358 if [ ! -e $CDMNT/images/install.img ]; then
359 echo "$ISO uses initrd.img w/o install.img"
360 imgtype=initrd
362 return
364 echo "ERROR: $ISO does not appear to be a Live image or DVD installer."
365 exitclean
368 cp_p() {
369 strace -q -ewrite cp -- "${1}" "${2}" 2>&1 \
370 | awk '{
371 count += $NF
372 if (count % 10 == 0) {
373 percent = count / total_size * 100
374 printf "%3d%% [", percent
375 for (i=0;i<=percent;i++)
376 printf "="
377 printf ">"
378 for (i=percent;i<100;i++)
379 printf " "
380 printf "]\r"
383 END { print "" }' total_size=$(stat -c '%s' "${1}") count=0
386 copyFile() {
387 if [ -x /usr/bin/rsync ]; then
388 rsync -P "$1" "$2"
389 return
391 if [ -x /usr/bin/gvfs-copy ]; then
392 gvfs-copy -p "$1" "$2"
393 return
395 if [ -x /usr/bin/strace -a -x /bin/awk ]; then
396 cp_p "$1" "$2"
397 return
399 cp "$1" "$2"
402 shopt -s extglob
404 cryptedhome=1
405 keephome=1
406 homesizemb=0
407 swapsizemb=0
408 overlaysizemb=0
409 isotype=
410 imgtype=
411 LIVEOS=LiveOS
413 HOMEFILE="home.img"
414 while [ $# -gt 2 ]; do
415 case $1 in
416 --overlay-size-mb)
417 checkint $2
418 overlaysizemb=$2
419 shift
421 --home-size-mb)
422 checkint $2
423 homesizemb=$2
424 shift
426 --swap-size-mb)
427 checkint $2
428 swapsizemb=$2
429 shift
431 --crypted-home)
432 cryptedhome=1
434 --unencrypted-home)
435 cryptedhome=""
437 --delete-home)
438 keephome=""
440 --noverify)
441 noverify=1
443 --reset-mbr|--resetmbr)
444 resetmbr=1
446 --efi|--mactel)
447 efi=1
449 --format)
450 format=1
452 --skipcopy)
453 skipcopy=1
455 --xo)
456 xo=1
457 skipcompress=1
459 --xo-no-home)
460 xonohome=1
462 --compress)
463 skipcompress=""
465 --skipcompress)
466 skipcompress=1
468 --extra-kernel-args)
469 kernelargs=$2
470 shift
472 --force)
473 force=1
475 --livedir)
476 LIVEOS=$2
477 shift
479 --multi)
480 multi=1
482 --timeout)
483 checkint $2
484 timeout=$2
485 shift
487 --totaltimeout)
488 checkint $2
489 totaltimeout=$2
490 shift
493 echo "invalid arg -- $1"
494 usage
496 esac
497 shift
498 done
500 ISO=$(readlink -f "$1")
501 USBDEV=$(readlink -f "$2")
503 if [ -z "$ISO" ]; then
504 echo "Missing source"
505 usage
508 if [ ! -b "$ISO" -a ! -f "$ISO" ]; then
509 echo "$ISO is not a file or block device"
510 usage
513 # FIXME: If --format is given, we shouldn't care and just use /dev/foo1
514 if [ -z "$USBDEV" ]; then
515 echo "Missing target device"
516 usage
519 if [ ! -b "$USBDEV" ]; then
520 echo "$USBDEV is not a block device"
521 usage
524 if [ -z "$noverify" ]; then
525 # verify the image
526 echo "Verifying image..."
527 checkisomd5 --verbose "$ISO"
528 if [ $? -ne 0 ]; then
529 echo "Are you SURE you want to continue?"
530 echo "Press Enter to continue or ctrl-c to abort"
531 read
535 #checkFilesystem $USBDEV
536 # do some basic sanity checks.
537 checkMounted $USBDEV
538 if [ -n "$format" -a -z "$skipcopy" ];then
539 checkLVM $USBDEV
540 # checks for a valid filesystem
541 if [ -n "$efi" ];then
542 createGPTLayout $USBDEV
543 elif [ "$USBFS" == "vfat" -o "$USBFS" == "msdos" ]; then
544 createMSDOSLayout $USBDEV
545 else
546 createEXTFSLayout $USBDEV
550 checkFilesystem $USBDEV
551 if [ -n "$efi" ]; then
552 checkGPT $USBDEV
555 checkSyslinuxVersion
556 # Because we can't set boot flag for EFI Protective on msdos partition tables
557 [ -z "$efi" ] && checkPartActive $USBDEV
558 [ -n "$resetmbr" ] && resetMBR $USBDEV
559 checkMBR $USBDEV
562 if [ "$overlaysizemb" -gt 0 -a "$USBFS" = "vfat" ]; then
563 if [ "$overlaysizemb" -gt 2047 ]; then
564 echo "Can't have an overlay of 2048MB or greater on VFAT"
565 exitclean
569 if [ "$homesizemb" -gt 0 -a "$USBFS" = "vfat" ]; then
570 if [ "$homesizemb" -gt 2047 ]; then
571 echo "Can't have a home overlay greater than 2048MB on VFAT"
572 exitclean
576 if [ "$swapsizemb" -gt 0 -a "$USBFS" = "vfat" ]; then
577 if [ "$swapsizemb" -gt 2047 ]; then
578 echo "Can't have a swap file greater than 2048MB on VFAT"
579 exitclean
583 # FIXME: would be better if we had better mountpoints
584 CDMNT=$(mktemp -d /media/cdtmp.XXXXXX)
585 if [ -b $ISO ]; then
586 mount -o ro "$ISO" $CDMNT || exitclean
587 elif [ -f $ISO ]; then
588 mount -o loop,ro "$ISO" $CDMNT || exitclean
589 else
590 echo "$ISO is not a file or block device."
591 exitclean
593 USBMNT=$(mktemp -d /media/usbdev.XXXXXX)
594 mount $mountopts $USBDEV $USBMNT || exitclean
596 trap exitclean SIGINT SIGTERM
598 detectisotype
600 if [ -f "$USBMNT/$LIVEOS/$HOMEFILE" -a -n "$keephome" -a "$homesizemb" -gt 0 ]; then
601 echo "ERROR: Requested keeping existing /home and specified a size for /home"
602 echo "Please either don't specify a size or specify --delete-home"
603 exitclean
606 if [ -n "$efi" ]; then
607 if [ -d $CDMNT/EFI/BOOT ]; then
608 EFI_BOOT="/EFI/BOOT"
609 elif [ -d $CDMNT/EFI/boot ]; then
610 EFI_BOOT="/EFI/boot"
611 else
612 echo "ERROR: This live image does not support EFI booting"
613 exitclean
617 # let's try to make sure there's enough room on the stick
618 if [ -d $CDMNT/LiveOS ]; then
619 check=$CDMNT/LiveOS
620 else
621 check=$CDMNT
623 if [ -d $USBMNT/$LIVEOS ]; then
624 tbd=$(du -s -B 1M $USBMNT/$LIVEOS | awk {'print $1;'})
625 [ -f $USBMNT/$LIVEOS/$HOMEFILE ] && homesz=$(du -s -B 1M $USBMNT/$LIVEOS/$HOMEFILE | awk {'print $1;'})
626 [ -n "$homesz" -a -n "$keephome" ] && tbd=$(($tbd - $homesz))
627 else
628 tbd=0
630 livesize=$(du -s -B 1M $check | awk {'print $1;'})
631 if [ -n "$skipcompress" ]; then
632 if [ -e $CDMNT/LiveOS/squashfs.img ]; then
633 if mount -o loop $CDMNT/LiveOS/squashfs.img $CDMNT; then
634 livesize=$(du -s -B 1M $CDMNT/LiveOS/ext3fs.img | awk {'print $1;'})
635 umount $CDMNT
636 else
637 echo "WARNING: --skipcompress or --xo was specified but the currently"
638 echo "running kernel can not mount the squashfs from the ISO file to extract"
639 echo "it. The compressed squashfs will be copied to the USB stick."
640 skipcompress=""
644 free=$(df -B1M $USBDEV |tail -n 1 |awk {'print $4;'})
646 if [ "$isotype" = "live" ]; then
647 tba=$(($overlaysizemb + $homesizemb + $livesize + $swapsizemb))
648 if [ $tba -gt $(($free + $tbd)) ]; then
649 echo "Unable to fit live image + overlay on available space on USB stick"
650 echo "+ Size of live image: $livesize"
651 [ "$overlaysizemb" -gt 0 ] && echo "+ Overlay size: $overlaysizemb"
652 [ "$homesizemb" -gt 0 ] && echo "+ Home overlay size: $homesizemb"
653 [ "$swapsizemb" -gt 0 ] && echo "+ Swap overlay size: $swapsizemb"
654 echo "---------------------------"
655 echo "= Requested: $tba"
656 echo "- Available: $(($free + $tbd))"
657 echo "---------------------------"
658 echo "= To fit, free or decrease requested size total by: $(($tba - $free - $tbd))"
659 exitclean
663 # Verify available space for DVD installer
664 if [ "$isotype" = "installer" ]; then
665 if [ -z "$skipcopy" ]; then
666 isosize=$(du -s -B 1M $ISO | awk {'print $1;'})
667 else
668 isosize=0
670 if [ "$imgtype" = "install" ]; then
671 imgpath=images/install.img
672 else
673 imgpath=isolinux/initrd.img
675 installimgsize=$(du -s -B 1M $CDMNT/$imgpath | awk {'print $1;'})
677 tbd=0
678 if [ -e $USBMNT/$imgpath ]; then
679 tbd=$(du -s -B 1M $USBMNT/$imgpath | awk {'print $1;'})
681 if [ -e $USBMNT/$(basename $ISO) ]; then
682 tbd=$(($tbd + $(du -s -B 1M $USBMNT/$(basename $ISO) | awk {'print $1;'})))
684 echo "Size of DVD image: $isosize"
685 echo "Size of $imgpath: $installimgsize"
686 echo "Available space: $(($free + $tbd))"
687 if [ $(($isosize + $installimgsize)) -gt $(($free + $tbd)) ]; then
688 echo "ERROR: Unable to fit DVD image + install.img on available space on USB stick"
689 exitclean
693 if [ -z "$skipcopy" ] && [ "$isotype" = "live" ]; then
694 if [ -d $USBMNT/$LIVEOS -a -z "$force" ]; then
695 echo "Already set up as live image."
696 if [ -z "$keephome" -a -e $USBMNT/$LIVEOS/$HOMEFILE ]; then
697 echo "WARNING: Persistent /home will be deleted!!!"
698 echo "Press Enter to continue or ctrl-c to abort"
699 read
700 else
701 echo "Deleting old OS in fifteen seconds..."
702 sleep 15
704 [ -e "$USBMNT/$LIVEOS/$HOMEFILE" -a -n "$keephome" ] && mv $USBMNT/$LIVEOS/$HOMEFILE $USBMNT/$HOMEFILE
707 rm -rf $USBMNT/$LIVEOS
711 # Bootloader is always reconfigured, so keep these out of the if skipcopy stuff.
712 [ ! -d $USBMNT/$SYSLINUXPATH ] && mkdir -p $USBMNT/$SYSLINUXPATH
713 [ -n "$efi" -a ! -d $USBMNT$EFI_BOOT ] && mkdir -p $USBMNT$EFI_BOOT
715 # Live image copy
716 set -o pipefail
717 if [ "$isotype" = "live" -a -z "$skipcopy" ]; then
718 echo "Copying live image to USB stick"
719 [ ! -d $USBMNT/$LIVEOS ] && mkdir $USBMNT/$LIVEOS
720 [ -n "$keephome" -a -f "$USBMNT/$HOMEFILE" ] && mv $USBMNT/$HOMEFILE $USBMNT/$LIVEOS/$HOMEFILE
721 if [ -n "$skipcompress" -a -f $CDMNT/LiveOS/squashfs.img ]; then
722 mount -o loop $CDMNT/LiveOS/squashfs.img $CDMNT || exitclean
723 copyFile $CDMNT/LiveOS/ext3fs.img $USBMNT/$LIVEOS/ext3fs.img || {
724 umount $CDMNT ; exitclean ; }
725 umount $CDMNT
726 elif [ -f $CDMNT/LiveOS/squashfs.img ]; then
727 copyFile $CDMNT/LiveOS/squashfs.img $USBMNT/$LIVEOS/squashfs.img || exitclean
728 elif [ -f $CDMNT/LiveOS/ext3fs.img ]; then
729 copyFile $CDMNT/LiveOS/ext3fs.img $USBMNT/$LIVEOS/ext3fs.img || exitclean
731 if [ -f $CDMNT/LiveOS/osmin.img ]; then
732 copyFile $CDMNT/LiveOS/osmin.img $USBMNT/$LIVEOS/osmin.img || exitclean
734 sync
737 # DVD installer copy
738 if [ \( "$isotype" = "installer" -o "$isotype" = "netinst" \) ]; then
739 echo "Copying DVD image to USB stick"
740 mkdir -p $USBMNT/images/
741 if [ "$imgtype" = "install" ]; then
742 for img in install.img updates.img product.img; do
743 if [ -e $CDMNT/images/$img ]; then
744 copyFile $CDMNT/images/$img $USBMNT/images/$img || exitclean
746 done
748 if [ "$isotype" = "installer" -a -z "$skipcopy" ]; then
749 copyFile $ISO $USBMNT/
751 sync
754 cp $CDMNT/isolinux/* $USBMNT/$SYSLINUXPATH
755 BOOTCONFIG=$USBMNT/$SYSLINUXPATH/isolinux.cfg
756 # Set this to nothing so sed doesn't care
757 BOOTCONFIG_EFI=
758 if [ -n "$efi" ]; then
759 cp $CDMNT$EFI_BOOT/* $USBMNT$EFI_BOOT
761 # FIXME
762 # There is a problem here. On older LiveCD's the files are boot?*.conf
763 # They really should be renamed to BOOT?*.conf
765 # this is a little ugly, but it gets the "interesting" named config file
766 BOOTCONFIG_EFI=$USBMNT$EFI_BOOT/+(BOOT|boot)?*.conf
767 rm -f $USBMNT$EFI_BOOT/grub.conf
770 echo "Updating boot config file"
771 # adjust label and fstype
772 if [ -n "$LANG" ]; then
773 kernelargs="$kernelargs LANG=$LANG"
775 sed -i -e "s/CDLABEL=[^ ]*/$USBLABEL/" -e "s/rootfstype=[^ ]*/rootfstype=$USBFS/" -e "s/LABEL=[^ ]*/$USBLABEL/" $BOOTCONFIG $BOOTCONFIG_EFI
776 if [ -n "$kernelargs" ]; then sed -i -e "s/liveimg/liveimg ${kernelargs}/" $BOOTCONFIG $BOOTCONFIG_EFI ; fi
777 if [ "$LIVEOS" != "LiveOS" ]; then sed -i -e "s;liveimg;liveimg live_dir=$LIVEOS;" $BOOTCONFIG $BOOTCONFIG_EFI ; fi
779 if [ -n "$efi" ]; then
780 sed -i -e "s;/isolinux/;/$SYSLINUXPATH/;g" $BOOTCONFIG_EFI
781 sed -i -e "s;/images/pxeboot/;/$SYSLINUXPATH/;g" $BOOTCONFIG_EFI
784 # DVD Installer
785 if [ "$isotype" = "installer" ]; then
786 sed -i -e "s;initrd=initrd.img;initrd=initrd.img ${LANG:+LANG=$LANG} repo=hd:$USBLABEL:/;g" $BOOTCONFIG
787 sed -i -e "s;stage2=\S*;;g" $BOOTCONFIG
788 if [ -n "$efi" ]; then
789 # Images are in $SYSLINUXPATH now
790 sed -i -e "s;/images/pxeboot/;/$SYSLINUXPATH/;g" -e "s;vmlinuz;vmlinuz ${LANG:+LANG=$LANG} repo=hd:$USBLABEL:/;g" $BOOTCONFIG_EFI
794 # DVD Installer for netinst
795 if [ "$isotype" = "netinst" ]; then
796 if [ "$imgtype" = "install" ]; then
797 sed -i -e "s;stage2=\S*;stage2=hd:$USBLABEL:/images/install.img;g" $BOOTCONFIG
798 else
799 # The initrd has everything, so no stage2
800 sed -i -e "s;stage2=\S*;;g" $BOOTCONFIG
802 if [ -n "$efi" ]; then
803 # Images are in $SYSLINUXPATH now
804 sed -ie "s;/images/pxeboot/;/$SYSLINUXPATH/;g" $BOOTCONFIG_EFI
808 # Adjust the boot timeouts
809 if [ -n "$timeout" ]; then
810 sed -i -e "s/^timeout.*$/timeout\ $timeout/" $BOOTCONFIG
812 if [ -n "$totaltimeout" ]; then
813 sed -i -e "/^timeout.*$/a\totaltimeout\ $totaltimeout" $BOOTCONFIG
816 # Use repo if the .iso has the repository on it, otherwise use stage2 which
817 # will default to using the network mirror
818 if [ -e "$CDMNT/.discinfo" ]; then
819 METHODSTR=repo
820 else
821 METHODSTR=stage2
824 if [ "$overlaysizemb" -gt 0 ]; then
825 echo "Initializing persistent overlay file"
826 OVERFILE="overlay-$( /sbin/blkid -s LABEL -o value $USBDEV )-$( /sbin/blkid -s UUID -o value $USBDEV )"
827 if [ -z "$skipcopy" ]; then
828 if [ "$USBFS" = "vfat" ]; then
829 # vfat can't handle sparse files
830 dd if=/dev/zero of=$USBMNT/$LIVEOS/$OVERFILE count=$overlaysizemb bs=1M
831 else
832 dd if=/dev/null of=$USBMNT/$LIVEOS/$OVERFILE count=1 bs=1M seek=$overlaysizemb
835 sed -i -e "s/liveimg/liveimg overlay=${USBLABEL}/" $BOOTCONFIG $BOOTCONFIG_EFI
836 sed -i -e "s/\ ro\ /\ rw\ /" $BOOTCONFIG $BOOTCONFIG_EFI
839 if [ "$swapsizemb" -gt 0 -a -z "$skipcopy" ]; then
840 echo "Initializing swap file"
841 dd if=/dev/zero of=$USBMNT/$LIVEOS/swap.img count=$swapsizemb bs=1M
842 mkswap -f $USBMNT/$LIVEOS/swap.img
845 if [ "$homesizemb" -gt 0 -a -z "$skipcopy" ]; then
846 echo "Initializing persistent /home"
847 homesource=/dev/zero
848 [ -n "$cryptedhome" ] && homesource=/dev/urandom
849 if [ "$USBFS" = "vfat" ]; then
850 # vfat can't handle sparse files
851 dd if=${homesource} of=$USBMNT/$LIVEOS/$HOMEFILE count=$homesizemb bs=1M
852 else
853 dd if=/dev/null of=$USBMNT/$LIVEOS/$HOMEFILE count=1 bs=1M seek=$homesizemb
855 if [ -n "$cryptedhome" ]; then
856 loop=$(losetup -f)
857 losetup $loop $USBMNT/$LIVEOS/$HOMEFILE
858 setupworked=1
859 until [ ${setupworked} == 0 ]; do
860 echo "Encrypting persistent /home"
861 cryptsetup luksFormat -y -q $loop
862 setupworked=$?
863 done
864 setupworked=1
865 until [ ${setupworked} == 0 ]; do
866 echo "Please enter the password again to unlock the device"
867 cryptsetup luksOpen $loop EncHomeFoo
868 setupworked=$?
869 done
870 mke2fs -j /dev/mapper/EncHomeFoo
871 tune2fs -c0 -i0 -ouser_xattr,acl /dev/mapper/EncHomeFoo
872 sleep 2
873 cryptsetup luksClose EncHomeFoo
874 losetup -d $loop
875 else
876 echo "Formatting unencrypted /home"
877 mke2fs -F -j $USBMNT/$LIVEOS/$HOMEFILE
878 tune2fs -c0 -i0 -ouser_xattr,acl $USBMNT/$LIVEOS/$HOMEFILE
882 # create the forth files for booting on the XO if requested
883 # we'd do this unconditionally, but you have to have a kernel that will
884 # boot on the XO anyway.
885 if [ -n "$xo" ]; then
886 echo "Setting up /boot/olpc.fth file"
887 args=$(grep "^ *append" $USBMNT/$SYSLINUXPATH/isolinux.cfg |head -n1 |sed -e 's/.*initrd=[^ ]*//')
888 if [ -z "$xonohome" -a ! -f $USBMNT/$LIVEOS/$HOMEFILE ]; then
889 args="$args persistenthome=mtd0"
891 args="$args reset_overlay"
892 xosyspath=$(echo $SYSLINUXPATH | sed -e 's;/;\\;')
893 if [ ! -d $USBMNT/boot ]; then mkdir -p $USBMNT/boot ; fi
894 cat > $USBMNT/boot/olpc.fth <<EOF
895 \ Boot script for USB boot
896 hex rom-pa fffc7 + 4 \$number drop h# 2e19 < [if]
897 patch 2drop erase claim-params
898 : high-ramdisk ( -- )
899 cv-load-ramdisk
900 h# 22c +lp l@ 1+ memory-limit umin /ramdisk - ffff.f000 and ( new-ramdisk-adr )
901 ramdisk-adr over /ramdisk move ( new-ramdisk-adr )
902 to ramdisk-adr
904 ' high-ramdisk to load-ramdisk
905 [then]
907 : set-bootpath-dev ( -- )
908 " /chosen" find-package if ( phandle )
909 " bootpath" rot get-package-property 0= if ( propval$ )
910 get-encoded-string ( bootpath$ )
911 [char] \ left-parse-string 2nip ( dn$ )
912 dn-buf place ( )
913 then
914 then
916 " /sd" dn-buf count sindex 0>= if
917 " sd:"
918 else
919 " u:"
920 then
921 " BOOTPATHDEV" \$set-macro
924 set-bootpath-dev
925 " $args" to boot-file
926 " \${BOOTPATHDEV}$xosyspath\initrd0.img" expand$ to ramdisk
927 " \${BOOTPATHDEV}$xosyspath\vmlinuz0" expand$ to boot-device
928 unfreeze
929 boot
934 if [ -z "$multi" ]; then
935 echo "Installing boot loader"
936 if [ -n "$efi" ]; then
937 # replace the ia32 hack
938 if [ -f "$USBMNT$EFI_BOOT/boot.conf" ]; then
939 cp -f $USBMNT$EFI_BOOT/BOOTia32.conf $USBMNT$EFI_BOOT/BOOT.conf
943 # this is a bit of a kludge, but syslinux doesn't guarantee the API for its com32 modules :/
944 if [ -f $USBMNT/$SYSLINUXPATH/vesamenu.c32 -a -f /usr/share/syslinux/vesamenu.c32 ]; then
945 cp /usr/share/syslinux/vesamenu.c32 $USBMNT/$SYSLINUXPATH/vesamenu.c32
946 elif [ -f $USBMNT/$SYSLINUXPATH/vesamenu.c32 -a -f /usr/lib/syslinux/vesamenu.c32 ]; then
947 cp /usr/lib/syslinux/vesamenu.c32 $USBMNT/$SYSLINUXPATH/vesamenu.c32
948 elif [ -f $USBMNT/$SYSLINUXPATH/menu.c32 -a -f /usr/share/syslinux/menu.c32 ]; then
949 cp /usr/share/syslinux/menu.c32 $USBMNT/$SYSLINUXPATH/menu.c32
950 elif [ -f $USBMNT/$SYSLINUXPATH/menu.c32 -a -f /usr/lib/syslinux/menu.c32 ]; then
951 cp /usr/lib/syslinux/menu.c32 $USBMNT/$SYSLINUXPATH/menu.c32
954 if [ "$USBFS" == "vfat" -o "$USBFS" == "msdos" ]; then
955 # syslinux expects the config to be named syslinux.cfg
956 # and has to run with the file system unmounted
957 mv $USBMNT/$SYSLINUXPATH/isolinux.cfg $USBMNT/$SYSLINUXPATH/syslinux.cfg
958 # deal with mtools complaining about ldlinux.sys
959 if [ -f $USBMNT/$SYSLINUXPATH/ldlinux.sys ] ; then rm -f $USBMNT/$SYSLINUXPATH/ldlinux.sys ; fi
960 cleanup
961 if [ -n "$SYSLINUXPATH" ]; then
962 syslinux -d $SYSLINUXPATH $USBDEV
963 else
964 syslinux $USBDEV
966 elif [ "$USBFS" == "ext2" -o "$USBFS" == "ext3" ]; then
967 # extlinux expects the config to be named extlinux.conf
968 # and has to be run with the file system mounted
969 mv $USBMNT/$SYSLINUXPATH/isolinux.cfg $USBMNT/$SYSLINUXPATH/extlinux.conf
970 extlinux -i $USBMNT/$SYSLINUXPATH
971 # Starting with syslinux 4 ldlinux.sys is used on all file systems.
972 if [ -f "$USBMNT/$SYSLINUXPATH/extlinux.sys" ]; then
973 chattr -i $USBMNT/$SYSLINUXPATH/extlinux.sys
974 elif [ -f "$USBMNT/$SYSLINUXPATH/ldlinux.sys" ]; then
975 chattr -i $USBMNT/$SYSLINUXPATH/ldlinux.sys
977 cleanup
979 else
980 # we need to do some more config file tweaks for multi-image mode
981 sed -i -e "s;kernel vm;kernel /$LIVEOS/syslinux/vm;" $USBMNT/$SYSLINUXPATH/isolinux.cfg
982 sed -i -e "s;initrd=i;initrd=/$LIVEOS/syslinux/i;" $USBMNT/$SYSLINUXPATH/isolinux.cfg
983 mv $USBMNT/$SYSLINUXPATH/isolinux.cfg $USBMNT/$SYSLINUXPATH/syslinux.cfg
984 cleanup
987 echo "USB stick set up as live image!"