TITLE: Easy Boot CD of your LFS LFS VERSION: all AUTHOR: Thomas Foecking Christian Hesse SYNOPSIS: How to create an easy Boot CD of your working LFS system. HINT: Version 0.2d 19/11/2002 Contents -------- 1. What do you need and what is the idea? 2. Configure & compile Kernel 3. Move /dev /var /tmp /root /home to /fake/needwrite 4. Create symlinks /... -> /fake/needwrite/... 5. Create boot script which mounts the ramdisk 6. Install the bootloader isolinux 7. Create initial ramdisk 8. Burn the Boot CD 9. Reboot and enjoy 1. What do you need and what is the idea? -------------------------------------- What do you need? - LFS system which you want to burn on CD - another linux/unix system to create some stuff and burn the CD - CD-R(W) drive to burn your LFS system and boot image on CD - 1 CD-R + 1 CD-RW is very recommended for saving money - additional software: syslinux: (contains isolinux to boot the LFS kernel on CD) http://freshmeat.net/redir/syslinux/10177/url_bz2/syslinux-1.67.tar.bz2 isoinfo: (optional to detect the LFS CD without mounting it) http://www-tet.ee.tu-berlin.de/solyga/linux/isoinfo-0.03.01.tar.gz First of all you need a running LFS system, which you want to burn on CD. You may want to have a LFS CD for creating new LFS systems on other computers. Whatever your ideas are, you'll first have to create this special system on your LFS partition. (e.g. I have created a LFS system with xfree86 and windowmaker; now I can boot from CD and create new LFS systems without missing xfree86 & windowmaker) What is the idea? - Create kernel with ramdisk and initrd support - Move /dev /var /tmp /root /home to /fake/needwrite - Set symlinks /dev -> /fake/needwrite/dev /var -> /fake/needwrite/var /... -> /fake/needwrite/... - Mount /dev/ram0 to /fake/ramdisk - Copy /fake/needwrite/* to /fake/ramdisk/ - Remount /dev/ram0 to /fake/needwrite We'll have read-write access on /dev /var /tmp /root /home because they point to /fake/needwrite which is then a ramdisk You are able to do the most things from the other linux/unix system by setting LFS to your LFS mountpoint. LFS=/path/to/lfs e.g.: LFS=/mnt/lfs Don't forget to set LFS again when you do a reboot! 2. Configure & compile Kernel -------------------------- Boot your LFS system or chroot to it. --- optional --- As we're just here we first install isoinfo which we use later. I assume the tarball isoinfo-0.03.01.tar.gz is placed in /usr/src. Skip this step if you have already installed cdrtools! These cdrtools also contain a program named isoinfo which we'll use then. cd /usr/src zcat isoinfo-0.03.01.tar.gz | tar x cd isoinfo ./configure sed "s/\/usr\/local\//\/usr\//g" Makefile > Makefile.new mv Makefile.new Makefile make make install --- end of optional --- Ok, now let's configure your kernel: cd /usr/src/linux make mrproper && make menuconfig You need ramdisk support! "Block devices --->" "<*> RAM disk support" "(4096) Default RAM disk size" "[*] Initial RAM disk (initrd) support" You need ISO 9660 CDROM file system support! "File systems --->" "<*> ISO 9660 CDROM file system support" You should also think about building some other drivers into your kernel or as modules which is much better. If you want to be able to boot the CD on a lot of PCs with different CPUs (e.g. 486, Pentium, PII, PIII, Athlon) you have to compile the kernel for 486 (then it runs on >= 486). "Processor type and features --->" "(486) Processor Family" Save config and compile your kernel: make dep && make bzImage && make modules && make modules_install Then you should copy the new built kernel to /boot: cp arch/i386/boot/bzImage /boot/lfskernel && cp System.map /boot/ Run Lilo (or update the bootloader you're using): /sbin/lilo Try to boot the new kernel in order to test ramdisk support: If you're using devfs you must change: dev_ram=/dev/rd/0 dev_ram=/dev/ram0 mke2fs -m 0 $dev_ram If this fails like > The device apparently does not exist; > did you specify it correctly? you have no ramdisk support in your kernel. You should read this chapter again ;-) Otherwise you have done your work very well! You can check the size of your ramdisk by mounting it to /mnt and doing an "df -h" mount $dev_ram /mnt df -h Now you can boot your other linux/unix system ... 3. Move /dev /var /tmp /root /home to /fake/needwrite -------------------------------------------------- We move all stuff needing write access to /fake/needwrite. First we have to create this directory and the mountpoint for the ramdisk: mkdir -p $LFS/fake/{needwrite,ramdisk} Then we can move it there: cd $LFS/ mv dev/ var/ tmp/ root/ home/ fake/needwrite/ 4. Create symlinks /... -> /fake/needwrite/... ------------------------------------------- We have moved /dev /var /tmp /root /home to /fake/needwrite. Now we must set symlinks so that everything seems to be as before. cd $LFS/ ln -s fake/needwrite/dev dev ln -s fake/needwrite/var var ln -s fake/needwrite/tmp tmp ln -s fake/needwrite/root root ln -s fake/needwrite/home home "ls -l" says: dev -> fake/needwrite/dev home -> fake/needwrite/home root -> fake/needwrite/root tmp -> fake/needwrite/tmp var -> fake/needwrite/var If you also want to be able to change files in /etc on your Boot CD you must repeat the same procedure with /etc. cd $LFS/ mv etc/ fake/needwrite/ ln -s fake/needwrite/etc etc 5. Create boot script which mounts the ramdisk -------------------------------------------- Ok, we have /dev /var /tmp /root /home linked to /fake/needwrite which is first read-only. To be able to login (and to run services on runlevel x which need write access to /dev /var /tmp /root or /home) we must call a script from our /etc/rc.d/init.d/ directory which creates a ramdisk to /fake/needwrite with write access. The following script creates a ramdisk to /fake/ramdisk and will copy everything of /fake/needwrite to /fake/ramdisk. Then it remounts the ramdisk to /fake/needwrite. cat > $LFS/etc/rc.d/init.d/create_ramdisk << "EOF" #!/bin/sh dev_ram=/dev/ram0 dir_ramdisk=/fake/ramdisk dir_needwrite=/fake/needwrite source /etc/rc.d/init.d/functions case "$1" in start) echo -n "Creating ext2fs on $dev_ram ... " /sbin/mke2fs -m 0 -i 1024 -q $dev_ram > /dev/null 2>&1 evaluate_retval sleep 1 echo -n "Mounting ramdisk on $dir_ramdisk ... " mount -n $dev_ram $dir_ramdisk evaluate_retval sleep 1 echo -n "Copying files to ramdisk ... " cp -dpR $dir_needwrite/* $dir_ramdisk > /dev/null 2>&1 evaluate_retval sleep 1 echo -n "Remount ramdisk to $dir_needwrite ... " umount -n $dir_ramdisk > /dev/null 2>&1 sleep 1 mount -n $dev_ram $dir_needwrite sleep 1 ;; *) echo "Usage: $0 {start}" exit 1 ;; esac EOF Make it executable: chmod 0755 $LFS/etc/rc.d/init.d/create_ramdisk create_ramdisk should be the first script excecuted by init, so we set this link: /etc/rc.d/rcsysinit.d/S00create_ramdisk -> ../init.d/create_ramdisk cd $LFS/etc/rc.d/rcsysinit.d ln -s ../init.d/create_ramdisk S00create_ramdisk 6. Install the bootloader isolinux ------------------------------- We also need a bootloader on the CD to boot the kernel and ramdisk. lilo and grub are all nice but perfect for a CD is isolinux (it comes with syslinux). I assume the tarball syslinux-1.67.tar.bz2 is already placed in $LFS/usr/src. cd $LFS/usr/src bzcat syslinux-1.72.tar.bz2 | tar x mkdir $LFS/isolinux cp syslinux-1.72/isolinux.bin $LFS/isolinux/ If all files associated with the boot process should be in one directory we have to move kernel and the Rest of /boot to /isolinux. mv $LFS/boot/* $LFS/isolinux Now we create a symlink from boot to isolinux. cd $LFS/ rmdir boot ln -s isolinux boot Kernel & co can now be found in /boot again. But isolinux still needs a config-file, so we create it now: cat > $LFS/isolinux/isolinux.cfg << "EOF" default bootcd label bootcd kernel lfskernel append initrd=initrd.gz root=/dev/ram0 init=/linuxrc ramdisk_size=16384 EOF isolinux is now installed completely. 7. Create initial ramdisk ---------------------- !!! But first we have to change /etc/fstab of LFS !!! Delete all entries you don't need. (e.g. all /dev/hd*) You only need proc (and maybe devfs, devpts) vi $LFS/etc/fstab Don't worry about mounting root filesystem "/". This will be mounted by linuxrc from initrd fs. The best is to remove also the following links: rm $LFS/etc/rc.d/rc3.d/S20network rm $LFS/etc/rc.d/rc0.d/K80network rm $LFS/etc/rc.d/rc6.d/K80network rm $LFS/etc/rc.d/rcsysinit.d/S40mountfs rm $LFS/etc/rc.d/rcsysinit.d/S30checkfs Now we create the initrd image file and filesystem. dd if=/dev/zero of=$LFS/boot/initrd bs=1024 count=6144 mke2fs -m 0 -i 1024 -F $LFS/boot/initrd mount -o loop $LFS/boot/initrd $LFS/mnt cd $LFS/mnt mkdir bin lib dev proc mnt cp $LFS/bin/{bash,mount,grep,umount,echo} bin/ cp $(find $LFS -name "test" -type f) bin/ cp $(find $LFS -name "chroot" -type f) bin/ cp $(find $LFS -name "pivot_root" -type f) bin/ cp $LFS/lib/{libncurses.so.5,libdl.so.2,libc.so.6,ld-linux.so.2} lib/ cp -dR $LFS/dev/{console,hd?,scd*,null,ram*} dev/ ln -s bash bin/sh ln -s test bin/[ If you wish to use isoinfo instead of mount to detect the LFS CD you must also copy isoinfo into the initial ramdisk. cp $(find $LFS -name "isoinfo" -type f) bin/ The first program executed by the kernel is /linuxrc. As it does not exist we create it. Our script will find the CD in the correct CD-ROM drive and then mount it as rootfs / and run /sbin/init 3. ----------- copy & paste ------------- cat > $LFS/mnt/linuxrc << "EOF" #!/bin/sh #if you want use devfs and don't have /dev/hd?, /dev/scd* then #you must mount your devfs here: #ID is the volume id / label of the LFS boot CD if you use /bin/isoinfo #or ID is a file in root of the LFS boot CD EOF echo "ID=\"LFS_$(date +%Y%m%d)\"" >> $LFS/mnt/linuxrc cat >> $LFS/mnt/linuxrc << "EOF" TMP_MOUNT="/mnt" PATH="/bin:/sbin:/usr/bin:/usr/sbin" #this script searches for cdrom devices and then tries to find #the LFS boot CD in order to mount it as / (rootfs) #it detects: IDE devices hda - hdn and SCSI devices scd0 - scd99 #or when using devfs: IDE/SCSI devices cdrom0 - cdrom99 #you need following programs: #- /bin/isoinfo (optional) #- /bin/sh (e.g. bash) #- echo #- [ (which is linked to test) #- mount #- umount #- grep #- pivot_root #- chroot #you need following devices: #- /dev/hd* or /dev/scd* or /dev/cdroms/cdrom* #- /dev/null #you need following directories: #- /proc #- $TMP_MOUNT if [ -e "/bin/isoinfo" ]; then CHECK_TYPE="isoinfo" else CHECK_TYPE="try_mount" fi if [ ! -d "/proc/" ]; then mkdir /proc fi mount -n proc /proc -t proc #1. search for cdrom devices and add them to CDROM_LIST CDROM_LIST="" #do we have devfs? (then its very easy) if [ -d "/dev/cdroms/" ]; then for cdrom_device in /dev/cdroms/cdrom[0-99] do if [ -e "$cdrom_device" ]; then CDROM_LIST="$CDROM_LIST $cdrom_device" fi done else #we search in proc tree for ide cdrom devices for ide_channel in /proc/ide/ide[0-9] do if [ ! -d "$ide_channel" ]; then break fi for ide_device in hda hdb hdc hdd hde hdf hdg hdh hdi hdj hdk hdl hdm hdn do device_media_file="$ide_channel/$ide_device/media" if [ -e "$device_media_file" ]; then grep -i "cdrom" $device_media_file > /dev/null 2>&1 if [ $? -eq 0 ]; then if [ -e "/dev/$ide_device" ]; then CDROM_LIST="$CDROM_LIST /dev/$ide_device" fi fi fi done done for scsi_cdrom in /dev/scd[0-99] do if [ -e "$scsi_cdrom" ]; then CDROM_LIST="$CDROM_LIST $scsi_cdrom" fi done fi #2. now we try to find the LFS boot CD (we use ID as identification) LFS_CDROM_DEVICE="" echo "Using $CHECK_TYPE" for cdrom_device in $CDROM_LIST do echo -n "Checking $cdrom_device ... " if [ "$CHECK_TYPE" = "try_mount" ]; then mount -n -t iso9660 $cdrom_device $TMP_MOUNT > /dev/null 2>&1 media_found=$? fi if [ "$CHECK_TYPE" = "isoinfo" ]; then isoinfo -d -i $cdrom_device > /dev/null 2>&1 media_found=$? if [ $media_found -ne 0 ]; then isoinfo -V $cdrom_device > /dev/null 2>&1 media_found=$? fi fi if [ $media_found -eq 0 ]; then echo -n "media found" if [ "$CHECK_TYPE" = "try_mount" ]; then [ -e "$TMP_MOUNT/$ID" ] media_lfs=$? fi if [ "$CHECK_TYPE" = "isoinfo" ]; then isoinfo -d -i $cdrom_device | grep -i "Volume id:" | grep "$ID" \ > /dev/null 2>&1 media_lfs=$? if [ $media_lfs -ne 0 ]; then isoinfo -V $cdrom_device | grep "$ID" > /dev/null 2>&1 media_lfs=$? fi fi if [ "$CHECK_TYPE" = "try_mount" ]; then umount -n $cdrom_device > /dev/null 2>&1 fi if [ $media_lfs -eq 0 ]; then echo ", LFS boot CD found. Ready!" LFS_CDROM_DEVICE="$cdrom_device" break; else echo ", not LFS boot CD." fi else echo "no media " fi done #3. mount LFS CD as / (root fs) if [ "$LFS_CDROM_DEVICE" = "" ]; then echo "No LFS boot CD found!!!" exit 1 else echo "Booting from $LFS_CDROM_DEVICE ... " mount -n -o ro -t iso9660 $LFS_CDROM_DEVICE $TMP_MOUNT cd $TMP_MOUNT pivot_root . mnt umount -n /mnt/proc >/dev/null 2>&1 exec chroot . sh -c 'umount -n /mnt >/dev/null 2>&1;\ exec -a init.new /sbin/init 3'\ dev/console 2>&1 fi EOF -------------------------------------- To make this script executable run chmod 0755 $LFS/mnt/linuxrc Ok, that's it. Unmount the image and compress it. cd $LFS/ umount $LFS/mnt gzip $LFS/boot/initrd 8. Burn the Boot CD ---------------- If you have a CD-RW you should take this for testing. When your system boots quite good from CD-RW you can burn it on a CD-R. (I give you this advice, because I got the clue after burning about 10 CD-Rs that didn't work ;-) Before you start burning, check the size of your LFS tree: du -h $LFS/ Delete all the stuff you don't need on a Boot CD. (e.g. /usr/src/*) Because linuxrc must be able to identify the CD you have to create a file called "LFS_YYYYMMDD". (But only if you don't use isoinfo) touch $LFS/LFS_$(date +%Y%m%d) Now burn the LFS system on CD Note! dev=0,0,0 is the device number of your CD-Writer Check your SCSI devices with "cdrecord -scanbus" speed=4 should be changed to (max) speed of your CD-Writer. If you are using a CD-RW add blank=fast to the cdrecord-command! cd $LFS/ mkisofs -R -l -L -D -b isolinux/isolinux.bin -c isolinux/boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table -V "LFS_$(date +%Y%m%d)" \ $LFS | \ cdrecord -v -eject dev=0,0,0 speed=4 - 9. Reboot and enjoy ---------------- Reboot and let your Bios boot from CD. Enjoy the kernel messages and login prompt ;-) ------------------------------------------------------------------ If you have any ideas, suggestions or found a bug you can send a mail to: Thomas Foecking Christian Hesse ------------------------------------------------------------------ Special thanks for bug reports and help to: David Maus ------------------------------------------------------------------