All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] multiboot-x86: support for non-elf kernels
@ 2018-08-02 14:04 cinap_lenrek
  2018-09-11 11:53 ` Simon Horman
  0 siblings, 1 reply; 3+ messages in thread
From: cinap_lenrek @ 2018-08-02 14:04 UTC (permalink / raw)
  To: kexec; +Cc: horms

Add support for non-elf multiboot kernels (such as Plan 9)
by handling the MULTIBOOT_AOUT_KLUDGE bit.

When the bit is clear then we are dealing with an ELF file
and probe for ELF as before with elf_x86_probe().

When the bit is set then load_addr, load_end_addr, header_addr
and entry_addr from the multiboot header are used load the
memory image.

Signed-off-by: Friedemann Gerold <cinap_lenrek@felloff.net>
---
diff --git a/kexec/arch/i386/kexec-multiboot-x86.c b/kexec/arch/i386/kexec-multiboot-x86.c
index 69027e2..afa0959 100644
--- a/kexec/arch/i386/kexec-multiboot-x86.c
+++ b/kexec/arch/i386/kexec-multiboot-x86.c
@@ -8,7 +8,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)
@@ -59,6 +58,7 @@
 /* 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))
 
@@ -67,10 +67,6 @@ 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 +77,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 +88,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, 
@@ -154,7 +171,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 +228,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,
@@ -384,7 +420,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 related	[flat|nested] 3+ messages in thread

* Re: [PATCH] multiboot-x86: support for non-elf kernels
  2018-08-02 14:04 [PATCH] multiboot-x86: support for non-elf kernels cinap_lenrek
@ 2018-09-11 11:53 ` Simon Horman
  0 siblings, 0 replies; 3+ messages in thread
From: Simon Horman @ 2018-09-11 11:53 UTC (permalink / raw)
  To: cinap_lenrek; +Cc: kexec

Hi,

thanks for your patch and sorry for the delay in reviewing it.

On Thu, Aug 02, 2018 at 04:04:01PM +0200, cinap_lenrek@felloff.net wrote:
> Add support for non-elf multiboot kernels (such as Plan 9)
> by handling the MULTIBOOT_AOUT_KLUDGE bit.
> 
> When the bit is clear then we are dealing with an ELF file
> and probe for ELF as before with elf_x86_probe().
> 
> When the bit is set then load_addr, load_end_addr, header_addr
> and entry_addr from the multiboot header are used load the
> memory image.
> 
> Signed-off-by: Friedemann Gerold <cinap_lenrek@felloff.net>
> ---
> diff --git a/kexec/arch/i386/kexec-multiboot-x86.c b/kexec/arch/i386/kexec-multiboot-x86.c
> index 69027e2..afa0959 100644
> --- a/kexec/arch/i386/kexec-multiboot-x86.c
> +++ b/kexec/arch/i386/kexec-multiboot-x86.c
> @@ -8,7 +8,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)
> @@ -59,6 +58,7 @@
>  /* Static storage */
>  static char headerbuf[MULTIBOOT_SEARCH];
>  static struct multiboot_header *mbh = NULL;
> +static off_t mbh_offset = 0;

I would prefer if we moved to fewer rather than more global variables.
But perhaps that is a bigger question than this patch seeks to answer.

>  
>  #define MIN(_x,_y) (((_x)<=(_y))?(_x):(_y))
>  
> @@ -67,10 +67,6 @@ 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 +77,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 +88,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;

Is it desirable for this check to be run for each iteration of the loop.

> +		}
>  		if (mbh->flags & MULTIBOOT_UNSUPPORTED) {
>  			/* Requires options we don't support */
>  			fprintf(stderr, 
> @@ -154,7 +171,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 +228,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,
> @@ -384,7 +420,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
> 

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

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

* Re: [PATCH] multiboot-x86: support for non-elf kernels
@ 2018-09-11 17:07 cinap_lenrek
  0 siblings, 0 replies; 3+ messages in thread
From: cinap_lenrek @ 2018-09-11 17:07 UTC (permalink / raw)
  To: horms; +Cc: kexec

> Is it desirable for this check to be run for each iteration of the loop.

thats is not really the case. that statemet is executed exactly once.
the first check in the loop body looks for the multiboot header
signature and continues the loop if not found. once that check
passes the iteration ends as we return at the bottom of the loop
body, and there are no other continues.

	for (mbh_offset = 0; mbh_offset <= (len - 12); mbh_offset += 4)
 	{
 		/* Search for a multiboot header */
		mbh = (struct multiboot_header *)(headerbuf + mbh_offset);
 		if (mbh->magic != MULTIBOOT_MAGIC 
 		    || ((mbh->magic+mbh->flags+mbh->checksum) & 0xffffffff))
 		{
			/* Not a multiboot header */
 			continue;
 		}
....

--
cinap

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

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

end of thread, other threads:[~2018-09-11 17:08 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-02 14:04 [PATCH] multiboot-x86: support for non-elf kernels cinap_lenrek
2018-09-11 11:53 ` Simon Horman
2018-09-11 17:07 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.