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