Problem:
After installing Linux (Tried CentOS7 and Debian 9.5) on a UEFI machine, pxegrub2 chainload to local disk fails.
Expected outcome:
search --file --no-floppy --set=root /EFI/BOOT/BOOTX64.EFI should result in a (hd?,*) device. Currently, $root is empty
Foreman and Proxy versions:
CentOS7: 1.14.3-1
Foreman and Proxy plugin versions:
CentOS7: 1.14.3-1
Other relevant data:
Steps to reproduce:
Configure UEFI on target machine
Install Linux on target machine (Debian 9.5/CentOS 7)
boot target using Network
Iβve compared the pxegrub2_chainload template with the 1.19 version of foreman, they use the same mechanism.
I noticed that the grub search command does not return the disk device on which efi installation exists. As a workaround, I tried this:
menuentry "BTH: Chainload Grub2 EFI from ESP" {
insmod part_gpt
insmod fat
insmod chain
echo Chainloading Grub2 EFI from ESP, available devices:
for efi in (*,gpt*)/efi/*/*.efi (*,gpt*)/efi/*/*/*.efi (*,gpt*)/*.efi (*,gpt*)/*/*.efi ; do
regexp --set=1:efi_device '^\((.*)\)/' "${efi}"
if [ -e "${efi}" ]; then
echo "Found efi boot on ${efi} on device ${efi_device}. Attempting efi boot."
sleep 5
root=${efi_device}
chainloader "${efi}"
fi
done
}
Has anyone run into this problem?
lzap
October 8, 2018, 3:11pm
#2
Our template assumes you only have your OS installed on the first disk (at least ESP is there).
Not sure where did you get your snippet from, this is our version:
<%#
kind: snippet
name: pxegrub2_chainload
model: ProvisioningTemplate
snippet: true
%>
<%
paths = ["fedora", "redhat", "centos", "debian", "ubuntu", "sles", "opensuse", "Microsoft", "EFI"]
-%>
menuentry 'Chainload Grub2 EFI from ESP' --id local {
unset root
echo Chainloading Grub2 EFI from ESP, available devices:
ls
echo -n "Probing ESP partition ... "
search --file --no-floppy --set=root /EFI/BOOT/BOOTX64.EFI
echo found $root
sleep 2
if [ -f ($root)/EFI/BOOT/grubx64.efi ]; then
chainloader ($root)/EFI/BOOT/grubx64.efi
<% paths.each do |path| %>
This file has been truncated. show original
Iβm using the same snippet as youβve posted. The OS is deployed on the first available disk. However, the output of the echo found $root statement is:
found
The $root is empty which surprised me. Using the grub menu on an node with debian deployed, Iβve also tried executing the following search statement:
search --file --no-floppy --set=root /EFI/debian/grubx64.efi which results in a successful found disk.
Do all distributions (installed on EFI systems) contain /EFI/BOOT/BOOTX64.EFI?
lzap
October 8, 2018, 5:56pm
#5
It is likely there is a bug, most of us use Red Hat compatible systems and I have been testing this only with RHEL and CentOS. Can you list all files of Debians EFI ESP partition?
That was my assumption when I designed this, I can be terribly wrong. We can improve.
Iβve created a tree output for CentOS7 and debian.
Debian9 tree:
# tree /boot/
/boot/
βββ config-4.9.0-7-amd64
βββ efi
β βββ EFI
β βββ debian
β βββ grubx64.efi
βββ grub
β βββ fonts
β β βββ unicode.pf2
β βββ grub.cfg
β βββ grubenv
β βββ locale
β β βββ ast.mo
β β βββ ca.mo
β β βββ da.mo
β β βββ de_CH.mo
β β βββ de@hebrew.mo
β β βββ de.mo
β β βββ en@arabic.mo
β β βββ en@cyrillic.mo
β β βββ en@greek.mo
β β βββ en@hebrew.mo
β β βββ en@piglatin.mo
β β βββ en@quot.mo
β β βββ eo.mo
β β βββ es.mo
β β βββ fi.mo
β β βββ fr.mo
β β βββ gl.mo
β β βββ hu.mo
β β βββ id.mo
β β βββ it.mo
β β βββ ja.mo
β β βββ lt.mo
β β βββ nb.mo
β β βββ nl.mo
β β βββ pa.mo
β β βββ pl.mo
β β βββ pt_BR.mo
β β βββ ru.mo
β β βββ sl.mo
β β βββ sr.mo
β β βββ sv.mo
β β βββ tr.mo
β β βββ uk.mo
β β βββ vi.mo
β β βββ zh_CN.mo
β β βββ zh_TW.mo
β βββ unicode.pf2
β βββ x86_64-efi
β βββ acpi.mod
β βββ adler32.mod
β βββ affs.mod
β βββ afs.mod
β βββ ahci.mod
β βββ all_video.mod
β βββ aout.mod
β βββ appleldr.mod
β βββ archelp.mod
β βββ ata.mod
β βββ at_keyboard.mod
β βββ backtrace.mod
β βββ bfs.mod
β βββ bitmap.mod
β βββ bitmap_scale.mod
β βββ blocklist.mod
β βββ boot.mod
β βββ bsd.mod
β βββ bswap_test.mod
β βββ btrfs.mod
β βββ bufio.mod
β βββ cat.mod
β βββ cbfs.mod
β βββ cbls.mod
β βββ cbmemc.mod
β βββ cbtable.mod
β βββ cbtime.mod
β βββ chain.mod
β βββ cmdline_cat_test.mod
β βββ cmp.mod
β βββ cmp_test.mod
β βββ command.lst
β βββ configfile.mod
β βββ core.efi
β βββ cpio_be.mod
β βββ cpio.mod
β βββ cpuid.mod
β βββ crc64.mod
β βββ cryptodisk.mod
β βββ crypto.lst
β βββ crypto.mod
β βββ cs5536.mod
β βββ ctz_test.mod
β βββ datehook.mod
β βββ date.mod
β βββ datetime.mod
β βββ diskfilter.mod
β βββ disk.mod
β βββ div.mod
β βββ div_test.mod
β βββ dm_nv.mod
β βββ echo.mod
β βββ efifwsetup.mod
β βββ efi_gop.mod
β βββ efinet.mod
β βββ efi_uga.mod
β βββ ehci.mod
β βββ elf.mod
β βββ eval.mod
β βββ exfat.mod
β βββ exfctest.mod
β βββ ext2.mod
β βββ extcmd.mod
β βββ fat.mod
β βββ file.mod
β βββ fixvideo.mod
β βββ font.mod
β βββ fshelp.mod
β βββ fs.lst
β βββ functional_test.mod
β βββ gcry_arcfour.mod
β βββ gcry_blowfish.mod
β βββ gcry_camellia.mod
β βββ gcry_cast5.mod
β βββ gcry_crc.mod
β βββ gcry_des.mod
β βββ gcry_dsa.mod
β βββ gcry_idea.mod
β βββ gcry_md4.mod
β βββ gcry_md5.mod
β βββ gcry_rfc2268.mod
β βββ gcry_rijndael.mod
β βββ gcry_rmd160.mod
β βββ gcry_rsa.mod
β βββ gcry_seed.mod
β βββ gcry_serpent.mod
β βββ gcry_sha1.mod
β βββ gcry_sha256.mod
β βββ gcry_sha512.mod
β βββ gcry_tiger.mod
β βββ gcry_twofish.mod
β βββ gcry_whirlpool.mod
β βββ geli.mod
β βββ gettext.mod
β βββ gfxmenu.mod
β βββ gfxterm_background.mod
β βββ gfxterm_menu.mod
β βββ gfxterm.mod
β βββ gptsync.mod
β βββ grub.efi
β βββ gzio.mod
β βββ halt.mod
β βββ hashsum.mod
β βββ hdparm.mod
β βββ hello.mod
β βββ help.mod
β βββ hexdump.mod
β βββ hfs.mod
β βββ hfspluscomp.mod
β βββ hfsplus.mod
β βββ http.mod
β βββ iorw.mod
β βββ iso9660.mod
β βββ jfs.mod
β βββ jpeg.mod
β βββ keylayouts.mod
β βββ keystatus.mod
β βββ ldm.mod
β βββ legacycfg.mod
β βββ legacy_password_test.mod
β βββ linux16.mod
β βββ linuxefi.mod
β βββ linux.mod
β βββ loadbios.mod
β βββ loadenv.mod
β βββ loopback.mod
β βββ lsacpi.mod
β βββ lsefimmap.mod
β βββ lsefi.mod
β βββ lsefisystab.mod
β βββ lsmmap.mod
β βββ ls.mod
β βββ lspci.mod
β βββ lssal.mod
β βββ luks.mod
β βββ lvm.mod
β βββ lzopio.mod
β βββ macbless.mod
β βββ macho.mod
β βββ mdraid09_be.mod
β βββ mdraid09.mod
β βββ mdraid1x.mod
β βββ memdisk.mod
β βββ memrw.mod
β βββ minicmd.mod
β βββ minix2_be.mod
β βββ minix2.mod
β βββ minix3_be.mod
β βββ minix3.mod
β βββ minix_be.mod
β βββ minix.mod
β βββ mmap.mod
β βββ moddep.lst
β βββ modinfo.sh
β βββ morse.mod
β βββ mpi.mod
β βββ msdospart.mod
β βββ mul_test.mod
β βββ multiboot2.mod
β βββ multiboot.mod
β βββ nativedisk.mod
β βββ net.mod
β βββ newc.mod
β βββ nilfs2.mod
β βββ normal.mod
β βββ ntfscomp.mod
β βββ ntfs.mod
β βββ odc.mod
β βββ offsetio.mod
β βββ ohci.mod
β βββ part_acorn.mod
β βββ part_amiga.mod
β βββ part_apple.mod
β βββ part_bsd.mod
β βββ part_dfly.mod
β βββ part_dvh.mod
β βββ part_gpt.mod
β βββ partmap.lst
β βββ part_msdos.mod
β βββ part_plan.mod
β βββ part_sun.mod
β βββ part_sunpc.mod
β βββ parttool.lst
β βββ parttool.mod
β βββ password.mod
β βββ password_pbkdf2.mod
β βββ pata.mod
β βββ pbkdf2.mod
β βββ pbkdf2_test.mod
β βββ pcidump.mod
β βββ play.mod
β βββ png.mod
β βββ priority_queue.mod
β βββ probe.mod
β βββ procfs.mod
β βββ progress.mod
β βββ raid5rec.mod
β βββ raid6rec.mod
β βββ random.mod
β βββ read.mod
β βββ reboot.mod
β βββ regexp.mod
β βββ reiserfs.mod
β βββ relocator.mod
β βββ romfs.mod
β βββ scsi.mod
β βββ search_fs_file.mod
β βββ search_fs_uuid.mod
β βββ search_label.mod
β βββ search.mod
β βββ serial.mod
β βββ setjmp.mod
β βββ setjmp_test.mod
β βββ setpci.mod
β βββ sfs.mod
β βββ shift_test.mod
β βββ signature_test.mod
β βββ sleep.mod
β βββ sleep_test.mod
β βββ spkmodem.mod
β βββ squash4.mod
β βββ syslinuxcfg.mod
β βββ tar.mod
β βββ terminal.lst
β βββ terminal.mod
β βββ terminfo.mod
β βββ test_blockarg.mod
β βββ testload.mod
β βββ test.mod
β βββ testspeed.mod
β βββ tftp.mod
β βββ tga.mod
β βββ time.mod
β βββ trig.mod
β βββ tr.mod
β βββ true.mod
β βββ udf.mod
β βββ ufs1_be.mod
β βββ ufs1.mod
β βββ ufs2.mod
β βββ uhci.mod
β βββ usb_keyboard.mod
β βββ usb.mod
β βββ usbms.mod
β βββ usbserial_common.mod
β βββ usbserial_ftdi.mod
β βββ usbserial_pl2303.mod
β βββ usbserial_usbdebug.mod
β βββ usbtest.mod
β βββ verify.mod
β βββ video_bochs.mod
β βββ video_cirrus.mod
β βββ video_colors.mod
β βββ video_fb.mod
β βββ videoinfo.mod
β βββ video.lst
β βββ video.mod
β βββ videotest_checksum.mod
β βββ videotest.mod
β βββ xfs.mod
β βββ xnu.mod
β βββ xnu_uuid.mod
β βββ xnu_uuid_test.mod
β βββ xzio.mod
β βββ zfscrypt.mod
β βββ zfsinfo.mod
β βββ zfs.mod
βββ initrd.img-4.9.0-7-amd64
βββ lost+found
βββ System.map-4.9.0-7-amd64
βββ vmlinuz-4.9.0-7-amd64
CentOS7 tree:
# tree /boot/
/boot/
βββ config-3.10.0-862.6.3.el7.x86_64
βββ efi
β βββ EFI
β βββ BOOT
β β βββ BOOTX64.EFI
β β βββ fbx64.efi
β βββ centos
β βββ BOOT.CSV
β βββ BOOTX64.CSV
β βββ fonts
β β βββ unicode.pf2
β βββ grub.cfg
β βββ grubenv
β βββ grubx64.efi
β βββ mmx64.efi
β βββ shim.efi
β βββ shimx64-centos.efi
β βββ shimx64.efi
βββ grub
β βββ splash.xpm.gz
βββ grub2
β βββ grubenv -> /boot/efi/EFI/centos/grubenv
βββ initramfs-0-rescue-6b17af8b36e6498a86e9e99c01d45921.img
βββ initramfs-3.10.0-514.el7.x86_64.img
βββ initramfs-3.10.0-862.6.3.el7.x86_64.img
βββ initramfs-3.10.0-862.6.3.el7.x86_64kdump.img
βββ symvers-3.10.0-862.6.3.el7.x86_64.gz
βββ System.map-3.10.0-862.6.3.el7.x86_64
βββ vmlinuz-0-rescue-6b17af8b36e6498a86e9e99c01d45921
βββ vmlinuz-3.10.0-862.6.3.el7.x86_64
Even on a CentOS7 system, the UEFI chainloading did not succeed as well even though the file efi/EFI/BOOT/BOOTX64.EFI does exist.
Iβm no grub expert but it seems that the search is unable to determine which device should be used as root.
I had a similar issue with windows 2012 r2 uefi boot and sorted out with the below modification of the template:
<% paths.each do |path| %>
elif [ -f ($root)/EFI/<%= path %>/grubx64.efi ]; then
chainloader ($root)/EFI/<%= path %>/grubx64.efi
<% end -%>
+ elif [ -f ($root)/EFI/Microsoft/boot/bootmgfw.efi ]; then
+ chainloader ($root)/EFI/Microsoft/boot/bootmgfw.efi
else
echo File grubx64.efi not found on ESP.
echo Update 'pxegrub2_chainload' paths array with:
ls ($root)/EFI
Does the EFI/Microsoft/boot/ directory contain multiple .efi files?
lzap
October 10, 2018, 5:51am
#9
I only tested this in libvirt VM, do not hesitate to send your patches to our community-templates repo please.
The problem is that grub2 only allows searching volumes by files not directories, that would be easier. I am gonna change that a bit so it tries to find the target EFI file instead of BOOTX64.EFI. I had impression that all OSes have that, I was wrong.
Can you tell me guys what ESP partition label did Windows and Debian OS installer set? We can also search by label too.
Once I have some patches, Iβll share them of course. I can test different HP machines equipped with EFI @ work to see if what works best. If you have patches available, I can help test them if you want.
Iβm back in the office tomorrow, Iβll check which label are assigned to the EFI partition for debian.
The efi partition is not formatted with a (vfat) label per se. Iβve checked on CentOS as well as Debian and Arch Linux. Iβll keep digging though.
lzap
October 11, 2018, 1:09pm
#12
This is on my radar, I just have some other duties. In the meantime please file a Redmine issue describing what does not work. Looks like we need to iterate through list of expected files for that search until we find the correct entry.
Iβll create an issue in Redmine for this. While trying different solutions, I now feel like Edison; Iβve found several ways not to chainload efi.
Sorry for the late answer. Here is the windows 2012 r2 EFI partition content:
PS Y:\EFI\Microsoft\Boot> dir
Directory: Y:\EFI\Microsoft\Boot
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 10/4/2018 5:54 PM bg-BG
d---- 10/4/2018 5:54 PM cs-CZ
d---- 10/4/2018 5:54 PM da-DK
d---- 10/4/2018 5:54 PM de-DE
d---- 10/4/2018 5:54 PM el-GR
d---- 10/4/2018 5:54 PM en-GB
d---- 10/4/2018 5:54 PM en-US
d---- 10/4/2018 5:54 PM es-ES
d---- 10/4/2018 5:54 PM et-EE
d---- 10/4/2018 5:54 PM fi-FI
d---- 10/4/2018 5:54 PM fr-FR
d---- 10/4/2018 5:54 PM hr-HR
d---- 10/4/2018 5:54 PM hu-HU
d---- 10/4/2018 5:54 PM it-IT
d---- 10/4/2018 5:54 PM ja-JP
d---- 10/4/2018 5:54 PM ko-KR
d---- 10/4/2018 5:54 PM lt-LT
d---- 10/4/2018 5:54 PM lv-LV
d---- 10/4/2018 5:54 PM nb-NO
d---- 10/4/2018 5:54 PM nl-NL
d---- 10/4/2018 5:54 PM pl-PL
d---- 10/4/2018 5:54 PM pt-BR
d---- 10/4/2018 5:54 PM pt-PT
d---- 10/4/2018 5:54 PM qps-ploc
d---- 10/4/2018 5:54 PM ro-RO
d---- 10/4/2018 5:54 PM ru-RU
d---- 10/4/2018 5:54 PM sk-SK
d---- 10/4/2018 5:54 PM sl-SI
d---- 10/4/2018 5:54 PM sr-Latn-CS
d---- 10/4/2018 5:54 PM sr-Latn-RS
d---- 10/4/2018 5:54 PM sv-SE
d---- 10/4/2018 5:54 PM tr-TR
d---- 10/4/2018 5:54 PM uk-UA
d---- 10/4/2018 5:54 PM zh-CN
d---- 10/4/2018 5:54 PM zh-HK
d---- 10/4/2018 5:54 PM zh-TW
d---- 10/4/2018 5:54 PM Fonts
d---- 10/4/2018 5:54 PM Resources
-a--- 10/11/2018 7:22 AM 49152 BCD
-a--- 2/7/2018 9:25 AM 5023 boot.stl
-a--- 12/14/2017 12:49 AM 1629536 bootmgfw.efi
-a--- 12/14/2017 12:49 AM 1625952 bootmgr.efi
-a--- 11/21/2014 8:45 PM 1500504 memtest.efi
PS Y:\EFI\Microsoft\Boot>
Thank you for the listing. Do you know if the EFI implementation of Windows 8/10 is similar to Windows 12 r2?
Iβve altered the pxegrub2_chainload snippet which seems to work on both Debian and CentOS deployed systems (testing on virtual machines and physical HP machines). @lzap : Can you review the snippet?
<%#
kind: snippet
name: pxegrub2_chainload
model: ProvisioningTemplate
snippet: true
%>
menuentry 'Chainload Grub2 EFI from ESP' --id local {
insmod part_gpt
insmod fat
insmod chain
for efi in (*,gpt*)/efi/*/*.efi (*,gpt*)/efi/*/*/*.efi (*,gpt*)/*.efi (*,gpt*)/*/*.efi ; do
regexp --set=1:efi_device '^\((.*)\)/' "${efi}"
regexp --set=1:efi_path '(.*)/.*$' "${efi}"
regexp --set=1:efi_file '.*\/(.*)$' "${efi}"
if [ "$efi_file" == "grubx64.efi" ]; then
set root=$efi_device
set efi_found=true
break
fi
if [ "$efi_file" == "bootmgfw.efi" ]; then
set root=$efi_device
set efi_found=true
break
fi
done
echo "Found efi boot on $efi_path/$efi_file"
sleep 2
if [ -f $efi_path/$efi_file ]; then
chainloader $efi_path/$efi_file
else
echo File grubx64.efi nor bootmgfw.efi not found on ESP.
echo Update 'pxegrub2_chainload' paths array with:
ls ($root)/EFI
echo The system will halt in 2 minutes or
echo press ESC to halt immediately.
sleep -i 120
halt --no-apm
fi
}
menuentry 'Chainload into BIOS bootloader on first disk' --id local_chain_hd0 {
set root=(hd0,0)
chainloader +1
}
menuentry 'Chainload into BIOS bootloader on second disk' --id local_chain_hd1 {
set root=(hd1,0)
chainloader +1
}
If this provides a working solution, what do I need to do in order to add this to future foreman releases?
1 Like
Iβm not sure. I never deployed Windows 8/10 using foreman but I think you can check EFI partition using βdiskpartβ command if you use windows 8/10 on your laptop/pc.
lzap
October 12, 2018, 12:12pm
#18
Awesome! Would Grub2 pick also regular shell syntax of:
if [ "$efi_file" == "grubx64.efi" -o "$efi_file" == "bootmgfw.efi" ]; then
Also we want to search for shim.efi
as well (actually as first), on Red Hats this is the signed shim which then loads (unsigned) Grub2. The question is if this will work in SecureBoot mode, we need to test.
But overall this is great improvement. Feel free to file PR into community templates so I can review and test from there.
Iβve made a mistake when creating an issue in the redmine for foreman. Bug #25185: Pxegrub2_chainload unable to determine disk containing /EFI/BOOT/BOOTX64.EFI - Templates - Foreman is under project templates and should be under project Foreman. How do I move the issue from project Templates to Foreman?