Skip to content

Commit 49f883d

Browse files
committed
cli: added support to sparse images flashing
Signed-off-by: Giuseppe Fabiano <gfabiano40@gmail.com>
1 parent b60ec68 commit 49f883d

File tree

3 files changed

+140
-3
lines changed

3 files changed

+140
-3
lines changed

Cargo.lock

Lines changed: 68 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ publish = false # TODO
1414
maintenance = { status = "actively-developed" }
1515

1616
[dependencies]
17+
android-sparse-image = "0.1.3"
1718
anyhow = "1.0.89"
1819
clap = { version = "4.5.18", features = ["derive"] }
1920
clap-num = "1.1.1"

cli/src/programfile.rs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: BSD-3-Clause
22
// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3-
use anyhow::bail;
3+
use anyhow::{Ok, bail};
44
use indexmap::IndexMap;
55
use std::{
66
fs,
@@ -14,6 +14,10 @@ use qdl::{
1414
types::QdlChan,
1515
};
1616

17+
use android_sparse_image::{
18+
ChunkHeader, ChunkHeaderBytes, ChunkType, FILE_HEADER_BYTES_LEN, FileHeader, FileHeaderBytes,
19+
};
20+
1721
fn parse_read_cmd<T: Read + Write + QdlChan>(
1822
channel: &mut T,
1923
out_dir: &Path,
@@ -141,7 +145,73 @@ fn parse_program_cmd<T: Read + Write + QdlChan>(
141145
}
142146
}
143147

148+
let sparse = attrs
149+
.get("sparse")
150+
.unwrap_or(&"false".to_owned())
151+
.parse::<bool>()
152+
.unwrap_or(false);
153+
144154
let mut buf = fs::File::open(file_path)?;
155+
156+
if sparse {
157+
let mut header_bytes: FileHeaderBytes = [0; FILE_HEADER_BYTES_LEN];
158+
buf.read_exact(&mut header_bytes)?;
159+
let header = FileHeader::from_bytes(&header_bytes)?;
160+
161+
let mut offset: usize = 0;
162+
let start_sector = start_sector.parse::<usize>()?;
163+
for index in 0..header.chunks {
164+
let label_sparse = format!("{label}_{index}");
165+
let mut chunk_bytes = ChunkHeaderBytes::default();
166+
buf.read_exact(&mut chunk_bytes)?;
167+
let chunk = ChunkHeader::from_bytes(&chunk_bytes)?;
168+
169+
let out_size = chunk.out_size(&header);
170+
let num_sectors = out_size / sector_size;
171+
let start_offset = start_sector + offset;
172+
match chunk.chunk_type {
173+
ChunkType::Raw => {
174+
firehose_program_storage(
175+
channel,
176+
&mut buf,
177+
&label_sparse,
178+
num_sectors,
179+
phys_part_idx,
180+
start_offset.to_string().as_str(),
181+
)?;
182+
}
183+
ChunkType::Fill => {
184+
let mut fill_value = [0u8; 4];
185+
buf.read_exact(&mut fill_value)?;
186+
187+
let mut fill_vec = Vec::<u8>::with_capacity(out_size);
188+
for _ in 0..out_size / 4 {
189+
fill_vec.extend_from_slice(&fill_value[..]);
190+
}
191+
192+
firehose_program_storage(
193+
channel,
194+
&mut &fill_vec[..],
195+
&label_sparse,
196+
num_sectors,
197+
phys_part_idx,
198+
start_offset.to_string().as_str(),
199+
)?;
200+
}
201+
ChunkType::DontCare => {
202+
// Don't Care, skip
203+
}
204+
ChunkType::Crc32 => {
205+
// Not supported, on qcom tools is ignored, seek if present
206+
buf.seek_relative(4)?;
207+
}
208+
}
209+
210+
offset += out_size;
211+
}
212+
return Ok(());
213+
}
214+
145215
buf.seek(SeekFrom::Current(
146216
sector_size as i64 * file_sector_offset as i64,
147217
))?;

0 commit comments

Comments
 (0)