The hobby of bootable media

Andrew Elian <[email protected]>
Newsgroups gmane.linux.lfs.general
Message-ID <[email protected]>
Hello one and all,

I've been puttering away with LFS 7.1 and turning it into a bootable
DVD.  The end result does boot and work in qemu.  Perhaps there is an
adventurous soul would like to try it out.  I wouldn't mind some
feedback on it.

Thanks!
ae
-- 
My Blog: http://elian001.wordpress.com

-- 
http://linuxfromscratch.org/mailman/listinfo/lfs-chat
FAQ: http://www.linuxfromscratch.org/faq/
Unsubscribe: See the above information page
Boot_DVD_Version3.txt (text/plain, 14.2 KB)
AUTHOR:        Andrew Elian <e_lion_1 at hotmail dot com>
INITIAL DATE:  2010-05-16
UPDATED:       2012-04-23
LICENSE:       GNU Free Documentation License Version 1.2
SYNOPSIS:      Bootable DVD creation 
DESCRIPTION:
  A brief guide on creating a complete LFS resuce DVD, using initramfs.  I have
  named my take of LFS: dLFS.  Be sure to change it to what you like!

PREREQUISITES:
    Time:            Even more time
    "Fresh" LFS:     7.1
    busybox:         1.19.4

    A host linux system with the following:
    syslinux:        4.04
    nasm:            2.07   (Needed only to compile syslinux)
    dvd+rw-tools:    7.1
    (GNU) cpio:      2.9
    cdrtools:        2.01   (Optional)
    qemu:            0.12.3 (Optional)

  Instructions for cdrtools, dvd+rw-tools, cpio and nasm can be found in the BLFS book. 

HINT:

This hint assumes that the instructions are done as root.
  Prepare the environment:
    export ROOTFS=<ROOTFS>
    export RESCUE=<RESCUE>
  Variable $LFS needs to be set too!

  Create the needed directories:
    mkdir -pv $ROOTFS
    mkdir -pv $RESCUE

  Install the needed programs on the host system.

  Unpack and build busybox:
    cd busybox-1.19.4
    make menuconfig
      Busybox Settings  --->
        Installation Options  --->
          ( <ROOTFS> ) BusyBox installation prefix
    make
    make install
  I found the default configuration to work well. Be sure to set the
  installation prefix as this will install the programs into $ROOTFS.

  Unpack and install syslinux on the host system if needed:
    cd syslinux-4.04
    make
    make install
  You may want to check and edit MCONFIG before running make.

  Create the ROOTFS init script:

cat > $ROOTFS/init << "EOF"
#!/bin/sh
# Begin /init

NORMAL="\\033[0m"
BRED="\\033[1;31m"
BBLUE="\\033[1;34m"
BCYAN="\\033[1;36m"
GREEN="\\033[0;32m"
BGREEN="\\033[1;32m"
YELLOW="\\033[0;33m"
BYELLOW="\\033[1;33m"

