FreeBSD/sys/mips/mips/elf_trampoline.c
/*
 * Relocate PT_LOAD segements of kernel ELF image to their respective
 * virtual addresses and return entry point
 */
Relocate PT_LOAD segements of kernel ELF image to their respective
virtual addresses and return entry point
Relocate PT_LOAD segements of kernel ELF image to their respective virtual addresses and return entry point
void *
load_kernel(void * kstart)
{
#if ELFSIZE == 64
	Elf64_Ehdr *eh;
	Elf64_Phdr phdr[64] ;
	Elf64_Shdr shdr[64] ;
#else
	Elf32_Ehdr *eh;
	Elf32_Phdr phdr[64] ;
	Elf32_Shdr shdr[64] ;
#endif
	int i, j;
	void *entry_point;
	vm_offset_t loadend = 0;
	intptr_t lastaddr;
	int symtabindex = -1;
	int symstrindex = -1;
	Elf_Size tmp;
#if ELFSIZE == 64
	eh = (Elf64_Ehdr *)kstart;
#else
	eh = (Elf32_Ehdr *)kstart;
#endif
	entry_point = mkptr(eh->e_entry);
	memcpy(phdr, (void *)(kstart + eh->e_phoff),
	    eh->e_phnum * sizeof(phdr[0]));
	memcpy(shdr, (void *)(kstart + eh->e_shoff),
	    sizeof(*shdr) * eh->e_shnum);
	if (eh->e_shnum * eh->e_shentsize != 0 && eh->e_shoff != 0) {
		for (i = 0; i < eh->e_shnum; i++) {
			if (shdr[i].sh_type == SHT_SYMTAB) {
				if (shdr[i].sh_offset != 0 && 
				    shdr[i].sh_size != 0) {
					symtabindex = i;
					symstrindex = shdr[i].sh_link;
				}
			}
		}
	}
	for (i = 0; i < eh->e_phnum; i++) {
		volatile char c;
		if (phdr[i].p_type != PT_LOAD)
			continue;
		memcpy(mkptr(phdr[i].p_vaddr),
		    (void*)(kstart + phdr[i].p_offset), phdr[i].p_filesz);
		if (phdr[i].p_filesz < phdr[i].p_memsz)
			bzero(mkptr(phdr[i].p_vaddr + phdr[i].p_filesz),
			    phdr[i].p_memsz - phdr[i].p_filesz);
		if (loadend < phdr[i].p_vaddr + phdr[i].p_memsz)
			loadend = phdr[i].p_vaddr + phdr[i].p_memsz;
	}
	lastaddr = (intptr_t)(int)loadend;
	if (symtabindex >= 0 && symstrindex >= 0) {
		tmp = SYMTAB_MAGIC;
		memcpy((void *)lastaddr, &tmp, sizeof(tmp));
		lastaddr += sizeof(Elf_Size);
		tmp = shdr[symtabindex].sh_size +
		    shdr[symstrindex].sh_size + 2*sizeof(Elf_Size);
		memcpy((void *)lastaddr, &tmp, sizeof(tmp));
		lastaddr += sizeof(Elf_Size);
		tmp = shdr[symtabindex].sh_size;
		memcpy((void *)lastaddr, &tmp, sizeof(tmp));
		lastaddr += sizeof(shdr[symtabindex].sh_size);
		memcpy((void*)lastaddr,
		    shdr[symtabindex].sh_offset + kstart,
		    shdr[symtabindex].sh_size);
		lastaddr += shdr[symtabindex].sh_size;
		tmp = shdr[symstrindex].sh_size;
		memcpy((void *)lastaddr, &tmp, sizeof(tmp));
		lastaddr += sizeof(shdr[symstrindex].sh_size);
		memcpy((void*)lastaddr,
		    shdr[symstrindex].sh_offset + kstart,
		    shdr[symstrindex].sh_size);
	} else {
		tmp = 0;
		memcpy((void *)lastaddr, &tmp, sizeof(tmp));
	}
	return entry_point;
}
void * load_kernel ( void * kstart ) { #if ELFSIZE == 64 Elf64_Ehdr * eh ; Elf64_Phdr phdr [ 64 ] ; Elf64_Shdr shdr [ 64 ] ; #else Elf32_Ehdr * eh ; Elf32_Phdr phdr [ 64 ] ; Elf32_Shdr shdr [ 64 ] ; #endif int i , j ; void * entry_point ; vm_offset_t loadend = 0 ; intptr_t lastaddr ; int symtabindex = -1 ; int symstrindex = -1 ; Elf_Size tmp ; #if ELFSIZE == 64 eh = ( Elf64_Ehdr * ) kstart ; #else eh = ( Elf32_Ehdr * ) kstart ; #endif entry_point = mkptr ( eh -> e_entry ) ; memcpy ( phdr , ( void * ) ( kstart + eh -> e_phoff ) , eh -> e_phnum * sizeof ( phdr [ 0 ] ) ) ; memcpy ( shdr , ( void * ) ( kstart + eh -> e_shoff ) , sizeof ( * shdr ) * eh -> e_shnum ) ; if ( eh -> e_shnum * eh -> e_shentsize != 0 && eh -> e_shoff != 0 ) { for ( i = 0 ; i < eh -> e_shnum ; i ++ ) { if ( shdr [ i ] . sh_type == SHT_SYMTAB ) { if ( shdr [ i ] . sh_offset != 0 && shdr [ i ] . sh_size != 0 ) { symtabindex = i ; symstrindex = shdr [ i ] . sh_link ; } } } } for ( i = 0 ; i < eh -> e_phnum ; i ++ ) { volatile char c ; if ( phdr [ i ] . p_type != PT_LOAD ) continue ; memcpy ( mkptr ( phdr [ i ] . p_vaddr ) , ( void * ) ( kstart + phdr [ i ] . p_offset ) , phdr [ i ] . p_filesz ) ; if ( phdr [ i ] . p_filesz < phdr [ i ] . p_memsz ) bzero ( mkptr ( phdr [ i ] . p_vaddr + phdr [ i ] . p_filesz ) , phdr [ i ] . p_memsz - phdr [ i ] . p_filesz ) ; if ( loadend < phdr [ i ] . p_vaddr + phdr [ i ] . p_memsz ) loadend = phdr [ i ] . p_vaddr + phdr [ i ] . p_memsz ; } lastaddr = ( intptr_t ) ( int ) loadend ; if ( symtabindex >= 0 && symstrindex >= 0 ) { tmp = SYMTAB_MAGIC ; memcpy ( ( void * ) lastaddr , & tmp , sizeof ( tmp ) ) ; lastaddr += sizeof ( Elf_Size ) ; tmp = shdr [ symtabindex ] . sh_size + shdr [ symstrindex ] . sh_size + 2 * sizeof ( Elf_Size ) ; memcpy ( ( void * ) lastaddr , & tmp , sizeof ( tmp ) ) ; lastaddr += sizeof ( Elf_Size ) ; tmp = shdr [ symtabindex ] . sh_size ; memcpy ( ( void * ) lastaddr , & tmp , sizeof ( tmp ) ) ; lastaddr += sizeof ( shdr [ symtabindex ] . sh_size ) ; memcpy ( ( void * ) lastaddr , shdr [ symtabindex ] . sh_offset + kstart , shdr [ symtabindex ] . sh_size ) ; lastaddr += shdr [ symtabindex ] . sh_size ; tmp = shdr [ symstrindex ] . sh_size ; memcpy ( ( void * ) lastaddr , & tmp , sizeof ( tmp ) ) ; lastaddr += sizeof ( shdr [ symstrindex ] . sh_size ) ; memcpy ( ( void * ) lastaddr , shdr [ symstrindex ] . sh_offset + kstart , shdr [ symstrindex ] . sh_size ) ; } else { tmp = 0 ; memcpy ( ( void * ) lastaddr , & tmp , sizeof ( tmp ) ) ; } return entry_point ; }
Relocate PT_LOAD segements of kernel ELF image to their respective
 virtual addresses and return entry point
Relocate PT_LOAD segements of kernel ELF image to their respective virtual addresses and return entry point
/* XXX */ /* XXX */ /* XXX */ /* XXX */ /*
				 * XXX: check if .symtab is in PT_LOAD?
				 */ /*
	 * Copy loadable segments
	 */ /* Clean space from oversized segments, eg: bss. */ /* Now grab the symbol tables. */ /* .symtab size */ /* .symtab data */ /* .strtab size */ /* .strtab data */ /* Do not take any chances */