机顶盒B860AV2.1改造为Ubuntu服务器(三)S905L-B移植Ubuntu文件系统和制作SD卡镜像
机顶盒B860AV2.1改造为Ubuntu服务器(三)S905L-B移植Ubuntu文件系统和制作SD卡镜像
简介
这个项目最终目标是在一个主芯片为S905L-B的电视机顶盒B860AV2.1上运行自己编译适配的Linux系统,前两篇我们分别移植了主线Uboot和主线Linux,并成功让Linux内核启动了。但由于没有根文件系统导致Linux启动最终出现kernel panic卡住,因此后面的步骤就是给板子再配一个根文件系统。一般教程开始都是移植一个busybox根文件系统,但busybox比较简单也导致其功能过于简陋,没有包管理系统导致安装各种软件很复杂。我常用的Linux发行版是Ubuntu,习惯了apt安装的方式,因此这里就给板子移植一个Ubuntu根文件系统。
制作并启动Ubuntu根文件系统
下载和修改Ubuntu根文件系统
下载和修改Ubuntu文件系统的操作参考之前我发布的一个通用的根文件系统制作教程,里面介绍了使用debootstrap在本地虚拟机上制作一个Ubuntu文件系统的步骤,这里主要补充下Linux使用网络根文件系统启动的教程。
Linux使用网络根文件系统启动
虚拟机端配置
配置虚拟机安装nfs服务器
# 安装nfs服务器
sudo apt install nfs-kernel-server
修改nfs服务器共享目录配置文件,将上一步制作好的根文件系统文件夹添加进去。
sudo vim /etc/exports

重启nfs服务器
sudo service nfs-kernel-server restart
# 查看nfs服务器状态
sudo service nfs-kernel-server status

机顶盒端配置
修改Uboot启动命令行,指定网络根文件系统路径。使用板子上的串口在上电后进入Uboot shell界面,添加下面的环境变量。
# nfsroot=后面需修改为虚拟机ip和前面制作的根文件系统的路径
setenv bootargs 'console=ttyAML0,115200 root=/dev/nfs rw nfsroot=192.168.1.56:/home/jch/Documents/Code/rootfs/ubuntu-arm64
ip=dhcp::eth0:off'
# 保存环境变量
saveenv
重新启动板子,可以看到Linux启动后通过网络连接到了虚拟机的NFS服务器,并成功启动了里面的Ubuntu文件系统。


制作完整的SD卡烧写镜像
通过前面两篇和本篇前半部分的教程,已经给板子适配完了Linux系统运行起来的所有重新和文件,保存Uboot、Linux内核、设备树、Ubuntu根文件系统。但前面只是使用网络加载启动的,一般是前期适配调试的时候常用这种方法启动,当所有程序都确定后,就可以把所有文件集成到一起形成一个镜像文件,
准备一个空白镜像文件和给文件分区
在虚拟机中执行以下命令创建空白镜像文件
# 创建一个1GB的空白img文件
dd if=/dev/zero of=./b860av21.img bs=1M count=1024
将创建的镜像文件挂载到虚拟机中
# 挂载进行文件到虚拟机
sudo losetup --partscan --find --show ./b860av21.img
# 执行完后会返回一个loop设备,我这里是/dev/loop12
使用fdisk给/dev/loop12也就是img文件分区,从10MB到100MB为第一个分区,用来存储Linux内核文件、设备树和环境变量,剩下空间为第二个分区,用来存储根文件系统。
sudo fdisk /dev/loop12

创建完后使用sudo fdisk -l命令查看设备,可以看到/dev/loop12设备已经有两个分区了。
sudo fdisk -l

