前言
上篇文章制作的ubuntu的镜像虽然能正常启动,但是ip a发现没有wifi网卡(准确的说是名为wlan0的网络设备)。导致不能使用网络。可能是参考文档参考的不对了。这里也不纠结了,就排查原因,然后把这个东西补上。
原因排查
原来是缺少网卡驱动
因为直接使用sdk制作的buildroot的镜像是有wlan0网卡的,但是我制作的ubuntu镜像就没有,于是就对比一下哪里有差别。通过dmesg查看发现ubuntu镜像少一段相关的初始化日志。然后lsmod了一下,发现ubuntu镜像少一个内核模块bcmdhd。豆包搜索了一下bcmdhd内核模块,是无线网卡的驱动程序。那怪不得没有wlan0网卡,感情连网卡驱动都没装0.0。那后面就想着手动安装这个驱动。
给ubuntu rootfs补充网卡驱动
linux可以把内核模块编译进内核,也可以以内核模块(ko)的形式加载。既然buildroot都是以内核模块的形式价值的,那我也以这个形式。
添加bcmdhd.ko模块
我看了下执行完编译buildroot镜像后产生的内核模块。发现除了bcmdhd.ko外还有mwifiex_sdio.ko和mwifiex.ko,不知道有没有用,一股脑都给它加进去。
root@lckfb:/home/lckfb/kernel# find . -name *.ko
./drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmdhd.ko
./drivers/net/wireless/marvell/mwifiex/mwifiex_sdio.ko
./drivers/net/wireless/marvell/mwifiex/mwifiex.ko
安装 kmod 软件包
我打算以标准的在/lib/module/4.19.232/(当前使用的linux内核是4.19.232版本)目录下去安装内核模块,要使用depmod去生成相关文件,所以先给rootfs去安装kmod 软件包,支持内核模块的相关命令。(在arm机器中chroot之后去安装就行)
- apt install kmod
创建/lib/modules/4.19.232目录
- mkdier -p /lib/modules/4.19.232
拷贝modules.builtin和modules.order
使用depmod生成相关文件需要modules.builtin和modules.order,这两个文件在编译内核模块时会产生。可以在${sdk根目录}/kernel/下找到,这个目录其实也是sdk的放置linux内核源码的目录。
拷贝modules.builtin和modules.order文件到ubuntu rootfs的/lib/modules/4.19.232下
拷贝相关ko文件
主要是将下面的三个ko文件拷贝到ubuntu rootfs的对应的目录下
./drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmdhd.ko
./drivers/net/wireless/marvell/mwifiex/mwifiex_sdio.ko
./drivers/net/wireless/marvell/mwifiex/mwifiex.ko
/lib/modules/4.19.232下的如下路径
kernel/drivers/net/wireless/marvell/mwifiex/mwifiex.ko
kernel/drivers/net/wireless/marvell/mwifiex/mwifiex_sdio.ko
kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmdhd.ko
然后将新的ubuntu rootfs去生成新的镜像,烧录到sd卡,并启动
在板子启动后,执行depmod 4.19.232,会自动生成内核模块的相关文件。这些文件在使用modprobe这种命令时可能就需要了。
lckfb@192:/lib/modules/4.19.232$ ll
total 92
drwxr-xr-x 3 root root 4096 Mar 2 2023 ./
drwxr-xr-x 3 root root 4096 Apr 4 02:20 ../
drwxr-xr-x 3 root root 4096 Apr 4 02:35 kernel/
-rw-r--r-- 1 root root 625 Mar 2 2023 modules.alias
-rw-r--r-- 1 root root 781 Mar 2 2023 modules.alias.bin
-rw-r--r-- 1 root root 20672 Apr 4 02:33 modules.builtin
-rw-r--r-- 1 root root 22208 Mar 2 2023 modules.builtin.bin
-rw-r--r-- 1 root root 239 Mar 2 2023 modules.dep
-rw-r--r-- 1 root root 349 Mar 2 2023 modules.dep.bin
-rw-r--r-- 1 root root 0 Mar 2 2023 modules.devname
-rw-r--r-- 1 root root 181 Apr 4 02:32 modules.order
-rw-r--r-- 1 root root 55 Mar 2 2023 modules.softdep
-rw-r--r-- 1 root root 1226 Mar 2 2023 modules.symbols
-rw-r--r-- 1 root root 1432 Mar 2 2023 modules.symbols.bin
然后执行modprobe bcmdhd,发现加载内核模块成功。此时再ip a去查看,就发现已经有wlan0网卡了。0.0
但是发现网卡还是不能正常工作,使用nmcli device发现wlan0的状态不对。而且会有内核打印如下报错:
root@localhost:/lib/modules/4.19.232# [ 972.881275] [dhd] dhd_conf_read_config : Ignore config file /vendor/etc/firmware/config.txt
[ 972.881392] [dhd] dhd_conf_set_path_params : Final fw_path=/vendor/etc/firmware/fw_bcm43438a1.bin
[ 972.881421] [dhd] dhd_conf_set_path_params : Final nv_path=/vendor/etc/firmware/nvram_ap6212a.txt
[ 972.881444] [dhd] dhd_conf_set_path_params : Final clm_path=/vendor/etc/firmware/clm_bcm43438a1.blob
[ 972.881466] [dhd] dhd_conf_set_path_params : Final conf_path=/vendor/etc/firmware/config.txt
[ 972.885080] [dhd-wlan0] wl_android_wifi_on : Failed
[ 972.885166] [dhd-wlan0] wl_android_wifi_off : in g_wifi_on=0, on_failure=1
[ 972.885423] [dhd-wlan0] wl_android_wifi_off : out
[ 972.936645] [dhd-wlan0] wl_android_wifi_on : in g_wifi_on=0
[ 973.647729] [dhd] dhd_conf_read_config : Ignore config file /vendor/etc/firmware/config.txt
[ 973.647850] [dhd] dhd_conf_set_path_params : Final fw_path=/vendor/etc/firmware/fw_bcm43438a1.bin
[ 973.647882] [dhd] dhd_conf_set_path_params : Final nv_path=/vendor/etc/firmware/nvram_ap6212a.txt
[ 973.647905] [dhd] dhd_conf_set_path_params : Final clm_path=/vendor/etc/firmware/clm_bcm43438a1.blob
[ 973.647929] [dhd] dhd_conf_set_path_params : Final conf_path=/vendor/etc/firmware/config.txt
[ 973.649972] [dhd-wlan0] wl_android_wifi_on : Failed
[ 973.650081] [dhd-wlan0] wl_android_wifi_off : in g_wifi_on=0, on_failure=1
[ 973.650292] [dhd-wlan0] wl_android_wifi_off : out
[ 973.654492] [dhd-wlan0] wl_android_wifi_on : in g_wifi_on=0
[ 974.352025] [dhd] dhd_conf_read_config : Ignore config file /vendor/etc/firmware/config.txt
[ 974.352153] [dhd] dhd_conf_set_path_params : Final fw_path=/vendor/etc/firmware/fw_bcm43438a1.bin
[ 974.352372] [dhd] dhd_conf_set_path_params : Final nv_path=/vendor/etc/firmware/nvram_ap6212a.txt
[ 974.352452] [dhd] dhd_conf_set_path_params : Final clm_path=/vendor/etc/firmware/clm_bcm43438a1.blob
[ 974.352501] [dhd] dhd_conf_set_path_params : Final conf_path=/vendor/etc/firmware/config.txt
[ 974.354419] [dhd-wlan0] wl_android_wifi_on : Failed
[ 974.354501] [dhd-wlan0] wl_android_wifi_off : in g_wifi_on=0, on_failure=1
[ 974.354726] [dhd-wlan0] wl_android_wifi_off : out
从上面可以看到是缺少一些固件文件,ds搜索也是这么说的,那基本可以确认是缺少一下网卡驱动的固件文件。老办法,去buildroot镜像中去找(其实sdk目录下能搜索到,但是相对零散)。
添加相关网卡驱动固件文件
去buildroot的rootfs上查看,发现了相关固件,并且也看到了bcmdhd.ko的位置
# tree system
system
├── etc
│ └── firmware
│ ├── BCM43430A1.hcd
│ ├── fw_bcm43438a0.bin
│ ├── fw_bcm43438a1.bin
│ ├── fw_bcm43438a1_mfg.bin
│ ├── nvram_ap6212a.txt
│ └── nvram_ap6212.txt
└── lib
└── modules
└── bcmdhd.ko
一股脑将对应的firmware下面的所有文件都拷贝到对应的我的ubuntu rootfs的目录下。然后做一个软链,vendor -> system,因为看报错找固件是在/vendor/目录下。而且buildroot镜像也是这么做的。
然后重新制作新的镜像后,烧录到sd卡,然后启动开发板,然后执行modprobe bcmdhd后,一切都ok了.
可以使用
- nmcli radio wifi on 开启wifi
- nmcli device wifi list 列出wifi
- nmcli device wifi connect “SSID_NAME” password “YOUR_PASSWORD” 连接wifi了。
然后就可以愉快的连接网络玩耍了0.0
总结制作update.img的流程
我这个制作update.img的流程确实有点绕,简单总结下怕以后忘了0.0
1、登录x86开发机
2、登录ubuntu的容器(在容器中去启动qemu)
- docker exec -it e6789e3c22bb /bin/bash
3、启动qemu的arm debian虚拟机
- bash start_arm64_debian.sh,这里我直接写成脚本了。其实这个虚拟机可以开个sshd,这样就不用每次重新启动了。
root@e6789e3c22bb:~/data# cat start_arm64_debian.sh
qemu-system-aarch64 \
-M virt -cpu cortex-a57 -smp 4 -m 4096 \
-drive if=pflash,format=raw,file=efi.img,readonly=on \
-drive if=virtio,file=debian-12-nocloud-arm64.qcow2 \
-device virtio-net-pci,netdev=net0 \
-netdev user,id=net0,hostfwd=tcp::2222-:22 \
-nographic
执行完就已经进入到arm的debian虚拟机中了,登录root就可以,这个镜像默认无密码登录。
4、修改之前制作linuxroot.img(ubuntu18.04的rootfs)
修改的话,通常就是apt安装一些东西,拷贝一些文件之类的。
cd /root
# 挂载linuxroot.img到rootfs目录
mount linuxroot.img rootfs
# 执行脚本,这会chroot到rootfs
bash rootfs-mount.sh -m rootfs
# 执行apt命令安装想要的东西
...
# exit退出chroot的rootfs
exit
# 解挂linuxroot.img
umount rootfs
这样就修改好linuxroot.img了
5、拷贝linuxroot.img到x86开发机
bash scp_linuxroot.sh
- 我直接写了个脚本,能拷贝到x86机器上的sdk的rockdev目录了。而且我之前是x86 机器上的ubuntu sdk编译容器是映射了x86机器的sdk目录的,所以就相当于直接拷贝到x86的ubuntu的编译容器中了。
6、在x86 机器上的ubuntu sdk编译容器中执行脚本生成sd卡镜像
cd rockdev
# 先做个rootfs.img到linuxroot.img的软链,因为脚本是使用rootfs.img
ln -snf linuxroot.img rootfs.img
# 执行脚本生成updateimg
cd ..
./build.sh updateimg
# 会在./rockdev/目录下生成userdata.img,这个就是sd卡镜像了
sd卡镜像制作完成。可以使用瑞芯微的sd烧录工具去烧写了。
小结
1、我这个制作ubuntu镜像的流程确实感觉非常笨,而且很绕。如果网友有更好的方法,可以评论区交流下。
2、瑞芯微的sd烧录工具当前只有windows的版本,这使得我不得不在mac上安装一个windows的虚拟机去做烧录动作。我看了下,这个工具的烧录原理应该就是将sd卡重新分成若干的分区。然后依次装入下面的各个内容,比如:MiniLoaderAll.bin、uboot、内核、rootfs、recovery之类的。
lrwxrwxrwx 1 root root 18 Apr 6 06:22 boot.img -> ../kernel/boot.img
-rw-r--r-- 1 root root 941568000 Apr 6 11:40 linuxroot.img
lrwxrwxrwx 1 root root 41 Apr 6 06:22 MiniLoaderAll.bin -> ../u-boot/rk356x_spl_loader_v1.13.112.bin
lrwxrwxrwx 1 root root 44 Apr 6 06:22 misc.img -> ../device/rockchip/rockimg/wipe_all-misc.img*
-rw-r--r-- 1 root root 17457152 Apr 6 06:22 oem.img
lrwxrwxrwx 1 root root 53 Apr 6 06:22 parameter.txt -> ../device/rockchip/rk356x/parameter-buildroot-fit.txt
lrwxrwxrwx 1 root root 64 Apr 6 06:22 recovery.img -> ../buildroot/output/rockchip_rk356x_recovery/images/recovery.img
lrwxrwxrwx 1 root root 54 Apr 6 06:22 rootfs.ext4 -> ../buildroot/output/rockchip_rk3566/images/rootfs.ext2
lrwxrwxrwx 1 root root 13 Apr 6 11:40 rootfs.img -> linuxroot.img
lrwxrwxrwx 1 root root 19 Apr 6 06:22 uboot.img -> ../u-boot/uboot.img
-rw-r--r-- 1 root root 4472832 Apr 6 06:22 userdata.img
update.img其实就是上面文件的打包。那其实咱们理论上可以在linux上自己用脚本完成这个过程,但是不知道有没有额外的什么格式校验之类的。这样就不用windows工具了。不知道有没有网友了解这个。。。
其他
1、其实我的内核模块的构建目录比较繁琐,直接像buildroot这样的结构应该就可以,但是这样应该处理不了依赖啥的,而且我以后想要单独再编译自己的内核模块啥的做练习,我那个标准目录应该比较好0.0
2、根文件系统可能没有占满对应的分区,使用resize2fs /dev/mmcblk1p6去扩展一下文件系统,占满整个分区。