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