系统镜像备份并重新烧录

在开发到生产过程中,对系统镜像的备份及再烧录过程是必不可少的,接下来介绍几种不同的备份方法和将备份镜像烧录的方法。

使用以下备份方法得到的备份镜像为RAW格式镜像,无法使用USB量产工具进行烧录,但可以使用其他支持RAW格式烧录的软件, 如Win32DiskImager、Etcher等,还可以自己使用dd命令来进行烧录。

注解

RAW格式原意是指未经加工的格式,野火相关文档中RAW格式是指镜像中已经包含了完整分区信息及分区文件,整个镜像是一个整体不可拆分。 与RK格式(打包时将分区标志打包进完整镜像,烧录时根据分区表将对应的分区烧录到相应的地址)做区分。

使用Win32DiskImager全卡备份SD卡系统镜像并重新烧录

使用Win32DiskImager进行全卡备份是最简单的一种备份SD卡的方法,但是由于对整个SD卡进行备份, 会导致备份文件和SD卡的容量一致,而且在还原的时候必须使用比镜像更大容量的SD卡。

Win32磁盘映像工具下载链接: https://win32diskimager.org/

在windows下新建一个空文件,后缀为img,例如backup.img, 将需要备份镜像的SD卡插到windows上并打开Win32磁盘映像工具,然后点击文件夹图标, 找到刚刚创建的backup.img文件并确认,并确认SD卡盘符,取消“仅读取已分配区”的勾选, 最后点击读取按钮,如果弹出是否覆盖backup.img的对话框,点击是即可,等待镜像备份完毕。

../../_images/image_backup036.png

此时镜像已经备份完毕,备份好的镜像就是RAW格式的backup.img。

除了使用Win32磁盘映像工具烧写backup.img镜像到SD卡,也可以使用Etcher等支持烧录RAW格式镜像的软件来烧录。 打开Win32磁盘映像工具,选择backup.img镜像,选择新的空白SD卡盘符, 最后点击写入按钮即可,注意被烧录的SD卡大小必须大于等于镜像的大小。

../../_images/image_backup037.png

使用dd命令压缩备份SD卡系统镜像并重新烧录

使用dd命令进行SD卡压缩备份虽然需要借助运行Linux系统的主机或虚拟机,但是备份出的镜像体积较小,便于再次发布和烧录。

将已经搭建好环境的SD卡从板卡取出并插到读卡器上,然后将读卡器接入PC机(Ubuntu中),

打开Gparted磁盘管理工具,将磁盘切换到SD卡,就能看到一下信息(烧录debian系统的SD卡为例)

没有Gparted的可以使用以下命令安装。

1
sudo apt install gparted
../../_images/image_backup01.png

从图中可以看到SD卡中共8个已分配的分区,要备份的内容是最后一个分区及之前的内容。

最后一个分区大小为23.43GiB,但是已用空间只有450KiB,我们将最后一个分区的大小进行压缩,就可以减小备份镜像的大小。

选中要调整大小的分区,点击鼠标右键,选中 更改大小/移动

../../_images/image_backup02.png

从图中看到,此分区的最小大小为481M,我们将它压缩到500M,然后点击 调整大小/移动

../../_images/image_backup03.png

配置完成后点击绿色对钩,开始执行的更改

../../_images/image_backup04.png

如果希望备份的镜像可以在烧录启动时自动扩展最后一个分区,可以在终端执行以下命令。

挂载rootfs分区,根据上图可知,也就是/dev/sdb6,然后删除其中的一个文件

1
2
3
4
5
6
7
8
#挂载rootfs分区
sudo mount /dev/sdb6 /mnt

#删除此文件,使用备份镜像启动会自动扩展分区
sudo rm /mnt/var/lib/misc/firstrun

# 删除完成后,卸载已挂载的分区
sudo umount /mnt

现在再计算一下需要备份的大小 (8+4+4+64+64+32+6.00x1024+128+500)MiB≈6948MiB, 由于显示的大小通过四舍五入的方式保留2位小数,所以我们可以加一点余量,备份7000MiB的大小。

注解

在Linux下 1MiB=1024KiB=1048576Byte,1MB=1000KB=1000000Byte。

使用 mkdir 命令创建一个新的目录,用于存放从带镜像的SD卡中拷贝的镜像。 然后使用 dd 命令将带镜像的SD中的镜像拷贝到新创建的目录中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#创建新目录
mkdir backup

#将带镜像的SD卡中的镜像拷贝到创建的目录中
sudo dd if=/dev/sdb of=./backup/backup.img count=7000 bs=1024k conv=sync

