os/kernelhwsrv/brdbootldr/ubootldr/ubootldrldd/ubootldrldd.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2005-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
//
sl@0
    15
sl@0
    16
#include <kernel/kern_priv.h>
sl@0
    17
#include <kernel/cache.h>
sl@0
    18
#include "ubootldrldd.h"
sl@0
    19
sl@0
    20
static TInt ChunkDestroyedCount=1;	// Test counter
sl@0
    21
sl@0
    22
//
sl@0
    23
// Class definitions
sl@0
    24
//
sl@0
    25
sl@0
    26
class DUBootldrFactory : public DLogicalDevice
sl@0
    27
	{
sl@0
    28
public:
sl@0
    29
	~DUBootldrFactory();
sl@0
    30
	virtual TInt Install();
sl@0
    31
	virtual void GetCaps(TDes8& aDes) const;
sl@0
    32
	virtual TInt Create(DLogicalChannelBase*& aChannel);
sl@0
    33
	void LockWait();
sl@0
    34
	void LockSignal();
sl@0
    35
private:
sl@0
    36
	NFastMutex iLock;
sl@0
    37
	};
sl@0
    38
sl@0
    39
class DUBootldrChannel : public DLogicalChannelBase
sl@0
    40
	{
sl@0
    41
public:
sl@0
    42
	~DUBootldrChannel();
sl@0
    43
	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
sl@0
    44
	virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
sl@0
    45
	DChunk* OpenChunk(TLinAddr* aKernelAddr=0, TInt* aMaxSize=0);
sl@0
    46
	inline void LockWait()
sl@0
    47
		{ iFactory->LockWait(); }
sl@0
    48
	inline void LockSignal()
sl@0
    49
		{ iFactory->LockSignal(); }
sl@0
    50
public:
sl@0
    51
	DUBootldrFactory*	iFactory;
sl@0
    52
	DChunk*					iChunk;
sl@0
    53
	TLinAddr				iKernelAddress;
sl@0
    54
	TInt					iMaxSize;
sl@0
    55
	};
sl@0
    56
sl@0
    57
class TChunkCleanup : public TDfc
sl@0
    58
	{
sl@0
    59
public:
sl@0
    60
	TChunkCleanup(DUBootldrFactory* aFactory,TBool aReleasePhysicalMemory);
sl@0
    61
	~TChunkCleanup();
sl@0
    62
	static void ChunkDestroyed(TChunkCleanup* aSelf);
sl@0
    63
	void Cancel();
sl@0
    64
public:
sl@0
    65
	DUBootldrFactory* iFactory;
sl@0
    66
	};
sl@0
    67
sl@0
    68
//
sl@0
    69
// TChunkCleanup
sl@0
    70
//
sl@0
    71
sl@0
    72
TChunkCleanup::TChunkCleanup(DUBootldrFactory* aFactory,TBool aReleasePhysicalMemory)
sl@0
    73
	: TDfc((TDfcFn)TChunkCleanup::ChunkDestroyed,this,Kern::SvMsgQue(),0)
sl@0
    74
	, iFactory(0)
sl@0
    75
	{
sl@0
    76
	aFactory->Open();
sl@0
    77
	iFactory = aFactory;
sl@0
    78
	}
sl@0
    79
sl@0
    80
TChunkCleanup::~TChunkCleanup()
sl@0
    81
	{
sl@0
    82
	if(iFactory)
sl@0
    83
		iFactory->Close(0);
sl@0
    84
	}
sl@0
    85
sl@0
    86
void TChunkCleanup::ChunkDestroyed(TChunkCleanup* aSelf)
sl@0
    87
	{
sl@0
    88
	DUBootldrFactory* factory = aSelf->iFactory;
sl@0
    89
	if(factory)
sl@0
    90
		{
sl@0
    91
		factory->LockWait();
sl@0
    92
		++ChunkDestroyedCount;
sl@0
    93
		factory->LockSignal();
sl@0
    94
		}
sl@0
    95
	delete aSelf;
sl@0
    96
	}
