我有一个应用程序,我需要启动到 Linux,执行自动化脚本,然后自动启动到 Windows。我可以使用 Kexec 来运行 grub 吗?
另一个用例是启动 Linux 内核来更新处理器微代码,然后kexec
启动 GRUB 或 Syslinux 来启动 Windows —— 因为微代码无法在完全重新启动后继续存在。
我听说过grub4dos
(链接(不可用),存档版本),但是好像已经停产了,那么有没有办法用GRUB2来做呢?
我基本上需要一个可加载的 GRUB 映像kexec
。我尝试加载在此找到的图像解释,但它们似乎不起作用。感谢您的任何提示。
注:已找到这个帖子从 2014 年开始,kexec 中还没有实现这一点。
答案1
这对于 Windows 来说似乎是可能的kexec
,但它似乎充其量只是实验性的(并且没有经过充分的测试)。
GRUB
kexec
grub本身是不可能的core.img
(因为它似乎没有兼容的二进制格式),另请参阅Launchpad 上的此错误报告。提到的错误仍然可以重现:
kexec -l /boot/grub2/i386-pc/core.img
根据kexec --help
,目前支持以下类型:
elf-x86_64
multiboot-x86
multiboot2-x86
elf-x86
bzImage64
bzImage
beoboot-x86
nbi-x86
如果您想加载不同的加载器,则需要采用这些格式之一,否则必须添加兼容性。我不确定 GRUB 使用什么格式 - 一个简单的file
命令只会产生以下结果:
/boot/grub2/i386-pc/core.img: data
创建可引导的 GRUB 映像
目前看来有以下几种可能:
grub2-mkimage
- 一部分
core.img
(kernel.img
) - 拼凑
lnxboot.img
和core.img
在一起。请参阅@Ardwena 的回答。 lnxboot.img
作为内核和core.img
作为initrd
.提示发现于拱门维基和grub devel 邮件列表上的一个旧线程。
引导程序
lnxboot.img
将是一个Linux kernel x86 boot executeable bzImage
.它似乎打算作为内核加载:
然后,您可以从 syslinux/isolinux/pxelinux/lilo 或任何其他支持 Linux 内核的引导加载程序加载 grub2.bin。
Kexec 确实加载了它,但执行时崩溃:
kexec -l /usr/lib/grub/i386-pc/lnxboot.img --initrd=/boot/grub2/i386-pc/core.img --debug
加载时似乎也出现问题(调试输出的前几行):
Try gzip decompression.
Try LZMA decompression.
lzma_decompress_file: read on /usr/lib/grub/i386-pc/lnxboot.img of 65536 bytes failed
[...]
Grub4Dos
快速浏览一下 Grub4Dos:
# file grub.exe
grub.exe: Linux kernel x86 boot executable bzImage, version \353kHdrS\003\002, RO-rootFS, Normal VGA
这应该意味着它是兼容的。这对我来说不是一个选择,因为它是遗留软件。
grub4dos
但是,我设法通过下载0.4.4
来加载来源锻造然后运行:
kexec -l grub.exe
kexec -e
未配置时,一段时间后它会退回到 grub shell。如果您想使用gru4dos
,您只需要调整cmdline
即可满足您的需求。这个线程仍应适用。
视窗
Kexec
Windows 似乎不是一句简单的话,但它之前已经做过。
我找到了这些幻灯片还有这个github 仓库。这似乎是文章中提到的使其发挥作用的项目。
这似乎是可能的,但需要做很多工作(并且没有可用的“生产就绪”解决方案 - 至少我还没有找到它)。不幸的是,似乎没有很多关于 LinuxBoot 的文档,所以你可能不得不询问开发人员。可能已经有一种更直接的方法可以做到这一点。
答案2
kexec 进入 Windows 之所以如此困难和复杂,是因为 kexec 的内部设计机制存在缺陷,它假设所有操作系统引导加载程序都以类似的方式加载操作系统内核映像,但事实显然并非如此。例如,某些操作系统内核映像必须从某些特殊的内存地址偏移量开始加载,某些操作系统可能需要与操作系统内核映像一起加载其他文件(包含驱动程序信息)等。因为我们无法控制操作系统如何加载其内核映像,或者将在未来版本中加载其内核映像,从长远来看,当前 kexec-ing 到另一个操作系统/内核的方式不会很好地工作。
kexec-ing 进入另一个操作系统的更通用/兼容的方式(正如我建议的)是加载实模式引导扇区引导代码,退出保护模式,然后直接跳转到实模式引导代码入口点。这是最通用的方式,因为任何操作系统的实模式引导扇区引导代码始终可以从任何内存地址开始加载,这就是 BIOS(不同的计算机制造商制造不同的 BIOS)引导到操作系统的方式(除非操作系统不这样做)不希望其他 BIOS 安装或引导它,例如 Apple,他们可以对如何加载引导扇区引导代码施加专有限制)。这样,我们总是可以引导到任何操作系统,无论其引导代码如何加载其操作系统内核映像,因为我们直接运行其自己的引导扇区引导代码。此外,这种模式不会造成任何减慢,因为引导扇区引导代码很小,因此加载速度很快,并且在实模式和保护模式下加载大型内核映像文件的差异不是很大。
然而,实现这一目标非常具有挑战性,因为:
对于所有现代操作系统,一旦从实模式进入保护模式,实模式内存就会被一些描述符表或页表条目覆盖。因此,没有备份。然而,实模式启动代码使用BIOS中断来访问硬件IO,因此如果不恢复原始实模式内存映射,它们将无法从硬盘加载内核映像文件。这个问题很棘手但可以解决。我们可以安装一些特殊的 Linux 引导加载程序,在进入保护模式之前拍摄内存快照,并且只需要在一台机器上完成一次。
并非所有处理器都很好地支持从保护模式返回实模式。出于生产成本和效率的原因,现代处理器被设计用于启动到操作系统(从实模式进入保护模式),而不是从操作系统中取消启动(从保护模式返回到实模式)。因此,从保护模式返回实模式的行为没有经过充分测试,因此非常不确定。由于每个型号的这种行为各不相同,因此无法控制,因此无法保证它可以在哪些品牌/型号的处理器上正常工作。
只有 Intel X86 处理器才有实模式和保护模式(因为它经历了很早期的遗留技术),因此从引导扇区重启的机制对于不同的处理器架构会有所不同,不一定涉及从保护模式返回实模式,但可能涉及处理器运行状态的一些其他切换。
尽管如此,如果一切都得到正确处理,原则上它应该可以工作。将来,Linux 应该具有 kexec-ing 到任何已安装的可引导分区的能力(但不一定标记为可引导,因为每个硬盘只能有一个标记为可引导的分区,否则 BIOS 将直接从任何硬盘报告错误并拒绝启动),而无需完全硬件重新启动,这要慢得多。这给Linux带来了更多的光明和希望^_^
答案3
您需要安装 grub 并将 Linux 系统作为默认启动。
在 Linux 系统上创建一个 crontab 条目,如下所示:
@reboot /do/some/stuff
其中 /do/some/stuff 是执行您需要执行的任何任务的脚本。在脚本末尾添加以下内容:
#!/bin/bash
#
# Do something here
sudo grub2-once "Windows"
sudo reboot
如果 Windows 的 grub 菜单项是“Windows”,那么它应该重新启动到 Windows。
下次重新启动时,它将返回 Linux 并执行相同的操作。
答案4
kexec
如果您将这两个 grub 映像组合起来可能会起作用:lnxboot.img
和core.img
,例如...
cat lnxboot.img core.img > your-kexec-able.img
值得尝试一下。
编辑:
现在我查看了图像内部,lnxboot.image
看起来更像是一个“ELF”而不是lnxboot.img
,所以也尝试一下。
编辑:
显然, /boot/grub2/i386-pc/xxx.img 映像不符合kexec
.那么为什么不尝试使用grub-mkimage
生成一些不同的格式,看看什么有效呢?从手册页来看,-O, --format=FORMAT
支持一大堆其他格式。也许尝试一下x86_64-xen
格式。