## 系统构建概述
对于移植到开发板上运行的linux系统,我们需要构建三个最基本的东西:
由烧写软件界面可以看到,我们在完成一个完整系统的移植时需要的成分也是以上三个。第一是引导程序,第二是内核系统,第三是命令行,第四是文件系统;
LINUX中bootloader、linuxkernel、rootfile三者之间的确切关系是怎么样的呢?
bootloader ----> linuxkernel ----> rootfile
后者需要前者提供功能支持,前者的目的就是启动后者。
一、内核简介
内核,是一个操作系统的核心。它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。
Linux的一个重要的特点就是其源代码的公开性,所有的内核源程序都可以在/usr/src/linux下找到,大部分应用软件也都是遵循GPL而设计的,你都可以获取相应的源程序代码。全世界任何一个软件工程师都可以将自己认为优秀的代码加入到其中,由此引发的一个明显的好处就是Linux修补漏洞的快速以及对最新软件技术的利用。而Linux的内核则是这些特点的最直接的代表。
想象一下,拥有了内核的源程序对你来说意味着什么?首先,我们可以了解系统是如何工作的。通过通读源代码,我们就可以了解系统的工作原理,这在Windows下简直是天方夜谭。其次,我们可以针对自己的情况,量体裁衣,定制适合自己的系统,这样就需要重新编译内核。在Windows下是什么情况呢?相信很多人都被越来越庞大的Windows整得莫名其妙过。再次,我们可以对内核进行修改,以符合自己的需要。这意味着什么?没错,相当于自己开发了一个操作系统,但是大部分的工作已经做好了,你所要做的就是要增加并实现自己需要的功能。在Windows下,除非你是微软的核心技术人员,否则就不用痴心妄想了。
二、内核版本号
由于Linux的源程序是完全公开的,任何人只要遵循GPL,就可以对内核加以修改并发布给他人使用。Linux的开发采用的是集市模型(bazaar,与cathedral–教堂模型–对应),为了确保这些无序的开发过程能够有序地进行,Linux采用了双树系统。一个树是稳定树(stable tree),另一个树是非稳定树(unstable tree)或者开发树(development tree)。一些新特性、实验性改进等都将首先在开发树中进行。如果在开发树中所做的改进也可以应用于稳定树,那么在开发树中经过测试以后,在稳定树中将进行相同的改进。一旦开发树经过了足够的发展,开发树就会成为新的稳定树。开发数就体现在源程序的版本号中;源程序版本号的形式为x.y.z:对于稳定树来说,y是偶数;对于开发树来说,y比相应的稳定树大一(因此,是奇数)。到目前为止,稳定树的最高版本是2.4.18;开发树的最新版本是2.5.10。下载内核版本请访问http://www.kernel.org。
三、为什么重新编译内核
Linux作为一个自由软件,在广大爱好者的支持下,内核版本不断更新。新的内核修订了旧内核的bug,并增加了许多新的特性。如果用户想要使用这些新特性,或想根据自己的系统度身定制一个更高效,更稳定的内核,就需要重新编译内核。
通常,更新的内核会支持更多的硬件,具备更好的进程管理能力,运行速度更快、 更稳定,并且一般会修复老版本中发现的许多漏洞等,经常性地选择升级更新的系统内核是Linux使用者的必要操作内容。
为了正确的合理地设置内核编译配置选项,从而只编译系统需要的功能的代码,一般主要有下面四个考虑:
l 自己定制编译的内核运行更快(具有更少的代码)
l 系统将拥有更多的内存(内核部分将不会被交换到虚拟内存中)
l 不需要的功能编译进入内核可能会增加被系统攻击者利用的漏洞
l 将某种功能编译为模块方式会比编译到内核内的方式速度要慢一些
四、内核编译模式
要增加对某部分功能的支持,比如网络之类,可以把相应部分编译到内核中(build-in),也可以把该部分编译成模块(module),动态调用。如果编译到内核中,在内核启动时就可以自动支持相应部分的功能,这样的优点是方便、速度快,机器一启动,你就可以使用这部分功能了;缺点是会使内核变得庞大起来,不管你是否需要这部分功能,它都会存在,这就是Windows惯用的招数,建议经常使用的部分直接编译到内核中,比如网卡。如果编译成模块,就会生成对应的.o文件,在使用的时候可以动态加载,优点是不会使内核过分庞大,缺点是你得自己来调用这些模块。
五、新版本内核的获取和更新
Linux内核版本发布的官方网站是http://www.kernel.org。新版本的内核…一种是patch文件,即补丁。完整的内核版本比较大,一般是tar.gz或者是.bz2文件,二者分别是使用gzip或者bzip2进行压缩的文件,使用时需要解压缩。patch文件则比较小,一般只有几十K到几百K,但是patch文件是针对于特定的版本的,你需要找到自己对应的版本才能使用。
编译内核需要root权限,以下操作都假定你是root用户。请把你需要升级的内核拷贝到/usr/src/下(下文中以2.4.18的内核的linux-2.4.18.tar.gz为例),命令为
#cp linux-2.4.18.tar.gz /usr/src
让我们先来查看一下当前/usr/src的内容,注意到有一个linux-2.4的符号链接,指向一个linux-2.4.7-10(以REDHAT7.2为例)的目录。这就是你所装linux的kernel源代码,删除这个链接。
现在解压我们下载的源程序文件。如果所下载的是.tar.gz(.tgz)文件,请使用下面的命令:
#tar -zxvf linux-2.4.18.tar.gz.tar.gz
如果你所下载的是.bz2文件,例如linux-2.4.0test8.tar.bz2,请使用下面的命令
#bzip2 -d linux-2.4.18.tar.bz2
#tar -xvf linux-2.4.18.tar
文件将解压到/usr/src/linux目录中,我们把它稍作修改:
#mv linux linux-2.4.18
#ln -s linux-2.4.18 linux
如果下载的是patch文件,就可以进行patch操作(下面假设patch-2.4.18已经位于/usr/src目录下了,否则你需要先把该文件拷贝到/usr/src下):
#patch -p0 < patch-2.4.18
六、内核编译
通常要运行的第一个命令是:
#cd /usr/src/linux
#make mrproper
该命令确保源代码目录下没有不正确的.o文件以及文件的互相依赖。由于我们使用刚下载的完整的源程序包进行编译,所以本步可以省略。而如果你多次使用了这些源程序编译内核,那么最好要先运行一下这个命令。
确保/usr/include/目录下的asm、linux和scsi等链接是指向要升级的内核源代码的。它们分别链向源代码目录下的真正的、该计算机体系结构(对于PC机来说,使用的体系结构是i386)所需要的真正的include子目录。如:asm指向/usr/src/linux/include/asm-i386等。若没有这些链接,就需要手工创建,按照下面的步骤进行:
这是配置非常重要的一部分。删除掉/usr/include下的asm、linux和scsi链接后,再创建新的链接指向新内核源代码目录下的同名的目录。这些头文件目录包含着保证内核在系统上正确编译所需要的重要的头文件。现在你应该明白为什么我们上面又在/usr/src下"多余"地创建了个名为linux的链接了吧?
接下来的内核配置过程比较烦琐,但是配置的适当与否与日后Linux的运行直接相关,有必要了解一下一些主要的且经常用到的选项的设置。
配置内核可以根据需要与爱好使用下面命令中的一个:
#make config(基于文本的最为传统的配置界面,不推荐使用)
#make menuconfig(基于文本选单的配置界面,字符终端下推荐使用)
#make xconfig(基于图形窗口模式的配置界面,Xwindow下推荐使用)
#make oldconfig(如果只想在原来内核配置的基础上修改一些小地方,会省去不少麻烦)
这三个命令中,make xconfig的界面最为友好,如果你可以使用Xwindow,那么就推荐你使用这个命令,界面如下:
如果你不能使用Xwindow,那么就使用make menuconfig好了。界面虽然比上面一个差点,总比make config的要好多了,下图为make menuconfig的界面:
选择相应的配置时,有三种选择,它们分别代表的含义如下:
如果使用的是make xconfig,使用鼠标就可以选择对应的选项。如果使用的是make menuconfig,则需要使用空格键进行选取。你会发现在每一个选项前都有个括号, 但有的是中括号有的是尖括号,还有一种圆括号。 用空格键选择时可以发现,中括号里要么是空,要么是"",而尖括号里可以是空,""和"M"这表示前者对应的项要么不要,要么编译到内核里;后者则多一样选择,可以编译成模块。而圆括号的内容是要你在所提供的几个选项中选择一项。
在编译内核的过程中,最烦杂的事情就是这步配置工作了,很多新手都不清楚到底该如何选取这些选项。实际上在配置时,大部分选项可以使用其缺省值,只有小部分需要根据用户不同的需要选择。选择的原则是将与内核其它部分关系较远且不经常使用的部分功能代码编译成为可加载模块,有利于减小内核的长度,减小内核消耗的内存,简化该功能相应的环境改变时对内核的影响;不需要的功能就不要选;与内核关心紧密而且经常使用的部分功能代码直接编译到内核中。
至于选项,因为比较复杂,只是简单做一介绍,编译时应视具体情况,参考帮助的内容再加以选择。
代码成熟等级。此处只有一项:prompt for development and/or incomplete code/drivers,如果你要试验现在仍处于实验阶段的功能,比如khttpd、IPv6等,就必须把该项选择为Y了;否则可以把它选择为N。
对模块的支持。这里面有三项:
Enable loadable module support:除非你准备把所有需要的内容都编译到内核里面,否则该项应该是必选的。
Set version inFORMation on all module symbols:可以不选它。
Kernel module loader:让内核在启动时有自己装入必需模块的能力,建议选上。
CPU类型。内容蛮多的,不一一介绍了,有关的几个如下:
Processor family:根据你自己的情况选择CPU类型。
High Memory Support:大容量内存的支持。可以支持到4G、64G,一般可以不选。
Math emulation:协处理器仿真。协处理器是在386时代的宠儿,现在早已不用了。
MTTR support:MTTR支持。可不选。
Symmetric multi-processing support:对称多处理支持。除非你富到有多个CPU,否则就不用选了。
这里是对最普通的一些属性进行设置。这部分内容非常多,一般使用缺省设置就可以了。下面介绍一下经常使用的一些选项:
Networking support:网络支持。必须,没有网卡也建议你选上。
PCI support:PCI支持。如果使用了PCI的卡,当然必选。
PCI access mode:PCI存取模式。可供选择的有BIOS、Direct和Any,选Any吧。
Support for hot-pluggabel devices:热插拔设备支持。支持的不是太好,可不选。
PCMCIA/CardBus support:PCMCIA/CardBus支持。有PCMCIA就必选了。
System V IPC
BSD Process Accounting
Sysctl support:以上三项是有关进程处理/IPC调用的,主要就是System V和BSD两种风格。如果你不是使用BSD,就按照缺省吧。
Power Management support:电源管理支持。
Advanced Power Management BIOS support:高级电源管理BIOS支持。
MTD设备支持。可不选。
并口支持。如果不打算使用串口,就别选了。
即插即用支持。虽然Linux对即插即用目前支持的不如Windows好,但是还是选上吧,这样你可以拔下鼠标之类的体验一下Linux下即插即用的感觉。
块设备支持。这个就得针对自己的情况来选了,简单说明一下吧:
Normal PC floppy disk support:普通PC软盘支持。这个应该必选。
XT hard disk support:
Compaq SMART2 support:
Mulex DAC960/DAC1100 PCI RAID Controller support:RAID镜像用的。
Loopback device support:
Network block device support:网络块设备支持。如果想访问网上邻居的东西,就选上。
Logical volume manager(LVM)support:逻辑卷管理支持。
Multiple devices driver support:多设备驱动支持。
RAM disk support:RAM盘支持。
网络选项。这里配置的是网络协议。内容太多了,不一一介绍了,自己看吧,如果你对网络协议有所了解的话,应该可以看懂的。如果懒得看,使用缺省选项(肯定要选中TCP/IP networking哦)就可以了。让我们看看,TCP/IP、ATM、IPX、DECnet、Appletalk……支持的协议好多哦,IPv6也支持了,Qos and/or fair queueing(服务质量公平调度)也支持了,还有kHTTPd,不过这些都还在实验阶段。
电话支持。Linux下可以支持电话卡,这样你就可以在IP上使用普通的电话提供语音服务了。记住,电话卡可和modem没有任何关系哦。
这个是有关各种接口的硬盘/光驱/磁带/软盘支持的,内容太多了,使用缺省的选项吧,如果你使用了比较特殊的设备,比如PCMCIA等,就到里面自己找相应的选项吧。
SCSI设备的支持。我没有SCSI的设备,所以根本就不用选,如果你用了SCSI的硬盘/光驱/磁带等设备,自己找好了。
需要Fusion MPT兼容PCI适配器,不用选。
需要I2O接口适配器支持,在智能Input/Output(I2O)体系接口中使用。
网络设备支持。上面选好协议了,现在该选设备了,可想而知,内容肯定多得很。还好还好,里面大概分类了,有ARCnet设备、Ethernet(10 or 100 Mbit)、Ethernet(1000Mbit)、Wireless LAN(non-hamradio)、Token Ring device、Wan interfaces、PCMCIA network device support几大类。我用的是10/100M的以太网,看来只需要选则这个了。还是10/100M的以太网设备熟悉,内容虽然多,一眼就可以看到我所用的RealTeck RTL-8139 PCI Fast Ethernet Adapter support,为了免得麻烦,编译到内核里面好了,不选M了,选Y。耐心点,一般说来你都能找到自己用的网卡。如果没有,你只好自己到厂商那里去要驱动了。
配置业余无线广播。
红外线支持。
如果你使用ISDN上网,这个就必不可少了。
做的可真周到,原来那些非SCSI/IDE口的光驱谁还在用啊,自己选吧,用IDE的CD-ROM不用选。
字符设备。这个内容又太多了,先使用缺省设置,需要的话自己就修改。把大类介绍一下吧:
I2C support:I2C是Philips极力推动的微控制应用中使用的低速串行总线协议。如果你要选择下面的Video For Linux,该项必选。
Mice:鼠标。现在可以支持总线、串口、PS/2、C&T 82C710 mouse port、PC110 digitizer pad,自己根据需要选择。
Joysticks:手柄。即使在Linux下把手柄驱动起来意义也不是太大,游戏太少了。
Watchdog Cards:虽然称为Cards,这个可以用纯软件来实现,当然也有硬件的。如果你把这个选中,那么就会在你的/dev下创建一个名为watchdog的文件,它可以记录你的系统的运行情况,一直到系统重新启动的1分钟左右。有了这个文件,你就可以恢复系统到重启前的状态了。
Video For Linux:支持有关的音频/视频卡。
Ftape, the floppy tape device driver:
PCMCIA character device support:
文件系统。内容又太多了,老法子,在缺省选项的基础上进行修改。介绍以下几项:
Quota support:Quota可以限制每个用户可以使用的硬盘空间的上限,在多用户共同使用一台主机的情况中十分有效。
DOS FAT fs support:DOS FAT文件格式的支持,可以支持FAT16、FAT32。
ISO 9660 CD-ROM file system support:光盘使用的就是ISO 9660的文件格式。
NTFS file system support:ntfs是NT使用的文件格式。
/proc file system support:/proc文件系统是Linux提供给用户和系统进行交互的通道,建议选上,否则有些功能没法正确执行。
还有另外三个大类都规到这儿了:Network File Systems(网络文件系统)、Partition Types(分区类型)、Native Language Support(本地语言支持)。值得一提的是Network File Systems里面的两种:NFS和SMB分别是Linux和Windows相互以网络邻居的形式访问对方所使用的文件系统,根据需要加以选择。
控制台驱动。一般使用VGA text console就可以了,标准的80*25的文本控制台。
声卡驱动。如果你能在列表中找到声卡驱动那自然最好,否则就试试OSS了。
USB支持。很多USB设备,比如鼠标、调制解调器、打印机、扫描仪等,在Linux都可以得到支持,根据需要自行选择。
配置了这个,即使在系统崩溃时,你也可以进行一定的工作了。普通用户是用不着这个功能的。
配置完后,存盘退出,当然你也可以把现在的配置文件保存起来,这样下次再配置的时候就省力气了。
接下来是编译,输入以下命令。
第一个命令make dep实际上读取配置过程生成的配置文件,来创建对应于配置的依赖关系树,从而决定哪些需要编译而那些不需要;第二命令make clean完成删除前面步骤留下的文件,以避免出现一些错误;make zImage和make bzImage则实现完全编译内核,二者生成的内核都是使用gzip压缩的,只要使用一个就够了,它们的区别在于使用make bzImage可以生成大一点的内核。建议大家使用make bzImage命令。
后面三个命令只有在你进行配置的过程中,在回答Enable loadable module support (CONFIG_MODULES)时选了"Yes"才是必要的,make modules和make modules_install分别生成相应的模块和把模块拷贝到需要的目录中。
严格说来,depmod -a命令和编译过程并没有关系,它是生成模块间的依赖关系,这样你启动新内核之后,使用modprobe命令加载模块时就能正确地定位模块。
更新
经过以上的步骤,我们终于得到了新版本的内核。为了能够使用新版本的内核,我们还需要做一些改动:
#cp /usr/src/linux/System.map /boot/System.map-2.4.18
#cp /usr/src/linux/arch/i386/bzImage /boot/vmlinuz-2.4.18
以上这两个文件是我们刚才编译时新生成的。下面修改/boot下的两个链接System.map和vmlinuz,使其指向新内核的文件:
#cd /boot;rm -f System.map vmlinuz
#ln -s vmlinuz-2.4.18 vmlinuz
#ln -s System.map-2.4.18 System.map
七、修改启动管理器
如果用LILO,修改/etc/lilo.conf,添加以下项:
image=/boot/vmlinuz-2.4.18
label=linux240
read-only
root=/dev/hda2
其中root=/dev/hda2一行要根据需要自行加以修改。
运行:
#/sbin/lilo -v
确认对/etc/lilo.conf的编辑无误,现在重新启动系统:
#shutdown -r now
如果是用Grub启动管理器,则添加如下几项即可。
title Red Hat Linux (2.4.18)
root (hd0,0)
kernel /vmlinuz-2.4.18 ro root=/dev/hda2
Grub不需再次调用命令,自动生效。
重启以后就可以用新内核了。
1、Bootloader基本概述
Bootloader是嵌入式系统的引导加载程序,它是系统上电后运行的第一段程序,其作用类似于PC机上的BIOS。Bootloader是依赖于硬件而实现的,特别是在嵌入式领域,为嵌入式系统建立一个通用的Bootloader是很困难的,但为了能达到启动Linux内核的目的,所有的Bootloader都必须具备以下功能:
1)初始化RAM
因为Linux内核一般都会在RAM中运行,所以在调用Linux内核之前Bootloader必须设置和初始化RAM,为调用Linux内核做好准备。初始化RAM的任务包括设置CPU的控制寄存器参数,以便能正常使用RAM以及检测RAM大小等。
2)初始化串口端口
在Linux的启动过程中有着非常重要的作用,它是Linux内核和用户交互的方式之一。Linux在启动过程中可以将信息通过串口输出,这样便可清楚的了解Linux的启动过程。虽然它并不是Bootloader必须要完成的工作,但是通过串口输出信息是调试Bootloader和Linux内核的强有力的工具,所以一般的Bootloader都会在执行过程中初始化一个串口作为调试端口。
3)检测处理器类型
Bootloader在调用Linux内核前必须检测系统的处理器类型,并将其保存到某个常量中提供给Linux内核。Linux内核在启动过程中会根据该处理器类型调用相应的初始化程序。
4)设置Linux启动参数
Bootloader在执行过程中必须设置和初始化Linux的内核启动参数。
5)调用Linux内核映像
Bootloader完成的最后一项工作便是调用Linux内核。如果Linux内核存放在Flash中,并且可直接在上面运行(这里的Flash指NorFlash),那么可直接跳转到内核中去执行。但由于在Flash中执行代码会有种种限制,而且速度也远不及RAM快,所以一般的嵌入式系统都是将Linux内核拷贝到RAM中,然后跳转到RAM中去执行。
2、Bootloader启动过程
嵌入式Linux系统通过Bootloader引导,一上电,就要执行Bootloader来初始化系统。在完成对系统的初始化任务之后,它会将非易失性存储器(通常是Flash或DOC等)中的Linux内核拷贝到RAM中去,然后跳转到内核的第一条指令处继续执行,从而启动Linux内核。Bootloader和Linux内核有着密不可分的联系。
Bootloader多数有两个阶段的启动过程:
Stage1:
基本的硬件初始化
为加载stage2准备RAM空间
拷贝内核映像和文件系统映像到RAM中
设置堆栈指针sp
跳到stage2的入口点
Stage2:
初始化本阶段要使用到的硬件设备
检测系统的内存映射
加载内核映像和文件系统映像
设置内核的启动参数
嵌入式系统中广泛采用的非易失性存储器通常是Flash,而Bootloader就位于该存储器的最前端,所以系统上电或复位后执行的第一段程序便是Bootloader。Bootloader在flash中的存储示意图如下:
3、Bootloader的启动方式
3.1网络启动方式
这种方式的开发板不需要较大的存储介质,跟无盘工作站有点类似,但是使用这种启动方式之前,需要把Bootloader安装到板上的EPROM或者Flash中。Bootloader通过以太网接口远程下载Linux内核映像或者文件系统。Bootloader下载文件一般都使用TFTP网络协议,还可以通过DHCP的方式动态配置IP地址。
3.2硬盘启动方式
传统的Linux系统运行在台式机或者服务器上,这些计算机一般都使用BIOS引导,并使用磁盘作为存储介质。Linux传统上是LILO(LinuxLoader)引导,后来又出现了GUN的软件(GrandUnifiedBootloader)。这两种Bootloader广泛应用在X86的Linux系统上。
3.3Flash启动方式
大多数嵌入式系统上都使用Flash存储介质。Flash有很多类型,包括NORFlash、NANDFlash和其它半导体盘。它们之间的不同在于:NORFlash支持芯片内执行(XIP,eXecuteInPlace),这样代码可以在Flash上直接执行而不必拷贝到RAM中去执行。而NANDFlash并不支持XIP,所以要想执行NANDFlash上的代码,必须先将其拷贝到RAM中去,然后跳到RAM中去执行。NORFlash使用最为普遍。Bootloader一般放在Flash的底端或者顶端,这需要根据处理器的复位向量来进行设置。可以配置成MTD设备来访问Flash分区
概述
最近在做linux内核移植,内核是编译好了,只是内核导进EMMC后启动不了,移植卡在Starting kernel ...所以有必要把启动梳理一遍,看卡在那个地方。
Uboot介绍
U-Boot是Das U-Boot的简称,其含义是Universal Boot Loader,是遵循GPL条款的开放源码项目。一开始德国DENX软件工程中心的Wolfgang Denk基于8xxROM和FADSROM的源码创建了PPCBoot工程项目,此后不断添加处理器的支持。后来,Sysgo Gmbh把PPCBoot移植到ARM平台上,创建了ARMBoot工程项目。然后以PPCBoot工程和ARMBoot工程为基础,创建了U-Boot工程,2002年12月17日第一个版本U-Boot-0.2.0发布,同时PPCBoot和ARMboot停止维护。而今,U-Boot作为一个主流、通用的Bootloader,成功地被移植到包括主流的PowerPC、ARM、X86 、MIPS、NIOS、XScale等体系结构的上百种开发板,成为功能最多、灵活性最强,并且开发最积极的开源BootLoader。目前。U-Boot仍然由DENX的Wolfgang Denk维护。
Uboot 下载
下载: [ftp://ftp.denx.de/pub/u-boot/](ftp://ftp.denx.de/pub/u-boot/)
介绍:[http://www.denx.de/wiki/U-Boot/SourceCode](http://www.denx.de/wiki/U-Boot/SourceCode)
4、Uboot 编译
1)下载后解压
tar -xjvf u-boot-2017.09.tar.bz2
2)编译
参考文档 https://blog.csdn.net/guyongqiangx/article/details/52565493
具体步骤:
》uboot也支持menuconfig,先调用设置处理器
》选择打印串口编号,迅为的开发板为 串口3
![](https://img-blog.csdn.net/20180418235221805)
》设置 交叉编译器
export CROSS_COMPILE=/home/cjx/Linux/Linux/LinuxTool/CompileTool/arm-2014.05/bin/arm-none-linux-gnueabi-
》设置处理器
export ARCH=arm
》设置板子类型
make am335x_evm_config
》开始编译
make
5、Uboot menuconfig 认识
> Architecture select (ARM architecture) ---> 处理器架构选择
>
> ARM architecture ---> ARM 架构子选项
>[ ] Support for ARM SMC Calling Convention (SMCCC) 支持SMCCC,这是一个开源的
Minecraft启动器核心库,SMCCC介绍点击打开链接
>[ ] support boot from semihosting 支持半主控,用于调试
>[*] Build U-Boot using the Thumb instruction set 用thumb指令建立uboot
>[*] Build SPL using the Thumb instruction set 用thumb指令建立SPL
>[ ] L2cache off
>[*] Use an assembly optimized implementation of memcpy memcpy用汇编优化执行
>
>[ ] ARM64 system support AArch32 execution state 32位执行支持
> Target select (Samsung EXYNOS) ---> 目标芯片选择
>[ ] EXYNOS architecture type select
>[ ] Use LPAE page table format 页表格式
>[ ] Support the 'dek_blob' command
> ARM debug ---> 调试
> General setup --->
>() Local version - append to U-Boot release 版本号
>[*] Automatically append version information to the version strin
>[*] Optimize for size 优化大小
>[*] Select defaults suitable for booting general purpose Linux di│ 选择何时的启动
>[*] Enable malloc() pool before relocation 使能malloc池在引导之前
>(0x400) Size of malloc() pool before relocation malloc大小
>[*] Configure standard U-Boot features (expert users) ---> 配置标准的uboot特性
>[ ] 64bit physical address support 64位物理地址支持
> Boot images ---> 镜像
>[*] Enable support for Android Boot Images 使能安卓引导
>[*] Support Flattened Image Tree 支持扁平镜像树
>[*] Support SHA256 checksum of FIT image contents 支持FIT镜像校验和
>[ ] Enable signature verification of FIT uImages FIT uimage签名验证
>[ ] Show verbose messages when FIT images fail 打印信息当FIT镜像失败
> [ ] Select the best match for the kernel device tree 选择最好的匹配到设备树
>-*- Support Flattened Image Tree within SPL
>[ ] Enable signature verification of FIT firmware within SPL
>[*] Enable SPL loading U-Boot as a FIT
>[ ] Set up board-specific details in device tree before boot
>
> API --->
>[ ] Enable U-Boot API 使能uboot api
> Boot timing ---> 开机时序
>[ ] Boot timing and reporting 开机报告
>(20) Number of boot ID numbers available for user use 引导ID给 user
>(30) Number of boot stage records to store 引导记录数
>(0) Address to stash boot timing information 开机时序记录存储地址
>(0x1000) Size of boot timing stash region 存储区大小
>Boot media ---> 引导媒介
>
>(2) delay in seconds before automatically booting 自动引导延时
>[ ] Enable boot arguments 启动参数
>() Boot arguments
> Console ---> 控制台
>[ ] Console recording 控制台记录
>() Board specific string to be added to uboot version string
>[ ] Support a silent console 支持无信息控制台
>[ ] Buffer characters before the console is available 控制台之前有效的字符缓冲
>[ ] Enable console multiplexing 使能控制台复用
>[ ] Select console devices from the environment 选择控制台设备根据环境
>[ ] Allow board control over console overwriting 允许控制台覆盖板控制
>[ ] Update environment variables during console init 更新环境变量在控制台初始化之前
>[*] Don't display the console devices on boot 在boot里面不显示控制台设备
>[ ] Allow deregistering stdio devices 允许注销输入输出设备
>[ ] Support a FIT image embedded in the U-boot image 支持FIT镜像到
U-boot镜像点击打开链接
>() Default fdt file 默认的fdt文件
>[*] add U-Boot environment variable vers 增加环境矢量
>[*] Display information about the CPU during start up 启动显示CPU信息
>[*] Display information about the board during start up 启动显示板子信息
> Start-up hooks ---> 启动钩子函数
> Security support ---- 安全支持
> SPL / TPL ---> SPL是uboot第一阶段执行的代码. 主要负责搬移uboot第二阶段的代码到内存中运行. SPL是由固化在芯片内部的ROM引导的. 我们知道很多芯片厂商固化的ROM支持从nandflash, SDCARD等外部介质启动
> Command line interface ---> 命令行接口
> [*] Support U-Boot commands
> Autoboot options ---> 自动引导选项
>
>[*] Fastboot support ---> fastboot支持,fastboot是一种比recovery更底层的刷机模式
>
> Info commands --->
> Boot commands ---> 启动命令
> Environment commands ---> 环境命令
>
> Memory commands ---> 内存命令
> Compression commands ---> 压缩命令
> Device access commands ---> 设备控制命令
> Shell scripting commands ---> 脚本命令
> Network commands ---> 网络命令
> Misc commands ---> 函数命令
> Power commands ---- 电源控制命令
> Security commands ---> 安全命令
> Firmware commands ---- 固件命令
> Filesystem commands ---> 文件系统命令
> Debug commands ---> 调试命令
>[ ] Enable UBI - Unsorted block images commands 是一种用于Raw Flash的卷管理系统,主要功能是在同一个Flash芯片上管理多个逻辑卷,并且平衡整个Flash读写操作
> Partition Types ---> 分区类型
>
> Device Tree Control ---> 设备树控制
>
> Environment ---> 环境
>
>-*- Networking support ---> 网络支持
>
> Device Drivers ---> 设备驱动
>
> File systems ---> 文件系统
> Library routines ---> 库程序
> [ ] Unit tests ---- 单元测试
Uboot启动流程分析
参考文档:
[ https://blog.csdn.net/kl1125290220/article/details/78683999](https://blog.csdn.net/kl1125290220/article/details/78683999 )
https://www.cnblogs.com/xiaojiang1025/p/6496704.html
**1)**概述
对于CPU来说整个启动分两步,第一步是固化在芯片内部的引导,主要加载uboot.bin。这段固件应该要先判断uboot是在那个存储里面,拷贝完之后进行跳转,执行uboot.bin。第二阶段uboot.bin先初始化外设,然后初始化系统允许环境
**2)**初始化外设的代码
arch/arm/cpu/armv7/start.S
board/samsung/myboard/lowlevel_init.S
arch/arm/lib/crt0.S
arch/arm/lib/board.c
arch/samsung/myboard/myboard.c
**start.S**
1、设置CPU为SVC模式,uboot需要更多的权限所以需要打开
2、关闭MMU,uboot操作的都是实际地址
3、关闭Cache,cache主要是做缓存的,因为内存的初始化比CPU初始化慢半拍,上电之初就操作存储可能会导致问题
4、跳转到lowerlevel_init.s low_level_init
**lowlevel_init.S**
5、初始化时钟
6、初始化内存
7、初始化串口,看门狗
8、跳转到crt0.S _main
**crt0.S**
9、设置栈
10、初始化C运行环境
11、调用board_init_f()
**board.c**
12、board_init_f对全局信息GD结构体进行填充
**crt0.S**
13、代码重定位
**3)**准备环境阶段
arch/arm/lib/crt0.S
arch/arm/lib/board.c
1. board_init_r()是进入定制板目录的入口common/main.c
2. main_loop()中关闭中断,执行命令以及加载引导内核
**4)**uboot是如何加载内核的
1.uboot需要先初始化好DRAM,因为要把内核搬运到这里面
2.初始化一个串口
3.uboot需要把板子类型传给内核,按照arch/arm/tools/mach-types中的描述,将板子编号存储在r1寄存器,这里板子类型有什么用?
4.建立内核参数,包含内存位置,内存大小及根文件系统的位置等
5.加载文件系统
6.启动内核镜像
本文适配fs4412开发板,使用的内核为linux4.9.9。
1.源码下载
Busybox的官方源码下载路径为:
http://busybox.net/downloads/
可以下载最新的busybox-1.28.1
参考文章:https://blog.csdn.net/qq_39077333/article/details/87090249
2.解压源码
tar xvf busybox-1.28.1.tar.bz2
3.进入源码目录
cd busybox-1.28.1
4.配置busybox
Busybox官方已经对其做了大量的默认的配置(如一些常用的shell命令:ls ,cd,mkdir等默认选择),所以我们只需要做几步简单的适配即可。
首先,执行
make menuconfig
4.1 busybox运行使用的库的选择
Settings --->
[*] Build static binary (no shared libs)
在这里选择编译编译静态库不依赖与任何动态链接库,编译出来的可执行文件busybox会大一点但是不过也只是1M大小。
4.2 交叉编译工具链的选择
Settings --->
( arm-none-linux-gnueabi-) Cross compiler prefix
根据你自己的平台选择填写自己的工具链
4.3 安装目录的选择
Settings --->
(./_install) Destination path for 'make install'
这里安装目录选择当前目录的_install目录
4.4 usr相关文件生成选择
Settings --->
[ ] Don't use /usr
注:此编译选择默认是选上的,我们要手动去掉,才能编译出/usr相关目录。
5.编译
执行
make
等待几分钟即可编译完成。
6.安装
执行
make install
结果如下:
......
./_install//usr/sbin/svlogd -> ../../bin/busybox
./_install//usr/sbin/telnetd -> ../../bin/busybox
./_install//usr/sbin/tftpd -> ../../bin/busybox
./_install//usr/sbin/ubiattach -> ../../bin/busybox
./_install//usr/sbin/ubidetach -> ../../bin/busybox
./_install//usr/sbin/ubimkvol -> ../../bin/busybox
./_install//usr/sbin/ubirename -> ../../bin/busybox
./_install//usr/sbin/ubirmvol -> ../../bin/busybox
./_install//usr/sbin/ubirsvol -> ../../bin/busybox
./_install//usr/sbin/ubiupdatevol -> ../../bin/busybox
./_install//usr/sbin/udhcpd -> ../../bin/busybox
You will probably need to make your busybox binary
setuid root to ensure all configured applets will
work properly.
7.查看编译生成的文件
进入_install目录
cd _install/
l$ ls
bin linuxrc sbin usr
可以发现生成了4个文件。
可以发现:/bin下的busybox大小为1.9M,其他的命令可执行文件都是指向它的符号链接。
如执行:ls <===> busybox ls
执行
$file bin/busybox
bin/busybox: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, for GNU/Linux 2.6.38, stripped
可以看到生成了arm架构的使用静态库的可执行文件busybox,即是安装成功
下面的步骤不进行操作,直接把以上的目录拷贝到/source/rootfs下启动开发板网络挂载,可以发现也可以进入系统且可以输入shell命令(能够输入shell命名说明了shell命令本身不是动态链接的,因为我们还没有在文件系统中放入库文件)。功能一样不少(/dev下也创建出了设备节点)但是一下的功能是没有的:
1) 系统不能运行使用动态库链接的可执行文件(何况默认情况下系统编译时会链接动态库,为了减可执行文件的体积,可以使用-static选项编译和不适用此选项编译放在根文件系统中试一下?)
2)/sys目录时空的,所以我们无法通过sysfs看到总线-设备-驱动的信息
3)/proc目录是空的,我们无法看不到内核导出的一些内核和进程信息(mount命令查看系统挂载情况都看不了,ps命令也看不到信息了)
4)Init进程解析的inittab文件没有所以采用了默认的配置
5)无法运行我们的启动程序等
这对于实际应用来说是不可忍受的,所以还需要加入其它的目录文件。
8.创建其他需要的目录
mkdir dev etc lib sys proc tmp var home root mnt
9.lib目录下添加库文件
需要拷贝交叉工具链的库拷贝到此目录下(这里拷贝的是动态库的原因是一般程序使动态编译需要板子上动态库的支持,而静态库一般在静态编译的时候用到是编译阶段,由于交叉编译的工作放在了PC上所以不需要静态库,这样还可以减小根文件系统的体积):
cp /home/linux/tool_chain/arm-2010.09/arm-none-linux-gnueabi/libc/lib/*.so* . -a
对库文件进行瘦身(去除符号表和调试信息):
arm-none-linux-strip *
查看文件类型已经被瘦身了
$file ld-2.11.1.so
ld-2.11.1.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, stripped
10.etc目录下添加配置文件
10.1 添加profile文件
!/bin/sh
export HOSTNAME=liebao
export USER=root
export HOME=home
export PS1="[$USER@$HOSTNAME \W]\# "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH
进入系统就显示了如下:
...
Please press Enter to activate this console.
[root@liebao:/]#
[root@liebao:/]#cd
[root@liebao:/home]#
[root@liebao:/home]#echo $PATH
/bin:/sbin:/usr/bin:/usr/sbin
可以看到我们自定义了命令提示符,cd进入了我们制定的家目录homes,导出了环境变量。
10.2 添加inittab和rcS文件
1)在 etc 下添加文件 inittab,文件内容如下:
#this is run first except when booting in single-user mode.
::sysinit:/etc/init.d/rcS
#/bin/sh invocations on selected ttys
#start an "askfirst" shell on the console (whatever that may be)
::askfirst:-/bin/sh
#stuff to do when restarting the init process
::restart:/sbin/init
#stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
这个是init进程解析的配置文件,通过这个配置文件决定执行哪个进程,何时执行。
2)创建etc/init.d目录
mkdir etc/init.d
进入 etc/init.d
创建文件rcS这是个启动脚本(里面可以放一些系统启动的时候需要执行的脚本或者程序)
写入一段语句如:
echo “welcome to linux” > rcS
加可执行权限:
chmod +x rcS
重启开发板观察打印,打印出了这句话说明配置文件配置成功,可以在里面添加自己的可执行程序。
10.3 添加fstab文件
为了让那个系统自动挂载一些文件,需要一个fstab文件,dev下创建fstab文件:
touch fstab
文件内容如下:
device mount-point type options dump fsck order
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
tmp /tmp tmpfs defaults 0 0
tmp /dev tmpfs defaults 0 0
指定挂载的文件系统。
这里我们挂在的文件系统有三个proc、sysfs和tmpfs,在内核中proc和sysfs默认都支持,而tmpfs是没有支持的,我们需要添加tmpfs的支持
修改内核配置:
$ make menuconfig
File systems --->
Pseudo filesystems --->
[*] Virtual memory file system support (former shm fs)
[*] Tmpfs POSIX Access Control Lists
重新编译内核即可(实际上,我们使用的linux4.9的内核已经配置好了)。
启动脚本/etc/init.s/rcS中添加自动挂载命令:
/bin/mount -a
/bin/mkdir /dev/pts
/bin/mount -t devpts devpts /dev/pts
第一句话为:将会执行/etc/fstab文件
第二三句为:创建虚拟的devpts 文件系统用于用于伪终端设备(当我们使用telnet或者ssh等登陆系统的时候就会自动在/dev/pts/下创建/dev/pts/0,/dev/pts/1等表示这些终端设备)
重启开发板,执行mount命令:
[root@liebao:/]#mount
172.16.21.104:/source/rootfs on / type nfs (rw,relatime,vers=2,rsize=4096,wsize=4096,namlen=255,hard,nolock,proto=udp,timeo=11,retrans=3,sec=sys,mountaddr=172.16.21.104,mountvers=1,mountproto=udp,local_lock=all,addr=172.16.21.104)
devtmpfs on /dev type devtmpfs (rw,relatime,size=469156k,nr_inodes=117289,mode=755)
sysfs on /sys type sysfs (rw,relatime)
proc on /proc type proc (rw,relatime)
tmpfs on /tmp type tmpfs (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=000)
挂载上了我们需要挂载的文件系统,这个时候查看/sys和/proc下都有了相应的文件(这时ps命令才可以从proc中读取进程相关信息)。
10.4 使能mdev功能
以上基本上实现了文件系统应该有的功能,但是我们知道“linux一切皆文件”,对于设备的访问都抽象为对文件的访问,所以就有了设备文件节点的概念,所以需要创建出设备节点后才能访问设备,手动创建不切实际,linux采用udev机制自动创建设备节点,嵌入式中使用小型的mdev来读取内核信息创建设备文件。
在/etc/init.d/rcS中添加:
/sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s
第一句:为设置内核热插拔,当有设备的热插拔时调用/sbin/mdev
第二句:为在/dev下生成内核支持的所有的设备节点
重启开发板,系统mdev就会扫描/sys/dev/block 和/sys/dev/char下的文件自动创建设备节点。
11.dev目录下添加设备文件
需要创建两个设备文件:
mknod /dev/console c 5 1
mknod /dev/null c 1 3
其实,不创建这两个文件系统也能够自动创建。
现在我们的系统就完全可以使用了,功能也基本完善了。
注:有关linux4.9.9内核的移植见《移植最新的linux4.9.9内核(适配fs4412平台)》:
http://blog.csdn.net/liebao_han/article/details/79436819
解压压缩包:
tar -zxvf linux-2.6.32.2-mini2440-20150709.tgz
进入解压得到的文件夹
cd linux-2.6.32.2
在我们这个由友善之臂整理的压缩包源码里,已经为我们配置了很多的缺省文件,这里,我们的开发板板载H43的LCD,因此,我们拷贝一个缺省文件来配置编译。如下,讲文件复制成.config文件,因为make默认的是这个文件。
cp config_mini2440_h43 .config
下面就是配置我们的内核文件,这里用make menuconfig启动界面化的配置界面:
make menuconfig
出现下面的界面:
在这里进行一些配置,因为我们使用的是缺省的配置文件,没有特许需求,不会有问题,我们直接保存。按下键到达最后,回车后保存ok之后,连按两次ESC即可退出。
配置完成后,我们就可以开始我们的编译了:
make zImage
等待一段时间后,编译结束后,会在 arch/arm/boot 目录下生成 linux 内核映象文件: zImage
这里,我们就拿到了我们编译出来的内核文件了,如果我们要用minitools来下载该文件到我们的开发板测试,我们还需要更改下该文件,更改他的后缀,也就是文件格式。才能被minitools识别,否则一直是灰色,不允许使用。
mv zImage zImage.bin
下载测试:
## 五.mini2440-bootloader构建分析
在友善之臂的CD中,找到我们可用的uboot的源码文件压缩包
解压文件
tar -xvf bootloader.tgz
进入得到的文件夹,其中就有一个u-boot,进入其中
cd bootloader/u-boot/
因为该文件是为mini2440这块开发板定制的,所以我们可以直接进行如下操作:
make mini2440_config
make
依次执行上面两个指令后,在u-boot目录下就会生成我们需要的u-boot.bin文件了,这也是我们要下载到板子上的文件。
下载测试:(minitools)
制作文件系统我们需要两个工具,这两个工具在我们友善之臂的CD里面可以找到:
Busybox用于定制根文件系统,利用这个来制作,可以很好的移植一些我们常用的工具到我们的系统当中。
mkyaffs2image,用来包装文件生成一个镜像文件。
安装mkyaffs2image
解压压缩包
tar -zxvf mkyaffs2image.tgz
进入对应的文件夹内
cd mkyaffs2image
在这个文件夹里面,我们就可以看到两个可执行的程序:mkyaffs2image 和 mkyaffs2image-128M,下面为了后面调用程序简单,我们进行如下操作:
cp mkyaffs2image /usr/bin/
cp mkyaffs2image-128M /usr/bin/
该操作将可执行文件加入到了我们的路径当中,任何时候都可以调用程序了。(bin目录对应的是普通用户)
# mkyaffs2image
mkyaffsimage: image building tool for YAFFS built Apr 29 2008
usage: mkyaffsimage dir image_file [convert]
dir the directory tree to be converted
image_file the output file to hold the image
'convert' produce a big-endian image from a little-endian machine
测试时输入mkyaffs2image,出现如上反应,即可。
使用:mkyaffs2image 文件夹 文件名
例子:mkyaffs2image-128M /opt/workspace/rootfs_qtopia_qt4 /opt/workspace/rootfs_qtopia_qt4.img
编译busybox,产生根文件系统
具体参考上方介绍的通用方法
也可以参照:https://blog.csdn.net/liebao_han/article/details/79450086
下面介绍如何建立自己的程序文件系统:
https://blog.csdn.net/u011308691/article/details/15811477
下面介绍下我们开发板自带的文件系统如何处理:
在我们的开发板资料CD中,有如下文件
这两个都是已经配置好的文件系统源码,上面一个是Qt的程序系统,下面的qtopia的程序文件系统,
下面我们以移植qtopia的程序系统为例子:
解压该压缩包:
#tar -zxvf rootfs_atopia_qt4-20141223.tar.gz
得到rootfs_atopia_qt4文件夹
执行指令:
#mkyaffs2image-128M rootfs_qtopia_qt4 rootfs_qtopia_qt4.img
得到一个rootfs_qtopia_qt4.img文件,这就是我们可以烧写到开发板的文件系统镜像
测试:
自此,我们就完成了一个基本的可移植的linux系统的制作,后期我们 在分部对每一部分进行详细的构建,从【bootloader的详细配置与搭建】 到 【内核kernel的详细配置与构建】 再到 【文件系统的详细构建】 以及【裸机程序的开发】【系统驱动的开发】【应用程序的制作】 等等。敬请期待!