summaryrefslogtreecommitdiff
path: root/security/tlk_driver
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2013-10-10 16:03:35 +0530
committerVarun Wadekar <vwadekar@nvidia.com>2013-10-11 00:32:06 -0700
commit18fa21f17cd94e12e42a50d0708081d5ce51502a (patch)
treed22296cae25942c124e8f1edef35ed7a82123a34 /security/tlk_driver
parent4c4615de71190bb190626a8f1d82d447bb869156 (diff)
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 <japatel@nvidia.com> Change-Id: I14d23d2598b391a98ca9e693ae47982da24e17cb Signed-off-by: Sharif Inamdar <isharif@nvidia.com> Signed-off-by: Varun Wadekar <vwadekar@nvidia.com> Reviewed-on: http://git-master/r/289035
Diffstat (limited to 'security/tlk_driver')
-rw-r--r--security/tlk_driver/Kconfig7
-rw-r--r--security/tlk_driver/Makefile1
-rw-r--r--security/tlk_driver/ote_comms.c6
-rw-r--r--security/tlk_driver/ote_log.c196
-rw-r--r--security/tlk_driver/ote_protocol.h4
5 files changed, 214 insertions, 0 deletions
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 <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/uaccess.h>
+
+#include <asm/page.h>
+#include <linux/dma-mapping.h>
+#include <linux/string.h>
+
+#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