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 <seos_priv.h> 43 #include <util.h> 44 #include <mpu.h> 45 #include <heap.h> 46 #include <slab.h> 47 #include <sensType.h> 48 #include <timer.h> 49 #include <appSec.h> 50 #include <cpu.h> 51 #include <cpu/cpuMath.h> 52 #include <algos/ap_hub_sync.h> 53 #include <sensors_priv.h> 54 55 #include <chre.h> 56 57 #define NANOHUB_COMMAND(_reason, _fastHandler, _handler, _minReqType, _maxReqType) \ 58 { .reason = _reason, .fastHandler = _fastHandler, .handler = _handler, \ 59 .minDataLen = sizeof(_minReqType), .maxDataLen = sizeof(_maxReqType) } 60 61 #define NANOHUB_HAL_LEGACY_COMMAND(_msg, _handler) \ 62 { .msg = _msg, .handler = _handler } 63 64 #define NANOHUB_HAL_COMMAND(_msg, _handler, _minReqType, _maxReqType) \ 65 { .msg = _msg, .handler = _handler, \ 66 .minDataLen = sizeof(_minReqType), .maxDataLen = sizeof(_maxReqType) } 67 68 // maximum number of bytes to feed into appSecRxData at once 69 // The bigger the number, the more time we block other event processing 70 // appSecRxData only feeds 16 bytes at a time into writeCbk, so large 71 // numbers don't buy us that much 72 #define MAX_APP_SEC_RX_DATA_LEN 64 73 74 #define REQUIRE_SIGNED_IMAGE true 75 #define DEBUG_APHUB_TIME_SYNC false 76 77 #if DEBUG_APHUB_TIME_SYNC 78 static void syncDebugAdd(uint64_t, uint64_t); 79 #endif 80 81 struct DownloadState 82 { 83 struct AppSecState *appSecState; 84 uint32_t size; // document size, as reported by client 85 uint32_t srcOffset; // bytes received from client 86 uint32_t dstOffset; // bytes sent to flash 87 struct AppHdr *start; // start of flash segment, where to write 88 uint32_t crc; // document CRC-32, as reported by client 89 uint32_t srcCrc; // current state of CRC-32 we generate from input 90 uint8_t data[NANOHUB_PACKET_PAYLOAD_MAX]; 91 uint8_t len; 92 uint8_t lenLeft; 93 uint8_t chunkReply; 94 bool erase; 95 bool eraseScheduled; 96 }; 97 98 static struct DownloadState *mDownloadState; 99 static AppSecErr mAppSecStatus; 100 static struct AppHdr *mApp; 101 static struct SlabAllocator *mEventSlab; 102 static struct HostIntfDataBuffer mTxCurr, mTxNext; 103 static uint8_t mTxCurrLength, mTxNextLength; 104 static uint8_t mPrefetchActive, mPrefetchTx; 105 static uint32_t mTxWakeCnt[2]; 106 static struct ApHubSync mTimeSync; 107 108 static inline bool isSensorEvent(uint32_t evtType) 109 { 110 return evtType > EVT_NO_FIRST_SENSOR_EVENT && evtType <= EVT_NO_FIRST_SENSOR_EVENT + SENS_TYPE_LAST_USER; 111 } 112 113 static void slabFree(void *ptr) 114 { 115 slabAllocatorFree(mEventSlab, ptr); 116 } 117 118 void nanohubInitCommand(void) 119 { 120 mEventSlab = slabAllocatorNew(NANOHUB_PACKET_PAYLOAD_MAX-sizeof(__le32), 4, 2); 121 } 122 123 static inline uint64_t unaligned_u64(uint64_t *val) { 124 uint64_t local; 125 memcpy(&local, val, sizeof(local)); 126 return local; 127 } 128 129 static inline uint32_t unaligned_u32(uint32_t *val) { 130 uint32_t local; 131 memcpy(&local, val, sizeof(local)); 132 return local; 133 } 134 135 static uint32_t getOsHwVersion(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 136 { 137 struct NanohubOsHwVersionsResponse *resp = tx; 138 resp->hwType = htole16(platHwType()); 139 resp->hwVer = htole16(platHwVer()); 140 resp->blVer = htole16(platBlVer()); 141 resp->osVer = htole16(OS_VER); 142 resp->variantVer = htole32(VARIANT_VER); 143 144 return sizeof(*resp); 145 } 146 147 static uint32_t getAppVersion(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 148 { 149 struct NanohubAppVersionsRequest *req = rx; 150 struct NanohubAppVersionsResponse *resp = tx; 151 uint32_t appIdx, appVer, appSize; 152 153 if (osAppInfoById(le64toh(unaligned_u64(&req->appId)), &appIdx, &appVer, &appSize)) { 154 resp->appVer = htole32(appVer); 155 return sizeof(*resp); 156 } 157 158 return 0; 159 } 160 161 static uint32_t queryAppInfo(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 162 { 163 struct NanohubAppInfoRequest *req = rx; 164 struct NanohubAppInfoResponse *resp = tx; 165 uint64_t appId; 166 uint32_t appVer, appSize; 167 168 if (osAppInfoByIndex(le32toh(unaligned_u32(&req->appIdx)), &appId, &appVer, &appSize)) { 169 resp->appId = htole64(appId); 170 resp->appVer = htole32(appVer); 171 resp->appSize = htole32(appSize); 172 return sizeof(*resp); 173 } 174 175 return 0; 176 } 177 178 static AppSecErr writeCbk(const void *data, uint32_t len) 179 { 180 AppSecErr ret = APP_SEC_BAD; 181 182 if (osWriteShared((uint8_t*)(mDownloadState->start) + mDownloadState->dstOffset, data, len)) { 183 ret = APP_SEC_NO_ERROR; 184 mDownloadState->dstOffset += len; 185 } 186 187 return ret; 188 } 189 190 static AppSecErr pubKeyFindCbk(const uint32_t *gotKey, bool *foundP) 191 { 192 const uint32_t *ptr; 193 uint32_t numKeys, i; 194 195 *foundP = false; 196 ptr = BL.blGetPubKeysInfo(&numKeys); 197 for (i = 0; ptr && i < numKeys; i++, ptr += RSA_LIMBS) { 198 if (!memcmp(gotKey, ptr, RSA_BYTES)) { 199 *foundP = true; 200 break; 201 } 202 } 203 204 return APP_SEC_NO_ERROR; 205 } 206 207 static AppSecErr osSecretKeyLookup(uint64_t keyId, void *keyBuf) 208 { 209 struct SeosEedataEncrKeyData kd; 210 void *state = NULL; 211 212 while(1) { 213 uint32_t sz = sizeof(struct SeosEedataEncrKeyData); 214 215 if (!eeDataGetAllVersions(EE_DATA_NAME_ENCR_KEY, &kd, &sz, &state)) 216 break; 217 218 if (sz == sizeof(struct SeosEedataEncrKeyData) && kd.keyID == keyId) { 219 if (keyBuf) 220 memcpy(keyBuf, kd.key, sizeof(kd.key)); 221 return APP_SEC_NO_ERROR; 222 } 223 } 224 225 return APP_SEC_KEY_NOT_FOUND; 226 } 227 228 static AppSecErr osSecretKeyDelete(uint64_t keyId) 229 { 230 struct SeosEedataEncrKeyData kd; 231 void *state = NULL; 232 bool good = true; 233 int count = 0; 234 235 while(1) { 236 uint32_t sz = sizeof(struct SeosEedataEncrKeyData); 237 void *addr = eeDataGetAllVersions(EE_DATA_NAME_ENCR_KEY, &kd, &sz, &state); 238 239 if (!addr) 240 break; 241 242 if (sz == sizeof(kd) && kd.keyID == keyId) { 243 good = eeDataEraseOldVersion(EE_DATA_NAME_ENCR_KEY, addr) && good; 244 count++; 245 } 246 } 247 248 return count == 0 ? APP_SEC_KEY_NOT_FOUND : good ? APP_SEC_NO_ERROR : APP_SEC_BAD; 249 } 250 251 static AppSecErr osSecretKeyAdd(uint64_t keyId, void *keyBuf) 252 { 253 struct SeosEedataEncrKeyData kd; 254 255 // do not add key if it already exists 256 if (osSecretKeyLookup(keyId, NULL) != APP_SEC_KEY_NOT_FOUND) 257 return APP_SEC_BAD; 258 259 memcpy(&kd.key, keyBuf, 32); 260 kd.keyID = keyId; 261 262 return eeDataSet(EE_DATA_NAME_ENCR_KEY, &kd, sizeof(kd)) ? APP_SEC_NO_ERROR : APP_SEC_BAD; 263 } 264 265 static void freeDownloadState() 266 { 267 if (mDownloadState->appSecState) 268 appSecDeinit(mDownloadState->appSecState); 269 heapFree(mDownloadState); 270 mDownloadState = NULL; 271 } 272 273 static bool resetDownloadState(bool initial, bool erase) 274 { 275 bool doCreate = true; 276 277 mAppSecStatus = APP_SEC_NO_ERROR; 278 if (mDownloadState->appSecState) 279 appSecDeinit(mDownloadState->appSecState); 280 mDownloadState->appSecState = appSecInit(writeCbk, pubKeyFindCbk, osSecretKeyLookup, REQUIRE_SIGNED_IMAGE); 281 mDownloadState->srcOffset = 0; 282 mDownloadState->srcCrc = ~0; 283 if (!initial) { 284 // if no data was written, we can reuse the same segment 285 if (mDownloadState->dstOffset) 286 osAppSegmentClose(mDownloadState->start, mDownloadState->dstOffset, SEG_ST_ERASED); 287 else 288 doCreate = false; 289 } 290 mDownloadState->dstOffset = 0; 291 if (doCreate) 292 mDownloadState->start = osAppSegmentCreate(mDownloadState->size); 293 if (!mDownloadState->start) { 294 if (erase) 295 mDownloadState->erase = true; 296 else 297 return false; 298 } 299 return true; 300 } 301 302 static bool doStartFirmwareUpload(struct NanohubStartFirmwareUploadRequest *req, bool erase) 303 { 304 if (!mDownloadState) { 305 mDownloadState = heapAlloc(sizeof(struct DownloadState)); 306 307 if (!mDownloadState) 308 return false; 309 else 310 memset(mDownloadState, 0x00, sizeof(struct DownloadState)); 311 } 312 313 mDownloadState->size = le32toh(req->size); 314 mDownloadState->crc = le32toh(req->crc); 315 mDownloadState->chunkReply = NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED; 316 return resetDownloadState(true, erase); 317 } 318 319 static uint32_t startFirmwareUpload(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 320 { 321 struct NanohubStartFirmwareUploadRequest *req = rx; 322 struct NanohubStartFirmwareUploadResponse *resp = tx; 323 324 resp->accepted = doStartFirmwareUpload(req, true); 325 326 return sizeof(*resp); 327 } 328 329 static void deferredUpdateOs(void *cookie) 330 { 331 const struct AppHdr *app = cookie; 332 struct OsUpdateHdr *os = (struct OsUpdateHdr *)(&(app->hdr) + 1); 333 uint32_t uploadStatus = OS_UPDT_HDR_CHECK_FAILED; 334 uint8_t marker = OS_UPDT_MARKER_DOWNLOADED; 335 struct Segment *seg = osGetSegment(app); 336 uint32_t segSize = osSegmentGetSize(seg); 337 338 osLog(LOG_INFO, "%s: checking OS image @ %p\n", __func__, os); 339 // some sanity checks before asking BL to do image lookup 340 hostIntfSetBusy(true); 341 if (segSize >= (sizeof(*app) + sizeof(*os)) && segSize > os->size) { 342 if (osWriteShared(&os->marker, &marker, sizeof(os->marker))) { 343 wdtDisableClk(); 344 uploadStatus = BL.blVerifyOsUpdate(); 345 wdtEnableClk(); 346 } else { 347 osLog(LOG_ERROR, "%s: could not set marker on OS image\n", __func__); 348 } 349 } 350 hostIntfSetBusy(false); 351 osLog(LOG_INFO, "%s: status=%" PRIu32 "\n", __func__, uploadStatus); 352 } 353 354 static AppSecErr updateKey(const struct AppHdr *app) 355 { 356 AppSecErr ret; 357 struct KeyInfo *ki = (struct KeyInfo *)(&(app->hdr) + 1); 358 uint8_t *data = (uint8_t *)(ki + 1); 359 uint64_t keyId = KEY_ID_MAKE(APP_ID_GET_VENDOR(app->hdr.appId), ki->id); 360 const char *op; 361 362 if ((app->hdr.fwFlags & FL_KEY_HDR_DELETE) != 0) { 363 // removing existing key 364 ret = osSecretKeyDelete(keyId); 365 op = "Removing"; 366 } else { 367 // adding new key 368 ret = osSecretKeyAdd(keyId, data); 369 op = "Adding"; 370 } 371 osLog(LOG_INFO, "%s: %s key: id=%016" PRIX64 "; ret=%" PRIu32 "\n", 372 __func__, op, keyId, ret); 373 374 return ret; 375 } 376 377 static uint32_t appSecErrToNanohubReply(AppSecErr status) 378 { 379 uint32_t reply; 380 381 switch (status) { 382 case APP_SEC_NO_ERROR: 383 reply = NANOHUB_FIRMWARE_UPLOAD_SUCCESS; 384 break; 385 case APP_SEC_KEY_NOT_FOUND: 386 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_KEY_NOT_FOUND; 387 break; 388 case APP_SEC_HEADER_ERROR: 389 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_HEADER_ERROR; 390 break; 391 case APP_SEC_TOO_MUCH_DATA: 392 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_TOO_MUCH_DATA; 393 break; 394 case APP_SEC_TOO_LITTLE_DATA: 395 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_TOO_LITTLE_DATA; 396 break; 397 case APP_SEC_SIG_VERIFY_FAIL: 398 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_SIG_VERIFY_FAIL; 399 break; 400 case APP_SEC_SIG_DECODE_FAIL: 401 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_SIG_DECODE_FAIL; 402 break; 403 case APP_SEC_SIG_ROOT_UNKNOWN: 404 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_SIG_ROOT_UNKNOWN; 405 break; 406 case APP_SEC_MEMORY_ERROR: 407 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_MEMORY_ERROR; 408 break; 409 case APP_SEC_INVALID_DATA: 410 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_INVALID_DATA; 411 break; 412 case APP_SEC_VERIFY_FAILED: 413 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_VERIFY_FAILED; 414 break; 415 default: 416 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_BAD; 417 break; 418 } 419 return reply; 420 } 421 422 static uint32_t firmwareFinish(bool valid) 423 { 424 struct AppHdr *app; 425 struct Segment *storageSeg; 426 uint32_t segState; 427 uint32_t ret = NANOHUB_FIRMWARE_UPLOAD_SUCCESS; 428 429 if (!mDownloadState) { 430 ret = appSecErrToNanohubReply(mAppSecStatus); 431 osLog(LOG_INFO, "%s: no DL status; decoding secure status: %" PRIu32 "\n", __func__, ret); 432 return ret; 433 } 434 435 app = mDownloadState->start; 436 storageSeg = osGetSegment(app); 437 438 if (mAppSecStatus == APP_SEC_NO_ERROR && valid) { 439 osLog(LOG_INFO, "%s: Secure verification passed\n", __func__); 440 if (storageSeg->state != SEG_ST_RESERVED || 441 mDownloadState->size < sizeof(struct FwCommonHdr) || 442 app->hdr.magic != APP_HDR_MAGIC || 443 app->hdr.fwVer != APP_HDR_VER_CUR) { 444 segState = SEG_ST_ERASED; 445 osLog(LOG_INFO, "%s: Header verification failed\n", __func__); 446 } else { 447 segState = SEG_ST_VALID; 448 } 449 } else { 450 segState = SEG_ST_ERASED; 451 osLog(LOG_INFO, "%s: Secure verification failed: valid=%d; status=%" PRIu32 "\n", __func__, valid, mAppSecStatus); 452 } 453 454 if (!osAppSegmentClose(app, mDownloadState->dstOffset, segState)) { 455 osLog(LOG_INFO, "%s: Failed to close segment\n", __func__); 456 valid = false; 457 mApp = NULL; 458 } else { 459 segState = osAppSegmentGetState(app); 460 mApp = app; 461 valid = (segState == SEG_ST_VALID); 462 } 463 osLog(LOG_INFO, "Loaded %s image type %" PRIu8 ": %" PRIu32 464 " bytes @ %p; state=%02" PRIX32 "; crc=%08" PRIX32 "\n", 465 valid ? "valid" : "invalid", 466 app->hdr.payInfoType, mDownloadState->size, 467 mDownloadState->start, segState, 468 mApp ? osAppSegmentGetCrc(mApp) : 0xFFFFFFFF); 469 470 freeDownloadState(); // no more access to mDownloadState 471 472 if (!valid) 473 ret = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_BAD; 474 475 // take extra care about some special payload types 476 if (ret == NANOHUB_FIRMWARE_UPLOAD_SUCCESS) { 477 switch(app->hdr.payInfoType) { 478 case LAYOUT_OS: 479 osLog(LOG_INFO, "Performing OS update\n"); 480 // we want to give this message a chance to reach host before we start erasing stuff 481 osDefer(deferredUpdateOs, (void*)app, false); 482 break; 483 case LAYOUT_KEY: 484 ret = appSecErrToNanohubReply(updateKey(app)); 485 break; 486 } 487 } 488 489 if (ret != NANOHUB_FIRMWARE_UPLOAD_SUCCESS || (app->hdr.fwFlags & FL_APP_HDR_VOLATILE)) { 490 if ((app->hdr.fwFlags & FL_APP_HDR_SECURE)) 491 osAppWipeData((struct AppHdr*)app); 492 osAppSegmentSetState(app, SEG_ST_ERASED); 493 } 494 495 // if any error happened after we downloaded and verified image, we say it is unknown fault 496 // we don't have download status, so e have to save returned value in secure status field, because 497 // host may request the same status multiple times 498 if (ret != NANOHUB_FIRMWARE_UPLOAD_SUCCESS) 499 mAppSecStatus = APP_SEC_BAD; 500 501 return ret; 502 } 503 504 static void firmwareErase(void *cookie) 505 { 506 if (mDownloadState->erase == true) { 507 osLog(LOG_INFO, "%s: erasing shared area\n", __func__); 508 osEraseShared(); 509 mDownloadState->start = osAppSegmentCreate(mDownloadState->size); 510 if (!mDownloadState->start) 511 firmwareFinish(false); 512 mDownloadState->erase = false; 513 hostIntfSetInterrupt(NANOHUB_INT_CMD_WAIT); 514 } 515 mDownloadState->eraseScheduled = false; 516 } 517 518 SET_PACKED_STRUCT_MODE_ON 519 struct FirmwareWriteCookie 520 { 521 uint32_t evtType; 522 union { 523 #ifdef LEGACY_HAL_ENABLED 524 struct NanohubHalLegacyContUploadTx respLegacy; 525 #endif 526 struct NanohubHalContUploadTx resp; 527 }; 528 } ATTRIBUTE_PACKED; 529 SET_PACKED_STRUCT_MODE_OFF 530 531 static void writeCookieFree(void *ptr) 532 { 533 struct FirmwareWriteCookie *buf = container_of(ptr, struct FirmwareWriteCookie, resp); 534 heapFree(buf); 535 } 536 537 static void firmwareWrite(void *cookie) 538 { 539 bool valid; 540 bool finished = false; 541 struct FirmwareWriteCookie *resp = cookie; 542 // only check crc when cookie is NULL (write came from kernel, not HAL) 543 bool checkCrc = !cookie; 544 545 if (mAppSecStatus == APP_SEC_NEED_MORE_TIME) { 546 mAppSecStatus = appSecDoSomeProcessing(mDownloadState->appSecState); 547 } else if (mDownloadState->lenLeft) { 548 const uint8_t *data = mDownloadState->data + mDownloadState->len - mDownloadState->lenLeft; 549 uint32_t len = mDownloadState->lenLeft, lenLeft, lenRem = 0; 550 551 if (len > MAX_APP_SEC_RX_DATA_LEN) { 552 lenRem = len - MAX_APP_SEC_RX_DATA_LEN; 553 len = MAX_APP_SEC_RX_DATA_LEN; 554 } 555 556 mAppSecStatus = appSecRxData(mDownloadState->appSecState, data, len, &lenLeft); 557 mDownloadState->lenLeft = lenLeft + lenRem; 558 } 559 560 valid = (mAppSecStatus == APP_SEC_NO_ERROR); 561 if (mAppSecStatus == APP_SEC_NEED_MORE_TIME || mDownloadState->lenLeft) { 562 osDefer(firmwareWrite, cookie, false); 563 return; 564 } else if (valid) { 565 if (mDownloadState->srcOffset == mDownloadState->size) { 566 mAppSecStatus = appSecRxDataOver(mDownloadState->appSecState); 567 finished = true; 568 valid = !checkCrc || mDownloadState->crc == ~mDownloadState->srcCrc; 569 } else if (mDownloadState->srcOffset > mDownloadState->size) { 570 valid = false; 571 } 572 } 573 if (!valid) 574 finished = true; 575 if (finished) { 576 if (firmwareFinish(valid) != NANOHUB_FIRMWARE_UPLOAD_SUCCESS) 577 valid = false; 578 } 579 if (resp) { 580 if (resp->evtType == EVT_APP_TO_HOST) { 581 #ifdef LEGACY_HAL_ENABLED 582 resp->respLegacy.success = valid; 583 osEnqueueEvtOrFree(EVT_APP_TO_HOST, &resp->respLegacy, writeCookieFree); 584 #endif 585 } else { 586 resp->resp.ret.status = !valid; 587 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, &resp->resp, writeCookieFree); 588 } 589 } 590 } 591 592 static uint32_t doFirmwareChunk(uint8_t *data, uint32_t offset, uint32_t len, void *cookie) 593 { 594 uint32_t reply, ret; 595 596 if (!mDownloadState) { 597 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_CANCEL_NO_RETRY; 598 } else if (mAppSecStatus == APP_SEC_NEED_MORE_TIME || mDownloadState->lenLeft) { 599 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_RESEND; 600 } else if (mDownloadState->chunkReply != NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED) { 601 reply = mDownloadState->chunkReply; 602 firmwareFinish(false); 603 } else { 604 if (mDownloadState->erase == true) { 605 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_WAIT; 606 if (!mDownloadState->eraseScheduled) { 607 ret = osExtAppStopAppsByAppId(APP_ID_ANY); 608 osLog(LOG_INFO, "%s: unloaded apps, ret=%08lx\n", __func__, ret); 609 mDownloadState->eraseScheduled = osDefer(firmwareErase, NULL, false); 610 } 611 } else if (!mDownloadState->start) { 612 // this means we can't allocate enough space even after we did erase 613 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_CANCEL_NO_RETRY; 614 firmwareFinish(false); 615 } else if (offset != mDownloadState->srcOffset) { 616 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_RESTART; 617 resetDownloadState(false, true); 618 } else { 619 if (!cookie) 620 mDownloadState->srcCrc = soft_crc32(data, len, mDownloadState->srcCrc); 621 mDownloadState->srcOffset += len; 622 memcpy(mDownloadState->data, data, len); 623 mDownloadState->lenLeft = mDownloadState->len = len; 624 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED; 625 osDefer(firmwareWrite, cookie, false); 626 } 627 } 628 629 return reply; 630 } 631 632 static uint32_t firmwareChunk(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 633 { 634 struct NanohubFirmwareChunkRequest *req = rx; 635 struct NanohubFirmwareChunkResponse *resp = tx; 636 uint32_t offset = le32toh(req->offset); 637 uint8_t len = rx_len - sizeof(req->offset); 638 639 resp->chunkReply = doFirmwareChunk(req->data, offset, len, NULL); 640 641 return sizeof(*resp); 642 } 643 644 static uint32_t doFinishFirmwareUpload(uint32_t *addr, uint32_t *crc) 645 { 646 uint32_t reply; 647 648 if (!mDownloadState) { 649 reply = appSecErrToNanohubReply(mAppSecStatus); 650 if (addr) { 651 if (mApp) 652 *addr = (uint32_t)mApp; 653 else 654 *addr = 0xFFFFFFFF; 655 } 656 if (crc) { 657 if (mApp) 658 *crc = osAppSegmentGetCrc(mApp); 659 else 660 *crc = 0xFFFFFFFF; 661 } 662 } else if (mDownloadState->srcOffset == mDownloadState->size) { 663 reply = NANOHUB_FIRMWARE_UPLOAD_PROCESSING; 664 } else { 665 reply = firmwareFinish(false); 666 } 667 668 return reply; 669 } 670 671 static uint32_t finishFirmwareUpload(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 672 { 673 struct NanohubFinishFirmwareUploadResponse *resp = tx; 674 resp->uploadReply = doFinishFirmwareUpload(NULL, NULL); 675 if (resp->uploadReply != NANOHUB_FIRMWARE_UPLOAD_PROCESSING) 676 osLog(LOG_INFO, "%s: reply=%" PRIu8 "\n", __func__, resp->uploadReply); 677 return sizeof(*resp); 678 } 679 680 static uint32_t getInterrupt(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 681 { 682 struct NanohubGetInterruptRequest *req = rx; 683 struct NanohubGetInterruptResponse *resp = tx; 684 int i; 685 686 if (rx_len == sizeof(struct NanohubGetInterruptRequest)) { 687 for (i = 0; i < HOSTINTF_MAX_INTERRUPTS; i++) { 688 if (req->clear[i/32] & (1UL << (i & 31))) 689 hostIntfClearInterrupt(i); 690 } 691 } 692 693 hostIntfCopyInterrupts(resp->interrupts, HOSTINTF_MAX_INTERRUPTS); 694 695 return sizeof(*resp); 696 } 697 698 static uint32_t maskInterrupt(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 699 { 700 struct NanohubMaskInterruptRequest *req = rx; 701 struct NanohubMaskInterruptResponse *resp = tx; 702 703 hostIntfSetInterruptMask(req->interrupt); 704 705 resp->accepted = true; 706 return sizeof(*resp); 707 } 708 709 static uint32_t unmaskInterrupt(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 710 { 711 struct NanohubUnmaskInterruptRequest *req = rx; 712 struct NanohubUnmaskInterruptResponse *resp = tx; 713 714 hostIntfClearInterruptMask(req->interrupt); 715 716 resp->accepted = true; 717 return sizeof(*resp); 718 } 719 720 static void addDelta(struct ApHubSync *sync, uint64_t apTime, uint64_t hubTime) 721 { 722 #if DEBUG_APHUB_TIME_SYNC 723 syncDebugAdd(apTime, hubTime); 724 #endif 725 apHubSyncAddDelta(sync, apTime, hubTime); 726 } 727 728 static int64_t getAvgDelta(struct ApHubSync *sync) 729 { 730 return apHubSyncGetDelta(sync, sensorGetTime()); 731 } 732 733 static int fillBuffer(void *tx, uint32_t totLength, uint32_t *wakeup, uint32_t *nonwakeup) 734 { 735 struct HostIntfDataBuffer *packet = &mTxNext; 736 struct HostIntfDataBuffer *firstPacket = tx; 737 uint8_t *buf = tx; 738 uint32_t length; 739 uint32_t prevWakeup, prevNonWakeup; 740 741 prevWakeup = *wakeup; 742 prevNonWakeup = *nonwakeup; 743 744 while (hostIntfPacketDequeue(&mTxNext, wakeup, nonwakeup)) { 745 length = packet->length + sizeof(packet->evtType); 746 if (packet->sensType == SENS_TYPE_INVALID) { 747 switch (packet->dataType) { 748 case HOSTINTF_DATA_TYPE_APP_TO_HOST: 749 packet->evtType = htole32(EVT_APP_TO_HOST); 750 break; 751 case HOSTINTF_DATA_TYPE_RESET_REASON: 752 packet->evtType = htole32(EVT_RESET_REASON); 753 break; 754 case HOSTINTF_DATA_TYPE_APP_TO_SENSOR_HAL: 755 packet->evtType = htole32(EVT_APP_TO_SENSOR_HAL_DATA); 756 break; 757 #ifdef DEBUG_LOG_EVT 758 case HOSTINTF_DATA_TYPE_LOG: 759 packet->evtType = htole32(HOST_EVT_DEBUG_LOG); 760 break; 761 #endif 762 default: 763 packet->evtType = htole32(0x00000000); 764 break; 765 } 766 } else { 767 packet->evtType = htole32(EVT_NO_FIRST_SENSOR_EVENT + packet->sensType); 768 if (packet->referenceTime) 769 packet->referenceTime += getAvgDelta(&mTimeSync); 770 771 if (*wakeup > 0) 772 packet->firstSample.interrupt = NANOHUB_INT_WAKEUP; 773 } 774 775 if ((!totLength || (isSensorEvent(firstPacket->evtType) && isSensorEvent(packet->evtType))) && 776 totLength + length <= sizeof(struct HostIntfDataBuffer)) { 777 memcpy(buf + totLength, &mTxNext, length); 778 totLength += length; 779 if (isSensorEvent(packet->evtType) && packet->firstSample.interrupt == NANOHUB_INT_WAKEUP) 780 firstPacket->firstSample.interrupt = NANOHUB_INT_WAKEUP; 781 } else { 782 mTxNextLength = length; 783 *wakeup = prevWakeup; 784 *nonwakeup = prevNonWakeup; 785 break; 786 } 787 788 prevWakeup = *wakeup; 789 prevNonWakeup = *nonwakeup; 790 } 791 792 return totLength; 793 } 794 795 static void updateInterrupts(void) 796 { 797 uint32_t wakeup = atomicRead32bits(&mTxWakeCnt[0]); 798 uint32_t nonwakeup = atomicRead32bits(&mTxWakeCnt[1]); 799 bool wakeupStatus = hostIntfGetInterrupt(NANOHUB_INT_WAKEUP); 800 bool nonwakeupStatus = hostIntfGetInterrupt(NANOHUB_INT_NONWAKEUP); 801 802 if (!wakeup && wakeupStatus) 803 hostIntfClearInterrupt(NANOHUB_INT_WAKEUP); 804 else if (wakeup && !wakeupStatus) 805 hostIntfSetInterrupt(NANOHUB_INT_WAKEUP); 806 807 if (!nonwakeup && nonwakeupStatus) 808 hostIntfClearInterrupt(NANOHUB_INT_NONWAKEUP); 809 else if (nonwakeup && !nonwakeupStatus) 810 hostIntfSetInterrupt(NANOHUB_INT_NONWAKEUP); 811 } 812 813 void nanohubPrefetchTx(uint32_t interrupt, uint32_t wakeup, uint32_t nonwakeup) 814 { 815 uint64_t state; 816 817 if (wakeup < atomicRead32bits(&mTxWakeCnt[0])) 818 wakeup = atomicRead32bits(&mTxWakeCnt[0]); 819 820 if (nonwakeup < atomicRead32bits(&mTxWakeCnt[1])) 821 nonwakeup = atomicRead32bits(&mTxWakeCnt[1]); 822 823 if (interrupt == HOSTINTF_MAX_INTERRUPTS && !hostIntfGetInterrupt(NANOHUB_INT_WAKEUP) && !hostIntfGetInterrupt(NANOHUB_INT_NONWAKEUP)) 824 return; 825 826 atomicWriteByte(&mPrefetchActive, 1); 827 828 if (interrupt < HOSTINTF_MAX_INTERRUPTS) 829 hostIntfSetInterrupt(interrupt); 830 831 do { 832 if (atomicReadByte(&mTxCurrLength) == 0 && mTxNextLength > 0) { 833 memcpy(&mTxCurr, &mTxNext, mTxNextLength); 834 atomicWriteByte(&mTxCurrLength, mTxNextLength); 835 mTxNextLength = 0; 836 } 837 838 if (mTxNextLength == 0) { 839 atomicWriteByte(&mTxCurrLength, fillBuffer(&mTxCurr, atomicReadByte(&mTxCurrLength), &wakeup, &nonwakeup)); 840 atomicWrite32bits(&mTxWakeCnt[0], wakeup); 841 atomicWrite32bits(&mTxWakeCnt[1], nonwakeup); 842 } 843 844 atomicWriteByte(&mPrefetchActive, 0); 845 846 if (atomicReadByte(&mPrefetchTx)) { 847 state = cpuIntsOff(); 848 849 // interrupt occured during this call 850 // take care of it 851 hostIntfTxAck(&mTxCurr, atomicReadByte(&mTxCurrLength)); 852 atomicWriteByte(&mPrefetchTx, 0); 853 atomicWriteByte(&mTxCurrLength, 0); 854 855 cpuIntsRestore(state); 856 857 updateInterrupts(); 858 } else { 859 break; 860 } 861 } while (mTxNextLength > 0); 862 } 863 864 static void nanohubPrefetchTxDefer(void *cookie) 865 { 866 nanohubPrefetchTx(HOSTINTF_MAX_INTERRUPTS, 0, 0); 867 } 868 869 static uint32_t readEventFast(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 870 { 871 struct NanohubReadEventRequest *req = rx; 872 uint8_t ret = 0; 873 874 if (atomicReadByte(&mPrefetchActive)) { 875 atomicWriteByte(&mPrefetchTx, 1); 876 return NANOHUB_FAST_DONT_ACK; 877 } else { 878 if ((ret = atomicReadByte(&mTxCurrLength))) { 879 addDelta(&mTimeSync, req->apBootTime, timestamp); 880 881 memcpy(tx, &mTxCurr, ret); 882 atomicWriteByte(&mTxCurrLength, 0); 883 884 updateInterrupts(); 885 osDefer(nanohubPrefetchTxDefer, NULL, true); 886 } else { 887 return NANOHUB_FAST_UNHANDLED_ACK; 888 } 889 } 890 891 return ret; 892 } 893 894 static uint32_t readEvent(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 895 { 896 struct NanohubReadEventRequest *req = rx; 897 uint8_t *buf = tx; 898 uint32_t length, wakeup, nonwakeup; 899 uint32_t totLength = 0; 900 901 addDelta(&mTimeSync, req->apBootTime, timestamp); 902 903 if ((totLength = atomicReadByte(&mTxCurrLength))) { 904 memcpy(tx, &mTxCurr, totLength); 905 atomicWriteByte(&mTxCurrLength, 0); 906 updateInterrupts(); 907 return totLength; 908 } 909 910 wakeup = atomicRead32bits(&mTxWakeCnt[0]); 911 nonwakeup = atomicRead32bits(&mTxWakeCnt[1]); 912 913 if (mTxNextLength > 0) { 914 length = mTxNextLength; 915 memcpy(buf, &mTxNext, length); 916 totLength = length; 917 mTxNextLength = 0; 918 } 919 920 totLength = fillBuffer(buf, totLength, &wakeup, &nonwakeup); 921 atomicWrite32bits(&mTxWakeCnt[0], wakeup); 922 atomicWrite32bits(&mTxWakeCnt[1], nonwakeup); 923 924 if (totLength) { 925 updateInterrupts(); 926 } else { 927 hostIntfClearInterrupt(NANOHUB_INT_WAKEUP); 928 hostIntfClearInterrupt(NANOHUB_INT_NONWAKEUP); 929 } 930 931 return totLength; 932 } 933 934 static bool forwardPacket(uint32_t event, void *data, size_t data_size, 935 void *hdr, size_t hdr_size, uint32_t tid) 936 { 937 bool res; 938 uint8_t *hostPacket = data; 939 uint8_t *packet = slabAllocatorAlloc(mEventSlab); 940 EventFreeF free = slabFree; 941 942 if (!packet) { 943 packet = heapAlloc(data_size + hdr_size); 944 free = heapFree; 945 } 946 if (!packet) 947 return false; 948 949 if (hdr && hdr_size) 950 memcpy(packet, hdr, hdr_size); 951 952 memcpy(packet + hdr_size, hostPacket, data_size); 953 if (tid) { 954 // send to specific TID 955 res = osEnqueuePrivateEvt(event, packet, free, tid); 956 if (!res) 957 free(packet); 958 } else { 959 // broadcast to all 960 res = osEnqueueEvtOrFree(event, packet, free); 961 } 962 963 return res; 964 } 965 966 static uint32_t writeEvent(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 967 { 968 struct NanohubWriteEventRequest *req = rx; 969 struct NanohubWriteEventResponse *resp = tx; 970 uint32_t tid; 971 uint32_t event = le32toh(req->evtType); 972 973 if (event == EVT_APP_FROM_HOST) { 974 // old version of HAL; message_type is not delivered to CHRE apps 975 struct HostMsgHdr *hostPacket = rx; 976 if (rx_len >= sizeof(struct HostMsgHdr) && 977 rx_len == sizeof(struct HostMsgHdr) + hostPacket->len && 978 osTidById(&hostPacket->appId, &tid)) { 979 resp->accepted = forwardPacket(event, hostPacket + 1, hostPacket->len, 980 &hostPacket->len, sizeof(hostPacket->len), tid); 981 } else { 982 resp->accepted = false; 983 } 984 } else if (event == EVT_APP_FROM_HOST_CHRE) { 985 // new version of HAL; full support for CHRE apps 986 struct HostMsgHdrChreV10 *hostPacketV10 = rx; 987 struct HostMsgHdrChre *hostPacket = rx; 988 if (rx_len >= sizeof(struct HostMsgHdrChre) && 989 rx_len == sizeof(struct HostMsgHdrChre) + hostPacket->len && 990 osTidById(&hostPacket->appId, &tid)) { 991 if (osAppChreVersion(tid) >= CHRE_API_VERSION_1_1) { 992 struct NanohubMsgChreHdr hdr = { 993 .size = hostPacket->len, 994 .endpoint = hostPacket->endpoint, 995 .appEvent = hostPacket->appEventId, 996 }; 997 // CHRE app receives message in new format 998 resp->accepted = forwardPacket(event, hostPacket + 1, hostPacket->len, 999 &hdr, sizeof(hdr), tid); 1000 } else if (osAppChreVersion(tid) == CHRE_API_VERSION_1_0) { 1001 struct NanohubMsgChreHdrV10 hdr = { 1002 .size = hostPacket->len, 1003 .appEvent = hostPacket->appEventId, 1004 }; 1005 // CHRE app receives message in new format 1006 resp->accepted = forwardPacket(event, hostPacket + 1, hostPacket->len, 1007 &hdr, sizeof(hdr), tid); 1008 } else { 1009 // legacy app receives message in old format 1010 resp->accepted = forwardPacket(EVT_APP_FROM_HOST, hostPacket + 1, hostPacket->len, 1011 &hostPacket->len, sizeof(hostPacket->len), tid); 1012 } 1013 } else if (rx_len >= sizeof(struct HostMsgHdrChreV10) && 1014 rx_len == sizeof(struct HostMsgHdrChreV10) + hostPacketV10->len && 1015 osTidById(&hostPacketV10->appId, &tid)) { 1016 if (osAppChreVersion(tid) >= CHRE_API_VERSION_1_1) { 1017 struct NanohubMsgChreHdr hdr = { 1018 .size = hostPacketV10->len, 1019 .endpoint = CHRE_HOST_ENDPOINT_UNSPECIFIED, 1020 .appEvent = hostPacketV10->appEventId, 1021 }; 1022 // CHRE app receives message in new format 1023 resp->accepted = forwardPacket(event, hostPacketV10 + 1, hostPacketV10->len, 1024 &hdr, sizeof(hdr), tid); 1025 } else if (osAppChreVersion(tid) == CHRE_API_VERSION_1_0) { 1026 struct NanohubMsgChreHdrV10 hdr = { 1027 .size = hostPacketV10->len, 1028 .appEvent = hostPacketV10->appEventId, 1029 }; 1030 // CHRE app receives message in new format 1031 resp->accepted = forwardPacket(event, hostPacketV10 + 1, hostPacketV10->len, 1032 &hdr, sizeof(hdr), tid); 1033 } else { 1034 // legacy app receives message in old format 1035 resp->accepted = forwardPacket(EVT_APP_FROM_HOST, hostPacketV10 + 1, hostPacketV10->len, 1036 &hostPacketV10->len, sizeof(hostPacketV10->len), tid); 1037 } 1038 } else { 1039 resp->accepted = false; 1040 } 1041 } else { 1042 resp->accepted = forwardPacket(event, 1043 req->evtData, rx_len - sizeof(req->evtType), 1044 NULL, 0, 0); 1045 } 1046 1047 return sizeof(*resp); 1048 } 1049 1050 const static struct NanohubCommand mBuiltinCommands[] = { 1051 NANOHUB_COMMAND(NANOHUB_REASON_GET_OS_HW_VERSIONS, 1052 getOsHwVersion, 1053 getOsHwVersion, 1054 struct NanohubOsHwVersionsRequest, 1055 struct NanohubOsHwVersionsRequest), 1056 NANOHUB_COMMAND(NANOHUB_REASON_GET_APP_VERSIONS, 1057 NULL, 1058 getAppVersion, 1059 struct NanohubAppVersionsRequest, 1060 struct NanohubAppVersionsRequest), 1061 NANOHUB_COMMAND(NANOHUB_REASON_QUERY_APP_INFO, 1062 NULL, 1063 queryAppInfo, 1064 struct NanohubAppInfoRequest, 1065 struct NanohubAppInfoRequest), 1066 NANOHUB_COMMAND(NANOHUB_REASON_START_FIRMWARE_UPLOAD, 1067 NULL, 1068 startFirmwareUpload, 1069 struct NanohubStartFirmwareUploadRequest, 1070 struct NanohubStartFirmwareUploadRequest), 1071 NANOHUB_COMMAND(NANOHUB_REASON_FIRMWARE_CHUNK, 1072 NULL, 1073 firmwareChunk, 1074 __le32, 1075 struct NanohubFirmwareChunkRequest), 1076 NANOHUB_COMMAND(NANOHUB_REASON_FINISH_FIRMWARE_UPLOAD, 1077 NULL, 1078 finishFirmwareUpload, 1079 struct NanohubFinishFirmwareUploadRequest, 1080 struct NanohubFinishFirmwareUploadRequest), 1081 NANOHUB_COMMAND(NANOHUB_REASON_GET_INTERRUPT, 1082 getInterrupt, 1083 getInterrupt, 1084 struct { }, 1085 struct NanohubGetInterruptRequest), 1086 NANOHUB_COMMAND(NANOHUB_REASON_MASK_INTERRUPT, 1087 maskInterrupt, 1088 maskInterrupt, 1089 struct NanohubMaskInterruptRequest, 1090 struct NanohubMaskInterruptRequest), 1091 NANOHUB_COMMAND(NANOHUB_REASON_UNMASK_INTERRUPT, 1092 unmaskInterrupt, 1093 unmaskInterrupt, 1094 struct NanohubUnmaskInterruptRequest, 1095 struct NanohubUnmaskInterruptRequest), 1096 NANOHUB_COMMAND(NANOHUB_REASON_READ_EVENT, 1097 readEventFast, 1098 readEvent, 1099 struct NanohubReadEventRequest, 1100 struct NanohubReadEventRequest), 1101 NANOHUB_COMMAND(NANOHUB_REASON_WRITE_EVENT, 1102 writeEvent, 1103 writeEvent, 1104 __le32, 1105 struct NanohubWriteEventRequest), 1106 }; 1107 1108 const struct NanohubCommand *nanohubFindCommand(uint32_t packetReason) 1109 { 1110 uint32_t i; 1111 1112 for (i = 0; i < ARRAY_SIZE(mBuiltinCommands); i++) { 1113 const struct NanohubCommand *cmd = &mBuiltinCommands[i]; 1114 if (cmd->reason == packetReason) 1115 return cmd; 1116 } 1117 return NULL; 1118 } 1119 1120 #ifdef LEGACY_HAL_ENABLED 1121 1122 static void halSendLegacyMgmtResponse(uint32_t cmd, uint32_t status) 1123 { 1124 struct NanohubHalLegacyMgmtTx *resp; 1125 1126 resp = heapAlloc(sizeof(*resp)); 1127 if (resp) { 1128 resp->hdr = (struct NanohubHalLegacyHdr) { 1129 .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 1130 .len = sizeof(*resp) - sizeof(resp->hdr) + sizeof(resp->hdr.msg), 1131 .msg = cmd, 1132 }; 1133 resp->status = htole32(status); 1134 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1135 } 1136 } 1137 1138 static void halLegacyExtAppsOn(void *rx, uint8_t rx_len) 1139 { 1140 struct NanohubHalLegacyMgmtRx *req = rx; 1141 1142 halSendLegacyMgmtResponse(NANOHUB_HAL_LEGACY_EXT_APPS_ON, osExtAppStartAppsByAppId(le64toh(unaligned_u64(&req->appId)))); 1143 } 1144 1145 static void halLegacyExtAppsOff(void *rx, uint8_t rx_len) 1146 { 1147 struct NanohubHalLegacyMgmtRx *req = rx; 1148 1149 halSendLegacyMgmtResponse(NANOHUB_HAL_LEGACY_EXT_APPS_OFF, osExtAppStopAppsByAppId(le64toh(unaligned_u64(&req->appId)))); 1150 } 1151 1152 static void halLegacyExtAppDelete(void *rx, uint8_t rx_len) 1153 { 1154 struct NanohubHalLegacyMgmtRx *req = rx; 1155 1156 halSendLegacyMgmtResponse(NANOHUB_HAL_LEGACY_EXT_APP_DELETE, osExtAppEraseAppsByAppId(le64toh(unaligned_u64(&req->appId)))); 1157 } 1158 1159 static void halLegacyQueryMemInfo(void *rx, uint8_t rx_len) 1160 { 1161 } 1162 1163 static void halLegacyQueryApps(void *rx, uint8_t rx_len) 1164 { 1165 struct NanohubHalLegacyQueryAppsRx *req = rx; 1166 struct NanohubHalLegacyQueryAppsTx *resp; 1167 struct NanohubHalLegacyHdr *hdr; 1168 uint64_t appId; 1169 uint32_t appVer, appSize; 1170 1171 if (osExtAppInfoByIndex(le32toh(req->idx), &appId, &appVer, &appSize)) { 1172 resp = heapAlloc(sizeof(*resp)); 1173 if (resp) { 1174 resp->hdr.appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 1175 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalLegacyHdr) + 1; 1176 resp->hdr.msg = NANOHUB_HAL_LEGACY_QUERY_APPS; 1177 resp->appId = appId; 1178 resp->version = appVer; 1179 resp->flashUse = appSize; 1180 resp->ramUse = 0; 1181 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1182 } 1183 } else { 1184 hdr = heapAlloc(sizeof(*hdr)); 1185 if (hdr) { 1186 hdr->appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 1187 hdr->len = 1; 1188 hdr->msg = NANOHUB_HAL_LEGACY_QUERY_APPS; 1189 osEnqueueEvtOrFree(EVT_APP_TO_HOST, hdr, heapFree); 1190 } 1191 } 1192 } 1193 1194 static void halLegacyQueryRsaKeys(void *rx, uint8_t rx_len) 1195 { 1196 struct NanohubHalLegacyQueryRsaKeysRx *req = rx; 1197 struct NanohubHalLegacyQueryRsaKeysTx *resp; 1198 int len = 0; 1199 const uint32_t *ptr; 1200 uint32_t numKeys; 1201 1202 if (!(resp = heapAlloc(sizeof(*resp) + NANOHUB_RSA_KEY_CHUNK_LEN))) 1203 return; 1204 1205 ptr = BL.blGetPubKeysInfo(&numKeys); 1206 if (ptr && numKeys * RSA_BYTES > req->offset) { 1207 len = numKeys * RSA_BYTES - req->offset; 1208 if (len > NANOHUB_RSA_KEY_CHUNK_LEN) 1209 len = NANOHUB_RSA_KEY_CHUNK_LEN; 1210 memcpy(resp->data, (uint8_t *)ptr + req->offset, len); 1211 } 1212 1213 resp->hdr.appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 1214 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalLegacyHdr) + 1 + len; 1215 resp->hdr.msg = NANOHUB_HAL_LEGACY_QUERY_RSA_KEYS; 1216 1217 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1218 } 1219 1220 static void halLegacyStartUpload(void *rx, uint8_t rx_len) 1221 { 1222 struct NanohubHalLegacyStartUploadRx *req = rx; 1223 struct NanohubStartFirmwareUploadRequest hwReq = { 1224 .size = req->length 1225 }; 1226 struct NanohubHalLegacyStartUploadTx *resp; 1227 1228 if (!(resp = heapAlloc(sizeof(*resp)))) 1229 return; 1230 1231 resp->hdr.appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 1232 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalLegacyHdr) + 1; 1233 resp->hdr.msg = NANOHUB_HAL_LEGACY_START_UPLOAD; 1234 resp->success = doStartFirmwareUpload(&hwReq, true); 1235 1236 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1237 } 1238 1239 static void halLegacyContUpload(void *rx, uint8_t rx_len) 1240 { 1241 uint32_t offset; 1242 uint32_t reply; 1243 uint8_t len; 1244 struct NanohubHalLegacyContUploadRx *req = rx; 1245 struct FirmwareWriteCookie *cookie; 1246 1247 if (!(cookie = heapAlloc(sizeof(*cookie)))) 1248 return; 1249 1250 cookie->evtType = EVT_APP_TO_HOST; 1251 cookie->respLegacy.hdr = (struct NanohubHalLegacyHdr) { 1252 .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 1253 .len = sizeof(cookie->respLegacy) - sizeof(struct NanohubHalLegacyHdr) + 1, 1254 .msg = NANOHUB_HAL_LEGACY_CONT_UPLOAD, 1255 }; 1256 cookie->respLegacy.success = false; 1257 1258 if (!mDownloadState) { 1259 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_CANCEL_NO_RETRY; 1260 } else { 1261 offset = le32toh(req->offset); 1262 len = rx_len - sizeof(req->offset); 1263 reply = doFirmwareChunk(req->data, offset, len, cookie); 1264 } 1265 if (reply != NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED) { 1266 osLog(LOG_ERROR, "%s: reply=%" PRIu32 "\n", __func__, reply); 1267 1268 osEnqueueEvtOrFree(EVT_APP_TO_HOST, &cookie->respLegacy, writeCookieFree); 1269 } 1270 } 1271 1272 static void halLegacyFinishUpload(void *rx, uint8_t rx_len) 1273 { 1274 struct NanohubHalLegacyFinishUploadTx *resp; 1275 uint32_t reply; 1276 1277 if (!(resp = heapAlloc(sizeof(*resp)))) 1278 return; 1279 1280 resp->hdr.appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 1281 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalLegacyHdr) + 1; 1282 resp->hdr.msg = NANOHUB_HAL_LEGACY_FINISH_UPLOAD; 1283 1284 reply = doFinishFirmwareUpload(NULL, NULL); 1285 1286 osLog(LOG_INFO, "%s: reply=%" PRIu32 "\n", __func__, reply); 1287 1288 resp->success = (reply == NANOHUB_FIRMWARE_UPLOAD_SUCCESS); 1289 1290 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1291 } 1292 1293 static void halLegacyReboot(void *rx, uint8_t rx_len) 1294 { 1295 BL.blReboot(); 1296 } 1297 1298 const static struct NanohubHalLegacyCommand mBuiltinHalLegacyCommands[] = { 1299 NANOHUB_HAL_LEGACY_COMMAND(NANOHUB_HAL_LEGACY_EXT_APPS_ON, 1300 halLegacyExtAppsOn), 1301 NANOHUB_HAL_LEGACY_COMMAND(NANOHUB_HAL_LEGACY_EXT_APPS_OFF, 1302 halLegacyExtAppsOff), 1303 NANOHUB_HAL_LEGACY_COMMAND(NANOHUB_HAL_LEGACY_EXT_APP_DELETE, 1304 halLegacyExtAppDelete), 1305 NANOHUB_HAL_LEGACY_COMMAND(NANOHUB_HAL_LEGACY_QUERY_MEMINFO, 1306 halLegacyQueryMemInfo), 1307 NANOHUB_HAL_LEGACY_COMMAND(NANOHUB_HAL_LEGACY_QUERY_APPS, 1308 halLegacyQueryApps), 1309 NANOHUB_HAL_LEGACY_COMMAND(NANOHUB_HAL_LEGACY_QUERY_RSA_KEYS, 1310 halLegacyQueryRsaKeys), 1311 NANOHUB_HAL_LEGACY_COMMAND(NANOHUB_HAL_LEGACY_START_UPLOAD, 1312 halLegacyStartUpload), 1313 NANOHUB_HAL_LEGACY_COMMAND(NANOHUB_HAL_LEGACY_CONT_UPLOAD, 1314 halLegacyContUpload), 1315 NANOHUB_HAL_LEGACY_COMMAND(NANOHUB_HAL_LEGACY_FINISH_UPLOAD, 1316 halLegacyFinishUpload), 1317 NANOHUB_HAL_LEGACY_COMMAND(NANOHUB_HAL_LEGACY_REBOOT, 1318 halLegacyReboot), 1319 }; 1320 1321 const struct NanohubHalLegacyCommand *nanohubHalLegacyFindCommand(uint8_t msg) 1322 { 1323 uint32_t i; 1324 1325 for (i = 0; i < ARRAY_SIZE(mBuiltinHalLegacyCommands); i++) { 1326 const struct NanohubHalLegacyCommand *cmd = &mBuiltinHalLegacyCommands[i]; 1327 if (cmd->msg == msg) 1328 return cmd; 1329 } 1330 return NULL; 1331 } 1332 1333 #endif /* LEGACY_HAL_ENABLED */ 1334 1335 static void halSendAppMgmtResponse(struct NanohubHalAppMgmtRx *req, uint32_t status, struct MgmtStatus stat, uint32_t transactionId) 1336 { 1337 struct NanohubHalAppMgmtTx *resp; 1338 1339 resp = heapAlloc(sizeof(*resp)); 1340 if (resp) { 1341 resp->hdr = (struct NanohubHalHdr) { 1342 .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 1343 .len = sizeof(*resp) - sizeof(resp->hdr), 1344 .transactionId = transactionId, 1345 }; 1346 resp->ret = (struct NanohubHalRet) { 1347 .msg = NANOHUB_HAL_APP_MGMT, 1348 .status = htole32(status), 1349 }; 1350 resp->cmd = req->cmd; 1351 resp->stat = stat; 1352 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1353 } 1354 } 1355 1356 static void halAppMgmt(void *rx, uint8_t rx_len, uint32_t transactionId) 1357 { 1358 struct NanohubHalAppMgmtRx *req = rx; 1359 struct MgmtStatus stat; 1360 uint32_t ret; 1361 1362 switch (req->cmd) { 1363 case NANOHUB_HAL_APP_MGMT_START: 1364 stat.value= osExtAppStartAppsByAppId(le64toh(unaligned_u64(&req->appId))); 1365 ret = stat.op > 0 ? 0 : -1; 1366 break; 1367 case NANOHUB_HAL_APP_MGMT_STOP: 1368 stat.value = osExtAppStopAppsByAppId(le64toh(unaligned_u64(&req->appId))); 1369 ret = stat.op > 0 ? 0 : -1; 1370 break; 1371 case NANOHUB_HAL_APP_MGMT_UNLOAD: 1372 stat.value = osExtAppStopAppsByAppId(le64toh(unaligned_u64(&req->appId))); 1373 ret = stat.op > 0 ? 0 : -1; 1374 break; 1375 case NANOHUB_HAL_APP_MGMT_DELETE: 1376 stat.value = osExtAppEraseAppsByAppId(le64toh(unaligned_u64(&req->appId))); 1377 ret = stat.erase > 0 ? 0 : -1; 1378 break; 1379 default: 1380 return; 1381 } 1382 1383 halSendAppMgmtResponse(req, ret, stat, transactionId); 1384 } 1385 1386 static void deferHalSysMgmtErase(void *cookie) 1387 { 1388 struct NanohubHalSysMgmtTx *resp = cookie; 1389 1390 bool success = osEraseShared(); 1391 1392 if (success) 1393 resp->ret.status = htole32(0); 1394 else 1395 resp->ret.status = htole32(-1); 1396 1397 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1398 } 1399 1400 static void halSysMgmt(void *rx, uint8_t rx_len, uint32_t transactionId) 1401 { 1402 struct NanohubHalSysMgmtRx *req = rx; 1403 struct NanohubHalSysMgmtTx *resp; 1404 uint32_t ret = 0; 1405 1406 if (!(resp = heapAlloc(sizeof(*resp)))) 1407 return; 1408 1409 resp->hdr = (struct NanohubHalHdr) { 1410 .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 1411 .len = sizeof(*resp) - sizeof(resp->hdr), 1412 .transactionId = transactionId, 1413 }; 1414 resp->ret = (struct NanohubHalRet) { 1415 .msg = NANOHUB_HAL_SYS_MGMT, 1416 }; 1417 resp->cmd = req->cmd; 1418 1419 switch (req->cmd) { 1420 case NANOHUB_HAL_SYS_MGMT_ERASE: 1421 ret = osExtAppStopAppsByAppId(APP_ID_ANY); 1422 osLog(LOG_INFO, "%s: unloaded apps, ret=%08lx\n", __func__, ret); 1423 // delay to make sure all apps are unloaded before erasing 1424 if (osDefer(deferHalSysMgmtErase, resp, false) == false) { 1425 resp->ret.status = htole32(-1); 1426 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1427 } 1428 break; 1429 case NANOHUB_HAL_SYS_MGMT_REBOOT: 1430 BL.blReboot(); 1431 break; 1432 default: 1433 resp->ret.status = htole32(-1); 1434 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1435 } 1436 } 1437 1438 static bool copyTLV64(uint8_t *buf, size_t *offset, size_t max_len, uint8_t tag, uint64_t val) 1439 { 1440 if (*offset + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint64_t) > max_len) 1441 return false; 1442 buf[(*offset)++] = tag; 1443 buf[(*offset)++] = sizeof(uint64_t); 1444 memcpy(&buf[*offset], &val, sizeof(uint64_t)); 1445 *offset += sizeof(uint64_t); 1446 return true; 1447 } 1448 1449 static bool copyTLV32(uint8_t *buf, size_t *offset, size_t max_len, uint8_t tag, uint32_t val) 1450 { 1451 if (*offset + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint32_t) > max_len) 1452 return false; 1453 buf[(*offset)++] = tag; 1454 buf[(*offset)++] = sizeof(uint32_t); 1455 memcpy(&buf[*offset], &val, sizeof(uint32_t)); 1456 *offset += sizeof(uint32_t); 1457 return true; 1458 } 1459 1460 static bool copyTLV8(uint8_t *buf, size_t *offset, size_t max_len, uint8_t tag, uint8_t val) 1461 { 1462 if (*offset + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint8_t) > max_len) 1463 return false; 1464 buf[(*offset)++] = tag; 1465 buf[(*offset)++] = sizeof(uint8_t); 1466 memcpy(&buf[*offset], &val, sizeof(uint8_t)); 1467 *offset += sizeof(uint8_t); 1468 return true; 1469 } 1470 1471 static bool copyTLVEmpty(uint8_t *buf, size_t *offset, size_t max_len, uint8_t tag) 1472 { 1473 if (*offset + sizeof(uint8_t) + sizeof(uint8_t) > max_len) 1474 return false; 1475 buf[(*offset)++] = tag; 1476 buf[(*offset)++] = 0; 1477 return true; 1478 } 1479 1480 static int processAppTags(const struct AppHdr *app, uint32_t crc, uint32_t size, uint8_t *data, uint8_t *tags, int cnt, bool req_tid) 1481 { 1482 int i; 1483 size_t offset = 0; 1484 const size_t max_len = HOST_HUB_CHRE_PACKET_MAX_LEN - sizeof(struct NanohubHalRet); 1485 bool success = true; 1486 uint32_t tid; 1487 bool tid_valid = false; 1488 struct Task *task; 1489 1490 if (app->hdr.magic != APP_HDR_MAGIC || 1491 app->hdr.fwVer != APP_HDR_VER_CUR || 1492 (app->hdr.fwFlags & FL_APP_HDR_APPLICATION) == 0 || 1493 app->hdr.payInfoType != LAYOUT_APP) { 1494 return 0; 1495 } 1496 1497 if (osTidById(&app->hdr.appId, &tid)) { 1498 tid_valid = true; 1499 task = osTaskFindByTid(tid); 1500 if (task) { 1501 if (task->app != app) 1502 tid_valid = false; 1503 } else 1504 tid_valid = false; 1505 } 1506 1507 if (!tid_valid && req_tid) 1508 return 0; 1509 1510 for (i=0; i<cnt && success; i++) { 1511 switch(tags[i]) { 1512 case NANOHUB_HAL_APP_INFO_APPID: 1513 success = copyTLV64(data, &offset, max_len, tags[i], app->hdr.appId); 1514 break; 1515 case NANOHUB_HAL_APP_INFO_CRC: 1516 if (size) 1517 success = copyTLV32(data, &offset, max_len, tags[i], crc); 1518 else 1519 success = copyTLVEmpty(data, &offset, max_len, tags[i]); 1520 break; 1521 case NANOHUB_HAL_APP_INFO_TID: 1522 if (tid_valid) 1523 success = copyTLV32(data, &offset, max_len, tags[i], tid); 1524 else 1525 success = copyTLVEmpty(data, &offset, max_len, tags[i]); 1526 break; 1527 case NANOHUB_HAL_APP_INFO_VERSION: 1528 success = copyTLV32(data, &offset, max_len, tags[i], app->hdr.appVer); 1529 break; 1530 case NANOHUB_HAL_APP_INFO_ADDR: 1531 success = copyTLV32(data, &offset, max_len, tags[i], (uint32_t)app); 1532 break; 1533 case NANOHUB_HAL_APP_INFO_SIZE: 1534 if (size) 1535 success = copyTLV32(data, &offset, max_len, tags[i], size); 1536 else 1537 success = copyTLVEmpty(data, &offset, max_len, tags[i]); 1538 break; 1539 case NANOHUB_HAL_APP_INFO_HEAP: 1540 if (tid_valid) 1541 success = copyTLV32(data, &offset, max_len, tags[i], heapGetTaskSize(tid)); 1542 else 1543 success = copyTLVEmpty(data, &offset, max_len, tags[i]); 1544 break; 1545 case NANOHUB_HAL_APP_INFO_DATA: 1546 success = copyTLV32(data, &offset, max_len, tags[i], app->sect.got_end - app->sect.data_start); 1547 break; 1548 case NANOHUB_HAL_APP_INFO_BSS: 1549 success = copyTLV32(data, &offset, max_len, tags[i], app->sect.bss_end - app->sect.bss_start); 1550 break; 1551 case NANOHUB_HAL_APP_INFO_CHRE_MAJOR: 1552 if (app->hdr.fwFlags & FL_APP_HDR_CHRE) 1553 success = copyTLV8(data, &offset, max_len, tags[i], 1554 (app->hdr.chreApiMajor == 0xFF && app->hdr.chreApiMinor == 0xFF) ? 0x01 : 1555 app->hdr.chreApiMajor); 1556 else 1557 success = copyTLVEmpty(data, &offset, max_len, tags[i]); 1558 break; 1559 case NANOHUB_HAL_APP_INFO_CHRE_MINOR: 1560 if (app->hdr.fwFlags & FL_APP_HDR_CHRE) 1561 success = copyTLV8(data, &offset, max_len, tags[i], 1562 (app->hdr.chreApiMajor == 0xFF && app->hdr.chreApiMinor == 0xFF) ? 0x00 : 1563 app->hdr.chreApiMinor); 1564 else 1565 success = copyTLVEmpty(data, &offset, max_len, tags[i]); 1566 break; 1567 case NANOHUB_HAL_APP_INFO_END: 1568 default: 1569 success = false; 1570 copyTLVEmpty(data, &offset, max_len, NANOHUB_HAL_APP_INFO_END); 1571 break; 1572 } 1573 } 1574 1575 return offset; 1576 } 1577 1578 static void halAppInfo(void *rx, uint8_t rx_len, uint32_t transactionId) 1579 { 1580 struct NanohubHalAppInfoRx *req = rx; 1581 struct NanohubHalAppInfoTx *resp; 1582 struct SegmentIterator it; 1583 uint32_t state; 1584 int ret, i; 1585 uint32_t sharedSize, numApps; 1586 const struct AppHdr *internal; 1587 const uint8_t *shared; 1588 1589 if (!(resp = heapAlloc(sizeof(*resp)))) 1590 return; 1591 1592 resp->hdr = (struct NanohubHalHdr) { 1593 .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 1594 .len = sizeof(*resp) - sizeof(resp->hdr) - sizeof(resp->data), 1595 .transactionId = transactionId, 1596 }; 1597 resp->ret = (struct NanohubHalRet) { 1598 .msg = NANOHUB_HAL_APP_INFO, 1599 }; 1600 1601 shared = platGetSharedAreaInfo(&sharedSize); 1602 internal = platGetInternalAppList(&numApps); 1603 1604 if ((le32toh(req->addr) >= (uint32_t)shared && le32toh(req->addr) < (uint32_t)shared + sharedSize) || 1605 (le32toh(req->addr) < (uint32_t)shared && 1606 ((uint32_t)shared < (uint32_t)internal || 1607 (numApps > 0 && le32toh(req->addr) > (uint32_t)(internal+numApps-1))))) { 1608 osSegmentIteratorInit(&it); 1609 while (osSegmentIteratorNext(&it)) { 1610 state = osSegmentGetState(it.seg); 1611 switch (state) { 1612 case SEG_ST_EMPTY: 1613 case SEG_ST_RESERVED: 1614 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1615 return; 1616 case SEG_ST_ERASED: 1617 case SEG_ST_VALID: 1618 if (le32toh(req->addr) <= (uint32_t)osSegmentGetData(it.seg)) { 1619 ret = processAppTags(osSegmentGetData(it.seg), osSegmentGetCrc(it.seg), osSegmentGetSize(it.seg), resp->data, req->tags, rx_len - 4, state == SEG_ST_ERASED); 1620 if (ret > 0) { 1621 resp->hdr.len += ret; 1622 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1623 return; 1624 } 1625 } 1626 break; 1627 } 1628 } 1629 } else { 1630 for (i = 0; i < numApps; i++, internal++) { 1631 if (le32toh(req->addr) <= (uint32_t)internal) { 1632 ret = processAppTags(internal, 0, 0, resp->data, req->tags, rx_len - 4, false); 1633 if (ret > 0) { 1634 resp->hdr.len += ret; 1635 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1636 return; 1637 } 1638 } 1639 } 1640 } 1641 1642 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1643 } 1644 1645 static void halSysInfo(void *rx, uint8_t rx_len, uint32_t transactionId) 1646 { 1647 extern uint8_t __code_start[]; 1648 extern uint8_t __code_end[]; 1649 extern uint8_t __text_end[]; 1650 extern uint8_t __ram_start[]; 1651 extern uint8_t __ram_end[]; 1652 1653 struct NanohubHalSysInfoRx *req = rx; 1654 struct NanohubHalSysInfoTx *resp; 1655 int i; 1656 size_t offset = 0; 1657 const size_t max_len = HOST_HUB_CHRE_PACKET_MAX_LEN - sizeof(struct NanohubHalRet); 1658 bool success = true; 1659 int free, chunks, largest; 1660 uint32_t shared_size; 1661 1662 free = heapGetFreeSize(&chunks, &largest); 1663 1664 if (!(resp = heapAlloc(sizeof(*resp)))) 1665 return; 1666 1667 resp->hdr = (struct NanohubHalHdr) { 1668 .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 1669 .len = sizeof(*resp) - sizeof(resp->hdr) - sizeof(resp->data), 1670 .transactionId = transactionId, 1671 }; 1672 resp->ret = (struct NanohubHalRet) { 1673 .msg = NANOHUB_HAL_SYS_INFO, 1674 }; 1675 1676 for (i=0; i<rx_len && success; i++) { 1677 switch(req->tags[i]) { 1678 case NANOHUB_HAL_SYS_INFO_HEAP_FREE: 1679 if (free >= 0) 1680 success = copyTLV32(resp->data, &offset, max_len, req->tags[i], free); 1681 else 1682 success = copyTLVEmpty(resp->data, &offset, max_len, req->tags[i]); 1683 break; 1684 case NANOHUB_HAL_SYS_INFO_RAM_SIZE: 1685 success = copyTLV32(resp->data, &offset, max_len, req->tags[i], __ram_end - __ram_start); 1686 break; 1687 case NANOHUB_HAL_SYS_INFO_EEDATA_SIZE: 1688 success = copyTLV32(resp->data, &offset, max_len, req->tags[i], eeDataGetSize()); 1689 break; 1690 case NANOHUB_HAL_SYS_INFO_EEDATA_FREE: 1691 success = copyTLV32(resp->data, &offset, max_len, req->tags[i], eeDataGetFree()); 1692 break; 1693 case NANOHUB_HAL_SYS_INFO_CODE_SIZE: 1694 success = copyTLV32(resp->data, &offset, max_len, req->tags[i], __code_end - __code_start); 1695 break; 1696 case NANOHUB_HAL_SYS_INFO_CODE_FREE: 1697 success = copyTLV32(resp->data, &offset, max_len, req->tags[i], __code_end - __text_end); 1698 break; 1699 case NANOHUB_HAL_SYS_INFO_SHARED_SIZE: 1700 platGetSharedAreaInfo(&shared_size); 1701 success = copyTLV32(resp->data, &offset, max_len, req->tags[i], shared_size); 1702 break; 1703 case NANOHUB_HAL_SYS_INFO_SHARED_FREE: 1704 success = copyTLV32(resp->data, &offset, max_len, req->tags[i], osSegmentGetFree()); 1705 break; 1706 case NANOHUB_HAL_SYS_INFO_END: 1707 default: 1708 success = false; 1709 copyTLVEmpty(resp->data, &offset, max_len, NANOHUB_HAL_APP_INFO_END); 1710 break; 1711 } 1712 } 1713 1714 resp->hdr.len += offset; 1715 1716 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1717 } 1718 1719 static void halKeyInfo(void *rx, uint8_t rx_len, uint32_t transactionId) 1720 { 1721 struct NanohubHalKeyInfoRx *req = rx; 1722 struct NanohubHalKeyInfoTx *resp; 1723 const uint32_t *ptr; 1724 uint32_t numKeys; 1725 uint32_t dataLength; 1726 1727 if (!(resp = heapAlloc(sizeof(*resp)))) 1728 return; 1729 1730 ptr = BL.blGetPubKeysInfo(&numKeys); 1731 1732 resp->hdr = (struct NanohubHalHdr) { 1733 .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 1734 .len = sizeof(*resp) - sizeof(resp->hdr) - sizeof(resp->data), 1735 .transactionId = transactionId, 1736 }; 1737 resp->ret = (struct NanohubHalRet) { 1738 .msg = NANOHUB_HAL_KEY_INFO, 1739 }; 1740 1741 resp->keyLength = 0; 1742 1743 if (ptr && req->keyNum < numKeys) { 1744 if (req->dataOffset < RSA_BYTES) { 1745 resp->keyLength = RSA_BYTES; 1746 if (RSA_BYTES - req->dataOffset > NANOHUB_RSA_KEY_CHUNK_LEN) 1747 dataLength = NANOHUB_RSA_KEY_CHUNK_LEN; 1748 else 1749 dataLength = RSA_BYTES - req->dataOffset; 1750 memcpy(resp->data, (const uint8_t *)ptr + (req->keyNum * RSA_BYTES) + req->dataOffset, dataLength); 1751 resp->hdr.len += dataLength; 1752 } 1753 } 1754 1755 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1756 } 1757 1758 static void halStartUpload(void *rx, uint8_t rx_len, uint32_t transactionId) 1759 { 1760 struct NanohubHalStartUploadRx *req = rx; 1761 struct NanohubStartFirmwareUploadRequest hwReq = { 1762 .size = req->length 1763 }; 1764 struct NanohubHalStartUploadTx *resp; 1765 1766 if (!(resp = heapAlloc(sizeof(*resp)))) 1767 return; 1768 1769 resp->hdr = (struct NanohubHalHdr) { 1770 .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 1771 .len = sizeof(*resp) - sizeof(resp->hdr), 1772 .transactionId = transactionId, 1773 }; 1774 1775 resp->ret.msg = NANOHUB_HAL_START_UPLOAD; 1776 if (doStartFirmwareUpload(&hwReq, false)) 1777 resp->ret.status = NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED; 1778 else 1779 resp->ret.status = NANOHUB_FIRMWARE_CHUNK_REPLY_NO_SPACE; 1780 1781 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1782 } 1783 1784 static void halContUpload(void *rx, uint8_t rx_len, uint32_t transactionId) 1785 { 1786 uint32_t offset; 1787 uint32_t reply; 1788 uint8_t len; 1789 struct NanohubHalContUploadRx *req = rx; 1790 struct FirmwareWriteCookie *cookie; 1791 1792 if (!(cookie = heapAlloc(sizeof(*cookie)))) 1793 return; 1794 1795 cookie->evtType = EVT_APP_TO_HOST_CHRE; 1796 cookie->resp.hdr = (struct NanohubHalHdr) { 1797 .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 1798 .len = sizeof(cookie->resp) - sizeof(cookie->resp.hdr), 1799 .transactionId = transactionId, 1800 }; 1801 cookie->resp.ret = (struct NanohubHalRet) { 1802 .msg = NANOHUB_HAL_CONT_UPLOAD, 1803 }; 1804 1805 if (!mDownloadState) { 1806 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_CANCEL_NO_RETRY; 1807 } else { 1808 offset = le32toh(req->offset); 1809 len = rx_len - sizeof(req->offset); 1810 reply = doFirmwareChunk(req->data, offset, len, cookie); 1811 } 1812 if (reply != NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED) { 1813 osLog(LOG_ERROR, "%s: reply=%" PRIu32 "\n", __func__, reply); 1814 1815 cookie->resp.ret.status = reply; 1816 1817 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, &cookie->resp, writeCookieFree); 1818 } 1819 } 1820 1821 static void halFinishUpload(void *rx, uint8_t rx_len, uint32_t transactionId) 1822 { 1823 struct NanohubHalFinishUploadTx *resp; 1824 uint32_t reply; 1825 uint32_t addr = 0xFFFFFFFF; 1826 uint32_t crc = 0xFFFFFFFF; 1827 1828 if (!(resp = heapAlloc(sizeof(*resp)))) 1829 return; 1830 1831 resp->hdr = (struct NanohubHalHdr) { 1832 .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 1833 .len = sizeof(*resp) - sizeof(resp->hdr), 1834 .transactionId = transactionId, 1835 }; 1836 1837 reply = doFinishFirmwareUpload(&addr, &crc); 1838 1839 osLog(LOG_INFO, "%s: reply=%" PRIu32 "\n", __func__, reply); 1840 1841 resp->ret = (struct NanohubHalRet) { 1842 .msg = NANOHUB_HAL_FINISH_UPLOAD, 1843 .status = reply, 1844 }; 1845 1846 resp->addr = addr; 1847 resp->crc = crc; 1848 1849 osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree); 1850 } 1851 1852 const static struct NanohubHalCommand mBuiltinHalCommands[] = { 1853 NANOHUB_HAL_COMMAND(NANOHUB_HAL_APP_MGMT, 1854 halAppMgmt, 1855 struct NanohubHalAppMgmtRx, 1856 struct NanohubHalAppMgmtRx), 1857 NANOHUB_HAL_COMMAND(NANOHUB_HAL_SYS_MGMT, 1858 halSysMgmt, 1859 struct NanohubHalSysMgmtRx, 1860 struct NanohubHalSysMgmtRx), 1861 NANOHUB_HAL_COMMAND(NANOHUB_HAL_APP_INFO, 1862 halAppInfo, 1863 __le32, 1864 struct NanohubHalAppInfoRx), 1865 NANOHUB_HAL_COMMAND(NANOHUB_HAL_SYS_INFO, 1866 halSysInfo, 1867 struct { }, 1868 struct NanohubHalSysInfoRx), 1869 NANOHUB_HAL_COMMAND(NANOHUB_HAL_KEY_INFO, 1870 halKeyInfo, 1871 struct NanohubHalKeyInfoRx, 1872 struct NanohubHalKeyInfoRx), 1873 NANOHUB_HAL_COMMAND(NANOHUB_HAL_START_UPLOAD, 1874 halStartUpload, 1875 struct NanohubHalStartUploadRx, 1876 struct NanohubHalStartUploadRx), 1877 NANOHUB_HAL_COMMAND(NANOHUB_HAL_CONT_UPLOAD, 1878 halContUpload, 1879 __le32, 1880 struct NanohubHalContUploadRx), 1881 NANOHUB_HAL_COMMAND(NANOHUB_HAL_FINISH_UPLOAD, 1882 halFinishUpload, 1883 struct { }, 1884 struct { }), 1885 }; 1886 1887 const struct NanohubHalCommand *nanohubHalFindCommand(uint8_t msg) 1888 { 1889 uint32_t i; 1890 1891 for (i = 0; i < ARRAY_SIZE(mBuiltinHalCommands); i++) { 1892 const struct NanohubHalCommand *cmd = &mBuiltinHalCommands[i]; 1893 if (cmd->msg == msg) 1894 return cmd; 1895 } 1896 return NULL; 1897 } 1898 1899 1900 int64_t hostGetTimeDelta(void) 1901 { 1902 int64_t delta = getAvgDelta(&mTimeSync); 1903 1904 if (delta == INT64_MIN) 1905 return 0ULL; 1906 else 1907 return delta; 1908 } 1909 1910 uint64_t hostGetTime(void) 1911 { 1912 int64_t delta = getAvgDelta(&mTimeSync); 1913 1914 if (!delta || delta == INT64_MIN) 1915 return 0ULL; 1916 else 1917 return sensorGetTime() + delta; 1918 } 1919 1920 #if DEBUG_APHUB_TIME_SYNC 1921 1922 #define N_APHUB_SYNC_DATA 256 1923 #define PRINT_DELAY 20000000 // unit ns, 20ms 1924 struct ApHubSyncDebug { 1925 uint64_t apFirst; 1926 uint64_t hubFirst; 1927 uint32_t apDelta[N_APHUB_SYNC_DATA]; // us 1928 uint32_t hubDelta[N_APHUB_SYNC_DATA]; // us 1929 int printIndex; //negative means not printing 1930 int writeIndex; 1931 1932 uint32_t printTimer; 1933 }; 1934 1935 static struct ApHubSyncDebug mApHubSyncDebug; 1936 1937 static void syncDebugCallback(uint32_t timerId, void *data) 1938 { 1939 1940 if (mApHubSyncDebug.printIndex >= mApHubSyncDebug.writeIndex || 1941 mApHubSyncDebug.printIndex >= N_APHUB_SYNC_DATA) { 1942 timTimerCancel(mApHubSyncDebug.printTimer); 1943 1944 osLog(LOG_DEBUG, "APHUB Done printing %d items", mApHubSyncDebug.printIndex); 1945 mApHubSyncDebug.writeIndex = 0; 1946 mApHubSyncDebug.printIndex = -1; 1947 1948 mApHubSyncDebug.printTimer = 0; 1949 } else { 1950 if (mApHubSyncDebug.printIndex == 0) { 1951 osLog(LOG_DEBUG, "APHUB init %" PRIu64 " %" PRIu64, 1952 mApHubSyncDebug.apFirst, 1953 mApHubSyncDebug.hubFirst); 1954 } 1955 1956 osLog(LOG_DEBUG, "APHUB %d %" PRIu32 " %" PRIu32, 1957 mApHubSyncDebug.printIndex, 1958 mApHubSyncDebug.apDelta[mApHubSyncDebug.printIndex], 1959 mApHubSyncDebug.hubDelta[mApHubSyncDebug.printIndex]); 1960 1961 mApHubSyncDebug.printIndex++; 1962 } 1963 } 1964 1965 static void syncDebugTriggerPrint() 1966 { 1967 if (mApHubSyncDebug.printTimer) { 1968 //printing already going 1969 return; 1970 } 1971 1972 mApHubSyncDebug.printIndex = 0; 1973 1974 syncDebugCallback(0, NULL); 1975 if (!(mApHubSyncDebug.printTimer = 1976 timTimerSet(PRINT_DELAY, 0, 50, syncDebugCallback, NULL, false /*oneShot*/))) { 1977 osLog(LOG_WARN, "Cannot get timer for printing"); 1978 1979 mApHubSyncDebug.writeIndex = 0; // discard all data 1980 mApHubSyncDebug.printIndex = -1; // not printing 1981 } 1982 } 1983 1984 static void syncDebugAdd(uint64_t ap, uint64_t hub) 1985 { 1986 if (mApHubSyncDebug.writeIndex >= N_APHUB_SYNC_DATA) { 1987 //full 1988 syncDebugTriggerPrint(); 1989 return; 1990 } 1991 1992 if (mApHubSyncDebug.writeIndex == 0) { 1993 mApHubSyncDebug.apFirst = ap; 1994 mApHubSyncDebug.hubFirst = hub; 1995 } 1996 1997 // convert ns to us 1998 mApHubSyncDebug.apDelta[mApHubSyncDebug.writeIndex] = 1999 (uint32_t) U64_DIV_BY_CONST_U16((ap - mApHubSyncDebug.apFirst), 1000u); 2000 mApHubSyncDebug.hubDelta[mApHubSyncDebug.writeIndex] = 2001 (uint32_t) U64_DIV_BY_CONST_U16((hub - mApHubSyncDebug.hubFirst), 1000u); 2002 2003 ++mApHubSyncDebug.writeIndex; 2004 } 2005 #endif 2006