1.创建fl2440内核的工作目录,便于管理查询:
3rdparty:今后移植到ARM开发板上的第三方应用程序软件包
bootloader:u-boot移植代码
crosstool:交叉编译器
drivers:今后写的驱动文件
images:编译出的image文件,如linux内核,根文件系统等
linux:kernel:Linux内核源码路径
roofts:根文件系统目录树路径
program:我们今后自己写的应用程序
2.下载内核和编译
地址:
https://www.kernel.org/pub/linux/kernel/v3.x/
将内核源码下载到文件linux下,然后解压。
(这里是源码包,记得要根据自己的开发板打补丁,否则会有很多错,我在fl2440移植遇到的问题的博客里有介绍)
3.修改内核(这里我根据fl2440开发板硬件来修改的)
将该vim arch/arm/mach-s3c2440/mach-smdk2440.c文件中的
s3c24xx init clocks(16934400)的晶振改为12000000。
将该vim arch/arm/tools/mach-types文件中的
s3c2440 362改为
s3c2440 1999;将
MINI2440 1999改为
MINI2440 362。
将该vim drivers/tty/serial/samsung.c文件中的
ttySAC改为
ttyS。
修改Makefile中
ARCH ?= ${SUBARCH},改为
ARCH ?= arm以及
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)改为交叉编译器的路
径/opt/x-tools/arm920t/bin/arm-arm920t-linux-gnueabi-(这是我自己安装的路径)这后面应该紧跟回车,空格什么的都不能有。
4.内核编译:
linux3.0内核有16198个C文件和1223个汇编文件,这一份源码支持了不同的CPU并且包含了大部分硬件的驱动源码。linux的源码编译系统中有一个很巧妙的铁三角关系,导致对每一个特定用途的嵌入式Linux系统image的过程显得没那么复杂。
这个铁三角分别是Kconfig、.config和Makefile文件,他们三者之间的关系简单来说就是去饭店点菜:Kconfig是菜单,.config就是你点的菜,Makefile是做法。
然后make s3c2410_defconfig
export TERM=vt100
make menuconfig
如图:
我们选用s3c2440做的SMDK2440开发板,所以其他的开发板里的内容都不选。
在System Type中这里只选如图所示的两个:
我们的交叉编译器使用的是EABI接口,所以这里一定要修改配置,否则跑不起来。
shell脚本:
#!/bin/bash
make
mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008040 -n "Linux Kernel" -d arch/arm/boot/zImage linux-s3c2440.bin
chmod a+x linux-s3c2440.bin
Shell脚本解释说明:make命令是编译Linux内核源码,编译完成后将生产arch/arm/boot/zImage内核启动文件。zImage并不能被u-boot的bootm命令启动,而需要使用mkimage工具在其前面加上bootm命令启动内核所需要的64字节(0x40)头信息方可启动,处
理后的文件一般叫做uImage。
mkimage命令是由u-boot编译产生(u-boot-2010.09/tools/mkimage),在编译完成u-boot后我们需要将它以root权限拷贝到系统/bin路径下。mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008040 -n "Linux Kernel" -d arch/arm/boot/zImage linuxroms3c2440.bin
-A arm 指定ARCH为arm-O linux指定操作系统(OS)为Linux-T kernel指定类型(Type)为内核-C none指定压缩类型为未压缩,zImage里有自解压的代码;-a 30008000指定Image加载的地址, u-boot下使用tftp命令下载linux内核到内存的相应地址-e 30008040指定Linux内核的入口地址, uImage的地址在30008000,uImage是在zImage前面加了64字节(0x40)头,所以内核
zImage入口地址为30008040。-n "Linux Kernel"指定Image的名字-d arch/arm/boot/zImage指定zImage文件所在位置
linuxrom-s3c2440.bin指定生成的uImage文件名
然后
chmod a+x bulid.sh
./build.sh
5.跟文件系统的制作:
切换到lib目录下,下面这个命令用来将/opt/xtools/arm920t路径下除gconv相关的所有动态库(.so)文件拷贝到
find /opt/xtools/arm920t/ -name "*.so*" | grep -v gconv | xargs -i cp -af {} ./
我这里遇到得问题是在指定的文件里没找到动态库的文件(应该有能指定编译器生成动态库的路径,我没找到,大家可以去尝试找找),所以可以直接到主目下用 find 命令查找,找到正确的路径。
我这里的路径是../../../crosstool/crosstool-ng-1.16.0/.build/arm-arm920t-linux-gnueabi/ -name "*.so*" | grep -v gconv | xargs -i cp -af {} ./
拷贝过来的文件有些链接可能 失效,所以我们可以创建一个脚本来重新制作符号链接到本地路径下:
#!/bin/bash
# find all the invalid symlink file and remove "./" before it
for sf in `find -L -type 1 | cut -d'/' -f2` ;
do
#parser and get svmlink target file name
file=`ls -l $sf | awk -F '/' '{ print $NF }'`
# remove invalid symlink file and generate new one
rm -f $sf && ln -s $file $sf
done
安装busybox,busybox集压了Linux的许多工具和命令,通过下载busybox的源码并配置编译并安装它就会提供这些Linux的基本命令的实现,它们将会被安装到
跟文件系统树的bin、sbin、usr/bin、usr/sbin等路径下。
make menuconfig:按照下图做出修改
Print Utilities:打印机不用的话,里面的全部都不要选,可以节约空间
Mail Utilities:邮件收发不用的话,里面的全部不要选,可以节约空间
编译安装busybox到根文件系统树路径下:make && make install
出错:
在nandwrite.c文件中将其注释掉了(实在不想深究,不知道是干啥的),然后编译完成。
2019/01/09增加:
三、编译错误解决参考
1、make出现如下错误:
miscutils/nandwrite.c: In function 'nandwrite_main':
miscutils/nandwrite.c:151: error: 'MTD_FILE_MODE_RAW' undeclared (first use in this?function)
miscutils/nandwrite.c:151: error: (Each undeclared identifier is reported only once
miscutils/nandwrite.c:151: error: for each function it appears in.)
scripts/Makefile.build:197: recipe for target 'miscutils/nandwrite.o' failed
make[1]: *** [miscutils/nandwrite.o] Error 1
Makefile:742: recipe for target 'miscutils' failed
make: *** [miscutils] Error 2
解决办法:
MTD_FILE_MODE_RAW在/usr/include/mtd/mtd-abi.h中定义。将/usr/include/mtd/mtd-abi.h拷贝到busybox的include文件中。
#gedit miscutils/nandwrite.c
修改头文件如下:
#include "libbb.h"
#include "mtd-abi.h"
#include
编译可以通过。
2、继续make,出现如下错误:
util-linux/blkdiscard.c: In function 'blkdiscard_main':
util-linux/blkdiscard.c:72: error: 'BLKSECDISCARD' undeclared (first use in this function)
util-linux/blkdiscard.c:72: error: (Each undeclared identifier is reported only once
util-linux/blkdiscard.c:72: error: for each function it appears in.)
scripts/Makefile.build:197: recipe for target 'util-linux/blkdiscard.o' failed
make[1]: *** [util-linux/blkdiscard.o] Error 1
Makefile:742: recipe for target 'util-linux' failed
make: *** [util-linux] Error 2
解决办法:
BLKSECDISCARD在/usr/include/linux/fs.h中定义,方法如上所述,将/usr/include/linux/fs.h拷贝到busybox的include文件中linux下。
#gedit util-linux/blkdiscard.c
修改内容如下:
#include
编译通过。
切换到根文件系统树路径下,创建符号链接指向busybox程序,如果使用initramfs根文件系统启动需要该命令:
ln -s bin/busybox init。在这里我遇到得问题是:busybox安装的相对路径出现了错误,导致链接不成功。所以一定要在busybox的解压目录下,用ls命令来看相对路径如图:
linux下所有的东西都是文件,其中设备也是文件。dev下路径存放所有的linux的设备文件,要用root权限执行mknod命令来创建系统必须启动的设备文件节点,其他的设备节点将有mdev动态创建。
创建var路径下文件
var路径会存放系统运行时的一些文件(入系统日志文件/var/log/message),在该路径下创建相应的符号链接到/tmp下。
创建etc路径下文件
Linux在内核自举启动完成后,最后将创建init进程并执行根文件系统中的/init或/initrc程序,改程序解析并执行/etc/inittab配置文件,在此文件中配置了init进程在系统启动要启动那些应用程序。
# mount all the file systems specified in /etc/fstab
::sysinit:/bin/mount -a
# Use mdev to auto generate device nod and auto mount SD card and USB storage
::sysinit:/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug
::sysinit:/sbin/mdev -s
#make shm, pts,support
::sysinit:/bin/mkdir -p /dev/pts
::sysinit:/bin/mkdir -p /dev/shm
::sysinit:/bin/mount -t devpts devpts /dev/pts
#set hostname
null::sysinit:/bin/hostname -F /etc/hostname
#Enable console logon
null::respawn:/sbin/getty -L ttyS0 115200 vt100
#now run any rc scripts, which used to start other application
null::wait:/etc/init.d/rcS
#system daemon
null::respawn:/sbin/syslogd -n
null::respawn:/sbin/klogd -n
#Stuff to do before rebooting
null::shutdown:/bin/killall klogd
null::shutdown:/bin/killall syslogd
null::shutdown:/bin/umount -a -r
创建etc/fstab文件
Linux下的mount -a命令将自动挂载/etc/fstab文件中指定的所有需要系统自动挂载的文件。在/etc/inittab中会使用改命令在上电时自动挂载相应的文件系统,这里面主要是挂载一些伪文件系统,这些伪文件系统主要是导出Linux内核运行的相关信息,比较重要的tmpfs,sysfs,proc文件系统等
创建hostname文件名
/etc/inittab文件中通过hostname -F /etc/hostname 命令设置主机名
创建系统启动脚本
系统所有的启动脚本我都放在了init.d路径下,接下来就创建这些脚本:
/etc/inittab 脚本会使用命令/etc/init.d/rcS启动所有其他的应用程序,改脚本执行/etc/init.d下所有文件名以S开头且后面紧跟至少包括2个字符的文件。
如果我们希望系统启动时自动设置网卡的IP地址,则可以创建一个文件名以S开头且后面紧跟至少包括2个字符的启动脚本,并给执行权限。
今后很多应用程序将会放在/apps分区下,有时我们希望这些程序的启动脚本也存放在该分区下便于管理。这时可以参考rcS脚本的实现机制,让它也执行在/apps/etc下的所有启动脚本。
创建shell的配置文件
在linux服务器上,我们可以通过修改~/.bash_profile或~/.bashrc文件来修改shell的配置文件,如修改PATH,LD_LIBRARY_PATH环境变量等,也可以在里面定义命令别名。在嵌入式环境下,这些Shell的配置保存在/etc/profile文件中。可以创建该文件配置嵌入式环境busybox里的shell(ash)
创建Linux登录账号文件
Linux系统中的登录账号信息保存在/etc/group、 /etc/passwd和/etc/shadow文件中
/etc/group:文件保存用户组信息
/etc/passwd:文件保存用户信息;
/etc/shadow:文件保存相应用户的密码;
在根文件系统中创建这些系统账号文件,我只创建root账号
groupname:passwd:gid:members;
第一个字段为用户组名称;
第二个字段为用户组密码,当为x时密码是映射到/etc/gshadow中的,是非逆的;
第三个字段为GID,及组号,为正整数或0,0被付于了root用户组;系统通常会预留一些较靠前的GID给系统虚拟用户之用,每个系统预留的GID都
不同,一般普通用户的GID从500开始;
第四个字段为用户列表,每个用户间用户逗号分隔;
/etc/passwd文件
该文件的格式为:
username:password:uid:gid:fullname:homedir:shell
第一个字段为登录用户名
第二个字段为密码,这里设置为
x表示密码被映射到
/etc/shadow文件中
第三个字段为用户ID(UID)
第四个字段为用户所属组ID(GID)
第五个字段为用户名全称
第六个字段为用户根目录
第七个字段为用户所用shell的类型
/etc/shadow
/etc/shadow文件保存了相应帐号的密文,这个文件内容不能直接创建。如果我们想在嵌入式Linux系统中设置root的登录密码为123456,则我们先在自
己的Linux服务器或虚拟机上修改root密码为123456,然后再将Linux服务器或虚拟机上的/etc/shadow文件里root帐号的密码密文部分拷贝出来,创建根
文件系统树里的etc/shadow时将密文部分用这个密文替换。这个过程做完后记得将自己的Linux服务器或虚拟机的root密码还原回去。
root:$6$ty8Kew3ECW4ZtpjR$oRvyYuuB6.KxIQoEwsLd6kxXelEqbKErXlzdKzUsv7QgjrBP5SHlLmfLShZ4sJeQ1V7tHGv3z4B.WdSxD7awE/:17588:0:99999:7:::
username:password:last_change:min_change:max_change:warm:failed_expire:expiration:reserved
第一字段:用户名(也被称为登录名),在/etc/shadow中,用户名和/etc/passwd 是相同的,这样就把passwd 和shadow中用的用户记录联系在
一起;这个字段是非空的;
第二字段:密码加密后的密文,这个字段是非空的;
第三字段:上次修改密码的时间;这个时间是从1970年01月01日算起到最近一次修改口令的时间间隔(天数);
第四字段:两次修改密码间隔最少的天数;如果这个字段的值为空,帐号永久可用;
第五字段:两次修改密码间隔最多的天数;如果这个字段的值为空,帐号永久可用;
第六字段:提前多少天警告用户密码将过期;如果这个字段的值为空,帐号永久可用;
第七字段:在密码过期之后多少天禁用此用户;如果这个字段的值为空,帐号永久可用;
第八字段:用户过期日期;此字段指定了用户作废的天数(从1970年的1月1日开始的天数),如果这个字段的值为空,帐号永久可用;
第九字段:保留字段,目前为空,以备将来发展之用;
创建Linux其他文件
在etc路径下创建resolv.conf文件
该文件用来设置Linux系统得DNS服务器;DNS服务器用来将转换成IP地址。
nameserver 114.114.114.114
nameserver 4.2.2.2
在etc创建hosts文件
/etc/hosts文件存放本机静态绑定的域名,如
下面在本机上域名localhost就会被解析成127.0.0.1,不需要DNS来做解析。
127.0.0.1 localhost
创建TZ文件
/etc/TZ文件
配置了系统的时区
MST7MDT
创建issue文件
/etc/issue文件里存放
在console上登录系统时提示的警告信息
Copyright (C) 2012 studio I.o.T Studio<123.com >
Default Logon Username: root Password: 123456
至此Linux根文件系统树所需要的基本文件都已经有了 ,可以烧录了。