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