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