一、稠密镜像降级背景

罕用零碎镜像格局为原始镜像,即RAW格局。镜像体积比拟大,在烧录固件或者降级固件时比拟耗时,而且在挪动设施降级过程时比拟消耗流量。为此,将原始镜像用稠密形容,能够大大地缩减镜像体积,省时省流量。

二、稠密镜像原理

1、稠密镜像的概念
原始镜像:即raw image,残缺的ext4分区镜像,蕴含很多全零的有效填充区
稠密镜像:即sparse image,将raw ext4进行稠密形容,因而尺寸比拟小,制作目录有多少文件就计算多少,没有全零填充

2、稠密镜像格局

稠密镜像数据格式:首先是sparse_header占用28byte,而后是12byte的chunk_header,同样这chunk_header的类型决定了前面跟着的数据,如果读到数据是0xCAC1意味着前面是自身的raw_data,如果是0xCAC3,则前面num为0,接着再0xCAC2意味着前面填充4byte的内容。

三、实现稠密镜像降级计划

版本基线:
OpenAtom OpenHarmony(以下简称“OpenHarmony”) 3.1 Release
代码门路:https://gitee.com/openharmony...

1、稠密镜像烧录
(1)生成稠密格局镜像
有2种办法能够生成稠密镜像:
1)批改文件build/ohos_var.gni中,sparse_image=true

2)编译命令减少--sparse-image字段,如./build.sh --product-name=xxx --sparse-image

(2)减少稠密格局转换工具
在目录build/ohos/images/mkimage中减少文件img2simg,该工具用于编译实现后将raw镜像转换为sparse格局,并设置权限为777。

(3)编译后的镜像比照

编译出的镜像格局为sparse格局,镜像大小相比raw格局显著变小。

(4)烧录稠密镜像

烧录稠密镜像办法和烧录原始镜像办法统一。

稠密镜像自身是不能间接挂载的,在烧录过程中通过uboot将稠密格局镜像还原为原始镜像,而后写到磁盘中,系统启动后可挂载对应的镜像。

2、稠密镜像降级
升级包采纳稠密镜像制作。
(1)批改升级包制作工具
官网升级包工具不反对生成稠密镜像的升级包,批改升级包工具,生成稠密格局的升级包。.\base\update\packaging_tools\image_class.py

依照上图所示正文代码

(2)生成稠密镜像升级包
和全量镜像升级包制作方法统一。
参考:https://gitee.com/openharmony...

(3)适配updater组件中稠密镜像性能

● 减少写稠密镜像分支
.\base\update\updater\services\applypatch\data_writer.cpp

写数据函数CreateDataWriter减少写稠密镜像分支

case WRITE_SPARSE:{    std::unique_ptr<SparseWriter> writer(std::make_unique<SparseWriter>(partitionName));    return std::move(writer);}

● 减少稠密镜像类申明
.\base\update\updater\services\applypatch\raw_writer.h
减少稠密镜像类申明及相干变量定义

