// Relocate init code and then call a function at its new address. // The passed function should be in the "init" section and must not // return. void __noreturn reloc_preinit(void *f, void *arg) { void (*func)(void *) __noreturn = f; if (!CONFIG_RELOCATE_INIT) func(arg); // Allocate space for init code. u32 initsize = SYMBOL(code32init_end) - SYMBOL(code32init_start); u32 codealign = SYMBOL(_reloc_min_align); void *codedest = memalign_tmp(codealign, initsize); void *codesrc = VSYMBOL(code32init_start); if (!codedest) panic("No space for init relocation.\n"); // Copy code and update relocs (init absolute, init relative, and runtime) dprintf(1, "Relocating init from %p to %p (size %d)\n" , codesrc, codedest, initsize); s32 delta = codedest - codesrc; memcpy(codedest, codesrc, initsize); updateRelocs(codedest, VSYMBOL(_reloc_abs_start), VSYMBOL(_reloc_abs_end) , delta); updateRelocs(codedest, VSYMBOL(_reloc_rel_start), VSYMBOL(_reloc_rel_end) , -delta); updateRelocs(VSYMBOL(code32flat_start), VSYMBOL(_reloc_init_start) , VSYMBOL(_reloc_init_end), delta); if (f >= codesrc && f < VSYMBOL(code32init_end)) func = f + delta; // Call function in relocated code. barrier(); func(arg); }
// Relocate init code and then call maininit() at new address. static void reloc_init(void) { if (!CONFIG_RELOCATE_INIT) { maininit(); return; } // Symbols populated by the build. extern u8 code32flat_start[]; extern u8 _reloc_min_align; extern u32 _reloc_abs_start[], _reloc_abs_end[]; extern u32 _reloc_rel_start[], _reloc_rel_end[]; extern u32 _reloc_init_start[], _reloc_init_end[]; extern u8 code32init_start[], code32init_end[]; extern u32 _reloc_datalow_start[], _reloc_datalow_end[]; extern u8 datalow_start[], datalow_end[], final_datalow_start[]; // Allocate space for init code. u32 initsize = code32init_end - code32init_start; u32 codealign = (u32)&_reloc_min_align; void *codedest = memalign_tmp(codealign, initsize); if (!codedest) panic("No space for init relocation.\n"); // Copy code and update relocs (init absolute, init relative, and runtime) dprintf(1, "Relocating low data from %p to %p (size %d)\n" , datalow_start, final_datalow_start, datalow_end - datalow_start); updateRelocs(code32flat_start, _reloc_datalow_start, _reloc_datalow_end , final_datalow_start - datalow_start); dprintf(1, "Relocating init from %p to %p (size %d)\n" , code32init_start, codedest, initsize); s32 delta = codedest - (void*)code32init_start; memcpy(codedest, code32init_start, initsize); updateRelocs(codedest, _reloc_abs_start, _reloc_abs_end, delta); updateRelocs(codedest, _reloc_rel_start, _reloc_rel_end, -delta); updateRelocs(code32flat_start, _reloc_init_start, _reloc_init_end, delta); // Call maininit() in relocated code. void (*func)(void) = (void*)afterReloc + delta; barrier(); func(); }
// Relocate init code and then call a function at its new address. // The passed function should be in the "init" section and must not // return. void __noreturn reloc_preinit(void *f, void *arg) { void (*func)(void *) __noreturn = f; if (!CONFIG_RELOCATE_INIT) func(arg); // Symbols populated by the build. extern u8 code32flat_start[]; extern u8 _reloc_min_align; extern u32 _reloc_abs_start[], _reloc_abs_end[]; extern u32 _reloc_rel_start[], _reloc_rel_end[]; extern u32 _reloc_init_start[], _reloc_init_end[]; extern u8 code32init_start[], code32init_end[]; // Allocate space for init code. u32 initsize = code32init_end - code32init_start; u32 codealign = (u32)&_reloc_min_align; void *codedest = memalign_tmp(codealign, initsize); if (!codedest) panic("No space for init relocation.\n"); // Copy code and update relocs (init absolute, init relative, and runtime) dprintf(1, "Relocating init from %p to %p (size %d)\n" , code32init_start, codedest, initsize); s32 delta = codedest - (void*)code32init_start; memcpy(codedest, code32init_start, initsize); updateRelocs(codedest, _reloc_abs_start, _reloc_abs_end, delta); updateRelocs(codedest, _reloc_rel_start, _reloc_rel_end, -delta); updateRelocs(code32flat_start, _reloc_init_start, _reloc_init_end, delta); if (f >= (void*)code32init_start && f < (void*)code32init_end) func = f + delta; // Call function in relocated code. barrier(); func(arg); }