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