系统镜像备份并重新烧录

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

备份SD卡系统镜像并重新烧录

使用以下备份方法得到的备份镜像为RAW格式镜像,对应Win32DiskImager、Etcher等,还可以自己使用dd命令来进行烧录。

注解

RAW格式原意是指未经加工的格式,野火相关文档中RAW格式是指镜像中已经包含了完整分区信息及分区文件,整个镜像是一个整体不可拆分。

压缩SD卡中的系统

由于SD卡启动后会进行初始化扩容,充分利用SD卡空间,如果完全备份SD卡,系统大小会很大,烧录时间会很长,因此,可以提前压缩SD卡中没有使用的空间,然后再进行备份,解决以上问题。

1、将SD卡插到板卡中,删除初始化判断文件,以及分区自动挂载配置,让镜像备份到其他SD卡启动时可以重新初始化。

1
2
3
4
5
#初始化判断文件以boot_开头,将其删除
sudo rm /boot/boot_*

#删除/etc/fstab文件中的boot分区自动挂载
sudo sed -i '/^\/dev\/mmcblk0p1  \/boot  auto  defaults  0 2/d' /etc/fstab

删除后直接断电,那么再次启动时就会进行扩容、将随机生成的mac固定。

2、拔下SD卡,将SD卡挂载到虚拟机,打开gparted工具,在终端执行以下命令

1
2
3
4
5
#安装gparted工具
sudo apt install gparted

#打开gparted工具
sudo gparted

3、在打开的界面先选择sd卡对应的设备,然后选择根文件系统分区卸载,再调整大小。

../../_images/image_backup_0.jpg

4、然后拉动边框缩小根文件系统分区大小,然后确认。

../../_images/image_backup_1.jpg

5、然后点击绿色勾确认分区当前配置,弹出的界面选择应用,等待完成。

../../_images/image_backup_2.jpg

6、完成以上操作后可以看到,sd卡的根文件系统分区被压缩。

../../_images/image_backup_3.jpg

使用dd命令压缩备份SD卡系统

1、在压缩完sd卡的根文件系统分区后可备份SD中系统,从下图中可以看到SD卡中共2个已分配的分区,要备份的内容是最后一个已分配的分区及之前的内容。

../../_images/image_backup_3.jpg

现在再计算一下需要备份的大小 (16+1060)MiB≈1076MiB, 由于显示的大小通过四舍五入的方式保留2位小数,所以我们可以加一点余量,备份1200MiB的大小。

注解

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

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

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

#将带镜像的SD卡中的镜像拷贝到创建的目录中,其中count和bs就是前面算出的大小
sudo dd if=/dev/sdb of=./backup/backup.img count=1200 bs=1024k conv=sync

#拷贝需要时间,请耐心等待,打印消息如下
记录了1200+0 的读入
记录了1200+0 的写出
1258291200字节(1.3 GB,1.2 GiB)已复制,133.188 s,9.4 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指定的字节数,此处设置的是1200, 表示1200个bs,也就是1200M。

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

烧录镜像到SD卡

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

1、使用balenaEtcher烧录方法前面系统镜像烧录章节已经介绍过了,以下介绍使用dd命令去写入到空的SD卡。

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#如果SD自动挂载了,需要先卸载
sudo umount /dev/sdb1

#将backup.img写入SD卡
sudo dd if=./backup/backup.img of=/dev/sdb bs=1024k conv=sync

#写入完成后,打印消息如下
记录了1200+0 的读入
记录了1200+0 的写出
1258291200字节(1.3 GB,1.2 GiB)已复制,268.577 s,4.7 MB/s

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

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

备份eMMC系统镜像并重新烧录

由于eMMC镜像系统使用的是cmdline partition方式管理分区,没有分区表,并且SD卡启动时也识别不了eMMC分区,所以备份eMMC的方法目前只能是打包eMMC的文件系统, 然后通过SDK工具打包成能烧录的文件系统格式,最后替换到镜像烧录包进行烧录。

打包板卡根文件系统

1、为了用打包出来的文件系统烧录到其他板卡时能够正常初始化,需要删除初始化判断文件和data分区自动挂载。

1
2
3
4
5
#初始化判断文件以boot_开头,将其删除
sudo rm /boot/boot_*

#删除/etc/fstab文件中的data分区自动挂载
sudo sed -i '/\/dev\/mmcblk0p7\s\+\/mnt\/data\s\+auto\s\+defaults\s\+0\s\+2/d' /etc/fstab

