硬件环境 Nanopi neo core2 .
定制系统固件 ## 整体流程概述1. 从友善官网下载emmc版本的固件。 2. 将官方固件写进TF卡。并copy出最后一个分区的emmc固件内容 -> friendlycore-xenial_4.14_arm64 目录。 3. 修改相关分区镜像。并覆盖TF卡的内容。 4. 将TF卡插入硬件,将EMMC固件烧进EMMC。 完成。
---- ### friendlycore-xenial_4.14_arm64 目录
| 文件 | 内容 | | ---- | ---- | | partmap.txt | 分区表。 | | info.conf | | | sunxi-spl.bin | uboot 第一阶段 | | u-boot.itb | uboot 第二阶段 | | boot.img | 引导分区,存 kernel、dtb、ramdisk.img | | rootfs.img | 根目录分区、overlayFs lower dir,只读分区。 | | userdata.img | 根目录分区、overlayFs upper dir,读写分区。 |
备注:友善的文件系统使用 overlayFs 。可以通过重置 userdata.img 恢复出厂设置。
---- # 动驱动
## 知识储备 ### 启动过程 sunxi-spl.bin 是指定到固定地址的。cpu 上电会从固定地址读取程序进行启动。 sunxi-spl.bin 被执行。初始化时钟、初始化ddr、初始化 sdio/emmc 驱动器。 加载 uboot.itb 并执行。 uboot.itb 被执行。初始化串口等必要外设。 命令行操作。(如果有) 加载 kernel dtb ramdisk 到内存。 引导内核启动(会传递参数给内核)。 内核启动,最后启动第一个用户进程。(在ramdisk内的/init) ramdisk 是个临时的简易 rootfs。 里面有一些基本的linux命令。以及 overlayFS 挂载过程。 ramdisk 内 /init 脚本得到执行。 init 脚本调用 mountroot 方法。 (mountroot 在 /script/local 文件内。) mountroot 调用 local_mount_overlay 方法。 local_mount_overlay 内执行 mount -t overlay..... 挂载 overlayfs。 此时,emmc 的分区正式被挂载。 ramdisk 被覆盖。 /script 目录将不可见。 也就找不到挂载 overlayfs 相关的代码了。 系统启动后是找不到挂载代码的。
overlayFS 的参数来自于 uboot 传递。 cat /proc/cmdline 可以看到参数内容是:console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootfstype=ext4 rw rootwait fsck.repair=yes panic=10 fbcon=map:0 data=/dev/mmcblk0p3 snd-soc-core.pmdown_time=3600000
引导启动过程大概如此。
### 驱动相关
驱动有两种存在形式。 1. 编译进内核。 (boot.img 内) 2. 以内核模块(.ko格式) 存在于 /lib/modules/&{内核版本} 目录下。(rootfs.img 内) 也可以存在于 ramdisk.img 内,但是友善没这么做。应该是做通用 ramdisk.img 考虑。
### .img 相关
可以通过 file 命令进行查看。 boot.img FAT 分区镜像。 可以直接使用 sudo mount boot.img /mnt/boot 挂载进行修改。 rootfs.img Android 稀疏镜像格式。内部是 EXT4 分区。 是个难点。
资料: https://segmentfault.com/a/1190000004363645
// sparse image 转化成为 ext4 的 raw imge Usage: simg2img rootfs.img rootfs.ext4
// 挂载分区到 /mount/rootfs sudo mount rootfs.ext4 /mount/rootfs
// 创建一个目录,将 rootfs 文件整个拖出来。 mkdir rootfsDir sudo cp /mnt/rootfs/* rootfsDir -rd
修改后使用友善 sd-fuse_h5/build_rootfs.sh 脚本将 rootfsDir 文件夹直接打包成 sparse image 的 img 并生成 partmap.txt // out 是目录,会存放 rootfs.img 和 partmap.txt 两个文件 sudo ./build_rootfs.sh rootfsDir out
---- ## 增加驱动、或增加内核模块
编译内核,并且编译驱动。 更新 boot.img 、rootfs.img。
所需文件 内核代码:linux.tar.bz2 (git clone https://github.com/friendlyarm/linux.git -b sunxi-4.14.y --depth 1) 交叉编译工具链:gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu.tar.xz (友善官方云盘下载) 制作镜像工具:sd-fuse_h5.tgz (git clone https://github.com/friendlyarm/sd-fuse_h5)
编译内核参考友善官方 http://wiki.friendlyarm.com/wiki/index.php/Building_U-boot_and_Linux_for_H5/H3/H2%2B/zh#.E7.BC.96.E8.AF.91Linux.E5.86.85.E6.A0.B8
编译内核最终文件: |文件名 |描述 | 存放位置 | |---- |---- |---- | | arch/arm64/boot/Image | 内核 | boot.img | | arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi*.dtb | dtb 设备树bin文件 | boot.img | | 各个目录的.ko | 内核模块。 加密或者驱动 | rootfs.img |
### 需要修改的文件
选择4G/5G模块需要的驱动模块。修改结果存在 .config 文件。
#### U9300C 4G 模块
需要启用的内核模块有: CONFIG_USB_SERIAL=y CONFIG_USB_SERIAL_GENERIC=y CONFIG_USB_SERIAL_OPTION=y CONFIG_USB_USBNET=y CONFIG_USB_NET_RNDIS_HOST=y CONFIG_USB_NET_CDCETHER=y 可以直接用 vim .comfig 修改,也可以通过 make menuconfig ARCH=arm64 进行图形化修改。
需要修改的 CONFIG_USB_SERIAL_OPTION 模块实际.c文件 /driver/usb/serial/option.c static const struct usb_device_id option_ids[] 数组内添加一项:
{ USB_DEVICE(0x1c9e, 0x9b3c) }, /* ULONG U9300C */
### 打包 .img
参考 《知识储备》 《.img 相关》 部分。
#### boot.img
挂载 boot 分区。 Image 和 dtb 文件直接 copy 到 mount 挂载出来的 boot 文件夹。 卸载 boot 分区。 完成。
#### rootfs.img
解压 rootfs.img 到目录。 在 linux 源码目录下执行: make modules_install INSTALL_MOD_PATH=/rootfsDir/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- 将新内核模块安装到 rootfsDir 相关目录。
重新打包 rootfs.img 并获得 分区描述文件 partmap.txt
完成修改。
---- # 预装系统软件/文件
预装系统软件只需要动 rootfs.img 打包系统镜像等完全参考驱动方面。
## 原理
直接修改 rootfs 文件,即预装软件。 由于 cpu 架构不同,rootfs 内的相关软件不能直接在PC上执行,需要一个模拟器。用于执行 rootfsDir 内的软件。 执行相关软件同样需要虚拟一个根目录。
## 操作 ### 修改文件
直接修改,注意权限即可。
### 预装软件
PC 主机安装模拟器: sudo apt-get install qemu-user-static PC 主机安装虚拟根目录软件: sudo apt-get install debootstrap
debootstrap 内包含 chroot 命令。这是虚拟根目录的软件。
// 从 PC 主机内 copy 刚安装的模拟器到 虚拟根目录下。 sudo cp /usr/bin/qemu-arm64-static rootfsDir/usr/bin/
// 进入需要需要虚拟成根目录的目录下。 cd rootfsDir
// 所有指令都需要下列打头。 // sudo 需要 PC 机的 root 权限执行。 // LC_ALL=C LANGUAGE=C 基础环境变量。必须。 // chroot . 将当前目录虚拟成根目录。并执行后面的命令。 sudo LC_ALL=C LANGUAGE=C LANG=C chroot .
// 例如:配置 dpkg sudo LC_ALL=C LANGUAGE=C LANG=C chroot . dpkg --configure -a
// 例如:安装 htop
sudo LC_ALL=C LANGUAGE=C LANG=C chroot . apt-get install htop