From 18fa21f17cd94e12e42a50d0708081d5ce51502a Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Thu, 10 Oct 2013 16:03:35 +0530 Subject: security: tlk_driver: shared buffer logging Changes to TLK driver to allow logging for TLK via the linux kmsg file. Bug 1332411 Original author: Jay Patel Change-Id: I14d23d2598b391a98ca9e693ae47982da24e17cb Signed-off-by: Sharif Inamdar Signed-off-by: Varun Wadekar Reviewed-on: http://git-master/r/289035 --- security/tlk_driver/Kconfig | 7 ++ security/tlk_driver/Makefile | 1 + security/tlk_driver/ote_comms.c | 6 ++ security/tlk_driver/ote_log.c | 196 +++++++++++++++++++++++++++++++++++++ security/tlk_driver/ote_protocol.h | 4 + 5 files changed, 214 insertions(+) create mode 100644 security/tlk_driver/ote_log.c (limited to 'security') diff --git a/security/tlk_driver/Kconfig b/security/tlk_driver/Kconfig index 240a3180d7a0..5199be43dd20 100644 --- a/security/tlk_driver/Kconfig +++ b/security/tlk_driver/Kconfig @@ -5,3 +5,10 @@ config TRUSTED_LITTLE_KERNEL This option adds kernel support for communication with the Trusted LK secure OS monitor/runtime support. If you are unsure how to answer this question, answer N. + +config OTE_ENABLE_LOGGER + bool "Enable TLK logs in linux kmsg" + depends on TRUSTED_LITTLE_KERNEL + help + This option adds support in the kernel driver to read the logs + from the secure world and make them available as a part of kmsg. diff --git a/security/tlk_driver/Makefile b/security/tlk_driver/Makefile index 2fb6a24acc24..86a293d2f009 100644 --- a/security/tlk_driver/Makefile +++ b/security/tlk_driver/Makefile @@ -25,5 +25,6 @@ tlk_driver-objs += ote_device.o tlk_driver-objs += ote_comms.o tlk_driver-objs += ote_fs.o tlk_driver-objs += ote_irq.o +tlk_driver-objs += ote_log.o obj-$(CONFIG_TRUSTED_LITTLE_KERNEL) += tlk_driver.o diff --git a/security/tlk_driver/ote_comms.c b/security/tlk_driver/ote_comms.c index 6e3eb0abbd82..1e800492ee01 100644 --- a/security/tlk_driver/ote_comms.c +++ b/security/tlk_driver/ote_comms.c @@ -288,6 +288,12 @@ static void do_smc(struct te_request *request, struct tlk_device *dev) } TLK_GENERIC_SMC(request->type, smc_args, smc_params); + + /* + * Check to see if there are any logs in written by TLK. + * If there are, print them out. + */ + ote_print_logs(); } /* diff --git a/security/tlk_driver/ote_log.c b/security/tlk_driver/ote_log.c new file mode 100644 index 000000000000..6df01263f8d3 --- /dev/null +++ b/security/tlk_driver/ote_log.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2013 NVIDIA Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ote_protocol.h" + +#define LOGBUF_SIZE 8192 + +struct circular_buffer { + uint32_t size; /* Indicates the total size of the buffer */ + uint32_t start; /* Starting point of valid data in buffer */ + uint32_t end; /* First character which is empty (can be written to) */ + uint32_t overflow; /* Indicator whether buffer has overwritten itself */ + char *buf; +}; + +#if defined(CONFIG_OTE_ENABLE_LOGGER) + +static int ote_logging_enabled; +struct circular_buffer *cb; + +/* + * Initialize the shared buffer for TLK logging. + * The shared buffer is allocated in DMA memory to get uncached memory + * since TLK directly writes to the physical address of the shared buffer. + * The structure is declared in DMA memory too since it's members will + * also be updated by the TLK directly to their physical addresses. + */ +static int circ_buf_init(struct circular_buffer **cbptr) +{ + + dma_addr_t tp; + + *cbptr = (struct circular_buffer *) dma_alloc_coherent(NULL, + sizeof(struct circular_buffer), &tp, GFP_KERNEL); + if (!*cbptr) { + pr_err("%s: no memory avaiable for circular buffer struct\n", + __func__); + return -ENOMEM; + } + memset(*cbptr, 0, sizeof(struct circular_buffer)); + + (*cbptr)->start = 0; + (*cbptr)->end = 0; + (*cbptr)->size = LOGBUF_SIZE; + + (*cbptr)->buf = (char *) dma_alloc_coherent(NULL, LOGBUF_SIZE, + &tp, GFP_KERNEL); + if (!(*cbptr)->buf) { + pr_err("%s: no memory avaiable for shared buffer\n", + __func__); + /* Frees the memory allocated using dma_alloc_coherent */ + dma_free_coherent(NULL, + sizeof(struct circular_buffer), cbptr, tp); + return -ENOMEM; + } + memset((*cbptr)->buf, 0, LOGBUF_SIZE); + + (*cbptr)->overflow = 0; + + return 0; +} + +/* + * Copy the contents of the circular buffer into a char buffer in order. + * This helps to treat the buffer like a string and use it to tokenize it + * into lines, tag and display it. + */ +static int circ_buf_copy(struct circular_buffer *cb, char *text) +{ + if (cb->end == cb->start) + return 0; + + if (cb->end > cb->start) { + if (abs(cb->end - cb->start) > LOGBUF_SIZE) { + pr_err("%s: cbuf pointers corrupted\n", __func__); + return -EINVAL; + } + + memcpy(text, cb->buf + cb->start, cb->end - cb->start); + + } else if (cb->start > cb->end) { + if (abs(cb->end - cb->start) > LOGBUF_SIZE) { + pr_err("%s: cbuf pointers corrupted\n", __func__); + return -EINVAL; + } + + memcpy(text, cb->buf + cb->start, cb->size - cb->start); + memcpy(text + cb->size - cb->start, cb->buf, cb->end); + + } + + return 0; +} + +/* + * Function which prints TLK logs. + * Tokenizes the TLK logs into lines, tags each line + * and prints it out to kmsg file. + */ +void ote_print_logs(void) +{ + char *text = NULL; + char *temp = NULL; + + if (!ote_logging_enabled) + return; + + text = kzalloc(LOGBUF_SIZE, GFP_KERNEL); + BUG_ON(!text); + + /* This detects if the buffer proved to be too small to hold the data. + * If buffer is not large enough, it overwrites it's oldest data, + * This warning serves to alert the user to possibly use a bigger buffer + */ + if (cb->overflow == 1) { + pr_info("\n[TLK] **WARNING** TLK buffer overwritten.\n\n"); + cb->overflow = 0; + } + + if (circ_buf_copy(cb, text) != 0) { + kfree(text); + return; + } + cb->buf[cb->end] = '\0'; + + temp = strsep(&text, "\n"); + while (temp != NULL) { + if (strnlen(temp, LOGBUF_SIZE)) + pr_info("[TLK] %s\n", temp); + temp = strsep(&text, "\n"); + } + + /* Indicate that buffer is empty */ + cb->start = cb->end; + kfree(text); +} +#else +void ote_print_logs(void) {} +#endif + +/* + * Call function to initialize circular buffer. + * An SMC is made to send the virtual address of the structure to + * the secure OS. + */ +static int __init ote_logger_init(void) +{ + uint32_t smc_args[MAX_EXT_SMC_ARGS]; + +#if defined(CONFIG_OTE_ENABLE_LOGGER) + if (circ_buf_init(&cb) != 0) + return -1; + + smc_args[0] = TE_SMC_INIT_LOGGER; + smc_args[1] = (uint32_t)cb; + tlk_extended_smc(smc_args); + + ote_logging_enabled = 1; + ote_print_logs(); +#else + smc_args[0] = TE_SMC_INIT_LOGGER; + smc_args[1] = 0; + tlk_extended_smc(smc_args); +#endif + + return 0; +} + +arch_initcall(ote_logger_init); diff --git a/security/tlk_driver/ote_protocol.h b/security/tlk_driver/ote_protocol.h index 4efade0be3f3..3da034918d3f 100644 --- a/security/tlk_driver/ote_protocol.h +++ b/security/tlk_driver/ote_protocol.h @@ -122,6 +122,8 @@ enum { TE_SMC_REGISTER_FS_HANDLERS = 0xFFFF1FF2, TE_SMC_REGISTER_REQ_BUF = 0xFFFF1FF3, TE_SMC_FS_OP_DONE = 0xFFFF1FFF, + TE_SMC_INIT_LOGGER = 0xFFFF1FF4, + }; enum { @@ -246,4 +248,6 @@ struct te_file_req { int te_handle_fs_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param); +void ote_print_logs(void); + #endif -- cgit v1.2.3