1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
4  */
5 
6 #include <console.h>
7 #include <linux/string.h>
8 #include <asm/cb_sysinfo.h>
9 
cbmemc_putc(struct stdio_dev * dev,char data)10 void cbmemc_putc(struct stdio_dev *dev, char data)
11 {
12 	const struct sysinfo_t *sysinfo = cb_get_sysinfo();
13 	struct cbmem_console *cons;
14 	uint pos, flags;
15 
16 	if (!sysinfo)
17 		return;
18 	cons = sysinfo->cbmem_cons;
19 	if (!cons)
20 		return;
21 
22 	pos = cons->cursor & CBMC_CURSOR_MASK;
23 
24 	/* preserve the overflow flag if present */
25 	flags = cons->cursor & ~CBMC_CURSOR_MASK;
26 
27 	cons->body[pos++] = data;
28 
29 	/*
30 	 * Deal with overflow - the flag may be cleared by another program which
31 	 * reads the buffer out later, e.g. Linux
32 	 */
33 	if (pos >= cons->size) {
34 		pos = 0;
35 		flags |= CBMC_OVERFLOW;
36 	}
37 
38 	cons->cursor = flags | pos;
39 }
40 
cbmemc_puts(struct stdio_dev * dev,const char * str)41 void cbmemc_puts(struct stdio_dev *dev, const char *str)
42 {
43 	char c;
44 
45 	while ((c = *str++) != 0)
46 		cbmemc_putc(dev, c);
47 }
48 
cbmemc_init(void)49 int cbmemc_init(void)
50 {
51 	int rc;
52 	struct stdio_dev cons_dev;
53 
54 	memset(&cons_dev, 0, sizeof(cons_dev));
55 
56 	strcpy(cons_dev.name, "cbmem");
57 	cons_dev.flags = DEV_FLAGS_OUTPUT; /* Output only */
58 	cons_dev.putc  = cbmemc_putc;
59 	cons_dev.puts  = cbmemc_puts;
60 
61 	rc = stdio_register(&cons_dev);
62 
63 	return (rc == 0) ? 1 : rc;
64 }
65