#拷贝需要时间,请耐心等待,打印消息如下
记录了7000+0 的读入
记录了7000+0 的写出
7340032000 bytes (7.3 GB, 6.8 GiB) copied, 492.74 s, 14.9 MB/s

提示

若备份的镜像烧录后仍无法正常运行,请将bs=1024k改为bs=1M并去掉conv参数,即 sudo dd if=/dev/sdb of=./backup/backup.img count=7000 bs=1M

等待dd命令运行完成后,就得到了RAW格式的backup.img镜像

dd命令参数的含义:

  • if=文件名:输入文件名,缺省为标准输入。即指定源文件。< if=/dev/sdb >

  • of=文件名:输出文件名,缺省为标准输出。即指定目的文件。< of=./backup/backup.img, 这里的.img是镜像的格式,转成.img格式的文件后方便后续使用etcher烧录镜像 >

  • bs = bytes:同时设置读入/输出的块大小为bytes个字节,此处填的是1024k,表示1M大小。

  • count = blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数,此处设置的是7000, 表示7000个bs,也就是7000M。

  • conv= sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。

RAW格式的backup.img镜像,可以使用使用Win32DiskImager或Etcher等软件来烧录到SD卡,也可以使用dd命令去写入到空的SD卡中。

将空白SD卡插入PC,确认插入SD卡的设备号,这里演示的设备号是/dev/sdc,烧录时以SD卡实际对应的设备号灵活修改。

1
2
3
4
5
6
7
#将backup.img写入SD卡
sudo dd if=./backup/backup.img of=/dev/sdc bs=1024k conv=sync

#写入完成后,打印消息如下
记录了7000+0 的读入
记录了7000+0 的写出
7340032000 bytes (7.3 GB, 6.8 GiB) copied, 427.027 s, 17.2 MB/s

不指定count,会将整个backup.img文件写入目标位置。

等待写入完成后,即可使用烧录好的SD卡来启动板卡了。

使用dd命令压缩备份eMMC中的系统镜像

使用dd命令对eMMC中的系统镜像进行备份和使用dd命令对SD卡备份的过程和原理都类似, 都是在Linux环境下,去读取并复制要备份存储设备中的内容。

备份SD卡和备份eMMC的不同点在于,SD卡是可移动存储设备,可以借助PC的Linux环境,而eMMC在板卡上不可拆卸。 如果使用SD卡启动启动系统,就能为eMMC备份提供Linux环境了。

注解

SD卡备份过程中以rkboot分区Debian镜像为例演示,eMMC备份过程中将以extboot分区Ubuntu镜像进行演示, 两系统镜像仅分区格式和数量有部分差异,对备份方法及过程无影响,可对照使用。

我们需要准备一张SD卡,并烧录用于备份的板卡通用备份镜像 RK356X-LUBANCAT-BACKUP_xxx_Update.img,xxx为更新日期, 使用最新版本即可。板卡通用备份镜像可以从网盘下载,适用于LubanCat-RK356x系列板卡。

还需要一个存储设备,用于存放备份后的镜像,最好是U盘,读写速度较快,可以加快备份速度。 没有U盘的话,也可以使用启动板卡的SD卡,单独创建一个用于存放备份镜像的分区。

先用eMMC启动,创建一个标志文件,用以验证修改过的内容是否被正确备份了。

../../_images/image_backup05.png

使用poweroff命令关机,插入SD卡,系统是优先SD卡启动的,直接上电启动即可。

后面的步骤就和使用Linux PC备份SD卡的流程一致了,只是有部分细节需要注意。

首先要获取eMMC的设备号,查看/dev目录下mmc设备,带有mmcblkx[boot]x的就是eMMC,这里就是/dev/mmcblk0。

../../_images/image_backup06.png

打开Gparted磁盘管理工具,将磁盘切换到eMMC

../../_images/image_backup07.png

从图中可以看到SD卡中共3个已分配的分区,将要备份的内容是最后一个分区及之前的空间。

我们发现最后一个分区,也就是rootfs分区的总空间为28.99GiB,但是已用空间只有2.92GiB, 我们将rootfs分区的大小进行压缩,就可以减小备份镜像的大小。

首先卸载eMMC已挂载的所有分区,如boot分区和rootfs分区。

提示

如果没有挂载emmc的分区,那么就不需要进行卸载。

../../_images/image_backup08.png

然后调整最后一个分区,也就是rootfs分区的大小。从图中可以看到,最小的空间是3143MiB,我们调整到3160MiB。

../../_images/image_backup09.png

