Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm/arm/elf_trampoline.c
Show All 33 Lines | |||||
#include <machine/asm.h> | #include <machine/asm.h> | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/elf32.h> | #include <sys/elf32.h> | ||||
#include <sys/inflate.h> | #include <sys/inflate.h> | ||||
#include <machine/elf.h> | #include <machine/elf.h> | ||||
#include <machine/pte-v4.h> | #include <machine/pte-v4.h> | ||||
#include <machine/cpufunc.h> | #include <machine/cpufunc.h> | ||||
#include <machine/armreg.h> | #include <machine/armreg.h> | ||||
#include <machine/cpu.h> | |||||
extern char kernel_start[]; | extern char kernel_start[]; | ||||
extern char kernel_end[]; | extern char kernel_end[]; | ||||
extern void *_end; | extern void *_end; | ||||
void _start(void); | void _start(void); | ||||
void __start(void); | void __start(void); | ||||
void __startC(void); | void __startC(unsigned r0, unsigned r1, unsigned r2, unsigned r3); | ||||
extern unsigned int cpu_ident(void); | extern unsigned int cpu_ident(void); | ||||
extern void armv6_idcache_wbinv_all(void); | extern void armv6_idcache_wbinv_all(void); | ||||
extern void armv7_idcache_wbinv_all(void); | extern void armv7_idcache_wbinv_all(void); | ||||
extern void do_call(void *, void *, void *, int); | extern void do_call(void *, void *, void *, int); | ||||
#define GZ_HEAD 0xa | #define GZ_HEAD 0xa | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | |||||
u_int arm_cache_loc; | u_int arm_cache_loc; | ||||
/* Additional cache information local to this file. Log2 of some of the | /* Additional cache information local to this file. Log2 of some of the | ||||
above numbers. */ | above numbers. */ | ||||
static int arm_dcache_l2_nsets; | static int arm_dcache_l2_nsets; | ||||
static int arm_dcache_l2_assoc; | static int arm_dcache_l2_assoc; | ||||
static int arm_dcache_l2_linesize; | static int arm_dcache_l2_linesize; | ||||
/* | |||||
* Boot parameters | |||||
*/ | |||||
static struct arm_boot_params s_boot_params; | |||||
extern int arm9_dcache_sets_inc; | extern int arm9_dcache_sets_inc; | ||||
extern int arm9_dcache_sets_max; | extern int arm9_dcache_sets_max; | ||||
extern int arm9_dcache_index_max; | extern int arm9_dcache_index_max; | ||||
extern int arm9_dcache_index_inc; | extern int arm9_dcache_index_inc; | ||||
static __inline void * | static __inline void * | ||||
memcpy(void *dst, const void *src, int len) | memcpy(void *dst, const void *src, int len) | ||||
Show All 32 Lines | if (count >= 4 && !((vm_offset_t)tmp & 3)) { | ||||
count--; | count--; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static void arm9_setup(void); | static void arm9_setup(void); | ||||
void | void | ||||
_startC(void) | _startC(unsigned r0, unsigned r1, unsigned r2, unsigned r3) | ||||
{ | { | ||||
int tmp1; | int tmp1; | ||||
unsigned int sp = ((unsigned int)&_end & ~3) + 4; | unsigned int sp = ((unsigned int)&_end & ~3) + 4; | ||||
unsigned int pc, kernphysaddr; | unsigned int pc, kernphysaddr; | ||||
s_boot_params.abp_r0 = r0; | |||||
s_boot_params.abp_r1 = r1; | |||||
s_boot_params.abp_r2 = r2; | |||||
s_boot_params.abp_r3 = r3; | |||||
/* | /* | ||||
* Figure out the physical address the kernel was loaded at. This | * Figure out the physical address the kernel was loaded at. This | ||||
* assumes the entry point (this code right here) is in the first page, | * assumes the entry point (this code right here) is in the first page, | ||||
* which will always be the case for this trampoline code. | * which will always be the case for this trampoline code. | ||||
*/ | */ | ||||
__asm __volatile("mov %0, pc\n" | __asm __volatile("mov %0, pc\n" | ||||
: "=r" (pc)); | : "=r" (pc)); | ||||
kernphysaddr = pc & ~PAGE_MASK; | kernphysaddr = pc & ~PAGE_MASK; | ||||
Show All 17 Lines | if ((FLASHADDR > LOADERRAMADDR && pc >= FLASHADDR) || | ||||
target_addr = (unsigned int)&_start - PHYSADDR + LOADERRAMADDR; | target_addr = (unsigned int)&_start - PHYSADDR + LOADERRAMADDR; | ||||
tmp_sp = target_addr + 0x100000 + | tmp_sp = target_addr + 0x100000 + | ||||
(unsigned int)&_end - (unsigned int)&_start; | (unsigned int)&_end - (unsigned int)&_start; | ||||
memcpy((char *)target_addr, (char *)src_addr, | memcpy((char *)target_addr, (char *)src_addr, | ||||
(unsigned int)&_end - (unsigned int)&_start); | (unsigned int)&_end - (unsigned int)&_start); | ||||
/* Temporary set the sp and jump to the new location. */ | /* Temporary set the sp and jump to the new location. */ | ||||
__asm __volatile( | __asm __volatile( | ||||
"mov sp, %1\n" | "mov sp, %1\n" | ||||
"mov r0, %2\n" | |||||
"mov r1, %3\n" | |||||
"mov r2, %4\n" | |||||
"mov r3, %5\n" | |||||
"mov pc, %0\n" | "mov pc, %0\n" | ||||
: : "r" (target_addr), "r" (tmp_sp)); | : : "r" (target_addr), "r" (tmp_sp), | ||||
"r" (s_boot_params.abp_r0), "r" (s_boot_params.abp_r1), | |||||
"r" (s_boot_params.abp_r2), "r" (s_boot_params.abp_r3), | |||||
: "r0", "r1", "r2", "r3"); | |||||
} | } | ||||
#endif | #endif | ||||
#ifdef KZIP | #ifdef KZIP | ||||
sp += KERNSIZE + 0x100; | sp += KERNSIZE + 0x100; | ||||
sp &= ~(L1_TABLE_SIZE - 1); | sp &= ~(L1_TABLE_SIZE - 1); | ||||
sp += 2 * L1_TABLE_SIZE; | sp += 2 * L1_TABLE_SIZE; | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | load_kernel(unsigned int kstart, unsigned int curaddr,unsigned int func_end, | ||||
Elf32_Shdr shdr[64] /* XXX */; | Elf32_Shdr shdr[64] /* XXX */; | ||||
int i,j; | int i,j; | ||||
void *entry_point; | void *entry_point; | ||||
int symtabindex = -1; | int symtabindex = -1; | ||||
int symstrindex = -1; | int symstrindex = -1; | ||||
vm_offset_t lastaddr = 0; | vm_offset_t lastaddr = 0; | ||||
Elf_Addr ssym = 0; | Elf_Addr ssym = 0; | ||||
Elf_Dyn *dp; | Elf_Dyn *dp; | ||||
struct arm_boot_params local_boot_params; | |||||
eh = (Elf32_Ehdr *)kstart; | eh = (Elf32_Ehdr *)kstart; | ||||
ssym = 0; | ssym = 0; | ||||
entry_point = (void*)eh->e_entry; | entry_point = (void*)eh->e_entry; | ||||
memcpy(phdr, (void *)(kstart + eh->e_phoff ), | memcpy(phdr, (void *)(kstart + eh->e_phoff ), | ||||
eh->e_phnum * sizeof(phdr[0])); | eh->e_phnum * sizeof(phdr[0])); | ||||
/* Determine lastaddr. */ | /* Determine lastaddr. */ | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | if (symtabindex >= 0 && symstrindex >= 0) { | ||||
sizeof(shdr[symstrindex].sh_size)); | sizeof(shdr[symstrindex].sh_size)); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (!d) | if (!d) | ||||
return ((void *)lastaddr); | return ((void *)lastaddr); | ||||
/* | |||||
* Now the stack is fixed, copy boot params | |||||
* before it's overrided | |||||
*/ | |||||
memcpy(&local_boot_params, &s_boot_params, sizeof(local_boot_params)); | |||||
j = eh->e_phnum; | j = eh->e_phnum; | ||||
for (i = 0; i < j; i++) { | for (i = 0; i < j; i++) { | ||||
volatile char c; | volatile char c; | ||||
if (phdr[i].p_type != PT_LOAD) | if (phdr[i].p_type != PT_LOAD) | ||||
continue; | continue; | ||||
memcpy((void *)(phdr[i].p_vaddr - KERNVIRTADDR + curaddr), | memcpy((void *)(phdr[i].p_vaddr - KERNVIRTADDR + curaddr), | ||||
(void*)(kstart + phdr[i].p_offset), phdr[i].p_filesz); | (void*)(kstart + phdr[i].p_offset), phdr[i].p_filesz); | ||||
Show All 33 Lines | load_kernel(unsigned int kstart, unsigned int curaddr,unsigned int func_end, | ||||
__asm __volatile("mcr p15, 0, %0, c7, c5, 0\n" | __asm __volatile("mcr p15, 0, %0, c7, c5, 0\n" | ||||
"mcr p15, 0, %0, c7, c10, 4\n" | "mcr p15, 0, %0, c7, c10, 4\n" | ||||
: : "r" (curaddr)); | : : "r" (curaddr)); | ||||
__asm __volatile("mrc p15, 0, %0, c1, c0, 0\n" /* CP15_SCTLR(%0)*/ | __asm __volatile("mrc p15, 0, %0, c1, c0, 0\n" /* CP15_SCTLR(%0)*/ | ||||
"bic %0, %0, #1\n" /* MMU_ENABLE */ | "bic %0, %0, #1\n" /* MMU_ENABLE */ | ||||
"mcr p15, 0, %0, c1, c0, 0\n" /* CP15_SCTLR(%0)*/ | "mcr p15, 0, %0, c1, c0, 0\n" /* CP15_SCTLR(%0)*/ | ||||
: "=r" (ssym)); | : "=r" (ssym)); | ||||
/* Jump to the entry point. */ | /* Jump to the entry point. */ | ||||
((void(*)(void))(entry_point - KERNVIRTADDR + curaddr))(); | ((void(*)(unsigned, unsigned, unsigned, unsigned)) | ||||
(entry_point - KERNVIRTADDR + curaddr)) | |||||
(local_boot_params.abp_r0, local_boot_params.abp_r1, | |||||
local_boot_params.abp_r2, local_boot_params.abp_r3); | |||||
__asm __volatile(".globl func_end\n" | __asm __volatile(".globl func_end\n" | ||||
"func_end:"); | "func_end:"); | ||||
/* NOTREACHED */ | /* NOTREACHED */ | ||||
return NULL; | return NULL; | ||||
} | } | ||||
extern char func_end[]; | extern char func_end[]; | ||||
▲ Show 20 Lines • Show All 120 Lines • Show Last 20 Lines |