Showing posts with label initrd. Show all posts
Showing posts with label initrd. Show all posts

2012-01-04

Using LILO to boot disks by UUID

If you're plugging USB drives in an out and using LILO to boot a Linux distro (eg. Slackware) you may have ended up with a kernel panic because your /dev/sd# were shuffled around and the kernel was no longer able to find its root partition on the expected device. Of course, having Linux failing to boot just because you happened to plug an extra drive sucks big time, so we want to fix that.

The well known solution of course it to use UUIDs or labels, since these are fixed. However, while recent versions of LILO are supposed to support root partitions that are identified by UUID/Label, in practice, this doesn't work UNLESS you are using an initrd disk. I'm not sure who of LILO or the kernel is responsible for this new layer of "suck" (I'd assume the kernel, since the expectation is that LILO is using the dev mappings that are being fed by the kernel), but I can only say that there really are some areas of Linux that could still benefit from long awaited improvements...

Thus, to be able to use UUIDs or labels for your root partition in LILO, you must boot using an initrd. Worse, as previously documented, you will most likely need to compile a new kernel that embeds the initrd, lest you want to run into the following issue while running LILO:
Warning: The initial RAM disk is too big to fit between
the kernel and the 15M-16M memory hole.

In practice (as also illustrated by this post), this means you will need to:
  1. Create an initrd cpio image that can be embedded into a kernel with:
    cd /boot
    mkinitrd -c
    cd initrd-tree
    find . | cpio -H newc -o > ../initrd.cpio
  2. Recompile a kernel, while making sure that you have the General Setup → Initial RAM filesystem and RAM disk (initramfd/initrd) support selected, and then set General Setup → Initramfs source file(s) to /boot/initrd.cpio

  3. Edit your /etc/lilo.conf and add an append = "root=UUID=<YOUR-DISK-GUID>" to your Linux boot entry. An example of a working lilo.conf is provided below. Note that you probably also want to use a fixed IDs for boot=, so that running LILO is also not dependent on the current /dev/sd# organization.. 

  4. Run LILO, plug drives around and watch in amazement as your system still boots the Linux partition regardless of how the drives are assigned
Example lilo.conf:
# Start LILO global section
boot = /dev/disk/by-id/ata-ST3320620AS_ABCD1234
compact
lba32
# LILO doesn't like same volume IDs of RAID 1
disk = /dev/sdb inaccessible
default = Windows
bitmap = /boot/slack.bmp
bmp-colors = 255,0,255,0,255,0
bmp-table = 60,6,1,16
bmp-timer = 65,27,0,255
# Append any additional kernel parameters:
append=" vt.default_utf8=1"
prompt
timeout = 35
# End LILO global section

image = /boot/vmlinuz
  append = "root=UUID=2cc11aaf-f838-4474-9d9a-f3881569f97c"
  label = Linux
  read-only
image = /boot/vmlinuz.rescue
  append = "root=UUID=2cc11aaf-f838-4474-9d9a-f3881569f97c"
  label = Rescue
  read-only
other = /dev/sda
  # Windows doesn't go to S3 sleep and has issues with backup,
  # unless it sees its disk as first in BIOS...
  boot-as = 0x80
  label = Windows
other = /dev/disk/by-id/ata-ST3320620AS_ABCD1234-part4
  label = OSX
Oh, and of course, don't forget to edit your /etc/fstab as required, if you still use /dev/sdX# entries there.

2009-10-01

LILO Warning: The initial RAM disk is too big

Just re-installed Slackware 13.0 x64 on the HTPC, this time using a small boot partition on the extra non fakeRAIDed HDD, which I recently added to the whole rig. This 4th HDD is now the boot disk for the whole rig, and contains the kernel and initrd (while the Linux partition itself is on the RAID5 set).

Install went without much of a hitch, and even the first few kernel recompilations we fine, but lately, after adding more kernel features, I got the following LILO warning and the kernel simply doesn't boot:
    Warning: The initial RAM disk is too big to fit between the kernel and
the 15M-16M memory hole. It will be loaded in the highest memory as
though the configuration file specified "large-memory" and it will
be assumed that the BIOS supports memory moves above 16M.
So much for checking the "Optimizing for size" kernel option.

The root of the matter seems to be that uncompressed kernel + uncompressed initrd must fit within the 0-15 MB low memory addresses, and it looks like a bzipped 4.5 MB kernel + a gzipped 1.4 MB initrd don't cut it, regardless of whether your BIOS has set a hole for the 15M-16M range.

Unlike what you might read elsewhere ("Remove options from your kernel to reduce its size! / Why are you using such a huge kernel?" - how's that helpful, guys?), there is a solution right there in the kernel conf, through the "General Setup -> Initramfs source file(s)" option.
Somehow when you do that, the kernel is able to find all the RAM it needs for the initrd.

Now, I'll grant you that this makes it less convenient to modify your initrd options on the fly, yet I believe this is better than being restricted in your choice of kernel features. Plus it appears that the kernel boots a little bit faster when using the emebedded initrd.

Of course, that means that you need to create your uncompressed cpio archive from your initrd-tree before you can point to it, which can easily be done as follows:
cd /boot/initrd-tree
find . | cpio -H newc -o > ../initrd.cpio