国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

稀疏鏡像在 OpenHarmony 上的探索

電子發燒友開源社區 ? 來源:未知 ? 2023-01-06 08:30 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一、稀疏鏡像升級背景
常用系統鏡像格式為原始鏡像,即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的內容。

三、實現稀疏鏡像升級方案
1. 稀疏鏡像燒錄
生成稀疏格式鏡像,有2種方法可以生成稀疏鏡像:
修改文件build/ohos_var.gni中,sparse_image=true

編譯命令增加--sparse-image字段,
如./build.sh --product-name=xxx --sparse-image

增加稀疏格式轉換工具
在目錄build/ohos/images/mkimage中增加文件img2simg,該工具用于編譯完成后將raw鏡像轉換為sparse格式,并設置權限為777。

編譯后的鏡像對比

編譯出的鏡像格式為sparse格式,鏡像大小相比raw格式明顯變小。燒錄稀疏鏡像方法和燒錄原始鏡像方法一致。稀疏鏡像本身是不能直接掛載的,在燒錄過程中通過uboot將稀疏格式鏡,還原為原始鏡像,然后寫到磁盤中,系統啟動后可掛載對應的鏡像。

2. 稀疏鏡像OTA升級
OTA升級的升級包采用稀疏鏡像制作。

(1)修改升級包制作工具
官方升級包工具不支持生成稀疏鏡像的升級包,修改升級包工具,生成稀疏格式的升級包。
.aseupdatepackaging_toolsimage_class.py
按照上圖所示注釋代碼

(2)生成稀疏鏡像升級包
和全量鏡像升級包制作方法一致。

(3)適配updater組件中稀疏鏡像功能
增加寫稀疏鏡像分支
.aseupdateupdaterservicesapplypatchdata_writer.cpp
寫數據函數CreateDataWriter增加寫稀疏鏡像分支
case WRITE_SPARSE:{std::make_unique(partitionName));return std::move(writer);}
增加稀疏鏡像類聲明
.aseupdateupdaterservicesapplypatch
aw_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    0xCAC4typedef 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_;};
增加稀疏鏡像類實現
.aseupdateupdaterservicesapplypatch
aw_writer.cpp
增加稀疏鏡像類實現及相關變量定義,原有代碼不變
bool SparseWriter::Write(const uint8_t *addr, size_t len, WriteMode mode, const std::string &partitionName)
{
if (addr == nullptr) {
LOG(ERROR) << "SparseWriter: invalid address.";
return false;
}
if (len == 0) {
LOG(INFO) << "SparseWriter: write length is 0, skip.";
return false;
}
if (fd_ < 0) {
fd_ = OpenPartition(partitionName_);
if (fd_ < 0) {
return false;
}
}




UPDATER_CHECK_ONLY_RETURN(WriteInternal(fd_, addr, len, partitionName_) >= 0, return false);
return true;
}








