/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 | } |