• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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