调整完成后点击绿色按钮应用修改

../../_images/image_backup10.png

扩容和网口随机mac

由于使用dd完整备份emmc里面的系统,网口mac是随机生成并固定在uboot环境变量的,且不能覆盖,但如果不修改mac会造成新烧录的一块或多块板的网口mac地址相同,造成网络无法通信,但是我们可以使用脚本重新随机或自定义网口mac。

另外,希望备份的镜像可以在烧录启动时自动扩展最后一个分区,可以按以下步骤进行操作。

注解

以下命令须使用管理员权限操作,如未使用root用户操作,需要在命令前加sudo

通用镜像和专用镜像的方法不同,分别对两种镜像进行讲解。

  • 通用镜像 执行以下操作:

首先需要emmc启动,安装macchanger工具,后续随机网口mac需要使用该工具。如果安装过程弹出选择窗口,选择NO即可,我们自行随机。

1
2
3
#emmc系统安装macchanger工具
sudo apt update
sudo apt install macchanger

然后插入烧录好系统的SD卡,以SD卡启动系统,进入系统后执行以下操作:

1
2
3
4
5
6
7
8
#创建目录挂载U盘
mkdir -p /media/emmc

#挂载根文件系统分区
mount /dev/mmcblk0p3 /media/emmc/

#打开系统初始化脚本
vim /media/emmc/etc/init.d/boot_init.sh

在系统初始化脚本boot_init.sh末尾添加以下内容,boot_init.sh脚本是初始化脚本,默认配置为了开机自启动。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#-------扩容------
#判断/boot/boot_dilatation_init文件是否存在,不存在则进行扩容
if [ ! -e "/boot/boot_dilatation_init" ] ;
   then

   #修改/dev/mmcblk0p3根文件系统分区空间配置
   printf 'yes\n-1\nyes' | parted /dev/mmcblk0 resizepart 3 ---pretend-input-tty

   #根据配置重新分配空间
   resize2fs /dev/mmcblk0p3

   #创建判断文件,第二次启动存在该文件不再执行此扩容
   touch /boot/boot_dilatation_init
fi

#------随机网口mac------
ifconfig eth0 down
ifconfig eth1 down

#判断/boot/boot_mac_eth0或/boot/boot_mac_eth1不存在则进行随机mac
if [ ! -e "/boot/boot_mac_eth0" ] || [ ! -e "/boot/boot_mac_eth1" ] ;
then
   #sleep 3
   #随机mac
   sudo macchanger -r eth0
   sudo macchanger -r eth1

   # 获取当前接口的MAC地址
   mac_address_eth0=$(ifconfig eth0 | grep ether | awk '{ print $2 }')
   mac_address_eth1=$(ifconfig eth1 | grep ether | awk '{ print $2 }')

   #创建判断文件,第二次启动存在该文件则不再执行随机mac
   touch /boot/boot_mac_eth0
   touch /boot/boot_mac_eth1

   #保存随机生成的mac到判断文件中
   echo "$mac_address_eth0" > /boot/boot_mac_eth0
   echo "$mac_address_eth1" > /boot/boot_mac_eth1
fi

#获取生成的mac并修改
mac_address_eth0=$(cat /boot/boot_mac_eth0)
mac_address_eth1=$(cat /boot/boot_mac_eth1)
sudo ifconfig eth0 hw ether $mac_address_eth0
sudo ifconfig eth1 hw ether $mac_address_eth1

sudo ifconfig eth0 up
sudo ifconfig eth1 up

修改完成后卸载挂载的分区

1
2
# 修改完成后,卸载已挂载的分区
umount /media/emmc/

提示

如果需要二次备份,请删除以上的判断文件,否则二次备份后烧录到其他板,文件存在则不会进行扩容和随机mac。

  • 专用镜像 执行以下操作:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#创建目录挂载U盘
mkdir -p /media/emmc

#挂载根文件系统分区,根据实际修改
mount /dev/mmcblk0p3 /media/emmc/

#删除此文件,使用备份镜像启动会自动扩展分区
rm /media/emmc/var/lib/misc/firstrun

#随机mac参考通用镜像,创建自启动脚本并进行随机。

# 删除完成后,卸载已挂载的分区
umount /media/emmc/
../../_images/image_backup11.png

手动计算一下需要备份的大小 (8+4+128+3.09x1024)MiB≈3305MiB, 由于显示的大小通过四舍五入的方式保留2位小数,所以我们可以加一点余量,备份3350MiB的大小。

