int coopth_set_detached(int tid) { struct coopth_t *thr; check_tid(tid); thr = &coopthreads[tid]; thr->detached = 1; return 0; }
void coopth_wake_up(int tid) { struct coopth_t *thr; struct coopth_per_thread_t *pth; check_tid(tid); thr = &coopthreads[tid]; pth = current_thr(thr); do_awake(pth); }
void coopth_ensure_sleeping(int tid) { struct coopth_t *thr; struct coopth_per_thread_t *pth; check_tid(tid); thr = &coopthreads[tid]; pth = current_thr(thr); assert(pth->st.state == COOPTHS_SLEEPING); }
/* attach some thread to current context */ void coopth_attach_to_cur(int tid) { struct coopth_t *thr; struct coopth_per_thread_t *pth; check_tid(tid); thr = &coopthreads[tid]; pth = current_thr(thr); assert(!pth->data.attached); coopth_callf(thr, pth); }
void *coopth_pop_user_data(int tid) { struct coopth_t *thr; struct coopth_per_thread_t *pth; check_tid(tid); thr = &coopthreads[tid]; pth = current_thr(thr); assert(pth->data.udata_num > 0); return pth->data.udata[--pth->data.udata_num]; }
void coopth_push_user_data(int tid, void *udata) { struct coopth_t *thr; struct coopth_per_thread_t *pth; check_tid(tid); thr = &coopthreads[tid]; pth = current_thr(thr); assert(pth->data.udata_num < MAX_UDATA); pth->data.udata[pth->data.udata_num++] = udata; }
void coopth_cancel(int tid) { struct coopth_t *thr; struct coopth_per_thread_t *pth; check_tid(tid); thr = &coopthreads[tid]; pth = current_thr(thr); if (_coopth_is_in_thread_nowarn()) assert(tid != coopth_get_tid()); do_cancel(thr, pth); }
int coopth_set_permanent_post_handler(int tid, coopth_hndl_t func) { struct coopth_t *thr; int i; check_tid(tid); for (i = 0; i < coopthreads[tid].len; i++) { thr = &coopthreads[tid + i]; thr->post = func; } return 0; }
int coopth_set_sleep_handlers(int tid, coopth_hndl_t pre, coopth_hndl_t post) { struct coopth_t *thr; int i; check_tid(tid); for (i = 0; i < coopthreads[tid].len; i++) { thr = &coopthreads[tid + i]; thr->sleeph.pre = pre; thr->sleeph.post = post; } return 0; }
int coopth_start(int tid, coopth_func_t func, void *arg) { struct coopth_t *thr; int err; check_tid(tid); thr = &coopthreads[tid]; assert(thr->tid == tid); err = do_start(thr, ST(RUNNING), func, arg); if (err) return err; return 0; }
int coopth_unsafe_detach(int tid) { struct coopth_t *thr; struct coopth_per_thread_t *pth; check_tid(tid); dosemu_error("coopth_unsafe_detach() called\n"); thr = &coopthreads[tid]; pth = current_thr(thr); assert(pth->data.attached); /* this is really unsafe and should be used only if * the DOS side of the thread have disappeared. */ pth->data.attached = 0; return 0; }
void coopth_join(int tid, void (*helper)(void)) { struct coopth_t *thr; struct coopth_per_thread_t *pth; /* since main thread can call this, we have to use helper * function instead of just coopth_sched(). As a result, * recursion into run_vm86() can happen. Hope its safe. */ assert(!_coopth_is_in_thread_nowarn() || is_detached()); check_tid(tid); thr = &coopthreads[tid]; pth = current_thr(thr); assert(pth->data.attached); do_join(pth, helper); }
int coopth_start_sleeping(int tid, coopth_func_t func, void *arg) { struct coopth_t *thr; int err; check_tid(tid); thr = &coopthreads[tid]; assert(thr->tid == tid); err = do_start(thr, ST(SLEEPING), func, arg); if (err) return err; if (thr->sleeph.pre) thr->sleeph.pre(thr->tid); return 0; }
void coopth_cancel(int tid) { struct coopth_t *thr; struct coopth_per_thread_t *pth; check_tid(tid); thr = &coopthreads[tid]; pth = current_thr(thr); if (_coopth_is_in_thread_nowarn()) { if (tid == coopth_get_tid()) { assert(pth->data.left); return; } } do_cancel(thr, pth); }
int main(int argc, char *argv[]) { app_title(); //Argument Checks if(argc < 3){ printf("[!] Not Enough Arguments\n"); help(argv[0]); return 1; } if(argc > 3){ printf("[!] Too Many Arguments\n"); help(argv[0]); return 1; } //Storing Current Working Directory char cwd[1024]; if (getcwdir(cwd, sizeof(cwd)) == NULL){ printf("[!] Could not store Current Working Directory\n"); return IO_FAIL; } //Changing to CDN Content Directory chdir(argv[1]); //Processing TIK FILE *tik = fopen("cetk","rb"); if(tik == NULL){ printf("[!] Could not open 'tik'\n"); return IO_FAIL; } TIK_CONTEXT tik_context = process_tik(tik); //Processing TMD FILE *tmd = fopen("tmd","rb"); if(tmd == NULL){ printf("[!] Could not open 'tmd'\n"); return IO_FAIL; } TMD_CONTEXT tmd_context = process_tmd(tmd); //Error Checking if(tik_context.result != 0 || tmd_context.result != 0){ printf("[!] Input files could not be processed successfully\n"); free(tmd_context.content_struct); free(tmd_context.content); fclose(tik); fclose(tmd); return FILE_PROCESS_FAIL; } //TID comparison check if(check_tid(tik_context.title_id,tmd_context.title_id) != TRUE){ printf("[!] Caution, Ticket and TMD Title IDs do not match\n"); printf("[!] CETK Title ID: "); u8_hex_print_be(tik_context.title_id,0x8); printf("\n"); printf("[!] TMD Title ID: "); u8_hex_print_be(tmd_context.title_id,0x8); printf("\n"); } //Title Version comparison if(tik_context.title_version != tmd_context.title_version){ printf("[!] Caution, Ticket and TMD Title Versions do not match\n"); printf("[!] CETK Title Ver: %d\n",tik_context.title_version); printf("[!] TMD Title Ver: %d\n",tmd_context.title_version); } //Returning to Original Working Directory chdir(cwd); //Opening Output file FILE *output = fopen(argv[2],"wb"); if(output == NULL){ printf("[!] Could not create '%s'\n",argv[2]); return IO_FAIL; } int result = generate_cia(tmd_context,tik_context,output); if(result != 0){ printf("[!] Failed to Generate %s\n",argv[2]); remove(argv[2]); } else printf("[*] %s Generated Sucessfully\n",argv[2]); return 0; }
int coopth_start(int tid, coopth_func_t func, void *arg) { struct coopth_t *thr; struct coopth_per_thread_t *pth; int tn; check_tid(tid); thr = &coopthreads[tid]; assert(thr->tid == tid); if (thr->cur_thr >= MAX_COOP_RECUR_DEPTH) { int i; error("Coopthreads recursion depth exceeded, %s off=%x\n", thr->name, thr->off); for (i = 0; i < thr->cur_thr; i++) { error("\tthread %i state %i dbg %#x\n", i, thr->pth[i].st.state, thr->pth[i].dbg); } leavedos(2); return -1; } tn = thr->cur_thr++; pth = &thr->pth[tn]; if (thr->cur_thr > thr->max_thr) { size_t stk_size = COOP_STK_SIZE(); thr->max_thr = thr->cur_thr; #ifndef MAP_STACK #define MAP_STACK 0 #endif pth->stack = mmap(NULL, stk_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); if (pth->stack == MAP_FAILED) { error("Unable to allocate stack\n"); leavedos(21); return 1; } pth->stk_size = stk_size; } pth->data.tid = &thr->tid; pth->data.attached = 0; pth->data.posth_num = 0; pth->data.sleep.func = NULL; pth->data.clnup.func = NULL; pth->data.udata_num = 0; pth->data.cancelled = 0; pth->data.left = 0; pth->args.thr.func = func; pth->args.thr.arg = arg; pth->args.thrdata = &pth->data; pth->dbg = LWORD(eax); // for debug pth->thread = co_create(coopth_thread, &pth->args, pth->stack, pth->stk_size); if (!pth->thread) { error("Thread create failure\n"); leavedos(2); return -1; } pth->st = ST(RUNNING); if (tn == 0) { assert(threads_active < MAX_ACT_THRS); active_tids[threads_active++] = tid; } else if (thr->pth[tn - 1].st.state == COOPTHS_SLEEPING) { static int logged; /* will have problems with wake-up by tid. It is possible * to do a wakeup-specific lookup, but this is nasty, and * the recursion itself is nasty too. Lets just print an * error to force the caller to create a separate thread. * vc.c does this to not sleep in the sighandling thread. */ if (!logged) { dosemu_error("thread %s recursed (%i) over sleep\n", thr->name, thr->cur_thr); logged = 1; } } threads_total++; if (!thr->detached) coopth_callf(thr, pth); return 0; }