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