9. Kernel

Everyone should build and install their own kernel. Here's how ...

You will need almost 45 MB of disk space for /usr/src/linux/ and the binaries it generates, that's as well as the 8 MB for the compressed tar file!. If you don't have it, you should find another machine that does.

You need to be familiar with simple commands like mv(1) rm(1) ln(1) ls(1) and cd (there is no MAN page for change-directory, it is a builtin part of bash(1) the shell).

You need the gcc compiler environment loaded, as well as make. Install ncurses so that you can use the nicer menuconfig program, but if this is a boot diskette, and you can hack it, then you don't have to. Most distributions will have helped you install these.

You will be able to delete most of this 45 MB after, (if you are desperate for space) but if you compile other things, you will still need the kernel include files.

9.1 XREFS
9.2 Check the Rescue Route
9.3 /etc/lilo.conf
9.4 Out With The Old ...
9.5 ... And In With The New
9.6 Read the Documentation!
9.7 Kernel - Config Drivers
9.8 Kernel - Makefile # SMP
9.9 Kernel - Compile
9.10 Keep the logfile
9.11 /sbin/installkernel
9.12 Kernel - Patch

9.1

XREFS

9.2

Check the Rescue Route

Make sure that you will be able to boot, even if your new vmlinuz doesn't work. I have the choice of several kernels to boot with. See the section about LILO and 1024 cylinders, it has more details about how to configure lilo, and how to place and find your kernels.

Run lilo now to see that it works, and boot with your backup kernel (to see that it works). If it doesn't work now, why should it work later?

Make sure that you have (will have) the choice of at least two kernels to boot from. One that you know works, and the new one. They must be different vmlinuz files!

Then if the new vmlinuz doesn't work, you simply type the old label at the LILO: prompt, and try again.

If this is the first time you are setting up LILO, make sure you have a BOOT DISKETTE, and that it works!

9.3

/etc/lilo.conf

You want to have the choice of which kernel to boot, and which root partition to boot with. You will need to edit /etc/lilo.conf for every new kernel version. When you run make zlilo, or make install, the last action will be to call lilo to install it as bootable. Make sure that all the necessary partitions are mounted!

Debian-1.1 came with lilo.17, but my shared lilo is version 19, so I had to upgrade it from the .tgz (to be the same on every sub-system). Lilo-19 has a few advantages with initrd support, but it must match whatever is in /boot. Lilo-20 is available and in beta.

Note that modules can have their parameters in /etc/conf.modules, instead of the LILO line (or parameters in /etc/lilo.conf). For a list of options see the Boot-Options-HOTWO.

OK, now that you have run lilo and know that the old system rebooted properly, you can build the new kernel, add an entry into lilo.conf and boot with that.

9.4

Out With The Old ...

Save your old kernel source, and be careful NOT to install the new source over the old. One way is to rename the top dir to something else, or carefully use the command rm -rf linux eg

cd /usr/src/
ls -l
mv linux linux-2.0.0-old # it wasn't a symb-link

Make sure that the directory /usr/src/linux/ does not exist.

9.5

... And In With The New

ftp a recent kernel source, untar it, and rename (mv) the directory, to something like /usr/src/linux-2.0.0. Create a symbolic link so that it appears to be /usr/src/linux. Substitute the actual version numbers (not 2.0.0).

If you choose to put the tree on another disk, do so, simply make the /usr/src/linux symb-link point to it.

cd /usr/src
ls -l
rm linux  # it was a symb link
tar -zxf /tmp/linux-2.0.tar.gz
mv linux linux-2.0.0
ln -s linux-2.0.0 linux
less linux/README

Check that the links to the include files from else-where are correctly set. Once done, they will still be valid next time. See /usr/src/linux/README What you want is:

/usr/include/linux	-> /usr/src/linux/include/linux
/usr/include/asm	-> /usr/src/linux/include/asm-i386
/usr/include/scsi	-> /usr/src/linux/include/scsi

Use ls to see that they are already correct or absent, (if they already exist but are wrong, use mv to put them out of the way, or rm to get rid of them). Use ln -s to create the correct links as follows:

cd /usr/include
ls -ld linux asm scsi	# all not found
ln -s /usr/src/linux/include/linux linux
ln -s /usr/src/linux/include/asm   asm
ln -s /usr/src/linux/include/scsi  scsi

Now that you have done that for this kernel, you don't need to do it again for the next kernel. Just check them! If you later need the disk space, and delete /usr/src/linux, you will still need those include files, to compile normal programs. That's because every program depends on the kernel, and needs the include files to bridge the link. In that case juggle the links to keep what you want and delete what you don't.

# test with:
cd /usr/include ; ls -ld asm   linux   scsi
cd /usr/include ; ls -ld asm/. linux/. scsi/.

A few places to look if you are curious.

9.6

Read the Documentation!

