Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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?

share|improve this question
add comment

2 Answers

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.

share|improve this answer
    
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 9:03
    
@Carlito Does this kernel have devtmpfs enabled (check the config file)? Debian only recently switched to devtmpfs. –  Gilles 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). –  Patrick 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
show 2 more comments

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).

share|improve this answer
    
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 9: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 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 Oct 24 '12 at 11:28
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.