| /* Microsoft Reference Implementation for TPM 2.0 |
| * |
| * The copyright in this software is being made available under the BSD License, |
| * included below. This software may be subject to other third party and |
| * contributor rights, including patent rights, and no such rights are granted |
| * under this license. |
| * |
| * Copyright (c) Microsoft Corporation |
| * |
| * All rights reserved. |
| * |
| * BSD License |
| * |
| * Redistribution and use in source and binary forms, with or without modification, |
| * are permitted provided that the following conditions are met: |
| * |
| * Redistributions of source code must retain the above copyright notice, this list |
| * of conditions and the following disclaimer. |
| * |
| * Redistributions in binary form must reproduce the above copyright notice, this |
| * list of conditions and the following disclaimer in the documentation and/or |
| * other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
| * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| //** Includes |
| #include "Platform.h" |
| |
| //** Functions |
| |
| //*** ActSignal() |
| // Function called when there is an ACT event to signal or unsignal |
| static void |
| ActSignal( |
| P_ACT_DATA actData, |
| int on |
| ) |
| { |
| if(actData == NULL) |
| return; |
| // If this is to turn a signal on, don't do anything if it is already on. If this |
| // is to turn the signal off, do it anyway because this might be for |
| // initialization. |
| if(on && (actData->signaled == TRUE)) |
| return; |
| actData->signaled = (uint8_t)on; |
| |
| // If there is an action, then replace the "Do something" with the correct action. |
| // It should test 'on' to see if it is turning the signal on or off. |
| switch(actData->number) |
| { |
| #if RH_ACT_0 |
| case 0: // Do something |
| return; |
| #endif |
| #if RH_ACT_1 |
| case 1: // Do something |
| return; |
| #endif |
| #if RH_ACT_2 |
| case 2: // Do something |
| return; |
| #endif |
| #if RH_ACT_3 |
| case 3: // Do something |
| return; |
| #endif |
| #if RH_ACT_4 |
| case 4: // Do something |
| return; |
| #endif |
| #if RH_ACT_5 |
| case 5: // Do something |
| return; |
| #endif |
| #if RH_ACT_6 |
| case 6: // Do something |
| return; |
| #endif |
| #if RH_ACT_7 |
| case 7: // Do something |
| return; |
| #endif |
| #if RH_ACT_8 |
| case 8: // Do something |
| return; |
| #endif |
| #if RH_ACT_9 |
| case 9: // Do something |
| return; |
| #endif |
| #if RH_ACT_A |
| case 0xA: // Do something |
| return; |
| #endif |
| #if RH_ACT_B |
| case 0xB: |
| // Do something |
| return; |
| #endif |
| #if RH_ACT_C |
| case 0xC: // Do something |
| return; |
| #endif |
| #if RH_ACT_D |
| case 0xD: // Do something |
| return; |
| #endif |
| #if RH_ACT_E |
| case 0xE: // Do something |
| return; |
| #endif |
| #if RH_ACT_F |
| case 0xF: // Do something |
| return; |
| #endif |
| default: |
| return; |
| } |
| } |
| |
| //*** ActGetDataPointer() |
| static P_ACT_DATA |
| ActGetDataPointer( |
| uint32_t act |
| ) |
| { |
| |
| #define RETURN_ACT_POINTER(N) if(0x##N == act) return &ACT_##N; |
| |
| FOR_EACH_ACT(RETURN_ACT_POINTER) |
| |
| return (P_ACT_DATA)NULL; |
| } |
| |
| //*** _plat__ACT_GetImplemented() |
| // This function tests to see if an ACT is implemented. It is a belt and suspenders |
| // function because the TPM should not be calling to manipulate an ACT that is not |
| // implemented. However, this could help the simulator code which doesn't necessarily |
| // know if an ACT is implemented or not. |
| LIB_EXPORT int |
| _plat__ACT_GetImplemented( |
| uint32_t act |
| ) |
| { |
| return (ActGetDataPointer(act) != NULL); |
| } |
| |
| //*** _plat__ACT_GetRemaining() |
| // This function returns the remaining time. If an update is pending, 'newValue' is |
| // returned. Otherwise, the current counter value is returned. Note that since the |
| // timers keep running, the returned value can get stale immediately. The actual count |
| // value will be no greater than the returned value. |
| LIB_EXPORT uint32_t |
| _plat__ACT_GetRemaining( |
| uint32_t act //IN: the ACT selector |
| ) |
| { |
| P_ACT_DATA actData = ActGetDataPointer(act); |
| uint32_t remain; |
| // |
| if(actData == NULL) |
| return 0; |
| remain = actData->remaining; |
| if(actData->pending) |
| remain = actData->newValue; |
| return remain; |
| } |
| |
| //*** _plat__ACT_GetSignaled() |
| LIB_EXPORT int |
| _plat__ACT_GetSignaled( |
| uint32_t act //IN: number of ACT to check |
| ) |
| { |
| P_ACT_DATA actData = ActGetDataPointer(act); |
| // |
| if(actData == NULL) |
| return 0; |
| return (int )actData->signaled; |
| } |
| |
| //*** _plat__ACT_SetSignaled() |
| LIB_EXPORT void |
| _plat__ACT_SetSignaled( |
| uint32_t act, |
| int on |
| ) |
| { |
| ActSignal(ActGetDataPointer(act), on); |
| } |
| |
| //*** _plat__ACT_GetPending() |
| LIB_EXPORT int |
| _plat__ACT_GetPending( |
| uint32_t act //IN: number of ACT to check |
| ) |
| { |
| P_ACT_DATA actData = ActGetDataPointer(act); |
| // |
| if(actData == NULL) |
| return 0; |
| return (int )actData->pending; |
| } |
| |
| |
| //*** _plat__ACT_UpdateCounter() |
| // This function is used to write the newValue for the counter. If an update is |
| // pending, then no update occurs and the function returns FALSE. If 'setSignaled' |
| // is TRUE, then the ACT signaled state is SET and if 'newValue' is 0, nothing |
| // is posted. |
| LIB_EXPORT int |
| _plat__ACT_UpdateCounter( |
| uint32_t act, // IN: ACT to update |
| uint32_t newValue // IN: the value to post |
| ) |
| { |
| P_ACT_DATA actData = ActGetDataPointer(act); |
| // |
| if(actData == NULL) |
| // actData doesn't exist but pretend update is pending rather than indicate |
| // that a retry is necessary. |
| return TRUE; |
| // if an update is pending then return FALSE so that there will be a retry |
| if(actData->pending != 0) |
| return FALSE; |
| actData->newValue = newValue; |
| actData->pending = TRUE; |
| |
| return TRUE; |
| } |
| |
| //***_plat__ACT_EnableTicks() |
| // This enables and disables the processing of the once-per-second ticks. This should |
| // be turned off ('enable' = FALSE) by _TPM_Init and turned on ('enable' = TRUE) by |
| // TPM2_Startup() after all the initializations have completed. |
| LIB_EXPORT void |
| _plat__ACT_EnableTicks( |
| int enable |
| ) |
| { |
| actTicksAllowed = enable; |
| } |
| |
| //*** ActDecrement() |
| // If 'newValue' is non-zero it is copied to 'remaining' and then 'newValue' is |
| // set to zero. Then 'remaining' is decremented by one if it is not already zero. If |
| // the value is decremented to zero, then the associated event is signaled. If setting |
| // 'remaining' causes it to be greater than 1, then the signal associated with the ACT |
| // is turned off. |
| static void |
| ActDecrement( |
| P_ACT_DATA actData |
| ) |
| { |
| // Check to see if there is an update pending |
| if(actData->pending) |
| { |
| // If this update will cause the count to go from non-zero to zero, set |
| // the newValue to 1 so that it will timeout when decremented below. |
| if((actData->newValue == 0) && (actData->remaining != 0)) |
| actData->newValue = 1; |
| actData->remaining = actData->newValue; |
| |
| // Update processed |
| actData->pending = 0; |
| } |
| // no update so countdown if the count is non-zero but not max |
| if((actData->remaining != 0) && (actData->remaining != UINT32_MAX)) |
| { |
| // If this countdown causes the count to go to zero, then turn the signal for |
| // the ACT on. |
| if((actData->remaining -= 1) == 0) |
| ActSignal(actData, TRUE); |
| } |
| // If the current value of the counter is non-zero, then the signal should be |
| // off. |
| if(actData->signaled && (actData->remaining > 0)) |
| ActSignal(actData, FALSE); |
| } |
| |
| //*** _plat__ACT_Tick() |
| // This processes the once-per-second clock tick from the hardware. This is set up |
| // for the simulator to use the control interface to send ticks to the TPM. These |
| // ticks do not have to be on a per second basis. They can be as slow or as fast as |
| // desired so that the simulation can be tested. |
| LIB_EXPORT void |
| _plat__ACT_Tick( |
| void |
| ) |
| { |
| // Ticks processing is turned off at certain times just to make sure that nothing |
| // strange is happening before pointers and things are |
| if(actTicksAllowed) |
| { |
| // Handle the update for each counter. |
| #define DECREMENT_COUNT(N) ActDecrement(&ACT_##N); |
| |
| FOR_EACH_ACT(DECREMENT_COUNT) |
| } |
| } |
| |
| //*** ActZero() |
| // This function initializes a single ACT |
| static void |
| ActZero( |
| uint32_t act, |
| P_ACT_DATA actData |
| ) |
| { |
| actData->remaining = 0; |
| actData->newValue = 0; |
| actData->pending = 0; |
| actData->number = (uint8_t)act; |
| ActSignal(actData, FALSE); |
| } |
| |
| //***_plat__ACT_Initialize() |
| // This function initializes the ACT hardware and data structures |
| LIB_EXPORT int |
| _plat__ACT_Initialize( |
| void |
| ) |
| { |
| actTicksAllowed = 0; |
| #define ZERO_ACT(N) ActZero(0x##N, &ACT_##N); |
| FOR_EACH_ACT(ZERO_ACT) |
| |
| return TRUE; |
| } |
| |