void mem_initialize(void) { u32 cr; u32 cookie = irq_kill(); gecko_printf("MEM: cleaning up\n"); _ic_inval(); _dc_inval(); _tlb_inval(); gecko_printf("MEM: unprotecting memory\n"); mem_protect(0,NULL,NULL); gecko_printf("MEM: mapping sections\n"); memset32(__page_table, 0, 16384); map_section(0x000, 0x000, 0x018, WRITEBACK_CACHE | DOMAIN(0) | AP_RWUSER); map_section(0x100, 0x100, 0x040, WRITEBACK_CACHE | DOMAIN(0) | AP_RWUSER); map_section(0x0d0, 0x0d0, 0x001, NONBUFFERABLE | DOMAIN(0) | AP_RWUSER); map_section(0x0d8, 0x0d8, 0x001, NONBUFFERABLE | DOMAIN(0) | AP_RWUSER); map_section(0xfff, 0xfff, 0x001, WRITEBACK_CACHE | DOMAIN(0) | AP_RWUSER); set_dacr(0xFFFFFFFF); //manager access for all domains, ignore AP set_ttbr((u32)__page_table); //configure translation table _drain_write_buffer(); cr = get_cr(); #ifndef NO_CACHES gecko_printf("MEM: enabling caches\n"); cr |= CR_DCACHE | CR_ICACHE; set_cr(cr); gecko_printf("MEM: enabling MMU\n"); cr |= CR_MMU; set_cr(cr); #endif gecko_printf("MEM: init done\n"); irq_restore(cookie); }
static void _func_copy(func_t *func) { size_t len = func->real_size; void *buf; if ((buf = mmap(NULL, len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)) == MAP_FAILED) { err(1, "mmap for function %s failed", func->name_demangled); } func->copy_addr = (uintptr_t)buf; func->copy_size = len; memcpy((void *)func->copy_addr, (void *)func->real_addr, func->real_size); mem_protect((void *)func->copy_addr, func->copy_size); }
static void _func_detour(func_t *func) { struct { uint8_t padding[3]; uint8_t opcode; ptrdiff_t offset; } jmp; _Static_assert(sizeof(jmp) == 8, "sizeof(jmp) != 8"); jmp.opcode = 0xE9; jmp.offset = (func->copy_addr - (func->real_addr + 5)); mem_unprotect((void *)func->real_addr, func->real_size); memcpy((void *)func->real_addr, &jmp.opcode, 5); mem_protect((void *)func->real_addr, func->real_size); }