Skip to content. | Skip to navigation

Navigation

You are here: Home / Support / Guides / Tools / Multiboot USB / Dual Booting Repair

Personal tools

Multiboot USB

Booting from multiple ISOs on one USB

Dual Booting Repair

Lost Windows

Let's suppose "a friend" has been a bit casual when they installed Linux on a nominally Windows box. If they weren't paying attention then they may have recreated the all important EFI System Partition (the FAT32 one). The problem isn't that the Windows filesystems have gone but that the means to boot to them has gone.

The underlying problem is that the Windows boot manager, bootmgfw.efi and its critical Boot Configuration database, BCD have gone. These two are the Windows equivalents of our grubx64.efi and (I guess) grub.cfg. Don't forget we encoded in grub.cfg the set of filesystems we want to look at and the specific kernels we want to boot and the order in which we want to try booting them.

With a bit of luck, though, we can get them back.

efibootmgr

efiboomgr can tell us a few things. First up the basics:

# efibootmgr
BootCurrent: 0001
Timeout: 2 seconds
BootOrder: 0001,0000
Boot0000* Windows Boot Manager
Boot0001* CentOS Linux

Then a bit more:

# efibootmgr -v
BootCurrent: 0001
Timeout: 2 seconds
BootOrder: 0001,0000
Boot0000* Windows Boot Manager HD(1,800,32000,aff3bcb2-74d3-464f-a4f0-5e378b3f1d86)File(\EFI\Microsoft\Boot\bootmgfw.efi)WINDOWS.........x...B.C.D.O.B.J.E.C.T.=.{.9.d.e.a.8.6.2.c.-.5.c.d.d.-.4.e.7.0.-.a.c.c.1.-.f.3.2.b.3.4.4.d.4.7.9.5.}...-...............
Boot0001* CentOS Linux HD(1,800,32000,aff3bcb2-74d3-464f-a4f0-5e378b3f1d86)File(\EFI\centos\shim.efi)

Hiding in there we can see:

  • HD(1,800,32000,aff3bcb2-74d3-464f-a4f0-5e378b3f1d86) and a similar entry against CentOS -- not unreasonably both are on the same disk
  • File(\EFI\Microsoft\Boot\bootmgfw.efi) for Windows and
  • File(\EFI\centos\shim.efi) for CentOS

Lets see if we can match those things up with anything:

# lsblk -f
NAME        FSTYPE      LABEL       UUID                                   MOUNTPOINT
nvme0n1
├─nvme0n1p5 ntfs        Image       8EC82E94C82E7B1B
├─nvme0n1p3 ntfs        OS          2E220A48220A160D
├─nvme0n1p1 vfat                    E228-FE41                              /boot/efi
├─nvme0n1p8 LVM2_member             md41Vj-sXY6-3dTI-AOLG-c7iZ-MHu2-MxlvDr
│ ├─cl-swap swap                    219bd38f-2b01-4772-9384-e830015ad7a8   [SWAP]
│ └─cl-root xfs                     147d107c-7300-42a6-8485-65f08ac52ffe   /
├─nvme0n1p6 ntfs        DELLSUPPORT E496A72096A6F1EA
├─nvme0n1p4 ntfs        WINRETOOLS  4EEC2DA8EC2D8B73
├─nvme0n1p2
└─nvme0n1p7 xfs                     9864704c-903f-4a5f-a520-77a461b9c3a7   /boot

Hmm, no sign of the disk but we might expect to see the .efi files in the ESP:

# cd /boot/efi/
# find EFI -name \*.efi
EFI/centos/gcdx64.efi
EFI/centos/grubx64.efi
EFI/centos/MokManager.efi
EFI/centos/shim-centos.efi
EFI/centos/shim.efi
EFI/BOOT/fallback.efi

Oh, no Microsoft directory for a start.

Back to that missing disk, something to do with aff3bcb2-74d3-464f-a4f0-5e378b3f1d86. blkid might help us:

