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