Skip to content

Implement sparse image support (no deps on libsparse) #37

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

bmx666
Copy link

@bmx666 bmx666 commented Feb 17, 2023

Hi @andersson, yep, it is another "sparse" version but without deps on libsparse. I've been testing it on several QCOM projects for over 2 years now, no problem.

@parport0
Copy link

parport0 commented Mar 4, 2023

@bmx666 Hi,

Why is this PR a draft? Are there any flaws in this implementation?

@bmx666
Copy link
Author

bmx666 commented Mar 5, 2023

Hi @parport0

Why is this PR a draft?

I'm waiting feedback from maintainer...

Are there any flaws in this implementation?

There are only two flaws:

  • upload speed can drop significantly if the image contains a lot of small chunks, compared to QPST / QFIL. Some kind of optimization is needed to merge and send many small fragments at once, because image may contain several small fragments following each other.
  • CHUNK_TYPE_FILL is not yet supported, but it can be easily implemented.

@obbardc
Copy link
Contributor

obbardc commented Oct 17, 2024

Looks pretty good to me, thanks @bmx666
Slowdown is fine, I guess. But perhaps CHUNK_TYPE_FILL is more important ?

@bmx666
Copy link
Author

bmx666 commented Oct 17, 2024

Looks pretty good to me, thanks @bmx666 Slowdown is fine, I guess. But perhaps CHUNK_TYPE_FILL is more important ?

Hi @obbardc , I uploaded an update to support CHUNK_TYPE_FILL a long time ago. Also during my research on Qualcomm tools, they replace the 4-byte chunks of fill values with one big CHUNK_TYPE_RAW.
Anyway, I don't have access to any Qualcomm boards anymore, I couldn't confirm and verify this patch.

@bmx666 bmx666 marked this pull request as ready for review October 17, 2024 10:53
@obbardc
Copy link
Contributor

obbardc commented Mar 22, 2025

@lumag I'd really love to see proper sparse support in qdl. Are you interested in that ?

@obbardc
Copy link
Contributor

obbardc commented Mar 26, 2025

@bmx666 can you rebase this, please?

@andersson
Copy link
Collaborator

Sorry for not commenting on this earlier. I think this PR looks good, but I wasn't able to validate the functionality - assuming PEBKAC I was going to get back to this, but didn't.

Given @bmx666 announcement that he doesn't have access to hardware it would be nice if someone with understanding of the sparse format/mechanism could conclude this effort (with appropriate credit to @bmx666 of course).

@obbardc
Copy link
Contributor

obbardc commented Mar 26, 2025

Sorry for not commenting on this earlier. I think this PR looks good, but I wasn't able to validate the functionality - assuming PEBKAC I was going to get back to this, but didn't.

Given @bmx666 announcement that he doesn't have access to hardware it would be nice if someone with understanding of the sparse format/mechanism could conclude this effort (with appropriate credit to @bmx666 of course).

I didn't see that. I'll try to take a look (assuming at @bmx666 is ok with it)

@bmx666 bmx666 force-pushed the sparse branch 2 times, most recently from ebfa696 to 92fd16d Compare March 27, 2025 00:36
@bmx666
Copy link
Author

bmx666 commented Mar 27, 2025

@bmx666 can you rebase this, please?

Hi @obbardc , done! I didn't notice any serious conflicts, build the current branch on my side.

if someone with understanding of the sparse format/mechanism could conclude this effort

@andersson Sparse format is pretty simple
sparse header + chunk header + (data optional) + chunk header + (data optional) + ...

Sparse header contains version, checksum, size of non-sparse image and number of chunks.
Chunk header can be one of 3 types: RAW, FILL, DON'T CARE.

  • RAW chunk header contains the data size for the RAW data, followed by the RAW data itself immediately after the header.
  • FILL chunk header contains a 4-byte value followed by a counter, indicating how many times the value should be written (e.g., flashing 0x11223344 20 times).
  • DON'T CARE chunk header specifies the number of bytes to skip. During the QDL flashing process, this simply advances the EMMC/UFS cursor offset and proceeds to the next chunk.

If the XML does not contain the partition attribute sparse="true", QDL will follow the default procedure. If the XML includes sparse="true" for a partition node but lacks a sparse header, it will be validated against the defined partition size. If the sizes match, it is likely that sparse="true" was set by mistake (https://github.com/linux-msm/qdl/pull/37/files#diff-1d3057ba972d033be63e0b915d1c3cf13e360aee440fded1f0db23c0a66bd596R95) and QDL will follow the default procedure (by setting sparse to false). Otherwise, if the size does not match the image size, QDL will return an error.
Qualcomm frequently ships an SDK where sparse="true" is mistakenly set, and some of their scripts used during image generation simply pass sparse="true" without actually generating a sparse image to final stage.

Copy link
Contributor

@obbardc obbardc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to add your Signed-off-by to commits too. There are just nitpicks in this review !

@@ -12,12 +12,16 @@ struct program {
const char *label;
unsigned num_sectors;
unsigned partition;
bool sparse;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool sparse;
bool is_sparse;

nitpick: wonder if it makes sense to put these with is_nand & is_erase ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, "sparse" naming reflects a real XML-attribute "sparse", same as "label", "num_sectors" and etc

@@ -0,0 +1,48 @@
#ifndef __SPARSE_H__
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this header need a copyright ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what it's supposed to be.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bmx666 added 2 commits March 27, 2025 15:41
Signed-off-by: Maxim Paymushkin <[email protected]>
Signed-off-by: Maxim Paymushkin <[email protected]>
@bmx666
Copy link
Author

bmx666 commented Mar 27, 2025

Need to add your Signed-off-by to commits too. There are just nitpicks in this review !

@obbardc done!

program.c Outdated
unsigned start_sector, chunk_size, chunk_type, chunk_data;

if (sparse_header_parse(fd, &sparse_header)) {
/* ignore false sparse images */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this comment misleading? If I read the code correctly we'll be programming the referenced image as a normal (non-sparse) image, not ignoring it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated to

/*
 * If the XML tag "program" contains the attribute 'sparse="true"'
 * for a partition node but lacks a sparse header,
 * it will be validated against the defined partition size.
 * If the sizes match, it is likely that the 'sparse="true"' attribute
 * was set by mistake.
 */

program.c Outdated
} else {
program_sparse = program_load_sparse(program, fd);
if (!program_sparse) {
fprintf(stderr, "[PROGRAM] load sparse failed\n");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you printed an (more useful) error in each error path within program_load_sparse() already, so no need to tell the user once more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, you can generate a correct sparse image, but all chunks will be DON'T CARE or the chunk header will contain zero bytes of data.
On the one hand, the sparse image is validated, but on the other hand, there is nothing to flash and the program will have to be skipped.
Maybe you can suggest a better scenario?

Signed-off-by: Maxim Paymushkin <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants