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