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