1/** @addtogroup MCD_IMPL_LIB
2 * @{
3 * @file
4 *
5 * Client library device management.
6 *
7 * Device and Trustlet Session management Funtions.
8 *
9 * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote
20 *    products derived from this software without specific prior
21 *    written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
24 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35#include <stdint.h>
36#include <vector>
37
38#include "mc_linux.h"
39#include "Device.h"
40
41#include "log.h"
42#include <assert.h>
43
44
45//------------------------------------------------------------------------------
46Device::Device(uint32_t deviceId, Connection *connection)
47{
48    this->deviceId = deviceId;
49    this->connection = connection;
50
51    pMcKMod = new CMcKMod();
52}
53
54
55//------------------------------------------------------------------------------
56Device::~Device(void)
57{
58    /* Delete all session objects. Usually this should not be needed as closeDevice()
59     * requires that all sessions have been closed before.
60     */
61    sessionIterator_t  sessionIterator = sessionList.begin();
62    while (sessionIterator != sessionList.end()) {
63        delete (*sessionIterator);
64        sessionIterator = sessionList.erase(sessionIterator);
65    }
66
67    // Free all allocated WSM descriptors
68    wsmIterator_t  wsmIterator = wsmL2List.begin();
69    while (wsmIterator != wsmL2List.end()) {
70        CWsm_ptr pWsm = *wsmIterator;
71
72        // ignore return code
73        pMcKMod->free(pWsm->handle, pWsm->virtAddr, pWsm->len);
74
75        delete (*wsmIterator);
76        wsmIterator = wsmL2List.erase(wsmIterator);
77    }
78    delete connection;
79    delete pMcKMod;
80}
81
82
83//------------------------------------------------------------------------------
84bool Device::open(const char *deviceName)
85{
86    return pMcKMod->open(deviceName);
87}
88
89
90//------------------------------------------------------------------------------
91void Device::close(void)
92{
93    pMcKMod->close();
94}
95
96
97//------------------------------------------------------------------------------
98bool Device::hasSessions(void)
99{
100    return sessionList.size() > 0;
101}
102
103
104//------------------------------------------------------------------------------
105void Device::createNewSession(uint32_t sessionId, Connection  *connection)
106{
107    Session *session = new Session(sessionId, pMcKMod, connection);
108    sessionList.push_back(session);
109}
110
111
112//------------------------------------------------------------------------------
113bool Device::removeSession(uint32_t sessionId)
114{
115    bool ret = false;
116
117    sessionIterator_t interator = sessionList.begin();
118    while (interator != sessionList.end()) {
119        if ((*interator)->sessionId == sessionId) {
120            delete (*interator);
121            interator = sessionList.erase(interator);
122            ret = true;
123            break;
124        } else {
125            interator++;
126        }
127    }
128    return ret;
129}
130
131
132//------------------------------------------------------------------------------
133Session *Device::resolveSessionId(uint32_t sessionId)
134{
135    Session  *ret = NULL;
136
137    // Get Session for sessionId
138    for ( sessionIterator_t interator = sessionList.begin();
139            interator != sessionList.end();
140            ++interator) {
141        if ((*interator)->sessionId == sessionId) {
142            ret = (*interator);
143            break;
144        }
145    }
146    return ret;
147}
148
149
150//------------------------------------------------------------------------------
151mcResult_t Device::allocateContiguousWsm(uint32_t len, CWsm **wsm)
152{
153    // Allocate shared memory
154    addr_t    virtAddr;
155    uint32_t  handle;
156    addr_t    physAddr;
157    mcResult_t  ret;
158
159    assert(wsm != NULL);
160
161    if (!len) {
162        return MC_DRV_ERR_INVALID_LENGTH;
163    }
164
165    ret = pMcKMod->mapWsm(len, &handle, &virtAddr, &physAddr);
166    if (ret) {
167        return ret;
168    }
169
170    LOG_I(" mapped handle %d to %p, phys=%p ", handle, virtAddr, physAddr);
171
172    // Register (vaddr,paddr) with device
173    *wsm = new CWsm(virtAddr, len, handle, physAddr);
174
175    wsmL2List.push_back(*wsm);
176
177    // Return pointer to the allocated memory
178    return MC_DRV_OK;
179}
180
181
182//------------------------------------------------------------------------------
183mcResult_t Device::freeContiguousWsm(CWsm_ptr  pWsm)
184{
185    mcResult_t ret = MC_DRV_ERR_WSM_NOT_FOUND;
186    wsmIterator_t iterator;
187
188    for (iterator = wsmL2List.begin(); iterator != wsmL2List.end(); ++iterator) {
189        if (pWsm == *iterator) {
190            ret = MC_DRV_OK;
191            break;
192        }
193    }
194    // We just looked this up using findContiguousWsm
195    assert(ret == MC_DRV_OK);
196
197    LOG_I(" unmapping handle %d from %p, phys=%p",
198          pWsm->handle, pWsm->virtAddr, pWsm->physAddr);
199
200    ret = pMcKMod->free(pWsm->handle, pWsm->virtAddr, pWsm->len);
201    if (ret != MC_DRV_OK) {
202        // developer forgot to free all references of this memory, we do not remove the reference here
203        return ret;
204    }
205
206    iterator = wsmL2List.erase(iterator);
207    delete pWsm;
208
209    return ret;
210}
211
212
213//------------------------------------------------------------------------------
214CWsm_ptr Device::findContiguousWsm(addr_t  virtAddr)
215{
216    CWsm_ptr pWsm = NULL;
217
218    for ( wsmIterator_t iterator = wsmL2List.begin();
219            iterator != wsmL2List.end();
220            ++iterator) {
221        CWsm_ptr pTmpWsm = *iterator;
222        if (virtAddr == pTmpWsm->virtAddr) {
223            pWsm = pTmpWsm;
224            break;
225        }
226    }
227
228    return pWsm;
229}
230
231/** @} */
232