Grub2 Configure Dual Boot Windows on Red Hat Enterprise 7

In this Linux CentOS 7 or Red Hat Enterprise 7 we will take a look at Grub2 which is become the default boot loader on the previous mentioned distributions. We will configure a system to dual boot CentOS 7 and Windows 7. And we also look at grub2 in general, how it is setup.

Grub2 Important Files and Directories

Under the /boot directory you have two sub-directories, one for grub and one for grub2. We of course will use grub2.

# cd /boot/grub2

In this directory you’ll see a number of files and directories:

# ls -l
total 32
-rw-r--r--. 1 root root   64 Jul 22 20:27
drwxr-xr-x. 2 root root   24 Jul 22 20:27 fonts
-rw-r--r--. 1 root root 5044 Jul 23 21:23 grub.cfg
-rw-r--r--. 1 root root 1024 Jul 23 21:15 grubenv
drwxr-xr-x. 2 root root 8192 Jul 22 21:11 i386-pc
drwxr-xr-x. 2 root root 4096 Jul 22 21:11 locale
drwxr-xr-x. 3 root root   19 Jul 22 20:23 themes

If you cat the file you will see the translation between devices and grub2 device names. In this case there is one disk /dev/sda which uses the grub2 device name hd0:

# cat

# this device map was generated by anaconda
(hd0)      /dev/sda

Another important file is the grub.cfg file, which is the file where the configuration script is saved (by grub2-mkconfig, more on that later). If you cat the file you’ll see that it is a complex script (for beginners), but the important parts are in the header. If you give the following head commando, you will see the top of the file:

# head grub.cfg
# It is automatically generated by grub2-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub

### BEGIN /etc/grub.d/00_header ###

The first thing you will notice is the line “DO NOT EDIT THIS FILE”. It then explains that you need to use the grub2 template file under /etc/grub.d or the grub2 default settings file /etc/default/grub.

Default Grub Config File

We first take a look at the default grub2 config file under /etc/default. As mentioned this is where the default config settings are made such as the time before the default menu entry is booted (default is 5 seconds, see variable: GRUB_TIMEOUT).

# cat /etc/default/grub
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_CMDLINE_LINUX=" vconsole.font=latarcyrheb-sun16 crashkernel=auto  vconsole.keymap=us rhgb quiet"

So let us change the GRUB_TIMEOUT variable to 10 seconds using vi (or any other editor you like). Let’s also add a variable that is not in the default grub configuration which is: GRUB_DISABLE_LINUX_UUID=“true” and save the file. This last variable will put the absolute device names instead of UUID- i.e. /dev/sdXY. (Note this is for example purpose only, I will explain later on).

Now to activate this configuration, you will need to generate a new /boot/grub2/grub.cfg file using the tool grub2-mkconfig.


If you run the tool grub2-mkconfig you will see a lot of text (the script that is generated on the screen). A common mistake people make is to think that this will generate and write the config file to disk. This is not so! The script will only be displayed on the screen, not to disk. (To verify you could now reboot and see if the boot timeout is set to 10 seconds).

To write to disk you need to use the following command:

# grub2-mkconfig -o /boot/grub2/grub.cfg

Now the default settings should be written to disk (reboot to verify, notice the boot timeout).

With the GRUB_DISABLE_LINUX_UUID entry in the default config you’ll see something like this when you run grub2-mkconfig:

# grub2-mkconfig -o /boot/grub2/grub.cfg 
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-123.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-123.el7.x86_64.img
Found linux image: /boot/vmlinuz-3.10.0-123.4.2.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-123.4.2.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-957d0004a0aa4a6080dd929ffd92555c
Found initrd image: /boot/initramfs-0-rescue-957d0004a0aa4a6080dd929ffd92555c.img

Now remove the line from the default config (remember it was for demonstration purpose only, more on that later) and save the file. Rerun the configure commando:

# grub2-mkconfig -o /boot/grub2/grub.cfg 
Generating grub configuration file ...
  No device found for PV 84ARqO-Fhcl-dNC0-dVa0-7EpR-Nl9K-pzdyQR.
  No device found for PV 84ARqO-Fhcl-dNC0-dVa0-7EpR-Nl9K-pzdyQR.
  No device found for PV 84ARqO-Fhcl-dNC0-dVa0-7EpR-Nl9K-pzdyQR.
  No device found for PV 84ARqO-Fhcl-dNC0-dVa0-7EpR-Nl9K-pzdyQR.
Found linux image: /boot/vmlinuz-3.10.0-123.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-123.el7.x86_64.img
Found linux image: /boot/vmlinuz-3.10.0-123.4.2.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-123.4.2.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-957d0004a0aa4a6080dd929ffd92555c
Found initrd image: /boot/initramfs-0-rescue-957d0004a0aa4a6080dd929ffd92555c.img

Note: ignore the “No device found for PV..” message, but as you can see UUID’s are now used.

