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