# blkid
/dev/nvme0n1p1: LABEL="SYSTEM" UUID="5247-E7D0" TYPE="vfat" PARTLABEL="EFI System Partition" PARTUUID="aff3bcb2-74d3-464f-a4f0-5e378b3f1d86"
/dev/nvme0n1p3: UUID="B84A58484A580592" TYPE="ntfs" PARTLABEL="Basic data partition" PARTUUID="d641a8bd-8a3c-4945-a463-b9ea0115cb8a"
/dev/nvme0n1p4: LABEL="Windows RE tools" UUID="425C4D7C5C4D6C2B" TYPE="ntfs" PARTLABEL="Basic data partition" PARTUUID="16f5a9f1-5371-49d0-a13b-0d86ac25ec45"
/dev/nvme0n1p5: UUID="9cf790ff-c2bb-42c2-9289-c997ab7707a7" TYPE="xfs" PARTUUID="4ea0e113-4803-411f-82d9-9c2471f0ffd5"
/dev/nvme0n1p6: UUID="L2CeRv-Llci-6Bus-K0E1-uh2f-zOlk-RqPQmn" TYPE="LVM2_member" PARTUUID="a7f58fd7-401c-475b-b655-f9a113264f36"
/dev/mapper/cl-root: UUID="ba7db830-d2be-4b58-a2bd-78a870d9ce9c" TYPE="xfs"
/dev/mapper/cl-swap: UUID="1f468b0c-aec9-4f9c-8c71-8702847da9b4" TYPE="swap"
/dev/nvme0n1: PTTYPE="gpt"
/dev/nvme0n1p2: PARTLABEL="Microsoft reserved partition" PARTUUID="b3871e4c-3c22-4a8e-8b20-354767c37ee5"

And there it is on the first line. Not hugely surprisingly, the HD(...) is referring to the ESP partition.

The blkid output is slightly hard to read and reading the man page for lsblk means we can get a much more readable version of the same:

# lsblk -o NAME,FSTYPE,UUID,PARTUUID
NAME        FSTYPE      UUID                                   PARTUUID
nvme0n1
├─nvme0n1p5 xfs         9cf790ff-c2bb-42c2-9289-c997ab7707a7   4ea0e113-4803-411f-82d9-9c2471f0ffd5
├─nvme0n1p3 ntfs        B84A58484A580592                       d641a8bd-8a3c-4945-a463-b9ea0115cb8a
├─nvme0n1p1 vfat        5247-E7D0                              aff3bcb2-74d3-464f-a4f0-5e378b3f1d86
├─nvme0n1p6 LVM2_member L2CeRv-Llci-6Bus-K0E1-uh2f-zOlk-RqPQmn a7f58fd7-401c-475b-b655-f9a113264f36
│ ├─cl-swap swap        1f468b0c-aec9-4f9c-8c71-8702847da9b4
│ └─cl-root xfs         ba7db830-d2be-4b58-a2bd-78a870d9ce9c
├─nvme0n1p4 ntfs        425C4D7C5C4D6C2B                       16f5a9f1-5371-49d0-a13b-0d86ac25ec45
└─nvme0n1p2                                                    b3871e4c-3c22-4a8e-8b20-354767c37ee5

Here, UUID is the filesystem's UUID and PARTUUID is the partition's UUID.

Luckily for us, Windows keeps backups of the files we need -- not perfect but enough for us to boot. We can find them on the ntfs OS partition.

You may need to install the ntfs drivers:

yum install ntfsprogs

Then you can mount the partition and go hunting for the bootmgfw.efi from the output of efibootmgr -v above:

# mount /dev/nvme0n1p3 /mnt
# cd /mnt
# find . -name bootmgfw.efi
./Windows/Boot/EFI/bootmgfw.efi
./Windows/Logs/PBR/Rollback/EFI/Microsoft/Boot/bootmgfw.efi
./Windows/Panther/Rollback/EFI/Microsoft/Boot/bootmgfw.efi
./Windows/WinSxS/amd64_microsoft-windows-b..ore-bootmanager-efi_31bf3856ad364e35_10.0.14393.447_none_c15aea503a4878cc/bootmgfw.efi
./Windows/WinSxS/amd64_microsoft-windows-b..ore-bootmanager-efi_31bf3856ad364e35_10.0.14393.0_none_b4f55452b3127f7f/bootmgfw.efi

Rummaging around on the Intertubes, it seems that bootmgfw.efi is more or less unchanged across the recent Windows releases (8, 8.1 and 10).

And the BCD file?

