18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 1996-2005 Paul Mackerras. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#include <linux/string.h> 68c2ecf20Sopenharmony_ci#include <asm/udbg.h> 78c2ecf20Sopenharmony_ci#include <asm/time.h> 88c2ecf20Sopenharmony_ci#include "nonstdio.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_cistatic bool paginating, paginate_skipping; 118c2ecf20Sopenharmony_cistatic unsigned long paginate_lpp; /* Lines Per Page */ 128c2ecf20Sopenharmony_cistatic unsigned long paginate_pos; 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_civoid xmon_start_pagination(void) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci paginating = true; 178c2ecf20Sopenharmony_ci paginate_skipping = false; 188c2ecf20Sopenharmony_ci paginate_pos = 0; 198c2ecf20Sopenharmony_ci} 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_civoid xmon_end_pagination(void) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci paginating = false; 248c2ecf20Sopenharmony_ci} 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_civoid xmon_set_pagination_lpp(unsigned long lpp) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci paginate_lpp = lpp; 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic int xmon_readchar(void) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci if (udbg_getc) 348c2ecf20Sopenharmony_ci return udbg_getc(); 358c2ecf20Sopenharmony_ci return -1; 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic int xmon_write(const char *ptr, int nb) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci int rv = 0; 418c2ecf20Sopenharmony_ci const char *p = ptr, *q; 428c2ecf20Sopenharmony_ci const char msg[] = "[Hit a key (a:all, q:truncate, any:next page)]"; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci if (nb <= 0) 458c2ecf20Sopenharmony_ci return rv; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (paginating && paginate_skipping) 488c2ecf20Sopenharmony_ci return nb; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci if (paginate_lpp) { 518c2ecf20Sopenharmony_ci while (paginating && (q = strchr(p, '\n'))) { 528c2ecf20Sopenharmony_ci rv += udbg_write(p, q - p + 1); 538c2ecf20Sopenharmony_ci p = q + 1; 548c2ecf20Sopenharmony_ci paginate_pos++; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci if (paginate_pos >= paginate_lpp) { 578c2ecf20Sopenharmony_ci udbg_write(msg, strlen(msg)); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci switch (xmon_readchar()) { 608c2ecf20Sopenharmony_ci case 'a': 618c2ecf20Sopenharmony_ci paginating = false; 628c2ecf20Sopenharmony_ci break; 638c2ecf20Sopenharmony_ci case 'q': 648c2ecf20Sopenharmony_ci paginate_skipping = true; 658c2ecf20Sopenharmony_ci break; 668c2ecf20Sopenharmony_ci default: 678c2ecf20Sopenharmony_ci /* nothing */ 688c2ecf20Sopenharmony_ci break; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci paginate_pos = 0; 728c2ecf20Sopenharmony_ci udbg_write("\r\n", 2); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (paginate_skipping) 758c2ecf20Sopenharmony_ci return nb; 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci return rv + udbg_write(p, nb - (p - ptr)); 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ciint xmon_putchar(int c) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci char ch = c; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (c == '\n') 888c2ecf20Sopenharmony_ci xmon_putchar('\r'); 898c2ecf20Sopenharmony_ci return xmon_write(&ch, 1) == 1? c: -1; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic char line[256]; 938c2ecf20Sopenharmony_cistatic char *lineptr; 948c2ecf20Sopenharmony_cistatic int lineleft; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic int xmon_getchar(void) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci int c; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci if (lineleft == 0) { 1018c2ecf20Sopenharmony_ci lineptr = line; 1028c2ecf20Sopenharmony_ci for (;;) { 1038c2ecf20Sopenharmony_ci c = xmon_readchar(); 1048c2ecf20Sopenharmony_ci if (c == -1 || c == 4) 1058c2ecf20Sopenharmony_ci break; 1068c2ecf20Sopenharmony_ci if (c == '\r' || c == '\n') { 1078c2ecf20Sopenharmony_ci *lineptr++ = '\n'; 1088c2ecf20Sopenharmony_ci xmon_putchar('\n'); 1098c2ecf20Sopenharmony_ci break; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci switch (c) { 1128c2ecf20Sopenharmony_ci case 0177: 1138c2ecf20Sopenharmony_ci case '\b': 1148c2ecf20Sopenharmony_ci if (lineptr > line) { 1158c2ecf20Sopenharmony_ci xmon_putchar('\b'); 1168c2ecf20Sopenharmony_ci xmon_putchar(' '); 1178c2ecf20Sopenharmony_ci xmon_putchar('\b'); 1188c2ecf20Sopenharmony_ci --lineptr; 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci break; 1218c2ecf20Sopenharmony_ci case 'U' & 0x1F: 1228c2ecf20Sopenharmony_ci while (lineptr > line) { 1238c2ecf20Sopenharmony_ci xmon_putchar('\b'); 1248c2ecf20Sopenharmony_ci xmon_putchar(' '); 1258c2ecf20Sopenharmony_ci xmon_putchar('\b'); 1268c2ecf20Sopenharmony_ci --lineptr; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci break; 1298c2ecf20Sopenharmony_ci default: 1308c2ecf20Sopenharmony_ci if (lineptr >= &line[sizeof(line) - 1]) 1318c2ecf20Sopenharmony_ci xmon_putchar('\a'); 1328c2ecf20Sopenharmony_ci else { 1338c2ecf20Sopenharmony_ci xmon_putchar(c); 1348c2ecf20Sopenharmony_ci *lineptr++ = c; 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci lineleft = lineptr - line; 1398c2ecf20Sopenharmony_ci lineptr = line; 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci if (lineleft == 0) 1428c2ecf20Sopenharmony_ci return -1; 1438c2ecf20Sopenharmony_ci --lineleft; 1448c2ecf20Sopenharmony_ci return *lineptr++; 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cichar *xmon_gets(char *str, int nb) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci char *p; 1508c2ecf20Sopenharmony_ci int c; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci for (p = str; p < str + nb - 1; ) { 1538c2ecf20Sopenharmony_ci c = xmon_getchar(); 1548c2ecf20Sopenharmony_ci if (c == -1) { 1558c2ecf20Sopenharmony_ci if (p == str) 1568c2ecf20Sopenharmony_ci return NULL; 1578c2ecf20Sopenharmony_ci break; 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci *p++ = c; 1608c2ecf20Sopenharmony_ci if (c == '\n') 1618c2ecf20Sopenharmony_ci break; 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci *p = 0; 1648c2ecf20Sopenharmony_ci return str; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_civoid xmon_printf(const char *format, ...) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci va_list args; 1708c2ecf20Sopenharmony_ci static char xmon_outbuf[1024]; 1718c2ecf20Sopenharmony_ci int rc, n; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci va_start(args, format); 1748c2ecf20Sopenharmony_ci n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args); 1758c2ecf20Sopenharmony_ci va_end(args); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci rc = xmon_write(xmon_outbuf, n); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci if (n && rc == 0) { 1808c2ecf20Sopenharmony_ci /* No udbg hooks, fallback to printk() - dangerous */ 1818c2ecf20Sopenharmony_ci pr_cont("%s", xmon_outbuf); 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_civoid xmon_puts(const char *str) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci xmon_write(str, strlen(str)); 1888c2ecf20Sopenharmony_ci} 189