2、用户需要准备一个u盘或者是sd卡, 注意u盘/sd卡的容量一定要比当前系统占用的磁盘空间要大, 否则备份过程将会失败。用户可通过在控制台终端输入以下命令,查看当前系统大小:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#查看挂载情况和分区大小
df -h

#输出信息如下
Filesystem      Size  Used Avail Use% Mounted on
/dev/root       2.9G  936M  1.9G  34% /
tmpfs           154M     0  154M   0% /dev/shm
tmpfs            62M 1000K   61M   2% /run
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
/dev/mmcblk0p7  4.1G   28K  3.9G   1% /mnt/data
tmpfs            31M     0   31M   0% /run/user/0
tmpfs            31M     0   31M   0% /run/user/1000

其中 / 表示当前根文件系统,占用大小为936M,用户需要确保u盘/sd卡容量大于936M, 又因为总大小是2.9G,单文件不超过4G,所以使用 fat32格式 的U盘或者SD卡备份即可。

3、插入u盘,拔动切换开关向USB A口方向,切换为host,USB-OTG切换开关可以理解成物理接口的切换开关。 切换到USB A接口方向时,主控的USB信号通往USB A接口;切换到Type-C接口方向时,主控的USB信号通往Type-C接口。

../../_images/image_backup_6.jpg

4、将拨码开关拨到USB A口方向后,仍需要软件配置usb口为host模式,因为系统默认设置usb为device模式,需要执行以下命令进行切换host。

1
2
#临时切换host模式
echo host > /proc/cviusb/otg_role

5、确保当前系统识别到相应设备文件,设备文件为:/dev/sdx(x为具体英文字母), 如果系统只有一个u盘设备, 那么该设备文件通常为:/dev/sda,用户可通过输入以下命令确认:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#查看设备
lsblk

#信息输出如下
NAME         MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda            8:0    1  7.5G  0 disk
`-sda1         8:1    1  7.5G  0 part
mmcblk0      179:0    0  7.3G  0 disk
|-mmcblk0p1  179:1    0    8M  0 part
|-mmcblk0p2  179:2    0  512K  0 part
|-mmcblk0p3  179:3    0  128K  0 part
|-mmcblk0p4  179:4    0    3G  0 part /
|-mmcblk0p5  179:5    0   40M  0 part
|-mmcblk0p6  179:6    0 14.9M  0 part
`-mmcblk0p7  179:7    0  4.2G  0 part /mnt/data
mmcblk0boot0 179:8    0    4M  1 disk
mmcblk0boot1 179:16   0    4M  1 disk

通过设备容量可以看出U盘的设备为sda,而sda下有一个分区sda1,也可以通过U盘插入前后的设备变化确定U盘的设备。

提示

若是直接使用板载的SD卡槽,相应的设备文件则为:/dev/mmcblk1p1。

6、创建backup_rootfs.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
#!/bin/sh -e

_exit_trap() {
   umount ${tmp_rootfs_dir}
   rmdir ${tmp_rootfs_dir}
}

_err_trap() {
   umount ${tmp_rootfs_dir}
   rmdir ${tmp_rootfs_dir}
}

tmp_rootfs_dir=/mnt/data/rootfs_backup

