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