Most new Linux distributions come these days with out of the box support for EFI boot (UEFI). However, if you are stuck with an ancient pc where maybe you installed Windows years ago, it would probably be on legacy BIOS mode. Moreover, GRUB, the legacy BIOS mode of Linux, is now old and has given way to UEFI based newer entrants, like systemd-boot that are used in the latest distributions of Arch, Linux Mint etc. So when we install a latest Linux distro, chances are that its systemd-boot loader has overwritten grub, and if your Windows installation happened to be on another drive altogether, then it would definitely not recognize that.
So the situation we are going to fix is:
- Existing Windows installation on /dev/sdb1 in BIOS (Legacy) mode
- New Linux installation on /dev/sda1 using systemd-bootin BIOS (Legacy) mode
- Possibly other linux/ windows installations in /dev/sdb or a third, /dev/sdc (yes, power users do like to use the choices available to them).
I faced this situation with a brand new installation of System76’s Pop OS, which is based on Ubuntu but getting some good reviews these days. To resolve the issue, I had to update grub after probing for existing OS across my drives (all of which were recognized in GParted or Parted disk utilities).
Follow the below steps to restore Windows or other OS installations, if you are in a similar situation:
1. List your partitions
$ lsblk -l
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 167.7G 0 disk
sda1 8:1 0 9.5G 0 part
sda2 8:3 0 142.9G 0 part /
sda3 8:5 0 15.3G 0 part
sdb 8:16 0 931.5G 0 disk
sdb1 8:17 0 200G 0 part
sdb2 8:18 0 200G 0 part
sdb3 8:19 0 84G 0 part
sr0 11:0 1 1024M 0 rom
cryptswap 253:0 0 15.3G 0 crypt [SWAP]
2. Identify your windows partition and mount it:
$ mkdir -p /media/user/sdb1
$ sudo mount /dev/sdb1 /media/user/sdb1
$ mkdir -p /media/user/sdb2
$ sudo mount /dev/sdb2 /media/user/sdb2
Here, sdb1 and sdb2 contain the previously installed OSes, like Windows and Linux.
(Steps 1 and 2 can also be done by simply mounting the Windows partition from File explorer: Files > Other Locations > click on the required partition among the list)
3. Install and run a utility ‘os-prober’ – it may not come with the distro – as in the case for Pop OS.
$ sudo apt-get install os-prober
$ sudo os-prober
In the output, we can see that it has picked the other OS installations across mounted drives. If the drive is not mounted, it wont search for bootloaders there, so we need to mount secondary and tertiary drives first (steps 1, 2).
4. Update good old GRUB, which systemd-boot would actually use in case of BIOS (Legacy) mode – to confirm we can check under /boot, which will have /grub as a subdirectory instead of /efi
$ sudo update-grub
Thats it*. Now restart the system to load into Grub Menu, from where we can boot into other OSes. (Curiously, Pop OS shows up as Ubuntu; probably they did not think of this use case so did not fix).
EDIT:
*In case this is a dual/ triple boot scenario with a second Linux distribution, this may or may not work always. The above procedure basically “updates” GRUB from the newest OS installed, i.e. Pop in this case. Pop is still in charge of the system GRUB after this. The previous Linux distro (not Windows) in my system was Linux Mint, which was in charge of GRUB before this (i.e. GRUB was last updated from there).
Now, some distros like Manjaro do not like being not in charge of GRUB. One issue with Manjaro is that it loads a Intel microcode kernel before the actual Linux kernel in it, and when Pop updated grub, it searched only for the Linux kernel as the file pointer, but since Manjaro expects it to be Intel microcode instead, it threw Kernel Panic on selecting the option from Pop’s GRUB. More details can be found here.
The solution to this is to put Manjaro in charge of GRUB, i.e run the os-prober from Manjaro and then update GRUB. For this to work, we first need to boot into Manjaro. When I installed Pop OS 20.04, at that time Manjaro was the previously installed OS in charge of GRUB. But it was in second hard drive, i.e. sda, so I simply changed the boot priority in BIOS and it booted into Manjaro desktop. From there, I ran the above commands and it recognized the newly installed Pop and previously installed Windows, not to mention itself as well. GRUB was updated and I was able to boot into all 3 OSes.
In case we had Manjaro in same drive as Pop OS, we would have to do this using Manjaro live USB stick/ DVD. There is an option to chroot into existing installation, from where we can run the above commands.