if [ $# -gt 0 ]; then
   DEV="$1"
else
   echo "please input a storage device!"
   exit 0
fi

if [ ! -d ${tmp_rootfs_dir} ] ; then
   mkdir ${tmp_rootfs_dir}
fi

trap _exit_trap EXIT
#trap _err_trap ERR

mount  $DEV $tmp_rootfs_dir

tar -cvf ${tmp_rootfs_dir}/rootfs.tar \
   --exclude=/dev \
   --exclude=/proc \
   --exclude=/sys \
   --exclude=/tmp \
   --exclude=/run \
   --exclude=/mnt/data \
   --exclude=/media \
   --exclude=/lost+found \
   /*

echo "roofs backup finished!!"

备份脚本讲解:

  • #!/bin/sh -e:-e参数代表命令一旦执行出错,脚本马上停止执行。

  • _exit_trap:设置脚本执行错误和退出时应当执行的函数,这里主要是卸载和删除临时挂载目录。

  • tmp_rootfs_dir:U盘/SD临时挂载目录。

  • trap _exit_trap EXIT:捕捉脚本执行错误和退出的信号,如果捕捉成功,则执行相应处理函数。

  • mount $DEV $tmp_rootfs_dir:挂载U盘/SD到时挂载目录

  • tar -cvf ${tmp_rootfs_dir}/rootfs.tar:打包文件系统

  • –exclude:排除不需要打包的目录

注意

data分区是不打包的,因为烧录系统启动后进行初始化,会将data分区格式化,然后挂载到/mnt/data/

7、用户执行该脚本时,需要输入u盘的设备文件作为参数,如以下命令所示:

1
2
3
4
5
#添加执行权限
sudo chmod 777 backup_rootfs.sh

#执行打包,需要指定实际u盘/sd操作符
sudo ./backup_rootfs.sh /dev/sda1

8、执行该文件后,系统将自动开始备份,在此过程中将不断打印提示消息,结束时打印消息如下。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
/var/lib/dpkg/triggers/File
/var/lib/dpkg/triggers/update-ca-certificates
/var/lib/dpkg/triggers/Unincorp
/var/lib/dpkg/lock
/var/lib/dpkg/updates/
/var/lib/dpkg/cmethopt
/var/lib/dpkg/lock-frontend
/var/lib/ntp/
/var/lib/ntp/ntp.drift
/var/lib/logrotate/
/var/lib/logrotate/status
/var/tmp/
/var/local/
/var/mail/
/var/lock
roofs backup finished!!

9、系统备份成功后,拔下u盘,插入到windows电脑上,可查看到rootfs.tar。

生成烧录文件

1、需要借助SDK来生成能够烧录的根文件系统文件,将rootfs.tar拷贝到SDK源码的Ubuntu目录下,然后解压,具体路径以情况以电脑上的镜像路径目录为准。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#进入sdk的ubuntu目录
cd sophon-image-build/ubuntu

#如果编译过sdk的需要删除构建产生临时文件目录
sudo rm -rf binary/
sudo rm -rf rootfs/

#创建临时目录
mkdir binary
mkdir rootfs

#解压文件系统到临时目录
tar xvfp rootfs.tar -C binary/

#借助mk-image.sh脚本打包成ext4文件
sudo ./mk-image.sh

打包完成后会生成的ubuntu-rootfs.ext4文件。

2、借助SDK改变根文件系统格式,生成能够烧录的根文件系统,在sdk源码顶层目录执行以下命令,初始化编译环境和加载对应的emmc配置文件,具体路径需要根据加载的配置确定:

  • 如果 没有编译过 sdk的执行以下命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#进入sdk顶层目录
cd sophon-image-build/

#初始化编译环境,输入当前用户的密码
source build/cvisetup.sh

#加载对应的板级配置文件
defconfig sg2000_lubancat_riscv_ubuntu_emmc

#创建目录
mkdir -p install/soc_sg2000_lubancat_riscv_ubuntu_emmc/rawimages

#将build/Makefile的rootfs:ebf-ubuntu-rootfs-prepare注释掉,不打包编译的sdk的.ko和.so进文件系统
sed -i 's/^rootfs:ebf-ubuntu-rootfs-prepare/#rootfs:ebf-ubuntu-rootfs-prepare/' build/Makefile

#打包文件系统
pack_rootfs

#打包完成后恢复build/Makefile配置
sed -i 's/^#rootfs:ebf-ubuntu-rootfs-prepare/rootfs:ebf-ubuntu-rootfs-prepare/' build/Makefile

生成的sophon-image-build/install/soc_sg2000_lubancat_riscv_ubuntu_emmc/rootfs.emmc 就是我们需要的文件系统。

  • 如果 编译过 sdk的执行以下命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#进入sdk顶层目录
cd sophon-image-build/

#初始化编译环境,输入当前用户的密码
source build/cvisetup.sh

#加载对应的板级配置文件
defconfig sg2000_lubancat_riscv_ubuntu_emmc

#打包文件系统
pack_rootfs

生成的sophon-image-build/install/soc_sg2000_lubancat_riscv_ubuntu_emmc/rootfs.emmc 就是我们需要的文件系统。

3、对生成的rootfs.emmc进行md5校验

1
2
3
4
5
#进行md5校验
md5sum  install/soc_sg2000_lubancat_riscv_ubuntu_emmc/rootfs.emmc

#信息输出如下
2a66297044f46517582beeadc72e1118  install/soc_sg2000_lubancat_riscv_ubuntu_emmc/rootfs.emmc

4、将生成的rootfs.emmc替换到eMMC镜像包

../../_images/image_backup_7.jpg

5、修改eMMC镜像包的META目录中的metadata.txt,将生成的md5校验值修改到文件中。

../../_images/image_backup_8.jpg

最终使用该emmc镜像包刷到emmc中即可。