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