最近在移植RK3188 Android4.4,而我的平台是整个SDK用GIT来管理,但原厂提供的是用REPO管理,于是我将原厂的SDK里的.repo删除然后创建自己的GIT库,一切准备就绪,就在Recovery时失败了。
原来原厂在Recovery时会去insmod打包的NAND KO文件,此时KO版本与Linux内核版本对应不上,于是就一直失败了,KO要求的版本是3.0.36+,而我编译出来的Linux内核版本一直是3.0.36,为何会多了个+呢?于是从启动信息入手:
Linux version 3.0.36 (stxinu@x-slam) (gcc version 4.6.x-google 20120106 (prerelease) (GCC) ) #5 SMP PREEMPT Wed Dec 25 16:29:49 CST 2013
在Linux内核源码里搜索Linux version,定位到在源码根目录下的init/version.c中有如下内容:
const char linux_banner[] = 'Linux version ' UTS_RELEASE ' (' LINUX_COMPILE_BY '@' LINUX_COMPILE_HOST ') (' LINUX_COMPILER ') ' UTS_VERSION '\n';
对照如下打印信息,刚好与UTS_RELEASE对应,于是继续搜索UTS_RELEASE,定位到根目录下的Makefile,有如下内容:
(echo \#define UTS_RELEASE '$(KERNELRELEASE)';
于是继续找KERNELRELEASE,在同文件中有如下内容:
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
那么继续找下kernel.release这个文件是如何生成的吧!在同文件中有如下内容:
# Store (new) KERNELRELASE string in include/config/kernel.release include/config/kernel.release: include/config/auto.conf FORCE $(Q)rm -f $@ $(Q)echo '$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))' > $@
其中最后的+号应该是由$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))生成的了,于是继续查找根目录下的scripts/setlocalversion文件,由于传进来的第一个参数不是--save-scmversion,故而scm_only一直为false,并且根目录下也不存在以“localversion”开头的文件名,还有CONFIG_LOCALVERSION和LOCALVERSION没有定义为任何内容,以及CONFIG_LOCALVERSION_AUTO也没有定义,故而最终定位到如下内容:
if test '${LOCALVERSION+set}' != 'set'; then scm=$(scm_version --short) res='$res${scm:++}'fi
因为LOCALVERSION为空,故而${LOCALVERSION+set}返回空,与set不相等,那么条件成立继续执行分支里的内容,执行scm_version函数,该函数开头有如下内容:
if test -e .scmversion; then cat .scmversion returnfi
为了方便,我直接在Linux内核源码根目录下创建一个名为.scmversion的文件,文件内容为+,如果不这样处理,往下会确认是否采用GIT或mercurial、SVN管理,并进行相应的提取处理,以便作为Linux内核版本号的后缀,故而返回+,即scm赋值为+,接下来的${scm:++}由于scm非空,此时会返回后面的+(其中:+为一个运算符),而res为空,故而连接后返回给res的为+,最终将res的+号返回,故而就有了3.0.36+的kernel.release文件中的内容了。END