使用 mkdir 命令创建一个目录用于挂载U盘,然后使用 使用 mount 命令挂载U盘,最后使用 dd 命令将镜像备份到挂载的U盘中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#创建目录挂载U盘
mkdir -p /media/usb

#挂载U盘
mount /dev/sda1 /media/usb/

#将镜像备份到挂载U盘中
dd if=/dev/mmcblk0 of=/media/usb/backup.img count=3350 bs=1024k conv=sync

#拷贝需要时间,请耐心等待,打印消息如下
3350+0 records in
3350+0 records out
3512729600 bytes (3.5 GB, 3.3 GiB) copied, 198.883 s, 17.7 MB/s

# 备份完成后,卸载U盘
umount /media/usb/

等待dd命令运行完成后,就得到了RAW格式的backup.img镜像,为了确保U盘中的镜像写入完整, 不要直接拔出U盘,使用umount命令卸载完成后再拔出U盘

使用RKDevTool烧录RAW格式镜像到eMMC

为了验证系统镜像确实被写入了eMMC,我们先删除原来的镜像。使用RKDevTool高级功能中的 擦除所有 来清空eMMC。

../../_images/image_backup12.png

注解

RKDevTool高级功能中的擦除所有功能虽然无法清除Loader文件,但是可以擦除其他分区。

接下来使用RKDevTool向eMMC中烧录RAW格式的镜像。

要想烧录RAW格式镜像,需要使用RKDevTool_Release_v2.86的版本,使用最新版的烧录工具会失败。

打开RKDevTool_Release_v2.86,默认配置文件就是用来烧录RAW格式的, 如果与下图红框的内容不一致,可以在 地址 下方的空白区域点击鼠标右键导入配置, 选择和RKDevTool_Release_v2.86同一文件夹的RAW.cfg。

../../_images/image_backup13.png

也可以按照图片中的地址和名字,手动点击 地址名字 进行修改, 还可以右键点击空白处 添加项

../../_images/image_backup14.png

上述工作准备完成后,点击路径后的 添加对应的文件,Boot是指Loader文件, 也就是芯片型号对应的MiniLoaderAll.bin,system对应的就是RAW格式的镜像, 可以是备份的RAW格式的镜像,也可以是OpenWrt的RAW格式镜像。

这里以备份镜像为例,选择完镜像后点击执行,开始下载。

../../_images/image_backup15.png

下载完成后启动板卡,看一下备份之前eMMC之前创建的文件。

../../_images/image_backup16.png

使用dd命令烧录RAW格式镜像到eMMC

除了使用RKDevTool工具烧录eMMC之外,还可以通过dd命令将RAW格式的backup.img镜像写入eMMC中。

使用dd命令对eMMC烧录RAW格式镜像和使用dd命令备份eMMC的过程类似,备份是将eMMC中的内容以RAW格式写入backup.img镜像, 而烧录过程就是将RAW格式的backup.img镜像写入eMMC中。

为了验证系统镜像确实被写入了eMMC,我们先删除原来的镜像。使用dd命令将eMMC的前16M写空内容,破坏原有的分区表就可以了。

1
2
# 将eMMC前16M写空内容
dd if=/dev/zero of=/dev/mmcblk0 bs=1M count=16

移除SD卡,重新上电,直接进入了Maskrom模式.

我们需要准备一张SD卡,并烧录用于备份的板卡通用备份镜像 RK356X-LUBANCAT-BACKUP_xxx_Update.img,xxx为更新日期

还需要一个存储设备,用于存放要烧录的RAW格式镜像,就使用刚刚用于备份的U盘。

为了验证通过dd命令烧录的镜像就是我们备份的镜像,先烧录Debian镜像覆盖eMMC中的内容。

../../_images/image_backup17.png

插入SD卡,从SD卡启动操作系统。由于系统启动时会自动挂载分区,我们先要手都卸载/media/cat/目录下的所有分区,然后重新挂载。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#卸载/media/cat/目录下挂载的所有分区
umount /media/cat/*

#挂载U盘到/mnt目录
mount /dev/sda1 /mnt

#将eMMC中的内容备份到/mnt/backup.img中
dd if=/mnt/backup.img of=/dev/mmcblk0 bs=1024k conv=sync

#拷贝需要时间,请耐心等待,打印消息如下
3350+0 records in
3350+0 records out
3512729600 bytes (3.5 GB, 3.3 GiB) copied, 133.043 s, 26.4 MB/s

# 卸载U盘
umount /mnt/

# 将内存中的缓存写入存储设备
sync

# 关机
poweroff

移除SD卡,重新上电启动

../../_images/image_backup18.png