Firewire Debian

Posted by Thomas Thu, 10 Mar 2005 22:06:05 +0000

The goal of this project is to create a bootable cd that contains a kernel and initrd image that will load appropriate modules as to allow an external storage device (primarily, but not limited to, either Firewire or USB2) to be mounted as the root partition of a full Debian/GNU Linux distribution. In addition to this functionality, the bootable cd will retrieve a new kernel and initrd image from the external storage device and boot to that new kernel and initrd image using Kexec.

1. Install Debian to External Drive

First we’ll install a bare Debian distribution onto the external drive. For my purposes, I will be doing this from an existing Debian machine. We’ll use the new Debian GNU/Linux Installation Guide and Installing Debian GNU/Linux from a Unix/Linux System as a reference.

Partition the external disk, using your favorite partitioner (e.g. fdisk, et. al.). My disk is /dev/sdc.

 # fdisk /dev/sdc

Format the partitions. My swap is /dev/sdc1 and my root is /dev/sdc2.

 # mkswap /dev/sdc1
 # mkfs.xfs /dev/sdc2

Mount the new root (as root) on [prexisting] /mnt/sdc2:

 # sudo mount /dev/sdc2 /mnt/sdc2

Install deboostrap (as root):

 # sudo apt-get install deboostrap

Run deboostrap. I ran mine from the d-i image that I happened to already have burned to disc. Adapt to your own use. Check out directions here.

 # sudo debootstrap --arch i386 sarge /mnt/sdc2/ file:/cdrw/debian

Chroot into the new base to finish up the job:

 # sudo chroot /mnt/sdc2 /bin/bash

You need to create /etc/fstab.

 # editor /etc/fstab

Here is a sample you can modify to suit. I will assume that your linux guru self can edit the file appropriately.

Note that I have to change from /dev/sdc to /dev/sda. This change is due to the fact that I know that it will be /dev/sda instead of /dev/sdc as it is detected by the machine that I am installing from.

# /etc/fstab: static file system information.
#
# file system    mount point   type    options                  dump pass
/dev/sda1        none          swap    sw                       0    0
/dev/sda2        /             xfs     defaults                 0    1
proc             /proc         proc    defaults                 0    0

Mount /proc.

 # mount -t proc proc /proc

Configure your keyboard:

 # dpkg-reconfigure console-data

Configure networking, edit /etc/network/interfaces and /etc/hostname.

 # editor /etc/network/interfaces

Here are some simple examples from /usr/share/doc/ifupdown/examples:

######################################################################
# /etc/network/interfaces -- configuration file for ifup(8), ifdown(8)
# See the interfaces(5) manpage for information on what options are
# available.
######################################################################

# We always want the loopback interface.
#
auto lo
iface lo inet loopback

# To use dhcp:
#
auto eth0
iface eth0 inet dhcp

# An example static IP setup: (broadcast and gateway are optional)
#
# auto eth0
# iface eth0 inet static
#     address 192.168.0.42
#     network 192.168.0.0
#     netmask 255.255.255.0
#     broadcast 192.168.0.255
#     gateway 192.168.0.1

Enter your system’s host name (2 to 63 characters):

 # echo DebianHostName > /etc/hostname

Set your timezone, add a normal user, and choose your apt sources.

 # /usr/sbin/base-config new

Note: I had some trouble with the above command (/usr/sbin/base-config new). For whatever reason, it just crapped out on me. I setup the timezone manually (tzconfig), added my usual user (useradd & passwd), and used apt-cdrom to setup my apt sources. Using apt-cdrom made me use the following.

I have a certain way that I like my cdrom to be structured in my filesystem. I use /cdrom as a link to /mnt/cdrom.
Create symlink for /dev/cdrom. My actual cdrom is /dev/hdb.

 # ln -s /dev/hdb /dev/cdrom
 # mkdir /mnt/cdrom
 # ln -s /cdrom /mnt/cdrom
 # mount /mnt/cdrom
 # apt-cdrom add

