1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptoh4rng.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,354 @@
1.4 +/*
1.5 +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +/**
1.23 + @file
1.24 + @internalComponent
1.25 + @released
1.26 +*/
1.27 +#include <kernel/kern_priv.h>
1.28 +#include "cryptodriver.h"
1.29 +#ifdef __MARM__
1.30 +#include <omap_hrp/assp/shared/omap_reg.h>
1.31 +#include <omap_hrp/assp/shared/omap_interrupt.h>
1.32 +#endif
1.33 +//#include "cryptoh4.h"
1.34 +#include "cryptoldd.h"
1.35 +#include "cryptoh4rng.h"
1.36 +
1.37 +inline void CryptoH4JobRandom::EnableIsr()
1.38 + {
1.39 + TRACE_FUNCTION("EnableIsr");
1.40 + // Kern::Printf("EI");
1.41 + SetRunning(ETrue);
1.42 +#ifdef __MARM__
1.43 + // Enable RNG interrupt. This interrupt will then queue the
1.44 + // "random number ready" DFC
1.45 + TInt32 tmp = TOmap::Register32(KHwBaseRngReg + KHoRng_Mask);
1.46 + tmp |= 4;
1.47 + TOmap::SetRegister32(KHwBaseRngReg + KHoRng_Mask, tmp);
1.48 +#else
1.49 + // Not on real h/w so just queue the DFC...
1.50 + // Queue the "random number ready" DFC
1.51 + iRandomDfc.Enque(); // Queue from task level
1.52 +#endif
1.53 + }
1.54 +
1.55 +inline void CryptoH4JobRandom::DisableIsr()
1.56 + {
1.57 + TRACE_FUNCTION("DisableIsr");
1.58 + // Kern::Printf("DI");
1.59 +#ifdef __MARM__
1.60 + TInt32 tmp = TOmap::Register32(KHwBaseRngReg + KHoRng_Mask);
1.61 + tmp &= ~4;
1.62 + TOmap::SetRegister32(KHwBaseRngReg + KHoRng_Mask, tmp);
1.63 +#endif
1.64 + }
1.65 +
1.66 +
1.67 +
1.68 +CryptoH4JobRandom::CryptoH4JobRandom(DLddChanRandom &aLddChanRandom)
1.69 + : iLddChanRandom(aLddChanRandom),
1.70 + iJobSizeInBytes(0),
1.71 + iSwReadByteOffset(0),
1.72 + iHw32Index(0),
1.73 + iIsrHooked(EFalse),
1.74 + iRandomDfc(RandomDfc, this, 1) // DFC is priority '1'
1.75 + {
1.76 + TRACE_FUNCTION("CryptoH4JobRandom");
1.77 + // Kern::Printf("CryptoH4JobRandom::CryptoH4JobRandom %x", this);
1.78 + }
1.79 +
1.80 +CryptoH4JobRandom::~CryptoH4JobRandom()
1.81 + {
1.82 + TRACE_FUNCTION("~CryptoH4JobRandom");
1.83 + // Kern::Printf("CryptoH4JobRandom::~CryptoH4JobRandom %x", this);
1.84 + UnHookIsr();
1.85 + }
1.86 +
1.87 +
1.88 +void CryptoH4JobRandom::SetDfcQ(TDfcQue *aDfcQue)
1.89 + {
1.90 + TRACE_FUNCTION("SetDfcQ");
1.91 + iRandomDfc.SetDfcQ(aDfcQue);
1.92 + }
1.93 +
1.94 +void CryptoH4JobRandom::SetDetails(DCryptoJobScheduler *aJobScheduler,
1.95 + MCryptoJobCallbacks *aCallbacks,
1.96 + TUint32 aNumOfBytes)
1.97 + {
1.98 + TRACE_FUNCTION("SetDetails");
1.99 + // Kern::Printf("CryptoH4JobRandom::SetDetails");
1.100 + iJobScheduler = aJobScheduler;
1.101 + iCallbacks = aCallbacks;
1.102 + iJobSizeInBytes = aNumOfBytes;
1.103 + }
1.104 +
1.105 +void CryptoH4JobRandom::GetToPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore)
1.106 + {
1.107 + TRACE_FUNCTION("GetToPddBuffer");
1.108 + aBuf = 0;
1.109 + aBufLen = 0;
1.110 + aMore = EFalse;
1.111 + }
1.112 +
1.113 +void CryptoH4JobRandom::BytesWrittenToPdd(TUint32)
1.114 + {
1.115 + TRACE_FUNCTION("BytesWrittenToPdd");
1.116 + }
1.117 +
1.118 +void CryptoH4JobRandom::GetFromPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore)
1.119 + {
1.120 + TRACE_FUNCTION("GetFromPddBuffer");
1.121 +
1.122 + TInt hw8Index = iHw32Index * 4;
1.123 + TUint8 *p = (TUint8 *) iRandomBuffer;
1.124 + aBuf = &p[iSwReadByteOffset];
1.125 +
1.126 + TInt len = hw8Index - iSwReadByteOffset;
1.127 + if(len >= 0)
1.128 + {
1.129 + aBufLen = len;
1.130 + aMore = EFalse;
1.131 + }
1.132 + else
1.133 + {
1.134 + // Wrap round condition, but can only return contiguous bytes
1.135 + aBufLen = sizeof(iRandomBuffer) - iSwReadByteOffset;
1.136 + aMore = ETrue;
1.137 + return;
1.138 + }
1.139 + }
1.140 +
1.141 +void CryptoH4JobRandom::BytesReadFromPdd(TUint32 aBytes)
1.142 + {
1.143 + TRACE_FUNCTION("BytesReadFromPdd");
1.144 + iSwReadByteOffset += aBytes;
1.145 + if(iSwReadByteOffset >= sizeof(iRandomBuffer))
1.146 + {
1.147 + iSwReadByteOffset -= sizeof(iRandomBuffer);
1.148 + }
1.149 + iJobSizeInBytes -= aBytes;
1.150 + }
1.151 +
1.152 +
1.153 +
1.154 +void CryptoH4JobRandom::DoSlice(TBool aFirstSlice)
1.155 + {
1.156 + TRACE_FUNCTION("DoSlice");
1.157 + // Kern::Printf("DoSlice(%d)", aFirstSlice);
1.158 + if(aFirstSlice)
1.159 + {
1.160 + HookIsr();
1.161 + }
1.162 +
1.163 + // Enable RNG interrupt. The interrupt will then queue the
1.164 + // "random number ready" DFC when the h/w is ready.
1.165 + // (when not on h/w, this immediately queues a DFC)
1.166 + EnableIsr();
1.167 + }
1.168 +
1.169 +TBool CryptoH4JobRandom::DoSaveState()
1.170 + {
1.171 + TRACE_FUNCTION("DoSaveState");
1.172 + UnHookIsr();
1.173 + return ETrue; // We want DoRestoreState to be called
1.174 + }
1.175 +
1.176 +void CryptoH4JobRandom::DoRestoreState()
1.177 + {
1.178 + TRACE_FUNCTION("DoRestoreState");
1.179 + HookIsr();
1.180 + }
1.181 +
1.182 +void CryptoH4JobRandom::DoReleaseHw()
1.183 + {
1.184 + TRACE_FUNCTION("DoReleaseHw");
1.185 + // Disable RNG interrupt
1.186 + DisableIsr();
1.187 +
1.188 + // Disable/unhook ISR
1.189 + UnHookIsr();
1.190 +
1.191 + // Cancel DFC
1.192 + iRandomDfc.Cancel();
1.193 +
1.194 + }
1.195 +
1.196 +TInt CryptoH4JobRandom::BytesAvailable() const
1.197 + {
1.198 + TRACE_FUNCTION("BytesAvailable");
1.199 + TInt hw8Index = iHw32Index * 4;
1.200 + TInt available = hw8Index - iSwReadByteOffset;
1.201 + if(available < 0)
1.202 + {
1.203 + available += sizeof(iRandomBuffer);
1.204 + }
1.205 + return available;
1.206 + }
1.207 +
1.208 +void CryptoH4JobRandom::RegionsAvailable(TUint8 * &aPtr1, TInt &aLen1,
1.209 + TUint8 * &aPtr2, TInt &aLen2) const
1.210 + {
1.211 + TRACE_FUNCTION("RegionsAvailable");
1.212 + TInt hw8Index = iHw32Index * 4;
1.213 + TUint8 *p = (TUint8 *) iRandomBuffer;
1.214 + aPtr1 = &p[iSwReadByteOffset];
1.215 +
1.216 + TInt len = hw8Index - iSwReadByteOffset;
1.217 + if(len < 0)
1.218 + {
1.219 + // Available data crosses buffer end so return two regions
1.220 + aLen1 = sizeof(iRandomBuffer) - iSwReadByteOffset;
1.221 + aPtr2 = &p[0];
1.222 + aLen2 = hw8Index;
1.223 + }
1.224 + else
1.225 + {
1.226 + // Available buffer is contiguous
1.227 + aLen1 = len;
1.228 + aPtr2 = 0;
1.229 + aLen2 = 0;
1.230 + }
1.231 + }
1.232 +
1.233 +
1.234 +
1.235 +void CryptoH4JobRandom::HookIsr()
1.236 + {
1.237 + TRACE_FUNCTION("HookIsr");
1.238 + // Kern::Printf("CryptoH4JobRandom::HookIsr iIsrHooked=%d this=%x", iIsrHooked, this);
1.239 +#ifdef __MARM__
1.240 + if(!iIsrHooked)
1.241 + {
1.242 + TInt r = Interrupt::Bind(EIrqRng, Isr, this);
1.243 + if(r != KErrNone) Kern::Fault("CryptoH4JobRandom::HookIsr Bind failed", r);
1.244 + r = Interrupt::Enable(EIrqRng);
1.245 + if(r != KErrNone) Kern::Fault("CryptoH4JobRandom::HookIsr Enable failed", r);
1.246 + iIsrHooked = ETrue;
1.247 + }
1.248 +#endif
1.249 + }
1.250 +
1.251 +void CryptoH4JobRandom::UnHookIsr()
1.252 + {
1.253 + TRACE_FUNCTION("UnHookIsr");
1.254 + // Kern::Printf("CryptoH4JobRandom::UnHookIsr iIsrHooked=%d this=%x", iIsrHooked, this);
1.255 +#ifdef __MARM__
1.256 + if(iIsrHooked)
1.257 + {
1.258 + Interrupt::Disable(EIrqRng);
1.259 + Interrupt::Unbind(EIrqRng);
1.260 + iIsrHooked = EFalse;
1.261 + }
1.262 +#endif
1.263 + }
1.264 +
1.265 +
1.266 +
1.267 +#ifdef __MARM__
1.268 +void CryptoH4JobRandom::Isr(TAny *aPtr)
1.269 + {
1.270 + TRACE_FUNCTION("Isr");
1.271 + CryptoH4JobRandom *p = static_cast<CryptoH4JobRandom *>(aPtr);
1.272 + // Disable RNG interrupt so DFC can run.
1.273 + p->DisableIsr();
1.274 + // Queue DFC to read the RNG
1.275 + p->iRandomDfc.Add();
1.276 + }
1.277 +#endif
1.278 +
1.279 +/**
1.280 + Called when the current h/w opperation is complete
1.281 +*/
1.282 +void CryptoH4JobRandom::RandomDfc(TAny* aPtr)
1.283 + {
1.284 + ((CryptoH4JobRandom*)aPtr)->DoRandomDfc();
1.285 + }
1.286 +
1.287 +void CryptoH4JobRandom::DoRandomDfc()
1.288 + {
1.289 + TRACE_FUNCTION("DoRandomDfc");
1.290 + // Set state to not using hw, if we continue using the h/w we will
1.291 + // call EnableIsr which will change the state back to ERunning.
1.292 + SetRunning(EFalse);
1.293 + // Kern::Printf("DoRandomDfc");
1.294 +#ifdef __MARM__
1.295 + // Read h/w
1.296 + iRandomBuffer[iHw32Index] = TOmap::Register32(KHwBaseRngReg + KHoRng_Out);
1.297 +#else
1.298 + static TUint32 n = 0;
1.299 + iRandomBuffer[iHw32Index]= n++;
1.300 +#endif
1.301 +
1.302 + ++iHw32Index;
1.303 + if(iHw32Index >= sizeof(iRandomBuffer)/sizeof(iRandomBuffer[0]))
1.304 + {
1.305 + iHw32Index = 0;
1.306 + }
1.307 +
1.308 + TInt outputAvailable = BytesAvailable();
1.309 + TInt space = sizeof(iRandomBuffer) - outputAvailable - 4;
1.310 + if((outputAvailable >= iJobSizeInBytes) || (space <= 0))
1.311 + {
1.312 + // Either have enough data to finish job, or out of buffer
1.313 + // space to read more. We pass available data to the LDD, and
1.314 + // declare the slice/job done and return.
1.315 +
1.316 + //
1.317 + // Pass available data to LDD
1.318 + //
1.319 + // LDD will call GetFromPddBuffer/BytesReadFromPdd to read the data.
1.320 + iLddChanRandom.DataAvailable();
1.321 + }
1.322 +
1.323 + // Are we done yet?
1.324 + if(iJobSizeInBytes <= 0)
1.325 + {
1.326 + // Tell the scheduler that this slice is done
1.327 + iJobScheduler->JobComplete(this, KErrNone);
1.328 + return;
1.329 + }
1.330 +
1.331 + // Re-calculate output available and space
1.332 + outputAvailable = BytesAvailable();
1.333 + space = sizeof(iRandomBuffer) - outputAvailable - 4;
1.334 +
1.335 + if((space != 0) && (iJobSizeInBytes-outputAvailable > 0))
1.336 + {
1.337 + // We have some space and we need more data
1.338 +
1.339 + // Enable RNG interrupt. The interrupt will then queue the
1.340 + // "random number ready" DFC when the h/w is ready.
1.341 + // (when not on h/w, this immediately queues a DFC)
1.342 + EnableIsr();
1.343 + }
1.344 + else
1.345 + {
1.346 + // Job stalled - either out of space or already have enough
1.347 + // data but LDD has not take it
1.348 + Stalled();
1.349 + }
1.350 +
1.351 + return;
1.352 + }
1.353 +
1.354 +
1.355 +
1.356 +
1.357 +// End of file