Hint update

Mike Hernandez mike at culmination.org
Tue Oct 5 11:26:27 PDT 2004


I updated this hint a lot, added more text and tried to make it easier
to follow. It's now "Beginners Guide To Creating A Live CD With LFS 6.0"

Mike
-------------- next part --------------
AUTHOR: Mike Hernandez <mike at culmination dot org>

DATE: 2004-09-30

LICENSE: GNU Free Documentation License Version 1.2

SYNOPSIS: Beginners Guide To Creating A Live CD With LFS 6.0
          
DESCRIPTION:
  This hint describes, in detail, the process by which I created a live cd
  from a system built with the LFS 6.0. The reader should be able to follow 
  the hint to create a live cd of their own. It was adapted from the "Easy" 
  hint to work with LFS 6.0. It is my intention to make it as easy as 
  possible for a first time live cd builder.

PREREQUISITES:
  1. A working LFS System (and cdrtools if you want to burn the cd, anyway)
  2. An LFS system built for the purpose of creating a live cd (see below)
  3. CD Writer + Media (but you knew that, I bet)
  4. Syslinux  (http://freshmeat.net/projects/syslinux/)

HINT:

  Before we get started here, let me make some things clear. 
  
  I call this section:

                         ------------------------------
                        | What it is and what it ain't |
                         ------------------------------

                                 ------------
                                | What it is |
                                 ------------

  This is a hint for creating a simple live cd. To be more clear:
  Upon booting from the cd, a user will be presented with a linux prompt.

  If you build it from an LFS system (no BLFS stuff) then the cd will be
  helpful for repairing an LFS system that got messed up (menu.lst typos
  /etc/fstab weirdness, things like that).

  Creating live cd's can be fun, and knowing how to do so opens up the door 
  for many possibilities. This hint is a good starting point for that 
  "ultimate rescue cd" idea you've had or maybe can help you answer the 
  "I wonder if Linux will run on my _____" question =)

                               ---------------
                              | What it ain't |
                               ---------------

  As I said above, this will help you make a simple livecd. The user will be 
  presented with a linux prompt and not much else beyond that unless you add 
  the functionality yourself.

  This hint does not describe how to put tons of software on the cd as you 
  might find on knoppix or the official LFS boot CD.
  
  This hint does not describe how to create an install program to copy the
  contents of the cd onto a hard drive.

  Also, you will not find any cross-compiling info here, so if you want your
  CD to boot on a completely different architecture than your own, you have
  to do that research yourself.

               --------------------------------------------------
              | Why it is what it is, and it ain't what it ain't |
               --------------------------------------------------

  This hint is designed to help a first time live cd builder. I tried to keep
  it as simple as possible, so that it wouldn't require too much advanced 
  knowledge of LFS to complete (the hint it's based on is called the "Easy"
  boot CD hint, after all.) Of course you need to know a bit, but expert 
  knowledge is not a requirement.  Creating an install CD, or using 
  filesystems such as squashfs, may require more info than a beginner might 
  have, and attempting to include all of it might make this hint more 
  confusing than helpful.

                               ---------------
                              | The Beginning |
                               ---------------
  
  This hint, like the hint it is based on, requires that the reader have two
  (yes 2) systems built. One system is your usual working system, which you
  will use to burn the cd when you are done. The other is the system created
  specifically for the purpose of putting on the live CD. If you just want 
  the CD to boot on the machine you built it on, then making a copy of your
  LFS system to another partition is fine.

  You might be wondering why you need two systems to create a live CD. The 
  reason is actually quite simple. If you are like me, you optimized your LFS 
  system to suit your pc (or in my case, laptop). I have a Pentium 4 system, 
  so all of the programs which can handle optimization have been built with:

        CFLAGS='-march=pentium4' 

  So what's the issue? It's that I want my live CD to run on just about 
  anything that can boot a CD! The programs on my current system won't run on 
  any machine that isn't a pentium 4. I actually use many more optimizations 
  when I build, but here I mention the architecture because it brings up an 
  important point:

          ----------------------------------------------------------
         | Know in advance what hardware you want the CD to run on! |
          ----------------------------------------------------------

  Before you start you should also decide what you want your live CD to do. 
  You may want to consider optimizing everything in your live CD system for 
  size, or for a specific type of machine, or not to optimize at all.
  Which is best? That's up to you. 

  Another reason you want to have a separate system is because in order to
  create the CD we make some directories and move very important files
  around. In the event that something goes wrong, having at least your
  initial working system (if not a backup of the live CD system) can be a
  life saver.

                          ----------------------------
                         | Setting up the environment |
                          ----------------------------

  To make things easier, you should set the LIVECD variable to point to the 
  mount point of the system you are going to use for the CD:

        export LIVECD=/mnt/livecd 

  You also might want to set CDDEV as well:

        export CDDEV=/dev/your-drive+partition

  Set the ISODIR to the location where you would like to keep the image:

        export ISODIR=/where/you/have/space

                        --------------------------------
                       | Configuring the live CD system |
                        --------------------------------

  Now that the environment is all set up, it's time to do some final
  configuration of the live CD system. This includes making sure the kernel
  is how you want it, and maybe adding some other programs if you so desire.

  If you are absolutely sure that the kernel for your CD system will work for 
  the system you want the CD to run on, and you don't need to install any
  other software for your CD, then you can skip to the section called
  "Moving around the furniture".

  Before we can configure and install a new kernel for the live CD, we have 
  to chroot into the system:

    1.  Mount your live CD system:

        mkdir -p $LIVECD
        mount $CDDEV $LIVECD

    2.  As per the directions of the LFS-6.0 book, 
        mount the virtual file systems prior to entering the chroot:
		
        mount -t proc proc $LIVECD/proc
        mount -t sysfs sysfs $LIVECD/sys

        and perform the fake mounts:

        mount -f -t ramfs ramfs $LIVECD/dev
        mount -f -t tmpfs tmpfs $LIVECD/dev/shm
        mount -f -t devpts -o gid=4,mode=620 devpts $LIVECD/dev/pts

    3.  chroot into the live CD system with the command given at the end of
        chapter 6. (NOT THE CHROOT COMMAND AT THE BEGINNING!!!):

        chroot $LIVECD /usr/bin/env -i \
        HOME=/root TERM=$TERM PS1='\u:\w\$ ' \
        PATH=/bin:/usr/bin:/sbin:/usr/sbin \
        /bin/bash --login

    4.  mount ramfs and populate /dev

        mount -n -t ramfs none /dev
        /sbin/udevstart

    5.  Create essential symlinks and directories not created by udev:

        ln -s /proc/self/fd /dev/fd
        ln -s /proc/self/fd/0 /dev/stdin
        ln -s /proc/self/fd/1 /dev/stdout
        ln -s /proc/self/fd/2 /dev/stderr
        ln -s /proc/kcore /dev/core
        mkdir /dev/pts
        mkdir /dev/shm

    6.  Perform the mounting of the proper virtual (kernel) file systems:

        mount -t devpts -o gid=4,mode=620 none /dev/pts
        mount -t tmpfs none /dev/shm


  Now you are in the chroot, so you can configure and build the kernel for
  the CD. If you are absolutely sure that the kernel for your CD system
  will work for the system you want the CD to run on, then you can skip this
  part and just install the software you need.

  Building the kernel for your live CD is not something to be taken lightly
  by even a veteran! There are options which need to be built in and others
  which can be built as modules. I assume that if you feel you are ready to
  create a live CD out of your system, that you know what you are doing. I do
  suggest not using modules, because it can create issues if you aren't
  familiar with all the work that goes into using modules with the 2.6 kernel
  and udev. Be Careful! =)

  When you are done installing your kernel you might want to test it to be 
  sure it works. Once you are all set, then you should exit the chroot and
  run the rest of the commands from your working system, as root.

                       -----------------------------
                      | Moving around the furniture |
                       ----------------------------- 

  A.K.A. Moving /dev /etc /home /root /tmp /var  to /fake/needwrite

  When I followed the "Easy" hint, I came to this point and wondered: 
  What is /fake/needwrite? (Actually it was more like "what the hell is this 
  /fake/needwrite stuff?") Here is an answer for those of you wondering the 
  same:

  The /fake/needwrite directory is used to hold files that must be writable 
  while the live CD is running. Obviously, these files can not remain on the 
  CD-ROM (due to the ROM part), and so they are moved to a location from which 
  they will be copied into a ramdisk during the CD boot process. Having the
  files in a ram disk allows us to modify them. Also, we can create files in
  the directories which reside on the ram disk, such as in /tmp, or /home.

	First we have to create the directory and a mount point for the ramdisk:

        mkdir -p $LIVECD/fake/{needwrite,ramdisk}

	Then we can move the directories which we want to have write access there:

        cd $LIVECD/
        mv dev/ etc/ home/ root/ tmp/ var/ fake/needwrite/

	Now we have to create symlinks so that everything seems to be	as before.

        cd $LIVECD/
        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
        ln -s fake/needwrite/etc etc

    now "ls -l" should say:
    dev  -> fake/needwrite/dev
    etc  -> fake/needwrite/etc
    home -> fake/needwrite/home
    root -> fake/needwrite/root
    tmp  -> fake/needwrite/tmp
    var  -> fake/needwrite/var

                 ---------------------------------------------
                | Tailoring the CD boot process for our needs |
                 ---------------------------------------------

	Ok, we have /etc /dev /var /tmp /root /home linked to /fake/needwrite 
  which is read-only (because it's on the CD). To be able to login (and to 
  run services which need write access to /dev /var /tmp /root /home or /etc) 
  we must call a script from our /etc/rc.d/init.d/ directory which mounts a 
  ram disk on /fake/needwrite with write access.

  The following script creates 2 ram disks, a temporary one, and one that 
  will house the directories which need write permission. It copies the files 
  from the CD to the temporary ram disk, and then from there to the final ram 
  disk.

  The original hint used 1 ram disk, but this caused a serious problem for me. 
  First of all, the initrd which is loaded at boot time uses the first ramdisk 
  (/dev/ram0). Therefore trying to mount /dev/ram0 somewhere else leads to 
  "device already mounted" errors. Secondly, unmounting a ram disk causes
  all of the files to be lost. The original hint unmounted the ram disk and 
  remounted it, assuming the files would still be there. That did not work for 
  me, which is why I made sure that /dev/ram{0,1,2} are all present, and 
  suggest that you do the same. If they aren't present you should check your
  udev setup. You might try using mknod to create the files, but for now
  I will say if you don't have /dev/ram devices, you are going to have to
  do some research on your own to figure out why.

  Copy and paste the script, and tailor it to your needs as necessary:

cat > $LIVECD/etc/rc.d/init.d/create_ramdisk << "EOF"
#!/bin/sh

# SET UP SOME VARIABLES FOR DEVICES AND DIRECTORIES

dev_ram=/dev/ram1
dev_ram2=/dev/ram2
dir_ramdisk=/fake/ramdisk
dir_needwrite=/fake/needwrite

# SOURCE THE FUNCTIONS FILE

source /etc/rc.d/init.d/functions

case "$1" in
        start)
          
					# CREATE THE RAM DISK
          
					echo "Creating ext2fs on $dev_ram..."
          /sbin/mke2fs -m 0 -i 1024 -q $dev_ram > /dev/null 2>&1
          evaluate_retval
          sleep 1

          # MOUNT THE RAM DISK

          echo "Mounting ramdisk on $dir_ramdisk..."
          mount -n $dev_ram $dir_ramdisk -t ext2
          evaluate_retval
          sleep 1

          # COPY FILES TO THE RAM DISK

          echo "Copying files to ramdisk..."
          cp -a $dir_needwrite/* $dir_ramdisk > /dev/null 2>&1
          evaluate_retval
          sleep 1

          # CREATE SECOND RAMDISK

          echo "Creating second ramdisk"
          /sbin/mke2fs -m 0 -i 1024 -q $dev_ram2 > /dev/null 2>&1
          evaluate_retval
          sleep 1
          
          # MOUNT SECOND RAMDISK

          echo "Mounting second ram disk"
          mount -n $dev_ram2 $dir_needwrite -t ext2
          evaluate_retval
          sleep 1
          
          # COPY FILES TO THE SECOND RAMDISK
          
          echo "Copying files to the second ram disk"
          cp -a $dir_ramdisk/* $dir_needwrite
          evaluate_retval
          sleep 1
          
          # UNMOUNT THE FIRST RAMDISK

          echo "Unmounting and clearing first ram disk"
          umount -n $dir_ramdisk > /dev/null 2>&1
          blockdev --flushbufs /dev/ram1
          evaluate_retval
          sleep 1
          ;;
        *)
          echo "Usage: $0 {start}"
          exit 1
          ;;
esac

EOF

	Make the script executable with the following command:

        chmod 0755 $LIVECD/etc/rc.d/init.d/create_ramdisk

  Gabe Munoz pointed out that this symlink can be S11, where it used to be at 
  S00. Of course feel free to number the symlink as you see fit. (This is LFS 
  after all!) Just make sure that you dont start any scripts that will try
  to write to one of the directories that needs write permission before
  the files are copied over.

        cd $LIVECD/etc/rc.d/rcsysinit.d
        ln -s ../init.d/create_ramdisk S00create_ramdisk


  Next we can install the bootloader, isolinux.  It is available with the
  syslinux package. You can find syslinux on freshmeat:

  http://freshmeat.net/projects/syslinux/

	The directions below  assume the tarball syslinux-2.11.tar.bz2 is
	already placed in $LIVECD/usr/src. (use the current version, 2.11 might be
  old by the time you read this)

  cd $LIVECD/usr/src

  tar xzf syslinux-2.11.tar.gz
  mkdir $LIVECD/isolinux
  cp syslinux-2.11/isolinux.bin $LIVECD/isolinux

  mv $LIVECD/boot/* $LIVECD/isolinux
  cd $LIVECD/
  rmdir boot
  ln -s isolinux boot

  The bootloader needs a configuration file. The cat command below creates
  this file.

cat > $LIVECD/isolinux/isolinux.cfg << "EOF"
default livecd

label livecd
  kernel lfskernel
  append initrd=initrd.gz root=/dev/ram0 init=/linuxrc ramdisk_size=16384
EOF


  Ok! So far so good right?! In order for the boot process to work the way
  we want, we create an initial ramdisk. More information about initial
  ram disks (initrd for short) can be found in your kernel documentation.

	At this point it's a good idea to change /etc/fstab of the live CD system.
	Delete all of the entries that you don't need. (e.g. all /dev/hd* entries)
	You only need proc and devpts.

  vi $LIVECD/etc/fstab

	Don't worry about mounting root filesystem "/".
	This will be mounted by the linuxrc script from the initial ram disk.

	You may find it helpful to remove the following links:

rm $LIVECD/etc/rc.d/rc3.d/S20network
rm $LIVECD/etc/rc.d/rc0.d/K80network
rm $LIVECD/etc/rc.d/rc6.d/K80network
rm $LIVECD/etc/rc.d/rcsysinit.d/S40mountfs
rm $LIVECD/etc/rc.d/rcsysinit.d/S30checkfs

	The directions below create the initial ram disk (initrd):

    dd if=/dev/zero of=$LIVECD/boot/initrd bs=1024 count=6144
    mke2fs -m 0 -i 1024 -F $LIVECD/boot/initrd

    mount -o loop $LIVECD/boot/initrd $LIVECD/mnt
    cd $LIVECD/mnt
    mkdir bin sbin lib dev proc mnt sys etc
    
    cp -a $LIVECD/bin/{bash,mount,grep,umount,echo,ln,mkdir} bin/
    cp -a $LIVECD/sbin/udev* sbin/
    cp -a $(find $LIVECD -name "test" -type f) bin/
    cp -a $(find $LIVECD -name "chroot" -type f) bin/
    cp -a $(find $LIVECD -name "pivot_root" -type f) bin/
    cp -H $LIVECD/lib/{libncurses.so.5,libdl.so.2,libc.so.6,ld-linux.so.2} lib/
		cp -H $LIVECD/lib/{libreadline.so.5.0,libhistory.so.5.0} lib/
    cp -a $LIVECD/dev/{console,null,ram{0,1,2}} dev/
    cp -a $LIVECD/etc/{udev,dev.d,hotplug.d} etc/

    ln -s bash bin/sh
    ln -s test 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 the root file system / and run /sbin/init 3.

  Copy and paste the script and tailor it to your needs if necessary:

cat > $LIVECD/mnt/linuxrc << "EOF"
#!/bin/sh
                                                                                
# ID is a file in root of the LFS boot CD, used to identify the CD.

ID="livecd"
TMP_MOUNT="/mnt"
                                                                                
PATH="/bin:/sbin:/usr/bin:/usr/sbin"
                                                                                
CHECK_TYPE="try_mount"
                                                                                
# MOUNT KERNEL FILESYSTEMS

# Create the proc directory if it does not exist

if [ ! -d "/proc/" ]; then
  mkdir /proc
fi

# Mount the proc filesystem

mount -n proc /proc -t proc

# If sysfs is listed as a valid filesystem type in /proc
# then mount it (if it doesnt then udev wont work
# and you wont have the devices you need)
                                                                              
if grep -q '[[:space:]]sysfs' /proc/filesystems; then
    if [ ! -d /sys/block ]; then
    mount -n sysfs /sys -t sysfs
    fi
fi
                                                                                
# Create some things that sysfs does not, and should not export for us.  Feel
# free to add devices to this list.

make_extra_nodes() {
        ln -s /proc/self/fd /dev/fd
        ln -s /proc/self/fd/0 /dev/stdin
        ln -s /proc/self/fd/1 /dev/stdout
        ln -s /proc/self/fd/2 /dev/stderr
        ln -s /proc/kcore /dev/core
        mkdir /dev/pts
        mkdir /dev/shm
}
                                                                                
                                                                                
if [ ! -x /sbin/hotplug ]; then
    echo /sbin/udev > /proc/sys/kernel/hotplug
fi
                                                                                
# Mount a temporary file system over /dev, so that any devices
# made or removed during this boot don't affect the next one.
# The reason we don't write to mtab is because we don't ever
# want /dev to be unavailable (such as by `umount -a').
                                                                                
mount -n ramfs /dev -t ramfs
                                                                                
/sbin/udevstart
                                                                                
make_extra_nodes                                                                               
# Detecting the live CD is pretty complicated, 
# but is a very logical process
                                                                                
#1. Search for cdrom devices and add them to CDROM_LIST
                                                                                
CDROM_LIST=""
                                                                                
# Search in proc tree for ide cdrom devices
# There used to be a section for devfs, but this was
# edited for udev. Actually we should probably not
# use /proc anymore, but use sysfs instead...
# Perhaps in the future;)
    
  # Check for ide channels.
 
  for ide_channel in /proc/ide/ide[0-9]
  do

    # If there are no ide channels found, then skip this

    if [ ! -d "$ide_channel" ]; then
     break
    fi

		# Try each ide device to see if we can find the cd-rom drive

    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
            CDROM_LIST="$CDROM_LIST /dev/$ide_device"
        fi
      fi
    done
  done

  # Check for scsi cds

  for scsi_cdrom in /dev/scd[0-99]
  do
    if [ -e "$scsi_cdrom" ]; then
      CDROM_LIST="$CDROM_LIST $scsi_cdrom"
    fi
  done
                                                                                
#2. now we try to find the LFS boot CD (we use ID as identification)
                                                                                
LFS_CDROM_DEVICE=""

for cdrom_device in $CDROM_LIST
do
  if [ "$CHECK_TYPE" = "try_mount" ]; then
    mount -n -t iso9660 ${cdrom_device} $TMP_MOUNT
    # > /dev/null 2>&1
    media_found=$?
  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..."
                                                    

# This is the magical part that makes a live CD live!
# The cd is mounted and pivot_root+chroot commands
# are used to start the system.
# If you really want to know what is going on here,
# You should read the chroot and pivot_root man pages                            
  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 >dev/console 2>&1

fi                                                                               
 
EOF


	To make this script executable run:

    chmod 0755 $LIVECD/mnt/linuxrc

	Ok, that's it. Unmount the image and compress it.

    cd $LIVECD/
    umount $LIVECD/mnt
    gzip $LIVECD/boot/initrd

                          ---------------------
                         | Burning the livd CD |
                          ---------------------

	If you have a CD-RW you should use it for testing. When	you know for sure
  that it works well from the 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 ;-) [that goes for myself, and the author
  of the "Easy" hint ;)]

	Before you start burning, check the size of your LFS tree:

du -sh $LIVECD/ | grep total

	Delete all the stuff you don't need on a live CD. (e.g. /usr/src/*)

	Because linuxrc must be able to identify the CD you have to create a
	file called "livecd".

touch $LIVECD/livecd

	Now burn the LFS system on CD

	Note!
	dev=/dev/hdc is the device number of your CD-Writer
	Check your SCSI devices with "cdrecord -scanbus"
	( as of this writing scsi-emulation is no longer required)
	speed=4 should be changed to (max) speed of your CD-Writer.
	If you are not using a CD-RW remove blank=fast from the cdrecord-command!

cd $LIVECD/
mkisofs -R -l -L -D -b isolinux/isolinux.bin -o $ISODIR/livecd_image.iso -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -V "livecd" $LIVECD && 
cdrecord -v -eject dev=/dev/hdc blank=fast $ISODIR/livecd_image.iso



ACKNOWLEDGEMENTS:

Thanks to:

 * Thomas Foecking <thomas at foecking.de> and Christian Hesse <mail at earthworm.de>
   For writing the "Easy Boot CD of your LFS" hint which confused me so much
   when I tried it with udev that I decided to write this one =o)

 * Gabriel Aneceto Munoz
   For bring syntax errors and other updates to my attention

Feel free to email me comments, point out typos, etc. 

CHANGELOG:
[2004-09-30]
  * Tons of text changes and typo fixes, and various other stuff
[2004-08-04]
  * Fixed syntax errors and made other updates
[2004-07-24]
  * Finally found the time to proofread and submit the hint;)
[2004-05-19]
  * Added environment variables for more flexibility
[2004-05-17]
  * Initial hint completed.


More information about the hints mailing list