sl@0
    97
sl@0
    98
void TChunkCleanup::Cancel()
sl@0
    99
	{
sl@0
   100
	if(iFactory)
sl@0
   101
		{
sl@0
   102
		iFactory->Close(0);
sl@0
   103
		iFactory = 0;
sl@0
   104
		}
sl@0
   105
	};
sl@0
   106
sl@0
   107
//
sl@0
   108
// DUBootldrFactory
sl@0
   109
//
sl@0
   110
sl@0
   111
TInt DUBootldrFactory::Install()
sl@0
   112
	{
sl@0
   113
	return SetName(&KBootldrLddName);
sl@0
   114
	}
sl@0
   115
sl@0
   116
DUBootldrFactory::~DUBootldrFactory()
sl@0
   117
	{
sl@0
   118
	}
sl@0
   119
sl@0
   120
void DUBootldrFactory::GetCaps(TDes8& /*aDes*/) const
sl@0
   121
	{
sl@0
   122
	// Not used but required as DLogicalDevice::GetCaps is pure virtual
sl@0
   123
	}
sl@0
   124
sl@0
   125
TInt DUBootldrFactory::Create(DLogicalChannelBase*& aChannel)
sl@0
   126
	{
sl@0
   127
	aChannel = NULL;
sl@0
   128
	DUBootldrChannel* channel=new DUBootldrChannel;
sl@0
   129
	if(!channel)
sl@0
   130
		return KErrNoMemory;
sl@0
   131
	channel->iFactory = this;
sl@0
   132
	aChannel = channel;
sl@0
   133
	return KErrNone;
sl@0
   134
	}
sl@0
   135
sl@0
   136
void DUBootldrFactory::LockWait()
sl@0
   137
	{
sl@0
   138
	NKern::FMWait(&iLock);
sl@0
   139
	}
sl@0
   140
sl@0
   141
void DUBootldrFactory::LockSignal()
sl@0
   142
	{
sl@0
   143
	NKern::FMSignal(&iLock);
sl@0
   144
	}
sl@0
   145
sl@0
   146
DECLARE_STANDARD_LDD()
sl@0
   147
	{
sl@0
   148
	return new DUBootldrFactory;
sl@0
   149
	}
sl@0
   150
sl@0
   151
//
sl@0
   152
// DUBootldrChannel
sl@0
   153
//
sl@0
   154
sl@0
   155
TInt DUBootldrChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
sl@0
   156
	{
sl@0
   157
	return KErrNone;
sl@0
   158
	}
sl@0
   159
sl@0
   160
DUBootldrChannel::~DUBootldrChannel()
sl@0
   161
	{
sl@0
   162
	if(iChunk)
sl@0
   163
		iChunk->Close(0);
sl@0
   164
	}
sl@0
   165
sl@0
   166
DChunk* DUBootldrChannel::OpenChunk(TLinAddr* aKernelAddr,TInt* aMaxSize)
sl@0
   167
	{
sl@0
   168
	__ASSERT_CRITICAL	// Thread must be in critical section (to avoid leaking access count on chunk)
sl@0
   169
	LockWait();
sl@0
   170
	DChunk* chunk=iChunk;
sl@0
   171
	if(chunk)
sl@0
   172
		if(chunk->Open()!=KErrNone)
sl@0
   173
			chunk = NULL;
sl@0
   174
	if(aKernelAddr)
sl@0
   175
		*aKernelAddr = chunk ? iKernelAddress : NULL;
sl@0
   176
	if(aMaxSize)
sl@0
   177
		*aMaxSize = chunk ? iMaxSize : 0;
sl@0
   178
	LockSignal();
sl@0
   179
	return chunk;
sl@0
   180
	}
sl@0
   181
sl@0
   182
sl@0
   183
TUint8 ReadByte(volatile TUint8* aPtr)
sl@0
   184
	{
sl@0
   185
	return *aPtr;
sl@0
   186
	}
