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