Skip to content

Commit

Permalink
drivers: Implement semihosting based console driver for log
Browse files Browse the repository at this point in the history
This commit implements a simple console driver which uses semihosting
operations to read/write the character. There are two paths to output
the log:
- If the caller of semihosting_console_init() provides the path of the
  file, the driver will try to open that file, and output the log to
  that host side file.
- If the caller of semihosting_console_init() does not provide the path
  of the file, the driver will try to output the log to host side
  console directly.

If CFG_SEMIHOSTING_CONSOLE is enabled, OP-TEE will try to initialize the
semihosting console driver by given CFG_SEMIHOSTING_CONSOLE_FILE.

Signed-off-by: Alvin Chang <alvinga@andestech.com>
Acked-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
  • Loading branch information
gagachang committed Feb 28, 2024
1 parent 0290eaa commit 2234612
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 1 deletion.
68 changes: 68 additions & 0 deletions core/drivers/semihosting_console.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2024 Andes Technology Corporation
*/

#include <compiler.h>
#include <console.h>
#include <drivers/semihosting_console.h>
#include <drivers/serial.h>
#include <kernel/semihosting.h>
#include <util.h>

/*
* struct semihosting_console_data - Structure for semihosting console driver
* @chip - General structure for each serial chip
* @fd - Handle of the file at @file_path when semihosting_console_init() is
* called, or -1 if using the semihosting console
*/
struct semihosting_console_data {
struct serial_chip chip;
int fd;
};

static struct semihosting_console_data sh_console_data __nex_bss;

static void semihosting_console_putc(struct serial_chip *chip __unused, int ch)
{
semihosting_sys_writec(ch);
}

static int semihosting_console_getchar(struct serial_chip *chip __unused)
{
return semihosting_sys_readc();
}

static const struct serial_ops semihosting_console_ops = {
.putc = semihosting_console_putc,
.getchar = semihosting_console_getchar,
};
DECLARE_KEEP_PAGER(semihosting_console_ops);

static void semihosting_console_fd_putc(struct serial_chip *chip __unused,
int ch)
{
if (sh_console_data.fd >= 0)
semihosting_write(sh_console_data.fd, &ch, 1);
}

static const struct serial_ops semihosting_console_fd_ops = {
.putc = semihosting_console_fd_putc,
};
DECLARE_KEEP_PAGER(semihosting_console_fd_ops);

void semihosting_console_init(const char *file_path)
{
if (file_path) {
/* Output log to given file on the semihosting host system. */
sh_console_data.chip.ops = &semihosting_console_fd_ops;
sh_console_data.fd =
semihosting_open(file_path, O_RDWR | O_CREAT | O_TRUNC);
} else {
/* Output log to semihosting host debug console. */
sh_console_data.chip.ops = &semihosting_console_ops;
sh_console_data.fd = -1;
}

register_serial_console(&sh_console_data.chip);
}
1 change: 1 addition & 0 deletions core/drivers/sub.mk
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ srcs-$(CFG_CBMEM_CONSOLE) += cbmem_console.c
srcs-$(CFG_RISCV_PLIC) += plic.c
srcs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisi_trng.c
srcs-$(CFG_WIDEVINE_HUK) += widevine_huk.c
srcs-$(CFG_SEMIHOSTING_CONSOLE) += semihosting_console.c

subdirs-y += crypto
subdirs-$(CFG_BNXT_FW) += bnxt
Expand Down
23 changes: 23 additions & 0 deletions core/include/drivers/semihosting_console.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2024 Andes Technology Corporation
*/
#ifndef __DRIVERS_SEMIHOSTING_CONSOLE_H
#define __DRIVERS_SEMIHOSTING_CONSOLE_H

#ifdef CFG_SEMIHOSTING_CONSOLE
/*
* Initialize console which uses architecture-specific semihosting mechanism.
* If @file_path is not NULL, OP-TEE OS will try to output log to that file,
* which is on the semihosting host system.
* Otherwise, if @file_path is NULL, OP-TEE OS will try to output log to the
* semihosting host debug console.
*/
void semihosting_console_init(const char *file_path);
#else
static inline void semihosting_console_init(const char *file_path __unused)
{
}
#endif

#endif /* __DRIVERS_SEMIHOSTING_CONSOLE_H */
6 changes: 5 additions & 1 deletion core/kernel/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <compiler.h>
#include <console.h>
#include <drivers/cbmem_console.h>
#include <drivers/semihosting_console.h>
#include <drivers/serial.h>
#include <kernel/dt.h>
#include <kernel/dt_driver.h>
Expand All @@ -24,7 +25,10 @@ __weak void plat_console_init(void)

void console_init(void)
{
plat_console_init();
if (IS_ENABLED(CFG_SEMIHOSTING_CONSOLE))
semihosting_console_init(CFG_SEMIHOSTING_CONSOLE_FILE);
else
plat_console_init();
}

void __weak console_putc(int ch)
Expand Down
15 changes: 15 additions & 0 deletions mk/config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -1163,3 +1163,18 @@ $(eval $(call cfg-depends-all,CFG_WIDEVINE_PTA,CFG_DT CFG_WIDEVINE_HUK))
# system (also called the target) to communicate with and use the I/O of the
# host computer.
CFG_SEMIHOSTING ?= n

# Enable the semihosting console driver which inputs/outputs the characters
# from/to the file or debug terminal on the semihosting host computer.
# - Specify CFG_SEMIHOSTING_CONSOLE_FILE="{your_log_file}" to output the
# characters to that file. Output to "optee.log" by default.
# - Specify CFG_SEMIHOSTING_CONSOLE_FILE=NULL to output the characters to the
# semihosting host terminal.
CFG_SEMIHOSTING_CONSOLE ?= n
ifeq ($(CFG_SEMIHOSTING_CONSOLE),y)
$(call force,CFG_SEMIHOSTING,y)
endif
CFG_SEMIHOSTING_CONSOLE_FILE ?= "optee.log"
ifeq ($(CFG_SEMIHOSTING_CONSOLE_FILE),)
$(error CFG_SEMIHOSTING_CONSOLE_FILE cannot be empty)
endif

0 comments on commit 2234612

Please sign in to comment.