2 * Copyright (c) 2013-2014 NVIDIA Corporation. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include <linux/slab.h>
20 #include <linux/syscalls.h>
21 #include <linux/list.h>
22 #include <linux/completion.h>
23 #include <linux/workqueue.h>
24 #include <linux/bitops.h>
25 #include <linux/uaccess.h>
28 #include <linux/dma-mapping.h>
29 #include <linux/string.h>
31 #include "ote_protocol.h"
33 #define LOGBUF_SIZE 8192
35 struct circular_buffer {
36 uint32_t size; /* Indicates the total size of the buffer */
37 uint32_t start; /* Starting point of valid data in buffer */
38 uint32_t end; /* First character which is empty (can be written to) */
39 uint32_t overflow; /* Indicator whether buffer has overwritten itself */
43 #if defined(CONFIG_OTE_ENABLE_LOGGER)
45 static int ote_logging_enabled;
46 struct circular_buffer *cb;
49 * Initialize the shared buffer for TLK logging.
50 * The shared buffer is allocated in DMA memory to get uncached memory
51 * since TLK directly writes to the physical address of the shared buffer.
52 * The structure is declared in DMA memory too since it's members will
53 * also be updated by the TLK directly to their physical addresses.
55 static int circ_buf_init(struct circular_buffer **cbptr)
60 *cbptr = (struct circular_buffer *) dma_alloc_coherent(NULL,
61 sizeof(struct circular_buffer), &tp, GFP_KERNEL);
63 pr_err("%s: no memory avaiable for circular buffer struct\n",
67 memset(*cbptr, 0, sizeof(struct circular_buffer));
71 (*cbptr)->size = LOGBUF_SIZE;
73 (*cbptr)->buf = (char *) dma_alloc_coherent(NULL, LOGBUF_SIZE,
76 pr_err("%s: no memory avaiable for shared buffer\n",
78 /* Frees the memory allocated using dma_alloc_coherent */
79 dma_free_coherent(NULL,
80 sizeof(struct circular_buffer), cbptr, tp);
83 memset((*cbptr)->buf, 0, LOGBUF_SIZE);
85 (*cbptr)->overflow = 0;
91 * Copy the contents of the circular buffer into a char buffer in order.
92 * This helps to treat the buffer like a string and use it to tokenize it
93 * into lines, tag and display it.
95 static int circ_buf_copy(struct circular_buffer *cb, char *text)
97 if (cb->end == cb->start)
100 if (cb->end > cb->start) {
101 if (abs(cb->end - cb->start) > LOGBUF_SIZE) {
102 pr_err("%s: cbuf pointers corrupted\n", __func__);
106 memcpy(text, cb->buf + cb->start, cb->end - cb->start);
108 } else if (cb->start > cb->end) {
109 if (abs(cb->end - cb->start) > LOGBUF_SIZE) {
110 pr_err("%s: cbuf pointers corrupted\n", __func__);
114 memcpy(text, cb->buf + cb->start, cb->size - cb->start);
115 memcpy(text + cb->size - cb->start, cb->buf, cb->end);
123 * Function which prints TLK logs.
124 * Tokenizes the TLK logs into lines, tags each line
125 * and prints it out to kmsg file.
127 void ote_print_logs(void)
133 if (!ote_logging_enabled)
136 buffer = kzalloc(LOGBUF_SIZE, GFP_KERNEL);
139 /* This detects if the buffer proved to be too small to hold the data.
140 * If buffer is not large enough, it overwrites it's oldest data,
141 * This warning serves to alert the user to possibly use a bigger buffer
143 if (cb->overflow == 1) {
144 pr_info("\n[TLK] **WARNING** TLK buffer overwritten.\n\n");
148 if (circ_buf_copy(cb, buffer) != 0) {
152 cb->buf[cb->end] = '\0';
154 /* In case no delimiter was found,
155 * the token is taken to be the entire string *stringp,
156 * and *stringp is made NULL.
159 temp = strsep(&text, "\n");
160 while (temp != NULL) {
161 if (strnlen(temp, LOGBUF_SIZE))
162 pr_info("[TLK] %s\n", temp);
163 temp = strsep(&text, "\n");
166 /* Indicate that buffer is empty */
171 void ote_print_logs(void) {}
175 * Call function to initialize circular buffer.
176 * An SMC is made to send the virtual address of the structure to
179 static int __init ote_logger_init(void)
181 uintptr_t smc_args[MAX_EXT_SMC_ARGS];
183 #if defined(CONFIG_OTE_ENABLE_LOGGER)
184 if (circ_buf_init(&cb) != 0)
187 smc_args[0] = TE_SMC_INIT_LOGGER;
188 smc_args[1] = (uintptr_t)cb;
190 /* enable logging only if secure firmware supports it */
191 if (!tlk_generic_smc(smc_args[0], smc_args[1], 0))
192 ote_logging_enabled = 1;
196 smc_args[0] = TE_SMC_INIT_LOGGER;
198 tlk_generic_smc(smc_args[0], smc_args[1], 0);
204 arch_initcall(ote_logger_init);