色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創作中心

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

3天內不再提示

稀疏鏡像在OpenHarmony上的應用

OpenAtom OpenHarmony ? 來源:未知 ? 2023-02-09 17:40 ? 次閱讀

開源項目 OpenHarmony是每個人的 OpenHarmony b486eddc-a85d-11ed-bfe3-dac502259ad0.jpg

陳甲印

鴻湖萬聯高級技術專家

鴻湖萬聯產品推薦官

一、稀疏鏡像升級背景

常用系統鏡像格式為原始鏡像,即RAW格式。鏡像體積比較大,在燒錄固件或者升級固件時比較耗時,而且在移動設備升級過程時比較耗費流量。為此,將原始鏡像用稀疏描述,可以大大地縮減鏡像體積,省時省流量。

二、稀疏鏡像原理

1、稀疏鏡像的概念 原始鏡像:即raw image,完整的ext4分區鏡像,包含很多全零的無效填充區 稀疏鏡像:即sparse image,將raw ext4進行稀疏描述,因此尺寸比較小,制作目錄有多少文件就計算多少,沒有全零填充2、稀疏鏡像格式 b4ab0d66-a85d-11ed-bfe3-dac502259ad0.png ? 稀疏鏡像數據格式:首先是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/docs/blob/master/zh-cn/release-notes/OpenHarmony-v3.1-release.md

1、稀疏鏡像燒錄(1)生成稀疏格式鏡像有2種方法可以生成稀疏鏡像:1)修改文件build/ohos_var.gni中,sparse_image=true b4c588c6-a85d-11ed-bfe3-dac502259ad0.png ?2)編譯命令增加--sparse-image字段,如./build.sh --product-name=xxx --sparse-image(2)增加稀疏格式轉換工具在目錄build/ohos/images/mkimage中增加文件img2simg,該工具用于編譯完成后將raw鏡像轉換為sparse格式,并設置權限為777。(3)編譯后的鏡像對比 b4f0c1e4-a85d-11ed-bfe3-dac502259ad0.png ?編譯出的鏡像格式為sparse格式,鏡像大小相比raw格式明顯變小。(4)燒錄稀疏鏡像燒錄稀疏鏡像方法和燒錄原始鏡像方法一致。稀疏鏡像本身是不能直接掛載的,在燒錄過程中通過uboot將稀疏格式鏡像還原為原始鏡像,然后寫到磁盤中,系統啟動后可掛載對應的鏡像。 2、稀疏鏡像升級升級包采用稀疏鏡像制作。(1)修改升級包制作工具官方升級包工具不支持生成稀疏鏡像的升級包,修改升級包工具,生成稀疏格式的升級包。.aseupdatepackaging_toolsimage_class.py b514972c-a85d-11ed-bfe3-dac502259ad0.png ?按照上圖所示注釋代碼(2)生成稀疏鏡像升級包和全量鏡像升級包制作方法一致。

參考:

https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-ota-guide.md#%E6%A0%87%E5%87%86%E7%B3%BB%E7%BB%9F%E5%8D%87%E7%BA%A7%E5%8C%85%E5%88%B6%E4%BD%9C

