Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
618a97ae79 | ||
|
|
75ea9beef6 | ||
|
|
70bbe178a0 | ||
|
|
03cc6418c1 | ||
|
|
340e2ef64b | ||
|
|
d0f4eee6ba | ||
|
|
6d67faf753 | ||
|
|
1c94482340 | ||
|
|
bf1e7f3646 | ||
|
|
cbdeff3610 | ||
|
|
81ed315188 | ||
|
|
18b67cfa7b | ||
|
|
f904c0cd47 | ||
|
|
b736974fda | ||
|
|
932517d73c | ||
|
|
e7e955ac9d |
@@ -332,6 +332,26 @@ config SYS_DEVICE_NULLDEV
|
|||||||
operation of the console by setting stdout to "nulldev". Enable
|
operation of the console by setting stdout to "nulldev". Enable
|
||||||
this to use a serial console under board control.
|
this to use a serial console under board control.
|
||||||
|
|
||||||
|
config CONSOLE_PAGER
|
||||||
|
bool "Enable console output paging"
|
||||||
|
depends on CONSOLE_MUX
|
||||||
|
default y if SANDBOX
|
||||||
|
help
|
||||||
|
Enable pager functionality for console output. When enabled, long
|
||||||
|
output will be paused after a configurable number of lines, waiting
|
||||||
|
for user input (SPACE) to continue. The number of lines per page is
|
||||||
|
controlled by the 'pager' environment variable. If the variable is
|
||||||
|
not set or is empty, paging is disabled.
|
||||||
|
|
||||||
|
config CONSOLE_PAGER_LINES
|
||||||
|
int "Number of lines per page"
|
||||||
|
depends on CONSOLE_PAGER
|
||||||
|
default 25
|
||||||
|
help
|
||||||
|
Sets the default number of lines that the pager assumes is visible on
|
||||||
|
the display. This is used as a default if the "pager" environment
|
||||||
|
variable is unset.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
menu "Logging"
|
menu "Logging"
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ obj-$(CONFIG_MII) += miiphyutil.o
|
|||||||
obj-$(CONFIG_CMD_MII) += miiphyutil.o
|
obj-$(CONFIG_CMD_MII) += miiphyutil.o
|
||||||
obj-$(CONFIG_PHYLIB) += miiphyutil.o
|
obj-$(CONFIG_PHYLIB) += miiphyutil.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_CONSOLE_PAGER) += pager.o
|
||||||
|
|
||||||
obj-$(CONFIG_USB_HOST) += usb.o usb_hub.o
|
obj-$(CONFIG_USB_HOST) += usb.o usb_hub.o
|
||||||
obj-$(CONFIG_USB_GADGET) += usb.o
|
obj-$(CONFIG_USB_GADGET) += usb.o
|
||||||
obj-$(CONFIG_USB_STORAGE) += usb_storage.o
|
obj-$(CONFIG_USB_STORAGE) += usb_storage.o
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <hang.h>
|
#include <hang.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <pager.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <watchdog.h>
|
#include <watchdog.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
@@ -650,6 +651,9 @@ int cli_readline_into_buffer(const char *const prompt, char *buffer,
|
|||||||
uint len = CONFIG_SYS_CBSIZE;
|
uint len = CONFIG_SYS_CBSIZE;
|
||||||
int rc;
|
int rc;
|
||||||
static int initted;
|
static int initted;
|
||||||
|
bool old_bypass;
|
||||||
|
|
||||||
|
old_bypass = pager_set_bypass(gd_pager(), true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Say N to CMD_HISTORY_USE_CALLOC will skip runtime
|
* Say N to CMD_HISTORY_USE_CALLOC will skip runtime
|
||||||
@@ -673,9 +677,14 @@ int cli_readline_into_buffer(const char *const prompt, char *buffer,
|
|||||||
puts(prompt);
|
puts(prompt);
|
||||||
|
|
||||||
rc = cread_line(prompt, p, &len, timeout);
|
rc = cread_line(prompt, p, &len, timeout);
|
||||||
return rc < 0 ? rc : len;
|
rc = rc < 0 ? rc : len;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return cread_line_simple(prompt, p);
|
rc = cread_line_simple(prompt, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pager_set_bypass(gd_pager(), old_bypass);
|
||||||
|
pager_reset(gd_pager());
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
101
common/console.c
101
common/console.c
@@ -16,6 +16,7 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <mapmem.h>
|
#include <mapmem.h>
|
||||||
#include <os.h>
|
#include <os.h>
|
||||||
|
#include <pager.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
#include <stdio_dev.h>
|
#include <stdio_dev.h>
|
||||||
#include <exports.h>
|
#include <exports.h>
|
||||||
@@ -321,14 +322,22 @@ static int console_tstc(int file)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void console_putc(int file, const char c)
|
static void console_puts_pager(int file, const char *s);
|
||||||
{
|
|
||||||
int i;
|
|
||||||
struct stdio_dev *dev;
|
|
||||||
|
|
||||||
for_each_console_dev(i, file, dev) {
|
static void console_putc_pager(int file, const char c)
|
||||||
if (dev->putc != NULL)
|
{
|
||||||
dev->putc(dev, c);
|
if (IS_ENABLED(CONFIG_CONSOLE_PAGER) && gd_pager()) {
|
||||||
|
char str[2] = {c, '\0'};
|
||||||
|
|
||||||
|
console_puts_pager(file, str);
|
||||||
|
} else {
|
||||||
|
int i;
|
||||||
|
struct stdio_dev *dev;
|
||||||
|
|
||||||
|
for_each_console_dev(i, file, dev) {
|
||||||
|
if (dev->putc != NULL)
|
||||||
|
dev->putc(dev, c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,17 +386,32 @@ int console_printf_select_stderr(bool serial_only, const char *fmt, ...)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void console_puts(int file, const char *s)
|
static void console_puts(int file, bool use_pager, const char *s)
|
||||||
{
|
{
|
||||||
int i;
|
int key = 0;
|
||||||
struct stdio_dev *dev;
|
|
||||||
|
|
||||||
for_each_console_dev(i, file, dev) {
|
for (s = pager_post(gd_pager(), use_pager, s); s;
|
||||||
if (dev->puts != NULL)
|
s = pager_next(gd_pager(), use_pager, key)) {
|
||||||
dev->puts(dev, s);
|
struct stdio_dev *dev;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
key = 0;
|
||||||
|
if (s == PAGER_WAITING) {
|
||||||
|
key = getchar();
|
||||||
|
} else if (*s) {
|
||||||
|
for_each_console_dev(i, file, dev) {
|
||||||
|
if (dev->puts != NULL)
|
||||||
|
dev->puts(dev, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void console_puts_pager(int file, const char *s)
|
||||||
|
{
|
||||||
|
console_puts(file, true, s);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
|
#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
|
||||||
static void console_flush(int file)
|
static void console_flush(int file)
|
||||||
{
|
{
|
||||||
@@ -407,7 +431,8 @@ static inline void console_doenv(int file, struct stdio_dev *dev)
|
|||||||
iomux_doenv(file, dev->name);
|
iomux_doenv(file, dev->name);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#else
|
|
||||||
|
#else /* !CONSOLE_MUX */
|
||||||
|
|
||||||
static void console_devices_set(int file, struct stdio_dev *dev)
|
static void console_devices_set(int file, struct stdio_dev *dev)
|
||||||
{
|
{
|
||||||
@@ -433,7 +458,7 @@ static inline int console_tstc(int file)
|
|||||||
return stdio_devices[file]->tstc(stdio_devices[file]);
|
return stdio_devices[file]->tstc(stdio_devices[file]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void console_putc(int file, const char c)
|
static inline void console_putc_pager(int file, const char c)
|
||||||
{
|
{
|
||||||
stdio_devices[file]->putc(stdio_devices[file], c);
|
stdio_devices[file]->putc(stdio_devices[file], c);
|
||||||
}
|
}
|
||||||
@@ -445,7 +470,7 @@ void console_puts_select(int file, bool serial_only, const char *s)
|
|||||||
stdio_devices[file]->puts(stdio_devices[file], s);
|
stdio_devices[file]->puts(stdio_devices[file], s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void console_puts(int file, const char *s)
|
static inline void console_puts_pager(int file, const char *s)
|
||||||
{
|
{
|
||||||
stdio_devices[file]->puts(stdio_devices[file], s);
|
stdio_devices[file]->puts(stdio_devices[file], s);
|
||||||
}
|
}
|
||||||
@@ -562,13 +587,13 @@ int ftstc(int file)
|
|||||||
void fputc(int file, const char c)
|
void fputc(int file, const char c)
|
||||||
{
|
{
|
||||||
if ((unsigned int)file < MAX_FILES)
|
if ((unsigned int)file < MAX_FILES)
|
||||||
console_putc(file, c);
|
console_putc_pager(file, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fputs(int file, const char *s)
|
void fputs(int file, const char *s)
|
||||||
{
|
{
|
||||||
if ((unsigned int)file < MAX_FILES)
|
if ((unsigned int)file < MAX_FILES)
|
||||||
console_puts(file, s);
|
console_puts_pager(file, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
|
#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
|
||||||
@@ -740,8 +765,8 @@ void putc(const char c)
|
|||||||
return pre_console_putc(c);
|
return pre_console_putc(c);
|
||||||
|
|
||||||
if (gd->flags & GD_FLG_DEVINIT) {
|
if (gd->flags & GD_FLG_DEVINIT) {
|
||||||
/* Send to the standard output */
|
/* Send to the standard output through pager system */
|
||||||
fputc(stdout, c);
|
console_putc_pager(stdout, c);
|
||||||
} else {
|
} else {
|
||||||
/* Send directly to the handler */
|
/* Send directly to the handler */
|
||||||
pre_console_putc(c);
|
pre_console_putc(c);
|
||||||
@@ -780,8 +805,8 @@ void puts(const char *s)
|
|||||||
return pre_console_puts(s);
|
return pre_console_puts(s);
|
||||||
|
|
||||||
if (gd->flags & GD_FLG_DEVINIT) {
|
if (gd->flags & GD_FLG_DEVINIT) {
|
||||||
/* Send to the standard output */
|
/* Send to the standard output through pager system */
|
||||||
fputs(stdout, s);
|
console_puts_pager(stdout, s);
|
||||||
} else {
|
} else {
|
||||||
/* Send directly to the handler */
|
/* Send directly to the handler */
|
||||||
pre_console_puts(s);
|
pre_console_puts(s);
|
||||||
@@ -1101,6 +1126,36 @@ static void stdio_print_current_devices(void)
|
|||||||
printf("%s\n", stderrname);
|
printf("%s\n", stderrname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setup_pager(void)
|
||||||
|
{
|
||||||
|
/* Init pager now that console is ready */
|
||||||
|
if (IS_ENABLED(CONFIG_CONSOLE_PAGER)) {
|
||||||
|
int lines = IF_ENABLED_INT(CONFIG_CONSOLE_PAGER,
|
||||||
|
CONFIG_CONSOLE_PAGER_LINES);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* get number of lines from the video console, if available */
|
||||||
|
if (IS_ENABLED(CONFIG_VIDEO)) {
|
||||||
|
struct udevice *dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = uclass_first_device_err(UCLASS_VIDEO_CONSOLE,
|
||||||
|
&dev);
|
||||||
|
if (!ret) {
|
||||||
|
struct vidconsole_priv *priv;
|
||||||
|
|
||||||
|
priv = dev_get_uclass_priv(dev);
|
||||||
|
lines = priv->rows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pager_init(gd_pagerp(), env_get_hex("pager", lines),
|
||||||
|
PAGER_BUF_SIZE);
|
||||||
|
if (ret)
|
||||||
|
printf("Failed to init pager\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
|
#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
|
||||||
/* Called after the relocation - use desired console functions */
|
/* Called after the relocation - use desired console functions */
|
||||||
int console_init_r(void)
|
int console_init_r(void)
|
||||||
@@ -1185,6 +1240,7 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
|
gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
|
||||||
|
setup_pager();
|
||||||
|
|
||||||
print_pre_console_buffer(flushpoint);
|
print_pre_console_buffer(flushpoint);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1252,6 +1308,7 @@ int console_init_r(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
|
gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
|
||||||
|
setup_pager();
|
||||||
|
|
||||||
print_pre_console_buffer(flushpoint);
|
print_pre_console_buffer(flushpoint);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
208
common/pager.c
Normal file
208
common/pager.c
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Deals with splitting up text output into separate screenfuls
|
||||||
|
*
|
||||||
|
* Copyright 2025 Simon Glass <sjg@chromium.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_CATEGORY LOGC_CONSOLE
|
||||||
|
|
||||||
|
#include <env.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <pager.h>
|
||||||
|
#include <asm/global_data.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
const char *pager_post(struct pager *pag, bool use_pager, const char *s)
|
||||||
|
{
|
||||||
|
struct membuf old;
|
||||||
|
int ret, len;
|
||||||
|
|
||||||
|
if (!pag || !use_pager || pag->state == PAGERST_TEST_BYPASS)
|
||||||
|
return s;
|
||||||
|
|
||||||
|
len = strlen(s);
|
||||||
|
if (!len)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
old = pag->mb;
|
||||||
|
ret = membuf_put(&pag->mb, s, len);
|
||||||
|
if (ret == len) {
|
||||||
|
/* all is well */
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* We couldn't store any of the text, so we'll store none of
|
||||||
|
* it. The pager is now in an non-functional state until it
|
||||||
|
* can eject the overflow text.
|
||||||
|
*
|
||||||
|
* The buffer is presumably empty, since callers are not allowed
|
||||||
|
* to call pager_post() unless all the output from the previous
|
||||||
|
* call was provided via pager_next().
|
||||||
|
*/
|
||||||
|
pag->overflow = s;
|
||||||
|
pag->mb = old;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pager_next(pag, true, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *pager_next(struct pager *pag, bool use_pager, int key)
|
||||||
|
{
|
||||||
|
char *str, *p, *end;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!use_pager)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* replace the real character we overwrite with nul, if needed */
|
||||||
|
if (pag->nulch) {
|
||||||
|
*pag->nulch = pag->oldch;
|
||||||
|
pag->nulch = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we're at the limit, wait */
|
||||||
|
switch (pag->state) {
|
||||||
|
case PAGERST_OK:
|
||||||
|
break;
|
||||||
|
case PAGERST_AT_LIMIT:
|
||||||
|
pag->state = PAGERST_WAIT_USER;
|
||||||
|
return "\n: Press SPACE to continue";
|
||||||
|
case PAGERST_WAIT_USER:
|
||||||
|
if (key != ' ')
|
||||||
|
return PAGER_WAITING;
|
||||||
|
pag->state = PAGERST_CLEAR_PROMPT;
|
||||||
|
return "\r \r";
|
||||||
|
case PAGERST_CLEAR_PROMPT:
|
||||||
|
pag->state = PAGERST_OK;
|
||||||
|
break;
|
||||||
|
case PAGERST_TEST_BYPASS:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = membuf_getraw(&pag->mb, pag->buf.size - 1, false, &str);
|
||||||
|
if (!ret) {
|
||||||
|
if (pag->overflow) {
|
||||||
|
const char *oflow = pag->overflow;
|
||||||
|
|
||||||
|
pag->overflow = NULL;
|
||||||
|
return oflow;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return lines until we reach the limit */
|
||||||
|
for (p = str, end = str + ret; p < end; p++) {
|
||||||
|
if (*p == '\n' && ++pag->line_count == pag->page_len - 1) {
|
||||||
|
/* remember to display the pager message next time */
|
||||||
|
pag->state = PAGERST_AT_LIMIT;
|
||||||
|
pag->line_count = 0;
|
||||||
|
|
||||||
|
/* skip the newline, since our prompt has one */
|
||||||
|
p++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove the used bytes from the membuf */
|
||||||
|
ret = membuf_getraw(&pag->mb, p - str, true, &str);
|
||||||
|
|
||||||
|
/* don't output the newline, since our prompt has one */
|
||||||
|
if (pag->state == PAGERST_AT_LIMIT)
|
||||||
|
p--;
|
||||||
|
|
||||||
|
/* terminate the string */
|
||||||
|
pag->nulch = p;
|
||||||
|
pag->oldch = *pag->nulch;
|
||||||
|
*pag->nulch = '\0';
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pager_uninit(struct pager *pag)
|
||||||
|
{
|
||||||
|
abuf_uninit(&pag->buf);
|
||||||
|
free(pag);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pager_set_bypass(struct pager *pag, bool bypass)
|
||||||
|
{
|
||||||
|
bool was_bypassed = false;
|
||||||
|
|
||||||
|
if (!pag)
|
||||||
|
return false;
|
||||||
|
was_bypassed = pag->state == PAGERST_TEST_BYPASS;
|
||||||
|
|
||||||
|
if (bypass)
|
||||||
|
pag->state = PAGERST_TEST_BYPASS;
|
||||||
|
else
|
||||||
|
pag->state = PAGERST_OK;
|
||||||
|
|
||||||
|
return was_bypassed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pager_set_page_len(struct pager *pag, int page_len)
|
||||||
|
{
|
||||||
|
if (page_len < 2)
|
||||||
|
return;
|
||||||
|
pag->page_len = page_len;
|
||||||
|
pag->line_count = 0;
|
||||||
|
if (!page_len)
|
||||||
|
pag->state = PAGERST_TEST_BYPASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pager_reset(struct pager *pag)
|
||||||
|
{
|
||||||
|
pag->line_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int on_pager(const char *name, const char *value, enum env_op op,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
struct pager *pag = gd_pager();
|
||||||
|
int new_page_len;
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_CONSOLE_PAGER) || !pag)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case env_op_create:
|
||||||
|
case env_op_overwrite:
|
||||||
|
if (value) {
|
||||||
|
new_page_len = simple_strtoul(value, NULL, 16);
|
||||||
|
pager_set_page_len(pag, new_page_len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case env_op_delete:
|
||||||
|
/* Reset to default when deleted */
|
||||||
|
pager_set_page_len(pag, CONFIG_CONSOLE_PAGER_LINES);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
U_BOOT_ENV_CALLBACK(pager, on_pager);
|
||||||
|
|
||||||
|
int pager_init(struct pager **pagp, int page_len, int buf_size)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
|
||||||
|
pag = malloc(sizeof(struct pager));
|
||||||
|
if (!pag)
|
||||||
|
return log_msg_ret("pag", -ENOMEM);
|
||||||
|
memset(pag, '\0', sizeof(struct pager));
|
||||||
|
pag->page_len = page_len;
|
||||||
|
if (!abuf_init_size(&pag->buf, buf_size))
|
||||||
|
return log_msg_ret("pah", -ENOMEM);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nul-terminate the buffer, which will come in handy if we need to
|
||||||
|
* return up to the last byte
|
||||||
|
*/
|
||||||
|
((char *)pag->buf.data)[buf_size - 1] = '\0';
|
||||||
|
membuf_init(&pag->mb, pag->buf.data, buf_size);
|
||||||
|
*pagp = pag;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
SPDX-License-Identifier: GPL-2.0+
|
|
||||||
/*
|
|
||||||
* (C) Copyright 2000
|
|
||||||
* Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
|
|
||||||
*/
|
|
||||||
|
|
||||||
U-Boot console handling
|
|
||||||
========================
|
|
||||||
|
|
||||||
HOW THE CONSOLE WORKS?
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
At system startup U-Boot initializes a serial console. When U-Boot
|
|
||||||
relocates itself to RAM, all console drivers are initialized (they
|
|
||||||
will register all detected console devices to the system for further
|
|
||||||
use).
|
|
||||||
|
|
||||||
If not defined in the environment, the first input device is assigned
|
|
||||||
to the 'stdin' file, the first output one to 'stdout' and 'stderr'.
|
|
||||||
|
|
||||||
You can use the command "coninfo" to see all registered console
|
|
||||||
devices and their flags. You can assign a standard file (stdin,
|
|
||||||
stdout or stderr) to any device you see in that list simply by
|
|
||||||
assigning its name to the corresponding environment variable. For
|
|
||||||
example:
|
|
||||||
|
|
||||||
setenv stdin serial <- To use the serial input
|
|
||||||
setenv stdout video <- To use the video console
|
|
||||||
|
|
||||||
Do a simple "saveenv" to save the console settings in the environment
|
|
||||||
and get them working on the next startup, too.
|
|
||||||
|
|
||||||
HOW CAN I USE STANDARD FILE INTO THE SOURCES?
|
|
||||||
---------------------------------------------
|
|
||||||
|
|
||||||
You can use the following functions to access the console:
|
|
||||||
|
|
||||||
* STDOUT:
|
|
||||||
putc (to put a char to stdout)
|
|
||||||
puts (to put a string to stdout)
|
|
||||||
printf (to format and put a string to stdout)
|
|
||||||
|
|
||||||
* STDIN:
|
|
||||||
tstc (to test for the presence of a char in stdin)
|
|
||||||
getc (to get a char from stdin)
|
|
||||||
|
|
||||||
* STDERR:
|
|
||||||
eputc (to put a char to stderr)
|
|
||||||
eputs (to put a string to stderr)
|
|
||||||
eprintf (to format and put a string to stderr)
|
|
||||||
|
|
||||||
* FILE (can be 'stdin', 'stdout', 'stderr'):
|
|
||||||
fputc (like putc but redirected to a file)
|
|
||||||
fputs (like puts but redirected to a file)
|
|
||||||
fprintf (like printf but redirected to a file)
|
|
||||||
ftstc (like tstc but redirected to a file)
|
|
||||||
fgetc (like getc but redirected to a file)
|
|
||||||
|
|
||||||
Remember that all FILE-related functions CANNOT be used before
|
|
||||||
U-Boot relocation (done in 'board_init_r' in arch/*/lib/board.c).
|
|
||||||
|
|
||||||
HOW CAN I USE STANDARD FILE INTO APPLICATIONS?
|
|
||||||
----------------------------------------------
|
|
||||||
|
|
||||||
Use the 'bd_mon_fnc' field of the bd_info structure passed to the
|
|
||||||
application to do everything you want with the console.
|
|
||||||
|
|
||||||
But REMEMBER that that will work only if you have not overwritten any
|
|
||||||
U-Boot code while loading (or uncompressing) the image of your
|
|
||||||
application.
|
|
||||||
|
|
||||||
For example, you won't get the console stuff running in the Linux
|
|
||||||
kernel because the kernel overwrites U-Boot before running. Only
|
|
||||||
some parameters like the framebuffer descriptors are passed to the
|
|
||||||
kernel in the high memory area to let the applications (the kernel)
|
|
||||||
use the framebuffers initialized by U-Boot.
|
|
||||||
|
|
||||||
SUPPORTED DRIVERS
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Working drivers:
|
|
||||||
|
|
||||||
serial (architecture dependent serial stuff)
|
|
||||||
video (mpc8xx video controller)
|
|
||||||
|
|
||||||
Work in progress:
|
|
||||||
|
|
||||||
wl_kbd (Wireless 4PPM keyboard)
|
|
||||||
|
|
||||||
Waiting for volounteers:
|
|
||||||
|
|
||||||
lcd (mpc8xx lcd controller; to )
|
|
||||||
|
|
||||||
TESTED CONFIGURATIONS
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
The driver has been tested with the following configurations (see
|
|
||||||
CREDITS for other contact informations):
|
|
||||||
|
|
||||||
- MPC823FADS with AD7176 on a PAL TV (YCbYCr) - arsenio@tin.it
|
|
||||||
78
doc/usage/console.rst
Normal file
78
doc/usage/console.rst
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
.. SPDX-License-Identifier: GPL-2.0+
|
||||||
|
.. sectionauthor:: Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
|
||||||
|
.. (C) Copyright 2000
|
||||||
|
|
||||||
|
=======================
|
||||||
|
U-Boot console handling
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
At system-startup U-Boot initializes a serial console. When U-Boot
|
||||||
|
relocates itself to RAM, all console drivers are initialized (they
|
||||||
|
will register all detected console devices to the system for further
|
||||||
|
use).
|
||||||
|
|
||||||
|
If not defined in the environment, the first input device is assigned
|
||||||
|
to the 'stdin' file, the first output one to 'stdout' and 'stderr'.
|
||||||
|
|
||||||
|
You can use the command `coninfo` to see all registered console
|
||||||
|
devices and their flags. You can assign a standard file (stdin,
|
||||||
|
stdout or stderr) to any device you see in that list simply by
|
||||||
|
assigning its name to the corresponding environment variable. For
|
||||||
|
example::
|
||||||
|
|
||||||
|
# Use the serial input
|
||||||
|
setenv stdin serial
|
||||||
|
|
||||||
|
# Use the video console
|
||||||
|
setenv stdout vidconsole
|
||||||
|
|
||||||
|
Do a simple `saveenv` to save the console settings in the environment
|
||||||
|
and get them working on the next startup, too.
|
||||||
|
|
||||||
|
How to output text to the console
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
You can use the following functions to access the console:
|
||||||
|
|
||||||
|
stdout
|
||||||
|
- putc() - write a char to stdout
|
||||||
|
- puts() - write a string to stdout
|
||||||
|
- printf() - format and write a string to stdout
|
||||||
|
|
||||||
|
stdin
|
||||||
|
- tstc() - test for the presence of a char in stdin
|
||||||
|
- getchar() - get a char from stdin
|
||||||
|
|
||||||
|
stderr
|
||||||
|
- eputc() - write a char to stderr
|
||||||
|
- eputs() - write a string to stderr
|
||||||
|
- eprintf() - format and write a string to stderr
|
||||||
|
|
||||||
|
file ('stdin', 'stdout' or 'stderr')
|
||||||
|
- fputc() - write a char to a file
|
||||||
|
- fputs() - write a string to a file
|
||||||
|
- fprintf() - format and write a string to a file
|
||||||
|
- ftstc() - test for the presence of a char in file
|
||||||
|
- fgetc() - get a char from a file
|
||||||
|
|
||||||
|
Remember that FILE-related functions CANNOT be used before U-Boot relocation,
|
||||||
|
which is done in `board_init_r()`.
|
||||||
|
|
||||||
|
Pager
|
||||||
|
-----
|
||||||
|
|
||||||
|
U-Boot has a simple pager feature, enabled with `CONFIG_CONSOLE_PAGER`. It is
|
||||||
|
only available if both `CONFIG_CONSOLE_MUX` is enabled.
|
||||||
|
|
||||||
|
When activated, the pager pauses at the end of each 'page' (screenful) of
|
||||||
|
output, shows a prompt and lets the user read the output. To continue, press
|
||||||
|
SPACE.
|
||||||
|
|
||||||
|
The number of lines before the pager kicks in is configurable using the `pager`
|
||||||
|
environment variable, which should contain a decimal value. Set it to 0 (or
|
||||||
|
leave it unset) to disable the pager. If the variable is not present then the
|
||||||
|
number of lines in the video console is used. If there is no video console, then
|
||||||
|
`CONSOLE_PAGER_LINES` sets the number of lines.
|
||||||
@@ -335,6 +335,10 @@ netretry
|
|||||||
Useful on scripts which control the retry operation
|
Useful on scripts which control the retry operation
|
||||||
themselves.
|
themselves.
|
||||||
|
|
||||||
|
pager
|
||||||
|
Decimal number of visible lines on the display, or serial console.
|
||||||
|
:doc:`/usage/console`.
|
||||||
|
|
||||||
rng_seed_size
|
rng_seed_size
|
||||||
Size of random value added to device-tree node /chosen/rng-seed.
|
Size of random value added to device-tree node /chosen/rng-seed.
|
||||||
This variable is given as a decimal number.
|
This variable is given as a decimal number.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Use U-Boot
|
|||||||
|
|
||||||
spl_boot
|
spl_boot
|
||||||
blkmap
|
blkmap
|
||||||
|
console
|
||||||
dfu
|
dfu
|
||||||
environment
|
environment
|
||||||
fdt_overlays
|
fdt_overlays
|
||||||
|
|||||||
@@ -477,6 +477,9 @@ struct global_data {
|
|||||||
*/
|
*/
|
||||||
struct upl *upl;
|
struct upl *upl;
|
||||||
#endif
|
#endif
|
||||||
|
#if CONFIG_IS_ENABLED(CONSOLE_PAGER)
|
||||||
|
struct pager *pager;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#ifndef DO_DEPS_ONLY
|
#ifndef DO_DEPS_ONLY
|
||||||
static_assert(sizeof(struct global_data) == GD_SIZE);
|
static_assert(sizeof(struct global_data) == GD_SIZE);
|
||||||
@@ -618,6 +621,14 @@ static_assert(sizeof(struct global_data) == GD_SIZE);
|
|||||||
#define gd_passage_dtb() 0
|
#define gd_passage_dtb() 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(CONSOLE_PAGER)
|
||||||
|
#define gd_pager() gd->pager
|
||||||
|
#define gd_pagerp() &gd->pager
|
||||||
|
#else
|
||||||
|
#define gd_pager() NULL
|
||||||
|
#define gd_pagerp() NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum gd_flags - global data flags
|
* enum gd_flags - global data flags
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -75,6 +75,12 @@
|
|||||||
#define DFU_CALLBACK
|
#define DFU_CALLBACK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_CONSOLE_PAGER
|
||||||
|
#define PAGER_CALLBACK "pager:pager,"
|
||||||
|
#else
|
||||||
|
#define PAGER_CALLBACK
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This list of callback bindings is static, but may be overridden by defining
|
* This list of callback bindings is static, but may be overridden by defining
|
||||||
* a new association in the ".callbacks" environment variable.
|
* a new association in the ".callbacks" environment variable.
|
||||||
@@ -88,6 +94,7 @@
|
|||||||
DFU_CALLBACK \
|
DFU_CALLBACK \
|
||||||
"loadaddr:loadaddr," \
|
"loadaddr:loadaddr," \
|
||||||
SILENT_CALLBACK \
|
SILENT_CALLBACK \
|
||||||
|
PAGER_CALLBACK \
|
||||||
"stdin:console,stdout:console,stderr:console," \
|
"stdin:console,stdout:console,stderr:console," \
|
||||||
"serial#:serialno," \
|
"serial#:serialno," \
|
||||||
CFG_ENV_CALLBACK_LIST_STATIC
|
CFG_ENV_CALLBACK_LIST_STATIC
|
||||||
|
|||||||
178
include/pager.h
Normal file
178
include/pager.h
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* Deals with splitting up text output into separate screenfuls
|
||||||
|
*
|
||||||
|
* Copyright 2025 Simon Glass <sjg@chromium.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PAGER_H
|
||||||
|
#define __PAGER_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <abuf.h>
|
||||||
|
#include <membuf.h>
|
||||||
|
#include <linux/sizes.h>
|
||||||
|
|
||||||
|
#define PAGER_BUF_SIZE SZ_4K
|
||||||
|
|
||||||
|
/* Special return value from pager_next() indicating it's waiting for user input */
|
||||||
|
#define PAGER_WAITING ((const char *)1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum pager_state: Tracks the state of the pager
|
||||||
|
*
|
||||||
|
* @PAGERST_OK: Normal output is happening
|
||||||
|
* @PAGERST_AT_LIMIT: No more output can be provided; the next call to
|
||||||
|
* pager_next() will return a user prompt
|
||||||
|
* @PAGERST_WAIT_USER: Waiting for the user to press a key
|
||||||
|
* @PAGERST_CLEAR_PROMPT: Clearing the prompt ready for more output
|
||||||
|
* @PAGERST_TEST_BYPASS: Pager is being bypassed since tests are running
|
||||||
|
*/
|
||||||
|
enum pager_state {
|
||||||
|
PAGERST_OK,
|
||||||
|
PAGERST_AT_LIMIT,
|
||||||
|
PAGERST_WAIT_USER,
|
||||||
|
PAGERST_CLEAR_PROMPT,
|
||||||
|
PAGERST_TEST_BYPASS,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct pager - pager state
|
||||||
|
*
|
||||||
|
* The pager uses a buffer @buf to hold text that it is in the process of
|
||||||
|
* sending out. This helps deal with the stdio puts() interface, which does not
|
||||||
|
* permit passing a string length, only a string, which means that strings must
|
||||||
|
* be nul-terminated. The termination is handled automatically by the pager.
|
||||||
|
*
|
||||||
|
* If the text passed to pager_post() is too large for @buf then all the next
|
||||||
|
* will be written at once, without any paging, in the next call to
|
||||||
|
* pager_next().
|
||||||
|
*
|
||||||
|
* The membuf @mb is only used to feed out text in chunks, with a pager message
|
||||||
|
* (and a keypress wait) inserted between each chunk.
|
||||||
|
*
|
||||||
|
* @line_count: Number of lines output since last pause
|
||||||
|
* @page_len: Sets the height of the page in lines. The maximum lines to display
|
||||||
|
* before pausing is one less than this. Set from 'pager' env variable
|
||||||
|
* @buf: Buffer containing text to eventually be returned
|
||||||
|
* @mb: Circular buffer to manage @buf
|
||||||
|
* @overflow: pointer to overflow text to send nexts
|
||||||
|
* @nulch: pointer to where a nul character was written, NULL if none
|
||||||
|
* @oldch: old character that was at @nulch
|
||||||
|
*/
|
||||||
|
struct pager {
|
||||||
|
int line_count;
|
||||||
|
int page_len;
|
||||||
|
struct abuf buf;
|
||||||
|
struct membuf mb;
|
||||||
|
const char *overflow;
|
||||||
|
char *nulch;
|
||||||
|
int oldch;
|
||||||
|
enum pager_state state;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(CONSOLE_PAGER)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pager_post() - Add text to the input buffer for later handling
|
||||||
|
*
|
||||||
|
* If @use_pager the text is added to the pager buffer and fed out a screenful
|
||||||
|
* at a time. This function calls pager_post() after storing the text.
|
||||||
|
*
|
||||||
|
* After calling pager_post(), if it returns anything other than NULL, you must
|
||||||
|
* repeatedly call pager_next() until it returns NULL, otherwise text may be
|
||||||
|
* lost
|
||||||
|
*
|
||||||
|
* If @pag is NULL, this does nothing but return @s
|
||||||
|
*
|
||||||
|
* @pag: Pager to use, may be NULL
|
||||||
|
* @use_pager: Whether or not to use the pager functionality
|
||||||
|
* @s: Text to add
|
||||||
|
* Return: text which should be sent to output, or NULL if there is no more.
|
||||||
|
* If !@use_pager this just returns @s and does not affect the pager state
|
||||||
|
*/
|
||||||
|
const char *pager_post(struct pager *pag, bool use_pager, const char *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pager_next() - Returns the next screenful of text to show
|
||||||
|
*
|
||||||
|
* If this function returns PAGER_WAITING then the caller must check for user
|
||||||
|
* input and pass in the keypress in the next call to pager_next(). It can
|
||||||
|
* busy-wait for a keypress, if desired, since pager_next() will only ever
|
||||||
|
* return PAGER_WAITING until @ch is non-zero.
|
||||||
|
*
|
||||||
|
* @pag: Pager to use
|
||||||
|
* @use_pager: Whether or not to use the pager functionality
|
||||||
|
* @ch: Key that the user has pressed, or 0 if none
|
||||||
|
*
|
||||||
|
* Return: text which should be sent to output, or PAGER_WAITING if waiting for
|
||||||
|
* the user to press a key, or NULL if there is no more text.
|
||||||
|
* If !@use_pager this just returns NULL and does not affect the pager state
|
||||||
|
*/
|
||||||
|
const char *pager_next(struct pager *pag, bool use_pager, int ch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pager_set_bypass() - put the pager into bypass mode
|
||||||
|
*
|
||||||
|
* This is used for tests. Bypass mode stops the pager from doing anything to
|
||||||
|
* interrupt output
|
||||||
|
*
|
||||||
|
* @pag: Pager to use, may be NULL in which case this function does nothing
|
||||||
|
* @bypass: true to put the pager in bypass mode, false to return to normal mode
|
||||||
|
* Return: old value of the bypass flag
|
||||||
|
*/
|
||||||
|
bool pager_set_bypass(struct pager *pag, bool bypass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pager_reset() - reset the line count in the pager
|
||||||
|
*
|
||||||
|
* Sets line_count to zero so that the pager starts afresh with its counting.
|
||||||
|
*
|
||||||
|
* @pag: Pager to update
|
||||||
|
*/
|
||||||
|
void pager_reset(struct pager *pag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pager_uninit() - Uninit the pager
|
||||||
|
*
|
||||||
|
* Frees all memory and also @pag
|
||||||
|
*
|
||||||
|
* @pag: Pager to uninit
|
||||||
|
*/
|
||||||
|
void pager_uninit(struct pager *pag);
|
||||||
|
|
||||||
|
#else
|
||||||
|
static inline const char *pager_post(struct pager *pag, bool use_pager,
|
||||||
|
const char *s)
|
||||||
|
{
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *pager_next(struct pager *pag, bool use_pager, int ch)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool pager_set_bypass(struct pager *pag, bool bypass)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pager_reset(struct pager *pag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pager_init() - Set up a new pager
|
||||||
|
*
|
||||||
|
* @pagp: Returns allocaed pager, on success
|
||||||
|
* @pagelen: Number of lines per page
|
||||||
|
* @buf_size: Buffer size to use in bytes, this is the maximum amount of output
|
||||||
|
* that can be paged
|
||||||
|
* Return: 0 if OK, -ENOMEM if out of memory
|
||||||
|
*/
|
||||||
|
int pager_init(struct pager **pagp, int page_len, int buf_size);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -22,6 +22,7 @@ config EFI_APP
|
|||||||
depends on X86 || ARM
|
depends on X86 || ARM
|
||||||
select CHARSET
|
select CHARSET
|
||||||
select EVENT
|
select EVENT
|
||||||
|
imply CONSOLE_PAGER
|
||||||
help
|
help
|
||||||
Build U-Boot as an application which can be started from EFI. This
|
Build U-Boot as an application which can be started from EFI. This
|
||||||
is useful for examining a platform in the early stages of porting
|
is useful for examining a platform in the early stages of porting
|
||||||
|
|||||||
@@ -10,4 +10,5 @@ endif
|
|||||||
obj-$(CONFIG_CYCLIC) += cyclic.o
|
obj-$(CONFIG_CYCLIC) += cyclic.o
|
||||||
obj-$(CONFIG_EVENT_DYNAMIC) += event.o
|
obj-$(CONFIG_EVENT_DYNAMIC) += event.o
|
||||||
obj-y += cread.o
|
obj-y += cread.o
|
||||||
|
obj-$(CONFIG_CONSOLE_PAGER) += pager.o
|
||||||
obj-$(CONFIG_$(PHASE_)CMDLINE) += print.o
|
obj-$(CONFIG_$(PHASE_)CMDLINE) += print.o
|
||||||
|
|||||||
576
test/common/pager.c
Normal file
576
test/common/pager.c
Normal file
@@ -0,0 +1,576 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Simon Glass <sjg@chromium.org>
|
||||||
|
*
|
||||||
|
* Test for pager functionality
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <pager.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <test/common.h>
|
||||||
|
#include <test/test.h>
|
||||||
|
#include <test/ut.h>
|
||||||
|
#include <asm/global_data.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
/* Test basic pager init and cleanup */
|
||||||
|
static int pager_test_basic_init(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
|
||||||
|
/* Test successful init */
|
||||||
|
ut_assertok(pager_init(&pag, 20, 1024));
|
||||||
|
ut_assertnonnull(pag);
|
||||||
|
ut_asserteq(20, pag->page_len);
|
||||||
|
ut_asserteq(0, pag->line_count);
|
||||||
|
ut_assertnull(pag->overflow);
|
||||||
|
ut_assertnull(pag->nulch);
|
||||||
|
|
||||||
|
/* Clean up */
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
/* Test init with different parameters */
|
||||||
|
ut_assertok(pager_init(&pag, 10, 2048));
|
||||||
|
ut_assertnonnull(pag);
|
||||||
|
ut_asserteq(10, pag->page_len);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_basic_init, 0);
|
||||||
|
|
||||||
|
/* Test pager with simple text */
|
||||||
|
static int pager_test_simple_text(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *text = "Hello, World!";
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
ut_assertok(pager_init(&pag, 20, 1024));
|
||||||
|
|
||||||
|
/* Post some text and get it back */
|
||||||
|
result = pager_post(pag, true, text);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str(text, result);
|
||||||
|
|
||||||
|
/* Should be no more text */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_simple_text, 0);
|
||||||
|
|
||||||
|
/* Test pager with multiple lines */
|
||||||
|
static int pager_test_multiline(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *text1 = "Line 1\n";
|
||||||
|
const char *text2 = "Line 2\n";
|
||||||
|
const char *text3 = "Line 3\n";
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
ut_assertok(pager_init(&pag, 20, 1024));
|
||||||
|
|
||||||
|
/* Post multiple pieces of text */
|
||||||
|
result = pager_post(pag, true, text1);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str(text1, result);
|
||||||
|
|
||||||
|
/* Should be no more text after first post */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
result = pager_post(pag, true, text2);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str(text2, result);
|
||||||
|
|
||||||
|
/* Should be no more text after second post */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
result = pager_post(pag, true, text3);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str(text3, result);
|
||||||
|
|
||||||
|
/* Should be no more text after third post */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_multiline, 0);
|
||||||
|
|
||||||
|
/* Test pager with large text that fills the buffer */
|
||||||
|
static int pager_test_large_text(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
ut_assertok(pager_init(&pag, 20, 16)); /* Small buffer */
|
||||||
|
|
||||||
|
/* Post large text - should fit in buffer */
|
||||||
|
result = pager_post(pag, true, "this is 16 chars");
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("this is 16 chars", result);
|
||||||
|
ut_assertnull(pager_next(pag, true, 0));
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_large_text, 0);
|
||||||
|
|
||||||
|
/* Test pager overflow handling */
|
||||||
|
static int pager_test_overflow(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
ut_assertok(pager_init(&pag, 20, 4)); /* Small buffer */
|
||||||
|
|
||||||
|
/* send some text which is too long for the buffer */
|
||||||
|
result = pager_post(pag, true, "test1");
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
|
||||||
|
/* overflow handling should return the text */
|
||||||
|
ut_asserteq_str("test1", result);
|
||||||
|
ut_assertnull(pager_next(pag, true, 0));
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_overflow, 0);
|
||||||
|
|
||||||
|
/* Test pager with NULL input */
|
||||||
|
static int pager_test_null_input(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
/* Test pager_post with NULL pager */
|
||||||
|
result = pager_post(NULL, true, "test");
|
||||||
|
ut_asserteq_str("test", result);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_null_input, 0);
|
||||||
|
|
||||||
|
/* Test pager with empty strings */
|
||||||
|
static int pager_test_empty_strings(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
ut_assertok(pager_init(&pag, 20, 1024));
|
||||||
|
|
||||||
|
/* Post empty string */
|
||||||
|
result = pager_post(pag, true, "");
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
/* Should be no more text */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_empty_strings, 0);
|
||||||
|
|
||||||
|
/* Test pager buffer management */
|
||||||
|
static int pager_test_buffer_management(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *text = "Test buffer management";
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
ut_assertok(pager_init(&pag, 20, 1024));
|
||||||
|
|
||||||
|
/* Verify buffer is properly inited */
|
||||||
|
ut_assertnonnull(pag->buf.data);
|
||||||
|
ut_asserteq(1024, pag->buf.size);
|
||||||
|
|
||||||
|
/* Post text and verify buffer state */
|
||||||
|
result = pager_post(pag, true, text);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
|
||||||
|
/* Verify the buffer contains our text */
|
||||||
|
ut_asserteq_str(text, result);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_buffer_management, 0);
|
||||||
|
|
||||||
|
/* Test pager with very long single line */
|
||||||
|
static int pager_test_long_single_line(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
char long_line[1000];
|
||||||
|
const char *result;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ut_assertok(pager_init(&pag, 20, 1024));
|
||||||
|
|
||||||
|
/* Create a very long line without newlines */
|
||||||
|
for (i = 0; i < sizeof(long_line) - 1; i++)
|
||||||
|
long_line[i] = 'X';
|
||||||
|
long_line[sizeof(long_line) - 1] = '\0';
|
||||||
|
|
||||||
|
/* Post the long line */
|
||||||
|
result = pager_post(pag, true, long_line);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
|
||||||
|
/* Should get our text back */
|
||||||
|
ut_asserteq_str(long_line, result);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_long_single_line, 0);
|
||||||
|
|
||||||
|
/* Test pager line counting and page breaks */
|
||||||
|
static int pager_test_line_counting(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *multiline_text = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\n";
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
/* Init with page length of 4 lines */
|
||||||
|
ut_assertok(pager_init(&pag, 4, 1024));
|
||||||
|
|
||||||
|
/* Post multiline text */
|
||||||
|
result = pager_post(pag, true, multiline_text);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
|
||||||
|
/* Should get first 3 lines (excluding the 3rd newline) */
|
||||||
|
ut_asserteq_str("Line 1\nLine 2\nLine 3", result);
|
||||||
|
/* line_count is reset to 0 when page limit is reached */
|
||||||
|
ut_asserteq(0, pag->line_count);
|
||||||
|
|
||||||
|
/* Next call should return pager prompt */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("\n: Press SPACE to continue", result);
|
||||||
|
|
||||||
|
/* Press space to continue */
|
||||||
|
result = pager_next(pag, true, ' ');
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("\r \r", result);
|
||||||
|
|
||||||
|
/* Get remaining lines */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("Line 4\nLine 5\n", result);
|
||||||
|
|
||||||
|
/* Should be no more text */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_line_counting, 0);
|
||||||
|
|
||||||
|
/* Test that PAGER_WAITING is returned when pager waits for user input */
|
||||||
|
static int pager_test_pager_waiting(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
/* Create pager with small page size to trigger waiting quickly */
|
||||||
|
ut_assertok(pager_init(&pag, 3, 1024));
|
||||||
|
|
||||||
|
/* Post text that fills exactly the page limit */
|
||||||
|
result = pager_post(pag, true, "Line 1\nLine 2\n");
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("Line 1\nLine 2", result);
|
||||||
|
|
||||||
|
/* Next call should return the prompt */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("\n: Press SPACE to continue", result);
|
||||||
|
|
||||||
|
/* Next call without space key should return PAGER_WAITING */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_asserteq_ptr(PAGER_WAITING, result);
|
||||||
|
|
||||||
|
/* Another call without space should still return PAGER_WAITING */
|
||||||
|
result = pager_next(pag, true, 'x'); /* Wrong key */
|
||||||
|
ut_asserteq_ptr(PAGER_WAITING, result);
|
||||||
|
|
||||||
|
/* Pressing space should clear the prompt */
|
||||||
|
result = pager_next(pag, true, ' ');
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("\r \r", result);
|
||||||
|
|
||||||
|
/* Now should return NULL (no more content) */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_pager_waiting, 0);
|
||||||
|
|
||||||
|
/* Test use_pager parameter - output text directly, while buffer is non-empty */
|
||||||
|
static int pager_test_use_pager_param(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *buffered_text = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\n";
|
||||||
|
const char *direct_text = "This should be written immediately";
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
/* Init with small page length to ensure paging occurs */
|
||||||
|
ut_assertok(pager_init(&pag, 3, 1024));
|
||||||
|
|
||||||
|
/* Post text with use_pager=true - should trigger paging */
|
||||||
|
result = pager_post(pag, true, buffered_text);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
/* Should get first 2 lines */
|
||||||
|
ut_asserteq_str("Line 1\nLine 2", result);
|
||||||
|
|
||||||
|
/* Now call pager_post with use_pager=false while text is still buffered */
|
||||||
|
result = pager_post(pag, false, direct_text);
|
||||||
|
/* Should get the text immediately, not from buffer */
|
||||||
|
ut_asserteq_ptr(direct_text, result);
|
||||||
|
|
||||||
|
/* Call pager_next with use_pager=false - should return NULL */
|
||||||
|
result = pager_next(pag, false, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
/* Now continue with use_pager=true to get buffered text */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
/* Should get the pager prompt */
|
||||||
|
ut_asserteq_str("\n: Press SPACE to continue", result);
|
||||||
|
|
||||||
|
/* Press space to continue */
|
||||||
|
result = pager_next(pag, true, ' ');
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("\r \r", result);
|
||||||
|
|
||||||
|
/* Get remaining buffered lines - should be next 2 lines due to page limit */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("Line 3\nLine 4", result);
|
||||||
|
|
||||||
|
/* Should get pager prompt again */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("\n: Press SPACE to continue", result);
|
||||||
|
|
||||||
|
/* Press space to continue */
|
||||||
|
result = pager_next(pag, true, ' ');
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("\r \r", result);
|
||||||
|
|
||||||
|
/* Get final line */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("Line 5\n", result);
|
||||||
|
|
||||||
|
/* Should be no more text */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_use_pager_param, 0);
|
||||||
|
|
||||||
|
/* Test pager bypass mode */
|
||||||
|
static int pager_test_bypass_mode(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *text = "This text should be returned directly";
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
/* Init with small page length to ensure paging would normally occur */
|
||||||
|
ut_assertok(pager_init(&pag, 2, 1024));
|
||||||
|
|
||||||
|
/* Enable bypass mode */
|
||||||
|
pager_set_bypass(pag, true);
|
||||||
|
|
||||||
|
/* Post text - should get original string back directly */
|
||||||
|
result = pager_post(pag, true, text);
|
||||||
|
ut_asserteq_ptr(text, result); /* Should be same pointer */
|
||||||
|
|
||||||
|
/* pager_next should return NULL in bypass mode */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
/* Disable bypass mode */
|
||||||
|
pager_set_bypass(pag, false);
|
||||||
|
|
||||||
|
/* Now pager should work normally */
|
||||||
|
result = pager_post(pag, true, text);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
/* In normal mode, result should be different from original text */
|
||||||
|
ut_assert(result != text);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_bypass_mode, 0);
|
||||||
|
|
||||||
|
/* Test that single character output via putc goes through pager */
|
||||||
|
static int pager_test_putc(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
/* Init pager */
|
||||||
|
ut_assertok(pager_init(&pag, 20, 1024));
|
||||||
|
pager_set_bypass(pag, true);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test that individual characters can be posted via pager API
|
||||||
|
* This verifies that console_putc_pager() routes through the pager
|
||||||
|
* system
|
||||||
|
*/
|
||||||
|
result = pager_post(pag, true, "A");
|
||||||
|
ut_asserteq_ptr("A", result); /* Bypass mode returns original pointer */
|
||||||
|
|
||||||
|
result = pager_post(pag, true, "\n");
|
||||||
|
ut_asserteq_ptr("\n", result);
|
||||||
|
|
||||||
|
result = pager_post(pag, true, "B");
|
||||||
|
ut_asserteq_ptr("B", result);
|
||||||
|
|
||||||
|
/* Disable bypass to test normal functionality with single chars */
|
||||||
|
pager_set_bypass(pag, false);
|
||||||
|
|
||||||
|
result = pager_post(pag, true, "X");
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("X", result);
|
||||||
|
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_putc, 0);
|
||||||
|
|
||||||
|
/* Test writing up to page limit then adding final newline */
|
||||||
|
static int pager_test_limit_plus_newline(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag;
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
/* Init with page length of 3 lines */
|
||||||
|
ut_assertok(pager_init(&pag, 3, 1024));
|
||||||
|
|
||||||
|
/* Write text that reaches exactly the page limit (2 newlines) */
|
||||||
|
result = pager_post(pag, true, "Line 1\nLine 2");
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("Line 1\nLine 2", result);
|
||||||
|
ut_asserteq(1, pag->line_count); /* Should have 1 line counted */
|
||||||
|
|
||||||
|
/* Should be no more text yet - haven't hit limit */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
/* Now post a single newline - this should trigger the page limit */
|
||||||
|
result = pager_post(pag, true, "\n");
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
/*
|
||||||
|
* Should get empty string since we hit the limit and the newline is
|
||||||
|
* consumed
|
||||||
|
*/
|
||||||
|
ut_asserteq_str("", result);
|
||||||
|
|
||||||
|
/* Next call should return the pager prompt since we hit the limit */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("\n: Press SPACE to continue", result);
|
||||||
|
|
||||||
|
/* Press space to continue */
|
||||||
|
result = pager_next(pag, true, ' ');
|
||||||
|
ut_assertnonnull(result);
|
||||||
|
ut_asserteq_str("\r \r", result);
|
||||||
|
|
||||||
|
/* Should be no more text */
|
||||||
|
result = pager_next(pag, true, 0);
|
||||||
|
ut_assertnull(result);
|
||||||
|
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_limit_plus_newline, 0);
|
||||||
|
|
||||||
|
/* Test console integration - pager prompt appears in console output */
|
||||||
|
static int pager_test_console(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct pager *pag, *orig_pag;
|
||||||
|
char line[100];
|
||||||
|
int avail, ret;
|
||||||
|
|
||||||
|
/* Save original pager */
|
||||||
|
orig_pag = gd_pager();
|
||||||
|
|
||||||
|
/* Create our own pager for testing */
|
||||||
|
ret = pager_init(&pag, 2, 1024);
|
||||||
|
if (ret) {
|
||||||
|
gd->pager = orig_pag;
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up pager to be one away from limit (1 line already counted) */
|
||||||
|
pag->line_count = 1;
|
||||||
|
|
||||||
|
/* Assign our pager to the global data */
|
||||||
|
gd->pager = pag;
|
||||||
|
|
||||||
|
/* Trigger paging with a second newline */
|
||||||
|
putc('\n');
|
||||||
|
|
||||||
|
/* Check if there's any console output available at all */
|
||||||
|
avail = console_record_avail();
|
||||||
|
|
||||||
|
/* Restore original pager first */
|
||||||
|
gd->pager = orig_pag;
|
||||||
|
pager_uninit(pag);
|
||||||
|
|
||||||
|
/* Now check what we got */
|
||||||
|
if (!avail) {
|
||||||
|
ut_reportf("No console output was recorded at all");
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to read the actual output */
|
||||||
|
ret = console_record_readline(line, sizeof(line));
|
||||||
|
if (ret < 0) {
|
||||||
|
ut_reportf("Failed to read first line, avail was %d", avail);
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* console recording does not see the pager prompt, so we should have
|
||||||
|
* just got a newline
|
||||||
|
*/
|
||||||
|
ut_asserteq_str("", line);
|
||||||
|
|
||||||
|
ut_assert_console_end();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
COMMON_TEST(pager_test_console, UTF_CONSOLE);
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <of_live.h>
|
#include <of_live.h>
|
||||||
#include <os.h>
|
#include <os.h>
|
||||||
|
#include <pager.h>
|
||||||
#include <spl.h>
|
#include <spl.h>
|
||||||
#include <usb.h>
|
#include <usb.h>
|
||||||
#include <dm/ofnode.h>
|
#include <dm/ofnode.h>
|
||||||
@@ -747,8 +748,10 @@ int ut_run_list(struct unit_test_state *uts, const char *category,
|
|||||||
memcpy(uts->fdt_copy, gd->fdt_blob, uts->fdt_size);
|
memcpy(uts->fdt_copy, gd->fdt_blob, uts->fdt_size);
|
||||||
}
|
}
|
||||||
uts->force_run = force_run;
|
uts->force_run = force_run;
|
||||||
|
pager_set_bypass(gd_pager(), true);
|
||||||
ret = ut_run_tests(uts, prefix, tests, count, select_name,
|
ret = ut_run_tests(uts, prefix, tests, count, select_name,
|
||||||
test_insert);
|
test_insert);
|
||||||
|
pager_set_bypass(gd_pager(), false);
|
||||||
|
|
||||||
/* Best efforts only...ignore errors */
|
/* Best efforts only...ignore errors */
|
||||||
if (has_dm_tests)
|
if (has_dm_tests)
|
||||||
|
|||||||
Reference in New Issue
Block a user