diff options
author | Dave Young <dyoung@redhat.com> | 2018-01-28 13:52:31 +0800 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2018-01-29 10:03:24 +0100 |
commit | 060eee589dd1499465ec8dae099824e81331b51a (patch) | |
tree | 30b709af7150998a43b6efb154a228f710d01050 /kexec/arch/i386/x86-linux-setup.c | |
parent | 282ff2a5e613b8291b44848fad42904541a031c1 (diff) |
x86: use old screen_info if needed
With modern drm/kms graphic driver kexec-tools does not setup screen_info
correctly so one will only see screen output after those drm drivers
reinitializing after rebooting. Copying the old screen info from original
boot_params will help during my test, although it could not work for some
potential cases, but it is not worse than before. This has been used in
the kernel kexec_file_load.
Signed-off-by: Dave Young <dyoung@redhat.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'kexec/arch/i386/x86-linux-setup.c')
-rw-r--r-- | kexec/arch/i386/x86-linux-setup.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c index c75adaa..6c7d260 100644 --- a/kexec/arch/i386/x86-linux-setup.c +++ b/kexec/arch/i386/x86-linux-setup.c @@ -27,6 +27,7 @@ #include <fcntl.h> #include <sys/ioctl.h> #include <linux/fb.h> +#include <linux/screen_info.h> #include <unistd.h> #include <dirent.h> #include <mntent.h> @@ -122,7 +123,8 @@ void setup_linux_bootloader_parameters_high( cmdline_ptr[cmdline_len - 1] = '\0'; } -int setup_linux_vesafb(struct x86_linux_param_header *real_mode) +static int get_bootparam(void *buf, off_t offset, size_t size); +static int setup_linux_vesafb(struct x86_linux_param_header *real_mode) { struct fb_fix_screeninfo fix; struct fb_var_screeninfo var; @@ -143,8 +145,13 @@ int setup_linux_vesafb(struct x86_linux_param_header *real_mode) /* VIDEO_TYPE_EFI */ real_mode->orig_video_isVGA = 0x70; } else { - /* cannot handle and other types */ - goto out; + 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) + goto out; } close(fd); @@ -826,6 +833,8 @@ out: void setup_linux_system_parameters(struct kexec_info *info, struct x86_linux_param_header *real_mode) { + int err; + /* get subarch from running kernel */ setup_subarch(real_mode); if (bzImage_support_efi_boot && !arch_options.noefi) @@ -841,8 +850,22 @@ void setup_linux_system_parameters(struct kexec_info *info, real_mode->orig_video_ega_bx = 0; real_mode->orig_video_isVGA = 1; real_mode->orig_video_points = 16; - setup_linux_vesafb(real_mode); + /* setup vesa fb if possible, or just use original screen_info */ + err = setup_linux_vesafb(real_mode); + if (err) { + uint16_t cl_magic, cl_offset; + + /* save and restore the old cmdline param if needed */ + cl_magic = real_mode->cl_magic; + cl_offset = real_mode->cl_offset; + + err = get_bootparam(real_mode, 0, sizeof(struct screen_info)); + if (!err) { + real_mode->cl_magic = cl_magic; + real_mode->cl_offset = cl_offset; + } + } /* Fill in the memsize later */ real_mode->ext_mem_k = 0; real_mode->alt_mem_k = 0; |