Now comes the time to do some magic. As you have no doubt realized during the frame buffer set up, there is a collision between two initramfs images that need to be loaded during booting. Even if the kernel manages to merge the two images and do the correct thing, what if you need a third? Or fourth? Since initramfs is a root file system which is embedded into the kernel and loaded at an early stage of the boot process it can be immensely useful when customized. Especially in a netbook with two graphics cards that are governed by a switch requiring a system restart can initramfs be used for early detection of GPUs, Wifi, etc. However, before we get ahead of ourselves, let us first simply merge the two initramfs we already have.
The frame buffer article on the Gentoo Wiki implies that this is possible, however, remains frustratingly vague on the subject:
If you need to addv86dto an already existinginitramfssource directory, look in/usr/share/v86d/initramfsand copy the files listed there.
For starters let's get a simple custom initramfs to work. The Gentoo Wiki article on initramfs has more detail if you require additional information. You already compiled all the necessary changes into your kernel so you can go on to create the necessary directories.
mkdir /usr/src/initramfs cd /usr/src/initramfs mkdir bin dev etc mnt proc root sbin sys
Since you will want to boot “into” your initramfs you need to add device nodes necessary for booting, including the device for your root partition. Note the important parameter -a for the cp command. It stands for –archive which is equal to –no-dereference, –preserve=all and –recursive. What it boils down to is that the copy command will copy everything it finds, recursively, while preserving the mode, ownership, and time stamps of the files, but it will not follow symbolic links.
cp -a /dev/console /dev/null /dev/sda1 dev/
Anything you want to execute during the boot process needs to be copied into your initramfs layout. In addition, you also need to copy any libraries that your binaries require. Since you require your initramfs to be a small but fully functioning system, this could be very tedious and error-prone. Luckily you can just use sys-apps/busybox. busybox is a set of utilities for rescue and embedded systems, which contains a shell, utilities like ls, mkdir, cp, mount, insmod, etc., all collected and nicely packaged in a single binary called /bin/busybox. However, anything you want to use within your initramfs cannot depend on any outside libraries. If it does your initramfs will complain (very nondescriptly) that it cannot find the binary.
To free any binary of its dependencies on external libraries you need to compile it statically. That simply includes all the external libraries (or their necessary parts) in the executable. Several ebuilds, such as busybox already provide a USE-flag called “static” that allows you to do just that. In case an ebuild does not have the “static” USE-flag you will need to manually compile it and set the appropriate static flags.
echo "# required for initramfs:" >> /etc/portage/package.use echo sys-apps/busybox static -dynamic >> /etc/portage/package.use emerge -avN sys-apps/busybox
After you statically emerged busybox copy its binary into your initramfs layout. (Do not forget the -a parameter!)
cp -a /bin/busybox bin/
The last thing your initramfs needs is an init file. The init file needs to be placed in the root directory of your initramfs - in our case /usr/src/initramfs/ and because busybox includes a fully functional shell it can be a simple shell script. Its very basic version looks like this:
#!/bin/busybox sh # mount proc and sys mount -t proc none /proc mount -t sysfs none /sys # mount the root file system mount -o ro /dev/sda3 /root # do your magic here # clean up umount /proc umount /sys # boot the real thing exec switch_root /root /sbin/init
Finally you need to make the init script executable and package everything together. For packaging you have two options - either you modify your kernel and point it to your initramfs directory or you create a stand-alone image. For the kernel version you simply point its General setup —> () Initramfs source file(s) option to the initramfs directory (see Simple Frame Buffer and when you recompile the kernel it automatically creates the image and then loads it at boot time. However, you will have to re-compile the kernel each time you change the files within the initramfs. Since this is too much of a hassle, I decided to create my own, separate image and link to it from grub.conf. To create a standalone archive file run the following commands:
cd /usr/src/initramfs find . -print0 | cpio -ov -0 --format=newc | gzip -9 > /boot/initramfs.cpio.gz
This will create a file called initramfs.cpio.gz in your /boot directory. You now need to instruct GRUB to load this file at boot time - you do this with the initrd line:
title = Gentoo Linux root (hd0,0) kernel /boot/bzImage initrd /boot/initramfs.cpio.gz
Note that you do not need to specify the root=/dev/sda3 parameter to the kernel, since your init script tells the kernel after it is done executing where it can find your root partition. You can also always look at the contents of an initramfs file by calling zcat on it (or opening it with a text editor like vim):
zcat /boot/initramfs.cpio.gz | cpio --list
When you now reboot your computer the kernel will extract the files from your initramfs archive automatically and execute your init script, which in turn should then take care of mounting your root partition and execute the init of your installed Gentoo.
Now you have a custom initramfs and loads during boot time, but it does not do anything. It is about time we changed that. Remember that you had two separate initramfs images that needed to be executed - the v86d (uvesafb) image and the fbsplash image. Combining those two is actually fairly easy if you know what you are doing, but unfortunately it is not documented anywhere. You can open and look at any initramfs image by simply calling
vi /path/to/initramfs
This will get you a list of the contents. Mostly - as it is the case with the v86d initramfs image found in /usr/share/v86d/initramfs - the contents will be files already present at your computer and you can simply copy them into the appropriate folders of your custom initramfs. In case an image contains files you do not have outside of it, you can always open the initramfs image, extract its contents into an empty directory and then copy the necessary files from there. Please note that this overwrites files in the directory you are currently in.
mkdir /tmp/initramfs cd /tmp/initramfs zcat /boot/initramfs.cpio.gz | (while true; do cpio -i -d -H newc --no-absolute-filenames || exit; done)
The following are the contents of the v86d initramfs:
dir /dev 0755 0 0 nod /dev/console 0600 0 0 c 5 1 nod /dev/tty1 0600 0 0 c 4 1 nod /dev/zero 0600 0 0 c 1 5 nod /dev/mem 0600 0 0 c 1 1 dir /root 0700 0 0 dir /sbin 0755 0 0 file /sbin/v86d /sbin/v86d 0755 0 0
As you can see there is nothing special in it - all files and devices already present on your system. The only catch when trying to copy these files is to always use the -a parameter. Without the copy command will fail.
cp -a /dev/console /dev/tty1 /dev/zero /dev/mem /usr/src/initramfs/dev cp -a /sbin/v86d /usr/src/initramfs/sbin/
After you copied all the files from the v86d initramfs it is time to do the same for the fbsplash initramfs. Luckily you do not have to repeat the procedure with opening the initramfs since fbsplash has a handy helper that simply copies all its necessary files to your custom initramfs:
splash_geninitramfs --verbose --res MxN --copy /path/to/initramfs theme
And voila, you have a combined initramfs. All you need to do now is package it with the command mentioned above and you can load it during boot time with all the video and splash parameters. The parameters get “magically”” routed to wherever they need to go. (Of course you have to make sure that the theme referenced in grub.conf is part of the initramfs.)
title = Gentoo Linux root (hd0,0) kernel /boot/bzImage video=uvesafb:ywrap,mtrr:3,800x600-32@60 splash=verbose,theme:gentoo console=tty1 initrd /boot/initramfs.cpio.gz
Now the splash screen comes much sooner and hides all the useful, but ugly kernel loading code.
The problem is that while the custom initramfs does something useful, it could do more. You have a boot run level process starting 915resolution, replacing a VideoBIOS mode and then starting uvesafb when there is no reason why it should be executed so late. Why not put those things into your custom initramfs as well?
For that to work, however, you need to first statically compile 915resolution. Unfortunately, the ebuild (which you had to patch by hand) does not provide a nice “static” USE-flag. In order to do that you need to open the 915resolution-0.5.3-r3.ebuild file and edit line number 34 by adding LDFLAGS=”-s -static”. That will instruct the compiler to do a static compilation. (You can find an already edited ebuild here.)
src_compile() {
filter-flags -O -O1 -O2 -O3 -Os
emake clean
emake CFLAGS="${CFLAGS}" LDFLAGS="-s -static" || die "Compiliation failed."
}
If you do not do this your initramfs's init function will always claim it cannot find the 915resolution binary, even though it is in the initramfs's sbin folder. Now you can call emerge 915resolution as usual, which will recompile the binary - this time statically. You can still run it from the system, because we did not change anything. It just does not have any dependencies, which makes it suitable for execution in initramfs. Now copy 915resolution from /usr/sbin to your initramfs directory:
cp -a /usr/sbin/915resolution /usr/src/initramfs/sbin
What we want the initramfs to do, ideally, is the following:
915resolution and replace the mode 5c with 1024×600.unvesafb with the correct resolution.
We already took care of number 1 and 915resolution is safely in the initramfs. To run uvesafb with the correct resolution you need to modprobe it. However, since you do not yet have access to the kernel modules in the initramfs you will need to copy the uvesafb.ko module into your initramfs as well, just like 915resolution. And since modprobe looks for the modules in a particular spot, you will need to mimic that location in your initramfs.
locate uvesafb.ko # tells you where it is located on your system, i.e. /lib/modules/2.6.xx-gentoo-rxx/kernel/drivers/video/uvesafb.ko mkdir /usr/src/initramfs/lib/modules/2.6.xx-gentoo-rxx/kernel/drivers/video/ cp -a /lib/modules/2.6.xx-gentoo-rxx/kernel/drivers/video/uvesafb.ko /usr/src/initramfs/lib/modules/2.6.xx-gentoo-rxx/kernel/drivers/video/
As you can see the path is very long and what is worse, kernel version-dependent. Hence you will need to create a new path and copy the new module each time you update the kernel. (
! - internal link) Similarly all themes you intend to use need to be copied into the initramfs. Again, you mimic the file structure of your system - for fbsplash your themes are located in /etc/splash and therefore you create a folder in /usr/src/initramfs/etc/splash. Then simply copy the .cfg file for your resolution and the images it needs (in ./image sub-directory) in there and you are good to go.
Most of the heavy lifting is accomplished in the init script. Here is my final, working version:
#!/bin/busybox sh # mount proc and sys mount -t proc none /proc mount -t sysfs none /sys # mount the root file system mount -o ro /dev/sda3 /root # load 915resolution 915resolution 5c 1024 600 # start uvesafb with the native resolution modprobe uvesafb mode_option=1024x600-32 scroll=ywrap # clean up umount /proc umount /sys # boot the real thing exec switch_root /root /sbin/init
You can see where 915resolution is being called to replace the mode 5c. Then I modprobe uvesafb and set it to the proper resolution. Please not that between kernels 2.6.26 and 2.6.27 there has been a syntax change in uvesafb's parameters:
modprobe uvesafb mode=1280x800-32 scroll=ywrap # kernel <= 2.6.26 modprobe uvesafb mode_option=1280x800-32 scroll=ywrap # kernel >= 2.6.27
This init script will take care of the resolution and uvesafb - from the very start (after the kernel goes through the basic hardware detection) you will have a beautiful, full resolution 1024×600 frame buffer console. Now you could specify which theme / boot splash to load in the init script as well, however, that would require a re-packaging of the initramfs image each time you decide to change the theme. Since the re-packaging is a pain, I created my initramfs with the top five themes I thought I would use1) and select them based on the grub.conf parameter. Because Linux is magic, the theme parameter of GRUB gets routed directly to the fbsplash helpers without any help of the init script2). My final grub.conf looks like this:
# This is the grub.conf for Asus N10J-A2 notebook. # Possible themes (compiled into the InitRAM-FS) are: # KillBillTux-Grey, -Yellow, ThinkLinux, darkevilness, emergence, girltattoo, livecd-2007.0, natural_gentoo, real-life default 0 timeout 30 splashimage=(hd0,0)/boot/grub/splash.xpm.gz title Gentoo Linux 2.6.xx-rxx root (hd0,0) kernel /boot/kernel-2.6.xx-gentoo-rxx splash=silent,theme:real-life console=tty1 initrd /boot/initramfs.cpio.gz title Gentoo Linux 2.6.xx-rxx (Rescue) root (hd0,0) kernel /boot/kernel-2.6.xx-gentoo-rxx_rescue root=/dev/sda3
If you are interested you can download my complete initramfs, ready to boot, here. Just make sure that your system has klibc, v86d, splashutils, busybox, and 915resolution emerged. Furthermore, it will only work if your root directory is on /dev/sda3.
Most of the information contained here has been gathered from the Gentoo Wiki and it still provides the most complete reference for all steps described here. The articles on initramfs, as well as the How-to for ASUS Eee PC 701 are recommended reading.
! static compilation of pciutils
Dobry den! >> Pokusam sa dostat pciutils, resp. lspci, do mojho initramfs image-u, >> aby mi umoznili rozpoznat, ktory hardware je prave zapojeny. Na to, >> aby hocico fungovalo v initramfs to musi byt "statically linked". >> >> Bohuzial moj pokus o skompilovanie pciutils (na Gentoo) s >> LDFLAGS="-s -static" nepodaril, pretoze sa compiler "attempted >> static link of dynamic object `lib/libpci.so.3.0.2'". (Viem, Gentoo >> pouziva staru verziu :) ) >> >> Existuje staticka verzia lspci? Da sa vobec staticky skompileovat? >> Ak ano, co vsetko musim zmenit? To bude tim, ze Gentoo pri kompilaci explicitne pozada o dynamicke linkovani tim, ze Makefilu preda SHARED=yes. Pokud SHARED ponechate na defaultnim `no' (viz komentare v Makefile), pciutils se slinkuji staticky. Have a nice fortnight Martin `MJ' Mares <mj@ucw.cz> http://mj.ucw.cz/ Faculty of Math and Physics, Charles University, Prague, Czech Rep., Earth
/etc/splash to /usr/src/initramfs/etc/splash. Again, do not forget the -a parameter when copying. Also in order to save space simply copy only the 1024×600.cfg file and the verbose-1024×600/silent-1024×600 images.video=uvesafb:1024×600-32 parameter, as it will not be applied to the modprobe.