# Find current screen size
# Borrowed from LFS functions script

  if [ -z "${COLUMNS}" ]; then
    COLUMNS=$(stty size)
    COLUMNS=${COLUMNS##* }
  fi

ECOL=$((${COLUMNS} - 2))
END_COL="\\033[${ECOL}G"

fancy()
{
  width=""
  width=$(( ($COLUMNS / 2) + (${#2}/2) - 3))
  echo -n -e " >>"
  printf "${1}%${width}s\c" "${2}"
  echo -n -e "${NORMAL}${END_COL}<<"
  echo
}

fancy ${BRED} ">> Mounting Kernel File Systems <<"
mount -n /proc
mount -n /sys

fancy ${BRED} ">> Running mdev <<"
echo > /proc/sys/kernel/hotplug
mdev -s

# Mount the DVD AutoMagically

fancy ${YELLOW} ">> Finding DVD <<"
for DEV in /sys/block/[hs]*                                                                                              
do                                                                                                                       
  C=$(cat $DEV/removable)
    case $C in
      1)  DNAME=`basename $DEV`
          if mount -o ro -t iso9660 /dev/$DNAME /media/dvd >/dev/null 2>&1; then
            fancy ${BYELLOW} ">> Found /dev/$DNAME <<"
            fancy ${BYELLOW} ">> Checking for dLFS-live <<"
            if [ -e /media/dvd/dLFS-live ]; then
                DVD_FOUND="/dev/$DNAME"
              else
                umount /media/dvd
            fi
          fi
      ;;
      0)
      ;;
    esac
done

mount -o ro -t iso9660 $DVD_FOUND /media/dvd >/dev/null 2>&1
umount -l /sys
umount -l /proc

fancy ${BGREEN} ">> Switching Root <<"
exec switch_root /media/dvd /sbin/init

# End /init
EOF
  Make the scipt executable
    chmod +x $ROOTFS/init

  Create some needed subdirectories
    mkdir -pv $ROOTFS/{dev,etc,lib,media/dvd,proc,sys}

  Add a few needed devices:
    mknod $ROOTFS/dev/console c 5 1
    mknod $ROOTFS/dev/null c 1 3
    mknod $ROOTFS/dev/tty c 5 1

  Copy needed shared libraries to $ROOTFS/lib.
    cp -v /lib/ld-linux-x86-64.so.2 $ROOTFS/lib
    cp -v /lib/libcrypt.so.1 $ROOTFS/lib
    cp -v /lib/libc.so.6 $ROOTFS/lib
    cp -v /lib/libm.so.6 $ROOTFS/lib

  ld-linux-x86-64.so.2 may be different depending on your host, so adjust accordingly.

  Create a link to lib, if needed:
    ln -sv ./lib $ROOTFS/lib64

  Create a minimal fstab for $ROOTFS:
cat > $ROOTFS/etc/fstab << "EOF"
proc     /proc    proc     defaults          0  0
sysfs    /sys     sysfs    defaults          0  0
devpts   /dev/pts devpts   gid=4,mode=620    0  0
EOF

  Create the raminitfs:
    cd $ROOTFS
    find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
    cd ../

  Prepare the rescue system:
  From BLFS, I usually add gpm (1.20.6), links (2.2), and dhcpcd (5.5.6) to the
  fresh LFS system. I found the easiest way to setup the rescue system was to copy 
  newly completed LFS system.
    cp -a $LFS/* $RESCUE 
  
  Some modifications are needed for the system work off a read only filesystem.
  Create needed links
    cd $RESCUE/etc
      rm localtime resolv.conf
      ln -sv /var/localtime localtime
      ln -sv /var/resolv.conf resolv.conf
      rm $RESCUE/etc/mtab
      ln -sv /proc/mounts mtab
    cd $RESCUE
      ln -sv /var/tmp tmp

  Modify the filesystem
    mkdir -pv $RESCUE/static
    mv -v $RESCUE/root $RESCUE/static/
    mkdir -v $RESCUE/static/lfs

  Create an empty file:

    touch $RESCUE/dLFS-live
  The startup script from $ROOTFS looks for the existence of this file.

  The rescue image needs a minimal fstab.  Replace the current fstab with the
  following:
    rm $RESCUE/etc/fstab
cat > $RESCUE/etc/fstab << "EOF"
# Begin /etc/fstab

proc           /proc        proc     nosuid,noexec,nodev 0     0
sysfs          /sys         sysfs    nosuid,noexec,nodev 0     0
devpts         /dev/pts     devpts   gid=4,mode=620      0     0
tmpfs          /run         tmpfs    defaults            0     0
devtmpfs       /dev         devtmpfs mode=0755,nosuid    0     0

# End /etc/fstab
EOF

  This live DVD uses custom BSD style boot scripts instead of the LFS standard SYS V.
  Mostly I found it a little easier to work with and modify.
  
  Remove the $RESCUE/etc/init.d link and create a directory:
    rm $RESCUE/etc/init.d
    mkdir $RESCUE/etc/init.d

cat > $RESCUE/etc/init.d/rc.common << "EOF"
#!/bin/bash
# Begin /etc/init.d/rc.common
# Common reused code

NORMAL="\\033[0m"
RED="\\033[0;31m"
BRED="\\033[1;31m"
GREEN="\\033[0;32m"
BGREEN="\\033[1;32m"
YELLOW="\\033[0;33m"
BYELLOW="\\033[1;33m"
BLUE="\\033[0;34m"
BBLUE="\\033[1;34m"
MAGENTA="\\033[0;35m"
BMAGENTA="\\033[1;35m"
CYAN="\\033[0;36m"
BCYAN="\\033[1;36m"
WHITE="\\033[0;37m"
BWHITE="\\033[01;37m"

# Find current screen size
if [ -z "${COLUMNS}" ]; then
  COLUMNS=$(stty size)
  COLUMNS=${COLUMNS##* }
fi

ECOL=$((${COLUMNS} - 2))
END_COL="\\033[${ECOL}G"

fancy()
  {
    width=""
    width=$(( ($COLUMNS / 2) + (${#2}/2) - 3))
    echo -n -e " >>"
    printf "${1}%${width}s" "${2}"
    echo -n -e "${NORMAL}${END_COL}<<"
    echo
  }

# End /etc/init.d/rc.common
EOF

cat > $RESCUE/etc/init.d/rc.S << "EOF"
#!/bin/bash
# Begin system init script
# With parts borrowed from LFS bootscripts

source /etc/init.d/rc.common

# Mount kernel filesystems
fancy ${RED} ">> Mounting kernel-based file systems <<"
mkdir -p /run
mount -n /run 
mkdir -p /run/{var,lock,shm}
chmod 1777 /run/shm

mount -n -o nosuid,noexec,nodev /proc
mount -n -o nosuid,noexec,nodev /sys
mount -n -o mode=0755,nosuid /dev
ln -s /run/shm /dev/shm

# Set the default loglevel
LOGLEVEL=7
fancy ${RED} ">> Console log level to ${LOGLEVEL} <<"
dmesg -n $LOGLEVEL

# Start udev
fancy ${YELLOW} ">> Creating device nodes <<"
mount -n -t tmpfs tmpfs /dev -o mode=755
echo > /proc/sys/kernel/hotplug
cp -a /lib/udev/devices/null /dev
/sbin/udevd --daemon
/sbin/udevadm trigger --action=add
/sbin/udevadm settle

# Create RAM disk
fancy ${YELLOW} ">> Preparing RAM disk <<"
mount -t tmpfs -o size=5M tmpfs /var
mkdir -p /var/{lock,log,mail,run,spool,tmp}
mkdir -p /var/{opt,cache,lib/{dhcpcd,misc,locate},local}
touch /var/run/utmp /var/log/{btmp,lastlog,wtmp}
cp /usr/share/zoneinfo/Canada/Saskatchewan /var/localtime
cp -a /static/{root,lfs} /var
chmod 755 /var/lfs
chmod 750 /var/root
chmod 1777 /var/tmp
chown lfs.lfs /var/lfs

fancy ${GREEN} ">> Mounting file systems <<"
mount -a -O no_netdev >/dev/null

fancy ${GREEN} ">> Bringing up the loopback interface <<"
ip addr add 127.0.0.1/8 label lo dev lo
ip link set lo up

source /etc/sysconfig/network
fancy ${GREEN} ">> Setting hostname to ${HOSTNAME} <<"
hostname ${HOSTNAME}

source /etc/sysconfig/console
ECHO="/bin/echo"
fancy ${GREEN} ">> Loading keymap and font <<"
     [ -z "${KEYMAP}" ] ||
         loadkeys ${KEYMAP} >/dev/null 2>&1
     [ -z "${FONT}" ] ||
          setfont ${FONT}

# End /etc/init.d/rcS
EOF

cat > $RESCUE/etc/init.d/rc.M << "EOF"
#!/bin/bash
# Going Multi-user

source /etc/init.d/rc.common

fancy ${BGREEN} ">> Starting system log daemon <<"
syslogd -m 0

fancy ${BGREEN} ">> Starting kernel log daemon <<"
klogd

if [ -f /etc/sysconfig/mouse ]
   then
   . /etc/sysconfig/mouse
fi

fancy ${BGREEN} ">> Starting gpm <<"
/usr/sbin/gpm -m $MDEVICE -t $PROTOCOL $GPM

if [ -e /sys/class/net/eth0 ];
then
  for DEV in /sys/class/net/eth[01]
  do
    NAME=$(basename $DEV)
    dhcpcd -q $NAME
      if [ $? = 0 ]; then
        fancy ${BGREEN} ">> Started dhcpcd on $NAME <<"
      else
        fancy ${RED} ">> Problems starting dhcpcd on $NAME <<"
      fi
  done
fi

fancy ${BCYAN} ">> Welcome! Login as lfs for normal user <<"

# End /etc/init.d/rc.M
EOF

cat > $RESCUE/etc/init.d/rc.K << "EOF"
#!/bin/bash
# Reboot/Halt Script

source /etc/init.d/rc.common

fancy()
{
  width=""
  width=$(( ($COLUMNS / 2) + (${#2}/2) - 3))
  echo -n -e " >>"
  printf "${1}%${width}s" "${2}"
  echo -n -e "${NORMAL}${END_COL}<<"
  echo
}

if [ -e /sys/class/net/eth0 ];
then
  for DEV in /sys/class/net/eth[01]
  do
    NAME=$(basename $DEV)
    dhcpcd -q -k $NAME
    if [ $? = 0 ]; then
      fancy ${BBLUE} ">> Stopped dhcpcd on $NAME <<"
    fi
  done
fi
fancy ${BBLUE} ">> TERM signal sent <<"
/sbin/killall5 -15
sleep 1

fancy ${BBLUE} ">> KILL signal sent <<"
/sbin/killall5 -9
sleep 1

case "$0" in
  *6)
    /sbin/reboot -w
  ;;
  *0)
    /sbin/halt -w
  ;;
esac


fancy ${BBLUE} ">> Unmounting local filesystems <<"
/bin/umount -a > /dev/null 2>&1
sleep 1
/bin/umount -a > /dev/null 2>&1

case "$0" in
  *6)
    fancy ${BYELLOW} ">> Rebooting <<"
    /sbin/reboot -d -f -i
  ;;
  *0)
    fancy ${BCYAN} ">> Bye <<"
    /sbin/halt -d -f -p
  ;;
esac

# End /etc/init.d/rc.K
EOF

cat > $RESCUE/etc/init.d/rc.1 << "EOF"
#!/bin/bash
# Single User

# Stop Networking, if any
if [ -e /sys/class/net/eth[01] ];
then
  for DEV in /sys/class/net/eth[01]
  do
    NAME=$(basename $DEV)
    dhcpcd -q -k $NAME
      if [ $? = 0 ]; then
        fancy ${BRED} ">> Stopped dhcpcd on $NAME <<"
      fi
  done
fi

# Kill all processes.
fancy ${BRED} ">> Sending all processes the SIGHUP signal <<"
killall5 -1
fancy ${BRED} ">> Sending all processes the SIGTERM signal <<"
killall5 -15
fancy ${BRED} ">> Sending all processes the SIGKILL signal <<"
killall5 -9

# End /etc/init.d/rc.1
EOF

  Create a couple of links to the kill script
    cd $RESCUE/etc/init.d
    ln -s rc.K rc.6
    ln -s rc.K rc.0

  Make sure that the scripts are executable:
    chmod -v +x rc.1 rc.K rc.M rc.S

  Replace the default /etc/inittab with this one:

    rm -v $RESCUE/etc/inittab
cat > $RESCUE/etc/inittab << "EOF"
# Begin /etc/inittab

id:2:initdefault:

si::sysinit:/etc/init.d/rc.S sysinit

l0:0:wait:/etc/init.d/rc.0
l1:S1:wait:/etc/init.d/rc.1
l2:2:wait:/etc/init.d/rc.M
l6:6:wait:/etc/init.d/rc.6

ca:12:ctrlaltdel:/sbin/shutdown -t1 -a -r now

su:S1:respawn:/sbin/sulogin

1:2:respawn:/sbin/agetty tty1 9600
2:2:respawn:/sbin/agetty tty2 9600
3:2:respawn:/sbin/agetty tty3 9600

# End /etc/inittab
EOF
  
  This will tell init to use the custom bootscripts.

  Add the lfs user by adding a line to the passwd and group files and creating a home
  directory:
    echo "lfs::1000:1500::/var/lfs:/bin/bash" >> $RESCUE/etc/passwd
    echo "lfs:x:2000:" >> $RESCUE/etc/group
  
  Modify $RESCUE/etc/passwd so root's $HOME is changed.
    sed 's/\/root/\/var\/root/g' $RESCUE/etc/passwd > $RESCUE/etc/passwd.new
    rm $RESCUE/etc/passwd
    mv -v $RESCUE/etc/passwd.new $RESCUE/etc/passwd

  Finish the modifications:
    mkdir -pv $RESCUE/static
    mv -v $RESCUE/root $RESCUE/static
    mkdir -pv $RESCUE/static/lfs
    cp -va $RESCUE/etc/skel/.bash* $RESCUE/static/lfs

  This moves or creates the home directories for root and lfs which are then copied into the 
  ramdisk during startup.

  According to your preference, add a password for root and lfs. Or not.
  Since the default LFS bootscripts are not used, they can be removed safely.

  Install isolinux by:
    mkdir -pv $RESCUE/boot/isolinux
    cd $RESCUE/boot/isolinux

cat > $RESCUE/boot/boot.msg << "EOF"
dLFS LiveDVD
EOF

cat > $RESCUE/boot/isolinux.cfg << "EOF"
display boot.msg

DEFAULT LiveDVD
    LABEL LiveDVD
    KERNEL /boot/vmlinux
    APPEND root=/dev/ram0 initrd=/boot/rootfs.cpio.gz quiet
EOF

    Of course, be sure to put the name of your kernel in the right place.  I had
    mistyped vmlinux vmlinuz and wondered why it wasn't working!

    cp /usr/share/syslinux/isolinux.bin $RESCUE/boot/isolinux
    cd $RESCUE/../
    mv -v rootfs.cpio.gz $RESCUE/boot/rootfs.cpio.gz

  Now create the dvd image:
    mkisofs -r -J -l -no-emul-boot -boot-load-size 4 -boot-info-table \
    -graft-points -iso-level 4 -pad -allow-leading-dots -b \
    boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat -o RESCUE.iso ./RESCUE

  Test the image with the right qemu, which for me is qemu-system-x86_64.
    qemu-system-x86_64 -net nic,vlan=1 -net user,vlan=1 -cdrom RESCUE.iso -boot d -m 512

  Burn to DVD:
    growisofs -Z /dev/hdc=RESCUE.iso

  Or burn to CD if the image is small enough:
    cdrecord -v dev=/dev/hdc RESCUE.iso

  If the ISO image is too large, recompressing all of the sources with xz works very well.
    
BUGS:
  BLFS now uses xorriso instead of cdrtools, but I'm not familiar with it.
  Suggestions and improvements welcome. 
 
ACKNOWLEDGEMENTS:
  LFS. The reason I can do UNIX like things on my computer!
  LFS liveCD. Provided lots of inspiration.
  boot-cd_easy hint. Now a bit outdated but I found it very useful.
  Slackware. It's been around this long for a reason.

CHANGELOG:
[2010-05-16]
  Initial hint creation.
[2010-11-11]
  Edited for clarity.
[2011-08-05]
  Changed to BSD style bootscripts.
  Updated to Syslinux 4.04.
[2012-04-23]
  Updated to busybox 1.19.4  
  Changed the instructions so as not to use a chroot.
  Modified the startup scripts to be in sync with LFS bootscripts.
  Removed screen.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.