Skip to contentSkip to conversation

Moving kernel_entry to LOADADDR

DISCUSSION Gerald Champagne 7 participants 9 messages Oct 19, 2001 – Oct 24, 2001 MIPS

lore
Share & tools
lore
#0 lore raw

I'm planning to work with a very minimal boot loader, and I'd like to hard-code a jump to kernel_entry in my boot loader. I got tired of having kernel_entry moving around, so I just moved it to the top of head.S, just afte the ".fill 0x280". That places kernel_entry at the same place every time. It's always at LOADADDR+0x280.

But wait a minute... the 0x280 is there to leave room for the exception vectors. Doesn't that only make sense if LOADADDR=0x80000000? Isn't this allocating the space for the exception vectors twice? Why not remove the .fill, then the kernel entry point will always be exactly LOADADDR? This would break any configuration that has LOADADDR=0x80000000, but the only configuration like that is CONFIG_ALGOR_P4032, and that could easily be modified to LOADADDR=0x80000280 to get the same effect.

I also removed the .fill, and now kernel_entry is always exactly LOADADDR, and that makes my bootloader easier to maintain.

Is this worth changing in cvs, or did I miss something?

Thanks.

Gerald

#1 lore raw

Gerald,

Quoted 4 lines

to hard-code a jump to kernel_entry in my boot loader. I got tired of having kernel_entry moving around, so I just moved it to the top of head.S, just afte the ".fill 0x280". That places kernel_entry at the same place every time. It's always at LOADADDR+0x280.

Don't know about all .fill & exception vecs... the trick I use in my (vr)boot loader...

KERNEL_ENTRY=$(shell awk '/kernel_entry/{print "0x" $$1}' $(LINUX_SRC)/System.map) CFLAGS+=-DKERNEL_ENTRY=$(KERNEL_ENTRY)

And compile boot.S or whatever your bootloader is.

But a fixed, well-known offset can't be a bad thing either.

Geoff

Signature · 1 line
Geoffrey Espin [email protected]
#2 lore raw
In reply to Gerald Champagne
Quoted 1 line · Gerald Champagne

Is this worth changing in cvs, or did I miss something?

Embed your kernel in your own bootloader, load the bootloader from fixed addr. In the bootloader move the kernel at any location you want and jump to the kernel entry. The kernel entry is known at compile time, so you can teach the bootloader. This way you won't disturb others.

Regards,
Gleb.

#3 lore raw
In reply to Gerald Champagne
Quoted 4 lines · Gerald Champagne

I also removed the .fill, and now kernel_entry is always exactly LOADADDR, and that makes my bootloader easier to maintain.

Is this worth changing in cvs, or did I miss something?

How about just getting it from the ELF header? It's trivial.

Signature · 3 lines
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email protected], PGP key available        +
#4 lore raw
Quoted 6 lines

Date: Fri, 19 Oct 2001 15:20:33 +0200 (MET DST)
From: "Maciej W. Rozycki" <[email protected]>
To: Gerald Champagne <[email protected]>
Subject: Re: Moving kernel_entry to LOADADDR

Quoted 8 lines
Quoted 4 lines · Gerald Champagne

I also removed the .fill, and now kernel_entry is always exactly LOADADDR, and that makes my bootloader easier to maintain.

Is this worth changing in cvs, or did I miss something?

How about just getting it from the ELF header? It's trivial.

Because a bare bones bootloader may not know anything about ELF. The
simplest solution is to just stick a "jmp start_kernel" at LOADADDR right before the fill. Then the load address and the entry point are the same. Once the exception vectors get loaded, they'll overwrite the jmp, so no space is wasted and none of the LOADADDRs have to be changed.

Mike McDonald
[email protected]

#5 lore raw
Quoted 10 lines
Quoted 3 lines

How about just getting it from the ELF header? It's trivial.

Because a bare bones bootloader may not know anything about ELF. The
simplest solution is to just stick a "jmp start_kernel" at LOADADDR right before the fill. Then the load address and the entry point are the same. Once the exception vectors get loaded, they'll overwrite the jmp, so no space is wasted and none of the LOADADDRs have to be changed.

That was my thinking.

