1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12
13 #include "tlv_sharedmem.h"
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include <securec.h>
18
19 #include "teeos_uuid.h"
20 #include "set_teeos_cfg.h"
21
22 static struct tlv_tag *g_tlv_start = NULL;
23 static uint64_t g_teeos_share_mem = 0;
24
tlv_start_init(void)25 static int32_t tlv_start_init(void)
26 {
27 if (g_tlv_start != NULL) {
28 teelog("tlv already started\n");
29 return 0;
30 }
31
32 uint64_t sharedmem_start = get_sharedmem_start();
33 uint64_t sharedmem_size = get_sharedmem_size();
34 if (sharedmem_start == 0 || sharedmem_size == 0) {
35 teelog("sharedmem start addr or size error\n");
36 return -1;
37 }
38
39 if (sharedmem_size < sizeof(struct tlv_tag)) {
40 teelog("sharedmem size not enough\n");
41 return -1;
42 }
43
44 if (memset_s((void *)(uintptr_t)sharedmem_start, sizeof(struct tlv_tag),
45 0, sizeof(struct tlv_tag)) != EOK) {
46 teelog("memset tlv start failed\n");
47 return -1;
48 }
49
50 g_teeos_share_mem = sharedmem_start + sizeof(*g_tlv_start);
51 struct tlv_tag *tlv = (struct tlv_tag *)(uintptr_t)sharedmem_start;
52 tlv->magic = MAGIC_START;
53 tlv->tlv_num = 0;
54 g_tlv_start = tlv;
55
56 return 0;
57 }
58
alloc_teeos_shared_mem(uint64_t * addr,uint32_t length)59 static int32_t alloc_teeos_shared_mem(uint64_t *addr, uint32_t length)
60 {
61 if (addr == NULL || length == 0) {
62 teelog("invalid params\n");
63 return -1;
64 }
65
66 uint64_t teeos_mem_start = get_teeos_start();
67 uint64_t teeos_mem_size = get_teeos_size();
68
69 if (UINT64_MAX - g_teeos_share_mem < length) {
70 teelog("tlv length too large\n");
71 return -1;
72 }
73
74 if (g_teeos_share_mem + length > teeos_mem_start + teeos_mem_size) {
75 teelog("tlv length too large\n");
76 return -1;
77 }
78
79 if (memset_s((void *)(uintptr_t)g_teeos_share_mem, length, 0, length) != EOK) {
80 teelog("memset sharedmem to zero failed\n");
81 return -1;
82 }
83
84 *addr = g_teeos_share_mem;
85 g_teeos_share_mem += length;
86
87 return 0;
88 }
89
share_mem_tlv_init_item(struct tlv_item_tag * new_item,struct tlv_item_data tlv_item_data)90 static int32_t share_mem_tlv_init_item(struct tlv_item_tag *new_item, struct tlv_item_data tlv_item_data)
91 {
92 uint32_t magic = MAGIC_START + tlv_item_data.value_len + tlv_item_data.owner_len;
93 struct tlv_item_tag tmp_item;
94 if (new_item == NULL) {
95 teelog("invalide params\n");
96 return 1;
97 }
98
99 if (tlv_item_data.value_len == 0)
100 return 1;
101
102 (void)memset_s(&tmp_item, sizeof(tmp_item), 0, sizeof(tmp_item));
103 if (memcpy_s(tmp_item.type, MAX_TAG_LEN,
104 tlv_item_data.type, tlv_item_data.type_size) != EOK) {
105 teelog("memcpy to tmp_item failed\n");
106 return -1;
107 }
108 tmp_item.length = tlv_item_data.value_len;
109 tmp_item.owner_len = tlv_item_data.owner_len;
110 tmp_item.magic = magic;
111
112 if (memcpy_s(new_item, sizeof(struct tlv_item_tag), &tmp_item, sizeof(struct tlv_item_tag)) != EOK) {
113 teelog("memcpy tag to new_item failed\n");
114 return -1;
115 }
116
117 if (memcpy_s((uint8_t *)(uintptr_t)TLV_ITEM_DATA(new_item), tlv_item_data.owner_len,
118 (uint8_t *)tlv_item_data.owner_list, tlv_item_data.owner_len) != EOK) {
119 teelog("memcpy owner_list to new_item failed\n");
120 return -1;
121 }
122
123 if (memcpy_s((uint8_t *)(uintptr_t)(TLV_ITEM_DATA(new_item) + tlv_item_data.owner_len), tlv_item_data.value_len,
124 (uint8_t *)tlv_item_data.value, tlv_item_data.value_len) != EOK) {
125 teelog("memcpy value to new_item failed\n");
126 return -1;
127 }
128 return 0;
129 }
130
share_mem_tlv_find(uint64_t start_share_mem,const struct tlv_tag * tlv,const char * type,uint32_t type_size)131 struct tlv_item_tag* share_mem_tlv_find(uint64_t start_share_mem,
132 const struct tlv_tag *tlv, const char *type, uint32_t type_size)
133 {
134 struct tlv_item_tag *pos = NULL;
135 uint32_t len;
136 uint64_t sharedmem_vaddr = g_teeos_share_mem + sizeof(struct tlv_tag);
137
138 pos = (struct tlv_item_tag *)(uintptr_t)(start_share_mem + sizeof(struct tlv_tag));
139 for (uint32_t i = 0; i < tlv->tlv_num; i++) {
140 len = sizeof(struct tlv_item_tag) + pos->length + pos->owner_len;
141 if (memcmp(pos->type, type, type_size) == 0 && strnlen(pos->type, MAX_TAG_LEN) <= type_size)
142 return pos;
143 if (i < tlv->tlv_num - 1)
144 pos = (struct tlv_item_tag *)(uintptr_t)(sharedmem_vaddr + len);
145 }
146
147 return NULL;
148 }
149
update_share_mem_tlv(struct tlv_item_data tlv_item_data)150 uint32_t update_share_mem_tlv(struct tlv_item_data tlv_item_data)
151 {
152 struct tlv_item_tag *new_item = NULL;
153
154 new_item = share_mem_tlv_find(g_teeos_share_mem, g_tlv_start, tlv_item_data.type, tlv_item_data.type_size);
155 if (new_item == NULL) {
156 teelog("invalide params\n");
157 return 1;
158 }
159
160 if (new_item->length == tlv_item_data.value_len)
161 share_mem_tlv_init_item(new_item, tlv_item_data);
162 else
163 return 1;
164 return 0;
165 }
166
share_mem_tlv_append(struct tlv_tag * tlv,struct tlv_item_data tlv_item_data)167 static uint32_t share_mem_tlv_append(struct tlv_tag *tlv, struct tlv_item_data tlv_item_data)
168 {
169 uint64_t addr;
170 if (tlv == NULL) {
171 teelog("invalide params\n");
172 return 1;
173 }
174
175 if (tlv->magic != MAGIC_START) {
176 teelog("append error, tlv format error\n");
177 return 1;
178 }
179
180 /* length is the tlv length */
181 uint32_t total_len = tlv_item_data.value_len + tlv_item_data.owner_len + sizeof(struct tlv_item_tag);
182 uint32_t ret = alloc_teeos_shared_mem(&addr, total_len);
183 if (ret != 0) {
184 teelog("get share mem error\n");
185 return 1;
186 }
187
188 share_mem_tlv_init_item((struct tlv_item_tag *)(uintptr_t)addr, tlv_item_data);
189 tlv->tlv_num++;
190
191 uint64_t sharedmem_size = get_sharedmem_size();
192 if (tlv->total_len + sizeof(struct tlv_tag) >= sharedmem_size) {
193 teelog("out of share mem size\n");
194 return 1;
195 }
196
197 tlv->total_len += tlv_item_data.value_len + tlv_item_data.owner_len + sizeof(struct tlv_item_tag);
198 return 0;
199 }
200
put_tlv_shared_mem(struct tlv_item_data tlv_item_data)201 uint32_t put_tlv_shared_mem(struct tlv_item_data tlv_item_data)
202 {
203 uint32_t ret;
204
205 if (tlv_start_init() != 0) {
206 teelog("tlv init failed\n");
207 return 1;
208 }
209
210 if (tlv_item_data.type == NULL || tlv_item_data.value == NULL) {
211 teelog("tlv_item data error\n");
212 return 1;
213 }
214
215 if (tlv_item_data.owner_len % (uint32_t)(sizeof(TEE_UUID)) != 0) {
216 teelog("tlv_item owner_len error\n");
217 return 1;
218 }
219
220 if (tlv_item_data.type_size >= MAX_TAG_LEN || tlv_item_data.type_size < MIN_TAG_LEN) {
221 teelog("tlv_item type_size error\n");
222 return 1;
223 }
224
225 ret = share_mem_tlv_append(g_tlv_start, tlv_item_data);
226 if (ret != 0) {
227 teelog("add share mem error\n");
228 return ret;
229 }
230 return ret;
231 }
232