For beginners the UUID’s can be very confusing because people read the absolute device notation much easier for instance /dev/sda1. But the UUID is much saver to use, because if you re-arrange partitions in partition table (for example insert/delete partitions) and partition numbers changed- grub can’t find the kernel to boot. If you use UUID, even when you re-arranging the partitions things won’t break. That’s why UUID is preferred, but I agree that it much harder to read. (So leave out the variable mentioned earlier).

Template /etc/grub.d Directory

Let’s goto the /etc/grub.d directory and see what is done in this directory.

# ls -l
total 68
-rwxr-xr-x. 1 root root  8698 Jun 30 18:16 00_header
-rwxr-xr-x. 1 root root  9517 Jun 30 18:16 10_linux
-rwxr-xr-x. 1 root root 10275 Jun 30 18:16 20_linux_xen
-rwxr-xr-x. 1 root root  2559 Jun 30 18:16 20_ppc_terminfo
-rwxr-xr-x. 1 root root 11110 Jun 30 18:16 30_os-prober
-rwxr-xr-x. 1 root root   214 Jul 22 21:55 40_custom
-rwxr-xr-x. 1 root root   216 Jun 30 18:16 41_custom

You see that the directory contains different script (that need to be executable, note that for later!) that are used to generate the /boot/grub2/grub.cfg file by the grub2-mkconfig POSIX shell script. These template are used in order (00 to 41). You may edit these files, but you have to know what you are doing.

Dual Boot Windows 7 and CentOS 7

If you reach it until here, you should know the basics of grub2 at least enough to start editing (and maybe break things 😉 )

In our case we have multiple disks on the machine but we have installed Windows and CentOS on the same SSD disk.

# fdisk -l |grep "Disk /dev"
Disk /dev/sda: 120.0 GB, 120034123776 bytes, 234441648 sectors
Disk /dev/sde: 3000.6 GB, 3000592982016 bytes, 5860533168 sectors
Disk /dev/sdb: 3000.6 GB, 3000592982016 bytes, 5860533168 sectors
Disk /dev/sdc: 3000.6 GB, 3000592982016 bytes, 5860533168 sectors
Disk /dev/sdd: 3000.6 GB, 3000592982016 bytes, 5860533168 sectors
Disk /dev/mapper/centos-swap: 8396 MB, 8396996608 bytes, 16400384 sectors
Disk /dev/mapper/centos-root: 35.9 GB, 35907436544 bytes, 70131712 sectors
Disk /dev/mapper/centos-home: 17.5 GB, 17527996416 bytes, 34234368 sectors

We first installed Windows 7 and used half of the first SSD disk and left the rest unpartitioned. Then we installed CentOS 7 (or Red Hat Enterprise 7) and used the other half of the disk. If we give the command blkid we see the following layout:

# blkid
/dev/block/253:0: UUID="ba700a61-092c-4042-a134-2876ae49e741" TYPE="swap" 
/dev/sda1: LABEL="Door systeem gereserveerd" UUID="76449D01449CC571" TYPE="ntfs" 
/dev/sda2: UUID="944A9D9F4A9D7F24" TYPE="ntfs" 
/dev/sda3: UUID="5abb20e8-9493-46bc-89bd-887452403619" TYPE="xfs" 
/dev/sda5: UUID="uJpBkk-ugcH-xrOR-DIZu-eJnJ-0g6a-ImDwo2" TYPE="LVM2_member" 
/dev/dm-2: UUID="5432cf99-6222-486b-9e21-f9dd7a663b48" TYPE="xfs" 
/dev/dm-1: UUID="57f5fade-253b-442d-be1a-d50906edb3d6" TYPE="xfs"

As you can see our Windows 7 partition is on /dev/sda1, which is hd0,1 in Grub2. Note that sda disk is 0 and a sdb is 1. The partition however start with 1 for sda1 or sdb1 for a second disk. (Different from grub, which had the first partition on hd0,0) The linux partition is in our case /dev/sda3, which is in grub2 hd0,3. But if you look in the generated /boot/grub2/grub.cfg file:

# cat /boot/grub2/grub.cfg |grep msdos
	insmod part_msdos 
	set root='hd0,msdos3'
	  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos3 --hint-efi=hd0,msdos3 --hint-baremetal=ahci0,msdos3 --hint='hd0,msdos3'  76f0fe64-3654-4dc2-b914-45d8a78d4829

you’ll see that the following notation is generated: ‘hd0,msdos3’ (which is sda3).

So now let’s add a template for Windows 7. You can do this in 40_custom, but we like to add it between 10 and 20. So vi /etc/grub.d/15_windows7:

