Added support to specify serial line options from the command line.
[bootcd.git] / build.sh
1 #!/bin/bash
2 #
3 # Builds custom BootCD ISO and USB images in the current
4 # directory. For backward compatibility, if an old-style static
5 # configuration is specified, that configuration file will be parsed
6 # instead of the current PLC configuration in
7 # /etc/planetlab/plc_config.
8 #
9 # Aaron Klingaman <alk@absarokasoft.com>
10 # Mark Huang <mlhuang@cs.princeton.edu>
11 # Copyright (C) 2004-2007 The Trustees of Princeton University
12 #
13 # $Id$
14 #
15
16 PATH=/sbin:/bin:/usr/sbin:/usr/bin
17
18 CONFIGURATION=default
19 NODE_CONFIGURATION_FILE=
20 TYPES="usb iso"
21 ALL_TYPES="usb iso usb_cramfs iso_cramfs"
22 # Leave 4 MB of free space
23 FREE_SPACE=4096
24 CUSTOM_DIR=
25 OUTPUT_BASE=
26 CONSOLE_INFO="graphic"
27 MKISOFS_OPTS="-R -J -r -f -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table"
28
29 usage()
30 {
31     echo "Usage: build.sh [OPTION]..."
32     echo "    -c name          (Deprecated) Static configuration to use (default: $CONFIGURATION)"
33     echo "    -f planet.cnf    Node to customize CD for (default: none)"
34     echo "    -t 'types'       Build the specified images (default: $TYPES)"
35     echo "                     All known types: $ALL_TYPES"
36     echo "    -s console-info  Enable a serial line as console and also bring up getty on that line"
37     echo "                     console-info=devicename:baudrate"
38     echo "    -a               Build all supported images"
39     echo "    -C custom-dir    Custom directory"
40     echo "    -O output-base   The basename of the generated files (default: PLC_NAME-BootCD-VERSION)"
41     echo "    -h               This message"
42     exit 1
43 }
44
45 # Get options
46 while getopts "O:c:f:s:t:C:ah" opt ; do
47     case $opt in
48     c)
49         CONFIGURATION=$OPTARG
50         ;;
51     f)
52         NODE_CONFIGURATION_FILE=$OPTARG
53         ;;
54     t)
55         TYPES="$OPTARG"
56         ;;
57     C)
58         CUSTOM_DIR="$OPTARG"
59         ;;
60     O)
61         OUTPUT_BASE="$OPTARG"
62         ;;
63     a)
64         TYPES="$ALL_TYPES"
65         ;;
66     s)
67         CONSOLE_INFO="$OPTARG"
68         ;;
69     h|*)
70         usage
71         ;;
72     esac
73 done
74
75 # Do not tolerate errors
76 set -e
77
78 # Change to our source directory
79 srcdir=$(cd $(dirname $0) && pwd -P)
80 pushd $srcdir
81
82 # Root of the isofs
83 isofs=$PWD/build/isofs
84
85 # The reference image is expected to have been built by prep.sh (see .spec)
86 # we disable the initial logic that called prep.sh if that was not the case
87 # this is because prep.sh needs to know pldistro 
88 if [ ! -f $isofs/bootcd.img -o ! -f build/version.txt ] ; then
89     echo "You have to run prep.sh prior to calling $0 - exiting"
90     exit 1
91 fi
92
93 # build/version.txt written by prep.sh
94 BOOTCD_VERSION=$(cat build/version.txt)
95
96 if [ -f /etc/planetlab/plc_config ] ; then
97     # Source PLC configuration
98     . /etc/planetlab/plc_config
99 fi
100
101 ### This support for backwards compatibility can be taken out in the
102 ### future. RC1 based MyPLCs set $PLC_BOOT_SSL_CRT in the plc_config
103 ### file, but >=RC2 based bootcd assumes that $PLC_BOOT_CA_SSL_CRT is
104 ### set.
105 if [ -z "$PLC_BOOT_CA_SSL_CRT" -a ! -z "$PLC_BOOT_SSL_CRT" ] ; then
106     PLC_BOOT_CA_SSL_CRT=$PLC_BOOT_SSL_CRT
107 fi
108
109 # If PLC configuration is not valid, try a static configuration
110 if [ -z "$PLC_BOOT_CA_SSL_CRT" -a -d configurations/$CONFIGURATION ] ; then
111     # (Deprecated) Source static configuration
112     . configurations/$CONFIGURATION/configuration
113     PLC_NAME="PlanetLab"
114     PLC_MAIL_SUPPORT_ADDRESS="support@planet-lab.org"
115     PLC_WWW_HOST="www.planet-lab.org"
116     PLC_WWW_PORT=80
117     if [ -n "$EXTRA_VERSION" ] ; then
118     BOOTCD_VERSION="$BOOTCD_VERSION $EXTRA_VERSION"
119     fi
120     PLC_BOOT_HOST=$PRIMARY_SERVER
121     PLC_BOOT_SSL_PORT=$PRIMARY_SERVER_PORT
122     PLC_BOOT_CA_SSL_CRT=configurations/$CONFIGURATION/$PRIMARY_SERVER_CERT
123     PLC_ROOT_GPG_KEY_PUB=configurations/$CONFIGURATION/$PRIMARY_SERVER_GPG
124 fi
125
126 FULL_VERSION_STRING="$PLC_NAME BootCD $BOOTCD_VERSION"
127
128 echo "* Building images for $FULL_VERSION_STRING"
129
130 # From within a myplc chroot /usr/tmp is too small 
131 # to build all possible images, whereas /data is part of the host
132 # filesystem and usually has sufficient space.  What we
133 # should do is check whether the expected amount of space
134 # is available.
135 BUILDTMP=/usr/tmp
136 if [ -d /data/tmp ] ; then
137     isreadonly=$(mktemp /data/tmp/isreadonly.XXXXXX || /bin/true)
138     if [ -n "$isreadonly" ] ; then
139         rm -f "$isreadonly"
140         BUILDTMP=/data/tmp
141     fi
142 fi
143
144 declare -a _CLEANUPS=()
145 function do_cleanup()
146 {
147     cd /
148     for i in "${_CLEANUPS[@]}"; do
149         $i
150     done
151 }
152 function push_cleanup()
153 {
154     _CLEANUPS=( "${_CLEANUPS[@]}" "$*" )
155 }
156 function pop_cleanup()
157 {
158     unset _CLEANUPS[$((${#_CLEANUPS[@]} - 1))]
159 }
160
161 trap "do_cleanup" ERR INT EXIT
162
163 BUILDTMP=$(mktemp -d ${BUILDTMP}/bootcd.XXXXXX)
164 push_cleanup rm -fr "${BUILDTMP}"
165 mkdir "${BUILDTMP}/isofs"
166 for i in "$isofs"/{bootcd.img,kernel}; do
167     ln -s "$i" "${BUILDTMP}/isofs"
168 done
169 cp "/usr/lib/syslinux/isolinux.bin" "${BUILDTMP}/isofs"
170 isofs="${BUILDTMP}/isofs"
171
172 # Root of the ISO and USB images
173 echo "* Populating root filesystem..."
174 overlay="${BUILDTMP}/overlay"
175 install -d -m 755 $overlay
176 push_cleanup rm -fr $overlay
177
178 # Create version files
179 echo "* Creating version files"
180
181 # Boot Manager compares pl_version in both places to make sure that
182 # the right CD is mounted. We used to boot from an initrd and mount
183 # the CD on /usr. Now we just run everything out of the initrd.
184 for file in $overlay/pl_version $overlay/usr/isolinux/pl_version ; do
185     mkdir -p $(dirname $file)
186     echo "$FULL_VERSION_STRING" >$file
187 done
188
189 # Install boot server configuration files
190 echo "* Installing boot server configuration files"
191
192 # We always intended to bring up and support backup boot servers,
193 # but never got around to it. Just install the same parameters for
194 # both for now.
195 for dir in $overlay/usr/boot $overlay/usr/boot/backup ; do
196     install -D -m 644 $PLC_BOOT_CA_SSL_CRT $dir/cacert.pem
197     install -D -m 644 $PLC_ROOT_GPG_KEY_PUB $dir/pubring.gpg
198     echo "$PLC_BOOT_HOST" >$dir/boot_server
199     echo "$PLC_BOOT_SSL_PORT" >$dir/boot_server_port
200     echo "/boot/" >$dir/boot_server_path
201 done
202
203 # (Deprecated) Install old-style boot server configuration files
204 install -D -m 644 $PLC_BOOT_CA_SSL_CRT $overlay/usr/bootme/cacert/$PLC_BOOT_HOST/cacert.pem
205 echo "$FULL_VERSION_STRING" >$overlay/usr/bootme/ID
206 echo "$PLC_BOOT_HOST" >$overlay/usr/bootme/BOOTSERVER
207 echo "$PLC_BOOT_HOST" >$overlay/usr/bootme/BOOTSERVER_IP
208 echo "$PLC_BOOT_SSL_PORT" >$overlay/usr/bootme/BOOTPORT
209
210 # Generate /etc/issue
211 echo "* Generating /etc/issue"
212
213 if [ "$PLC_WWW_PORT" = "443" ] ; then
214     PLC_WWW_URL="https://$PLC_WWW_HOST/"
215 elif [ "$PLC_WWW_PORT" != "80" ] ; then
216     PLC_WWW_URL="http://$PLC_WWW_HOST:$PLC_WWW_PORT/"
217 else
218     PLC_WWW_URL="http://$PLC_WWW_HOST/"
219 fi
220
221 mkdir -p $overlay/etc
222 cat >$overlay/etc/issue <<EOF
223 $FULL_VERSION_STRING
224 $PLC_NAME Node: \n
225 Kernel \r on an \m
226 $PLC_WWW_URL
227
228 This machine is a node in the $PLC_NAME distributed network.  It has
229 not fully booted yet. If you have cancelled the boot process at the
230 request of $PLC_NAME Support, please follow the instructions provided
231 to you. Otherwise, please contact $PLC_MAIL_SUPPORT_ADDRESS.
232
233 Console login at this point is restricted to root. Provide the root
234 password of the default $PLC_NAME Central administrator account at the
235 time that this CD was created.
236
237 EOF
238
239 # Set root password
240 echo "* Setting root password"
241
242 if [ -z "$ROOT_PASSWORD" ] ; then
243     # Generate an encrypted password with crypt() if not defined
244     # in a static configuration.
245     ROOT_PASSWORD=$(python <<EOF
246 import crypt, random, string
247 salt = [random.choice(string.letters + string.digits + "./") for i in range(0,8)]
248 print crypt.crypt('$PLC_ROOT_PASSWORD', '\$1\$' + "".join(salt) + '\$')
249 EOF
250 )
251 fi
252
253 # build/passwd copied out by prep.sh
254 sed -e "s@^root:[^:]*:\(.*\)@root:$ROOT_PASSWORD:\1@" build/passwd \
255     >$overlay/etc/passwd
256
257 # Install node configuration file (e.g., if node has no floppy disk or USB slot)
258 if [ -f "$NODE_CONFIGURATION_FILE" ] ; then
259     echo "* Installing node configuration file $NODE_CONFIGURATION_FILE -> /usr/boot/plnode.txt of the bootcd image"
260     install -D -m 644 $NODE_CONFIGURATION_FILE $overlay/usr/boot/plnode.txt
261 fi
262
263 # Pack overlay files into a compressed archive
264 echo "* Compressing overlay image"
265 (cd $overlay && find . | cpio --quiet -c -o) | gzip -9 >$isofs/overlay.img
266
267 rm -rf $overlay
268 pop_cleanup
269
270 if [ -n "$CUSTOM_DIR" ]; then
271     echo "* Compressing custom image"
272     (cd "$CUSTOM_DIR" && find . | cpio --quiet -c -o) | gzip -9 >$isofs/custom.img
273 fi
274
275 # Calculate ramdisk size (total uncompressed size of both archives)
276 ramdisk_size=$(gzip -l $isofs/bootcd.img $isofs/overlay.img ${CUSTOM_DIR:+$isofs/custom.img} | tail -1 | awk '{ print $2; }') # bytes
277 ramdisk_size=$((($ramdisk_size + 1023) / 1024)) # kilobytes
278
279 echo "$FULL_VERSION_STRING" >$isofs/pl_version
280
281 popd
282
283 function extract_console_dev()
284 {
285     local console="$1"
286     dev=$(echo $console| awk -F: ' {print $1}')
287     echo $dev
288 }
289
290 function extract_console_baud()
291 {
292     local console="$1"
293     baud=$(echo $console| awk -F: ' {print $2}')
294     [ -z "$baud" ] && baud="115200"
295     echo $baud
296 }
297
298 function extract_console_parity()
299 {
300     local console="$1"
301     parity=$(echo $console| awk -F: ' {print $3}')
302     [ -z "$parity" ] && parity="n"
303     echo $parity
304 }
305
306 function extract_console_bits()
307 {
308     local console="$1"
309     bits=$(echo $console| awk -F: ' {print $4}')
310     [ -z "$bits" ] && bits="8"
311     echo $bits
312 }
313
314 function build_iso()
315 {
316     local iso="$1" ; shift
317     local console="$1" ; shift
318     local custom="$1"
319     local serial=0
320
321     if [ "$console" != "graphic" ] ; then
322         serial=1
323         console_dev=$(extract_console_dev $console)
324         console_baud=$(extract_console_baud $console)
325         console_parity=$(extract_console_parity $console)
326         console_bits=$(extract_console_bits $console)
327     fi
328
329     # Write isolinux configuration
330     cat >$isofs/isolinux.cfg <<EOF
331 ${serial:+SERIAL 0 115200}
332 DEFAULT kernel
333 APPEND ramdisk_size=$ramdisk_size initrd=bootcd.img,overlay.img${custom:+,custom.img} root=/dev/ram0 rw ${serial:+console=${console_dev},${console_baud}${console_parity}${console_bits}}
334 DISPLAY pl_version
335 PROMPT 0
336 TIMEOUT 40
337 EOF
338
339     # Create ISO image
340     echo "* Creating ISO image"
341     mkisofs -o "$iso" \
342         $MKISOFS_OPTS \
343         $isofs
344 }
345
346 function build_usb_partition()
347 {
348     echo -n "* Creating USB image with partitions..."
349     local usb="$1" ; shift
350     local console="$1" ; shift
351     local custom="$1"
352     local serial=0
353
354     if [ "$console" != "graphic" ] ; then
355         serial=1
356         console_dev=$(extract_console_dev $console)
357         console_baud=$(extract_console_baud $console)
358         console_parity=$(extract_console_parity $console)
359         console_bits=$(extract_console_bits $console)
360     fi
361
362     local size=$(($(du -Lsk $isofs | awk '{ print $1; }') + $FREE_SPACE))
363     size=$(( $size / 1024 ))
364
365     local heads=64
366     local sectors=32
367     local cylinders=$(( ($size*1024*2)/($heads*$sectors) ))
368     local offset=$(( $sectors*512 ))
369
370     /usr/lib/syslinux/mkdiskimage -M -4 "$usb" $size $heads $sectors
371     
372     cat >${BUILDTMP}/mtools.conf<<EOF
373 drive z:
374 file="${usb}"
375 cylinders=$cylinders
376 heads=$heads
377 sectors=$sectors
378 offset=$offset
379 mformat_only
380 EOF
381     # environment variable for mtools
382     export MTOOLSRC="${BUILDTMP}/mtools.conf"
383
384     ### COPIED FROM build_usb() below!!!!
385     echo -n " populating USB image... "
386     mcopy -bsQ -i "$usb" "$isofs"/* z:/
387         
388     # Use syslinux instead of isolinux to make the image bootable
389     tmp="${BUILDTMP}/syslinux.cfg"
390     cat >$tmp <<EOF
391 ${serial:+SERIAL 0 ${console_baud}}
392 DEFAULT kernel
393 APPEND ramdisk_size=$ramdisk_size initrd=bootcd.img,overlay.img${custom:+,custom.img} root=/dev/ram0 rw ${serial:+console=${console_dev},${console_baud}${console_parity}${console_bits}}
394 DISPLAY pl_version
395 PROMPT 0
396 TIMEOUT 40
397 EOF
398     mdel -i "$usb" z:/isolinux.cfg 2>/dev/null || :
399     mcopy -i "$usb" "$tmp" z:/syslinux.cfg
400     rm -f "$tmp"
401     rm -f "${BUILDTMP}/mtools.conf"
402     unset MTOOLSRC
403
404     echo "making USB image bootable."
405     syslinux -o $offset "$usb"
406
407 }
408
409 # Create USB image
410 function build_usb()
411 {
412     echo -n "* Creating USB image... "
413     local usb="$1" ; shift
414     local console="$1" ; shift
415     local custom="$1"
416     local serial=0
417
418     if [ "$console" != "graphic" ] ; then
419         serial=1
420         console_dev=$(extract_console_dev $console)
421         console_baud=$(extract_console_baud $console)
422         console_parity=$(extract_console_parity $console)
423         console_bits=$(extract_console_bits $console)
424     fi
425
426     mkfs.vfat -C "$usb" $(($(du -Lsk $isofs | awk '{ print $1; }') + $FREE_SPACE))
427
428     # Populate it
429     echo -n " populating USB image... "
430     mcopy -bsQ -i "$usb" "$isofs"/* ::/
431
432     # Use syslinux instead of isolinux to make the image bootable
433     tmp="${BUILDTMP}/syslinux.cfg"
434     cat >$tmp <<EOF
435 ${serial:+SERIAL 0 $console_baud}
436 DEFAULT kernel
437 APPEND ramdisk_size=$ramdisk_size initrd=bootcd.img,overlay.img${custom:+,custom.img} root=/dev/ram0 rw ${serial:+console=${console_dev},${console_baud}${console_parity}${console_bits}}
438 DISPLAY pl_version
439 PROMPT 0
440 TIMEOUT 40
441 EOF
442     mdel -i "$usb" ::/isolinux.cfg 2>/dev/null || :
443     mcopy -i "$usb" "$tmp" ::/syslinux.cfg
444     rm -f "$tmp"
445
446     echo "making USB image bootable."
447     syslinux "$usb"
448 }
449
450
451 # Setup CRAMFS related support
452 function prepare_cramfs()
453 {
454     [ -n "$CRAMFS_PREPARED" ] && return 0
455     local console=$1; shift
456     local custom=$1; 
457     local serial=0
458     if [ "$console" != "graphic" ] ; then
459         serial=1
460         console_dev=$(extract_console_dev $console)
461         console_baud=$(extract_console_baud $console)
462     fi
463
464     echo "* Setting up CRAMFS-based images"
465     local tmp="${BUILDTMP}/cramfs-tree"
466     mkdir -p "$tmp"
467     push_cleanup rm -rf $tmp
468     pushd $tmp
469     gzip -d -c $isofs/bootcd.img     | cpio -diu
470     gzip -d -c $isofs/overlay.img    | cpio -diu
471     [ -n "$custom" ] && \
472         gzip -d -c $isofs/custom.img | cpio -diu
473
474     # clean out unnecessary rpm lib
475     echo "* clearing var/lib/rpm/*"
476     rm -f var/lib/rpm/*
477
478     # bootcd requires this directory
479     mkdir -p mnt/confdevice
480
481     # relocate various directory to /tmp
482     rm -rf root
483     ln -fs /tmp/root root
484     ln -fs /sbin/init linuxrc 
485     ln -fs /tmp/resolv.conf etc/resolv.conf
486     ln -fs /tmp/etc/mtab etc/mtab
487
488     # have pl_rsysinit copy over appropriate etc & var directories into /tmp/etc/
489     # make /tmp/etc
490     echo "* renaming dirs in ./etc"
491     pushd etc
492     for dir in `find * -type d -prune | grep -v rc.d`; do
493         mv ${dir} ${dir}_o
494         ln -fs /tmp/etc/${dir} ${dir}
495     done
496     popd
497
498     echo "* renaming dirs in ./var"
499     # rename all top-level directories and put in a symlink to /tmp/var
500     pushd var
501     for dir in `find * -type d -prune`; do
502         mv ${dir} ${dir}_o
503         ln -fs /tmp/var/${dir} ${dir}
504     done
505     popd
506
507     # overwrite fstab to mount / as cramfs and /tmp as tmpfs
508     echo "* Overwriting etc/fstab to use cramfs and tmpfs"
509     rm -f ./etc/fstab
510     cat >./etc/fstab <<EOF
511 /dev/ram0     /              cramfs     ro              0 0
512 none          /dev/pts       devpts     gid=5,mode=620  0 0
513 none          /proc          proc       defaults        0 0
514 none          /sys           sysfs      defaults        0 0
515 EOF
516
517     pushd dev
518     rm -f console
519     mknod console c 5 1
520     #for i in 0 1 2 3 4 5 6 7 8; do rm -f ram${i} ; done
521     #for i in 0 1 2 3 4 5 6 7 8; do mknod ram${i} b 1 ${i} ; done
522     #ln -fs ram1 ram
523     #ln -fs ram0 ramdisk
524     popd
525
526     # update etc/inittab to start with pl_rsysinit
527     sed -i 's,pl_sysinit,pl_rsysinit,' etc/inittab
528
529     # modify inittab to have a serial console
530     if [ $serial -eq 1 ] ; then
531         echo "T0:23:respawn:/sbin/agetty -L $console_dev $console_baud vt100" >> etc/inittab
532         # and let root log in
533         echo "$console_dev" >> etc/securetty
534     fi
535
536     # calculate the size of /tmp based on the size of /etc & /var + 8MB slack
537     etcsize=$(du -s ./etc | awk '{ print $1 }')
538     varsize=$(du -s ./var | awk '{ print $1 }')
539     let msize=($varsize+$etcsize+8192)/1024
540
541     # make dhclient happy
542     for i in $(seq 0 9); do ln -fs /tmp/etc/dhclient-eth${i}.conf etc/dhclient-eth${i}.conf ; done
543     ln -fs /tmp/etc/resolv.conf etc/resolv.conf
544     ln -fs /tmp/etc/resolv.conf.predhclient etc/resolv.conf.predhclient
545
546     # generate pl_rsysinit
547     cat > etc/rc.d/init.d/pl_rsysinit <<EOF
548 #!/bin/sh
549 # generated by build.sh
550 echo -n "pl_rsysinit: preparing /etc and /var for pl_sysinit..."
551 mount -t tmpfs -orw,size=${msize}M,mode=1777 tmpfs /tmp
552 mkdir -p /tmp/root
553 mkdir -p /tmp/etc
554 touch /tmp/etc/resolv.conf
555 touch /tmp/etc/mtab
556 mkdir -p /tmp/var
557
558 # make mtab happy
559 echo "tmpfs /tmp tmpfs rw,size=${msize}M,mode=1777 1 1" > /tmp/etc/mtab
560
561 # copy over directory contents of all _o directories from /etc and /var
562 # /tmp/etc and /tmp/var
563 pushd /etc
564 for odir in \$(cd /etc && ls -d *_o); do dir=\$(echo \$odir | sed 's,\_o$,,'); (mkdir -p /tmp/etc/\$dir && cd \$odir && find . | cpio -p -d -u /tmp/etc/\$dir); done
565 popd
566 pushd /var
567 for odir in \$(cd /var && ls -d *_o); do dir=\$(echo \$odir | sed 's,\_o$,,'); (mkdir -p /tmp/var/\$dir && cd \$odir && find . | cpio -p -d -u /tmp/var/\$dir); done
568 popd
569
570 echo "done"
571
572 # hand over to pl_sysinit
573 echo "pl_rsysinit: handing over to pl_sysinit"
574 /etc/init.d/pl_sysinit
575 EOF
576     chmod +x etc/rc.d/init.d/pl_rsysinit
577
578     popd
579
580     # create the cramfs image
581     echo "* Creating cramfs image"
582     mkfs.cramfs $tmp/ ${BUILDTMP}/cramfs.img
583     cramfs_size=$(($(du -sk ${BUILDTMP}/cramfs.img | awk '{ print $1; }') + 1))
584     rm -rf $tmp
585     pop_cleanup
586 }
587
588 # Create ISO CRAMFS image
589 function build_iso_cramfs()
590 {
591     local iso="$1" ; shift
592     local console="$1" ; shift
593     local custom="$1"
594     local serial=0
595
596     if [ "$console" != "graphic" ] ; then
597         serial=1
598         console_dev=$(extract_console_dev $console)
599         console_baud=$(extract_console_baud $console)
600         console_parity=$(extract_console_parity $console)
601         console_bits=$(extract_console_bits $console)
602     fi
603     prepare_cramfs "$console" "$custom"
604     echo "* Creating ISO CRAMFS-based image"
605
606     local tmp="${BUILDTMP}/cramfs-iso"
607     mkdir -p "$tmp"
608     push_cleanup rm -rf $tmp
609     (cd $isofs && find . | grep -v "\.img$" | cpio -p -d -u $tmp/)
610     cat >$tmp/isolinux.cfg <<EOF
611 ${serial:+SERIAL 0 $console_baud}
612 DEFAULT kernel
613 APPEND ramdisk_size=$cramfs_size initrd=cramfs.img root=/dev/ram0 ro ${serial:+console=${console_dev},${console_baud}${console_parity}${console_bits}}
614 DISPLAY pl_version
615 PROMPT 0
616 TIMEOUT 40
617 EOF
618
619     cp ${BUILDTMP}/cramfs.img $tmp
620     mkisofs -o "$iso" \
621         $MKISOFS_OPTS \
622         $tmp
623
624     rm -fr "$tmp"
625     pop_cleanup
626 }
627
628 # Create USB CRAMFS based image
629 function build_usb_cramfs()
630 {
631     local usb="$1" ; shift
632     local console="$1" ; shift
633     local custom="$1"
634     local serial=0
635
636     if [ "$console" != "graphic" ] ; then
637         serial=1
638         console_dev=$(extract_console_dev $console)
639         console_baud=$(extract_console_baud $console)
640         console_parity=$(extract_console_parity $console)
641         console_bits=$(extract_console_bits $console)
642     fi
643     prepare_cramfs "$console" "$custom"
644     echo "* Creating USB CRAMFS based image"
645
646     let vfat_size=${cramfs_size}+$FREE_SPACE
647
648     # Make VFAT filesystem for USB
649     mkfs.vfat -C "$usb" $vfat_size
650
651     # Populate it
652     echo "* Populating USB with overlay images and cramfs"
653     mcopy -bsQ -i "$usb" $isofs/kernel $isofs/pl_version ::/
654     mcopy -bsQ -i "$usb" ${BUILDTMP}/cramfs.img ::/
655
656     # Use syslinux instead of isolinux to make the image bootable
657     tmp="${BUILDTMP}/syslinux.cfg"
658     cat >$tmp <<EOF
659 ${serial:+SERIAL 0 $console_baud}
660 DEFAULT kernel
661 APPEND ramdisk_size=$cramfs_size initrd=cramfs.img root=/dev/ram0 ro ${serial:+console=${console_dev},${console_baud}${console_parity}${console_bits}}
662 DISPLAY pl_version
663 PROMPT 0
664 TIMEOUT 40
665 EOF
666     mcopy -bsQ -i "$usb" "$tmp" ::/syslinux.cfg
667     rm -f "$tmp"
668
669     echo "* Making USB CRAMFS based image bootable"
670     syslinux "$usb"
671 }
672
673 function type_to_name()
674 {
675     echo $1 | sed '
676         s/usb$/.usb/;
677         s/usb_partition$/-partition.usb/;
678         s/usb_serial$/-serial.usb/;
679         s/iso$/.iso/;
680         s/iso_serial$/-serial.iso/;
681         s/usb_cramfs$/-cramfs.usb/;
682         s/usb_cramfs_serial$/-cramfs-serial.usb/;
683         s/iso_cramfs$/-cramfs.iso/;
684         s/iso_cramfs_serial$/-cramfs-serial.iso/;
685         '
686 }
687
688 [ -z "$OUTPUT_BASE" ] && OUTPUT_BASE="$PLC_NAME-BootCD-$BOOTCD_VERSION"
689
690 for t in $TYPES; do
691     CONSOLE=$CONSOLE_INFO
692     tname=`type_to_name $t`
693     if [[ "$t" == *_serial ]]; then
694         [ "$CONSOLE_INFO" == "graphic" ] && CONSOLE="ttyS0:115200"
695         t=`echo $t | sed 's/_serial$//'`
696     fi
697     
698     OUTPUTNAME="${OUTPUT_BASE}${tname}"
699     if [ "$CONSOLE" != "graphic" ] ; then
700         CONSOLE_NAME=$(echo $CONSOLE | sed 's,\:,,g')
701         OUTPUTNAME="${OUTPUT_BASE}-serial-${CONSOLE_NAME}${tname}"
702     fi
703     build_$t "$OUTPUTNAME" "$CONSOLE" "$CUSTOM_DIR"
704 done
705
706 exit 0