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 <string.h> 19 #include <stdint.h> 20 #include <sys/endian.h> 21 22 #include <variant/variant.h> 23 #include <eventnums.h> 24 25 #include <plat/taggedPtr.h> 26 #include <plat/plat.h> 27 #include <plat/wdt.h> 28 29 #include <nanohub/crc.h> 30 #include <nanohub/rsa.h> 31 #include <nanohub/nanohub.h> 32 33 #include <bl.h> 34 #include <atomicBitset.h> 35 #include <atomic.h> 36 #include <hostIntf.h> 37 #include <hostIntf_priv.h> 38 #include <nanohubCommand.h> 39 #include <nanohubPacket.h> 40 #include <eeData.h> 41 #include <seos.h> 42 #include <util.h> 43 #include <mpu.h> 44 #include <heap.h> 45 #include <slab.h> 46 #include <sensType.h> 47 #include <timer.h> 48 #include <appSec.h> 49 #include <cpu.h> 50 #include <cpu/cpuMath.h> 51 #include <algos/ap_hub_sync.h> 52 53 #define NANOHUB_COMMAND(_reason, _fastHandler, _handler, _minReqType, _maxReqType) \ 54 { .reason = _reason, .fastHandler = _fastHandler, .handler = _handler, \ 55 .minDataLen = sizeof(_minReqType), .maxDataLen = sizeof(_maxReqType) } 56 57 #define NANOHUB_HAL_COMMAND(_msg, _handler) \ 58 { .msg = _msg, .handler = _handler } 59 60 // maximum number of bytes to feed into appSecRxData at once 61 // The bigger the number, the more time we block other event processing 62 // appSecRxData only feeds 16 bytes at a time into writeCbk, so large 63 // numbers don't buy us that much 64 #define MAX_APP_SEC_RX_DATA_LEN 64 65 66 #define REQUIRE_SIGNED_IMAGE true 67 #define DEBUG_APHUB_TIME_SYNC false 68 69 #if DEBUG_APHUB_TIME_SYNC 70 static void syncDebugAdd(uint64_t, uint64_t); 71 #endif 72 73 struct DownloadState 74 { 75 struct AppSecState *appSecState; 76 uint32_t size; // document size, as reported by client 77 uint32_t srcOffset; // bytes received from client 78 uint32_t dstOffset; // bytes sent to flash 79 struct AppHdr *start; // start of flash segment, where to write 80 uint32_t crc; // document CRC-32, as reported by client 81 uint32_t srcCrc; // current state of CRC-32 we generate from input 82 uint8_t data[NANOHUB_PACKET_PAYLOAD_MAX]; 83 uint8_t len; 84 uint8_t lenLeft; 85 uint8_t chunkReply; 86 bool erase; 87 bool eraseScheduled; 88 }; 89 90 static struct DownloadState *mDownloadState; 91 static AppSecErr mAppSecStatus; 92 static struct SlabAllocator *mEventSlab; 93 static struct HostIntfDataBuffer mTxCurr, mTxNext; 94 static uint8_t mTxCurrLength, mTxNextLength; 95 static uint8_t mPrefetchActive, mPrefetchTx; 96 static uint32_t mTxWakeCnt[2]; 97 static struct ApHubSync mTimeSync; 98 99 static inline bool isSensorEvent(uint32_t evtType) 100 { 101 return evtType > EVT_NO_FIRST_SENSOR_EVENT && evtType <= EVT_NO_FIRST_SENSOR_EVENT + SENS_TYPE_LAST_USER; 102 } 103 104 static void slabFree(void *ptr) 105 { 106 slabAllocatorFree(mEventSlab, ptr); 107 } 108 109 void nanohubInitCommand(void) 110 { 111 mEventSlab = slabAllocatorNew(NANOHUB_PACKET_PAYLOAD_MAX-sizeof(__le32), 4, 2); 112 } 113 114 static inline uint64_t unaligned_u64(uint64_t *val) { 115 uint64_t local; 116 memcpy(&local, val, sizeof(local)); 117 return local; 118 } 119 120 static inline uint32_t unaligned_u32(uint32_t *val) { 121 uint32_t local; 122 memcpy(&local, val, sizeof(local)); 123 return local; 124 } 125 126 static uint32_t getOsHwVersion(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 127 { 128 struct NanohubOsHwVersionsResponse *resp = tx; 129 resp->hwType = htole16(platHwType()); 130 resp->hwVer = htole16(platHwVer()); 131 resp->blVer = htole16(platBlVer()); 132 resp->osVer = htole16(OS_VER); 133 resp->variantVer = htole32(VARIANT_VER); 134 135 return sizeof(*resp); 136 } 137 138 static uint32_t getAppVersion(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 139 { 140 struct NanohubAppVersionsRequest *req = rx; 141 struct NanohubAppVersionsResponse *resp = tx; 142 uint32_t appIdx, appVer, appSize; 143 144 if (osAppInfoById(le64toh(unaligned_u64(&req->appId)), &appIdx, &appVer, &appSize)) { 145 resp->appVer = htole32(appVer); 146 return sizeof(*resp); 147 } 148 149 return 0; 150 } 151 152 static uint32_t queryAppInfo(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 153 { 154 struct NanohubAppInfoRequest *req = rx; 155 struct NanohubAppInfoResponse *resp = tx; 156 uint64_t appId; 157 uint32_t appVer, appSize; 158 159 if (osAppInfoByIndex(le32toh(unaligned_u32(&req->appIdx)), &appId, &appVer, &appSize)) { 160 resp->appId = htole64(appId); 161 resp->appVer = htole32(appVer); 162 resp->appSize = htole32(appSize); 163 return sizeof(*resp); 164 } 165 166 return 0; 167 } 168 169 static AppSecErr writeCbk(const void *data, uint32_t len) 170 { 171 AppSecErr ret = APP_SEC_BAD; 172 173 if (osWriteShared((uint8_t*)(mDownloadState->start) + mDownloadState->dstOffset, data, len)) { 174 ret = APP_SEC_NO_ERROR; 175 mDownloadState->dstOffset += len; 176 } 177 178 return ret; 179 } 180 181 static AppSecErr pubKeyFindCbk(const uint32_t *gotKey, bool *foundP) 182 { 183 const uint32_t *ptr; 184 uint32_t numKeys, i; 185 186 *foundP = false; 187 ptr = BL.blGetPubKeysInfo(&numKeys); 188 for (i = 0; ptr && i < numKeys; i++, ptr += RSA_LIMBS) { 189 if (!memcmp(gotKey, ptr, RSA_BYTES)) { 190 *foundP = true; 191 break; 192 } 193 } 194 195 return APP_SEC_NO_ERROR; 196 } 197 198 static AppSecErr osSecretKeyLookup(uint64_t keyId, void *keyBuf) 199 { 200 struct SeosEedataEncrKeyData kd; 201 void *state = NULL; 202 203 while(1) { 204 uint32_t sz = sizeof(struct SeosEedataEncrKeyData); 205 206 if (!eeDataGetAllVersions(EE_DATA_NAME_ENCR_KEY, &kd, &sz, &state)) 207 break; 208 209 if (sz == sizeof(struct SeosEedataEncrKeyData) && kd.keyID == keyId) { 210 if (keyBuf) 211 memcpy(keyBuf, kd.key, sizeof(kd.key)); 212 return APP_SEC_NO_ERROR; 213 } 214 } 215 216 return APP_SEC_KEY_NOT_FOUND; 217 } 218 219 static AppSecErr osSecretKeyDelete(uint64_t keyId) 220 { 221 struct SeosEedataEncrKeyData kd; 222 void *state = NULL; 223 bool good = true; 224 int count = 0; 225 226 while(1) { 227 uint32_t sz = sizeof(struct SeosEedataEncrKeyData); 228 void *addr = eeDataGetAllVersions(EE_DATA_NAME_ENCR_KEY, &kd, &sz, &state); 229 230 if (!addr) 231 break; 232 233 if (sz == sizeof(kd) && kd.keyID == keyId) { 234 good = eeDataEraseOldVersion(EE_DATA_NAME_ENCR_KEY, addr) && good; 235 count++; 236 } 237 } 238 239 return count == 0 ? APP_SEC_KEY_NOT_FOUND : good ? APP_SEC_NO_ERROR : APP_SEC_BAD; 240 } 241 242 static AppSecErr osSecretKeyAdd(uint64_t keyId, void *keyBuf) 243 { 244 struct SeosEedataEncrKeyData kd; 245 246 // do not add key if it already exists 247 if (osSecretKeyLookup(keyId, NULL) != APP_SEC_KEY_NOT_FOUND) 248 return APP_SEC_BAD; 249 250 memcpy(&kd.key, keyBuf, 32); 251 kd.keyID = keyId; 252 253 return eeDataSet(EE_DATA_NAME_ENCR_KEY, &kd, sizeof(kd)) ? APP_SEC_NO_ERROR : APP_SEC_BAD; 254 } 255 256 static void freeDownloadState() 257 { 258 if (mDownloadState->appSecState) 259 appSecDeinit(mDownloadState->appSecState); 260 heapFree(mDownloadState); 261 mDownloadState = NULL; 262 } 263 264 static void resetDownloadState(bool initial) 265 { 266 bool doCreate = true; 267 268 mAppSecStatus = APP_SEC_NO_ERROR; 269 if (mDownloadState->appSecState) 270 appSecDeinit(mDownloadState->appSecState); 271 mDownloadState->appSecState = appSecInit(writeCbk, pubKeyFindCbk, osSecretKeyLookup, REQUIRE_SIGNED_IMAGE); 272 mDownloadState->srcOffset = 0; 273 mDownloadState->srcCrc = ~0; 274 if (!initial) { 275 // if no data was written, we can reuse the same segment 276 if (mDownloadState->dstOffset) 277 osAppSegmentClose(mDownloadState->start, mDownloadState->dstOffset, SEG_ST_ERASED); 278 else 279 doCreate = false; 280 } 281 if (doCreate) 282 mDownloadState->start = osAppSegmentCreate(mDownloadState->size); 283 if (!mDownloadState->start) 284 mDownloadState->erase = true; 285 mDownloadState->dstOffset = 0; 286 } 287 288 static bool doStartFirmwareUpload(struct NanohubStartFirmwareUploadRequest *req) 289 { 290 if (!mDownloadState) { 291 mDownloadState = heapAlloc(sizeof(struct DownloadState)); 292 293 if (!mDownloadState) 294 return false; 295 else 296 memset(mDownloadState, 0x00, sizeof(struct DownloadState)); 297 } 298 299 mDownloadState->size = le32toh(req->size); 300 mDownloadState->crc = le32toh(req->crc); 301 mDownloadState->chunkReply = NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED; 302 resetDownloadState(true); 303 304 return true; 305 } 306 307 static uint32_t startFirmwareUpload(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 308 { 309 struct NanohubStartFirmwareUploadRequest *req = rx; 310 struct NanohubStartFirmwareUploadResponse *resp = tx; 311 312 resp->accepted = doStartFirmwareUpload(req); 313 314 return sizeof(*resp); 315 } 316 317 static void deferredUpdateOs(void *cookie) 318 { 319 const struct AppHdr *app = cookie; 320 struct OsUpdateHdr *os = (struct OsUpdateHdr *)(&(app->hdr) + 1); 321 uint32_t uploadStatus = OS_UPDT_HDR_CHECK_FAILED; 322 uint8_t marker = OS_UPDT_MARKER_DOWNLOADED; 323 struct Segment *seg = osGetSegment(app); 324 uint32_t segSize = osSegmentGetSize(seg); 325 326 osLog(LOG_INFO, "%s: checking OS image @ %p\n", __func__, os); 327 // some sanity checks before asking BL to do image lookup 328 hostIntfSetBusy(true); 329 if (segSize >= (sizeof(*app) + sizeof(*os)) && segSize > os->size) { 330 if (osWriteShared(&os->marker, &marker, sizeof(os->marker))) { 331 wdtDisableClk(); 332 uploadStatus = BL.blVerifyOsUpdate(); 333 wdtEnableClk(); 334 } else { 335 osLog(LOG_ERROR, "%s: could not set marker on OS image\n", __func__); 336 } 337 } 338 hostIntfSetBusy(false); 339 osLog(LOG_INFO, "%s: status=%" PRIu32 "\n", __func__, uploadStatus); 340 } 341 342 static AppSecErr updateKey(const struct AppHdr *app) 343 { 344 AppSecErr ret; 345 struct KeyInfo *ki = (struct KeyInfo *)(&(app->hdr) + 1); 346 uint8_t *data = (uint8_t *)(ki + 1); 347 uint64_t keyId = KEY_ID_MAKE(APP_ID_GET_VENDOR(app->hdr.appId), ki->id); 348 const char *op; 349 350 if ((app->hdr.fwFlags & FL_KEY_HDR_DELETE) != 0) { 351 // removing existing key 352 ret = osSecretKeyDelete(keyId); 353 op = "Removing"; 354 } else { 355 // adding new key 356 ret = osSecretKeyAdd(keyId, data); 357 op = "Adding"; 358 } 359 osLog(LOG_INFO, "%s: %s key: id=%016" PRIX64 "; ret=%" PRIu32 "\n", 360 __func__, op, keyId, ret); 361 362 return ret; 363 } 364 365 static uint32_t appSecErrToNanohubReply(AppSecErr status) 366 { 367 uint32_t reply; 368 369 switch (status) { 370 case APP_SEC_NO_ERROR: 371 reply = NANOHUB_FIRMWARE_UPLOAD_SUCCESS; 372 break; 373 case APP_SEC_KEY_NOT_FOUND: 374 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_KEY_NOT_FOUND; 375 break; 376 case APP_SEC_HEADER_ERROR: 377 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_HEADER_ERROR; 378 break; 379 case APP_SEC_TOO_MUCH_DATA: 380 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_TOO_MUCH_DATA; 381 break; 382 case APP_SEC_TOO_LITTLE_DATA: 383 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_TOO_LITTLE_DATA; 384 break; 385 case APP_SEC_SIG_VERIFY_FAIL: 386 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_SIG_VERIFY_FAIL; 387 break; 388 case APP_SEC_SIG_DECODE_FAIL: 389 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_SIG_DECODE_FAIL; 390 break; 391 case APP_SEC_SIG_ROOT_UNKNOWN: 392 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_SIG_ROOT_UNKNOWN; 393 break; 394 case APP_SEC_MEMORY_ERROR: 395 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_MEMORY_ERROR; 396 break; 397 case APP_SEC_INVALID_DATA: 398 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_INVALID_DATA; 399 break; 400 case APP_SEC_VERIFY_FAILED: 401 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_VERIFY_FAILED; 402 break; 403 default: 404 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_BAD; 405 break; 406 } 407 return reply; 408 } 409 410 static uint32_t firmwareFinish(bool valid) 411 { 412 struct AppHdr *app; 413 struct Segment *storageSeg; 414 uint32_t segState; 415 uint32_t ret = NANOHUB_FIRMWARE_UPLOAD_SUCCESS; 416 417 if (!mDownloadState) { 418 ret = appSecErrToNanohubReply(mAppSecStatus); 419 osLog(LOG_INFO, "%s: no DL status; decoding secure status: %" PRIu32 "\n", __func__, ret); 420 return ret; 421 } 422 423 app = mDownloadState->start; 424 storageSeg = osGetSegment(app); 425 426 if (mAppSecStatus == APP_SEC_NO_ERROR && valid) { 427 osLog(LOG_INFO, "%s: Secure verification passed\n", __func__); 428 if (storageSeg->state != SEG_ST_RESERVED || 429 mDownloadState->size < sizeof(struct FwCommonHdr) || 430 app->hdr.magic != APP_HDR_MAGIC || 431 app->hdr.fwVer != APP_HDR_VER_CUR) { 432 segState = SEG_ST_ERASED; 433 osLog(LOG_INFO, "%s: Header verification failed\n", __func__); 434 } else { 435 segState = SEG_ST_VALID; 436 } 437 } else { 438 segState = SEG_ST_ERASED; 439 osLog(LOG_INFO, "%s: Secure verification failed: valid=%d; status=%" PRIu32 "\n", __func__, valid, mAppSecStatus); 440 } 441 442 if (!osAppSegmentClose(app, mDownloadState->dstOffset, segState)) { 443 osLog(LOG_INFO, "%s: Failed to close segment\n", __func__); 444 valid = false; 445 } else { 446 segState = osAppSegmentGetState(app); 447 valid = (segState == SEG_ST_VALID); 448 } 449 osLog(LOG_INFO, "Loaded %s image type %" PRIu8 ": %" PRIu32 450 " bytes @ %p; state=%02" PRIX32 "\n", 451 valid ? "valid" : "invalid", 452 app->hdr.payInfoType, mDownloadState->size, 453 mDownloadState->start, segState); 454 455 freeDownloadState(); // no more access to mDownloadState 456 457 if (!valid) 458 ret = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_BAD; 459 460 // take extra care about some special payload types 461 if (ret == NANOHUB_FIRMWARE_UPLOAD_SUCCESS) { 462 switch(app->hdr.payInfoType) { 463 case LAYOUT_OS: 464 osLog(LOG_INFO, "Performing OS update\n"); 465 // we want to give this message a chance to reach host before we start erasing stuff 466 osDefer(deferredUpdateOs, (void*)app, false); 467 break; 468 case LAYOUT_KEY: 469 ret = appSecErrToNanohubReply(updateKey(app)); 470 break; 471 } 472 } 473 474 if (ret != NANOHUB_FIRMWARE_UPLOAD_SUCCESS || (app->hdr.fwFlags & FL_APP_HDR_VOLATILE)) { 475 if ((app->hdr.fwFlags & FL_APP_HDR_SECURE)) 476 osAppWipeData((struct AppHdr*)app); 477 osAppSegmentSetState(app, SEG_ST_ERASED); 478 } 479 480 // if any error happened after we downloaded and verified image, we say it is unknown fault 481 // we don't have download status, so e have to save returned value in secure status field, because 482 // host may request the same status multiple times 483 if (ret != NANOHUB_FIRMWARE_UPLOAD_SUCCESS) 484 mAppSecStatus = APP_SEC_BAD; 485 486 return ret; 487 } 488 489 static void firmwareErase(void *cookie) 490 { 491 if (mDownloadState->erase == true) { 492 osLog(LOG_INFO, "%s: erasing shared area\n", __func__); 493 osEraseShared(); 494 mDownloadState->start = osAppSegmentCreate(mDownloadState->size); 495 if (!mDownloadState->start) 496 firmwareFinish(false); 497 mDownloadState->erase = false; 498 hostIntfSetInterrupt(NANOHUB_INT_CMD_WAIT); 499 } 500 mDownloadState->eraseScheduled = false; 501 } 502 503 static void firmwareWrite(void *cookie) 504 { 505 bool valid; 506 bool finished = false; 507 struct NanohubHalContUploadTx *resp = cookie; 508 // only check crc when cookie is NULL (write came from kernel, not HAL) 509 bool checkCrc = !cookie; 510 511 if (mAppSecStatus == APP_SEC_NEED_MORE_TIME) { 512 mAppSecStatus = appSecDoSomeProcessing(mDownloadState->appSecState); 513 } else if (mDownloadState->lenLeft) { 514 const uint8_t *data = mDownloadState->data + mDownloadState->len - mDownloadState->lenLeft; 515 uint32_t len = mDownloadState->lenLeft, lenLeft, lenRem = 0; 516 517 if (len > MAX_APP_SEC_RX_DATA_LEN) { 518 lenRem = len - MAX_APP_SEC_RX_DATA_LEN; 519 len = MAX_APP_SEC_RX_DATA_LEN; 520 } 521 522 mAppSecStatus = appSecRxData(mDownloadState->appSecState, data, len, &lenLeft); 523 mDownloadState->lenLeft = lenLeft + lenRem; 524 } 525 526 valid = (mAppSecStatus == APP_SEC_NO_ERROR); 527 if (mAppSecStatus == APP_SEC_NEED_MORE_TIME || mDownloadState->lenLeft) { 528 osDefer(firmwareWrite, cookie, false); 529 return; 530 } else if (valid) { 531 if (mDownloadState->srcOffset == mDownloadState->size) { 532 mAppSecStatus = appSecRxDataOver(mDownloadState->appSecState); 533 finished = true; 534 valid = !checkCrc || mDownloadState->crc == ~mDownloadState->srcCrc; 535 } else if (mDownloadState->srcOffset > mDownloadState->size) { 536 valid = false; 537 } 538 } 539 if (!valid) 540 finished = true; 541 if (finished) { 542 if (firmwareFinish(valid) != NANOHUB_FIRMWARE_UPLOAD_SUCCESS) 543 valid = false; 544 } 545 if (resp) { 546 resp->success = valid; 547 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 548 } 549 } 550 551 static uint32_t doFirmwareChunk(uint8_t *data, uint32_t offset, uint32_t len, void *cookie) 552 { 553 uint32_t reply, ret; 554 555 if (!mDownloadState) { 556 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_CANCEL_NO_RETRY; 557 } else if (mAppSecStatus == APP_SEC_NEED_MORE_TIME || mDownloadState->lenLeft) { 558 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_RESEND; 559 } else if (mDownloadState->chunkReply != NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED) { 560 reply = mDownloadState->chunkReply; 561 firmwareFinish(false); 562 } else { 563 if (mDownloadState->erase == true) { 564 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_WAIT; 565 if (!mDownloadState->eraseScheduled) { 566 ret = osExtAppStopApps(APP_ID_ANY); 567 osLog(LOG_INFO, "%s: unloaded apps, ret=%08lx\n", __func__, ret); 568 mDownloadState->eraseScheduled = osDefer(firmwareErase, NULL, false); 569 } 570 } else if (!mDownloadState->start) { 571 // this means we can't allocate enough space even after we did erase 572 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_CANCEL_NO_RETRY; 573 firmwareFinish(false); 574 } else if (offset != mDownloadState->srcOffset) { 575 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_RESTART; 576 resetDownloadState(false); 577 } else { 578 if (!cookie) 579 mDownloadState->srcCrc = crc32(data, len, mDownloadState->srcCrc); 580 mDownloadState->srcOffset += len; 581 memcpy(mDownloadState->data, data, len); 582 mDownloadState->lenLeft = mDownloadState->len = len; 583 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED; 584 osDefer(firmwareWrite, cookie, false); 585 } 586 } 587 588 return reply; 589 } 590 591 static uint32_t firmwareChunk(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 592 { 593 struct NanohubFirmwareChunkRequest *req = rx; 594 struct NanohubFirmwareChunkResponse *resp = tx; 595 uint32_t offset = le32toh(req->offset); 596 uint8_t len = rx_len - sizeof(req->offset); 597 598 resp->chunkReply = doFirmwareChunk(req->data, offset, len, NULL); 599 600 return sizeof(*resp); 601 } 602 603 static uint32_t doFinishFirmwareUpload() 604 { 605 uint32_t reply; 606 607 if (!mDownloadState) { 608 reply = appSecErrToNanohubReply(mAppSecStatus); 609 } else if (mDownloadState->srcOffset == mDownloadState->size) { 610 reply = NANOHUB_FIRMWARE_UPLOAD_PROCESSING; 611 } else { 612 reply = firmwareFinish(false); 613 } 614 615 return reply; 616 } 617 618 static uint32_t finishFirmwareUpload(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 619 { 620 struct NanohubFinishFirmwareUploadResponse *resp = tx; 621 resp->uploadReply = doFinishFirmwareUpload(); 622 if (resp->uploadReply != NANOHUB_FIRMWARE_UPLOAD_PROCESSING) 623 osLog(LOG_INFO, "%s: reply=%" PRIu8 "\n", __func__, resp->uploadReply); 624 return sizeof(*resp); 625 } 626 627 static uint32_t getInterrupt(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 628 { 629 struct NanohubGetInterruptRequest *req = rx; 630 struct NanohubGetInterruptResponse *resp = tx; 631 int i; 632 633 if (rx_len == sizeof(struct NanohubGetInterruptRequest)) { 634 for (i = 0; i < HOSTINTF_MAX_INTERRUPTS; i++) { 635 if (req->clear[i/32] & (1UL << (i & 31))) 636 hostIntfClearInterrupt(i); 637 } 638 } 639 640 hostIntfCopyInterrupts(resp->interrupts, HOSTINTF_MAX_INTERRUPTS); 641 642 return sizeof(*resp); 643 } 644 645 static uint32_t maskInterrupt(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 646 { 647 struct NanohubMaskInterruptRequest *req = rx; 648 struct NanohubMaskInterruptResponse *resp = tx; 649 650 hostIntfSetInterruptMask(req->interrupt); 651 652 resp->accepted = true; 653 return sizeof(*resp); 654 } 655 656 static uint32_t unmaskInterrupt(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 657 { 658 struct NanohubUnmaskInterruptRequest *req = rx; 659 struct NanohubUnmaskInterruptResponse *resp = tx; 660 661 hostIntfClearInterruptMask(req->interrupt); 662 663 resp->accepted = true; 664 return sizeof(*resp); 665 } 666 667 static void addDelta(struct ApHubSync *sync, uint64_t apTime, uint64_t hubTime) 668 { 669 #if DEBUG_APHUB_TIME_SYNC 670 syncDebugAdd(apTime, hubTime); 671 #endif 672 apHubSyncAddDelta(sync, apTime, hubTime); 673 } 674 675 static int64_t getAvgDelta(struct ApHubSync *sync) 676 { 677 return apHubSyncGetDelta(sync, sensorGetTime()); 678 } 679 680 static int fillBuffer(void *tx, uint32_t totLength, uint32_t *wakeup, uint32_t *nonwakeup) 681 { 682 struct HostIntfDataBuffer *packet = &mTxNext; 683 struct HostIntfDataBuffer *firstPacket = tx; 684 uint8_t *buf = tx; 685 uint32_t length; 686 uint32_t prevWakeup, prevNonWakeup; 687 688 prevWakeup = *wakeup; 689 prevNonWakeup = *nonwakeup; 690 691 while (hostIntfPacketDequeue(&mTxNext, wakeup, nonwakeup)) { 692 length = packet->length + sizeof(packet->evtType); 693 if (packet->sensType == SENS_TYPE_INVALID) { 694 switch (packet->dataType) { 695 case HOSTINTF_DATA_TYPE_APP_TO_HOST: 696 packet->evtType = htole32(EVT_APP_TO_HOST); 697 break; 698 case HOSTINTF_DATA_TYPE_RESET_REASON: 699 packet->evtType = htole32(EVT_RESET_REASON); 700 break; 701 case HOSTINTF_DATA_TYPE_APP_TO_SENSOR_HAL: 702 packet->evtType = htole32(EVT_APP_TO_SENSOR_HAL_DATA); 703 break; 704 #ifdef DEBUG_LOG_EVT 705 case HOSTINTF_DATA_TYPE_LOG: 706 packet->evtType = htole32(HOST_EVT_DEBUG_LOG); 707 break; 708 #endif 709 default: 710 packet->evtType = htole32(0x00000000); 711 break; 712 } 713 } else { 714 packet->evtType = htole32(EVT_NO_FIRST_SENSOR_EVENT + packet->sensType); 715 if (packet->referenceTime) 716 packet->referenceTime += getAvgDelta(&mTimeSync); 717 718 if (*wakeup > 0) 719 packet->firstSample.interrupt = NANOHUB_INT_WAKEUP; 720 } 721 722 if ((!totLength || (isSensorEvent(firstPacket->evtType) && isSensorEvent(packet->evtType))) && 723 totLength + length <= sizeof(struct HostIntfDataBuffer)) { 724 memcpy(buf + totLength, &mTxNext, length); 725 totLength += length; 726 if (isSensorEvent(packet->evtType) && packet->firstSample.interrupt == NANOHUB_INT_WAKEUP) 727 firstPacket->firstSample.interrupt = NANOHUB_INT_WAKEUP; 728 } else { 729 mTxNextLength = length; 730 *wakeup = prevWakeup; 731 *nonwakeup = prevNonWakeup; 732 break; 733 } 734 735 prevWakeup = *wakeup; 736 prevNonWakeup = *nonwakeup; 737 } 738 739 return totLength; 740 } 741 742 static void updateInterrupts(void) 743 { 744 uint32_t wakeup = atomicRead32bits(&mTxWakeCnt[0]); 745 uint32_t nonwakeup = atomicRead32bits(&mTxWakeCnt[1]); 746 bool wakeupStatus = hostIntfGetInterrupt(NANOHUB_INT_WAKEUP); 747 bool nonwakeupStatus = hostIntfGetInterrupt(NANOHUB_INT_NONWAKEUP); 748 749 if (!wakeup && wakeupStatus) 750 hostIntfClearInterrupt(NANOHUB_INT_WAKEUP); 751 else if (wakeup && !wakeupStatus) 752 hostIntfSetInterrupt(NANOHUB_INT_WAKEUP); 753 754 if (!nonwakeup && nonwakeupStatus) 755 hostIntfClearInterrupt(NANOHUB_INT_NONWAKEUP); 756 else if (nonwakeup && !nonwakeupStatus) 757 hostIntfSetInterrupt(NANOHUB_INT_NONWAKEUP); 758 } 759 760 void nanohubPrefetchTx(uint32_t interrupt, uint32_t wakeup, uint32_t nonwakeup) 761 { 762 uint64_t state; 763 764 if (wakeup < atomicRead32bits(&mTxWakeCnt[0])) 765 wakeup = atomicRead32bits(&mTxWakeCnt[0]); 766 767 if (nonwakeup < atomicRead32bits(&mTxWakeCnt[1])) 768 nonwakeup = atomicRead32bits(&mTxWakeCnt[1]); 769 770 if (interrupt == HOSTINTF_MAX_INTERRUPTS && !hostIntfGetInterrupt(NANOHUB_INT_WAKEUP) && !hostIntfGetInterrupt(NANOHUB_INT_NONWAKEUP)) 771 return; 772 773 atomicWriteByte(&mPrefetchActive, 1); 774 775 if (interrupt < HOSTINTF_MAX_INTERRUPTS) 776 hostIntfSetInterrupt(interrupt); 777 778 do { 779 if (atomicReadByte(&mTxCurrLength) == 0 && mTxNextLength > 0) { 780 memcpy(&mTxCurr, &mTxNext, mTxNextLength); 781 atomicWriteByte(&mTxCurrLength, mTxNextLength); 782 mTxNextLength = 0; 783 } 784 785 if (mTxNextLength == 0) { 786 atomicWriteByte(&mTxCurrLength, fillBuffer(&mTxCurr, atomicReadByte(&mTxCurrLength), &wakeup, &nonwakeup)); 787 atomicWrite32bits(&mTxWakeCnt[0], wakeup); 788 atomicWrite32bits(&mTxWakeCnt[1], nonwakeup); 789 } 790 791 atomicWriteByte(&mPrefetchActive, 0); 792 793 if (atomicReadByte(&mPrefetchTx)) { 794 state = cpuIntsOff(); 795 796 // interrupt occured during this call 797 // take care of it 798 hostIntfTxAck(&mTxCurr, atomicReadByte(&mTxCurrLength)); 799 atomicWriteByte(&mPrefetchTx, 0); 800 atomicWriteByte(&mTxCurrLength, 0); 801 802 cpuIntsRestore(state); 803 804 updateInterrupts(); 805 } else { 806 break; 807 } 808 } while (mTxNextLength > 0); 809 } 810 811 static void nanohubPrefetchTxDefer(void *cookie) 812 { 813 nanohubPrefetchTx(HOSTINTF_MAX_INTERRUPTS, 0, 0); 814 } 815 816 static uint32_t readEventFast(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 817 { 818 struct NanohubReadEventRequest *req = rx; 819 uint8_t ret = 0; 820 821 if (atomicReadByte(&mPrefetchActive)) { 822 atomicWriteByte(&mPrefetchTx, 1); 823 return NANOHUB_FAST_DONT_ACK; 824 } else { 825 if ((ret = atomicReadByte(&mTxCurrLength))) { 826 addDelta(&mTimeSync, req->apBootTime, timestamp); 827 828 memcpy(tx, &mTxCurr, ret); 829 atomicWriteByte(&mTxCurrLength, 0); 830 831 updateInterrupts(); 832 osDefer(nanohubPrefetchTxDefer, NULL, true); 833 } else { 834 return NANOHUB_FAST_UNHANDLED_ACK; 835 } 836 } 837 838 return ret; 839 } 840 841 static uint32_t readEvent(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 842 { 843 struct NanohubReadEventRequest *req = rx; 844 uint8_t *buf = tx; 845 uint32_t length, wakeup, nonwakeup; 846 uint32_t totLength = 0; 847 848 addDelta(&mTimeSync, req->apBootTime, timestamp); 849 850 if ((totLength = atomicReadByte(&mTxCurrLength))) { 851 memcpy(tx, &mTxCurr, totLength); 852 atomicWriteByte(&mTxCurrLength, 0); 853 updateInterrupts(); 854 return totLength; 855 } 856 857 wakeup = atomicRead32bits(&mTxWakeCnt[0]); 858 nonwakeup = atomicRead32bits(&mTxWakeCnt[1]); 859 860 if (mTxNextLength > 0) { 861 length = mTxNextLength; 862 memcpy(buf, &mTxNext, length); 863 totLength = length; 864 mTxNextLength = 0; 865 } 866 867 totLength = fillBuffer(buf, totLength, &wakeup, &nonwakeup); 868 atomicWrite32bits(&mTxWakeCnt[0], wakeup); 869 atomicWrite32bits(&mTxWakeCnt[1], nonwakeup); 870 871 if (totLength) { 872 updateInterrupts(); 873 } else { 874 hostIntfClearInterrupt(NANOHUB_INT_WAKEUP); 875 hostIntfClearInterrupt(NANOHUB_INT_NONWAKEUP); 876 } 877 878 return totLength; 879 } 880 881 static bool forwardPacket(uint32_t event, void *data, size_t data_size, 882 void *hdr, size_t hdr_size, uint32_t tid) 883 { 884 bool res; 885 uint8_t *hostPacket = data; 886 uint8_t *packet = slabAllocatorAlloc(mEventSlab); 887 EventFreeF free = slabFree; 888 889 if (!packet) { 890 packet = heapAlloc(data_size + hdr_size); 891 free = heapFree; 892 } 893 if (!packet) 894 return false; 895 896 if (hdr && hdr_size) 897 memcpy(packet, hdr, hdr_size); 898 899 memcpy(packet + hdr_size, hostPacket, data_size); 900 if (tid) { 901 // send to specific TID 902 res = osEnqueuePrivateEvt(event, packet, free, tid); 903 if (!res) 904 free(packet); 905 } else { 906 // broadcast to all 907 res = osEnqueueEvtOrFree(event, packet, free); 908 } 909 910 return res; 911 } 912 913 static uint32_t writeEvent(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 914 { 915 struct NanohubWriteEventRequest *req = rx; 916 struct NanohubWriteEventResponse *resp = tx; 917 uint32_t tid; 918 uint32_t event = le32toh(req->evtType); 919 920 if (event == EVT_APP_FROM_HOST) { 921 // old version of HAL; message_type is not delivered to CHRE apps 922 struct HostMsgHdr *hostPacket = rx; 923 if (rx_len >= sizeof(struct HostMsgHdr) && 924 rx_len == sizeof(struct HostMsgHdr) + hostPacket->len && 925 osTidById(&hostPacket->appId, &tid)) { 926 resp->accepted = forwardPacket(event, hostPacket + 1, hostPacket->len, 927 &hostPacket->len, sizeof(hostPacket->len), tid); 928 } else { 929 resp->accepted = false; 930 } 931 } else if (event == EVT_APP_FROM_HOST_CHRE) { 932 // new version of HAL; full support for CHRE apps 933 struct HostMsgHdrChre *hostPacket = rx; 934 if (rx_len >= sizeof(struct HostMsgHdrChre) && 935 rx_len == sizeof(struct HostMsgHdrChre) + hostPacket->len && 936 osTidById(&hostPacket->appId, &tid)) { 937 if (osAppIsChre(tid)) { 938 struct NanohubMsgChreHdr hdr = { 939 .size = hostPacket->len, 940 .appEvent = hostPacket->appEventId, 941 }; 942 // CHRE app receives message in new format 943 resp->accepted = forwardPacket(event, hostPacket + 1, hostPacket->len, 944 &hdr, sizeof(hdr), tid); 945 } else { 946 // legacy app receives message in old format 947 resp->accepted = forwardPacket(EVT_APP_FROM_HOST, hostPacket + 1, hostPacket->len, 948 &hostPacket->len, sizeof(hostPacket->len), tid); 949 } 950 } else { 951 resp->accepted = false; 952 } 953 } else { 954 resp->accepted = forwardPacket(event, 955 req->evtData, rx_len - sizeof(req->evtType), 956 NULL, 0, 0); 957 } 958 959 return sizeof(*resp); 960 } 961 962 const static struct NanohubCommand mBuiltinCommands[] = { 963 NANOHUB_COMMAND(NANOHUB_REASON_GET_OS_HW_VERSIONS, 964 getOsHwVersion, 965 getOsHwVersion, 966 struct NanohubOsHwVersionsRequest, 967 struct NanohubOsHwVersionsRequest), 968 NANOHUB_COMMAND(NANOHUB_REASON_GET_APP_VERSIONS, 969 NULL, 970 getAppVersion, 971 struct NanohubAppVersionsRequest, 972 struct NanohubAppVersionsRequest), 973 NANOHUB_COMMAND(NANOHUB_REASON_QUERY_APP_INFO, 974 NULL, 975 queryAppInfo, 976 struct NanohubAppInfoRequest, 977 struct NanohubAppInfoRequest), 978 NANOHUB_COMMAND(NANOHUB_REASON_START_FIRMWARE_UPLOAD, 979 NULL, 980 startFirmwareUpload, 981 struct NanohubStartFirmwareUploadRequest, 982 struct NanohubStartFirmwareUploadRequest), 983 NANOHUB_COMMAND(NANOHUB_REASON_FIRMWARE_CHUNK, 984 NULL, 985 firmwareChunk, 986 __le32, 987 struct NanohubFirmwareChunkRequest), 988 NANOHUB_COMMAND(NANOHUB_REASON_FINISH_FIRMWARE_UPLOAD, 989 NULL, 990 finishFirmwareUpload, 991 struct NanohubFinishFirmwareUploadRequest, 992 struct NanohubFinishFirmwareUploadRequest), 993 NANOHUB_COMMAND(NANOHUB_REASON_GET_INTERRUPT, 994 getInterrupt, 995 getInterrupt, 996 0, 997 struct NanohubGetInterruptRequest), 998 NANOHUB_COMMAND(NANOHUB_REASON_MASK_INTERRUPT, 999 maskInterrupt, 1000 maskInterrupt, 1001 struct NanohubMaskInterruptRequest, 1002 struct NanohubMaskInterruptRequest), 1003 NANOHUB_COMMAND(NANOHUB_REASON_UNMASK_INTERRUPT, 1004 unmaskInterrupt, 1005 unmaskInterrupt, 1006 struct NanohubUnmaskInterruptRequest, 1007 struct NanohubUnmaskInterruptRequest), 1008 NANOHUB_COMMAND(NANOHUB_REASON_READ_EVENT, 1009 readEventFast, 1010 readEvent, 1011 struct NanohubReadEventRequest, 1012 struct NanohubReadEventRequest), 1013 NANOHUB_COMMAND(NANOHUB_REASON_WRITE_EVENT, 1014 writeEvent, 1015 writeEvent, 1016 __le32, 1017 struct NanohubWriteEventRequest), 1018 }; 1019 1020 const struct NanohubCommand *nanohubFindCommand(uint32_t packetReason) 1021 { 1022 uint32_t i; 1023 1024 for (i = 0; i < ARRAY_SIZE(mBuiltinCommands); i++) { 1025 const struct NanohubCommand *cmd = &mBuiltinCommands[i]; 1026 if (cmd->reason == packetReason) 1027 return cmd; 1028 } 1029 return NULL; 1030 } 1031 1032 static void halSendMgmtResponse(uint32_t cmd, uint32_t status) 1033 { 1034 struct NanohubHalMgmtTx *resp; 1035 1036 resp = heapAlloc(sizeof(*resp)); 1037 if (resp) { 1038 resp->hdr = (struct NanohubHalHdr) { 1039 .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 1040 .len = sizeof(*resp) - sizeof(resp->hdr) + sizeof(resp->hdr.msg), 1041 .msg = cmd, 1042 }; 1043 resp->status = htole32(status); 1044 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1045 } 1046 } 1047 1048 static void halExtAppsOn(void *rx, uint8_t rx_len) 1049 { 1050 struct NanohubHalMgmtRx *req = rx; 1051 1052 halSendMgmtResponse(NANOHUB_HAL_EXT_APPS_ON, osExtAppStartApps(le64toh(unaligned_u64(&req->appId)))); 1053 } 1054 1055 static void halExtAppsOff(void *rx, uint8_t rx_len) 1056 { 1057 struct NanohubHalMgmtRx *req = rx; 1058 1059 halSendMgmtResponse(NANOHUB_HAL_EXT_APPS_OFF, osExtAppStopApps(le64toh(unaligned_u64(&req->appId)))); 1060 } 1061 1062 static void halExtAppDelete(void *rx, uint8_t rx_len) 1063 { 1064 struct NanohubHalMgmtRx *req = rx; 1065 1066 halSendMgmtResponse(NANOHUB_HAL_EXT_APP_DELETE, osExtAppEraseApps(le64toh(unaligned_u64(&req->appId)))); 1067 } 1068 1069 static void halQueryMemInfo(void *rx, uint8_t rx_len) 1070 { 1071 } 1072 1073 static void halQueryApps(void *rx, uint8_t rx_len) 1074 { 1075 struct NanohubHalQueryAppsRx *req = rx; 1076 struct NanohubHalQueryAppsTx *resp; 1077 struct NanohubHalHdr *hdr; 1078 uint64_t appId; 1079 uint32_t appVer, appSize; 1080 1081 if (osAppInfoByIndex(le32toh(req->idx), &appId, &appVer, &appSize)) { 1082 resp = heapAlloc(sizeof(*resp)); 1083 resp->hdr.appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 1084 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalHdr) + 1; 1085 resp->hdr.msg = NANOHUB_HAL_QUERY_APPS; 1086 resp->appId = appId; 1087 resp->version = appVer; 1088 resp->flashUse = appSize; 1089 resp->ramUse = 0; 1090 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1091 } else { 1092 hdr = heapAlloc(sizeof(*hdr)); 1093 hdr->appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 1094 hdr->len = 1; 1095 hdr->msg = NANOHUB_HAL_QUERY_APPS; 1096 osEnqueueEvtOrFree(EVT_APP_TO_HOST, hdr, heapFree); 1097 } 1098 } 1099 1100 static void halQueryRsaKeys(void *rx, uint8_t rx_len) 1101 { 1102 struct NanohubHalQueryRsaKeysRx *req = rx; 1103 struct NanohubHalQueryRsaKeysTx *resp; 1104 int len = 0; 1105 const uint32_t *ptr; 1106 uint32_t numKeys; 1107 1108 if (!(resp = heapAlloc(sizeof(*resp) + NANOHUB_RSA_KEY_CHUNK_LEN))) 1109 return; 1110 1111 ptr = BL.blGetPubKeysInfo(&numKeys); 1112 if (ptr && numKeys * RSA_BYTES > req->offset) { 1113 len = numKeys * RSA_BYTES - req->offset; 1114 if (len > NANOHUB_RSA_KEY_CHUNK_LEN) 1115 len = NANOHUB_RSA_KEY_CHUNK_LEN; 1116 memcpy(resp->data, (uint8_t *)ptr + req->offset, len); 1117 } 1118 1119 resp->hdr.appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 1120 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalHdr) + 1 + len; 1121 resp->hdr.msg = NANOHUB_HAL_QUERY_RSA_KEYS; 1122 1123 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1124 } 1125 1126 static void halStartUpload(void *rx, uint8_t rx_len) 1127 { 1128 struct NanohubHalStartUploadRx *req = rx; 1129 struct NanohubStartFirmwareUploadRequest hwReq = { 1130 .size= req->length 1131 }; 1132 struct NanohubHalStartUploadTx *resp; 1133 1134 if (!(resp = heapAlloc(sizeof(*resp)))) 1135 return; 1136 1137 resp->hdr.appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 1138 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalHdr) + 1; 1139 resp->hdr.msg = NANOHUB_HAL_START_UPLOAD; 1140 resp->success = doStartFirmwareUpload(&hwReq); 1141 1142 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1143 } 1144 1145 static void halContUpload(void *rx, uint8_t rx_len) 1146 { 1147 uint32_t offset; 1148 uint32_t reply; 1149 uint8_t len; 1150 struct NanohubHalContUploadRx *req = rx; 1151 struct NanohubHalContUploadTx *resp; 1152 1153 if (!(resp = heapAlloc(sizeof(*resp)))) 1154 return; 1155 1156 resp->hdr.appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 1157 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalHdr) + 1; 1158 resp->hdr.msg = NANOHUB_HAL_CONT_UPLOAD; 1159 1160 if (!mDownloadState) { 1161 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_CANCEL_NO_RETRY; 1162 } else { 1163 offset = le32toh(req->offset); 1164 len = rx_len - sizeof(req->offset); 1165 reply = doFirmwareChunk(req->data, offset, len, resp); 1166 } 1167 if (reply != NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED) { 1168 osLog(LOG_ERROR, "%s: reply=%" PRIu32 "\n", __func__, reply); 1169 1170 resp->success = false; 1171 1172 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1173 } 1174 } 1175 1176 static void halFinishUpload(void *rx, uint8_t rx_len) 1177 { 1178 struct NanohubHalFinishUploadTx *resp; 1179 uint32_t reply; 1180 1181 if (!(resp = heapAlloc(sizeof(*resp)))) 1182 return; 1183 1184 resp->hdr.appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 1185 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalHdr) + 1; 1186 resp->hdr.msg = NANOHUB_HAL_FINISH_UPLOAD; 1187 1188 reply = doFinishFirmwareUpload(); 1189 1190 osLog(LOG_INFO, "%s: reply=%" PRIu32 "\n", __func__, reply); 1191 1192 resp->success = (reply == NANOHUB_FIRMWARE_UPLOAD_SUCCESS); 1193 1194 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1195 } 1196 1197 static void halReboot(void *rx, uint8_t rx_len) 1198 { 1199 BL.blReboot(); 1200 } 1201 1202 const static struct NanohubHalCommand mBuiltinHalCommands[] = { 1203 NANOHUB_HAL_COMMAND(NANOHUB_HAL_EXT_APPS_ON, 1204 halExtAppsOn), 1205 NANOHUB_HAL_COMMAND(NANOHUB_HAL_EXT_APPS_OFF, 1206 halExtAppsOff), 1207 NANOHUB_HAL_COMMAND(NANOHUB_HAL_EXT_APP_DELETE, 1208 halExtAppDelete), 1209 NANOHUB_HAL_COMMAND(NANOHUB_HAL_QUERY_MEMINFO, 1210 halQueryMemInfo), 1211 NANOHUB_HAL_COMMAND(NANOHUB_HAL_QUERY_APPS, 1212 halQueryApps), 1213 NANOHUB_HAL_COMMAND(NANOHUB_HAL_QUERY_RSA_KEYS, 1214 halQueryRsaKeys), 1215 NANOHUB_HAL_COMMAND(NANOHUB_HAL_START_UPLOAD, 1216 halStartUpload), 1217 NANOHUB_HAL_COMMAND(NANOHUB_HAL_CONT_UPLOAD, 1218 halContUpload), 1219 NANOHUB_HAL_COMMAND(NANOHUB_HAL_FINISH_UPLOAD, 1220 halFinishUpload), 1221 NANOHUB_HAL_COMMAND(NANOHUB_HAL_REBOOT, 1222 halReboot), 1223 }; 1224 1225 const struct NanohubHalCommand *nanohubHalFindCommand(uint8_t msg) 1226 { 1227 uint32_t i; 1228 1229 for (i = 0; i < ARRAY_SIZE(mBuiltinHalCommands); i++) { 1230 const struct NanohubHalCommand *cmd = &mBuiltinHalCommands[i]; 1231 if (cmd->msg == msg) 1232 return cmd; 1233 } 1234 return NULL; 1235 } 1236 1237 uint64_t hostGetTime(void) 1238 { 1239 int64_t delta = getAvgDelta(&mTimeSync); 1240 1241 if (!delta || delta == INT64_MIN) 1242 return 0ULL; 1243 else 1244 return sensorGetTime() + delta; 1245 } 1246 1247 #if DEBUG_APHUB_TIME_SYNC 1248 1249 #define N_APHUB_SYNC_DATA 256 1250 #define PRINT_DELAY 20000000 // unit ns, 20ms 1251 struct ApHubSyncDebug { 1252 uint64_t apFirst; 1253 uint64_t hubFirst; 1254 uint32_t apDelta[N_APHUB_SYNC_DATA]; // us 1255 uint32_t hubDelta[N_APHUB_SYNC_DATA]; // us 1256 int printIndex; //negative means not printing 1257 int writeIndex; 1258 1259 uint32_t printTimer; 1260 }; 1261 1262 static struct ApHubSyncDebug mApHubSyncDebug; 1263 1264 static void syncDebugCallback(uint32_t timerId, void *data) 1265 { 1266 1267 if (mApHubSyncDebug.printIndex >= mApHubSyncDebug.writeIndex || 1268 mApHubSyncDebug.printIndex >= N_APHUB_SYNC_DATA) { 1269 timTimerCancel(mApHubSyncDebug.printTimer); 1270 1271 osLog(LOG_DEBUG, "APHUB Done printing %d items", mApHubSyncDebug.printIndex); 1272 mApHubSyncDebug.writeIndex = 0; 1273 mApHubSyncDebug.printIndex = -1; 1274 1275 mApHubSyncDebug.printTimer = 0; 1276 } else { 1277 if (mApHubSyncDebug.printIndex == 0) { 1278 osLog(LOG_DEBUG, "APHUB init %" PRIu64 " %" PRIu64, 1279 mApHubSyncDebug.apFirst, 1280 mApHubSyncDebug.hubFirst); 1281 } 1282 1283 osLog(LOG_DEBUG, "APHUB %d %" PRIu32 " %" PRIu32, 1284 mApHubSyncDebug.printIndex, 1285 mApHubSyncDebug.apDelta[mApHubSyncDebug.printIndex], 1286 mApHubSyncDebug.hubDelta[mApHubSyncDebug.printIndex]); 1287 1288 mApHubSyncDebug.printIndex++; 1289 } 1290 } 1291 1292 static void syncDebugTriggerPrint() 1293 { 1294 if (mApHubSyncDebug.printTimer) { 1295 //printing already going 1296 return; 1297 } 1298 1299 mApHubSyncDebug.printIndex = 0; 1300 1301 syncDebugCallback(0, NULL); 1302 if (!(mApHubSyncDebug.printTimer = 1303 timTimerSet(PRINT_DELAY, 0, 50, syncDebugCallback, NULL, false /*oneShot*/))) { 1304 osLog(LOG_WARN, "Cannot get timer for printing"); 1305 1306 mApHubSyncDebug.writeIndex = 0; // discard all data 1307 mApHubSyncDebug.printIndex = -1; // not printing 1308 } 1309 } 1310 1311 static void syncDebugAdd(uint64_t ap, uint64_t hub) 1312 { 1313 if (mApHubSyncDebug.writeIndex >= N_APHUB_SYNC_DATA) { 1314 //full 1315 syncDebugTriggerPrint(); 1316 return; 1317 } 1318 1319 if (mApHubSyncDebug.writeIndex == 0) { 1320 mApHubSyncDebug.apFirst = ap; 1321 mApHubSyncDebug.hubFirst = hub; 1322 } 1323 1324 // convert ns to us 1325 mApHubSyncDebug.apDelta[mApHubSyncDebug.writeIndex] = 1326 (uint32_t) U64_DIV_BY_CONST_U16((ap - mApHubSyncDebug.apFirst), 1000u); 1327 mApHubSyncDebug.hubDelta[mApHubSyncDebug.writeIndex] = 1328 (uint32_t) U64_DIV_BY_CONST_U16((hub - mApHubSyncDebug.hubFirst), 1000u); 1329 1330 ++mApHubSyncDebug.writeIndex; 1331 } 1332 #endif 1333