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