• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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