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
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.
--
http://linuxfromscratch.org/mailman/listinfo/lfs-chat
FAQ: http://www.linuxfromscratch.org/faq/
Unsubscribe: See the above information page