1 /** @addtogroup MCD_MCDIMPL_DAEMON_DEV
2 * @{
3 * @file
4 *
5 *
6 * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote
17 * products derived from this software without specific prior
18 * written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
21 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <cstdlib>
34 #include <pthread.h>
35 #include "McTypes.h"
36
37 #include "DeviceScheduler.h"
38 #include "DeviceIrqHandler.h"
39 #include "ExcDevice.h"
40 #include "Connection.h"
41 #include "TrustletSession.h"
42
43 #include "MobiCoreDevice.h"
44 #include "Mci/mci.h"
45 #include "mcLoadFormat.h"
46
47
48 #include "log.h"
49 #include "public/MobiCoreDevice.h"
50
51
52 //------------------------------------------------------------------------------
MobiCoreDevice()53 MobiCoreDevice::MobiCoreDevice()
54 {
55 mcFault = false;
56 }
57
58 //------------------------------------------------------------------------------
~MobiCoreDevice()59 MobiCoreDevice::~MobiCoreDevice()
60 {
61 delete mcVersionInfo;
62 mcVersionInfo = NULL;
63 }
64
65 //------------------------------------------------------------------------------
getTrustletSession(uint32_t sessionId)66 TrustletSession *MobiCoreDevice::getTrustletSession(uint32_t sessionId)
67 {
68 for (trustletSessionIterator_t session = trustletSessions.begin();
69 session != trustletSessions.end();
70 ++session) {
71 TrustletSession *tsTmp = *session;
72 if (tsTmp->sessionId == sessionId) {
73 return tsTmp;
74 }
75 }
76 return NULL;
77 }
78
79
cleanSessionBuffers(TrustletSession * session)80 void MobiCoreDevice::cleanSessionBuffers(TrustletSession *session)
81 {
82 CWsm_ptr pWsm = session->popBulkBuff();
83
84 while (pWsm) {
85 unlockWsmL2(pWsm->handle);
86 pWsm = session->popBulkBuff();
87 }
88 }
89 //------------------------------------------------------------------------------
removeTrustletSession(uint32_t sessionId)90 void MobiCoreDevice::removeTrustletSession(uint32_t sessionId)
91 {
92 for (trustletSessionIterator_t session = trustletSessions.begin();
93 session != trustletSessions.end();
94 ++session) {
95 if ((*session)->sessionId == sessionId) {
96 cleanSessionBuffers(*session);
97 trustletSessions.erase(session);
98 return;
99 }
100 }
101 }
102 //------------------------------------------------------------------------------
getSessionConnection(uint32_t sessionId,notification_t * notification)103 Connection *MobiCoreDevice::getSessionConnection(uint32_t sessionId, notification_t *notification)
104 {
105 Connection *con = NULL;
106 TrustletSession *ts = NULL;
107
108 ts = getTrustletSession(sessionId);
109 if (ts == NULL) {
110 return NULL;
111 }
112
113 con = ts->notificationConnection;
114 if (con == NULL) {
115 ts->queueNotification(notification);
116 return NULL;
117 }
118
119 return con;
120 }
121
122
123 //------------------------------------------------------------------------------
open(Connection * connection)124 bool MobiCoreDevice::open(Connection *connection)
125 {
126 // Link this device to the connection
127 connection->connectionData = this;
128 return true;
129 }
130
131
132 //------------------------------------------------------------------------------
133 /**
134 * Close device.
135 *
136 * Removes all sessions to a connection. Though, clientLib rejects the closeDevice()
137 * command if still sessions connected to the device, this is needed to clean up all
138 * sessions if client dies.
139 */
close(Connection * connection)140 void MobiCoreDevice::close(Connection *connection)
141 {
142 trustletSessionList_t::reverse_iterator interator;
143 static CMutex mutex;
144 // 1. Iterate through device session to find connection
145 // 2. Decide what to do with open Trustlet sessions
146 // 3. Remove & delete deviceSession from vector
147
148 // Enter critical section
149 mutex.lock();
150 for (interator = trustletSessions.rbegin();
151 interator != trustletSessions.rend();
152 interator++) {
153 TrustletSession *ts = *interator;
154
155 if (ts->deviceConnection == connection) {
156 closeSession(connection, ts->sessionId);
157 }
158 }
159 // Leave critical section
160 mutex.unlock();
161
162 // After the trustlet is done make sure to tell the driver to cleanup
163 // all the orphaned drivers
164 cleanupWsmL2();
165
166 connection->connectionData = NULL;
167 }
168
169
170 //------------------------------------------------------------------------------
start(void)171 void MobiCoreDevice::start(void)
172 {
173 // Call the device specific initialization
174 // initDevice();
175
176 LOG_I("Starting DeviceIrqHandler...");
177 // Start the irq handling thread
178 DeviceIrqHandler::start();
179
180 if (schedulerAvailable()) {
181 LOG_I("Starting DeviceScheduler...");
182 // Start the scheduling handling thread
183 DeviceScheduler::start();
184 } else {
185 LOG_I("No DeviceScheduler available.");
186 }
187 }
188
189
190 //------------------------------------------------------------------------------
signalMcpNotification(void)191 void MobiCoreDevice::signalMcpNotification(void)
192 {
193 mcpSessionNotification.signal();
194 }
195
196
197 //------------------------------------------------------------------------------
waitMcpNotification(void)198 bool MobiCoreDevice::waitMcpNotification(void)
199 {
200 int counter = 5;
201 while (1) {
202 // In case of fault just return, nothing to do here
203 if (mcFault) {
204 return false;
205 }
206 // Wait 10 seconds for notification
207 if (mcpSessionNotification.wait(10) == false) {
208 // No MCP answer received and mobicore halted, dump mobicore status
209 // then throw exception
210 LOG_I("No MCP answer received in 2 seconds.");
211 if (getMobicoreStatus() == MC_STATUS_HALT) {
212 dumpMobicoreStatus();
213 mcFault = true;
214 return false;
215 } else {
216 counter--;
217 if (counter < 1) {
218 mcFault = true;
219 return false;
220 }
221 }
222 } else {
223 break;
224 }
225 }
226
227 // Check healthiness state of the device
228 if (DeviceIrqHandler::isExiting()) {
229 LOG_I("waitMcpNotification(): IrqHandler thread died! Joining");
230 DeviceIrqHandler::join();
231 LOG_I("waitMcpNotification(): Joined");
232 LOG_E("IrqHandler thread died!");
233 return false;
234 }
235
236 if (DeviceScheduler::isExiting()) {
237 LOG_I("waitMcpNotification(): Scheduler thread died! Joining");
238 DeviceScheduler::join();
239 LOG_I("waitMcpNotification(): Joined");
240 LOG_E("Scheduler thread died!");
241 return false;
242 }
243 return true;
244 }
245
246
247 //------------------------------------------------------------------------------
openSession(Connection * deviceConnection,loadDataOpenSession_ptr pLoadDataOpenSession,MC_DRV_CMD_OPEN_SESSION_struct * cmdOpenSession,mcDrvRspOpenSessionPayload_ptr pRspOpenSessionPayload)248 mcResult_t MobiCoreDevice::openSession(
249 Connection *deviceConnection,
250 loadDataOpenSession_ptr pLoadDataOpenSession,
251 MC_DRV_CMD_OPEN_SESSION_struct *cmdOpenSession,
252 mcDrvRspOpenSessionPayload_ptr pRspOpenSessionPayload
253 )
254 {
255 do {
256 addr_t tci;
257 uint32_t len;
258 uint32_t handle = cmdOpenSession->handle;
259
260 if (!findContiguousWsm(handle, &tci, &len)) {
261 LOG_E("Failed to find contiguous WSM %u", handle);
262 return MC_DRV_ERR_DAEMON_WSM_HANDLE_NOT_FOUND;
263 }
264
265 if (!lockWsmL2(handle)) {
266 LOG_E("Failed to lock contiguous WSM %u", handle);
267 return MC_DRV_ERR_DAEMON_WSM_HANDLE_NOT_FOUND;
268 }
269
270 // Write MCP open message to buffer
271 mcpMessage->cmdOpen.cmdHeader.cmdId = MC_MCP_CMD_OPEN_SESSION;
272 mcpMessage->cmdOpen.uuid = cmdOpenSession->uuid;
273 mcpMessage->cmdOpen.wsmTypeTci = WSM_CONTIGUOUS;
274 mcpMessage->cmdOpen.adrTciBuffer = (uint32_t)(tci);
275 mcpMessage->cmdOpen.ofsTciBuffer = 0;
276 mcpMessage->cmdOpen.lenTciBuffer = len;
277
278 LOG_I(" Using phys=%p, len=%d as TCI buffer",
279 (addr_t)(cmdOpenSession->tci),
280 cmdOpenSession->len);
281
282 // check if load data is provided
283 mcpMessage->cmdOpen.wsmTypeLoadData = WSM_L2;
284 mcpMessage->cmdOpen.adrLoadData = (uint32_t)pLoadDataOpenSession->baseAddr;
285 mcpMessage->cmdOpen.ofsLoadData = pLoadDataOpenSession->offs;
286 mcpMessage->cmdOpen.lenLoadData = pLoadDataOpenSession->len;
287 memcpy(&mcpMessage->cmdOpen.tlHeader, pLoadDataOpenSession->tlHeader, sizeof(*pLoadDataOpenSession->tlHeader));
288
289 // Clear the notifications queue. We asume the race condition we have
290 // seen in openSession never happens elsewhere
291 notifications = std::queue<notification_t>();
292 // Notify MC about a new command inside the MCP buffer
293 notify(SID_MCP);
294
295 // Wait till response from MC is available
296 if (!waitMcpNotification()) {
297 // Here Mobicore can be considered dead.
298 unlockWsmL2(handle);
299 return MC_DRV_ERR_DAEMON_MCI_ERROR;
300 }
301
302 // Check if the command response ID is correct
303 if ((MC_MCP_CMD_OPEN_SESSION | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) {
304 LOG_E("CMD_OPEN_SESSION got invalid MCP command response(0x%X)", mcpMessage->rspHeader.rspId);
305 // Something is messing with our MCI memory, we cannot know if the Trustlet was loaded.
306 // Had in been loaded, we are loosing track of it here.
307 unlockWsmL2(handle);
308 return MC_DRV_ERR_DAEMON_MCI_ERROR;
309 }
310
311 uint32_t mcRet = mcpMessage->rspOpen.rspHeader.result;
312
313 if (mcRet != MC_MCP_RET_OK) {
314 LOG_E("MCP OPEN returned code %d.", mcRet);
315 unlockWsmL2(handle);
316 return MAKE_MC_DRV_MCP_ERROR(mcRet);
317 }
318
319 LOG_I(" After MCP OPEN, we have %d queued notifications",
320 notifications.size());
321 // Read MC answer from MCP buffer
322 TrustletSession *trustletSession = new TrustletSession(
323 deviceConnection,
324 mcpMessage->rspOpen.sessionId);
325
326 pRspOpenSessionPayload->sessionId = trustletSession->sessionId;
327 pRspOpenSessionPayload->deviceSessionId = (uint32_t)trustletSession;
328 pRspOpenSessionPayload->sessionMagic = trustletSession->sessionMagic;
329
330 trustletSessions.push_back(trustletSession);
331
332 trustletSession->addBulkBuff(new CWsm((void *)pLoadDataOpenSession->offs, pLoadDataOpenSession->len, handle, 0));
333
334 // We have some queued notifications and we need to send them to them
335 // trustlet session
336 while (!notifications.empty()) {
337 trustletSession->queueNotification(¬ifications.front());
338 notifications.pop();
339 }
340
341 } while (0);
342 return MC_DRV_OK;
343 }
344
345
346 //------------------------------------------------------------------------------
registerTrustletConnection(Connection * connection,MC_DRV_CMD_NQ_CONNECT_struct * cmdNqConnect)347 TrustletSession *MobiCoreDevice::registerTrustletConnection(
348 Connection *connection,
349 MC_DRV_CMD_NQ_CONNECT_struct *cmdNqConnect
350 )
351 {
352 LOG_I(" Registering notification socket with Service session %d.",
353 cmdNqConnect->sessionId);
354 LOG_V(" Searching sessionId %d with sessionMagic %d",
355 cmdNqConnect->sessionId,
356 cmdNqConnect->sessionMagic);
357
358 for (trustletSessionIterator_t iterator = trustletSessions.begin();
359 iterator != trustletSessions.end();
360 ++iterator) {
361 TrustletSession *ts = *iterator;
362
363 if (ts != (TrustletSession *) (cmdNqConnect->deviceSessionId)) {
364 continue;
365 }
366
367 if ( (ts->sessionMagic != cmdNqConnect->sessionMagic)
368 || (ts->sessionId != cmdNqConnect->sessionId)) {
369 continue;
370 }
371
372 ts->notificationConnection = connection;
373
374 LOG_I(" Found Service session, registered connection.");
375
376 return ts;
377 }
378
379 LOG_I("registerTrustletConnection(): search failed");
380 return NULL;
381 }
382
383
384 //------------------------------------------------------------------------------
closeSession(uint32_t sessionId)385 mcResult_t MobiCoreDevice::closeSession(uint32_t sessionId)
386 {
387 LOG_I(" Write MCP CLOSE message to MCI, notify and wait");
388
389 // Write MCP close message to buffer
390 mcpMessage->cmdClose.cmdHeader.cmdId = MC_MCP_CMD_CLOSE_SESSION;
391 mcpMessage->cmdClose.sessionId = sessionId;
392
393 // Notify MC about the availability of a new command inside the MCP buffer
394 notify(SID_MCP);
395
396 // Wait till response from MSH is available
397 if (!waitMcpNotification()) {
398 return MC_DRV_ERR_DAEMON_MCI_ERROR;
399 }
400
401 // Check if the command response ID is correct
402 if ((MC_MCP_CMD_CLOSE_SESSION | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) {
403 LOG_E("CMD_CLOSE_SESSION got invalid MCP response");
404 return MC_DRV_ERR_DAEMON_MCI_ERROR;
405 }
406
407 // Read MC answer from MCP buffer
408 uint32_t mcRet = mcpMessage->rspOpen.rspHeader.result;
409
410 if (mcRet != MC_MCP_RET_OK) {
411 LOG_E("CMD_CLOSE_SESSION error %d", mcRet);
412 return MAKE_MC_DRV_MCP_ERROR(mcRet);
413 }
414
415 return MC_DRV_OK;
416 }
417
418 //------------------------------------------------------------------------------
419 /**
420 * TODO-2012-09-19-haenellu: Do some more checks here, otherwise rogue clientLib
421 * can close sessions from different TLCs. That is, deviceConnection is ignored below.
422 *
423 * Need connection as well as according session ID, so that a client can not
424 * close sessions not belonging to him.
425 */
closeSession(Connection * deviceConnection,uint32_t sessionId)426 mcResult_t MobiCoreDevice::closeSession(Connection *deviceConnection, uint32_t sessionId)
427 {
428 TrustletSession *ts = getTrustletSession(sessionId);
429 if (ts == NULL) {
430 LOG_E("no session found with id=%d", sessionId);
431 return MC_DRV_ERR_DAEMON_UNKNOWN_SESSION;
432 }
433
434 uint32_t mcRet = closeSession(sessionId);
435 if (mcRet != MC_DRV_OK) {
436 return mcRet;
437 }
438
439 // remove objects
440 removeTrustletSession(sessionId);
441 delete ts;
442
443 return MC_DRV_OK;
444 }
445
446
447 //------------------------------------------------------------------------------
mapBulk(uint32_t sessionId,uint32_t handle,uint32_t pAddrL2,uint32_t offsetPayload,uint32_t lenBulkMem,uint32_t * secureVirtualAdr)448 mcResult_t MobiCoreDevice::mapBulk(uint32_t sessionId, uint32_t handle, uint32_t pAddrL2,
449 uint32_t offsetPayload, uint32_t lenBulkMem, uint32_t *secureVirtualAdr)
450 {
451 TrustletSession *ts = getTrustletSession(sessionId);
452 if (ts == NULL) {
453 LOG_E("no session found with id=%d", sessionId);
454 return MC_DRV_ERR_DAEMON_UNKNOWN_SESSION;
455 }
456
457 // TODO-2012-09-06-haenellu: Think about not ignoring the error case, ClientLib does not allow this.
458 ts->addBulkBuff(new CWsm((void *)offsetPayload, lenBulkMem, handle, (void *)pAddrL2));
459 // Write MCP map message to buffer
460 mcpMessage->cmdMap.cmdHeader.cmdId = MC_MCP_CMD_MAP;
461 mcpMessage->cmdMap.sessionId = sessionId;
462 mcpMessage->cmdMap.wsmType = WSM_L2;
463 mcpMessage->cmdMap.adrBuffer = (uint32_t)(pAddrL2);
464 mcpMessage->cmdMap.ofsBuffer = offsetPayload;
465 mcpMessage->cmdMap.lenBuffer = lenBulkMem;
466
467 // Notify MC about the availability of a new command inside the MCP buffer
468 notify(SID_MCP);
469
470 // Wait till response from MC is available
471 if (!waitMcpNotification()) {
472 return MC_DRV_ERR_DAEMON_MCI_ERROR;
473 }
474
475 // Check if the command response ID is correct
476 if (mcpMessage->rspHeader.rspId != (MC_MCP_CMD_MAP | FLAG_RESPONSE)) {
477 LOG_E("CMD_MAP got invalid MCP response");
478 return MC_DRV_ERR_DAEMON_MCI_ERROR;
479 }
480
481 uint32_t mcRet = mcpMessage->rspMap.rspHeader.result;
482
483 if (mcRet != MC_MCP_RET_OK) {
484 LOG_E("MCP MAP returned code %d.", mcRet);
485 return MAKE_MC_DRV_MCP_ERROR(mcRet);
486 }
487
488 *secureVirtualAdr = mcpMessage->rspMap.secureVirtualAdr;
489 return MC_DRV_OK;
490 }
491
492
493 //------------------------------------------------------------------------------
unmapBulk(uint32_t sessionId,uint32_t handle,uint32_t secureVirtualAdr,uint32_t lenBulkMem)494 mcResult_t MobiCoreDevice::unmapBulk(uint32_t sessionId, uint32_t handle,
495 uint32_t secureVirtualAdr, uint32_t lenBulkMem)
496 {
497 TrustletSession *ts = getTrustletSession(sessionId);
498 if (ts == NULL) {
499 LOG_E("no session found with id=%d", sessionId);
500 return MC_DRV_ERR_DAEMON_UNKNOWN_SESSION;
501 }
502
503 // Write MCP unmap command to buffer
504 mcpMessage->cmdUnmap.cmdHeader.cmdId = MC_MCP_CMD_UNMAP;
505 mcpMessage->cmdUnmap.sessionId = sessionId;
506 mcpMessage->cmdUnmap.wsmType = WSM_L2;
507 mcpMessage->cmdUnmap.secureVirtualAdr = secureVirtualAdr;
508 mcpMessage->cmdUnmap.lenVirtualBuffer = lenBulkMem;
509
510 // Notify MC about the availability of a new command inside the MCP buffer
511 notify(SID_MCP);
512
513 // Wait till response from MC is available
514 if (!waitMcpNotification()) {
515 return MC_DRV_ERR_DAEMON_MCI_ERROR;
516 }
517
518 // Check if the command response ID is correct
519 if (mcpMessage->rspHeader.rspId != (MC_MCP_CMD_UNMAP | FLAG_RESPONSE)) {
520 LOG_E("CMD_OPEN_SESSION got invalid MCP response");
521 return MC_DRV_ERR_DAEMON_MCI_ERROR;
522 }
523
524 uint32_t mcRet = mcpMessage->rspUnmap.rspHeader.result;
525
526 if (mcRet != MC_MCP_RET_OK) {
527 LOG_E("MCP UNMAP returned code %d.", mcRet);
528 return MAKE_MC_DRV_MCP_ERROR(mcRet);
529 } else {
530 // Just remove the buffer
531 // TODO-2012-09-06-haenellu: Haven't we removed it already?
532 if (!ts->removeBulkBuff(handle))
533 LOG_I("unmapBulk(): no buffer found found with handle=%u", handle);
534 }
535
536 return MC_DRV_OK;
537 }
538
539
540 //------------------------------------------------------------------------------
donateRam(const uint32_t donationSize)541 void MobiCoreDevice::donateRam(const uint32_t donationSize)
542 {
543 // Donate additional RAM to the MobiCore
544 CWsm_ptr ram = allocateContiguousPersistentWsm(donationSize);
545 if (NULL == ram) {
546 LOG_E("Allocation of additional RAM failed");
547 return;
548 }
549 ramType_t ramType = RAM_GENERIC;
550 addr_t adrBuffer = ram->physAddr;
551 const uint32_t numPages = donationSize / (4 * 1024);
552
553
554 LOG_I("donateRam(): adrBuffer=%p, numPages=%d, ramType=%d",
555 adrBuffer,
556 numPages,
557 ramType);
558
559 do {
560 // Write MCP open message to buffer
561 mcpMessage->cmdDonateRam.cmdHeader.cmdId = MC_MCP_CMD_DONATE_RAM;
562 mcpMessage->cmdDonateRam.adrBuffer = (uint32_t) adrBuffer;
563 mcpMessage->cmdDonateRam.numPages = numPages;
564 mcpMessage->cmdDonateRam.ramType = ramType;
565
566 // Notify MC about a new command inside the MCP buffer
567 notify(SID_MCP);
568
569 // Wait till response from MC is available
570 if (!waitMcpNotification()) {
571 break;
572 }
573
574 // Check if the command response ID is correct
575 if ((MC_MCP_CMD_DONATE_RAM | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) {
576 LOG_E("donateRam(): CMD_DONATE_RAM got invalid MCP response - rspId is: %d",
577 mcpMessage->rspHeader.rspId);
578 break;
579 }
580
581 uint32_t mcRet = mcpMessage->rspDonateRam.rspHeader.result;
582 if (MC_MCP_RET_OK != mcRet) {
583 LOG_E("donateRam(): CMD_DONATE_RAM error %d", mcRet);
584 break;
585 }
586
587 LOG_I("donateRam() succeeded.");
588
589 } while (0);
590 }
591
592 //------------------------------------------------------------------------------
getMobiCoreVersion(mcDrvRspGetMobiCoreVersionPayload_ptr pRspGetMobiCoreVersionPayload)593 mcResult_t MobiCoreDevice::getMobiCoreVersion(
594 mcDrvRspGetMobiCoreVersionPayload_ptr pRspGetMobiCoreVersionPayload
595 )
596 {
597 // If MobiCore version info already fetched.
598 if (mcVersionInfo != NULL) {
599 pRspGetMobiCoreVersionPayload->versionInfo = *mcVersionInfo;
600 return MC_DRV_OK;
601 // Otherwise, fetch it via MCP.
602 } else {
603 // Write MCP unmap command to buffer
604 mcpMessage->cmdGetMobiCoreVersion.cmdHeader.cmdId = MC_MCP_CMD_GET_MOBICORE_VERSION;
605
606 // Notify MC about the availability of a new command inside the MCP buffer
607 notify(SID_MCP);
608
609 // Wait till response from MC is available
610 if (!waitMcpNotification()) {
611 return MC_DRV_ERR_DAEMON_MCI_ERROR;
612 }
613
614 // Check if the command response ID is correct
615 if ((MC_MCP_CMD_GET_MOBICORE_VERSION | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) {
616 LOG_E("MC_MCP_CMD_GET_MOBICORE_VERSION got invalid MCP response");
617 return MC_DRV_ERR_DAEMON_MCI_ERROR;
618 }
619
620 uint32_t mcRet = mcpMessage->rspGetMobiCoreVersion.rspHeader.result;
621
622 if (mcRet != MC_MCP_RET_OK) {
623 LOG_E("MC_MCP_CMD_GET_MOBICORE_VERSION error %d", mcRet);
624 return MAKE_MC_DRV_MCP_ERROR(mcRet);
625 }
626
627 pRspGetMobiCoreVersionPayload->versionInfo = mcpMessage->rspGetMobiCoreVersion.versionInfo;
628
629 // Store MobiCore info for future reference.
630 mcVersionInfo = new mcVersionInfo_t();
631 *mcVersionInfo = pRspGetMobiCoreVersionPayload->versionInfo;
632 return MC_DRV_OK;
633 }
634 }
635
636 //------------------------------------------------------------------------------
queueUnknownNotification(notification_t notification)637 void MobiCoreDevice::queueUnknownNotification(
638 notification_t notification
639 )
640 {
641 notifications.push(notification);
642 }
643
644 /** @} */
645