To configure your locale settings to use a language other than English, install the locales support package and configure it:

 # apt-get install locales
 # dpkg-reconfigure locales

NOTE: Apt must be configured before, ie. during the base-config phase. Before using locales with character sets other than ASCII or latin1, please consult the appropriate localization HOWTO.

If you intend to boot this system, you probably want a Linux kernel and a boot loader. Identify available pre-packaged kernels and install.

 # apt-cache search kernel-image
 # apt-get install kernel-image-2.6.8-1-386

Normally, you might setup the boot loader here, but we don’t care, since we boot from cd.

Make sure that the config files in /etc/mkinitrd/ are setup correctly. Shown below are, respectively, /etc/mkinitrd/mkinitrd.conf and /etc/mkinitrd/modules.

# /etc/mkinitrd/mkinitrd.conf:
# Configuration file for mkinitrd(8).  See mkinitrd.conf(5).
#
# This file is meant to be parsed as a shell script.

# What modules to install.
MODULES=dep

# The length (in seconds) of the startup delay during which linuxrc may be
# interrupted.
DELAY=10

# If this is set to probe mkinitrd will try to figure out what's needed to
# mount the root file system.  This is equivalent to the old PROBE=on setting.
ROOT=/dev/sda2

# This controls the permission of the resulting initrd image.
UMASK=022

# Command to generate the initrd image.
MKIMAGE='mkcramfs %s %s > /dev/null'

# Set this to yes if you want to use busybox(1).
BUSYBOX=no

# Set this to no if you want to disable /usr/share/initrd-tools/scripts.
PKGSCRIPTS=yes

 

# /etc/mkinitrd/modules: Kernel modules to load for initrd.
#
# This file should contain the names of kernel modules and their arguments
# (if any) that are needed to mount the root file system, one per line.
# Comments begin with a `#', and everything on the line after them are ignored.
#
# You must run mkinitrd(8) to effect this change.
#
# Examples:
#
#  ext2
#  wd io=0x300
#
# for 1394/firewire
ieee1394
ohci1394
sbp2
#
# for usb
usbcore
ohci-hcd
uhci-hcd
usb-storage

2. Create CD

Next we need to create the bootable cd that contains our kexec kernel and initrd image. I created a working directory called firewire-debian-2.0/ to work in.

 # mkdir firewire-debian-2.0
 # cd firewire-debian-2.0

2.1 Build Kexec tools

Download, compile, install tools. The lastest version of Kexec as of the writing of this document is version 1.101.

 # wget http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz
 # tar zxvf kexec-tools-1.101.tar.gz
 # cd kexec-tools-1.101
 # ./configure
 # make
 # sudo make install

This installs kexec and kdump in /usr/local/bin.

2.2 Setup Debian’s mkinitrd tools

We’ll go ahead and create the necessary mkinitrd files for Debian’s mkinitrd. You would normally just edit the files that already exist in /etc/mkinitrd, but since this is a special case of installing a kernel, we will leave those files alone so that next time we upgrade our kernel, we don’t get kernel panics.

 # mkdir -p mkinitrd/scripts
 # cd mkinitrd

Debian’s mkinitrd, for our purposes, will take a directory as an argument. This directory has several config files in it, exe, mkinitrd.conf, and modules. Respectively, shown below are the contents of my files:

/usr/local/sbin/kexec

 

# mkinitrd/mkinitrd.conf:
# Configuration file for mkinitrd(8).  See mkinitrd.conf(5).
#
# This file is meant to be parsed as a shell script.

# What modules to install.
MODULES=dep

# The length (in seconds) of the startup delay during which linuxrc may be
# interrupted.
DELAY=10

# If this is set to probe mkinitrd will try to figure out what's needed to
# mount the root file system.  This is equivalent to the old PROBE=on setting.
ROOT=/dev/sda2

# This controls the permission of the resulting initrd image.
UMASK=022

# Command to generate the initrd image.
MKIMAGE='mkcramfs %s %s > /dev/null'

# Set this to yes if you want to use busybox(1).
BUSYBOX=no

