11

I am trying to learn stuff about initrd. I have followed this tutorial to build my own initrd from scratch, and I installed busybox on it. Then I made an .iso from it with isolinux, so I could test it in virtualbox. It works great!

I have the basic commands from busybox, so I wanted to mount a filesystem. But the /dev directory is almost empty (no sda), except for some files I created while following the tutorial. I learned about udev and I think this is what I need. However I am not sure how to go on this.

Should I just grab the latest source code from udev, compile it and add it to my initrd? And then call /bin/udev or something like that in my init script? Or is there an other/better way to populate the /dev directory?

Edit: Some additional info and updates on what I have done already.

  • I test everything in virtual box. I just installed ubuntu minimal in virtual box, made an .iso from my initrd, and then boot from the iso in virtualbox.
  • I used the vmlinuz and /lib/modules that were present on a debian-businesscard.iso and copied those over to my initrd which I created by following the tutorial I linked earlier.
  • Kernel has CONFIG_DEVTMPFS=y
  • Some devices show up in /dev, like tty0-tty63 and some others, but no sda/hda.
  • Ran lspci -k in my currently running OS and in a virtual box to check which modules are in use. SATA Controller says it uses ahci as module.
  • When I execute modprobe -v ahci it complains a lot about "unknown symbol: ata_some_stuff", but after that it returns something like SCSI Subsystem initialized, ATA-6: VBOX HARDDISK and Direct-Access ATA VBOX HARDDISK. However, still no harddrive devices found in /dev.

My current /init/ script is as follows:

#!/bin/ash
mount -t devtmpfs none /dev
mount -t proc /proc /proc
mount -t sysfs none /sys
modprobe -v ahci
echo "Hello world"
exec /bin/ash --login

Does anyone has any idea what I am doing wrong and what I should be doing instead?

Paradox
  • 1,369
  • 3
  • 13
  • 27
Carlito
  • 548
  • 3
  • 6
  • 15

2 Answers2

13

While gilles' answer is correct, it's old school :-). Another item of note (more a nitpick on the terminology than anything) is that guide you linked to is instructions on how to create an initramfs, not an initrd. The two are similar, and serve the same purpose, but are different in how the image is stored and loaded.

Anyway, the answer to your question is actually really really simple.

  1. Enable devtmpfs in the kernel (CONFIG_DEVTMPFS=y)
  2. Run mount -t devtmpfs none /dev as the very first thing in your init script.

That's it. The devtmpfs will populate /dev just like udev. You don't even need to pre-populate /dev (in the initramfs image) with the basics like null, zero, or console.

phemmer
  • 70,657
  • 19
  • 188
  • 223
  • 1
    Thanks for your comment. I ran your command, and I now have more devices, but still no sda or hda to mount. Is there something I forgot to do? I use the vmlinuz kernel I got from debians live system, should I actually compile my own? – Carlito Oct 24 '12 at 09:03
  • @Carlito Does this kernel have devtmpfs enabled (check the config file)? Debian only recently switched to devtmpfs. – Gilles 'SO- stop being evil' Oct 24 '12 at 10:14
  • @Gilles There isn't a config file supplied, but I loaded the kernel I got from debian, the config file said `CONFIG_DEVTMPFS=y`, but I still don't get any sda devices. I think this is because I have not loaded any modules (lsmod returns nothing). What modules should I load to get the filesystem devices? Or is there something else I forgot? – Carlito Oct 24 '12 at 10:46
  • @Carlito yes, if you have other things showing up in `/dev`, just not the drives, then devtmpfs is working and you're likely missing the disk controller module (as you guessed). Unfortunately the only way to know which driver/module you need is to either read the information for each one in the kernel config, or run `lspci -k` in a running linux system (which will show you what kernel driver the various components of your system are using). – phemmer Oct 24 '12 at 11:44
  • I ran `lspci -k` in my current running system and in a virtual box system. Both use "ahci" as kernel driver for my SATA controller. So I just copied the `/lib/modules/` directory over to the one on my initramfs and added `modprobe -v ahci` before running the `mount -t devtmpfs none /dev` as you suggested. modprobe complains about some missing symbols, but then returns `ATA-6: VBOX HARDDISK` and `Direct-Access ATA VBOX HARDDISK`. However, still no sda/hda device in the `/dev` directory. Any idea what I am doing wrong? – Carlito Oct 24 '12 at 19:09
  • @Carlito you can't just copy modules from any kernel, they have to belong to the kernel you're currently running. If you're using a custom built kernel, you have to use the modules that were built for it. Also the modprobe should come after the `mount -t devtmpfs ...`. The mount should be the very first thing. – phemmer Oct 24 '12 at 21:45
  • I used the modules and the kernel from the same debian businesscard.iso, so I assume the modules belong to that kernel. I did modprobe after the mount command, but still no success. I have updated my main post with some more info. – Carlito Oct 24 '12 at 23:42
  • Hi patrick, just to understand, is there any problem with CONFIG_DEVTMPFS_MOUNT=y ? This is what current buildroot is doing. – Ciro Santilli OurBigBook.com Jun 01 '17 at 09:44
  • 1
    @CiroSantilli709大抓捕六四事件法轮功 `CONFIG_DEVTMPFS_MOUNT=y` does not have any effect on initramfs. From the kernel help text: "This option does not affect initramfs based booting, here the devtmpfs filesystem always needs to be mounted manually after the rootfs is mounted" – phemmer Jun 01 '17 at 12:35
