Authored by : Praveen Paladugu - Dell Linux Engineering

I have been working on creating live CentOS USB images for some time. One of the problems I ran into was, identifying the right final root device to chroot to. One way to get around this problem would be to use the filesystem label. That is, identify the USB device with the right device label and chroot into it. But, what will happen if two USB sticks have the same label on them? Is there a better way to identify the right root device? This is the question I am trying to answer in this article.

For example, consider you have a system with two internal HDDs and two USB storage keys plugged into it and these devices are enumerated as /dev/sd{a,b,c,d} by the OS. After you select the right device in BIOS to boot into, the bootloader installed on that device will be loaded and the boot menu will be loaded. After the boot option of interest, is selected, the corresponding kernel is loaded to memory and the init script in the initrd image will be executed.

Among the things the init script (in initrd image) has to do is, to identify the right root device. In order to do this, the right modules will be loaded and the udevd daemon will be started. This will populate the /dev file system with the four devices mentioned above (two HDDs and two USBs). Now the challenge here for the init script is, to identify the device that was selected by the user in the BIOS. This is where the edd module is quite helpful.

BIOS will assign a device ID to all the disks, when it enumerates all the devices connected to a system. The device that is selected for boot (by user or the default BIOS options) is assigned a device ID of 0x80. Linux kernel has a loadable module edd, which can be loaded to provide the information of the selected boot device (0x80) to the operating system. This module provides a sysfs interface to the information of the device, which the BIOS thinks it is booting into (device 0x80). After the edd module is loaded, the /sys/firmware/edd/int13_dev80 directory will be created and populated with the information of the disk selected for boot.

A ton of information is provided in that directory. You can use the information about:

  • the number of cylinders or
  • the number of sectors on the disk or
  • mbr signature

to identify the right disk, among the above mentioned four devices. Among the robust methods is, to use the mbr signature to identify the right device.

Now that all the required information is available, how is this information to be used? The information provided by the edd module in /sys/firmware/edd/int13_dev80 directory has to be compared to each of the four devices (/dev/sd{a,b,c,d}) and the device having the matching information will be selected as the final root device. Since we are using the "mbr signature", we will compare the content of /sys/firmware/edd/int13_dev80/mbr_signature file with that of each of the disks.

We now have the information of the device 0x80. How do we find the mbr information of each of the disks? There are a couple of ways to do it:

Using dd


Run the following command:

dd if=/dev/sda bs=1 skip=440 count=4 | hexdump -e '"0x%x\n"'
4+0 records in
4+0 records out
4 bytes (4 B) copied, 6.7816e-05 s, 59.0 kB/s
0x48acedce

The last line in the input shows the mbr signature of disk /dev/sda. Run this command on the all four disks and select the one with the matching signature.

When a bootloader is installed on a disk, a MBR (Master Boot Record) will be installed in the first 512 bytes of the disk. The structure of the MBR is shown at http://en.wikipedia.org/wiki/Master_boot_record. Starting at the offset 440 (which is used with dd command above) an Optional Disk Signature will be present. This signature uniquely identifies a disk, so we rely on this signature while selecting the right root device in initrd

Using fdisk


Run fdisk on the system and parse the output.

fdisk -l /dev/sda
Disk /dev/sda: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x48acedce
Device Boot Start End Blocks Id System
/dev/sda1 2423 9562 57344000 83 Linux
/dev/sda2 * 1 1913 15360000 83 Linux
/dev/sda3 1913 2423 4096000 83 Linux
/dev/sda4 9563 9729 1341427+ 5 Extended
/dev/sda5 9563 9690 1024000 82 Linux swap / Solaris

In the output of the above command, the disk identifier is the mbr signature of the disk /dev/sda. Run the fdisk command on all the disks and select the disk with the matching signature.

Summary


Implementing the above described check will make sure that the init script chooses the right final root device to chroot into, irrespective of how many disk/usb sticks are plugged into the system. This information is primarily used by the live image creation tools. KIWI, a versatile Live Image making tool, uses some of the information provided above. More information about KIWI can be found at http://en.opensuse.org/Build_Service/KIWI. More information about the EDD module can be found at http://linux.dell.com/projects.shtml. Not all BIOS implementations are in total compliance with the EDD 3.0 specification, so this link captures some of the BIOSs which support the EDD specification.