Given vmlinuz and initrd.gz, how do I find out, where the kernel is going to load / (root) file system from?
Solution 1
It is given at boot time by your bootloader, for example Grub.
To see with which arguments your kernel was started, do this:
$ cat /proc/cmdline
For me, this ouputs:
BOOT_IMAGE=/vmlinuz-3.5.0-13-generic root=/dev/mapper/crypt-precise--root ro
So the initrd/initramfs will try to mount my /dev/mapper/crypt-precise--root
(encrypted LVM) logical volume as /
.
You can re-configure Grub to load other operating systems from your harddrive using the same kernel (multi-boot) or edit this line runtime by pressing e while selecting (not yet booting) the Grub entry.
For recent Debian-based distributions, changing it permanently works like this:
(be careful, you may not be able to boot into your original operating system again!)
In the file /etc/default/grub
set some GRUB_CMDLINE_LINUX="root=/dev/mydevice"
yourself and update Grub by doing update-grub
.
However, I recommend you to configure multiboot, otherwise it's not possible to change or update your Grub configuration again easily.
Solution 2
Given the boot image, you could find internal kernel version string with file
command:
%> file /boot/vmlinuz-linux
/boot/vmlinuz-linux: Linux kernel x86 boot executable bzImage, version 3.5.3-1-NAME (X@Y) #1 SMP PREEMPT WEEK MON DAY, RO-rootFS, swap_dev 0x5, Normal VGA
Solution 3
Not sure if this is still something of interest but for the sake of future googlers like myself:
There are two separate root
directories in play when booting/installing from grub. There is the grub root and the linux root (I'm not sure if this is the technical term).
The grub root can be set within the grub.cfg
, and determines which files are readily visible within grub. The default grub root should be the root directory of the drive booting grub, so if the contents of your bootable drive are:
/boot/
/boot/grub2/
/boot/grub2/grub.cfg
...
Then the location of the grub.cfg from the grub root is /boot/grub2/grub.cfg
The grub root can be changed in the grub.cfg using set root=
.
You can use this to set the root to a directory within the current root (set root=/boot/
would cause the grub.cfg
to be located at /grub2/grub.cfg
) which behaves similar to a chroot
in Linux.
You can also change the current root to another drive (set root=(hd0,1)
would set your root to hd0, partition 1. For a full listing of what devices you can use, see the grub page about it http://www.gnu.org/software/grub/manual/grub.html#Device-syntax).
While changing the grub root can be useful, you can also prefix any path with whatever you were going to use (e.x. linux (hd0,1):/boot/OS/RHEL/isolinux/vmlinuz
instead of set root=(hd0,1)
first). Also, once the kernel starts the grub root is irrelevant
As for the Linux root, that is a parameter you can pass the kernel (vmlinuz) when you load it. For this you can pass the kernel a parameter root=
(this value will appear in /proc/cmdline)
However it's important to note that this new root is expected to contain a Linux root filesystem (looking for /etc/ /var/ and so on). When installing you provide the initrd (INITial Ram Disk) which contains these elements, so you probably don't want/need to change the Linux root during installation.
If you do change the Linux root be wary that Linux installation media is not a Linux root filesystem, though the initrd.img contained within is.
If what you're trying to do is use files within your iso as arguments to your kernel then there is a solution. If you create a loopback device in grub the device will persist when the kernel starts (so you should see a device called /dev/loop0
in the Linux root during installation)
I'll give a little snippet of a grub.cfg that relates to ISOs and RHEL specifically:
menuentry "RHEL" {
set isofile='/boot/iso/RHEL.iso' #this is just a grub variable
loopback loop $isofile #mount the $isofile with label=loop as a loopback device
set root=(loop) #set the grub root to the mounted iso (so / is the top level directory in the iso)
#this starts the kernel and passes the paramter inst.stage2 using the ISO and kickstart as a location on the loopback device created by grub (the syntax for this line is liable to change between distros)
linux /isolinux/vmlinuz noeject inst.ks=hd:/dev/loop0:/ks/ks.cfg inst.stage2=hd:LABEL=USBDRIVELABEL:/$isofile
initrd /isolinux/initrd.img #provide an initial ramdisk (which will become the **Linux root**
}
Be aware that the syntax for the kernel line in grub.cfg is:
linux [path to kernel] [kernel argument 1] [kernel argument 2] ...
The kernel arguments will all appear in /proc/cmdline
. It's important to note that because they are processed by the kernel grub syntax is not valid.
You can find more about this in the grub documentation (http://www.gnu.org/software/grub/manual/grub.html#Introduction)
and kernel parameters archwiki page (https://wiki.archlinux.org/index.php/kernel_parameters#GRUB)
as well as boot options for your relevant distro (RHEL https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Installation_Guide/chap-anaconda-boot-options.html#list-boot-options-sources)
Solution 4
On most installations, you specify the root device to the bootloader. The root device is passed to the kernel as a parameter called root
. Depending on the bootloader, this may be part of the kernel command line arguments (which may look like ro quiet root=/dev/sda1
) or a separate setting. For some common bootloaders:
- Lilo: in the configuration file (
/etc/lilo.conf
), there is aroot
directive to indicate the Linux root device. - Grub legacy (versions 0.9x): in the configuration file (typically
/boot/grub/menu.lst
), the root device is passed as part of the kernel command line (kernel
directive). Note that there is a differentroot
directive for Grub itself; that tells Grub where to look for files such as the kernel. On many systems, the Grub configuration file is generated by theupdate-grub
script which fills in the root device from the installed system (using/boot/grub/device.map
). - Grub 2 (versions 1.9x): in the configuration file (typically
/boot/grub/grub.cfg
), the root device is passed as part of the kernel command line (linux
directive). Note that there is a differentroot
variable (set root=(hd0,1)
) that tells Grub where to look for files such as the kernel. On many systems, the Grub configuration file is generated by theupdate-grub
script which fills in the root device from the installed system (using/boot/grub/device.map
). - U-Boot: the root device is passed as part of the command line arguments in the
bootargs
environment variable. The U-Boot binary contains a default value baked in at compile time, which can be overridden by a setting in flash memory (if the device permits).
In the absence of a root
command line argument, the initrd or initramfs, if used, may try to find a root partition to mount. Even in the presence of a root
argument, the initrd or initramfs may decide to use a different device. The code calls switch_root
to switch from the initrd to the actual root.
The default root device when there is no root
command line argument is determined at compile time. You can change that value in a binary image with the rdev
utility.
On a booted kernel, you can see the root
parameter (if any) that was passed to the kernel in /proc/cmdline
. You can see the actual device mounted on /
in /proc/mounts
.
Related videos on Youtube
CoOl
Updated on September 18, 2022Comments
-
CoOl over 1 year
I'm trying various ways of Linux installation (from iso, flash, iso on flash, kernel on flash, root FS in iso-file on flash...) and want to understand what's going on.
My question is: is it possible, given the built kernel and ramfs files from a distribution (vmlinuz and initrd), to find out, where they are going to look for the "/" file system? Is it possible to configure this without re-compiling the kernel?
And one more: when kernel loads the root filesystem from loopback device, created from .iso-filesystem, how can I configure this process? Thanks!
EDIT: In fact, GRUB configuration contains GRUB root, which is not the real kernel root filesystem location, but just a folder that contains GRUB's belongings,.
The real root is configured in
init
script ininitrd
as described here.That's how Debian kernel finds an ISO file on hard drive, when booting from it - initramfs finds it: http://www.debian.org/releases/stable/i386/apas02.html.en#howto-getting-images-hard-disk; note that GRUB configuration doesn't contain any reference to ISO location.
-
CoOl over 11 yearsThanks, gertvdijk! (I should've found that myself, just overlooked lines in config, sorry.)
-
CoOl over 10 yearsHey, gertvdijk, seems, that you deceived me with your answer :) See my update to the question.
-
gertvdijk over 10 years@Bob No, I think you're overlooking the fact that the initrd you're referring to is not the same as the one you install - note the
hd-media
prefix in the docs. Also, "The real root is configured ininit
script [...]" <-- is taken from the kernel parameter, unless the initrd is customized to load it from somewhere else (like the Debianhd-media
version of the initrd.) -
CoOl over 10 yearsOk, that's fair, there might be no initramfs at all. :) hd-media is a temporary kernel and initramfs for CD image installer, but its initramfs, who makes the kernel search for root in .ISO, not GRUB. Thanks and cheers!