• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <inttypes.h>
18 #include <stdarg.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include <plat/eeData.h>
23 #include <plat/plat.h>
24 #include <plat/wdt.h>
25 
26 #include <apInt.h>
27 #include <atomic.h>
28 #include <bl.h>
29 #include <cpu.h>
30 #include <crc.h>
31 #include <eventQ.h>
32 #include <heap.h>
33 #include <hostIntf.h>
34 #include <mpu.h>
35 #include <nanohubPacket.h>
36 #include <osApi.h>
37 #include <platform.h>
38 #include <printf.h>
39 #include <sensors.h>
40 #include <seos.h>
41 #include <seos_priv.h>
42 #include <slab.h>
43 #include <syscall.h>
44 #include <timer.h>
45 #include <util.h>
46 
47 #include <nanohub/nanohub.h>
48 
49 #include <chreApi.h>
50 
51 struct TaskPool {
52     struct Task data[MAX_TASKS];
53 };
54 
55 static struct TaskPool mTaskPool;
56 static struct EvtQueue *mEvtsInternal;
57 static struct SlabAllocator* mMiscInternalThingsSlab;
58 static struct TaskList mFreeTasks;
59 static struct TaskList mTasks;
60 static struct Task *mCurrentTask;
61 static struct Task *mSystemTask;
62 static TaggedPtr *mCurEvtEventFreeingInfo = NULL; //used as flag for retaining. NULL when none or already retained
63 
list_init(struct TaskList * l)64 static inline void list_init(struct TaskList *l)
65 {
66     l->prev = l->next = NO_NODE;
67 }
68 
osGetCurrentTask()69 struct Task *osGetCurrentTask()
70 {
71     return mCurrentTask;
72 }
73 
osSetCurrentTask(struct Task * task)74 struct Task *osSetCurrentTask(struct Task *task)
75 {
76     struct Task *old = mCurrentTask;
77     while (true) {
78         old = mCurrentTask;
79         if (atomicCmpXchgPtr((uintptr_t*)&mCurrentTask, (uintptr_t)old, (uintptr_t)task)) {
80             break;
81         }
82     }
83     return old;
84 }
85 
86 // beyond this point, noone shall access mCurrentTask directly
87 
osTaskTestFlags(struct Task * task,uint32_t mask)88 static inline bool osTaskTestFlags(struct Task *task, uint32_t mask)
89 {
90     return (atomicReadByte(&task->flags) & mask) != 0;
91 }
92 
osAppIsChre(uint16_t tid)93 bool osAppIsChre(uint16_t tid)
94 {
95     struct Task *task = osTaskFindByTid(tid);
96 
97     return task && osTaskIsChre(task);
98 }
99 
osAppChreVersion(uint16_t tid)100 uint32_t osAppChreVersion(uint16_t tid)
101 {
102     struct Task *task = osTaskFindByTid(tid);
103 
104     if (task)
105         return osTaskChreVersion(task);
106     else
107         return 0;
108 }
109 
osTaskClrSetFlags(struct Task * task,uint32_t clrMask,uint32_t setMask)110 static inline uint32_t osTaskClrSetFlags(struct Task *task, uint32_t clrMask, uint32_t setMask)
111 {
112     while (true) {
113         uint8_t flags = atomicReadByte(&task->flags);
114         uint8_t newFlags = (flags & ~clrMask) | setMask;
115         if (atomicCmpXchgByte(&task->flags, flags, newFlags))
116             return newFlags;
117     }
118 }
119 
osTaskAddIoCount(struct Task * task,int32_t delta)120 static inline uint32_t osTaskAddIoCount(struct Task *task, int32_t delta)
121 {
122     uint8_t count = atomicAddByte(&task->ioCount, delta);
123 
124     count += delta; // old value is returned, so we add it again
125 
126     return count;
127 }
128 
osTaskGetIoCount(struct Task * task)129 static inline uint32_t osTaskGetIoCount(struct Task *task)
130 {
131     return atomicReadByte(&task->ioCount);
132 }
133 
osTaskIndex(struct Task * task)134 uint8_t osTaskIndex(struct Task *task)
135 {
136     // we don't need signed diff here: this way we simplify boundary check
137     size_t idx = task - &mTaskPool.data[0];
138     return idx >= MAX_TASKS || &mTaskPool.data[idx] != task ? NO_NODE : idx;
139 }
140 
osTaskByIdx(size_t idx)141 static inline struct Task *osTaskByIdx(size_t idx)
142 {
143     return idx >= MAX_TASKS ? NULL : &mTaskPool.data[idx];
144 }
145 
osGetCurrentTid()146 uint32_t osGetCurrentTid()
147 {
148     struct Task *task = osGetCurrentTask();
149     if (task == NULL) {
150         return UINT32_MAX;
151     }
152     return task->tid;
153 }
154 
osSetCurrentTid(uint32_t tid)155 uint32_t osSetCurrentTid(uint32_t tid)
156 {
157     struct Task *task = osTaskByIdx(TID_TO_TASK_IDX(tid));
158 
159     if (task && task->tid == tid) {
160         struct Task *preempted = osSetCurrentTask(task);
161         return preempted->tid;
162     }
163 
164     return osGetCurrentTid();
165 }
166 
osTaskListPeekHead(struct TaskList * listHead)167 static inline struct Task *osTaskListPeekHead(struct TaskList *listHead)
168 {
169     TaskIndex idx = listHead->next;
170     return idx == NO_NODE ? NULL : &mTaskPool.data[idx];
171 }
172 
173 #ifdef DEBUG
dumpListItems(const char * p,struct TaskList * listHead)174 static void dumpListItems(const char *p, struct TaskList *listHead)
175 {
176     int i = 0;
177     struct Task *task;
178 
179     osLog(LOG_ERROR, "List: %s (%p) [%u;%u]\n",
180           p,
181           listHead,
182           listHead ? listHead->prev : NO_NODE,
183           listHead ? listHead->next : NO_NODE
184     );
185     if (!listHead)
186         return;
187 
188     for_each_task(listHead, task) {
189         osLog(LOG_ERROR, "  item %d: task=%p TID=%04X [%u;%u;%u]\n",
190               i,
191               task,
192               task->tid,
193               task->list.prev,
194               osTaskIndex(task),
195               task->list.next
196         );
197         ++i;
198     }
199 }
200 
dumpTaskList(const char * f,struct Task * task,struct TaskList * listHead)201 static void dumpTaskList(const char *f, struct Task *task, struct TaskList *listHead)
202 {
203     osLog(LOG_ERROR, "%s: pool: %p; task=%p [%u;%u;%u]; listHead=%p [%u;%u]\n",
204           f,
205           &mTaskPool,
206           task,
207           task ? task->list.prev : NO_NODE,
208           osTaskIndex(task),
209           task ? task->list.next : NO_NODE,
210           listHead,
211           listHead ? listHead->prev : NO_NODE,
212           listHead ? listHead->next : NO_NODE
213     );
214     dumpListItems("Tasks", &mTasks);
215     dumpListItems("Free Tasks", &mFreeTasks);
216 }
217 #else
218 #define dumpTaskList(a,b,c)
219 #endif
220 
osTaskListRemoveTask(struct TaskList * listHead,struct Task * task)221 static inline void osTaskListRemoveTask(struct TaskList *listHead, struct Task *task)
222 {
223     if (task && listHead) {
224         struct TaskList *cur = &task->list;
225         TaskIndex left_idx = cur->prev;
226         TaskIndex right_idx = cur->next;
227         struct TaskList *left =  left_idx == NO_NODE ? listHead : &mTaskPool.data[left_idx].list;
228         struct TaskList *right = right_idx == NO_NODE ? listHead : &mTaskPool.data[right_idx].list;
229         cur->prev = cur->next = NO_NODE;
230         left->next = right_idx;
231         right->prev = left_idx;
232     } else {
233         dumpTaskList(__func__, task, listHead);
234     }
235 }
236 
osTaskListAddTail(struct TaskList * listHead,struct Task * task)237 static inline void osTaskListAddTail(struct TaskList *listHead, struct Task *task)
238 {
239     if (task && listHead) {
240         struct TaskList *cur = &task->list;
241         TaskIndex last_idx = listHead->prev;
242         TaskIndex new_idx = osTaskIndex(task);
243         struct TaskList *last = last_idx == NO_NODE ? listHead : &mTaskPool.data[last_idx].list;
244         cur->prev = last_idx;
245         cur->next = NO_NODE;
246         last->next = new_idx;
247         listHead->prev = new_idx;
248     } else {
249         dumpTaskList(__func__, task, listHead);
250     }
251 }
252 
osAllocTask()253 static struct Task *osAllocTask()
254 {
255     struct Task *task = osTaskListPeekHead(&mFreeTasks);
256 
257     if (task) {
258         osTaskListRemoveTask(&mFreeTasks, task);
259         uint16_t tid = task->tid;
260         memset(task, 0, sizeof(*task));
261         task->tid = tid;
262     }
263 
264     return task;
265 }
266 
osFreeTask(struct Task * task)267 static void osFreeTask(struct Task *task)
268 {
269     if (task) {
270         task->flags = 0;
271         task->ioCount = 0;
272         osTaskListAddTail(&mFreeTasks, task);
273     }
274 }
275 
osRemoveTask(struct Task * task)276 static void osRemoveTask(struct Task *task)
277 {
278     osTaskListRemoveTask(&mTasks, task);
279 }
280 
osAddTask(struct Task * task)281 static void osAddTask(struct Task *task)
282 {
283     osTaskListAddTail(&mTasks, task);
284 }
285 
osTaskFindByTid(uint32_t tid)286 struct Task* osTaskFindByTid(uint32_t tid)
287 {
288     TaskIndex idx = TID_TO_TASK_IDX(tid);
289 
290     return idx < MAX_TASKS ? &mTaskPool.data[idx] : NULL;
291 }
292 
osTaskInit(struct Task * task)293 static inline bool osTaskInit(struct Task *task)
294 {
295     struct Task *preempted = osSetCurrentTask(task);
296     bool done = cpuAppInit(task->app, &task->platInfo, task->tid);
297     osSetCurrentTask(preempted);
298     return done;
299 }
300 
osTaskRelease(struct Task * task)301 static void osTaskRelease(struct Task *task)
302 {
303     uint32_t taskTid = task->tid;
304     uint32_t platErr, sensorErr;
305     int timErr, heapErr;
306     uint64_t appId;
307 
308     if (task->app)
309         appId = task->app->hdr.appId;
310     else
311         appId = 0;
312 
313     platErr = platFreeResources(taskTid); // HW resources cleanup (IRQ, DMA etc)
314     sensorErr = sensorFreeAll(taskTid);
315     timErr = timTimerCancelAll(taskTid);
316     heapErr = heapFreeAll(taskTid);
317 
318     if (platErr || sensorErr || timErr || heapErr)
319         osLog(LOG_WARN, "released app ID 0x%" PRIx64 "; plat:%08" PRIx32 " sensor:%08" PRIx32 " tim:%d heap:%d; TID %04" PRIX32 "\n", appId, platErr, sensorErr, timErr, heapErr, taskTid);
320     else
321         osLog(LOG_INFO, "released app ID 0x%" PRIx64 "; TID %04" PRIX32 "\n", appId, taskTid);
322 }
323 
osTaskEnd(struct Task * task)324 static inline void osTaskEnd(struct Task *task)
325 {
326     if (!osTaskTestFlags(task, FL_TASK_ABORTED)) {
327         struct Task *preempted = osSetCurrentTask(task);
328         cpuAppEnd(task->app, &task->platInfo);
329         osSetCurrentTask(preempted);
330     }
331 
332     // task was supposed to release it's resources,
333     // but we do our cleanup anyway
334     // NOTE: we don't need to unsubscribe from events
335     osTaskRelease(task);
336 }
337 
osTaskHandle(struct Task * task,uint16_t evtType,uint16_t fromTid,const void * evtData)338 static inline void osTaskHandle(struct Task *task, uint16_t evtType, uint16_t fromTid, const void* evtData)
339 {
340     struct Task *preempted = osSetCurrentTask(task);
341     cpuAppHandle(task->app, &task->platInfo,
342                  EVENT_WITH_ORIGIN(evtType, osTaskIsChre(task) ? fromTid : 0),
343                  evtData);
344     osSetCurrentTask(preempted);
345 }
346 
osTaskInvokeMessageFreeCallback(struct Task * task,void (* freeCallback)(void *,size_t),void * message,uint32_t messageSize)347 void osTaskInvokeMessageFreeCallback(struct Task *task, void (*freeCallback)(void *, size_t), void *message, uint32_t messageSize)
348 {
349     if (!task || !freeCallback)
350         return;
351     cpuAppInvoke(task->app, &task->platInfo, (void (*)(uintptr_t,uintptr_t))freeCallback, (uintptr_t)message, (uintptr_t)messageSize);
352 }
353 
osTaskInvokeEventFreeCallback(struct Task * task,void (* freeCallback)(uint16_t,void *),uint16_t event,void * data)354 void osTaskInvokeEventFreeCallback(struct Task *task, void (*freeCallback)(uint16_t, void *), uint16_t event, void *data)
355 {
356     if (!task || !freeCallback)
357         return;
358     cpuAppInvoke(task->app, &task->platInfo,
359                  (void (*)(uintptr_t,uintptr_t))freeCallback,
360                  (uintptr_t)event, (uintptr_t)data);
361 }
362 
osPrivateEvtFreeF(void * event)363 static void osPrivateEvtFreeF(void *event)
364 {
365     union SeosInternalSlabData *act = event;
366     uint16_t fromTid = act->privateEvt.fromTid;
367     struct Task *srcTask = osTaskFindByTid(fromTid);
368     TaggedPtr evtFreeInfo = act->privateEvt.evtFreeInfo;
369     uint32_t evtType = act->privateEvt.evtType;
370     void *evtData = act->privateEvt.evtData;
371 
372     slabAllocatorFree(mMiscInternalThingsSlab, event);
373 
374     if (!srcTask) {
375         osLog(LOG_ERROR, "ERROR: Failed to find task to free event: evtType=%08" PRIX32 "\n", evtType);
376         return;
377     }
378 
379     if (taggedPtrIsPtr(evtFreeInfo) && taggedPtrToPtr(evtFreeInfo)) {
380         if (osTaskIsChre(srcTask) && (evtType >> 16) == EVT_PRIVATE_CLASS_CHRE) {
381             osChreFreeEvent(fromTid,
382                             (void (*)(uint16_t, void *))taggedPtrToPtr(evtFreeInfo),
383                             evtType & EVT_MASK, evtData);
384         } else {
385             // this is for internal non-CHRE tasks, and CHRE tasks
386             // System may schedule non-CHRE events on behalf of CHRE app;
387             // this is the place we release them
388             struct Task *preempted = osSetCurrentTask(srcTask);
389             ((EventFreeF)taggedPtrToPtr(evtFreeInfo))(evtData);
390             osSetCurrentTask(preempted);
391         }
392     } else if (taggedPtrIsUint(evtFreeInfo)) {
393         // this is for external non-CHRE tasks
394         struct AppEventFreeData fd = {.evtType = evtType, .evtData = evtData};
395         osTaskHandle(srcTask, EVT_APP_FREE_EVT_DATA, OS_SYSTEM_TID, &fd);
396     }
397 
398     osTaskAddIoCount(srcTask, -1);
399 }
400 
handleEventFreeing(uint32_t evtType,void * evtData,TaggedPtr evtFreeData)401 static void handleEventFreeing(uint32_t evtType, void *evtData, TaggedPtr evtFreeData) // watch out, this is synchronous
402 {
403     struct Task *srcTask = osTaskFindByTid(EVENT_GET_ORIGIN(evtType));
404 
405     if (!srcTask) {
406         osLog(LOG_ERROR, "ERROR: Failed to find task to free event: evtType=%08" PRIX32 "\n", evtType);
407         return;
408     }
409 
410     // release non-CHRE event; we can't determine if this is CHRE or non-CHRE event, but
411     // this method is only called to release non-CHRE events, so we make use of that fact
412 
413     if (taggedPtrIsPtr(evtFreeData) && taggedPtrToPtr(evtFreeData)) {
414         // this is for internal non-CHRE tasks, and CHRE tasks
415         // System may schedule non-CHRE events on behalf of CHRE app;
416         // this is the place we release them
417         struct Task *preempted = osSetCurrentTask(srcTask);
418         ((EventFreeF)taggedPtrToPtr(evtFreeData))(evtData);
419         osSetCurrentTask(preempted);
420     } else if (taggedPtrIsUint(evtFreeData)) {
421         // this is for external non-CHRE tasks
422         struct AppEventFreeData fd = {.evtType = EVENT_GET_EVENT(evtType), .evtData = evtData};
423         osTaskHandle(srcTask, EVT_APP_FREE_EVT_DATA, OS_SYSTEM_TID, &fd);
424     }
425 
426     osTaskAddIoCount(srcTask, -1);
427 }
428 
osInit(void)429 static void osInit(void)
430 {
431     heapInit();
432     platInitialize();
433 
434     osLog(LOG_INFO, "SEOS Initializing\n");
435     cpuInitLate();
436 
437     /* create the queues */
438     if (!(mEvtsInternal = evtQueueAlloc(512, handleEventFreeing))) {
439         osLog(LOG_INFO, "events failed to init\n");
440         return;
441     }
442 
443     mMiscInternalThingsSlab = slabAllocatorNew(sizeof(union SeosInternalSlabData), alignof(union SeosInternalSlabData), 64 /* for now? */);
444     if (!mMiscInternalThingsSlab) {
445         osLog(LOG_INFO, "deferred actions list failed to init\n");
446         return;
447     }
448 }
449 
osTaskFindByAppID(uint64_t appID)450 static struct Task* osTaskFindByAppID(uint64_t appID)
451 {
452     struct Task *task;
453 
454     for_each_task(&mTasks, task) {
455         if (task->app && task->app->hdr.appId == appID)
456             return task;
457     }
458 
459     return NULL;
460 }
461 
osSegmentIteratorInit(struct SegmentIterator * it)462 void osSegmentIteratorInit(struct SegmentIterator *it)
463 {
464     uint32_t sz;
465     uint8_t *start = platGetSharedAreaInfo(&sz);
466 
467     it->shared    = (const struct Segment *)(start);
468     it->sharedEnd = (const struct Segment *)(start + sz);
469     it->seg       = NULL;
470 }
471 
osAppSegmentSetState(const struct AppHdr * app,uint32_t segState)472 bool osAppSegmentSetState(const struct AppHdr *app, uint32_t segState)
473 {
474     bool done;
475     struct Segment *seg = osGetSegment(app);
476     uint8_t state = segState;
477 
478     if (!seg)
479         return false;
480 
481     mpuAllowRamExecution(true);
482     mpuAllowRomWrite(true);
483     done = BL.blProgramShared(&seg->state, &state, sizeof(state), BL_FLASH_KEY1, BL_FLASH_KEY2);
484     mpuAllowRomWrite(false);
485     mpuAllowRamExecution(false);
486 
487     return done;
488 }
489 
osSegmentSetSize(struct Segment * seg,uint32_t size)490 bool osSegmentSetSize(struct Segment *seg, uint32_t size)
491 {
492     bool ret = true;
493 
494     if (!seg)
495         return false;
496 
497     if (size > SEG_SIZE_MAX) {
498         seg->state = SEG_ST_ERASED;
499         size = SEG_SIZE_MAX;
500         ret = false;
501     }
502     seg->size[0] = size;
503     seg->size[1] = size >> 8;
504     seg->size[2] = size >> 16;
505 
506     return ret;
507 }
508 
osSegmentGetEnd()509 struct Segment *osSegmentGetEnd()
510 {
511     uint32_t size;
512     uint8_t *start = platGetSharedAreaInfo(&size);
513     return (struct Segment *)(start + size);
514 }
515 
osSegmentGetFree()516 uint32_t osSegmentGetFree()
517 {
518     struct SegmentIterator it;
519     const struct Segment *storageSeg = NULL;
520 
521     osSegmentIteratorInit(&it);
522     while (osSegmentIteratorNext(&it)) {
523         if (osSegmentGetState(it.seg) == SEG_ST_EMPTY) {
524             storageSeg = it.seg;
525             break;
526         }
527     }
528     if (!storageSeg || storageSeg > it.sharedEnd)
529         return 0;
530 
531     return (uint8_t *)it.sharedEnd - (uint8_t *)storageSeg;
532 }
533 
osGetSegment(const struct AppHdr * app)534 struct Segment *osGetSegment(const struct AppHdr *app)
535 {
536     uint32_t size;
537     uint8_t *start = platGetSharedAreaInfo(&size);
538 
539     return (struct Segment *)((uint8_t*)app &&
540                               (uint8_t*)app >= start &&
541                               (uint8_t*)app < (start + size) ?
542                               (uint8_t*)app - sizeof(struct Segment) : NULL);
543 }
544 
osEraseShared()545 bool osEraseShared()
546 {
547     wdtDisableClk();
548     mpuAllowRamExecution(true);
549     mpuAllowRomWrite(true);
550     (void)BL.blEraseShared(BL_FLASH_KEY1, BL_FLASH_KEY2);
551     mpuAllowRomWrite(false);
552     mpuAllowRamExecution(false);
553     wdtEnableClk();
554     return true;
555 }
556 
osWriteShared(void * dest,const void * src,uint32_t len)557 bool osWriteShared(void *dest, const void *src, uint32_t len)
558 {
559     bool ret;
560 
561     mpuAllowRamExecution(true);
562     mpuAllowRomWrite(true);
563     ret = BL.blProgramShared(dest, src, len, BL_FLASH_KEY1, BL_FLASH_KEY2);
564     mpuAllowRomWrite(false);
565     mpuAllowRamExecution(false);
566 
567     if (!ret)
568         osLog(LOG_ERROR, "osWriteShared: blProgramShared return false\n");
569 
570     return ret;
571 }
572 
osAppSegmentCreate(uint32_t size)573 struct AppHdr *osAppSegmentCreate(uint32_t size)
574 {
575     struct SegmentIterator it;
576     const struct Segment *storageSeg = NULL;
577     struct AppHdr *app;
578 
579     osSegmentIteratorInit(&it);
580     while (osSegmentIteratorNext(&it)) {
581         if (osSegmentGetState(it.seg) == SEG_ST_EMPTY) {
582             storageSeg = it.seg;
583             break;
584         }
585     }
586     if (!storageSeg || osSegmentSizeGetNext(storageSeg, size) > it.sharedEnd)
587         return NULL;
588 
589     app = osSegmentGetData(storageSeg);
590     osAppSegmentSetState(app, SEG_ST_RESERVED);
591 
592     return app;
593 }
594 
osAppSegmentClose(struct AppHdr * app,uint32_t segDataSize,uint32_t segState)595 bool osAppSegmentClose(struct AppHdr *app, uint32_t segDataSize, uint32_t segState)
596 {
597     struct Segment seg;
598 
599     // this is enough for holding padding to uint32_t and the footer
600     uint8_t footer[sizeof(uint32_t) + FOOTER_SIZE];
601     int footerLen;
602     bool ret;
603     uint32_t totalSize;
604     uint8_t *start = platGetSharedAreaInfo(&totalSize);
605     uint8_t *end = start + totalSize;
606     int32_t fullSize = segDataSize + sizeof(seg); // without footer or padding
607     struct Segment *storageSeg = osGetSegment(app);
608 
609     // sanity check
610     if (segDataSize >= SEG_SIZE_MAX)
611         return false;
612 
613     // physical limits check
614     if (osSegmentSizeAlignedWithFooter(segDataSize) + sizeof(struct Segment) > totalSize)
615         return false;
616 
617     // available space check: we could truncate size, instead of disallowing it,
618     // but we know that we performed validation on the size before, in *Create call,
619     // and it was fine, so this must be a programming error, and so we fail.
620     // on a side note: size may grow or shrink compared to original estimate.
621     // typically it shrinks, since we skip some header info and padding, as well
622     // as signature blocks, but it is possible that at some point we may produce
623     // more data for some reason. At that time the logic here may need to change
624     if (osSegmentSizeGetNext(storageSeg, segDataSize) > (struct Segment*)end)
625         return false;
626 
627     seg.state = segState;
628     osSegmentSetSize(&seg, segDataSize);
629 
630     ret = osWriteShared((uint8_t*)storageSeg, (uint8_t*)&seg, sizeof(seg));
631 
632     footerLen = (-fullSize) & 3;
633     memset(footer, 0x00, footerLen);
634 
635     wdtDisableClk();
636     struct SegmentFooter segFooter = {
637         .crc = ~soft_crc32(storageSeg, fullSize, ~0),
638     };
639     wdtEnableClk();
640     memcpy(&footer[footerLen], &segFooter, sizeof(segFooter));
641     footerLen += sizeof(segFooter);
642 
643     if (ret && footerLen)
644         ret = osWriteShared((uint8_t*)storageSeg + fullSize, footer, footerLen);
645 
646     return ret;
647 }
648 
osAppWipeData(struct AppHdr * app)649 bool osAppWipeData(struct AppHdr *app)
650 {
651     struct Segment *seg = osGetSegment(app);
652     int32_t size = osSegmentGetSize(seg);
653     uint8_t *p = (uint8_t*)app;
654     uint32_t state = osSegmentGetState(seg);
655     uint8_t buf[256];
656     bool done = true;
657 
658     if (!seg || size == SEG_SIZE_INVALID || state == SEG_ST_EMPTY) {
659         osLog(LOG_ERROR, "%s: can't erase segment: app=%p; seg=%p"
660                          "; size=%" PRIu32
661                          "; state=%" PRIu32
662                          "\n",
663                          __func__, app, seg, size, state);
664         return false;
665     }
666 
667     size = osSegmentSizeAlignedWithFooter(size);
668 
669     memset(buf, 0, sizeof(buf));
670     while (size > 0) {
671         uint32_t flashSz = size > sizeof(buf) ? sizeof(buf) : size;
672         // keep trying to zero-out stuff even in case of intermittent failures.
673         // flash write may occasionally fail on some byte, but it is not good enough
674         // reason to not rewrite other bytes
675         bool res = osWriteShared(p, buf, flashSz);
676         done = done && res;
677         size -= flashSz;
678         p += flashSz;
679     }
680 
681     return done;
682 }
683 
osAppIsValid(const struct AppHdr * app)684 static inline bool osAppIsValid(const struct AppHdr *app)
685 {
686     return app->hdr.magic == APP_HDR_MAGIC &&
687            app->hdr.fwVer == APP_HDR_VER_CUR &&
688            (app->hdr.fwFlags & FL_APP_HDR_APPLICATION) != 0 &&
689            app->hdr.payInfoType == LAYOUT_APP;
690 }
691 
osExtAppIsValid(const struct AppHdr * app,uint32_t len)692 static bool osExtAppIsValid(const struct AppHdr *app, uint32_t len)
693 {
694     return  osAppIsValid(app) &&
695             len >= sizeof(*app) &&
696             osAppSegmentGetState(app) == SEG_ST_VALID &&
697             osAppSegmentCalcCrcResidue(app) == CRC_RESIDUE &&
698             !(app->hdr.fwFlags & FL_APP_HDR_INTERNAL);
699 }
700 
osIntAppIsValid(const struct AppHdr * app)701 static bool osIntAppIsValid(const struct AppHdr *app)
702 {
703     return  osAppIsValid(app) &&
704             osAppSegmentGetState(app) == SEG_STATE_INVALID &&
705             (app->hdr.fwFlags & FL_APP_HDR_INTERNAL) != 0;
706 }
707 
osExtAppErase(const struct AppHdr * app)708 static inline bool osExtAppErase(const struct AppHdr *app)
709 {
710     return osAppSegmentSetState(app, SEG_ST_ERASED);
711 }
712 
osLoadApp(const struct AppHdr * app)713 static struct Task *osLoadApp(const struct AppHdr *app) {
714     struct Task *task;
715 
716     task = osAllocTask();
717     if (!task) {
718         osLog(LOG_WARN, "External app id %016" PRIX64 " @ %p cannot be used as too many apps already exist.\n", app->hdr.appId, app);
719         return NULL;
720     }
721     task->app = app;
722     bool done = (app->hdr.fwFlags & FL_APP_HDR_INTERNAL) ?
723                 cpuInternalAppLoad(task->app, &task->platInfo) :
724                 cpuAppLoad(task->app, &task->platInfo);
725 
726     if (!done) {
727         osLog(LOG_WARN, "App @ %p ID %016" PRIX64 " failed to load\n", app, app->hdr.appId);
728         osFreeTask(task);
729         task = NULL;
730     }
731 
732     return task;
733 }
734 
osUnloadApp(struct Task * task)735 static void osUnloadApp(struct Task *task)
736 {
737     // this is called on task that has stopped running, or had never run
738     cpuAppUnload(task->app, &task->platInfo);
739     osFreeTask(task);
740 }
741 
osStartApp(const struct AppHdr * app)742 static bool osStartApp(const struct AppHdr *app)
743 {
744     bool done = false;
745     struct Task *task;
746 
747     if ((task = osLoadApp(app)) != NULL) {
748         task->subbedEvtListSz = MAX_EMBEDDED_EVT_SUBS;
749         task->subbedEvents = task->subbedEventsInt;
750         osTaskMakeNewTid(task);
751 
752         // print external NanoApp info to facilitate NanoApp debugging
753         if (!(task->app->hdr.fwFlags & FL_APP_HDR_INTERNAL))
754             osLog(LOG_INFO,
755                   "loaded app ID 0x%" PRIx64 " at flash base 0x%" PRIxPTR " ram base 0x%" PRIxPTR "; TID %04" PRIX16 "\n",
756                   task->app->hdr.appId, (uintptr_t) task->app, (uintptr_t) task->platInfo.data, task->tid);
757 
758         done = osTaskInit(task);
759 
760         if (!done) {
761             osLog(LOG_WARN, "App @ %p ID %016" PRIX64 " failed to init\n", task->app, task->app->hdr.appId);
762             osUnloadApp(task);
763         } else {
764             osAddTask(task);
765             (void)osEnqueueEvt(EVT_APP_BEGIN, task, NULL);
766         }
767     }
768 
769     return done;
770 }
771 
osStopTask(struct Task * task,bool abort)772 static bool osStopTask(struct Task *task, bool abort)
773 {
774     struct Task *preempted;
775 
776     if (!task)
777         return false;
778 
779     if (osTaskTestFlags(task, FL_TASK_STOPPED))
780         return true;
781 
782     preempted = osSetCurrentTask(mSystemTask);
783     osRemoveTask(task);
784     osTaskClrSetFlags(task, 0, FL_TASK_STOPPED);
785 
786     if (abort)
787         osTaskClrSetFlags(task, 0, FL_TASK_ABORTED);
788     else if (osTaskGetIoCount(task))
789         osTaskHandle(task, EVT_APP_STOP, OS_SYSTEM_TID, NULL);
790     osEnqueueEvt(EVT_APP_END, task, NULL);
791 
792     osSetCurrentTask(preempted);
793 
794     return true;
795 }
796 
osTaskAbort(struct Task * task)797 void osTaskAbort(struct Task *task)
798 {
799     osStopTask(task, true);
800 }
801 
matchAutoStart(const void * cookie,const struct AppHdr * app)802 static bool matchAutoStart(const void *cookie, const struct AppHdr *app)
803 {
804     bool match = (bool)cookie;
805 
806     if (app->hdr.fwFlags & FL_APP_HDR_CHRE) {
807         if (app->hdr.chreApiMajor == 0xFF && app->hdr.chreApiMinor == 0xFF)
808             return match;
809         else if ((app->hdr.chreApiMajor < 0x01) ||
810                  (app->hdr.chreApiMajor == 0x01 && app->hdr.chreApiMinor < 0x01))
811             return match;
812         else
813             return !match;
814     } else {
815         return match;
816     }
817 }
818 
matchAppId(const void * data,const struct AppHdr * app)819 static bool matchAppId(const void *data, const struct AppHdr *app)
820 {
821     uint64_t appId, vendor, seqId, curAppId;
822 
823     memcpy(&appId, data, sizeof(appId));
824     vendor = APP_ID_GET_VENDOR(appId);
825     seqId = APP_ID_GET_SEQ_ID(appId);
826     curAppId = app->hdr.appId;
827 
828     if ((vendor == APP_VENDOR_ANY || vendor == APP_ID_GET_VENDOR(curAppId)) &&
829         (seqId == APP_SEQ_ID_ANY || seqId == APP_ID_GET_SEQ_ID(curAppId))) {
830         return true;
831     } else {
832         return false;
833     }
834 }
835 
osExtAppFind(struct SegmentIterator * it,appMatchFunc func,const void * data)836 static bool osExtAppFind(struct SegmentIterator *it, appMatchFunc func, const void *data)
837 {
838     const struct AppHdr *app;
839     const struct Segment *seg;
840 
841     while (osSegmentIteratorNext(it)) {
842         seg = it->seg;
843         if (!seg)
844             break;
845         if (seg->state == SEG_ST_EMPTY)
846             break;
847         if (seg->state != SEG_ST_VALID)
848             continue;
849         app = osSegmentGetData(seg);
850         if (func(data, app))
851             return true;
852     }
853 
854     return false;
855 }
856 
osExtAppStopEraseApps(appMatchFunc func,const void * data,bool doErase)857 static uint32_t osExtAppStopEraseApps(appMatchFunc func, const void *data, bool doErase)
858 {
859     const struct AppHdr *app;
860     int32_t len;
861     struct SegmentIterator it;
862     uint32_t stopCount = 0;
863     uint32_t eraseCount = 0;
864     uint32_t appCount = 0;
865     uint32_t taskCount = 0;
866     struct MgmtStatus stat = { .value = 0 };
867     struct Task *task;
868 
869     osSegmentIteratorInit(&it);
870     while (osExtAppFind(&it, func, data)) {
871         app = osSegmentGetData(it.seg);
872         len = osSegmentGetSize(it.seg);
873         if (!osExtAppIsValid(app, len))
874             continue;
875         appCount++;
876         /* it is safe to erase a running app;
877          * erase merely sets a flag in the header,
878          * and app keeps running until it is stopped */
879         if (doErase && osExtAppErase(app))
880             eraseCount++;
881         task = osTaskFindByAppID(app->hdr.appId);
882         if (task) {
883             taskCount++;
884             if (osStopTask(task, false))
885                stopCount++;
886         }
887     }
888     SET_COUNTER(stat.app,   appCount);
889     SET_COUNTER(stat.task,  taskCount);
890     SET_COUNTER(stat.op,    stopCount);
891     SET_COUNTER(stat.erase, eraseCount);
892 
893     return stat.value;
894 }
895 
osExtAppStopAppsByAppId(uint64_t appId)896 uint32_t osExtAppStopAppsByAppId(uint64_t appId)
897 {
898     return osExtAppStopEraseApps(matchAppId, &appId, false);
899 }
900 
osExtAppEraseAppsByAppId(uint64_t appId)901 uint32_t osExtAppEraseAppsByAppId(uint64_t appId)
902 {
903     return osExtAppStopEraseApps(matchAppId, &appId, true);
904 }
905 
osScanExternal()906 static void osScanExternal()
907 {
908     struct SegmentIterator it;
909     osSegmentIteratorInit(&it);
910     while (osSegmentIteratorNext(&it)) {
911         switch (osSegmentGetState(it.seg)) {
912         case SEG_ST_EMPTY:
913             // everything looks good
914             osLog(LOG_INFO, "External area is good\n");
915             return;
916         case SEG_ST_ERASED:
917         case SEG_ST_VALID:
918             // this is valid stuff, ignore
919             break;
920         case SEG_ST_RESERVED:
921         default:
922             // something is wrong: erase everything
923             osLog(LOG_ERROR, "External area is damaged. Erasing\n");
924             osEraseShared();
925             return;
926         }
927     }
928 }
929 
osExtAppStartApps(appMatchFunc func,void * data)930 static uint32_t osExtAppStartApps(appMatchFunc func, void *data)
931 {
932     const struct AppHdr *app;
933     int32_t len;
934     struct SegmentIterator it;
935     struct SegmentIterator checkIt;
936     uint32_t startCount = 0;
937     uint32_t eraseCount = 0;
938     uint32_t appCount = 0;
939     uint32_t taskCount = 0;
940     struct MgmtStatus stat = { .value = 0 };
941 
942     osScanExternal();
943 
944     osSegmentIteratorInit(&it);
945     while (osExtAppFind(&it, func, data)) {
946         app = osSegmentGetData(it.seg);
947         len = osSegmentGetSize(it.seg);
948 
949         // skip erased or malformed apps
950         if (!osExtAppIsValid(app, len))
951             continue;
952 
953         appCount++;
954         checkIt = it;
955         // find the most recent copy
956         while (osExtAppFind(&checkIt, matchAppId, &app->hdr.appId)) {
957             if (osExtAppErase(app)) // erase the old one, so we skip it next time
958                 eraseCount++;
959             app = osSegmentGetData(checkIt.seg);
960         }
961 
962         if (osTaskFindByAppID(app->hdr.appId)) {
963             // this either the most recent external app with the same ID,
964             // or internal app with the same id; in both cases we do nothing
965             taskCount++;
966             continue;
967         }
968 
969         if (osStartApp(app))
970             startCount++;
971     }
972     SET_COUNTER(stat.app,   appCount);
973     SET_COUNTER(stat.task,  taskCount);
974     SET_COUNTER(stat.op,    startCount);
975     SET_COUNTER(stat.erase, eraseCount);
976 
977     return stat.value;
978 }
979 
osExtAppStartAppsByAppId(uint64_t appId)980 uint32_t osExtAppStartAppsByAppId(uint64_t appId)
981 {
982     return osExtAppStartApps(matchAppId, &appId);
983 }
984 
osStartTasks(void)985 static void osStartTasks(void)
986 {
987     const struct AppHdr *app;
988     uint32_t i, nApps;
989     struct Task* task;
990     uint32_t status = 0;
991     uint32_t taskCnt = 0;
992 
993     osLog(LOG_DEBUG, "Initializing task pool...\n");
994     list_init(&mTasks);
995     list_init(&mFreeTasks);
996     for (i = 0; i < MAX_TASKS; ++i) {
997         task = &mTaskPool.data[i];
998         list_init(&task->list);
999         osFreeTask(task);
1000     }
1001 
1002     mSystemTask = osAllocTask(); // this is a dummy task; holder of TID 0; all system code will run with TID 0
1003     osSetCurrentTask(mSystemTask);
1004     osLog(LOG_DEBUG, "System task is: %p\n", mSystemTask);
1005 
1006     /* first enum all internal apps, making sure to check for dupes */
1007     osLog(LOG_DEBUG, "Starting internal apps...\n");
1008     for (i = 0, app = platGetInternalAppList(&nApps); i < nApps; i++, app++) {
1009         if (!osIntAppIsValid(app)) {
1010             osLog(LOG_WARN, "Invalid internal app @ %p ID %016" PRIX64
1011                             "header version: %" PRIu16
1012                             "\n",
1013                             app, app->hdr.appId, app->hdr.fwVer);
1014             continue;
1015         }
1016 
1017         if (!(app->hdr.fwFlags & FL_APP_HDR_INTERNAL)) {
1018             osLog(LOG_WARN, "Internal app is not marked: [%p]: flags: 0x%04" PRIX16
1019                             "; ID: %016" PRIX64
1020                             "; ignored\n",
1021                             app, app->hdr.fwFlags, app->hdr.appId);
1022             continue;
1023         }
1024         if ((task = osTaskFindByAppID(app->hdr.appId))) {
1025             osLog(LOG_WARN, "Internal app ID %016" PRIX64
1026                             "@ %p attempting to update internal app @ %p; app @%p ignored.\n",
1027                             app->hdr.appId, app, task->app, app);
1028             continue;
1029         }
1030         if (osStartApp(app))
1031             taskCnt++;
1032     }
1033 
1034     osLog(LOG_DEBUG, "Starting external apps...\n");
1035     status = osExtAppStartApps(matchAutoStart, (void *)true);
1036     osLog(LOG_DEBUG, "Started %" PRIu32 " internal apps; EXT status: %08" PRIX32 "\n", taskCnt, status);
1037 }
1038 
osInternalEvtHandle(uint32_t evtType,void * evtData)1039 static void osInternalEvtHandle(uint32_t evtType, void *evtData)
1040 {
1041     union SeosInternalSlabData *da = (union SeosInternalSlabData*)evtData;
1042     struct Task *task, *ssTask;
1043     uint32_t i, j;
1044     uint16_t tid = EVENT_GET_ORIGIN(evtType);
1045     uint16_t evt = EVENT_GET_EVENT(evtType), newEvt;
1046     struct Task *srcTask = osTaskFindByTid(tid);
1047     struct Task *preempted = osSetCurrentTask(srcTask);
1048     struct AppEventStartStop ssMsg;
1049 
1050     switch (evt) {
1051     case EVT_SUBSCRIBE_TO_EVT:
1052     case EVT_UNSUBSCRIBE_TO_EVT:
1053         /* get task */
1054         task = osTaskFindByTid(da->evtSub.tid);
1055         if (!task)
1056             break;
1057 
1058         for (j = 0; j < da->evtSub.numEvts; j++) {
1059             /* find if subscribed to this evt */
1060             for (i = 0; i < task->subbedEvtCount && task->subbedEvents[i] != da->evtSub.evts[j]; i++);
1061 
1062             /* if unsub & found -> unsub */
1063             if (evt == EVT_UNSUBSCRIBE_TO_EVT && i != task->subbedEvtCount)
1064                 task->subbedEvents[i] = task->subbedEvents[--task->subbedEvtCount];
1065             /* if sub & not found -> sub */
1066             else if (evt == EVT_SUBSCRIBE_TO_EVT && i == task->subbedEvtCount) {
1067                 if (task->subbedEvtListSz == task->subbedEvtCount) { /* enlarge the list */
1068                     uint32_t newSz = (task->subbedEvtListSz * 3 + 1) / 2;
1069                     uint32_t *newList = heapAlloc(sizeof(uint32_t[newSz])); /* grow by 50% */
1070                     if (newList) {
1071                         memcpy(newList, task->subbedEvents, sizeof(uint32_t[task->subbedEvtListSz]));
1072                         if (task->subbedEvents != task->subbedEventsInt)
1073                             heapFree(task->subbedEvents);
1074                         task->subbedEvents = newList;
1075                         task->subbedEvtListSz = newSz;
1076                     }
1077                 }
1078                 if (task->subbedEvtListSz > task->subbedEvtCount) { /* have space ? */
1079                     task->subbedEvents[task->subbedEvtCount++] = da->evtSub.evts[j];
1080                 }
1081             }
1082         }
1083         break;
1084 
1085     case EVT_APP_BEGIN:
1086     case EVT_APP_END:
1087         ssTask = evtData;
1088         ssMsg.appId = ssTask->app->hdr.appId;
1089         ssMsg.version = ssTask->app->hdr.appVer;
1090         ssMsg.tid = ssTask->tid;
1091         if (evt == EVT_APP_BEGIN) {
1092             newEvt = EVT_APP_STARTED;
1093         } else {
1094             newEvt = EVT_APP_STOPPED;
1095             osTaskEnd(ssTask);
1096             osUnloadApp(ssTask);
1097         }
1098 
1099         /* send this event to all tasks who want it */
1100         for_each_task(&mTasks, task) {
1101             if (task != ssTask) {
1102                 for (i = 0; i < task->subbedEvtCount; i++) {
1103                     if (task->subbedEvents[i] == newEvt) {
1104                         osTaskHandle(task, newEvt, OS_SYSTEM_TID, &ssMsg);
1105                         break;
1106                     }
1107                 }
1108             }
1109         }
1110         break;
1111 
1112     case EVT_DEFERRED_CALLBACK:
1113         da->deferred.callback(da->deferred.cookie);
1114         break;
1115 
1116     case EVT_PRIVATE_EVT:
1117         task = osTaskFindByTid(da->privateEvt.toTid);
1118         evtType = da->privateEvt.evtType & EVT_MASK;
1119         evtData = da->privateEvt.evtData;
1120         if (task) {
1121             //private events cannot be retained
1122             TaggedPtr *tmp = mCurEvtEventFreeingInfo;
1123             mCurEvtEventFreeingInfo = NULL;
1124             osTaskHandle(task, evtType, da->privateEvt.fromTid, da->privateEvt.evtData);
1125             mCurEvtEventFreeingInfo = tmp;
1126         }
1127         break;
1128     }
1129     osSetCurrentTask(preempted);
1130 }
1131 
abort(void)1132 void abort(void)
1133 {
1134     /* this is necessary for va_* funcs... */
1135     osLog(LOG_ERROR, "Abort called");
1136     while(1);
1137 }
1138 
osRetainCurrentEvent(TaggedPtr * evtFreeingInfoP)1139 bool osRetainCurrentEvent(TaggedPtr *evtFreeingInfoP)
1140 {
1141     if (!mCurEvtEventFreeingInfo)
1142         return false;
1143 
1144     *evtFreeingInfoP = *mCurEvtEventFreeingInfo;
1145     mCurEvtEventFreeingInfo = NULL;
1146     return true;
1147 }
1148 
osFreeRetainedEvent(uint32_t evtType,void * evtData,TaggedPtr * evtFreeingInfoP)1149 void osFreeRetainedEvent(uint32_t evtType, void *evtData, TaggedPtr *evtFreeingInfoP)
1150 {
1151     //TODO: figure the way to calculate src tid here to pass to handleEventFreeing
1152     handleEventFreeing(evtType, evtData, *evtFreeingInfoP);
1153 }
1154 
osMainInit(void)1155 void osMainInit(void)
1156 {
1157     cpuInit();
1158     cpuIntsOff();
1159     osInit();
1160     timInit();
1161     sensorsInit();
1162     syscallInit();
1163     osApiExport(mMiscInternalThingsSlab);
1164     osChreApiExport();
1165     apIntInit();
1166     cpuIntsOn();
1167     wdtInit();
1168     osStartTasks();
1169 
1170     //broadcast app start to all already-loaded apps
1171     (void)osEnqueueEvt(EVT_APP_START, NULL, NULL);
1172 }
1173 
osMainDequeueLoop(void)1174 void osMainDequeueLoop(void)
1175 {
1176     TaggedPtr evtFreeingInfo;
1177     uint32_t evtType, j;
1178     void *evtData;
1179     struct Task *task;
1180     uint16_t tid, evt;
1181 
1182     /* get an event */
1183     if (!evtQueueDequeue(mEvtsInternal, &evtType, &evtData, &evtFreeingInfo, true))
1184         return;
1185 
1186     /* by default we free them when we're done with them */
1187     mCurEvtEventFreeingInfo = &evtFreeingInfo;
1188     tid = EVENT_GET_ORIGIN(evtType);
1189     evt = EVENT_GET_EVENT(evtType);
1190 
1191     if (evt < EVT_NO_FIRST_USER_EVENT) {
1192         /* handle deferred actions and other reserved events here */
1193         osInternalEvtHandle(evtType, evtData);
1194     } else {
1195         /* send this event to all tasks who want it */
1196         for_each_task(&mTasks, task) {
1197             for (j = 0; j < task->subbedEvtCount; j++) {
1198                 if (task->subbedEvents[j] == evt) {
1199                     osTaskHandle(task, evt, tid, evtData);
1200                     break;
1201                 }
1202             }
1203         }
1204     }
1205 
1206     /* free it */
1207     if (mCurEvtEventFreeingInfo)
1208         handleEventFreeing(evtType, evtData, evtFreeingInfo);
1209 
1210     /* avoid some possible errors */
1211     mCurEvtEventFreeingInfo = NULL;
1212 }
1213 
osMain(void)1214 void __attribute__((noreturn)) osMain(void)
1215 {
1216     osMainInit();
1217 
1218     while (true)
1219     {
1220         osMainDequeueLoop();
1221         platPeriodic();
1222     }
1223 }
1224 
osDeferredActionFreeF(void * event)1225 static void osDeferredActionFreeF(void* event)
1226 {
1227     slabAllocatorFree(mMiscInternalThingsSlab, event);
1228 }
1229 
osEventsSubscribeUnsubscribeV(bool sub,uint32_t numEvts,va_list ap)1230 static bool osEventsSubscribeUnsubscribeV(bool sub, uint32_t numEvts, va_list ap)
1231 {
1232     struct Task *task = osGetCurrentTask();
1233     union SeosInternalSlabData *act;
1234     int i;
1235 
1236     if (!sub && osTaskTestFlags(task, FL_TASK_STOPPED)) // stopping, so this is a no-op
1237         return true;
1238 
1239     if (numEvts > MAX_EVT_SUB_CNT)
1240         return false;
1241 
1242     act = slabAllocatorAlloc(mMiscInternalThingsSlab);
1243 
1244     if (!act)
1245         return false;
1246 
1247     act->evtSub.tid = task->tid;
1248     act->evtSub.numEvts = numEvts;
1249     for (i = 0; i < numEvts; i++)
1250         act->evtSub.evts[i] = va_arg(ap, uint32_t);
1251 
1252     return osEnqueueEvtOrFree(sub ? EVT_SUBSCRIBE_TO_EVT : EVT_UNSUBSCRIBE_TO_EVT, act, osDeferredActionFreeF);
1253 }
1254 
osEventsSubscribeUnsubscribe(bool sub,uint32_t numEvts,...)1255 static bool osEventsSubscribeUnsubscribe(bool sub, uint32_t numEvts, ...)
1256 {
1257     bool ret;
1258     va_list ap;
1259 
1260     va_start(ap, numEvts);
1261     ret = osEventsSubscribeUnsubscribeV(sub, numEvts, ap);
1262     va_end(ap);
1263 
1264     return ret;
1265 }
1266 
osEventSubscribe(uint32_t tid,uint32_t evtType)1267 bool osEventSubscribe(uint32_t tid, uint32_t evtType)
1268 {
1269     (void)tid;
1270     return osEventsSubscribeUnsubscribe(true, 1, evtType);
1271 }
1272 
osEventUnsubscribe(uint32_t tid,uint32_t evtType)1273 bool osEventUnsubscribe(uint32_t tid, uint32_t evtType)
1274 {
1275     (void)tid;
1276     return osEventsSubscribeUnsubscribe(false, 1, evtType);
1277 }
1278 
osEventsSubscribe(uint32_t numEvts,...)1279 bool osEventsSubscribe(uint32_t numEvts, ...)
1280 {
1281     bool ret;
1282     va_list ap;
1283 
1284     va_start(ap, numEvts);
1285     ret = osEventsSubscribeUnsubscribeV(true, numEvts, ap);
1286     va_end(ap);
1287 
1288     return ret;
1289 }
1290 
osEventsUnsubscribe(uint32_t numEvts,...)1291 bool osEventsUnsubscribe(uint32_t numEvts, ...)
1292 {
1293     bool ret;
1294     va_list ap;
1295 
1296     va_start(ap, numEvts);
1297     ret = osEventsSubscribeUnsubscribeV(false, numEvts, ap);
1298     va_end(ap);
1299 
1300     return ret;
1301 }
1302 
osEnqueueEvtCommon(uint32_t evt,void * evtData,TaggedPtr evtFreeInfo,bool urgent)1303 static bool osEnqueueEvtCommon(uint32_t evt, void *evtData, TaggedPtr evtFreeInfo, bool urgent)
1304 {
1305     struct Task *task = osGetCurrentTask();
1306     uint32_t evtType = EVENT_WITH_ORIGIN(evt, osGetCurrentTid());
1307 
1308     osTaskAddIoCount(task, 1);
1309 
1310     if (osTaskTestFlags(task, FL_TASK_STOPPED) ||
1311         !evtQueueEnqueue(mEvtsInternal, evtType, evtData, evtFreeInfo, urgent)) {
1312         osTaskAddIoCount(task, -1);
1313         return false;
1314     }
1315 
1316     return true;
1317 }
1318 
osRemovePendingEvents(bool (* match)(uint32_t evtType,const void * evtData,void * context),void * context)1319 void osRemovePendingEvents(bool (*match)(uint32_t evtType, const void *evtData, void *context), void *context)
1320 {
1321     evtQueueRemoveAllMatching(mEvtsInternal, match, context);
1322 }
1323 
osEnqueueEvt(uint32_t evtType,void * evtData,EventFreeF evtFreeF)1324 bool osEnqueueEvt(uint32_t evtType, void *evtData, EventFreeF evtFreeF)
1325 {
1326     return osEnqueueEvtCommon(evtType, evtData, taggedPtrMakeFromPtr(evtFreeF), false);
1327 }
1328 
osEnqueueEvtOrFree(uint32_t evtType,void * evtData,EventFreeF evtFreeF)1329 bool osEnqueueEvtOrFree(uint32_t evtType, void *evtData, EventFreeF evtFreeF)
1330 {
1331     bool success = osEnqueueEvt(evtType, evtData, evtFreeF);
1332 
1333     if (!success && evtFreeF)
1334         evtFreeF(evtData);
1335 
1336     return success;
1337 }
1338 
osEnqueueEvtAsApp(uint32_t evtType,void * evtData,bool freeData)1339 bool osEnqueueEvtAsApp(uint32_t evtType, void *evtData, bool freeData)
1340 {
1341     // compatibility with existing external apps
1342     if (evtType & EVENT_TYPE_BIT_DISCARDABLE_COMPAT)
1343         evtType |= EVENT_TYPE_BIT_DISCARDABLE;
1344 
1345     return osEnqueueEvtCommon(evtType, evtData, freeData ? taggedPtrMakeFromUint(osGetCurrentTid()) : taggedPtrMakeFromPtr(NULL), false);
1346 }
1347 
osDefer(OsDeferCbkF callback,void * cookie,bool urgent)1348 bool osDefer(OsDeferCbkF callback, void *cookie, bool urgent)
1349 {
1350     union SeosInternalSlabData *act = slabAllocatorAlloc(mMiscInternalThingsSlab);
1351     if (!act)
1352             return false;
1353 
1354     act->deferred.callback = callback;
1355     act->deferred.cookie = cookie;
1356 
1357     if (osEnqueueEvtCommon(EVT_DEFERRED_CALLBACK, act, taggedPtrMakeFromPtr(osDeferredActionFreeF), urgent))
1358         return true;
1359 
1360     slabAllocatorFree(mMiscInternalThingsSlab, act);
1361     return false;
1362 }
1363 
osEnqueuePrivateEvtEx(uint32_t evtType,void * evtData,TaggedPtr evtFreeInfo,uint32_t toTid)1364 static bool osEnqueuePrivateEvtEx(uint32_t evtType, void *evtData, TaggedPtr evtFreeInfo, uint32_t toTid)
1365 {
1366     union SeosInternalSlabData *act = slabAllocatorAlloc(mMiscInternalThingsSlab);
1367     bool result;
1368 
1369     if (!act) {
1370         osLog(LOG_ERROR, "[seos] ERROR: osEnqueuePrivateEvtEx: call to slabAllocatorAlloc() failed\n");
1371         return false;
1372     }
1373     struct Task *task = osGetCurrentTask();
1374     osTaskAddIoCount(task, 1);
1375 
1376     act->privateEvt.evtType = evtType;
1377     act->privateEvt.evtData = evtData;
1378     act->privateEvt.evtFreeInfo = evtFreeInfo;
1379     act->privateEvt.fromTid = task->tid;
1380     act->privateEvt.toTid = toTid;
1381 
1382     osSetCurrentTask(mSystemTask);
1383     result = osEnqueueEvtOrFree(EVT_PRIVATE_EVT, act, osPrivateEvtFreeF);
1384     osSetCurrentTask(task);
1385     return result;
1386 }
1387 
1388 // only called to send events for CHRE apps
osEnqueuePrivateEvtNew(uint16_t evtType,void * evtData,void (* evtFreeCallback)(uint16_t evtType,void * evtData),uint32_t toTid)1389 bool osEnqueuePrivateEvtNew(uint16_t evtType, void *evtData,
1390                                    void (*evtFreeCallback)(uint16_t evtType, void *evtData),
1391                                    uint32_t toTid)
1392 {
1393     if (!osEnqueuePrivateEvtEx(evtType | (EVT_PRIVATE_CLASS_CHRE << 16), evtData,
1394                                taggedPtrMakeFromPtr(evtFreeCallback), toTid)) {
1395         osChreFreeEvent(osGetCurrentTid(), evtFreeCallback, evtType, evtData);
1396         return false;
1397     }
1398     return true;
1399 }
1400 
osEnqueuePrivateEvt(uint32_t evtType,void * evtData,EventFreeF evtFreeF,uint32_t toTid)1401 bool osEnqueuePrivateEvt(uint32_t evtType, void *evtData, EventFreeF evtFreeF, uint32_t toTid)
1402 {
1403     return osEnqueuePrivateEvtEx(evtType & EVT_MASK, evtData, taggedPtrMakeFromPtr(evtFreeF), toTid);
1404 }
1405 
osEnqueuePrivateEvtAsApp(uint32_t evtType,void * evtData,uint32_t toTid)1406 bool osEnqueuePrivateEvtAsApp(uint32_t evtType, void *evtData, uint32_t toTid)
1407 {
1408     return osEnqueuePrivateEvtEx(evtType & EVT_MASK, evtData, taggedPtrMakeFromUint(osGetCurrentTid()), toTid);
1409 }
1410 
osTidById(const uint64_t * appId,uint32_t * tid)1411 bool osTidById(const uint64_t *appId, uint32_t *tid)
1412 {
1413     struct Task *task;
1414 
1415     for_each_task(&mTasks, task) {
1416         if (task->app && !memcmp(&task->app->hdr.appId, appId, sizeof(*appId))) {
1417             *tid = task->tid;
1418             return true;
1419         }
1420     }
1421 
1422     return false;
1423 }
1424 
osAppInfoById(uint64_t appId,uint32_t * appIdx,uint32_t * appVer,uint32_t * appSize)1425 bool osAppInfoById(uint64_t appId, uint32_t *appIdx, uint32_t *appVer, uint32_t *appSize)
1426 {
1427     uint32_t i = 0;
1428     struct Task *task;
1429 
1430     for_each_task(&mTasks, task) {
1431         const struct AppHdr *app = task->app;
1432         if (app && app->hdr.appId == appId) {
1433             *appIdx = i;
1434             *appVer = app->hdr.appVer;
1435             *appSize = app->sect.rel_end;
1436             return true;
1437         }
1438         i++;
1439     }
1440 
1441     return false;
1442 }
1443 
osAppInfoByIndex(uint32_t appIdx,uint64_t * appId,uint32_t * appVer,uint32_t * appSize)1444 bool osAppInfoByIndex(uint32_t appIdx, uint64_t *appId, uint32_t *appVer, uint32_t *appSize)
1445 {
1446     struct Task *task;
1447     int i = 0;
1448 
1449     for_each_task(&mTasks, task) {
1450         if (i != appIdx) {
1451             ++i;
1452         } else {
1453             const struct AppHdr *app = task->app;
1454             *appId = app->hdr.appId;
1455             *appVer = app->hdr.appVer;
1456             *appSize = app->sect.rel_end;
1457             return true;
1458         }
1459     }
1460 
1461     return false;
1462 }
1463 
osExtAppInfoByIndex(uint32_t appIdx,uint64_t * appId,uint32_t * appVer,uint32_t * appSize)1464 bool osExtAppInfoByIndex(uint32_t appIdx, uint64_t *appId, uint32_t *appVer, uint32_t *appSize)
1465 {
1466     struct Task *task;
1467     int i = 0;
1468 
1469     for_each_task(&mTasks, task) {
1470         const struct AppHdr *app = task->app;
1471         if (!(app->hdr.fwFlags & FL_APP_HDR_INTERNAL)) {
1472             if (i != appIdx) {
1473                 ++i;
1474             } else {
1475                 *appId = app->hdr.appId;
1476                 *appVer = app->hdr.appVer;
1477                 *appSize = app->sect.rel_end;
1478                 return true;
1479             }
1480         }
1481     }
1482 
1483     return false;
1484 }
1485 
osLogv(char clevel,uint32_t flags,const char * str,va_list vl)1486 void osLogv(char clevel, uint32_t flags, const char *str, va_list vl)
1487 {
1488     void *userData = platLogAllocUserData();
1489 
1490     platLogPutcharF(userData, clevel);
1491     cvprintf(platLogPutcharF, flags, userData, str, vl);
1492 
1493     platLogFlush(userData);
1494 }
1495 
osLog(enum LogLevel level,const char * str,...)1496 void osLog(enum LogLevel level, const char *str, ...)
1497 {
1498     va_list vl;
1499 
1500     va_start(vl, str);
1501     osLogv((char)level, 0, str, vl);
1502     va_end(vl);
1503 }
1504 
1505 
1506 
1507 
1508 //Google's public key for Google's apps' signing
1509 const uint8_t __attribute__ ((section (".pubkeys"))) _RSA_KEY_GOOGLE[] = {
1510     0xd9, 0xcd, 0x83, 0xae, 0xb5, 0x9e, 0xe4, 0x63, 0xf1, 0x4c, 0x26, 0x6a, 0x1c, 0xeb, 0x4c, 0x12,
1511     0x5b, 0xa6, 0x71, 0x7f, 0xa2, 0x4e, 0x7b, 0xa2, 0xee, 0x02, 0x86, 0xfc, 0x0d, 0x31, 0x26, 0x74,
1512     0x1e, 0x9c, 0x41, 0x43, 0xba, 0x16, 0xe9, 0x23, 0x4d, 0xfc, 0xc4, 0xca, 0xcc, 0xd5, 0x27, 0x2f,
1513     0x16, 0x4c, 0xe2, 0x85, 0x39, 0xb3, 0x0b, 0xcb, 0x73, 0xb6, 0x56, 0xc2, 0x98, 0x83, 0xf6, 0xfa,
1514     0x7a, 0x6e, 0xa0, 0x9a, 0xcc, 0x83, 0x97, 0x9d, 0xde, 0x89, 0xb2, 0xa3, 0x05, 0x46, 0x0c, 0x12,
1515     0xae, 0x01, 0xf8, 0x0c, 0xf5, 0x39, 0x32, 0xe5, 0x94, 0xb9, 0xa0, 0x8f, 0x19, 0xe4, 0x39, 0x54,
1516     0xad, 0xdb, 0x81, 0x60, 0x74, 0x63, 0xd5, 0x80, 0x3b, 0xd2, 0x88, 0xf4, 0xcb, 0x6b, 0x47, 0x28,
1517     0x80, 0xb0, 0xd1, 0x89, 0x6d, 0xd9, 0x62, 0x88, 0x81, 0xd6, 0xc0, 0x13, 0x88, 0x91, 0xfb, 0x7d,
1518     0xa3, 0x7f, 0xa5, 0x40, 0x12, 0xfb, 0x77, 0x77, 0x4c, 0x98, 0xe4, 0xd3, 0x62, 0x39, 0xcc, 0x63,
1519     0x34, 0x76, 0xb9, 0x12, 0x67, 0xfe, 0x83, 0x23, 0x5d, 0x40, 0x6b, 0x77, 0x93, 0xd6, 0xc0, 0x86,
1520     0x6c, 0x03, 0x14, 0xdf, 0x78, 0x2d, 0xe0, 0x9b, 0x5e, 0x05, 0xf0, 0x93, 0xbd, 0x03, 0x1d, 0x17,
1521     0x56, 0x88, 0x58, 0x25, 0xa6, 0xae, 0x63, 0xd2, 0x01, 0x43, 0xbb, 0x7e, 0x7a, 0xa5, 0x62, 0xdf,
1522     0x8a, 0x31, 0xbd, 0x24, 0x1b, 0x1b, 0xeb, 0xfe, 0xdf, 0xd1, 0x31, 0x61, 0x4a, 0xfa, 0xdd, 0x6e,
1523     0x62, 0x0c, 0xa9, 0xcd, 0x08, 0x0c, 0xa1, 0x1b, 0xe7, 0xf2, 0xed, 0x36, 0x22, 0xd0, 0x5d, 0x80,
1524     0x78, 0xeb, 0x6f, 0x5a, 0x58, 0x18, 0xb5, 0xaf, 0x82, 0x77, 0x4c, 0x95, 0xce, 0xc6, 0x4d, 0xda,
1525     0xca, 0xef, 0x68, 0xa6, 0x6d, 0x71, 0x4d, 0xf1, 0x14, 0xaf, 0x68, 0x25, 0xb8, 0xf3, 0xff, 0xbe,
1526 };
1527 
1528 
1529 #ifdef DEBUG
1530 
1531 //debug key whose privatekey is checked in as misc/debug.privkey
1532 const uint8_t __attribute__ ((section (".pubkeys"))) _RSA_KEY_GOOGLE_DEBUG[] = {
1533     0x2d, 0xff, 0xa6, 0xb5, 0x65, 0x87, 0xbe, 0x61, 0xd1, 0xe1, 0x67, 0x10, 0xa1, 0x9b, 0xc6, 0xca,
1534     0xc8, 0xb1, 0xf0, 0xaa, 0x88, 0x60, 0x9f, 0xa1, 0x00, 0xa1, 0x41, 0x9a, 0xd8, 0xb4, 0xd1, 0x74,
1535     0x9f, 0x23, 0x28, 0x0d, 0xc2, 0xc4, 0x37, 0x15, 0xb1, 0x4a, 0x80, 0xca, 0xab, 0xb9, 0xba, 0x09,
1536     0x7d, 0xf8, 0x44, 0xd6, 0xa2, 0x72, 0x28, 0x12, 0x91, 0xf6, 0xa5, 0xea, 0xbd, 0xf8, 0x81, 0x6b,
1537     0xd2, 0x3c, 0x50, 0xa2, 0xc6, 0x19, 0x54, 0x48, 0x45, 0x8d, 0x92, 0xac, 0x01, 0xda, 0x14, 0x32,
1538     0xdb, 0x05, 0x82, 0x06, 0x30, 0x25, 0x09, 0x7f, 0x5a, 0xbb, 0x86, 0x64, 0x70, 0x98, 0x64, 0x1e,
1539     0xe6, 0xca, 0x1d, 0xc1, 0xcb, 0xb6, 0x23, 0xd2, 0x62, 0x00, 0x46, 0x97, 0xd5, 0xcc, 0xe6, 0x36,
1540     0x72, 0xec, 0x2e, 0x43, 0x1f, 0x0a, 0xaf, 0xf2, 0x51, 0xe1, 0xcd, 0xd2, 0x98, 0x5d, 0x7b, 0x64,
1541     0xeb, 0xd1, 0x35, 0x4d, 0x59, 0x13, 0x82, 0x6c, 0xbd, 0xc4, 0xa2, 0xfc, 0xad, 0x64, 0x73, 0xe2,
1542     0x71, 0xb5, 0xf4, 0x45, 0x53, 0x6b, 0xc3, 0x56, 0xb9, 0x8b, 0x3d, 0xeb, 0x00, 0x48, 0x6e, 0x29,
1543     0xb1, 0xb4, 0x8e, 0x2e, 0x43, 0x39, 0xef, 0x45, 0xa0, 0xb8, 0x8b, 0x5f, 0x80, 0xb5, 0x0c, 0xc3,
1544     0x03, 0xe3, 0xda, 0x51, 0xdc, 0xec, 0x80, 0x2c, 0x0c, 0xdc, 0xe2, 0x71, 0x0a, 0x14, 0x4f, 0x2c,
1545     0x22, 0x2b, 0x0e, 0xd1, 0x8b, 0x8f, 0x93, 0xd2, 0xf3, 0xec, 0x3a, 0x5a, 0x1c, 0xba, 0x80, 0x54,
1546     0x23, 0x7f, 0xb0, 0x54, 0x8b, 0xe3, 0x98, 0x22, 0xbb, 0x4b, 0xd0, 0x29, 0x5f, 0xce, 0xf2, 0xaa,
1547     0x99, 0x89, 0xf2, 0xb7, 0x5d, 0x8d, 0xb2, 0x72, 0x0b, 0x52, 0x02, 0xb8, 0xa4, 0x37, 0xa0, 0x3b,
1548     0xfe, 0x0a, 0xbc, 0xb3, 0xb3, 0xed, 0x8f, 0x8c, 0x42, 0x59, 0xbe, 0x4e, 0x31, 0xed, 0x11, 0x9b,
1549 };
1550 
1551 #endif
1552