Coverage Report

Created: 2024-10-04 06:14

/src/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformACT.c
Line
Count
Source (jump to first uncovered line)
1
/* Microsoft Reference Implementation for TPM 2.0
2
 *
3
 *  The copyright in this software is being made available under the BSD License,
4
 *  included below. This software may be subject to other third party and
5
 *  contributor rights, including patent rights, and no such rights are granted
6
 *  under this license.
7
 *
8
 *  Copyright (c) Microsoft Corporation
9
 *
10
 *  All rights reserved.
11
 *
12
 *  BSD License
13
 *
14
 *  Redistribution and use in source and binary forms, with or without modification,
15
 *  are permitted provided that the following conditions are met:
16
 *
17
 *  Redistributions of source code must retain the above copyright notice, this list
18
 *  of conditions and the following disclaimer.
19
 *
20
 *  Redistributions in binary form must reproduce the above copyright notice, this
21
 *  list of conditions and the following disclaimer in the documentation and/or
22
 *  other materials provided with the distribution.
23
 *
24
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28
 *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31
 *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
 *  (INCLUDING 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
//** Includes
36
#include "Platform.h"
37
38
//** Functions
39
40
//*** ActSignal()
41
// Function called when there is an ACT event to signal or unsignal
42
static void ActSignal(P_ACT_DATA actData, int on)
43
16.5k
{
44
16.5k
    if(actData == NULL)
45
0
        return;
46
    // If this is to turn a signal on, don't do anything if it is already on. If this
47
    // is to turn the signal off, do it anyway because this might be for
48
    // initialization.
49
16.5k
    if(on && (actData->signaled == TRUE))
50
0
        return;
51
16.5k
    actData->signaled = (uint8_t)on;
52
53
    // If there is an action, then replace the "Do something" with the correct action.
54
    // It should test 'on' to see if it is turning the signal on or off.
55
16.5k
    switch(actData->number)
56
16.5k
    {
57
0
#if RH_ACT_0
58
8.29k
        case 0:  // Do something
59
8.29k
            return;
60
0
#endif
61
#if RH_ACT_1
62
        case 1:  // Do something
63
            return;
64
#endif
65
#if RH_ACT_2
66
        case 2:  // Do something
67
            return;
68
#endif
69
#if RH_ACT_3
70
        case 3:  // Do something
71
            return;
72
#endif
73
#if RH_ACT_4
74
        case 4:  // Do something
75
            return;
76
#endif
77
#if RH_ACT_5
78
        case 5:  // Do something
79
            return;
80
#endif
81
#if RH_ACT_6
82
        case 6:  // Do something
83
            return;
84
#endif
85
#if RH_ACT_7
86
        case 7:  // Do something
87
            return;
88
#endif
89
#if RH_ACT_8
90
        case 8:  // Do something
91
            return;
92
#endif
93
#if RH_ACT_9
94
        case 9:  // Do something
95
            return;
96
#endif
97
0
#if RH_ACT_A
98
8.29k
        case 0xA:  // Do something
99
8.29k
            return;
100
0
#endif
101
#if RH_ACT_B
102
        case 0xB:
103
            // Do something
104
            return;
105
#endif
106
#if RH_ACT_C
107
        case 0xC:  // Do something
108
            return;
109
#endif
110
#if RH_ACT_D
111
        case 0xD:  // Do something
112
            return;
113
#endif
114
#if RH_ACT_E
115
        case 0xE:  // Do something
116
            return;
117
#endif
118
#if RH_ACT_F
119
        case 0xF:  // Do something
120
            return;
121
#endif
122
0
        default:
123
0
            return;
124
16.5k
    }
125
16.5k
}
126
127
//*** ActGetDataPointer()
128
static P_ACT_DATA ActGetDataPointer(uint32_t act)
129
23.8k
{
130
131
23.8k
#define RETURN_ACT_POINTER(N) \
132
35.8k
  if(0x##N == act)            \
133
35.8k
    return &ACT_##N;
134
135
35.8k
    FOR_EACH_ACT(RETURN_ACT_POINTER)
136
137
19
    return (P_ACT_DATA)NULL;
138
11.9k
}
139
140
//*** _plat__ACT_GetImplemented()
141
// This function tests to see if an ACT is implemented. It is a belt and suspenders
142
// function because the TPM should not be calling to manipulate an ACT that is not
143
// implemented. However, this could help the simulator code which doesn't necessarily
144
// know if an ACT is implemented or not.
145
LIB_EXPORT int _plat__ACT_GetImplemented(uint32_t act)
146
106
{
147
106
    return (ActGetDataPointer(act) != NULL);
148
106
}
149
150
//*** _plat__ACT_GetRemaining()
151
// This function returns the remaining time. If an update is pending, 'newValue' is
152
// returned. Otherwise, the current counter value is returned. Note that since the
153
// timers keep running, the returned value can get stale immediately. The actual count
154
// value will be no greater than the returned value.
155
LIB_EXPORT uint32_t _plat__ACT_GetRemaining(uint32_t act  //IN: the ACT selector
156
)
157
11.8k
{
158
11.8k
    P_ACT_DATA actData = ActGetDataPointer(act);
159
11.8k
    uint32_t   remain;
160
    //
161
11.8k
    if(actData == NULL)
162
0
        return 0;
163
11.8k
    remain = actData->remaining;
164
11.8k
    if(actData->pending)
165
0
        remain = actData->newValue;
166
11.8k
    return remain;
167
11.8k
}
168
169
//*** _plat__ACT_GetSignaled()
170
LIB_EXPORT int _plat__ACT_GetSignaled(uint32_t act  //IN: number of ACT to check
171
)
172
11.8k
{
173
11.8k
    P_ACT_DATA actData = ActGetDataPointer(act);
174
    //
175
11.8k
    if(actData == NULL)
176
0
        return 0;
177
11.8k
    return (int)actData->signaled;
178
11.8k
}
179
180
//*** _plat__ACT_SetSignaled()
181
LIB_EXPORT void _plat__ACT_SetSignaled(uint32_t act, int on)
182
0
{
183
0
    ActSignal(ActGetDataPointer(act), on);
184
0
}
185
186
//*** _plat__ACT_GetPending()
187
LIB_EXPORT int _plat__ACT_GetPending(uint32_t act  //IN: number of ACT to check
188
)
189
0
{
190
0
    P_ACT_DATA actData = ActGetDataPointer(act);
191
    //
192
0
    if(actData == NULL)
193
0
        return 0;
194
0
    return (int)actData->pending;
195
0
}
196
197
//*** _plat__ACT_UpdateCounter()
198
// This function is used to write the newValue for the counter. If an update is
199
// pending, then no update occurs and the function returns FALSE. If 'setSignaled'
200
// is TRUE, then the ACT signaled state is SET and if 'newValue' is 0, nothing
201
// is posted.
202
LIB_EXPORT int _plat__ACT_UpdateCounter(uint32_t act,      // IN: ACT to update
203
                                        uint32_t newValue  // IN: the value to post
204
)
205
52
{
206
52
    P_ACT_DATA actData = ActGetDataPointer(act);
207
    //
208
52
    if(actData == NULL)
209
        // actData doesn't exist but pretend update is pending rather than indicate
210
        // that a retry is necessary.
211
0
        return TRUE;
212
    // if an update is pending then return FALSE so that there will be a retry
213
52
    if(actData->pending != 0)
214
0
        return FALSE;
215
52
    actData->newValue = newValue;
216
52
    actData->pending  = TRUE;
217
218
52
    return TRUE;
219
52
}
220
221
//***_plat__ACT_EnableTicks()
222
// This enables and disables the processing of the once-per-second ticks. This should
223
// be turned off ('enable' = FALSE) by _TPM_Init and turned on ('enable' = TRUE) by
224
// TPM2_Startup() after all the initializations have completed.
225
LIB_EXPORT void _plat__ACT_EnableTicks(int enable)
226
16.5k
{
227
16.5k
    actTicksAllowed = enable;
228
16.5k
}
229
230
//*** ActDecrement()
231
// If 'newValue' is non-zero it is copied to 'remaining' and then 'newValue' is
232
// set to zero. Then 'remaining' is decremented by one if it is not already zero. If
233
// the value is decremented to zero, then the associated event is signaled. If setting
234
// 'remaining' causes it to be greater than 1, then the signal associated with the ACT
235
// is turned off.
236
static void ActDecrement(P_ACT_DATA actData)
237
0
{
238
    // Check to see if there is an update pending
239
0
    if(actData->pending)
240
0
    {
241
        // If this update will cause the count to go from non-zero to zero, set
242
        // the newValue to 1 so that it will timeout when decremented below.
243
0
        if((actData->newValue == 0) && (actData->remaining != 0))
244
0
            actData->newValue = 1;
245
0
        actData->remaining = actData->newValue;
246
247
        // Update processed
248
0
        actData->pending = 0;
249
0
    }
250
    // no update so countdown if the count is non-zero but not max
251
0
    if((actData->remaining != 0) && (actData->remaining != UINT32_MAX))
252
0
    {
253
        // If this countdown causes the count to go to zero, then turn the signal for
254
        // the ACT on.
255
0
        if((actData->remaining -= 1) == 0)
256
0
            ActSignal(actData, TRUE);
257
0
    }
258
    // If the current value of the counter is non-zero, then the signal should be
259
    // off.
260
0
    if(actData->signaled && (actData->remaining > 0))
261
0
        ActSignal(actData, FALSE);
262
0
}
263
264
//*** _plat__ACT_Tick()
265
// This processes the once-per-second clock tick from the hardware. This is set up
266
// for the simulator to use the control interface to send ticks to the TPM. These
267
// ticks do not have to be on a per second basis. They can be as slow or as fast as
268
// desired so that the simulation can be tested.
269
LIB_EXPORT void _plat__ACT_Tick(void)
270
0
{
271
    // Ticks processing is turned off at certain times just to make sure that nothing
272
    // strange is happening before pointers and things are
273
0
    if(actTicksAllowed)
274
0
    {
275
        // Handle the update for each counter.
276
0
#define DECREMENT_COUNT(N) ActDecrement(&ACT_##N);
277
278
0
        FOR_EACH_ACT(DECREMENT_COUNT)
279
0
    }
280
0
}
281
282
//*** ActZero()
283
// This function initializes a single ACT
284
static void ActZero(uint32_t act, P_ACT_DATA actData)
285
16.5k
{
286
16.5k
    actData->remaining = 0;
287
16.5k
    actData->newValue  = 0;
288
16.5k
    actData->pending   = 0;
289
16.5k
    actData->number    = (uint8_t)act;
290
16.5k
    ActSignal(actData, FALSE);
291
16.5k
}
292
293
//***_plat__ACT_Initialize()
294
// This function initializes the ACT hardware and data structures
295
LIB_EXPORT int _plat__ACT_Initialize(void)
296
8.29k
{
297
8.29k
    actTicksAllowed = 0;
298
16.5k
#define ZERO_ACT(N) ActZero(0x##N, &ACT_##N);
299
16.5k
    FOR_EACH_ACT(ZERO_ACT)
300
301
8.29k
    return TRUE;
302
8.29k
}