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