Re: [PATCH] multiboot-x86: support for non-elf kernels

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxx 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@xxxxxxxxxxx>
> ---
> 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@xxxxxxxxxxxxxxxxxxx
> http://lists.infradead.org/mailman/listinfo/kexec
> 

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



[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux