100305160053_mkusbinstall 8.88 KB
Newer Older
ole's avatar
ole committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
#!/bin/bash
# Convert a Install iso so that it's bootable off of a USB stick
# Copyright 2008  Jerry Vonau.
# Jerry Vonau <jvonau@shaw.ca>
# base on livecd-iso-to-disk 
# by:
# Jeremy Katz <katzj@redhat.com>
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


export PATH=/sbin:/usr/sbin:$PATH

usage() {
    echo "$0 [--reset-mbr] [--noverify] <isopath> <usbstick device>"
    exit 1
}

cleanup() {
    [ -d "$CDMNT" ] && umount $CDMNT && rmdir $CDMNT
    [ -d "$USBMNT" ] && umount $USBMNT && rmdir $USBMNT
}

exitclean() {
    echo "Cleaning up to exit..."
    cleanup
    exit 1
}

getdisk() {
    DEV=$1

    p=$(udevadm info -q path -n $DEV)
    if [ -e /sys/$p/device ]; then
	device=$(basename /sys/$p)
    else
	device=$(basename $(readlink -f /sys/$p/../))
    fi
    if [ ! -e /sys/block/$device -o ! -e /dev/$device ]; then
	echo "Error finding block device of $DEV.  Aborting!"
	exitclean
    fi

    device="/dev/$device"
}

resetMBR() {
    getdisk $1
    if [ -f /usr/lib/syslinux/mbr.bin ]; then
	cat /usr/lib/syslinux/mbr.bin > $device
    elif [ -f /usr/share/syslinux/mbr.bin ]; then
	cat /usr/share/syslinux/mbr.bin > $device
    else
	exitclean
    fi
}

checkMBR() {
    getdisk $1

    bs=$(mktemp /tmp/bs.XXXXXX)
    dd if=$device of=$bs bs=512 count=1 2>/dev/null || exit 2
    
    mbrword=$(hexdump -n 2 $bs |head -n 1|awk {'print $2;'})
    rm -f $bs
    if [ "$mbrword" = "0000" ]; then
	echo "MBR appears to be blank."
	echo "Do you want to replace the MBR on this device?"
	echo "Press Enter to continue or ctrl-c to abort"
	read
	resetMBR $1
    fi

    return 0
}

checkPartActive() {
    dev=$1
    getdisk $dev
    
    # if we're installing to whole-disk and not a partition, then we 
    # don't need to worry about being active
    if [ "$dev" = "$device" ]; then
	return
    fi

    if [ "$(/sbin/fdisk -l $device 2>/dev/null |grep $dev |awk {'print $2;'})" != "*" ]; then
	echo "Partition isn't marked bootable!"
	echo "You can mark the partition as bootable with "
        echo "    # /sbin/parted $device"
	echo "    (parted) toggle N boot"
	echo "    (parted) quit"
	exitclean
    fi
}


checkFilesystem() {
    dev=$1

#    USBFS=$(/lib/udev/vol_id -t $dev)
#modified for use of blkid replacing vol_id
    USBFS=$(/sbin/blkid  -s TYPE $dev | cut -d '"' -f2)
    if [ "$USBFS" != "vfat" -a "$USBFS" != "msdos" -a "$USBFS" != "ext2" -a "$USBFS" != "ext3" ]; then
	echo "USB filesystem must be vfat or ext[23]"
	exitclean
    fi
}

checkLABEL() {
    dev=$1
#    USBLABEL=$(/lib/udev/vol_id -l $dev)
    USBLABEL=$(/sbin/blkid  -s LABEL $dev | cut -d '"' -f2)
    if [ "$USBLABEL" != "XSRepo" ]; then 
	USBLABEL="XSRepo" 
	echo "Need to have a filesystem label for your USB device"
	if [ "$USBFS" = "vfat" -o "$USBFS" = "msdos" ]; then
	    echo "Label will be set with /sbin/dosfslabel"
            dosfslabel $dev $USBLABEL 
  
	elif [ "$USBFS" = "ext2" -o "$USBFS" = "ext3" ]; then
	    echo "Label will be set with /sbin/e2label"
            e2label $dev $USBLABEL
	fi
    fi
}

