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