1 #!/usr/bin/bash 2 # 3 # CDDL HEADER START 4 # 5 # The contents of this file are subject to the terms of the 6 # Common Development and Distribution License (the "License"). 7 # You may not use this file except in compliance with the License. 8 # 9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 # or http://www.opensolaris.org/os/licensing. 11 # See the License for the specific language governing permissions 12 # and limitations under the License. 13 # 14 # When distributing Covered Code, include this CDDL HEADER in each 15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 # If applicable, add the following below this CDDL HEADER, with the 17 # fields enclosed by brackets "[]" replaced with your own identifying 18 # information: Portions Copyright [yyyy] [name of copyright owner] 19 # 20 # CDDL HEADER END 21 # 22 # Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 # Use is subject to license terms. 24 # 25 # This script pulls in binaries from various locations and builds 26 # a complete bootable CD and memory based filesystem image of 27 # OpenSolaris. Finally it generates an iso image that can be burned 28 # onto the CDROM to get a bootable OpenSolaris Live DVD. 29 # 30 # This script performs the following steps: 31 # 32 # 1) Load the configuration file build_live_dvd.conf 33 # 34 # 2) Remove the proto directory if it exists. This directory will 35 # contain the complete OpenSolaris filesystem image 36 # 37 # 3) Install the complete set of packages from a Solaris Express image 38 # to the proto area. 39 # 40 # 4) Copy lists of files/binaries/directories defined in various 41 # packages under the packages directory. 42 # 43 # 5) Copy skeleton scripts and configuration files contained in the 44 # bootcd_skel directory. These files contain the essential customizations 45 # necessary to make our OpenSolaris Live DVD work. 46 # 47 # 6) Create our minimal root filesystem image that will be mounted as 48 # the ramdisk. This is essentially a file that contains a ufs 49 # filesystem image. This file is loaded into memory by grub and is 50 # ultimately mounted by the kernel via the ramdisk driver. 51 # 52 # 7) Copy a predefined list of files onto our minimal root. The files in 53 # copied into this minimal root (ramdisk) are carefully chosen to 54 # minimize the size of the miniroot and reduce memory usage. This 55 # miniroot contains files that are absolutely necessary to boot till 56 # the point where /usr is mounted from the DVD. This split mount 57 # is the essential character of a Live DVD. 58 # 59 # 8) Create some essential symbolic links in /dev in the miniroot. These 60 # are used much before devfsadm can run. In the normal case where Solaris 61 # is installed onto a hard disk, the installer executes devfsadm to 62 # pre-populate /dev on the hard disk before the newly installed OS boots 63 # for the first time. Since this cannot happen with a Live DVD, we need 64 # to forcibly create the symlinks here even though /devices is empty. The 65 # symlinks will point to valid /devices entries when our Live DVD boots. 66 # 67 # 9) Create other necessary symlinks in the miniroot. These include some 68 # SMF links that indicate the default inetd service profile. 69 # 70 # 10) Gzip the file containing the miniroot. Grub will unzip it when it loads 71 # the file into memory. The file is then copied into the default location 72 # proto/boot/solaris. 73 # 74 # 11) mkisofs is invoked to build a bootable iso image containing the 75 # entire contents of our proto directory. Grub's eltorito stage2 bootloader 76 # is used, that enables booting directly off a DVD. We violate the ISO9660 77 # specs somewhat to accomodate file properties essential for a proper Unix 78 # file/directory layout. 79 # 80 # 12) If requested, transform the ISO image into a UFS filesystem suitable for 81 # copying to a USB storage device, typically flash memory. This allows 82 # creating copies of the USB image to take 10 minutes or so. The usbcopy 83 # script included with this kit is used to copy the image to the USB stick. 84 85 # 86 # Load our configuration 87 # 88 89 source build_live_dvd.conf 90 source build_live_dvd.lib 91 92 # Set up root of build area 93 if [ -n $PREFIX_DATASET ]; then 94 zfs list $PREFIX_DATASET >/dev/null 2>&1 || zfs create $PREFIX_DATASET 95 if [ $? != 0 ] ; then 96 echo "Unable to create dataset $PREFIX_DATASET" 97 exit 1 98 fi 99 fi 100 [ -d $PREFIX ] || mkdir $PREFIX 101 102 ( 103 echo "=== $0 started at `date`" 104 105 # 106 # Initial sanity check 107 # 108 if [ -z "$BOOTCD_PROTO" -o "$BOOTCD_PROTO" = "/" ]; then 109 echo "You must specify either PROTO_DATASET or BOOTCD_PROTO in the" 110 echo "configuration file. Aborting." 111 exit 1 112 fi 113 114 soldprodlofi="" 115 # Config specified an ISO image, mount it up 116 if [ -n "$SOLPRODUCTISO" ]; then 117 solprodlofi=`lofiadm -a $SOLPRODUCTISO` 118 if [ $? != 0 ]; then 119 echo "Unable to create loopback device for $SOLPRODUCTISO" 120 exit 1 121 fi 122 [ -d $SOLPRODUCT ] || mkdir -p $SOLPRODUCT 123 mount -F hsfs $solprodlofi $SOLPRODUCT 124 fi 125 126 if [ ! -d "$PKGREPOS" ]; then 127 echo "$SOLPRODUCT is not a Solaris Nevada image!" 128 umount $SOLPRODUCT 129 lofiadm -d $solprodlofi 130 exit 1 131 fi 132 133 [ -d $TMPDIR ] || mkdir $TMPDIR 134 135 TARGET=/ 136 137 cd $PREFIX 138 139 MNT=$PREFIX/bootcd_rootfs 140 141 # If we're configured to use a ZFS dataset, then set it up if necessary 142 # or figure out which snapshots already exist 143 NEED_PKGS=true 144 NEED_POSTRUN=true 145 NEED_SKELETON=true 146 if [ -n "$PROTO_DATASET" ]; then 147 zfs list $PROTO_DATASET >/dev/null 2>&1 || zfs create $PROTO_DATASET 148 zfs set snapdir=hidden $PROTO_DATASET 149 PKG_SNAPSHOT=$PROTO_DATASET@pkg 150 POSTRUN_SNAPSHOT=$PROTO_DATASET@postrun 151 SKELETON_SNAPSHOT=$PROTO_DATASET@skeleton 152 zfs list $SKELETON_SNAPSHOT >/dev/null 2>&1 && NEED_SKELETON=false 153 zfs list $POSTRUN_SNAPSHOT >/dev/null 2>&1 && NEED_POSTRUN=false 154 zfs list $PKG_SNAPSHOT >/dev/null 2>&1 && NEED_PKGS=false 155 else 156 echo "Cleaning up $BOOTCD_PROTO" 157 rm -rf $BOOTCD_PROTO 158 mkdir $BOOTCD_PROTO 159 fi 160 161 # 162 # Minimal directory structure 163 # 164 echo "Creating basic directory structure" 165 mkdirs $BOOTCD_PROTO $LIVEKIT/mkbootcd.files.minimal 166 167 # If we already have the snapshot of this stage, skip 168 if [ $NEED_PKGS = true ]; then 169 170 # 171 # Generate package list from media 172 # 173 174 # Create admin file for non-interactive pkgadd's 175 ADMIN_FILE=$TMPDIR/admin 176 cat << \ADMIN_EOF > $ADMIN_FILE 177 mail= 178 instance=unique 179 partial=nocheck 180 runlevel=nocheck 181 idepend=nocheck 182 rdepend=nocheck 183 space=nocheck 184 setuid=nocheck 185 conflict=nocheck 186 action=nocheck 187 networktimeout=60 188 networkretries=3 189 authentication=quit 190 keystore=/var/sadm/security 191 proxy= 192 basedir=default 193 ADMIN_EOF 194 195 echo "Generating ordered package list from $PKGREPOS and installing to $BOOTCD_PROTO" 196 197 /usr/bin/perl $LIVEKIT/proc_toc.pl SUNWCXall $SOLPRODUCT | /usr/ccs/bin/tsort | grep -v "INFORM: cycle" | grep -v "SUNWdummy" > $TMPDIR/ordered 198 perl $LIVEKIT/rev_file.pl $TMPDIR/ordered | while read pkg 199 do 200 if [ -d $PKGREPOS/$pkg ] 201 then 202 pkgadd -n -a $ADMIN_FILE -d $PKGREPOS -R $BOOTCD_PROTO $pkg 203 else 204 pkgi="${pkg}.i" 205 if [ -d $PKGREPOS/$pkgi ] 206 then 207 pkgadd -n -a $ADMIN_FILE -d $PKGREPOS -R $BOOTCD_PROTO $pkgi 208 fi 209 fi 210 if [[ $? -ne 0 ]] 211 then 212 echo "******* Install of $pkg failed *******" 213 fi 214 done 215 216 # Install Developer Tools if present and requested 217 if [ "$INSTALL_DEVTOOLS" = true -a -x $SOLPRODUCT/DeveloperTools/install_devtools.sh ] 218 then 219 $SOLPRODUCT/DeveloperTools/install_devtools.sh -R $BOOTCD_PROTO 220 fi 221 222 # Save snapshot if possible to skip this on next build 223 [ -n "$PKG_SNAPSHOT" ] && zfs snapshot $PKG_SNAPSHOT 224 fi 225 226 # Unmount the ISO if specified 227 if [ -n "$SOLPRODUCTISO" ]; then 228 umount $SOLPRODUCT 229 lofiadm -d $solprodlofi 230 fi 231 232 if [ $NEED_SKELETON = true ]; then 233 [ -n "$PKG_SNAPSHOT" ] && zfs rollback $PKG_SNAPSHOT 234 # 235 # Copy extra binaries from various packages including 236 # Free and Open Source software packages 237 # 238 # This loop goes through all the subdirectories of PACKAGEDIR 239 # if the subdirectory is mentioned in PACKAGEDIR/buildpkg.list 240 # then that package has been installed in TARGET 241 # and the binaries should be transferred from TARGET to BOOTCD_PROTO/TARGET. 242 # Otherwise the package binaries are in the same subdirectory 243 # of TARGET/<package> and should be transferred to BOOTCD_PROTO. 244 # 245 echo "Copying Package files" 246 247 # 248 # Minimal package registry 249 # 250 mkdir -p $BOOTCD_PROTO/pkgs 251 252 for d in `cat $PACKAGEDIR/cdpkg.list` 253 do 254 # If package includes an installation script, use it 255 if [[ -x $PACKAGEDIR/$d/install.live ]]; then 256 echo $d 257 $PACKAGEDIR/$d/install.live $PACKAGEDIR/$d $BOOTCD_PROTO 258 continue 259 fi 260 # Install using file list 261 flist="" 262 if [[ -f "$PACKAGEDIR/$d/${d}.files.livecd" ]] 263 then 264 flist="$PACKAGEDIR/$d/${d}.files.livecd" 265 266 elif [[ -f "$PACKAGEDIR/$d/${d}.files" ]] 267 then 268 flist="$PACKAGEDIR/$d/${d}.files" 269 fi 270 271 if [[ "x$flist" != "x" ]] 272 then 273 echo $d 274 grep "^$d/" $PACKAGEDIR/buildpkg.list > /dev/null 275 if [ $? -ne 0 ] 276 then 277 mkdir -p "$BOOTCD_PROTO/pkgs/$d" 278 cp "$flist" "$BOOTCD_PROTO/pkgs/$d" 279 280 if [ -f "$PACKAGEDIR/$d/installprefix" ] 281 then 282 pref=`cat "$PACKAGEDIR/$d/installprefix"` 283 copyfiles "$PACKAGEDIR/$d" "$BOOTCD_PROTO/$pref" "$flist" 284 else 285 copyfiles "$PACKAGEDIR/$d" "$BOOTCD_PROTO" "$flist" 286 fi 287 else 288 mkdir -p "$BOOTCD_PROTO/pkgs/$d" 289 cp "$flist" "$BOOTCD_PROTO/pkgs/$d" 290 291 if [ -f "$PACKAGEDIR/$d/installprefix" ] 292 then 293 pref=`cat "$PACKAGEDIR/$d/installprefix"` 294 copyfiles "$TARGET" "$BOOTCD_PROTO/$pref" "$flist" 295 else 296 copyfiles "$TARGET" "$BOOTCD_PROTO/$TARGET" "$flist" 297 fi 298 fi 299 fi 300 done 301 302 # 303 # Copy all the basic customizations required for the Live DVD to 304 # work. These are called the skeleton customisation files. 305 # 306 cd $LIVEKIT 307 echo "Copying skeleton files" 308 # First save the originals for use in installation 309 while read t m p f; do 310 [ -f $BOOTCD_PROTO/$f ] && echo $f 311 done <$BOOTCD_SKEL/bootcd_skel.files | (cd $BOOTCD_PROTO; cpio -o -O skeleton.cpio) 312 # Now copy skeleton into place 313 copyfiles "$BOOTCD_SKEL" "$BOOTCD_PROTO" $BOOTCD_SKEL/bootcd_skel.files 314 315 # 316 # Remove basic registration files from GNOME login session 317 # Does not make much sense in a LiveDVD and is a perf hog 318 # 319 rm ${BOOTCD_PROTO}/usr/dt/config/Xsession.d/1001.swupnot 320 rm ${BOOTCD_PROTO}/usr/dt/config/Xsession.d/1099.br 321 322 # Copy installer into place 323 pkgadd -n -R $BOOTCD_PROTO -d $LIVEKIT/SUNWgui-install.pkg SUNWgui-install 324 cd $BOOTCD_PROTO/usr/share/gui-install 325 bzip2 -dc $LIVEKIT/gui-install-dummy-txt.tar.bz2 | tar xf - 326 cd $LIVEKIT 327 cp $LIVEKIT/dummy_install $BOOTCD_PROTO/usr/bin 328 329 [ -n "$SKELETON_SNAPSHOT" ] && zfs snapshot $SKELETON_SNAPSHOT 330 fi 331 332 # 333 # Pre-configure Gnome databases and SMF repository 334 # 335 if [ $NEED_POSTRUN = false ]; then 336 zfs rollback -r $POSTRUN_SNAPSHOT 337 else 338 [ -n "$SKELETON_SNAPSHOT" ] && zfs rollback -r $SKELETON_SNAPSHOT 339 340 echo "Configuring Gnome" 341 [ -x $BOOTCD_PROTO/var/lib/postrun/postrun-runq ] && chroot $BOOTCD_PROTO /var/lib/postrun/postrun-runq 342 343 echo "Creating font cache" 344 [ -x $BOOTCD_PROTO/usr/bin/fc-cache ] && chroot $BOOTCD_PROTO /usr/bin/fc-cache --force 345 346 echo "Preloading SMF repository" 347 export LIVEKIT 348 $LIVEKIT/mkrepo $BOOTCD_PROTO 349 350 [ -n "$POSTRUN_SNAPSHOT" ] && zfs snapshot $POSTRUN_SNAPSHOT 351 fi 352 353 # 354 # Create the boot archive. This is a UFS filesystem image in a file 355 # that is loaded into RAM by Grub. A file is created using mkfile 356 # and is added as a block device using lofiadm. newfs is then used 357 # to create a UFS filesystem on the lofi device and then it is 358 # mounted and all the files required for a minimal root fs are 359 # copied. 360 # 361 echo "Initializing Boot Archive" 362 363 rm -f ${BOOT_ARCHIVE} 364 /usr/sbin/mkfile ${RAMDISK_SIZE}k $BOOT_ARCHIVE 365 366 lofidev=`/usr/sbin/lofiadm -a $BOOT_ARCHIVE` 367 if [ $? != 0 ] ; then 368 echo "Unable to create loopback device for $BOOT_SARCHIVE" 369 exit 2 370 fi 371 372 rlofidev=`echo $lofidev | sed s/lofi/rlofi/` 373 newfs -m 0 $rlofidev < /dev/null 2> /dev/null 374 [ -d $MNT ] || mkdir $MNT 375 mount -o nologging $lofidev $MNT 376 rmdir ${MNT}/lost+found 377 378 echo "Copying files to Boot Archive" 379 cd $LIVEKIT 380 copyfiles "$BOOTCD_PROTO" "$MNT" `pwd`/mkbootcd.files.minimal 381 382 # 383 # Additional /var /etc setup. Putting these in the ramdisk will 384 # increase ramdisk size substantially, so these are left on the 385 # cd with symlinks from the ramdisk. 386 # 387 # Ideally these should be in another compressed file mounted via 388 # lofi to conserve space and get a big performance increase. 389 # 390 cd ${MNT}/etc 391 ln -sf /.cdrom/etc/gtk 392 ln -sf /.cdrom/etc/gtk-2.0 393 ln -sf /.cdrom/etc/cacao 394 ln -sf /.cdrom/etc/lu 395 ln -sf /.cdrom/etc/usb 396 ln -sf /.cdrom/etc/orbitrc 397 ln -sf /.cdrom/etc/gconf 398 ln -sf /.cdrom/etc/gnome-vfs-2.0 399 ln -sf /.cdrom/etc/gnome-vfs-mime-magic 400 ln -sf /.cdrom/etc/gnopernicus-1.0 401 ln -sf /.cdrom/etc/gimp 402 ln -sf /.cdrom/etc/wgetrc 403 ln -sf /.cdrom/etc/sfw 404 ln -sf /.cdrom/etc/scrollkeeper.conf 405 ln -sf /.cdrom/etc/sound 406 ln -sf /.cdrom/etc/esd.conf 407 ln -sf /.cdrom/etc/xml 408 ln -sf /.cdrom/etc/xpdfrc 409 ln -sf /.cdrom/etc/xdg 410 411 cd ${MNT}/var/sadm 412 ln -s /.cdrom/var/sadm/install 413 ln -s /.cdrom/var/sadm/install_data 414 ln -s /.cdrom/var/sadm/wbem 415 ln -s /.cdrom/var/sadm/system 416 ln -s /.cdrom/var/sadm/spool 417 ln -s /.cdrom/var/sadm/softinfo 418 419 cd ${MNT}/var 420 ln -s /.cdrom/var/cc-ccr 421 422 echo "$VOLUMEID" > $MNT/.volumeid 423 chmod 0444 $MNT/.volumeid 424 chown root:root $MNT/.volumeid 425 426 # 427 # Unmount the lofi device and remove it. Then gzip the file 428 # containing the root fs image. Grub will decompress it while 429 # loading. 430 # 431 echo "Archiving Boot Archive" 432 433 cd $PREFIX 434 lockfs -f $MNT 435 umount $MNT 436 rmdir $MNT 437 lofiadm -d $BOOT_ARCHIVE 438 439 cd $PREFIX 440 441 rm -f ${BOOT_ARCHIVE}.gz 442 gzip -f $BOOT_ARCHIVE 443 mv ${BOOT_ARCHIVE}.gz $BOOT_ARCHIVE 444 chmod a+r $BOOT_ARCHIVE 445 446 if [[ "x$1" = "x-nocd" ]] 447 then 448 exit 0 449 fi 450 451 cd "$BOOTCD_PROTO" 452 453 echo "Generating usr filesystem image" 454 if [ -f $LIVEKIT/iso.sort ]; then 455 mkisofs -o solaris -sort $LIVEKIT/iso.sort -N -l -R -U -allow-multidot -no-iso-translate -cache-inodes -d -D -V "compress" usr 456 else 457 mkisofs -o solaris -N -l -R -U -allow-multidot -no-iso-translate -cache-inodes -d -D -V "compress" usr 458 fi 459 rm -rf usr 460 461 echo "Compressing usr filesystem image" 462 time $LIVEKIT/packages/clofi/lcompress solaris 65536 2048 463 rm solaris 464 465 echo "Generating opt filesystem image" 466 mkisofs -o solarisopt -N -l -R -U -allow-multidot -no-iso-translate -cache-inodes -d -D -V "compress" opt 467 rm -rf opt 468 469 echo "Compressing opt filesystem image" 470 time $LIVEKIT/packages/clofi/lcompress solarisopt 65536 2048 471 rm solarisopt 472 473 echo "Generating var/sadm/pkg filesystem image" 474 mkisofs -o solarispkg -N -l -R -U -allow-multidot -no-iso-translate -cache-inodes -d -D -V "compress" var/sadm/pkg 475 rm -rf var/sadm/pkg/* 476 477 echo "Compressing var/sadm/pkg filesystem image" 478 time $LIVEKIT/packages/clofi/lcompress solarispkg 65536 2048 479 rm solarispkg 480 481 cd $PREFIX 482 echo "Making final ISO image" 483 rm -f $ISO_FILE 484 485 mkisofs -o $ISO_FILE -b boot/grub/stage2_eltorito -c .catalog -no-emul-boot -boot-load-size 4 -boot-info-table -N -l -R -U -allow-multidot -no-iso-translate -cache-inodes -d -D -V "$VOLUMEID" "$BOOTCD_PROTO" 486 487 echo "ISO creation completed at `date`" 488 489 cd $LIVEKIT 490 491 # Generate USB image if requested 492 [ "$GEN_USB_IMG" = "true" ] && $LIVEKIT/usbgen 493 494 echo "=== $0 completed at `date`" 495 exit 0 496 497 ) 2>&1 | tee $PREFIX/$0.log 498