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 ActSignal(
44 P_ACT_DATA actData,
45 int on
46 )
47 {
48 if(actData == NULL)
49 return;
50 // If this is to turn a signal on, don't do anything if it is already on. If this
51 // is to turn the signal off, do it anyway because this might be for
52 // initialization.
53 if(on && (actData->signaled == TRUE))
54 return;
55 actData->signaled = (uint8_t)on;
56
57 // If there is an action, then replace the "Do something" with the correct action.
58 // It should test 'on' to see if it is turning the signal on or off.
59 switch(actData->number)
60 {
61 #if RH_ACT_0
62 case 0: // Do something
63 return;
64 #endif
65 #if RH_ACT_1
66 case 1: // Do something
67 return;
68 #endif
69 #if RH_ACT_2
70 case 2: // Do something
71 return;
72 #endif
73 #if RH_ACT_3
74 case 3: // Do something
75 return;
76 #endif
77 #if RH_ACT_4
78 case 4: // Do something
79 return;
80 #endif
81 #if RH_ACT_5
82 case 5: // Do something
83 return;
84 #endif
85 #if RH_ACT_6
86 case 6: // Do something
87 return;
88 #endif
89 #if RH_ACT_7
90 case 7: // Do something
91 return;
92 #endif
93 #if RH_ACT_8
94 case 8: // Do something
95 return;
96 #endif
97 #if RH_ACT_9
98 case 9: // Do something
99 return;
100 #endif
101 #if RH_ACT_A
102 case 0xA: // Do something
103 return;
104 #endif
105 #if RH_ACT_B
106 case 0xB:
107 // Do something
108 return;
109 #endif
110 #if RH_ACT_C
111 case 0xC: // Do something
112 return;
113 #endif
114 #if RH_ACT_D
115 case 0xD: // Do something
116 return;
117 #endif
118 #if RH_ACT_E
119 case 0xE: // Do something
120 return;
121 #endif
122 #if RH_ACT_F
123 case 0xF: // Do something
124 return;
125 #endif
126 default:
127 return;
128 }
129 }
130
131 //*** ActGetDataPointer()
132 static P_ACT_DATA
ActGetDataPointer(uint32_t act)133 ActGetDataPointer(
134 uint32_t act
135 )
136 {
137
138 #define RETURN_ACT_POINTER(N) if(0x##N == act) return &ACT_##N;
139
140 FOR_EACH_ACT(RETURN_ACT_POINTER)
141
142 return (P_ACT_DATA)NULL;
143 }
144
145 //*** _plat__ACT_GetImplemented()
146 // This function tests to see if an ACT is implemented. It is a belt and suspenders
147 // function because the TPM should not be calling to manipulate an ACT that is not
148 // implemented. However, this could help the simulator code which doesn't necessarily
149 // know if an ACT is implemented or not.
150 LIB_EXPORT int
_plat__ACT_GetImplemented(uint32_t act)151 _plat__ACT_GetImplemented(
152 uint32_t act
153 )
154 {
155 return (ActGetDataPointer(act) != NULL);
156 }
157
158 //*** _plat__ACT_GetRemaining()
159 // This function returns the remaining time. If an update is pending, 'newValue' is
160 // returned. Otherwise, the current counter value is returned. Note that since the
161 // timers keep running, the returned value can get stale immediately. The actual count
162 // value will be no greater than the returned value.
163 LIB_EXPORT uint32_t
_plat__ACT_GetRemaining(uint32_t act)164 _plat__ACT_GetRemaining(
165 uint32_t act //IN: the ACT selector
166 )
167 {
168 P_ACT_DATA actData = ActGetDataPointer(act);
169 uint32_t remain;
170 //
171 if(actData == NULL)
172 return 0;
173 remain = actData->remaining;
174 if(actData->pending)
175 remain = actData->newValue;
176 return remain;
177 }
178
179 //*** _plat__ACT_GetSignaled()
180 LIB_EXPORT int
_plat__ACT_GetSignaled(uint32_t act)181 _plat__ACT_GetSignaled(
182 uint32_t act //IN: number of ACT to check
183 )
184 {
185 P_ACT_DATA actData = ActGetDataPointer(act);
186 //
187 if(actData == NULL)
188 return 0;
189 return (int )actData->signaled;
190 }
191
192 //*** _plat__ACT_SetSignaled()
193 LIB_EXPORT void
_plat__ACT_SetSignaled(uint32_t act,int on)194 _plat__ACT_SetSignaled(
195 uint32_t act,
196 int on
197 )
198 {
199 ActSignal(ActGetDataPointer(act), on);
200 }
201
202 //*** _plat__ACT_GetPending()
203 LIB_EXPORT int
_plat__ACT_GetPending(uint32_t act)204 _plat__ACT_GetPending(
205 uint32_t act //IN: number of ACT to check
206 )
207 {
208 P_ACT_DATA actData = ActGetDataPointer(act);
209 //
210 if(actData == NULL)
211 return 0;
212 return (int )actData->pending;
213 }
214
215
216 //*** _plat__ACT_UpdateCounter()
217 // This function is used to write the newValue for the counter. If an update is
218 // pending, then no update occurs and the function returns FALSE. If 'setSignaled'
219 // is TRUE, then the ACT signaled state is SET and if 'newValue' is 0, nothing
220 // is posted.
221 LIB_EXPORT int
_plat__ACT_UpdateCounter(uint32_t act,uint32_t newValue)222 _plat__ACT_UpdateCounter(
223 uint32_t act, // IN: ACT to update
224 uint32_t newValue // IN: the value to post
225 )
226 {
227 P_ACT_DATA actData = ActGetDataPointer(act);
228 //
229 if(actData == NULL)
230 // actData doesn't exist but pretend update is pending rather than indicate
231 // that a retry is necessary.
232 return TRUE;
233 // if an update is pending then return FALSE so that there will be a retry
234 if(actData->pending != 0)
235 return FALSE;
236 actData->newValue = newValue;
237 actData->pending = TRUE;
238
239 return TRUE;
240 }
241
242 //***_plat__ACT_EnableTicks()
243 // This enables and disables the processing of the once-per-second ticks. This should
244 // be turned off ('enable' = FALSE) by _TPM_Init and turned on ('enable' = TRUE) by
245 // TPM2_Startup() after all the initializations have completed.
246 LIB_EXPORT void
_plat__ACT_EnableTicks(int enable)247 _plat__ACT_EnableTicks(
248 int enable
249 )
250 {
251 actTicksAllowed = enable;
252 }
253
254 //*** ActDecrement()
255 // If 'newValue' is non-zero it is copied to 'remaining' and then 'newValue' is
256 // set to zero. Then 'remaining' is decremented by one if it is not already zero. If
257 // the value is decremented to zero, then the associated event is signaled. If setting
258 // 'remaining' causes it to be greater than 1, then the signal associated with the ACT
259 // is turned off.
260 static void
ActDecrement(P_ACT_DATA actData)261 ActDecrement(
262 P_ACT_DATA actData
263 )
264 {
265 // Check to see if there is an update pending
266 if(actData->pending)
267 {
268 // If this update will cause the count to go from non-zero to zero, set
269 // the newValue to 1 so that it will timeout when decremented below.
270 if((actData->newValue == 0) && (actData->remaining != 0))
271 actData->newValue = 1;
272 actData->remaining = actData->newValue;
273
274 // Update processed
275 actData->pending = 0;
276 }
277 // no update so countdown if the count is non-zero but not max
278 if((actData->remaining != 0) && (actData->remaining != UINT32_MAX))
279 {
280 // If this countdown causes the count to go to zero, then turn the signal for
281 // the ACT on.
282 if((actData->remaining -= 1) == 0)
283 ActSignal(actData, TRUE);
284 }
285 // If the current value of the counter is non-zero, then the signal should be
286 // off.
287 if(actData->signaled && (actData->remaining > 0))
288 ActSignal(actData, FALSE);
289 }
290
291 //*** _plat__ACT_Tick()
292 // This processes the once-per-second clock tick from the hardware. This is set up
293 // for the simulator to use the control interface to send ticks to the TPM. These
294 // ticks do not have to be on a per second basis. They can be as slow or as fast as
295 // desired so that the simulation can be tested.
296 LIB_EXPORT void
_plat__ACT_Tick(void)297 _plat__ACT_Tick(
298 void
299 )
300 {
301 // Ticks processing is turned off at certain times just to make sure that nothing
302 // strange is happening before pointers and things are
303 if(actTicksAllowed)
304 {
305 // Handle the update for each counter.
306 #define DECREMENT_COUNT(N) ActDecrement(&ACT_##N);
307
308 FOR_EACH_ACT(DECREMENT_COUNT)
309 }
310 }
311
312 //*** ActZero()
313 // This function initializes a single ACT
314 static void
ActZero(uint32_t act,P_ACT_DATA actData)315 ActZero(
316 uint32_t act,
317 P_ACT_DATA actData
318 )
319 {
320 actData->remaining = 0;
321 actData->newValue = 0;
322 actData->pending = 0;
323 actData->number = (uint8_t)act;
324 ActSignal(actData, FALSE);
325 }
326
327 //***_plat__ACT_Initialize()
328 // This function initializes the ACT hardware and data structures
329 LIB_EXPORT int
_plat__ACT_Initialize(void)330 _plat__ACT_Initialize(
331 void
332 )
333 {
334 actTicksAllowed = 0;
335 #define ZERO_ACT(N) ActZero(0x##N, &ACT_##N);
336 FOR_EACH_ACT(ZERO_ACT)
337
338 return TRUE;
339 }
340
341