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