11

I have an application where I need to boot to Linux, execute automated scripts and then automatically boot to Windows. Can I use Kexec to run grub?

Another use case would be to boot a Linux kernel to update the processor microcode, and then kexec to GRUB or Syslinux to boot Windows -- because the microcode won't survive a full reboot.

I've heard of grub4dos (link (unavailable), archived version), but it seems to be discontinued, so is there a way to do it with GRUB2?

I would basically need a loadable image of GRUB for kexec. I tried to load the images found in this explanation, but they don't seem to work. Thanks for any hints.


Note: Found this post from back in 2014, which said that this was not yet implemented in kexec.

9
  • Alternatively, could I kexec directly to a Windows loader? Commented Nov 15, 2020 at 4:47
  • @Pourko I'm not sure about windows loader, but windows itself seems to be possible. phoronix.com/… However, they didn't seem to show how they did it and it might not work with the default kexec. Commented Nov 15, 2020 at 9:19
  • Why don't you set up grub to boot to linux by default. Then, on booting the linux machine, you can execute the required commands and reboot to Windows with: grub-reboot. More info: wiki.debian.org/GrubReboot Commented Nov 15, 2020 at 13:25
  • @JesúsÁngel Yes, that was the solution I settled on back then. I was looking for a faster way to do it (without having to reboot). Commented Nov 15, 2020 at 15:29
  • "grub-reboot" is not the solution, as I am speciffically trying to avoid a full reboot. If for example the Linux kernel updates the processor microcode -- that microcode won't survive a fill reboot. Commented Nov 15, 2020 at 15:48

5 Answers 5

3

It seems to be possible to kexec Windows, but it seems to be experimental at best (and not well tested).

GRUB

It's not possible to kexec the grub core.img by itself (as it doesn't seem to have a compatible binary format), also see this bug report on launchpad. The error mentioned is still reproducible:

kexec -l /boot/grub2/i386-pc/core.img 

According to kexec --help, the following types are supported at the moment:

elf-x86_64 multiboot-x86 multiboot2-x86 elf-x86 bzImage64 bzImage beoboot-x86 nbi-x86 

If you want to load a different loader, it would need to be in one of these formats or the compatibility would have to be added. I'm not sure what format GRUB is using - a simple file command only produces this:

/boot/grub2/i386-pc/core.img: data 

Creating a bootable GRUB Image

Currently there seem to be these possibilities:

lnxboot

lnxboot.img would be a Linux kernel x86 boot executeable bzImage. It seems to be intended to be loaded as a kernel:

You can then load grub2.bin from syslinux/isolinux/pxelinux/lilo or any other boot loader that supports linux kernel.

Kexec does load it, but crashes when executing:

kexec -l /usr/lib/grub/i386-pc/lnxboot.img --initrd=/boot/grub2/i386-pc/core.img --debug 

There also seems to be an issue occuring while loading (first few lines of debug output):

Try gzip decompression. Try LZMA decompression. lzma_decompress_file: read on /usr/lib/grub/i386-pc/lnxboot.img of 65536 bytes failed [...] 

Grub4Dos

A quick look at Grub4Dos:

# file grub.exe grub.exe: Linux kernel x86 boot executable bzImage, version \353kHdrS\003\002, RO-rootFS, Normal VGA 

This should mean that it is compatible. It wasn't an option for me as it's legacy software.

However, I managed to load grub4dos by downloading 0.4.4 from sourceforge and then running:

kexec -l grub.exe kexec -e 

Unconfigured, it falls back to the grub shell after some time. If you want to use gru4dos, you should only need to tweak the cmdline to fit your needs. This thread should still apply.

Windows

Kexec'ing Windows doesn't seem to be a one-liner, but it has been done before.

Most of the work in this direction seems to be associated with the LinuxBoot project. Github

I found these slides as well as this github repo. This seems to be the project mentioned in the article that was making it work.

