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