Run spatch on devcons.c
[akaros.git] / kern / drivers / dev / cons.c
1 /* Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
2  * Portions Copyright © 1997-1999 Vita Nuova Limited
3  * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited
4  *                                (www.vitanuova.com)
5  * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
6  *
7  * Modified for the Akaros operating system:
8  * Copyright (c) 2013-2014 The Regents of the University of California
9  * Copyright (c) 2013-2015 Google Inc.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a copy
12  * of this software and associated documentation files (the "Software"), to deal
13  * in the Software without restriction, including without limitation the rights
14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  * SOFTWARE. */
28
29 #include <vfs.h>
30 #include <kfs.h>
31 #include <slab.h>
32 #include <kmalloc.h>
33 #include <kref.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <assert.h>
37 #include <error.h>
38 #include <cpio.h>
39 #include <pmap.h>
40 #include <smp.h>
41 #include <ip.h>
42 #include <monitor.h>
43 #include <ros/vmm.h>
44
45 struct dev consdevtab;
46
47 static char *devname(void)
48 {
49         return consdevtab.name;
50 }
51
52 extern char *eve;
53 /* much stuff not ready yet. */
54
55 extern int cflag;
56
57 /* this would be good to have; when processes die, keep them around so we can
58  * debug them.
59  */
60 int keepbroken;
61
62 #if 0
63 void (*serwrite) (char *, int);
64
65 struct queue *kscanq;                   /* keyboard raw scancodes (when needed) */
66 char *kscanid;                                  /* name of raw scan format (if defined) */
67 struct queue *kbdq;                             /* unprocessed console input */
68 struct queue *lineq;                    /* processed console input */
69 struct queue *printq;                   /* console output */
70 struct queue *klogq;                    /* kernel print (log) output */
71 int iprintscreenputs;
72
73 static struct {
74         rwlock_t rwlock;
75         Queue *q;
76 } kprintq;
77
78 static struct {
79         qlock_t qlock;
80
81         int raw;                                        /* true if we shouldn't process input */
82         int ctl;                                        /* number of opens to the control file */
83         int kbdr;                                       /* number of open reads to the keyboard */
84         int scan;                                       /* true if reading raw scancodes */
85         int x;                                          /* index into line */
86         char line[1024];                        /* current input line */
87
88         char c;
89         int count;
90         int repeat;
91 } kbd;
92
93 #endif
94 char *sysname = "Your machine";
95 char *eve = "eve";
96
97 enum {
98         CMreboot,
99         CMhalt,
100         CMpanic,
101         CMbroken,
102         CMnobroken,
103         CMconsole,
104         CMV,
105 };
106
107 static struct cmdtab sysctlcmd[] = {
108         {CMreboot, "reboot", 0},
109         {CMhalt, "halt", 0},
110         {CMpanic, "panic", 0},
111         {CMconsole, "console", 1},
112         {CMbroken, "broken", 0},
113         {CMnobroken, "nobroken", 0},
114         {CMV, "V", 4},
115 };
116
117 void printinit(void)
118 {
119 #if 0
120         lineq = qopen(2 * 1024, 0, NULL, NULL);
121         if (lineq == NULL)
122                 panic("printinit");
123         qdropoverflow(lineq, 1);
124 #endif
125 }
126
127 /*
128  *  return true if current user is eve
129  */
130 int iseve(void)
131 {
132 #if 0
133         Osenv *o;
134
135         o = up->env;
136         return strcmp(eve, o->user) == 0;
137 #endif
138         return 1;
139 }
140
141 #if 0
142 static int consactive(void)
143 {
144         if (printq)
145                 return qlen(printq) > 0;
146         return 0;
147 }
148
149 static void prflush(void)
150 {
151         uint32_t now;
152
153         now = m->ticks;
154         while (serwrite == NULL && consactive())
155                 if (m->ticks - now >= HZ)
156                         break;
157 }
158
159 /*
160  *   Print a string on the console.  Convert \n to \r\n for serial
161  *   line consoles.  Locking of the queues is left up to the screen
162  *   or uart code.  Multi-line messages to serial consoles may get
163  *   interspersed with other messages.
164  */
165 static void putstrn0(char *str, int n, int usewrite)
166 {
167         int m;
168         char *t;
169         char buf[PRINTSIZE + 2];
170         ERRSTACK(1);
171
172         /*
173          *  if kprint is open, put the message there, otherwise
174          *  if there's an attached bit mapped display,
175          *  put the message there.
176          */
177         m = consoleprint;
178         if (canrlock(&(&kprintq)->rwlock)) {
179                 if (kprintq.q != NULL) {
180                         if (waserror()) {
181                                 runlock(&(&kprintq)->rwlock);
182                                 nexterror();
183                         }
184                         if (usewrite)
185                                 qwrite(kprintq.q, str, n);
186                         else
187                                 qiwrite(kprintq.q, str, n);
188                         poperror();
189                         m = 0;
190                 }
191                 runlock(&(&kprintq)->rwlock);
192         }
193         if (m && screenputs != NULL)
194                 screenputs(str, n);
195
196         /*
197          *  if there's a serial line being used as a console,
198          *  put the message there.
199          */
200         if (serwrite != NULL) {
201                 serwrite(str, n);
202                 return;
203         }
204
205         if (printq == 0)
206                 return;
207
208         while (n > 0) {
209                 t = memchr(str, '\n', n);
210                 if (t && !kbd.raw) {
211                         m = t - str;
212                         if (m > sizeof(buf) - 2)
213                                 m = sizeof(buf) - 2;
214                         memmove(buf, str, m);
215                         buf[m] = '\r';
216                         buf[m + 1] = '\n';
217                         if (usewrite)
218                                 qwrite(printq, buf, m + 2);
219                         else
220                                 qiwrite(printq, buf, m + 2);
221                         str = t + 1;
222                         n -= m + 1;
223                 } else {
224                         if (usewrite)
225                                 qwrite(printq, str, n);
226                         else
227                                 qiwrite(printq, str, n);
228                         break;
229                 }
230         }
231 }
232
233 /*
234  * mainly for libmp
235  */
236 void sysfatal(char *fmt, ...)
237 {
238         va_list arg;
239         char buf[64];
240
241         va_start(arg, fmt);
242         vsnprintf(buf, sizeof(buf), fmt, arg);
243         va_end(arg);
244         error(EFAIL, buf);
245 }
246
247 int pprint(char *fmt, ...)
248 {
249         ERRSTACK(1);
250         int n;
251         struct chan *c;
252         Osenv *o;
253         va_list arg;
254         char buf[2 * PRINTSIZE];
255
256         n = sprint(buf, "%s %ld: ", up->text, up->pid);
257         va_start(arg, fmt);
258         n = vseprintf(buf + n, buf + sizeof(buf), fmt, arg) - buf;
259         va_end(arg);
260
261         o = up->env;
262         if (o->fgrp == 0) {
263                 printd("%s", buf);
264                 return 0;
265         }
266         /* TODO: this is probably wrong (VFS hack) */
267         c = o->fgrp->fd[2];
268         if (c == 0 || (c->mode != OWRITE && c->mode != ORDWR)) {
269                 printd("%s", buf);
270                 return 0;
271         }
272
273         if (waserror()) {
274                 printd("%s", buf);
275                 poperror();
276                 return 0;
277         }
278         devtab[c->type].write(c, buf, n, c->offset);
279         poperror();
280
281         spin_lock(&c->lock);
282         c->offset += n;
283         spin_unlock(&c->lock);
284
285         return n;
286 }
287
288 void echo(Rune r, char *buf, int n)
289 {
290         if (kbd.raw)
291                 return;
292
293         if (r == '\n') {
294                 if (printq)
295                         qiwrite(printq, "\r", 1);
296         } else if (r == 0x15) {
297                 buf = "^U\n";
298                 n = 3;
299         }
300         if (consoleprint && screenputs != NULL)
301                 screenputs(buf, n);
302         if (printq)
303                 qiwrite(printq, buf, n);
304 }
305 #endif
306 #if 0
307 /*
308  *      Debug key support.  Allows other parts of the kernel to register debug
309  *      key handlers, instead of devcons.c having to know whatever's out there.
310  *      A kproc is used to invoke most handlers, rather than tying up the CPU at
311  *      splhi, which can choke some device drivers (eg softmodem).
312  */
313 typedef struct {
314         Rune r;
315         char *m;
316         void (*f) (Rune);
317         int i;                                          /* function called at interrupt time */
318 } Dbgkey;
319
320 static struct {
321         Rendez;
322         Dbgkey *work;
323         Dbgkey keys[50];
324         int nkeys;
325         int on;
326 } dbg;
327
328 static Dbgkey *finddbgkey(Rune r)
329 {
330         int i;
331         Dbgkey *dp;
332
333         for (dp = dbg.keys, i = 0; i < dbg.nkeys; i++, dp++)
334                 if (dp->r == r)
335                         return dp;
336         return NULL;
337 }
338
339 static int dbgwork(void *)
340 {
341         return dbg.work != 0;
342 }
343
344 static void dbgproc(void *)
345 {
346         Dbgkey *dp;
347
348         setpri(PriRealtime);
349         for (;;) {
350                 do {
351                         rendez_sleep(&dbg, dbgwork, 0);
352                         dp = dbg.work;
353                 } while (dp == NULL);
354                 dp->f(dp->r);
355                 dbg.work = NULL;
356         }
357 }
358
359 void debugkey(Rune r, char *msg, void (*fcn) (), int iflag)
360 {
361         Dbgkey *dp;
362
363         if (dbg.nkeys >= ARRAY_SIZE(dbg.keys))
364                 return;
365         if (finddbgkey(r) != NULL)
366                 return;
367         for (dp = &dbg.keys[dbg.nkeys++] - 1; dp >= dbg.keys; dp--) {
368                 if (strcmp(dp->m, msg) < 0)
369                         break;
370                 dp[1] = dp[0];
371         }
372         dp++;
373         dp->r = r;
374         dp->m = msg;
375         dp->f = fcn;
376         dp->i = iflag;
377 }
378
379 static int isdbgkey(Rune r)
380 {
381         static int ctrlt;
382         Dbgkey *dp;
383         int echoctrlt = ctrlt;
384
385         /*
386          * ^t hack BUG
387          */
388         if (dbg.on || (ctrlt >= 2)) {
389                 if (r == 0x14 || r == 0x05) {
390                         ctrlt++;
391                         return 0;
392                 }
393                 if (dp = finddbgkey(r)) {
394                         if (dp->i || ctrlt > 2)
395                                 dp->f(r);
396                         else {
397                                 dbg.work = dp;
398                                 rendez_wakeup(&dbg);
399                         }
400                         ctrlt = 0;
401                         return 1;
402                 }
403                 ctrlt = 0;
404         } else if (r == 0x14) {
405                 ctrlt++;
406                 return 1;
407         } else
408                 ctrlt = 0;
409         if (echoctrlt) {
410                 char buf[3];
411
412                 buf[0] = 0x14;
413                 while (--echoctrlt >= 0) {
414                         echo(buf[0], buf, 1);
415                         qproduce(kbdq, buf, 1);
416                 }
417         }
418         return 0;
419 }
420
421 static void dbgtoggle(Rune)
422 {
423         dbg.on = !dbg.on;
424         printd("Debug keys %s\n", dbg.on ? "HOT" : "COLD");
425 }
426
427 static void dbghelp(void)
428 {
429         int i;
430         Dbgkey *dp;
431         Dbgkey *dp2;
432         static char fmt[] = "%c: %-22s";
433
434         dp = dbg.keys;
435         dp2 = dp + (dbg.nkeys + 1) / 2;
436         for (i = dbg.nkeys; i > 1; i -= 2, dp++, dp2++) {
437                 printd(fmt, dp->r, dp->m);
438                 printd(fmt, dp2->r, dp2->m);
439                 printd("\n");
440         }
441         if (i)
442                 printd(fmt, dp->r, dp->m);
443         printd("\n");
444 }
445
446 static void debuginit(void)
447 {
448         ktask("consdbg", dbgproc, NULL);
449         debugkey('|', "HOT|COLD keys", dbgtoggle, 0);
450         debugkey('?', "help", dbghelp, 0);
451 }
452 #endif
453 #if 0
454 /*
455  *  Called by a uart interrupt for console input.
456  *
457  *  turn '\r' into '\n' before putting it into the queue.
458  */
459 int kbdcr2nl(struct queue *q, int ch)
460 {
461         if (ch == '\r')
462                 ch = '\n';
463         return kbdputc(q, ch);
464 }
465
466 /*
467  *  Put character, possibly a rune, into read queue at interrupt time.
468  *  Performs translation for compose sequences
469  *  Called at interrupt time to process a character.
470  */
471 int kbdputc(struct queue *q, int ch)
472 {
473         int n;
474         char buf[3];
475         Rune r;
476         static Rune kc[15];
477         static int nk, collecting = 0;
478
479         r = ch;
480         if (r == Latin) {
481                 collecting = 1;
482                 nk = 0;
483                 return 0;
484         }
485         if (collecting) {
486                 int c;
487                 nk += runetochar((char *unused_char_p_t)&kc[nk], &r);
488                 c = latin1(kc, nk);
489                 if (c < -1)     /* need more keystrokes */
490                         return 0;
491                 collecting = 0;
492                 if (c == -1) {  /* invalid sequence */
493                         echo(kc[0], (char *unused_char_p_t)kc, nk);
494                         qproduce(q, kc, nk);
495                         return 0;
496                 }
497                 r = (Rune) c;
498         }
499         kbd.c = r;
500         n = runetochar(buf, &r);
501         if (n == 0)
502                 return 0;
503         if (!isdbgkey(r)) {
504                 echo(r, buf, n);
505                 qproduce(q, buf, n);
506         }
507         return 0;
508 }
509
510 void kbdrepeat(int rep)
511 {
512         kbd.repeat = rep;
513         kbd.count = 0;
514 }
515
516 void kbdclock(void)
517 {
518         if (kbd.repeat == 0)
519                 return;
520         if (kbd.repeat == 1 && ++kbd.count > HZ) {
521                 kbd.repeat = 2;
522                 kbd.count = 0;
523                 return;
524         }
525         if (++kbd.count & 1)
526                 kbdputc(kbdq, kbd.c);
527 }
528 #endif
529
530 enum {
531         Qdir,
532         Qcons,
533         Qsysctl,
534         Qvmctl,
535         Qconsctl,
536         Qdrivers,
537         Qhostowner,
538         Qkeyboard,
539         Qklog,
540         Qkprint,
541         Qscancode,
542         Qmemory,
543         Qmsec,
544         Qnull,
545         Qrandom,
546         Qsysname,
547         Qtime,
548         Qurandom,
549         Quser,
550         Qjit,
551 };
552
553 static struct dirtab consdir[] = {
554         {".", {Qdir, 0, QTDIR}, 0, DMDIR | 0555},
555         {"cons", {Qcons}, 0, 0660},
556         {"consctl", {Qconsctl}, 0, 0220},
557         {"sysctl", {Qsysctl}, 0, 0666},
558         {"vmctl", {Qvmctl}, 0, 0666},
559         {"drivers", {Qdrivers}, 0, 0444},
560         {"hostowner", {Qhostowner}, 0, 0644},
561         {"keyboard", {Qkeyboard}, 0, 0666},
562         {"klog", {Qklog}, 0, 0444},
563         {"kprint", {Qkprint}, 0, 0444},
564         {"scancode", {Qscancode}, 0, 0444},
565         {"memory", {Qmemory}, 0, 0444},
566         {"msec", {Qmsec}, NUMSIZE, 0444},
567         {"null", {Qnull}, 0, 0666},
568         {"random", {Qrandom}, 0, 0444},
569         {"sysname", {Qsysname}, 0, 0664},
570         {"time", {Qtime}, 0, 0664},
571         {"user", {Quser}, 0, 0644},
572         {"urandom", {Qurandom}, 0, 0444},
573         {"jit", {Qjit}, 0, 0666},
574 };
575
576 uint32_t boottime;                              /* seconds since epoch at boot */
577
578 #if 0
579 void fddump()
580 {
581         struct proc *p;
582         Osenv *o;
583         int i;
584         struct chan *c;
585
586         p = proctab(6);
587         o = p->env;
588         for (i = 0; i <= o->fgrp->maxfd; i++) {
589                 if ((c = o->fgrp->fd[i]) == NULL)
590                         continue;
591                 printd("%d: %s\n", i, c->name == NULL ? "???" : c->name->s);
592         }
593 }
594 #endif
595
596 static void consinit(void)
597 {
598         randominit();
599 #if 0
600         debuginit();
601         debugkey('f', "files/6", fddump, 0);
602         debugkey('q', "panic", qpanic, 1);
603         debugkey('r', "exit", rexit, 1);
604         klogq = qopen(128 * 1024, 0, 0, 0);
605 #endif
606 }
607
608 static struct chan *consattach(char *spec)
609 {
610         return devattach(devname(), spec);
611 }
612
613 static struct walkqid *conswalk(struct chan *c, struct chan *nc, char **name,
614                                                                 int nname)
615 {
616         return devwalk(c, nc, name, nname, consdir, ARRAY_SIZE(consdir), devgen);
617 }
618
619 static int consstat(struct chan *c, uint8_t * dp, int n)
620 {
621         return devstat(c, dp, n, consdir, ARRAY_SIZE(consdir), devgen);
622 }
623
624 #if 0
625 static void flushkbdline(struct queue *q)
626 {
627         if (kbd.x) {
628                 qwrite(q, kbd.line, kbd.x);
629                 kbd.x = 0;
630         }
631 }
632 #endif
633
634 static struct chan *consopen(struct chan *c, int omode)
635 {
636         c->aux = 0;
637 #if 0
638         switch ((uint32_t) c->qid.path) {
639                 case Qconsctl:
640                         if (!iseve())
641                                 error(EPERM, NULL);
642                         qlock(&(&kbd)->qlock);
643                         kbd.ctl++;
644                         qunlock(&(&kbd)->qlock);
645                         break;
646
647                 case Qkeyboard:
648                         if ((omode & 3) != OWRITE) {
649                                 qlock(&(&kbd)->qlock);
650                                 kbd.kbdr++;
651                                 flushkbdline(kbdq);
652                                 kbd.raw = 1;
653                                 qunlock(&(&kbd)->qlock);
654                         }
655                         break;
656
657                 case Qscancode:
658                         qlock(&(&kbd)->qlock);
659                         if (kscanq || !kscanid) {
660                                 qunlock(&(&kbd)->qlock);
661                                 c->flag &= ~COPEN;
662                                 if (kscanq)
663                                         error(EBUSY, NULL);
664                                 else
665                                         error(EINVAL, NULL);
666                         }
667                         kscanq = qopen(256, 0, NULL, NULL);
668                         qunlock(&(&kbd)->qlock);
669                         break;
670
671                 case Qkprint:
672                         if ((omode & 3) != OWRITE) {
673                                 wlock(&(&kprintq)->rwlock);
674                                 if (kprintq.q != NULL) {
675                                         wunlock(&(&kprintq)->rwlock);
676                                         error(EBUSY, NULL);
677                                 }
678                                 kprintq.q = qopen(32 * 1024, Qcoalesce, NULL, NULL);
679                                 if (kprintq.q == NULL) {
680                                         wunlock(&(&kprintq)->rwlock);
681                                         error(ENOMEM, NULL);
682                                 }
683                                 qdropoverflow(kprintq.q, 1);
684                                 wunlock(&(&kprintq)->rwlock);
685                                 c->iounit = qiomaxatomic;
686                         }
687                         break;
688         }
689 #endif
690         return devopen(c, omode, consdir, ARRAY_SIZE(consdir), devgen);
691 }
692
693 static void consclose(struct chan *c)
694 {
695         if ((c->flag & COPEN) == 0)
696                 return;
697
698         switch ((uint32_t) c->qid.path) {
699 #if 0
700                 case Qconsctl:
701                         /* last close of control file turns off raw */
702                         qlock(&(&kbd)->qlock);
703                         if (--kbd.ctl == 0)
704                                 kbd.raw = 0;
705                         qunlock(&(&kbd)->qlock);
706                         break;
707
708                 case Qkeyboard:
709                         if (c->mode != OWRITE) {
710                                 qlock(&(&kbd)->qlock);
711                                 --kbd.kbdr;
712                                 qunlock(&(&kbd)->qlock);
713                         }
714                         break;
715
716                 case Qscancode:
717                         qlock(&(&kbd)->qlock);
718                         if (kscanq) {
719                                 qfree(kscanq);
720                                 kscanq = 0;
721                         }
722                         qunlock(&(&kbd)->qlock);
723                         break;
724
725                 case Qkprint:
726                         wlock(&(&kprintq)->rwlock);
727                         qfree(kprintq.q);
728                         kprintq.q = NULL;
729                         wunlock(&(&kprintq)->rwlock);
730                         break;
731 #endif
732                 default:
733                         break;
734         }
735 }
736
737 /* we do it this way to avoid the many fun deadlock opportunities
738  * we keep hitting. And, if you don't suck it
739  * out soon enough, you lost it. No real effort to ensure goodness
740  * here as it can get called anywhere. Barret will fix it.
741  */
742 static uint8_t logbuffer[1 << 20];
743 static int index = 0;
744 static struct queue *logqueue = NULL;
745 static int reading_kmesg = 0;
746 void logbuf(int c)
747 {
748         if (reading_kmesg)
749                 return;
750         if (index > 1 << 20)
751                 return;
752         logbuffer[index++] = c;
753 }
754
755 static long consread(struct chan *c, void *buf, long n, int64_t offset)
756 {
757         ERRSTACK(1);
758         int l;
759
760         int ch, eol, i;
761         char *p, tmp[128];
762         char *cbuf = buf;
763
764         if (n <= 0)
765                 return n;
766
767         switch ((uint32_t) c->qid.path) {
768                 case Qdir:
769                         return devdirread(c, buf, n, consdir, ARRAY_SIZE(consdir), devgen);
770                 case Qsysctl:
771                         return readstr(offset, buf, n, "akaros");
772 #if 0
773                 case Qcons:
774                 case Qkeyboard:
775                         qlock(&(&kbd)->qlock);
776                         if (waserror()) {
777                                 qunlock(&(&kbd)->qlock);
778                                 nexterror();
779                         }
780                         if (kbd.raw || kbd.kbdr) {
781                                 if (qcanread(lineq))
782                                         n = qread(lineq, buf, n);
783                                 else {
784                                         /* read as much as possible */
785                                         do {
786                                                 i = qread(kbdq, cbuf, n);
787                                                 cbuf += i;
788                                                 n -= i;
789                                         } while (n > 0 && qcanread(kbdq));
790                                         n = cbuf - (char *unused_char_p_t)buf;
791                                 }
792                         } else {
793                                 while (!qcanread(lineq)) {
794                                         qread(kbdq, &kbd.line[kbd.x], 1);
795                                         ch = kbd.line[kbd.x];
796                                         eol = 0;
797                                         switch (ch) {
798                                                 case '\b':
799                                                         if (kbd.x)
800                                                                 kbd.x--;
801                                                         break;
802                                                 case 0x15:
803                                                         kbd.x = 0;
804                                                         break;
805                                                 case '\n':
806                                                 case 0x04:
807                                                         eol = 1;
808                                                 default:
809                                                         kbd.line[kbd.x++] = ch;
810                                                         break;
811                                         }
812                                         if (kbd.x == sizeof(kbd.line) || eol) {
813                                                 if (ch == 0x04)
814                                                         kbd.x--;
815                                                 qwrite(lineq, kbd.line, kbd.x);
816                                                 kbd.x = 0;
817                                         }
818                                 }
819                                 n = qread(lineq, buf, n);
820                         }
821                         qunlock(&(&kbd)->qlock);
822                         poperror();
823                         return n;
824
825                 case Qscancode:
826                         if (offset == 0)
827                                 return readstr(0, buf, n, kscanid);
828                         else
829                                 return qread(kscanq, buf, n);
830
831                 case Qtime:
832                         snprintf(tmp, sizeof(tmp), "%.lld", (int64_t) mseconds() * 1000);
833                         return readstr(offset, buf, n, tmp);
834
835                 case Qhostowner:
836                         return readstr(offset, buf, n, eve);
837
838                 case Quser:
839                         return readstr(offset, buf, n, o->user);
840
841                 case Qjit:
842                         snprintf(tmp, sizeof(tmp), "%d", cflag);
843                         return readstr(offset, buf, n, tmp);
844 #endif
845                 case Qnull:
846                         return 0;
847 #if 0
848                 case Qmsec:
849                         return readnum(offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE);
850 #endif
851                 case Qsysname:
852                         if (sysname == NULL)
853                                 return 0;
854                         return readstr(offset, buf, n, "Akaros");
855
856                 case Qrandom:
857                 case Qurandom:
858                         return randomread(buf, n);
859 #if 0
860                 case Qmemory:
861                         return poolread(buf, n, offset);
862 #endif
863                 case Qdrivers:
864                         p = kzmalloc(READSTR, 0);
865                         if (p == NULL)
866                                 error(ENOMEM, NULL);
867                         l = 0;
868                         for (i = 0; &devtab[i] < __devtabend; i++)
869                                 l += snprintf(p + l, READSTR - l, "#%s\n", devtab[i].name);
870                         if (waserror()) {
871                                 kfree(p);
872                                 nexterror();
873                         }
874                         n = readstr(offset, buf, n, p);
875                         kfree(p);
876                         poperror();
877                         return n;
878                 case Qklog:
879                         //return qread(klogq, buf, n);
880                         /* the queue gives us some elasticity for log reading. */
881                         if (!logqueue)
882                                 logqueue = qopen(1 << 20, 0, 0, 0);
883                         if (logqueue) {
884                                 int ret;
885                                 /* atomic sets/gets are not that important in this case. */
886                                 reading_kmesg = 1;
887                                 qwrite(logqueue, logbuffer, index);
888                                 index = 0;
889                                 ret = qread(logqueue, buf, n);
890                                 reading_kmesg = 0;
891                                 return ret;
892                         }
893                         break;
894 #if 0
895                 case Qkprint:
896                         rlock(&(&kprintq)->rwlock);
897                         if (waserror()) {
898                                 runlock(&(&kprintq)->rwlock);
899                                 nexterror();
900                         }
901                         n = qread(kprintq.q, buf, n);
902                         poperror();
903                         runlock(&(&kprintq)->rwlock);
904                         return n;
905 #endif
906                 default:
907                         printd("consread %llu\n", c->qid.path);
908                         error(EINVAL, NULL);
909         }
910         return -1;      /* never reached */
911 }
912
913 static long conswrite(struct chan *c, void *va, long n, int64_t offset)
914 {
915         ERRSTACK(1);
916         int64_t t;
917         uint64_t ip;
918         long l, bp;
919         char *a = va;
920         struct cmdbuf *cb;
921         struct cmdtab *ct;
922         char buf[256];
923         int x;
924         uint64_t rip, rsp, cr3, flags, vcpu;
925         int ret;
926         struct vmctl vmctl;
927
928         switch ((uint32_t) c->qid.path) {
929 #if 0
930                 case Qcons:
931                         /*
932                          * Can't page fault in putstrn, so copy the data locally.
933                          */
934                         l = n;
935                         while (l > 0) {
936                                 bp = l;
937                                 if (bp > sizeof buf)
938                                         bp = sizeof buf;
939                                 memmove(buf, a, bp);
940                                 putstrn0(a, bp, 1);
941                                 a += bp;
942                                 l -= bp;
943                         }
944                         break;
945
946                 case Qconsctl:
947                         if (n >= sizeof(buf))
948                                 n = sizeof(buf) - 1;
949                         strncpy(buf, a, n);
950                         buf[n] = 0;
951                         for (a = buf; a;) {
952                                 if (strncmp(a, "rawon", 5) == 0) {
953                                         qlock(&(&kbd)->qlock);
954                                         flushkbdline(kbdq);
955                                         kbd.raw = 1;
956                                         qunlock(&(&kbd)->qlock);
957                                 } else if (strncmp(a, "rawoff", 6) == 0) {
958                                         qlock(&(&kbd)->qlock);
959                                         kbd.raw = 0;
960                                         kbd.x = 0;
961                                         qunlock(&(&kbd)->qlock);
962                                 }
963                                 if (a = strchr(a, ' '))
964                                         a++;
965                         }
966                         break;
967
968                 case Qkeyboard:
969                         for (x = 0; x < n;) {
970                                 Rune r;
971                                 x += chartorune(&r, &a[x]);
972                                 kbdputc(kbdq, r);
973                         }
974                         break;
975
976                 case Qtime:
977                         if (n >= sizeof(buf))
978                                 n = sizeof(buf) - 1;
979                         strncpy(buf, a, n);
980                         buf[n] = 0;
981                         t = strtoll(buf, 0, 0) / 1000000;
982                         boottime = t - TK2SEC(MACHP(0)->ticks);
983                         break;
984
985                 case Qhostowner:
986                         if (!iseve())
987                                 error(EPERM, NULL);
988                         if (offset != 0 || n >= sizeof(buf))
989                                 error(EINVAL, NULL);
990                         memmove(buf, a, n);
991                         buf[n] = '\0';
992                         if (n > 0 && buf[n - 1] == '\n')
993                                 buf[--n] = 0;
994                         if (n <= 0)
995                                 error(EINVAL, NULL);
996                         renameuser(eve, buf);
997                         renameproguser(eve, buf);
998                         kstrdup(&eve, buf);
999                         kstrdup(&up->env->user, buf);
1000                         break;
1001
1002                 case Quser:
1003                         if (!iseve())
1004                                 error(EPERM, NULL);
1005                         if (offset != 0)
1006                                 error(EINVAL, NULL);
1007                         if (n <= 0 || n >= sizeof(buf))
1008                                 error(EINVAL, NULL);
1009                         strncpy(buf, a, n);
1010                         buf[n] = 0;
1011                         if (buf[n - 1] == '\n')
1012                                 buf[n - 1] = 0;
1013                         kstrdup(&up->env->user, buf);
1014                         break;
1015
1016                 case Qjit:
1017                         if (n >= sizeof(buf))
1018                                 n = sizeof(buf) - 1;
1019                         strncpy(buf, va, n);
1020                         buf[n] = '\0';
1021                         x = atoi(buf);
1022                         if (x < 0 || x > 9)
1023                                 error(EINVAL, NULL);
1024                         cflag = x;
1025                         return n;
1026
1027                 case Qnull:
1028                         break;
1029
1030                 case Qsysname:
1031                         if (offset != 0)
1032                                 error(EINVAL, NULL);
1033                         if (n <= 0 || n >= sizeof(buf))
1034                                 error(EINVAL, NULL);
1035                         strncpy(buf, a, n);
1036                         buf[n] = 0;
1037                         if (buf[n - 1] == '\n')
1038                                 buf[n - 1] = 0;
1039                         kstrdup(&sysname, buf);
1040                         break;
1041 #endif
1042                 case Qvmctl:
1043                         memmove(&vmctl, a, sizeof(vmctl));
1044                         if ((offset >> 12) ==1) {
1045                                 ret = vm_post_interrupt(&vmctl);
1046                                 n = ret;
1047                                 //printk("vm_interrupt_notify returns %d\n", ret);
1048                         }
1049                         else {
1050                                 ret = vm_run(&vmctl);
1051                                 printd("vm_run returns %d\n", ret);
1052                                 n = ret;
1053                                 memmove(a, &vmctl, sizeof(vmctl));
1054                         }
1055                         break;
1056                 case Qsysctl:
1057                         //if (!iseve()) error(EPERM, NULL);
1058                         cb = parsecmd(a, n);
1059                         if (cb->nf > 1)
1060                         printd("cons sysctl cmd %s\n", cb->f[0]);
1061                         if (waserror()) {
1062                                 kfree(cb);
1063                                 nexterror();
1064                         }
1065                         ct = lookupcmd(cb, sysctlcmd, ARRAY_SIZE(sysctlcmd));
1066                         switch (ct->index) {
1067                                 case CMreboot:
1068                                         reboot();
1069                                         break;
1070                                 case CMhalt:
1071                                         cpu_halt();
1072                                         break;
1073                                 case CMpanic:
1074                                         panic("sysctl");
1075                                         //case CMconsole:
1076                                         //consoleprint = strcmp(cb->f[1], "off") != 0;
1077                                         break;
1078                                 case CMbroken:
1079                                         keepbroken = 1;
1080                                         break;
1081                                 case CMnobroken:
1082                                         keepbroken = 0;
1083                                         break;
1084                                 case CMV:
1085                                         /* it's ok to throw away this struct each time;
1086                                          * this is stateless and going away soon anyway.
1087                                          * we only kept it here until we can rewrite all the
1088                                          * tests
1089                                          */
1090                                         rip =  strtoul(cb->f[1], NULL, 0);
1091                                         rsp =  strtoul(cb->f[2], NULL, 0);
1092                                         cr3 =  strtoul(cb->f[3], NULL, 0);
1093                                         if (cr3) {
1094                                                 vmctl.command = REG_RSP_RIP_CR3;
1095                                                 vmctl.cr3 = cr3;
1096                                                 vmctl.regs.tf_rip = rip;
1097                                                 vmctl.regs.tf_rsp = rsp;
1098                                         } else {
1099                                                 vmctl.command = RESUME;
1100                                         }
1101                                         ret = vm_run(&vmctl);
1102                                         printd("vm_run returns %d\n", ret);
1103                                         n = ret;
1104                                         break;
1105                         }
1106                         poperror();
1107                         kfree(cb);
1108                         break;
1109                 default:
1110                         printd("conswrite: %llu\n", c->qid.path);
1111                         error(EINVAL, NULL);
1112         }
1113         return n;
1114 }
1115
1116 struct dev consdevtab __devtab = {
1117         .name = "cons",
1118
1119         .reset = devreset,
1120         .init = consinit,
1121         .shutdown = devshutdown,
1122         .attach = consattach,
1123         .walk = conswalk,
1124         .stat = consstat,
1125         .open = consopen,
1126         .create = devcreate,
1127         .close = consclose,
1128         .read = consread,
1129         .bread = devbread,
1130         .write = conswrite,
1131         .bwrite = devbwrite,
1132         .remove = devremove,
1133         .wstat = devwstat,
1134         .power = devpower,
1135         .chaninfo = devchaninfo,
1136 };
1137
1138 static uint32_t randn;
1139
1140 static void seedrand(void)
1141 {
1142         randomread((void *)&randn, sizeof(randn));
1143 }
1144
1145 int nrand(int n)
1146 {
1147         if (randn == 0)
1148                 seedrand();
1149         randn = randn * 1103515245 + 12345 + read_tsc();
1150         return (randn >> 16) % n;
1151 }
1152
1153 int rand(void)
1154 {
1155         nrand(1);
1156         return randn;
1157 }
1158
1159 uint32_t truerand(void)
1160 {
1161         uint32_t x;
1162
1163         randomread(&x, sizeof(x));
1164         return x;
1165 }
1166
1167 /* TODO: qlock_init this, if you ever use this */
1168 qlock_t grandomlk;
1169
1170 void _genrandomqlock(void)
1171 {
1172         qlock(&grandomlk);
1173 }
1174
1175 void _genrandomqunlock(void)
1176 {
1177         qunlock(&grandomlk);
1178 }