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