Commit Graph

186 Commits

Author SHA1 Message Date
Igor Opaniuk
669c2005d3 checkpatch: add more exceptions
Add more rules to ignore, as some of them incorrectly report
false positive results, for example in [1].

[1] https://github.com/linux-msm/qdl/actions/runs/15830061230/job/44624781156?pr=37
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 19:58:21 +02:00
Igor Opaniuk
2204f90bee github: create a full rep clone
Increase fetch-depth property for [1] action, which indicates that all
history for all branches and tags should be fetched.

This fix address such checkpatch issues as:

WARNING: Unknown commit id '4ed250c18436', maybe rebased or not pulled?
Fixes: 4ed250c184 ("qdl: add support for vip table of digests generation")
Error: WARNING: Unknown commit id '4ed250c18436', maybe rebased or not pulled?

[1] https://github.com/webispy/checkpatch-action
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 14:26:25 +02:00
Igor Opaniuk
7bdf416118 README: extend list of packages for Windows
Install "base-devel" package as well, which provides diff/cmp/make
tools.
Suggest to use "make" instead of "mingw32-make".

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 14:26:25 +02:00
Igor Opaniuk
4c942eea55 github: enable tests for windows
* Enable running tests on Windows
* Don't install cmake package, as it's not needed
* Install base-devel package, which contains regular make, diff and cmp
  tools.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 14:26:25 +02:00
Igor Opaniuk
fb47383c92 vip: open digest file as binary
read() returns the number of bytes read, which might be less than
provided buffer_size if there are fewer than buffer_size bytes left
in the file, or if the file was opened in text mode.

In text mode, each carriage return-line feed pair \r\n is replaced with a
single line feed character \n, which leads to failures on Windows
when reading digests from DIGEST_TABLE.bin (as we read less data than
we expect).

Fixes: 4ed250c184 ("qdl: add support for vip table of digests generation")
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 14:26:25 +02:00
Igor Opaniuk
a691179284 qdl: improve usage output
Prettify usage details and introduce explicit -h param:

Usage: qdl [options] <prog.mbn> [<program> <patch> ...]
 -d, --debug			Print detailed debug info
 -v, --version			Print the current version and exit
 -n, --dry-run			Dry run execution, no device reading or flashing
 -f, --allow-missing		Allow skipping of missing files during flashing
 -s, --storage=T		Set target storage type T: <emmc|nand|ufs>
 -l, --finalize-provisioning	Provision the target storage
 -i, --include=T		Set an optional folder T to search for files
 -S, --serial=T			Select target by serial number T (e.g. <0AA94EFD>)
 -u, --out-chunk-size=T		Override chunk size for transaction with T
 -t, --create-digests=T		Generate table of digests in the T folder
 -D, --vip-table-path=T		Use digest tables in the T folder for VIP
 -h, --help			Print this usage info

Example: qdl prog_firehose_ddr.elf rawprogram*.xml patch*.xml

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 14:26:14 +02:00
Igor Opaniuk
c70255e3e8 qdl: fix provided options to getopt_long
Fix list of provided command-line options to getopt_long() for parsing.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 14:26:14 +02:00
Igor Opaniuk
7a8b6f3115 qdl: drop enum for chunk size param
Drop enum definition for chunk size parameter.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 14:26:14 +02:00
Igor Opaniuk
8818b98e85 firehose: support VIP extension
This extends the Firehose protocol implementation to support the VIP
extension. It implements a state machine that counts the number of
packets sent, then injects the VIP table as the next RAW packet when
the Firehose programmer runs out of provided digests and needs a new table
of digests to validate the next packets. For example:

Packet 0: DigestsTableToSign.bin.mbn (53 digest + 1 digest of next table)
Packet 1: <configure>
Packet 2: <program>
Packet 3: ...
...
Packet 54: ChainedTableOfDigests0.bin (255 digests + digest of next table)
Packet 55: <program>
...
Packet 309: ChainedTableOfDigests1.bin

To enable VIP extension provide a path where previously generated VIP
tables are stored using "--vip-table-path" param:

$ qdl --vip-table-path "<vip-table-path>" prog_firehose_ddr.elf \
  rawprogram*.xml patch*.xml

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 14:26:14 +02:00
Igor Opaniuk
6454ab46f2 firehose: don't send configure packet in simulation
There is a regression in the current implementation of simulation mode,
which leads to sending two configure packets:

