#!/bin/bash # A shell script to generate tftpboot images, particularly for Gentoo/Sparc. # I tried to write it so it might be semi-portable, but only tested on sparc, # so YMMV # # Author: Jason Wever # Last Updated: 13 Dec 2003 # Released under the terms of the GPL V2 license # # Modified by Donald Teed # Added support for lzop and UDPCast to be built into tftpboot image, # for use in cloning disks on the Sun platform. # Last updated: Nov 12, 2004 # # Some env variables you may need to adjust for your setup ARCH=`uname -m` # Tells us what architecture we are running on BBVER="1.00" # Version of busybox to use KVER="2.4.27" # Version of linux kernel to use E2VER="1.35" # Version of e2fsprogs to use DHCPVER="1.3.22-pl4" # Version of dhcpcd to use RAIDVER="1.00.3" # Version of raidtools to use LZOPVER="1.01" # Version of lzop (compression tool) to use LZOVER="1.08" # Version of lzop library (compression tool) to use UDPVER="20040531" # Version of Udpcast to use DATE=`date +%Y%m%d` # Get the current date ORIGDIR=`pwd` # so we know where we started from WORKDIR="/tmp/tftpboot" # directory into which build image SOURCEDIR="${WORKDIR}/sources" # Where to download sources to VERSION="1.4_rc4" # version we are building for OUTPUT_FILE="${WORKDIR}/gentoo-${ARCH}-${VERSION}-${DATE}.tftpboot" # The file we end up with # You probably shouldn't need to tweak anything below here # (unless you're adding new arch suppport). # Subroutines setupDirs() { # Make some directories to work with if [ ! -d ${WORKDIR} ]; then # Make the main work and rootfs dirs mkdir ${WORKDIR} mkdir ${WORKDIR}/rootfs mkdir ${WORKDIR}/sources fi } fetchFiles() { # Download files based on passed arguments # Variables for source URLS BBFILE="http://busybox.net/downloads/busybox-${BBVER}.tar.bz2" KFILE="http://www.kernel.org/pub/linux/kernel/v2.4/linux-${KVER}.tar.bz2" E2FILE="http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-${E2VER}.tar.gz" DHCPFILE="http://www.phystech.com/ftp/dhcpcd-${DHCPVER}.tar.gz" RAIDFILE="http://people.redhat.com/mingo/raidtools/raidtools-${RAIDVER}.tar.gz" LZOPFILE="http://www.lzop.org/download/lzop-${LZOPVER}.tar.gz" LZOFILE="http://www.oberhumer.com/opensource/lzo/download/lzo-${LZOVER}.tar.gz" UDPFILE="http://udpcast.linux.lu/current/udpcast-${UDPVER}.tar.gz" CURDIR=`pwd` # Get where we are now cd ${SOURCEDIR} case "$1" in busybox) [ -f busybox-${BBVER}.tar.bz2 ] || wget ${BBFILE};; kernel) [ -f linux-${KVER}.tar.bz2 ] || wget ${KFILE};; e2fsprogs) [ -f e2fsprogs-${E2VER}.tar.gz ] || wget ${E2FILE};; dhcpcd) [ -f dhcpcd-${DHCPVER}.tar.gz ] || wget ${DHCPFILE};; raidtools) [ -f raidtools-${RAIDVER}.tar.gz ] || wget ${RAIDFILE};; lzop) [ -f lzop-${LZOPVER}.tar.gz ] || wget ${LZOPFILE};; lzo) [ -f lzo-${LZOVER}.tar.gz ] || wget ${LZOFILE};; udp) [ -f udpcast-${UDPVER}.tar.gz ] || wget ${UDPFILE};; esac # Return us from whence we came cd ${CURDIR} # All done } die() { # Prints error message and exits with status 1 echo "${1}" exit 1 } makeBusyBox() { # Here we will build busybox, using the generic config. # Get busybox. fetchFiles busybox # Unpack, copy and adjust config. cd ${WORKDIR} bunzip2 -c ${SOURCEDIR}/busybox-${BBVER}.tar.bz2 | tar xf - cp ${ORIGDIR}/configs/busybox/busybox-${BBVER}.config \ busybox-${BBVER}/.config cd busybox-${BBVER} # Adjust the path in the busybox config to match ${WORKDIR} sed -i s#\./foodir#${WORKDIR}/rootfs# ./.config # Use a patch from Keith M Wesolowski to fix an ash # and/or compiler problem # Know it's needed on sparcs, not sure about the rest of the world if [ ${ARCH} = "sparc" ] || [ ${ARCH} = "sparc64" ]; then if [ ${BBVER} = "1.00-pre3" ] || [ ${BBVER} = "1.00-pre4" ]; then if [ ${BBVER} = "1.00-pre3" ]; then patch -p1 < ${ORIGDIR}/patches/busybox/busybox-1.00-pre2-decl.patch fi patch -p1 < ${ORIGDIR}/patches/busybox/busybox-1.00-pre3-sparc.patch fi fi # Build build build make || die "busybox-${BBVER} failed to compile!" make install # Busybox is configured later on # All done } makeKernel() { # Makes a vmlinux we can use for tftpboot image # get kernel sources fetchFiles kernel # unpack kernel cd ${WORKDIR} bunzip2 -c ${SOURCEDIR}/linux-${KVER}.tar.bz2 | tar xf - cd linux-${KVER} || cd linux || die "Cant cd to kernel dir!" # apply patches here if [ `ls ${ORIGDIR}/patches/kernel` ]; then for i in `ls ${ORIGDIR}/patches/kernel` do patch < ${ORIGDIR}/patches/kernel/$i done fi # copy kernel config in. cp ${ORIGDIR}/configs/kernel/kernel-${KVER}-${ARCH}.config .config # Here are the makers of kernels # Note: using ARCH=${ARCH} in case you want to build a sparc32 kernel # on a sparc64 machine make oldconfig if [ ${ARCH} = "sparc" ]; then make ARCH=${ARCH} dep vmlinux || die "Kernel failed to build!" cp vmlinux arch/${ARCH}/boot/image strip -R .comment -R .note arch/${ARCH}/boot/image elif [ ${ARCH} = "sparc64" ]; then make ARCH=${ARCH} dep vmlinux image || die "Kernel failed to build!" fi # copy the kernel and System.map to ${WORKDIR} for later usage cp arch/${ARCH}/boot/image System.map ${WORKDIR} # All done } makeE2fsProgs() { # Build e2fsprogs for our initrd fetchFiles e2fsprogs # Unpack the e2fsprogs tarball cd ${WORKDIR} gunzip -c ${SOURCEDIR}/e2fsprogs-${E2VER}.tar.gz | tar xf - # Set our CC to uclibc if a sparc, then build build build! # if [ "${ARCH}" = "sparc" ] || [ "${ARCH}" = "sparc64" ]; then # CC="${WORKDIR}/uclibc-toolchain-3.3.x/toolchain_sparc/bin/sparc-linux-gcc" # fi cd e2fsprogs-${E2VER} ./configure --prefix=${WORKDIR}/rootfs -disable-nls \ --disable-swapfs --disable-debugfs \ --without-libintl-prefix make make install # All done } makeDhcpcd() { # Install dhcpcd fetchFiles dhcpcd # Unpack and build dhcpcd cd ${WORKDIR} gunzip -c ${SOURCEDIR}/dhcpcd-${DHCPVER}.tar.gz | tar xf - cd dhcpcd-${DHCPVER} ./configure --prefix=${WORKDIR}/rootfs make make install } makeRaidTools() { # Install raidtools fetchFiles raidtools # Unpack and build raidtools cd ${WORKDIR} gunzip -c ${SOURCEDIR}/raidtools-${RAIDVER}.tar.gz | tar xf - cd raidtools-${RAIDVER} ./configure --prefix=${WORKDIR}/rootfs make make install } makeLzo() { # Install lzop fetchFiles lzo # Unpack and build dhcpcd cd ${WORKDIR} gunzip -c ${SOURCEDIR}/lzo-${LZOVER}.tar.gz | tar xf - cd lzo-${LZOVER} ./configure --prefix=${WORKDIR}/rootfs make # make install exec_prefix=${WORKDIR}/rootfs # LDFLAGS and CPPFLAGS below builds the lzo lib support into the binary } makeLzop() { # Install lzop fetchFiles lzop # Unpack and build dhcpcd cd ${WORKDIR} gunzip -c ${SOURCEDIR}/lzop-${LZOPVER}.tar.gz | tar xf - cd lzop-${LZOPVER} CPPFLAGS=-I${WORKDIR}/lzo-${LZOVER}/include LDFLAGS=-L${WORKDIR}/lzo-${LZOVER}/src/.libs export CPPFLAGS LDFLAGS ./configure --prefix=${WORKDIR}/rootfs make make install-strip exec_prefix=${WORKDIR}/rootfs unset CPPFLAGS LDFLAGS } makeUdpcast() { # Install Udpcast fetchFiles udp # Unpack and build udpcast cd ${WORKDIR} gunzip -c ${SOURCEDIR}/udpcast-${UDPVER}.tar.gz | tar xf - cd udpcast make make install } configRootFs() { # Setup rootfs beyond what the installed packages have done # Set local variable to make life easier ROOTFS="${WORKDIR}/rootfs" # Add missing directories DIRS="dev etc/init.d mnt/gentoo proc root var/log lib/dev-state" for i in ${DIRS}; do mkdir -p ${ROOTFS}/${i} done # Copy over /etc/files cp -R ${ORIGDIR}/files/etc/* ${ROOTFS}/etc # Copy over /sbin/functions/sh cp ${ORIGDIR}/files/functions.sh ${ROOTFS}/sbin # Busybox needs some libs to work right # so copy them over and strip them #LIBFILES="ld-linux.so.2 libc.so.6 libcrypt.so.1 libnss_compat.so.2 libnss_dns.so.2 libnss_files.so.2 libresolv.so.2 libpthread.so.0 libdl.so.2" LIBFILES="ld-linux.so.2 libc.so.6 libcrypt.so.1 libnss_compat.so.2 libnss_dns.so.2 libnss_files.so.2 libresolv.so.2 libpthread.so.0" for i in ${LIBFILES}; do cp /lib/${i} ${ROOTFS}/lib strip -R .note -R .comment ${ROOTFS}/lib/${i} done # Copy over the udpcast compression tools cp /usr/sbin/udp-sender ${ROOTFS}/bin cp /usr/sbin/udp-receiver ${ROOTFS}/bin # Remove unneeded files # Trim the fat! rm -rf ${ROOTFS}/info ${ROOTFS}/man ${ROOTFS}/share } makeInitRd() { # Make a file to be our initrd, and format with ext2 # Create a file 2.5MB in size dd if=/dev/zero of=${WORKDIR}/initrd bs=1k count=4000 # Format initrd with ext2 mke2fs -F -N3000 ${WORKDIR}/initrd } populateInitRd() { # Mount initrd, copy contents of ${WORKDIR}/rootfs into it, then unmount # Mount mount -o loop -t ext2 ${WORKDIR}/initrd /mnt/floppy # Copy cp -ax ${WORKDIR}/rootfs/* /mnt/floppy # Unmount umount /mnt/floppy } createTftpBootImage() { # Take our kernel and initrd and make us a tftpboot image cd ${WORKDIR} if [ "${ARCH}" = "sparc" ] || [ "${ARCH}" = "sparc64" ]; then # Convert kernel to a.out format as that's what OBP needs elftoaout -o vmlinux image # Compress the initrd with gzip gzip -9f initrd # Now make the tftpboot image using piggyback{64} if [ "${ARCH}" = "sparc" ]; then piggyback vmlinux System.map initrd.gz else piggyback64 vmlinux System.map initrd.gz fi # Now move the tftpboot.img file to ${OUTPUT_FILE} mv vmlinux ${OUTPUT_FILE} fi } setupDirs makeBusyBox makeKernel makeE2fsProgs makeDhcpcd makeRaidTools makeLzo makeLzop makeUdpcast configRootFs makeInitRd populateInitRd createTftpBootImage