(3)適配updater組件中稀疏鏡像功能●增加寫稀疏鏡像分支.aseupdateupdaterservicesapplypatchdata_writer.cpp寫數據函數CreateDataWriter增加寫稀疏鏡像分支
case WRITE_SPARSE:
{
    std::unique_ptr writer(std::make_unique(partitionName));
    return std::move(writer);
}
●增加稀疏鏡像類聲明.aseupdateupdaterservicesapplypatch aw_writer.h增加稀疏鏡像類聲明及相關變量定義
typedefstructsparse_header{
 uint32_tmagic;  /* 0xed26ff3a */
 uint16_tmajor_version;/* (0x1) - reject images with higher major versions */
 uint16_tminor_version;/* (0x0) - allow images with higer minor versions */
 uint16_tfile_hdr_sz; /* 28 bytes for first revision of the file format */
 uint16_tchunk_hdr_sz; /* 12 bytes for first revision of the file format */
 uint32_tblk_sz;  /* block size in bytes, must be a multiple of 4 (4096) */
 uint32_ttotal_blks;/* total blocks in the non-sparse output image */
 uint32_ttotal_chunks; /* total chunks in the sparse input image */
 uint32_timage_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;

#defineSPARSE_HEADER_MAGIC 0xed26ff3a

#defineCHUNK_TYPE_RAW   0xCAC1
#defineCHUNK_TYPE_FILL   0xCAC2
#defineCHUNK_TYPE_DONT_CARE  0xCAC3
#defineCHUNK_TYPE_CRC32  0xCAC4

typedefstructchunk_header{
 uint16_tchunk_type;/* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
 uint16_treserved1;
 uint32_tchunk_sz; /* in blocks in output image */
 uint32_ttotal_sz; /* in bytes of chunk input file including chunk header and data */
} chunk_header_t;

classSparseWriter: publicDataWriter{
public:
  virtualboolWrite(constuint8_t*addr, size_tlen, WriteModemode, conststd::string&partitionName);

  explicitSparseWriter(conststd::stringpartitionName) : offset_(0), fd_(-1), partitionName_(partitionName) {}

  virtual~SparseWriter()
  {
    offset_= 0;
    if(fd_> 0) {
      fsync(fd_);
      close(fd_);
    }
    fd_= -1;
  }
private:
  intWriteInternal(intfd, constuint8_t*data, size_tlen, conststd::string&partitionName);

  SparseWriter(constSparseWriter&) = delete;

  constSparseWriter&operator=(constSparseWriter&) = delete;
  off64_toffset_;
  intfd_;
  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;
}
3、驗證稀疏鏡像升級(1)拷貝升級包將制作的稀疏鏡像升級包通過HDC工具推進系統data目錄,并修改文件名為updater.zip,路徑如下:/data/updater/updater.zip(2)啟動升級系統啟動后,在命令行工具輸入如下命令啟動升級reboot updater:--update_package=/data/updater/updater.zip輸入命令后,系統重啟,進入升級頁面,等待升級完成。 本文介紹了OpenHarmony系統中實現稀疏鏡像升級的方法,理解稀疏鏡像原理及稀疏鏡像還原方法可以快速在自己的系統中應用稀疏鏡像升級,提高系統升級速度。


原文標題:稀疏鏡像在OpenHarmony上的應用

文章出處:【微信公眾號:OpenAtom OpenHarmony】歡迎添加關注!文章轉載請注明出處。


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

    關注

    57

    文章

    2464

    瀏覽量

    43601
  • OpenHarmony
    +關注

    關注

    26

    文章

    3800

    瀏覽量

    17697

原文標題:稀疏鏡像在OpenHarmony上的應用

文章出處:【微信號:gh_e4f28cfa3159,微信公眾號:OpenAtom OpenHarmony】歡迎添加關注!文章轉載請注明出處。

收藏 0人收藏

    評論

    相關推薦

    OpenVINO? Toolkit中如何保持模型稀疏性?

    OpenVINO? Toolkit 中支持的優化方法,保持模型稀疏性。
    發表于 03-06 06:47

    【北京迅為】itop-3568 開發板openharmony鴻蒙燒寫及測試-第1章 體驗OpenHarmony—燒寫鏡像

    【北京迅為】itop-3568 開發板openharmony鴻蒙燒寫及測試-第1章 體驗OpenHarmony—燒寫鏡像
    的頭像 發表于 03-04 16:31 ?317次閱讀
    【北京迅為】itop-3568 開發板<b class='flag-5'>openharmony</b>鴻蒙燒寫及測試-第1章 體驗<b class='flag-5'>OpenHarmony</b>—燒寫<b class='flag-5'>鏡像</b>

    蜂鳥板Openharmony系統跑QT程序

    將QT程序放到Openharmony系統跑,可以運行,但是會被覆蓋掉。(用的網盤里面的install,支持QT組件的版本)。 運行情況是,在終端運行QT程序,可以正常運行出來,但是觸摸屏幕后,會被Openharmony操作界面
    發表于 02-26 13:04

    Flexusx 實例與 Harbor 私有鏡像倉庫的完美結合

    前言 華為云 828 企業云節,Flexus X 實例攜手 Harbor 私有鏡像倉庫,共創云安全高效新生態!Flexus X 以其卓越性能與穩定性,為 Harbor 提供了理想的運行環境
    的頭像 發表于 01-22 18:04 ?255次閱讀
    Flexusx 實例與 Harbor 私有<b class='flag-5'>鏡像</b>倉庫的完美結合

    Docker-鏡像的分層-busybox鏡像制作

    目錄 知識點1:鏡像的分層 示例:進入 docker hub查看Jenkins的Dockerfile 知識點2:base鏡像 知識點3:scratch鏡像 scratch 鏡像是什么?
    的頭像 發表于 01-15 10:44 ?419次閱讀
    Docker-<b class='flag-5'>鏡像</b>的分層-busybox<b class='flag-5'>鏡像</b>制作

    華為云 X 實例的鏡像管理詳解

    前言 隨著云計算的不斷普及,云服務器成為企業和開發者日常工作中的重要工具。為了提升工作效率和降低運維成本,云服務器鏡像的管理尤為重要。鏡像作為服務器或磁盤的模板,預裝了操作系統、軟件及配置,是快速
    的頭像 發表于 01-07 17:01 ?406次閱讀
    華為云 X 實例的<b class='flag-5'>鏡像</b>管理詳解

    OpenHarmony通過掛載鏡像來修改鏡像內容,RK3566鴻蒙開發板演示

    OpenHarmony通過掛載鏡像來修改鏡像內容的教程,提高修改鏡像內容效率!
    的頭像 發表于 01-03 14:21 ?371次閱讀
    <b class='flag-5'>OpenHarmony</b>通過掛載<b class='flag-5'>鏡像</b>來修改<b class='flag-5'>鏡像</b>內容,RK3566鴻蒙開發板演示

    OpenHarmony源碼編譯后燒錄鏡像教程,RK3566鴻蒙開發板演示

    本文介紹瑞芯微主板/開發板編譯OpenHarmony源碼后燒錄鏡像的教程,觸覺智能Purple Pi OH鴻蒙開發板演示。搭載了瑞芯微RK3566四核處理器,樹莓派卡片電腦設計,支持開源鴻蒙OpenHarmony3.2-5.0系
    的頭像 發表于 12-30 10:08 ?464次閱讀
    <b class='flag-5'>OpenHarmony</b>源碼編譯后燒錄<b class='flag-5'>鏡像</b>教程,RK3566鴻蒙開發板演示

    dayu200 rk3568 openharmony5.0 sim卡 通話服務

    想請問一下有人在dayu200 rk3568插過sim卡并且成功完成過通話服務嗎? 我現在在dayu200燒錄了openHarmony release 5.0.0版本的鏡像,在上面
    發表于 12-26 16:52

    嵌入式學習-飛凌嵌入式ElfBoard ELF 1板卡-mfgtools燒錄流程介紹之燒寫所需鏡像

    USB OTG燒寫所需鏡像在:ELF 1開發板資料包\\06-常用工具\\06-4 燒寫工具\\OTG燒寫\\mfgtools\\Profiles\\Linux\\OS Firmware
    發表于 12-21 09:25

    飛凌嵌入式ElfBoard ELF 1板卡-mfgtools燒錄流程介紹之燒寫所需鏡像

    USB OTG燒寫所需鏡像在:ELF 1開發板資料包\\06-常用工具\\06-4 燒寫工具\\OTG燒寫\\mfgtools\\Profiles\\Linux\\OS Firmware
    發表于 12-20 09:05

    [2K300適配OpenharmonyV4.1]根文件系統制作請教

    官方你好,我這邊需要適配OpenharmonyV4.1,但是目前網上找不到2K300的開源資料,我嘗試使用2K500開源資料搭建開發環境,目前已成功編譯出對應鏡像,但是我想將OpenHarmony
    發表于 09-11 11:18

    第二屆大會回顧第25期 | OpenHarmony的Python設備應用開發

    Python以其簡單、易學和功能強大而聞名,有著廣泛的用戶群體。采用Python開發有助于降低OpenHarmony的學習門檻。如何在OpenHarmony用Python開發設備應用,有哪些關鍵技術?電
    的頭像 發表于 08-27 11:53 ?980次閱讀
    第二屆大會回顧第25期 | <b class='flag-5'>OpenHarmony</b><b class='flag-5'>上</b>的Python設備應用開發

    【飛凌嵌入式OK527N-C開發板體驗】- 3. 打包鏡像以及燒錄

    只想更新boot或者設備樹等則勾選單或多分區下載,并勾選需要下載的部分。 內核鏡像在BOOT分區,設備樹和uboot在BOOT-RESOURCE分區 查看燒錄的是不是自己編譯的版本,進入系統后輸入如下
    發表于 07-11 21:27

    【飛凌嵌入式OK527N-C開發板體驗】-打包鏡像以及燒錄

    只想更新boot或者設備樹等則勾選單或多分區下載,并勾選需要下載的部分。 內核鏡像在BOOT分區,設備樹和uboot在BOOT-RESOURCE分區 查看燒錄的是不是自己編譯的版本,進入系統后輸入如下
    發表于 07-05 23:15
    主站蜘蛛池模板: 久久精品国产亚洲AV天美18 | 99热精品在线视频观看 | 青青久在线 | 国产精品久久久久激情影院 | 娇小萝被两个黑人用半米长 | 国产九色在线 | 视频一区在线免费观看 | 精品日韩欧美一区二区三区 | 97在线超碰免费视频 | 浪荡女天天不停挨CAO日常视 | 出差无套内射小秘书 | 综合久久久久久久综合网 | 女人精69xxxxx | 18禁无遮挡羞羞污污污污免费 | 69式国产真人免费视频 | 国产一区二区免费在线观看 | brazzers欧美最新版视频 | 花蝴蝶在线高清视频观看免费播放 | 国产AV亚洲精品久久久久 | 免费精品国偷自产在线 | 麻豆一二三四区乱码 | 美女国产毛片A区内射 | 久久综合中文字幕佐佐木希 | 国产做国产爱免费视频 | 亚洲 无码 在线 专区 | 日日夜夜天天操 | 成人短片迅雷下载 | 3344永久在线观看视频免费 | 国产亚洲美女在线视频视频 | 97视频在线观看视频最新 | 一个人的HD高清在线观看 | 国产精品日本不卡一区二区 | 2021久久最新国产精品 | 99国产精品成人免费视频 | 日本久久久WWW成人免费毛片丨 | MD传媒在线观看佳片 | 精品第一国产综合精品蜜芽 | 理论片在线观看片免费 | 午夜福利试看120秒体验区 | 免费韩伦影院在线观看 | 国产色精品VR一区二区 |

    電子發燒友

    中國電子工程師最喜歡的網站

    • 2931785位工程師會員交流學習
    • 獲取您個性化的科技前沿技術信息
    • 參加活動獲取豐厚的禮品