• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&copy) == 0) {
344         switch (copy.entryType) {
345             case NOTIFY_DATA_ENTRY_WAKEUP:
346                 TcNotifyWakeupFn(&copy);
347                 break;
348             case NOTIFY_DATA_ENTRY_SHADOW:
349                 TcNotifyShadowFn(&copy);
350                 break;
351             case NOTIFY_DATA_ENTRY_FIQSHD:
352                 TcNotifyFiqshdFn(&copy);
353                 break;
354             case NOTIFY_DATA_ENTRY_SHADOW_EXIT:
355                 TcNotifyShadowExitFn(&copy);
356                 break;
357             default:
358                 tloge("invalid entry type = %u\n", copy.entryType);
359                 break;
360         }
361         if (memset_s(&copy, 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