1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptoh4aes.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,941 @@
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 "cryptoh4aes.h"
1.34 +
1.35 +#if 0
1.36 +#undef __MARM__
1.37 +#ifndef __MARM__
1.38 +#warning "h/w disabled"
1.39 +#endif
1.40 +#endif
1.41 +
1.42 +#ifdef DUMPBUFFER
1.43 +LOCAL_D void dumpBuffer(const char *aName, TUint32 *aBuf, TUint32 aLen);
1.44 +#else
1.45 +#define dumpBuffer(aName, aBuf, aLen)
1.46 +#endif
1.47 +
1.48 +CryptoH4JobAes::CryptoH4JobAes(DLddChanAes &aLddChanAes)
1.49 + : iLddChanAes(aLddChanAes),
1.50 + iEncrypt(EFalse),
1.51 + iKeyLengthBytes(0),
1.52 + iSwWriteByteOffset(0),
1.53 + iHwReadIndex(0),
1.54 + iHwWriteIndex(0),
1.55 + iSwReadByteOffset(0),
1.56 + iHwRunning(EFalse),
1.57 + iDmaToHwPending(0),
1.58 + iDmaFromHwPending(0),
1.59 +#ifdef FAKE_DMA
1.60 + iFakeDmaToHwQueued(0),
1.61 + iFakeDmaFromHwQueued(0),
1.62 +#endif
1.63 + iDmaToHwCompleteDfc(DmaToHwCompleteDfc, this, 1), // DFC is priority '1'
1.64 + iDmaFromHwCompleteDfc(DmaFromHwCompleteDfc, this, 1)
1.65 + {
1.66 + TRACE_FUNCTION("CryptoH4JobAes");
1.67 + }
1.68 +
1.69 +CryptoH4JobAes::~CryptoH4JobAes()
1.70 + {
1.71 + TRACE_FUNCTION("~CryptoH4JobAes");
1.72 + StopHw();
1.73 + }
1.74 +
1.75 +
1.76 +void CryptoH4JobAes::SetDfcQ(TDfcQue *aDfcQue)
1.77 + {
1.78 + TRACE_FUNCTION("SetDfcQ");
1.79 + iDmaToHwCompleteDfc.SetDfcQ(aDfcQue);
1.80 + iDmaFromHwCompleteDfc.SetDfcQ(aDfcQue);
1.81 + }
1.82 +
1.83 +TUint8 *CryptoH4JobAes::GetKeyBuffer()
1.84 + {
1.85 + TRACE_FUNCTION("GetKeyBuffer");
1.86 + return (TUint8 *) &iKey;
1.87 + }
1.88 +
1.89 +TUint8 *CryptoH4JobAes::GetIVBuffer()
1.90 + {
1.91 + TRACE_FUNCTION("GetIVBuffer");
1.92 + return (TUint8 *) &iIV;
1.93 + }
1.94 +
1.95 +TUint32 CryptoH4JobAes::MaxBytes() const
1.96 + {
1.97 + TRACE_FUNCTION("MaxBytes");
1.98 + return sizeof(iAesBuffer); // return size in bytes
1.99 + }
1.100 +
1.101 +TUint8 *CryptoH4JobAes::GetIOBuffer()
1.102 + {
1.103 + TRACE_FUNCTION("GetIOBuffer");
1.104 + return (TUint8 *) &iAesBuffer;
1.105 + }
1.106 +
1.107 +void CryptoH4JobAes::GetToPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore)
1.108 + {
1.109 + TRACE_FUNCTION("GetToPddBuffer");
1.110 + CheckIndexes();
1.111 + TUint8 *p = (TUint8 *) iAesBuffer;
1.112 + aBuf = &p[iSwWriteByteOffset];
1.113 +
1.114 + if(iSwReadByteOffset > iSwWriteByteOffset)
1.115 + {
1.116 + // Available buffer is contiguous
1.117 + aBufLen = iSwReadByteOffset - iSwWriteByteOffset;
1.118 + if(aBufLen) --aBufLen; // Never use all space to stop index collision
1.119 + aMore = EFalse;
1.120 + return;
1.121 + }
1.122 + else
1.123 + {
1.124 + // Available data crosses buffer end so return two regions
1.125 + // OR indexes are equal
1.126 + aBufLen = sizeof(iAesBuffer) - iSwWriteByteOffset;
1.127 + if(iSwReadByteOffset == 0)
1.128 + {
1.129 + // Do not fill to end of buffer because index would wrap and collid
1.130 + --aBufLen;
1.131 + aMore = EFalse;
1.132 + return;
1.133 + }
1.134 + aMore = (iSwReadByteOffset != iSwWriteByteOffset); // Another region to read
1.135 + return;
1.136 + }
1.137 + // Never gets here
1.138 + }
1.139 +
1.140 +void CryptoH4JobAes::BytesWrittenToPdd(TUint32 aBytes)
1.141 + {
1.142 + TRACE_FUNCTION("BytesWrittenToPdd");
1.143 + CheckIndexes();
1.144 + iSwWriteByteOffset += aBytes;
1.145 + if(iSwWriteByteOffset >= sizeof(iAesBuffer))
1.146 + {
1.147 + iSwWriteByteOffset -= sizeof(iAesBuffer);
1.148 + }
1.149 +
1.150 + CheckIndexes();
1.151 + }
1.152 +
1.153 +void CryptoH4JobAes::GetFromPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore)
1.154 + {
1.155 + TRACE_FUNCTION("GetFromPddBuffer");
1.156 + CheckIndexes();
1.157 + TInt hwWrite8Index = iHwWriteIndex * 4;
1.158 + TUint8 *p = (TUint8 *) iAesBuffer;
1.159 + aBuf = &p[iSwReadByteOffset];
1.160 +
1.161 + TInt len = hwWrite8Index - iSwReadByteOffset;
1.162 + if(len >= 0)
1.163 + {
1.164 + aBufLen = len;
1.165 + aMore = EFalse;
1.166 + }
1.167 + else
1.168 + {
1.169 + // Wrap round condition, but can only return contiguous bytes
1.170 + aBufLen = sizeof(iAesBuffer) - iSwReadByteOffset;
1.171 + aMore = (hwWrite8Index != 0);
1.172 + }
1.173 + CheckIndexes();
1.174 + }
1.175 +
1.176 +void CryptoH4JobAes::BytesReadFromPdd(TUint32 aBytes)
1.177 + {
1.178 + TRACE_FUNCTION("BytesReadFromPdd");
1.179 + CheckIndexes();
1.180 + iSwReadByteOffset += aBytes;
1.181 + if(iSwReadByteOffset >= sizeof(iAesBuffer))
1.182 + {
1.183 + iSwReadByteOffset -= sizeof(iAesBuffer);
1.184 + }
1.185 + CheckIndexes();
1.186 + iReadRequestLength -= aBytes;
1.187 + }
1.188 +
1.189 +
1.190 +
1.191 +TInt CryptoH4JobAes::SetDetails(DCryptoJobScheduler *aJobScheduler,
1.192 + MCryptoJobCallbacks *aCallbacks,
1.193 + TBool aEncrypt,
1.194 + TInt aKeyLengthBytes,
1.195 + RCryptoDriver::TChainingMode aMode)
1.196 + {
1.197 + TRACE_FUNCTION("TChainingMode");
1.198 + // Kern::Printf("AES Details %s: Key len %d, Mode %s (%d)",
1.199 + // aEncrypt?"Encrypt":"Decrypt", aKeyLengthBytes, (aMode == RCryptoDriver::ECbcMode)?"CBC":"ECB", aMode);
1.200 +
1.201 + if(State() != ECreated)
1.202 + {
1.203 + return KErrArgument;
1.204 + }
1.205 +
1.206 + iJobScheduler = aJobScheduler;
1.207 + iCallbacks = aCallbacks;
1.208 + iEncrypt = aEncrypt;
1.209 + iKeyLengthBytes = aKeyLengthBytes;
1.210 +
1.211 + if((aMode != RCryptoDriver::EEcbMode) && (aMode != RCryptoDriver::ECbcMode))
1.212 + {
1.213 + return KErrArgument;
1.214 + }
1.215 + iMode = aMode;
1.216 + if(iMode == RCryptoDriver::ECbcMode)
1.217 + {
1.218 + // For CBC we need to save the IV incase we need to
1.219 + // re-initialise the h/w mid-job
1.220 + TUint32 *from;
1.221 + TUint32 *to;
1.222 + if(iEncrypt)
1.223 + {
1.224 + // For encryption - DoSaveState saves the last encrypted
1.225 + // block. We set this to the IV to handle the case where
1.226 + // we do not encrypt any blocks before being suspended.
1.227 + from = &iIV[0];
1.228 + to = &iAesBuffer[((sizeof(iAesBuffer)-16)/4)];
1.229 + }
1.230 + else
1.231 + {
1.232 + // For decryption - MaybeSetupWriteDmaToHw maintains
1.233 + // iSavedState as a copy of the last ciphertext
1.234 + // (pre-decryption) so DoSaveState does not need to do
1.235 + // anything.
1.236 + //
1.237 + // To cover the case where we do not decrypt any blocks
1.238 + // before being suspended, we initialise iSavedState to the IV.
1.239 + from = &iIV[0];
1.240 + to = &iSavedState[0];
1.241 + }
1.242 + // Save the IV
1.243 + *to++ = *from++;
1.244 + *to++ = *from++;
1.245 + *to++ = *from++;
1.246 + *to++ = *from++;
1.247 + if(iEncrypt)
1.248 + {
1.249 + dumpBuffer("SetDetails - end of iAesBuffer", to-4, 4);
1.250 + }
1.251 + else
1.252 + {
1.253 + dumpBuffer("SetDetails - iSavedState", iSavedState, 4);
1.254 + }
1.255 + }
1.256 +
1.257 + // Reset indexes
1.258 + iSwWriteByteOffset = 0;
1.259 + iHwReadIndex = 0,
1.260 + iHwWriteIndex = 0,
1.261 + iSwReadByteOffset = 0;
1.262 +
1.263 + return KErrNone;
1.264 + }
1.265 +
1.266 +void CryptoH4JobAes::DoSlice(TBool aFirstSlice)
1.267 + {
1.268 + TRACE_FUNCTION("DoSlice");
1.269 + // Kern::Printf("DoSlice %s", aFirstSlice?"FIRST":"");
1.270 + if(aFirstSlice)
1.271 + {
1.272 + SetupHw(EFalse);
1.273 + }
1.274 +
1.275 + // Push any available data to user
1.276 + TInt r = iCallbacks->DataAvailable();
1.277 + if(r != KErrNone)
1.278 + {
1.279 + iJobScheduler->JobComplete(this,r);
1.280 + return;
1.281 + }
1.282 + // Read available data from user
1.283 + r = iCallbacks->DataRequired();
1.284 + if(r != KErrNone)
1.285 + {
1.286 + iJobScheduler->JobComplete(this,r);
1.287 + return;
1.288 + }
1.289 +
1.290 + // Setup to read data (if enough is available).
1.291 + // Kern::Printf("DoSlice - calling MaybeSetupWriteDmaToHw");
1.292 + MaybeSetupWriteDmaToHw();
1.293 +
1.294 + FAKE_DMA();
1.295 +
1.296 + if(!iDmaToHwPending && !iDmaFromHwPending)
1.297 + {
1.298 + Stalled();
1.299 + }
1.300 +
1.301 + return;
1.302 + }
1.303 +
1.304 +TBool CryptoH4JobAes::DoSaveState()
1.305 + {
1.306 + TRACE_FUNCTION("DoSaveState");
1.307 +
1.308 + if((iMode == RCryptoDriver::ECbcMode) && iEncrypt)
1.309 + {
1.310 + // Doing CBC encryption - Need to save a copy of the last
1.311 + // ciphertext block (after encryption) so we can use it as the
1.312 + // IV if we are later resumed.
1.313 + //
1.314 + // Last block processed by h/w just BEFORE iHwWriteIndex. If
1.315 + // we have not processed any data, then SetDetails will have
1.316 + // initialised this to the IV
1.317 + TInt32 fromIndex = (iHwWriteIndex!=0) ? (iHwWriteIndex-4) : ((sizeof(iAesBuffer)-16)/4);
1.318 + TUint32 *from = &iAesBuffer[fromIndex];
1.319 + TUint32 *to = &iSavedState[0];
1.320 + *to++ = *from++;
1.321 + *to++ = *from++;
1.322 + *to++ = *from++;
1.323 + *to++ = *from++;
1.324 + dumpBuffer("DoSaveState - iSavedState", iSavedState, 4);
1.325 + }
1.326 +
1.327 + StopHw();
1.328 + return ETrue; // We want DoRestoreState to be called
1.329 + }
1.330 +
1.331 +void CryptoH4JobAes::DoRestoreState()
1.332 + {
1.333 + TRACE_FUNCTION("DoRestoreState");
1.334 + SetupHw(ETrue);
1.335 + }
1.336 +
1.337 +void CryptoH4JobAes::DoReleaseHw()
1.338 + {
1.339 + TRACE_FUNCTION("DoReleaseHw");
1.340 + StopHw();
1.341 +#ifndef FAKE_DMA
1.342 + // Cancel DFCs - Doesn't work for FAKE_DMA case....
1.343 + iDmaToHwCompleteDfc.Cancel();
1.344 + iDmaFromHwCompleteDfc.Cancel();
1.345 +#endif
1.346 + }
1.347 +
1.348 +void CryptoH4JobAes::MaybeSetupWriteDmaToHw()
1.349 + {
1.350 + TRACE_FUNCTION("MaybeSetupWriteDmaToHw");
1.351 + if(!iDmaToHwPending)
1.352 + {
1.353 + // Calculate space between H/W read index and S/W write index or end of buffer
1.354 + TInt hwReadIndex8 = iHwReadIndex*4;
1.355 + TInt avail = (iSwWriteByteOffset >= hwReadIndex8) ? (iSwWriteByteOffset - hwReadIndex8) : (sizeof(iAesBuffer) - hwReadIndex8);
1.356 +
1.357 + if(avail >= 16)
1.358 + {
1.359 + // At least another block of data is available.
1.360 + if((avail <= 31) && (iMode == RCryptoDriver::ECbcMode) && !iEncrypt)
1.361 + {
1.362 + // Only one complete block is available
1.363 +
1.364 + // Doing CBC decryption, so need to save a copy of the
1.365 + // last ciphertext block (before it is decrypted) so we
1.366 + // can use it as the IV if we are kicked off the h/w
1.367 + // and have to reconfigure.
1.368 + // Last block available for h/w is at hwReadIndex8
1.369 + TUint32 *from = &iAesBuffer[iHwReadIndex];
1.370 + TUint32 *to = &iSavedState[0];
1.371 + *to++ = *from++;
1.372 + *to++ = *from++;
1.373 + *to++ = *from++;
1.374 + *to++ = *from++;
1.375 + dumpBuffer("MaybeSetupWriteDmaToHw - iSavedState", iSavedState, 4);
1.376 + }
1.377 + SetupDma((TUint32)&iAesBuffer[iHwReadIndex], ETrue);
1.378 + }
1.379 + }
1.380 + }
1.381 +
1.382 +
1.383 +#ifdef FAKE_DMA
1.384 +void CryptoH4JobAes::FakeDma()
1.385 + {
1.386 + TRACE_FUNCTION("FakeDma");
1.387 + if(iFakeDmaToHwQueued < iDmaToHwPending)
1.388 + {
1.389 + // Calculate number of 32 bit values in the h/w
1.390 + TInt inHw32 = iHwReadIndex - iHwWriteIndex;
1.391 + if(inHw32 < 0)
1.392 + {
1.393 + inHw32 += sizeof(iAesBuffer)/sizeof(iAesBuffer[0]);
1.394 + }
1.395 + // Convert to number of 16 byte blocks in h/w
1.396 + TInt inHwBlocks = inHw32/4;
1.397 +
1.398 + if((inHwBlocks + iFakeDmaToHwQueued) < 2)
1.399 + {
1.400 + // Pipeline is not full, so the next DMA to complete would be a "to h/w"
1.401 + // Wait for h/w to be ready
1.402 +#ifdef __MARM__
1.403 + // Kern::Printf("CryptoH4JobAes::FakeDma - Start waiting for h/w input ready (%x)", TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
1.404 + while(! (TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlInputReady))
1.405 + {
1.406 + Kern::Printf("CryptoH4JobAes::FakeDma - Waiting for h/w input ready (%x)", TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
1.407 + }
1.408 +#endif
1.409 + // Queue the fake "to dma" complete DFC
1.410 + iDmaToHwCompleteDfc.Enque();
1.411 + ++iFakeDmaToHwQueued;
1.412 + return;
1.413 + }
1.414 + }
1.415 +
1.416 + // Either pipeline is full, or we are out of input data.
1.417 +
1.418 + // Check for output
1.419 + if(iFakeDmaFromHwQueued < iDmaFromHwPending)
1.420 + {
1.421 +#ifdef __MARM__
1.422 + // Kern::Printf("CryptoH4JobAes::FakeDma - Start waiting for output ready (%x)", TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
1.423 + while(! (TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlOutputReady))
1.424 + {
1.425 + Kern::Printf("CryptoH4JobAes::FakeDma - waiting for output ready (%x)",TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
1.426 + }
1.427 +#endif
1.428 + // Queue the fake "from dma" complete DFC
1.429 + iDmaFromHwCompleteDfc.Enque();
1.430 + ++iFakeDmaFromHwQueued;
1.431 + return;
1.432 + }
1.433 +
1.434 + return;
1.435 + }
1.436 +#endif
1.437 +
1.438 +
1.439 +
1.440 +
1.441 +void CryptoH4JobAes::SetupHw(TBool aUseSavedState)
1.442 + {
1.443 + TRACE_FUNCTION("SetupHw");
1.444 + // Kern::Printf("SetupHw");
1.445 +#ifdef __MARM__
1.446 + // AES_MASK
1.447 +#ifdef FAKE_DMA
1.448 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_MASK, KHtAesMaskAutoIdle);
1.449 +#else
1.450 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_MASK,
1.451 + KHtAesMaskDmaReqIn | KHtAesMaskDmaReqOut | KHtAesMaskAutoIdle);
1.452 +#endif
1.453 + iHwRunning = EFalse; // Previous MASK register write cleared the start bit.
1.454 +
1.455 + TUint32 ctrl = 0;
1.456 + if(iEncrypt)
1.457 + {
1.458 + ctrl |= KHtAesCtrlDirection;
1.459 + }
1.460 +
1.461 + switch(iKeyLengthBytes)
1.462 + {
1.463 + case 32:
1.464 + // KEYS
1.465 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_L, iKey[0]);
1.466 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_H, iKey[1]);
1.467 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_L, iKey[2]);
1.468 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_H, iKey[3]);
1.469 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY3_L, iKey[4]);
1.470 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY3_H, iKey[5]);
1.471 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY4_L, iKey[6]);
1.472 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY4_H, iKey[7]);
1.473 + ctrl |= KHtAesCtrlKeySize256;
1.474 + break;
1.475 + case 24:
1.476 + // KEYS
1.477 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_L, iKey[0]);
1.478 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_H, iKey[1]);
1.479 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_L, iKey[2]);
1.480 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_H, iKey[3]);
1.481 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY3_L, iKey[4]);
1.482 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY3_H, iKey[5]);
1.483 + ctrl |= KHtAesCtrlKeySize192;
1.484 + break;
1.485 + case 16:
1.486 + // KEYS
1.487 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_L, iKey[0]);
1.488 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_H, iKey[1]);
1.489 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_L, iKey[2]);
1.490 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_H, iKey[3]);
1.491 + ctrl |= KHtAesCtrlKeySize128;
1.492 + break;
1.493 + }
1.494 +
1.495 +
1.496 +
1.497 + // IV (CBC only)
1.498 + if(iMode == RCryptoDriver::ECbcMode)
1.499 + {
1.500 + if(!aUseSavedState)
1.501 + {
1.502 + // Kern::Printf("Setting IV");
1.503 + // Set IV
1.504 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_1, iIV[0]);
1.505 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_2, iIV[1]);
1.506 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_3, iIV[2]);
1.507 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_4, iIV[3]);
1.508 + dumpBuffer("SetupHw(EFalse) - iIV", iIV, 4);
1.509 + }
1.510 + else
1.511 + {
1.512 + // Set IV to saved state
1.513 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_1, iSavedState[0]);
1.514 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_2, iSavedState[1]);
1.515 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_3, iSavedState[2]);
1.516 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_4, iSavedState[3]);
1.517 + dumpBuffer("SetupHw(ETrue) - iSavedState", iSavedState, 4);
1.518 + }
1.519 +
1.520 + ctrl |= KHsAesCtrlCBC;
1.521 + }
1.522 +
1.523 + // AES_CTRL
1.524 + // Kern::Printf("Setting crtl to %x", ctrl);
1.525 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_CTRL, ctrl);
1.526 +
1.527 + // AES_MASK START bit to start DMA
1.528 + // This is done by SetupDma
1.529 +#else
1.530 + (void)aUseSavedState;
1.531 +
1.532 +#endif
1.533 + }
1.534 +
1.535 +void CryptoH4JobAes::SetupDma(TUint32 aPtr, TBool aToHw)
1.536 + {
1.537 + TRACE_FUNCTION("SetupDma");
1.538 + // Kern::Printf("\t\tSetupDMA - %s, iHwReadIndex %d iHwWriteIndex %d",
1.539 + // aToHw?"toHw":"fromHw", iHwReadIndex, iHwWriteIndex);
1.540 + // Start the h/w
1.541 + if(!iHwRunning)
1.542 + {
1.543 + // Kern::Printf("SetupDma - starting h/w");
1.544 +#ifdef __MARM__
1.545 + // If h/w is not enabled yet, then set the start bit. This is
1.546 + // required even when NOT using DMA...
1.547 + TUint32 mask = TOmap::Register32(KHwBaseAesReg + KHoAES_MASK);
1.548 + // Kern::Printf("mask is %x", mask);
1.549 + mask |= KHtDesMaskDmaReqStart;
1.550 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_MASK, mask);
1.551 + // Kern::Printf("changed to %x", TOmap::Register32(KHwBaseAesReg + KHoAES_MASK));
1.552 +#else
1.553 + (void)aPtr;
1.554 +#endif
1.555 + iHwRunning = ETrue;
1.556 + }
1.557 +
1.558 + if(aToHw)
1.559 + {
1.560 + ++iDmaToHwPending;
1.561 + SetRunning(ETrue);
1.562 + }
1.563 + else
1.564 + {
1.565 + ++iDmaFromHwPending;
1.566 + SetRunning(ETrue);
1.567 + }
1.568 +
1.569 + }
1.570 +
1.571 +
1.572 +void CryptoH4JobAes::StopHw()
1.573 + {
1.574 + TRACE_FUNCTION("StopHw");
1.575 +#ifdef __MARM__
1.576 + // Disable h/w
1.577 + TUint32 mask = TOmap::Register32(KHwBaseAesReg + KHoAES_MASK);
1.578 + mask &= ~KHtDesMaskDmaReqStart;
1.579 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_MASK, mask);
1.580 +#endif
1.581 + iHwRunning = EFalse;
1.582 + }
1.583 +
1.584 +
1.585 +
1.586 +/**
1.587 + Called when the current h/w opperation is complete
1.588 +*/
1.589 +void CryptoH4JobAes::DmaComplete(DDmaRequest::TResult aResult, TAny *aPtr)
1.590 + {
1.591 + TRACE_FUNCTION("TResult");
1.592 + (void)aResult;
1.593 + // Queue our DFC to action the DMA complete notification in our thread.
1.594 + reinterpret_cast<TDfc *>(aPtr)->Enque();
1.595 + }
1.596 +
1.597 +
1.598 +
1.599 +
1.600 +void CryptoH4JobAes::DmaToHwCompleteDfc(TAny* aPtr)
1.601 + {
1.602 + ((CryptoH4JobAes*)aPtr)->DoDmaToHwCompleteDfc();
1.603 + }
1.604 +
1.605 +
1.606 +void CryptoH4JobAes::DoDmaToHwCompleteDfc()
1.607 + {
1.608 + TRACE_FUNCTION("DoDmaToHwCompleteDfc");
1.609 + // Kern::Printf("**DoDmaToHwCompleteDfc iHwReadIndex %d, iHwWriteIndex %d",iHwReadIndex, iHwWriteIndex);
1.610 + --iDmaToHwPending;
1.611 + if(iDmaToHwPending < 0) Kern::Fault("DoDmaToHwCompleteDfc - iDmaToHwPending is negative",1);
1.612 +
1.613 +#ifdef FAKE_DMA
1.614 + --iFakeDmaToHwQueued;
1.615 + if(iFakeDmaToHwQueued < 0) Kern::Fault("DoDmaToHwCompleteDfc - iFakeDmaToHwQueued is negative",2);
1.616 +#endif
1.617 +
1.618 + CheckIndexes();
1.619 +
1.620 +#ifdef __MARM__
1.621 + if(! (TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlInputReady))
1.622 + {
1.623 + Kern::Fault("DoDmaToHwCompleteDfc - h/w not ready for input!",3);
1.624 + }
1.625 + // Kern::Printf("DoDmaToHwCompleteDfc - Writing data into h/w index %d (%x)", iHwReadIndex, TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
1.626 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_1, iAesBuffer[iHwReadIndex]);
1.627 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_2, iAesBuffer[iHwReadIndex+1]);
1.628 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_3, iAesBuffer[iHwReadIndex+2]);
1.629 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_4, iAesBuffer[iHwReadIndex+3]);
1.630 +#endif
1.631 +
1.632 + // Update index to point at next block to be passed to the h/w
1.633 + iHwReadIndex += 4; // 4x32bit == 16bytes == block length
1.634 + if(iHwReadIndex == sizeof(iAesBuffer)/sizeof(TUint32))
1.635 + {
1.636 + iHwReadIndex = 0;
1.637 + }
1.638 +
1.639 + if(!iDmaFromHwPending)
1.640 + {
1.641 + SetupDma((TUint32)&iAesBuffer[iHwWriteIndex], EFalse);
1.642 + }
1.643 +
1.644 + CheckIndexes();
1.645 +
1.646 + // Setup to read data (if enough is available).
1.647 + MaybeSetupWriteDmaToHw();
1.648 +
1.649 + FAKE_DMA();
1.650 + }
1.651 +
1.652 +void CryptoH4JobAes::DmaFromHwCompleteDfc(TAny* aPtr)
1.653 + {
1.654 + ((CryptoH4JobAes*)aPtr)->DoDmaFromHwCompleteDfc();
1.655 + }
1.656 +
1.657 +
1.658 +void CryptoH4JobAes::DoDmaFromHwCompleteDfc()
1.659 + {
1.660 + TRACE_FUNCTION("DoDmaFromHwCompleteDfc");
1.661 + // Kern::Printf("**DoDmaFromHwCompleteDfc iHwReadIndex %d, iHwWriteIndex %d", iHwReadIndex, iHwWriteIndex);
1.662 +
1.663 + --iDmaFromHwPending;
1.664 + if(iDmaFromHwPending < 0) Kern::Fault("DoDmaFromHwCompleteDfc - iDmaFromHwPending is negative",1);
1.665 +
1.666 +#ifdef FAKE_DMA
1.667 + --iFakeDmaFromHwQueued;
1.668 + if(iFakeDmaFromHwQueued < 0) Kern::Fault("iFakeDmaFromHwQueued - iFakeDmaFromHwQueued is negative",2);
1.669 +#endif
1.670 +
1.671 + CheckIndexes();
1.672 +
1.673 +#ifdef __MARM__
1.674 + if(! (TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlOutputReady))
1.675 + {
1.676 + Kern::Fault("DoDmaToHwCompleteDfc - h/w not ready for output!",3);
1.677 + }
1.678 +
1.679 + // Kern::Printf("DoDmaFromHwCompleteDfc - Reading data from h/w index %d (%x)", iHwWriteIndex, TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
1.680 + iAesBuffer[iHwWriteIndex] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_1);
1.681 + iAesBuffer[iHwWriteIndex+1] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_2);
1.682 + iAesBuffer[iHwWriteIndex+2] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_3);
1.683 + iAesBuffer[iHwWriteIndex+3] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_4);
1.684 +#endif
1.685 +
1.686 + // Update index to point at next block to be read from the h/w
1.687 + iHwWriteIndex += 4; // 4x32bit == 16bytes == block length
1.688 + if(iHwWriteIndex == sizeof(iAesBuffer)/sizeof(TUint32))
1.689 + {
1.690 + iHwWriteIndex= 0;
1.691 + }
1.692 +
1.693 + CheckIndexes();
1.694 +
1.695 +
1.696 +
1.697 + TInt hwWrite8Index = iHwWriteIndex * 4;
1.698 + TInt hwRead8Index = iHwReadIndex * 4;
1.699 +
1.700 + // Check if we either have enough data to finish the current LDD
1.701 + // user read request, or if we are running out of space
1.702 + //
1.703 + // Calculate data available for xfer to user
1.704 + TInt availableForUser = hwWrite8Index - iSwReadByteOffset;
1.705 + if(availableForUser < 0)
1.706 + {
1.707 + availableForUser += sizeof(iAesBuffer);
1.708 + }
1.709 +
1.710 + if((availableForUser >= sizeof(iAesBuffer) - 32) ||
1.711 + (availableForUser >= iReadRequestLength))
1.712 + {
1.713 + // Pass available data to user
1.714 + TInt r = iCallbacks->DataAvailable();
1.715 + if(r != KErrNone)
1.716 + {
1.717 + iJobScheduler->JobComplete(this,r);
1.718 + return;
1.719 + }
1.720 + }
1.721 +
1.722 + // Are we running short of data?
1.723 + TInt availableForHw = iSwWriteByteOffset - hwRead8Index;
1.724 + if(availableForHw < 0)
1.725 + {
1.726 + availableForHw += sizeof(iAesBuffer);
1.727 + }
1.728 +
1.729 + if(availableForHw < 16)
1.730 + {
1.731 + TInt r = iCallbacks->DataRequired();
1.732 + if(r != KErrNone)
1.733 + {
1.734 + iJobScheduler->JobComplete(this,r);
1.735 + return;
1.736 + }
1.737 + }
1.738 +
1.739 + // Kick off a new to h/w DMA if one is not already running
1.740 + MaybeSetupWriteDmaToHw();
1.741 +
1.742 + // Current h/w -> iAesBuffer DMA request has completed
1.743 + if(iHwWriteIndex != iHwReadIndex)
1.744 + {
1.745 + SetupDma((TUint32)&iAesBuffer[iHwWriteIndex], EFalse);
1.746 + }
1.747 +
1.748 + if(!iDmaToHwPending && ! iDmaFromHwPending)
1.749 + {
1.750 + // Kern::Printf("\t\tDoDmaFromHwCompleteDfc STALLED (underrun), iHwReadIndex %d iHwWriteIndex %d",
1.751 + // iHwReadIndex, iHwWriteIndex);
1.752 + // Run out of data to process!
1.753 + // Tell the scheduler that we are stalled & therefore this slice is done
1.754 + Stalled();
1.755 + return;
1.756 + }
1.757 +
1.758 +
1.759 + CheckIndexes();
1.760 +
1.761 + FAKE_DMA();
1.762 + }
1.763 +
1.764 +void CryptoH4JobAes::CheckIndexes() const
1.765 + {
1.766 + TRACE_FUNCTION("CheckIndexes");
1.767 + if(iSwWriteByteOffset < 0 || iSwWriteByteOffset > sizeof(iAesBuffer)) Kern::Fault("CryptoH4JobAes::checkIndexes", 1);
1.768 +
1.769 + if(iHwReadIndex < 0 || iHwReadIndex > sizeof(iAesBuffer)/sizeof(iAesBuffer[0])) Kern::Fault("CryptoH4JobAes::checkIndexes", 2);
1.770 +
1.771 + if(iHwWriteIndex < 0 || iHwWriteIndex > sizeof(iAesBuffer)/sizeof(iAesBuffer[0])) Kern::Fault("CryptoH4JobAes::checkIndexes", 3);
1.772 +
1.773 + if(iSwReadByteOffset < 0 || iSwReadByteOffset > sizeof(iAesBuffer)) Kern::Fault("CryptoH4JobAes::checkIndexes", 4);
1.774 +
1.775 +
1.776 + TInt32 d = iSwWriteByteOffset;
1.777 + TInt32 c = iHwReadIndex * 4;
1.778 + TInt32 b = iHwWriteIndex * 4;
1.779 + TInt32 a = iSwReadByteOffset;
1.780 +
1.781 + // Kern::Printf("%d %d %d %d", a, b, c, d);
1.782 +
1.783 + TInt32 offset = 0;
1.784 + if(b < a) offset = sizeof(iAesBuffer);
1.785 + b += offset;
1.786 + if(c < b) offset = sizeof(iAesBuffer);
1.787 + c += offset;
1.788 + if(d < c) offset = sizeof(iAesBuffer);
1.789 + d += offset;
1.790 +
1.791 + if(a>b) Kern::Fault("CryptoH4JobAes::CheckIndexes", 5);
1.792 + if(b>c) Kern::Fault("CryptoH4JobAes::CheckIndexes", 6);
1.793 + if(c>d) Kern::Fault("CryptoH4JobAes::CheckIndexes", 7);
1.794 + }
1.795 +
1.796 +
1.797 +void CryptoH4JobAes::NotifyReadRequestLength(TUint32 aReadRequestLength)
1.798 + {
1.799 + TRACE_FUNCTION("NotifyReadRequestLength");
1.800 + iReadRequestLength = aReadRequestLength;
1.801 + }
1.802 +
1.803 +/**
1.804 + HwPerfCheck
1.805 +
1.806 + This function uses 100% of the CPU power to attempt to drive
1.807 + the AES h/w as fast as possible.
1.808 +
1.809 + This will give some indication of the maximum achievable speed of the h/w
1.810 + excluding the overhead of (almost all of) the driver framework.
1.811 + */
1.812 +void CryptoH4JobAes::HwPerfCheck()
1.813 + {
1.814 + TRACE_FUNCTION("HwPerfCheck");
1.815 + SetupHw(EFalse);
1.816 +
1.817 + // Start h/w
1.818 +#ifdef __MARM__
1.819 + TUint32 mask = TOmap::Register32(KHwBaseAesReg + KHoAES_MASK);
1.820 + mask |= KHtDesMaskDmaReqStart;
1.821 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_MASK, mask);
1.822 +#endif
1.823 +
1.824 + // Reset indexes
1.825 + iSwWriteByteOffset = 0;
1.826 + iHwReadIndex = 0,
1.827 + iHwWriteIndex = 0,
1.828 + iSwReadByteOffset = 0;
1.829 +
1.830 + // Read data
1.831 + iCallbacks->DataRequired();
1.832 + // Process all data
1.833 + while(iHwWriteIndex*4 < iSwWriteByteOffset)
1.834 + {
1.835 +#ifdef __MARM__
1.836 + // Kern::Printf("Ctrl %08x", TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
1.837 +#endif
1.838 + // Have we got more data to write to h/w?
1.839 + if(iHwReadIndex < iSwWriteByteOffset/4)
1.840 + {
1.841 + // Yes, but is h/w ready for it?
1.842 +#ifdef __MARM__
1.843 + if(TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlInputReady)
1.844 + {
1.845 + // Kern::Printf("toHw iHwReadIndex=%d", iHwReadIndex);
1.846 + // ok, write data to h/w
1.847 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_1, iAesBuffer[iHwReadIndex]);
1.848 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_2, iAesBuffer[iHwReadIndex+1]);
1.849 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_3, iAesBuffer[iHwReadIndex+2]);
1.850 + TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_4, iAesBuffer[iHwReadIndex+3]);
1.851 + iHwReadIndex += 4;
1.852 + }
1.853 +#else
1.854 + iHwReadIndex += 4;
1.855 +#endif
1.856 + }
1.857 + // Do we expect more data from the h/w?
1.858 + if(iHwWriteIndex < iSwWriteByteOffset/4)
1.859 + {
1.860 + // Yes, but is h/w ready?
1.861 +#ifdef __MARM__
1.862 + if(TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlOutputReady)
1.863 + {
1.864 + // Kern::Printf("ReadHw to iHwWriteIndex=%d", iHwWriteIndex);
1.865 + iAesBuffer[iHwWriteIndex] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_1);
1.866 + iAesBuffer[iHwWriteIndex+1] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_2);
1.867 + iAesBuffer[iHwWriteIndex+2] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_3);
1.868 + iAesBuffer[iHwWriteIndex+3] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_4);
1.869 + iHwWriteIndex += 4;
1.870 + }
1.871 +#else
1.872 + iHwWriteIndex += 4;
1.873 +#endif
1.874 + }
1.875 + }
1.876 +
1.877 + // Write data back to user
1.878 + iCallbacks->DataAvailable();
1.879 + }
1.880 +
1.881 +
1.882 +
1.883 +
1.884 +#ifdef TDFC_WRAPPER
1.885 +TDfcWrapper::TDfcWrapper(const TDfcWrapper &aOrig)
1.886 + : TDfc(DfcWrapperFunc, this, aOrig.iPriority)
1.887 + {
1.888 + TRACE_FUNCTION("TDfcWrapper");
1.889 + iRealFunction = aOrig.iRealFunction,
1.890 + iRealPtr = aOrig.iRealPtr;
1.891 + SetDfcQ(aOrig.iDfcQ);
1.892 + }
1.893 +
1.894 +
1.895 +TDfcWrapper::TDfcWrapper(TDfcFn aFunction, TAny* aPtr, TInt aPriority)
1.896 + : TDfc(DfcWrapperFunc, this, aPriority),
1.897 + iRealFunction(aFunction),
1.898 + iRealPtr(aPtr)
1.899 + {
1.900 + TRACE_FUNCTION("TDfcWrapper");
1.901 + }
1.902 +
1.903 +void TDfcWrapper::Enque()
1.904 + {
1.905 + TRACE_FUNCTION("Enque");
1.906 + // Clone self and queue the clone
1.907 + TDfcWrapper *p = new TDfcWrapper(*this);
1.908 + p->BaseEnque();
1.909 + }
1.910 +
1.911 +void TDfcWrapper::BaseEnque()
1.912 + {
1.913 + TRACE_FUNCTION("BaseEnque");
1.914 + TDfc::Enque();
1.915 + }
1.916 +
1.917 +
1.918 +void TDfcWrapper::DfcWrapperFunc(TAny* aPtr)
1.919 + {
1.920 + TRACE_FUNCTION("DfcWrapperFunc");
1.921 + TDfcWrapper *p = (TDfcWrapper *) aPtr;
1.922 + p->iRealFunction(p->iRealPtr);
1.923 + delete p;
1.924 + }
1.925 +#endif
1.926 +
1.927 +#ifdef DUMPBUFFER
1.928 +LOCAL_D void dumpBuffer(const char *aName, TUint32 *aBuf, TUint32 aLen)
1.929 + {
1.930 + Kern::Printf("%s =", aName);
1.931 + TUint8 *buf8 = reinterpret_cast<TUint8 *>(aBuf);
1.932 + for(TInt i = 0 ; i < aLen*4; ++i)
1.933 + {
1.934 + if(i%16 == 0)
1.935 + {
1.936 + Kern::Printf("\n ");
1.937 + }
1.938 + Kern::Printf("%02x ", buf8[i]);
1.939 + }
1.940 + Kern::Printf("\n");
1.941 + }
1.942 +#endif
1.943 +
1.944 +// End of file