typedef struct sparse_header {  uint32_t  magic;      /* 0xed26ff3a */  uint16_t  major_version;  /* (0x1) - reject images with higher major versions */  uint16_t  minor_version;  /* (0x0) - allow images with higer minor versions */  uint16_t  file_hdr_sz;    /* 28 bytes for first revision of the file format */  uint16_t  chunk_hdr_sz;   /* 12 bytes for first revision of the file format */  uint32_t  blk_sz;     /* block size in bytes, must be a multiple of 4 (4096) */  uint32_t  total_blks; /* total blocks in the non-sparse output image */  uint32_t  total_chunks;   /* total chunks in the sparse input image */  uint32_t  image_checksum; /* CRC32 checksum of the original data, counting "don't care" */                /* as 0. Standard 802.3 polynomial, use a Public Domain */                /* table implementation */} sparse_header_t; #define SPARSE_HEADER_MAGIC 0xed26ff3a #define CHUNK_TYPE_RAW      0xCAC1#define CHUNK_TYPE_FILL     0xCAC2#define CHUNK_TYPE_DONT_CARE    0xCAC3#define CHUNK_TYPE_CRC32    0xCAC4 typedef struct chunk_header {  uint16_t  chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */  uint16_t  reserved1;  uint32_t  chunk_sz;   /* in blocks in output image */  uint32_t  total_sz;   /* in bytes of chunk input file including chunk header and data */} chunk_header_t; class SparseWriter : public DataWriter {public:    virtual bool Write(const uint8_t *addr, size_t len, WriteMode mode, const std::string &partitionName);     explicit SparseWriter(const std::string partitionName) : offset_(0), fd_(-1), partitionName_(partitionName) {}     virtual ~SparseWriter()    {        offset_ = 0;        if (fd_ > 0) {            fsync(fd_);            close(fd_);        }        fd_ = -1;    }private:    int WriteInternal(int fd, const uint8_t *data, size_t len, const std::string &partitionName);     SparseWriter(const SparseWriter&) = delete;     const SparseWriter& operator=(const SparseWriter&) = delete;    off64_t offset_;    int fd_;    std::string partitionName_;};

● 减少稠密镜像类实现
.\base\update\updater\services\applypatch\raw_writer.cpp
减少稠密镜像类实现及相干变量定义,原有代码不变

typedef struct sparse_header {  uint32_t  magic;      /* 0xed26ff3a */  uint16_t  major_version;  /* (0x1) - reject images with higher major versions */  uint16_t  minor_version;  /* (0x0) - allow images with higer minor versions */  uint16_t  file_hdr_sz;    /* 28 bytes for first revision of the file format */  uint16_t  chunk_hdr_sz;   /* 12 bytes for first revision of the file format */  uint32_t  blk_sz;     /* block size in bytes, must be a multiple of 4 (4096) */  uint32_t  total_blks; /* total blocks in the non-sparse output image */  uint32_t  total_chunks;   /* total chunks in the sparse input image */  uint32_t  image_checksum; /* CRC32 checksum of the original data, counting "don't care" */                /* as 0. Standard 802.3 polynomial, use a Public Domain */                /* table implementation */} sparse_header_t; #define SPARSE_HEADER_MAGIC 0xed26ff3a #define CHUNK_TYPE_RAW      0xCAC1#define CHUNK_TYPE_FILL     0xCAC2#define CHUNK_TYPE_DONT_CARE    0xCAC3#define CHUNK_TYPE_CRC32    0xCAC4 typedef struct chunk_header {  uint16_t  chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */  uint16_t  reserved1;  uint32_t  chunk_sz;   /* in blocks in output image */  uint32_t  total_sz;   /* in bytes of chunk input file including chunk header and data */} chunk_header_t; class SparseWriter : public DataWriter {public:    virtual bool Write(const uint8_t *addr, size_t len, WriteMode mode, const std::string &partitionName);     explicit SparseWriter(const std::string partitionName) : offset_(0), fd_(-1), partitionName_(partitionName) {}     virtual ~SparseWriter()    {        offset_ = 0;        if (fd_ > 0) {            fsync(fd_);            close(fd_);        }        fd_ = -1;    }private:    int WriteInternal(int fd, const uint8_t *data, size_t len, const std::string &partitionName);     SparseWriter(const SparseWriter&) = delete;     const SparseWriter& operator=(const SparseWriter&) = delete;    off64_t offset_;    int fd_;    std::string partitionName_;};

3、验证稠密镜像降级
(1)拷贝升级包
将制作的稠密镜像升级包通过HDC工具推动零碎data目录,并批改文件名为updater.zip,门路如下:/data/updater/updater.zip

(2)启动降级
系统启动后,在命令行工具输出如下命令启动降级
reboot updater:--update_package=/data/updater/updater.zip
输出命令后,零碎重启,进入降级页面,期待降级实现。

本文介绍了OpenHarmony零碎中实现稠密镜像降级的办法,了解稠密镜像原理及稠密镜像还原办法能够疾速在本人的零碎中利用稠密镜像降级,进步系统升级速度。