Multiboot 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