From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Alexander E. Patrakov" Date: Tue, 01 Nov 2005 15:56:01 +0000 Subject: Re: Kernel Firmware Loading Message-Id: <43679011.4020505@ums.usu.ru> List-Id: References: <4365DBD9.2040407@ukonline.co.uk> In-Reply-To: <4365DBD9.2040407@ukonline.co.uk> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: linux-hotplug@vger.kernel.org Andrew Benton wrote: > If I wanted to build an initramfs with the SpeedTouch firmware into > the kernel, how much else will I need to include to get this to work? > Surely to load the firmware I'll also need to include /sbin/udevsend, > /etc/udev/rules.d/10-udev.rules, /sbin/firmware_helper...and what > else? Won't these things need a whole load of other things? This is > looking very complicated. The general case is indeed very complicated, SUSE's script for creating initramfs is more than 64K long. But since you are interested only in firmware loading, the following stupid hack may work for you. The hack is to put a firmware hotplug handler into initramfs, but still rely upon the (obsolete) builtin kernel mechanism for creating and mounting the root device. I do use an initramfs because my root filesystem is on LVM2, and also because of suspend2 with swap on LVM2. But it doesn't load any firmware because my devices don't need that. Details for firmware-loading initramfs (untested, since none of my devices generate firmware hotplug events): 1) Compile klibc, for small-sized "cat", "mount", "sleep", "sh" and "umount" programs, as follows: Download and unpack http://www.kernel.org/pub/linux/libs/klibc/Stable/klibc-1.1.1.tar.bz2 Replace "flag = 0" with "flag = MNT_DETACH" in utils/umount.c, line 15, so that umount is lazy. ln -s /lib/modules/`uname -r`/build linux make and optionally "make install" Find those small statically linked programs in ash/sh, utils/static/{cat,mount,sleep,umount}. Alternatively, use glibc-based utils from your existing system, but then you should copy the required libraries into /lib at step (3) below. 2) Install cpio 3) Make a directory and populate it with the following files: dev/{console,null} (you should know how to mknod them) bin/{sh,cat,mount,sleep,umount} (from klibc) sys (empty directory) sbin/hotplug (see the contents below) lib/firmware (copy your firmware files there) The /sbin/hotplug script should contain the following: #!/bin/sh [ "$1" != "firmware" ] || [ "$ACTION" != "add" ] || [ ! -f "/lib/firmware/$FIRMWARE" ] || exit 0 mount -t sysfs sysfs /sys # FIXME: still needed? if [ ! -e /sys/$DEVPATH/loading ]; then sleep 1 fi echo 1 > /sys/$DEVPATH/loading cat "/lib/firmware/$FIRMWARE" >/sys/$DEVPATH/data echo 0 > /sys/$DEVPATH/loading umount /sys # racy, see below Then cd to this directory and create the initramfs: find . | cpio -o -H newc | gzip -9 > /boot/initramfs_data.cpio.gz 4) modify your boot loader configuration in order to load initramfs_data.cpio.gz as an initrd. 5) Reboot. Please report if firmware loading from this initramfs actually worked for you. ------------------------------ Now about my initramfs. As you have noticed, the simple initramfs above doesn't include the /init file and thus relies on the obsolete in-kernel mechanism for mounting the root fs. This is racy because mounting/unmounting of /sys in the hotplug handler and in the kernel (or in two instances of hotplug handler) can clash. Also this doesnn't work in my case because there's some non-trivial work required in order to activate LVM2 and resume from swsusp2 when swap is on LVM2. Thus, I have to use the /init file. It is just a shell script. If this script is present in initramfs, it is executed instead of mounting the root fs. It's then the responsibility of the script to parse the kernel command line and mount the filesystem. My initramfs is glibc-based, doesn't use udev, and contains all device nodes needed for the "vgchange -ay" command to run. The contents of the /init script: #!/bin/sh mount -n -t proc proc /proc mount -n -t sysfs sysfs /sys # Needed in order to activate LVM2 # Relies upon /dev/mapper/control and /dev/hda being present vgchange -ay init=/sbin/init ro="ro" read CMDLINE /proc/suspend2/do_resume # We get here when we are not resuming. mount -n -o "$ro" "$root" /root umount -n /sys umount -n /proc # run-init is a program from klibc, but it compiles fine against glibc too. exec run-init /root "$init" "$@" /root/dev/console Isn't that simple enough? :) Also this /init file helps avoiding the /sys mounting race: just don't unmount it in the hotplug handler. This /init file will do that for you at the very end. -- Alexander E. Patrakov ------------------------------------------------------- SF.Net email is sponsored by: Tame your development challenges with Apache's Geronimo App Server. Download it for free - -and be entered to win a 42" plasma tv or your very own Sony(tm)PSP. Click here to play: http://sourceforge.net/geronimo.php _______________________________________________ Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net Linux-hotplug-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel