xref: /optee_os/core/drivers/semihosting_console.c (revision 9f34db38245c9b3a4e6e7e63eb78a75e23ab2da3)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2024 Andes Technology Corporation
4  */
5 
6 #include <compiler.h>
7 #include <console.h>
8 #include <drivers/semihosting_console.h>
9 #include <drivers/serial.h>
10 #include <kernel/semihosting.h>
11 #include <util.h>
12 
13 /*
14  * struct semihosting_console_data - Structure for semihosting console driver
15  * @chip - General structure for each serial chip
16  * @fd - Handle of the file at @file_path when semihosting_console_init() is
17  *       called, or -1 if using the semihosting console
18  */
19 struct semihosting_console_data {
20 	struct serial_chip chip;
21 	int fd;
22 };
23 
24 static struct semihosting_console_data sh_console_data __nex_bss;
25 
26 static void semihosting_console_putc(struct serial_chip *chip __unused, int ch)
27 {
28 	semihosting_sys_writec(ch);
29 }
30 
31 static int semihosting_console_getchar(struct serial_chip *chip __unused)
32 {
33 	return semihosting_sys_readc();
34 }
35 
36 static const struct serial_ops semihosting_console_ops = {
37 	.putc = semihosting_console_putc,
38 	.getchar = semihosting_console_getchar,
39 };
40 DECLARE_KEEP_PAGER(semihosting_console_ops);
41 
42 static void semihosting_console_fd_putc(struct serial_chip *chip __unused,
43 					int ch)
44 {
45 	if (sh_console_data.fd >= 0)
46 		semihosting_write(sh_console_data.fd, &ch, 1);
47 }
48 
49 static const struct serial_ops semihosting_console_fd_ops = {
50 	.putc = semihosting_console_fd_putc,
51 };
52 DECLARE_KEEP_PAGER(semihosting_console_fd_ops);
53 
54 void semihosting_console_init(const char *file_path)
55 {
56 	if (file_path) {
57 		/* Output log to given file on the semihosting host system. */
58 		sh_console_data.chip.ops = &semihosting_console_fd_ops;
59 		sh_console_data.fd =
60 			semihosting_open(file_path, O_RDWR | O_CREAT | O_TRUNC);
61 	} else {
62 		/* Output log to semihosting host debug console. */
63 		sh_console_data.chip.ops = &semihosting_console_ops;
64 		sh_console_data.fd = -1;
65 	}
66 
67 	register_serial_console(&sh_console_data.chip);
68 }
69