# Set this to no if you want to disable /usr/share/initrd-tools/scripts.
PKGSCRIPTS=yes

 

# mkinitrd/modules: Kernel modules to load for initrd.
#
# This file should contain the names of kernel modules and their arguments
# (if any) that are needed to mount the root file system, one per line.
# Comments begin with a `#', and everything on the line after them are ignored.
#
# You must run mkinitrd(8) to effect this change.
#
# Examples:
#
#  ext2
#  wd io=0x300
#
# for 1394/firewire
ieee1394
ohci1394
sbp2
#
# for usb
usbcore
ohci-hcd
uhci-hcd
usb-storage

The standard /usr/share/initrd-tools/init file must be edited to reflect the new usage of Kexec. The diff is shown below:

  *** /tmp/init   Sat Oct  2 13:35:43 2004
  --- /usr/share/initrd-tools/init        Fri Aug 27 13:43:34 2004
  ***************
  *** 416,427 ****
          mount_root
          cd mnt
          [ $DEVFS ] && mount -nt devfs devfs dev
  -       # must mount proc for kexec
  -       mount -nt proc proc /proc
  -       kexec -l --append="$cmdline" --initrd=initrd.img vmlinuz
  -       #kexec -l --append="$cmdline" --initrd=initrd.img.old vmlinuz.old
  -       kexec -e
  -       umount -n /proc
          pivot_root . initrd
    fi
    if ! [ -x ${init#/} ]; then
  --- 416,421 ----

2.3 Build Kexec kernel package

I will be using version 2.6.10-mm2 of the Linux kernel. Download 2.6.10 tarball and mm2 patch. Package kernel. I prefer to do this all as root.

 # sudo su

Download all the files.

 # cd /usr/src
 # wget http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.10.tar.bz2
 # wget http://kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.10/2.6.10-mm2/2.6.10-mm2.bz2

Untar and/or unzip the files.

 # tar jvf linux-2.6.10.tar.bz2
 # tar zxvf 2.6.10-mm2-kexec3.tgz

Cautiosly remove linux symlink. Rename the stock 2.6.10 directory to reflect the changes. Replace symlink. Patch the stock 2.6.10 kernel with the mm2 patch.

 # rm linux
 # mv linux-2.6.10 linux-2.6.10-mm2
 # ln -s linux-2.6.10-mm2 linux
 # cd linux
 # cat ../2.6.10-mm2 | patch -p1

Configure the kernel. I prefer menuconfig.

 # make menuconfig

Here is a copy of my .config file

I use a script to make my kernels for me. This script handles [first time setup of] distcc, appends the date to the kernel, and times how long it takes.

#!/bin/bash

MAKE_KPKG=/usr/bin/make-kpkg
KERNEL_DIR=/usr/src/linux
CONFIG_TYPE=oldconfig
export CONCURRENCY_LEVEL=8

export DISTCC_HOSTS='localhost ezekiel'
# make sure /root/bin instead of ~/bin
export PATH="/root/bin:$PATH"

# Assume that symlinks to distcc are already in place
# ln -s /usr/bin/distcc ~/bin/cc
# ln -s /usr/bin/distcc ~/bin/gcc
# ln -s /usr/bin/distcc ~/bin/c++
# ln -s /usr/bin/distcc ~/bin/g++

# Assume that /usr/src/linux symlink is already in place
cd $KERNEL_DIR

# Make everything
$MAKE_KPKG clean
time $MAKE_KPKG --append-to-version=.`date +%m%d%y` \
	--config=$CONFIG_TYPE kernel_image modules_image

After the kernel-image package has been compiled, move it to your firewire-debian-2.0/ working directory.

 # cd /usr/src/linux
 # mv kernel-image-2.6.10-mm2.031005_10.00.Custom_i386.deb ~/firewire-debian-2.0

2.4 Build initrd image and iso

I use this Makefile to create the appropriate initrd image and iso for the cd. Be sure that you use tabs in the appropriate places!

KERNEL_VERSION=2.6.10-mm2.031005
KERNEL_IMAGE_DEB=kernel-image-2.6.10-mm2.031005_10.00.Custom_i386.deb
ISO=cd_image.iso
CDRW_DEV=/dev/hdb

all: clean clean_tmp initrd iso clean_tmp iso

initrd:
	# create directorires
	mkdir -p master/isolinux

	# create initrd image from debian kernel-image package
	dpkg -x ${KERNEL_IMAGE_DEB} .
	cp boot/config-${KERNEL_VERSION} master/isolinux/config
	gzip -f master/isolinux/config

	cp boot/System.map-${KERNEL_VERSION} master/isolinux/sys_map
	gzip -f master/isolinux/sys_map

	cp boot/vmlinuz-${KERNEL_VERSION} master/isolinux/vmlinuz

	# try to get around mkinitrd's inability to specify a modules directory
	sudo mv lib/modules/${KERNEL_VERSION} /lib/modules/
	sudo chown -R root.root /lib/modules/${KERNEL_VERSION}

	# make first initrd to boot to /vmlinuz (and /intird)
	sudo vim /usr/share/initrd-tools/init
	sudo mkinitrd -d mkinitrd/ -o miniroot ${KERNEL_VERSION}

	# move to cd
	mv -f miniroot master/isolinux/miniroot
	sudo chown tlg1466.tlg1466 master/isolinux/miniroot

	# make second initrd to boot to /vmlinuz.old (and /initrd.old)
	sudo vim /usr/share/initrd-tools/init
	sudo mkinitrd -d mkinitrd/ -o miniroot ${KERNEL_VERSION}

	# move to cd
	mv -f miniroot master/isolinux/miniroo2
	sudo chown tlg1466.tlg1466 master/isolinux/miniroo2

	# clean up
	sudo rm -rf /lib/modules/${KERNEL_VERSION}

iso:
	./bin/mkiso ${ISO}

burn:
	/usr/bin/cdrecord -v -pad -overburn -eject -tao speed=48 gracetime=2 \
		dev=${CDRW_DEV} driveropts=burnproof fs=400x53k ${ISO}

clean:
	rm -f ${ISO}

clean_tmp:
	# remove tmp directories
	rm -rf boot/ lib/ usr/
	rm -f miniroot
	sudo rm -rf /lib/modules/${KERNEL_VERSION}

I use this script to actually make the iso. Place it in a directory called bin.

#!/bin/sh

# helper script, because makefiles are stupid
# argument is output cd iso filename

cd master
/usr/bin/mkisofs -R -o ../$1 -b isolinux/isolinux.bin -c isolinux/boot.cat \
  -no-emul-boot -boot-load-size 4 -boot-info-table .

You also must copy the isolinux.bin file to the master/isolinux/ directory.

 # cp /usr/lib/syslinux/isolinux.bin master/isolinux/

AND, you also create a isolinux.cfg file in the master/isolinux/ directory. My file is below:

FONT font.psf
# see /usr/doc/syslinux/syslinux.doc.gz for file format description
DEFAULT linux
APPEND vga=normal load_ramdisk=1 ramdisk_size=4096
TIMEOUT 0
#DISPLAY debian.txt
PROMPT 1
LABEL linux
  KERNEL vmlinuz
  APPEND initrd=miniroot root=/dev/ram0
LABEL linux.old
  KERNEL vmlinuz
  APPEND initrd=miniroo2 root=/dev/ram0

Now, you can finally run make to create the iso and make burn to burn it to disc.

 # make
 # make burn

Hopefully, now you have a bootable iso. I know that these instructions are quite terse, and there are bound to be things that I left out, but hopefully they give somebody who wants to try and replicate this project can do it. It might take some work, but hopefully they can fill in the details from the big picture.

Posted in | 1 Comment

Comments

  1. chobas.com’s blog » A While said on March 25, 2005 @ 12:54 pm:

    [...] , but not so much for Intel-type products. You can check out my preliminary documentation here. It could use some polishing, and it may be quite wordy, but, hey, all the info is there. If you r [...]

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.