int SparseWriter::WriteInternal(int fd, const uint8_t *data, size_t len, const std::string &partitionName)
{
uint32_t written = 0;
sparse_header_t *sparse_header;
chunk_header_t *chunk_header;
unsigned int chunk;
void *membuf = NULL;
uint32_t *fill_buf = NULL;
uint32_t fill_val;
uint32_t bytes_written = 0;
uint32_t total_bytes = 0;
uint32_t blk = 0;
uint32_t chunk_data_sz = 0;
uint32_t blkcnt = 0;
uint32_t blks = 0;
uint32_t total_blocks = 0;
uint32_t addr_offset = 0;
uint32_t fill_buf_num_blks = 0;








uint32_t block_size = 4096;
uint32_t block_count = 524288;
uint32_t i;
uint32_t j;
int ret = lseek64(fd, offset_, SEEK_SET);
UPDATER_FILE_CHECK(ret != -1, "RawWriter: failed to seek file to " << offset_, return -1);
fill_buf_num_blks = CONFIG_FASTBOOT_FLASH_FILLBUF_SIZE / block_size;
LOG(INFO) << "WriteInternal offset_ " << offset_;
/* Read and skip over sparse image header */
sparse_header = (sparse_header_t *)data;
data += sparse_header->file_hdr_sz;
if (sparse_header->file_hdr_sz > sizeof(sparse_header_t)) {
/*
* Skip the remaining bytes in a header that is longer than
* we expected.
*/
data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
}
LOG(INFO) << "=== Sparse Image Header ===";
LOG(INFO) << "magic: " << sparse_header->magic;
LOG(INFO) << "major_version: " << sparse_header->major_version;
LOG(INFO) << "minor_version: " << sparse_header->minor_version;
LOG(INFO) << "file_hdr_sz: " << sparse_header->file_hdr_sz;
LOG(INFO) << "chunk_hdr_sz: " << sparse_header->chunk_hdr_sz;
LOG(INFO) << "blk_sz: " << sparse_header->blk_sz;
LOG(INFO) << "total_blks: " << sparse_header->total_blks;
LOG(INFO) << "total_chunks: " << sparse_header->total_chunks;








LOG(INFO) << "Flashing Sparse Image";
blk = 0;
for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) {
/* Read and skip over chunk header */
chunk_header = (chunk_header_t *)data;
data += sizeof(chunk_header_t);
if (chunk_header->chunk_type != CHUNK_TYPE_RAW)
{
LOG(INFO) << "=== Chunk Header ===";
LOG(INFO) << "chunk_type: " << chunk_header->chunk_type;
LOG(INFO) << "chunk_sz: " << chunk_header->chunk_sz;
LOG(INFO) << "total_sz: " << chunk_header->total_sz;
}
if (sparse_header->chunk_hdr_sz > sizeof(chunk_header_t)) {
/*
* Skip the remaining bytes in a header that is longer
* than we expected.
*/
data += (sparse_header->chunk_hdr_sz -
sizeof(chunk_header_t));
}
chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
blkcnt = chunk_data_sz / block_size;
switch (chunk_header->chunk_type) {
case CHUNK_TYPE_RAW:
if (chunk_header->total_sz !=
(sparse_header->chunk_hdr_sz + chunk_data_sz)) {
LOG(ERROR) << "Bogus chunk size for chunk type Raw";
return -1;
}
if (blk + blkcnt > 0 + block_count) {
LOG(ERROR) << "Request would exceed partition size!";
return -1;
}
addr_offset = blk * block_size;
ret = lseek64(fd, offset_ + addr_offset, SEEK_SET);
if (ret < 0) {
LOG(ERROR) << "failed to seek file to " << addr_offset << " error=" << strerror(errno);
return -1;
}
written = write(fd, data, blkcnt * block_size);
if (written < 0) {
LOG(ERROR) << "SparseWriter: failed to write data of len ";
return -1;
}
total_bytes = total_bytes + blkcnt * block_size;
blks = written / block_size;
blk += blks;
bytes_written += blkcnt * block_size;
total_blocks += chunk_header->chunk_sz;
data += chunk_data_sz;
break;
case CHUNK_TYPE_FILL:
if (chunk_header->total_sz !=
(sparse_header->chunk_hdr_sz + sizeof(uint32_t))) {
LOG(ERROR) << "Bogus chunk size for chunk type FILL total_sz err " << chunk_header->total_sz << " ";
return -1;
}
ret = posix_memalign (&membuf, 64,
ROUNDUP(
block_size * fill_buf_num_blks,
64));
if (ret) {
LOG(ERROR) << "posix_memalign:" << strerror (errno);
return -1;
}
fill_buf = (uint32_t *)membuf;
if (!fill_buf) {
LOG(ERROR) << "Malloc failed for: CHUNK_TYPE_FILL";
return -1;
}
fill_val = *(uint32_t *)data;
data = data + sizeof(uint32_t);
for (i = 0;
i < (block_size * fill_buf_num_blks /
sizeof(fill_val));
i++)
fill_buf[i] = fill_val;
if (blk + blkcnt > 0 + block_count) {
LOG(ERROR) << "Request would exceed partition size!";
return -1;
}
for (i = 0; i < blkcnt;) {
j = blkcnt - i;
if (j > fill_buf_num_blks)
j = fill_buf_num_blks;
addr_offset = blk * block_size;
ret = lseek64(fd, offset_ + addr_offset, SEEK_SET);
if (ret < 0) {
LOG(ERROR) << "failed to lseek file to " << addr_offset << " error=" << strerror(errno);
return -1;
}
written = write(fd, fill_buf, j * block_size);
if (written < 0) {
LOG(ERROR) << "SparseWriter: failed to write data of len ";
return -1;
}
total_bytes = total_bytes + j * block_size;
blks = written / block_size;
if (blks < j) {
LOG(ERROR) << "Write failed, block";
free(fill_buf);
return -1;
}
blk += blks;
i += j;
}
bytes_written += blkcnt * block_size;
total_blocks += chunk_data_sz / sparse_header->blk_sz;
free(fill_buf);
break;
case CHUNK_TYPE_DONT_CARE:
blk += blkcnt;
total_blocks += chunk_header->chunk_sz;
break;
case CHUNK_TYPE_CRC32:
if (chunk_header->total_sz !=
sparse_header->chunk_hdr_sz) {
LOG(ERROR) << "Bogus chunk size for chunk type CRC32 total_sz err " << chunk_header->total_sz;
return -1;
}
total_blocks += chunk_header->chunk_sz;
data += chunk_data_sz;
break;
default:
LOG(INFO) << __func__ << ": Unknown chunk type: " << chunk_header->chunk_type;
return -1;
}
}
LOG(INFO) << "Wrote "<< chunk <<"blocks, expected to write " << sparse_header->total_blks << "blocks ";
LOG(INFO) << "........ wrote "<< bytes_written <<"bytes to " << partitionName << " ";
LOG(INFO) << "total_bytes=" << total_bytes;
return 0;
}

