背景
之前我把一个A10s方案的MK802+的电视棒编译3.4内核与8189es无线网卡的驱动,也制作了Debian 8 rootfs系统。运作了七年半之后,这个设备因为内核比较老,不能更新到新的Debian系统。
其实几年前有段时间我曾经试着更新到4.14内核,但是当时一直没能跑成功。最近一段时间手又开始犯贱了,查了下现在的mainline kernel支持A10s是没有问题的,设备树也有我用的这款型号,所以就是想把之前运行3.4内核升级到5.10,然后rootfs也更新到使用同样内核版本的Debian 11
事不宜迟,搞起来~
方案
为了更新到5.10 mainline内核,需要做以下几个更新
- 更新uboot到支持mainline内核的版本
- 编译内核与设备树与内核模块
- 编译无线网卡内核驱动
- 更新启动脚本参数
如果内核顺利更新,则依次将目前的Debian进行升级
- Debian 8 -> Debian 9
- Debian 9 -> Debian 10
- Debian 10 -> Debian 11
实施
准备编译环境
这里使用了Ubuntu 20.04,安装了以下包,确保编译用到的工具都存在
1 2 |
sudo apt-get install gcc-arm-linux-gnueabihf u-boot-tools bison build-essential flex libncurses-dev python swig python-dev |
准备与更新Uboot
根据linux-sunxi上的u-boot页面信息,首先克隆下u-boot的代码库
1 2 |
git clone git://git.denx.de/u-boot.git |
然后切到比较新的release分支上
1 2 |
git checkout v2021.4 |
然后进行编译工作
1 2 3 4 5 |
make CROSS_COMPILE=arm-linux-gnueabihf- mk802_a10s_defconfig # 我修改了.config的CONFIG_CONS_INDEX,将默认的值2改为1,不然在我的设备的串口上不会输出 make CROSS_COMPILE=arm-linux-gnueabihf- menuconfig make CROSS_COMPILE=arm-linux-gnueabihf- |
编译完成后,将生成的u-boot-sunxi-with-spl.bin
刷写到TF卡上
这里附带说明下TF卡的分区结构
1 2 3 4 5 6 7 8 9 10 11 |
# fdisk -l /dev/mmcblk0 > Disk /dev/mmcblk0: 14.73 GiB, 15811477504 bytes, 30881792 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xee8e91ae Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 2048 30881791 30879744 14.7G 83 Linux |
只分了一个分区,分区开始扇区是2048,格式化为ext4,作为rootfs,包含boot目录。boot目录内含启动脚本和内核
在刷写时,我们首先清空从TF卡存放u-boot的区域,然后再进行刷写
1 2 3 4 |
dd if=/dev/zero of=/dev/sdc bs=1k seek=8 count=1016 dd if=u-boot-sunxi-with-spl.bin of=/dev/sdc bs=1k seek=8 sync |
刷写完成后,执行sync同步数据,此步骤即完成
准备与更新内核
此次准备配合更新到Debian 11, 所以需要更新到mainline 5.10kernel。访问 https://www.kernel.org/ 来查看最新的5.10kernle的版本号。截止到我操作时,最新的版本号是5.10.47,因此我基于此版本进行编译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.47.tar.xz tar -xf linux-5.10.47.tar.xz cd linux-5.10.47 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- sunxi_defconfig # 我在menuconfig步骤,关闭了与sun5i架构不相关的其他架构支持 # 另外把kernel model功能打开,也打开了cfg80211的支持 # 为后续编译8189es SDIO无线网卡驱动做准备 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig # 构建内核镜像 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make -j4 zImage # 构建设备树 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make -j4 dtbs # 构建内核模块 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make -j4 modules # 拷贝内核模块到指定目录 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=./build-root make modules modules_install # 拷贝内核头文件到指定目录 ARCH=arm INSTALL_HDR_PATH=./build-root/usr/ make headers_install |
然后拷贝zImage, dtb, modules到目标文件系统上
1 2 3 4 5 |
mkdir [path-to-rootfs]/boot/5.10.47 cp arch/arm/boot/zImage [path-to-rootfs]/boot/5.10.47 cp arch/arm/boot/dts/sun5i-a10s-mk802.dtb [path-to-rootfs]/boot/5.10.47/ cp -r build-root/lib/modules/5.10.47 [path-to-rootfs]/lib/modules/ |
到这一步,内核与自带的模块准备完成
准备与更新WIFI驱动
我手头这台设备使用的是基于SDIO的8189ES无线网卡。根据官方的文档,下载并编译驱动
1 2 3 4 |
git clone https://github.com/jwrdegoede/rtl8189ES_linux.git cd rtl8189ES_linux.git make -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KSRC=../linux-5.10.47 |
然后把生成的8189es.ko
拷贝到目标文件系统的/lib/modules/5.10.47/kernel/drivers/net/wireless/
目录下
然后修改目标文件系统的/etc/modules
文件,添加8189es
一行并保存,使得启动时自动加载8189es驱动
更新启动参数
首先备份之前的启动文件
1 2 3 |
mv boot.cmd boot-old.cmd mv boot.scr boot-old.scr |
我们使用新的u-boot所以需要适配新的启动参数,在目标文件系统的boot目录下新建boot.cmd,内容如下
1 2 3 4 5 6 |
setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p1 rootwait rw panic=10 mitigations=off ext4load mmc 0 0x46000000 boot/5.10.47/zImage ext4load mmc 0 0x49000000 boot/5.10.47/sun5i-a10s-mk802.dtb bootz 0x46000000 - 0x49000000 |
接下来将其构建成启动用二进制文件
1 2 |
mkimage -C none -A arm -T script -d boot.cmd boot.scr |
到这一步启动参数准备完毕
使用新内核启动Debian 8
接下来就是启动了。将TF卡查到MK802设备上,通电启动,串口顺利显示出新的u-boot,并启动启动,刷过内核信息后,显示了Debian 8的登录提示。登录后,确认WIFI正常驱动,IP也正常获取,使用uname -a
验证内核已经更新到5.10.47
首次启动后记得使用串口登录到系统,执行一下depmod
更新Debian 8至Debian 11
确保内核更新没问题之后,就可以进行系统更新了,依次进行以下升级
Debian 8 -> Debian 9
首先替换/etc/apt/sources.list和/etc/apt/sources.list.d/下所有的文件中的jessie
到stretch
然后执行以下命令
1 2 3 4 5 |
apt update apt upgrade apt dist-upgrade apt autoremove |
过程中注意有提示需要手工选择菜单或按下y/n及时处理即可
升级完成后,执行一次重启
Debian 9 -> Debian 10
首先替换/etc/apt/sources.list和/etc/apt/sources.list.d/下所有的文件中的stretch
到buster
然后执行以下命令
1 2 3 4 5 |
apt update apt upgrade apt dist-upgrade apt autoremove |
过程中注意有提示需要手工选择菜单或按下y/n及时处理即可
升级完成后,执行一次重启
Debian 10 -> Debian 11
首先替换/etc/apt/sources.list和/etc/apt/sources.list.d/下所有的文件中的buster
到bullseye
但是实际上有些具体的apt dist信息需要做调整,具体参照这篇文章
然后执行以下命令
1 2 3 |
apt update apt full-upgrade |
过程中注意有提示需要手工选择菜单或按下y/n及时处理即可
升级完成后,执行一次重启
后记
最后系统升级完成后效果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ ssh 192.168.xxx.xxx sharpbai@192.168.xxx.xxx's password: Warning: No xauth data; using fake authentication data for X11 forwarding. Linux Sharpbai-MK802-Server 5.10.47 #5 Fri Jul 2 03:22:31 CST 2021 armv7l The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Thu Jul 8 17:59:54 2021 from 192.168.xxx.xxx sharpbai@Sharpbai-MK802-Server:~$ |
我记得13年在学校搞这件事情的时候,前后花了好几天,当时用W520+虚拟机编译内核,解决各种奇奇怪怪的问题,最后好不容易才调成功。
这次整个过程比我预想的要快不少,实际上查阅信息+编译内核+u-boot+WIFI驱动整个流程下来一共花了不到3个小时。然后升级系统,因为TF卡和设备本身速度比较慢,升级一次需要消耗大概40分钟左右。这些年来确实长了不少经验,这次用到的东西,包括但不限于
- 理解armhf架构及CPU兼容
- 理解Linux内核及构建
- 理解u-boot内核及构建
- 理解GNU/autotools工具体系
- GCC工具链与编译链接及问题处理
- glibc,版本与二进制兼容性
- Linux设备、文件及文件系统
- Debian系列系统的应用及rootfs制作
- dpkg及apt应用与问题处理
上面这些东西部分来自于日常的折腾,部分来自于日常工作处理Android/Linux相关问题后自己延伸了解了更多信息。
当然这里能快速完成有个前提,是Allwinner将在mainline kernel上相对比较成熟,不考虑显示系统,麦克风摄像头等等这些东西,只是用到CPU和内存以及网卡这种需求,都已经支持的比较好了。
本次玩耍大功告成~