Dual boot windows on second harddrive, UEFI/GPT system

31,354

I'm going use the term BIOS below when referring to concepts that are the same for both newer UEFI systems and traditional BIOS systems, since while this is a UEFI oriented question, talking about the "BIOS" jibes better with, e.g., GRUB documentation, and "BIOS/UEFI" is too clunky. GRUB (actually, GRUB 2 — this is often used ambiguously) is the bootloader installed by linux and used to dual boot Windows.

First, a word about drive order and boot order. Drive order refers to the order in which the drives are physically connected to the bus on the motherboard (first drive, second drive, etc.); this information is reported by the BIOS. Boot order refers to the sequence in which the BIOS checks for a bootable drive. This is not necessarily the same as the drive order, and is usually configurable via the BIOS set-up screen. Drive order should not be configurable or affected by boot order, since that would be a very OS unfriendly thing to do (but in theory an obtuse BIOS could). Also, if you unplug the first drive, the second drive will likely become the first one. We are going to use UUIDs in configuring the boot loader to try and avoid issues such as this (contemporary linux installers also do this).

The ideal way to get what you want is to install linux onto the second drive in terms of drive order and then select it first in terms of boot order using the UEFI set-up. An added advantage of this is that you can then use the BIOS/UEFI boot order to select the windows drive and bypass grub if you want. The reason I recommend linux on the second drive is because GRUB must "chainload" the Windows native bootloader, and the windows bootloader always assumes it is on the first drive. There is a way to trick it, however, if you prefer or need it the other way around.

Hopefully, you can just go ahead and use a live CD or whatever and get this done using the GUI installer. Not all installers are created equal, however, and if this gets screwed up and you are left with problems such as:

  1. I installed linux onto the first disk and now I can't boot windows, or

  2. I installed linux onto the second disk, but using the first disk for the bootloader, and now I can't boot anything!

Then keep reading. In the second case, you should first try and re-install linux onto the second disk, and this time make sure that's where the bootloader goes. The easiest and most foolproof way to do that would be to temporarily remove the Windows drive from the machine, since we are going to assume there is nothing extra installed on it, regardless of drive order.

Once you have linux installed and you've made sure it can boot, plug the Windows drive back in (if you removed it — and remember, we ideally want it first in terms of drive order, and the second drive first in terms of boot order) and proceed to the next step.

Accessing the GRUB configuration

Boot linux, open a terminal, and

> su root

You will be asked for root's password. From this point forward, you are the superuser in that terminal (to check, try whoami), so do not do anything stupid. However, you are still a normal user in the GUI, and since we will be editing a text file, if you prefer a GUI editor we will have to temporarily change the ownership of that file and the directory it is in:

> chown -R yourusername /etc/grub.d/

If you get "Operation not permitted", you did not su properly. If you get chown: invalid user: ‘yourusername’, you took the last command too literally.

You can now navigate to /etc/grub.d in your filebrowser and look for a file called 40_custom. It should look like this:

#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.

If you can't find it, in the root terminal enter the following commands:

> touch /etc/grub.d/40_custom
> chmod 755 /etc/grub.d/40_custom
> chown yourusername /etc/grub.d/40_custom