FIREHOSE WRITE: <?xml version="1.0"?>
<data><configure MemoryName="ufs" MaxPayloadSizeToTargetInBytes="1048576"
verbose="0" ZLPAwareHost="1" SkipStorageInit="0"/></data>

FIREHOSE WRITE: <?xml version="1.0"?>
<data><configure MemoryName="ufs" MaxPayloadSizeToTargetInBytes="0"
verbose="0" ZLPAwareHost="1" SkipStorageInit="0"/></data>

In simulated mode "remote" target can't propose different size, so
we just don't re-send configure packet.
Move the check for simulation mode to prevent sending additional
configure packets with the attribute MaxPayloadSizeToTargetInBytes=0.

Also change DIGEST_TABLE.bin sha256 hash to
a05e1124edbe34dc504a327544fb66572591353dc3fa25e6e7eafbe4803e63e0,
as amount of packets supposed to be sent to the target changed.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 14:26:14 +02:00
Igor Opaniuk
62464e4ab6 firehose: try to obtain a status when usb write fails
In some cases (for instance, in VIP mode), the Firehose programmer can
report an additional error code before stalling and can provide
valuable information about the type of error that occurred.

For example, when digest verification fails, Firehose programmer provides
additional log messages before stalling:

<data>
<log value="ERROR: Hash of data doesn't match the expected hash 179" />
</data>
<data>
<log value="INFO: Expected hash (32)" /></data>
<data>
<log value="INFO: 30 E1 49 55 EB F1 35 22 66 ..." /></data>
<data>
<log value="INFO: Calculated hash (32)" /></data>
<data>
<log value="INFO: AE BA 2E DE 99 FA 44 30 E4 ... " /></data>
...
</xml>

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 14:26:14 +02:00
Igor Opaniuk
54da7531ea README: extend existing readme
Convert the existing README to Markdown format and expand it with build
instructions and usage examples.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-23 13:33:16 -05:00
Igor Opaniuk
4d612bc25b github: add Markdown lint action
Add Markdown linter invocation for new pull requests for README.md.
This is using existing GitHub action from [1].

[1] https://github.com/DavidAnson/markdownlint-cli2-action
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-23 13:33:16 -05:00
Igor Opaniuk
cdcdc51a3d checkpatch: address all obvious issues
Address all obvious coding style issues caught by checkpatch.pl tool.
sha2.c and sha2.h were kept as there are.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-21 21:32:25 +02:00
Igor Opaniuk
6c0fbcce08 tests: add initial test set
Add tests make target and a simple test that executes qdl in dry-run mode
for a synthetic reference FLAT build with VIP table generation.

The FLAT build contains:
- patch0.xml
- patch1.xml
- rawprogram0.xml
- rawprogram1.xml

All binaries that these XML files point to are filled with zeros, generated
during github action  execution.

Tests ensures that the table is generated correctly by comparing
calculated and expected SHA256 hashes of DigestToSign.bin file.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-20 11:51:49 +02:00
Dmitry Baryshkov
ad123a9531 Merge pull request #112 from igoropaniuk/checkpatch_check
github: add checkpatch action
2025-06-16 12:12:36 +03:00
Igor Opaniuk
81da98bc8a github: add checkpatch action
Add checkpatch.pl invocation for new pull requests. This is using
existing GitHub action from [1].

[1] https://github.com/webispy/checkpatch-action
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-16 09:41:10 +02:00
Dmitry Baryshkov
4bb672f00f Merge pull request #111 from igoropaniuk/spdx_licenses
qdl: add SPDX license identifiers
2025-06-13 17:46:56 +03:00
Igor Opaniuk
52cb41f0d7 qdl: add SPDX license identifiers
Add SPDX-License-Identifier line to each source file that
contains license text. More details about SPDX license identifiers
can be found at [1].

The scancode-toolkit [2] was used to match license text to the correct
SPDX-License-Identifier:
$ scancode --license --copyright --html scancode_result.html ./

