Linux 系统的编译、镜像制作、以及烧录的概述
1. 获取Loader、Kernel、File System
这里不同CPU厂家的有些许差异,如果厂家没有提供可以获取基础版,目前市面上做系统移植的基本都是去各个CUP厂家下载源码,新建立几个文件夹,分别用来保存获取到的文件便于后续的编译管理,
ex:使用
mkdir uboot kernel rootfs
命令建立uboot kernel rootfs 3个文件夹。
2.配置交叉编译器
不同厂家的交叉编译器会不同,根据要编译的CPU选择对应的交叉编译器;初次配置好交叉编译器后,你再次编译该厂家的系统就不需要重新编译了;配置交叉编译器本质就是:把交叉编译器下载下来,修改文件权限,解压到一个文件夹,再把该文件夹的路径配置到环境变量中即可;
ex: 控制台输入
vim ~/.bashrc
在文件最后添加
export PATH=${PATH}:/home/aplex/aplex/tools/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/bin
(冒号后面是你解压的环境变量bin文件的路径),保存退出即可。
3.编译前先配置一下编译环境
控制台输入
vim ~/.bashrc
在文件最后添加
export ARCH=arm (arm是你CPU的平台,这里是告诉make命令要编译的是什么平台的系统)、
export CROSS_COMPILE=arm-linux-gnueabihf-(arm-linux-gnueabihf-是第二步你配置好的交叉编译器的前缀,告诉make文件使用什么编译器编译)
因为在make的时候会执行makefile文件,该文件会寻找ARCH和CROSS_COMPILE的信息进行配置;
第2第3步配置一次后就永久生效的,这里你如果要编译其他厂家的不同CPU系统的话,需要把这两步的内容注释掉重新配置新的CPU的配置;第2第3部配置好后,可以执行
cat ~/.bashrc
命令查看环境变量末尾的配置效果如下:
配置环境后需要使能环境变量,使用
source ~/.bashrc
命令使能环境变量,注意如果使能后你不重启这次的使能只能在该命令窗口生效,新开的命令窗口无法生效,如果重启后就会全局生效。
4.开始分别编译boot Loader、Kernel、File System
每个部分编译前都要先make一下它对应的配置文件(make ****_deconfig),配置好文件后即可直接编译。
编译boot Loader:先进入到保存boot Loader的文件夹,配置对应的项目的配置文件 ***deconfig ,然后执行
make ***deconfig
指令编译它的配置文件,该指令会让make自动到下层文件寻找defconfig文件执行配置,然后直接执行make指令系统会直接编译该文件夹里的loader,如果需要开多线程编译,可以执行 make -j** 指令(**是指你需要开启的线程数),编译后会生成一个MLO文件和一个 ***.img文件,这两个文件后续做系统镜像的时候需要用到。
编译Kernel:先跳转到保存Kernel文件夹,后续步骤跟编译Loader步骤一样要先配置deconfig文件(该文件一般保存在 arch/arm/configs/ 或者 arch/arm64/configs/ 文件夹里,注意:arm代表32位,arm64代表64位),
编译File System:关于File System的创建编译这里先不提,后续补充。这里先说一下一个已经创建编译好的文件系统如何生成镜像文件,这里如果你是初次操作,首先需要执行
sudo apt install mtd-utils
指令安装工具。然后用到mkfs.ubifs ,使用指令
sudo mkfs.ubifs -q -r rootfs -m 2048 -e 126976 -c 2047 -o ubifs.img -F
(参数参考,可根据自己需求修改这些参数)。
-r rootfs : 将制作好的文件系统的文件夹rootfs(你用其他名称的文件夹也行,只要是保存你的文件系统的即可),制作成UBIFS镜像。
-m 2048:-m参数指定了最小的I/O操作的大小为,这里指定为2048bytes,也就是NAND FLASH一个page的大小。
-e 126976:-e参数指定了逻辑擦除快的大小,这里指定为126976 bytes,等于 (每块的页数 - 2)* 页大小。
-c 2047:-c指定了最大的逻辑块号,这里指定为2047, 这个是从下表4-2的 ubinize.cfg 里面的( vol_size) / (ubinize 里面的-p参数计算得来)。
-o ubifs.img:是指定输出文件名为ubifs.img。
-F:是指自动调整大小,通过此命令制作的出的UBIFS文件系统镜像可在u-boot下使用ubi write命令烧写到NAND FLASH上。
接着使用ubinize命令可将使用mkfs.ubifs命令制作的UBIFS文件系统镜像转换成可直接在FLASH上烧写的格式。先建立一个ubinize,配置文件,使用指令
sudo ubinize -o ubi.img -m 2048 -p 128KiB -s 512 -O 2048 ubinize.cfg
(参数参考表可根据自己需求修改这些参数)。
-o ubi.img:指输出文件名为ubi.img。
-m 2048:-m参数指定了最小的I/O操作的大小为,一般是页大小,这里指定为2048bytes。
-p 128KiB: 指定的是目标flash的physical eraseblock块的大小。
-s 512:用于UBI头部信息的最小输入输出单元,一般与最小输入输出单元(-m参数)大小一样,这里指定为512 bytes。
ubinize.cfg:是ubinize需要建立的一个配置文件,这个文件我们自己新建,里面配置文件主要内容和说明如下表。
[ubifs]
mode=ubi
image=ubifs.img #mkfs.ubi生成的镜像源
vol_id=0 #卷序号
vol_size=462MiB #卷大小,即CPU分配给文件系统的内存大小
vol_type=dynamic #动态卷
vol_name=rootfs #卷名
vol_flags=autoresize
经过上过步骤后生成的ubi.img文件,在后面镜像烧录时候需要用到。
5.生成可烧录的镜像文件
新建一个文件夹mkdir Image 把上面编译boot Loader后生成的MLO、 ***.img文件(两个都是u-boot文件);编译Kernel后生成的 ***.dtb文件(设备树文件)、zImage文件(Kernel镜像);File System使用ubinize命令操作后生成的ubi.img文件(文件系统镜像);这5个文件复制进Image文件夹。
接着新建一个空的镜像文件,该镜像文件就是你后续要做复制在SD卡里烧录系统的镜像文件。执行指令
sudo dd if=/dev/zero of=myname.img bs=1M count=200
该指令创建了一个名为myneme.img的大小为1M*100=200M的空镜像文件(由if=/dev/zero定义,if是指定源文件,如果是指定SD卡if= /dev/sdX),该文件大小最好根据上面复制过来的5个文件内存大小来定,比他们加起来的内存大一点即可。
接着通过 losetup 命令挂载新创建的空镜像,通过
sudo losetup -f --show myname.img
指令把文件虚拟成块设备,在执行该指令后会显示出一行信息来显示虚拟的设备块节点:/dev/loopX (X表示1.2.3…)。
然后对该镜像进行磁盘分区,使用
sudo fdisk /dev/loopX
( X是上一步显示出来的节点数 ) 指令后根据提示开始磁盘分区过程(这里的分区过程主要是对于Nandflash内存的CPU来说):
Welcome to fdisk (util-linux 2.31.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xf953eec2.
Command (m for help): n #这里输入 n 代表新建一个分区
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p #这里需要你输入,选择 p
Partition number (1-4, default 1): 1 #分区号
First sector (2048-204799, default 2048): 2048 #这里输入2048,First Sector 表示起始扇区,默认从第2048
#块扇区开始是因为,EFI的兴起,要给EFI代码留磁盘最
#开始的1M空间.
Last sector, +sectors or +size{K,M,G,T,P} (2048-204799, default 204799): #回车就会把其他内存自动分配
Created a new partition 1 of type 'Linux' and of size 99 MiB.
Command (m for help): t # 改变分区格式命令
Partition number (1-4): 1 # 改变第几个分区
Hex code (type L to list codes): e # 把分区改为FAT16
Changed system type of partition 1 to e (W95 FAT16 (LBA))
Command (m for help): a #这里输入 a ,增加boot属性使得该分区变成可boot启动的分区
Selected partition 1 #选定要变增加boot属性的分区号
The bootable flag on partition 1 is enabled now.
Command (m for help): w #保存相关信息并完成分区步骤
The partition table has been altered.
Calling ioctl() to re-read partition table.
Re-reading the partition table failed.: Invalid argument
The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8).
接着同步该分区
sudo kpartx -av /dev/loopX ( X模拟成块设备时的设备节点数,如果提升找不到该命令执行sudo apt-get install kpartx指令安装即可)
执行该命令后会出现下面提示信息:
[sudo] password for aplex:
add map loopXp1 (253:0): 0 202752 linear 7:2 2048 #如果你分了两个区,还会出现多一行类似的信息
下一步根据上面的显示信息,使用下面指令对该分区进去格式化:
sudo mkfs.vfat -n "boot" -F 16 /dev/mapper/loopXp1 #-n “boot”
是指把该分区命名为boot;-F 16 是指把该分区格式化为FAT16格式分区,这个看你CPU,一些CUP可能不需要格式化为FAT16。
sudo mkfs.ext3 -L "rootfs" /dev/mapper/loopXp2 这里是格式化另外一个分区,并把它命名为rootfs;如果你分区了多一个就要执行多一次该指令,格式化多的那个分区,格式化成ext*没有要求,有多少分区就格式化多少个。
接下来根据kpartx同步分区的信息把分区进行挂载,挂载的目的是使文件能够复制到镜像的分区:
sudo mount /dev/mapper/loopXp1 /mnt #把分区挂载到mnt设备目录,或者你自己建一个新的Test文件夹挂载到自己的文件夹也可以,挂载了才能读取内容,而直接访问只能读设备信息,好比看碟,你访问dev相当于直接拿碟片用眼看最多你能看出来是个CD或DVD,但插到光驱里读就能看到电影了,注意如果你系统原来已经挂载了一个镜像记得先取消那个镜像的挂载。
接着执行
sudo cp MLO ***.img ***.dtb zImage u-boot.img /mnt/
把前面复制过来的5个备用文件复制到你挂载起来的镜像里。如果你分区的时候分了多个区就需要再把其他的分区再通过mount指令挂载在mnt上,再把你需要的文件通过cp指令复制到该分区。
下一步执行指令
sudo umount /mnt/
将挂载解除,然后分别执行
sudo kpartx -d /dev/loopX
sudo losetup -d /dev/loopX
指令,到此镜像制作完成。
6.将镜像写入TF卡烧录
做好的镜像文件复制出来,在window系统上使用Win32DiskImager工具,执行下图操作制作,这样你的SD卡就会变成你上面做的镜像大小的带boot属性的SD卡了: