1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 1996-2005 Paul Mackerras.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun #include <linux/string.h>
6*4882a593Smuzhiyun #include <asm/udbg.h>
7*4882a593Smuzhiyun #include <asm/time.h>
8*4882a593Smuzhiyun #include "nonstdio.h"
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun static bool paginating, paginate_skipping;
11*4882a593Smuzhiyun static unsigned long paginate_lpp; /* Lines Per Page */
12*4882a593Smuzhiyun static unsigned long paginate_pos;
13*4882a593Smuzhiyun
xmon_start_pagination(void)14*4882a593Smuzhiyun void xmon_start_pagination(void)
15*4882a593Smuzhiyun {
16*4882a593Smuzhiyun paginating = true;
17*4882a593Smuzhiyun paginate_skipping = false;
18*4882a593Smuzhiyun paginate_pos = 0;
19*4882a593Smuzhiyun }
20*4882a593Smuzhiyun
xmon_end_pagination(void)21*4882a593Smuzhiyun void xmon_end_pagination(void)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun paginating = false;
24*4882a593Smuzhiyun }
25*4882a593Smuzhiyun
xmon_set_pagination_lpp(unsigned long lpp)26*4882a593Smuzhiyun void xmon_set_pagination_lpp(unsigned long lpp)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun paginate_lpp = lpp;
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun
xmon_readchar(void)31*4882a593Smuzhiyun static int xmon_readchar(void)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun if (udbg_getc)
34*4882a593Smuzhiyun return udbg_getc();
35*4882a593Smuzhiyun return -1;
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun
xmon_write(const char * ptr,int nb)38*4882a593Smuzhiyun static int xmon_write(const char *ptr, int nb)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun int rv = 0;
41*4882a593Smuzhiyun const char *p = ptr, *q;
42*4882a593Smuzhiyun const char msg[] = "[Hit a key (a:all, q:truncate, any:next page)]";
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun if (nb <= 0)
45*4882a593Smuzhiyun return rv;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun if (paginating && paginate_skipping)
48*4882a593Smuzhiyun return nb;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (paginate_lpp) {
51*4882a593Smuzhiyun while (paginating && (q = strchr(p, '\n'))) {
52*4882a593Smuzhiyun rv += udbg_write(p, q - p + 1);
53*4882a593Smuzhiyun p = q + 1;
54*4882a593Smuzhiyun paginate_pos++;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun if (paginate_pos >= paginate_lpp) {
57*4882a593Smuzhiyun udbg_write(msg, strlen(msg));
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun switch (xmon_readchar()) {
60*4882a593Smuzhiyun case 'a':
61*4882a593Smuzhiyun paginating = false;
62*4882a593Smuzhiyun break;
63*4882a593Smuzhiyun case 'q':
64*4882a593Smuzhiyun paginate_skipping = true;
65*4882a593Smuzhiyun break;
66*4882a593Smuzhiyun default:
67*4882a593Smuzhiyun /* nothing */
68*4882a593Smuzhiyun break;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun paginate_pos = 0;
72*4882a593Smuzhiyun udbg_write("\r\n", 2);
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun if (paginate_skipping)
75*4882a593Smuzhiyun return nb;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun return rv + udbg_write(p, nb - (p - ptr));
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
xmon_putchar(int c)83*4882a593Smuzhiyun int xmon_putchar(int c)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun char ch = c;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun if (c == '\n')
88*4882a593Smuzhiyun xmon_putchar('\r');
89*4882a593Smuzhiyun return xmon_write(&ch, 1) == 1? c: -1;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun static char line[256];
93*4882a593Smuzhiyun static char *lineptr;
94*4882a593Smuzhiyun static int lineleft;
95*4882a593Smuzhiyun
xmon_getchar(void)96*4882a593Smuzhiyun static int xmon_getchar(void)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun int c;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun if (lineleft == 0) {
101*4882a593Smuzhiyun lineptr = line;
102*4882a593Smuzhiyun for (;;) {
103*4882a593Smuzhiyun c = xmon_readchar();
104*4882a593Smuzhiyun if (c == -1 || c == 4)
105*4882a593Smuzhiyun break;
106*4882a593Smuzhiyun if (c == '\r' || c == '\n') {
107*4882a593Smuzhiyun *lineptr++ = '\n';
108*4882a593Smuzhiyun xmon_putchar('\n');
109*4882a593Smuzhiyun break;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun switch (c) {
112*4882a593Smuzhiyun case 0177:
113*4882a593Smuzhiyun case '\b':
114*4882a593Smuzhiyun if (lineptr > line) {
115*4882a593Smuzhiyun xmon_putchar('\b');
116*4882a593Smuzhiyun xmon_putchar(' ');
117*4882a593Smuzhiyun xmon_putchar('\b');
118*4882a593Smuzhiyun --lineptr;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun break;
121*4882a593Smuzhiyun case 'U' & 0x1F:
122*4882a593Smuzhiyun while (lineptr > line) {
123*4882a593Smuzhiyun xmon_putchar('\b');
124*4882a593Smuzhiyun xmon_putchar(' ');
125*4882a593Smuzhiyun xmon_putchar('\b');
126*4882a593Smuzhiyun --lineptr;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun break;
129*4882a593Smuzhiyun default:
130*4882a593Smuzhiyun if (lineptr >= &line[sizeof(line) - 1])
131*4882a593Smuzhiyun xmon_putchar('\a');
132*4882a593Smuzhiyun else {
133*4882a593Smuzhiyun xmon_putchar(c);
134*4882a593Smuzhiyun *lineptr++ = c;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun lineleft = lineptr - line;
139*4882a593Smuzhiyun lineptr = line;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun if (lineleft == 0)
142*4882a593Smuzhiyun return -1;
143*4882a593Smuzhiyun --lineleft;
144*4882a593Smuzhiyun return *lineptr++;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
xmon_gets(char * str,int nb)147*4882a593Smuzhiyun char *xmon_gets(char *str, int nb)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun char *p;
150*4882a593Smuzhiyun int c;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun for (p = str; p < str + nb - 1; ) {
153*4882a593Smuzhiyun c = xmon_getchar();
154*4882a593Smuzhiyun if (c == -1) {
155*4882a593Smuzhiyun if (p == str)
156*4882a593Smuzhiyun return NULL;
157*4882a593Smuzhiyun break;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun *p++ = c;
160*4882a593Smuzhiyun if (c == '\n')
161*4882a593Smuzhiyun break;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun *p = 0;
164*4882a593Smuzhiyun return str;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
xmon_printf(const char * format,...)167*4882a593Smuzhiyun void xmon_printf(const char *format, ...)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun va_list args;
170*4882a593Smuzhiyun static char xmon_outbuf[1024];
171*4882a593Smuzhiyun int rc, n;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun va_start(args, format);
174*4882a593Smuzhiyun n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
175*4882a593Smuzhiyun va_end(args);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun rc = xmon_write(xmon_outbuf, n);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun if (n && rc == 0) {
180*4882a593Smuzhiyun /* No udbg hooks, fallback to printk() - dangerous */
181*4882a593Smuzhiyun pr_cont("%s", xmon_outbuf);
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
xmon_puts(const char * str)185*4882a593Smuzhiyun void xmon_puts(const char *str)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun xmon_write(str, strlen(str));
188*4882a593Smuzhiyun }
189