It seems to be possible, but a lot of work (and no "production-ready" solution available - At least I haven't found it yet). Unfortunately there doesn't seem to be a lot of documentation for LinuxBoot, so you may have to ask the developers. There may already be a more straightforward way to do this.

10
  • When you say it like "It's not possible to kexec grub, because non-elf multiboot images aren't supported yet" -- like it's an authoritative answer -- that is just somebody said something in some post from 2014. And contrary to that statement, kexec-ing to grub4dos used to be possible at that time. Commented Nov 15, 2020 at 16:44
  • @Pourko it's not an authorative answer, but it's all the info I found on it. And I tried it when asking that question in 2017. It will give you an error and say that the image isn't compatible. (It might be fixed by now). I believe that grub4dos had a different format (elf? non multiboot?) and that's why it worked (so that wouldn't necessarily contradict anything). Commented Nov 15, 2020 at 16:59
  • 1
    That's why I am not limiting my search to grub2. I would be happy if I find a way to kexec to ANY bootloader, like Syslinux, or Clover, or something. Commented Nov 15, 2020 at 17:19
  • @Pourko well - for now, the only option i know of with which this may work is grub4dos (if you're ok with ANY bootloader). There may be others, you'd have to check the image formats with file. Commented Nov 15, 2020 at 19:09
  • I would accept your answer, if it was not for that section about grub, where you make it sound like you know what you're talking about, while you're actually basing it all on somebody's very old post you googled. Commented Nov 15, 2020 at 19:45
2

The reason why kexec-ing into Windows is so difficult and complicated is because the internal design mechanism of kexec has an imperfection that, it assumes all OS boot loaders loads OS kernel image in a similar way, which is clearly not the case. For example, some OS kernel image must be loaded starting from some special memory address offset, some OS may require loading additional files (that containing driver info) alongside OS kernel image, etc. Since we have no control over how an operating system loads its kernel image, or will load its kernel image in a future release, the current way of kexec-ing into another OS/kernel is not going to work very well in the long run.

The more universal/compatible way (as I propose) of kexec-ing into another OS is to load the real-mode boot-sector boot code, quit the protected mode, and then jump directly into the real-mode boot code entry point. This is the most universal way because any operating system's real-mode boot-sector boot code can always be loaded starting at any memory address, that is how BIOS (different computer manufacturers make different BIOS) boots into an operating system (unless an OS does not want other BIOS to install or boot it, e.g., Apple, they can impose proprietary restrictions on how to load boot-sector boot codes). In this way, we can always boot into any operating system regardless of how its boot code loads its OS kernel image simply because we are running its own boot-sector boot code directly. Moreover, this mode does not introduce any slow-down because boot-sector boot code is small and thus fast to load, and the difference in loading a large kernel image file in real mode vs in protected mode is not very big.

However, to achieve this is very challenging because:

  1. For all modern OS, once they enter protected mode from real mode, the real-mode memory is over-written by some descriptor tables or page tables entries. Thus, there is no backup. However, real mode boot codes use BIOS interrupts to access hardware IO, so without restoring the original real-mode memory map, they won't be able to load kernel image file from hard-disk. This problem is tricky but solvable. We can install some special Linux boot loader that takes a memory snapshot before entering protected mode and it only needs to be done once for all on one machine.

  2. Not all processors well support going back to real mode from protected mode. Modern processors are designed for booting into an OS (entering protected mode from real mode), rather than un-booting out of an OS (returning to real mode from protected mode), for production cost and efficiency reasons. Thus, the behavior of returning to real mode from protected mode is not well tested and thus very much undefined. Since this behavior varies in each model, there is no control thus no guarantee of on which brand/models processors will it work correctly.

  3. Only Intel X86 processors have real mode and protected mode (because it went through a very early stage legacy technology). Thus, the mechanism of rebooting from boot sector will be different for different processor architectures, not necessarily involving returning to real mode from protected mode, but may involve some other switches in processor operating states.

Nevertheless, it should work in principle if everything is correctly taken care of. In the future, Linux should have the capability of kexec-ing into any mounted boot-able partition (but not necessarily marked as boot-able because each hard-disk can only have one partition that is marked as boot-able, or BIOS will report an error and refuse to boot) from any hard-disk directly without a full hardware reboot which is much slower. This shed more light and hope to Linux ^_^

7
  • Welcome to the site, and thank you for your contribution. Unfortunately, while you describe how the desired function could be implemented in the future, your answer doesn't really describe what the OP could do now to solve the problem. You may want to consider posting your proposition on the kexec mailing list or a different developer's forum instead. Commented Nov 12, 2021 at 7:45
  • On x86 PCs, your proposal would run into EFI hand-off issues: boot loaders are expected to cooperate with EFI during system boot, but that can only happen once. Also, point 2 was only ever an issue with the 286, current processors support returning to real mode just fine. In any case, EFI systems wouldn’t return to real mode — EFI boot programs run in protected mode. Commented Nov 12, 2021 at 16:53
  • @StephenKitt FYI, EFI starts in real mode (github.com/tianocore/edk2/blob/master/UefiCpuPkg/ResetVector/… ) and switches to protected mode (github.com/tianocore/edk2/blob/master/IntelFsp2Pkg/FspSecCore/… ). In particular, different OS provide their own EFI firmware image (e.g., bootmgr.efi for Windows, grubx64.efi for Linux). So ideally, kexec should provide the option of either kexec-ing from before *.efi is loaded or after *.efi is loaded. Commented Nov 13, 2021 at 10:36
  • Of course EFI starts in real mode, that’s the mode x86 CPUs start in. But it switches to protected mode before loading the boot manager. So even if you want kexec to re-execute the boot manager, there’s no need to return to real mode if the system was booted by EFI. Commented Nov 13, 2021 at 12:19
  • bootmgr.efi, grubx64.efi etc. aren’t firmware images. Commented Nov 13, 2021 at 12:20
1

You need to have grub installed and the Linux system as the default boot.

On the linux system create a crontab entry like this:

@reboot /do/some/stuff 

Where /do/some/stuff is a script to perform whatever tasks you need to do. At the end of the script add the following:

#!/bin/bash # # Do something here sudo grub2-once "Windows" sudo reboot 

It should then reboot into windows provided the grub menu item for windows is "Windows".

At the next reboot it will go back into linux and do the same thing.

4
  • 1
    Sorry, but this is not what we're looking for. Were trying to not reboot here. (but it's what I did to get similar behaviour though - but it's not what the question is about). Commented Nov 18, 2020 at 21:05
  • @Paranoid great answer. I was looking into conditional boot with a file being used as a flag. But this is both simpler and cleaner. Commented Nov 18, 2020 at 21:29
  • @rubid, out of curiosity, why don't you want to reboot? Commented Nov 18, 2020 at 21:30
  • @EduardoTrápani Originally it was just to save time. Now also out of curiosity. Also, Pourko wants to use it to update microcode (which would be lost on reboot). Commented Nov 18, 2020 at 22:26
0

Not exactly what has been asked for, but starting a Windows-VM using Linux is a solution feasible, if you have got enough power on that machine.

I can recommend VirtualBox for this. There you can configure VMs to autostart during bootup, to.

By modifying the runlevel relationships you can time when to start that windows-VM. With shared folders you can even use a signalling mechanism between Linux and the Windows VM.

5
  • Yes, that is not what has been asked for, and is completely unrelated. Suppose I have a machine that's strictly Windows. I know how to boot it through Grub, but I'd love to find a way to boot it through Linux. (for example, if I want to use the Linux kernel to update the processor microcode before I boot Windows -- hense my desire to be able to jump from Linux back to Grub) Commented Nov 22, 2020 at 2:06
  • @Pourko I asked wether this would be a solution. And the CPU-microcode-update will be there, too. In the VM you could map the windows-partitions to virtual storage for that VM, too. Commented Nov 25, 2020 at 16:56
  • No, a virtual box has no real access to the hardware of the host, let alone messing with the microcode of the CPU. Commented Nov 25, 2020 at 17:36
  • @Pourko the virtual CPUs will inherit the mircrocode from the hardware CPU. Which is installed during ealry boot in root-space, whereas the VM resides in user space. Commented Nov 25, 2020 at 20:57
  • I have no use of virtual machines "inheriting" anything. Virtual machines have nothing to do with the problem at hand. Commented Nov 25, 2020 at 21:04
0
+100

kexec might work if you combine these two grub images: lnxboot.img and core.img, like...

cat lnxboot.img core.img > your-kexec-able.img 

Worth trying that.

EDIT:

Now that I looked inside the images, lnxboot.image looks more like an "ELF" than lnxboot.img, so try that one too.

EDIT:

Aparently, the /boot/grub2/i386-pc/xxx.img images are not to the liking of kexec. Then why not try using grub-mkimage to genrate some different formats, and see what works? From the man page, -O, --format=FORMAT supports a whole bunch of other formats. Maybe try the x86_64-xen format.

3
  • Looks promising. lnxboot.img is valid, but doesn't boot. I'll try the .image too. Commented Nov 15, 2020 at 21:09
  • Yes, both can be loaded, but unfortunately it crashes when executing. Commented Nov 15, 2020 at 21:23
  • Splendid idea! I can't quite make it work though. Kexec actually loads the combined image, kexec -l -t bzImage lnx-core.img, but then when I execute kexec -e it just displays the message "kexec-core: Starting new kernel!", and all freezes right there. Commented Nov 15, 2020 at 21:45

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.