Home | History | Annotate | Download | only in Generic
      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_linux.h"
     43 #include "mcVersionHelper.h"
     44 
     45 #include "CMcKMod.h"
     46 
     47 #include "log.h"
     48 
     49 //------------------------------------------------------------------------------
     50 MC_CHECK_VERSION(MCDRVMODULEAPI, 1, 1);
     51 
     52 //------------------------------------------------------------------------------
     53 mcResult_t CMcKMod::mapWsm(
     54     uint32_t    len,
     55     uint32_t    *pHandle,
     56     addr_t      *pVirtAddr,
     57     addr_t      *pPhysAddr)
     58 {
     59     int ret = 0;
     60     LOG_V(" mapWsm(): len=%d", len);
     61 
     62     if (!isOpen()) {
     63         LOG_E("no connection to kmod");
     64         return MC_DRV_ERR_KMOD_NOT_OPEN;
     65     }
     66 
     67     // mapping response data is in the buffer
     68 struct mc_ioctl_map mapParams = { len:
     69         len
     70     };
     71 
     72     ret = ioctl(fdKMod, MC_IO_MAP_WSM, &mapParams);
     73     if (ret != 0) {
     74         LOG_ERRNO("ioctl MC_IO_MAP_WSM");
     75         return MAKE_MC_DRV_KMOD_WITH_ERRNO(errno);
     76     }
     77 
     78     addr_t virtAddr = ::mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED,
     79                              fdKMod, mapParams.phys_addr);
     80     if (virtAddr == MAP_FAILED) {
     81         LOG_ERRNO("mmap");
     82         return MAKE_MC_DRV_KMOD_WITH_ERRNO(errno);
     83     }
     84 
     85 
     86     LOG_V(" mapped to %p, handle=%d, phys=%p ", virtAddr,
     87           mapParams.handle, (addr_t) (mapParams.phys_addr));
     88 
     89     if (pVirtAddr != NULL) {
     90         *pVirtAddr = virtAddr;
     91     }
     92 
     93     if (pHandle != NULL) {
     94         *pHandle = mapParams.handle;
     95     }
     96 
     97     if (pPhysAddr != NULL) {
     98         *pPhysAddr = (addr_t) (mapParams.phys_addr);
     99     }
    100 
    101     return 0;
    102 }
    103 
    104 //------------------------------------------------------------------------------
    105 mcResult_t CMcKMod::mapMCI(
    106     uint32_t    len,
    107     uint32_t    *pHandle,
    108     addr_t      *pVirtAddr,
    109     addr_t      *pPhysAddr,
    110     bool        *pReuse)
    111 {
    112     LOG_I("Mapping MCI: len=%d", len);
    113     // mapping response data is in the buffer
    114 struct mc_ioctl_map mapParams = { len:
    115         len
    116     };
    117 
    118     if (!isOpen()) {
    119         LOG_E("no connection to kmod");
    120         return MC_DRV_ERR_KMOD_NOT_OPEN;
    121     }
    122 
    123     int ret = ioctl(fdKMod, MC_IO_MAP_MCI, &mapParams);
    124     if (ret != 0) {
    125         LOG_ERRNO("ioctl MC_IO_MAP_MCI");
    126         return MAKE_MC_DRV_KMOD_WITH_ERRNO(errno);
    127     }
    128 
    129     addr_t virtAddr = ::mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED,
    130                              fdKMod, 0);
    131     if (virtAddr == MAP_FAILED) {
    132         LOG_ERRNO("mmap");
    133         return MAKE_MC_DRV_KMOD_WITH_ERRNO(errno);
    134     }
    135     mapParams.addr = (unsigned long)virtAddr;
    136     *pReuse = mapParams.reused;
    137 
    138     LOG_V(" MCI mapped to %p, handle=%d, phys=%p, reused=%s",
    139           (void *)mapParams.addr, mapParams.handle, (addr_t) (mapParams.phys_addr),
    140           mapParams.reused ? "true" : "false");
    141 
    142     if (pVirtAddr != NULL) {
    143         *pVirtAddr = (void *)mapParams.addr;
    144     }
    145 
    146     if (pHandle != NULL) {
    147         *pHandle = mapParams.handle;
    148     }
    149 
    150     if (pPhysAddr != NULL) {
    151         *pPhysAddr = (addr_t) (mapParams.phys_addr);
    152     }
    153 
    154     // clean memory
    155     //memset(pMmapResp, 0, sizeof(*pMmapResp));
    156 
    157     return MC_DRV_OK;
    158 }
    159 
    160 //------------------------------------------------------------------------------
    161 mcResult_t CMcKMod::mapPersistent(
    162     uint32_t    len,
    163     uint32_t    *pHandle,
    164     addr_t      *pVirtAddr,
    165     addr_t      *pPhysAddr)
    166 {
    167     // Not currently supported by the driver
    168     LOG_E("MobiCore Driver does't support persistent buffers");
    169     return MC_DRV_ERR_NOT_IMPLEMENTED;
    170 }
    171 
    172 
    173 //------------------------------------------------------------------------------
    174 int CMcKMod::read(addr_t buffer, uint32_t len)
    175 {
    176     int ret = 0;
    177 
    178     if (!isOpen()) {
    179         LOG_E("no connection to kmod");
    180         return MC_DRV_ERR_KMOD_NOT_OPEN;
    181     }
    182 
    183     ret = ::read(fdKMod, buffer, len);
    184     if (ret == -1) {
    185         LOG_ERRNO("read");
    186     }
    187     return ret;
    188 }
    189 
    190 
    191 //------------------------------------------------------------------------------
    192 bool CMcKMod::waitSSIQ(uint32_t *pCnt)
    193 {
    194     uint32_t cnt;
    195     if (read(&cnt, sizeof(cnt)) != sizeof(cnt)) {
    196         return false;
    197     }
    198 
    199     if (pCnt != NULL) {
    200         *pCnt = cnt;
    201     }
    202 
    203     return true;
    204 }
    205 
    206 
    207 //------------------------------------------------------------------------------
    208 int CMcKMod::fcInit(uint32_t nqOffset, uint32_t nqLength, uint32_t mcpOffset,
    209                     uint32_t mcpLength)
    210 {
    211     int ret = 0;
    212 
    213     if (!isOpen()) {
    214         return MC_DRV_ERR_KMOD_NOT_OPEN;
    215     }
    216 
    217     // Init MC with NQ and MCP buffer addresses
    218     struct mc_ioctl_init fcInitParams = {
    219 nq_offset :
    220         nqOffset,
    221 nq_length :
    222         nqLength,
    223 mcp_offset :
    224         mcpOffset,
    225 mcp_length :
    226         mcpLength
    227     };
    228     ret = ioctl(fdKMod, MC_IO_INIT, &fcInitParams);
    229     if (ret != 0) {
    230         LOG_ERRNO("ioctl MC_IO_INIT");
    231     }
    232 
    233     return ret;
    234 }
    235 
    236 //------------------------------------------------------------------------------
    237 int CMcKMod::fcInfo(uint32_t extInfoId, uint32_t *pState, uint32_t *pExtInfo)
    238 {
    239     int ret = 0;
    240 
    241     if (!isOpen()) {
    242         LOG_E("no connection to kmod");
    243         return MC_DRV_ERR_KMOD_NOT_OPEN;
    244     }
    245 
    246     // Init MC with NQ and MCP buffer addresses
    247 struct mc_ioctl_info fcInfoParams = {ext_info_id :
    248         extInfoId
    249     };
    250     ret = ioctl(fdKMod, MC_IO_INFO, &fcInfoParams);
    251     if (ret != 0) {
    252         LOG_ERRNO("ioctl MC_IO_INFO");
    253         return ret;
    254     }
    255 
    256     if (pState != NULL) {
    257         *pState = fcInfoParams.state;
    258     }
    259 
    260     if (pExtInfo != NULL) {
    261         *pExtInfo = fcInfoParams.ext_info;
    262     }
    263 
    264     return ret;
    265 }
    266 
    267 
    268 //------------------------------------------------------------------------------
    269 int CMcKMod::fcYield(void)
    270 {
    271     int ret = 0;
    272 
    273     if (!isOpen()) {
    274         LOG_E("no connection to kmod");
    275         return MC_DRV_ERR_KMOD_NOT_OPEN;
    276     }
    277 
    278     ret = ioctl(fdKMod, MC_IO_YIELD, NULL);
    279     if (ret != 0) {
    280         LOG_ERRNO("ioctl MC_IO_YIELD");
    281         LOG_E("ret = %d", ret);
    282     }
    283 
    284     return ret;
    285 }
    286 
    287 
    288 //------------------------------------------------------------------------------
    289 int CMcKMod::fcNSIQ(void)
    290 {
    291     int ret = 0;
    292 
    293     if (!isOpen()) {
    294         LOG_E("no connection to kmod");
    295         return  MC_DRV_ERR_KMOD_NOT_OPEN;
    296     }
    297 
    298     ret = ioctl(fdKMod, MC_IO_NSIQ, NULL);
    299     if (ret != 0) {
    300         LOG_ERRNO("ioctl MC_IO_NSIQ");
    301         LOG_E("ret = %d", ret);
    302     }
    303 
    304     return ret;
    305 }
    306 
    307 
    308 //------------------------------------------------------------------------------
    309 mcResult_t CMcKMod::free(uint32_t handle, addr_t buffer, uint32_t len)
    310 {
    311     LOG_V("free(): handle=%d", handle);
    312 
    313     if (!isOpen()) {
    314         LOG_E("no connection to kmod");
    315         return MC_DRV_ERR_KMOD_NOT_OPEN;
    316     }
    317 
    318     // Even if unmap fails we still go on with our request
    319     if (::munmap(buffer, len)) {
    320         LOG_I("buffer = %p, len = %d", buffer, len);
    321         LOG_ERRNO("mmap failed");
    322     }
    323 
    324     int ret = ioctl(fdKMod, MC_IO_FREE, handle);
    325     if (ret != 0) {
    326         LOG_ERRNO("ioctl MC_IO_FREE");
    327         return MAKE_MC_DRV_KMOD_WITH_ERRNO(errno);
    328     }
    329 
    330     return MC_DRV_OK;
    331 }
    332 
    333 
    334 //------------------------------------------------------------------------------
    335 mcResult_t CMcKMod::registerWsmL2(
    336     addr_t      buffer,
    337     uint32_t    len,
    338     uint32_t    pid,
    339     uint32_t    *pHandle,
    340     addr_t      *pPhysWsmL2)
    341 {
    342     LOG_I(" Registering virtual buffer at %p, len=%d as World Shared Memory", buffer, len);
    343 
    344     if (!isOpen()) {
    345         LOG_E("no connection to kmod");
    346         return MC_DRV_ERR_KMOD_NOT_OPEN;
    347     }
    348 
    349     struct mc_ioctl_reg_wsm params = {
    350 buffer :
    351         (uint32_t) buffer,
    352 len :
    353         len,
    354 pid :
    355         pid
    356     };
    357 
    358     int ret = ioctl(fdKMod, MC_IO_REG_WSM, &params);
    359     if (ret != 0) {
    360         LOG_ERRNO("ioctl MC_IO_UNREG_WSM");
    361         return MAKE_MC_DRV_KMOD_WITH_ERRNO(errno);
    362     }
    363 
    364     LOG_I(" Registered, handle=%d, L2 phys=0x%x ", params.handle, params.table_phys);
    365 
    366     if (pHandle != NULL) {
    367         *pHandle = params.handle;
    368     }
    369 
    370     if (pPhysWsmL2 != NULL) {
    371         *pPhysWsmL2 = (addr_t) params.table_phys;
    372     }
    373 
    374     return MC_DRV_OK;
    375 }
    376 
    377 
    378 //------------------------------------------------------------------------------
    379 mcResult_t CMcKMod::unregisterWsmL2(uint32_t handle)
    380 {
    381     LOG_I(" Unregistering World Shared Memory with handle %d", handle);
    382 
    383     if (!isOpen()) {
    384         LOG_E("no connection to kmod");
    385         return MC_DRV_ERR_KMOD_NOT_OPEN;
    386     }
    387 
    388     int ret = ioctl(fdKMod, MC_IO_UNREG_WSM, handle);
    389     if (ret != 0) {
    390         LOG_ERRNO("ioctl MC_IO_UNREG_WSM");
    391         return MAKE_MC_DRV_KMOD_WITH_ERRNO(errno);
    392     }
    393 
    394     return MC_DRV_OK;
    395 }
    396 
    397 //------------------------------------------------------------------------------
    398 mcResult_t CMcKMod::lockWsmL2(uint32_t handle)
    399 {
    400     int ret = 0;
    401 
    402     LOG_I(" Locking World Shared Memory with handle %d", handle);
    403 
    404     if (!isOpen()) {
    405         LOG_E("no connection to kmod");
    406         return MC_DRV_ERR_KMOD_NOT_OPEN;
    407     }
    408 
    409     ret = ioctl(fdKMod, MC_IO_LOCK_WSM, handle);
    410     if (ret != 0) {
    411         LOG_ERRNO("ioctl MC_IO_UNREG_WSM");
    412         LOG_E("ret = %d", ret);
    413     }
    414 
    415     return ret;
    416 }
    417 
    418 //------------------------------------------------------------------------------
    419 mcResult_t CMcKMod::unlockWsmL2(uint32_t handle)
    420 {
    421     int ret = 0;
    422 
    423     LOG_I(" Unlocking World Shared Memory with handle %d", handle);
    424 
    425     if (!isOpen()) {
    426         LOG_E("no connection to kmod");
    427         return MC_DRV_ERR_KMOD_NOT_OPEN;
    428     }
    429 
    430     ret = ioctl(fdKMod, MC_IO_UNLOCK_WSM, handle);
    431     // Failure here is not really important
    432     if (ret != 0) {
    433         LOG_I("ret = %d", ret);
    434     }
    435 
    436     return ret;
    437 }
    438 
    439 
    440 //------------------------------------------------------------------------------
    441 addr_t CMcKMod::findWsmL2(uint32_t handle)
    442 {
    443     int ret = 0;
    444     uint32_t param = handle;
    445 
    446     LOG_I(" Resolving the WSM l2 for handle=%u", handle);
    447 
    448     if (!isOpen()) {
    449         LOG_E("no connection to kmod");
    450         return NULL;
    451     }
    452 
    453     ret = ioctl(fdKMod, MC_IO_RESOLVE_WSM, &param);
    454     if (ret != 0 || param == 0) {
    455         LOG_ERRNO("ioctl MC_IO_RESOLVE_WSM");
    456         LOG_E("param %u, ret = %d", param, ret);
    457     }
    458 
    459     return (addr_t)param;
    460 }
    461 
    462 //------------------------------------------------------------------------------
    463 mcResult_t CMcKMod::findContiguousWsm(uint32_t handle, addr_t *phys, uint32_t *len)
    464 {
    465     mcResult_t ret = MC_DRV_OK;
    466     struct mc_ioctl_resolv_cont_wsm wsm;
    467 
    468     wsm.handle = handle;
    469 
    470     LOG_I(" Resolving the contiguous WSM l2 for handle=%u", handle);
    471 
    472     if (!isOpen()) {
    473         LOG_E("no connection to kmod");
    474         return NULL;
    475     }
    476 
    477     ret = ioctl(fdKMod, MC_IO_RESOLVE_CONT_WSM, &wsm);
    478     if (ret != 0) {
    479         LOG_ERRNO("ioctl MC_IO_RESOLVE_CONT_WSM");
    480     } else {
    481         *phys = (addr_t)wsm.phys;
    482         *len = wsm.length;
    483     }
    484 
    485     return ret;
    486 }
    487 
    488 //------------------------------------------------------------------------------
    489 mcResult_t CMcKMod::cleanupWsmL2(void)
    490 {
    491     int ret = 0;
    492 
    493     LOG_I(" Cleaning up the orphaned bulk buffers");
    494 
    495     if (!isOpen()) {
    496         LOG_E("no connection to kmod");
    497         return MC_DRV_ERR_KMOD_NOT_OPEN;
    498     }
    499 
    500     ret = ioctl(fdKMod, MC_IO_CLEAN_WSM, 0);
    501     if (ret != 0) {
    502         LOG_ERRNO("ioctl MC_IO_UNREG_WSM");
    503         LOG_E("ret = %d", ret);
    504     }
    505 
    506     return ret;
    507 }
    508 
    509 //------------------------------------------------------------------------------
    510 int CMcKMod::fcExecute(addr_t startAddr, uint32_t areaLength)
    511 {
    512     int ret = 0;
    513     struct mc_ioctl_execute params = {
    514 phys_start_addr :
    515         (uint32_t)startAddr,
    516 length :
    517         areaLength
    518     };
    519 
    520     if (!isOpen()) {
    521         LOG_E("no connection to kmod");
    522         return MC_DRV_ERR_KMOD_NOT_OPEN;
    523     }
    524 
    525     ret = ioctl(fdKMod, MC_IO_EXECUTE, &params);
    526     if (ret != 0) {
    527         LOG_ERRNO("ioctl MC_IO_EXECUTE");
    528     }
    529 
    530     return ret;
    531 }
    532 //------------------------------------------------------------------------------
    533 bool CMcKMod::checkVersion(void)
    534 {
    535     uint32_t version;
    536     if (!isOpen()) {
    537         LOG_E("no connection to kmod");
    538         return false;
    539     }
    540 
    541     int ret = ioctl(fdKMod, MC_IO_VERSION, &version);
    542     if (ret != 0) {
    543         LOG_ERRNO("ioctl MC_IO_VERSION");
    544         LOG_E("ret = %d", ret);
    545         return false;
    546     }
    547 
    548     // Run-time check.
    549     char *errmsg;
    550     if (!checkVersionOkMCDRVMODULEAPI(version, &errmsg)) {
    551         LOG_E("%s", errmsg);
    552         return false;
    553     }
    554     LOG_I("%s", errmsg);
    555 
    556     return true;
    557 }
    558 
    559 /** @} */
    560