Linux – Automatically include N latest kernel versions in GRUB / GRUB2 menu on kernel upgrade

arch linuxbootgrub2linux-kernel

What I like about Ubuntu is that the GRUB menu always allows me to pick the latest (default) or second-latest (etc.) kernel version at boot time.

In Arch Linux, I can't do that by default. The only options are normal and fallback images, and both boot the latest kernel. How can I achieve the Ubuntu-like behavior in Arch? I use Grub and Grub2, but I guess that I wouldn't have to configure the bootloader much. It will probably include the images it finds in /boot in the menu automatically. I can be wrong, though.

So, what I need, from most to least important, is:

  1. That the new kernel image created by mkinitcpio during the upgrade doesn't overwrite the previous one;
  2. That the latest kernel is present in the bootloader menu as default option;
  3. That very old versions are excluded from the menu or hidden into "older version" menu item (not that important).

How would one go about this? Should I look into mkinitcpio config or maybe pacman config? I've actually tried looking at configuration files for both, no ideas so far.

Best Answer

See this bug: https://bugs.archlinux.org/task/16702#comment80122

And this blogpost: http://losinggeneration.homelinux.org/2009/10/16/why-arch-linuxs-kernel-upgrades-suck/

So far I haven't found a good solution, but I will update if I do.

One thing to keep in mind beyond grub, the kernel, and initrd is /usr/lib/modules/. When the linux package updates the old package deletes it's folders in /usr/lib/modules/ and the new kernel adds its new modules. If you want both kernels working, you're going to want both sets of modules. And /usr/src/ contains the kernel headers (needed to build new modules, such as the nvidia drivers), so you'll probably want to keep those, too.

The steps I guess would be something like:
1. Detect linux package is going to be upgraded.
2. Backup what it's going to delete on uninstall (/usr/src/$(uname -r), /usr/lib/modules/$(uname -r), /boot/{vmlinuz-linux,initramfs-linux.img,initramfs-linux-fallback.img})
3. Let pacman do its upgrade
4. Restore everything in 2 (probably giving a new name to the stuff in /boot
5. Edit grub or whatever.

Alternate steps (somewhat less good)
1. Let pacman update
2. Detect kernel was updated
3. from /var/cache/packman/pkg/linux-${previous_version}-pkg.tar.xz extract /usr/src/, /usr/lib/{modules,extramodules}, and /boot/vmlinuz (renaming the one in /boot, obviously)
4. run mkinitcpio with the -k option to build the old init
5. Edit grub or whatever

In this alternate method, you loose your 3rd party modules (virtual box, ATI/Nvidia, etc), but it might be something you could run from cron and automagically detect kernel updates have occured.

Related Question