Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: SPITIS_TPM20.cpp
- Revision:
- 3:4b9ad18eae02
- Parent:
- 2:526bf792254d
diff -r 526bf792254d -r 4b9ad18eae02 SPITIS_TPM20.cpp --- a/SPITIS_TPM20.cpp Tue Apr 07 19:13:09 2015 +0000 +++ b/SPITIS_TPM20.cpp Sat Apr 11 04:01:54 2015 +0000 @@ -23,7 +23,6 @@ */ #include "SPITIS_TPM20.h" -#include "TPM20Tables.h" TIS_TPM20::TIS_RESULT TIS_TPM20::InitializeTis() @@ -43,7 +42,7 @@ result = TIS_SESSION_RESULT_FAILED; goto Cleanup; } - m_intfCabability = LE_BYTEARRAY_TO_UINT32(dataRegister, 0); + m_intfCabability = BYTE_ARRAY_TO_LEUINT32(dataRegister); #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.InitializeTis.IntfCapability = 0x%08x\n\r", m_intfCabability); @@ -85,87 +84,12 @@ return result; } -#ifndef TPM_TPM_TIS_NO_COMMAND_FILTERING TIS_TPM20::TIS_RESULT -TIS_TPM20::ApplyFilter(TIS_TPM20::TIS_LOCALITY locality, uint8_t* pbCmd, uint32_t cbCmd) -{ - uint32_t cursor = sizeof(uint16_t) + sizeof(uint32_t); - uint32_t ordinal = BE_BYTEARRAY_TO_UINT32(pbCmd, cursor); - int32_t handleCount = -1; - - // First filter ordinals based on locality - if(locality == TIS_LOCALITY_0) - { - switch(ordinal) - { - // We will not allow certain from locality 0 - aka the external TPM channel - case TPM_CC_ChangeEPS: - case TPM_CC_ChangePPS: - case TPM_CC_Clear: - case TPM_CC_ClearControl: - case TPM_CC_ClockSet: - case TPM_CC_PCR_Allocate: - case TPM_CC_PCR_SetAuthPolicy: - case TPM_CC_Shutdown: - return TIS_SESSION_RESULT_FILTERED; - default: - break; - } - } - - // Move on the and lets look at the handle filter - cursor += sizeof(ordinal); - - // Lookup the number of handles in the command - for(uint32_t n = 0; s_ccAttr[n].commandIndex != 0x0000 ;n++) - { - if(s_ccAttr[n].commandIndex == ordinal) - { - handleCount = s_ccAttr[n].cHandles; - break; - } - } - - // Easy elimination of invalid cases - if((handleCount < 0) || (handleCount > 3) || - (cbCmd < (cursor + (sizeof(uint32_t) * handleCount)))) - { - return TIS_SESSION_RESULT_FILTERED; - } - - // Read the handles from the command and see if they are allowed - for(uint32_t n = 0 ;n < handleCount; n++) - { - uint32_t objectHandle = BE_BYTEARRAY_TO_UINT32(pbCmd, cursor); - cursor += sizeof(objectHandle); - - if(locality == TIS_LOCALITY_0) - { - switch(objectHandle) - { - // We will not allow the platform entity to be used from locality 0 - case TPM_RH_PLATFORM: - return TIS_SESSION_RESULT_FILTERED; - default: - break; - } - } - } - - return TIS_SESSION_RESULT_COMPLETE; -} -#endif - -TIS_TPM20::TIS_RESULT -TIS_TPM20::SendCommand( - uint8_t* pbCmd, - uint32_t cbCmd, - TIS_TPM20::TIS_LOCALITY locality) +TIS_TPM20::StartSession( + TIS_TPM20::TIS_LOCALITY locality + ) { TIS_RESULT result = TIS_SESSION_RESULT_COMPLETE; - uint8_t tisStatus = 0; - uint16_t burstCount = 0; - uint32_t index = 0; // Is the driver busy? if(m_locality != TIS_NOT_IN_USE) @@ -186,9 +110,73 @@ } } + // Request the locality + if(!RequestLocality(locality)) + { + result = TIS_SESSION_RESULT_FAILED; + goto Cleanup; + } + +Cleanup: + return result; +} + +TIS_TPM20::TIS_RESULT +TIS_TPM20::EndSession() +{ + if(m_locality != TIS_NOT_IN_USE) + { + // Release the locality again +#ifdef TPM_TIS_DEBUG_OUTPUT + printf("TIS.ReleaseLocality\r\n"); +#endif + if(!ReleaseLocality()) + { + return TIS_SESSION_RESULT_FAILED; + } + } + return TIS_SESSION_RESULT_COMPLETE; +} + +TIS_TPM20::TIS_RESULT +TIS_TPM20::AbortCommand() +{ + TIS_RESULT result = TIS_SESSION_RESULT_COMPLETE; + uint8_t tisStatus = TIS_STS_COMMAND_READY; +#ifdef TPM_TIS_DEBUG_OUTPUT + printf("TIS.AbortCommand\n\r"); +#endif + if((!WriteRegister(TIS_STS_REGISTER, &tisStatus, sizeof(tisStatus))) || + (!ReadRegister(TIS_STS_REGISTER, &tisStatus, sizeof(tisStatus))) || + ((tisStatus & TIS_STS_COMMAND_READY) == 0)) + { + result = TIS_SESSION_RESULT_FAILED; + } + return result; +} + +TIS_TPM20::TIS_RESULT +TIS_TPM20::SendCommand( + uint8_t* pbCmd, + uint32_t cbCmd, + uint8_t* pbTrailingData, + uint32_t cbTrailingData) +{ + TIS_RESULT result = TIS_SESSION_RESULT_COMPLETE; + uint8_t tisStatus = 0; + uint16_t burstCount = 0; + uint32_t index = 0; + + // In all TPM, a buffer size of 1,024 octets is allowed. + if(cbTrailingData > 1024) + { + result = TIS_SESSION_RESULT_FAILED; + goto Cleanup; + } + #ifndef TPM_TIS_NO_COMMAND_FILTERING // Apply command filtering - if(ApplyFilter(locality, pbCmd, cbCmd) == TIS_SESSION_RESULT_FILTERED) + if(ApplyFilter(m_locality, pbCmd, cbCmd) == TIS_SESSION_RESULT_FILTERED) { #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.Schedule: Command filtered\n\r"); @@ -204,30 +192,23 @@ printf("\n\r"); #endif - // Assert the locality - - if(!RequestLocality(locality)) + // Make sure the TPM is ready for a command + do { - result = TIS_SESSION_RESULT_FAILED; - goto Cleanup; - } - - // Make sure the TPM is ready for a command - if(!ReadRegister(TIS_STS_REGISTER, &tisStatus, sizeof(tisStatus))) - { - result = TIS_SESSION_RESULT_FAILED; - goto Cleanup; - } - - // Get TPM ready - if((tisStatus & TIS_STS_COMMAND_READY) == 0) - { - if(!AbortCommand()) + tisStatus = TIS_STS_COMMAND_READY; + if(!WriteRegister(TIS_STS_REGISTER, &tisStatus, sizeof(tisStatus))) + { + result = TIS_SESSION_RESULT_FAILED; + goto Cleanup; + } + if(!ReadRegister(TIS_STS_REGISTER, &tisStatus, sizeof(tisStatus))) { result = TIS_SESSION_RESULT_FAILED; goto Cleanup; } } + while((tisStatus & TIS_STS_COMMAND_READY) == 0); + #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.ReadyForCommand\n\r"); #endif @@ -258,6 +239,36 @@ index += iteration; } while((cbCmd - index) > 0); + // Submit trailing data if there is any + if((pbTrailingData != NULL) && (cbTrailingData != 0)) + { + index = 0; + do + { + uint16_t iteration = 0; + + if((burstCount = GetBurstCount()) == 0) + { + result = TIS_SESSION_RESULT_FAILED; + goto Cleanup; + } + + // Assemble the buffer for transmission + iteration = min((cbTrailingData - index), min(burstCount, TIS_MAX_HW_FRAME_SIZE)); +#ifdef TPM_TIS_DEBUG_OUTPUT + printf("TIS.SendingBurst = %d\r\n", iteration); +#endif + if(!WriteRegister(TIS_DATA_FIFO, &pbTrailingData[index], iteration)) + { + result = TIS_SESSION_RESULT_FAILED; + goto Cleanup; + } + + // Update the index + index += iteration; + } while((cbTrailingData - index) > 0); + } + // Command complete? if((!ReadRegister(TIS_STS_REGISTER, &tisStatus, sizeof(tisStatus))) || (!(tisStatus & TIS_STS_VALID) || (tisStatus & TIS_STS_DATA_EXPECT))) @@ -305,7 +316,6 @@ ) { TIS_RESULT result = TIS_SESSION_RESULT_COMPLETE; - uint8_t tisStatus = 0; uint16_t burstCount = 0; uint32_t index = 0; uint32_t rspSize = 0; @@ -328,16 +338,6 @@ goto Cleanup; } - if((!ReadRegister(TIS_STS_REGISTER, &tisStatus, sizeof(tisStatus))) || - (!(tisStatus & TIS_STS_VALID) || !(tisStatus & TIS_STS_DATA_AVAIL))) - { - result = TIS_SESSION_RESULT_FAILED; - goto Cleanup; - } -#ifdef TPM_TIS_DEBUG_OUTPUT - printf("TIS.DataAvailable\r\n"); -#endif - // Get the response header from the TPM if(((burstCount = GetBurstCount()) == 0) || (burstCount < (sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t))) || @@ -347,7 +347,8 @@ goto Cleanup; } index += (sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t)); - rspSize = BE_BYTEARRAY_TO_UINT32(pbRsp, sizeof(uint16_t)); + rspSize = BYTE_ARRAY_TO_UINT32(&pbRsp[sizeof(uint16_t)]); + #ifdef TPM_TIS_DEBUG_OUTPUT printf("Tis.ResponseSize = %d\r\n", rspSize); #endif @@ -356,17 +357,14 @@ { do { - uint16_t iteration = 0; - - // Check to make sure the TPM has still data for us - if((!ReadRegister(TIS_STS_REGISTER, &tisStatus, sizeof(tisStatus))) || - (!(tisStatus & TIS_STS_VALID) || !(tisStatus & TIS_STS_DATA_AVAIL)) || - ((burstCount = GetBurstCount()) == 0)) + // Calculate the response iteration size + uint16_t iteration = min((rspSize - index), (cbRsp - index)); + if((burstCount = GetBurstCount()) == 0) { result = TIS_SESSION_RESULT_FAILED; - goto Cleanup; + goto Cleanup; } - iteration = min((rspSize - index), min((cbRsp - index), min(burstCount, TIS_MAX_HW_FRAME_SIZE))); + iteration = min(iteration, burstCount); #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.ReceivingBurst = %d\r\n", iteration); #endif @@ -374,6 +372,7 @@ // Read the data for this iteration if(!ReadRegister(TIS_DATA_FIFO, &pbRsp[index], iteration)) { + result = TIS_SESSION_RESULT_FAILED; goto Cleanup; } index += iteration; @@ -396,53 +395,9 @@ { AbortCommand(); } - // Release the locality again -#ifdef TPM_TIS_DEBUG_OUTPUT - printf("TIS.ReleaseLocality\r\n"); -#endif - ReleaseLocality(); return result; } -uint32_t -TIS_TPM20::ParseResponseHeader(uint8_t* pbRsp, uint32_t cbRsp, uint16_t* rspTag, uint32_t* rspSize) -{ - uint32_t rspResponseCode = 0; - uint32_t cursor = 0; - - // Check that the response header is well formatted - if(cbRsp < (sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t))) - { -#ifdef TPM_TIS_DEBUG_OUTPUT - printf("TIS.ResponseHdr: Too short = 0x%08x\n\r", cbRsp); -#endif - rspResponseCode = TPM_RC_FAILURE; - goto Cleanup; - } - - // Read the header components - *rspTag = BE_BYTEARRAY_TO_UINT16(pbRsp, cursor); - cursor += sizeof(*rspTag); - *rspSize = BE_BYTEARRAY_TO_UINT32(pbRsp, cursor); - cursor += sizeof(*rspSize); - rspResponseCode = BE_BYTEARRAY_TO_UINT32(pbRsp, cursor); - cursor += sizeof(rspResponseCode); - - // Check the components - if(((*rspTag != TPM_ST_NO_SESSIONS) && (*rspTag != TPM_ST_SESSIONS)) || - (*rspSize != cbRsp)) - { -#ifdef TPM_TIS_DEBUG_OUTPUT - printf("TIS.ResponseHdr: Tag=0x%04x, Len=0x%08x, RC=0x%08x\n\r", *rspTag, *rspSize, rspResponseCode); -#endif - rspResponseCode = TPM_RC_FAILURE; - goto Cleanup; - } - -Cleanup: - return rspResponseCode; -} - bool TIS_TPM20::FullDuplex( bool readCycle, @@ -531,7 +486,7 @@ { return 0; } - burstCount = min(LE_BYTEARRAY_TO_UINT16(dataBytes , 0), m_maxBurstCount); + burstCount = min(BYTE_ARRAY_TO_LEUINT16(dataBytes), m_maxBurstCount); #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.BurstCount = %d\r\n", burstCount); #endif @@ -642,31 +597,44 @@ uint8_t dataRegister[sizeof(uint32_t)] = {0}; uint8_t dataByte = 0; - if(intEnable != 0) + if(intEnable == 0) { + // Reset the interrupt. Turns out the TPM needs some time to actually do this let me tell you: + // That was a very interesting bug hunt! What we end up with here is the following - We reset + // the interrupts now and don't look at them. While the TPM actually resets the line, we use + // that time to send the next command but before interrupts are turned on for the next command + // execution we have to wait until the line is back up again (see below). + dataByte = TIS_INT_STATUS_RESET_ALL; + if(!WriteRegister(TIS_INT_STATUS_REGISTER, &dataByte, sizeof(dataByte))) + { + return false; + } + } + else + { + // Make sure the interrupt is really, really clear before we turn it back on. The TPM takes + // around 5-10ms to transition the line back high. +#ifdef TPM_TIS_DEBUG_OUTPUT + if(intEnable == 0) printf("TIS.InteruptStillActive\n\r"); +#endif + while(m_interrupt == 0) + { + wait_us(1000); + } + int_enable |= (uint32_t)TIS_INT_ENABLE_GLOBAL_INT_ENABLE | intEnable; } - // Read the Interrupt state - ReadRegister(TIS_INT_STATUS_REGISTER, &dataByte, sizeof(dataByte)); + LEUINT32_TO_BYTE_ARRAY(int_enable, dataRegister); - dataByte = TIS_INT_STATUS_RESET_ALL; - LE_UINT32_TO_BYTEARRAY(int_enable, dataRegister, 0); #ifdef TPM_TIS_DEBUG_OUTPUT - printf("TIS.ArmTpmInterupt = 0x%08x\n\r", intEnable); + if(intEnable) + printf("TIS.TpmInterupt = 0x%08x\n\r", intEnable); + else + printf("TIS.TpmInterupt = OFF\n\r"); #endif - return ((WriteRegister(TIS_INT_STATUS_REGISTER, &dataByte, sizeof(dataByte))) && - (WriteRegister(TIS_INT_ENABLE_REGISTER, dataRegister, sizeof(dataRegister)))); + return(WriteRegister(TIS_INT_ENABLE_REGISTER, dataRegister, sizeof(dataRegister))); } -bool -TIS_TPM20::AbortCommand() -{ - uint8_t tisStatus = TIS_STS_COMMAND_READY; -#ifdef TPM_TIS_DEBUG_OUTPUT - printf("TIS.AbortCommand\n\r"); -#endif - return((WriteRegister(TIS_STS_REGISTER, &tisStatus, sizeof(tisStatus))) && - (ReadRegister(TIS_STS_REGISTER, &tisStatus, sizeof(tisStatus))) && - ((tisStatus & TIS_STS_COMMAND_READY) != 0)); -} + +