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} ;
44use indexmap:: IndexMap ;
55use 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+
1721fn 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