Except the fill has nothing to do with exception vectors any more. It looks like at one time LOADADDR was always 0x8000_0000. Now that it's set to something else, the fill just leaves a hole for no reason. That's why I recommend removing it regardless of whether there's a use for my idea.

With the fill is gone, and since the kernel is not normally placed at 0x8000_0000, I suggest just moving kernel_entry to the top of head.S instead of putting a jump at the top of the file.

Also, compile tricks won't work (at least in my case). Normally the bootloader and the kernel are in two memories, often programmed in different ways. For example, a system normally has rom at the boot address at 0x1fc0_0000, ram at 0x8000_0000, and some other memory (flash, hard disk, whatever) storing a kernel (or kernels) somewhere else. Any compile time tricks require the boot rom to be reprogrammed when the kernel changes. That's part of what I wanted to avoid.

Gerald

#6 lore raw
In reply to Mike McDonald
Quoted 6 lines · Mike McDonald

Because a bare bones bootloader may not know anything about ELF. The
simplest solution is to just stick a "jmp start_kernel" at LOADADDR right before the fill. Then the load address and the entry point are the same. Once the exception vectors get loaded, they'll overwrite the jmp, so no space is wasted and none of the LOADADDRs have to be changed.

This may be true, but grokking ELF far enough to find e_entry just a matter of looking at a fixed offset into the kernel image. Problems that require bootloaders to be simpler than that are pretty rare...

-Justin

#7 lore raw
Quoted 16 lines

Subject: Re: Moving kernel_entry to LOADADDR
From: Justin Carlson <[email protected]>
To: [email protected]
Date: 19 Oct 2001 11:21:41 -0400

Quoted 6 lines · Mike McDonald

Because a bare bones bootloader may not know anything about ELF. The
simplest solution is to just stick a "jmp start_kernel" at LOADADDR right before the fill. Then the load address and the entry point are the same. Once the exception vectors get loaded, they'll overwrite the jmp, so no space is wasted and none of the LOADADDRs have to be changed.

Quoted 5 lines

This may be true, but grokking ELF far enough to find e_entry just a matter of looking at a fixed offset into the kernel image. Problems that require bootloaders to be simpler than that are pretty rare...

-Justin

But they do exist, especially in the embedded world. For instance,
I've run linux with boot loader out of a 1MB flash into 8MB of RAM. (VR4121 based system.) The kernel image stored in the flash had to be a compressed raw memory image inorder to fit in the flash. (The flash also had to have room to the initrd.) Adding ELF headers to the image would probably have pushed the size over the limit.

Mike McDonald
[email protected]

#8 lore raw
In reply to Gerald Champagne
Quoted 5 lines · Gerald Champagne

I'm planning to work with a very minimal boot loader, and I'd like to hard-code a jump to kernel_entry in my boot loader. I got tired of having kernel_entry moving around, so I just moved it to the top of head.S, just afte the ".fill 0x280". That places kernel_entry at the same place every time. It's always at LOADADDR+0x280.

Dont do this - Its easy to decode the elf stuff:

Basically this is the code needed to relocate the elf chunks
and return the entry point. I might have corrupted it a bit due to stripping unneeded bits but you will get the point. This code even clears bss chunk which the kernel will do itself again.

	Elf32_Ehdr	*fhdr = fb;
	Elf32_Shdr	*shdr;	
	int		i;

	if (fhdr->e_machine != EM_MIPS) {
		printf("No Mips ELF\n");
		return(0);	
	}

	fhdr=(void *) KSEG1ADDR(fb);

	shdr=fb + fhdr->e_shoff;

	for(i=0;i<fhdr->e_shnum;i++,shdr++) {

		if (shdr->sh_size <= 0) 
			continue;

		if (shdr->sh_type == SHT_PROGBITS) {
			memcpy((void *) KSEG1ADDR(shdr->sh_addr),
				KSEG1ADDR(fb + shdr->sh_offset),
				shdr->sh_size);
		} else if (shdr->sh_type == SHT_NOBITS) {
			memset((void *) KSEG1ADDR(shdr->sh_addr), 0x0, shdr->sh_size);
		}
	}
	return((void *) fhdr->e_entry);
Signature · 2 lines
Florian Lohoff                  [email protected]             +49-5201-669912
Nine nineth on september the 9th              Welcome to the new billenium