• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //------------------------------------------------------------------------------
mapWsm(uint32_t len,uint32_t * pHandle,addr_t * pVirtAddr,addr_t * pPhysAddr)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 //------------------------------------------------------------------------------
mapMCI(uint32_t len,uint32_t * pHandle,addr_t * pVirtAddr,addr_t * pPhysAddr,bool * pReuse)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 //------------------------------------------------------------------------------
mapPersistent(uint32_t len,uint32_t * pHandle,addr_t * pVirtAddr,addr_t * pPhysAddr)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 //------------------------------------------------------------------------------
read(addr_t buffer,uint32_t len)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 //------------------------------------------------------------------------------
waitSSIQ(uint32_t * pCnt)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 //------------------------------------------------------------------------------
fcInit(uint32_t nqOffset,uint32_t nqLength,uint32_t mcpOffset,uint32_t mcpLength)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 //------------------------------------------------------------------------------
fcInfo(uint32_t extInfoId,uint32_t * pState,uint32_t * pExtInfo)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 //------------------------------------------------------------------------------
fcYield(void)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 //------------------------------------------------------------------------------
fcNSIQ(void)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 //------------------------------------------------------------------------------
free(uint32_t handle,addr_t buffer,uint32_t len)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 //------------------------------------------------------------------------------
registerWsmL2(addr_t buffer,uint32_t len,uint32_t pid,uint32_t * pHandle,addr_t * pPhysWsmL2)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 //------------------------------------------------------------------------------
unregisterWsmL2(uint32_t handle)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 //------------------------------------------------------------------------------
lockWsmL2(uint32_t handle)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 //------------------------------------------------------------------------------
unlockWsmL2(uint32_t handle)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 //------------------------------------------------------------------------------
findWsmL2(uint32_t handle)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 //------------------------------------------------------------------------------
findContiguousWsm(uint32_t handle,addr_t * phys,uint32_t * len)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 //------------------------------------------------------------------------------
cleanupWsmL2(void)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 //------------------------------------------------------------------------------
fcExecute(addr_t startAddr,uint32_t areaLength)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 //------------------------------------------------------------------------------
checkVersion(void)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