本文介紹了OpenHarmony系統中實現稀疏鏡像升級的方法,理解稀疏鏡像原理及稀疏鏡像還原方法可以快速在自己的系統中應用稀疏鏡像升級,提高系統升級速度。


更多熱點文章閱讀
  • DevEco Studio新特性分享-跨語言調試,讓調試更便捷高效
  • 基于 OpenHarmony 的智聯北斗海防系統
  • 玩轉OpenHarmony智能家居:如何實現樹莓派“碰一碰”設備控制
  • 玩轉OpenHarmony社交場景:即時通訊平臺
  • HarmonyOS多媒體框架介紹


提示:本文由電子發燒友社區發布,轉載請注明以上來源。如需社區合作及入群交流,請添加微信EEFans0806,或者發郵箱liuyong@huaqiu.com。


原文標題:稀疏鏡像在 OpenHarmony 上的探索

文章出處:【微信公眾號:電子發燒友開源社區】歡迎添加關注!文章轉載請注明出處。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 電子發燒友
    +關注

    關注

    34

    文章

    591

    瀏覽量

    34137
  • 開源社區
    +關注

    關注

    1

    文章

    95

    瀏覽量

    798

原文標題:稀疏鏡像在 OpenHarmony 上的探索

文章出處:【微信號:HarmonyOS_Community,微信公眾號:電子發燒友開源社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    使用Dockerfile構建鏡像的詳細步驟

    Dockerfile寫得好不好,直接影響三件事:鏡像大小、構建速度、運行安全性。我見過太多團隊的Dockerfile是"能跑就行"的水平——基礎鏡像用ubuntu:latest
    的頭像 發表于 02-26 09:43 ?172次閱讀

    【原創】OpenHarmony系統投屏工具軟件 - OpenHarmony_OHScrcpy使用推薦

    Android平臺的scrcpy投屏工具。它能夠將OpenHarmony設備的屏幕實時鏡像到計算機,并提供設備控制功能。 實現原理框圖 計算機側(客戶端) :基于Python跨平臺實現 OpenHarmony設備
    發表于 01-22 18:34

    #OpenHarmony HDC調試

    OpenHarmony
    視美泰
    發布于 :2026年01月16日 09:46:28

    #OpenHarmony 開發環境準備

    OpenHarmony
    視美泰
    發布于 :2026年01月16日 09:44:31

    #OpenHarmony 鏡像燒錄

    OpenHarmony
    視美泰
    發布于 :2026年01月16日 09:42:36

    #OpenHarmony 系統概述

    OpenHarmony
    視美泰
    發布于 :2026年01月16日 09:39:20

    #OpenHarmony Hello World應用以及部署

    OpenHarmony
    視美泰
    發布于 :2026年01月16日 09:32:52

    OpenHarmony系統】本期視頻將為您介紹怎樣將鏡像燒錄到板卡中。

    OpenHarmony
    視美泰
    發布于 :2026年01月15日 14:29:55

    炎核開源開放平臺上架推出OpenSparseBlas高性能稀疏計算庫

    在科學計算與工程仿真領域,高效處理大規模稀疏矩陣運算是提升整體計算效能的關鍵。為此,我們在炎核開源開放平臺上架推出 OpenSparseBlas——一個專為稀疏矩陣/向量計算而打造的高性能稀疏計算庫
    的頭像 發表于 12-15 15:18 ?639次閱讀

    請問各位dayu200是不是不支持燒錄64位的OpenHarmony

    我自己編譯了OpenHarmony5.0.2的鏡像,發現如果使用arm64參數編譯為64位版本,燒錄后卡在開機動畫無法開機,如果編譯為32位就可以正常。請問dayu200不支持64位系統嗎?
    發表于 08-16 17:39

    Allegro Skill布局功能之整體模塊鏡像介紹

    使用“整體鏡像”功能可以實現快速、批量、多元素的鏡像操作,此功能可以將整個模塊電路快速鏡像,包括電路中的走線、銅皮、字符等,有便捷方便的操作方式,例如下文演示。 1、在菜單欄中點擊“FanySkill-布局-整體
    的頭像 發表于 05-08 16:42 ?2414次閱讀
    Allegro Skill布局功能之整體模塊<b class='flag-5'>鏡像</b>介紹

    rootfs鏡像制作其實沒那么難

    在嵌入式Linux開發中,文件系統的打包和鏡像制作是關鍵步驟。本文介紹了Linux核心板文件系統的打包與鏡像制作方法,適合嵌入式開發人員快速上手。前言致遠電子Linux核心板提供的系統固件里,除了
    的頭像 發表于 04-03 11:37 ?1095次閱讀
    rootfs<b class='flag-5'>鏡像</b>制作其實沒那么難

    樹莓派鏡像的制作、燒錄及運行

    你是否想過自己動手打造一個專屬的操作系統鏡像?無論是為極客項目定制開發環境,還是讓老舊設備煥發新生,系統鏡像定制都是極客玩家的必備技能。
    的頭像 發表于 03-27 16:00 ?2571次閱讀

    【貝啟科技BQ3568HM開源鴻蒙開發板深度試用報告】系統鏡像編譯和燒錄

    兩個部分,分別是系統鏡像編譯環境、DevEco Studio開發環境。 在系統鏡像編譯環境中,用于從源碼編譯系統的鏡像,以及命令行運行的系統程序或者用戶程序。 DevEco Studio開發環境,則用
    發表于 03-16 10:53

    基于Docker鏡像逆向生成Dockerfile

    在本文中, 我們將通過理解Docker鏡像如何存儲數據, 以及如何使用工具查看鏡像方方面面的信息來逆向工程一個Docker鏡像; 以及如何使用Python的Docker API來構建一個類似Dedockify的工具來創建Dock
    的頭像 發表于 03-10 09:45 ?1552次閱讀
    基于Docker<b class='flag-5'>鏡像</b>逆向生成Dockerfile