All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: multiboot non-elf and framebuffer support for kexec-tools
       [not found] <34EA379E6200FBA190C21A4D9996C7AB@felloff.net>
@ 2018-08-02 10:14 ` Simon Horman
  0 siblings, 0 replies; 2+ messages in thread
From: Simon Horman @ 2018-08-02 10:14 UTC (permalink / raw)
  To: cinap_lenrek; +Cc: kexec

Hi,

On Sat, Jul 28, 2018 at 06:18:11PM +0200, cinap_lenrek@felloff.net wrote:
> theres a patch that provides support for non-elf multiboot kernels
> and passes framebuffer information to the kernel if requested in
> the multiboot header.
> 
> only rgb truecolor framebuffers are supported right now. if --reset-vga
> or --console-vga was specified, it assumes the framebuffer will be
> standard ega text mode.
> 
> also pass acpi nvs and acpi reclaim ranges in the multiboot memory
> map as such; instead of just reserved. this allowing to kernel to
> locate acpi tables on uefi systems.
> 
> i'm new on the list, so is there a prefered address to send patches
> like this to?

kexec@lists.infradead.org is the right list to send kexec-tools patches.

Patches need a changelog which includes a Signed-off-by line,
like used with the Linux kernel, in order to be accepted.

> diff --git a/include/x86/mb_info.h b/include/x86/mb_info.h
> index 317bdfa..fd1bb1d 100644
> --- a/include/x86/mb_info.h
> +++ b/include/x86/mb_info.h
> @@ -172,6 +172,28 @@ struct multiboot_info
>  	uint16_t vbe_interface_seg;
>  	uint16_t vbe_interface_off;
>  	uint16_t vbe_interface_len;
> +
> +	uint64_t framebuffer_addr;
> +	uint32_t framebuffer_pitch;
> +	uint32_t framebuffer_width;
> +	uint32_t framebuffer_height;
> +	uint8_t  framebuffer_bpp;
> +	uint8_t	 framebuffer_type;
> +
> +	union {
> +		struct {
> +			uint32_t	framebuffer_palette_addr;
> +			uint16_t	framebuffer_palette_num_color;
> +		};
> +		struct {
> +			uint8_t		framebuffer_red_field_position;
> +			uint8_t		framebuffer_red_mask_size;
> +			uint8_t		framebuffer_green_field_position;
> +			uint8_t		framebuffer_green_mask_size;
> +			uint8_t		framebuffer_blue_field_position;
> +			uint8_t		framebuffer_blue_mask_size;
> +		};
> +	};
>  };
>  
>  /*
> @@ -211,6 +233,11 @@ struct multiboot_info
>  
>  /* Is there video information?  */
>  #define MB_INFO_VIDEO_INFO		0x00000800
> +#define MB_INFO_FRAMEBUFFER_INFO	0x00001000
> +
> +#define MB_FRAMEBUFFER_TYPE_INDEXED	0
> +#define MB_FRAMEBUFFER_TYPE_RGB		1
> +#define MB_FRAMEBUFFER_TYPE_EGA_TEXT	2
>  
>  /*
>   *  The following value must be present in the EAX register.
> diff --git a/kexec/arch/i386/kexec-multiboot-x86.c b/kexec/arch/i386/kexec-multiboot-x86.c
> index 69027e2..9bba4c1 100644
> --- a/kexec/arch/i386/kexec-multiboot-x86.c
> +++ b/kexec/arch/i386/kexec-multiboot-x86.c
> @@ -7,9 +7,6 @@
>   * 
>   *  TODO:  
>   *    - smarter allocation of new segments
> - *    - proper support for the MULTIBOOT_VIDEO_MODE bit
> - *    - support for the MULTIBOOT_AOUT_KLUDGE bit
> - *
>   *
>   *  Copyright (C) 2003  Tim Deegan (tjd21 at cl.cam.ac.uk)
>   * 
> @@ -56,21 +53,23 @@
>  #include <x86/mb_header.h>
>  #include <x86/mb_info.h>
>  
> +/* Framebuffer */
> +#include <sys/ioctl.h>
> +#include <linux/fb.h>
> +
>  /* Static storage */
>  static char headerbuf[MULTIBOOT_SEARCH];
>  static struct multiboot_header *mbh = NULL;
> +static off_t mbh_offset = 0;
>  
> -#define MIN(_x,_y) (((_x)<=(_y))?(_x):(_y))
> +extern struct arch_options_t arch_options;
>  
> +#define MIN(_x,_y) (((_x)<=(_y))?(_x):(_y))
>  
>  int multiboot_x86_probe(const char *buf, off_t buf_len)
>  /* Is it a good idea to try booting this file? */
>  {
>  	int i, len;
> -	/* First of all, check that this is an ELF file */
> -	if ((i=elf_x86_probe(buf, buf_len)) < 0) {
> -		return i;
> -	}

I'm a little confused about how we can parse the file if we don't know its
type. Perhaps rather than removing this check it should be an x || y check?

>  	/* Now look for a multiboot header in the first 8KB */
>  	len = MULTIBOOT_SEARCH;
>  	if (len > buf_len) {
> @@ -81,10 +80,10 @@ int multiboot_x86_probe(const char *buf, off_t buf_len)
>  		/* Short file */
>  		return -1;
>  	}
> -	for (i = 0; i <= (len - 12); i += 4)
> +	for (mbh_offset = 0; mbh_offset <= (len - 12); mbh_offset += 4)
>  	{
>  		/* Search for a multiboot header */
> -		mbh = (struct multiboot_header *)(headerbuf + i);
> +		mbh = (struct multiboot_header *)(headerbuf + mbh_offset);
>  		if (mbh->magic != MULTIBOOT_MAGIC 
>  		    || ((mbh->magic+mbh->flags+mbh->checksum) & 0xffffffff))
>  		{
> @@ -92,13 +91,34 @@ int multiboot_x86_probe(const char *buf, off_t buf_len)
>  			continue;
>  		}
>  		if (mbh->flags & MULTIBOOT_AOUT_KLUDGE) {
> -			/* Requires options we don't support */
> -			fprintf(stderr, 
> -				"Found a multiboot header, but it uses "
> -				"a non-ELF header layout,\n"
> -				"and I can't do that (yet).  Sorry.\n");
> -			return -1;
> -		} 
> +			if (mbh->load_addr & 0xfff) {
> +				fprintf(stderr, "multiboot load address not 4k aligned\n");
> +				return -1;
> +			}
> +			if (mbh->load_addr > mbh->header_addr) {
> +				fprintf(stderr, "multiboot header address > load address\n");
> +				return -1;
> +			}
> +			if (mbh->load_end_addr < mbh->load_addr) {
> +				fprintf(stderr, "multiboot load end address < load address\n");
> +				return -1;
> +			}
> +			if (mbh->bss_end_addr < mbh->load_end_addr) {
> +				fprintf(stderr, "multiboot bss end address < load end address\n");
> +				return -1;
> +			}
> +			if (mbh->load_end_addr - mbh->header_addr > buf_len - mbh_offset) {
> +				fprintf(stderr, "multiboot file truncated\n");
> +				return -1;
> +			}
> +			if (mbh->entry_addr < mbh->load_addr || mbh->entry_addr >= mbh->load_end_addr) {
> +				fprintf(stderr, "multiboot entry out of range\n");
> +				return -1;
> +			}
> +		} else {
> +			if ((i=elf_x86_probe(buf, buf_len)) < 0)
> +				return i;
> +		}
>  		if (mbh->flags & MULTIBOOT_UNSUPPORTED) {
>  			/* Requires options we don't support */
>  			fprintf(stderr, 
> @@ -107,16 +127,6 @@ int multiboot_x86_probe(const char *buf, off_t buf_len)
>  				"don't understand.  Sorry.\n");
>  			return -1;
>  		} 
> -		if (mbh->flags & MULTIBOOT_VIDEO_MODE) { 
> -			/* Asked for screen mode information */
> -			/* XXX carry on regardless */
> -			fprintf(stderr, 
> -				"BEWARE!  Found a multiboot header which asks "
> -				"for screen mode information.\n"
> -				"BEWARE!  I am NOT supplying screen mode "
> -                                "information, but loading it regardless.\n");
> -			
> -		}
>  		/* Bootable */
>  		return 0;
>  	}
> @@ -134,6 +144,75 @@ void multiboot_x86_usage(void)
>  	printf("                                 (can be used multiple times).\n");
>  }
>  
> +static int framebuffer_info(struct multiboot_info *mbi)
> +{
> +	struct fb_fix_screeninfo info;
> +	struct fb_var_screeninfo mode;
> +	int fd;
> +
> +	/* check if purgatory will reset to standard ega text mode */
> +	if (arch_options.reset_vga || arch_options.console_vga) {
> +		mbi->framebuffer_type = MB_FRAMEBUFFER_TYPE_EGA_TEXT;
> +		mbi->framebuffer_addr = 0xb8000;
> +		mbi->framebuffer_pitch = 80*2;
> +		mbi->framebuffer_width = 80;
> +		mbi->framebuffer_height = 25;
> +		mbi->framebuffer_bpp = 16;
> +
> +		mbi->flags |= MB_INFO_FRAMEBUFFER_INFO;
> +		return 0;
> +	}
> +
> +	/* use current graphics framebuffer settings */
> +	fd = open("/dev/fb0", O_RDONLY);
> +	if (fd < 0) {
> +		fprintf(stderr, "can't open /dev/fb0: %s\n", strerror(errno));
> +		return -1;
> +	}
> +	if (ioctl(fd, FBIOGET_FSCREENINFO, &info) < 0){
> +		fprintf(stderr, "can't get screeninfo: %s\n", strerror(errno));
> +		close(fd);
> +		return -1;
> +	}
> +	if (ioctl(fd, FBIOGET_VSCREENINFO, &mode) < 0){
> +		fprintf(stderr, "can't get modeinfo: %s\n", strerror(errno));
> +		close(fd);
> +		return -1;
> +	}
> +	close(fd);
> +
> +	if (info.smem_start == 0 || info.smem_len == 0) {
> +		fprintf(stderr, "can't get linerar framebuffer address\n");
> +		return -1;
> +	}
> +
> +	if (info.type != FB_TYPE_PACKED_PIXELS) {
> +		fprintf(stderr, "unsupported framebuffer type\n");
> +		return -1;
> +	}
> +
> +	if (info.visual != FB_VISUAL_TRUECOLOR) {
> +		fprintf(stderr, "unsupported framebuffer visual\n");
> +		return -1;
> +	}
> +
> +	mbi->framebuffer_type = MB_FRAMEBUFFER_TYPE_RGB;
> +	mbi->framebuffer_addr = info.smem_start;
> +	mbi->framebuffer_pitch = info.line_length;
> +	mbi->framebuffer_width = mode.xres;
> +	mbi->framebuffer_height = mode.yres;
> +	mbi->framebuffer_bpp = mode.bits_per_pixel;
> +	mbi->framebuffer_red_field_position = mode.red.offset;
> +	mbi->framebuffer_red_mask_size = mode.red.length;
> +	mbi->framebuffer_green_field_position = mode.green.offset;
> +	mbi->framebuffer_green_mask_size = mode.green.length;
> +	mbi->framebuffer_blue_field_position = mode.blue.offset;
> +	mbi->framebuffer_blue_mask_size = mode.blue.length;
> +
> +	mbi->flags |= MB_INFO_FRAMEBUFFER_INFO;
> +	return 0;
> +}
> +
>  int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
>  	struct kexec_info *info)
>  /* Marshal up a multiboot-style kernel */
> @@ -154,7 +233,7 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
>  	struct AddrRangeDesc *mmap;
>  	int command_line_len;
>  	int i, result;
> -	uint32_t u;
> +	uint32_t u, entry;
>  	int opt;
>  	int modules, mod_command_line_space;
>  	/* See options.h -- add any more there, too. */
> @@ -211,8 +290,18 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
>  	}
>  	command_line_len = strlen(command_line) + 1;
>  	
> -	/* Load the ELF executable */
> -	elf_exec_build_load(info, &ehdr, buf, len, 0);
> +	if (mbh->flags & MULTIBOOT_AOUT_KLUDGE) {
> +		add_segment(info,
> +			buf + (mbh_offset - (mbh->header_addr - mbh->load_addr)),
> +			mbh->load_end_addr - mbh->load_addr,
> +			mbh->load_addr,
> +			mbh->bss_end_addr - mbh->load_addr);
> +		entry = mbh->entry_addr;
> +	} else {
> +		/* Load the ELF executable */
> +		elf_exec_build_load(info, &ehdr, buf, len, 0);
> +		entry = ehdr.e_entry;
> +	}
>  
>  	/* Load the setup code */
>  	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, 0,
> @@ -259,7 +348,8 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
>  		mmap[i].base_addr_high  = range[i].start >> 32;
>  		mmap[i].length_low     = length & 0xffffffff;
>  		mmap[i].length_high    = length >> 32;
> -		if (range[i].type == RANGE_RAM) {
> +		switch (range[i].type) {
> +		case RANGE_RAM:
>  			mmap[i].Type = 1; /* RAM */
>  			/*
>                           * Is this the "low" memory?  Can't just test
> @@ -277,7 +367,15 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
>  			if ((range[i].start <= 0x100000)
>  			    && (range[i].end > mem_upper + 0x100000))
>  				mem_upper = range[i].end - 0x100000;
> -		} else {
> +			break;
> +		case RANGE_ACPI:
> +			mmap[i].Type = 3;
> +			break;
> +		case RANGE_ACPI_NVS:
> +			mmap[i].Type = 4;
> +			break;
> +		case RANGE_RESERVED:
> +		default:
>  			mmap[i].Type = 2;  /* Not RAM (reserved) */
>  		}
>  	}
> @@ -302,6 +400,12 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
>  		/* done */
>  	}
>  
> +	/* Video */
> +	if (mbh->flags & MULTIBOOT_VIDEO_MODE) {
> +		if (framebuffer_info(mbi) < 0)
> +			fprintf(stderr, "not providing framebuffer information.\n");
> +	}
> +
>  	/* Load modules */
>  	if (modules) {
>  		char *mod_filename, *mod_command_line, *mod_clp, *buf;
> @@ -384,7 +488,7 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
>  	elf_rel_get_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
>  	regs.eax = 0x2BADB002;
>  	regs.ebx = mbi_offset;
> -	regs.eip = ehdr.e_entry;
> +	regs.eip = entry;
>  	elf_rel_set_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
>  
>  out:


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 2+ messages in thread

* multiboot non-elf and framebuffer support for kexec-tools
@ 2018-07-28 16:18 cinap_lenrek
  0 siblings, 0 replies; 2+ messages in thread
From: cinap_lenrek @ 2018-07-28 16:18 UTC (permalink / raw)
  To: kexec

[-- Attachment #1: Type: text/plain, Size: 580 bytes --]

theres a patch that provides support for non-elf multiboot kernels
and passes framebuffer information to the kernel if requested in
the multiboot header.

only rgb truecolor framebuffers are supported right now. if --reset-vga
or --console-vga was specified, it assumes the framebuffer will be
standard ega text mode.

also pass acpi nvs and acpi reclaim ranges in the multiboot memory
map as such; instead of just reserved. this allowing to kernel to
locate acpi tables on uefi systems.

i'm new on the list, so is there a prefered address to send patches
like this to?

--
cinap

[-- Attachment #2: Type: text/plain, Size: 9827 bytes --]

diff --git a/include/x86/mb_info.h b/include/x86/mb_info.h
index 317bdfa..fd1bb1d 100644
--- a/include/x86/mb_info.h
+++ b/include/x86/mb_info.h
@@ -172,6 +172,28 @@ struct multiboot_info
 	uint16_t vbe_interface_seg;
 	uint16_t vbe_interface_off;
 	uint16_t vbe_interface_len;
+
+	uint64_t framebuffer_addr;
+	uint32_t framebuffer_pitch;
+	uint32_t framebuffer_width;
+	uint32_t framebuffer_height;
+	uint8_t  framebuffer_bpp;
+	uint8_t	 framebuffer_type;
+
+	union {
+		struct {
+			uint32_t	framebuffer_palette_addr;
+			uint16_t	framebuffer_palette_num_color;
+		};
+		struct {
+			uint8_t		framebuffer_red_field_position;
+			uint8_t		framebuffer_red_mask_size;
+			uint8_t		framebuffer_green_field_position;
+			uint8_t		framebuffer_green_mask_size;
+			uint8_t		framebuffer_blue_field_position;
+			uint8_t		framebuffer_blue_mask_size;
+		};
+	};
 };
 
 /*
@@ -211,6 +233,11 @@ struct multiboot_info
 
 /* Is there video information?  */
 #define MB_INFO_VIDEO_INFO		0x00000800
+#define MB_INFO_FRAMEBUFFER_INFO	0x00001000
+
+#define MB_FRAMEBUFFER_TYPE_INDEXED	0
+#define MB_FRAMEBUFFER_TYPE_RGB		1
+#define MB_FRAMEBUFFER_TYPE_EGA_TEXT	2
 
 /*
  *  The following value must be present in the EAX register.
diff --git a/kexec/arch/i386/kexec-multiboot-x86.c b/kexec/arch/i386/kexec-multiboot-x86.c
index 69027e2..9bba4c1 100644
--- a/kexec/arch/i386/kexec-multiboot-x86.c
+++ b/kexec/arch/i386/kexec-multiboot-x86.c
@@ -7,9 +7,6 @@
  * 
  *  TODO:  
  *    - smarter allocation of new segments
- *    - proper support for the MULTIBOOT_VIDEO_MODE bit
- *    - support for the MULTIBOOT_AOUT_KLUDGE bit
- *
  *
  *  Copyright (C) 2003  Tim Deegan (tjd21 at cl.cam.ac.uk)
  * 
@@ -56,21 +53,23 @@
 #include <x86/mb_header.h>
 #include <x86/mb_info.h>
 
+/* Framebuffer */
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+
 /* Static storage */
 static char headerbuf[MULTIBOOT_SEARCH];
 static struct multiboot_header *mbh = NULL;
+static off_t mbh_offset = 0;
 
-#define MIN(_x,_y) (((_x)<=(_y))?(_x):(_y))
+extern struct arch_options_t arch_options;
 
+#define MIN(_x,_y) (((_x)<=(_y))?(_x):(_y))
 
 int multiboot_x86_probe(const char *buf, off_t buf_len)
 /* Is it a good idea to try booting this file? */
 {
 	int i, len;
-	/* First of all, check that this is an ELF file */
-	if ((i=elf_x86_probe(buf, buf_len)) < 0) {
-		return i;
-	}
 	/* Now look for a multiboot header in the first 8KB */
 	len = MULTIBOOT_SEARCH;
 	if (len > buf_len) {
@@ -81,10 +80,10 @@ int multiboot_x86_probe(const char *buf, off_t buf_len)
 		/* Short file */
 		return -1;
 	}
-	for (i = 0; i <= (len - 12); i += 4)
+	for (mbh_offset = 0; mbh_offset <= (len - 12); mbh_offset += 4)
 	{
 		/* Search for a multiboot header */
-		mbh = (struct multiboot_header *)(headerbuf + i);
+		mbh = (struct multiboot_header *)(headerbuf + mbh_offset);
 		if (mbh->magic != MULTIBOOT_MAGIC 
 		    || ((mbh->magic+mbh->flags+mbh->checksum) & 0xffffffff))
 		{
@@ -92,13 +91,34 @@ int multiboot_x86_probe(const char *buf, off_t buf_len)
 			continue;
 		}
 		if (mbh->flags & MULTIBOOT_AOUT_KLUDGE) {
-			/* Requires options we don't support */
-			fprintf(stderr, 
-				"Found a multiboot header, but it uses "
-				"a non-ELF header layout,\n"
-				"and I can't do that (yet).  Sorry.\n");
-			return -1;
-		} 
+			if (mbh->load_addr & 0xfff) {
+				fprintf(stderr, "multiboot load address not 4k aligned\n");
+				return -1;
+			}
+			if (mbh->load_addr > mbh->header_addr) {
+				fprintf(stderr, "multiboot header address > load address\n");
+				return -1;
+			}
+			if (mbh->load_end_addr < mbh->load_addr) {
+				fprintf(stderr, "multiboot load end address < load address\n");
+				return -1;
+			}
+			if (mbh->bss_end_addr < mbh->load_end_addr) {
+				fprintf(stderr, "multiboot bss end address < load end address\n");
+				return -1;
+			}
+			if (mbh->load_end_addr - mbh->header_addr > buf_len - mbh_offset) {
+				fprintf(stderr, "multiboot file truncated\n");
+				return -1;
+			}
+			if (mbh->entry_addr < mbh->load_addr || mbh->entry_addr >= mbh->load_end_addr) {
+				fprintf(stderr, "multiboot entry out of range\n");
+				return -1;
+			}
+		} else {
+			if ((i=elf_x86_probe(buf, buf_len)) < 0)
+				return i;
+		}
 		if (mbh->flags & MULTIBOOT_UNSUPPORTED) {
 			/* Requires options we don't support */
 			fprintf(stderr, 
@@ -107,16 +127,6 @@ int multiboot_x86_probe(const char *buf, off_t buf_len)
 				"don't understand.  Sorry.\n");
 			return -1;
 		} 
-		if (mbh->flags & MULTIBOOT_VIDEO_MODE) { 
-			/* Asked for screen mode information */
-			/* XXX carry on regardless */
-			fprintf(stderr, 
-				"BEWARE!  Found a multiboot header which asks "
-				"for screen mode information.\n"
-				"BEWARE!  I am NOT supplying screen mode "
-                                "information, but loading it regardless.\n");
-			
-		}
 		/* Bootable */
 		return 0;
 	}
@@ -134,6 +144,75 @@ void multiboot_x86_usage(void)
 	printf("                                 (can be used multiple times).\n");
 }
 
+static int framebuffer_info(struct multiboot_info *mbi)
+{
+	struct fb_fix_screeninfo info;
+	struct fb_var_screeninfo mode;
+	int fd;
+
+	/* check if purgatory will reset to standard ega text mode */
+	if (arch_options.reset_vga || arch_options.console_vga) {
+		mbi->framebuffer_type = MB_FRAMEBUFFER_TYPE_EGA_TEXT;
+		mbi->framebuffer_addr = 0xb8000;
+		mbi->framebuffer_pitch = 80*2;
+		mbi->framebuffer_width = 80;
+		mbi->framebuffer_height = 25;
+		mbi->framebuffer_bpp = 16;
+
+		mbi->flags |= MB_INFO_FRAMEBUFFER_INFO;
+		return 0;
+	}
+
+	/* use current graphics framebuffer settings */
+	fd = open("/dev/fb0", O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr, "can't open /dev/fb0: %s\n", strerror(errno));
+		return -1;
+	}
+	if (ioctl(fd, FBIOGET_FSCREENINFO, &info) < 0){
+		fprintf(stderr, "can't get screeninfo: %s\n", strerror(errno));
+		close(fd);
+		return -1;
+	}
+	if (ioctl(fd, FBIOGET_VSCREENINFO, &mode) < 0){
+		fprintf(stderr, "can't get modeinfo: %s\n", strerror(errno));
+		close(fd);
+		return -1;
+	}
+	close(fd);
+
+	if (info.smem_start == 0 || info.smem_len == 0) {
+		fprintf(stderr, "can't get linerar framebuffer address\n");
+		return -1;
+	}
+
+	if (info.type != FB_TYPE_PACKED_PIXELS) {
+		fprintf(stderr, "unsupported framebuffer type\n");
+		return -1;
+	}
+
+	if (info.visual != FB_VISUAL_TRUECOLOR) {
+		fprintf(stderr, "unsupported framebuffer visual\n");
+		return -1;
+	}
+
+	mbi->framebuffer_type = MB_FRAMEBUFFER_TYPE_RGB;
+	mbi->framebuffer_addr = info.smem_start;
+	mbi->framebuffer_pitch = info.line_length;
+	mbi->framebuffer_width = mode.xres;
+	mbi->framebuffer_height = mode.yres;
+	mbi->framebuffer_bpp = mode.bits_per_pixel;
+	mbi->framebuffer_red_field_position = mode.red.offset;
+	mbi->framebuffer_red_mask_size = mode.red.length;
+	mbi->framebuffer_green_field_position = mode.green.offset;
+	mbi->framebuffer_green_mask_size = mode.green.length;
+	mbi->framebuffer_blue_field_position = mode.blue.offset;
+	mbi->framebuffer_blue_mask_size = mode.blue.length;
+
+	mbi->flags |= MB_INFO_FRAMEBUFFER_INFO;
+	return 0;
+}
+
 int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info)
 /* Marshal up a multiboot-style kernel */
@@ -154,7 +233,7 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
 	struct AddrRangeDesc *mmap;
 	int command_line_len;
 	int i, result;
-	uint32_t u;
+	uint32_t u, entry;
 	int opt;
 	int modules, mod_command_line_space;
 	/* See options.h -- add any more there, too. */
@@ -211,8 +290,18 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
 	}
 	command_line_len = strlen(command_line) + 1;
 	
-	/* Load the ELF executable */
-	elf_exec_build_load(info, &ehdr, buf, len, 0);
+	if (mbh->flags & MULTIBOOT_AOUT_KLUDGE) {
+		add_segment(info,
+			buf + (mbh_offset - (mbh->header_addr - mbh->load_addr)),
+			mbh->load_end_addr - mbh->load_addr,
+			mbh->load_addr,
+			mbh->bss_end_addr - mbh->load_addr);
+		entry = mbh->entry_addr;
+	} else {
+		/* Load the ELF executable */
+		elf_exec_build_load(info, &ehdr, buf, len, 0);
+		entry = ehdr.e_entry;
+	}
 
 	/* Load the setup code */
 	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, 0,
@@ -259,7 +348,8 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
 		mmap[i].base_addr_high  = range[i].start >> 32;
 		mmap[i].length_low     = length & 0xffffffff;
 		mmap[i].length_high    = length >> 32;
-		if (range[i].type == RANGE_RAM) {
+		switch (range[i].type) {
+		case RANGE_RAM:
 			mmap[i].Type = 1; /* RAM */
 			/*
                          * Is this the "low" memory?  Can't just test
@@ -277,7 +367,15 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
 			if ((range[i].start <= 0x100000)
 			    && (range[i].end > mem_upper + 0x100000))
 				mem_upper = range[i].end - 0x100000;
-		} else {
+			break;
+		case RANGE_ACPI:
+			mmap[i].Type = 3;
+			break;
+		case RANGE_ACPI_NVS:
+			mmap[i].Type = 4;
+			break;
+		case RANGE_RESERVED:
+		default:
 			mmap[i].Type = 2;  /* Not RAM (reserved) */
 		}
 	}
@@ -302,6 +400,12 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
 		/* done */
 	}
 
+	/* Video */
+	if (mbh->flags & MULTIBOOT_VIDEO_MODE) {
+		if (framebuffer_info(mbi) < 0)
+			fprintf(stderr, "not providing framebuffer information.\n");
+	}
+
 	/* Load modules */
 	if (modules) {
 		char *mod_filename, *mod_command_line, *mod_clp, *buf;
@@ -384,7 +488,7 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
 	elf_rel_get_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
 	regs.eax = 0x2BADB002;
 	regs.ebx = mbi_offset;
-	regs.eip = ehdr.e_entry;
+	regs.eip = entry;
 	elf_rel_set_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
 
 out:

[-- Attachment #3: Type: text/plain, Size: 143 bytes --]

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2018-08-02 10:14 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <34EA379E6200FBA190C21A4D9996C7AB@felloff.net>
2018-08-02 10:14 ` multiboot non-elf and framebuffer support for kexec-tools Simon Horman
2018-07-28 16:18 cinap_lenrek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.