heads/patches/kexec-2.0.26.patch

162 lines
5.7 KiB
Diff

diff --git a/Makefile.in b/Makefile.in
index 09bbd5c..500ad35 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -167,12 +167,12 @@ include $(srcdir)/kexec/Makefile
# vmcore-dmesg (read dmesg from a vmcore)
#
-include $(srcdir)/vmcore-dmesg/Makefile
+#include $(srcdir)/vmcore-dmesg/Makefile
#
# kexec_test (test program)
#
-include $(srcdir)/kexec_test/Makefile
+#include $(srcdir)/kexec_test/Makefile
SPEC=$(PACKAGE_NAME).spec
GENERATED_SRCS:= $(SPEC)
diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
index 14263b0..55291d6 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -138,31 +138,76 @@ static int setup_linux_vesafb(struct x86_linux_param_header *real_mode)
if (-1 == fd)
return -1;
- if (-1 == ioctl(fd, FBIOGET_FSCREENINFO, &fix))
+ if (-1 == ioctl(fd, FBIOGET_FSCREENINFO, &fix)) {
+ dbgprintf("%s: FBIOGET_FSCREENINFO failed, can't provide framebuffer\n",
+ __func__);
goto out;
- if (-1 == ioctl(fd, FBIOGET_VSCREENINFO, &var))
+ }
+ if (-1 == ioctl(fd, FBIOGET_VSCREENINFO, &var)) {
+ dbgprintf("%s: FBIOGET_FSCREENINFO failed, can't provide framebuffer\n",
+ __func__);
goto out;
- if (0 == strcmp(fix.id, "VESA VGA")) {
+ }
+ /*
+ * If we can get a framebuffer from the host kernel, provide it to the
+ * target kernel. This does not work for all drivers - we have to be
+ * able to get the framebuffer address, and the framebuffer must be a
+ * plain flat framebuffer. This should work for VESA framebuffers
+ * since that is the only type of framebuffer it creates.
+ *
+ * Since Linux 4.20, getting the framebuffer address requires
+ * CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM and
+ * drm_kms_helper.drm_leak_fbdev_smem=1 on the command line.
+ *
+ * Since Linux 5.8, i915 often uses a compressed framebuffer, this must
+ * be disabled with i915.enable_fbc=0 on the kernel command line.
+ *
+ * This does not work with ast ("astdrmfb") currently as it uses a
+ * shadow buffer internally in the kernel, and there is no way to get
+ * the real framebuffer address.
+ */
+ if (0 == strcmp(fix.id, "VESA VGA")
+ || 0 == strcmp(fix.id, "inteldrmfb")
+ || 0 == strcmp(fix.id, "i915drmfb")) {
/* VIDEO_TYPE_VLFB */
real_mode->orig_video_isVGA = 0x23;
+ dbgprintf("%s: Found driver %s, providing VIDEO_TYPE_VLFB\n",
+ __func__, fix.id);
} else if (0 == strcmp(fix.id, "EFI VGA")) {
/* VIDEO_TYPE_EFI */
real_mode->orig_video_isVGA = 0x70;
+ dbgprintf("%s: Found driver %s, providing VIDEO_TYPE_EFI\n",
+ __func__, fix.id);
} else if (arch_options.reuse_video_type) {
int err;
off_t offset = offsetof(typeof(*real_mode), orig_video_isVGA);
/* blindly try old boot time video type */
err = get_bootparam(&real_mode->orig_video_isVGA, offset, 1);
- if (err)
+ if (err) {
+ dbgprintf("%s: Can't get booted video type, can't provide framebuffer\n",
+ __func__);
goto out;
+ }
+ dbgprintf("%s: Reusing video type %d\n",
+ __func__, real_mode->orig_video_isVGA);
} else {
+ fprintf(stderr, "Unknown driver %s, can't provide framebuffer\n kexec'ed OS will take over console only if %s is provided\n",
+ fix.id, fix.id);
real_mode->orig_video_isVGA = 0;
close(fd);
return 0;
}
close(fd);
+ if (!fix.smem_start) {
+ dbgprintf("%s: Kernel did not provide framebuffer address\n",
+ __func__);
+ dbgprintf("%s: Try enabling CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM and "
+ "drm_kms_helper.drm_leak_fbdev_smem in kernel command-line options\n",
+ __func__);
+ }
+
real_mode->lfb_width = var.xres;
real_mode->lfb_height = var.yres;
real_mode->lfb_depth = var.bits_per_pixel;
diff --git a/kexec/kexec.c b/kexec/kexec.c
index 0e92d96..f7984a8 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -807,6 +807,27 @@ static int my_load(const char *type, int fileind, int argc, char **argv,
if (sort_segments(&info) < 0) {
return -1;
}
+
+#if 1
+ // force segment 0 to have memsz == bufsz
+ // so that it won't overwrite EBDA
+ if (info.segment[0].mem == 0)
+ {
+ if (kexec_debug)
+ printf("hack ebda into segment 0!\n");
+
+ uint8_t * ebda = calloc(1, info.segment[0].memsz);
+ memcpy(ebda, info.segment[0].buf, info.segment[0].bufsz);
+ info.segment[0].bufsz = info.segment[0].memsz;
+ info.segment[0].buf = ebda;
+
+ // install some default EBDA values that are off scale,
+ // which will force Xen to use the multiboot info
+ *(uint16_t*)(ebda + 0x40e) = 0xFFFF; // segment
+ *(uint16_t*)(ebda + 0x413) = 0xFFFF; // size
+ }
+#endif
+
/* if purgatory is loaded update it */
update_purgatory(&info);
if (entry)
diff --git a/purgatory/Makefile b/purgatory/Makefile
index 4d2d071..ee5c642 100644
--- a/purgatory/Makefile
+++ b/purgatory/Makefile
@@ -45,7 +45,6 @@ purgatory/sha256.o: $(srcdir)/util_lib/sha256.c
mkdir -p $(@D)
$(COMPILE.c) -o $@ $^
-$(PURGATORY): CC=$(TARGET_CC)
$(PURGATORY): CFLAGS=$(PURGATORY_EXTRA_CFLAGS) \
$($(ARCH)_PURGATORY_EXTRA_CFLAGS) \
-Os -fno-builtin -ffreestanding \
diff --git a/util/Makefile b/util/Makefile
index 948ee63..833a897 100644
--- a/util/Makefile
+++ b/util/Makefile
@@ -2,7 +2,7 @@ BIN_TO_HEX:= bin/bin-to-hex
$(BIN_TO_HEX): $(srcdir)/util/bin-to-hex.c
@$(MKDIR) -p $(@D)
- $(LINK.o) $(CFLAGS) -o $@ $^
+ $(BUILD_CC) $(BUILD_CFLAGS) -o $@ $^
$(BIN_TO_HEX): CC=$(BUILD_CC)
$(BIN_TO_HEX): CFLAGS=$(BUILD_CFLAGS)