使用mkfs命令给两个分区格式化文件系统,第一个分区为了可以在windows下打开,选择格式化为fat文件系统,第二个分区格式化为ext4文件系统。
# 格式化第一个分区
sudo mkfs.vfat /dev/loop12p1
# 格式化第二个分区
sudo mkfs.ext4 /dev/loop12p2
在第一个分区中新建boot、dts和extlinux文件夹,复制Linux内核和设备树到到对应的文件夹。
sudo mount /dev/loop12p1 /media
sudo mkdir /media/boot
sudo mkdir /media/boot/dts
sudo mkdir /media/boot/extlinux
sudo cp ../linux/arch/arm64/boot/Image.gz /media/boot
sudo cp ../linux/arch/arm64/boot/meson-gxl-s905x-p212.dtb /media/boot/dts
在boot/extlinux文件夹下新建一个extlinux.conf文件,输入以下内容。
DEFAULT linux
TIMEOUT 30
MENU TITLE Boot Menu
LABEL linux
MENU LABEL Linux
KERNEL /boot/Image.gz
FDT /boot/dtb/meson-gxl-s905x-p212.dtb
APPEND root=/dev/mmcblk0p2 rw rootwait ip=dhcp eth0::off
卸载第一个分区挂载。
sudo umount /media
复制根文件系统到第二个分区。
sudo mount /dev/loop12p2 /media
sudo cp -rfp ubuntu-arm64/* /media
sudo umount /media
卸载/dev/loop12设备。
sudo losetup -d /dev/loop12
将第一篇生成的bootloader文件烧写到img文件的开头,跳过第一个扇区。
# ../gxlimg/gxl-boot.bin修改为实际bootloader的路径,b860av21.img修改为实际镜像文件路径
sudo dd if=../gxlimg/gxl-boot.bin of=b860av21.img bs=512 seek=1 conv=notrunc
烧写到新SD卡
将新SD卡插入电脑,虚拟机中使用fdisk命令查看SD设备号,我这里是/dev/sdb。
sudo fdisk -l
使用dd命令将镜像文件写入SD卡。
sudo dd if=b860av21.img of=/dev/sdb bs=1M

将SD卡插入机顶盒,可以看到上电后Uboot识别到了SD卡中的extlinux.conf配置文件,并将文件内指定的Linux内核和设备树加载到内存并启动。

启动后使用df命令查看磁盘使用情况,可以看到识别到的SD卡分区只有900MB只有,这是因为前面制作镜像时我们设置的文件分区只有这么大,板子启动后需要再手动操作扩展下SD卡分区到整个SD卡。
df -h

查看根文件系统分区设备名称为/dev/mmcblk0p2

使用fdisk命令重新给根文件系统分区划分大小,先查看分区起始扇区并记下,这里是204850,再删除第2个分区并重新创建分区,新分区起始扇区设置为和原始分区起始扇区一样,分区结束扇区默认就是整个SD卡空间结尾,保存退出。
sudo fdisk /dev/mmcblk0

使用resize2fs命令重新调整文件系统大小,重新查看文件系统大小,可以看到总空间已经拓展到了SD卡实际容量大小。
sudo resize2fs /dev/mmcblk0p2
df -h

来一个启动后的资源占用情况,可以看到4个CPU核心都跑起来了,目前没跑图形界面内存占用只用了100MB左右。

烧写到EMMC
因为机顶盒内部有8GB的EMMC,因此可以把整个系统放在EMMC上运行,无需外部SD卡,要做到这一点,需要将前面制作的镜像重新烧写到EMMC的0扇区处。因为外面虚拟机不能直接读写到EMMC,因此只能使用网络加载或SD卡启动的方式先让板子把Ubuntu跑起来,再在Ubuntu中使用dd命令将前面制作的SD卡镜像写入EMMC。
最简单的方案是把SD卡的镜像先拷贝到SD卡根文件系统中,再直接SD卡启动,启动后使用dd命令将镜像直接写入EMMC设备。
首先使用FTP或SAMBA等网络共享协议连接板子和电脑,将镜像文件拷贝进盒子的家目录中。
首先在板子上使用fdisk命令查看EMMC设备,我这里是/dev/mmcblk1。
sudo fdisk -l

使用dd命令将SD卡镜像拷贝到EMMC。
sudo dd if=/media/b860av21.img of=/dev/mmcblk1 bs=1M

写入完成后可以看到EMMC也有2个分区了。

挂载第一个分区,修改里面的extlinux.conf文件,EMMC启动时使用的根文件系统路径需要改一下。
# 挂载EMMC启动分区
sudo mount /dev/mmcblk1p1 /media
# 修改启动配置文件中的根文件系统路径root=
sudo vim /media/boot/extlinux/extlinux.conf
修改为以下内容:
DEFAULT linux
TIMEOUT 30
MENU TITLE Boot Menu
LABEL linux
MENU LABEL Linux
KERNEL /boot/Image
FDT /boot/dtb/meson-gxl-s905x-p212.dtb
APPEND root=/dev/mmcblk1p2 rw rootwait ip=dhcp eth0::off
# 卸载EMMC分区
sudo umount /media
拔掉SD卡,重新上电启动。

可以看到板子能正常启动,启动后根文件系统容量又变成1G了,需要按照SD卡分区扩容的步骤重新操作一遍就行了。

至此,机顶盒适配主线Linux和运行Ubuntu系统的目标就完全实现了。
总结
经过前面两篇和这一篇的步骤,已经成功将一个安卓机顶盒完整的移植了主线Uboot、Linux和Ubuntu根文件系统,并将所有文件打包成一个可直接烧写到SD卡的镜像文件。烧写SD卡镜像后电视盒子就完全变成了一个Ubuntu服务器,可以随便在上面运行各种Linux软件或脚本了,比如运行个博客网站、作为家庭文件服务器等等,看个人需求发挥了。
由于机顶盒板子硬件比较简单,移植过程中没有涉及太多源码配置修改、驱动移植或设备树修改,只是大概过了一遍适配新Uboot和Linux的流程,整个适配流程还是比较简单的。建议感兴趣的读者可以根据这个移植教程,自己尝试手动给身边废弃的机顶盒或者其他板子适配一个自己的系统,一来可以熟悉Linux系统的常用命令和嵌入式Linux的移植步骤,二来当最终板子上跑起来自己编译出来的系统时,一定会体会到满满的成就感的。

浙公网安备 33010602011771号