<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Computer, Electron and Technology &#187; 动态加载</title>
	<atom:link href="http://www.donevii.com/post/tag/%e5%8a%a8%e6%80%81%e5%8a%a0%e8%bd%bd/feed" rel="self" type="application/rss+xml" />
	<link>http://www.donevii.com</link>
	<description>关注技术、移动互联网以及一切 GEEK &#38; NERD 的事情</description>
	<lastBuildDate>Wed, 21 Dec 2011 10:49:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>How to run mod file that is loaded into HEAP</title>
		<link>http://www.donevii.com/post/820.html</link>
		<comments>http://www.donevii.com/post/820.html#comments</comments>
		<pubDate>Sun, 17 May 2009 07:23:07 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[life]]></category>
		<category><![CDATA[brew]]></category>
		<category><![CDATA[heap]]></category>
		<category><![CDATA[mod]]></category>
		<category><![CDATA[modloader]]></category>
		<category><![CDATA[动态加载]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=820</guid>
		<description><![CDATA[05-15-2008, 11:20 PM Brewin Registered User Join Date: Mar 2006 Posts: 152 Rep Power: 4 How to run mod file that is loaded in the HEAP&#8230; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;... ]]></description>
			<content:encoded><![CDATA[<p>05-15-2008, 11:20 PM<br />
 Brewin<br />
Registered User   Join Date: Mar 2006<br />
Posts: 152<br />
Rep Power: 4</p>
<p> How to run <a href="http://www.donevii.com/post/tag/mod" class="st_tag internal_tag" rel="tag" title="Posts tagged with mod">mod</a> file that is loaded in the <a href="http://www.donevii.com/post/tag/heap" class="st_tag internal_tag" rel="tag" title="Posts tagged with heap">HEAP</a>&#8230;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Hi everyone,<br />
How can I run a MOD file that is loaded into the HEAP???? Any idea&#8217;s&#8230;</p>
<p>__________________<br />
Thanks everyone for the info they share here..<br />
Ramki@TTSL<br />
 VALUE HAS A VALUE ONLY IF ITS VALUE IS VALUED</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Last edited by Brewin : 05-15-2008 at 11:27 PM. </p>
<p>Brewin<br />
View Public Profile<br />
Send a private message to Brewin<br />
Send email to Brewin<br />
Find all posts by Brewin<br />
Add Brewin to Your Buddy List </p>
<p>  #2   06-04-2008, 07:36 PM<br />
ArdyFalls<br />
Registered User   Join Date: Apr 2007<br />
Posts: 23<br />
Rep Power: 0</p>
<p>Steps for loading a mod into the heap</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>1) malloc memory on the heap that is the size of the mode file + 4 in bytes.<br />
2) Set the initial 4 btyes to point to the AEE struct thing that has all the AEEStdlib funcitons.<br />
3) Set the processors program counter (PC register) to address 0<br />
Please note, I could be kinda off, look at the code for AEE_ModLoad, it is always at address zero. It will tell you the arguments that you need to pass to it before setting the pc register to it. Remember, the first four arguments of any function are passed in registers r0 -r4.</p>
<p>I hope this helps</p>
<p>__________________<br />
Ardavon Falls<br />
Senior Software Engineer<br />
MobiTV Inc</p>
<p>ArdyFalls<br />
View Public Profile<br />
Send a private message to ArdyFalls<br />
Find all posts by ArdyFalls<br />
Add ArdyFalls to Your Buddy List </p>
<p>  #3   07-28-2008, 10:45 PM<br />
 Brewin<br />
Registered User   Join Date: Mar 2006<br />
Posts: 152<br />
Rep Power: 4</p>
<p> Loading and running a compressed mod file&#8230;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Hi All,<br />
To run a compressed mod file in <a href="http://www.donevii.com/post/tag/brew" class="st_tag internal_tag" rel="tag" title="Posts tagged with brew">BREW</a> you need to create a mod loader(Approxmately 700+ bytes, atleast mine).</p>
<p>For 2.x brew devices, your mod loader file name should be same as of your app name.<br />
Ex: myapp.mif, myapp.mod(your mod loader), filename.gz(your compressed myapp.mod file, you can name this file as filename.bar so that you don&#8217;t have any problems when user disables your app).</p>
<p>For 3.x brew devices on which we can read a mod file by setting the required permissions in MIF can add this mod loader file content at the start of your compressed mod file or you can use the same as that used for 2.x which don&#8217;t required any permissions or settings in MIF.<br />
Ex: myapp.mif, myapp.mod(your mod loader + filename.gz).</p>
<p>To create a mod loader, you have every information you need in 2 threads.</p>
<p>First read only the first post by user &#8220;ajiva&#8221; in the following thread. Then return to this thread for additional info you need.</p>
<p>Quote:</p>
<p>http://brewforums.qualcomm.com/showthread.php?t=11637</p>
<p>A call to AEEMod_Load that you have seen in the first thread will set the params in the registers.</p>
<p>Quote:<br />
Note 1: Don&#8217;t release the buffer that contains the uncompressed content of your actual mod file in your mod loader. Once the actual app is closed, it will released by BREW system.<br />
Note2: Release all other allocated buffers and interfaces you created in mod loader before making a call to AEEMod_Load.</p>
<p>Thanks for ajiva and Ardy Falls for the valuable info they provided. </p>
<p>__________________<br />
Thanks everyone for the info they share here..<br />
Ramki@TTSL<br />
 VALUE HAS A VALUE ONLY IF ITS VALUE IS VALUED</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Last edited by Brewin : 08-06-2008 at 12:59 AM. </p>
<p>Brewin<br />
View Public Profile<br />
Send a private message to Brewin<br />
Send email to Brewin<br />
Find all posts by Brewin<br />
Add Brewin to Your Buddy List </p>
<p>  #4   07-29-2008, 12:36 AM<br />
Rajni<br />
Registered User   Join Date: Apr 2005<br />
Posts: 32<br />
Rep Power: 0</p>
<p> Really usefull</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Hi Ramki,<br />
Really very useful information.</p>
<p>Rajni<br />
View Public Profile<br />
Send a private message to Rajni<br />
Find all posts by Rajni<br />
Add Rajni to Your Buddy List </p>
<p>  #5   08-06-2008, 12:57 AM<br />
 Brewin<br />
Registered User   Join Date: Mar 2006<br />
Posts: 152<br />
Rep Power: 4</p>
<p> Loading and running a compressed extension mod file&#8230;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Hi all,<br />
The above procedure is not working in case if the compressed mod file is an extension. Applet compressed mod file is running fine. The decompressed file of the extension mod is Identical with the original extension mod file, but device is getting crashed when AEEMod_Load of the extension mod is executed.</p>
<p>if both an applet and extensions loads the same way then<br />
why is this difference..</p>
<p>If I use normal extension mod everything goes well.</p>
<p>Do anyone has any idea about this. </p>
<p>Quote:<br />
The extension I used is xmlparser, I will write my own extension and check does it make any difference using debug info. </p>
<p>__________________<br />
Thanks everyone for the info they share here..<br />
Ramki@TTSL<br />
 VALUE HAS A VALUE ONLY IF ITS VALUE IS VALUED</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Last edited by Brewin : 08-06-2008 at 01:02 AM. </p>
<p>Brewin<br />
View Public Profile<br />
Send a private message to Brewin<br />
Send email to Brewin<br />
Find all posts by Brewin<br />
Add Brewin to Your Buddy List </p>
<p>  #6   08-06-2008, 06:15 AM<br />
 Brewin<br />
Registered User   Join Date: Mar 2006<br />
Posts: 152<br />
Rep Power: 4</p>
<p> Loading a compressed module(Application/Extension)</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>I hope I got the resolution,<br />
Quote:<br />
Originally Posted by Brewin<br />
Hi all,<br />
The above procedure is not working in case if the compressed mod file is an extension. Applet compressed mod file is running fine. The decompressed file of the extension mod is Identical with the original extension mod file, but device is getting crashed when AEEMod_Load of the extension mod is executed.</p>
<p>if both an applet and extensions loads the same way then<br />
why is this difference..</p>
<p>If I use normal extension mod everything goes well.</p>
<p>Do anyone has any idea about this. </p>
<p>If the module irrespective of Application or Extension, is complied with standard AEEModGen.C then the MOD compression will work else the behavior is unknown.</p>
<p>Hope this helps, Please correct me if I am wrong.<br />
But since all module will have the same entry point why this happens&#8230; </p>
<p>__________________<br />
Thanks everyone for the info they share here..<br />
Ramki@TTSL<br />
 VALUE HAS A VALUE ONLY IF ITS VALUE IS VALUED</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Last edited by Brewin : 08-06-2008 at 06:17 AM. </p>
<p>Brewin<br />
View Public Profile<br />
Send a private message to Brewin<br />
Send email to Brewin<br />
Find all posts by Brewin<br />
Add Brewin to Your Buddy List </p>
<p>  #7   08-07-2008, 12:32 PM<br />
TG1e<br />
Registered User   Join Date: May 2008<br />
Posts: 3<br />
Rep Power: 0</p>
<p>Reference code please [if possible]</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Addressed to all who are working (or have worked) on this topic of loading a mod from heap mem&#8230;<br />
Will it be possible for you to post some reference code?</p>
<p>Also, for clarity&#8230;</p>
<p>Do we only have to call AEEMod_Load?<br />
Or do we have to call the other functions as well&#8230;.How does the AEE come to know that we have loaded the compressed (and now decompressed) mod? How will the AEE send events to this newly loaded mod?</p>
<p>Awaiting your response(s)&#8230;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Last edited by TG1e : 08-07-2008 at 12:34 PM. </p>
<p>TG1e<br />
View Public Profile<br />
Send a private message to TG1e<br />
Find all posts by TG1e<br />
Add TG1e to Your Buddy List </p>
<p>  #8   08-23-2008, 06:51 AM<br />
 Brewin<br />
Registered User   Join Date: Mar 2006<br />
Posts: 152<br />
Rep Power: 4</p>
<p> Loading compressed mod file..Step by Step</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Quote:<br />
Originally Posted by TG1e<br />
Addressed to all who are working (or have worked) on this topic of loading a mod from heap mem&#8230;<br />
Will it be possible for you to post some reference code?</p>
<p>What code you need, first compress you MOD file with gzip(if 7zip is used then you need to supply you own decompressor code in the mod loader or bootloader)<br />
Example: You have an application with myapp.mod, myapp.bar, myapp.mif<br />
After compressing MOD, your files are myapp.zip, myapp.bar,myapp.mif.<br />
Now write a bootloader which will load myapp.zip into memory and uncompress..</p>
<p>1. Create a project with name ex: <a href="http://www.donevii.com/post/tag/modloader" class="st_tag internal_tag" rel="tag" title="Posts tagged with modloader">modloader</a>.</p>
<p>2. copy AEEModGen.C and AEEModGen.H into your project and add the following header files<br />
AEE.h, AEEShell.h, AEEUnzipStream.h, AEEFile.h, AEEHeap.h, AEEStdLib.h.</p>
<p>3. Delete everything not related to AEEMod_Load and AEEStaticMod_New in both files and add the below line</p>
<p>Quote:<br />
For AEEMod_Load typecast&#8230;..<br />
typedef int (*RunLoadMod)(IShell *ps, void * ph, IModule ** pMod);</p>
<p>2. Delete every thing inside the AEEStaticMod_New function.</p>
<p>3. Now inside the AEEStaticMod_New function declare pointers to IUnzipAStream, IFileMgr and IFile interfaces.</p>
<p>4. Create an Instance of IFileMgr and IUnzipStream(if compressed with gzip). else<br />
provide your own decompress function here.</p>
<p>5.Now allocate some memory and copy the &#8220;ph&#8221; variable which is the pointer to AEEHelper Functions into the first four bytes of allocated memory.</p>
<p>6. Open myapp.zip and Set it for uncompressing using<br />
&#8221; IUNZIPASTREAM_SetStream &#8220;.</p>
<p>7. Now read the uncompressed stream using &#8221; IUNZIPASTREAM_Read &#8221; and copy the contents from 5th byte onwards into the same buffer using MEMCPY, REALLOC as per requirements.<br />
( Now your buffer contains pointer to AEEHelper functions + uncompressed myapp.zip, now buffer size will be a minimum of 4+sizeof(myapp.mod) ).</p>
<p>8. Once your buffer is ready with the above you are done. Release the IFileMgr, Ifile and IUnzipStream interface pointers.</p>
<p>9. Now type cast the 5th byte of the buffer to AEEMod_Load with a return statement like</p>
<p>Quote:<br />
return (RunLoadMod)(buffer+4)(pIShell,ph,ppMod);<br />
to execute the actual mod file&#8230;.  </p>
<p>Note: Don&#8217;t release the buffer, once the app exits this memory will be released by AEE.</p>
<p>You modloader is ready now.<br />
Compile and create the mod file and rename the mod file as myapp.mod.</p>
<p>Now you app contains, myapp.mif, myapp.mod, myapp.zip, myapp.bar.</p>
<p>Quote:<br />
Also, for clarity&#8230;<br />
Do we only have to call AEEMod_Load?<br />
Or do we have to call the other functions as well&#8230;.How does the AEE come to know that we have loaded the compressed (and now decompressed) mod? How will the AEE send events to this newly loaded mod?</p>
<p>When you click on your app, AEE loads the mod file associated with the app name in this case it is myapp.mod(mod loader) and executes the first address i.e AEEMod_load which will feed the actual mod to the AEE, it&#8217;s not the AEE that load your actual MOD file.</p>
<p>There is no applet related to modloader, when AEE encounter the last statement in the AEEStaticMod_New of the modloader AEE just jumps to the address where we have kept the actual MOD file and exectues from there in the process whatever is created and registered(IModuleVtbl, Applet, Applet_HandleEvent) are all belongs to the actual application mod file and AEE will send events to the registered handleEvent of the top visible applet which is nothing but your application handle Event. </p>
<p>__________________<br />
Thanks everyone for the info they share here..<br />
Ramki@TTSL<br />
 VALUE HAS A VALUE ONLY IF ITS VALUE IS VALUED</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Last edited by Brewin : 08-23-2008 at 06:59 AM. </p>
<p>Brewin<br />
View Public Profile<br />
Send a private message to Brewin<br />
Send email to Brewin<br />
Find all posts by Brewin<br />
Add Brewin to Your Buddy List </p>
<p>  #9   01-13-2009, 07:55 AM<br />
ed_est<br />
Registered User   Join Date: Jan 2009<br />
Posts: 3<br />
Rep Power: 0</p>
<p>Hi Brewin,<br />
I am interested in the functionality that you have described in this topic and I have tried to create a modloader by myself according the steps you have provided, but unfortunately my device just reboots when I am trying to execute the loaded into memory .mod file. I have tried my code on different devices with different BREW version and on all of them I had device reboot.<br />
Here is my code in AEEStaticMod_New function ( I have simplified it because I don&#8217;t use compression for .MOD file, also I have removed all checks):</p>
<p>ISHELL_CreateInstance(pIShell, AEECLSID_FILEMGR, (void**) &#038;piFileMgr);<br />
piFile = IFILEMGR_OpenFile(piFileMgr, &#8220;realmod.bin&#8221;, _OFM_READ);<br />
IFILE_GetInfo(piFile, &#038;iFileInfo);<br />
filesize = iFileInfo.dwSize;<br />
pBuf = (byte*) MALLOC (filesize + 4);<br />
MEMCPY(pBuf, ph, 4);<br />
pBuf2 = pBuf + 4;<br />
pFunc = (RunLoadMod)pBuf2;<br />
bytesread = IFILE_Read(piFile, pBuf2, filesize);<br />
IFILE_Release(piFile);<br />
IFILEMGR_Release(piFileMgr);<br />
return pFunc(pIShell,ph,ppMod);</p>
<p>Can you help me to understand why I can&#8217;t start .MOD file I have loaded by modloader? I am doing all needed steps that you provided in your post and everything seems correct for me, but maybe you will find that I am doing something wrong.</p>
<p>Thanks in advance.</p>
<p>ed_est<br />
View Public Profile<br />
Send a private message to ed_est<br />
Send email to ed_est<br />
Find all posts by ed_est<br />
Add ed_est to Your Buddy List </p>
<p>  #10   01-13-2009, 08:44 PM<br />
 Brewin<br />
Registered User   Join Date: Mar 2006<br />
Posts: 152<br />
Rep Power: 4</p>
<p>Helper functions Entry point problem&#8230;..</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Quote:<br />
Originally Posted by ed_est<br />
MEMCPY(pBuf, ph, 4); *********<br />
pBuf2 = pBuf + 4;<br />
((RunLoadMod)pBuf2)(pIShell,ph,ppMod); </p>
<p>You problem is here. It not properly copying the ph pointer(Helper functions Entry point).<br />
MEMCPY(pBuf, ph, 4);</p>
<p>__________________<br />
Thanks everyone for the info they share here..<br />
Ramki@TTSL<br />
 VALUE HAS A VALUE ONLY IF ITS VALUE IS VALUED</p>
<p>Brewin<br />
View Public Profile<br />
Send a private message to Brewin<br />
Send email to Brewin<br />
Find all posts by Brewin<br />
Add Brewin to Your Buddy List </p>
<p>  #11   01-14-2009, 06:17 AM<br />
ed_est<br />
Registered User   Join Date: Jan 2009<br />
Posts: 3<br />
Rep Power: 0</p>
<p>Brewin,<br />
Thank you very match for your help.<br />
I have fixed the this part of code and now it works.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/820.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>在BREW程序中调用另一个mod的分析</title>
		<link>http://www.donevii.com/post/817.html</link>
		<comments>http://www.donevii.com/post/817.html#comments</comments>
		<pubDate>Sun, 17 May 2009 07:10:27 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[brew]]></category>
		<category><![CDATA[c/c++/c#]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[mtk]]></category>
		<category><![CDATA[mod]]></category>
		<category><![CDATA[动态加载]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=817</guid>
		<description><![CDATA[近日读到这样一段程序。可以在程序运行时调用另一个mod文件并执行。这样可以做到应用自升级，压缩程序文件等实用的功能。    要想理解这点，先看一下正常的BREW程序加载过程。  BREW程序... ]]></description>
			<content:encoded><![CDATA[<p>近日读到这样一段程序。可以在程序运行时调用另一个mod文件并执行。这样可以做到应用自升级，压缩程序文件等实用的功能。</p>
<p> </p>
<p> 要想理解这点，先看一下正常的BREW程序加载过程。</p>
<p> BREW程序的入口，即相当于c程序的main，是位于AEEModGen.c中的AEEMod_Load函数。这可以从mak文件的连接选项中看出来。</p>
<p> </p>
<p>LINK_ORDER = -first AEEMod_Load</p>
<p> </p>
<p> 这个选项使得链接程序将该函数放在程序文件的0地址处。函数的定义如下：</p>
<p> </p>
<p>int AEEMod_Load(IShell *pIShell, void *ph, IModule **ppMod)</p>
<p>{</p>
<p>  <span> </span>// Invoke helper function to do the actual loading.</p>
<p>   return AEEStaticMod_New(sizeof(AEEMod),pIShell,ph,ppMod,NULL,NULL);</p>
<p>}</p>
<p>  </p>
<p>  BREW底层调用这个函数，需要提供三个参数。pIShell是ISHELL接口的指针，有了它就可以创建和访问其它接口。ph是helper function类函数的函数列表指针，有了它就可以调用MALLOC等函数。ppMod是用于返回给BREW底层的地址，存储生成的module的信息。</p>
<p>  AEEMod_Load函数调用了AEEStaticMod_New函数。在这个函数中初始化了module数据结构，ppMod就是指向它的。函数结束后返回BREW底层。</p>
<p>  BREW底层稍后通过存储在module数据结构中的函数指针，调用同样位于AEEModGen.c中的AEEMod_CreateInstance函数，生成该Module的某一个Applet实例。在这个函数中会调用到我们所编写的AEEClsCreateInstance函数。在我们这个函数中注册了HandleEvent函数和FreeAppDate函数。这些信息同样通过一个applet数据结构指针返回给BREW底层。这之后，BREW会通过给HandleEvent发各种Event，来驱动程序运行。</p>
<p> </p>
<p>  通过这整个过程，可以总结出BREW程序运行的必要条件。</p>
<p>  程序必须得到IShell指针，Helper Function指针，这样程序中对BREW底层各种函数的调用才能进行。BREW底层必须知道两个地址，通过它们，可以将Event传递给程序，调用FreeAppDate函数。</p>
<p>  因此，想在程序中调用另外一个mod,只需要想办法把程序里的IShell指针，Helper Function指针传递给mod，同时得到mod中的HandleEvent函数，FreeAppDate函数的地址就可以了。</p>
<p>  剩下的问题就是,程序怎样和mod文件交互呢，mod文件的格式是怎样的？</p>
<p> </p>
<p>  生成mod的mak文件最后一般有这样两句话，</p>
<p> </p>
<p>ld *.o a.elf</p>
<p>fromelf &#8211;bin a.elf a.<a href="http://www.donevii.com/post/tag/mod" class="st_tag internal_tag" rel="tag" title="Posts tagged with mod">mod</a></p>
<p> </p>
<p>  arm链接器ld生成ELF格式，之后用格式转换工具fromelf将ELF文件转换成mod文件。</p>
<p>  ELF文件是带格式的可执行文件，对它的执行要靠操作系统的解析来进行。而通过&#8211;bin选项生成的mod文件，格式却是plain binary,即赤裸裸的二进制机器指令，其实是无格式的。只要将mod文件载入内存，跳转到它的0地址处，就可以一条条指令的执行下来。和mod文件交互，也就是要安排好mod文件0地址处的内容，知道mod文件的调用者会传入什么东西，mod文件会返回什么东西。</p>
<p> </p>
<p>  </p>
<p>  下面来看一种实际的调用方法吧。代码如下：</p>
<p> </p>
<p>typedef int (*RunLoadMod)(IShell *pIShell, void *ph, IModule **ppMod);</p>
<p> </p>
<p>pData = MyLoadZip(pIShell);</p>
<p>if( !pData )</p>
<p>return EFAILED;</p>
<p>DBGPRINTF(&#8220;to RunLoadMod&#8221;);</p>
<p>if( SUCCESS != ((RunLoadMod)pData)(pIShell,ph,&amp;pOrgMod) )</p>
<p>{</p>
<p>DBGPRINTF(&#8220;RunLoadMod_Err&#8221;);</p>
<p>goto Crt_Err;</p>
<p>}</p>
<p>  </p>
<p>  这段程序将mod文件读入内存，放在pData缓冲区内，用((RunLoadMod)pData)(pIShell,ph,&amp;pOrgMod)一句执行之。RunLoadMod只不过是用typedef定义的一种函数指针类型。这句话的意思相当于是为待调用的mod文件准备好pIShell,ph,pOrgMod三个数据后，直接跳到内存中的mod文件的第一个字节处，将它当做普通机器指令一样执行。这种方法调用的mod文件，应是一个用完整的BREW框架编译后生成的。0地址处放下的是AEEMod_Load函数。Mod文件直接将Applet信息传递给BREW底层，注册HandleEvent函数。实际上是Mod文件取代了调用者的位置。</p>
<p>  </p>
<p>  但是这段程序很可能会运行失败。因为BREW底层除了传参外，还做了其它事情。这在AEEStdlib.h中可以看出。</p>
<p> </p>
<p>#define GET_HELPER()      (*(((AEEHelperFuncs **)AEEMod_Load) &#8211; 1))</p>
<p>#define GET_HELPER_VER()  (*((uint32 *)(((byte *)AEEMod_Load) &#8211; sizeof(AEEHelperFuncs *) &#8211; sizeof(uint32))))</p>
<p> </p>
<p>  这两个宏定义可以看成是两个全局常量。第一个是BREW Helper Function的函数指针表，第二个是函数指针表的版本号。上面提到的通过参数传递Helper Function函数指针，是只在模拟器上成立的。手机上其实是通过全局常量形式传递的。为保证mod可以正常运行，也应在缓冲区前保存这两个常量。</p>
<p> </p>
<p>  这种“冒名顶替”的方式，对于只想压缩一下mod的应用来说是完全可以的。但有时，我们希望新调用的mod只是整个应用的一小部分，调用者继续存在。这就需要调用者充当BREW底层的一部分角色，记住mod返回的各种信息，在适当的时候调用mod中的相应函数。新调用的mod如果想要取得主mod的信息，类似于上面提到的HelperFuncs全局常量指针的方法是个可行的选择。</p>
<p> </p>
<p>  其实知道了BREW程序的加载过程，就可以比较灵活的达到调用mod的目的，甚至BREW程序架构都是可以改动的。但是改动之后，如何在模拟器上进行调试就又成了一个问题。</p>
<p> </p>
<p>  程序中调用mod的技巧，在国外几年前就已得到了应用。甚至有家公司专门开发了利用这个技巧压缩mod的工具。</p>
<p> </p>
<p>http://www.s-cradle.com/english/products/sophiacompress_<a href="http://www.donevii.com/post/tag/brew" class="st_tag internal_tag" rel="tag" title="Posts tagged with brew">brew</a>/index.html</p>
<p> </p>
<p>参考文章：</p>
<p> </p>
<p>1.How to build A mod to load B mod?<span> </span></p>
<p> </p>
<p>http://brewforums.qualcomm.com/showthread.php?t=11637</p>
<p> </p>
<p>2.How to run mod file that is loaded in the <a href="http://www.donevii.com/post/tag/heap" class="st_tag internal_tag" rel="tag" title="Posts tagged with heap">HEAP</a>&#8230;</p>
<p> </p>
<p>http://brewforums.qualcomm.com/showthread.php?t=18413&#038;highlight=<a href="http://www.donevii.com/post/tag/modloader" class="st_tag internal_tag" rel="tag" title="Posts tagged with modloader">modloader</a></p>
<p> </p>
<p>3.深入BREW模块加载机制</p>
<p> </p>
<p>http://nicefuture.ycool.com/post.722858.html</p>
<p> </p>
<p>4.深度剖析BREW实现原理收藏</p>
<p> </p>
<p>http://blog.csdn.net/Gemsea/archive/2006/09/07/1190206.aspx</p>
]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/817.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转] 实现动态加载VXWORKS .O/.OUT模块</title>
		<link>http://www.donevii.com/post/481.html</link>
		<comments>http://www.donevii.com/post/481.html#comments</comments>
		<pubDate>Wed, 10 Sep 2008 17:23:21 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[mtk]]></category>
		<category><![CDATA[vxworks]]></category>
		<category><![CDATA[动态加载]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=481</guid>
		<description><![CDATA[转至：http://www.cnblogs.com/hpunix/articles/355758.html 整个过程为： 创建文件系统&#8211;》下载文件&#8211;》加载模块&#8211;》查找符号地址并执行 以下为演示该过程的一个简易实现文件，有使用或者引用... ]]></description>
			<content:encoded><![CDATA[<p>转至：<a href="http://www.cnblogs.com/hpunix/articles/355758.html">http://www.cnblogs.com/hpunix/articles/355758.html</a></p>
<p><span style="font-family: Arial; font-size: xx-small;">整个过程为：<br />
创建文件系统&#8211;》下载文件&#8211;》加载模块&#8211;》查找符号地址并执行</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">以下为演示该过程的一个简易实现文件，有使用或者引用的话，也<br />
打个招呼，或者给评论一下：<br />
==============START OF THE FILE=============<br />
/*********************************************************<br />
 * 版权所有 NP系统工作室。<br />
 * <br />
 * 文件名称：    \FilseSystemCreate.c<br />
 * 文件标识：    <br />
 * 内容摘要：    创建文件系统，在系统启动之后保存文件<br />
 * 其它说明： <br />
 * 当前版本：    S 1.0<br />
 * 作    者：    william<br />
 * 完成日期：    2005-10-12 17:04<br />
 * 当前责任人-1：william<br />
 *<br />
 * 修改记录1：   <br />
 *    修改日期：2006-3-21 12:00<br />
 *    版 本 号：S 1.0<br />
 *    修 改 人：william<br />
 *    修改内容：创建 <br />
 * 修改记录2：<br />
 **********************************************************/</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">#include &lt;taskLib.h&gt;<br />
#include &lt;<a href="http://www.donevii.com/post/tag/vxworks" class="st_tag internal_tag" rel="tag" title="Posts tagged with vxworks">vxWorks</a>.h&gt;<br />
#include &lt;stdio.h&gt;<br />
#include &lt;string.h&gt; <br />
#include &lt;ioLib.h &gt;<br />
#include &lt;symLib.h &gt;<br />
#include &lt;loadlib.h &gt;</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">#include &#8220;dosFsLib.h&#8221;<br />
#include &#8220;ramDrv.h&#8221;<br />
#include &#8220;usrLib.h&#8221;</span><br />
<span style="font-family: Arial; font-size: xx-small;">typedef int                       STATUS;<br />
#define ERROR                     -1<br />
#define OK                        0<br />
#define DIAG_RAM_DISK_SIZE        (0&#215;100000*10)  /* 64M */<br />
#define DIAG_RAM_DISK_NAME        &#8220;/selfdev/&#8221;</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">STATUS FileSystem_Init()<br />
{<br />
    BLK_DEV     *pBlkDev;<br />
    char        *pFileSysRamDiskBase = NULL;<br />
    <br />
    ramDrv();<br />
    pFileSysRamDiskBase = malloc(DIAG_RAM_DISK_SIZE);<br />
    if(NULL == pFileSysRamDiskBase)<br />
        return ERROR;<br />
        <br />
    bzero(pFileSysRamDiskBase,DIAG_RAM_DISK_SIZE);</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">    pBlkDev = ramDevCreate( pFileSysRamDiskBase,  <br />
                            /* start address */                <br />
                            512,        <br />
                            /* sector size */                                                  <br />
                            64,     <br />
                            /* sectors per track */                                                      <br />
                            (int)(DIAG_RAM_DISK_SIZE/512),    <br />
                            /* total sectors 64 MBytes */<br />
                            0);                               <br />
                            /* offset */<br />
    if(NULL == pBlkDev)<br />
    {<br />
        free(pFileSysRamDiskBase);<br />
        return ERROR;<br />
    }</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">    if(NULL == dosFsMkfs (DIAG_RAM_DISK_NAME, pBlkDev))<br />
    {<br />
        free(pFileSysRamDiskBase);<br />
        return ERROR;</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">    }</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">    return OK;<br />
}</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">extern SYMTAB_ID sysSymTbl ;<br />
void runModule()<br />
{<br />
    STATUS status=ERROR;<br />
    int fd;     <br />
    MODULE_ID hModule ;<br />
    FUNCPTR taskEntry = NULL ;<br />
    SYM_TYPE * pType ;</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">    if ((fd = open(&#8220;/selfdev/youown.o&#8221;, O_RDONLY, 0)) &lt; 0) <br />
    {<br />
          printf(&#8220;\nCannot open memory device.\n&#8221;);<br />
          goto done;<br />
    }<br />
     <br />
    if ((hModule=loadModule(fd,LOAD_ALL_SYMBOLS))==NULL)<br />
    {<br />
        printf(&#8220;loadModule error = 0x%x.\n&#8221;,errno) ;<br />
        goto done;<br />
    }<br />
   <br />
    status = symFindByName(sysSymTbl,<br />
                           &#8220;willian_test&#8221;,<br />
                           (char **)&amp;taskEntry,pType ) ;<br />
    if (status==ERROR)<br />
    {<br />
          printf(&#8220;symFindByName error=%d\\n&#8221;, errno) ;<br />
          goto done;<br />
    }<br />
    else<br />
    {<br />
        printf(&#8220;taskEntryr=0x%x, type=%d\n.&#8221;,<br />
                    (int)taskEntry,(int)*pType);         <br />
        status = taskSpawn(&#8220;test1&#8243;,<br />
                           100,<br />
                           0,<br />
                           30000,<br />
                           taskEntry,<br />
                           0,0,0,0,0,0,0,0,0,0) ;<br />
        if (status==ERROR)<br />
        {<br />
            printf(&#8220;taskSpawn error=%d\n&#8221;,errno) ;<br />
            goto done;<br />
        }<br />
    }<br />
    <br />
done: <br />
     if (fd &gt;= 0)<br />
       close(fd);    <br />
}</span></p>
<p> </p>
<p><span style="font-family: Arial; font-size: xx-small;">int downLoadModules(<br />
    char *hostName,<br />
    char *srcfileName,<br />
    char *destfileName,<br />
    char *usr,<br />
    char *passwd)<br />
{<br />
    &#8230;&#8230;&#8230;<br />
    /*实现下载远端PC模块到本地机*/</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">    return (filesize);<br />
}</span><br />
<span style="font-family: Arial; font-size: xx-small;">STATUS test_dynamic_download()<br />
{<br />
    STATUE status = OK;<br />
    int fileLenth = 0;<br />
    <br />
    status = FileSystem_Init();<br />
    if(status == ERROR)<br />
    {<br />
        printf(&#8220;\nerror occured during init file system\n&#8221;);<br />
        return ERROK;        <br />
    }<br />
    <br />
    fileLenth = downLoadModules(&#8220;winner2&#8243;,<br />
                                &#8220;youown.o&#8221;,<br />
                                &#8220;/selfdev/youown.o&#8221;,<br />
                                &#8220;target&#8221;,<br />
                                &#8220;target&#8221;);<br />
    if(ERROR == fileLenth)<br />
    {<br />
        printf(&#8220;\nSome error occured when download files\n&#8221;); <br />
        return ERROK;                 <br />
    }                                <br />
    else<br />
    {<br />
        if(0 == fileLenth)  <br />
        {<br />
            return OK;    <br />
        }<br />
    }<br />
    <br />
    runModule();<br />
}<br />
=============END OF THE FILE==========</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">几个需要注意的问题：<br />
1：在文件系统初始化中使用的是MALLOC，该部分是使用的实际是<br />
   BSP的空间在实际申请的过程中一定要根据自己可能拷贝的文<br />
   件大小和实际的BSP的空间</span></p>
<p><span style="font-family: Arial; font-size: xx-small;">2：在创建文件系统之后，可以查看该目录的文件列表，或者执行<br />
   COPY，前提是必须在TORNADO中选择初始化文件系统组件；<br />
   <br />
3：在下载文件的过程中，有的BSP初始化已经可以直接通过COPY<br />
   在远端FTP SERVER直接拷贝文件，比如：<br />
         copy &#8220;youown.o&#8221;,&#8221;/selfdev/youown.o&#8221;<br />
   这种情况没有必要再调用downLoadModules，至于如何使能，<br />
   大家关注的话可以在后边对其专门论述。     </span></p>
<p><span style="font-family: Arial; font-size: xx-small;">4：加载模块的过程可以调用如下代码：<br />
        if ((hModule=loadModule(fd,LOAD_ALL_SYMBOLS))==NULL)<br />
    同样也可以如下实现：<br />
        ld(1,0,&#8221;/selfdev/youown.o&#8221;);<br />
    至于各个参数什么意思，参考HELP就可以找到结论了！<br />
    <br />
    <br />
5：在    status = symFindByName(sysSymTbl,<br />
                           &#8220;willian_test&#8221;,<br />
                           (char **)&amp;taskEntry,pType ) ;<br />
   中，有可能实际返回错误，但是通过lkup 是可以实际找到的，<br />
   对于这个问题，我看网上答案比较少，原因是这样的：<br />
   <br />
   假如你在主机运行shell,默认的远端目标机是没有符号表<br />
   （symbol table）的，只有在主机的shell上，你运行LKUP的<br />
   时候，才能找到这个符号，不信你可以这样尝试一下，打开两<br />
   个SHELL，一个通过串口，一个通过TORNADO的网口，你在其中<br />
   一个中能够使用LKUP找到，而在另外一个则不能找到，是不是<br />
   呀？？   <br />
       接下来继续解释，我们的symFindByName是在目标机器上<br />
   执行的，所以自然的就返回错误了，也是没有找到了！<br />
       解决方法是这样的：在目标机中包含符号表，同时将其和<br />
   主机保持同步。<br />
   Wind River told us to include all this defines in the <br />
        config files for the target:<br />
        <br />
       #define INCLUDE_SYM_TBL_SYNC<br />
       #define INCLUDE_LOADER<br />
       /* object module loading */<br />
       #define INCLUDE_NET_SYM_TBL  <br />
       /* load the symbol table by whatever means */<br />
       #define INCLUDE_SHELL <br />
       /* target-based shell */<br />
       #define INCLUDE_SHOW_ROUTINES <br />
       /* optional target-based system utilities */<br />
       #define INCLUDE_STAT_SYM_TBL  <br />
       /* optional target error status routines */<br />
       #define INCLUDE_SYM_TBL         <br />
       /* symbol table package */<br />
       #define INCLUDE_UNLOADER        <br />
       /* optional object module unloading */<br />
       #define INCLUDE_WDB</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/481.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[转] 嵌入式单地址空间中实现动态加载的过程</title>
		<link>http://www.donevii.com/post/479.html</link>
		<comments>http://www.donevii.com/post/479.html#comments</comments>
		<pubDate>Wed, 10 Sep 2008 16:42:23 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[mtk]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[nucleus]]></category>
		<category><![CDATA[动态加载]]></category>
		<category><![CDATA[嵌入式]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=479</guid>
		<description><![CDATA[转至：http://blog.csdn.net/pengzhenwanli/archive/2008/04/23/2319412.aspx#875603 之前有一篇文章是关于嵌入式单地址空间实现动态加载的想法，里面描述的是我根据相关资料进行猜测的地方，以及从技术上来说... ]]></description>
			<content:encoded><![CDATA[<p>转至：<a href="http://blog.csdn.net/pengzhenwanli/archive/2008/04/23/2319412.aspx#875603">http://blog.csdn.net/pengzhenwanli/archive/2008/04/23/2319412.aspx#875603</a></p>
<p class="MsoNormal"><span>之前有一篇文章是关于嵌入式单地址空间实现动态加载的想法，里面描述的是我根据相关资料进行猜测的地方，以及从技术上来说，可能需要的技术，最近难得有空闲时间，我实现了一下动态加载的。目前已经成功实现，下面说一下实现的过程。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span>先说一下实现此技术需要的平台：</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';">OS</span></span><span>：</span><span lang="EN-US"><span style="font-family: 'Times New Roman';"><a href="http://www.donevii.com/post/tag/nucleus" class="st_tag internal_tag" rel="tag" title="Posts tagged with nucleus">Nucleus</a></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';">CPU</span></span><span>：</span><span lang="EN-US"><span style="font-family: 'Times New Roman';"><a href="http://www.donevii.com/post/tag/arm" class="st_tag internal_tag" rel="tag" title="Posts tagged with arm">ARM</a>7+cache</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';">Baseband</span></span><span>：</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">VT3406</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';">ADS1.2</span></span></p>
<p class="MsoNormal"><span>说一下这些东西的来历，</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">Nucleus</span></span><span>是实时嵌入式单地址空间操作系统，</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">CPU</span></span><span>是介于</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">ARM7</span></span><span>与</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">ARM9</span></span><span>之间的</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">CPU</span></span><span>，</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">BB</span></span><span>芯片是</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">VIA</span></span><span>出的，这些东西目前都已经收掉不再使用，我也正好离职，从而有时间去实现一下动态加载的问题。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span>从理论上来说，动态加载很简单，只需要把当前的</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">PC</span></span><span>指针指向下一句执行的语句即可。也就是使用如下的</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">ASM</span></span><span>就可以实现：</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';">MOV PC, Address</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>这样就可以顺利执行程序，在我实现的时候，考虑如下问题，程序执行如何返回，参数如何传递，程序执行完毕返回到哪里。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>这些问题的解决，看起来比较复杂，其实很简单，程序的返回是放在</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LR</span></span><span>中，这样在上一个函数调用的时候，只要</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LR</span></span><span>的值不变，这样可以在下一个函数调用的时候，同样使用</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LR</span></span><span>，这样就可以顺利返回。关于参数传递，由于</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">ARM</span></span><span>中使用</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">r0-r3</span></span><span>传递参数，这样只要不更改</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">r0-r3</span></span><span>，就可以顺利传递参数。这个地方想明白，我用了好久，特别是返回地址的问题，程序如何执行，应该返回哪里。解决方法如下</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>实现</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">DynamicLoader(UINT8 *pAddress)</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';">MOV PC, R0</span></span></p>
<p class="MsoNormal"><span>这个地方一定要用</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">ASM</span></span><span>实现，否则无法完成需要的功能。由于在调用此函数时，已经把函数的返回地址放到</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LR</span></span><span>中，具体</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">ASM</span></span><span>如下：</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';">MOV r0,address</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';">BL DynamicLoader</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>由于</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">DynamicLoaer</span></span><span>的实现问题，没有实际的返回，也就是不需要使用</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';">BX lr</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>这样来做为函数的返回。这是由于</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">R0</span></span><span>所指向的一个函数的开始地址，从</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">DynamicLoader</span></span><span>开始，其实执行的是另一个函数，这里的</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">DynamicLoader</span></span><span>只是起到了一个跳转的作用。但是又必须使用函数调用的方式来进行，而不能直接跳转，否则函数没有办法返回。由于</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">BL</span></span><span>的时候填充了</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LR</span></span><span>，这样在下一个由于实际调用不是使用的</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">B</span></span><span>指令，因为并没有设置</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LR</span></span><span>，这样仍旧是在调用</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">DynamicLoader</span></span><span>时的</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LR</span></span><span>，因此可以正确返回。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>函数可以正确调用并返回，这是程序很大的一个进步，这样就可以实际构造可以运行的程序了。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>下面说一下</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">ADS</span></span><span>编译为二进制可执行文件的问题，使用编译器如果一开始把所有的数据都放好，这样包括全局变量和静态变量，以及函数的执行地址等，都已在</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LINK</span></span><span>的时候根据指定规则确定实际的运行地址，也就是说所有的函数的实际运行地址在</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LINK</span></span><span>的时候已经确定。这样对于动态运行来说是不可行的，因为既然要动态加载，就需要所有地址都是静态的，因为每次对于读入内存的数据，起始地址是不缺定的，因此不能再</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LINK</span></span><span>时把所有的地址固定死。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>解决这个问题有两种方式，一种是在</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">scatter loader</span></span><span>中把程序的可执行地址固定好，在</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LINK</span></span><span>时不</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LINK</span></span><span>实际的数据，而在系统启动的时候，把这部分可执行文件拷贝的固定的地址，这样可以作为一个整体运行。但是这种方式由问题，就是应用的大小什么的都是固定死的，不能太灵活，不能根据应用实际调整。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>这里使用另外一种方式，选择程序不在</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LINK</span></span><span>的时候把所有的地址固定死，而是使用相对独立的函数调用方式。如下：</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>原来的方式可能使这这样</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';"><span>       </span>BL 0&#215;10008;</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>而使用相对的地址程序如下：</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';"><span>       </span>ADD r5,pc,#18</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';"><span>       </span>BL r5</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>这样虽然多了一句，但是可以做到函数的运行地址是动态指定的，而不是编译为固定的地址。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>其实</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">ADS</span></span><span>提供了把函数编译为独立地址的方式，</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';"><span>       </span>COMPILER</span></span><span>使用如下的参数</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">/ropi/rwpi</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';"><span>       </span>LINK</span></span><span>使用如下的参数</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">-rwpi –ropi</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>就可以把编译的程序做到运行时地址是独立的。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>从上面来开，编译时地址的问题，还有运行时加载的问题，都已经顺利解决。但是这里还有一个问题，就是如何确保动态应用如何每次在使用的时候，都从固定的入口进入的问题。也就是说，虽然有了内存中的运行地址，但是如何保证每次都从固定的函数开始执行呢？如果每次都从编译的可执行文件</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">0</span></span><span>地址开始执行，没有办法保证每次调用的是同一个函数。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>这个可以通过</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LINK</span></span><span>来保证每次是同一个函数在</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">0</span></span><span>地址，使用如下的参数</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: 'Times New Roman';">-first DyanmicAppEntry</span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>这样就可以保证</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">DyanmicAppEntry</span></span><span>的入口地址为可执行文件的开始了。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>上面的文章解决了动态编译和加载的问题，下面说一下动态应用的问题。如果要使一个应用有价值，比然需要提供本地的功能调用，而且对于手机来说，系统已经基本上实现了大多数的功能，如果在动态应用中再重复实现一些功能，可以说既浪费了空间，又浪费了时间。而且对于硬件相关的功能，必须通过本地调用来进行，这样就需要如何把本地调用传入动态应用中。如上文所说，本地的调用地址都是在</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">LINK</span></span><span>的时候确定的没有办法直接在动态应用中使用，这样需要在运行时把本地调用传入动态应用，由于动态应用的入口还有好几个参数可以使用，这样就可以构造一张系统调用的表，在运行的时候传入动态应用，这样可以通过表来调用系统功能，这样就解决了系统本地调用的问题。</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span lang="EN-US"><span><span style="font-family: 'Times New Roman';">       </span></span></span><span>这里要特别说一下安全的问题，由于动态应用是直接更改</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">PC</span></span><span>指针运行的，这样，如果应用出错，系统可能就</span><span lang="EN-US"><span style="font-family: 'Times New Roman';">CRASH</span></span><span>了，无法再继续运行，而且由于可以调用本地系统调用，可能做许多意想不到的功能，这样就可以在系统调用的时候</span><span lang="EN-US"></span></p>
<p class="MsoNormal"><span>增加一个中间层，一些核心功能，必须满足一定的权限在可以调用。</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/479.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转] 在嵌入式单地址空间OS中实现动态加载的问题</title>
		<link>http://www.donevii.com/post/477.html</link>
		<comments>http://www.donevii.com/post/477.html#comments</comments>
		<pubDate>Wed, 10 Sep 2008 16:37:41 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[mtk]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[dynamic load]]></category>
		<category><![CDATA[动态加载]]></category>
		<category><![CDATA[嵌入式]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=477</guid>
		<description><![CDATA[转至：http://blog.csdn.net/pengzhenwanli/archive/2007/02/26/1514689.aspx 本文的的主要想法是来源于手持设备可运行应用程序和如何实现智能机问题的思考。问题的主要来源是关于可扩充应用程序的考虑，目... ]]></description>
			<content:encoded><![CDATA[<p align="left">转至：<a href="http://blog.csdn.net/pengzhenwanli/archive/2007/02/26/1514689.aspx">http://blog.csdn.net/pengzhenwanli/archive/2007/02/26/1514689.aspx</a></p>
<p align="left"><span style="font-size: small;">本文的的主要想法是来源于手持设备可运行应用程序和如何实现智能机问题的思考。问题的主要来源是关于可扩充应用程序的考虑，目前大部分手机都是非智能机，也就是不能扩充应用程序</span></p>
<p align="left"><span style="font-size: small;">1.智能手机与非智能手机<br />
        一般来说，智能手机目前公认三大系统，Windows Mobile，Linux和Symbian，也即是说采用这三种系统的手机，都成为智能机。我认为，从技术上来讲，智能机最主要的特征就是第一可扩充应用程序，也就是说用户可以自行安装需要的程序而不局限于手机自带的，第二就是多用户任务，也就是用户具有同时运行多个应用程序的权力。而非智能手机的操作系统可以说是五花八门，什么都有。但是基本上都有一个核心的特征，就是同时只能运行一个应用程序，而且所有的应用程序都运行在相同的地址空间，而智能机是运行在独立地址空间。一般来说，非智能机也支持多任务，不同的是这些任务共用相同的地址空间。用户操作的UI就是一个单独的任务，用户所能使用的功能基本上就是由UI提供的。<br />
        我原来对于非智能机是非常的不屑，认为没有什么发展前途，但是我最近又弄了一个非智能机的手机用了一下，发现很多功能都非常的人性化，从使用上来讲，并不亚于智能机，由此引发了我对于非智机功能的思考。对于智能机来讲可扩充的应用程序一般来说，都是由第三方开发商开发的，稳定性都有所缺陷，并不如原生的系统应用程序稳定。而且有些比较好的用程序价格不菲，我见过使用智能机的人大部分都是使用破解的应用程序，我本人也是。这个行为是违法的，当市场成熟以后，比如像美国，是不太可能的。</span></p>
<p align="left"><span style="font-size: small;">        智能机由于操作系统功能强大，一般要求系统的硬件性能强劲，这样相应的功耗也大，待机时间相应的缩短。非智能机可以运行在性能较差的硬件上，并且获得的UI表现，不弱于智能机。这样就可以在相同的电力消耗的情况下，获得更长的使用时间。<br />
2.非智能机获得智能机功能必须的要求<br />
        如上文所说，只要非智能机实现智能机最主要的两个特征即可获得智能机的功能。一个是用户自行安装应用程序的功能。另一个是同时运行多个应用程序的功能。<br />
3.用户自行安装应用程序的功能<br />
        除了智能机以外，目前有两种技术都实现了用户可自行安装应用程序的功能，一个是BREW另一个是Java ME(J2ME)。下面分别说一下这两种技术，BREW技术由Qualcomm（高通）创建，包括一整套的体系，从运营到分发都有。在本文里只是对于客户端技术的说明，对于BREW技术而言，已经非常符合本文中所提及的技术，本文从另一方面来讲，也可以说是分析了BREW的基本技术。BREW技术高通把持的非常严密，目前而言，并没</span><span style="font-size: small;">有开放源代码而且对于技术内部也是进行严密的封锁，因此目前出现的文章都是猜测技术的实现，但是对于技术来讲，万变不离其宗，要实现某种技术，有些东西是绕不开的，就像使用CDMA技术，无论是WCDMA，CDMA2000，还是TDS-CDMA都无法绕开CDMA的基本专利一样。BREW技术基本达到了本文的技术要求，既能动态加载，也能同时运行多个任务，而且对于系统功能的使用不像JavaME一样有严重的限制，基本上来说，可以使用系统提供的所有功能。而对JavaME，所提供的功能十分有限，就连存取本地文件都不可以。对于系统功能的使用，如果没有附加的支持，基本上不可能，目前应用最得的是游戏，最多有些网络方面的应用。对于提供系统级别的应用，比如说闹钟等，根本无能为力。也许以后能够提供，但是本人不太看好。另外还有一个就是Flash Lite技术，这个技术我并没有接触，就不详细说了。对于BREW和JavaME我都有相当长时间的接触，了解也比较细致，有些问题还是能够说一下的。<br />
        要解决用户可以自行安装应用程序的问题，必须解决以下几个问题，应用程序的加载运行问题，系统API的调用问题。<br />
3.1应用程序加载<br />
        对于嵌入系统来讲，与通常的Windows系统不一样，Windows的所用应用程序都在硬盘上，运行的时候根据需要加载到内存中，在运行，或者是使用虚拟内存技术，直接映射的硬盘也可以执行。而嵌入式系统通常是在ROM中，并不需要加载到内存才能运行，直接就可以运行，因此大部分的嵌入式系统都是统一做好一个系统的Image，然后放到ROM中运行。这样所有的地址都在编译期间确定，要是再动态加载应用程序，将会面临运行时地址确认的问题。一般而言，对于嵌入式系统，ROM使用Flash来代替，Flash中一部分作为ROM，另一部分作为嵌入式的文件系统，具体的系统格式这里不作考虑。要是可加载应用程序的话，一般来说是放在文件系统中。这样要运行可动态加载的应用程序，并不复杂，只要把应用程序调入内存中，运行时设置正确的寄存器就可以了。</span></p>
<p align="left"><span style="font-size: small;">这里也就是把可执行的文件加载到内存中，由于是单地址空间的，而不是像Windows一样每个应用程序都是独立的地址空间，这样应用程序可以从任意地址开始执行，这样载入内存以后，把当前的执行指针PC这为此内存地址即可。这也是单地址空间的程序可以执行的关键。</span></p>
<p align="left"><span style="font-size: small;">3.2系统API的提供</span></p>
<p align="left"><span style="font-size: small;"> 要提供可以运行时call的API，在单地址空间可加载应用程序的约束条件下，可以使用的方法也非常的单调。一般来说，单地址空间的应用程序是统一编译和链接的，这样生成可执行文件以后，所有的地址已经固定了，这样如</span><span style="font-size: small;">3.1所说，应用程序如果每个都调用相同的系统API，比如memset等，由于应用程序时独立加载的，这样由于在编译过程中已经把所有的地址确定，所以每个应用必须链接独立的lib，这样造成了空间浪费。如果只是单独的应用，不提供这一步，系统已经可以动态加载了。</span></p>
<p align="left"><span style="font-size: small;">但是目前是要求在嵌入式单地址空间实现，必须考虑空间的问题。因此必须解决系统库可以动态加载的问题。也就是库的地址不是在链接的时候确定。</span><span style="font-size: small;">只要能够解决编译时的链接问题，就可以做到。</span></p>
<p align="left"><span style="font-size: small;">关于<br />
4.同时运行多个应用程序的功能</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/477.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