checkSyslinuxVersion() {
    if [ ! -x /usr/bin/syslinux ]; then
	echo "You need to have syslinux installed to run this script"
	exit 1
    fi
    if ! syslinux 2>&1 | grep -qe -d; then
	SYSLINUXPATH=""
    else
	SYSLINUXPATH="syslinux"
    fi
}

checkMounted() {
    dev=$1
    if grep -q "^$dev " /proc/mounts ; then
      echo "$dev is mounted, please unmount for safety"
      exitclean
    fi
    if grep -q "^$dev " /proc/swaps; then
      echo "$dev is in use as a swap device, please disable swap"
      exitclean
    fi
}

if [ $(id -u) != 0 ]; then 
    echo "You need to be root to run this script"
    exit 1
fi

while [ $# -gt 2 ]; do
    case $1 in
	--noverify)
	    noverify=1
	    shift;
	    ;;
	--reset-mbr|--resetmbr)
	    resetmbr=1
	    shift;
	    ;;
	*)
	    usage
	    ;;
    esac
done

ISO=$(readlink -f "$1")
USBDEV=$2

if [ -z "$ISO" ]; then
    usage
fi

if [ ! -b "$ISO" -a ! -f "$ISO" ]; then
    usage
fi

if [ -z "$USBDEV" -o ! -b "$USBDEV" ]; then
    usage
fi

if [ -z "$noverify" ]; then
    # verify the image
    echo "Verifying image..."
    checkisomd5 --verbose "$ISO"
    if [ $? -ne 0 ]; then
	echo "Are you SURE you want to continue?"
	echo "Press Enter to continue or ctrl-c to abort"
	read
    fi
fi

# do some basic sanity checks.  
checkSyslinuxVersion 
checkFilesystem $USBDEV
checkPartActive $USBDEV
checkMBR $USBDEV
checkMounted $USBDEV
checkLABEL $USBDEV
[ -n $resetmbr ] && resetMBR $USBDEV


# FIXME: would be better if we had better mountpoints
CDMNT=$(mktemp -d /media/cdtmp.XXXXXX)
mount -o loop,ro "$ISO" $CDMNT || exitclean
USBMNT=$(mktemp -d /media/usbdev.XXXXXX)
mount $USBDEV $USBMNT || exitclean

trap exitclean SIGINT SIGTERM

## let's try to make sure there's enough room on the stick
  check=$CDMNT

# let's try to make sure there's enough room on the stick
tbd=0
if [ -d $USBMNT/iso ]; then
    tbd=$(du -s -B 1M $USBMNT/iso | awk {'print $1;'})
fi
livesize=$(du -s -B 1M $check | awk {'print $1;'})
free=$(df  -B1M $USBDEV  |tail -n 1 |awk {'print $4;'})
if [ $livesize -gt $(($free + $tbd)) ]; then
  echo "Unable to fit installer on available space on USB stick"
  echo "Size of live image: $livesize"
  echo "Available space: $(($free + $tbd))"
  exitclean
fi


###############

if [ -d $USBMNT/iso ]; then
    echo "Already set up as installer image. Deleting old in fifteen seconds..."
    sleep 15

    if [ -d $USBMNT/iso ]; then
    echo "Removing old directory iso"
    rm -fr $USBMNT/iso
    fi

    if [ -d $USBMNT/images ]; then
    echo "Removing old directory images"
    rm -fr $USBMNT/images
    fi

    if [ -d $USBMNT/boot ]; then
    echo "Removing old directory boot"
    rm -fr $USBMNT/boot
    fi
fi

