blob: 5a8e3771a8927b0f8b4c929b86853757700ba687 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * Copyright (c) 2017, ASR Micro Limited. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26#include <linux/uaccess.h>
27#include <linux/tee_drv.h>
28#include <linux/device.h>
29#include <linux/slab.h>
30#include <soc/asr/ramdump.h>
31#include "asr_tee_getmsg.h"
32#include "asr_tee_spinlock.h"
33#include "optee_smc.h"
34
35#define VIRTUAL_UART_SIZE 0x3000
36#define VIRTUART_STRING_MAX_SIZE 2048
37#define SINGLE_PRINT_MAX_SIZE 512
38
39static struct virtual_uart_buf *log_buffer = NULL;
40static char virtuart_current_string[VIRTUART_STRING_MAX_SIZE];
41
42static int ringbuf_sync(struct virtual_uart_buf *pbuf, char *string, int max_size)
43{
44 uint32_t start, end, pos;
45 uint32_t i;
46
47 if (pbuf->flags & VIRTUART_FLAG_OVERFLOW) {
48 start = pbuf->write;
49 end = pbuf->write;
50 pbuf->flags &= ~VIRTUART_FLAG_OVERFLOW;
51 } else {
52 if (pbuf->read == pbuf->write)
53 return 1;
54 start = pbuf->read;
55 end = pbuf->write;
56 }
57
58 i = 0;
59 for (pos = start; pos != end; pos++, i++) {
60 if (pos >= pbuf->size)
61 pos -= pbuf->size;
62 string[i] = pbuf->buf[pos];
63
64 /* Cannot happen.. but nothing is impossible */
65 if (string[i] == 0 && i > 0)
66 break;
67 if (string[i] == '\n' && i > SINGLE_PRINT_MAX_SIZE) {
68 string[i+1] = 0;
69 pbuf->read = pos + 1;
70 return 0;
71 }
72 /* long string? */
73 if (i == (max_size - 3)) {
74 /* use '*' to indicate message has been droped */
75 string[max_size - 2] = '*';
76 string[max_size - 1] = 0;
77 pbuf->read = pbuf->write;
78
79 return 0;
80 }
81 }
82
83 if (i > 1)
84 string[i] = 0;
85
86 pbuf->read = pbuf->write;
87
88 return 0;
89}
90
91char *get_msg_from_tee(void)
92{
93 char *p = NULL;
94 unsigned long flags;
95
96 /* Do not touch pbuf if not initialized by optee os */
97 if (log_buffer->magic != VIRTUART_MAGIC_NUMBER)
98 return 0;
99
100 memset(virtuart_current_string, 0x0, VIRTUART_STRING_MAX_SIZE);
101 local_irq_save(flags);
102 local_fiq_disable();
103
104 optee_spin_lock(&log_buffer->lock);
105 if(ringbuf_sync(log_buffer, virtuart_current_string,
106 VIRTUART_STRING_MAX_SIZE) == 0)
107 p = virtuart_current_string;
108 optee_spin_unlock(&log_buffer->lock);
109
110 local_fiq_enable();
111 local_irq_restore(flags);
112
113 return p;
114}
115
116void print_msg_from_tee(void)
117{
118 char *p = NULL;
119
120 if (log_buffer == NULL)
121 return;
122
123 do {
124 p = get_msg_from_tee();
125 if (p != NULL)
126 pr_alert("%s", p);
127 }while(p != NULL);
128
129 return;
130}
131
132#define OPTEE_SMC_FUNCID_DELIVER_VIRTUART 19
133#define OPTEE_SMC_CALL_DELIVER_VIRTUART \
134 OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_DELIVER_VIRTUART)
135
136static bool optee_msg_deliver_virtual_uart_addr(optee_invoke_fn *invoke_fn, phys_addr_t addr)
137{
138 struct arm_smccc_res res;
139 u32 addr1, addr2;
140
141#ifdef CONFIG_PHYS_ADDR_T_64BIT
142 addr1 = ((u64)addr >> 32) & 0xFFFFFFFF;
143#else
144 addr1 = 0;
145#endif
146 addr2 = addr & 0xFFFFFFFF;
147 invoke_fn(OPTEE_SMC_CALL_DELIVER_VIRTUART, addr1, addr2, VIRTUAL_UART_SIZE, 0, 0, 0, 0, &res);
148
149 if (res.a0 == 0)
150 return true;
151
152 return false;
153}
154
155void tee_setup_virtual_uart(optee_invoke_fn *invoke_fn)
156{
157 log_buffer = kmalloc(VIRTUAL_UART_SIZE, GFP_KERNEL | __GFP_ZERO);
158 if (!log_buffer) {
159 pr_warn("can't alloc memory for optee virtual uart!\n");
160 return;
161 }
162
163 pr_info("optee virtual uart log addr:0x%llx\n", (u64)virt_to_phys(log_buffer));
164
165 /* the fields of log_buffer are initilized by opteeos */
166 if(!optee_msg_deliver_virtual_uart_addr(invoke_fn, virt_to_phys(log_buffer))) {
167 pr_warn("can't set up virtual uart buffer in optee!\n");
168 kfree(log_buffer);
169 return;
170 }
171
172 return;
173}