bool HardwareBaremetal::Reboot(void) { hardware_led_set(1); h3_watchdog_enable(); invalidate_instruction_cache(); flush_branch_target_cache(); flush_prefetch_buffer(); clean_data_cache(); invalidate_data_cache(); for (;;) ; __builtin_unreachable (); return true; }
void firmlaunch_arm9hax() { invalidate_data_cache(); invalidate_instruction_cache(); print("Invalidated instruction and data cache"); uint32_t code_offset = 0x3F00000; asm_memcpy((void *)(fw->fcram_address + code_offset), (void *)(fw->fcram_address + APP_CFW_OFFSET), ARM9_PAYLOAD_MAXSIZE); print("Copied arm9 code"); setup_gpu(); asm_memcpy((void *)fw->jump_table_address, &jump_table, (&jump_table_end - &jump_table + 1) * 4); print("Copied jump table"); *(uint32_t *)(fw->jump_table_address + (&jt_return - &jump_table) * 4) = fw->func_patch_return; *(uint32_t *)(fw->jump_table_address + (&jt_pdn_regs - &jump_table) * 4) = fw->pdn_regs; *(uint32_t *)(fw->jump_table_address + (&jt_pxi_regs - &jump_table) * 4) = fw->pxi_regs; print("Written firmware specific offsets"); *(uint32_t *)fw->func_patch_address = 0xE51FF004; *(uint32_t *)(fw->func_patch_address + 4) = 0xFFFF0C80; *(uint32_t *)fw->reboot_patch_address = 0xE51FF004; *(uint32_t *)(fw->reboot_patch_address + 4) = 0x1FFF4C80+4; print("Patched arm11 functions"); invalidate_data_cache(); print("Invalidated data cache"); print("Triggering reboot"); ((void (*)())fw->reboot_func_address)(0, 0, 2, 0); while (1) {}; }
long xexec(WORD flag, char *path, char *tail, char *env) { PD *p; PGMHDR01 hdr; MD *m, *env_md; LONG rc; long max, needed; FH fh; KDEBUG(("BDOS xexec: flag or mode = %d\n",flag)); /* first branch - actions that do not require loading files */ switch(flag) { #if DETECT_NATIVE_FEATURES case PE_RELOCATE: /* internal use only, see bootstrap() in bios/bios.c */ p = (PD *) tail; rc = kpgm_relocate(p, (long)path); if (rc) { KDEBUG(("BDOS xexec: kpgm_reloc returned %ld (0x%lx)\n",rc,rc)); return rc; } /* invalidate instruction cache for the TEXT segment only * programs that jump into their DATA, BSS or HEAP are kindly invited * to do their cache management themselves. */ invalidate_instruction_cache( p+1, p->p_tlen); return (long)p; #endif case PE_BASEPAGE: /* just create a basepage */ path = (char *) 0L; /* (same as basepage+flags with flags set to zero) */ /* drop thru */ case PE_BASEPAGEFLAGS: /* create a basepage, respecting the flags */ env_md = alloc_env(env); if (env_md == NULL) { KDEBUG(("BDOS xexec: not enough memory!\n")); return ENSMEM; } m = alloc_tpa((ULONG)path,sizeof(PD),&max); if (m == NULL) { /* not even enough memory for basepage */ freeit(env_md, &pmd); KDEBUG(("BDOS xexec: No memory for basepage\n")); return ENSMEM; } p = (PD *) m->m_start; /* memory ownership */ m->m_own = env_md->m_own = run; /* initialize the PD */ init_pd_fields(p, tail, max, env_md); p->p_flags = (ULONG)path; /* set the flags */ init_pd_files(p); return (long)p; case PE_GOTHENFREE: /* set the owner of the memory to be this process */ p = (PD *) tail; set_owner(p, p, find_mpb(p)); set_owner(p->p_env, p, find_mpb(p->p_env)); /* fall through */ case PE_GO: p = (PD *) tail; proc_go(p); /* should not return ? */ return (long)p; case PE_LOADGO: case PE_LOAD: break; default: return EINVFN; } /* we now need to load a file */ KDEBUG(("BDOS xexec: trying to find the command ...\n")); if (ixsfirst(path,0,0L)) { KDEBUG(("BDOS xexec: command %s not found!!!\n",path)); return EFILNF; /* file not found */ } /* load the header - if I/O error occurs now, the longjmp in rwabs will * jump directly back to bdosmain.c, which is not a problem because * we haven't allocated anything yet. */ rc = kpgmhdrld(path, &hdr, &fh); if (rc) { KDEBUG(("BDOS xexec: kpgmhdrld returned %ld (0x%lx)\n",rc,rc)); return rc; } /* allocate the environment first, always in ST RAM */ env_md = alloc_env(env); if (env_md == NULL) { KDEBUG(("BDOS xexec: not enough memory!\n")); return ENSMEM; } /* allocate the basepage depending on memory policy */ needed = hdr.h01_tlen + hdr.h01_dlen + hdr.h01_blen + sizeof(PD); m = alloc_tpa(hdr.h01_flags,needed,&max); /* if failed, free env_md and return */ if (m == NULL) { KDEBUG(("BDOS xexec: no memory for TPA\n")); freeit(env_md, &pmd); return ENSMEM; } p = (PD *) m->m_start; /* memory ownership - the owner is either the new process being created, * or the parent */ if (flag == PE_LOADGO) { m->m_own = env_md->m_own = p; } else { m->m_own = env_md->m_own = run; } /* initialize the fields in the PD structure */ init_pd_fields(p, tail, max, env_md); /* set the flags (must be done after init_pd) */ p->p_flags = hdr.h01_flags; /* use static variable to avoid the obscure longjmp warning */ cur_p = p; cur_m = m; cur_env_md = env_md; /* we have now allocated memory, so we need to intercept longjmp. */ memcpy(bakbuf, errbuf, sizeof(errbuf)); if (setjmp(errbuf)) { KDEBUG(("Error and longjmp in xexec()!\n")); /* free any memory allocated yet */ freeit(cur_env_md, &pmd); freeit(cur_m, find_mpb(cur_m->m_start)); /* we still have to jump back to bdosmain.c so that the proper error * handling can occur. */ longjmp(bakbuf, 1); } /* now, load the rest of the program and perform relocation */ rc = kpgmld(cur_p, fh, &hdr); if (rc) { KDEBUG(("BDOS xexec: kpgmld returned %ld (0x%lx)\n",rc,rc)); /* free any memory allocated yet */ freeit(cur_env_md, &pmd); freeit(cur_m, find_mpb(cur_m->m_start)); return rc; } /* at this point the program has been correctly loaded in memory, and * more I/O errors cannot occur, so it is safe now to finish initializing * the new process. */ init_pd_files(cur_p); /* invalidate instruction cache for the TEXT segment only * programs that jump into their DATA, BSS or HEAP are kindly invited * to do their cache management themselves. */ invalidate_instruction_cache(((char *)cur_p) + sizeof(PD), hdr.h01_tlen); if (flag != PE_LOAD) proc_go(cur_p); return (long)cur_p; }