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 64 static inline void list_init(struct TaskList *l) 65 { 66 l->prev = l->next = NO_NODE; 67 } 68 69 struct Task *osGetCurrentTask() 70 { 71 return mCurrentTask; 72 } 73 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 88 static inline bool osTaskTestFlags(struct Task *task, uint32_t mask) 89 { 90 return (atomicReadByte(&task->flags) & mask) != 0; 91 } 92 93 bool osAppIsChre(uint16_t tid) 94 { 95 struct Task *task = osTaskFindByTid(tid); 96 97 return task && osTaskIsChre(task); 98 } 99 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 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 119 static inline uint32_t osTaskGetIoCount(struct Task *task) 120 { 121 return atomicReadByte(&task->ioCount); 122 } 123 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 131 static inline struct Task *osTaskByIdx(size_t idx) 132 { 133 return idx >= MAX_TASKS ? NULL : &mTaskPool.data[idx]; 134 } 135 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 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 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 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 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 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 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 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 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 266 static void osRemoveTask(struct Task *task) 267 { 268 osTaskListRemoveTask(&mTasks, task); 269 } 270 271 static void osAddTask(struct Task *task) 272 { 273 osTaskListAddTail(&mTasks, task); 274 } 275 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 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 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 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 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 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 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 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 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 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 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 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 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 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 487 struct Segment *osSegmentGetEnd() 488 { 489 uint32_t size; 490 uint8_t *start = platGetSharedAreaInfo(&size); 491 return (struct Segment *)(start + size); 492 } 493 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 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 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 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 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 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 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 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 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 668 static inline bool osExtAppErase(const struct AppHdr *app) 669 { 670 return osAppSegmentSetState(app, SEG_ST_ERASED); 671 } 672 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 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 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 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 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 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 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 827 uint32_t osExtAppStopApps(uint64_t appId) 828 { 829 return osExtAppStopEraseApps(appId, false); 830 } 831 832 uint32_t osExtAppEraseApps(uint64_t appId) 833 { 834 return osExtAppStopEraseApps(appId, true); 835 } 836 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 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 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 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 1036 void abort(void) 1037 { 1038 /* this is necessary for va_* funcs... */ 1039 osLog(LOG_ERROR, "Abort called"); 1040 while(1); 1041 } 1042 1043 bool osRetainCurrentEvent(TaggedPtr *evtFreeingInfoP) 1044 { 1045 if (!mCurEvtEventFreeingInfo) 1046 return false; 1047 1048 *evtFreeingInfoP = *mCurEvtEventFreeingInfo; 1049 mCurEvtEventFreeingInfo = NULL; 1050 return true; 1051 } 1052 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 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 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 1118 void __attribute__((noreturn)) osMain(void) 1119 { 1120 osMainInit(); 1121 1122 while (true) 1123 { 1124 osMainDequeueLoop(); 1125 platPeriodic(); 1126 } 1127 } 1128 1129 static void osDeferredActionFreeF(void* event) 1130 { 1131 slabAllocatorFree(mMiscInternalThingsSlab, event); 1132 } 1133 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 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 1162 bool osEventSubscribe(uint32_t tid, uint32_t evtType) 1163 { 1164 (void)tid; 1165 return osEventsSubscribeUnsubscribe(true, 1, evtType); 1166 } 1167 1168 bool osEventUnsubscribe(uint32_t tid, uint32_t evtType) 1169 { 1170 (void)tid; 1171 return osEventsSubscribeUnsubscribe(false, 1, evtType); 1172 } 1173 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 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 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 1218 void osRemovePendingEvents(bool (*match)(uint32_t evtType, const void *evtData, void *context), void *context) 1219 { 1220 evtQueueRemoveAllMatching(mEvtsInternal, match, context); 1221 } 1222 1223 bool osEnqueueEvt(uint32_t evtType, void *evtData, EventFreeF evtFreeF) 1224 { 1225 return osEnqueueEvtCommon(evtType, evtData, taggedPtrMakeFromPtr(evtFreeF), false); 1226 } 1227 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 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 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 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 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 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 1305 bool osEnqueuePrivateEvtAsApp(uint32_t evtType, void *evtData, uint32_t toTid) 1306 { 1307 return osEnqueuePrivateEvtEx(evtType & EVT_MASK, evtData, taggedPtrMakeFromUint(osGetCurrentTid()), toTid); 1308 } 1309 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 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 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 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 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