Open it in your text editor, copy paste the part above (starting w/ #!/bin/sh) and on to the next step.

Adding a Windows boot option

Copy-paste this in with the text editor at the end of the file:

menuentry "MS Windows" {
        insmod part_gpt
        insmod search_fs_uuid
        insmod ntfs
        insmod chain
}

This is list of modules GRUB will need to get things done (ntfs may be superfluous, but shouldn't hurt anything either). Note that this is an incomplete entry — we need to add some crucial commands.

Finding the Windows Second Stage Bootloader

Your linux install has probably automounted your Windows partition and you should be able to find it in a file browser. If not, figure out a way to make it so (if you are not sure how, ask a question on this site). Once that's done, we need to know the mount point -- this should be obvious in the file browser, e.g. /media/ASDF23SF23/. To save some typing, we're going put that into a shell variable:

win="/whatever/the/path/is"

There should be no spaces on either side of the equals sign. Do not include any elements of a Windows path here. This should point to the top level folder on the Windows partition. Now:

cd $win
find . -name bootmgfw.efi

This could take a few minutes if you have a big partition, but most likely the first thing it spits out is what we are looking for; there may be further references in the filesystem containing long gobbledygook strings — those aren't it. Use Ctrl-c to stop the find once you see something short and simple like ./Windows/Boot/EFI/bootmgfw.efi or ./EFI/HP/boot/bootmgfw.efi.

Except for the . at the beginning, remember this path for later; you can copy it into your text editor on a blank line at the bottom, since we will be using it there. If you want to go back to your previous directory now, use cd -, although it does not matter where you are in the shell from here on forward.

Setting the Right Parameters

GRUB needs to be able to find and hand off the boot process to the second stage Windows bootloader. We already have the path on the Windows partition, but we also need some parameters to tell GRUB where that partition is. There should be a tool installed on your system called grub-probe or (on, e.g., Fedora) grub2-probe. Type grub and then hit Tab two or three times; you should see a list including one or the other.

> grub-probe --target=hints_string $win

You should see a string such as:

--hint-bios=hd1,msdos1 --hint-efi=hd1,msdos1 --hint-baremetal=ahci1,msdos1

Go back to the text editor with the GRUB configuration in it and add a line after all the insmod commands (but before the closing curly brace) so it looks like:

    insmod chain
    search --fs-uuid --set=root [the complete "hint bios" string]
}

Don't break that line or allow your text editor to do so. It may wrap around in the display — an easy way to tell the difference is to set line numbering on. Next:

> grub-probe --target=fs_uuid $win

This should return a shorter string of letters, numbers, and possible dashes such as "123A456B789X6X" or "b942fb5c-2573-4222-acc8-bbb883f19043". Add that to the end of the search --fs-uuid line after the hint bios string, separated with a space.


Next, if (and only if) Windows is on the second drive in terms of drive order, add a line after the search --fs-uuid line:

    drivemap -s hd0 hd1

This is "the trick" mentioned earlier. Note it is not guaranteed to work but it does not hurt to try.


Finally, the last line should be:

    chainloader (${root})[the Windows path to the bootloader]
}

Just to be clear, for example:

    chainloader (${root})/Windows/Boot/EFI/bootmgfw.efi

That's it. Save the file and check in a file browser to make sure it really has been saved and looks the way it should.

Add the New Menu Option to GRUB

This is done with a tool called grub-mkconfig or grub2-mkconfig; it will have been in that list you found with Tab earlier. You may also have a a command called update-grub. To check for that, just type it in the root terminal. If you get "command not found", you need to use grub-mkconfig directly. If not (including getting a longer error), you've just set the configuration and can skim down a bit.

To use grub-mkconfig directly, we first need to find grub.cfg:

> find /boot -name grub.cfg

This will probably be /boot/grub/grub.cfg or /boot/grub2/grub.cfg.

> grub-mkconfig -o /boot/grub/grub.cfg

update-grub will automatically scan the configuration for errors. grub-mkconfig will not, but it is important to do so because it's much easier to deal with them now than when you try to boot the machine. For this, use grub-script-check (or grub2-script-check):

> grub-script-check /boot/grub/grub.cfg

If this (or update-grub) produces an error indicating a line number, that's the line number in grub.cfg, but you need to fix the corresponding part in /etc/grub.d/40_custom (the file in your text editor). You may need to be root just to look at the former file though, so try less /boot/grub/grub.cfg in the terminal, hit :, and enter the line number. You should see your menu entry. Find the typo, correct it in the text editor, and run update-grub or grub-mkconfig again.