#! /bin/sh -e
echo "Adding Windows 7" >&2
cat <<EOF
menuentry "Windows 7" {
set root=(hd0,1)
chainloader +1

Note: make sure the script has executable rights (if not use: chmod +x /etc/grub.d/15_windows7). If the script has no executable rights the grub2-mkconfig command won’t pickup the script (you won’t see “Adding Windows 7” when you run grub2-mkconfig -o /boot/grub2/grub.cfg)
Note2: sometimes when the script is cut and paste from the website the ” are messed up. In that case you get an error running grub2-mkconfig. In that case just retype the ” in the script and rerun grub2-mkconfig.

You can see we add (hd0,1) which is /dev/sda1 to boot Windows (this is where the boot manager of windows resides). Now run the grub2-mkconfig -o /boot/grub2/grub.cfg to generate and save a new config file. Reboot and select your windows partition to boot (of course you should enter your disk, retry if windows won’t boot, because you maybe have selected the wrong disk). The grub2 menu should look like something like this:

CentOS 7 
CentOS 7 Rescue
Windows 7

The first entry is selected at default. What if we want the Windows 7 partition to be the default to boot.


With the command grub2-set-default you can set the default selected menu-entry at boot time. So in this case we want Windows 7 to be the default. Run the following command and reboot:

grub2-set-default 2

Note: we start counting by zero and not one. So zero is CentOS 7 and so on.

You’ll see during booting that Windows 7 is highlighted by default. Rerun the command after booting to Linux, but now with 0 for CentOS 7 as default.

That’s all for this tutorial. If you made it to here you should now have a basic knowledge of grub2, at least to make minor changes to the configuration. Good luck in your grub2 endeavours.

This entry was posted in Linux Install (Tooling). You can follow any responses to this entry through the RSS 2.0 feed. You can trackback from your own site. Tweet This! Tweet This! or use to share this post with others.

There are currently 24 responses to “Grub2 Configure Dual Boot Windows on Red Hat Enterprise 7”

Why not let us know what you think by adding your own comment!

  1. Tarmizi Hamid on November 30th, 2014:

    Dear Bro,

    Thanks for writing, it’s very helpful for me 🙂


    Tarmizi H

  2. Saga on July 21st, 2015:

    Very helpful; many thanks!


  3. Richard on August 10th, 2015:

    Worked perfectly with RHEL 7! Thanks!

  4. Keith on October 14th, 2015:

    Worked well.
    Frustrating that OS Prober does not seem to do well with Cent OS, though no issue with Ubunto finding the Windows 7/8/10 partion.

  5. Naresh Kumar on October 23rd, 2015:

    thank your this is help full for me.

  6. Tony on October 23rd, 2015:

    I thought I trashed my windows partition when I installed Centos7. This got me working again! Thank you.

  7. Dele on January 12th, 2016:

    you saved the day. i’ve been trying to get it to work for almost a day

  8. Levy on February 6th, 2016:

    This worked perfectly for Windows 10 and CentOS 7. You saved my day. Thank you!!!

  9. datta on March 29th, 2016:

    Thank you
    Worked fine for getting windows back but cant getting option to dual boot ie only windows starts directly no option for booting RHEL 7

  10. Joanne Thomas on March 31st, 2016:

    Perfect! Just the help I needed. Thanks for making this page

  11. Dileep Jose on April 9th, 2016:

    Well written doument. Work for me
    Thank you sir

  12. Mark Ma on December 6th, 2016:

    Confirmed works with RHEL 7.2 and Windows Server 2008 R2. Thank you.

  13. CJ on March 4th, 2017:

    This was a very helpful page. I was trying to get my windows drive back (Ya i know but sadly I need it for some apps) and came across this info.
    Great step by step.

    Thank you for posting it.

  14. Nahar on March 25th, 2017:

    Its done… Done with rhel 7 and win 7…thanx a lot….

  15. Timmy on April 4th, 2017:

    This was the most helpful and simple resolution I have ever had from the Linux Help Tools. Well done!!

  16. Dan on June 7th, 2017:

    Thank you so much. This just saved me a lot of research. I found your page, followed the instructions and it is working with Windows 7 64bit and Red Hat v7.2 Enterprise Workstation.

    You are the best!

  17. Martin on August 29th, 2017:

    Thanks – after quite some searching this was very helpful!

  18. Mike on October 2nd, 2017:

    Thank you, this worked for me with
    Windows 10 Pro (10.0.14393) and Redhat 7.3 (RHEL)

  19. Abhishek kumar on November 19th, 2017:

    Thanks, this work for me on rhel 7.3

  20. Sam on March 31st, 2018:

    Perfect solution for Dual boot.

  21. David Y on June 22nd, 2018:

    I have a UEFI computer. The file is /etc/grub2-efi.cfg
    I have another second SSD in the computer, with CentOS 7 installed. How can I add a menuentry to the boot options?

  22. Rajesh on January 10th, 2019:

    Its working. Thanks a lot! Though I didnt get the concept behind this What we did.But followed the steps n ots working now

  23. Kamesh K on November 12th, 2019:

    Super Bro!!!

  24. DoraM on September 15th, 2021:

    Thank you, this worked for me with
    Windows 10 and CentOS 7

Leave a Reply: