int copyoutstr(const void *kaddr, void *udaddr, size_t len, size_t *done) { struct pmap *pm = curproc->p_vmspace->vm_map.pmap; int rv, msr, pid, tmp, ctx; struct faultbuf env; if ((rv = setfault(&env))) { curpcb->pcb_onfault = NULL; /* XXXX -- len may be lost on a fault */ if (done) *done = len; return rv; } if (!(ctx = pm->pm_ctx)) { /* No context -- assign it one */ ctx_alloc(pm); ctx = pm->pm_ctx; } if (len) { __asm volatile("mtctr %3;" /* Set up counter */ "mfmsr %0;" /* Save MSR */ "li %1,0x20; " "andc %1,%0,%1; mtmsr %1;" /* Disable IMMU */ "mfpid %1;" /* Save old PID */ "sync; isync;" "li %3,0;" /* Clear len */ "1:" "mtpid %1;sync;" "lbz %2,0(%6); addi %6,%6,1;" /* Store kernel byte */ "sync; isync;" "mtpid %4; sync;" /* Load user ctx */ "stb %2,0(%5); dcbf 0,%5; addi %5,%5,1;" /* Load byte */ "sync; isync;" "addi %3,%3,1;" /* Inc len */ "or. %2,%2,%2;" "bdnzf 2,1b;" /* * while(ctr-- && !zero) */ "mtpid %1; mtmsr %0;" /* Restore PID, MSR */ "sync; isync;" : "=&r" (msr), "=&r" (pid), "=&r" (tmp), "+b" (len) : "r" (ctx), "b" (udaddr), "b" (kaddr)); } curpcb->pcb_onfault = NULL; if (done) *done = len; return 0; }
/** * Process input characters to the command system * * @param commands Commands container * @param ctxp Pointer to context for editor (optional) * @param key Input character * @param pf Print function * @param data Application data * * @return 0 if success, otherwise errorcode */ int cmd_process(struct commands *commands, struct cmd_ctx **ctxp, char key, struct re_printf *pf, void *data) { const struct cmd *cmd; if (!commands) return EINVAL; if (key == KEYCODE_NONE) { warning("cmd: process: illegal keycode NONE\n"); return EINVAL; } /* are we in edit-mode? */ if (ctxp && *ctxp) { if (key == KEYCODE_REL) return 0; return cmd_process_edit(commands, ctxp, key, pf, data); } cmd = cmd_find_by_key(commands, key); if (cmd) { struct cmd_arg arg; /* check for parameters */ if (cmd->flags & CMD_PRM) { int err = 0; if (ctxp) { err = ctx_alloc(ctxp, cmd); if (err) return err; } key = isdigit(key) ? key : KEYCODE_REL; return cmd_process_edit(commands, ctxp, key, pf, data); } arg.key = key; arg.prm = NULL; arg.complete = true; arg.data = data; return cmd->h(pf, &arg); } else if (key == LONG_PREFIX) { int err; err = re_hprintf(pf, "%c", LONG_PREFIX); if (err) return err; if (!ctxp) { warning("cmd: ctxp is required\n"); return EINVAL; } err = ctx_alloc(ctxp, cmd); if (err) return err; (*ctxp)->is_long = true; return 0; } else if (key == '\t') { return cmd_print_all(pf, commands, false, true, NULL, 0); } if (key == KEYCODE_REL) return 0; return cmd_print(pf, commands); }