<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
	<channel>
		<title>CoolCode.Org</title>
		<link>http://www.coolcode.org/</link>
		<description>人的头脑太复杂,时间过得久,有时候连自己也被自己骗了,记下来才是最真实的......</description>
		<copyright>Copyright (C) 2004 Security Angel Team [S4T] All Rights Reserved.</copyright>
		<generator>SaBlog-X Version 1.6 Build 20080806</generator>
		<lastBuildDate>Thu, 09 Feb 2012 20:06:46 +0000</lastBuildDate>
		<ttl>30</ttl>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=386</guid>
			<title>系统汉化</title>
			<author>andot</author>
			<description><![CDATA[<p>&nbsp;要对系统进行汉化与其说是个技术活，不如说是个力气活，但确实又少不了细心。系统汉化可以分为应用汉化、框架汉化、Luna汉化和其它部分汉化。</p>
<h1>应用汉化</h1>
<p>ROM中预先安装好的应用都在rootfs/usr/palm/applications中，对每个应用汉化时要注意，不同的程序编写方式，汉化方式也不一样。mojo和enyo的程序在多国语言化方面有些差异。</p>
<h2>MOJO程序汉化</h2>
<p>mojo程序汉化时，在相应的包名目录下，建一个resources/zh/cn目录。</p>
<p>如果要汉化桌面图标上的显示文字，全局搜索等内容，你需要建立一个appinfo.json的文件，这个文件内容可以直接把从软件包中的这个文件复制过去然后修改，修改时需要注意，图标位置，执行文件的位置等内容，一定要加上../../../这样的路径，否则这些文件找不到。</p>
<p>如果你要汉化js中的那些为实现多国语言已经做了处理的字符串（就是用$L()包含的那些字符串），那你需要再建立一个strings.json文件，其中的内容格式为：</p>
<div class="codeText">
<ol start="0" class="dp-c">
    <li class="alt"><span><span>{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="string">&quot;OK&quot;</span><span>:&nbsp;</span><span class="string">&quot;确定&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="string">&quot;Cancel&quot;</span><span>:&nbsp;</span><span class="string">&quot;取消&quot;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>}</span>&nbsp;&nbsp;</li>
</ol>
</div>
<p>如果字符串中包含一些特殊字符，一定要注意要用json的转义方式来写。</p>
<p>还有些需要汉化的字符串是在views中的html中的，这些内容的汉化，只需要在这个目录下建立对应的目录，将原始的html复制到这些目录下，对其进行汉化即可。</p>
<p>有时候汉化还涉及到css的一些调整，同样把css文件复制过来做修改就可以啦。</p>
<h2>ENYO程序汉化</h2>
<p>enyo的程序汉化相对来说简单些。</p>
<p>对appinfo.json的汉化与mojo相同。</p>
<p>对字符串的汉化只需要在resources下建一个zh_cn.json的文件就可以了，内容格式跟mojo的strings.json格式相同。</p>
<p>enyo没有views这种东西，所以就不用管了。</p>
<h1>框架汉化</h1>
<p>在rootfs/usr/palm/frameworks下的许多框架文件也需要汉化。具体那些文件需要汉化就不说了，可以参考其它多语言化文件来处理。</p>
<p>frameworks这里面有些目录在一些比较新版本的原始ROM中就已经包含了汉化内容，比如mojo，mojo2，enyo这些目录，所以如果发现他们里面原本就有汉化内容的，就不需要重复汉化了。</p>
<h1>LUNA汉化</h1>
<p>在rootfs/usr/lib/luna下，有部分资源是需要汉化的，其中包括luna-network和system。汉化的内容跟汉化的方法跟mojo应用程序相同。</p>
<p>其中关于信标的汉化最主要的部分也在这里。在rootfs/usr/lib/luna/system/luna-systemui/resources/zh/cn/strings.json中，添加：</p>
<div class="codeText">
<ol start="0" class="dp-c">
    <li class="alt"><span><span class="string">&quot;CHINA&nbsp;&nbsp;MOBILE&quot;</span><span>:&nbsp;</span><span class="string">&quot;中国移动&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="string">&quot;CHN-UNICOM&quot;</span><span>:&nbsp;</span><span class="string">&quot;中国联通&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="string">&quot;China&nbsp;Telecom&quot;</span><span>:&nbsp;</span><span class="string">&quot;中国电信&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="string">&quot;China&nbsp;Unicom&quot;</span><span>:&nbsp;</span><span class="string">&quot;中国联通&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="string">&quot;CMCC&quot;</span><span>:&nbsp;</span><span class="string">&quot;中国移动&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<p>就可以实现对信标的汉化了。注意上面&quot;CHINA &nbsp;MOBILE&quot;中间是两个空格，而不是一个。</p>
<p>但要实现更完美的信标汉化，还需要在：</p>
<p>rootfs/usr/palm/applications/com.palm.app.phoneprefs/resources/zh/cn/strings.json</p>
<p>rootfs/usr/palm/sysmgr/localization/zh_cn/strings.json</p>
<p>里面都添加上这一段内容。</p>
<p>对于一卡多号的用户来说，上面这些数据可以能对您的信标中文化无效，因为一卡多号的卡里面的信标内容跟上面的是不同的，有同学反映他的一卡多号的信标后面还带有手机号，所以对于这种卡就没办法做统一的汉化了，但是使用者可以按照这种方法，把自己那些特殊的信标加到这里面。</p>
<h1>其它部分汉化</h1>
<p>在rootfs/usr/palm/public和rootfs/usr/palm/sysmgr里面也有一点资源需要汉化。至于那些文件，可以参考这里面的其它语言的资源。</p>
<p>这里主要提一点关于启动器中那些页面标题的汉化，这些标题的汉化可以在rootfs/usr/palm/sysmgr/localization/zh_cn/strings.json中添加上。</p>
<p>而且不但可以添加默认的那几个（Applications、Extras、System这些），你还可以添加用户可能会建立的新页面的标题，比如Games、News等，这些添加之后，用户在建立具有这些名称的页面之后，当再次重启系统时候，这些英文名在中文界面下也会自动变成中文了。</p>
<p>最后还要强调一下，汉化是个细心的活，要想完美汉化，对每个词每个句子甚至每个缩写都要字斟句酌才能得到完美的结果。</p>
<p>举个例子，比如在日历的汉化中，有几个英文序数词结尾的汉化，这些序数词后缀分别是&quot;nd&quot;、&quot;rd&quot;、&quot;st&quot;、&quot;th&quot;，如果你不了解上下文，当看这几个词你可能不知道什么意思（但如果你够聪明的话，当看到这几个摆在一起时应该也会想到）。我们知道在中文里序数词和基数词是没区别的（如果非要说有区别的话，那区别就是中文的序数词是在基数词前面加一个&ldquo;第&rdquo;字），那么在汉化这几个词时，我们就应该把它们汉化为空字符串，而不应该原样保留（因为我们没办法把后缀汉化改成前缀汉化，所以不能把它们汉化成&ldquo;第&rdquo;）。</p>
<p>类似的地方还有好多，这里仅仅是举个例子。从这里我们可以看出，汉化的确不是一件容易的事情，所以，在这里我要向一直以来提供系统汉化包的开发者们表示崇高的敬意！</p>
<h1>汉化包的打包</h1>
<p>汉化包在打包时，如果考虑到集成到ROM中，并且可以方便卸载的话，最好的方式是把这些新添加的汉化资源单独拿出来打成一个包，这些资源在包里面就以原始路径存在，不需要postinst、postrm之类的脚本，直接打包之后，放在&lt;carrier&gt;.tar中就可以啦。</p>
<p>这样做的好处是，便于汉化包的卸载和升级。</p>
<p>但是这种包直接提供给用户安装的话，用户还需要一定的Linux命令行知识，能够自己使用ipkg命令来安装卸载包才行。因为这些包是不能通过preware、WQI来安装的，否则安装位置是不对的。</p>
<p>现在直接提供给用户安装的汉化包，大部分都是以应用程序方式来打包，然后通过postinst方式来将汉化资源再复制到相应的汉化目录下。这种汉化包对用户来说，便于使用preware、WQI来安装，但是却不方便卸载，也不方便集成到ROM中。</p>
<p>所以，两种方式各有利弊，根据具体情况来做选择就行了。</p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=386</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-11-27 17:31</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=385</guid>
			<title>将ROM分解为IPK</title>
			<author>andot</author>
			<description><![CDATA[<p>&nbsp;前面6节基本上已经把ROM定制的具体过程都讲完了。从这节开始，我们来讨论一点高级内容。不过本人水平有限，以下内容算是抛砖引玉了。</p>
<p>前面在ROM文件结构一节中，我们已经提到，rootfs下的大部分文件都是预安装好的包，那我们有没有可能将这些包都还原为ipk呢？</p>
<p>当然可以。</p>
<p>下面我们就来看一下这个过程该如何实现。</p>
<p>首先我们需要把ROM分解，分解的工具最方便的还是使用MetaDoctor里面的unpack-doctor这个脚本。在Linux下，我们最好是用root帐号来执行这个命令，以保证包中文件的权限不会改变。</p>
<p>展开之后，我们可以在rootfs/usr/lib/ipkg/info中找到所有已安装的包的control文件，因为每个包都有一个对应的control，所以我们以这个control文件为依据，就可以列出系统内所有的包。</p>
<p>之后循环读取这些control文件名，然后通过它来获取包名，然后用包名为该包建立一个目录，在其中再创建CONTROL和data这两个目录，然后把control复制（或移动）到CONTROL目录下，然后把该包对应的preinst、postinst、prerm、postrm脚本也都统统复制（或移动）到CONTROL目录下，最后再根据list文件中的内容，将该包中包含的文件及其目录复制（或移动）到data目录下，最后使用ipkg-build脚本，对该目录进行打包就可以啦。</p>
<p>下面是将ROM分解为ipk文件的完整脚本：</p>
<div class="codeText">
<ol start="0" class="dp-perl">
    <li class="alt"><span><span class="comment">#!/bin/sh</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>[&nbsp;-f&nbsp;<span class="vars">$1</span><span>&nbsp;]&nbsp;||&nbsp;</span><span class="keyword">exit</span><span>&nbsp;1&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>currpath=`pwd`&nbsp;&nbsp;</span></li>
    <li class=""><span><span class="vars">$currpath</span><span>/</span><span class="func">unpack</span><span>-doctor&nbsp;</span><span class="vars">$1</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>NAME=`basename&nbsp;<span class="vars">$1</span><span>&nbsp;.jar`&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>rm&nbsp;-rf&nbsp;<span class="vars">$NAME</span><span>/ipkgs&nbsp;</span><span class="vars">$NAME</span><span>/build&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="func">mkdir</span><span>&nbsp;-p&nbsp;</span><span class="vars">$NAME</span><span>/ipkgs&nbsp;</span><span class="vars">$NAME</span><span>/build&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>cd&nbsp;<span class="vars">$NAME</span><span>/ipkgs&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>ROOTFS=<span class="vars">$currpath</span><span>/</span><span class="vars">$NAME</span><span>/rootfs&nbsp;&nbsp;</span></span></li>
    <li class=""><span>INFOPATH=<span class="vars">$ROOTFS</span><span>/usr/lib/ipkg/info&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>ls&nbsp;<span class="vars">$INFOPATH</span><span>/*.control&nbsp;|&nbsp;</span><span class="keyword">while</span><span>&nbsp;</span><span class="func">read</span><span>&nbsp;control;&nbsp;</span><span class="keyword">do</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">package</span><span>=`basename&nbsp;</span><span class="vars">$control</span><span>&nbsp;.control`&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;PACKAGE=<span class="vars">$currpath</span><span>/</span><span class="vars">$NAME</span><span>/build/</span><span class="vars">$package</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;CONTROL=<span class="vars">$PACKAGE</span><span>/CONTROL&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;data=<span class="vars">$PACKAGE</span><span>/data&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">mkdir</span><span>&nbsp;-p&nbsp;</span><span class="vars">$CONTROL</span><span>&nbsp;</span><span class="vars">$data</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;cp&nbsp;<span class="vars">$control</span><span>&nbsp;</span><span class="vars">$CONTROL</span><span>/control&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$INFOPATH</span><span>/</span><span class="vars">$package</span><span>.preinst&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mv&nbsp;<span class="vars">$INFOPATH</span><span>/</span><span class="vars">$package</span><span>.preinst&nbsp;</span><span class="vars">$CONTROL</span><span>/preinst&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$INFOPATH</span><span>/</span><span class="vars">$package</span><span>.postinst&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mv&nbsp;<span class="vars">$INFOPATH</span><span>/</span><span class="vars">$package</span><span>.postinst&nbsp;</span><span class="vars">$CONTROL</span><span>/postinst&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$INFOPATH</span><span>/</span><span class="vars">$package</span><span>.prerm&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mv&nbsp;<span class="vars">$INFOPATH</span><span>/</span><span class="vars">$package</span><span>.prerm&nbsp;</span><span class="vars">$CONTROL</span><span>/prerm&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$INFOPATH</span><span>/</span><span class="vars">$package</span><span>.postrm&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mv&nbsp;<span class="vars">$INFOPATH</span><span>/</span><span class="vars">$package</span><span>.postrm&nbsp;</span><span class="vars">$CONTROL</span><span>/postrm&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$INFOPATH</span><span>/</span><span class="vars">$package</span><span>.list&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cat&nbsp;<span class="vars">$INFOPATH</span><span>/</span><span class="vars">$package</span><span>.list&nbsp;|&nbsp;</span><span class="keyword">while</span><span>&nbsp;</span><span class="func">read</span><span>&nbsp;filename;&nbsp;</span><span class="keyword">do</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pathname=`dirname&nbsp;<span class="string">&quot;$filename&quot;</span><span>`&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">mkdir</span><span>&nbsp;-p&nbsp;</span><span class="string">&quot;$data/$pathname&quot;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mv&nbsp;-f&nbsp;-T&nbsp;<span class="string">&quot;$ROOTFS/$filename&quot;</span><span>&nbsp;</span><span class="string">&quot;$data/$filename&quot;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;done&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$currpath</span><span>/ipkg-build&nbsp;</span><span class="vars">$PACKAGE</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>done&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>cd&nbsp;<span class="vars">$currpath</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<p>把这个保存为一个脚本，然后在同一个目录下放上unpack-doctor和ipkg-build脚本，然后再把要展开的ROM放在这个目录下，这个脚本的目录下运行脚本后面跟上ROM名称，就可以将ROM分解为ipk了。</p>
<p>理解了以上脚本之后，根据该原理，就也可以很方便的完成ROM杂交，ROM内置安装包移除等脚本了。这些脚本的编写就看各位高手的啦。</p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=385</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-11-26 16:45</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=384</guid>
			<title>集成安装IPK</title>
			<author>andot</author>
			<description><![CDATA[<p>&nbsp;完成了ipk的打包之后，我们需要将修改过的或者新添加的ipk包加入到我们自己要定制的ROM当中。但ipk包的安装位置是有区别的，一种是安装到root的ipk包，另一种是安装到/media/cryptofs/apps下的ipk包。</p>
<p>安装到root的ipk包，有两种集成方式，一种是预安装方式，一种是放在&lt;carrier&gt;.tar中（&lt;carrier&gt;表示att、wr、verizon等）。</p>
<p>预安装方式采用跟原始ROM中那些预安装的包一样的方法，MetaDoctor里面有两个选项EXTRA_ROOTFS_IPKGS和EXTRA_ROOTFS_TARBALL，把事先修改过的包手动展开按照ROM文件结构打包成tar文件，然后放在跟Makefile相同的目录下，然后设定好这个EXTRA_ROOTFS_TARBALL这个参数，然后把跟这个tar里面有关的包名放在EXTRA_ROOTFS_IPKGS这个参数里，就可以了。这种方式比较麻烦，而且容易出错，修改之后对root分区镜像的影响是永久性的，所以，这不是推荐的方式。</p>
<p>而放在&lt;carrier&gt;.tar中则非常方便。但是仍然有需要注意的问题，如果ROM中已经有预安装的同名的包，需要先手动从rootfs镜像中删除。删除方法不难，但比较繁琐：</p>
<p>到rootfs/usr/lib/ipkg/info下找到跟要删除的包名相关的所有文件（control，list，preinst等），根据这里面的list文件中的内容，找到这里面的这些文件一一删除，修改rootfs/md5sums.tar里面的md5sums文件，将其中跟这个包有关的所有内容删除。然后根据control文件中所描述的构架到rootfs/usr/lib/ipkg/lists中找到对应构架的那个文件，打开它将其中关于这个包的部分删除掉。打开rootfs/usr/lib/ipkg/status，将其中跟这个包有关的内容删除掉。把rootfs/usr/lib/ipkg/info中的跟这个包有关的所有文件删除。最后再次修改rootfs/md5sums.tar里面的md5sums文件，将修改过的rootfs/usr/lib/ipkg/lists/oe-&lt;arch&gt;和rootfs/usr/lib/ipkg/status这两个的md5sum值重新计算后更新。</p>
<p>以上步骤可以通过写一个脚本来自动完成，有兴趣的同学可以自己来写。</p>
<p>另一种是安装到/media/cryptofs/apps中的包，这些包实际上并不是在刷机过程中安装的，而是在刷机之后配置完毕的第一次启动时安装的。</p>
<p>在webOS 2.1中，系统给出了一个这样的例子。那就是系统里内置的app-ipkgs这个包。这个包在webOS 2.2.x和webOS 3.x中有更新，更新之后的安装方式有些变化，我们暂时不管，我们先来看看webOS 2.1中的app-ipkgs这个包是怎么做的。</p>
<p>这个包包含2个部分，一部分是/usr/palm/ipkgs这个目录下的一些安装包、图标和一个manifest.json文件，另一部分是/etc/event.d/app-install这个安装脚本。</p>
<p>/usr/palm/ipkgs下的安装包没什么好说的，单说manifest.json这个文件，这里面是安装包的一些包信息，如果你要安装的包的信息不在这个文件里，也没有什么太大影响。如果在这个文件里，在软件管理器中就看不到这个软件的删除选项。但在启动器中仍然可以通过按住白方块点图标删除。</p>
<p>我们重点看一下/etc/event.d/app-install这个脚本。</p>
<p>2.1的这个脚本很简单，就是将/usr/palm/ipkgs下的所有ipk列出来然后通过循环方式执行安装。</p>
<p>在安装时首先将安装文件复制到/media/internal/downloads下，其实复制到/media/internal的其它任何自建的目录下都可以，这样做是因为安装时，安装位置是需要可写入的，因为在安装过程中安装器会自动创建一个tmp目录。另外，如果要保证安装目录可写，也可以用rootfs_open &ndash;w的方法。这样可以省去文件的复制过程。</p>
<p>然后通过：</p>
<p>ipkg &ndash;o /media/cryptofs/apps install $package</p>
<p>命令安装。</p>
<p>最后通过：</p>
<p>luna-send -n 1 palm://com.palm.applicationManager/forceSingleAppScan '{&quot;id&quot;:&quot;'$pkg'&quot;}'</p>
<p>来使安装的软件生效（桌面上就可以看到图标了）。</p>
<p>这样的一个安装过程，对于安装没有安装依赖顺序，没有postinst脚本的ipk来说是足够了。</p>
<p>但对于带有postinst脚本、prerm等脚本的应用来说还是有些问题的。因为ipkg &ndash;o 方式安装时，不会自动执行postinst脚本，这就使得带有postinst脚本的安装程序不能被完全安装。</p>
<p>我们可以在ipkg &ndash;o 之后加上这样一段：</p>
<div class="codeText">
<ol start="0" class="dp-perl">
    <li class="alt"><span><span class="comment">#check&nbsp;if&nbsp;install&nbsp;succeeded,&nbsp;then&nbsp;run&nbsp;postinst&nbsp;if&nbsp;needed</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$APPS</span><span>/usr/lib/ipkg/info/</span><span class="vars">$pkg</span><span>.control&nbsp;]&nbsp;;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$APPS</span><span>/usr/lib/ipkg/info/</span><span class="vars">$pkg</span><span>.prerm&nbsp;]&nbsp;;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;!&nbsp;-f&nbsp;</span><span class="vars">$APPS</span><span>/.scripts/</span><span class="vars">$pkg</span><span>/pmPreRemove.script&nbsp;]&nbsp;;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/bin/<span class="func">mkdir</span><span>&nbsp;-</span><span class="func">m</span><span>&nbsp;777&nbsp;-p&nbsp;</span><span class="vars">$APPS</span><span>/.scripts/</span><span class="vars">$pkg</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/bin/cp&nbsp;-f&nbsp;<span class="vars">$APPS</span><span>/usr/lib/ipkg/info/</span><span class="vars">$pkg</span><span>.prerm&nbsp;</span><span class="vars">$APPS</span><span>/.scripts/</span><span class="vars">$pkg</span><span>/pmPreRemove.script&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$APPS</span><span>/usr/lib/ipkg/info/</span><span class="vars">$pkg</span><span>.postinst&nbsp;]&nbsp;;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;$UPSTART_JOB:&nbsp;Running&nbsp;$pkg.postinst&quot;</span><span>&nbsp;|&nbsp;logger&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;export&nbsp;IPKG_OFFLINE_ROOT=<span class="vars">$APPS</span><span>&nbsp;;&nbsp;/bin/sh&nbsp;</span><span class="vars">$APPS</span><span>/usr/lib/ipkg/info/</span><span class="vars">$pkg</span><span>.postinst&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>fi&nbsp;&nbsp;</span></li>
</ol>
</div>
<p>就实现了这些安装脚本的处理。</p>
<p>但是对于有安装依赖顺序的ipk来说，通过for循环目录可能无法保证正确的安装顺序，所以我们可以人为的来写一个安装文件列表，比如叫packages（其实叫什么都行），里面一行一个ipk文件名，例如：</p>
<div class="codeText">
<ol start="0" class="dp-cpp">
    <li class="alt"><span><span>com.palm.app.findapps_2.0.23300_all.ipk&nbsp;&nbsp;</span></span></li>
    <li class=""><span>org.webosinternals.preware_1.8.5_arm.ipk&nbsp;&nbsp;</span></li>
    <li class="alt"><span>org.webosinternals.diffstat_1.45-1_armv7.ipk&nbsp;&nbsp;</span></li>
    <li class=""><span>org.webosinternals.lsdiff_0.3.1-1_armv7.ipk&nbsp;&nbsp;</span></li>
    <li class="alt"><span>org.webosinternals.patch_2.5.9-4_armv7.ipk&nbsp;&nbsp;</span></li>
    <li class=""><span>org.webosinternals.unzip_6.0-1_armv7.ipk&nbsp;&nbsp;</span></li>
    <li class="alt"><span>org.webosinternals.zip_3.0-1_armv7.ipk&nbsp;&nbsp;</span></li>
    <li class=""><span>ca.canucksoftware.js-service-framework_1.0.1_all.ipk&nbsp;&nbsp;</span></li>
    <li class="alt"><span>ca.canucksoftware.filemgr_2.0.7_all.ipk&nbsp;&nbsp;</span></li>
    <li class=""><span>ca.canucksoftware.internalz_1.5.0_all.ipk&nbsp;&nbsp;</span></li>
    <li class="alt"><span>org.webosinternals.patches.misc-unthrottle-download-manager_2.1.0-160_all.ipk&nbsp;&nbsp;</span></li>
</ol>
</div>
<p>这样一个格式，只要这个文件里的包安装顺序正确，就可以用for循环来读取这个文件来保证顺序了。</p>
<p>然后还有一点小问题，就是如果安装的程序里包含有服务，例如上面例子中的filemgr，这样安装之后，可能服务无法自动启动，原因是在/var/palm/ls2/roles/prv和pub下没有生成服务规则文件。本来这些文件应该是在程序安装之后，系统根据usr/palm/services/包名/services.json自动生成的，但既然系统没有生成，那我们就自己创建一下这两个文件，加入下面的代码可以完成规则文件的创建：</p>
<div>
<div class="codeText">
<ol start="0" class="dp-perl">
    <li class="alt"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$APPS</span><span>/usr/palm/services/</span><span class="vars">$pkg</span><span>/services.json&nbsp;]&nbsp;;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;{&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;role\&quot;</span><span>:&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;exeName\&quot;:\&quot;js\&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;type\&quot;:&nbsp;\&quot;regular\&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;allowedNames\&quot;:&nbsp;[\&quot;$pkg\&quot;</span><span>]&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;permissions\&quot;</span><span>:&nbsp;[&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;service\&quot;:\&quot;$pkg\&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;inbound\&quot;:[\&quot;*\&quot;</span><span>],&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;outbound\&quot;:[\&quot;*\&quot;</span><span>]&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;]&nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&quot;&nbsp;&gt;&nbsp;/var/palm/ls2/roles/prv/<span class="vars">$pkg</span><span>.json&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">chmod</span><span>&nbsp;+x&nbsp;/var/palm/ls2/roles/prv/</span><span class="vars">$pkg</span><span>.json&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cp&nbsp;/var/palm/ls2/roles/prv/<span class="vars">$pkg</span><span>.json&nbsp;/var/palm/ls2/roles/pub/</span><span class="vars">$pkg</span><span>.json&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
</ol>
</div>
<p>最后，我们修改之后的完整脚本是这样子的：</p>
<div class="codeText">
<ol start="0" class="dp-perl">
    <li class="alt"><span><span class="comment">#&nbsp;-*-&nbsp;mode:&nbsp;shell-script;&nbsp;-*-</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>start&nbsp;on&nbsp;stopped&nbsp;configurator&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>script&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;rootfs_open&nbsp;-w&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;APPS=/media/cryptofs/apps&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;IPK_DIR=/usr/palm/ipkgs&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;</span><span class="keyword">package</span><span>&nbsp;in&nbsp;$(cat&nbsp;</span><span class="vars">$IPK_DIR</span><span>/packages)&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">do</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;$UPSTART_JOB:&nbsp;attempt&nbsp;to&nbsp;install&nbsp;$package&quot;</span><span>&nbsp;|&nbsp;logger&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">#call&nbsp;luna-send&nbsp;to&nbsp;begin&nbsp;installation</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ipkg&nbsp;-o&nbsp;<span class="vars">$APPS</span><span>&nbsp;install&nbsp;</span><span class="vars">$IPK_DIR</span><span>/</span><span class="vars">$package</span><span>&nbsp;|&nbsp;logger&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">#&nbsp;Get&nbsp;the&nbsp;pkg&nbsp;name&nbsp;from&nbsp;the&nbsp;file&nbsp;name.</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="declarations">local</span><span>&nbsp;bname=${</span><span class="keyword">package</span><span class="comment">##*/}</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="declarations">local</span><span>&nbsp;rname=${bname%.ipk}&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="declarations">local</span><span>&nbsp;pkg=${rname%</span><span class="vars">%_</span><span>*}&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$APPS</span><span>/usr/palm/services/</span><span class="vars">$pkg</span><span>/services.json&nbsp;]&nbsp;;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;{&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;role\&quot;</span><span>:&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;exeName\&quot;:\&quot;js\&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;type\&quot;:&nbsp;\&quot;regular\&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;allowedNames\&quot;:&nbsp;[\&quot;$pkg\&quot;</span><span>]&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;permissions\&quot;</span><span>:&nbsp;[&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;service\&quot;:\&quot;$pkg\&quot;</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;inbound\&quot;:[\&quot;*\&quot;</span><span>],&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<span class="string">&quot;outbound\&quot;:[\&quot;*\&quot;</span><span>]&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;]&nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&quot;&nbsp;&gt;&nbsp;/var/palm/ls2/roles/prv/<span class="vars">$pkg</span><span>.json&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">chmod</span><span>&nbsp;+x&nbsp;/var/palm/ls2/roles/prv/</span><span class="vars">$pkg</span><span>.json&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cp&nbsp;/var/palm/ls2/roles/prv/<span class="vars">$pkg</span><span>.json&nbsp;/var/palm/ls2/roles/pub/</span><span class="vars">$pkg</span><span>.json&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">#check&nbsp;if&nbsp;install&nbsp;succeeded,&nbsp;then&nbsp;run&nbsp;postinst&nbsp;if&nbsp;needed</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$APPS</span><span>/usr/lib/ipkg/info/</span><span class="vars">$pkg</span><span>.control&nbsp;]&nbsp;;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$APPS</span><span>/usr/lib/ipkg/info/</span><span class="vars">$pkg</span><span>.prerm&nbsp;]&nbsp;;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;!&nbsp;-f&nbsp;</span><span class="vars">$APPS</span><span>/.scripts/</span><span class="vars">$pkg</span><span>/pmPreRemove.script&nbsp;]&nbsp;;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/bin/<span class="func">mkdir</span><span>&nbsp;-</span><span class="func">m</span><span>&nbsp;777&nbsp;-p&nbsp;</span><span class="vars">$APPS</span><span>/.scripts/</span><span class="vars">$pkg</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/bin/cp&nbsp;-f&nbsp;<span class="vars">$APPS</span><span>/usr/lib/ipkg/info/</span><span class="vars">$pkg</span><span>.prerm&nbsp;</span><span class="vars">$APPS</span><span>/.scripts/</span><span class="vars">$pkg</span><span>/pmPreRemove.script&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$APPS</span><span>/usr/lib/ipkg/info/</span><span class="vars">$pkg</span><span>.postinst&nbsp;]&nbsp;;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;$UPSTART_JOB:&nbsp;Running&nbsp;$pkg.postinst&quot;</span><span>&nbsp;|&nbsp;logger&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;export&nbsp;IPKG_OFFLINE_ROOT=<span class="vars">$APPS</span><span>&nbsp;;&nbsp;/bin/sh&nbsp;</span><span class="vars">$APPS</span><span>/usr/lib/ipkg/info/</span><span class="vars">$pkg</span><span>.postinst&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;$UPSTART_JOB:&nbsp;attempt&nbsp;to&nbsp;scan&nbsp;$pkg&quot;</span><span>&nbsp;|&nbsp;logger&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">#&nbsp;Have&nbsp;the&nbsp;applicationManager&nbsp;rescan&nbsp;the&nbsp;pkg&nbsp;so&nbsp;that&nbsp;it&nbsp;will&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">#&nbsp;show&nbsp;up&nbsp;in&nbsp;the&nbsp;launcher.</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returnVal=$(luna-<span class="func">send</span><span>&nbsp;-n&nbsp;1&nbsp;palm://com.palm.applicationManager/forceSingleAppScan&nbsp;\&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="string">'{&quot;id&quot;:&quot;'</span><span class="vars">$pkg</span><span class="string">'&quot;}'</span><span>&nbsp;2&gt;&amp;1)&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger&nbsp;<span class="string">&quot;$UPSTART_JOB:&nbsp;returnVal&nbsp;is&nbsp;$returnVal&quot;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;done&nbsp;&nbsp;</span></li>
    <li class="alt"><span>end&nbsp;script&nbsp;&nbsp;</span></li>
</ol>
</div>
<p>现在我们可以把这个包单独拿出来，然后把rootfs下的这个预先安装的这个包删掉。最后修改之后，放在&lt;carrier&gt;.tar里面就可以啦。</p>
<p>当然，更好的方法是，不要动系统的这个app-ipkgs。自己创建一个类似的包，脚本按照自己设置的目录来写。最后单独打一个包，名字不要跟系统已有的包冲突，最后放在&lt;carrier&gt;.tar中就可以了。自己创建类似安装包的好处是，它可以减少你对rootfs的修改，保证系统自带的升级程序不会被破坏，另外还能适用于1.x、2.2.x和3.x系统，而不仅仅局限于2.1.x系统。</p>
</div>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=384</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-11-26 00:05</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=383</guid>
			<title>修改打包IPK</title>
			<author>andot</author>
			<description><![CDATA[<p>上一节我们讲到WebOS Doctor中的rootfs实际上是一组预先安装好的包（ipk）的集合，那我们如何自己修改和打包ipk呢？这一节我们就来讲讲这个。</p>
<p>ipk文件实际上是用ar命令打包的一个归档包。没有数字签名的ipk中一般包含control.tar.gz、data.tar.gz和debian-binary这三个文件。</p>
<p>其中debian-binary里面是固定的。</p>
<p>control.tar.gz中包含了control、md5sums、preinst、postinst、prerm、postrm这几个文件，其中control是必须的，其它都是可选的。</p>
<p>data.tar.gz中包含了要安装的程序和数据。</p>
<p>ipk的安装对于大多数用户来说都是使用preware、WebOS Quick Install、Internalz Pro来安装程序的。如果不考虑postinst脚本，那么使用这些工具安装的文件都是相对于/media/cryptofs/apps目录进行安装的。如果直接使用不带-o参数的ipkg install命令安装的话，那么安装的文件都是相对于/目录的。也就是说ipk包中实际上并不包含相对于那个路径进行安装的信息。安装到哪儿只跟安装的方式有关。</p>
<p>rootfs.tar.gz中那些预先安装好的包都是相对于/目录安装的。相对于/目录安装的程序，用户通过preware、WebOS Quick Install和系统自带的软件包管理器都是无法卸载的，但并不是说就真的无法卸载，实际上只要你愿意，这些包都可以在root帐号下用ipkg remove命令来卸载掉。</p>
<p>我们在上一节中有一个&lt;carrier&gt;.tar没有介绍（&lt;carrier&gt;表示att、wr、verizon等），之所以没介绍主要原因就是我们需要先了解上面的这些内容，然后才比较容易解释这个&lt;carrier&gt;.tar。</p>
<p>这个&lt;carrier&gt;.tar中的主要内容就是一些ipk包，另外，还有一个installer.xml。这个installer.xml如果不是要做跨运营商或跨机型移植，是不需要修改的。那么剩下的就是运营商定制的一些ipk包了。这些包是在刷机程序把rootfs.tar.gz写入设备之后，进行安装的。他们都是相对于/目录进行安装的。因此这些包从本质上来讲，跟rootfs.tar.gz中预先安装的包是没有区别的。唯一的区别就是rootfs.tar.gz中的包是预先安装好的，&lt;carrier&gt;.tar中的包是在刷机过程中进行安装的。而ROM验证md5sums的过程是在&lt;carrier&gt;.tar中的所有ipk安装之后才进行的。因此，&lt;carrier&gt;.tar中的包也是需要进行md5sums验证的。</p>
<p>既然&lt;carrier&gt;.tar中的包也需要验证，所以对于放在&lt;carrier&gt;.tar中的包来说，它的control.tar.gz中的md5sums不是可选的，而是必须的。如果缺少了这个md5sums，那么刷机到82%时，同样会因为无法通过md5sums验证而终止刷机，无法重启。</p>
<p>要生成一个带md5sums的ipk，如果靠手工来计算编写md5sums，并自己通过tar、gzip、ar等命令来打包实在是麻烦的很。实际上前人早在10年前就做好了这样的打包脚本，叫ipkg-build。我们可以直接拿来用。</p>
<p>下面是这个脚本的完整内容：</p>
<div class="codeText">
<ol start="0" class="dp-perl">
    <li class="alt"><span><span class="comment">#!/bin/sh</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span><span class="comment">#&nbsp;ipkg-build&nbsp;--&nbsp;construct&nbsp;a&nbsp;.ipk&nbsp;from&nbsp;a&nbsp;directory</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="comment">#&nbsp;Carl&nbsp;Worth&nbsp;&lt;cworth@east.isi.edu&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="comment">#&nbsp;based&nbsp;on&nbsp;a&nbsp;script&nbsp;by&nbsp;Steve&nbsp;Redler&nbsp;IV,&nbsp;steve@sr-tech.com&nbsp;5-21-2001</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>set&nbsp;-e&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>ipkg_extract_value()&nbsp;{&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;sed&nbsp;-e&nbsp;<span class="string">&quot;s/^[^:]*:[[:space:]]*//&quot;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>required_field()&nbsp;{&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;field=<span class="vars">$1</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;value=`<span class="func">grep</span><span>&nbsp;</span><span class="string">&quot;^$field:&quot;</span><span>&nbsp;&lt;&nbsp;</span><span class="vars">$CONTROL</span><span>/control&nbsp;|&nbsp;ipkg_extract_value`&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-z&nbsp;</span><span class="string">&quot;$value&quot;</span><span>&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;***&nbsp;Error:&nbsp;$CONTROL/control&nbsp;is&nbsp;missing&nbsp;field&nbsp;$field&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;1&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="vars">$value</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;0&nbsp;&nbsp;</span></span></li>
    <li class=""><span>}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>pkg_appears_sane()&nbsp;{&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="declarations">local</span><span>&nbsp;pkg_dir=</span><span class="vars">$1</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="declarations">local</span><span>&nbsp;owd=`pwd`&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;cd&nbsp;<span class="vars">$pkg_dir</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;PKG_ERROR=0&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;large_uid_files=`find&nbsp;.&nbsp;-uid&nbsp;+99`&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-n&nbsp;</span><span class="string">&quot;$large_uid_files&quot;</span><span>&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;***&nbsp;Warning:&nbsp;The&nbsp;following&nbsp;files&nbsp;have&nbsp;a&nbsp;UID&nbsp;greater&nbsp;than&nbsp;99.&nbsp;&nbsp;</span></li>
    <li class="alt"><span>You&nbsp;probably&nbsp;want&nbsp;to&nbsp;<span class="func">chown</span><span>&nbsp;these&nbsp;to&nbsp;a&nbsp;</span><span class="func">system</span><span>&nbsp;user:&nbsp;&quot;&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ls&nbsp;-ld&nbsp;<span class="vars">$large_uid_files</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;!&nbsp;-f&nbsp;</span><span class="string">&quot;$CONTROL/control&quot;</span><span>&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;***&nbsp;Error:&nbsp;Control&nbsp;file&nbsp;$pkg_dir/$CONTROL/control&nbsp;not&nbsp;found.&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cd&nbsp;<span class="vars">$owd</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;1&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;pkg=`required_field&nbsp;Package`&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;<span class="string">&quot;$?&quot;</span><span>&nbsp;-ne&nbsp;0&nbsp;]&nbsp;&amp;&amp;&nbsp;PKG_ERROR=1&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;version=`required_field&nbsp;Version&nbsp;|&nbsp;sed&nbsp;<span class="string">'s/.*://;'</span><span>`&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;<span class="string">&quot;$?&quot;</span><span>&nbsp;-ne&nbsp;0&nbsp;]&nbsp;&amp;&amp;&nbsp;PKG_ERROR=1&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;arch=`required_field&nbsp;Architecture`&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;<span class="string">&quot;$?&quot;</span><span>&nbsp;-ne&nbsp;0&nbsp;]&nbsp;&amp;&amp;&nbsp;PKG_ERROR=1&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;required_field&nbsp;Maintainer&nbsp;&gt;/dev/null&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;<span class="string">&quot;$?&quot;</span><span>&nbsp;-ne&nbsp;0&nbsp;]&nbsp;&amp;&amp;&nbsp;PKG_ERROR=1&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;required_field&nbsp;Description&nbsp;&gt;/dev/null&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;<span class="string">&quot;$?&quot;</span><span>&nbsp;-ne&nbsp;0&nbsp;]&nbsp;&amp;&amp;&nbsp;PKG_ERROR=1&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;section=`required_field&nbsp;Section`&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;<span class="string">&quot;$?&quot;</span><span>&nbsp;-ne&nbsp;0&nbsp;]&nbsp;&amp;&amp;&nbsp;PKG_ERROR=1&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-z&nbsp;</span><span class="string">&quot;$section&quot;</span><span>&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;The&nbsp;Section&nbsp;field&nbsp;should&nbsp;have&nbsp;one&nbsp;of&nbsp;the&nbsp;following&nbsp;values:&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;Games,&nbsp;Multimedia,&nbsp;Communications,&nbsp;Settings,&nbsp;Utilies,&nbsp;Applications,&nbsp;Console,&nbsp;Misc&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;priority=`required_field&nbsp;Priority`&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;<span class="string">&quot;$?&quot;</span><span>&nbsp;-ne&nbsp;0&nbsp;]&nbsp;&amp;&amp;&nbsp;PKG_ERROR=1&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-z&nbsp;</span><span class="string">&quot;$priority&quot;</span><span>&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;The&nbsp;Priority&nbsp;field&nbsp;should&nbsp;have&nbsp;one&nbsp;of&nbsp;the&nbsp;following&nbsp;values:&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;required,&nbsp;important,&nbsp;standard,&nbsp;optional,&nbsp;extra.&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;If&nbsp;you&nbsp;don't&nbsp;know&nbsp;which&nbsp;priority&nbsp;value&nbsp;you&nbsp;should&nbsp;be&nbsp;using,&nbsp;then&nbsp;use&nbsp;\`optional'&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;echo&nbsp;</span><span class="vars">$pkg</span><span>&nbsp;|&nbsp;</span><span class="func">grep</span><span>&nbsp;</span><span class="string">'[^a-z0-9.+-]'</span><span>;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;***&nbsp;Error:&nbsp;Package&nbsp;name&nbsp;$name&nbsp;contains&nbsp;illegal&nbsp;characters,&nbsp;(other&nbsp;than&nbsp;[a-z0-9.+-])&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PKG_ERROR=1;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="declarations">local</span><span>&nbsp;bad_fields=`sed&nbsp;-ne&nbsp;</span><span class="string">'s/^\([^[:space:]][^:[:space:]]\+[[:space:]]\+\)[^:].*/\1/p'</span><span>&nbsp;&lt;&nbsp;</span><span class="vars">$CONTROL</span><span>/control&nbsp;|&nbsp;sed&nbsp;-e&nbsp;</span><span class="string">'s/\\n//'</span><span>`&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-n&nbsp;</span><span class="string">&quot;$bad_fields&quot;</span><span>&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bad_fields=`echo&nbsp;<span class="vars">$bad_fields</span><span>`&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;***&nbsp;Error:&nbsp;The&nbsp;following&nbsp;fields&nbsp;in&nbsp;$CONTROL/control&nbsp;are&nbsp;missing&nbsp;a&nbsp;':'&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;&nbsp;&nbsp;$bad_fields&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;ipkg-build:&nbsp;This&nbsp;may&nbsp;be&nbsp;due&nbsp;to&nbsp;a&nbsp;missing&nbsp;initial&nbsp;space&nbsp;for&nbsp;a&nbsp;multi-line&nbsp;field&nbsp;value&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PKG_ERROR=1&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;script&nbsp;in&nbsp;</span><span class="vars">$CONTROL</span><span>/preinst&nbsp;</span><span class="vars">$CONTROL</span><span>/postinst&nbsp;</span><span class="vars">$CONTROL</span><span>/prerm&nbsp;</span><span class="vars">$CONTROL</span><span>/postrm;&nbsp;</span><span class="keyword">do</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$script</span><span>&nbsp;-a&nbsp;!&nbsp;-x&nbsp;</span><span class="vars">$script</span><span>&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;***&nbsp;Error:&nbsp;package&nbsp;script&nbsp;$script&nbsp;is&nbsp;not&nbsp;executable&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PKG_ERROR=1&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;done&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;-f&nbsp;</span><span class="vars">$CONTROL</span><span>/conffiles&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;cf&nbsp;in&nbsp;`cat&nbsp;</span><span class="vars">$CONTROL</span><span>/conffiles`;&nbsp;</span><span class="keyword">do</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;[&nbsp;!&nbsp;-f&nbsp;./</span><span class="vars">$cf</span><span>&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;***&nbsp;Error:&nbsp;$CONTROL/conffiles&nbsp;mentions&nbsp;conffile&nbsp;$cf&nbsp;which&nbsp;does&nbsp;not&nbsp;exist&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PKG_ERROR=1&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;done&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;cd&nbsp;<span class="vars">$owd</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;</span><span class="vars">$PKG_ERROR</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span><span class="comment">###</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="comment">#&nbsp;ipkg-build&nbsp;&quot;main&quot;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="comment">###</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span><span class="keyword">case</span><span>&nbsp;$</span><span class="comment">#&nbsp;in</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>1)&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;dest_dir=.&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>2)&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;dest_dir=<span class="vars">$2</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;&nbsp;</span></li>
    <li class=""><span>*)&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;Usage:&nbsp;ipkg-build&nbsp;&lt;pkg_directory&gt;&nbsp;[&lt;destination_directory&gt;]&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">exit</span><span>&nbsp;1&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;&nbsp;</span></li>
    <li class=""><span>esac&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>pkg_dir=<span class="vars">$1</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span><span class="keyword">if</span><span>&nbsp;[&nbsp;!&nbsp;-d&nbsp;</span><span class="vars">$pkg_dir</span><span>&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;***&nbsp;Error:&nbsp;Directory&nbsp;$pkg_dir&nbsp;does&nbsp;not&nbsp;exist&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">exit</span><span>&nbsp;1&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>fi&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span><span class="comment">#&nbsp;CONTROL&nbsp;is&nbsp;second&nbsp;so&nbsp;that&nbsp;it&nbsp;takes&nbsp;precedence</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>CONTROL=&nbsp;&nbsp;</span></li>
    <li class="alt"><span>[&nbsp;-d&nbsp;<span class="vars">$pkg_dir</span><span>/DEBIAN&nbsp;]&nbsp;&amp;&amp;&nbsp;CONTROL=DEBIAN&nbsp;&nbsp;</span></span></li>
    <li class=""><span>[&nbsp;-d&nbsp;<span class="vars">$pkg_dir</span><span>/CONTROL&nbsp;]&nbsp;&amp;&amp;&nbsp;CONTROL=CONTROL&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="keyword">if</span><span>&nbsp;[&nbsp;-z&nbsp;</span><span class="string">&quot;$CONTROL&quot;</span><span>&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;***&nbsp;Error:&nbsp;Directory&nbsp;$pkg_dir&nbsp;has&nbsp;no&nbsp;CONTROL&nbsp;subdirectory.&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">exit</span><span>&nbsp;1&nbsp;&nbsp;</span></span></li>
    <li class=""><span>fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span><span class="keyword">if</span><span>&nbsp;!&nbsp;pkg_appears_sane&nbsp;</span><span class="vars">$pkg_dir</span><span>;&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="string">&quot;ipkg-build:&nbsp;Please&nbsp;fix&nbsp;the&nbsp;above&nbsp;errors&nbsp;and&nbsp;try&nbsp;again.&quot;</span><span>&nbsp;&gt;&amp;2&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">exit</span><span>&nbsp;1&nbsp;&nbsp;</span></span></li>
    <li class=""><span>fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>tmp_dir=<span class="vars">$dest_dir</span><span>/IPKG_BUILD.$$&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="func">mkdir</span><span>&nbsp;</span><span class="vars">$tmp_dir</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>(cd&nbsp;<span class="vars">$pkg_dir</span><span>/data;&nbsp;find&nbsp;.&nbsp;-type&nbsp;f&nbsp;-print0&nbsp;|&nbsp;xargs&nbsp;-0&nbsp;md5sum&nbsp;)&nbsp;&gt;&nbsp;</span><span class="vars">$pkg_dir</span><span>/</span><span class="vars">$CONTROL</span><span>/md5sums&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">if</span><span>&nbsp;[&nbsp;!&nbsp;-f&nbsp;</span><span class="string">&quot;$pkg_dir/files.txt&quot;</span><span>&nbsp;];&nbsp;then&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;(cd&nbsp;<span class="vars">$pkg_dir</span><span>/data;&nbsp;find&nbsp;.&nbsp;-type&nbsp;f&nbsp;-print0&nbsp;|xargs&nbsp;-0&nbsp;</span><span class="func">grep</span><span>&nbsp;</span><span class="string">''</span><span>&nbsp;-l)&nbsp;&gt;</span><span class="vars">$pkg_dir</span><span>/files.txt&nbsp;&nbsp;</span></span></li>
    <li class=""><span>fi&nbsp;&nbsp;</span></li>
    <li class="alt"><span><span class="comment">#&nbsp;tar&nbsp;-C&nbsp;$pkg_dir/data&nbsp;-cf&nbsp;$tmp_dir/data.tar&nbsp;-T&nbsp;$pkg_dir/files.txt&nbsp;-h&nbsp;--verify</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>tar&nbsp;-C&nbsp;<span class="vars">$pkg_dir</span><span>/data&nbsp;-cf&nbsp;</span><span class="vars">$tmp_dir</span><span>/data.tar&nbsp;.&nbsp;--verify&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>gzip&nbsp;-f&nbsp;<span class="vars">$tmp_dir</span><span>/data.tar&nbsp;&nbsp;</span></span></li>
    <li class=""><span>tar&nbsp;-C&nbsp;<span class="vars">$pkg_dir</span><span>/</span><span class="vars">$CONTROL</span><span>&nbsp;-czf&nbsp;</span><span class="vars">$tmp_dir</span><span>/control.tar.gz&nbsp;.&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>echo&nbsp;<span class="string">&quot;2.0&quot;</span><span>&nbsp;&gt;&nbsp;</span><span class="vars">$tmp_dir</span><span>/debian-binary&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>pkg_file=<span class="vars">$dest_dir</span><span>/${pkg}_${version}_${arch}.ipk&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="comment">#tar&nbsp;-C&nbsp;$tmp_dir&nbsp;-czf&nbsp;$pkg_file&nbsp;./debian-binary&nbsp;./data.tar.gz&nbsp;./control.tar.gz</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>(cd&nbsp;<span class="vars">$tmp_dir</span><span>&nbsp;;ar&nbsp;-qc&nbsp;</span><span class="vars">$pkg_file</span><span>&nbsp;./debian-binary&nbsp;./data.tar.gz&nbsp;./control.tar.gz&nbsp;;&nbsp;mv&nbsp;</span><span class="vars">$pkg_file</span><span>&nbsp;../)&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>rm&nbsp;<span class="vars">$tmp_dir</span><span>/debian-binary&nbsp;</span><span class="vars">$tmp_dir</span><span>/data.tar.gz&nbsp;</span><span class="vars">$tmp_dir</span><span>/control.tar.gz&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="func">rmdir</span><span>&nbsp;</span><span class="vars">$tmp_dir</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>echo&nbsp;<span class="string">&quot;Packaged&nbsp;contents&nbsp;of&nbsp;$pkg_dir&nbsp;into&nbsp;$pkg_file&quot;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<p>这个脚本我对它作过一处非常细微的修改，旧的脚本中在打包data.tar.gz时，对软连接和硬连接是将连接指向的文件进行打包的。而实际上我们没有必要这样做，我们可以直接将连接以原始方式打包到ipk的data.tar.gz中，这是ipk包允许的。而且实际上webOS系统中原本有好多包本来就是带有软连接的，如果不做这个修改，后面我们就不能正确的将系统全部打包回ipk。</p>
<p>好了，有了这个脚本，我们就可以自制ipk包了。首先建立一个包的目录，通常我们以包名来命名，然后在其下建立两个目录，分别为CONTROL和data，注意大小写。</p>
<p>CONTROL目录下放control.tar.gz解压之后的内容。其中不必包含md5sums，即使包含在打包时也会重新生成，因此不必担心md5sums的正确性。</p>
<p>data目录下放data.tar.gz解压之后的内容。注意它是相对于/的，里面的内容要包含相对于/的路径。另外，即使你希望这些内容被安装到/media/cryptofs/apps，也不要把这个路径建立到data目录下，这个路径是在安装时才决定的。</p>
<p>之后你可以对这两个目录下的内容进行修改编辑，添加删除内容都可以。修改完毕之后，退回到这个包目录的上级目录下，然后将其拥有者和用户组都改为root（对于普通包是这样的，对于系统包来说，我们应该在解压系统包时就保留系统包的用户组，在修改时不要变更原来文件的用户组）。最后执行ipkg-build 包名，就可以重新打包生成修改之后的ipk了。</p>
<p>上文中提到的ipkg-build可在此直接下载：<a href="http://www.coolcode.org/attachment.php?id=239" title="4.38 K, 下载次数:234" target="_blank">ipkg-build</a></p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=383</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-11-25 14:38</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=382</guid>
			<title>ROM文件结构</title>
			<author>andot</author>
			<description><![CDATA[<p>前面我们对如何修改WebOS ROM有了一个大致的了解，但是要想更好的定制ROM，熟悉ROM的文件结构还是有必要的。</p>
<p>webOS的ROM被叫做webOS Doctor，虽然不同版本的webOS Doctor内容不同，但大致结构上是一样的。</p>
<p>webOS Doctor是一个jar文件，它是一个可执行的java压缩包。你可以把它改名为zip就可以直接用解压缩工具将它解压缩（当然不改名也可以解压缩）。</p>
<p>解压缩之后，我们得到了3个目录。它们分别是META-INF、com和resources。</p>
<p>其中META-INF从名字上看我们就知道他是这个jar包的元信息。原版的webOS Doctor的这个目录下有三个文件：JARKEY.RSA、JARKEY.SF和MANIFEST.MF。这三个文件包含了这个jar文件的数字签名信息和启动信息。数字签名是用来验证这个jar包是否被修改过的。如果我们要修改webOS Doctor，就需要把数字签名去掉，只保留启动信息。去掉数字签名并不会影响刷机程序的正常运行，因为数字签名不改变jar中的其它文件。</p>
<p>而com目录下是刷机程序的可执行文件，都是一些java的class程序，我们通常修改webOS Doctor时，是不去修改这个目录下的东西的。所以我们可以不去管它。</p>
<p>resources下面是刷机程序的资源。其中那些png是刷机程序里的图片，不用管它（如果你愿意也可以替换它们）。那些html是最终用户许可协议，如果你愿意的话，可以把它汉化。messages*.properties是刷机程序中的一些信息，可以按照这个格式写一份汉化版，这样刷机时选择中文，就会显示中文信息。但是要想选择中文，还需要修改一下languagePicker.properties，修改这个才能让你在刷机开始时选择语言。这些都改完了，刷机程序就可以彻底汉化了。</p>
<p>然后NovacomInstaller.pkg.tar.gz是Mac OS X上的驱动程序，NovacomInstaller_x64.msi和NovacomInstaller_x86.msi是Windows上的驱动程序，分别对于x64和x86系统。这些都不用管它。</p>
<p>recoverytool.config这个是非常重要的一个文件。</p>
<p>前面四行是跟版本信息有关的，可以根据喜好改。</p>
<p>BaseBuild是基础包，它指向webOS.tar这个文件，你可以修改成你自己喜欢的名字，但实在没这个必要。</p>
<p>CustomizationBuild这个是定制包，att的版本这个包名是att.tar，o2等欧洲版本这个包名是wr.tar，verizon版本这个报名是verizon.tar或verizon-world.tar。其实这个包名叫啥都行，可以自己改。</p>
<p>ForceModemUpdate决定是否升级MODEM模块，默认为true，改成false就不刷MODEM了。</p>
<p>SoftwareUpdateSite应该是指软件升级的站点，我们能看到的就是production这个选项，其它选项是什么我就不知道了。</p>
<p>在接下来的三项（AppSubmssion、LibCoreSubmssion、WcpSubmssion）是ROM中软件包的数量，这个不用管它。</p>
<p>DeviceType这个是机型，这个跟webOS.tar中的那个xml是对应的。不要乱改。除非你知道自己在做什么。</p>
<p>ApprovalBuildName是指这个ROM的编译版本，后面那一堆看似乱码的东西是可以解码的，例如Veer ATT 2.1.2的ROM中，这个值解码之后是：ps.palmws.com 'Release Build Name 1.3.2 (SDK935KRY93455)'。跟这个目录下的ps.palmws.com文件和其内容相对应。</p>
<p>ApprovalCharlieHash是指这个ROM的运营商，同样可解码。例如Veer ATT 2.1.2的ROM中，这个值解码之后是：./carrier_NAB.txt 'ATT'。</p>
<p>ApprovalMikeHash是指这个ROM的机型，同样可解码。例如Veer ATT 2.1.2的ROM中，这个值解码之后是：./model_Nova_ATT_Broadway.txt 'P160UNA'。</p>
<p>最后我们讲两个最重要的文件，那就是webOS.tar和另一个&lt;carrier&gt;.tar文件（&lt;carrier&gt;表示att、wr、verizon等）。关于&lt;carrier&gt;.tar我们下次再谈。这次先来详解一下webOS.tar。</p>
<p>webOS.tar是刷机的基本包。它里面包含了整个系统的内容。</p>
<p>其中，boot-&lt;model&gt;.bin是启动文件（其中&lt;model&gt;表示设备制式，例如pre/pre+是castle，pixi/pixi+是pixie，pre2是roadrunner，veer是broadway，pre3是mantaray，touchpad是topaz），它负责载入安装镜像nova-installer-image-&lt;model&gt;.uImage。</p>
<p>*umts*.tar，*cdma*.tar这些是MODEM模块。</p>
<p>*.tga是一些系统的图片。如果你想美好它们的话，可以对它们进行修改和替换。</p>
<p>上面这些文件我们通常不做修改。除非在跨运营商或跨机型移植ROM时，才会替换这些文件。跨运营商移植是比较常见的，替换MODEM模块之后再稍做些修改就可以了。跨机型移植难度较大，不知道是否有人真的尝试过，因为跨机型移植不是替换几个文件就能搞定的。</p>
<p>定制ROM时修改最多的是这三个文件：nova-cust-image-&lt;model&gt;.rootfs.tar.gz，installer.xml和&lt;model&gt;.xml。</p>
<p>nova-cust-image-&lt;model&gt;.rootfs.tar.gz这个里面就是我们手机上运行的系统的根分区的主要内容的压缩包。刷机最关键的部分就是把它来写入到手机的根分区。</p>
<p>installer.xml是里面是刷机的基本配置信息，我们通常不对它修改，最多就是修改ModemUpdater这个，去掉它就不更新MODEM了。</p>
<p>&lt;model&gt;.xml这个文件是非常重要的，里面包含了文件系统的分区信息，哪些数据写入到哪儿，键盘配置等等信息。这个文件我们通常也不会去修改它。最常见的修改就是键盘布局和对分区的调整的修改（例如增加分区，调整某些分区大小等）。而直接用MetaDoctor的选项来对该文件作这些修改更安全一些。</p>
<p>我们再回到nova-cust-image-&lt;model&gt;.rootfs.tar.gz这个文件的讨论上来。</p>
<p>nova-cust-image-&lt;model&gt;.rootfs.tar.gz是对根文件系统做的tar归档文件，然后用gzip进行了压缩。我们可以直接用tar命令将它展开。更方便的方法是借助MetaDoctor中的unpack-doctor或者unpack-rootfs。推荐使用unpack-doctor，这个更好用一些。</p>
<p>解压之后，我们就可以看到系统的大部分文件了。这里说大部分的意思是，有些系统文件不是在这里面直接包含的，而是在另一个&lt;carrier&gt;.tar中安装的，还有一些是在刷机之后第一次启动过程中动态生成的。我们先不管这么多。</p>
<p>在rootfs的根目录下，有一个md5sums.gz文件，解压之后里面是一个名为md5sums的文本文件。该文件记录了这个rootfs中包含的所有文件的md5sum值，如果你对rootfs里的任何文件作了修改，一定要更新md5sums中对应的md5sum值，否则刷机到82%时，刷机程序会提示你设备无法重启。</p>
<p>当然系统验证并不是简单的只看这个md5sums.gz文件。实际上这个rootfs下的内容基本上都是系统预安装好的包（ipk），而这些包的信息保存在/usr/lib/ipkg目录下。</p>
<p>这个目录下，status是保存了包的安装状态。</p>
<p>lists目录下有三个文件，oe-all，oe-&lt;arch&gt;，oe-&lt;model&gt;。其中&lt;arch&gt;是指构架，例如armv7，armv6，i386。&lt;model&gt;是指机型，上面已经介绍了，这里不再重复。</p>
<p>其中oe-all是可以完全移植到其它机器上的包，oe-&lt;arch&gt;是可以移植到相同构架机器上的包，而oe-&lt;model&gt;最为严格，只有相同的机型才能够移植。例如，如果你打算把pre3的系统移植到veer上来，pre3的oe-all和oe-armv7这两个里面的包应该都是可以顺利的那到veer上来的，而oe-mantaray里面的包则不能移植到veer上来，而应该保留veer上原有的oe-broadway的这些包，但这种杂交系统的做法是否真的不影响兼容性我倒是未曾作过验证和尝试。有兴趣并有能力的同学可以试试看。</p>
<p>info目录下就是每个包的控制文件了。其中：</p>
<p>*.control文件是每个包的基本信息文件。</p>
<p>*.list里面记录了每个包中都包含了哪些文件。</p>
<p>*.preinst是每个包安装之前要执行的脚本文件。这种脚本很少。</p>
<p>*postinst是每个包安装之后要执行的脚本文件。</p>
<p>*.prerm是每个包卸载之前要执行的脚本文件。</p>
<p>*.postrm是每个包卸载之后要执行的脚本文件。</p>
<p>*.md5sums是每个包的验证文件，在系统刷机之后，刷机程序也会来验证这些*.md5sums中记录的md5散列值，所以刷机之后的验证是一个双重的验证，因此要手工修改rootfs又要做到能够通过验证确实是非常不容易的，这也是目前国内的一些ROM定制团队定制的ROM无法通过刷机之后的验证，到82%就提示无法启动的主要原因。</p>
<p>几乎所有的文件都可以归入包中，有少数不在包中的文件也都是由预先安装的包因已经执行过postinst脚本所生成的。</p>
<p>所以，我们可以认为这个rootfs.tar.gz就是一组预先安装好的包的集合。搞清楚这个结构，我们后面修改ROM就容易多了。</p>
]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=382</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-11-25 14:22</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=381</guid>
			<title>免发激活短信</title>
			<author>andot</author>
			<description><![CDATA[<p>可能很多人把WIFI激活和免发激活短信弄混（包括我最开始也有弄混），实际上它们之间没有任何关系。</p>
<p>WIFI激活并不能免发激活国际短信，免发激活国际短信也不一定非要WIFI激活。</p>
<p>如果只是向上文中那样改成可WIFI激活，并不能免发激活短信。</p>
<p>那怎么才能免发激活短信呢？</p>
<p>最简单就是同时开启BYPASS_ACTIVATION和我们上篇中添加的WIFI_ACTIVATION选项。并在刷机时不要插卡（不插卡能不能成功激活Profile还不好说，反正我没成功过，不知是当时的网络问题还是不插卡就不能注册或登录Profile），或者插一张废卡（这个有人测试成功过），即可避免发激活短信了。</p>
<p>但上面的方法是有缺陷的，首先你不能用2G、3G这些传统的方法来注册或登录Profile了。然后就是进入系统之后，手势教程也是不能用的。BYPASS_ACTIVATION可能还会带来一些其它的副作用。所以，我们不推荐用上面的方法。</p>
<p>下面就来说一下本人发现的免发激活短信的方法。</p>
<p>虽然发现该方法费了好多工夫，但该方法在实现上却非常简单。在com.palm.app.firstuse的app/models/account-service.js文件中有一个方法：postLoginSettings。这个方法是发送激活短信的罪魁祸首。</p>
<p>它是在哪儿被调用的呢？</p>
<p>它在两处被调用。一处是在com.palm.app.firstuse的app/controllers/restorecomplete-assistant.js的restoreDone方法中被调用的。另一处是com.palm.app.firstuse的app/controllers/status-assistant.js的setup方法中被调用的。</p>
<p>restoreDone这个方法显然是在Profile被恢复的之后，按了完成按钮之后执行的。而status-assistant.js的情况稍微复杂一点。</p>
<p>但是不管是在哪儿被调用，他们都有一个共同点，就是这个方法不管是调用成功还是调用失败都不影响后续正常执行，因为它的成功回调和失败回调除了日志内容不同以外，其它的主要操作都是一模一样的。也就是说完全可以跳过这个方法的执行。</p>
<p>最简单的跳过方式当然就是直接修改postLoginSettings方法，而不是修改调用的地方。那该如何修改呢？最简单的方法就是把原来的对服务的调用注释掉，然后改为直接调用回调方法：</p>
<div class="codeText">
<div class="codeHead">JavaScript代码</div>
<div class="bar">&nbsp;</div>
<ol start="0" class="dp-c">
    <li class="alt"><span><span>postLoginSettings:&nbsp;</span><span class="keyword">function</span><span>(AccountLocales,&nbsp;successCallback,&nbsp;errorCallback,&nbsp;sceneController)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/*return&nbsp;sceneController.serviceRequest(NovaAccountService.identifier,&nbsp;{</span>&nbsp;</span></li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method:&nbsp;'postLoginSettings',</span>&nbsp;</span></li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters:&nbsp;{&quot;firstTime&quot;:&nbsp;true,&nbsp;'language':AccountLocales.language,&nbsp;'country':AccountLocales.country},</span>&nbsp;</span></li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onSuccess:&nbsp;successCallback,</span>&nbsp;</span></li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onFailure:&nbsp;errorCallback</span>&nbsp;</span></li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;true);*/</span><span>&nbsp;successCallback({&nbsp;</span><span class="string">&quot;returnValue&quot;</span><span>:&nbsp;</span><span class="keyword">true</span><span>,&nbsp;</span><span class="string">&quot;errorCode&quot;</span><span>:&nbsp;0,&nbsp;</span><span class="string">&quot;errorString&quot;</span><span>:&nbsp;</span><span class="string">&quot;success&quot;</span><span>});&nbsp;&nbsp;</span></span></li>
    <li class=""><span>},&nbsp;&nbsp;</span></li>
</ol>
</div>
<p>&nbsp;注意，这里我们没有增加行数，没有减少行数，为的是避免跟其它的补丁产生冲突。这样修改之后，对于restoreDone中的调用可以完美实现不发激活国际短信了。但是对于新注册或者原来的帐号没有备份的情况下，却会发生点击完成无限转圈圈的问题。这是什么原因呢？</p>
<p>仔细分析我们会发现，在status-assistant.js的setup最后有两行代码：</p>
<div class="codeText">
<div class="codeHead">JavaScript代码</div>
<div class="bar">&nbsp;</div>
<ol start="0" class="dp-c">
    <li class="alt"><span><span class="keyword">this</span><span>.postLoginRequestComplete&nbsp;=&nbsp;</span><span class="keyword">false</span><span>;&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">this</span><span>.provisioningRequestComplete&nbsp;=&nbsp;</span><span class="keyword">false</span><span>;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<p>而在对postLoginSettings的回调方法中会将this.postLoginRequestComplete设置为true。并在最后的saveDoneState方法中对这两个标志检测是否都为true，只有都为true时才会保存设置并重启手机。</p>
<p>而上面的修改我们把正常的回调改成了直接调用回调方法，结果就是回调方法被提前执行了，之后又执行到setup底部时，this.postLoginRequestComplete又被重新设置为了false，导致这个标志永远都无法变成true，也就导致了无法重启，一直转圈圈了。</p>
<p>所以，我们应该把直接调用回调方法改成延迟回调，最简单的方法就是用setTimeout方法，下面是正确的修改：</p>
<div class="codeText">
<div class="codeHead">JavaScript代码</div>
<div class="bar">&nbsp;</div>
<ol start="0" class="dp-c">
    <li class="alt"><span><span>postLoginSettings:&nbsp;</span><span class="keyword">function</span><span>(AccountLocales,&nbsp;successCallback,&nbsp;errorCallback,&nbsp;sceneController)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/*return&nbsp;sceneController.serviceRequest(NovaAccountService.identifier,&nbsp;{</span>&nbsp;</span></li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method:&nbsp;'postLoginSettings',</span>&nbsp;</span></li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters:&nbsp;{&quot;firstTime&quot;:&nbsp;true,&nbsp;'language':AccountLocales.language,&nbsp;'country':AccountLocales.country},</span>&nbsp;</span></li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onSuccess:&nbsp;successCallback,</span>&nbsp;</span></li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onFailure:&nbsp;errorCallback</span>&nbsp;</span></li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;true);*/</span><span>setTimeout(</span><span class="keyword">function</span><span>()&nbsp;{successCallback({&nbsp;</span><span class="string">&quot;returnValue&quot;</span><span>:&nbsp;</span><span class="keyword">true</span><span>,&nbsp;</span><span class="string">&quot;errorCode&quot;</span><span>:&nbsp;0,&nbsp;</span><span class="string">&quot;errorString&quot;</span><span>:&nbsp;</span><span class="string">&quot;success&quot;</span><span>});},&nbsp;3000);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>},&nbsp;&nbsp;</span></li>
</ol>
</div>
<p>如此修改之后，便实现了完美的任何环境下激活都免发国际短信了。</p>
<p>我们可以把这个修改合并到前面的WIFI激活补丁中去，这样就可以直接用MetaDoctor来实现对ROM的完美修改了。</p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=381</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-11-25 13:34</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=380</guid>
			<title>WiFi激活</title>
			<author>andot</author>
			<description><![CDATA[<p>WiFi激活不是本人首创，该方法在WebOS还只是1.0.2的时候，就已经被开发出来了，并被记录在了&nbsp;<a href="http://www.webos-internals.org/wiki/Patch_webOS_Bypassing_Activation">http://www.webos-internals.org/wiki/Patch_webOS_Bypassing_Activation</a>&nbsp;上。</p>
<p>但是上面写的都是手工修改的方法，做起来比较麻烦，用MetaDoctor就会简单的多：</p>
<p>第一步，在patches目录下找到你需要修改的版本的目录，然后在里面创建一个空的patch文件，比如叫wifi-activation.patch。</p>
<p>第二步，用MetaDoctor的scripts目录下面的unpack-doctor或者unpack-rootfs把WebOS Doctor解开。</p>
<p>第三步，找到/usr/palm/applications/com.palm.app.firstuse/app/controllers/firstuse-util.js，复制一份，比如叫firstuse-util.new.js，然后对其修改保存。</p>
<p>第四步，运行diff &ndash;u firstuse-util.js firstuse-util.new.js &gt; firstuse-util.patch，生成补丁。</p>
<p>第五步，同样方法修改并生成account-service.patch。</p>
<p>第六步，把这两个patch里的内容复制到patches目录下创建的那个wifi-activation.patch文件中，每个文件开头那两行的格式，可以按照bypass-activation.patch里面的格式改一下（我没试过不改可不可以用）。</p>
<p>最后，修改Makefile，在其中加上WIFI_ACTIVATION这个选项，修改方法可以参考它原来的BYPASS_ACTIVATION的代码，具体修改那几行这里就不列出来了。 上面的说明中，细心的读者也许会发现，我把Wiki里面关于app-assistant.js的修改给忽略了。不是我忘记了，而是故意的，下面就来解释为何忽略。关于app-assistant.js的修改其实就是bypass-activation.patch做的事情，不同版本的webOS的bypass-activation.patch并不相同，所以按照那个修改并不是最好的方法，最好的方法是直接在Makefile中把BYPASS_ACTIVATION这一项打开就一样了。另外，WIFI_ACTIVATION跟BYPASS_ACTIVATION并没有直接的关系，只是打开BYPASS_ACTIVATION之后，你可以在刷机之后不用插卡，但是不能用其它方式激活，只能用WIFI激活。而不打开BYPASS_ACTIVATION的话则必须插卡，但是除了可以用WIFI激活意外，也可以用2G、3G方式激活。</p>
<p>好了，现在运行一下MetaDoctor的make命令，你的带WIFI激活的ROM就生成了。</p>
<p>刷机之后，在紧急拨号菜单里就可以打开WIFI设置页了。</p>
<p>但这个WIFI设置有一点点小问题，就是设置完成之后，你会发现无法退出这个设置界面，要想继续激活的过程，就需要用&ldquo;方块+Sym+R&rdquo;来重启手机才能继续。</p>
<p>那如何才能让让WIFI设置界面可以在设置完成之后正常退出呢？这个思路可以参考紧急拨号界面。</p>
<p>在account-service.js这个文件中，有一个方法是用来打开紧急拨号界面的，我们来看一下它的代码：</p>
<div class="codeText">
<div class="codeHead">JavaScript代码</div>
<div class="bar">&nbsp;</div>
<ol start="0" class="dp-c">
    <li class="alt"><span><span>makeEmergencyCall:&nbsp;</span><span class="keyword">function</span><span>&nbsp;(emergencyNumber)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;Mojo.Log.info(<span class="string">&quot;Emegerncy&nbsp;call&nbsp;to&nbsp;phone&nbsp;app&nbsp;-------------------------------------------------:&nbsp;&quot;</span><span>,emergencyNumber);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Mojo.Service.Request(</span><span class="string">&quot;palm://com.palm.applicationManager/open&quot;</span><span>,&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters:&nbsp;{&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id:&nbsp;<span class="string">'com.palm.app.phone'</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params:&nbsp;{&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="string">&quot;prefill&quot;</span><span>:&nbsp;emergencyNumber,&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="string">&quot;firstuse&quot;</span><span>:</span><span class="keyword">true</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="string">&quot;locale&quot;</span><span>:&nbsp;Account.language&nbsp;+&nbsp;</span><span class="string">'_'</span><span>&nbsp;+&nbsp;Account.country&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
    <li class=""><span>},&nbsp;&nbsp;</span></li>
</ol>
</div>
<p>这段代码中，我们可以看到firstuse和locale这两个参数，也就是说紧急拨号调用的就是电话程序，只不过是传入了一个firstuse参数让其可以作特殊处理（locale则是可以在调用它时设置语言）。所以，我们在紧急拨号界面下可以看到取消按钮，而普通情况下打电话则没有这个按钮。</p>
<p>所以，我们也可以给WIFI设置程序增加一个firstuse参数，如果要让他也能根据调用环境设置语言，我们也可以给它增加一个locale参数，不过com.palm.app.wifi本身是不支持这两个参数的，因此我们要对它进行修改。下面是对com.palm.app.wifi相关文件进行的修改：</p>
<div class="codeText">
<div class="codeHead">JavaScript代码</div>
<div class="bar">&nbsp;</div>
<ol start="0" class="dp-c">
    <li class="alt"><span><span>---&nbsp;.orig/usr/palm/applications/com.palm.app.wifi/app/controllers/app-assistant.js&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+++&nbsp;/usr/palm/applications/com.palm.app.wifi/app/controllers/app-assistant.js&nbsp;&nbsp;</span></li>
    <li class="alt"><span>@@&nbsp;-9,6&nbsp;+9,16&nbsp;@@&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span>&nbsp;dashboardStage&nbsp;=&nbsp;</span><span class="keyword">this</span><span>.controller.getStageProxy(</span><span class="string">'wifidashboard'</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span>&nbsp;networkListStage&nbsp;=&nbsp;</span><span class="keyword">this</span><span>.controller.getStageProxy(</span><span class="string">'networklist'</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(params)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.firstuse&nbsp;=&nbsp;PalmSystem.isMinimal&nbsp;||&nbsp;params.firstuse&nbsp;===&nbsp;</span><span class="keyword">true</span><span>;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//If&nbsp;the&nbsp;First&nbsp;Use&nbsp;passes&nbsp;the&nbsp;locale&nbsp;different&nbsp;than&nbsp;the&nbsp;current&nbsp;one,&nbsp;change&nbsp;the&nbsp;Mojo.Locale(Framework)</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="keyword">this</span><span>.firstuse)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(params.locale&nbsp;&amp;&amp;&nbsp;params.locale.length&nbsp;===&nbsp;5&nbsp;&amp;&amp;&nbsp;params.locale&nbsp;!=&nbsp;Mojo.Locale.current)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mojo.Locale.set(params.locale);&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(networkListStage)&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mojo.Log.info(<span class="string">&quot;Wifi&nbsp;launch&nbsp;reactivate&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>---&nbsp;.orig/usr/palm/applications/com.palm.app.wifi/app/controllers/networklist-assistant.js&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+++&nbsp;/usr/palm/applications/com.palm.app.wifi/app/controllers/networklist-assistant.js&nbsp;&nbsp;</span></li>
    <li class=""><span>@@&nbsp;-3,6&nbsp;+3,7&nbsp;@@&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;<span class="keyword">var</span><span>&nbsp;list_label_toggle_off&nbsp;=&nbsp;$L(</span><span class="string">&quot;Off&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;<span class="keyword">var</span><span>&nbsp;list_label_list_other_network&nbsp;=&nbsp;$L(</span><span class="string">&quot;Join&nbsp;other&nbsp;network&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;<span class="keyword">var</span><span>&nbsp;list_label_list_network&nbsp;=&nbsp;$L(</span><span class="string">&quot;Join&nbsp;network&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+<span class="keyword">var</span><span>&nbsp;list_label_done_button&nbsp;=&nbsp;$L(</span><span class="string">&quot;Done&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;<span class="keyword">var</span><span>&nbsp;list_label_status_associating&nbsp;=&nbsp;$L(</span><span class="string">&quot;Connecting......&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;<span class="keyword">var</span><span>&nbsp;list_label_status_associated&nbsp;=&nbsp;$L(</span><span class="string">&quot;...Connecting...&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>@@&nbsp;-70,7&nbsp;+71,7&nbsp;@@&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mojo.Log.info(<span class="string">&quot;initialize():&nbsp;called&nbsp;via&nbsp;wifi&nbsp;preferences&nbsp;with&nbsp;params&nbsp;-&nbsp;&quot;</span><span>&nbsp;+&nbsp;Object.toJSON(params));&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.bRunViaPreferencesMenu&nbsp;=&nbsp;</span><span class="keyword">true</span><span>;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.params&nbsp;=&nbsp;params;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(params.hotspot)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(params.hotspot&nbsp;||&nbsp;params.firstuse)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.params&nbsp;=&nbsp;params;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.findNetworksHandle&nbsp;=&nbsp;undefined;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>@@&nbsp;-170,6&nbsp;+171,17&nbsp;@@&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.doneButtonModel&nbsp;=&nbsp;{buttonLabel:&nbsp;list_label_done_button};&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.controller.setupWidget(</span><span class="string">'doneButton'</span><span>,&nbsp;{type:Mojo.Widget.activityButton},&nbsp;</span><span class="keyword">this</span><span>.doneButtonModel);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.doneButton&nbsp;=&nbsp;</span><span class="keyword">this</span><span>.controller.get(</span><span class="string">'doneButton'</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="keyword">this</span><span>.params&nbsp;&amp;&amp;&nbsp;</span><span class="keyword">this</span><span>.params.firstuse)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.doneButton.style.display&nbsp;=&nbsp;</span><span class="string">&quot;block&quot;</span><span>;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.doneButton.style.display&nbsp;=&nbsp;</span><span class="string">&quot;none&quot;</span><span>;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mojo.Event.listen(<span class="keyword">this</span><span>.doneButton,&nbsp;</span><span class="string">'mojo-tap'</span><span>,&nbsp;</span><span class="keyword">this</span><span>.closeAllStages.bind(</span><span class="keyword">this</span><span>))&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timing.pause(<span class="string">'scene#networklist#setup'</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;<span class="comment">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mojo.Log.info(&quot;setup():&nbsp;leaving&quot;);</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;&nbsp;</span></li>
    <li class="alt"><span>@@&nbsp;-976,6&nbsp;+988,10&nbsp;@@&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template:&nbsp;<span class="string">'joinwapicerts/joinwapicerts-scene'</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assistant:&nbsp;<span class="keyword">new</span><span>&nbsp;JoinwapicertsAssistant(</span><span class="keyword">this</span><span>,&nbsp;item)&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;closeAllStages:&nbsp;<span class="keyword">function</span><span>()&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.controller.stageController.getAppController().closeAllStages();&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;});&nbsp;&nbsp;</span></li>
    <li class=""><span>---&nbsp;.orig/usr/palm/applications/com.palm.app.wifi/app/views/networklist/networklist-scene.html&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+++&nbsp;/usr/palm/applications/com.palm.app.wifi/app/views/networklist/networklist-scene.html&nbsp;&nbsp;</span></li>
    <li class=""><span>@@&nbsp;-18,4&nbsp;+18,5&nbsp;@@&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&nbsp;id=<span class="string">&quot;wifiOffText&quot;</span><span>&nbsp;style=</span><span class="string">&quot;display:none;&quot;</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">&quot;palm-text-wrapper&quot;</span><span>&gt;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&nbsp;<span class="keyword">class</span><span>=</span><span class="string">&quot;palm-body-text&quot;</span><span>&nbsp;x-mojo-loc=</span><span class="string">''</span><span>&gt;Wi-Fi&nbsp;is&nbsp;turned&nbsp;off.&lt;/div&gt;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&nbsp;x-mojo-element=<span class="string">&quot;Button&quot;</span><span>&nbsp;style=</span><span class="string">&quot;display:none;&quot;</span><span>&nbsp;id=</span><span class="string">&quot;doneButton&quot;</span><span>&gt;&lt;/div&gt;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&lt;/div&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<p>其实很简单就是增加一个Done的按钮，这个按钮在com.palm.app.wifi启动时，如果带有firstuse这个参数就设置为可见，而这个按钮的用处就是关闭WIFI设置程序。另外，开头还会根据locale参数来设置一下语言。</p>
<p>那现在我们在com.palm.app.firstuse里面再调用它，只要带上这两个参数就可以了。接下来我们可能还希望在刷机第一次启动时，选择语言之前就能进行WIFI配置。最简单的方法当然就是在设置语言的页面里面也调用这个打开WIFI设置程序的方法咯。但如果你真的这样做的话，会发现你并看不到WIFI设置程序。原因是最开始执行时，被放在后面了，只有当它完全启动之后，再调用一次，他才会显示到前面来。但是我们不知道它需要多久才能启动完毕，所以我们设置几个定时器，每隔一段时间调用一次就可以啦：</p>
<div class="codeText">
<div class="codeHead">JavaScript代码</div>
<div class="bar">&nbsp;</div>
<ol start="0" class="dp-c">
    <li class="alt"><span><span>---&nbsp;.orig/usr/palm/applications/com.palm.app.firstuse/app/controllers/language-assistant.js&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+++&nbsp;/usr/palm/applications/com.palm.app.firstuse/app/controllers/language-assistant.js&nbsp;&nbsp;</span></li>
    <li class="alt"><span>@@&nbsp;-34,6&nbsp;+34,7&nbsp;@@&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;Listen&nbsp;to&nbsp;##&nbsp;key&nbsp;presses</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.controller.listen(</span><span class="keyword">this</span><span>.controller.sceneElement,&nbsp;Mojo.Event.keydown,&nbsp;FirstUseUtil.handleKeyPressEvent.bind(</span><span class="keyword">this</span><span>));&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AppAssistant.accountService.enableWifi();&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;powerDownDevice:&nbsp;<span class="keyword">function</span><span>&nbsp;()&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>---&nbsp;.orig/usr/palm/applications/com.palm.app.firstuse/app/controllers/firstuse-util.js&nbsp;&nbsp;</span></li>
    <li class=""><span>+++&nbsp;/usr/palm/applications/com.palm.app.firstuse/app/controllers/firstuse-util.js&nbsp;&nbsp;</span></li>
    <li class="alt"><span>@@&nbsp;-197,11&nbsp;+197,13&nbsp;@@&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labels&nbsp;=&nbsp;[{label:&nbsp;$L(<span class="string">'Emergency&nbsp;call'</span><span>),&nbsp;command:&nbsp;</span><span class="string">'emergency-call'</span><span>},&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{label:&nbsp;$L(<span class="string">'Enable&nbsp;WiFi'</span><span>),&nbsp;command:&nbsp;</span><span class="string">'enable-wifi'</span><span>},&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{label:&nbsp;$L(<span class="string">'Cancel'</span><span>),&nbsp;command:&nbsp;</span><span class="string">'cancel'</span><span>}&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;];&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(FirstUseUtil.customerCareNumber&nbsp;&amp;&amp;&nbsp;FirstUseUtil.customerCareNumber.length&nbsp;&gt;&nbsp;0)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labels&nbsp;=&nbsp;[{label:&nbsp;$L(<span class="string">'Emergency&nbsp;call'</span><span>),&nbsp;command:&nbsp;</span><span class="string">'emergency-call'</span><span>},&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{label:&nbsp;$L(<span class="string">'Call&nbsp;customer&nbsp;service'</span><span>),&nbsp;command:&nbsp;</span><span class="string">'customer-care'</span><span>},&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{label:&nbsp;$L(<span class="string">'Enable&nbsp;WiFi'</span><span>),&nbsp;command:&nbsp;</span><span class="string">'enable-wifi'</span><span>},&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{label:&nbsp;$L(<span class="string">'Cancel'</span><span>),&nbsp;command:&nbsp;</span><span class="string">'cancel'</span><span>}&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;];&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>@@&nbsp;-220,6&nbsp;+222,8&nbsp;@@&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mojo.Log.info(<span class="string">&quot;-----------------&nbsp;FirstUseUtil.carrierName&nbsp;----------------&quot;</span><span>,&nbsp;FirstUseUtil.carrierName());&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span>&nbsp;carrierName&nbsp;=&nbsp;Mojo.Environment.DeviceInfo.carrierName&nbsp;||&nbsp;(FirstUseUtil.carrierString&nbsp;&amp;&amp;&nbsp;</span><span class="keyword">typeof</span><span>&nbsp;FirstUseUtil.carrierString&nbsp;===&nbsp;</span><span class="string">&quot;string&quot;</span><span>&nbsp;?&nbsp;FirstUseUtil.carrierString.toUpperCase()&nbsp;:&nbsp;</span><span class="string">&quot;&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AppAssistant.accountService.callCustomerCare(FirstUseUtil.customerCareNumber,&nbsp;$L(carrierName));&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(value&nbsp;==&nbsp;</span><span class="string">&quot;enable-wifi&quot;</span><span>)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AppAssistant.accountService.enableWifi();&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>(value&nbsp;==&nbsp;</span><span class="string">&quot;exit&quot;</span><span>){&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(isDemoMode){&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">new</span><span>&nbsp;Mojo.Service.Request(</span><span class="string">'palm://com.palm.oddService'</span><span>,&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>---&nbsp;.orig/usr/palm/applications/com.palm.app.firstuse/app/models/account-service.js&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+++&nbsp;/usr/palm/applications/com.palm.app.firstuse/app/models/account-service.js&nbsp;&nbsp;</span></li>
    <li class=""><span>@@&nbsp;-408,6&nbsp;+408,33&nbsp;@@&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;enableWifi:&nbsp;<span class="keyword">function</span><span>()&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span>&nbsp;method&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Mojo.Service.Request(</span><span class="string">&quot;palm://com.palm.applicationManager/open&quot;</span><span>,&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters:&nbsp;{&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id:&nbsp;<span class="string">'com.palm.app.wifi'</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params:&nbsp;{&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="string">&quot;firstuse&quot;</span><span>:&nbsp;</span><span class="keyword">true</span><span>,&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="string">&quot;locale&quot;</span><span>:&nbsp;Account.language&nbsp;+&nbsp;</span><span class="string">'_'</span><span>&nbsp;+&nbsp;Account.country&nbsp;&nbsp;</span></span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span>&nbsp;t1&nbsp;=&nbsp;setTimeout(</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clearTimeout(t1);&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method();&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;8000);&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span>&nbsp;t2&nbsp;=&nbsp;setTimeout(</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clearTimeout(t2);&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method();&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;4000);&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span>&nbsp;t3&nbsp;=&nbsp;setTimeout(</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clearTimeout(t3);&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method();&nbsp;&nbsp;</span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;2000);&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;method();&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>+&nbsp;&nbsp;&nbsp;},&nbsp;&nbsp;</span></li>
    <li class=""><span>+&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;makeEmergencyCall:&nbsp;<span class="keyword">function</span><span>&nbsp;(emergencyNumber)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mojo.Log.info(<span class="string">&quot;Emegerncy&nbsp;call&nbsp;to&nbsp;phone&nbsp;app&nbsp;-------------------------------------------------:&nbsp;&quot;</span><span>,emergencyNumber);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Mojo.Service.Request(</span><span class="string">&quot;palm://com.palm.applicationManager/open&quot;</span><span>,&nbsp;{&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<p>经过这样的修改，我们就可以实现完美的开机WIFI设置了。</p>
<p>上面两段加起来就是WIFI激活的补丁了。我们用这个补丁来替换最开始那个wifi-activation.patch就可以啦。</p>
<p>不过我们还需要作一点小小的工作，那就是要把com.palm.app.wifi这个包的处理部分也要加入到Makefile中，我们可以在Makefile中寻找这段代码：</p>
<div class="codeText">
<ol start="0" class="dp-perl">
    <li class="alt"><span><span>ifeq&nbsp;(${ADD_EXTRA_CARRIERS},1)&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;OLDIPKGS&nbsp;+=&nbsp;pmcarrierdb&nbsp;&nbsp;</span></li>
    <li class="alt"><span>endif&nbsp;&nbsp;</span></li>
</ol>
</div>
<p>然后再它前面加入：</p>
<div class="codeText">
<ol start="0" class="dp-perl">
    <li class="alt"><span><span>ifeq&nbsp;(${WIFI_ACTIVATION},1)&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;OLDIPKGS&nbsp;+=&nbsp;com.palm.app.wifi&nbsp;&nbsp;</span></li>
    <li class="alt"><span>endif&nbsp;&nbsp;</span></li>
</ol>
</div>
<p>就可以啦，接下来的工作，Makefile就可以正确处理了。</p>
<p>最后我们运行：</p>
<pre><code>make DEVICE=veer CARRIER=att all</code></pre>
<p>就可以生成带有WIFI激活功能的ROM了。</p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=380</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-11-04 23:55</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=379</guid>
			<title>WebOS ROM修改工具</title>
			<author>andot</author>
			<description><![CDATA[<p>工欲善其事，必先利其器。所以，我们要先把用于修改WebOS ROM的工具找好，其实工具不多，下面先列一下这些工具：</p>
<ol>
    <li>Linux（例如Ubuntu或Debian）或Mac OS X</li>
    <li>JRE</li>
    <li>Palm SDK</li>
    <li>MetaDoctor</li>
</ol>
<p>接下来，我们就有细细讲解了。</p>
<h1>Linux或Mac OS X</h1>
<p>必须的！</p>
<p>Windows不行，因为后面要介绍的主力工具MetaDoctor不支持Windows，就算在Windows上装了Cygwin也不支持。至于是不是真是这样，我倒没有亲自验证过，www.webos-internals.org上是这样写的。具有科学态度的同学如果有时间，可以自己验证一下。</p>
<p>用Linux的话，它的shell是现成的，定制ROM需要到一些命令和工具在系统装好之后也都有了，比如tar、ar、unzip、make等等。另外，推荐用Ubuntu或Debian。因为就算缺少什么命令没有安装，直接用apt-get或者图形界面的软件包管理器安装就可以啦，非常方便。</p>
<p>用Mac OS X的话，需要把XCode一起安装一下，虽然用不到XCode本身，但需要用到它带的一些开发用的工具。另外，还需要安装MacPorts，它也依赖XCode。所以，用Mac OS X的话，比起用Ubuntu或Debian来还是比较麻烦的。</p>
<p>至于这两个系统怎么用这里就不再详解了，否则就跑题了。</p>
<h1>JRE</h1>
<p>必须的！</p>
<p>后面介绍的工具需要调用它来完成一些工作。</p>
<p>这个怎么安装，干啥用的也不介绍了。我想用webOS手机的同学应该没有不知道它的。而且资料多的很，就算真的不了解的同学也可以自己去查嘛。我就不再废话了。</p>
<h1>Palm SDK</h1>
<p>必须的吗？不是。它是webOS的开发包，虽然我们并不是要用它来做开发，但它在我们用于定制ROM的调试过程中会很有用。另外，MetaDoctor中也有调用它的地方，不过也不是在定制ROM的环节上。但我们装了它总没坏处。</p>
<h1>MetaDoctor</h1>
<p>定制WebOS ROM的主力工具。虽然它只是几个不算怎么长的脚本的集合，但是有了它，可以让你在定制ROM上做到事半功倍，比纯手工打造要方便太多了。当然，它本身内置的脚本并不一定能满足你所有的要求，但你可以扩展修改它，至于怎么扩展修改，我们下一节再举例说明。</p>
<p>现在先介绍它的基本功能。</p>
<p>在<a href="http://www.webos-internals.org/wiki/Application:MetaDoctor">http://www.webos-internals.org/wiki/Application:MetaDoctor</a>上有关于MetaDoctor的一些英文介绍，大致涵盖了安装，基本运行方法，和一些杂七杂八的东西。所以，这些也不详细讲解了，不过为了保持文章完整性，还是要大体说一下。</p>
<h2>安装</h2>
<p>很简单。</p>
<p>只有Windows的同学，需要安装一下Linux，推荐是Ubuntu最新版。安装方式上面的英文介绍里说的是用Wubi方式，其实装在虚拟机里也一样用。</p>
<p>然后呢，就是安装git，安装jre，之后用git来把meta-doctor从服务器上下载下来，这样你就有了。</p>
<p>在Mac OS X上也差不多，不过要先安装XCode、再安装MacPorts，再用MacPorts安装md5sha1sum、gnutar、git-core、wget、gpatch这些基本工具，最后也是用git把meta-doctor从服务器上下载下来。</p>
<h2>目录结构</h2>
<p>从服务器上下载的meta-doctor目录下面有一个Makefile和三个目录。</p>
<p>这个Makefile是定制ROM的最关键的主文件，后面详解其中的关键。先说说那三个目录：</p>
<h3>patches目录</h3>
<p>这个目录下，保存的是一些补丁。</p>
<p>其中carriers目录下是某些运营商的网络配置的定制文件，doctor目录下是对刷机工具的几个补丁文件。</p>
<p>webos-x.x.x这些目录下面是对具体版本的ROM的一些补丁，自带的里面只有一个bypass-activation的补丁。</p>
<p>这些文件都是供Makefile调用的，如果有需要我们也可以把自己写的补丁放在它下面，然后对Makefile做相应修改之后，我们自己的补丁也就可以用了。</p>
<h3>hashes目录</h3>
<p>这个目录下，保存的是一些运营商（carriers）和手机制式（models）的散列数据。用于设置自定义ROM的运营商和手机制式用。它们也是供Makefile调用的。</p>
<h3>scripts目录</h3>
<p>这个目录下保存了很多宝贝脚本。</p>
<p>一部分是供Makefile调用的，一部分是单独使用的，还有一部分是例子。</p>
<p>这里面replace-md5sums.py是供Makefile调用的。</p>
<p>preware-ca-bundle.crt和preware-install.db也是供Makefile调用的，不过已经过时，没啥用了。</p>
<p>decode-hashes是解码刷机文件中recoverytool.config这个文件里面那些运营商、手机制式等Hash值用的工具。</p>
<p>encode-hash是教你如何实现自定义运营商、手机制式等Hash值的编码的一个例子。</p>
<p>unpack-doctor可以帮你把刷机的doctor的jar分解成目录和文件的工具。</p>
<p>unpack-rootfs跟unpack-doctor功能类似，但它只分解rootfs。</p>
<p>WebOS-Internals.tga是Makefile用来替换手机启动时的第一个启动画面的文件。你也可以把它替换掉。</p>
<p>剩下的那些xxx-xxx-1.4.5.1是用来自制某些运营商发布的某些制式的手机的1.4.5.1的刷机ROM的。xxx-xxx-2.1.0当然就是定制2.1.0的刷机ROM的咯。关于这些2.1.0的脚本的使用方法，可以参见：<a href="http://www.webos-internals.org/wiki/WebOS_2_Upgrade">http://www.webos-internals.org/wiki/WebOS_2_Upgrade</a>。因为这不是本文的重点，这里就不做更进一步的介绍了。</p>
<h2>Makefile</h2>
<p>这个文件才是重点要介绍的。</p>
<p>该文件开头有许多选项，这些是基本功能定制的开关。下面先把这些选项作个简单说明。</p>
<h3>BYPASS_ACTIVATION</h3>
<p>该选项的功能说明是去掉刷机后第一次启动时的激活过程。而实际上它的作用仅仅是让第一次启动的运营商网络变得无效，以至于无法激活。另外，它还有一个作用就是让机器不检查Sim卡状态。这时，你就是插一张坏卡也能开机，不插卡也能开机。但不能激活你就进不了系统啊。那怎么办呢？</p>
<p>如果是2.x的系统，那好办，可以在紧急拨号界面里，输入#*3386633#来启动开发者模式开关程序，打开开发者模式之后重启，第二次启动就自动进入系统了。</p>
<p>但如果是1.x的系统，那就麻烦了。因为上面的方法对1.x系统不适用啊。那该怎么办呢？</p>
<p>一种办法当然就是我们下一节介绍的WIFI激活。另一种方法则是跳过第一次启动时运行的First Use程序，也就是第二个选项。</p>
<h3>BYPASS_FIRST_USE_APP</h3>
<p>这个选项做的事情正如上面所说，是跳过第一次启动时运行的First Use程序，如何实现的呢？</p>
<p>他在rootfs（就是ROM的根分区）的/var/luna/preferences下建了两个空文件，一个是ran-first-use，另一个是first-use-profile-created，这样就可以欺骗系统在第一次运行时就认为已经运行过firstuse程序了，所以，第一次运行就进入了桌面。</p>
<p>2.x系统的firstuse程序跟手势教程是同一个，想要激活profile，直接运行手势教程就好了。所以就不存在什么问题。但对于1.x的系统来说，firstuse程序默认是不可见的，所以进入桌面之后，想再激活profile就难了。这一点其实开发meta-doctor的大婶们早就想到了。所以，这个选项做的第二件事情就是将/usr/palm/applications/com.palm.app.firstuse下面的appinfo.json和它的资源目录下所有语言的appinfo.json中的visible选项从false改为true。</p>
<p>所以，一般要实现免激活的ROM，只要打开上面两个选项就好了。</p>
<p>注意：BYPASS_FIRST_USE_APP这个选项在修改程序可见性时，有点小问题。使得它跟1.x的advanced configuration for app laucher这个补丁有冲突，使其无法正确安装。解决方法有很多，比如用户安装advanced configuration for app laucher前先把原始的appinfo.json文件替换回去。或者把Makefile中关于appinfo.json的修改的那一段代码注释掉。更多方法大家可以自己琢磨。</p>
<h3>ENABLE_DEVELOPER_MODE</h3>
<p>第三个选项是默认打开开发者模式，这样在第一次启动时，WQI就可以跟手机连接啦。这个选项打开是安全的。它的实现也很简单，就是在根分区的/var/gadget目录下建立一个novacom_enabled的空文件。</p>
<p>该选项只对刷机后未运行删除应用程序和数据（或完全清除）前有效。如果日后在系统的&ldquo;重设选项&rdquo;中选择了任何上述按钮的话，则该文件也会被清除，这样系统启动时，再次进入First Use界面时，开发者模式就关闭了。</p>
<h3>ENABLE_BETA_FEEDS、ENABLE_ALPHA_FEEDS</h3>
<p>第四个选项是针对preware的，该选项打开之后，可以允许preware载入测试版本的程序和补丁列表。</p>
<p>这两个选项的实现是在rootfs（根分区）的/var/preferences/org.webosinternals.preware目录下面建立enable-beta-feeds或enable-alpha-feeds这两个空文件。所以它们并不依赖于是否在ROM中集成preware。</p>
<p>INSTALL_SSH_AUTH_KEYS</p>
<p>这个选项不用于定制通用ROM，仅用于定制个人使用的ROM时使用。它的作用是将SSH的authorized_keys文件导入到设备的用户目录下，这样当在设备上安装了ssh监听程序后，就可以直接从自己的电脑上通过ssh来登录到设备上了。</p>
<h3>INSTALL_WIFI_PROFILES</h3>
<p>这个选项跟上面一样不能用于定制通用ROM，仅用于定制个人使用的ROM。它的作用是让用户刷机之后第一次启动就可以连接上WiFi，这个功能听上去很神奇，但如果你知道该怎么做才能实现时，你就会觉得很没用了。你需要先把现在设备上设置好的WiFi配置文件（/var/preferences/com.palm.wifi/ prefsDB.sl）复制到自己PC（Linux）上，路径是：~/.ssh/com.palm.wifi.prefsDB.sl 或 to ./config/com.palm.wifi.prefsDB.sl，然后开启这个选项后，在运行make时，meta-doctor会把这个文件放到你的ROM中的那个目录下。而每个人的WiFi配置各不相同，所以它不是一个通用的选项。</p>
<h3>AUTO_INSTALL_PREWARE</h3>
<p>这个选项的本意是系统启动后，自动通过网络安装preware。但很不幸，这个选项已经不好用了。所以你只能在注释中看到它。在下面的主要开关列表部分你并看不到它的身影。所以如果你想实现在ROM中集成preware，不要使用这个选项，后面我会介绍如何集成软件到ROM中。</p>
<h3>DISABLE_UPLOAD_DAEMON</h3>
<p>这是一个很有用的选项。官方ROM里有个自动上传数据到PALM服务器的功能。这个自动上传数据的功能会在后台悄悄地自动地上传系统或应用程序崩溃的相关调试信息，用户的GPS信息，每个应用程序所使用的数据，以及它们的运行时长。关掉它可以节省大量的流量。</p>
<p>这个选项的实现很简单，就是把/usr/bin下面的uploadd、contextupload、rdxd这三个程序的可执行权限去掉了。这样当你真的需要恢复时，只要改一下权限就好了。所以即使在刷机之后，用同样的方法也可以关闭上传功能。</p>
<h3>DISABLE_UPDATE_DAEMON</h3>
<p>这个是用来关闭升级服务的。通常用于定制比较旧的，官方不再提供升级的ROM时使用，在定制较新的ROM时，如果开启这个选项，对于不懂下面这段话的用户会影响后续的正常升级。</p>
<p>这个选项的实现跟上面那个选项差不多，它是把/usr/bin目录下的UpdateDaemon和OmaDm这两个程序的可执行权限去掉了。所以如果到时候真的系统真的有升级，用户其实也是可以通过修改这两个文件的权限来恢复升级服务功能的。同样，如果没有开启这个选项，用户在刷机后，也可以用这个方法来关闭升级服务。</p>
<h3>DISABLE_MODEM_UPDATE</h3>
<p>该选项的作用是禁止刷写设备的MODEM。因为对于同一款手机的同一个版本的ROM来说，MODEM通常是不会单独升级的，只有大版本升级时，MODEM才会有可能升级（例如从1.4.5到2.1），通常忽略MODEM刷写是安全的。而且它可以节省刷机的时间，刷写MODEM时，大约需要4-5分钟，禁止刷写MODEM可以节省将近1/3的刷机时间。不过，要是为了保险的话，这个选项还是不要开启的好。</p>
<p>它的实现方式是修改webOS.tar里面的installer.xml，将其中ModemUpdater开头的这行删除掉。</p>
<h3>ENABLE_USB_NETWORKING</h3>
<p>该选项的作用是激活USB网络功能。因为这个功能需要电脑上单独安装驱动。所以一般不打开。</p>
<p>它的实现方式是在/var/gadget下建立一个名为usbnet_enabled的空文件。</p>
<h3>REMOVE_MODEL_CHECK</h3>
<p>该选项的作用是移除手机型号检查。例如将P130UNA的ROM刷到P130UEU的设备上时，可以使用该选项。但你如果把P101UNA刷到P121UNA的设备上时，也是可以使用该选项的，但这真的很有风险，因为没有人可以保证任何两个不同型号的手机的ROM一定会兼容，所以，如果你不知道你在干什么，就不要随便打开这个选项。</p>
<p>这个选项的实现其实很简单，将doctor里面的resources目录下的recoverytool.config文件中的ApprovalMikeHash那一行删除就可以啦。</p>
<h3>REMOVE_CARRIER_CHECK</h3>
<p>该选项的作用是移除运营商检测。例如你打算将ATT的ROM刷到O2上（当然因为这两个手机的型号也不同，所以你还需要把上面那个选项也打开），你就应该打开这个选项。不过它会带来很多副作用，因为开启这个选项之后，刷机时将不会为你安装运营商提供的系统级的ipk，而这些ipk有几个还是相当重要的，完全忽略安装的情况下，你会得到一个很纯的系统，而这个很纯的系统还会有些功能上的缺失，例如壁纸、铃声设置不能保存，应用商店可能无法使用，也无法升级程序等等。所以，通常我们也不会打开这个选项。要实现刷写其它运营商更高版本的ROM，我们其实还有更好的方法。</p>
<p>这个选项的实现比上面的选项稍微复杂些，除了将doctor里面的resources目录下的recoverytool.config文件中的ApprovalCharlieHash和CustomizationBuild这两行删除外，对正常的关于运营商提供的安装包的操作也都忽略不做了。这个功能其实没啥用，所以就不做更详细解释了。如果大家感兴趣，还是自己读代码吧。</p>
<h3>CHANGE_KEYBOARD_TYPE</h3>
<p>这个选项很有用，主要用于给德国键盘、法国键盘的手机替换为正键键盘时制作ROM使用。它有三个选项，z表示QWERTY键盘，y或者y1表示QWERTZ键盘，w1表示AZERTY键盘。</p>
<p>它是通过修改webOS.tar中的intaller.xml以外的另一个xml文件实现的，那个文件的名字对于不同的手机有所差别。它是在这个文件的tokens这个段中，插入&lt;Val name=&quot;KEYoBRD&quot; action=&quot;overwrite&quot; value=&quot;${CHANGE_KEYBOARD_TYPE}&quot;/&gt;这个选项来实现的，其中${CHANGE_KEYBOARD_TYPE}就是上面列出的三个选项值。</p>
<h3>ADD_EXTRA_CARRIERS</h3>
<p>这个选项是用来增加运营商网络配置信息的，还记得上面提到的patches/carriers目录吗？</p>
<p>这个选项就是将这个目录中的文件信息都加到根分区的/etc/carrierdb/carrierdb.json文件中，这样就可以实现自定义网络运营商的网络参数了。虽然这个选项的注释中说仅对2.0.0系统有效，其实是对2.0.0及其以上的版本都有效。只不过我们用不到，因为中国移动、中国联通和中国电信这三大运营商的配置早就写在这个配置文件里了。根本不需要我们去添加，这也是我们为什么拿到手机，插卡就能上网的主要原因。</p>
<h3>VAR_PARTITION_SIZE</h3>
<p>该选项可以让你更改/var分区的大小。这个分区用于保存一些用户数据，不过它下面还有几个目录实际上也是独立的分区都有自己固定的大小，单纯扩大/var分区不能够改变那些目录的空间大小，比如/var/log，/var/db，/var/file-cache等。</p>
<p>该选项的实现也是通过修改webOS.tar中的那个xml文件实现的。</p>
<h3>SWAP_PARTITION_SIZE</h3>
<p>该选项可以让你更改交换分区的大小。实现方式同上。</p>
<h3>EXT3FS_PARTITION_SIZE</h3>
<p>该选项可以增加一个/media/ext3fs的分区。安装ubuntu、debian、android到webOS中时，创建这样一个分区可以让系统更快速稳定一些（跟没有创建这个分区时比，不是跟没有安装上述系统时比）。实现方式同上。</p>
<h2>总结</h2>
<p>上面的修改中，有些修改涉及到根分区下的文件，这些文件中有些不属于某个包（ipk），添加之后只需要计算它的md5值，然后将该值增加到根分区根目录下的md5sum.tar中就可以啦。而有些文件是属于某个包的，对这些文件，在修改之后除了需要重新计算md5值，并将它写入根分区下的md5sum.tar中以外，还需要将该值写入到该包的md5sum校验文件中。另外，因为它所在包的md5sum校验文件也被修改过，因此它所在的包的md5sum校验文件也要重新计算md5值，并写入根分区总的md5sum校验文件包中。如果要在包中增加或删除文件，过程要更复杂，除了修改md5文件，还需要修改list文件和更新list文件的md5值。这个过程不但看上去非常复杂，手动作起来也确实繁琐，好在meta-doctor都帮我们做好了。所以我们借助meta-doctor这个工具，比我们纯手工修改定制ROM还是要方便的多的。</p>
<p>但是对recoverytool.config，webOS.tar下的两个xml文件的修改，手工修改可能比用meta-doctor更方便灵活一些。但手工修改难免会出错，所以风险也要大一些。修改ROM是个细心的活，一定要小心再小心。</p>
<p>meta-doctor的功能远不止上面介绍的这么点。其实它还提供了好多的选项让你更细化的对ROM做定制，只是这些选项并没有列在Makefile头顶的列表里罢了。如果你仔细读源码，你会发现很多有趣且有用的选项。另外，如果现有的功能真的不够用，你也可以通过修改Makefile来自己添加新的选项予以扩展。下一节我们就来讲如何通过修改meta-doctor来实现WIFI激活的功能。</p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=379</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-11-04 14:37</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=378</guid>
			<title>WebOS ROM修改入门教程</title>
			<author>andot</author>
			<description><![CDATA[<p>&nbsp;</p>
<div>1、<a href="http://www.coolcode.org/?action=show&amp;id=379">WebOS ROM修改工具</a></div>
<div>2、<a href="http://www.coolcode.org/?action=show&amp;id=380">WiFi激活</a></div>
<div>3、<a href="http://www.coolcode.org/?action=show&amp;id=381">免发激活短信</a></div>
<div>4、<a href="http://www.coolcode.org/?action=show&amp;id=382">ROM文件结构</a></div>
<div>5、<a href="http://www.coolcode.org/?action=show&amp;id=383">修改打包ipk</a></div>
<div>6、<a href="http://www.coolcode.org/?action=show&amp;id=384">集成安装ipk</a></div>
<div>7、<a href="http://www.coolcode.org/?action=show&amp;id=385">将ROM分解为ipk</a></div>
<div>8、<a href="http://www.coolcode.org/?action=show&amp;id=386">系统汉化</a></div>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=378</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-11-04 14:12</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=375</guid>
			<title>HP Veer ATT 2.1.2 纯净版 ROM（11月6日更新）</title>
			<author>andot</author>
			<description><![CDATA[<p><span class="Apple-style-span" style="font-family: &quot;Droid Sans Fallback&quot;; font-size: medium;">&nbsp;</span>我的Veer终于到了，其实这个是给我老婆买的，这样我是黑色的pixi plus，她用白色的veer，正好配一对。</p>
<div style="font: 14px/normal Tahoma; margin: 0px; padding: 5px; font-size-adjust: none; font-stretch: normal; background-color: rgb(255, 255, 255);">
<p>当然原始的Veer ROM里面有很多的垃圾软件和垃圾信息，俺不喜欢，所以必须去掉。而且俺老婆的Sim卡是移动神州行，没有开通GPRS，但家里有Wifi，所以必须要支持Wifi激活Profile才行。所以，特此定制了这个ROM。</p>
<p>还是先介绍一下该 ROM 的特点吧：</p>
<ol>
    <li>删掉了amazonservice，attwisprd，com.palm.app.amazonstore，com.palm.app.attsyncpanel，com.palm.app.minidm，com.palm.app.mobilehotspot，com.palm.attaddresssync，com.telenav.attnavigation，com.yellowpages.ypmobile.preload，contacts.plugin.pmvoicecommand，minidm，pmvoicecommand-enus，pmvoicecommand-esmx，pmvoicecommand这些 att 的定制包。</li>
    <li>对 sweatshop-attwireless-broadway 做了修改：
    <ul>
        <li>删除了att的客服电话。</li>
        <li>删除了att的电话号码。</li>
        <li>删除了att在浏览器中加入的书签。</li>
        <li>删除了在音乐中加入的amazon市场按钮。</li>
        <li>删除了上面步骤1中删除的包的桌面布局。</li>
        <li>关闭了语音拨号。</li>
        <li>在激活页面时打开了WIFI。</li>
        <li>其它几个记不太清的小的修改。</li>
    </ul>
    </li>
    <li>刷机后第一次启动自动开启WIFI配置，打开WIFI之后，再选择语言（只有英语可选）可以免发国际短信（节省1块钱）。手机激活后，可以通过WIFI来激活或注册profile。另外，在激活页面中也有开启WIFI选项卡的功能。</li>
    <li>关闭了自动数据上传功能。这个自动上传功能会在后台悄悄地自动地上传系统或应用程序崩溃的相关调试信息，用户的GPS信息，每个应用程序所使用的数据，以及它们的运行时长。关掉它可以节省大量的流量。据很多人说，他们使用Veer后，一旦打开2G或3G，每天甚至每小时都有大量的数据通讯，应该就是系统自带的这个功能造成的，现在关闭了，应该就好了。</li>
</ol>
<p>大概的修改就这么多，在优化的同时仍然保持了系统的原汁原味。</p>
<p>下载地址：<a href="http://www.coolcode.org/webos/veer/webosdoctorp160unaatt-2.1.2.jar">http://www.coolcode.org/webos/veer/webosdoctorp160unaatt-2.1.2.jar</a></p>
<p>&nbsp;</p>
<p>10月24日更新：</p>
<p>修复了手势教程不能打开的问题。</p>
<p>除了可用WIFI激活，GSM也可以激活了。&nbsp;</p>
<p>关闭了系统更新，再也不会被系统更新打扰了。</p>
<p>必须插卡才能激活（但是开始可以配置WIFI，免发1元国际短信）。</p>
<p>可选择多国语言。</p>
<p>&nbsp;</p>
<p>10月26、27日更新：</p>
<p>对网络运营商（中国移动、中国联通、中国电信）标识进行了汉化，在中文下自动显示中文，英文下还是显示英文。当然veer不支持中国电信，所以你可能没机会看到这个标识。</p>
<p>删除了内置的Google地图，因为它不支持中国地区。现在刷机完毕之后可以从HP App Catalog中查找Map，有个HP的Bing地图，这个是支持中国的，并且内置中文，而且安装之后，你的veer就有了Enyo框架了。删除的Google地图可以在此下载：http://bbs.zoopda.com/thread-94913-1-1.html</p>
<p>默认开启了开发者模式，刷机之后就可以马上使用WQI用电脑连手机装软件了，不需要用咒语开启开发者模式了。</p>
<p>将中日韩文的字体替换为了最新的android 4.0的Droid Sans FallBack字体，这个字体比旧的android字体体积大一点点，有5M，但是效果却比旧的android字体效果好。而且简体中文、繁体中文、韩文、日文这四种字体都使用这个字体，并且用的是硬链接方式，所以虽然你看到有4个文件，其实只占一份空间。</p>
<p>删除了烦人、无用且乱码的 STK 程序。删除的 STK 程序可以在此下载：http://115.com/file/cl7ik95p#com.palm.app.stk_1.0-64_armv7.ipk有需要的同学，单独安装就可以用了，不想用了还可以卸载掉。</p>
<p>&nbsp;</p>
<p>10月29日更新：</p>
<p>1、任意方式下激活（GPRS/EDGE，3G，WIFI）都免发国际短信，我现在终于不纠结了。</p>
<p>2、中文下有完美的手势教程。</p>
<p>3、更完美的细节汉化（波浪乱码仍然无法解决，没找到可以修改的地方）。</p>
<p>4、集成了Preware 1.8.3官方版本（带中文），可升级，防卸载（实在想卸载也可以用命令行操作，但这个应该说是必装软件，你真的会卸载吗？）。以后刷完机装软件，不需要WQI了。</p>
<p>5、集成了Diffstat、GNU Patch、Lsdiff、UnZip、Zip这五个装补丁之前必装的软件，以后不用担心装以前下载好的补丁缺少依赖无法安装的问题了。</p>
<p>6、App Catalog 内置的是 2.0.23300 版本，比之前自动更新的版本还要新，这个版本是从pre3里面提取出来的，经测试，完美支持Veer。</p>
<p>7、提供了集成软件的新方式（其实是在2.x自带的集成软件方式基础上作了修改，增加了对postinst脚本的支持），基于这个ROM，你可以轻松制作集成版了。</p>
<p>8、不再显示SIM卡联系人。激活后，SIM卡显示的号码是：460004433591831，而不是你的手机号（这也是免发国际短信的关键）。但不影响电话、短信等功能。有同学说他的还是原来的号码，有两个可能，一是原来注册的没删掉，旧的就会保留，二是可能手机卡不同效果也不同，我是动感地带，刷前一个版本时用的是神州行，刷完之后，帐号里显示2个手机卡，一个是旧的神州行，另一个是这个460004433591831，如果你的刷完不变，应该就是你没换卡，显示的就是旧的。</p>
<p>9、免刷MODEM，免查MODEL，刷机速度更快，大约10分钟就可以刷好（不包括重启时间）。</p>
<p>&nbsp;</p>
<p>&nbsp;11月1日更新：</p>
<p>1、去掉了29日更新的第9条，因为它会引起某些机器激活之后无法重启，或者强制重启之后启动不了。现在不会出现刷机之后不能重启的问题了。</p>
<p>2、集成了enyo框架，来自pre3的ROM，以后可以装enyo的程序了。</p>
<p>3、字体换成了Arial Unicode MS，可显示简、繁、日、韩、阿拉伯等国文字。官方的字体和Android字体均不能显示阿拉伯文。</p>
<p>4、在高级大厨jarryson的完美汉化包的基础上做了一些很小的修改，并重新打包为可卸载语言包（App Catalog 我还是没汉化）。感谢jarryson和最初提供汉化包的elite大神们为汉化所做的工作。</p>
<p>5、更正上一个版本的说明，SIM卡卡号虽然在帐号里不一定能看到（有些同学能看到），但Sim卡联系人仍然可以正常访问。也就是说功能跟原版一样。如果不想显示SIM卡联系人，可能只有清空SIM卡了（我不是开玩笑，我本人就是这么干的）。</p>
<p>&nbsp;</p>
<p>11月6日更新：</p>
<p>&nbsp;</p>
<p>1、完美的，不同于任何其它ROM的，任意环境下激活，都免发国际短信（过几天放出方法，正在整理成文）。</p>
<p>2、完全修复刷机之后设置完成最后一步转圈圈的问题（所有情况均已亲测）。</p>
<p>3、集成了最新的preware 1.8.5。一是为了提供一个安装软件的基础环境，二是为了提供一个基础的集成软件的例子（过几天放出方法）。</p>
<p>4、集成了Homebrew JS Service Framework 1.0.1，FileMgr 2.0.7，Internalz Pro 1.5.0。一是为了提供一个文件管理器。二是提供一个集成多个具有依赖，具有服务的软件集成的例子（过几天放出方法）。</p>
<p>5、集成了Unthrottle Download Manager补丁（这个补丁是用来解除下载限制的，该补丁没有任何副作用），集成这个仅是为了提供一个集成补丁的例子，该补丁可卸载，通过该方法集成其它本来可以卸载的补丁均可卸载（过几天放出方法）。</p>
<p>6、集成了jarryson提供的带有iphone UserAgent的libWebKitLuna.so，可以方便浏览针对iphone优化的3G网站，还可以继续使用Google maps了，详细描述请参见jarryson大大的帖子：http://bbs.zoopda.com/thread-97790-1-1.html。</p>
<p>&nbsp;</p>
<p>可卸载的中文包：<a href="http://www.coolcode.org/webos/veer/com.palm.veer.languagepack.zh-cn_2.1.2-6_all.ipk">http://www.coolcode.org/webos/veer/com.palm.veer.languagepack.zh-cn_2.1.2-6_all.ipk</a></p>
</div>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=375</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-10-29 22:17</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=377</guid>
			<title>为M110S内置存储硬件损坏专门制作的VJ04外置存储内核升级包</title>
			<author>andot</author>
			<description><![CDATA[<p>这次这个版本跟上次的VG26版本使用方式相同，将卡分成2个FAT32分区即可，其中第一个分区是sdcard分区，第二个分区是data分区，第二个分区一定要大于1G，有条件的最好给2G。</p>
<p>内核地址：</p>
<p><a href="http://coolcode.org/android/M110S/M110S-Gingerbread-Externel-SDCard-zIMAGE-REV03-VJ04-1944-USER.tar">http://coolcode.org/android/M110S/M110S-Gingerbread-Externel-SDCard-zIMAGE-REV03-VJ04-1944-USER.tar</a></p>
<p>
<p><a href="http://115.com/file/aq6ty55q#M110S-Gingerbread-Externel-SDCard-zIMAGE-REV03-VJ04-1944-USER.tar">http://115.com/file/aq6ty55q#M110S-Gingerbread-Externel-SDCard-zIMAGE-REV03-VJ04-1944-USER.tar</a></p>
</p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=377</link>
			<category domain="http://www.coolcode.org/?cid=30">Android</category>
			<pubDate>2011-10-19 23:36</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=376</guid>
			<title>Palm Pixi Plus att 1.4.5.1 纯净版 ROM（10月12日更新）</title>
			<author>andot</author>
			<description><![CDATA[<p>给老婆定制完Veer的纯净版ROM之后，我制作ROM的经验值增加了，等级也从1级升级为2级。所以要给俺自己的Pixi Plus重新定制一回纯净版ROM。</p>
<p>还是先介绍一下该 ROM 的特点吧：</p>
<blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">
<p>1、删掉了amazonservice，attwisprd，com.palm.app.amazonstore，com.palm.app.attsyncpanel，com.palm.app.minidm，com.palm.attaddresssync，com.telenav.attnavigation，com.yellowpages.ypmobile.preload，minidm 这些 att 的定制包。</p>
<p>2、对 sweatshop-attwireless-broadway 做了修改：</p>
</blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">
<ul>
    <li>删除了att的客服电话。</li>
    <li>删除了att的电话号码。</li>
    <li>删除了att在浏览器中加入的书签。</li>
    <li>删除了在音乐中加入的amazon市场按钮。</li>
    <li>删除了上面步骤1中删除的包的桌面布局。</li>
    <li>删除了激活页面时选择的西班牙语，只保留英语。</li>
    <li>增加了Veer默认桌面（一会儿见截图）。</li>
    <li>在激活页面时打开了WIFI。</li>
    <li>其它几个记不太清的小的修改。&nbsp;</li>
</ul>
</blockquote></blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">
<p>3、刷机后第一次启动自动开启WIFI配置，打开WIFI之后，再选择语言（只有英语可选）可以免发国际短信（节省1块钱）。手机激活后，可以通过WIFI来激活或注册profile。另外，在激活页面中也有开启WIFI选项卡的功能。</p>
<p>4、在激活页面中增加了开启开发模式的选项卡的功能，这样激活Profile之后，就可以直接用WQI安装软件了。&nbsp;</p>
<p>5、关闭了自动数据上传功能。这个自动上传功能会在后台悄悄地自动地上传系统或应用程序崩溃的相关调试信息，用户的GPS信息，每个应用程序所使用的数据，以及它们的运行时长。关掉它可以节省大量的流量。&nbsp;</p>
</blockquote>
<p>大概的修改就这么多，在优化的同时仍然保持了系统的原汁原味。下面是截图赏析时间：</p>
<p>&nbsp;<a href="http://www.coolcode.org/attachment.php?id=226" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/5b804d8db1fe5dd9e55aa443e0463c18.png" border="0" alt="大小: 97.2 K&#13;尺寸: 320 x 400&#13;浏览: 82 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a></p>
<p>刷完开机，可以看到只有一个英文选择，再也不会因为手指太粗而点错变成看不懂的西班牙文了。</p>
<p>&nbsp;<a href="http://www.coolcode.org/attachment.php?id=227" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/5e6bd7cb43cd2f30f10d557e6f3ebae6.png" border="0" alt="大小: 82.98 K&#13;尺寸: 320 x 400&#13;浏览: 70 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=228" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/7da55ccec56fb329d8354b3e70e426ec.png" border="0" alt="大小: 61 K&#13;尺寸: 320 x 400&#13;浏览: 68 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a></p>
<p>激活手机，看到菜单了木有～</p>
<p><a href="http://www.coolcode.org/attachment.php?id=230" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/7cfd54763f278bd06db8e3726da06907.png" border="0" alt="大小: 74.19 K&#13;尺寸: 320 x 400&#13;浏览: 83 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=231" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/0a58e0fb74585c63e84fb8e4b7b08c7f.png" border="0" alt="大小: 97.04 K&#13;尺寸: 320 x 400&#13;浏览: 71 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a></p>
<p>注册或者登录Profile也是完全通过Wifi，此图以验证，绝对没问题。</p>
<p>&nbsp;<a href="http://www.coolcode.org/attachment.php?id=232" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/316696f65836f275aedc45a3b3441dc8.png" border="0" alt="大小: 84.36 K&#13;尺寸: 320 x 400&#13;浏览: 67 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a></p>
<p>进入激动人心的桌面了，Veer的桌面，比pixiplus原来那个大红花好看多了。</p>
<p>&nbsp;<a href="http://www.coolcode.org/attachment.php?id=233" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/05e98d2acc1fce58ffabebc737bd4629.png" border="0" alt="大小: 146.75 K&#13;尺寸: 320 x 400&#13;浏览: 71 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=234" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/4cc58a915fc2d802d005496ceb6a489d.png" border="0" alt="大小: 140.51 K&#13;尺寸: 320 x 400&#13;浏览: 90 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=235" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/b3e173caaa7c3151c9d887c463889b93.png" border="0" alt="大小: 118.11 K&#13;尺寸: 320 x 400&#13;浏览: 69 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=236" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/3d086a00747e2933b187484412e2644c.png" border="0" alt="大小: 150.33 K&#13;尺寸: 320 x 400&#13;浏览: 65 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=237" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/2bc14498d8e20f3002e45258140bb3d9.png" border="0" alt="大小: 145.28 K&#13;尺寸: 320 x 400&#13;浏览: 78 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a></p>
<p>只有原始程序，ATT的定制程序一个都木有了，真干净～</p>
<p>&nbsp;<a href="http://www.coolcode.org/attachment.php?id=238" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/2621fc47ebb380e508fa7ea7ca8d8aef.png" border="0" alt="大小: 31.21 K&#13;尺寸: 320 x 400&#13;浏览: 70 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a></p>
<p>升级程序居然可以用耶，而且报告你已经是最新的1.4.5.1版本咯，尽管ATT从来没有发布过这个版本，哈哈～</p>
<p>好了现在，你可以自己安装自己喜欢的字体，自己喜欢的输入法，自己喜欢的补丁，是不是汉化也完全由你自己来决定啦，纯净版最大到处就是可以让你在纯净的基础上随心所欲，哈哈～</p>
<p>下载：<a href="http://www.coolcode.org/webos/pixiplus/webosdoctorp121ewwatt-1.4.5.1.jar">http://www.coolcode.org/webos/pixiplus/webosdoctorp121ewwatt-1.4.5.1.jar</a></p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=376</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-10-12 02:30</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=374</guid>
			<title>放几张Pixi Plus的WebOS系统截图</title>
			<author>andot</author>
			<description><![CDATA[<p>&nbsp;<a href="http://www.coolcode.org/attachment.php?id=216" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/905544658da4c39f6b30728d396dd774.png" border="0" alt="大小: 31.27 K&#13;尺寸: 320 x 400&#13;浏览: 80 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=217" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/83ef8b71b138e3e9ac6b04f113784d75.png" border="0" alt="大小: 36.07 K&#13;尺寸: 320 x 400&#13;浏览: 75 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=218" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/66133bc8410344a24ae3dff6f2ba9b8b.png" border="0" alt="大小: 38.6 K&#13;尺寸: 320 x 400&#13;浏览: 69 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a></p>
<p>系统版本已经是1.4.5.1了，虽然pixi plus可以刷2.1，但是速度太慢了，尤其是装了汉字输入法之后，慢到基本没法用。</p>
<p><a href="http://www.coolcode.org/attachment.php?id=219" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/1e2a720aa56645ef3ff623ba3bc1d551.png" border="0" alt="大小: 42.88 K&#13;尺寸: 320 x 400&#13;浏览: 67 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a></p>
<p>internalz 原来是支持中文文件名的，之前一直以为它不支持，原来是没有设置好选项，有几个选项设置一下，中文文件名显示就没问题了。</p>
<p><a href="http://www.coolcode.org/attachment.php?id=220" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/ce425e6623dd7f3b5227ca5fca484bed.png" border="0" alt="大小: 162.23 K&#13;尺寸: 320 x 400&#13;浏览: 71 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a></p>
<p>音乐是从谷歌音乐上下载的，mp3里面自带了图片和信息，在WebOS自带的音乐里面打开不会乱码，很爽。</p>
<p><a href="http://www.coolcode.org/attachment.php?id=221" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/6cd01e92fa0b57324f05608fdd98be67.png" border="0" alt="大小: 87.89 K&#13;尺寸: 320 x 400&#13;浏览: 63 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=222" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/c059c743cbd4e27bce0052f0b2542d39.png" border="0" alt="大小: 112.33 K&#13;尺寸: 320 x 400&#13;浏览: 72 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=223" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/eec02a23c05f2d601d48dac31f032753.png" border="0" alt="大小: 84.87 K&#13;尺寸: 320 x 400&#13;浏览: 70 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=224" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/e8cd7f7008a02c7d991632543e5c343a.png" border="0" alt="大小: 81.31 K&#13;尺寸: 320 x 400&#13;浏览: 69 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a><a href="http://www.coolcode.org/attachment.php?id=225" target="_blank"><img src="http://www.coolcode.org/attachments//date_201110/6056f393530b99a434fde4ed7f99fe61.png" border="0" alt="大小: 107.18 K&#13;尺寸: 320 x 400&#13;浏览: 67 次&#13;点击打开新窗口浏览全图" width="320" height="400" /></a></p>
<p>这是我的程序，装的不多，基本够用。ATT定制的那些亚马逊商店什么的，在我定制这个1.4.5.1 ROM的时候就已经去掉了，现在系统很干净。JustInput输入法真的很好用，可惜2.0以上的系统都不支持。</p>
<p>1.4.5.1还有个好处，安装<span class="Apple-style-span" style="color: rgb(51, 51, 51); font-family: Verdana, Tahoma, sans-serif; line-height: 24px; ">Advanced Configuration for App Launcher之后，他的启动器比2.x甚至3.x都强大。可以选择桌面图标排列方式，个数，大小，还可以给图标改名，还能直接删除、隐藏程序。2.x和3.x虽然比1.4.5默认的启动器强大，但是跟这个补丁比起来，实在是差太远了。</span></p>
<p><span class="Apple-style-span" style="color: rgb(51, 51, 51); font-family: Verdana, Tahoma, sans-serif; line-height: 24px; ">过两天，veer就到手了，要是veer能刷1.4.5.1的系统就好了。</span></p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=374</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-10-06 21:27</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=373</guid>
			<title>自用的palm pixi plus att 1.4.5.1 纯净版 ROM</title>
			<author>andot</author>
			<description><![CDATA[<p>入手palm pixi plus也有一个多月了，这是我的第二个WebOS手机，第一个是palm pre，因为装的游戏太多了（8G都被游戏塞满了），所以平时都被儿子拿去玩，成了他的游戏机了。而我又非常喜欢WebOS这个系统，所以果断的入手了pixi plus。pixi plus跟pre的cpu不同，屏幕尺寸也不同。pixi plus上能玩的游戏跟pre比起来少的可怜，但pixi plus的直板全键盘打字很舒服，所以这个现在成了我的主力机。</p>
<p>刚入手时，刷的是官方的att 1.4.5版本的ROM，刷完之后，里面有一些att定制的程序，通讯录里面也有一些att的电话号码，用移动卡当然这些号码都是多余的，浏览器里默认的书签也都是些用不到的。连系统的音乐程序里都有amazon商店的按钮。这些都不是什么大问题，所以将就着用了一个月。这两天看到有人安装debian系统到pixi plus手机上，于是也心血来潮打算玩玩，所以用meta-doctor定制了一个带2G ext3fs分区的ROM，最后装完debian之后，发现除了可以炫耀一下之外，实在是没啥用处，pixi plus的屏幕那么小，跑debian一点都不爽。所以再次重新刷机。</p>
<p>之前用的原版ROM有那么多让我不满意的地方，既然要重新刷机，这次就干脆自己定制一个纯净版的ROM好了，顺便把att原版的1.4.5跟verizon的1.4.5.1做了一个杂交，让att也可以用上1.4.5.1的ROM。定制过程很简单，原来的meta-doctor中自带一个wr升级到verizon的1.4.5.1的脚本，在这个脚本的基础上很容易就可以修改成att升级到verizon的1.4.5.1的版本。然后就是把att中的定制的程序全部删除，那些程序删掉很安全，完全不影响正常使用，而且仍然可以激活profile帐号，可以正常使用App Catlog软件市场。</p>
<p>下面是这个新ROM的特点：</p>
<p>1、适用于ATT版本的pixi plus，其它版本的pixi plus不能刷。</p>
<p>2、免激活且可激活，通过 2G 和 Wifi 都可以激活profile，激活之后应用商店可用。</p>
<p>3、1.4.5.1系统，但在profile上注册后，在<a href="https://ps.palmws.com/palmcsext/console/pages/LoginPage.iface">https://ps.palmws.com/palmcsext/console/pages/LoginPage.iface</a>里登录查看，版本号是1.40.50，但手机上是显示1.4.5.1的。</p>
<p>4、默认开启开发者模式。</p>
<p>5、没有ATT的定制的那些程序和电话号码之类的东西，最原始的ROM，原汁原味。</p>
<p>6、可以安装中文包：<a href="http://www.coolcode.org/attachment.php?id=213" title="264.18 K, 下载次数:790" target="_blank">com.palm.app.languagepack.zh-cn_1.4.5.2_all.ipk</a></p>
<p>7、如果安装Advanced Configuration for App Launcher的话，需要先替换 /usr/palm/applications/com.palm.app.firstuse/appinfo.json，替换成这个就可以了：<a href="http://www.coolcode.org/attachment.php?id=214" title="139 bytes, 下载次数:139" target="_blank">appinfo.json</a></p>
<p>8、如果安装了中文包，又希望汉化Advanced Configuration for App Launcher（v1.4.5-73）的话，将/usr/lib/luna/system/luna-applauncher/resources下的zh_cn替换为：<a href="http://www.coolcode.org/attachment.php?id=215" title="6.05 K, 下载次数:143" target="_blank">zh_cn.zip</a>即可。</p>
<p>9、如果发现壁纸设置后，重启会变成默认壁纸的话，删除：/usr/lib/luna/system/luna-systemui/images/flowers.png 就可以啦。</p>
<p>下载地址：<a href="http://www.coolcode.org/webos/pixiplus/webosdoctorp121ewwatt-1.4.5.1.jar">http://www.coolcode.org/webos/pixiplus/webosdoctorp121ewwatt-1.4.5.1.jar</a></p>
<div>&nbsp;</div>
<p>&nbsp;</p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=373</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-10-04 22:17</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=372</guid>
			<title>HP如何才能让WebOS起死回生</title>
			<author>andot</author>
			<description><![CDATA[<div><strong><br />
</strong></div>
<div><strong>1、HP应该赶快招回被裁掉的WebOS硬件部门，继续生产硬件设备。</strong></div>
<div>&nbsp;</div>
<div>HP停止WebOS硬件设备生产，我想本来是为了向其它手机和平板硬件设备生产商表明不与他们在硬件上竞争的立场（趁Google收购摩托罗拉之际），好让其它硬件设备生产商都来合作生产WebOS硬件设备，有了更多样的WebOS硬件设备占领市场，就可以向Google在android上那样，自己专攻WebOS软件系统和软件市场，通过WebOS合作授权和WebOS软件市场来取得盈利。</div>
<div>&nbsp;</div>
<div>但这个计划却被HP自己将已生产的WebOS产品降价大甩卖的行为给破坏了。因为现有的WebOS产品降价大甩卖，使得用户很难在日后其它设备生产商生产出新的WebOS硬件设备后，会愿意花比现在更多的钱去购买。其他硬件设备生产商当然能看到这点，所以就算现在HP免费给其它硬件厂商WebOS使用授权，那些硬件厂商也不会跟HP合作生产销售WebOS硬件设备的，因为现在这种情况下，单纯生产销售WebOS硬件产品已经不赚钱了。</div>
<div>&nbsp;</div>
<div>而现在HP又不愿意将WebOS低价卖给别的手机和平板生产商，另一方面那些手机和平板生产商对WebOS这个系统也没有能够驾驭的信心，所以如果现在HP不赶快恢复WebOS硬件部门，继续自己生产销售WebOS硬件产品的话，WebOS注定只能等死。</div>
<div>&nbsp;</div>
<div>而现在HP如果恢复硬件部门，继续生产硬件设备的话，WebOS则不但有希望活下来，并且还有希望获得更好的发展。因为近期的WebOS硬件产品降价大甩卖，使得WebOS用户在短时间内增长了许多。已经购买了WebOS产品的用户当然是不希望WebOS死掉，还没有买到的甚至以前没听过WebOS的用户也因为这次事件知道了WebOS的存在。这从一定意义上来说，也算是起到了宣传推动的作用。虽然负面作用也不小，但负面作用都是因为HP要放弃WebOS硬件部门引起的，如果这时HP恢复WebOS硬件部门，则负面影响则会减到最小。</div>
<div>&nbsp;</div>
<div>现在恢复硬件部门，继续生产并低价销售WebOS硬件产品，虽然并不会给HP带来直接受益，如果销售价格继续向现在一样低于成本价格销售甚至还会带来更多的亏损，但这些亏损都是短期的。应该把这些亏损当成是一种投资，等WebOS硬件产品有了一定的市场占有率的时候，给WebOS开发应用的软件开发者就会越来越多，到时候WebOS应用市场火了，HP则可以从应用市场中把之前的亏损都赚回来。而应用市场的中的软件越多，WebOS硬件产品的价值就越大，到时候再推出下一代更高级的WebOS硬件产品时，就可以恢复之前的价格，WebOS也就起死回生了。</div>
<div>&nbsp;</div>
<div>因此恢复硬件部门是现在HP应该首要做的。不然等解散的硬件团队都被其它公司挖走之后，HP再后悔就来不及了。</div>
<div>&nbsp;</div>
<div><strong>2、加大在WebOS软件和硬件产品上创新力度。</strong></div>
<div>&nbsp;</div>
<div>低价销售现有的WebOS硬件产品不是长久之计，虽然它能让WebOS系统占领更多的市场，甚至可以吸引更多的WebOS开发者来开发应用。尽快的完善WebOS系统，在硬件产品上加大创新力度，才是后期制胜的王道。</div>
<div>&nbsp;</div>
<div>WebOS系统尽管从构架上来说，是一个非常先进的系统，但是现在仍然有许多不足之处，甚至新的3.x版本中去掉了之前1.4.5和2.1版本中许多优秀的设计，比如后退和前进手势，应用之前切换的高级手势等。这样搞是没有出路的。</div>
<div>&nbsp;</div>
<div>在硬件上，在保留之前好的设计的同时，要加大创新，只靠一个样式改改大小，改改做工恐怕是不够的。在平板上靠模仿ipad更是不够的，模仿ipad就注定要跟在ipad屁股后面跑，总是跑在人家后面，肯定是没有出路的。</div>
<div>&nbsp;</div>
<div>之所以出现这种状况，我想并不是之前收购来的Palm团队不给力，而是因为HP本身内部的协调不得力，下面的声音上面听不到，好的创意不能被采纳，上面的决定下面也不能被有效的执行。所以&hellip;&hellip;</div>
<div>&nbsp;</div>
<div><strong>3、HP现在应该尽快的把Palm从HP分离出来，并给其足够的投资，然后让其独立发展。</strong></div>
<div>&nbsp;</div>
<div>只有交给Palm这种小的创业型团队，并拥有足够的资金支持，才能有效的改善WebOS软件系统和硬件设计。为股东赚钱并不是只有收购这一种办法，投资同样可以为股东赚钱。如果投资这种方式比收购这种方式能够使WebOS发展的更好，可以让WebOS日后能够赚到更多的钱，又何必拘泥于收购这一种方式呢。</div>
<div>&nbsp;</div>
<div><strong>4、一定要重视中国市场和中国开发者。</strong></div>
<div>&nbsp;</div>
<div>不管是之前的Palm也好，还是现在的HP，都忽视了中国这个大市场。重视起中国市场来，对WebOS的发展绝对是至关重要的。</div>
<div>&nbsp;</div>
<div>首先，WebOS产品在中国是有市场的。现在国内很多的用户只能通过购买水货或者国外代购的方式才能得到WebOS产品，并且中文支持都是靠中国民间来完成的。在这种情况下，WebOS在国内都有一定的用户。如果WebOS现在直接打入中国市场，提供官方的中文支持，并且联合中国几个大的软件开发商，来定制一些中国国内的必备软件的话，定能快速的打开WebOS在中国的市场。</div>
<div>&nbsp;</div>
<div>一旦WebOS打开了中国市场，就能立刻吸引大批的中国开发者来投入到WebOS的应用开发上来。现在不管是iOS还是android的应用开发者中，中国的开发者都不在少数。因此，中国开发者的力量不可小觑。当有了大量的WebOS中国开发者，自然就有了大量的WebOS应用。而只有有了大量的应用，WebOS才能真正体现出它的价值。</div>
<div>&nbsp;</div>
<div><strong>5、投资或收购一个支持WebOS的移动广告平台，并加大对WebOS广告平台的支持力度。</strong></div>
<div>&nbsp;</div>
<div>大量的应用当中，有一部分是收费的，而另一部分是免费的，免费的应用并不一定不能盈利，通过嵌入广告的方式也是可以实现盈利的。如果没有足够的对WebOS支持的广告平台，那么开发免费应用的开发者就会失去开发应用的动力，这必然会影响到应用的总数量。Google有android软件市场，也有adsense/admob移动广告平台，苹果有app store,同时也拥有iAd广告平台。而HP现在只有HP App Calalog这一个软件市场，却缺少了WebOS的广告平台，这不但会影响自己的盈利，而且不利于WebOS生态系统的发展。因此，HP除了完善自己的WebOS软件市场以外，投资或收购一个支持WebOS的移动广告平台，并加大对WebOS广告平台的支持力度是绝对有利的。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>如果HP能够做到以上5点，WebOS还是有起死回生的希望的。否则WebOS这个大好的系统恐怕就要葬送在HP手中了。</strong></div>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=372</link>
			<category domain="http://www.coolcode.org/?cid=32">WebOS</category>
			<pubDate>2011-09-30 17:18</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=371</guid>
			<title>M110S 2.3.4 VG26 外置存储内核和外置存储中文版</title>
			<author>andot</author>
			<description><![CDATA[<p>&nbsp;</p>
<p>这次这个版本跟上次的VG14版本略有不同，虽然VG14和这次的VG26版本的/data分区都是挂载到外置卡的第二个分区上的，但上次第二个分区是被格式化为ext4分区的，而这次采用的是跟内置卡完全一样的rfs分区。</p>
<p>所以这次再刷这个ROM或者内核之前，需要先把外置卡重新分区，这次把TF卡的两个分区都分成FAT32分区就可以啦，因为我发现FAT32的分区是可以被recovery格式化成rfs分区的，而ext2/ext3/ext4的分区则不能被recovery格式化成rfs分区。</p>
<p>为啥不用ext4而改用rfs了呢？因为我发现ext4分区在M110S上不太稳定，用一段时间就出现无法读取的情况。还好是外置卡，可以随时拿出来分区格式化，就算坏了也能替换。但最好还是不要出状况啦，所以这次干脆就用系统内置的rfs分区，现在跟原版内核效果就完全一样了。</p>
<p>内核地址：<a href="http://coolcode.org/android/M110S/ExtSD-Kernel-M110S-2.3.4-VG26.zip">ExtSD-Kernel-M110S-2.3.4-VG26.zip</a> 或者 <a href="http://u.115.com/file/bhdwikin">http://u.115.com/file/bhdwikin#ExtSD-Kernel-M110S-2.3.4-VG26.zip</a></p>
<div>
<p>完整ROM下载地址：<a href="http://coolcode.org/android/M110S/M110S-2.3.4-VG26-ODEX-1.3-rat9-ExtSD.zip">M110S-2.3.4-VG26-ODEX-1.3-rat9-ExtSD.zip</a></p>
</div>
<p>&nbsp;</p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=371</link>
			<category domain="http://www.coolcode.org/?cid=30">Android</category>
			<pubDate>2011-08-10 01:15</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=370</guid>
			<title>LG E900 解锁</title>
			<author>andot</author>
			<description><![CDATA[<p>LG E900 到手已经半个多月了，感觉还不错，尤其是解锁很方便，在任何版本下都可以直接通过注册表解锁。下面的解锁步骤都是从网上搜到的，并非原创，记录下来仅为方便下次解锁。</p>
<p><strong>进入工程模式：</strong></p>
<p>拨号界面输入＃＃634＃，输入密码277634#*#</p>
<p><strong>解锁：</strong></p>
<p>\HKEY_LOCAL_MACHINE\\Comm\Security\LVMod</p>
<p>&quot;DeveloperUnlockState&quot;=1</p>
<p><strong>防锁：</strong></p>
<p>\HKEY_LOCAL_MACHINE\\Software\Microsoft\DeviceReg</p>
<p>&quot;PortalUrlProd&quot;=&quot;&quot;</p>
<p>&quot;PortalUrlInt&quot;=&quot;&quot;</p>
<p><strong>最大无签名应用部署：</strong></p>
<p>\HKEY_LOCAL_MACHINE\\Software\Microsoft\DeviceReg\Install</p>
<p>&quot;MaxUnsignedApp&quot;=2147483647</p>
<p>如果有开发者帐号，可以直接通过 Windows Phone Developer Registration 解锁，但是对无签名应用程序部署数量会有限制，只要修改最大无签名应用部署的注册表项就可以解除部署限制了。</p>
<p>&nbsp;</p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=370</link>
			<category domain="http://www.coolcode.org/?cid=31">WP7</category>
			<pubDate>2011-08-01 16:57</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=369</guid>
			<title>M110S 用外置卡替换内置卡的 TF 卡的分区方法</title>
			<author>andot</author>
			<description><![CDATA[<p>其实分区很简单，本来不想写的，不过既然好多人问，一个一个回答太麻烦，还是写出来好了。前面的那篇 <a href="http://www.coolcode.org/?action=show&amp;id=364">M110S(i9000)内置存储硬件损坏的替换外置存储修复法</a>&nbsp;文章里，讲了直接用 adb shell 连接手机，用 fdisk 分区的方法，不过这个对于好多人来说太难点了，下面说说在 Windows 上用 Acronis Disk Director Suite 怎么分区吧。</p>
<p>首先当然要先安装这个软件，然后把TF卡插到适配器上，然后再插到电脑上，我用的是USB接口的TF卡适配器，至于哪种转SD卡读卡器的适配器可不可以分区我不清楚，有的可以自己试试。</p>
<p>打开之后，找到你的TF卡所在的磁盘，一般情况下，这个卡是有一个分区的，一般大于 8G 的就是 FAT32(LBA) 的分区，不到 8G 的都是 FAT32 的分区，所以如果你看不到 LBA 这个东西，那是因为你的分区大小还不够大，所以有没有都不影响你的使用。</p>
<p>选中已有的分区，然后点右键，或者上面的菜单，选Resize：</p>
<p><a href="http://www.coolcode.org/attachment.php?id=208" target="_blank"><img src="http://www.coolcode.org/attachments/date_201107/thumb_d5467814d1b74875a697a62a37157060.png" border="0" alt="大小: 211.98 K&#13;尺寸: 500 x 320&#13;浏览: 1025 次&#13;点击打开新窗口浏览全图" width="500" height="320" /></a></p>
<p>然后调整分区的大小，以便留出足够的剩余空间作为data分区：</p>
<p><a href="http://www.coolcode.org/attachment.php?id=209" target="_blank"><img src="http://www.coolcode.org/attachments//date_201107/fca59c2e49725e74d74f42372d824cd8.png" border="0" alt="大小: 52.42 K&#13;尺寸: 416 x 387&#13;浏览: 811 次&#13;点击打开新窗口浏览全图" width="416" height="387" /></a></p>
<p>调整好之后，在留出来的剩余空间部分点右键，选Create Partition：</p>
<p><a href="http://www.coolcode.org/attachment.php?id=210" target="_blank"><img src="http://www.coolcode.org/attachments/date_201107/thumb_e4ffb0754e48b41e1bfc72a50e55c350.png" border="0" alt="大小: 208.5 K&#13;尺寸: 500 x 320&#13;浏览: 852 次&#13;点击打开新窗口浏览全图" width="500" height="320" /></a></p>
<p>然后文件系统选ext3（选ext2也可以，反正最后放在手机上都要重新wipe格式化成ext4的），分区一定要选主分区（Primary Partition），不然的话，手机就识别不了啦。分区卷标（Partition label）可写可不写，写上当然好看一点：</p>
<p><a href="http://www.coolcode.org/attachment.php?id=211" target="_blank"><img src="http://www.coolcode.org/attachments//date_201107/05e94b38d94da0539bcfe57d787aa1cf.png" border="0" alt="大小: 54.28 K&#13;尺寸: 416 x 432&#13;浏览: 769 次&#13;点击打开新窗口浏览全图" width="416" height="432" /></a></p>
<p>都做完之后，点Commit按钮，就是上面那一排按钮上的第三个按钮（小旗子），然后出现下面的界面后，再点Proceed：</p>
<p><a href="http://www.coolcode.org/attachment.php?id=212" target="_blank"><img src="http://www.coolcode.org/attachments//date_201107/00779e5776b68bae05732a00174425ad.png" border="0" alt="大小: 58.61 K&#13;尺寸: 416 x 438&#13;浏览: 819 次&#13;点击打开新窗口浏览全图" width="416" height="438" /></a></p>
<p>最后都执行完之后，就可以关闭了。如果提示你重启电脑，不用重启。把卡拔下来，插入手机，然后进recovery之后wipe一下（前提是你已经把外置卡替换内置卡的内核已经刷好了），就可以啦。如果还没有刷那个内核，那你可以先进挖煤刷机，然后再wipe，一定要刷机之后再wipe，刷机之前wipe是没用的。</p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=369</link>
			<category domain="http://www.coolcode.org/?cid=30">Android</category>
			<pubDate>2011-07-27 13:40</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=368</guid>
			<title>16G TF卡终于收到了，M110S成功复活</title>
			<author>andot</author>
			<description><![CDATA[<p>&nbsp;前几天 M110S 内置存储坏了，通过高人的指点研究出了通过外置卡代替内置卡的内核。但实验过程中用的是一个 class2 的2G卡，速度当然不会很快。现在外置卡终于到了。下面来看看效率比较。</p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.1em; margin-left: 0px; ">2G卡速度测试：</p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.1em; margin-left: 0px; "><a href="http://www.coolcode.org/attachment.php?id=205" target="_blank"><img src="http://www.coolcode.org/attachments/date_201107/thumb_df931ba7b091487e8b56ba75bcf69880.png" border="0" alt="大小: 93.37 K&#13;尺寸: 300 x 500&#13;浏览: 174 次&#13;点击打开新窗口浏览全图" width="300" height="500" /></a></p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.1em; margin-left: 0px; ">16G卡速度测试：</p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.1em; margin-left: 0px; "><a href="http://www.coolcode.org/attachment.php?id=206" target="_blank"><img src="http://www.coolcode.org/attachments/date_201107/thumb_8980d54547c16a5a0c5bb8e6d12de678.png" border="0" alt="大小: 92.63 K&#13;尺寸: 300 x 500&#13;浏览: 172 次&#13;点击打开新窗口浏览全图" width="300" height="500" /></a></p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.1em; margin-left: 0px; ">class 10 的16G 卡写入速度比起 class 2 的 2G 卡速度真是快很多呢。不过读取好像都差不多，12MB/s 就是上限了。其实在电脑上测试的时候这个2G卡和16G卡在电脑上读取都能达到18M 左右的速度。所以看来是手机读取性能有问题。</p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.1em; margin-left: 0px; ">2G卡跑分：</p>
<p><a href="http://www.coolcode.org/attachment.php?id=203" target="_blank"><img src="http://www.coolcode.org/attachments/date_201107/thumb_c841eea2f9b0e0ce8071a1ee619d9bdf.png" border="0" alt="大小: 40.28 K&#13;尺寸: 300 x 500&#13;浏览: 171 次&#13;点击打开新窗口浏览全图" width="300" height="500" /></a></p>
<p>16G卡跑分：</p>
<p><a href="http://www.coolcode.org/attachment.php?id=204" target="_blank"><img src="http://www.coolcode.org/attachments/date_201107/thumb_2480551cc8946a9aa8f0b78e0fd3ad6d.png" border="0" alt="大小: 62.02 K&#13;尺寸: 300 x 500&#13;浏览: 173 次&#13;点击打开新窗口浏览全图" width="300" height="500" /></a></p>
<p>跑分很奇怪，换上16G卡后，IO测试分数没什么变化，倒是其它分数都高了，尤其是 CPU 和内存。看来跑分的性能瓶颈现在不在卡的速度上。</p>
<p>16G卡安装之后效果：</p>
<p><a href="http://www.coolcode.org/attachment.php?id=207" target="_blank"><img src="http://www.coolcode.org/attachments/date_201107/thumb_6b4516678ce292a6a3239359211d0141.png" border="0" alt="大小: 53.92 K&#13;尺寸: 300 x 500&#13;浏览: 164 次&#13;点击打开新窗口浏览全图" width="300" height="500" /></a></p>
<p>看上去跟原来内置卡效果一样，哈哈，但是分区大小现在是自己可以随便设置了，比内置卡灵活多了。</p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=368</link>
			<category domain="http://www.coolcode.org/?cid=30">Android</category>
			<pubDate>2011-07-27 13:20</pubDate>
		</item>
		<item>
			<guid>http://www.coolcode.org/?action=show&amp;id=367</guid>
			<title>为M110S内置存储硬件损坏专门制作的VG14外置存储内核升级包</title>
			<author>andot</author>
			<description><![CDATA[<p>昨天为M110S制作了外置存储版的VG14中文版之后，有用户希望能够出一个纯内核版本，这样的话，不管刷那个版本的VG14 ROM，都可以通过刷内核就可以支持外置存储替换内置存储了。</p>
<p>经过一晚上的努力，终于搞定。</p>
<p>刷完之后，这个内核不会自动 wipe，需要自己手动进 recovery 模式进行 wipe。</p>
<p>这个内核是针对 M110S 2.3.4 VG14 版本的，其它版本不要刷。</p>
<p>刷了这个内核之后，/data 分区自动就是 ext4 的啦（这个/data分区是挂载到外部存储卡上的，不像其他加速用的是内置存储卡），相当于自动有了加速功能（当然你的外部卡需要足够快才有加速效果，比如是class 10的TF卡，如果是class 2的，应该不会比原来的内置存储卡快，但也不会慢多少，因为我已经测试过内部存储卡的速度就相当于class 2 TF 卡的速度）。因为没有修改内部存储卡，所以下次刷别的 ROM 直接刷就可以，刷完之后再刷这个内核就可以啦（当然，如果三星出新的版本的升级，我也会跟进内核的升级的）。</p>
<p>注意，在刷本内核升级包之前和之后，千万不要刷其它的加速内核包，如果之前刷过加速内核，一定要先禁用原来的加速，才能刷本内核。否则出现冲突或异常情况，本人概不负责。</p>
<p>第一个版本因为开机带有显示SD卡已损坏的提示，大家强烈要求去掉，特此更新！</p>
<p>下载升级：<a href="http://u.115.com/file/aqzlp45q">http://u.115.com/file/aqzlp45q#ExtSD-Kernel-for-M110S-2.3.4-VG14.tar</a></p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.1em; margin-left: 0px; ">本地下载：<a href="http://coolcode.org/android/M110S/ExtSD-Kernel-for-M110S-2.3.4-VG14.tar">http://coolcode.org/android/M110S/ExtSD-Kernel-for-M110S-2.3.4-VG14.tar</a></p>]]></description>
			<link>http://www.coolcode.org/?action=show&amp;id=367</link>
			<category domain="http://www.coolcode.org/?cid=30">Android</category>
			<pubDate>2011-07-25 21:11</pubDate>
		</item>
	</channel>
</rss>