4

Udev populates /dev automatically based on the drivers that are loaded into the kernel and the devices that these drivers detect. The names of the devices and their permissions are based on a set of rules that administrators can fine-tune. Most Linux systems should use udev; the exception is systems (usually embedded) where the hardware configuration is known at the time the system is set up and won't change afterwards.

You would typically call udev fairly early in your startup sequence. One of the few things you should (must?) do before that is mount /proc and /sys. After starting the daemon, call udevadm trigger --action=add; udevadm settle to make udev process all pending events from the kernel (trigger) and wait until the events are processed before continuing (settle). You can then proceed to locate the device containing the root filesystem.

Besides the udevd binary, you'll need the other parts of udev on your initrd. This includes configuration files in /etc/udev, the base configuration in /lib/udev as well as helper binaries such as scsi_id also in /lib/udev. You need all the programs that are called from udev rules that you include in the initrd.

At the end of the initrd, before transfering control to the real root partition, you'll need to stop udevd like every other program from the initrd. This doesn't remove any device from /dev. Use mount --move /dev /root/dev to move the mounted /dev to the real root.

Gentoo has an initramfs guide and an initramfs wiki page which mention udev among other things. Initramfs is the modern successor to initrd, using a cpio archive rather than a filesystem image, and with a different process interface (on an initrd, /linuxrc must exit, whereas on an initramfs, /init must exec the init from the real root); most systems have switched these days (even if the file might still be called initrd).

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
  • Thanks for your answer. I came to the conclusion that I actually made an initramfs instead of an initrd. But I use the vmlinuz kernel I got from debians live system, should I actually compile my own kernel for this (so I know which modules there are for loading harddrives), or is there a sort of minimal version I could use with the basic modules? I will probably download the latest udev and try to compile and run it. – Carlito Oct 24 '12 at 09:22
  • @Carlito I recommend first trying with the Debian kernel, as forgetting a necessary driver is a common mistake when compiling your own kernel. – Gilles 'SO- stop being evil' Oct 24 '12 at 10:12
  • But how would I get one? I just copied the vmlinuz I found in the debian-businesscard.iso (probably not the best idea). Should I just copy the standard kernel I got from ubuntu or debian, and the whole /lib/modules directory? – Carlito Oct 24 '12 at 10:45
  • @Carlito You'll need at least all the modules that are necessary for your hardware. It can be difficult to find all you need from browsing the list. The best way to find out what you need is to run `lsmod` on a working system. So start with all of them, then prune intelligently if you need to save space. – Gilles 'SO- stop being evil' Oct 24 '12 at 11:28