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