os/kernelhwsrv/kernel/eka/memmodel/epoc/putils.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/memmodel/epoc/putils.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1189 @@
     1.4 +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32\memmodel\epoc\putils.cpp
    1.18 +// EPOC implementation of the ROM related parts of the system
    1.19 +// 
    1.20 +//
    1.21 +
    1.22 +#include "plat_priv.h"
    1.23 +#include <e32uid.h>
    1.24 +#include "execs.h"
    1.25 +#include "cache_maintenance.h"
    1.26 +
    1.27 +_LIT(KKernelFullPathNameSysBin,"z:\\sys\\bin\\ekern.exe");
    1.28 +
    1.29 +#ifdef __MARM__
    1.30 +#define	CHECK_ROM_ENTRY_POINT(a)	__ASSERT_ALWAYS( ((a).iFlags & KRomImageEptMask) == KRomImageEpt_Eka2, PP::Panic(PP::EUnsupportedOldBinary) )
    1.31 +#else
    1.32 +#define	CHECK_ROM_ENTRY_POINT(a)
    1.33 +#endif
    1.34 +
    1.35 +void PP::Panic(TPlatPanic aPanic)
    1.36 +	{
    1.37 +	Kern::Fault("PLAT",aPanic);
    1.38 +	}
    1.39 + 
    1.40 +void PP::InitSuperPageFromRom(TLinAddr aRomHeader, TLinAddr aSuperPage)
    1.41 +	{
    1.42 +	RomHeaderAddress = aRomHeader;
    1.43 +	SuperPageAddress = aSuperPage;
    1.44 +
    1.45 +	TInt j;
    1.46 +	for (j = 0; j < KNumTraceMaskWords; j++)
    1.47 +		TheSuperPage().iDebugMask[j] = TheRomHeader().iTraceMask[j];
    1.48 +
    1.49 +	for (j = 0; j < 8; j++)
    1.50 +		TheSuperPage().iInitialBTraceFilter[j] = TheRomHeader().iInitialBTraceFilter[j];
    1.51 +
    1.52 +	Kern::SuperPage().iInitialBTraceBuffer = TheRomHeader().iInitialBTraceBuffer;
    1.53 +	Kern::SuperPage().iInitialBTraceMode = TheRomHeader().iInitialBTraceMode;
    1.54 +
    1.55 +	TheSuperPage().SetKernelConfigFlags(TheRomHeader().iKernelConfigFlags);
    1.56 +
    1.57 +	memcpy(&TheSuperPage().iDisabledCapabilities, &TheRomHeader().iDisabledCapabilities, sizeof(TheRomHeader().iDisabledCapabilities));
    1.58 +	}
    1.59 +
    1.60 +TInt P::DefaultInitialTime()
    1.61 +	{
    1.62 +//
    1.63 +// Default implementation of the kernel hook for getting the initial system
    1.64 +// time, can be overriden by variant.
    1.65 +//
    1.66 +    TInt seconds;
    1.67 +	if (K::ColdStart || A::SystemTimeInSecondsFrom2000(seconds)!=KErrNone)
    1.68 +		return KErrCorrupt;
    1.69 +	else
    1.70 +		return seconds;
    1.71 +	}
    1.72 +
    1.73 +TInt P::InitSystemTime()
    1.74 +	{
    1.75 +//
    1.76 +//  Initialise system time
    1.77 +//	Return the initial time in seconds from 00:00:00 01-01-2000
    1.78 +//
    1.79 +
    1.80 +	// Reset the UTC offset (I assume this gets loaded from storage at some point after F32 loads)
    1.81 +	TUint dummy;
    1.82 +	K::SetSystemTimeAndOffset(0, 0, 0, dummy, ETimeSetOffset | ETimeSetNoTimeUpdate);
    1.83 +
    1.84 +	// Read the hardware clock value. If this is negative it means it couldnt be read.
    1.85 +    TInt seconds = K::InitialTimeHandler()();	
    1.86 +
    1.87 +	if (seconds >= 0)
    1.88 +		{
    1.89 +		K::SecureClockStatus |= ESecureClockPresent;
    1.90 +		__KTRACE_OPT(KBOOT,Kern::Printf("Read initial system time"));
    1.91 +		// now=Hardware RTC value
    1.92 +		}
    1.93 +	else 
    1.94 +		{
    1.95 +		__KTRACE_OPT(KBOOT,Kern::Printf("Could not read initial system time - using ROM timestamp to set system time"));
    1.96 +		TTimeK rom_time=*(const TTimeK*)&TheRomHeader().iTime;
    1.97 +		rom_time -= TTimeK(K::HomeTimeOffsetSeconds)*1000000;
    1.98 +		TInt s;
    1.99 +		TInt r=K::SecondsFrom2000(rom_time,s);
   1.100 +		if (r!=KErrNone)
   1.101 +			PP::Panic(PP::EInitialSystemTimeInvalid);
   1.102 +		seconds=s;
   1.103 +
   1.104 +		// write the ROM timestamp to the hardware RTC
   1.105 +		A::SetSystemTimeInSecondsFrom2000(seconds);
   1.106 +		}
   1.107 +	return seconds;
   1.108 +	}
   1.109 +
   1.110 +
   1.111 +void FindRomRootDirectory()
   1.112 +	{
   1.113 +	TUint variant = TheSuperPage().iActiveVariant;
   1.114 +	TUint cpu = (variant >> 16) & 0xff;
   1.115 +	TUint asic = (variant >> 24);
   1.116 +	PP::RomRootDirAddress=0;
   1.117 +	TRomRootDirectoryList* pL=(TRomRootDirectoryList*)TheSuperPage().iRootDirList;
   1.118 +	if (!pL)
   1.119 +		pL=(TRomRootDirectoryList*)TheRomHeader().iRomRootDirectoryList;
   1.120 +	TInt i;
   1.121 +	for (i=0; i<pL->iNumRootDirs; i++)
   1.122 +		{
   1.123 +		if (THardwareVariant(pL->iRootDir[i].iHardwareVariant).IsCompatibleWith(cpu,asic,variant))
   1.124 +			{
   1.125 +			__KTRACE_OPT(KBOOT,Kern::Printf("Found ROM root dir index %d addr %08x",
   1.126 +				i, pL->iRootDir[i].iAddressLin));
   1.127 +			PP::RomRootDirAddress=pL->iRootDir[i].iAddressLin;
   1.128 +			return;
   1.129 +			}
   1.130 +		}
   1.131 +	}
   1.132 +
   1.133 +typedef TInt (*TInitVarExtFn)(const TRomImageHeader&);
   1.134 +
   1.135 +#ifdef KBOOT
   1.136 +void DumpRomFileInfo(const TRomEntry& aRomEntry)
   1.137 +	{
   1.138 +	TBuf8<128> name;
   1.139 +	TInt i;
   1.140 +	for (i=0; i<aRomEntry.iNameLength; ++i)
   1.141 +		{
   1.142 +		name.Append(TChar(aRomEntry.iName[i<<1]&0xff));
   1.143 +		}
   1.144 +	const TRomImageHeader& img = *(const TRomImageHeader*)aRomEntry.iAddressLin;
   1.145 +	__KTRACE_OPT(KBOOT,Kern::Printf("File %S[%08x]", &name, TUint(img.iHardwareVariant) ));
   1.146 +	}
   1.147 +#endif
   1.148 +
   1.149 +void InitVarExt(TBool aVar, TInitVarExtFn aFn)
   1.150 +	{
   1.151 +	__KTRACE_OPT(KBOOT,Kern::Printf("InitVarExt var=%d, fn=%08x", aVar, aFn));
   1.152 +	TUint variant = TheSuperPage().iActiveVariant;
   1.153 +	TUint cpu = (variant >> 16) & 0xff;
   1.154 +	TUint asic = (variant >> 24);
   1.155 +	__KTRACE_OPT(KBOOT,Kern::Printf("cpu=%d, asic=%d, variant=%x", cpu, asic, variant));
   1.156 +	const TRomHeader& rh = TheRomHeader();
   1.157 +	TRomEntry* pE = aVar ? (TRomEntry*)rh.iVariantFile : (TRomEntry*)rh.iExtensionFile;
   1.158 +	while(pE)
   1.159 +		{
   1.160 +#ifdef KBOOT
   1.161 +		DumpRomFileInfo(*pE);
   1.162 +#endif
   1.163 +		const TRomImageHeader& img = *(const TRomImageHeader*)pE->iAddressLin;
   1.164 +		if (THardwareVariant(img.iHardwareVariant).IsCompatibleWith(cpu,asic,variant))
   1.165 +			{
   1.166 +			__KTRACE_OPT(KBOOT,Kern::Printf("Processing"));
   1.167 +			(*aFn)(img);
   1.168 +			if (aVar)
   1.169 +				{
   1.170 +				__KTRACE_OPT(KBOOT,Kern::Printf("Variant installed"));
   1.171 +				return;
   1.172 +				}
   1.173 +			}
   1.174 +		pE=(TRomEntry*)img.iNextExtension;
   1.175 +		}
   1.176 +	if (aVar)
   1.177 +		Kern::Fault("NoVariant",0);
   1.178 +	}
   1.179 +
   1.180 +TInt InitData(const TRomImageHeader& a)
   1.181 +	{
   1.182 +	__KTRACE_OPT(KBOOT,Kern::Printf("InitData %08x+%x->%08x", a.iDataAddress, a.iDataSize, a.iDataBssLinearBase));
   1.183 +	CHECK_ROM_ENTRY_POINT(a);
   1.184 +	if (a.iDataSize)
   1.185 +		memcpy((TAny*)a.iDataBssLinearBase,(TAny*)a.iDataAddress,a.iDataSize);
   1.186 +	TLibraryEntry ep = (TLibraryEntry)a.iEntryPoint;
   1.187 +	__KTRACE_OPT(KBOOT,Kern::Printf("Calling entrypoint %08x(VariantInit0)", ep));
   1.188 +	TInt r = ep(KModuleEntryReasonVariantInit0);
   1.189 +	__KTRACE_OPT(KBOOT,Kern::Printf("Entrypoint returned %d",r));
   1.190 +	if(!(++K::ExtensionCount&0x7fffffff))
   1.191 +		K::Fault(K::ETooManyExtensions);
   1.192 +	return r;
   1.193 +	}
   1.194 +
   1.195 +TInt InitVariant(const TRomImageHeader& a)
   1.196 +	{
   1.197 +	TInt r = InitData(a);
   1.198 +	__KTRACE_OPT(KBOOT,Kern::Printf("InitVariant: entry point returns %08x", r));
   1.199 +	if (r<0)
   1.200 +		Kern::Fault("VariantEntry",r);
   1.201 +
   1.202 +	// Initialise and create the variant object
   1.203 +	r = A::CreateVariant(&a, r);
   1.204 +	if (r<0)
   1.205 +		Kern::Fault("VariantInit",r);
   1.206 +	return r;
   1.207 +	}
   1.208 +
   1.209 +void P::CreateVariant()
   1.210 +	{
   1.211 +	__KTRACE_OPT(KBOOT,Kern::Printf("CreateVariant"));
   1.212 +	BTrace::Init0();
   1.213 +	InitVarExt(EFalse, &InitData);		// initialise .data for all extensions
   1.214 +	InitVarExt(ETrue, &InitVariant);	// find variant and initialise it
   1.215 +	FindRomRootDirectory();
   1.216 +	}
   1.217 +
   1.218 +struct SExtInit1EntryPoint
   1.219 +	{
   1.220 +	inline SExtInit1EntryPoint() : iEntryPoint(0),iReturnCode(0)
   1.221 +		{}
   1.222 +	inline SExtInit1EntryPoint(TLibraryEntry aEp, TInt aVal) : iEntryPoint(aEp),iReturnCode(aVal)
   1.223 +		{}
   1.224 +	TLibraryEntry iEntryPoint;
   1.225 +	TInt iReturnCode;		// bits 7-0 used for extension startup priority order
   1.226 +	};
   1.227 +
   1.228 +// This ordering function when used in conjunction with RArray<>::InsertInOrderAllowRepeats
   1.229 +// orders the array of extensions as follow:
   1.230 +//		highest priority -> lowest priority
   1.231 +//		if same priority -> first in, lowest index
   1.232 +//
   1.233 +TInt priorityOrder(const SExtInit1EntryPoint& aMatch, const SExtInit1EntryPoint& aEntry)
   1.234 +	{
   1.235 +	TUint8 l=(TUint8)aMatch.iReturnCode;
   1.236 +	TUint8 r=(TUint8)aEntry.iReturnCode;
   1.237 +	if(l>r)
   1.238 +		return -1;
   1.239 +	else if(l<r)
   1.240 +		return 1;
   1.241 +	else
   1.242 +		return 0;
   1.243 +	}
   1.244 +
   1.245 +TInt InitExt0(const TRomImageHeader& a)
   1.246 +	{
   1.247 +	CHECK_ROM_ENTRY_POINT(a);
   1.248 +	TLibraryEntry ep = (TLibraryEntry)a.iEntryPoint;
   1.249 +	__KTRACE_OPT(KBOOT,Kern::Printf("InitExt0 %08x ep=%08x", &a, ep));
   1.250 +	TInt r = (*ep)(KModuleEntryReasonExtensionInit0);
   1.251 +	if (r<KErrNone)
   1.252 +		{
   1.253 +		__KTRACE_OPT(KBOOT,Kern::Printf("Already started"));
   1.254 +		return r;
   1.255 +		}
   1.256 +	SExtInit1EntryPoint s(ep,r);
   1.257 +	TInt count=K::ExtensionArray->Count();
   1.258 +	if(count==K::ExtensionCount)					// this function is only called if extensions exist, i.e. K::ExtensionCount>0
   1.259 +		K::Fault(K::EExtensionArrayOverflowed);		// the first insertion will allocate space for K::ExtensionCount entries and that is the maximum number of entries allowed
   1.260 +	TLinearOrder<SExtInit1EntryPoint> PriorityOrder(priorityOrder);
   1.261 +	if(K::ExtensionArray->InsertInOrderAllowRepeats(s,PriorityOrder)!=KErrNone)
   1.262 +		K::Fault(K::EInsertExtensionFailed);
   1.263 +	__KTRACE_OPT(KBOOT,Kern::Printf("Inserted at index %d, priority %d, last index %d", K::ExtensionArray->SpecificFindInOrder(s,PriorityOrder,EArrayFindMode_Last)-1, (TUint8)r, count));
   1.264 +	return KErrNone;
   1.265 +	}
   1.266 +
   1.267 +void P::StartExtensions()
   1.268 +	{
   1.269 +	// start extensions...
   1.270 +	__KTRACE_OPT(KBOOT, Kern::Printf("Starting kernel extensions..."));
   1.271 +
   1.272 +	K::ExtensionArray = new RArray<SExtInit1EntryPoint>(--K::ExtensionCount);	// ordered array of extensions excluding Variant
   1.273 +	if(!K::ExtensionArray)
   1.274 +		K::Fault(K::EExtensionArrayAllocationFailed);
   1.275 +	__KTRACE_OPT(KBOOT, Kern::Printf("Entry point array at %08x, max size %d",K::ExtensionArray,K::ExtensionCount));
   1.276 +
   1.277 +	InitVarExt(EFalse, &InitExt0);		// populates the array of entry points in priority order
   1.278 +
   1.279 +	for(TInt i=0; i<K::ExtensionArray->Count(); i++)	// call entry points in combined priority and temporal orders
   1.280 +		{
   1.281 +		TLibraryEntry ep = (*K::ExtensionArray)[i].iEntryPoint;
   1.282 +		__KTRACE_OPT(KBOOT,Kern::Printf("InitExt1: calling entrypoint %08x", ep));
   1.283 +		TInt r = ep(KModuleEntryReasonExtensionInit1);
   1.284 +		__KTRACE_OPT(KBOOT,Kern::Printf("Entrypoint returned %d", r));
   1.285 +		if (r!=KErrNone)
   1.286 +			K::Fault(K::EStartExtensionsFailed);
   1.287 +		}
   1.288 +	// preserve array of extensions, it contains the returned codes from ExtInit0 which may be useful for future use
   1.289 +	//delete K::ExtensionArray;
   1.290 +	//K::ExtensionArray=NULL;
   1.291 +	}
   1.292 +
   1.293 +void P::KernelInfo(TProcessCreateInfo& aInfo, TAny*& aStack, TAny*& aHeap)
   1.294 +//
   1.295 +// Provide the initial supervisor data information from the ROM
   1.296 +//
   1.297 +	{
   1.298 +	aInfo.iFileName=KKernelFullPathNameSysBin;
   1.299 +	aInfo.iRootNameOffset=11;
   1.300 +	aInfo.iRootNameLength=9;
   1.301 +	aInfo.iExtOffset = 16;
   1.302 +
   1.303 +	aInfo.iAttr=ECodeSegAttKernel|ECodeSegAttFixed;
   1.304 +
   1.305 +	const TRomHeader& romHdr=TheRomHeader();
   1.306 +	const TRomEntry* primaryEntry=(const TRomEntry*)TheSuperPage().iPrimaryEntry;
   1.307 +	const TRomImageHeader* primaryImageHeader=(const TRomImageHeader*)primaryEntry->iAddressLin;
   1.308 +	Epoc::RomProcessInfo(aInfo, *primaryImageHeader);
   1.309 +	aStack = (TAny*)(romHdr.iKernDataAddress + Kern::RoundToPageSize(romHdr.iTotalSvDataSize));
   1.310 +	aHeap = (TAny*)(TLinAddr(aStack) + Kern::RoundToPageSize(aInfo.iStackSize));
   1.311 +	aInfo.iTotalDataSize=romHdr.iTotalSvDataSize;
   1.312 +	aInfo.iHeapSizeMin=TheSuperPage().iInitialHeapSize;
   1.313 +	}
   1.314 +
   1.315 +EXPORT_C void Epoc::RomProcessInfo(TProcessCreateInfo& aInfo, const TRomImageHeader& a)
   1.316 +	{
   1.317 +	CHECK_PAGING_SAFE;
   1.318 +	aInfo.iUids=*(const TUidType*)&a.iUid1;
   1.319 +	aInfo.iCodeSize=a.iCodeSize;
   1.320 +	aInfo.iTextSize=a.iTextSize;
   1.321 +	aInfo.iDataSize=a.iDataSize;
   1.322 +	aInfo.iBssSize=a.iBssSize;
   1.323 +	aInfo.iTotalDataSize=a.iTotalDataSize;
   1.324 +	aInfo.iEntryPtVeneer=a.iEntryPoint;
   1.325 +	aInfo.iFileEntryPoint=a.iEntryPoint;
   1.326 +	aInfo.iDepCount=a.iDllRefTable ? a.iDllRefTable->iNumberOfEntries : 0;
   1.327 +	aInfo.iExportDir=a.iExportDir;
   1.328 +	aInfo.iExportDirCount=a.iExportDirCount;
   1.329 +	aInfo.iCodeLoadAddress=(TLinAddr)&a;//a.iCodeAddress;
   1.330 +	aInfo.iCodeRunAddress=a.iCodeAddress;
   1.331 +	aInfo.iDataLoadAddress=a.iDataAddress;
   1.332 +	aInfo.iDataRunAddress=a.iDataBssLinearBase;
   1.333 +	aInfo.iExceptionDescriptor = a.iExceptionDescriptor;
   1.334 +	aInfo.iHeapSizeMin=a.iHeapSizeMin;
   1.335 +	aInfo.iHeapSizeMax=a.iHeapSizeMax;
   1.336 +	aInfo.iStackSize=a.iStackSize;
   1.337 +	aInfo.iPriority=a.iPriority;
   1.338 +	aInfo.iHandle=NULL;
   1.339 +	aInfo.iS = a.iS;
   1.340 +	aInfo.iModuleVersion = a.iModuleVersion;
   1.341 +	if (a.iFlags&KRomImageFlagsKernelMask)
   1.342 +		aInfo.iAttr=ECodeSegAttKernel;
   1.343 +	else
   1.344 +		aInfo.iAttr=ECodeSegAttGlobal;
   1.345 +	if (a.iFlags&KRomImageFlagFixedAddressExe)
   1.346 +		aInfo.iAttr|=ECodeSegAttFixed;
   1.347 +	aInfo.iAttr &= ~ECodeSegAttABIMask;
   1.348 +	aInfo.iAttr |= (a.iFlags & KRomImageABIMask);
   1.349 +	if(a.iFlags&KRomImageSMPSafe)
   1.350 +		aInfo.iAttr |= ECodeSegAttSMPSafe;
   1.351 +	aInfo.iClientHandle = KCurrentThreadHandle;
   1.352 +	aInfo.iClientProcessHandle = 0;
   1.353 +	aInfo.iFinalHandle = 0;
   1.354 +	aInfo.iOwnerType = EOwnerProcess;
   1.355 +	aInfo.iFlags &= ~(TProcessCreateInfo::EDataPagingMask);
   1.356 +	if(a.iFlags&KRomImageFlagDataPaged)
   1.357 +		aInfo.iFlags |= TProcessCreateInfo::EDataPaged;
   1.358 +	if(a.iFlags&KRomImageFlagDataUnpaged)
   1.359 +		aInfo.iFlags |= TProcessCreateInfo::EDataUnpaged;
   1.360 +	CHECK_ROM_ENTRY_POINT(a);
   1.361 +	}
   1.362 +
   1.363 +EXPORT_C void Epoc::SetMonitorEntryPoint(TDfcFn aFn)
   1.364 +	{
   1.365 +	if (aFn)
   1.366 +		{
   1.367 +		TUint32 x=(TUint32)aFn;
   1.368 +		PP::MonitorEntryPoint[0]=x;
   1.369 +		PP::MonitorEntryPoint[1]=~x;
   1.370 +		PP::MonitorEntryPoint[2]=((x>>2)*~x);
   1.371 +		}
   1.372 +	else
   1.373 +		{
   1.374 +		PP::MonitorEntryPoint[0]=0;
   1.375 +		PP::MonitorEntryPoint[1]=0;
   1.376 +		PP::MonitorEntryPoint[2]=0;
   1.377 +		}
   1.378 +	}
   1.379 +
   1.380 +EXPORT_C void Epoc::SetMonitorExceptionHandler(TLinAddr aHandler)
   1.381 +	{
   1.382 +	TheScheduler.iMonitorExceptionHandler=aHandler;
   1.383 +	}
   1.384 +
   1.385 +EXPORT_C TAny* Epoc::ExceptionInfo()
   1.386 +	{
   1.387 +#ifdef __SMP__
   1.388 +	return 0;	// separate for each CPU
   1.389 +#else
   1.390 +	return TheScheduler.i_ExcInfo;
   1.391 +#endif
   1.392 +	}
   1.393 +
   1.394 +EXPORT_C const TRomHeader& Epoc::RomHeader()
   1.395 +	{
   1.396 +	return TheRomHeader();
   1.397 +	}
   1.398 +
   1.399 +TLinAddr ExecHandler::RomHeaderAddress()
   1.400 +	{
   1.401 +	return ::RomHeaderAddress;
   1.402 +	}
   1.403 +
   1.404 +TLinAddr ExecHandler::RomRootDirectoryAddress()
   1.405 +	{
   1.406 +	return PP::RomRootDirAddress;
   1.407 +	}
   1.408 +
   1.409 +TBool M::IsRomAddress(const TAny* aPtr)
   1.410 +	{
   1.411 +    TLinAddr start=::RomHeaderAddress;
   1.412 +    TLinAddr end=start+TheRomHeader().iUncompressedSize;
   1.413 +	return ((TLinAddr)aPtr>=start) && ((TLinAddr)aPtr<end);
   1.414 +	}
   1.415 +
   1.416 +void P::SetSuperPageSignature()
   1.417 +	{
   1.418 +	TUint32* sig = TheSuperPage().iSignature;
   1.419 +	const TUint32* time = (const TUint32*)&TheRomHeader().iTime;
   1.420 +	sig[0] = time[0] ^ 0xb504f333;
   1.421 +	sig[1] = time[1] ^ 0xf9de6484;
   1.422 +	}
   1.423 +
   1.424 +TBool P::CheckSuperPageSignature()
   1.425 +	{
   1.426 +	const TUint32* sig = TheSuperPage().iSignature;
   1.427 +	const TUint32* time = (const TUint32*)&TheRomHeader().iTime;
   1.428 +	return ( (sig[0]^time[0])==0xb504f333 && (sig[1]^time[1])==0xf9de6484 );
   1.429 +	}
   1.430 +
   1.431 +static const TUint32 KMapAttrType2 = 0x80000000;
   1.432 +static const TUint32 KMapAttrTypeShift 		 = 26;
   1.433 +
   1.434 +#if defined(__CPU_MEMORY_TYPE_REMAPPING)
   1.435 +extern TUint32 PrimaryRegionRemapRegister();
   1.436 +extern TUint32 NormalMemoryRemapRegister();
   1.437 +#endif
   1.438 +
   1.439 +EXPORT_C TMappingAttributes2::TMappingAttributes2(TMemoryType	aType,
   1.440 +														TBool	aUserAccess,
   1.441 +														TBool	aWritable,
   1.442 +														TBool	aExecutable,
   1.443 +														TInt	aShared,
   1.444 +														TInt	aParity)
   1.445 +	{
   1.446 +	//Sort out default values:
   1.447 +	if (aShared<0)
   1.448 +		#if defined	(__CPU_USE_SHARED_MEMORY)
   1.449 +		aShared = 1;
   1.450 +		#else
   1.451 +		aShared = 0;	
   1.452 +		#endif
   1.453 +	if (aParity<0)
   1.454 +		aParity = 0;
   1.455 +	
   1.456 +	// KMapAttrType2 bit marks the object as of TMappingAttributes2 type (as opposed to TMappingAttributes bitmask).
   1.457 +	// We have to make sure that these two types can work together.
   1.458 +
   1.459 +	iAttributes =	KMapAttrType2				|	// Mark it as TMappingAttributes2 object
   1.460 +					EMapAttrReadSup				|	// All memory is readable from Kernel (Supervisor) mode
   1.461 +					(aType <<KMapAttrTypeShift)	|
   1.462 +					(aUserAccess ? EMapAttrReadUser : 0)|
   1.463 +					(aWritable	 ? EMapAttrWriteSup : 0)|
   1.464 +		((aWritable&&aUserAccess)? EMapAttrWriteUser: 0)|
   1.465 +#ifdef __MMU_USE_SYMMETRIC_ACCESS_PERMISSIONS
   1.466 +					(aExecutable   ? EMapAttrExecSup : 0)|
   1.467 +		((aExecutable&&aUserAccess)? EMapAttrExecUser: 0)|
   1.468 +#else
   1.469 +					(aExecutable ? EMapAttrExecUser|EMapAttrExecSup : 0)|
   1.470 +#endif
   1.471 +					(aShared	 ? EMapAttrShared	: 0)|
   1.472 +					(aParity	 ? EMapAttrUseECC	: 0);
   1.473 +	
   1.474 +	// Kernel relies on TMappingAttributes bitmask when dealing with various memory mappings.
   1.475 +	// Set cache attribute bits as they are in TMappingAttributes.
   1.476 +	iAttributes |= InternalCache::TypeToCachingAttributes(aType);
   1.477 +	}
   1.478 +
   1.479 +TMappingAttributes2::TMappingAttributes2(TUint aMapAttr):iAttributes(aMapAttr)
   1.480 +	{
   1.481 +	};
   1.482 +
   1.483 +TMemoryType TMappingAttributes2::Type()
   1.484 +	{
   1.485 +	if(iAttributes&KMapAttrType2)
   1.486 +		return (TMemoryType)(iAttributes>>KMapAttrTypeShift & 0x7); //three bits for memory type.
   1.487 +
   1.488 +	switch(iAttributes&EMapAttrL1CacheMask)
   1.489 +		{
   1.490 +	case EMapAttrFullyBlocking:
   1.491 +		return EMemAttStronglyOrdered;
   1.492 +
   1.493 +	case EMapAttrBufferedNC:
   1.494 +		return EMemAttDevice;
   1.495 +
   1.496 +	case EMapAttrBufferedC:
   1.497 +	case EMapAttrL1Uncached:
   1.498 +	case EMapAttrCachedWTRA:
   1.499 +	case EMapAttrCachedWTWA:
   1.500 +	case EMapAttrAltCacheWTRA:
   1.501 +	case EMapAttrAltCacheWTWA:
   1.502 +		return EMemAttNormalUncached;
   1.503 +
   1.504 +	case EMapAttrCachedWBRA:
   1.505 +	case EMapAttrCachedWBWA:
   1.506 +	case EMapAttrAltCacheWBRA:
   1.507 +	case EMapAttrAltCacheWBWA:
   1.508 +	case EMapAttrL1CachedMax:
   1.509 +		return EMemAttNormalCached;
   1.510 +
   1.511 +	default:
   1.512 +		Panic(KErrArgument);
   1.513 +		return EMemAttNormalCached;
   1.514 +		}
   1.515 +	}
   1.516 +
   1.517 +TBool TMappingAttributes2::UserAccess()	{return (iAttributes&EMapAttrUserRw   ?	(TBool)ETrue : (TBool)EFalse);}
   1.518 +TBool TMappingAttributes2::Writable()	{return (iAttributes&EMapAttrWriteMask? (TBool)ETrue : (TBool)EFalse);}
   1.519 +#ifdef __MMU_USE_SYMMETRIC_ACCESS_PERMISSIONS
   1.520 +TBool TMappingAttributes2::Executable()	{return (iAttributes&EMapAttrExecMask ? (TBool)ETrue : (TBool)EFalse);}
   1.521 +#else
   1.522 +TBool TMappingAttributes2::Executable()	{return (iAttributes&EMapAttrExecUser ? (TBool)ETrue : (TBool)EFalse);}
   1.523 +#endif
   1.524 +TBool TMappingAttributes2::Shared()		{return (iAttributes&EMapAttrShared   ?	(TBool)ETrue : (TBool)EFalse);}
   1.525 +TBool TMappingAttributes2::Parity()		{return (iAttributes&EMapAttrUseECC	  ?	(TBool)ETrue : (TBool)EFalse);}
   1.526 +TBool TMappingAttributes2::ObjectType2(){return (iAttributes&KMapAttrType2	  ?	(TBool)ETrue : (TBool)EFalse);}
   1.527 +void  TMappingAttributes2::Panic(TInt aPanic)	{Kern::Fault("TMappingAttributes2",aPanic);}
   1.528 +
   1.529 +
   1.530 +#ifdef __DEBUGGER_SUPPORT__
   1.531 + /**
   1.532 + Initialises the breakpoint pool.
   1.533 + There is only one breakpoint pool in the system. The breakpoint pool should be initialised only once - usually from
   1.534 + the run-mode debugger device driver.
   1.535 +
   1.536 + @param aCapabilities	On return this is set to a bitmask of values from enum DebugSupport::TType which represents the
   1.537 + 						supported breakpoint types. At the moment only DebugSupport::EBreakpointGlobal type is supported.
   1.538 + @param aMaxBreakpoints The number of breakpoints for which resources should be reserved. It represents
   1.539 +                        the maximum number of the breakpoints at a time.
   1.540 +
   1.541 + @return KErrNoMemory, 		if not enough memory to reserve breakpoint resources.
   1.542 +   		 KErrInUse,    		if breakpoint pool already exists. Indicates that another debug tool might be using it at the moment.
   1.543 +   		 KErrNotSupported, 	if Kernel is not built with __DEBUGGER_SUPPORT__ option
   1.544 +   		 KErrNone,			on success.
   1.545 +
   1.546 + @pre   No fast mutex can be held.
   1.547 + @pre   Kernel must be unlocked.
   1.548 + @pre	Call in a thread context.
   1.549 + @pre	Interrupts must be enabled.
   1.550 + */
   1.551 +EXPORT_C TInt DebugSupport::InitialiseCodeModifier(TUint& aCapabilities, TInt aMaxBreakpoints)
   1.552 +	{
   1.553 +	CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::InitialiseCodeModifier");
   1.554 +	TInt err;
   1.555 +	NKern::ThreadEnterCS();
   1.556 +	Kern::MutexWait(CodeModifier::Mutex());
   1.557 +
   1.558 +	if ( KErrNone == (err =CodeModifier::CreateAndInitialise(aMaxBreakpoints)))
   1.559 +		aCapabilities = EBreakpointGlobal;
   1.560 +	
   1.561 +	Kern::MutexSignal(CodeModifier::Mutex());
   1.562 +	NKern::ThreadLeaveCS(); 
   1.563 +	return err;
   1.564 +	}
   1.565 +
   1.566 + /**
   1.567 + Restore all breakpoints and free resources.
   1.568 + Must not be called before Initialise().
   1.569 +
   1.570 + @panic CodeModifier 0 if called before InitialiseCodeModifier().
   1.571 +
   1.572 + @pre   No fast mutex can be held.
   1.573 + @pre   Kernel must be unlocked.
   1.574 + @pre	Call in a thread context.
   1.575 + @pre	Interrupts must be enabled.
   1.576 + */
   1.577 +EXPORT_C void DebugSupport::CloseCodeModifier()
   1.578 +	{
   1.579 +	CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::CloseCodeModifier");
   1.580 +	NKern::ThreadEnterCS(); 
   1.581 +	Kern::MutexWait(CodeModifier::Mutex());
   1.582 +
   1.583 +	if (!TheCodeModifier)
   1.584 +		{
   1.585 +		Kern::MutexSignal(CodeModifier::Mutex());
   1.586 +		NKern::ThreadLeaveCS(); 
   1.587 +		CodeModifier::Fault(CodeModifier::EPanicNotInitialised);
   1.588 +		}
   1.589 +	TheCodeModifier->Close();
   1.590 +
   1.591 +	Kern::MutexSignal(CodeModifier::Mutex());
   1.592 +	NKern::ThreadLeaveCS(); 
   1.593 +	}
   1.594 +
   1.595 +/**
   1.596 +Write a single breakpoint.
   1.597 +I.e. store aValue at location aAddress in the address space of aThread.
   1.598 +If the address resides in XIP code (ROM image), the memory page is shadowed before the content of the aAddress is altered.
   1.599 +
   1.600 +The breakpoint should be cleared/restored by DebugSupport::RestoreCode with matching aThread and aAddress.
   1.601 +The breakpoints are owned by the corresponding process. Therefore:
   1.602 +@code 
   1.603 +DebugSupport::ModifyCode(thread1, address, size, value, type);
   1.604 +and
   1.605 +DebugSupport::ModifyCode(thread2, address size, value, type);
   1.606 +@endcode
   1.607 +have the same effect if thread1 and thread2 belong to the same process.
   1.608 +
   1.609 +Breakpoints of the diferent type(size) cannot overlap each other. For example:
   1.610 +@code 
   1.611 +DebugSupport::ModifyCode(thread, address,   4, value, type); //address is word aligned address
   1.612 +DebugSupport::ModifyCode(thread, address,   2, value, type); //will return KErrAccessDenied
   1.613 +DebugSupport::ModifyCode(thread, address+2, 2, value, type); //will return KErrAccessDenied
   1.614 +DebugSupport::ModifyCode(thread, address+1, 1, value, type); //will return KErrAccessDenied
   1.615 +@endcode
   1.616 +
   1.617 +After the content of aAddress is altered, instruction cache invalidation is performed on the cache line that aAddress
   1.618 +belongs to. Therefore, the device driver doesn't have to call Cache::IMB_Range().
   1.619 +
   1.620 +If a code segment (which a valid breakpoint belongs to) is removed from the given process, the breakpoint will be
   1.621 +automatically removed. This occures just before EEventRemoveCodeSeg event is issued with DProcess* matching
   1.622 +the breakpoint's process. This also applies to the terminating/killed process, as all breakpoints belonging to it will be removed too.
   1.623 +
   1.624 +@param aThread 	The thread in who's address space the breakpoint is to be written.
   1.625 +@param aAddress The linear address of the breakpoint. Must be a multiple of aSize.
   1.626 +@param aSize 	The size, in bytes, of the breakpoint. Must be 1,2 or 4.
   1.627 +@param aValue 	The value to be stored at aAddress. This value is trucated to the
   1.628 +     			number of bits relevent to aSize.
   1.629 +@param aType 	The breakpoint type required. This is a bitmask of values from enum TType.
   1.630 +     			If this specifies more than one type, then the type with least scope
   1.631 +     			(i.e. EBreakpointLocal) is used when this is supported.
   1.632 +
   1.633 + @return KErrNoMemory,      if no resources are available.
   1.634 +   		 KErrAlreadyExists, if a breakpoint with the same address, size and the same owning process already exists in the pool.
   1.635 +   		 KErrAccessDenied, 	if an existing breakpoint of a different size and the same owning process overlaps the specified breakpoint.
   1.636 +   		 KErrNotSupported,  if none of the breakpoints types specified are supported or if Kernel is not built with __DEBUGGER_SUPPORT__ option
   1.637 +   		 Otherwise,         a positive value from enum TType which represents the type of breakpoint written.
   1.638 +
   1.639 + @panic CodeModifier 0 if called before InitialiseCodeModifier().
   1.640 + @panic CodeModifier 1 if aSize value or aAdress alignement is invalid.
   1.641 +
   1.642 + @pre   No fast mutex can be held.
   1.643 + @pre   Kernel must be unlocked.
   1.644 + @pre	Call in a thread context.
   1.645 + @pre	Interrupts must be enabled.
   1.646 + */
   1.647 +EXPORT_C TInt DebugSupport::ModifyCode(DThread* aThread, TLinAddr aAddress, TInt aSize, TUint aValue, TUint aType)
   1.648 +	{
   1.649 +	CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::ModifyCode");
   1.650 +	switch(aSize) //Chack aSize and aValue
   1.651 +	{
   1.652 +	case CodeModifier::EByte:
   1.653 +		break;
   1.654 +	case CodeModifier::EHalfword:
   1.655 +		if ((TInt)aAddress & 1)
   1.656 +			CodeModifier::Fault(CodeModifier::EPanicInvalidSizeOrAlignment);
   1.657 +		break;
   1.658 +	case CodeModifier::EWord:	
   1.659 +		if ((TInt)aAddress & 3)
   1.660 +			CodeModifier::Fault(CodeModifier::EPanicInvalidSizeOrAlignment);
   1.661 +		break;
   1.662 +	default:
   1.663 +		CodeModifier::Fault(CodeModifier::EPanicInvalidSizeOrAlignment);
   1.664 +	}
   1.665 +
   1.666 +	if (aType != DebugSupport::EBreakpointGlobal)//Check breakpoint type
   1.667 +		return KErrNotSupported;
   1.668 +	
   1.669 +	NKern::ThreadEnterCS(); 
   1.670 +	Kern::MutexWait(CodeModifier::Mutex());
   1.671 +	
   1.672 +	if (!TheCodeModifier)
   1.673 +		{
   1.674 +		Kern::MutexSignal(CodeModifier::Mutex());
   1.675 +		NKern::ThreadLeaveCS(); 
   1.676 +		CodeModifier::Fault(CodeModifier::EPanicNotInitialised);	
   1.677 +		}
   1.678 +	TInt r = TheCodeModifier->Modify(aThread, aAddress, aSize, aValue);
   1.679 +
   1.680 +	Kern::MutexSignal(CodeModifier::Mutex());
   1.681 +	NKern::ThreadLeaveCS(); 
   1.682 +
   1.683 +	if (r)
   1.684 +		return r;
   1.685 +	return EBreakpointGlobal;
   1.686 +	}
   1.687 +
   1.688 + /**
   1.689 + Restore a previousely written breakpoint.
   1.690 + I.e. restore the value at location aAddress in the address space of aProcess.
   1.691 +
   1.692 + After the content of aAddress is altered, instruction cache invalidation is performed on the cache line
   1.693 + that aAddress belongs to. Therefore, the device driver doesn't have to call Cache::IMB_Range().
   1.694 +
   1.695 + If the address resides in shadowed memory, the memory page will be un-shadowed if this is the last breakpoint
   1.696 + in the page. However, if the page had been already shadowed before the first breakpoint in the page was applied,
   1.697 + the page will remain shadowed.
   1.698 +
   1.699 + @param aProcess The process in who's address space aAddress lies.
   1.700 + @param aAddress The linear address of an existing breakpoint.
   1.701 +
   1.702 + @return KErrNotFound,		if the breakpoint hadn't been previously written. It is also returned if the breakpoint
   1.703 +                        	was previously removed from the list because the code segment (which the breakpoint belongs to) was
   1.704 +                        	unloaded/removed from the process associated with the breakpoint.
   1.705 +   		 KErrNotSupported, 	if Kernel is not built with __DEBUGGER_SUPPORT__ option
   1.706 +    	 KErrNone,			on success.
   1.707 +
   1.708 + @panic CodeModifier 0 if called before InitialiseCodeModifier().
   1.709 +
   1.710 + @pre   No fast mutex can be held.
   1.711 + @pre   Kernel must be unlocked.
   1.712 + @pre	Call in a thread context.
   1.713 + @pre	Interrupts must be enabled.
   1.714 + */
   1.715 +EXPORT_C TInt DebugSupport::RestoreCode(DThread* aThread, TLinAddr aAddress)
   1.716 +	{
   1.717 +	CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::RestoreCode");
   1.718 +	NKern::ThreadEnterCS(); 
   1.719 +	Kern::MutexWait(CodeModifier::Mutex());
   1.720 +
   1.721 +	if (!TheCodeModifier)
   1.722 +		{
   1.723 +		Kern::MutexSignal(CodeModifier::Mutex());
   1.724 +		NKern::ThreadLeaveCS(); 
   1.725 +		CodeModifier::Fault(CodeModifier::EPanicNotInitialised);
   1.726 +		}
   1.727 +	TInt r = TheCodeModifier->Restore(aThread, aAddress);
   1.728 +
   1.729 +	Kern::MutexSignal(CodeModifier::Mutex());
   1.730 +	NKern::ThreadLeaveCS(); 
   1.731 +	return r;
   1.732 +	}
   1.733 +
   1.734 + /**
   1.735 + Terminates a specified process on behalf of a debugger.
   1.736 +
   1.737 + @param aProcess The process in who's address space aAddress lies.
   1.738 + @param aReason The reason code to supply when terminating a process
   1.739 +
   1.740 + @return N/A.
   1.741 +
   1.742 + @pre   No fast mutex can be held.
   1.743 + @pre   Kernel must be unlocked.
   1.744 + @pre	Call in a thread context.
   1.745 + @pre	Interrupts must be enabled.
   1.746 + */
   1.747 +EXPORT_C void DebugSupport::TerminateProcess(DProcess* aProcess, const TInt aReason)
   1.748 +	{
   1.749 +	CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::TerminateProcess");
   1.750 +	NKern::ThreadEnterCS(); 
   1.751 +	aProcess->Die(EExitTerminate,aReason,KNullDesC);
   1.752 +	NKern::ThreadLeaveCS(); 
   1.753 +	return;
   1.754 +	}
   1.755 +
   1.756 +/**
   1.757 +Creates CodeModifier.
   1.758 +@param aMaxBreakpoints The number of breakpoints to be allocated.
   1.759 +@return KErrInUse 	 if code modifier already exists.
   1.760 +		KErrNoMemory if out of memory
   1.761 +		KErrNone 	 on success
   1.762 +@pre Calling thread must be in the critical section
   1.763 +@pre CodeSeg mutex held
   1.764 +*/
   1.765 +TInt CodeModifier::CreateAndInitialise(TInt aMaxBreakpoints)
   1.766 +	{
   1.767 +	if (TheCodeModifier)
   1.768 +		return KErrInUse;
   1.769 +
   1.770 +	CodeModifier* modifier = new CodeModifier;
   1.771 +	if (!modifier)
   1.772 +		return KErrNoMemory;
   1.773 +	
   1.774 +	modifier->iBreakpoints = new TBreakpoint[aMaxBreakpoints];
   1.775 +	if (!modifier->iBreakpoints)
   1.776 +		{
   1.777 +		delete modifier;	
   1.778 +		return KErrNoMemory;
   1.779 +		};
   1.780 +		
   1.781 +	modifier->iPages = new TPageInfo[aMaxBreakpoints];
   1.782 +	if (!modifier->iPages)
   1.783 +		{
   1.784 +		delete[] modifier->iBreakpoints;
   1.785 +		delete modifier;	
   1.786 +		return KErrNoMemory;
   1.787 +		}
   1.788 +
   1.789 +	modifier->iPoolSize = aMaxBreakpoints;
   1.790 +	modifier->iPageSize = Kern::RoundToPageSize(1);
   1.791 +	modifier->iPageMask = ~(modifier->iPageSize-1);
   1.792 +
   1.793 +	TheCodeModifier = modifier;
   1.794 +	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::CreateAndInitialise() Size:%d created", aMaxBreakpoints));
   1.795 +	return KErrNone;	
   1.796 +	}
   1.797 +
   1.798 +/**
   1.799 +Sets breakpoint.
   1.800 +@pre Calling thread must be in the critical section
   1.801 +@pre CodeSeg mutex held
   1.802 +*/
   1.803 +TInt CodeModifier::Modify(DThread* aThread, TLinAddr aAddress, TInt aSize, TUint aValue)
   1.804 +	{
   1.805 +	TInt r;
   1.806 +	TUint oldValue;
   1.807 +	TBool overlap;
   1.808 +	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Modify() T:%x Addr:%x, Size:%d Val:%x", aThread, aAddress, aSize, aValue));
   1.809 +	
   1.810 +	TBreakpoint* brk =FindBreakpoint(aThread, aAddress,aSize,overlap);
   1.811 +	if (overlap)
   1.812 +		return KErrAccessDenied;
   1.813 +	if (brk)
   1.814 +		return KErrAlreadyExists;
   1.815 +	
   1.816 +	if(NULL==(brk = FindEmptyBrk()))
   1.817 +		return KErrNoMemory;
   1.818 +	
   1.819 +	//Find the page (if exists). Shadow the page if necessery.
   1.820 +	TInt pageIndex = -1;
   1.821 +
   1.822 +#ifndef __DEMAND_PAGING__ 
   1.823 +	if (IsRom(aAddress))  // If no demand paging, only need to do this if the address is in rom
   1.824 +#endif
   1.825 +		{
   1.826 +		pageIndex = FindPageInfo(aAddress);
   1.827 +		if (pageIndex < 0)
   1.828 +			{
   1.829 +			pageIndex = FindEmptyPageInfo();
   1.830 +			if (pageIndex < 0)
   1.831 +				return KErrNoMemory;
   1.832 +			TPageInfo& page = iPages[pageIndex];
   1.833 +			memclr(&page, sizeof(page));
   1.834 +			page.iAddress = aAddress & iPageMask;
   1.835 +			
   1.836 +			if (IsRom(aAddress))
   1.837 +				{
   1.838 +				__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Modify() - Shadowing Page"));
   1.839 +				r = Epoc::AllocShadowPage(aAddress & iPageMask);
   1.840 +				if (r==KErrAlreadyExists)
   1.841 +					page.iWasShadowed = ETrue;
   1.842 +				else if (r!=KErrNone)
   1.843 +					return r;
   1.844 +				}
   1.845 +#ifdef __DEMAND_PAGING__
   1.846 +			else
   1.847 +				{
   1.848 +				DDemandPagingLock* lock = new DDemandPagingLock;
   1.849 +				if (lock == NULL)
   1.850 +					return KErrNoMemory;
   1.851 +				r = lock->Alloc(iPageSize);
   1.852 +				if (r != KErrNone)
   1.853 +					{
   1.854 +					delete lock;
   1.855 +					return r;
   1.856 +					}
   1.857 +				lock->Lock(aThread, aAddress & iPageMask, iPageSize);
   1.858 +				page.iPagingLock = lock;
   1.859 +				}
   1.860 +#endif
   1.861 +			}
   1.862 +		iPages[pageIndex].iCounter++;
   1.863 +		}
   1.864 +
   1.865 +	r = SafeWriteCode(aThread->iOwningProcess, aAddress, aSize, aValue, &oldValue);
   1.866 +	if (r != KErrNone)
   1.867 +		{//aAddress is invalid
   1.868 +		if (pageIndex >= 0)
   1.869 +			RestorePage(pageIndex);
   1.870 +		return r;
   1.871 +		}
   1.872 +
   1.873 +	//All done. Update the internal structures.
   1.874 +	brk->iAddress = aAddress;
   1.875 +	brk->iProcessId = (aThread->iOwningProcess)->iId;
   1.876 +	brk->iOldValue = oldValue;
   1.877 +	brk->iSize = aSize;
   1.878 +	brk->iPageIndex = pageIndex;
   1.879 +	return KErrNone;
   1.880 +	}
   1.881 +
   1.882 +/**
   1.883 +@pre Calling thread must be in the critical section
   1.884 +@pre CodeSeg mutex held
   1.885 +*/
   1.886 +TInt CodeModifier::Restore(DThread* aThread, TLinAddr aAddress)
   1.887 +	{
   1.888 +	TUint oldValue;
   1.889 +	TBool overlaps;
   1.890 +	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Restore() T:%x Addr:%x", aThread, aAddress));
   1.891 +	TInt r = KErrNone;;
   1.892 +	TBreakpoint* br = FindBreakpoint(aThread, aAddress, 0, overlaps);
   1.893 +	if (br==NULL)
   1.894 +		return KErrNotFound;
   1.895 +	
   1.896 +	r = SafeWriteCode(aThread->iOwningProcess, br->iAddress, br->iSize, br->iOldValue, &oldValue);
   1.897 +	if (r)
   1.898 +		r=KErrNotFound;
   1.899 +	
   1.900 +	br->iSize = (TUint)EEmpty;
   1.901 +		
   1.902 +	TInt pageIndex = br->iPageIndex;
   1.903 +	if (pageIndex>=0)
   1.904 +		RestorePage(pageIndex);
   1.905 +	
   1.906 +	return r;
   1.907 +	}
   1.908 +
   1.909 +/*
   1.910 +@pre Calling thread must be in the critical section
   1.911 +@pre CodeSeg mutex held
   1.912 +*/
   1.913 +void CodeModifier::Close()
   1.914 +	{
   1.915 +	TUint oldValue;
   1.916 +	TInt brkIndex;
   1.917 +
   1.918 +	TheCodeModifier = NULL;
   1.919 +	
   1.920 +	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Close()"));
   1.921 +
   1.922 +	for (brkIndex=0; brkIndex<iPoolSize; brkIndex++)	
   1.923 +		{
   1.924 +		if (iBreakpoints[brkIndex].iSize ==(TUint16)EEmpty)
   1.925 +			continue;
   1.926 +		DProcess* process = Process(iBreakpoints[brkIndex].iProcessId);
   1.927 +		
   1.928 +		__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Close() - Removing Brk:%x",iBreakpoints[brkIndex].iAddress));
   1.929 +		
   1.930 +		//Write back the original value
   1.931 +		if (process)
   1.932 +			SafeWriteCode(process, iBreakpoints[brkIndex].iAddress, iBreakpoints[brkIndex].iSize, iBreakpoints[brkIndex].iOldValue, &oldValue);
   1.933 +			
   1.934 +		iBreakpoints[brkIndex].iSize = (TUint)EEmpty;
   1.935 +		TInt pageIndex = iBreakpoints[brkIndex].iPageIndex;
   1.936 +		if (pageIndex>=0)
   1.937 +			RestorePage(pageIndex);
   1.938 +		}
   1.939 +
   1.940 +	delete this;
   1.941 +	}
   1.942 +
   1.943 +/*
   1.944 +Destructor. The object is deleted asynchroniously from Kernel Supervisor thread.
   1.945 +*/
   1.946 +CodeModifier::~CodeModifier()
   1.947 +	{
   1.948 +	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::~CodeModifier()"));
   1.949 +	delete[] iPages;
   1.950 +	delete[] iBreakpoints;
   1.951 +	}
   1.952 +
   1.953 +/**
   1.954 +This is executed when a code segment is about to be unmapped from the process. It corresponds to EEventRemoveCodeSeg Kernel event.
   1.955 +Removes breakpoints that belong to the threads from aProcess. Also, removes shadow pages if there is no breakpoint left in them.
   1.956 +
   1.957 +@param aCodeSeg Code Segment that is removed from aProcess.
   1.958 +@param aProcess Process from whom the code segment is removed.
   1.959 +
   1.960 +@pre Calling thread must be in the critical section
   1.961 +@pre CodeSeg mutex held
   1.962 +*/
   1.963 +void CodeModifier::CodeSegRemoved(DCodeSeg* aCodeSeg, DProcess* aProcess)
   1.964 +	{
   1.965 +	if (!TheCodeModifier)
   1.966 +		return;
   1.967 +	TheCodeModifier->DoCodeSegRemoved(aCodeSeg, aProcess);
   1.968 +	}
   1.969 +
   1.970 +void CodeModifier::DoCodeSegRemoved(DCodeSeg* aCodeSeg, DProcess* aProcess)
   1.971 +	{
   1.972 +	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::CodeSegRemoved()"));
   1.973 +	
   1.974 +	TUint oldValue;
   1.975 +	TUint minAddr = aCodeSeg->iRunAddress;
   1.976 +	TUint maxAddr = aCodeSeg->iRunAddress + aCodeSeg->iSize;
   1.977 +
   1.978 +	TBreakpoint* bp = iBreakpoints;
   1.979 +	TBreakpoint* bpEnd = bp+iPoolSize; //points right behind iBreakpoints
   1.980 +	for (; bp<bpEnd; ++bp)
   1.981 +		{
   1.982 +		if (bp->iSize == (TUint)EEmpty) continue;
   1.983 +
   1.984 +		if (aProcess->iId == bp->iProcessId)
   1.985 +			{
   1.986 +			if (bp->iAddress >= minAddr && bp->iAddress <  maxAddr)   
   1.987 +				{
   1.988 +				__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::CodeSegRemoved()- a breakpoint"));
   1.989 +
   1.990 +				//Remove breakpoint. Don't examine error code as there is nobody to report to.
   1.991 +				SafeWriteCode(aProcess, bp->iAddress, bp->iSize, bp->iOldValue, &oldValue);
   1.992 +
   1.993 +				//Mark the slot as empty and decrease the counter of the shadow page slot (if there is any associated)
   1.994 +				bp->iSize = (TUint)EEmpty;
   1.995 +				if (bp->iPageIndex >= 0)
   1.996 +					RestorePage(bp->iPageIndex);
   1.997 +				}
   1.998 +			}
   1.999 +		}
  1.1000 +
  1.1001 +	}
  1.1002 +
  1.1003 +/*
  1.1004 +Finds DProcess that matches to processId
  1.1005 +@param aProcessId ProcessId
  1.1006 +@return Pointer to matching DProcess or NULL
  1.1007 +*/
  1.1008 +DProcess* CodeModifier::Process(TUint aProcessId)
  1.1009 +	{
  1.1010 +	TInt i;
  1.1011 +	DProcess* process = NULL;
  1.1012 +	DObjectCon* processCon = Kern::Containers()[EProcess];
  1.1013 +	processCon->Wait();
  1.1014 +
  1.1015 +	for (i=0;i<processCon->Count();i++)
  1.1016 +		{
  1.1017 +		DProcess* pr = (DProcess*)(*processCon)[i];
  1.1018 +		if (pr->iId == aProcessId)
  1.1019 +			{
  1.1020 +			process=(DProcess*)pr;
  1.1021 +			break;
  1.1022 +			}
  1.1023 +		}
  1.1024 +
  1.1025 +	processCon->Signal();
  1.1026 +	return process;
  1.1027 +	}
  1.1028 +
  1.1029 +/*
  1.1030 +Returns eTrue if given virtual address belongs to rom image, EFalse otherwise
  1.1031 +*/
  1.1032 +TBool CodeModifier::IsRom(TLinAddr aAddress)
  1.1033 +	{
  1.1034 +	TRomHeader romHeader = Epoc::RomHeader();
  1.1035 +	if ( (aAddress >= romHeader.iRomBase ) && (aAddress < (romHeader.iRomBase + romHeader.iUncompressedSize)) )
  1.1036 +		return ETrue;
  1.1037 +	return EFalse;
  1.1038 +	}
  1.1039 +
  1.1040 +/*
  1.1041 +Finds the first available(empty) breakpoint slot.
  1.1042 +@return The pointer of the empty slot or NULL if all occupied.
  1.1043 +*/
  1.1044 +CodeModifier::TBreakpoint* CodeModifier::FindEmptyBrk()
  1.1045 +	{
  1.1046 +	TBreakpoint* bp = TheCodeModifier->iBreakpoints;
  1.1047 +	TBreakpoint* bpEnd = bp+TheCodeModifier->iPoolSize; //points right behind iBreakpoints
  1.1048 +	for (; bp<bpEnd; ++bp)
  1.1049 +		if (bp->iSize == (TInt16)EEmpty)
  1.1050 +			return bp;
  1.1051 +		
  1.1052 +	return NULL;	
  1.1053 +	}
  1.1054 +	
  1.1055 +/*
  1.1056 +Finds matching breakpoint.
  1.1057 +
  1.1058 +@param aThread 		The thread who's process owns the breakpoint
  1.1059 +@param aAddress 	Address of the breakpoint.
  1.1060 +@param aSize 		The size of the breakpoint. Value 0, 1,2 or 4 is assumed. If 0, it doesn't check the size nor overlaps(used to remove breakpoint).
  1.1061 +@param aOverlap 	On return, it is true if a breakpoint is found that doesn't match the size but overlaps with
  1.1062 +					the specified breakpoint(i.e. address and process are the same but the size is different).
  1.1063 +
  1.1064 +@return - The pointer to the breakpoint slot that matches the entry (adress, size and the owning process)
  1.1065 +		- NULL - if could't find the matching breakpoint.
  1.1066 +*/
  1.1067 +CodeModifier::TBreakpoint* CodeModifier::FindBreakpoint(DThread* aThread, TLinAddr aAddress, TInt aSize, TBool& aOverlap)
  1.1068 +	{
  1.1069 +	TInt bytes=0;
  1.1070 +	aOverlap = EFalse;
  1.1071 +	TUint processId = aThread->iOwningProcess->iId;//processId of the thread that owns aThread
  1.1072 +
  1.1073 +	if (aSize) //if size==0, we do not check overlaps.
  1.1074 +		bytes = ((1<<aSize)-1)<<(aAddress&3);	//bits[3-0] marks the bytes that are contained in the breakpoint:
  1.1075 +												//	address: ...00b size: 1 => bytes=0001b 
  1.1076 +												//	address: ...01b size: 1 => bytes=0010b 
  1.1077 +												//	address: ...10b size: 1 => bytes=0100b 
  1.1078 +												//	address: ...11b size: 1 => bytes=1000b 
  1.1079 +												//	address: ...00b size: 2 => bytes=0011b 
  1.1080 +												//	address: ...10b size: 2 => bytes=1100b 
  1.1081 +												//	address: ...00b size: 4 => bytes=1111b 
  1.1082 +
  1.1083 +	TBreakpoint* bp = TheCodeModifier->iBreakpoints;
  1.1084 +	TBreakpoint* bpEnd = bp+TheCodeModifier->iPoolSize; //points right behind iBreakpoints
  1.1085 +	for (; bp<bpEnd; ++bp)
  1.1086 +		{
  1.1087 +		if (bp->iSize == (TInt16)EEmpty || bp->iProcessId != processId)
  1.1088 +			continue;//Either empty or not matchng process. 
  1.1089 +
  1.1090 +		if (!aSize)
  1.1091 +			{ //Do not check the size. If the address does not match, do not check for overlap.
  1.1092 +			if (bp->iAddress == aAddress)
  1.1093 +				return bp;
  1.1094 +			else
  1.1095 +				continue;
  1.1096 +			}
  1.1097 +			
  1.1098 +		if (bp->iAddress == aAddress && bp->iSize == aSize)
  1.1099 +			return bp;//If we find a matching breakpoint, there cannot be another one that overlaps
  1.1100 +		
  1.1101 +		//Check if bp breakpoint overlaps with the specified one.
  1.1102 +		if ((bp->iAddress^aAddress)>>2)
  1.1103 +			continue;//Not in the same word
  1.1104 +			
  1.1105 +		if (((1<<bp->iSize)-1)<<(bp->iAddress&3)&bytes)
  1.1106 +			{//Two brakpoints are within the same word with some overlaping bytes.
  1.1107 +			aOverlap = ETrue;
  1.1108 +			return NULL; //If we find an overlaping breakpoint, there cannot be another one that matches exactly.
  1.1109 +			}
  1.1110 +		}
  1.1111 +	return NULL;	
  1.1112 +	}
  1.1113 +
  1.1114 +/*
  1.1115 +Finds the first available(empty) page info slot.
  1.1116 +@return The index of the slot or KErrNotFound if all occupied.
  1.1117 +*/
  1.1118 +TInt CodeModifier::FindEmptyPageInfo()
  1.1119 +	{
  1.1120 +	TInt i;
  1.1121 +	for (i=0; i<iPoolSize; i++)
  1.1122 +		if (!iPages[i].iCounter)
  1.1123 +			return i;
  1.1124 +	return KErrNotFound;
  1.1125 +	}
  1.1126 +
  1.1127 +/*
  1.1128 +Finds the page info structure that contains given virtual address
  1.1129 +@return The index of the page info slot or KErrNotFound.
  1.1130 +*/
  1.1131 +TInt CodeModifier::FindPageInfo(TLinAddr aAddress)
  1.1132 +	{
  1.1133 +	TInt i;
  1.1134 +	aAddress &= iPageMask; //round down to the page base address
  1.1135 +	for (i=0; i<iPoolSize; i++)
  1.1136 +		if(iPages[i].iCounter)
  1.1137 +			if (iPages[i].iAddress == aAddress)
  1.1138 +				return i;
  1.1139 +	return KErrNotFound;
  1.1140 +	}
  1.1141 +
  1.1142 +/**
  1.1143 +Decrement the count of breakpoints associated with this page, and restores page
  1.1144 +to its original state if there are none remaining.
  1.1145 +*/
  1.1146 +void CodeModifier::RestorePage(TInt aPageIndex)
  1.1147 +	{
  1.1148 +	TPageInfo& page = iPages[aPageIndex];
  1.1149 +	if(--page.iCounter==0)
  1.1150 +		{
  1.1151 +		if (!page.iWasShadowed)
  1.1152 +			{
  1.1153 +			__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Restore() - Freeing Shadow Page"));
  1.1154 +			Epoc::FreeShadowPage(page.iAddress);
  1.1155 +			}
  1.1156 +#ifdef __DEMAND_PAGING__
  1.1157 +		if (page.iPagingLock)
  1.1158 +			{
  1.1159 +			// Release lock and free resources
  1.1160 +			delete page.iPagingLock;
  1.1161 +			page.iPagingLock = NULL;
  1.1162 +			}
  1.1163 +#endif
  1.1164 +		}
  1.1165 +	}
  1.1166 +
  1.1167 +void CodeModifier::Fault(TPanic aPanic)
  1.1168 +	{
  1.1169 +	Kern::Fault("CodeModifier", aPanic);
  1.1170 +	}
  1.1171 +
  1.1172 +#else //__DEBUGGER_SUPPORT__
  1.1173 +EXPORT_C TInt DebugSupport::InitialiseCodeModifier(TUint& /*aCapabilities*/, TInt /*aMinBreakpoints*/)
  1.1174 +	{
  1.1175 +	return KErrNotSupported;	
  1.1176 +	}
  1.1177 +EXPORT_C void DebugSupport::CloseCodeModifier()
  1.1178 +	{
  1.1179 +	}
  1.1180 +EXPORT_C TInt DebugSupport::ModifyCode(DThread* /*aProcess*/, TLinAddr /*aAddress*/, TInt /*aSize*/, TUint /*aValue*/, TUint /*aType*/)
  1.1181 +	{
  1.1182 +	return KErrNotSupported;	
  1.1183 +	}
  1.1184 +EXPORT_C TInt DebugSupport::RestoreCode(DThread* /*aProcess*/, TLinAddr /*aAddress*/)
  1.1185 +	{
  1.1186 +	return KErrNotSupported;	
  1.1187 +	}
  1.1188 +EXPORT_C void DebugSupport::TerminateProcess(DProcess* /*aProcess*/, const TInt /*aReason*/)
  1.1189 +	{
  1.1190 +	}
  1.1191 +#endif
  1.1192 +