和绝大多数源码编译安装一样,uboot的编译流程也类似于"make config->make->make install"**三步,只是由于uboot本身是针对多种平台的bootloader,软件的复杂性和通用型决定了编译uboot需要自行填补很多坑。本文主要讨论的就是移植uboot-2013.01的第一个坑——uboot分析。
配置编译环境
既然要编译uboot,首先就要有相应的编译器,我的目标板是三星的exynos4412,就是一个ARM核的SoC,这意味着两件事,第一,我编译的时候必须写明"export ARCH=arm"来表明我要编译的目标平台。第二,必须选择合适的开发工具,由于各种uboot各种linux都是对编译器比较敏感的,所以强烈建议使用tar来安装交叉编译器而不是apt,这样可以防止多个编译工具的冲突,这里,uboot作为裸板程序,我用的是arm-none-linux-guneabi-xxx的编译器,所以用来编译的脚本加了下面两句:
export ARCH=arm
export CROSS_COMPILE=/opt/arm-cross-compile/arm-none-linux-gnueabi-2014-05/bin/arm-none-linux-gnueabi-
...
config的流程
uboot的顶层配置主要依靠下面的这棵树
.
├── Makefile
├── mkconfig
├── include
│ ├── config.mk
│ └── config.h
└── boards.cfg
uboot的配置就是通过键入相应的命令将相应的Makfile变量赋值,通过你的配置,Makefile相应的变量就知道编译哪个平台下的哪个cpu的哪个版本的开发板。注意:不同版本的uboot的配置命令可能是不同的,拿到源码包看README是个很好的习惯,比如uboot-2013-01的配置命令是下面这个样子的,但uboot-2016.10的配置命令就不是这个,感兴趣的可以查一下。:
![README (~-Documents-LearnNote-Porting-src-MakeUboot-u-boot-2013.01) - VIM_20170220_013.png-26.8kB](https://img-blog.csdnimg.cn/img_convert/69bf589f27fc71c5f9165b8efb8dd4f1.png)
在uboot-2013-01中,顶层目录下的boards.cfs文件中查看它支持的开发板和相应的信息,这个文件就像一个全局的"字典",后续的编译过程需要根据配置名检索到相应的信息,所以不要随意修改。下面这个就是字典的样子
![boards.cfg (~-Documents-LearnNote-Porting-src-MakeUboot-u-boot-2013.01) - VIM_20170220_012.png-19.2kB](https://img-blog.csdnimg.cn/img_convert/b7d692be02dff0d73831960720d0ea99.png)
了解了这些,手痒的话就可以先执行下面的脚本试一下,但是并不会生成真正适配我们板子的uboot,只是适配参考板
#!/bin/bash
export ARCH=arm
export CROSS_COMPILE=/opt/arm-cross-compile/arm-none-linux-gnueabi-2014-05/bin/arm-none-linux-gnueabi-
make origen_config
make all
config的分析
首先,当我们"make origen_config"的时候,显然是打算创建makefile里面的一个叫origen_config的目标。根据Makefile的语法,我们就可以找到下面这一段(然而并不是想象中的origen_config:)
![Makefile (~-Documents-LearnNote-Porting-src-MakeUboot-u-boot-2013.01) - VIM_20170220_011.png-22.4kB](https://img-blog.csdnimg.cn/img_convert/2675a1ed542670593812ae665bf2e9bb.png)
Makefile
--770-->unconfig目标的作用是删除所有由于配置产生的文件
--775-->%是Makefile中的通配符,表示任意字符串,所以我们的origen_config
就会与之相匹配,这个目标的依赖于unconfig
,即每次config之前都会删除之前的配置。如果你键入两次"make xxx_config",那么它最终只会形成一个相应的配置文件,这种写法值得借鉴
--776-->"MKCONFIG"就是顶层目录下的mkconfig脚本,而"$(@:_config=)"
就是去除目标中的"_config"串,所以实际上就是去到顶层目录下执行"$mkconfig -A origen"。
我们去到这个mkconfig看看它都做了什么
![mkconfig (~-Documents-LearnNote-Porting-src-MakeUboot-u-boot-2013.01) - VIM_20170220_014.png-33kB](https://img-blog.csdnimg.cn/img_convert/4e3d1a1e3a38c55dd6bc5f14163f7b2a.png)
mkconfig
--22-->我们传入的参数会导致脚本执行这个if里面的内容
--23-31-->用扩展正则表达式去顶层目录下的boads.cfg文件中提取含有origen
相应的行到line
变量中,并把line设置为新的参数列表。取得了这个参数字符串,mkconfig就可以把相应的头文件,链接和全局变量准备好。
我们来稍微看点细节,首先,line里应该有的内容是我们在Boards.cfg中搜到的这个:
![boards.cfg (~-Documents-LearnNote-Porting-src-MakeUboot-u-boot-2013.01) - VIM_20170220_015.png-3.6kB](https://img-blog.csdnimg.cn/img_convert/5b519c979ef990e344f594fbfd4c37d0.png)
根据boards.cfg,这几个参数分别是:TARGET,ARCH,CPU,Board name,Vendor,SoC,Options(origen只有6个,加上之前的$1
一共7个参数),So执行的代码是:
![mkconfig (~-Documents-LearnNote-Porting-src-MakeUboot-u-boot-2013.01) - VIM_20170220_016.png-168.4kB](https://img-blog.csdnimg.cn/img_convert/37aa082566fe7609a2e7107025607707.png)
从中可以看出,这段代码就是把之前line的内容分段并赋值给开头的arch、cpu、board等变量,显然,这些变量对于我们找到相应的目录,相应的文件进行编译至关重要。这些信息,会在mkconfig的之后写入到相应的文件中:
![mkconfig (~-Documents-LearnNote-Porting-src-MakeUboot-u-boot-2013.01) - VIM_20170220_017.png-53.3kB](https://img-blog.csdnimg.cn/img_convert/2753c4517648d6a1f5235dda4159170e.png)
此外,还要建立一些硬链接:
![mkconfig (~-Documents-LearnNote-Porting-src-MakeUboot-u-boot-2013.01) - VIM_20170220_018.png-27.9kB](https://img-blog.csdnimg.cn/img_convert/f5eb13e08a1d24ed6ac89213098691cd.png)
至此,我们需要的"include/config.mk"就配置完成了,这个文件是长成这个样子的:
![Selection_20170222_043.png-10.2kB](https://img-blog.csdnimg.cn/img_convert/f0b87d4433f7045e5744a985ca976d69.png)
除了生成"include/config.mk",mkconfig还负责生成"include/config.h"文件,不过有了之前准备好的变量,这部分只不过是将上面的变量和相应的文件夹进行了初步的定位,代码就是下面这部分:
![mkconfig (~-Documents-LearnNote-Porting-src-MakeUboot-u-boot-2013.01) - VIM_20170220_019.png-117.5kB](https://img-blog.csdnimg.cn/img_convert/a1d70a7b592fd01501f74499d53eb917.png)
它生成的"include/config.h"最终是长成这个样子的:
![Selection_20170222_044.png-50.6kB](https://img-blog.csdnimg.cn/img_convert/1c079aa47b28ae8d841aaa14d505aa0a.png)
有了这两个文件,当我们再执行"$make"的时候就可以找到相应的文件了。