# find . -name BCD -ls
 30150   16 -rwxrwxrwx   2 root     root        16384 Jul 16  2016 ./Windows/Boot/DVD/EFI/BCD
 30154   16 -rwxrwxrwx   2 root     root        16384 Jul 16  2016 ./Windows/Boot/DVD/PCAT/BCD
   321   32 -rwxrwxrwx   1 root     root        32768 Jan 14 08:24 ./Windows/Logs/PBR/Rollback/EFI/Microsoft/Boot/BCD
  1539   12 -rwxrwxrwx   1 root     root        32768 Jan 14 08:24 ./Windows/Panther/Rollback/EFI/Microsoft/Boot/BCD
 30150   16 -rwxrwxrwx   2 root     root        16384 Jul 16  2016 ./Windows/WinSxS/amd64_microsoft-windows-b..environment-dvd-efi_31bf3856ad364e35_10.0.14393.0_none_02bc02d09b35c16a/BCD
 30154   16 -rwxrwxrwx   2 root     root        16384 Jul 16  2016 ./Windows/WinSxS/amd64_microsoft-windows-b..nvironment-dvd-pcat_31bf3856ad364e35_10.0.14393.0_none_c78c3cde47314e28/BCD

There appears to be a recent enough one in Windows/Logs/PBR/Rollback/EFI/Microsoft/Boot that lines up with the last time Windows organised itself.

Put the lot together and we need to copy those files into the current ESP:

cd /boot/efi
mkdir -p EFI/Microsoft/Boot
cp /mnt/Windows/Boot/EFI/bootmgfw.efi EFI/Microsoft/Boot
cp /mnt/Windows/Panther/Rollback/EFI/Microsoft/Boot/BCD EFI/Microsoft/Boot

Warning

That should be enough to allow you to select Windows Boot Manager from the BIOS Boot Selection Dialog (F12 during BIOS startup).

You may be prompted then to Repair your Windows installation after which the EFI/Microsoft tree will be much more populated.

Of course, you may need to chainload the Windows Boot Manager in grub.cfg (see the previous article on Dual Booting).

Wrong Linux

You might be running CentOS but fancy (require) the latest kernel from, say, the ELRepo people. The problem now is that the stock CentOS and ELRepo repositories are competing against one another to update GRUB when the latest kernel in each repo comes out. Every now and again it defaults to the wrong one (wrong being CentOS, presumably).

The way it hangs together is a little convoluted. First up is /etc/default/grub:

# cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet"
GRUB_DISABLE_RECOVERY="true"

If GRUB_DEFAULT has the value saved then we need to look in the ESP for grubenv:

# find /boot/efi/EFI -name grubenv
/boot/efi/EFI/centos/grubenv

# ls -l /boot/efi/EFI/centos/grubenv
-rwx------. 1 root root 1024 Feb 18 18:49 /boot/efi/EFI/centos/grubenv

which is a fixed size(?) text file containing some key value pairs:

# cat /boot/efi/EFI/centos/grubenv
# GRUB Environment Block
saved_entry=CentOS Linux (3.10.0-514.el7.x86_64) 7 (Core)
#################[...]

grub.cfg has some simple code to access and manipulate these values, for example:

if [ -s $prefix/grubenv ]; then
  load_env
fi
if [ "${next_entry}" ] ; then
   set default="${next_entry}"
   set next_entry=
   save_env next_entry
   set boot_once=true
else
   set default="${saved_entry}"
fi

What values can we set? You can use either a menuentry index or the menuentry string from grub.cfg. Indexes must be a bit risky in the face of upgrades (or manual edits) especially when we can refer to specific strings.

Let's assume that the ELRepo update will give us the new shiny kernel and that we only have to manage things when CentOS resets us back to an old kernel.

grub2-editenv manipulates grubenv (albeit in an inconsistent fashion as list doesn't require a FILENAME argument):

# grub2-editenv list
saved_entry=CentOS Linux (3.10.0-514.el7.x86_64) 7 (Core)

Which one do we want?

# awk -F\' '/^menuentry/ {print $2}' /boot/efi/EFI/centos/grub.cfg
CentOS Linux (4.9.10-1.el7.elrepo.x86_64) 7 (Core)
CentOS Linux (3.10.0-514.el7.x86_64) 7 (Core)
CentOS Linux (0-rescue-fc3b3b7819ce48b59374e39a939ad571) 7 (Core)
Windows Boot Manager (on /dev/nvme0n1p1)

any of the above!

# grub2-editenv /boot/efi/EFI/centos/grubenv set saved_entry='CentOS Linux (4.9.10-1.el7.elrepo.x86_64) 7 (Core)'

# grub2-editenv list
saved_entry=CentOS Linux (4.9.10-1.el7.elrepo.x86_64) 7 (Core)

The proof is in the pudding, of course. Only a reboot will demonstrate the truth of the matter.

Document Actions