原始鏡像:即raw image,完整的ext4分區鏡像,包含很多全零的無效填充區 稀疏鏡像:即sparse image,將raw ext4進行稀疏描述,因此尺寸比較小,制作目錄有多少文件就計算多少,沒有全零填充
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;
}
DevEco Studio新特性分享-跨語言調試,讓調試更便捷高效 基于 OpenHarmony 的智聯北斗海防系統 玩轉OpenHarmony智能家居:如何實現樹莓派“碰一碰”設備控制 玩轉OpenHarmony社交場景:即時通訊平臺 HarmonyOS多媒體框架介紹
提示:本文由電子發燒友社區發布,轉載請注明以上來源。如需社區合作及入群交流,請添加微信EEFans0806,或者發郵箱liuyong@huaqiu.com。
原文標題:稀疏鏡像在 OpenHarmony 上的探索
文章出處:【微信公眾號:電子發燒友開源社區】歡迎添加關注!文章轉載請注明出處。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
電子發燒友
+關注
關注
33文章
552瀏覽量
33018 -
開源社區
+關注
關注
0文章
94瀏覽量
461
原文標題:稀疏鏡像在 OpenHarmony 上的探索
文章出處:【微信號:HarmonyOS_Community,微信公眾號:電子發燒友開源社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
華為云 X 實例的鏡像管理詳解
前言 隨著云計算的不斷普及,云服務器成為企業和開發者日常工作中的重要工具。為了提升工作效率和降低運維成本,云服務器鏡像的管理尤為重要。鏡像作為服務器或磁盤的模板,預裝了操作系統、軟件及配置,是快速
OpenHarmony源碼編譯后燒錄鏡像教程,RK3566鴻蒙開發板演示
本文介紹瑞芯微主板/開發板編譯OpenHarmony源碼后燒錄鏡像的教程,觸覺智能Purple Pi OH鴻蒙開發板演示。搭載了瑞芯微RK3566四核處理器,樹莓派卡片電腦設計,支持開源鴻蒙OpenHarmony3.2-5.0系
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
星光璀璨,聆聽 OpenHarmony 貢獻者之聲
在第三屆開放原子開源基金會OpenHarmony技術大會上,
我們滿懷敬意地對取得優秀成果的星光OpenHarmony技術俱樂部、星光導師、星光貢獻者、星光活動進行了致謝。
他們不僅是技術的探索
發表于 10-28 17:09
[2K300適配OpenharmonyV4.1]根文件系統制作請教
官方你好,我這邊需要適配OpenharmonyV4.1,但是目前網上找不到2K300的開源資料,我嘗試使用2K500開源資料搭建開發環境,目前已成功編譯出對應鏡像,但是我想將OpenHarmony
發表于 09-11 11:18
河南大學OpenHarmony技術俱樂部正式揭牌成立
8月30日,由OpenAtom OpenHarmony(以下簡稱“OpenHarmony”)項目群技術指導委員會與河南大學共同舉辦的“河南大學OpenHarmony技術俱樂部成立大會”在鄭州校區友蘭
第二屆大會回顧第25期 | OpenHarmony上的Python設備應用開發
Python以其簡單、易學和功能強大而聞名,有著廣泛的用戶群體。采用Python開發有助于降低OpenHarmony的學習門檻。如何在OpenHarmony上用Python開發設備應用,有哪些關鍵技術?電
鴻蒙OpenHarmony南向/北向快速開發教程-迅為RK3568開發板
4.1學習之旅了嗎?快來加入我們,一起探索鴻蒙4.1系統的無限魅力吧!
【北京迅為】OpenHarmony學習開發系列教程(第1期 北向基礎篇一)
P0_先導課
P1_OpenHarmony系統概述
發表于 07-23 10:44
【飛凌嵌入式OK527N-C開發板體驗】- 3. 打包鏡像以及燒錄
只想更新boot或者設備樹等則勾選單或多分區下載,并勾選需要下載的部分。
內核鏡像在BOOT分區,設備樹和uboot在BOOT-RESOURCE分區
查看燒錄的是不是自己編譯的版本,進入系統后輸入如下
發表于 07-11 21:27
【飛凌嵌入式OK527N-C開發板體驗】-打包鏡像以及燒錄
只想更新boot或者設備樹等則勾選單或多分區下載,并勾選需要下載的部分。
內核鏡像在BOOT分區,設備樹和uboot在BOOT-RESOURCE分區
查看燒錄的是不是自己編譯的版本,進入系統后輸入如下
發表于 07-05 23:15
【五】Purple Pi OH開發板帶你7天入門OpenHarmony
在完成了PurplePiOH大部分的接口測試之后,緊接著就是一個充滿挑戰的任務——利用SDK來編譯生成我們自己的鏡像文件。通過這一過程,不僅能夠讓你獲得一個可在真實硬件上運行的系統鏡像,更重要的是,它讓你對
評論