echo "Copying install image to USB stick"
if [ ! -d $USBMNT/$SYSLINUXPATH ]; then mkdir $USBMNT/$SYSLINUXPATH ; fi
if [ ! -d $USBMNT/iso ]; then mkdir $USBMNT/iso ; fi
if [ ! -d $USBMNT/images ]; then mkdir $USBMNT/images ; fi
if [ ! -d $USBMNT/boot ]; then mkdir $USBMNT/boot ; fi

cat > $USBMNT/boot/olpc.fth << EOF
\ Boot script for USB boot
hex  rom-pa fffc7 + 4 $number drop  h# 2e19 < [if]
  patch 2drop erase claim-params
  : high-ramdisk  ( -- )
     cv-load-ramdisk
     h# 22c +lp l@ 1+   memory-limit  umin  /ramdisk - ffff.f000 and ( new-ramdisk-adr )
     ramdisk-adr over  /ramdisk move                    ( new-ramdisk-adr )
     to ramdisk-adr
  ;
  ' high-ramdisk to load-ramdisk
[then]

: set-bootpath-dev  ( -- )
   " /chosen" find-package  if                       ( phandle )
      " bootpath" rot  get-package-property  0=  if  ( propval$ )
         get-encoded-string                          ( bootpath$ )
         [char] \ left-parse-string  2nip            ( dn$ )
         dn-buf place                                ( )
      then
   then

   " /sd"  dn-buf  count  sindex  0>=   if
          " sd:"
   else
          " u:"
   then
   " BOOTPATHDEV" \$set-macro
;

set-bootpath-dev
" text ks=hd:LABEL=XSRepo:/ks.cfg method=hd:LABEL=XSRepo:/iso  " to boot-file
" \${BOOTPATHDEV}\\$SYSLINUXPATH\initrd.img" expand$ to ramdisk
" \${BOOTPATHDEV}\\$SYSLINUXPATH\vmlinuz" expand$ to boot-device
unfreeze
boot
EOF

# Copy the iso
if [ -f "$ISO" ]; then
    cp $CDMNT/images/* $USBMNT/images/
    cp "$ISO" $USBMNT/iso/ || exitclean
fi

cp $CDMNT/isolinux/* $USBMNT/$SYSLINUXPATH

if [ -e $CDMNT/ks.cfg ];then
    cp $CDMNT/ks.cfg $USBMNT/
fi

echo "Updating boot config file"
# adjust ks label and fstype 
if grep -q method $USBMNT/$SYSLINUXPATH/isolinux.cfg ;then
    sed -i -e 's/cdrom:/hd:LABEL=XSRepo:/g' -e 's|method=cdrom|method=hd:sdb1:/iso|' $USBMNT/$SYSLINUXPATH/isolinux.cfg
else
    sed -i -e 's/cdrom:/hd:LABEL=XSRepo:/g' -e 's|cfg|cfg method=hd:sdb1:/iso|' $USBMNT/$SYSLINUXPATH/isolinux.cfg
fi

echo "Installing boot loader"
if [ "$USBFS" = "vfat" -o "$USBFS" = "msdos" ]; then
    # syslinux expects the config to be named syslinux.cfg 
    # and has to run with the file system unmounted
    mv $USBMNT/$SYSLINUXPATH/isolinux.cfg $USBMNT/$SYSLINUXPATH/syslinux.cfg
    cleanup
    if [ -n "$SYSLINUXPATH" ]; then
	syslinux -d $SYSLINUXPATH $USBDEV
    else
	syslinux $USBDEV
    fi

elif [ "$USBFS" = "ext2" -o "$USBFS" = "ext3" ]; then
    # extlinux expects the config to be named extlinux.conf
    # and has to be run with the file system mounted
    mv $USBMNT/$SYSLINUXPATH/isolinux.cfg $USBMNT/$SYSLINUXPATH/extlinux.conf
    extlinux -i $USBMNT/syslinux
    cleanup
fi

echo "USB stick set up as installer image!"