//------------------------------------------------------------------------------ bool MobiCoreDevice::waitMcpNotification(void) { int counter = 5; while (1) { // In case of fault just return, nothing to do here if (mcFault) { return false; } // Wait 10 seconds for notification if (mcpSessionNotification.wait(10) == false) { // No MCP answer received and mobicore halted, dump mobicore status // then throw exception LOG_I("No MCP answer received in 2 seconds."); if (getMobicoreStatus() == MC_STATUS_HALT) { dumpMobicoreStatus(); mcFault = true; return false; } else { counter--; if (counter < 1) { mcFault = true; return false; } } } else { break; } } // Check healthiness state of the device if (DeviceIrqHandler::isExiting()) { LOG_I("waitMcpNotification(): IrqHandler thread died! Joining"); DeviceIrqHandler::join(); LOG_I("waitMcpNotification(): Joined"); LOG_E("IrqHandler thread died!"); return false; } if (DeviceScheduler::isExiting()) { LOG_I("waitMcpNotification(): Scheduler thread died! Joining"); DeviceScheduler::join(); LOG_I("waitMcpNotification(): Joined"); LOG_E("Scheduler thread died!"); return false; } return true; }
/** * Set up MCI and wait till MC is initialized * @return true if mobicore is already initialized */ bool TrustZoneDevice::initDevice( const char *devFile, bool loadMobiCore, const char *mobicoreImage, bool enableScheduler ) throw (ExcDevice) { notificationQueue_t* nqStartOut; notificationQueue_t* nqStartIn; addr_t mciBuffer; pMcKMod = new CMcKMod(); if (!pMcKMod->open(devFile)) { LOG_E("open() kernel module device failed"); return false; } if (!pMcKMod->checkKmodVersionOk()) { LOG_E("kernel module version mismatch"); return false; } // Start MobiCore from DDRAM if (loadMobiCore) { // 1. Allocate DDRAM as pseudo IRAM mobicoreInDDR = allocateContiguousPersistentWsm(SIZE_DDRAM); if (NULL == mobicoreInDDR) { LOG_E("Allocation of additional RAM failed"); return false; } memset(mobicoreInDDR->virtAddr,0xCC,SIZE_DDRAM); int ret = loadMobiCoreImage(mobicoreInDDR->virtAddr, SIZE_DDRAM, mobicoreImage); if (0 != ret) { LOG_E("loading Mobicore file failed: %d", ret); return false; } ret = pMcKMod->fcExecute( mobicoreInDDR->physAddr, MCP_BUFFER_SIZE); if (0 != ret) { LOG_E("pMcKMod->fcExecute() failed : %d", ret); return false; } } this->schedulerEnabled = enableScheduler; // Init MC with NQ and MCP buffer addresses // Set up MCI buffer if(!getMciInstance(MCI_BUFFER_SIZE, &pWsmMcp, &mciReused)) { return false; } mciBuffer = pWsmMcp->virtAddr; if(!checkMciVersion()) { return false; } // Only do a fastcall if MCI has not been reused (MC already initialized) if (!mciReused) { // Wipe memory before first usage bzero(mciBuffer, MCI_BUFFER_SIZE); // Init MC with NQ and MCP buffer addresses int ret = pMcKMod->fcInit( pWsmMcp->physAddr, 0, NQ_BUFFER_SIZE, NQ_BUFFER_SIZE, MCP_BUFFER_SIZE); if (0 != ret) { LOG_E("pMcKMod->fcInit() failed"); return false; } // First empty N-SIQ which results in set up of the MCI structure if(!nsiq()) { return false; } // Wait until MobiCore state switches to MC_STATUS_INITIALIZED // It is assumed that MobiCore always switches state at a certain point in time. while(1) { uint32_t status = getMobicoreStatus(); if (MC_STATUS_INITIALIZED == status) { break; } else if (MC_STATUS_NOT_INITIALIZED == status) { // Switch to MobiCore to give it more CPU time. if(!yield()) { return false; } } else if (MC_STATUS_HALT == status) { dumpMobicoreStatus(); LOG_E("MobiCore halted during init !!!, state is 0x%x", status); return false; } else // MC_STATUS_BAD_INIT or anything else { LOG_E("MCI buffer init failed, state is 0x%x", status); return false; } } } nqStartOut = (notificationQueue_t *) mciBuffer; nqStartIn = (notificationQueue_t *) ((uint8_t *) nqStartOut + sizeof(notificationQueueHeader_t) + NQ_NUM_ELEMS * sizeof(notification_t)); // Set up the NWd NQ nq = new NotificationQueue(nqStartIn, nqStartOut, NQ_NUM_ELEMS); mcpBuffer_t *mcpBuf = (mcpBuffer_t*) ((uint8_t *) mciBuffer + NQ_BUFFER_SIZE); // Set up the MC flags mcFlags = &(mcpBuf->mcFlags); // Set up the MCP message mcpMessage = &(mcpBuf->mcpMessage); // convert virtual address of mapping to physical address for the init. LOG_I("MCP: virt=%p, phys=%p, reused=%s", pWsmMcp->virtAddr, pWsmMcp->physAddr, mciReused ? "true" : "false"); return true; }
/** * Set up MCI and wait till MC is initialized * @return true if mobicore is already initialized */ bool TrustZoneDevice::initDevice( const char *devFile, bool loadMobiCore, const char *mobicoreImage, bool enableScheduler) { notificationQueue_t *nqStartOut; notificationQueue_t *nqStartIn; addr_t mciBuffer; pMcKMod = new CMcKMod(); mcResult_t ret = pMcKMod->open(devFile); if (ret != MC_DRV_OK) { LOG_W(" Opening kernel module device failed"); return false; } if (!pMcKMod->checkVersion()) { LOG_E("kernel module version mismatch"); return false; } this->schedulerEnabled = enableScheduler; // Init MC with NQ and MCP buffer addresses // Set up MCI buffer if (!getMciInstance(MCI_BUFFER_SIZE, &pWsmMcp, &mciReused)) { return false; } mciBuffer = pWsmMcp->virtAddr; if (!checkMciVersion()) { return false; } // Only do a fastcall if MCI has not been reused (MC already initialized) if (!mciReused) { // Wipe memory before first usage bzero(mciBuffer, MCI_BUFFER_SIZE); // Init MC with NQ and MCP buffer addresses int ret = pMcKMod->fcInit(0, NQ_BUFFER_SIZE, NQ_BUFFER_SIZE, MCP_BUFFER_SIZE); if (ret != 0) { LOG_E("pMcKMod->fcInit() failed"); return false; } // First empty N-SIQ which results in set up of the MCI structure if (!nsiq()) { return false; } // Wait until MobiCore state switches to MC_STATUS_INITIALIZED // It is assumed that MobiCore always switches state at a certain point in time. while (1) { uint32_t status = getMobicoreStatus(); if (MC_STATUS_INITIALIZED == status) { break; } else if (MC_STATUS_NOT_INITIALIZED == status) { // Switch to MobiCore to give it more CPU time. if (!yield()) return false; ::sleep(1); } else if (MC_STATUS_HALT == status) { dumpMobicoreStatus(); LOG_E("MobiCore halted during init !!!, state is 0x%x", status); return false; } else { // MC_STATUS_BAD_INIT or anything else LOG_E("MCI buffer init failed, state is 0x%x", status); return false; } } } nqStartOut = (notificationQueue_t *) mciBuffer; nqStartIn = (notificationQueue_t *) ((uint8_t *) nqStartOut + sizeof(notificationQueueHeader_t) + NQ_NUM_ELEMS * sizeof(notification_t)); // Set up the NWd NQ nq = new NotificationQueue(nqStartIn, nqStartOut, NQ_NUM_ELEMS); mcpBuffer_t *mcpBuf = (mcpBuffer_t *) ((uint8_t *) mciBuffer + NQ_BUFFER_SIZE); // Set up the MC flags mcFlags = &(mcpBuf->mcFlags); // Set up the MCP message mcpMessage = &(mcpBuf->mcpMessage); // convert virtual address of mapping to physical address for the init. LOG_I("MCI established, at %p, phys=%p, reused=%s", pWsmMcp->virtAddr, pWsmMcp->physAddr, mciReused ? "true" : "false"); return true; }