blob: d00123421e0075c1a0d2e340961183a912af074b [file] [log] [blame]
Paul Mackerrasfca5dcd2005-11-08 22:55:08 +11001/*
2 * Copyright (C) 1996-2005 Paul Mackerras.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9#include <linux/string.h>
Michael Ellerman33b5cd62012-10-09 04:20:32 +000010#include <asm/udbg.h>
Paul Mackerrasfca5dcd2005-11-08 22:55:08 +110011#include <asm/time.h>
12#include "nonstdio.h"
13
Sam bobroff958b7c82015-10-08 11:50:23 +110014static bool paginating, paginate_skipping;
15static unsigned long paginate_lpp; /* Lines Per Page */
16static unsigned long paginate_pos;
Michael Ellerman33b5cd62012-10-09 04:20:32 +000017
Sam bobroff958b7c82015-10-08 11:50:23 +110018void xmon_start_pagination(void)
Michael Ellerman33b5cd62012-10-09 04:20:32 +000019{
Sam bobroff958b7c82015-10-08 11:50:23 +110020 paginating = true;
21 paginate_skipping = false;
22 paginate_pos = 0;
23}
24
25void xmon_end_pagination(void)
26{
27 paginating = false;
28}
29
30void xmon_set_pagination_lpp(unsigned long lpp)
31{
32 paginate_lpp = lpp;
Michael Ellerman33b5cd62012-10-09 04:20:32 +000033}
34
35static int xmon_readchar(void)
36{
37 if (udbg_getc)
38 return udbg_getc();
39 return -1;
40}
41
Sam bobroff958b7c82015-10-08 11:50:23 +110042static int xmon_write(const char *ptr, int nb)
43{
44 int rv = 0;
45 const char *p = ptr, *q;
46 const char msg[] = "[Hit a key (a:all, q:truncate, any:next page)]";
47
48 if (nb <= 0)
49 return rv;
50
51 if (paginating && paginate_skipping)
52 return nb;
53
54 if (paginate_lpp) {
55 while (paginating && (q = strchr(p, '\n'))) {
56 rv += udbg_write(p, q - p + 1);
57 p = q + 1;
58 paginate_pos++;
59
60 if (paginate_pos >= paginate_lpp) {
61 udbg_write(msg, strlen(msg));
62
63 switch (xmon_readchar()) {
64 case 'a':
65 paginating = false;
66 break;
67 case 'q':
68 paginate_skipping = true;
69 break;
70 default:
71 /* nothing */
72 break;
73 }
74
75 paginate_pos = 0;
76 udbg_write("\r\n", 2);
77
78 if (paginate_skipping)
79 return nb;
80 }
81 }
82 }
83
84 return rv + udbg_write(p, nb - (p - ptr));
85}
86
Paul Mackerrasfca5dcd2005-11-08 22:55:08 +110087int xmon_putchar(int c)
88{
89 char ch = c;
90
91 if (c == '\n')
92 xmon_putchar('\r');
93 return xmon_write(&ch, 1) == 1? c: -1;
94}
95
96static char line[256];
97static char *lineptr;
98static int lineleft;
99
Michael Ellerman88c6d622012-10-09 04:20:31 +0000100static int xmon_getchar(void)
Paul Mackerrasfca5dcd2005-11-08 22:55:08 +1100101{
102 int c;
103
104 if (lineleft == 0) {
105 lineptr = line;
106 for (;;) {
107 c = xmon_readchar();
108 if (c == -1 || c == 4)
109 break;
110 if (c == '\r' || c == '\n') {
111 *lineptr++ = '\n';
112 xmon_putchar('\n');
113 break;
114 }
115 switch (c) {
116 case 0177:
117 case '\b':
118 if (lineptr > line) {
119 xmon_putchar('\b');
120 xmon_putchar(' ');
121 xmon_putchar('\b');
122 --lineptr;
123 }
124 break;
125 case 'U' & 0x1F:
126 while (lineptr > line) {
127 xmon_putchar('\b');
128 xmon_putchar(' ');
129 xmon_putchar('\b');
130 --lineptr;
131 }
132 break;
133 default:
134 if (lineptr >= &line[sizeof(line) - 1])
135 xmon_putchar('\a');
136 else {
137 xmon_putchar(c);
138 *lineptr++ = c;
139 }
140 }
141 }
142 lineleft = lineptr - line;
143 lineptr = line;
144 }
145 if (lineleft == 0)
146 return -1;
147 --lineleft;
148 return *lineptr++;
149}
150
151char *xmon_gets(char *str, int nb)
152{
153 char *p;
154 int c;
155
156 for (p = str; p < str + nb - 1; ) {
157 c = xmon_getchar();
158 if (c == -1) {
159 if (p == str)
160 return NULL;
161 break;
162 }
163 *p++ = c;
164 if (c == '\n')
165 break;
166 }
167 *p = 0;
168 return str;
169}
170
171void xmon_printf(const char *format, ...)
172{
173 va_list args;
Paul Mackerrasfca5dcd2005-11-08 22:55:08 +1100174 static char xmon_outbuf[1024];
Michael Ellermanb2bb65f2012-10-09 04:20:47 +0000175 int rc, n;
Paul Mackerrasfca5dcd2005-11-08 22:55:08 +1100176
177 va_start(args, format);
178 n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
179 va_end(args);
Michael Ellermanb2bb65f2012-10-09 04:20:47 +0000180
181 rc = xmon_write(xmon_outbuf, n);
182
183 if (n && rc == 0) {
184 /* No udbg hooks, fallback to printk() - dangerous */
Kees Cook50b66db2014-06-10 10:54:06 -0700185 printk("%s", xmon_outbuf);
Michael Ellermanb2bb65f2012-10-09 04:20:47 +0000186 }
Paul Mackerrasfca5dcd2005-11-08 22:55:08 +1100187}
Ishizaki Kou4d404ed2007-07-18 19:26:40 +1000188
189void xmon_puts(const char *str)
190{
191 xmon_write(str, strlen(str));
192}