NanoPC-T2制作刷机包
anoPC-T2制作刷机包
前提:到友善的wiki中,仔细看编译uboot、内核、制作刷机包的教程。
准备工作:
1、 虚拟机Ubuntu安装,并安装n多软件可以支撑编译内核等等。
2、 安装交叉编译器,参考wiki-8.1。
3、 下载友善修改好的uboot、内核源代码,debian_nanopi2、sd-fuse_nanopi2等制作刷机包的脚本,友善有两套代码:
Uboot2014,和linux-3.4.y是配套使用,没有使用设备树.
Uboot2016和linux-4.4.y是配套使用,使用设备树.
4、 下载友善已经制作好的刷机包,也可以使用sd-fuse_nanopi2自己制作(最好使用这种方法,里面有东西后面用到)。
我使用的源码版本是uboot2014和linux-3.4.y,文件系统是busybox-1.30.0,具体分析就不多说了,直接来操作:
第一步-编译:
到友善的git上去下载对应得源码包(最好使用git拉取,直接下载好像会出错,选好分支不然编译会失败)
以上只用到了部分,全是用git拉取后,压缩的包,备份起来,下载是真的慢。
解压出来(具体命令自己百度)
分别是文件系统,kernel,刷机包工具、uboot
进入uboot_nanopi2目录下,直接编译,大概不到一分钟,就ok了,具体命令wiki上有,
进入linux-3.4.y目录下,直接编译,时间大概5分钟,具体命令wiki上有,
make nanopi2_linux_defconfig
make uImage -j12 (PC机cpu多核可以使用jn 的命令)
进入busybox目录下,直接编译,时间大概10分钟,可以百度下具体做法。
make menuconfig
设置完交叉工具链的前缀后,保存退出,直接make,
执行make install
至于剩下的拷贝库文件,创建各种文件等等,就自行百度就可以解决, 或者直接看韦东山老师的教程,写的很详细。其中一点:脚本里面的串口设备名称是ttyAMA0,不要写错了,要不然会出错。
第二步-分析官方的二进制文件分布
进入sd-fuse_s5p4418目录下,文件和文件夹如下:
fusing.sh mkimage.sh prebuilt README.md tools,最好先看下readme,先了解下。
首先执行脚本mkimage.sh,跟一个参数android(也可以是其他的,分析下脚本就知道了)
./mkimage.sh android
虚拟机必须联网,因为需要下载一些东西,我提前下载好了,也可以把脚本中的链接复制到迅雷中下载,然后再拷到虚拟机解压在当前目录下,也是可以的。android-lollipop-images.tgz,解压在当前文件夹。
进入文件夹,可以看到很多文件:
2ndboot.bin bootloader env.conf partmap.txt userdata.img
boot.img cache.img info.conf system.img
其中2ndboot.bin是s5p4418官方的,看不到源码,猜测就是一个自举文件。
bootloader 就是uboot生成的文件
boot.img 是kernel和类似于ramdisk的小文件系统。
Cache.img system.img userdata.img是安卓的文件,我暂时没有去管它。
剩下两个.conf文件是一些环境变量,最后一个文件partmap.txt对我们有很大的参考价值
# sd0 partition map
# flash= <device>.<dev no>:<partition>:<fstype>:<start>,<length>
# support device : eeprom, nand, mmc
# support fstype : 2nd, boot, raw, fat, ext4, ubi
#
flash=mmc,0:2ndboot:2nd:0x200,0x7e00:2ndboot.bin;
flash=mmc,0:bootloader:boot:0x8000,0x77000:bootloader;
flash=mmc,0:boot:fat:0x000100000,0x004000000:boot.img;
flash=mmc,0:system:ext4:0x04100000,0x2F200000:system.img;
flash=mmc,0:cache:ext4:0x33300000,0x1AC00000:cache.img;
flash=mmc,0:misc:emmc:0x4E000000,0x00800000;
flash=mmc,0:recovery:emmc:0x4E900000,0x01600000;
flash=mmc,0:userdata:ext4:0x50000000,0x0:userdata.img;
文件直接把刷机包的分区和地址写好了,但是我们不知道bootloader是否和我们编译好的完全一样,其中的boot.img又是由那些文件组成的?我们就需要分析这些。
脚本执行完毕后,会生成一个s5p4418-android-lollipop-20190420.img文件,我们需要分析这个文件,看下官方是怎么做的。
把刚做好的刷机包、android-lollipop-images.tgz解压出来的文件、我们编译好的uboot和uImage拷贝到PC上,对比文件,看下有那些差异。
首先看刷机包,使用分区助手看下分区情况:
Boot分区,有uImage,root.img.gz,ramdisk-recovery.img等等文件
System分区和其他分区是安卓文件系统,对我们没什么价值,就不看了。
分析分区,我们知道第一个分区放的是kernel和ramdisk这样的文件系统,第二个分区放的是文件系统。可以对比下boot分区下的uImage和我们编译的有什么大的差异(其实官方仅仅把它放在里面而已)
接下来对比uboot,发现BootLoader就是uboot,没有什么大的差异。
从上面的分析,可以得出友善官方规划的刷机包分区其实和partmap.txt中的分区是一一对应的,那么我们是不是可以测试下,看是否可以成功做出最小的刷机包512M(可以参考下韦东山老师关于友善neo的视频(免费),里面讲的比较好)。
截取partmap.txt中和我们相关的分区部分,我规划了一个分区,没装visio,不能画图,只有写下来
flash=mmc,0:2ndboot:2nd:0x200,0x7e00:2ndboot.bin;
flash=mmc,0:bootloader:boot:0x8000,0x77000:bootloader;
flash=mmc,0:boot:fat:0x000100000,0x004000000:boot.img;
flash=mmc,0:system:ext4:0x04100000,0x2F200000:system.img;
SD卡的一个小知识:SD卡的分区信息放在前512B中,而一般SD卡的最小擦除单元刚好是512B=0x200=1 sector;(也可能不是sector)
2ndboot.bin 0x200 = 1 sector
Bootloader 0x8000 =64 sector
boot.img 第一个分区-格式fat 20M
文件系统 第二个分区-格式ext4 256-20M(我们暂时先分区,等内核可以跑起来再说)
进入我们的linux目录下,新建build目录,把2ndboot.bin,我们自己编译的u-boot.bin,uImage拷贝到build目录下。
一下操作可以百度下它的意思,我就不细说了,注意空格:
dd if=/dev/zero of=fs_nanopc_256M.img bs=1M count=256
losetup /dev/loop0 fs_nanopc_256M.img
fdisk /dev/loop0 //参看分区表,直接按回车代表默认属性,+20M代表第一个分区是20M,第二个分区直接回车代表剩余空间全部分配给第二个分区,最好w,代表写入分区表,
可以输入p查看分区情况
分区完后,写入分区文件系统格式:
partprobe /dev/loop0
mkfs.fat /dev/loop0p1
mkfs.ext4 /dev/loop0p2
拷贝文件到img文件中:
dd if=2ndboot.bin of=/dev/loop0 bs=512 seek=1
dd if=u-boot.bin of=/dev/loop0 bs=512 seek=64
现在我们的uboot已经放入到刷机包中,我们可以把这个刷机包烧写到SD卡中测试了,文件只有512M,烧写不超过1分钟,预计uboot可以启动。然而我们发现,串口输出可以预估的不一样,如下:
串口打印出这些信息,说明2ndboot.bin已经执行了,但是uboot没启动。
分析可能:
我们下载的android目录下的bootloader和我们编译的一样,是不是脚本执行过程中往里面添加了一些东西???
看下脚本,但是感觉友善这个脚本写的有点乱,也没看出什么来,所以我接直接粗暴的方式对比文件:到0x8000的位置,看使用官方的脚本制作的刷机包s5p4418-android-lollipop-xxx.img,和我们的uboot有什么不一样
发现uboot并不是放在0x8000的地址上,而是放在0x8200的地址上,而且0x8000-0x8200之间还有一些数据,暂时不知道具体含义。
使用粗暴的做法,直接创建一个bin文件,把0x8000-0x8200的内容放到里面,
再次修改我们的分区信息:
2ndboot.bin 0x200 = 1 sector
head.bin 0x8000 = 64 sector
Bootloader 0x8200 =65 sector
boot.img 第一个分区-格式fat 20M
文件系统 第二个分区-格式ext4 256-20M(我们暂时先分区,等内核可以跑起来再说)
修改我们的刷机包:
dd if=2ndboot.bin of=/dev/loop0 bs=512 seek=1
dd if=head.bin of=/dev/loop0 bs=512 seek=64
dd if=u-boot.bin of=/dev/loop0 bs=512 seek=65
顺便把内核也放到里面:
mount /dev/loop0p1 /mnt
cp uImage /mnt
umount /mnt
重新烧写SD卡,启动:
Uboot正常启动,但是内核没有加载,看下默认的环境变量,有很多设置不符合我们现在的情况,修改如下
setenv bootdelay 5
setenv kernel uImage
setenv bootargs console=ttyAMA0,115200n8 root=/dev/mmcblk1p2 rootfstype=ext4 rootwait init=/sbin/init loglevel=7 printk.time=1 consoleblank=0 bootdev=2
setenv bootcmd $bloader 0x48000000 $bootfile
set bloader ext4load mmc 0:1
但是我们发现设置后,无法加载ext2文件系统,我们在分区时,boot的文件系统是fat的,但是uboot并没有支持fat文件系统,我们在分区助手里面看到boot分区也是ext4的,所以我们应该修改boot分区的文件系统为ext4
再次制作:
losetup -d /dev/loop0 //首先卸载设备
rm fs_nanopc_256M.img //删除未完善的刷机包
重复刚才的步骤:
dd if=/dev/zero of=fs_nanopc_256M.img bs=1M count=256
losetup /dev/loop0 fs_nanopc_256M.img
fdisk /dev/loop0
partprobe /dev/loop0
mkfs.ext4 /dev/loop0p1
mkfs.ext4 /dev/loop0p2
把所有需要的文件全部写入到刷机包中
dd if=2ndboot.bin of=/dev/loop0 bs=512 seek=1
dd if=head.bin of=/dev/loop0 bs=512 seek=64
dd if=u-boot.bin of=/dev/loop0 bs=512 seek=65
mount /dev/loop0p1 /mnt //挂载第一个分区到
cp uImage /mnt
umount /mnt
mount /dev/loop0p2 /mnt //挂载第二个分区
cp ../imgForNanopi2/fs_nanopi2/* -rfd /mnt/ //复制文件系统到第二个分区,使用rfd的参数
umount /mnt
losetup -d /dev/loop0
重新烧写测试:
设置环境变量:
setenv bootdelay 5
setenv kernel uImage
setenv bootargs console=ttyAMA0,115200n8 root=/dev/mmcblk1p2 rootfstype=ext4 rootwait init=/sbin/init loglevel=7 printk.time=1 consoleblank=0 bootdev=2
setenv bootcmd $bloader 0x48000000 $bootfile
set bloader ext4load mmc 0:1
因为控制台设置环境变量不能有分号,所以,现在不能自动启动内核,需要我们手动
run bootcmd
bootm
进入了熟悉的界面,说明我们只做刷机包已经成功了。关于uboot环境变量的设置,最好修改uboot源码,修改宏定义。
但是实际操作中,并没有这么顺利,还是有很多问题:
1、 uboot的环境变量,有些官方写死了,就算是我们修改了,重启就恢复了
2、 boot分区下的ramdisK文件系统,有什么用?我暂时没去管它
3、 官方代码更新了,相应的脚本等等一些文件并没有及时更新,
已经很晚了,就不写了!有事不要找我,没事更不要找我!!!