CMcKMod.cpp revision 4e9e8c9c0169b40318386436d762c3d73cf4c328
1/** @addtogroup MCD_MCDIMPL_DAEMON_KERNEL 2 * @{ 3 * @file 4 * 5 * MobiCore Driver Kernel Module Interface. 6 * 7 * <!-- 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#include <cstdlib> 34 35#include <sys/mman.h> 36#include <sys/ioctl.h> 37#include <errno.h> 38#include <inttypes.h> 39#include <cstring> 40 41#include "McTypes.h" 42#include "mc_drv_module_api.h" 43#include "mcVersionHelper.h" 44 45#include "CMcKMod.h" 46 47#define LOG_TAG "McDaemon" 48#include "log.h" 49 50//------------------------------------------------------------------------------ 51MC_CHECK_VERSION(MCDRVMODULEAPI,0,1); 52 53// TODO: rename this to mapWsm 54//------------------------------------------------------------------------------ 55int CMcKMod::mmap( 56 uint32_t len, 57 uint32_t *pHandle, 58 addr_t *pVirtAddr, 59 addr_t *pPhysAddr, 60 bool *pMciReuse 61) { 62 int ret = 0; 63 do 64 { 65 LOG_I("mmap(): len=%d, mci_reuse=%x", len, *pMciReuse); 66 67 if (!isOpen()) 68 { 69 LOG_E("no connection to kmod"); 70 ret = ERROR_KMOD_NOT_OPEN; 71 break; 72 } 73 74 // TODO: add type parameter to distinguish between non-freeing TCI, MCI and others 75 addr_t virtAddr = ::mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, 76 fdKMod, *pMciReuse ? MC_DRV_KMOD_MMAP_MCI 77 : MC_DRV_KMOD_MMAP_WSM); 78 if (MAP_FAILED == virtAddr) 79 { 80 LOG_E("mmap() failed with errno: %d", errno); 81 ret = ERROR_MAPPING_FAILED; 82 break; 83 } 84 85 // mapping response data is in the buffer 86 struct mc_mmap_resp *pMmapResp = (struct mc_mmap_resp *) virtAddr; 87 88 *pMciReuse = pMmapResp->is_reused; 89 90 LOG_I("mmap(): virtAddr=%p, handle=%d, phys_addr=%p, is_reused=%s", 91 virtAddr, pMmapResp->handle, (addr_t) (pMmapResp->phys_addr), 92 pMmapResp->is_reused ? "true" : "false"); 93 94 if (NULL != pVirtAddr) 95 { 96 *pVirtAddr = virtAddr; 97 } 98 99 if (NULL != pHandle) 100 { 101 *pHandle = pMmapResp->handle; 102 } 103 104 if (NULL != pPhysAddr) 105 { 106 *pPhysAddr = (addr_t) (pMmapResp->phys_addr); 107 } 108 109 // clean memory 110 memset(pMmapResp, 0, sizeof(*pMmapResp)); 111 112 } while (0); 113 114 return ret; 115} 116 117 118//------------------------------------------------------------------------------ 119int CMcKMod::mapPersistent( 120 uint32_t len, 121 uint32_t *pHandle, 122 addr_t *pVirtAddr, 123 addr_t *pPhysAddr 124) { 125 int ret = 0; 126 do 127 { 128 LOG_I("mapPersistent(): len=%d", len); 129 130 if (!isOpen()) 131 { 132 LOG_E("no connection to kmod"); 133 ret = ERROR_KMOD_NOT_OPEN; 134 break; 135 } 136 137 addr_t virtAddr = ::mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, 138 fdKMod, MC_DRV_KMOD_MMAP_PERSISTENTWSM); 139 140 if (MAP_FAILED == virtAddr) 141 { 142 LOG_E("mmap() failed with errno: %d", errno); 143 ret = ERROR_MAPPING_FAILED; 144 break; 145 } 146 147 // mapping response data is in the buffer 148 struct mc_mmap_resp *pMmapResp = (struct mc_mmap_resp *) virtAddr; 149 150 LOG_I("mapPersistent(): virtAddr=%p, handle=%d, phys_addr=%p, is_reused=%s", 151 virtAddr, pMmapResp->handle, 152 (addr_t) (pMmapResp->phys_addr), 153 pMmapResp->is_reused ? "true" : "false"); 154 155 if (NULL != pVirtAddr) 156 { 157 *pVirtAddr = virtAddr; 158 } 159 160 if (NULL != pHandle) 161 { 162 *pHandle = pMmapResp->handle; 163 } 164 165 if (NULL != pPhysAddr) 166 { 167 *pPhysAddr = (addr_t) (pMmapResp->phys_addr); 168 } 169 170 // clean memory 171 memset(pMmapResp, 0, sizeof(*pMmapResp)); 172 173 } while (0); 174 175 return ret; 176} 177 178 179//------------------------------------------------------------------------------ 180int CMcKMod::read( 181 addr_t buffer, 182 uint32_t len 183) { 184 int ret = 0; 185 186 do 187 { 188 if (!isOpen()) 189 { 190 LOG_E("no connection to kmod"); 191 ret = ERROR_KMOD_NOT_OPEN; 192 break; 193 } 194 195 ret = ::read(fdKMod, buffer, len); 196 if(-1 == ret) 197 { 198 LOG_E("read() failed with errno: %d", errno); 199 } 200 201 } while (0); 202 203 return ret; 204} 205 206 207//------------------------------------------------------------------------------ 208bool CMcKMod::waitSSIQ( 209 uint32_t *pCnt 210) { 211 int ret = true; 212 213 do 214 { 215 uint32_t cnt; 216 int ret = read(&cnt, sizeof(cnt)); 217 if (sizeof(cnt) != ret) 218 { 219 ret = false; 220 } 221 222 if (NULL != pCnt) 223 { 224 *pCnt = cnt; 225 } 226 227 } while (0); 228 229 return ret; 230} 231 232 233//------------------------------------------------------------------------------ 234int CMcKMod::fcInit( 235 addr_t mciBuffer, 236 uint32_t nqOffset, 237 uint32_t nqLength, 238 uint32_t mcpOffset, 239 uint32_t mcpLength 240) { 241 int ret = 0; 242 243 do 244 { 245 if (!isOpen()) 246 { 247 ret = ERROR_KMOD_NOT_OPEN; 248 break; 249 } 250 251 // Init MC with NQ and MCP buffer addresses 252 union mc_ioctl_init_params fcInitParams = { 253 // C++ does not support C99 designated initializers 254 /* .in = */{ 255 /* .base = */(uint32_t) mciBuffer, 256 /* .nq_offset = */nqOffset, 257 /* .nq_length = */nqLength, 258 /* .mcp_offset = */mcpOffset, 259 /* .mcp_length = */mcpLength } }; 260 ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_INIT, &fcInitParams); 261 if (ret != 0) 262 { 263 LOG_E("IOCTL_FC_INIT failed with ret = %d and errno = %d", ret, errno); 264 break; 265 } 266 267 } while (0); 268 269 return ret; 270} 271 272 273//------------------------------------------------------------------------------ 274int CMcKMod::fcInfo( 275 uint32_t extInfoId, 276 uint32_t *pState, 277 uint32_t *pExtInfo 278) { 279 int ret = 0; 280 281 do 282 { 283 if (!isOpen()) 284 { 285 LOG_E("no connection to kmod"); 286 ret = ERROR_KMOD_NOT_OPEN; 287 break; 288 } 289 290 // Init MC with NQ and MCP buffer addresses 291 union mc_ioctl_info_params fcInfoParams = { 292 // C++ does not support C99 designated initializers 293 /* .in = */{ 294 /* .ext_info_id = */extInfoId } }; 295 ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_INFO, &fcInfoParams); 296 if (ret != 0) 297 { 298 LOG_E("IOCTL_FC_INFO failed with ret = %d and errno = %d", ret, errno); 299 break; 300 } 301 302 if (NULL != pState) 303 { 304 *pState = fcInfoParams.out.state; 305 } 306 307 if (NULL != pExtInfo) 308 { 309 *pExtInfo = fcInfoParams.out.ext_info; 310 } 311 312 } while (0); 313 314 return ret; 315} 316 317 318//------------------------------------------------------------------------------ 319int CMcKMod::fcYield( 320 void 321) { 322 int ret = 0; 323 324 do 325 { 326 if (!isOpen()) 327 { 328 LOG_E("no connection to kmod"); 329 ret = ERROR_KMOD_NOT_OPEN; 330 break; 331 } 332 333 ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_YIELD, NULL); 334 if (ret != 0) 335 { 336 LOG_E("IOCTL_FC_YIELD failed with ret = %d and errno = %d", ret, errno); 337 break; 338 } 339 340 } while (0); 341 342 return ret; 343} 344 345 346//------------------------------------------------------------------------------ 347int CMcKMod::fcNSIQ( 348 void 349) { 350 int ret = 0; 351 352 do 353 { 354 if (!isOpen()) 355 { 356 LOG_E("no connection to kmod"); 357 ret = ERROR_KMOD_NOT_OPEN; 358 break; 359 } 360 361 ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_NSIQ, NULL); 362 if (ret != 0) 363 { 364 LOG_E("IOCTL_FC_NSIQ failed with ret = %d and errno = %d", ret, errno); 365 break; 366 } 367 368 } while (0); 369 370 return ret; 371} 372 373 374//------------------------------------------------------------------------------ 375int CMcKMod::free( 376 uint32_t handle 377) { 378 int ret = 0; 379 380 do 381 { 382 LOG_I("free(): handle=%d", handle); 383 384 if (!isOpen()) 385 { 386 LOG_E("no connection to kmod"); 387 ret = ERROR_KMOD_NOT_OPEN; 388 break; 389 } 390 391 union mc_ioctl_free_params freeParams = { 392 // C++ does not support c99 designated initializers 393 /* .in = */{ 394 /* .handle = */(uint32_t) handle } }; 395 396 ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FREE, &freeParams); 397 if (0 != ret) 398 { 399 LOG_E("IOCTL_FREE failed with ret = %d and errno = %d", ret, errno); 400 break; 401 } 402 403 } while (0); 404 405 return ret; 406} 407 408 409//------------------------------------------------------------------------------ 410int CMcKMod::registerWsmL2( 411 addr_t buffer, 412 uint32_t len, 413 uint32_t pid, 414 uint32_t *pHandle, 415 addr_t *pPhysWsmL2 416) { 417 int ret = 0; 418 419 do 420 { 421 LOG_I("registerWsmL2(): buffer=%p, len=%d, pid=%d", buffer, len, pid); 422 423 if (!isOpen()) 424 { 425 LOG_E("no connection to kmod"); 426 ret = ERROR_KMOD_NOT_OPEN; 427 break; 428 } 429 430 union mc_ioctl_app_reg_wsm_l2_params params = { 431 // C++ does not support C99 designated initializers 432 /* .in = */{ 433 /* .buffer = */(uint32_t) buffer, 434 /* .len = */len, 435 /* .pid = */pid } }; 436 437 ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_APP_REGISTER_WSM_L2, ¶ms); 438 if (0 != ret) 439 { 440 LOG_E("IOCTL_APP_REGISTER_WSM_L2 failed with ret = %d and errno = %d", ret, errno); 441 break; 442 } 443 444 LOG_I("WSM L2 phys=%x, handle=%d", params.out.phys_wsm_l2_table, 445 params.out.handle); 446 447 if (NULL != pHandle) 448 { 449 *pHandle = params.out.handle; 450 } 451 452 if (NULL != pPhysWsmL2) 453 { 454 *pPhysWsmL2 = (addr_t) params.out.phys_wsm_l2_table; 455 } 456 457 } while (0); 458 459 return ret; 460} 461 462 463//------------------------------------------------------------------------------ 464int CMcKMod::unregisterWsmL2( 465 uint32_t handle 466) { 467 int ret = 0; 468 469 do 470 { 471 LOG_I("unregisterWsmL2(): handle=%d", handle); 472 473 if (!isOpen()) 474 { 475 LOG_E("no connection to kmod"); 476 ret = ERROR_KMOD_NOT_OPEN; 477 break; 478 } 479 480 struct mc_ioctl_app_unreg_wsm_l2_params params = { 481 // C++ does not support c99 designated initializers 482 /* .in = */{ 483 /* .handle = */handle } }; 484 485 int ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_APP_UNREGISTER_WSM_L2, ¶ms); 486 if (0 != ret) 487 { 488 LOG_E("IOCTL_APP_UNREGISTER_WSM_L2 failed with ret = %d and errno = %d", ret, errno); 489 break; 490 } 491 492 } while (0); 493 494 return ret; 495} 496 497//------------------------------------------------------------------------------ 498int CMcKMod::fcExecute( 499 addr_t startAddr, 500 uint32_t areaLength 501) { 502 int ret = 0; 503 union mc_ioctl_fc_execute_params params = { 504 /*.in =*/ { 505 /*.phys_start_addr = */ (uint32_t)startAddr, 506 /*.length = */ areaLength 507 } 508 }; 509 do 510 { 511 if (!isOpen()) 512 { 513 LOG_E("no connection to kmod"); 514 break; 515 } 516 517 ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_EXECUTE, ¶ms); 518 if (ret != 0) 519 { 520 LOG_E("IOCTL_FC_EXECUTE failed with ret = %d and errno = %d", ret, errno); 521 break; 522 } 523 524 } while(0); 525 526 return ret; 527} 528//------------------------------------------------------------------------------ 529bool CMcKMod::checkKmodVersionOk( 530 void 531) { 532 bool ret = false; 533 534 do 535 { 536 if (!isOpen()) 537 { 538 LOG_E("no connection to kmod"); 539 break; 540 } 541 542 struct mc_ioctl_get_version_params params; 543 544 int ioret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_GET_VERSION, ¶ms); 545 if (0 != ioret) 546 { 547 LOG_E("IOCTL_GET_VERSION failed with ret = %d and errno = %d", ret, errno); 548 break; 549 } 550 551 // Run-time check. 552 char* errmsg; 553 if (!checkVersionOkMCDRVMODULEAPI(params.out.kernel_module_version, &errmsg)) { 554 LOG_E("%s", errmsg); 555 break; 556 } 557 LOG_I("%s", errmsg); 558 559 ret = true; 560 561 } while (0); 562 563 return ret; 564} 565 566/** @} */ 567