kernel/eka/memmodel/epoc/putils.cpp
changeset 0 a41df078684a
child 62 4a8fed1c0ef6
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\memmodel\epoc\putils.cpp
       
    15 // EPOC implementation of the ROM related parts of the system
       
    16 // 
       
    17 //
       
    18 
       
    19 #include "plat_priv.h"
       
    20 #include <e32uid.h>
       
    21 #include "execs.h"
       
    22 #include "cache_maintenance.h"
       
    23 
       
    24 _LIT(KKernelFullPathNameSysBin,"z:\\sys\\bin\\ekern.exe");
       
    25 
       
    26 #ifdef __MARM__
       
    27 #define	CHECK_ROM_ENTRY_POINT(a)	__ASSERT_ALWAYS( ((a).iFlags & KRomImageEptMask) == KRomImageEpt_Eka2, PP::Panic(PP::EUnsupportedOldBinary) )
       
    28 #else
       
    29 #define	CHECK_ROM_ENTRY_POINT(a)
       
    30 #endif
       
    31 
       
    32 void PP::Panic(TPlatPanic aPanic)
       
    33 	{
       
    34 	Kern::Fault("PLAT",aPanic);
       
    35 	}
       
    36  
       
    37 void PP::InitSuperPageFromRom(TLinAddr aRomHeader, TLinAddr aSuperPage)
       
    38 	{
       
    39 	RomHeaderAddress = aRomHeader;
       
    40 	SuperPageAddress = aSuperPage;
       
    41 
       
    42 	TInt j;
       
    43 	for (j = 0; j < KNumTraceMaskWords; j++)
       
    44 		TheSuperPage().iDebugMask[j] = TheRomHeader().iTraceMask[j];
       
    45 
       
    46 	for (j = 0; j < 8; j++)
       
    47 		TheSuperPage().iInitialBTraceFilter[j] = TheRomHeader().iInitialBTraceFilter[j];
       
    48 
       
    49 	Kern::SuperPage().iInitialBTraceBuffer = TheRomHeader().iInitialBTraceBuffer;
       
    50 	Kern::SuperPage().iInitialBTraceMode = TheRomHeader().iInitialBTraceMode;
       
    51 
       
    52 	TheSuperPage().SetKernelConfigFlags(TheRomHeader().iKernelConfigFlags);
       
    53 
       
    54 	memcpy(&TheSuperPage().iDisabledCapabilities, &TheRomHeader().iDisabledCapabilities, sizeof(TheRomHeader().iDisabledCapabilities));
       
    55 	}
       
    56 
       
    57 TInt P::DefaultInitialTime()
       
    58 	{
       
    59 //
       
    60 // Default implementation of the kernel hook for getting the initial system
       
    61 // time, can be overriden by variant.
       
    62 //
       
    63     TInt seconds;
       
    64 	if (K::ColdStart || A::SystemTimeInSecondsFrom2000(seconds)!=KErrNone)
       
    65 		return KErrCorrupt;
       
    66 	else
       
    67 		return seconds;
       
    68 	}
       
    69 
       
    70 TInt P::InitSystemTime()
       
    71 	{
       
    72 //
       
    73 //  Initialise system time
       
    74 //	Return the initial time in seconds from 00:00:00 01-01-2000
       
    75 //
       
    76 
       
    77 	// Reset the UTC offset (I assume this gets loaded from storage at some point after F32 loads)
       
    78 	TUint dummy;
       
    79 	K::SetSystemTimeAndOffset(0, 0, 0, dummy, ETimeSetOffset | ETimeSetNoTimeUpdate);
       
    80 
       
    81 	// Read the hardware clock value. If this is negative it means it couldnt be read.
       
    82     TInt seconds = K::InitialTimeHandler()();	
       
    83 
       
    84 	if (seconds >= 0)
       
    85 		{
       
    86 		K::SecureClockStatus |= ESecureClockPresent;
       
    87 		__KTRACE_OPT(KBOOT,Kern::Printf("Read initial system time"));
       
    88 		// now=Hardware RTC value
       
    89 		}
       
    90 	else 
       
    91 		{
       
    92 		__KTRACE_OPT(KBOOT,Kern::Printf("Could not read initial system time - using ROM timestamp to set system time"));
       
    93 		TTimeK rom_time=*(const TTimeK*)&TheRomHeader().iTime;
       
    94 		rom_time -= TTimeK(K::HomeTimeOffsetSeconds)*1000000;
       
    95 		TInt s;
       
    96 		TInt r=K::SecondsFrom2000(rom_time,s);
       
    97 		if (r!=KErrNone)
       
    98 			PP::Panic(PP::EInitialSystemTimeInvalid);
       
    99 		seconds=s;
       
   100 
       
   101 		// write the ROM timestamp to the hardware RTC
       
   102 		A::SetSystemTimeInSecondsFrom2000(seconds);
       
   103 		}
       
   104 	return seconds;
       
   105 	}
       
   106 
       
   107 
       
   108 void FindRomRootDirectory()
       
   109 	{
       
   110 	TUint variant = TheSuperPage().iActiveVariant;
       
   111 	TUint cpu = (variant >> 16) & 0xff;
       
   112 	TUint asic = (variant >> 24);
       
   113 	PP::RomRootDirAddress=0;
       
   114 	TRomRootDirectoryList* pL=(TRomRootDirectoryList*)TheSuperPage().iRootDirList;
       
   115 	if (!pL)
       
   116 		pL=(TRomRootDirectoryList*)TheRomHeader().iRomRootDirectoryList;
       
   117 	TInt i;
       
   118 	for (i=0; i<pL->iNumRootDirs; i++)
       
   119 		{
       
   120 		if (THardwareVariant(pL->iRootDir[i].iHardwareVariant).IsCompatibleWith(cpu,asic,variant))
       
   121 			{
       
   122 			__KTRACE_OPT(KBOOT,Kern::Printf("Found ROM root dir index %d addr %08x",
       
   123 				i, pL->iRootDir[i].iAddressLin));
       
   124 			PP::RomRootDirAddress=pL->iRootDir[i].iAddressLin;
       
   125 			return;
       
   126 			}
       
   127 		}
       
   128 	}
       
   129 
       
   130 typedef TInt (*TInitVarExtFn)(const TRomImageHeader&);
       
   131 
       
   132 #ifdef KBOOT
       
   133 void DumpRomFileInfo(const TRomEntry& aRomEntry)
       
   134 	{
       
   135 	TBuf8<128> name;
       
   136 	TInt i;
       
   137 	for (i=0; i<aRomEntry.iNameLength; ++i)
       
   138 		{
       
   139 		name.Append(TChar(aRomEntry.iName[i<<1]&0xff));
       
   140 		}
       
   141 	const TRomImageHeader& img = *(const TRomImageHeader*)aRomEntry.iAddressLin;
       
   142 	__KTRACE_OPT(KBOOT,Kern::Printf("File %S[%08x]", &name, TUint(img.iHardwareVariant) ));
       
   143 	}
       
   144 #endif
       
   145 
       
   146 void InitVarExt(TBool aVar, TInitVarExtFn aFn)
       
   147 	{
       
   148 	__KTRACE_OPT(KBOOT,Kern::Printf("InitVarExt var=%d, fn=%08x", aVar, aFn));
       
   149 	TUint variant = TheSuperPage().iActiveVariant;
       
   150 	TUint cpu = (variant >> 16) & 0xff;
       
   151 	TUint asic = (variant >> 24);
       
   152 	__KTRACE_OPT(KBOOT,Kern::Printf("cpu=%d, asic=%d, variant=%x", cpu, asic, variant));
       
   153 	const TRomHeader& rh = TheRomHeader();
       
   154 	TRomEntry* pE = aVar ? (TRomEntry*)rh.iVariantFile : (TRomEntry*)rh.iExtensionFile;
       
   155 	while(pE)
       
   156 		{
       
   157 #ifdef KBOOT
       
   158 		DumpRomFileInfo(*pE);
       
   159 #endif
       
   160 		const TRomImageHeader& img = *(const TRomImageHeader*)pE->iAddressLin;
       
   161 		if (THardwareVariant(img.iHardwareVariant).IsCompatibleWith(cpu,asic,variant))
       
   162 			{
       
   163 			__KTRACE_OPT(KBOOT,Kern::Printf("Processing"));
       
   164 			(*aFn)(img);
       
   165 			if (aVar)
       
   166 				{
       
   167 				__KTRACE_OPT(KBOOT,Kern::Printf("Variant installed"));
       
   168 				return;
       
   169 				}
       
   170 			}
       
   171 		pE=(TRomEntry*)img.iNextExtension;
       
   172 		}
       
   173 	if (aVar)
       
   174 		Kern::Fault("NoVariant",0);
       
   175 	}
       
   176 
       
   177 TInt InitData(const TRomImageHeader& a)
       
   178 	{
       
   179 	__KTRACE_OPT(KBOOT,Kern::Printf("InitData %08x+%x->%08x", a.iDataAddress, a.iDataSize, a.iDataBssLinearBase));
       
   180 	CHECK_ROM_ENTRY_POINT(a);
       
   181 	if (a.iDataSize)
       
   182 		memcpy((TAny*)a.iDataBssLinearBase,(TAny*)a.iDataAddress,a.iDataSize);
       
   183 	TLibraryEntry ep = (TLibraryEntry)a.iEntryPoint;
       
   184 	__KTRACE_OPT(KBOOT,Kern::Printf("Calling entrypoint %08x(VariantInit0)", ep));
       
   185 	TInt r = ep(KModuleEntryReasonVariantInit0);
       
   186 	__KTRACE_OPT(KBOOT,Kern::Printf("Entrypoint returned %d",r));
       
   187 	if(!(++K::ExtensionCount&0x7fffffff))
       
   188 		K::Fault(K::ETooManyExtensions);
       
   189 	return r;
       
   190 	}
       
   191 
       
   192 TInt InitVariant(const TRomImageHeader& a)
       
   193 	{
       
   194 	TInt r = InitData(a);
       
   195 	__KTRACE_OPT(KBOOT,Kern::Printf("InitVariant: entry point returns %08x", r));
       
   196 	if (r<0)
       
   197 		Kern::Fault("VariantEntry",r);
       
   198 
       
   199 	// Initialise and create the variant object
       
   200 	r = A::CreateVariant(&a, r);
       
   201 	if (r<0)
       
   202 		Kern::Fault("VariantInit",r);
       
   203 	return r;
       
   204 	}
       
   205 
       
   206 void P::CreateVariant()
       
   207 	{
       
   208 	__KTRACE_OPT(KBOOT,Kern::Printf("CreateVariant"));
       
   209 	BTrace::Init0();
       
   210 	InitVarExt(EFalse, &InitData);		// initialise .data for all extensions
       
   211 	InitVarExt(ETrue, &InitVariant);	// find variant and initialise it
       
   212 	FindRomRootDirectory();
       
   213 	}
       
   214 
       
   215 struct SExtInit1EntryPoint
       
   216 	{
       
   217 	inline SExtInit1EntryPoint() : iEntryPoint(0),iReturnCode(0)
       
   218 		{}
       
   219 	inline SExtInit1EntryPoint(TLibraryEntry aEp, TInt aVal) : iEntryPoint(aEp),iReturnCode(aVal)
       
   220 		{}
       
   221 	TLibraryEntry iEntryPoint;
       
   222 	TInt iReturnCode;		// bits 7-0 used for extension startup priority order
       
   223 	};
       
   224 
       
   225 // This ordering function when used in conjunction with RArray<>::InsertInOrderAllowRepeats
       
   226 // orders the array of extensions as follow:
       
   227 //		highest priority -> lowest priority
       
   228 //		if same priority -> first in, lowest index
       
   229 //
       
   230 TInt priorityOrder(const SExtInit1EntryPoint& aMatch, const SExtInit1EntryPoint& aEntry)
       
   231 	{
       
   232 	TUint8 l=(TUint8)aMatch.iReturnCode;
       
   233 	TUint8 r=(TUint8)aEntry.iReturnCode;
       
   234 	if(l>r)
       
   235 		return -1;
       
   236 	else if(l<r)
       
   237 		return 1;
       
   238 	else
       
   239 		return 0;
       
   240 	}
       
   241 
       
   242 TInt InitExt0(const TRomImageHeader& a)
       
   243 	{
       
   244 	CHECK_ROM_ENTRY_POINT(a);
       
   245 	TLibraryEntry ep = (TLibraryEntry)a.iEntryPoint;
       
   246 	__KTRACE_OPT(KBOOT,Kern::Printf("InitExt0 %08x ep=%08x", &a, ep));
       
   247 	TInt r = (*ep)(KModuleEntryReasonExtensionInit0);
       
   248 	if (r<KErrNone)
       
   249 		{
       
   250 		__KTRACE_OPT(KBOOT,Kern::Printf("Already started"));
       
   251 		return r;
       
   252 		}
       
   253 	SExtInit1EntryPoint s(ep,r);
       
   254 	TInt count=K::ExtensionArray->Count();
       
   255 	if(count==K::ExtensionCount)					// this function is only called if extensions exist, i.e. K::ExtensionCount>0
       
   256 		K::Fault(K::EExtensionArrayOverflowed);		// the first insertion will allocate space for K::ExtensionCount entries and that is the maximum number of entries allowed
       
   257 	TLinearOrder<SExtInit1EntryPoint> PriorityOrder(priorityOrder);
       
   258 	if(K::ExtensionArray->InsertInOrderAllowRepeats(s,PriorityOrder)!=KErrNone)
       
   259 		K::Fault(K::EInsertExtensionFailed);
       
   260 	__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));
       
   261 	return KErrNone;
       
   262 	}
       
   263 
       
   264 void P::StartExtensions()
       
   265 	{
       
   266 	// start extensions...
       
   267 	__KTRACE_OPT(KBOOT, Kern::Printf("Starting kernel extensions..."));
       
   268 
       
   269 	K::ExtensionArray = new RArray<SExtInit1EntryPoint>(--K::ExtensionCount);	// ordered array of extensions excluding Variant
       
   270 	if(!K::ExtensionArray)
       
   271 		K::Fault(K::EExtensionArrayAllocationFailed);
       
   272 	__KTRACE_OPT(KBOOT, Kern::Printf("Entry point array at %08x, max size %d",K::ExtensionArray,K::ExtensionCount));
       
   273 
       
   274 	InitVarExt(EFalse, &InitExt0);		// populates the array of entry points in priority order
       
   275 
       
   276 	for(TInt i=0; i<K::ExtensionArray->Count(); i++)	// call entry points in combined priority and temporal orders
       
   277 		{
       
   278 		TLibraryEntry ep = (*K::ExtensionArray)[i].iEntryPoint;
       
   279 		__KTRACE_OPT(KBOOT,Kern::Printf("InitExt1: calling entrypoint %08x", ep));
       
   280 		TInt r = ep(KModuleEntryReasonExtensionInit1);
       
   281 		__KTRACE_OPT(KBOOT,Kern::Printf("Entrypoint returned %d", r));
       
   282 		if (r!=KErrNone)
       
   283 			K::Fault(K::EStartExtensionsFailed);
       
   284 		}
       
   285 	// preserve array of extensions, it contains the returned codes from ExtInit0 which may be useful for future use
       
   286 	//delete K::ExtensionArray;
       
   287 	//K::ExtensionArray=NULL;
       
   288 	}
       
   289 
       
   290 void P::KernelInfo(TProcessCreateInfo& aInfo, TAny*& aStack, TAny*& aHeap)
       
   291 //
       
   292 // Provide the initial supervisor data information from the ROM
       
   293 //
       
   294 	{
       
   295 	aInfo.iFileName=KKernelFullPathNameSysBin;
       
   296 	aInfo.iRootNameOffset=11;
       
   297 	aInfo.iRootNameLength=9;
       
   298 	aInfo.iExtOffset = 16;
       
   299 
       
   300 	aInfo.iAttr=ECodeSegAttKernel|ECodeSegAttFixed;
       
   301 
       
   302 	const TRomHeader& romHdr=TheRomHeader();
       
   303 	const TRomEntry* primaryEntry=(const TRomEntry*)TheSuperPage().iPrimaryEntry;
       
   304 	const TRomImageHeader* primaryImageHeader=(const TRomImageHeader*)primaryEntry->iAddressLin;
       
   305 	Epoc::RomProcessInfo(aInfo, *primaryImageHeader);
       
   306 	aStack = (TAny*)(romHdr.iKernDataAddress + Kern::RoundToPageSize(romHdr.iTotalSvDataSize));
       
   307 	aHeap = (TAny*)(TLinAddr(aStack) + Kern::RoundToPageSize(aInfo.iStackSize));
       
   308 	aInfo.iTotalDataSize=romHdr.iTotalSvDataSize;
       
   309 	aInfo.iHeapSizeMin=TheSuperPage().iInitialHeapSize;
       
   310 	}
       
   311 
       
   312 EXPORT_C void Epoc::RomProcessInfo(TProcessCreateInfo& aInfo, const TRomImageHeader& a)
       
   313 	{
       
   314 	CHECK_PAGING_SAFE;
       
   315 	aInfo.iUids=*(const TUidType*)&a.iUid1;
       
   316 	aInfo.iCodeSize=a.iCodeSize;
       
   317 	aInfo.iTextSize=a.iTextSize;
       
   318 	aInfo.iDataSize=a.iDataSize;
       
   319 	aInfo.iBssSize=a.iBssSize;
       
   320 	aInfo.iTotalDataSize=a.iTotalDataSize;
       
   321 	aInfo.iEntryPtVeneer=a.iEntryPoint;
       
   322 	aInfo.iFileEntryPoint=a.iEntryPoint;
       
   323 	aInfo.iDepCount=a.iDllRefTable ? a.iDllRefTable->iNumberOfEntries : 0;
       
   324 	aInfo.iExportDir=a.iExportDir;
       
   325 	aInfo.iExportDirCount=a.iExportDirCount;
       
   326 	aInfo.iCodeLoadAddress=(TLinAddr)&a;//a.iCodeAddress;
       
   327 	aInfo.iCodeRunAddress=a.iCodeAddress;
       
   328 	aInfo.iDataLoadAddress=a.iDataAddress;
       
   329 	aInfo.iDataRunAddress=a.iDataBssLinearBase;
       
   330 	aInfo.iExceptionDescriptor = a.iExceptionDescriptor;
       
   331 	aInfo.iHeapSizeMin=a.iHeapSizeMin;
       
   332 	aInfo.iHeapSizeMax=a.iHeapSizeMax;
       
   333 	aInfo.iStackSize=a.iStackSize;
       
   334 	aInfo.iPriority=a.iPriority;
       
   335 	aInfo.iHandle=NULL;
       
   336 	aInfo.iS = a.iS;
       
   337 	aInfo.iModuleVersion = a.iModuleVersion;
       
   338 	if (a.iFlags&KRomImageFlagsKernelMask)
       
   339 		aInfo.iAttr=ECodeSegAttKernel;
       
   340 	else
       
   341 		aInfo.iAttr=ECodeSegAttGlobal;
       
   342 	if (a.iFlags&KRomImageFlagFixedAddressExe)
       
   343 		aInfo.iAttr|=ECodeSegAttFixed;
       
   344 	aInfo.iAttr &= ~ECodeSegAttABIMask;
       
   345 	aInfo.iAttr |= (a.iFlags & KRomImageABIMask);
       
   346 	if(a.iFlags&KRomImageSMPSafe)
       
   347 		aInfo.iAttr |= ECodeSegAttSMPSafe;
       
   348 	aInfo.iClientHandle = KCurrentThreadHandle;
       
   349 	aInfo.iClientProcessHandle = 0;
       
   350 	aInfo.iFinalHandle = 0;
       
   351 	aInfo.iOwnerType = EOwnerProcess;
       
   352 	aInfo.iFlags &= ~(TProcessCreateInfo::EDataPagingMask);
       
   353 	if(a.iFlags&KRomImageFlagDataPaged)
       
   354 		aInfo.iFlags |= TProcessCreateInfo::EDataPaged;
       
   355 	if(a.iFlags&KRomImageFlagDataUnpaged)
       
   356 		aInfo.iFlags |= TProcessCreateInfo::EDataUnpaged;
       
   357 	CHECK_ROM_ENTRY_POINT(a);
       
   358 	}
       
   359 
       
   360 EXPORT_C void Epoc::SetMonitorEntryPoint(TDfcFn aFn)
       
   361 	{
       
   362 	if (aFn)
       
   363 		{
       
   364 		TUint32 x=(TUint32)aFn;
       
   365 		PP::MonitorEntryPoint[0]=x;
       
   366 		PP::MonitorEntryPoint[1]=~x;
       
   367 		PP::MonitorEntryPoint[2]=((x>>2)*~x);
       
   368 		}
       
   369 	else
       
   370 		{
       
   371 		PP::MonitorEntryPoint[0]=0;
       
   372 		PP::MonitorEntryPoint[1]=0;
       
   373 		PP::MonitorEntryPoint[2]=0;
       
   374 		}
       
   375 	}
       
   376 
       
   377 EXPORT_C void Epoc::SetMonitorExceptionHandler(TLinAddr aHandler)
       
   378 	{
       
   379 	TheScheduler.iMonitorExceptionHandler=aHandler;
       
   380 	}
       
   381 
       
   382 EXPORT_C TAny* Epoc::ExceptionInfo()
       
   383 	{
       
   384 #ifdef __SMP__
       
   385 	return 0;	// separate for each CPU
       
   386 #else
       
   387 	return TheScheduler.i_ExcInfo;
       
   388 #endif
       
   389 	}
       
   390 
       
   391 EXPORT_C const TRomHeader& Epoc::RomHeader()
       
   392 	{
       
   393 	return TheRomHeader();
       
   394 	}
       
   395 
       
   396 TLinAddr ExecHandler::RomHeaderAddress()
       
   397 	{
       
   398 	return ::RomHeaderAddress;
       
   399 	}
       
   400 
       
   401 TLinAddr ExecHandler::RomRootDirectoryAddress()
       
   402 	{
       
   403 	return PP::RomRootDirAddress;
       
   404 	}
       
   405 
       
   406 TBool M::IsRomAddress(const TAny* aPtr)
       
   407 	{
       
   408     TLinAddr start=::RomHeaderAddress;
       
   409     TLinAddr end=start+TheRomHeader().iUncompressedSize;
       
   410 	return ((TLinAddr)aPtr>=start) && ((TLinAddr)aPtr<end);
       
   411 	}
       
   412 
       
   413 void P::SetSuperPageSignature()
       
   414 	{
       
   415 	TUint32* sig = TheSuperPage().iSignature;
       
   416 	const TUint32* time = (const TUint32*)&TheRomHeader().iTime;
       
   417 	sig[0] = time[0] ^ 0xb504f333;
       
   418 	sig[1] = time[1] ^ 0xf9de6484;
       
   419 	}
       
   420 
       
   421 TBool P::CheckSuperPageSignature()
       
   422 	{
       
   423 	const TUint32* sig = TheSuperPage().iSignature;
       
   424 	const TUint32* time = (const TUint32*)&TheRomHeader().iTime;
       
   425 	return ( (sig[0]^time[0])==0xb504f333 && (sig[1]^time[1])==0xf9de6484 );
       
   426 	}
       
   427 
       
   428 static const TUint32 KMapAttrType2 = 0x80000000;
       
   429 static const TUint32 KMapAttrTypeShift 		 = 26;
       
   430 
       
   431 #if defined(__CPU_MEMORY_TYPE_REMAPPING)
       
   432 extern TUint32 PrimaryRegionRemapRegister();
       
   433 extern TUint32 NormalMemoryRemapRegister();
       
   434 #endif
       
   435 
       
   436 EXPORT_C TMappingAttributes2::TMappingAttributes2(TMemoryType	aType,
       
   437 														TBool	aUserAccess,
       
   438 														TBool	aWritable,
       
   439 														TBool	aExecutable,
       
   440 														TInt	aShared,
       
   441 														TInt	aParity)
       
   442 	{
       
   443 	//Sort out default values:
       
   444 	if (aShared<0)
       
   445 		#if defined	(__CPU_USE_SHARED_MEMORY)
       
   446 		aShared = 1;
       
   447 		#else
       
   448 		aShared = 0;	
       
   449 		#endif
       
   450 	if (aParity<0)
       
   451 		aParity = 0;
       
   452 	
       
   453 	// KMapAttrType2 bit marks the object as of TMappingAttributes2 type (as opposed to TMappingAttributes bitmask).
       
   454 	// We have to make sure that these two types can work together.
       
   455 
       
   456 	iAttributes =	KMapAttrType2				|	// Mark it as TMappingAttributes2 object
       
   457 					EMapAttrReadSup				|	// All memory is readable from Kernel (Supervisor) mode
       
   458 					(aType <<KMapAttrTypeShift)	|
       
   459 					(aUserAccess ? EMapAttrReadUser : 0)|
       
   460 					(aWritable	 ? EMapAttrWriteSup : 0)|
       
   461 		((aWritable&&aUserAccess)? EMapAttrWriteUser: 0)|
       
   462 #ifdef __MMU_USE_SYMMETRIC_ACCESS_PERMISSIONS
       
   463 					(aExecutable   ? EMapAttrExecSup : 0)|
       
   464 		((aExecutable&&aUserAccess)? EMapAttrExecUser: 0)|
       
   465 #else
       
   466 					(aExecutable ? EMapAttrExecUser|EMapAttrExecSup : 0)|
       
   467 #endif
       
   468 					(aShared	 ? EMapAttrShared	: 0)|
       
   469 					(aParity	 ? EMapAttrUseECC	: 0);
       
   470 	
       
   471 	// Kernel relies on TMappingAttributes bitmask when dealing with various memory mappings.
       
   472 	// Set cache attribute bits as they are in TMappingAttributes.
       
   473 	iAttributes |= InternalCache::TypeToCachingAttributes(aType);
       
   474 	}
       
   475 
       
   476 TMappingAttributes2::TMappingAttributes2(TUint aMapAttr):iAttributes(aMapAttr)
       
   477 	{
       
   478 	};
       
   479 
       
   480 TMemoryType TMappingAttributes2::Type()
       
   481 	{
       
   482 	if(iAttributes&KMapAttrType2)
       
   483 		return (TMemoryType)(iAttributes>>KMapAttrTypeShift & 0x7); //three bits for memory type.
       
   484 
       
   485 	switch(iAttributes&EMapAttrL1CacheMask)
       
   486 		{
       
   487 	case EMapAttrFullyBlocking:
       
   488 		return EMemAttStronglyOrdered;
       
   489 
       
   490 	case EMapAttrBufferedNC:
       
   491 		return EMemAttDevice;
       
   492 
       
   493 	case EMapAttrBufferedC:
       
   494 	case EMapAttrL1Uncached:
       
   495 	case EMapAttrCachedWTRA:
       
   496 	case EMapAttrCachedWTWA:
       
   497 	case EMapAttrAltCacheWTRA:
       
   498 	case EMapAttrAltCacheWTWA:
       
   499 		return EMemAttNormalUncached;
       
   500 
       
   501 	case EMapAttrCachedWBRA:
       
   502 	case EMapAttrCachedWBWA:
       
   503 	case EMapAttrAltCacheWBRA:
       
   504 	case EMapAttrAltCacheWBWA:
       
   505 	case EMapAttrL1CachedMax:
       
   506 		return EMemAttNormalCached;
       
   507 
       
   508 	default:
       
   509 		Panic(KErrArgument);
       
   510 		return EMemAttNormalCached;
       
   511 		}
       
   512 	}
       
   513 
       
   514 TBool TMappingAttributes2::UserAccess()	{return (iAttributes&EMapAttrUserRw   ?	(TBool)ETrue : (TBool)EFalse);}
       
   515 TBool TMappingAttributes2::Writable()	{return (iAttributes&EMapAttrWriteMask? (TBool)ETrue : (TBool)EFalse);}
       
   516 #ifdef __MMU_USE_SYMMETRIC_ACCESS_PERMISSIONS
       
   517 TBool TMappingAttributes2::Executable()	{return (iAttributes&EMapAttrExecMask ? (TBool)ETrue : (TBool)EFalse);}
       
   518 #else
       
   519 TBool TMappingAttributes2::Executable()	{return (iAttributes&EMapAttrExecUser ? (TBool)ETrue : (TBool)EFalse);}
       
   520 #endif
       
   521 TBool TMappingAttributes2::Shared()		{return (iAttributes&EMapAttrShared   ?	(TBool)ETrue : (TBool)EFalse);}
       
   522 TBool TMappingAttributes2::Parity()		{return (iAttributes&EMapAttrUseECC	  ?	(TBool)ETrue : (TBool)EFalse);}
       
   523 TBool TMappingAttributes2::ObjectType2(){return (iAttributes&KMapAttrType2	  ?	(TBool)ETrue : (TBool)EFalse);}
       
   524 void  TMappingAttributes2::Panic(TInt aPanic)	{Kern::Fault("TMappingAttributes2",aPanic);}
       
   525 
       
   526 
       
   527 #ifdef __DEBUGGER_SUPPORT__
       
   528  /**
       
   529  Initialises the breakpoint pool.
       
   530  There is only one breakpoint pool in the system. The breakpoint pool should be initialised only once - usually from
       
   531  the run-mode debugger device driver.
       
   532 
       
   533  @param aCapabilities	On return this is set to a bitmask of values from enum DebugSupport::TType which represents the
       
   534  						supported breakpoint types. At the moment only DebugSupport::EBreakpointGlobal type is supported.
       
   535  @param aMaxBreakpoints The number of breakpoints for which resources should be reserved. It represents
       
   536                         the maximum number of the breakpoints at a time.
       
   537 
       
   538  @return KErrNoMemory, 		if not enough memory to reserve breakpoint resources.
       
   539    		 KErrInUse,    		if breakpoint pool already exists. Indicates that another debug tool might be using it at the moment.
       
   540    		 KErrNotSupported, 	if Kernel is not built with __DEBUGGER_SUPPORT__ option
       
   541    		 KErrNone,			on success.
       
   542 
       
   543  @pre   No fast mutex can be held.
       
   544  @pre   Kernel must be unlocked.
       
   545  @pre	Call in a thread context.
       
   546  @pre	Interrupts must be enabled.
       
   547  */
       
   548 EXPORT_C TInt DebugSupport::InitialiseCodeModifier(TUint& aCapabilities, TInt aMaxBreakpoints)
       
   549 	{
       
   550 	CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::InitialiseCodeModifier");
       
   551 	TInt err;
       
   552 	NKern::ThreadEnterCS();
       
   553 	Kern::MutexWait(CodeModifier::Mutex());
       
   554 
       
   555 	if ( KErrNone == (err =CodeModifier::CreateAndInitialise(aMaxBreakpoints)))
       
   556 		aCapabilities = EBreakpointGlobal;
       
   557 	
       
   558 	Kern::MutexSignal(CodeModifier::Mutex());
       
   559 	NKern::ThreadLeaveCS(); 
       
   560 	return err;
       
   561 	}
       
   562 
       
   563  /**
       
   564  Restore all breakpoints and free resources.
       
   565  Must not be called before Initialise().
       
   566 
       
   567  @panic CodeModifier 0 if called before InitialiseCodeModifier().
       
   568 
       
   569  @pre   No fast mutex can be held.
       
   570  @pre   Kernel must be unlocked.
       
   571  @pre	Call in a thread context.
       
   572  @pre	Interrupts must be enabled.
       
   573  */
       
   574 EXPORT_C void DebugSupport::CloseCodeModifier()
       
   575 	{
       
   576 	CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::CloseCodeModifier");
       
   577 	NKern::ThreadEnterCS(); 
       
   578 	Kern::MutexWait(CodeModifier::Mutex());
       
   579 
       
   580 	if (!TheCodeModifier)
       
   581 		{
       
   582 		Kern::MutexSignal(CodeModifier::Mutex());
       
   583 		NKern::ThreadLeaveCS(); 
       
   584 		CodeModifier::Fault(CodeModifier::EPanicNotInitialised);
       
   585 		}
       
   586 	TheCodeModifier->Close();
       
   587 
       
   588 	Kern::MutexSignal(CodeModifier::Mutex());
       
   589 	NKern::ThreadLeaveCS(); 
       
   590 	}
       
   591 
       
   592 /**
       
   593 Write a single breakpoint.
       
   594 I.e. store aValue at location aAddress in the address space of aThread.
       
   595 If the address resides in XIP code (ROM image), the memory page is shadowed before the content of the aAddress is altered.
       
   596 
       
   597 The breakpoint should be cleared/restored by DebugSupport::RestoreCode with matching aThread and aAddress.
       
   598 The breakpoints are owned by the corresponding process. Therefore:
       
   599 @code 
       
   600 DebugSupport::ModifyCode(thread1, address, size, value, type);
       
   601 and
       
   602 DebugSupport::ModifyCode(thread2, address size, value, type);
       
   603 @endcode
       
   604 have the same effect if thread1 and thread2 belong to the same process.
       
   605 
       
   606 Breakpoints of the diferent type(size) cannot overlap each other. For example:
       
   607 @code 
       
   608 DebugSupport::ModifyCode(thread, address,   4, value, type); //address is word aligned address
       
   609 DebugSupport::ModifyCode(thread, address,   2, value, type); //will return KErrAccessDenied
       
   610 DebugSupport::ModifyCode(thread, address+2, 2, value, type); //will return KErrAccessDenied
       
   611 DebugSupport::ModifyCode(thread, address+1, 1, value, type); //will return KErrAccessDenied
       
   612 @endcode
       
   613 
       
   614 After the content of aAddress is altered, instruction cache invalidation is performed on the cache line that aAddress
       
   615 belongs to. Therefore, the device driver doesn't have to call Cache::IMB_Range().
       
   616 
       
   617 If a code segment (which a valid breakpoint belongs to) is removed from the given process, the breakpoint will be
       
   618 automatically removed. This occures just before EEventRemoveCodeSeg event is issued with DProcess* matching
       
   619 the breakpoint's process. This also applies to the terminating/killed process, as all breakpoints belonging to it will be removed too.
       
   620 
       
   621 @param aThread 	The thread in who's address space the breakpoint is to be written.
       
   622 @param aAddress The linear address of the breakpoint. Must be a multiple of aSize.
       
   623 @param aSize 	The size, in bytes, of the breakpoint. Must be 1,2 or 4.
       
   624 @param aValue 	The value to be stored at aAddress. This value is trucated to the
       
   625      			number of bits relevent to aSize.
       
   626 @param aType 	The breakpoint type required. This is a bitmask of values from enum TType.
       
   627      			If this specifies more than one type, then the type with least scope
       
   628      			(i.e. EBreakpointLocal) is used when this is supported.
       
   629 
       
   630  @return KErrNoMemory,      if no resources are available.
       
   631    		 KErrAlreadyExists, if a breakpoint with the same address, size and the same owning process already exists in the pool.
       
   632    		 KErrAccessDenied, 	if an existing breakpoint of a different size and the same owning process overlaps the specified breakpoint.
       
   633    		 KErrNotSupported,  if none of the breakpoints types specified are supported or if Kernel is not built with __DEBUGGER_SUPPORT__ option
       
   634    		 Otherwise,         a positive value from enum TType which represents the type of breakpoint written.
       
   635 
       
   636  @panic CodeModifier 0 if called before InitialiseCodeModifier().
       
   637  @panic CodeModifier 1 if aSize value or aAdress alignement is invalid.
       
   638 
       
   639  @pre   No fast mutex can be held.
       
   640  @pre   Kernel must be unlocked.
       
   641  @pre	Call in a thread context.
       
   642  @pre	Interrupts must be enabled.
       
   643  */
       
   644 EXPORT_C TInt DebugSupport::ModifyCode(DThread* aThread, TLinAddr aAddress, TInt aSize, TUint aValue, TUint aType)
       
   645 	{
       
   646 	CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::ModifyCode");
       
   647 	switch(aSize) //Chack aSize and aValue
       
   648 	{
       
   649 	case CodeModifier::EByte:
       
   650 		break;
       
   651 	case CodeModifier::EHalfword:
       
   652 		if ((TInt)aAddress & 1)
       
   653 			CodeModifier::Fault(CodeModifier::EPanicInvalidSizeOrAlignment);
       
   654 		break;
       
   655 	case CodeModifier::EWord:	
       
   656 		if ((TInt)aAddress & 3)
       
   657 			CodeModifier::Fault(CodeModifier::EPanicInvalidSizeOrAlignment);
       
   658 		break;
       
   659 	default:
       
   660 		CodeModifier::Fault(CodeModifier::EPanicInvalidSizeOrAlignment);
       
   661 	}
       
   662 
       
   663 	if (aType != DebugSupport::EBreakpointGlobal)//Check breakpoint type
       
   664 		return KErrNotSupported;
       
   665 	
       
   666 	NKern::ThreadEnterCS(); 
       
   667 	Kern::MutexWait(CodeModifier::Mutex());
       
   668 	
       
   669 	if (!TheCodeModifier)
       
   670 		{
       
   671 		Kern::MutexSignal(CodeModifier::Mutex());
       
   672 		NKern::ThreadLeaveCS(); 
       
   673 		CodeModifier::Fault(CodeModifier::EPanicNotInitialised);	
       
   674 		}
       
   675 	TInt r = TheCodeModifier->Modify(aThread, aAddress, aSize, aValue);
       
   676 
       
   677 	Kern::MutexSignal(CodeModifier::Mutex());
       
   678 	NKern::ThreadLeaveCS(); 
       
   679 
       
   680 	if (r)
       
   681 		return r;
       
   682 	return EBreakpointGlobal;
       
   683 	}
       
   684 
       
   685  /**
       
   686  Restore a previousely written breakpoint.
       
   687  I.e. restore the value at location aAddress in the address space of aProcess.
       
   688 
       
   689  After the content of aAddress is altered, instruction cache invalidation is performed on the cache line
       
   690  that aAddress belongs to. Therefore, the device driver doesn't have to call Cache::IMB_Range().
       
   691 
       
   692  If the address resides in shadowed memory, the memory page will be un-shadowed if this is the last breakpoint
       
   693  in the page. However, if the page had been already shadowed before the first breakpoint in the page was applied,
       
   694  the page will remain shadowed.
       
   695 
       
   696  @param aProcess The process in who's address space aAddress lies.
       
   697  @param aAddress The linear address of an existing breakpoint.
       
   698 
       
   699  @return KErrNotFound,		if the breakpoint hadn't been previously written. It is also returned if the breakpoint
       
   700                         	was previously removed from the list because the code segment (which the breakpoint belongs to) was
       
   701                         	unloaded/removed from the process associated with the breakpoint.
       
   702    		 KErrNotSupported, 	if Kernel is not built with __DEBUGGER_SUPPORT__ option
       
   703     	 KErrNone,			on success.
       
   704 
       
   705  @panic CodeModifier 0 if called before InitialiseCodeModifier().
       
   706 
       
   707  @pre   No fast mutex can be held.
       
   708  @pre   Kernel must be unlocked.
       
   709  @pre	Call in a thread context.
       
   710  @pre	Interrupts must be enabled.
       
   711  */
       
   712 EXPORT_C TInt DebugSupport::RestoreCode(DThread* aThread, TLinAddr aAddress)
       
   713 	{
       
   714 	CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::RestoreCode");
       
   715 	NKern::ThreadEnterCS(); 
       
   716 	Kern::MutexWait(CodeModifier::Mutex());
       
   717 
       
   718 	if (!TheCodeModifier)
       
   719 		{
       
   720 		Kern::MutexSignal(CodeModifier::Mutex());
       
   721 		NKern::ThreadLeaveCS(); 
       
   722 		CodeModifier::Fault(CodeModifier::EPanicNotInitialised);
       
   723 		}
       
   724 	TInt r = TheCodeModifier->Restore(aThread, aAddress);
       
   725 
       
   726 	Kern::MutexSignal(CodeModifier::Mutex());
       
   727 	NKern::ThreadLeaveCS(); 
       
   728 	return r;
       
   729 	}
       
   730 
       
   731  /**
       
   732  Terminates a specified process on behalf of a debugger.
       
   733 
       
   734  @param aProcess The process in who's address space aAddress lies.
       
   735  @param aReason The reason code to supply when terminating a process
       
   736 
       
   737  @return N/A.
       
   738 
       
   739  @pre   No fast mutex can be held.
       
   740  @pre   Kernel must be unlocked.
       
   741  @pre	Call in a thread context.
       
   742  @pre	Interrupts must be enabled.
       
   743  */
       
   744 EXPORT_C void DebugSupport::TerminateProcess(DProcess* aProcess, const TInt aReason)
       
   745 	{
       
   746 	CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::TerminateProcess");
       
   747 	NKern::ThreadEnterCS(); 
       
   748 	aProcess->Die(EExitTerminate,aReason,KNullDesC);
       
   749 	NKern::ThreadLeaveCS(); 
       
   750 	return;
       
   751 	}
       
   752 
       
   753 /**
       
   754 Creates CodeModifier.
       
   755 @param aMaxBreakpoints The number of breakpoints to be allocated.
       
   756 @return KErrInUse 	 if code modifier already exists.
       
   757 		KErrNoMemory if out of memory
       
   758 		KErrNone 	 on success
       
   759 @pre Calling thread must be in the critical section
       
   760 @pre CodeSeg mutex held
       
   761 */
       
   762 TInt CodeModifier::CreateAndInitialise(TInt aMaxBreakpoints)
       
   763 	{
       
   764 	if (TheCodeModifier)
       
   765 		return KErrInUse;
       
   766 
       
   767 	CodeModifier* modifier = new CodeModifier;
       
   768 	if (!modifier)
       
   769 		return KErrNoMemory;
       
   770 	
       
   771 	modifier->iBreakpoints = new TBreakpoint[aMaxBreakpoints];
       
   772 	if (!modifier->iBreakpoints)
       
   773 		{
       
   774 		delete modifier;	
       
   775 		return KErrNoMemory;
       
   776 		};
       
   777 		
       
   778 	modifier->iPages = new TPageInfo[aMaxBreakpoints];
       
   779 	if (!modifier->iPages)
       
   780 		{
       
   781 		delete[] modifier->iBreakpoints;
       
   782 		delete modifier;	
       
   783 		return KErrNoMemory;
       
   784 		}
       
   785 
       
   786 	modifier->iPoolSize = aMaxBreakpoints;
       
   787 	modifier->iPageSize = Kern::RoundToPageSize(1);
       
   788 	modifier->iPageMask = ~(modifier->iPageSize-1);
       
   789 
       
   790 	TheCodeModifier = modifier;
       
   791 	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::CreateAndInitialise() Size:%d created", aMaxBreakpoints));
       
   792 	return KErrNone;	
       
   793 	}
       
   794 
       
   795 /**
       
   796 Sets breakpoint.
       
   797 @pre Calling thread must be in the critical section
       
   798 @pre CodeSeg mutex held
       
   799 */
       
   800 TInt CodeModifier::Modify(DThread* aThread, TLinAddr aAddress, TInt aSize, TUint aValue)
       
   801 	{
       
   802 	TInt r;
       
   803 	TUint oldValue;
       
   804 	TBool overlap;
       
   805 	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Modify() T:%x Addr:%x, Size:%d Val:%x", aThread, aAddress, aSize, aValue));
       
   806 	
       
   807 	TBreakpoint* brk =FindBreakpoint(aThread, aAddress,aSize,overlap);
       
   808 	if (overlap)
       
   809 		return KErrAccessDenied;
       
   810 	if (brk)
       
   811 		return KErrAlreadyExists;
       
   812 	
       
   813 	if(NULL==(brk = FindEmptyBrk()))
       
   814 		return KErrNoMemory;
       
   815 	
       
   816 	//Find the page (if exists). Shadow the page if necessery.
       
   817 	TInt pageIndex = -1;
       
   818 
       
   819 #ifndef __DEMAND_PAGING__ 
       
   820 	if (IsRom(aAddress))  // If no demand paging, only need to do this if the address is in rom
       
   821 #endif
       
   822 		{
       
   823 		pageIndex = FindPageInfo(aAddress);
       
   824 		if (pageIndex < 0)
       
   825 			{
       
   826 			pageIndex = FindEmptyPageInfo();
       
   827 			if (pageIndex < 0)
       
   828 				return KErrNoMemory;
       
   829 			TPageInfo& page = iPages[pageIndex];
       
   830 			memclr(&page, sizeof(page));
       
   831 			page.iAddress = aAddress & iPageMask;
       
   832 			
       
   833 			if (IsRom(aAddress))
       
   834 				{
       
   835 				__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Modify() - Shadowing Page"));
       
   836 				r = Epoc::AllocShadowPage(aAddress & iPageMask);
       
   837 				if (r==KErrAlreadyExists)
       
   838 					page.iWasShadowed = ETrue;
       
   839 				else if (r!=KErrNone)
       
   840 					return r;
       
   841 				}
       
   842 #ifdef __DEMAND_PAGING__
       
   843 			else
       
   844 				{
       
   845 				DDemandPagingLock* lock = new DDemandPagingLock;
       
   846 				if (lock == NULL)
       
   847 					return KErrNoMemory;
       
   848 				r = lock->Alloc(iPageSize);
       
   849 				if (r != KErrNone)
       
   850 					{
       
   851 					delete lock;
       
   852 					return r;
       
   853 					}
       
   854 				lock->Lock(aThread, aAddress & iPageMask, iPageSize);
       
   855 				page.iPagingLock = lock;
       
   856 				}
       
   857 #endif
       
   858 			}
       
   859 		iPages[pageIndex].iCounter++;
       
   860 		}
       
   861 
       
   862 	r = SafeWriteCode(aThread->iOwningProcess, aAddress, aSize, aValue, &oldValue);
       
   863 	if (r != KErrNone)
       
   864 		{//aAddress is invalid
       
   865 		if (pageIndex >= 0)
       
   866 			RestorePage(pageIndex);
       
   867 		return r;
       
   868 		}
       
   869 
       
   870 	//All done. Update the internal structures.
       
   871 	brk->iAddress = aAddress;
       
   872 	brk->iProcessId = (aThread->iOwningProcess)->iId;
       
   873 	brk->iOldValue = oldValue;
       
   874 	brk->iSize = aSize;
       
   875 	brk->iPageIndex = pageIndex;
       
   876 	return KErrNone;
       
   877 	}
       
   878 
       
   879 /**
       
   880 @pre Calling thread must be in the critical section
       
   881 @pre CodeSeg mutex held
       
   882 */
       
   883 TInt CodeModifier::Restore(DThread* aThread, TLinAddr aAddress)
       
   884 	{
       
   885 	TUint oldValue;
       
   886 	TBool overlaps;
       
   887 	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Restore() T:%x Addr:%x", aThread, aAddress));
       
   888 	TInt r = KErrNone;;
       
   889 	TBreakpoint* br = FindBreakpoint(aThread, aAddress, 0, overlaps);
       
   890 	if (br==NULL)
       
   891 		return KErrNotFound;
       
   892 	
       
   893 	r = SafeWriteCode(aThread->iOwningProcess, br->iAddress, br->iSize, br->iOldValue, &oldValue);
       
   894 	if (r)
       
   895 		r=KErrNotFound;
       
   896 	
       
   897 	br->iSize = (TUint)EEmpty;
       
   898 		
       
   899 	TInt pageIndex = br->iPageIndex;
       
   900 	if (pageIndex>=0)
       
   901 		RestorePage(pageIndex);
       
   902 	
       
   903 	return r;
       
   904 	}
       
   905 
       
   906 /*
       
   907 @pre Calling thread must be in the critical section
       
   908 @pre CodeSeg mutex held
       
   909 */
       
   910 void CodeModifier::Close()
       
   911 	{
       
   912 	TUint oldValue;
       
   913 	TInt brkIndex;
       
   914 
       
   915 	TheCodeModifier = NULL;
       
   916 	
       
   917 	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Close()"));
       
   918 
       
   919 	for (brkIndex=0; brkIndex<iPoolSize; brkIndex++)	
       
   920 		{
       
   921 		if (iBreakpoints[brkIndex].iSize ==(TUint16)EEmpty)
       
   922 			continue;
       
   923 		DProcess* process = Process(iBreakpoints[brkIndex].iProcessId);
       
   924 		
       
   925 		__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Close() - Removing Brk:%x",iBreakpoints[brkIndex].iAddress));
       
   926 		
       
   927 		//Write back the original value
       
   928 		if (process)
       
   929 			SafeWriteCode(process, iBreakpoints[brkIndex].iAddress, iBreakpoints[brkIndex].iSize, iBreakpoints[brkIndex].iOldValue, &oldValue);
       
   930 			
       
   931 		iBreakpoints[brkIndex].iSize = (TUint)EEmpty;
       
   932 		TInt pageIndex = iBreakpoints[brkIndex].iPageIndex;
       
   933 		if (pageIndex>=0)
       
   934 			RestorePage(pageIndex);
       
   935 		}
       
   936 
       
   937 	delete this;
       
   938 	}
       
   939 
       
   940 /*
       
   941 Destructor. The object is deleted asynchroniously from Kernel Supervisor thread.
       
   942 */
       
   943 CodeModifier::~CodeModifier()
       
   944 	{
       
   945 	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::~CodeModifier()"));
       
   946 	delete[] iPages;
       
   947 	delete[] iBreakpoints;
       
   948 	}
       
   949 
       
   950 /**
       
   951 This is executed when a code segment is about to be unmapped from the process. It corresponds to EEventRemoveCodeSeg Kernel event.
       
   952 Removes breakpoints that belong to the threads from aProcess. Also, removes shadow pages if there is no breakpoint left in them.
       
   953 
       
   954 @param aCodeSeg Code Segment that is removed from aProcess.
       
   955 @param aProcess Process from whom the code segment is removed.
       
   956 
       
   957 @pre Calling thread must be in the critical section
       
   958 @pre CodeSeg mutex held
       
   959 */
       
   960 void CodeModifier::CodeSegRemoved(DCodeSeg* aCodeSeg, DProcess* aProcess)
       
   961 	{
       
   962 	if (!TheCodeModifier)
       
   963 		return;
       
   964 	TheCodeModifier->DoCodeSegRemoved(aCodeSeg, aProcess);
       
   965 	}
       
   966 
       
   967 void CodeModifier::DoCodeSegRemoved(DCodeSeg* aCodeSeg, DProcess* aProcess)
       
   968 	{
       
   969 	__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::CodeSegRemoved()"));
       
   970 	
       
   971 	TUint oldValue;
       
   972 	TUint minAddr = aCodeSeg->iRunAddress;
       
   973 	TUint maxAddr = aCodeSeg->iRunAddress + aCodeSeg->iSize;
       
   974 
       
   975 	TBreakpoint* bp = iBreakpoints;
       
   976 	TBreakpoint* bpEnd = bp+iPoolSize; //points right behind iBreakpoints
       
   977 	for (; bp<bpEnd; ++bp)
       
   978 		{
       
   979 		if (bp->iSize == (TUint)EEmpty) continue;
       
   980 
       
   981 		if (aProcess->iId == bp->iProcessId)
       
   982 			{
       
   983 			if (bp->iAddress >= minAddr && bp->iAddress <  maxAddr)   
       
   984 				{
       
   985 				__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::CodeSegRemoved()- a breakpoint"));
       
   986 
       
   987 				//Remove breakpoint. Don't examine error code as there is nobody to report to.
       
   988 				SafeWriteCode(aProcess, bp->iAddress, bp->iSize, bp->iOldValue, &oldValue);
       
   989 
       
   990 				//Mark the slot as empty and decrease the counter of the shadow page slot (if there is any associated)
       
   991 				bp->iSize = (TUint)EEmpty;
       
   992 				if (bp->iPageIndex >= 0)
       
   993 					RestorePage(bp->iPageIndex);
       
   994 				}
       
   995 			}
       
   996 		}
       
   997 
       
   998 	}
       
   999 
       
  1000 /*
       
  1001 Finds DProcess that matches to processId
       
  1002 @param aProcessId ProcessId
       
  1003 @return Pointer to matching DProcess or NULL
       
  1004 */
       
  1005 DProcess* CodeModifier::Process(TUint aProcessId)
       
  1006 	{
       
  1007 	TInt i;
       
  1008 	DProcess* process = NULL;
       
  1009 	DObjectCon* processCon = Kern::Containers()[EProcess];
       
  1010 	processCon->Wait();
       
  1011 
       
  1012 	for (i=0;i<processCon->Count();i++)
       
  1013 		{
       
  1014 		DProcess* pr = (DProcess*)(*processCon)[i];
       
  1015 		if (pr->iId == aProcessId)
       
  1016 			{
       
  1017 			process=(DProcess*)pr;
       
  1018 			break;
       
  1019 			}
       
  1020 		}
       
  1021 
       
  1022 	processCon->Signal();
       
  1023 	return process;
       
  1024 	}
       
  1025 
       
  1026 /*
       
  1027 Returns eTrue if given virtual address belongs to rom image, EFalse otherwise
       
  1028 */
       
  1029 TBool CodeModifier::IsRom(TLinAddr aAddress)
       
  1030 	{
       
  1031 	TRomHeader romHeader = Epoc::RomHeader();
       
  1032 	if ( (aAddress >= romHeader.iRomBase ) && (aAddress < (romHeader.iRomBase + romHeader.iUncompressedSize)) )
       
  1033 		return ETrue;
       
  1034 	return EFalse;
       
  1035 	}
       
  1036 
       
  1037 /*
       
  1038 Finds the first available(empty) breakpoint slot.
       
  1039 @return The pointer of the empty slot or NULL if all occupied.
       
  1040 */
       
  1041 CodeModifier::TBreakpoint* CodeModifier::FindEmptyBrk()
       
  1042 	{
       
  1043 	TBreakpoint* bp = TheCodeModifier->iBreakpoints;
       
  1044 	TBreakpoint* bpEnd = bp+TheCodeModifier->iPoolSize; //points right behind iBreakpoints
       
  1045 	for (; bp<bpEnd; ++bp)
       
  1046 		if (bp->iSize == (TInt16)EEmpty)
       
  1047 			return bp;
       
  1048 		
       
  1049 	return NULL;	
       
  1050 	}
       
  1051 	
       
  1052 /*
       
  1053 Finds matching breakpoint.
       
  1054 
       
  1055 @param aThread 		The thread who's process owns the breakpoint
       
  1056 @param aAddress 	Address of the breakpoint.
       
  1057 @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).
       
  1058 @param aOverlap 	On return, it is true if a breakpoint is found that doesn't match the size but overlaps with
       
  1059 					the specified breakpoint(i.e. address and process are the same but the size is different).
       
  1060 
       
  1061 @return - The pointer to the breakpoint slot that matches the entry (adress, size and the owning process)
       
  1062 		- NULL - if could't find the matching breakpoint.
       
  1063 */
       
  1064 CodeModifier::TBreakpoint* CodeModifier::FindBreakpoint(DThread* aThread, TLinAddr aAddress, TInt aSize, TBool& aOverlap)
       
  1065 	{
       
  1066 	TInt bytes=0;
       
  1067 	aOverlap = EFalse;
       
  1068 	TUint processId = aThread->iOwningProcess->iId;//processId of the thread that owns aThread
       
  1069 
       
  1070 	if (aSize) //if size==0, we do not check overlaps.
       
  1071 		bytes = ((1<<aSize)-1)<<(aAddress&3);	//bits[3-0] marks the bytes that are contained in the breakpoint:
       
  1072 												//	address: ...00b size: 1 => bytes=0001b 
       
  1073 												//	address: ...01b size: 1 => bytes=0010b 
       
  1074 												//	address: ...10b size: 1 => bytes=0100b 
       
  1075 												//	address: ...11b size: 1 => bytes=1000b 
       
  1076 												//	address: ...00b size: 2 => bytes=0011b 
       
  1077 												//	address: ...10b size: 2 => bytes=1100b 
       
  1078 												//	address: ...00b size: 4 => bytes=1111b 
       
  1079 
       
  1080 	TBreakpoint* bp = TheCodeModifier->iBreakpoints;
       
  1081 	TBreakpoint* bpEnd = bp+TheCodeModifier->iPoolSize; //points right behind iBreakpoints
       
  1082 	for (; bp<bpEnd; ++bp)
       
  1083 		{
       
  1084 		if (bp->iSize == (TInt16)EEmpty || bp->iProcessId != processId)
       
  1085 			continue;//Either empty or not matchng process. 
       
  1086 
       
  1087 		if (!aSize)
       
  1088 			{ //Do not check the size. If the address does not match, do not check for overlap.
       
  1089 			if (bp->iAddress == aAddress)
       
  1090 				return bp;
       
  1091 			else
       
  1092 				continue;
       
  1093 			}
       
  1094 			
       
  1095 		if (bp->iAddress == aAddress && bp->iSize == aSize)
       
  1096 			return bp;//If we find a matching breakpoint, there cannot be another one that overlaps
       
  1097 		
       
  1098 		//Check if bp breakpoint overlaps with the specified one.
       
  1099 		if ((bp->iAddress^aAddress)>>2)
       
  1100 			continue;//Not in the same word
       
  1101 			
       
  1102 		if (((1<<bp->iSize)-1)<<(bp->iAddress&3)&bytes)
       
  1103 			{//Two brakpoints are within the same word with some overlaping bytes.
       
  1104 			aOverlap = ETrue;
       
  1105 			return NULL; //If we find an overlaping breakpoint, there cannot be another one that matches exactly.
       
  1106 			}
       
  1107 		}
       
  1108 	return NULL;	
       
  1109 	}
       
  1110 
       
  1111 /*
       
  1112 Finds the first available(empty) page info slot.
       
  1113 @return The index of the slot or KErrNotFound if all occupied.
       
  1114 */
       
  1115 TInt CodeModifier::FindEmptyPageInfo()
       
  1116 	{
       
  1117 	TInt i;
       
  1118 	for (i=0; i<iPoolSize; i++)
       
  1119 		if (!iPages[i].iCounter)
       
  1120 			return i;
       
  1121 	return KErrNotFound;
       
  1122 	}
       
  1123 
       
  1124 /*
       
  1125 Finds the page info structure that contains given virtual address
       
  1126 @return The index of the page info slot or KErrNotFound.
       
  1127 */
       
  1128 TInt CodeModifier::FindPageInfo(TLinAddr aAddress)
       
  1129 	{
       
  1130 	TInt i;
       
  1131 	aAddress &= iPageMask; //round down to the page base address
       
  1132 	for (i=0; i<iPoolSize; i++)
       
  1133 		if(iPages[i].iCounter)
       
  1134 			if (iPages[i].iAddress == aAddress)
       
  1135 				return i;
       
  1136 	return KErrNotFound;
       
  1137 	}
       
  1138 
       
  1139 /**
       
  1140 Decrement the count of breakpoints associated with this page, and restores page
       
  1141 to its original state if there are none remaining.
       
  1142 */
       
  1143 void CodeModifier::RestorePage(TInt aPageIndex)
       
  1144 	{
       
  1145 	TPageInfo& page = iPages[aPageIndex];
       
  1146 	if(--page.iCounter==0)
       
  1147 		{
       
  1148 		if (!page.iWasShadowed)
       
  1149 			{
       
  1150 			__KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Restore() - Freeing Shadow Page"));
       
  1151 			Epoc::FreeShadowPage(page.iAddress);
       
  1152 			}
       
  1153 #ifdef __DEMAND_PAGING__
       
  1154 		if (page.iPagingLock)
       
  1155 			{
       
  1156 			// Release lock and free resources
       
  1157 			delete page.iPagingLock;
       
  1158 			page.iPagingLock = NULL;
       
  1159 			}
       
  1160 #endif
       
  1161 		}
       
  1162 	}
       
  1163 
       
  1164 void CodeModifier::Fault(TPanic aPanic)
       
  1165 	{
       
  1166 	Kern::Fault("CodeModifier", aPanic);
       
  1167 	}
       
  1168 
       
  1169 #else //__DEBUGGER_SUPPORT__
       
  1170 EXPORT_C TInt DebugSupport::InitialiseCodeModifier(TUint& /*aCapabilities*/, TInt /*aMinBreakpoints*/)
       
  1171 	{
       
  1172 	return KErrNotSupported;	
       
  1173 	}
       
  1174 EXPORT_C void DebugSupport::CloseCodeModifier()
       
  1175 	{
       
  1176 	}
       
  1177 EXPORT_C TInt DebugSupport::ModifyCode(DThread* /*aProcess*/, TLinAddr /*aAddress*/, TInt /*aSize*/, TUint /*aValue*/, TUint /*aType*/)
       
  1178 	{
       
  1179 	return KErrNotSupported;	
       
  1180 	}
       
  1181 EXPORT_C TInt DebugSupport::RestoreCode(DThread* /*aProcess*/, TLinAddr /*aAddress*/)
       
  1182 	{
       
  1183 	return KErrNotSupported;	
       
  1184 	}
       
  1185 EXPORT_C void DebugSupport::TerminateProcess(DProcess* /*aProcess*/, const TInt /*aReason*/)
       
  1186 	{
       
  1187 	}
       
  1188 #endif
       
  1189