1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "tz_spi_notify.h"
33 #include <securec.h>
34 #include "gp_ops.h"
35 #include "mailbox_mempool.h"
36 #include "smc.h"
37 #include "tc_client_driver.h"
38 #include "tc_client_sub_driver.h"
39 #include "tc_ns_client.h"
40 #include "tc_ns_log.h"
41 #include "teek_client_constants.h"
42
43 #define MAX_CALLBACK_COUNT 100
44 #define UUID_SIZE 16
45 struct TeecTimerProperty;
46
47 #ifdef DEF_ENG
48 static int g_timerType;
49 #endif
50
51 enum TimerClassType {
52 /* timer event using timer10 */
53 TIMER_GENERIC,
54 /* timer event using RTC */
55 TIMER_RTC
56 };
57
58 struct TeecTimerProperty {
59 unsigned int type;
60 unsigned int timerId;
61 unsigned int timerClass;
62 unsigned int reserved2;
63 };
64
65 struct NotifyContextTimer {
66 unsigned int devFileId;
67 unsigned char uuid[UUID_SIZE];
68 unsigned int sessionId;
69 struct TeecTimerProperty property;
70 uint32_t expireTime;
71 };
72
73 #ifdef CONFIG_TEE_SMP
74 struct NotifyContextWakeup {
75 pid_t caThreadId;
76 };
77
78 struct NotifyContextShadow {
79 uint64_t targetTcb;
80 };
81
82 struct NotifyContextStats {
83 uint32_t sends;
84 uint32_t recvs;
85 uint32_t sendw;
86 uint32_t recvw;
87 uint32_t missed;
88 };
89 #endif
90
91 union NotifyContext {
92 struct NotifyContextTimer timer;
93 #ifdef CONFIG_TEE_SMP
94 struct NotifyContextWakeup wakeup;
95 struct NotifyContextShadow shadow;
96 struct NotifyContextStats meta;
97 #endif
98 };
99
100 struct NotifyDataEntry {
101 uint32_t entryType : 31;
102 uint32_t filled : 1;
103 union NotifyContext context;
104 };
105
106 #define NOTIFY_DATA_ENTRY_COUNT \
107 ((PAGE_SIZE / sizeof(struct NotifyDataEntry)) - 1)
108 struct NotifyDataStruct {
109 struct NotifyDataEntry entry[NOTIFY_DATA_ENTRY_COUNT];
110 struct NotifyDataEntry meta;
111 };
112
113 static struct NotifyDataStruct *g_notifyData = NULL;
114 static struct NotifyDataEntry *g_notifyDataEntryTimer = NULL;
115 static struct NotifyDataEntry *g_notifyDataEntryRtc = NULL;
116 #ifdef CONFIG_TEE_SMP
117 static struct NotifyDataEntry *g_notifyDataEntryShadow = NULL;
118 #endif
119
120 enum NotifyDataType {
121 NOTIFY_DATA_ENTRY_UNUSED,
122 NOTIFY_DATA_ENTRY_TIMER,
123 NOTIFY_DATA_ENTRY_RTC,
124 #ifdef CONFIG_TEE_SMP
125 NOTIFY_DATA_ENTRY_WAKEUP,
126 NOTIFY_DATA_ENTRY_SHADOW,
127 NOTIFY_DATA_ENTRY_FIQSHD,
128 NOTIFY_DATA_ENTRY_SHADOW_EXIT,
129 #endif
130 NOTIFY_DATA_ENTRY_MAX,
131 };
132
133 struct TcNsCallback {
134 unsigned char uuid[UUID_SIZE];
135 mutex_t callbackLock;
136 void (*callbackFunc)(void *);
137 struct list_head head;
138 };
139
140 struct TcNsCallbackList {
141 unsigned int callbackCount;
142 mutex_t callbackListLock;
143 struct list_head callbackList;
144 };
145
146 static void TcNotifyFn(struct work_struct *dummy);
147 static struct TcNsCallbackList g_taCallbackFuncList;
148 static DECLARE_WORK(tc_notify_work, TcNotifyFn);
149 #ifdef CONFIG_TEE_SMP
150 static struct workqueue_struct *g_tzSpiWq = NULL;
151 #endif
152
WalkCallback(struct NotifyContextTimer * tcNotifyDataTimer,struct TcNsCallback * callbackFuncT)153 static void WalkCallback(struct NotifyContextTimer *tcNotifyDataTimer, struct TcNsCallback *callbackFuncT)
154 {
155 if (tcNotifyDataTimer->property.timerClass == TIMER_RTC) {
156 tlogd("start to call callback func\n");
157 callbackFuncT->callbackFunc((void *)(&(tcNotifyDataTimer->property)));
158 tlogd("end to call callback func\n");
159 } else if (tcNotifyDataTimer->property.timerClass == TIMER_GENERIC) {
160 tlogd("timer60 no callback func\n");
161 }
162 }
163
WalkCallbackList(struct NotifyContextTimer * tcNotifyDataTimer)164 static void WalkCallbackList(struct NotifyContextTimer *tcNotifyDataTimer)
165 {
166 struct TcNsCallback *callbackFuncT = NULL;
167
168 mutex_lock(&g_taCallbackFuncList.callbackListLock);
169 list_for_each_entry(callbackFuncT, &g_taCallbackFuncList.callbackList, head) {
170 if (memcmp(callbackFuncT->uuid, tcNotifyDataTimer->uuid, UUID_SIZE) == 0) {
171 WalkCallback(tcNotifyDataTimer, callbackFuncT);
172 }
173 }
174 mutex_unlock(&g_taCallbackFuncList.callbackListLock);
175 }
176
TcNotifyTimerFn(struct NotifyDataEntry * notifyDataEntry)177 static void TcNotifyTimerFn(struct NotifyDataEntry *notifyDataEntry)
178 {
179 TcNsDevFile *tempDevFile = NULL;
180 TcNsService *tempSvc = NULL;
181 TcNsSession *tempSes = NULL;
182 int encFound = 0;
183 struct NotifyContextTimer *tcNotifyDataTimer = NULL;
184
185 tcNotifyDataTimer = &(notifyDataEntry->context.timer);
186 notifyDataEntry->filled = 0;
187 tlogd("notify_data timer type is 0x%x, timer ID is 0x%x\n",
188 tcNotifyDataTimer->property.type,
189 tcNotifyDataTimer->property.timerId);
190 WalkCallbackList(tcNotifyDataTimer);
191 mutex_lock(&GetTcNsDevList()->devLock);
192 list_for_each_entry(tempDevFile, &GetTcNsDevList()->devFileList, head) {
193 tlogd("dev file id1 = %u, id2 = %u\n", tempDevFile->devFileId, tcNotifyDataTimer->devFileId);
194 if (tempDevFile->devFileId == tcNotifyDataTimer->devFileId) {
195 mutex_lock(&tempDevFile->serviceLock);
196 tempSvc = TcFindServiceInDev(tempDevFile, tcNotifyDataTimer->uuid, UUID_LEN);
197 GetServiceStruct(tempSvc);
198 mutex_unlock(&tempDevFile->serviceLock);
199 if (tempSvc == NULL) {
200 break;
201 }
202 mutex_lock(&tempSvc->SessionLock);
203 tempSes = TcFindSessionWithOwner(&tempSvc->sessionList, tcNotifyDataTimer->sessionId, tempDevFile);
204 GetSessionStruct(tempSes);
205 mutex_unlock(&tempSvc->SessionLock);
206 PutServiceStruct(tempSvc);
207 tempSvc = NULL;
208 if (tempSes != NULL) {
209 tlogd("send cmd ses id %u\n", tempSes->sessionId);
210 encFound = 1;
211 break;
212 }
213 break;
214 }
215 }
216 mutex_unlock(&GetTcNsDevList()->devLock);
217 if (tcNotifyDataTimer->property.timerClass == TIMER_GENERIC) {
218 tlogd("timer60 wake up event\n");
219 if (encFound && tempSes != NULL) {
220 tempSes->waitData.sendWaitFlag = 1;
221 wake_up(&tempSes->waitData.sendCmdWq);
222 PutSessionStruct(tempSes);
223 tempSes = NULL;
224 }
225 } else {
226 tlogd("RTC do not need to wakeup\n");
227 }
228 }
229
230 #ifdef CONFIG_TEE_SMP
GetNotifyDataEntry(struct NotifyDataEntry * copy)231 static noinline int GetNotifyDataEntry(struct NotifyDataEntry *copy)
232 {
233 uint32_t i;
234 int filled;
235 int ret = -1;
236
237 if (copy == NULL) {
238 tloge("Bad parameters! ");
239 return ret;
240 }
241 /* TIMER and RTC use fix entry, skip them. */
242 for (i = NOTIFY_DATA_ENTRY_WAKEUP - 1; i < NOTIFY_DATA_ENTRY_COUNT; i++) {
243 struct NotifyDataEntry *e = NULL;
244 e = &g_notifyData->entry[i];
245 filled = e->filled;
246 DMB;
247 if (!filled) {
248 continue;
249 }
250 switch (e->entryType) {
251 case NOTIFY_DATA_ENTRY_SHADOW: // fall through
252 case NOTIFY_DATA_ENTRY_SHADOW_EXIT: // fall through
253 case NOTIFY_DATA_ENTRY_FIQSHD: // fall through
254 g_notifyData->meta.context.meta.recvs++;
255 break;
256 case NOTIFY_DATA_ENTRY_WAKEUP:
257 g_notifyData->meta.context.meta.recvw++;
258 break;
259 default:
260 tloge("invalid notify type=%u\n", e->entryType);
261 goto exit;
262 }
263 if (memcpy_s(copy, sizeof(*copy), e, sizeof(*e)) != EOK) {
264 tloge("memcpy entry failed\n");
265 break;
266 }
267 DMB;
268 e->filled = 0;
269 ret = 0;
270 break;
271 }
272 exit:
273 return ret;
274 }
275
TcNotifyWakeupFn(struct NotifyDataEntry * entry)276 static void TcNotifyWakeupFn(struct NotifyDataEntry *entry)
277 {
278 struct NotifyContextWakeup *tcNotifyWakeup = NULL;
279
280 tcNotifyWakeup = &(entry->context.wakeup);
281 SmcWakeupCa(tcNotifyWakeup->caThreadId);
282 tlogd("notify_data_entry_wakeup ca: %d\n", tcNotifyWakeup->caThreadId);
283 }
284
TcNotifyShadowFn(struct NotifyDataEntry * entry)285 static void TcNotifyShadowFn(struct NotifyDataEntry *entry)
286 {
287 struct NotifyContextShadow *tcNotifyShadow = NULL;
288
289 tcNotifyShadow = &(entry->context.shadow);
290 SmcQueueShadowWorker(tcNotifyShadow->targetTcb);
291 }
292
TcNotifyFiqshdFn(struct NotifyDataEntry * entry)293 static void TcNotifyFiqshdFn(struct NotifyDataEntry *entry)
294 {
295 struct NotifyContextShadow *tcNotifyShadow = NULL;
296
297 if (entry == NULL) {
298 /* for NOTIFY_DATA_ENTRY_FIQSHD missed */
299 FiqShadowWorkFunc(0);
300 return;
301 }
302 tcNotifyShadow = &(entry->context.shadow);
303 FiqShadowWorkFunc(tcNotifyShadow->targetTcb);
304 }
305
TcNotifyShadowExitFn(struct NotifyDataEntry * entry)306 static void TcNotifyShadowExitFn(struct NotifyDataEntry *entry)
307 {
308 struct NotifyContextWakeup *tcNotifyWakeup = NULL;
309
310 tcNotifyWakeup = &(entry->context.wakeup);
311 if (SmcShadowExit(tcNotifyWakeup->caThreadId) != 0) {
312 tloge("shadow ca exit failed: %d\n",
313 (int)tcNotifyWakeup->caThreadId);
314 }
315 }
316
SpiBroadcastNotifications(void)317 static void SpiBroadcastNotifications(void)
318 {
319 uint32_t missed;
320
321 DMB;
322 missed = LOS_AtomicXchg32bits((Atomic *)&g_notifyData->meta.context.meta.missed, 0);
323 if (!missed) {
324 return;
325 }
326 if (missed & (1U << NOTIFY_DATA_ENTRY_WAKEUP)) {
327 SmcWakeupBroadcast();
328 missed &= ~(1U << NOTIFY_DATA_ENTRY_WAKEUP);
329 }
330 if (missed & (1U << NOTIFY_DATA_ENTRY_FIQSHD)) {
331 TcNotifyFiqshdFn(NULL);
332 missed &= ~(1U << NOTIFY_DATA_ENTRY_FIQSHD);
333 }
334 if (missed) {
335 tloge("missed spi notification mask %x\n", missed);
336 }
337 }
338
TcNotifyOtherFun(void)339 static void TcNotifyOtherFun(void)
340 {
341 struct NotifyDataEntry copy = {0};
342
343 while (GetNotifyDataEntry(©) == 0) {
344 switch (copy.entryType) {
345 case NOTIFY_DATA_ENTRY_WAKEUP:
346 TcNotifyWakeupFn(©);
347 break;
348 case NOTIFY_DATA_ENTRY_SHADOW:
349 TcNotifyShadowFn(©);
350 break;
351 case NOTIFY_DATA_ENTRY_FIQSHD:
352 TcNotifyFiqshdFn(©);
353 break;
354 case NOTIFY_DATA_ENTRY_SHADOW_EXIT:
355 TcNotifyShadowExitFn(©);
356 break;
357 default:
358 tloge("invalid entry type = %u\n", copy.entryType);
359 break;
360 }
361 if (memset_s(©, sizeof(copy), 0, sizeof(copy))) {
362 tloge("memset copy failed\n");
363 }
364 }
365 SpiBroadcastNotifications();
366 }
367 #else
TcNotifyOtherFun(void)368 static void TcNotifyOtherFun(void) {}
369 #endif
370 int g_spiInited = 0;
TcNotifyFn(struct work_struct * dummy)371 static void TcNotifyFn(struct work_struct *dummy)
372 {
373 if (!g_spiInited) {
374 return;
375 }
376 if (g_notifyDataEntryTimer->filled) {
377 TcNotifyTimerFn(g_notifyDataEntryTimer);
378 }
379 if (g_notifyDataEntryRtc->filled) {
380 TcNotifyTimerFn(g_notifyDataEntryRtc);
381 }
382 TcNotifyOtherFun();
383 }
384
TcSecureNotify(int irq,void * devId)385 static irqreturn_t TcSecureNotify(int irq, void *devId)
386 {
387 #ifdef CONFIG_TEE_SMP
388 #define N_WORK 8
389 int i;
390 static struct work_struct tcNotifyWorks[N_WORK];
391 static int init = 0;
392 if (!init) {
393 for (i = 0; i < N_WORK; i++) {
394 INIT_WORK(&tcNotifyWorks[i], TcNotifyFn);
395 }
396 init = 1;
397 }
398 for (i = 0; i < N_WORK; i++) {
399 if (queue_work(g_tzSpiWq, &tcNotifyWorks[i])) {
400 break;
401 }
402 }
403 #undef N_WORK
404 #else
405 schedule_work(&tc_notify_work);
406 ISB;
407 DSB;
408 TcSmcWakeup();
409 #endif
410 return IRQ_HANDLED;
411 }
412
TcNsRegisterServiceCallBackFunc(const char * uuid,void * func)413 int TcNsRegisterServiceCallBackFunc(const char *uuid, void *func)
414 {
415 struct TcNsCallback *callbackFunc = NULL;
416 struct TcNsCallback *newCallback = NULL;
417 int ret = 0;
418 errno_t sret;
419 bool checkStat = (uuid == NULL || func == NULL);
420
421 if (checkStat) {
422 return -EINVAL;
423 }
424
425 mutex_lock(&g_taCallbackFuncList.callbackListLock);
426 if (g_taCallbackFuncList.callbackCount > MAX_CALLBACK_COUNT) {
427 mutex_unlock(&g_taCallbackFuncList.callbackListLock);
428 tloge("callbackCount is out\n");
429 return -ENOMEM;
430 }
431 list_for_each_entry(callbackFunc,
432 &g_taCallbackFuncList.callbackList, head) {
433 if (memcmp(callbackFunc->uuid, uuid, UUID_SIZE) == 0) {
434 callbackFunc->callbackFunc = (void (*)(void *))func;
435 tlogd("succeed to find uuid ta_callback_func_list\n");
436 goto FIND_CALLBACK;
437 }
438 }
439 /* create a new callback struct if we couldn't find it in list */
440 newCallback = calloc(1, sizeof(*newCallback));
441 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)newCallback)) {
442 tloge("calloc failed\n");
443 ret = -ENOMEM;
444 goto FIND_CALLBACK;
445 }
446 sret = memcpy_s(newCallback->uuid, UUID_SIZE, uuid, UUID_SIZE);
447 if (sret != EOK) {
448 free(newCallback);
449 newCallback = NULL;
450 ret = -ENOMEM;
451 goto FIND_CALLBACK;
452 }
453 g_taCallbackFuncList.callbackCount++;
454 tlogd("ta_callback_func_list.callbackCount is %u\n",
455 g_taCallbackFuncList.callbackCount);
456 INIT_LIST_HEAD(&newCallback->head);
457 newCallback->callbackFunc = (void (*)(void *))func;
458 mutex_init(&newCallback->callbackLock);
459 list_add_tail(&newCallback->head, &g_taCallbackFuncList.callbackList);
460 FIND_CALLBACK:
461 mutex_unlock(&g_taCallbackFuncList.callbackListLock);
462 return ret;
463 }
464
465 #ifdef DEF_ENG
TimerCallbackFunc(void * param)466 static void TimerCallbackFunc(void *param)
467 {
468 struct TeecTimerProperty *timerProperty =
469 (struct TeecTimerProperty *)param;
470 tlogd("timerProperty->type = %x, timerProperty->timerId = %x\n",
471 timerProperty->type, timerProperty->timerId);
472 g_timerType = (int)timerProperty->type;
473 }
474
TstGetTimerType(int * type)475 static void TstGetTimerType(int *type)
476 {
477 *type = g_timerType;
478 }
479
CallbackDemoMain(const char * uuid)480 static void CallbackDemoMain(const char *uuid)
481 {
482 int ret;
483
484 tlogd("step into CallbackDemoMain\n");
485 ret = TcNsRegisterServiceCallBackFunc(uuid,
486 (void *)&TimerCallbackFunc);
487 if (ret != 0) {
488 tloge("failed to TcNsRegisterServiceCallBackFunc\n");
489 }
490 }
491
492 #define PARAM1 1
493 #define DUMP_UUID_INDEX0 0
494 #define DUMP_UUID_INDEX1 1
495 #define DUMP_UUID_INDEX2 2
496 #define DUMP_UUID_INDEX3 3
HandleTstCmdId(int cmdId,TcNsClientContext * clientContext)497 static int HandleTstCmdId(int cmdId, TcNsClientContext *clientContext)
498 {
499 int timerType;
500 int ret;
501 switch (cmdId) {
502 case TST_CMD_01:
503 CallbackDemoMain((char *)clientContext->uuid);
504 break;
505 case TST_CMD_02:
506 TstGetTimerType(&timerType);
507 if (TcUserParamValid(clientContext, (unsigned int)PARAM1)) {
508 tloge("param 1 is invalid\n");
509 ret = -EFAULT;
510 return ret;
511 }
512 if (copy_to_user(
513 (void *)(uintptr_t)clientContext->params[PARAM1].value.aAddr,
514 &timerType, sizeof(timerType))) {
515 tloge("copy to user failed:timerType\n");
516 ret = -ENOMEM;
517 return ret;
518 }
519 break;
520 default:
521 ret = -EINVAL;
522 return ret;
523 }
524 return 0;
525 }
526
TcNsTstCmd(TcNsDevFile * devId,void * argp)527 int TcNsTstCmd(TcNsDevFile *devId, void *argp)
528 {
529 TcNsClientContext clientContext;
530 int ret;
531 int cmdId;
532
533 TeecUuid secureTimerUuid = {
534 0x19b39980, 0x2487, 0x7b84,
535 {0xf4, 0x1a, 0xbc, 0x89, 0x22, 0x62, 0xbb, 0x3d}
536 };
537 if (argp == NULL) {
538 tloge("argp is NULL input buffer\n");
539 ret = -EINVAL;
540 return ret;
541 }
542 if (copy_from_user(&clientContext, argp, sizeof(clientContext))) {
543 tloge("copy from user failed\n");
544 ret = -ENOMEM;
545 return ret;
546 }
547 if (TcUserParamValid(&clientContext, (unsigned int)0)) {
548 tloge("param 0 is invalid\n");
549 ret = -EFAULT;
550 return ret;
551 }
552 /* aAddr contain the command id */
553 if (copy_from_user(&cmdId, (void *)(uintptr_t)clientContext.params[0].value.aAddr, sizeof(cmdId))) {
554 tloge("copy from user failed:cmdId\n");
555 ret = -ENOMEM;
556 return ret;
557 }
558 if (memcmp((char *)clientContext.uuid, (char *)&secureTimerUuid, sizeof(TeecUuid))) {
559 tloge("request not from secure_timer\n");
560 tloge("request uuid: %x %x %x %x\n", clientContext.uuid[DUMP_UUID_INDEX0],
561 clientContext.uuid[DUMP_UUID_INDEX1], clientContext.uuid[DUMP_UUID_INDEX2],
562 clientContext.uuid[DUMP_UUID_INDEX3]); // just wanna print the first four characters of uuid
563 ret = -EACCES;
564 return ret;
565 }
566 ret = HandleTstCmdId(cmdId, &clientContext);
567 if (ret) {
568 return ret;
569 }
570
571 if (copy_to_user(argp, (void *)&clientContext, sizeof(clientContext))) {
572 tloge("copy to user failed:client context\n");
573 ret = -ENOMEM;
574 return ret;
575 }
576 return ret;
577 }
578 #endif
579
TcNsRegisterNotifyDataMemory(void)580 static int TcNsRegisterNotifyDataMemory(void)
581 {
582 TcNsSmcCmd smcCmd = { {0}, 0 };
583 int ret;
584 struct MbCmdPack *mbPack = NULL;
585
586 mbPack = MailboxAllocCmdPack();
587 if (mbPack == NULL) {
588 return TEEC_ERROR_GENERIC;
589 }
590 mbPack->operation.paramTypes =
591 TEE_PARAM_TYPE_VALUE_INPUT | TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM;
592 mbPack->operation.params[TEE_PARAM_ONE].value.a = LOS_PaddrQuery(g_notifyData);
593 mbPack->operation.params[TEE_PARAM_ONE].value.b = 0;
594 mbPack->operation.params[TEE_PARAM_TWO].value.a = SZ_4K;
595 smcCmd.globalCmd = true;
596 smcCmd.cmdId = GLOBAL_CMD_ID_REGISTER_NOTIFY_MEMORY;
597 smcCmd.operationPhys = LOS_PaddrQuery(&mbPack->operation);
598 smcCmd.operationHphys = 0;
599 tlogd("cmd. context_phys:%x\n", smcCmd.contextId);
600 ret = TcNsSmc(&smcCmd);
601 MailboxFree(mbPack);
602 mbPack = NULL;
603 return ret;
604 }
605
TcNsUnregisterNotifyDataMemory(void)606 static int TcNsUnregisterNotifyDataMemory(void)
607 {
608 TcNsSmcCmd smcCmd = { {0}, 0 };
609 int ret;
610 struct MbCmdPack *mbPack = NULL;
611
612 mbPack = MailboxAllocCmdPack();
613 if (mbPack == NULL) {
614 return TEEC_ERROR_GENERIC;
615 }
616 mbPack->operation.paramTypes =
617 TEE_PARAM_TYPE_VALUE_INPUT | TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM;
618 mbPack->operation.params[TEE_PARAM_ONE].value.a = LOS_PaddrQuery(g_notifyData);
619 mbPack->operation.params[TEE_PARAM_ONE].value.b = 0;
620 mbPack->operation.params[TEE_PARAM_TWO].value.a = SZ_4K;
621 smcCmd.globalCmd = true;
622 smcCmd.cmdId = GLOBAL_CMD_ID_UNREGISTER_NOTIFY_MEMORY;
623 smcCmd.operationPhys = LOS_PaddrQuery(&mbPack->operation);
624 smcCmd.operationHphys = 0;
625 tlogd("cmd. context_phys:%x\n", smcCmd.contextId);
626 ret = TcNsSmc(&smcCmd);
627 MailboxFree(mbPack);
628 mbPack = NULL;
629 return ret;
630 }
631
InitNotifyData(void)632 static int InitNotifyData(void)
633 {
634 if (g_notifyData != NULL) {
635 return 0;
636 }
637
638 g_notifyData = (struct NotifyDataStruct *)GetPhyPage();
639 if (g_notifyData == NULL) {
640 tloge("GetFreePage failed for notification data\n");
641 return -ENOMEM;
642 }
643 int ret = memset_s(g_notifyData, PAGESIZE, 0, sizeof(struct NotifyDataStruct));
644 if (ret != EOK) {
645 return -EFAULT;
646 }
647 ret = TcNsRegisterNotifyDataMemory();
648 if (ret != TEEC_SUCCESS) {
649 tloge("Shared memory failed ret is 0x%x\n", ret);
650 FreePhyPage(g_notifyData);
651 g_notifyData = NULL;
652 return -EFAULT;
653 }
654 g_notifyDataEntryTimer = &g_notifyData->entry[NOTIFY_DATA_ENTRY_TIMER - 1];
655 g_notifyDataEntryRtc = &g_notifyData->entry[NOTIFY_DATA_ENTRY_RTC - 1];
656 #ifdef CONFIG_TEE_SMP
657 g_notifyDataEntryShadow = &g_notifyData->entry[NOTIFY_DATA_ENTRY_SHADOW - 1];
658 tlogi("test target is: %llx\n", g_notifyDataEntryShadow->context.shadow.targetTcb);
659 #endif
660 return 0;
661 }
662
TzSpiInit()663 int TzSpiInit()
664 {
665 unsigned int irq;
666 #ifdef CONFIG_TEE_SMP
667 g_tzSpiWq = AllocOrderedWorkqueue("g_tzSpiWq", WQ_HIGHPRI);
668 if (g_tzSpiWq == NULL) {
669 tloge("it failed to create workqueue g_tzSpiWq\n");
670 return -ENOMEM;
671 }
672 #endif
673 /* Map IRQ 0 from the OF interrupts list */
674 irq = NUM_HAL_INTERRUPT_TEE_SPI_NOTIFY;
675 int ret = DevmRequestIrq(irq, TcSecureNotify, IRQF_NO_SUSPEND, TC_NS_CLIENT_DEV, NULL);
676 if (ret < 0) {
677 tloge("device irq %u request failed %u", irq, ret);
678 goto clean;
679 }
680 ret = memset_s(&g_taCallbackFuncList, sizeof(g_taCallbackFuncList), 0, sizeof(g_taCallbackFuncList));
681 if (ret != EOK) {
682 ret = -EFAULT;
683 goto clean;
684 }
685 g_taCallbackFuncList.callbackCount = 0;
686 INIT_LIST_HEAD(&g_taCallbackFuncList.callbackList);
687 mutex_init(&g_taCallbackFuncList.callbackListLock);
688
689 ret = InitNotifyData();
690 if (ret < 0) {
691 goto clean;
692 }
693
694 g_spiInited = 1;
695 return 0;
696 clean:
697 TzSpiExit();
698 return ret;
699 }
700
TzSpiExit(void)701 void TzSpiExit(void)
702 {
703 g_spiInited = 0;
704
705 if (g_notifyData != NULL) {
706 if (TcNsUnregisterNotifyDataMemory() != TEEC_SUCCESS) {
707 tloge("unregister notify data mem failed\n");
708 }
709 FreePhyPage(g_notifyData);
710 g_notifyData = NULL;
711 }
712 #ifdef CONFIG_TEE_SMP
713 if (g_tzSpiWq != NULL) {
714 destroy_workqueue(g_tzSpiWq);
715 g_tzSpiWq = NULL;
716 }
717 #endif
718 }
719