sl@0
   187
sl@0
   188
sl@0
   189
TInt DUBootldrChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
sl@0
   190
	{
sl@0
   191
//	Kern::Printf("Request a1 0x%x a2 0x%x", (TUint)a1, (TUint)a2);
sl@0
   192
	TInt r=KErrNotSupported;
sl@0
   193
sl@0
   194
	switch(aFunction)
sl@0
   195
		{
sl@0
   196
sl@0
   197
	case RUBootldrLdd::ECreateChunk:
sl@0
   198
		{
sl@0
   199
		if(ChunkDestroyedCount==0)
sl@0
   200
			NKern::Sleep(NKern::TimerTicks(100)); // Go idle for a while to let chunk cleanup DFCs to be called
sl@0
   201
sl@0
   202
		NKern::ThreadEnterCS();
sl@0
   203
		TInt chunksize = (TInt)a1;
sl@0
   204
sl@0
   205
		TChunkCleanup* cleanup = new TChunkCleanup(this->iFactory,ETrue);
sl@0
   206
		if(!cleanup)
sl@0
   207
			{
sl@0
   208
			NKern::ThreadLeaveCS();
sl@0
   209
			return KErrNoMemory;
sl@0
   210
			}
sl@0
   211
sl@0
   212
		// Try and create chunk...
sl@0
   213
		DChunk* chunk;
sl@0
   214
		TChunkCreateInfo info;
sl@0
   215
sl@0
   216
		info.iType=TChunkCreateInfo::ESharedKernelSingle;
sl@0
   217
		info.iMaxSize	 = chunksize;
sl@0
   218
		info.iMapAttr	 = EMapAttrFullyBlocking;
sl@0
   219
		info.iOwnsMemory = EFalse;
sl@0
   220
		info.iDestroyedDfc = cleanup;
sl@0
   221
sl@0
   222
		TUint32 mapAttr;
sl@0
   223
		TUint32 kernAddr;
sl@0
   224
		r = Kern::ChunkCreate(info, chunk, kernAddr, mapAttr);
sl@0
   225
		if(r!=KErrNone)
sl@0
   226
			{
sl@0
   227
			delete cleanup;
sl@0
   228
			NKern::ThreadLeaveCS();
sl@0
   229
			return r;
sl@0
   230
			}
sl@0
   231
sl@0
   232
		// Setup data members
sl@0
   233
		LockWait();
sl@0
   234
		if(iChunk)
sl@0
   235
			r = KErrAlreadyExists;
sl@0
   236
		else
sl@0
   237
			{
sl@0
   238
			if(r==KErrNone)
sl@0
   239
				{
sl@0
   240
				iChunk = chunk;
sl@0
   241
				iKernelAddress = kernAddr;
sl@0
   242
				iMaxSize = info.iMaxSize;
sl@0
   243
				ChunkDestroyedCount = 0;
sl@0
   244
				}
sl@0
   245
			}
sl@0
   246
		LockSignal();
sl@0
   247
sl@0
   248
		if(r!=KErrNone)
sl@0
   249
			{
sl@0
   250
			// There was an error, so discard created chunk
sl@0
   251
			cleanup->Cancel();
sl@0
   252
			Kern::ChunkClose(chunk);
sl@0
   253
			NKern::ThreadLeaveCS();
sl@0
   254
			return r;
sl@0
   255
			}
sl@0
   256
sl@0
   257
		NKern::ThreadLeaveCS();
sl@0
   258
sl@0
   259
		// Write back kernel address of chunk
sl@0
   260
		if(a2)
sl@0
   261
			kumemput32(a2,(TAny*)&kernAddr,4);
sl@0
   262
sl@0
   263
		return KErrNone;
sl@0
   264
		}
sl@0
   265
sl@0
   266
sl@0
   267
	case RUBootldrLdd::EGetChunkHandle:
sl@0
   268
		{
sl@0
   269
		NKern::ThreadEnterCS();
sl@0
   270
		DChunk* chunk=OpenChunk();
sl@0
   271
		if(chunk)
sl@0
   272
			{
sl@0
   273
			r = Kern::MakeHandleAndOpen(0,chunk);
sl@0
   274
			chunk->Close(0);
sl@0
   275
			}
sl@0
   276
		else
sl@0
   277
			r = KErrNotFound;
sl@0
   278
		NKern::ThreadLeaveCS();
sl@0
   279
		return r;
sl@0
   280
		}
sl@0
   281
sl@0
   282
sl@0
   283
	case RUBootldrLdd::ECloseChunkHandle:
sl@0
   284
		{
sl@0
   285
		NKern::ThreadEnterCS();
sl@0
   286
		r = Kern::CloseHandle(0,(TInt)a1);
sl@0
   287
		NKern::ThreadLeaveCS();
sl@0
   288
		return r;
sl@0
   289
		}
sl@0
   290
sl@0
   291
sl@0
   292
	case RUBootldrLdd::ECommitMemory:
sl@0
   293
		{
sl@0
   294
		NKern::ThreadEnterCS();
sl@0
   295
		TUint32 chunkKernelAddress;
sl@0
   296
		DChunk* chunk=OpenChunk(&chunkKernelAddress);
sl@0
   297
		if(chunk)
sl@0
   298
			{
sl@0
   299
			TUint sz=(TUint)a1;
sl@0
   300
			TUint physaddr=(TUint)a2;
sl@0
   301
sl@0
   302
			// Kern::Printf("Commit chunk = 0x%x sz = 0x%x, addr = 0x%x", chunk, sz, physaddr);	// XXX
sl@0
   303
sl@0
   304
			// LDD i/f guarantees page alignment of physaddr
sl@0
   305
			r = Kern::ChunkCommitPhysical(chunk,0,sz,physaddr);
sl@0
   306
			// chunk->Close(0);
sl@0
   307
			}
sl@0
   308
		else
sl@0
   309
			r = KErrNotFound;
sl@0
   310
		NKern::ThreadLeaveCS();
sl@0
   311
		return r;
sl@0
   312
		}
sl@0
   313
sl@0
   314
sl@0
   315
	case RUBootldrLdd::EIsDestroyed:
sl@0
   316
		{
sl@0
   317
		// First wait for short while to allow idle thread to run and do
sl@0
   318
		// cleanup of chunk
sl@0
   319
		NKern::Sleep(NKern::TimerTicks(100));
sl@0
   320
		return ChunkDestroyedCount;
sl@0
   321
		}
sl@0
   322
sl@0
   323
sl@0
   324
	case RUBootldrLdd::ECloseChunk:
sl@0
   325
		{
sl@0
   326
		NKern::ThreadEnterCS();
sl@0
   327
sl@0
   328
		// Claim ownership of the chunk
sl@0
   329
		LockWait();
sl@0
   330
		DChunk* chunk=iChunk;
sl@0
   331
		iChunk = 0;
sl@0
   332
		LockSignal();
sl@0
   333
sl@0
   334
		// Close the chunk
sl@0
   335
		if(chunk)
sl@0
   336
			r = Kern::ChunkClose(chunk);
sl@0
   337
		else
sl@0
   338
			r = KErrNotFound;
sl@0
   339
sl@0
   340
		NKern::ThreadLeaveCS();
sl@0
   341
		return r;
sl@0
   342
		}
sl@0
   343
	case RUBootldrLdd::ERestart:
sl@0
   344
		{
sl@0
   345
		TInt aReason = (TInt)a1;
sl@0
   346
		// Kern::Printf("Restart:: %d", aReason);
sl@0
   347
		Kern::Restart(aReason);
sl@0
   348
		return KErrNone; // Notreached
sl@0
   349
		}
sl@0
   350
	default:
sl@0
   351
		return KErrNotSupported;
sl@0
   352
		}
sl@0
   353
	}