[1] https://spdx.org/licenses/
[2] https://github.com/nexB/scancode-toolkit
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-13 16:27:47 +02:00
Dmitry Baryshkov
cc55fda4b2 Merge pull request #108 from igoropaniuk/vip_table_generation
VIP table generation
2025-06-13 14:43:48 +03:00
Igor Opaniuk
4ed250c184 qdl: add support for vip table of digests generation
Add support for Digests Table generation for Validated Image
Programming (VIP), which is activated when Secure Boot is enabled
on the target. VIP controls which packets are allowed to be issued to
the target. Controlling the packets that can be sent to the target is
done through hashing. The target applies a hashing function to all
received data, comparing the resulting hash digest against an existing
digest table in memory. If the calculated hash digest matches the next
entry in the table, the packet (data or command) is accepted; otherwise,
the packet is rejected, and the target halts.

This change introduces logic for VIP table generation.
In the current VIP design the first signed hash table can be a
maximum of 8 KB. Considering that it must be in MBN format, and in
addition to the raw hash table, it also includes an MBN header,
a signature, and certificates, the number of hash digests it can
contain is limited to 54 hashes (a 40-byte MBN header +
a 1696-byte hash table + a 256-byte signature + 6144 bytes of certificates).
All hashes left are stored in the additional ChainedTableOfDigests<n>.bin
files.

To generate table of digests run QDL with --create-digests param,
providing a path to store VIP tables.

As a result 3 types of files are generated:
- DIGEST_TABLE.bin - contains the SHA256 table of digests for all firehose
  packets to be sent to the target. It is an intermediary table and is
  used only for the subsequent generation of "DigestsToSign.bin" and
  "ChainedTableOfDigests.bin" files. It is not used by QDL for VIP
  programming.

- DigestsToSign.bin - first 53 digests + digest of ChainedTableOfDigests.bin.
  This file has to be converted to MBN format and then signed with sectools:

  $ sectools mbn-tool generate --data DigestsToSign.bin --mbn-version 6
    --outfile DigestsToSign.bin.mbn
  $ sectools secure-image --sign DigestsToSign.bin.mbn --image-id=VIP

  Please check the security profile for your SoC to determine which version of
  the MBN format should be used.

- ChainedTableOfDigests<n>.bin - contains left digests, split on
  multiple files with 255 digests + appended hash of next table.

For example, for 400 packets supposed to be sent to the target, these files
will be generated (all digests are 32 bytes in size):

DIGEST_TABLE.bin
 _____________
| Digest 0    |
| Digest 1    |
| etc.        |
|             |
| Digest 399  |
|_____________|

DigestsTableToSign.bin  ChainedTableOfDigests0.bin  ChainedTableOfDigests1.bin
 ___________________       ___________________       ____________
| Digest 0          |     | Digest 53         |     | Digest 308 |
| Digest 1          |     | Digest 54         |     | Digest 309 |
| etc.              |     | etc.              |     | etc.       |
| Digest 52         |     | Digest 307        |     | Digest 399 |
| Next table digest |     | Next table digest |     |____________|
|___________________|     |___________________|

When QDL is executed with --debug parameter, it will also report
Firehose packet SHA-256 hashes, for example:

FIREHOSE WRITE: <?xml version="1.0"?>
<data><patch SECTOR_SIZE_IN_BYTES="4096" byte_offset="72" filename="DISK"
physical_partition_number="5" size_in_bytes="8"
start_sector="NUM_DISK_SECTORS-1" value="NUM_DISK_SECTORS-5."/></data>

FIREHOSE PACKET SHA256: a27b1459042ea36f654c5eed795730bf73ce37ce5e92e204fe06833e5e5e1749

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-10 20:36:52 +02:00
Dmitry Baryshkov
5db7794e9f Merge pull request #106 from Henry-ZHR/master
Include stdlib in usb.c
2025-05-26 16:30:01 +03:00
Igor Opaniuk
824d4c067e qdl: fix identation issue in QDL_DEVICE_TYPE
Fix identation issue in QDL_DEVICE_TYPE enum definition.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-05-25 09:31:11 +02:00
Igor Opaniuk
ec0e19f068 sha2: add implementation of the sha256 digest algo
Add a minimal implementation of the SHA-256 digest algorithm.
This implementation is pulled from the OpenBSD project, and [1] [2]
were used as a base.

[1] https://github.com/openbsd/src/blob/master/lib/libc/hash/sha2.c
[2] https://github.com/openbsd/src/blob/master/include/sha2.h

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-05-25 09:31:11 +02:00
Igor Opaniuk
4e944d29da firehose: add debug output for raw packets
Add detailed output for binary raw packets sent to the target,
displaying the filename and size.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-05-25 09:31:07 +02:00