You should browse linux/README and linux/Documentation/* If you don't, you might get a system that doesn't work quite right, and flamed on USENET for not reading the Changes file. I also have an index of kerndocs online, see my home web page. Read the Changes file! It has a list of things that you may need to make a running system.

9.7

Kernel - Config Drivers

(( where is there a HOWTO on this ))

The kernel is made of several drivers, and components. You decide which components go into your system, and what flags are needed for them.

You pick them by running make config, make menuconfig, or make xconfig. I do make menuconfig, which offers a nice menu interface, and runs on a plain console.

cd /usr/src/linux/
make menuconfig

Every option has a help text (cleverly taken from Documentaion/Configure.help) which may help.

Only the necessary

Basically you include the absolutely necessary drivers, needed to run the hard disk during boot time. Other drivers should be built as modules, which you could load from the hard disk (or network, or cdrom, or floppy, ... ), and will be built separately. Most drivers can be configured as modules.

You also set standard options, such as SYSV-IPC and networking. For you they are essential, but someone somewhere sees them as optional, and Linus supports that.

You also get to specify which CPU to compile for, ie Pentium, 486 or 386 (Other non-Intel CPU's will have to read a bit further, I only have a 486). In general, a 486 is a go faster 386, and ditto for the Pentium, but there are a few tiny differences, and there are real optimisations that the compiler can do.

Lots of screens

Getting to grips with the configure options isn't easy, and familiarity helps. eg it is hard to find the NE2000 driver option, unless you know that it appears under "Other ISA Cards", and that selecting that option has no effect, other then making more options available on the screen. Similarly, selecting maturity/allow development code, increases the number of drivers offered to you.

Basically, navigate through every screen, and pick what you think is sensible. If you miss a feature, you can always run through this again, if so you should only have to (re-)run make install modules modules_install and it will only recomile the things that it thinks it has to.

Keep the .config result

The result of running menuconfig is /usr/src/linux/.config It may be worth saving this file for comparing it when compiling the next release.

9.8

Kernel - Makefile # SMP

Normally, you don't have to edit /usr/src/linux/Makefile because all the options are set by make menuconfig above, however recent kernels come shipped with SMP=1.

This will make your machine substantially slower, if you don't have more than one CPU, and it caused my 486 to crash a lot.

Edit Makefile and comment out the line as follows:

# SMP = 1

9.9

Kernel - Compile

If you use /sbin/installkernel, type it in now! (It's listed with in the LILO section). Also check/edit /etc/lilo.conf now. Most people then do this:

cd /usr/src/linux
vi Makefile	# comment out SMP = 1 !!!
make menuconfig
make dep
make install # -or- # make zlilo 
make modules
make modules_install
depmod -a 2.0.0	# or depmod -a between reboots

Building the kernel and modules will take a while. It may be a bit quicker, if you exit X11, and all large applications, to make more memory available to the cache. If you know it will work, you can merge options on the command line, use make install modules modules_install and also make lunch.

9.10

Keep the logfile

If an error does happen, make will stop at that point, leaving the error message on the screen. You can also keep the output in a logfile using

make install 2>&1 | tee my_log_file
Note: the 2>&1 means "send the error-out stream-2 down the same channel as the stdout stream-1". Both get piped through tee(1) which copies the data down two paths, the screen and the file (like a plumbing tee).

Note: if you didn't run config as above, make will run it now, and that interactive IO just won't work with tee. For some reason (isatty) the buffering is all wrong and it just doesn't work.

Re-compile after stange manipulations.

If this is a new linux version, you do NOT have to do the following. You may or may not have to do it for minor .config changes.

Basically, it is for people who play around with the source, and have lots of outdated .o files in there. If you do it, you do it before the above.

cd /usr/src/linux
make mrproper
make clean
make menuconfig

9.11

/sbin/installkernel

If you have configured lilo to use /vmlinuz, you don't have to do this, but I prefer to archive my kernels and keep access to older versions. I also have a disk bigger than 1024 cylinders, so I use a separate partition for all the boot files (/dev/hda4). This is described in the LILO section.

Having the installkernel script, allows you to run make install, instead of make zlilo. Remember to chmod 755 it.

Debian comes with it's own installkernel, slackware doesn't. I still use my own:

#!/bin/sh
# /sbin/installkernel

DIR1=${4:-/boot/kernel/}

[ -f $DIR1/vmlinuz    ] && mv $DIR1/vmlinuz    $DIR1/vmlinuz.old
[ -f $DIR1/System.map ] && mv $DIR1/System.map $DIR1/System.old

cat $2 > $DIR1/vmlinuz-$1	|| exit $?
cat $2 > $DIR1/vmlinuz		|| exit $?
cp  $3   $DIR1/System.map-$1
cp  $3   $DIR1/System.map

lilo

If you rebuilt the kernel, but there was an error in your /etc/lilo.conf, simply fix the error, and run lilo again. It is the last command run, so if it fails there is no need to run make install again. However, doing so won't take as long as most things have already been done.

9.12

Kernel - Patch

The kernel source .tar.gz is about 8 MB. A kernel patch is typically under 100 K. Instead of downloading the whole thing, you download the patch (or patches) for every increment between the source you have and the source you want.

A typical command to "apply a patch" is something like:

cd /usr/src
zcat patch-X.X.X.gz | patch -p0
find linux | grep rej

If your browser uncompressed the patch.gz file, you don't need zcat. You really should rename the kernel directory to the new version, and set the new link. This time you ought to run make mrproper, to avoid Makefile confusing itself. But before then check for any .rej files, where patch failed, eg because someone manually tweaked a file.

cd /usr/src/
mv linux-2.0.0 linux-2.0.1  # youv'e patched it so it is different
rm linux
ln -s linux-2.0.1 linux

Then you run make menuconfig -etc- as above. The result is vmlinux, built and installed. You know it works because a reboot works, and the version number is displayed, eg by uname -a

There will typically be other things to do (eg modules) and accasionally things will break. Read the README and Fix them.