When you are done you can close the text editor and type exit in the terminal to leave superuser mode.

Reboot!

When you get to the grub menu, scroll down quickly (before the timeout expires, usually 5 seconds) to the "Windows" option and test it. If you get a text message error from grub, something is wrong with the configuration. If you get an error message from Windows, that problem is between you and Microsoft. Don't worry, however, your Windows drive has not been modified and you will be able to boot directly into it by putting it first (in terms of boot order) via the BIOS set-up.

When you return to linux again, return the ownership of the /etc/grub.d directory and it's contents to their original state:

sudo chmod 755 /etc/grub.d/40_custom

References

Share:
31,354

Related videos on Youtube

goldilocks
Author by

goldilocks

Gentleman programmer and linux enthusiast; raised by bears. o_O? "You are lost in the Real." (Baudrillard) http://cognitivedissonance.ca/cogware/

Updated on September 18, 2022

Comments

  • goldilocks
    goldilocks almost 2 years

    I'd like to install linux, but I don't want to risk damaging my current windows installation as I have heard a lot of horror stories. Fortunately, I have an extra hard drive. Can I install linux onto that and then dual boot windows without having to modify the windows drive?

    Also, I have a UEFI "BIOS" and the windows drive is in GPT format.

  • Milind R
    Milind R almost 10 years
    The technically correct term that you're looking for, which is also not clunky, is firmware, which can present itself either as BIOS or as UEFI.
  • Kylotan
    Kylotan over 9 years
    Unfortunately firmware also has a much more general meaning in that it refers to any software that is embedded into hardware.
  • FlogFR
    FlogFR about 9 years
    on my desktop, "chain" is unfound as a command while booting, but it's chainloader in the 40_custom file I need to write. let me know if this is normal
  • sobek
    sobek about 9 years
    Very nice! However when i try this, my Windows 8 install will not appear as an entry in grub2. I've fixed all syntax errors and the grub.cfg file is created without errors. Also please note that there is a syntax error when chainload is first mentioned: chainload $({root}) should be chainload (${root}) (i can't edit it because it's too small of a change).
  • goldilocks
    goldilocks about 9 years
    @sobek Thanks for that -- corrected. If you've added something to a file in /etc/grub.d and it is not being added when you generate the configuration, something weird is going on. If you run grub-mkconfig without -o it spits to standard out, that might help confirm or deny that your additions are being processed.
  • sobek
    sobek about 9 years
    I'm starting to feel a bit stupid now as i realized my Windows partition must be MBR based, not GPT. Sorry i wasted your time.
  • Sardathrion - against SE abuse
    Sardathrion - against SE abuse over 8 years
    This looked so promising... I am getting ntfs,.mod not found errors when I try it. Also, the chainload should be chainloader for Fedora 23. More details here if that helps.
  • goldilocks
    goldilocks over 8 years
    @Sardathrion Thx, I think the "chainload" thing was just a typo.
  • tomasb
    tomasb over 7 years
    @goldilocks the drivemap command throws error like unknown command at boot time, have any tip around that? also I wonder how can the windows path (mount point in linux) work at boot time, there is another error for me related to it, no windows boot found at boot time, uuid not working too, have error no device 'XXXXXX' found, using Mint 18
  • goldilocks
    goldilocks over 7 years
    @tomasb I suggest you ask another question. This was written more than two years ago, and while I recall putting a lot of effort into it and believe it contains some useful information that has helped has people some people since then, I'm actually not much of a windows user and currently don't have any UEFI/GPT systems with it installed.
  • tomasb
    tomasb over 7 years
    @goldilocks yes it is very useful, perfect starting point for me makes me at least understand a little, just a pity there is no working solution around nowadays but no problem a solution will occur sooner or later thank you :)
  • David Murdoch
    David Murdoch over 5 years
    grub-probe --target=fs_uuid $win returns: grub-probe: warning unknown device type nvme1n1 followed by a . on a new line