186 Commits
v1.0 ... v2.2

Author SHA1 Message Date
Julien Vanier
a601db1868 github: update libxml DLL bundled with Windows binary
Include new version of libxml DLL in Windows CI build.

Signed-off-by: Julien Vanier <julien@particle.io>
2025-09-08 14:16:39 -05:00
Bjorn Andersson
29f623bd8c sparse: Clean up endianness and chunk type signedness
The sparse image format is defined in little endian, not in network
order, so we should not invoke ntohs()/ntohl() when reading them.
Further, the various constants are defined in host order, so we
shouldn't ntohs()/ntohl() them either.

This also implies that the code only works for little endian host
systems today.

Drop all the ntohs()/ntohl() conversions for now, to clean out the
incorrect conversions. The task to convert from little to host is left
as an exercise for the future.

While rewriting sparse_chunk_header_parse() the large if statement is
swapped for a select, to improve readability with a single successful
exit at the end and scattered exit returns throughout.

Fixes: 02c008adfd ("add support sparse attribute")
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2025-08-28 10:42:08 -05:00
Bjorn Andersson
a83406f21b sparse: Handle larger FILL and DONT_CARE chunks
The unsparsed chunk size is expressed in units of blk_sz. For RAW chunks
this is then limited to (just under) 32-bits due to the total_sz
(sparsed chunk size), but FILL and DONT_CARE can be much bigger.

But doing the size calculation on the 32-bit integers overflows and any
upper bits are lost, and the unsparsed result is wrong. So, switch this
to 64-bit instead.

It's unclear what happens if we pass a larger num_sectors to the
programmer, so this limitation is left, and checked for.

Fixes: 02c008adfd ("add support sparse attribute")
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2025-08-28 10:42:08 -05:00
Bjorn Andersson
739b1ad4db sparse: Handle larger-than-32bit sparse images
When the sparse image parser finds a RAW chunk, it queries the current
file offset in the sparse image and store this for the programming
phase. But the offset is stored in a 32-bit unsigned int, so when the
sparse image passes 4GB the program entries start to refer to the wrong
data.

Split the fill_value and offset into dedicated fields and give them both
their specific type, to avoid any confusion related to the size of these
data types.

Fixes: 02c008adfd ("add support sparse attribute")
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2025-08-28 10:42:08 -05:00
Sam Freund
cd32723503 Fix linux command to install libusb
Signed-off-by: Sam Freund <techguy763@gmail.com>
2025-07-04 15:02:54 +02:00
Igor Opaniuk
9e5195cbe1 sahara: fix memory leak
Fix memory leak, buffer have to be freed if file is not opened
successfully in sahara_debug64_one().

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-30 14:46:17 +02:00
Bjorn Andersson
ce6faee104 Merge pull request #118 from igoropaniuk/readme_update
Readme update + cosmetic improvements
2025-06-26 15:32:35 -05:00
Bjorn Andersson
a9deec3349 Merge branch 'bmx666-sparse'
Manually merge pull request #37 in order to fix the outstanding
checkpatch SPDX warning.
2025-06-26 15:26:36 -05:00
Maxim Paymushkin
02c008adfd add support sparse attribute
Signed-off-by: Maxim Paymushkin <maxim.paymushkin.development@gmail.com>
2025-06-26 13:19:21 +02:00
Igor Opaniuk
3250ce0026 README: add details about contribution and license
1. Add build/license badges.
2. Add details about contribution workflow and "make check-cached"
   usage.
3. Fix make cmd description for Windows.
4. Add details about running tests.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-25 15:42:39 +02:00
Igor Opaniuk
228ab33af8 make: simplify check-cached target
Simplify "check-cached" target, as the previous sometimes
provides wrong results.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-25 15:27:35 +02:00
Maxim Paymushkin
4288cebfdb program: add sparse attribute
Signed-off-by: Maxim Paymushkin <maxim.paymushkin.development@gmail.com>
2025-06-25 01:30:24 +02:00
Maxim Paymushkin
7447251b25 util: add attr_as_bool
Signed-off-by: Maxim Paymushkin <maxim.paymushkin.development@gmail.com>
2025-06-25 01:30:19 +02:00
Bjorn Andersson
80b45a99fe Merge pull request #116 from igoropaniuk/checkpatch_rework
Checkpatch exceptions and rework
2025-06-24 16:36:46 -05:00
Igor Opaniuk
25562d208d qdl: move MIN and ROUND_UP macros
Move MIN and ROUND_UP macros to avoid code duplication.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 20:15:20 +02:00
Igor Opaniuk
d48d852ca2 makefile: add check and check-cached targets
`check` target runs checkpatch.pl on all sources files.
`check-cached` target runs checkpatch.pl on staged changes.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 20:15:20 +02:00
Igor Opaniuk
ec418a144f spdx: add missing license identifiers
Add missing SPDX license identifiers to source files.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 20:15:20 +02:00
Igor Opaniuk
3e5426d5cb program: address checkpatch issues
WARNING: Comparisons should place the constant on the right side of the test
if (NULL != xmlGetProp(node, (xmlChar *)"last_sector")) {

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 20:15:20 +02:00
Igor Opaniuk
03560e9e04 vip: address checkpatch issues
CHECK: Please use a blank line after function/struct/union/enum declarations
+};

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 20:15:20 +02:00
Igor Opaniuk
adf906c646 ux: address checkpatch issues
CHECK: Macro argument reuse 'x' - possible side-effects?
+#define MIN(x, y) ((x) < (y) ? (x) : (y))

CHECK: Macro argument reuse 'y' - possible side-effects?
+#define MIN(x, y) ((x) < (y) ? (x) : (y))

CHECK: line length of 167 exceeds 120 columns
+static const char * const progress_hashes = "########################################################################################################################";

CHECK: line length of 167 exceeds 120 columns
+static const char * const progress_dashes = "------------------------------------------------------------------------------------------------------------------------";

WARNING: please, no spaces at the start of a line
+    CONSOLE_SCREEN_BUFFER_INFO csbi;$

WARNING: please, no spaces at the start of a line
+    HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);$

WARNING: please, no spaces at the start of a line
+    if (GetConsoleScreenBufferInfo(stdoutHandle, &csbi)) {$

WARNING: suspect code indent for conditional statements (4, 16)
+    if (GetConsoleScreenBufferInfo(stdoutHandle, &csbi)) {
+		columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;

WARNING: please, no spaces at the start of a line
+    }$

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 20:15:15 +02:00
Igor Opaniuk
67472bf750 qdl: address checkpatch issues
CHECK: Macro argument 'typecast' may be better as '(typecast)' to

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 20:00:13 +02:00
Igor Opaniuk
cc4dced2f8 sahara: address checkpatch issues
CHECK: Macro argument reuse 'x' - possible side-effects?
+#define MIN(x, y) ((x) < (y) ? (x) : (y))

CHECK: Macro argument reuse 'y' - possible side-effects?
+#define MIN(x, y) ((x) < (y) ? (x) : (y))

CHECK: line length of 123 exceeds 120 columns
+		ux_debug("%-2d: type 0x%" PRIx64 " address: 0x%" PRIx64 " length: 0x%" PRIx64 " region: %s filename: %s\

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 19:58:25 +02:00
Igor Opaniuk
e46302830c util: address checkpatch issues
CHECK: Macro argument reuse 'x' - possible side-effects?
+#define MIN(x, y) ((x) < (y) ? (x) : (y))

CHECK: Macro argument reuse 'y' - possible side-effects?
+#define MIN(x, y) ((x) < (y) ? (x) : (y))

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 19:58:25 +02:00
Igor Opaniuk
a79ccefb2e sim: address checkpatch issues
Address these issues reported by checkpatch.pl script:

WARNING: void function return statements are not generally useful
+	return;
+}

WARNING: void function return statements are not generally useful
+	return;
+}

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 19:58:25 +02:00
Igor Opaniuk
fbb965174d ufs: address checkpatch issues
Address these issues reported by checkpatch.pl:
CHECK: Alignment should match open parenthesis
+int ufs_provisioning_execute(struct qdl_device *qdl,
+	int (*apply_ufs_common)(struct qdl_device *qdl, struct ufs_common *ufs),

CHECK: line length of 133 exceeds 120 columns
+	result->bWriteBoosterBufferPreserveUserSpaceEn = !!attr_as_unsigned(node, "bWriteBoosterBufferPreserveUserSpaceEn", &errors);

CHECK: Please don't use multiple blank lines

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 19:58:25 +02:00
Igor Opaniuk
eab45794d2 firehose: address checkpatch issues
Address this checkpatch issue:
CHECK: line length of 136 exceeds 120 columns
+		xml_setpropf(node_to_send, "bWriteBoosterBufferPreserveUserSpaceEn", "%d", ufs->bWriteBoosterBufferPreserveUserSpaceEn);

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-06-24 19:58:25 +02:00
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
Henry-ZHR
77df84fa12 Include stdlib in usb.c
As malloc is used

Signed-off-by: Henry-ZHR <henry-zhr@qq.com>
2025-05-15 14:50:29 +08:00
Igor Opaniuk
672abb1e81 qdl: add support for dry run execution
This mode assists in validating the `rawprogram_.xml` and `patch_.xml`
files, as well as the Firehose commands that are expected to be sent
to the Firehose programmer.

Dry run implementation is also expected to be extended for
the Digests Table generation required for Firehose Validated Image
Programming (VIP).

Example of usage:
$ qdl --dry-run --serial=0AA94EFD --debug prog_firehose_ddr.elf rawprogram*.xml patch*.xml
qdl version v2.1-24-g30ac3a8-dirty
This is a dry-run execution of QDL. No actual flashing has been performed
waiting for programmer...
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>

accepted max payload size: 0
FIREHOSE WRITE: <?xml version="1.0"?>
<data><program SECTOR_SIZE_IN_BYTES="4096" num_partition_sectors="131072"
physical_partition_number="0" start_sector="6" filename="efi.bin"/></data>

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-05-15 02:41:08 +02:00
Igor Opaniuk
f066304676 qdl: decouple transport logic
Decouple the flashing logic from the underlying type of communication.
This is needed for introducing simulation mode, where no real flashing is
performed, but firehose packets are used for other tasks, like
VIP table generation.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-05-15 02:41:08 +02:00
Dmitry Baryshkov
fde56c8993 Merge pull request #99 from juniskane/qcm6490_pr
usb: add new USB pid 0x901d for Qualcomm QCM6490
2025-05-14 21:45:00 +03:00
Dmitry Baryshkov
1ec12f6a1f Merge pull request #101 from monkbroc/erase-all
Allow erasing all storage types
2025-05-14 21:44:02 +03:00
Dmitry Baryshkov
c856721827 Merge pull request #103 from igoropaniuk/allow_fusing
qdl: introduce allow-fusing parameter
2025-05-14 02:33:01 +03:00
Dmitry Baryshkov
0b6b9e3b78 Merge pull request #102 from igoropaniuk/sahara_warning_fix
sahara: fix ignoring return value warning
2025-05-14 02:32:46 +03:00
Igor Opaniuk
328e06962b qdl: introduce allow-fusing parameter
Introduce the --allow-fusing parameter, which must be explicitly set
if the "secdata" partition is programmed, as it will lead to irreversible
changes (fuses will be blown during the next boot).

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-05-13 14:37:05 +02:00
Igor Opaniuk
172c3c257c program: refactor program_find_bootable_partition
Split the implementation of the program_find_bootable_partition() function
into two functions. One of these should be a generic program_find_partition()
function that can be used to search for a specific program struct in the
programs linked list.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-05-13 14:33:27 +02:00
Igor Opaniuk
8a996e5fed sahara: fix ignoring return value warning
Fix build warning in sahara protocol implementation:
sahara.c: In function ‘sahara_debug64_one’:
sahara.c:348:25: warning: ignoring return value of ‘write’
      declared with attribute ‘warn_unused_result’ [-Wunused-result]
  348 |                         write(fd, buf, n);
      |                         ^~~~~~~~~~~~~~~~~

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2025-05-13 14:02:51 +02:00
Dmitry Baryshkov
3ed79bef47 Merge pull request #105 from monkbroc/windows-build
Windows build
2025-05-07 17:12:09 +03:00
Julien Vanier
ccfa1fe073 Enable additional platforms in CI
Add Linux arm64, Mac Intel and Windows arm64 to the CI build. GitHub Actions runners for those platforms are available for OSS repos for free.

Signed-off-by: Julien Vanier <jvanier@gmail.com>
2025-05-06 10:31:59 -04:00
Julien Vanier
f87efad54b Implement err functions on Windows
Implement a portable version of err, errx, warn, warnx for Windows.

Signed-off-by: Julien Vanier <jvanier@gmail.com>
2025-05-02 19:00:09 -04:00
Julien Vanier
c07419cb81 Open files in binary mode on Windows
Data files must be opened in binary mode on Windows to avoid EOF being reported early when null bytes are encountered.

Signed-off-by: Julien Vanier <jvanier@gmail.com>
2025-05-02 19:00:09 -04:00
Julien Vanier
6867a75063 Remove workers not supported on free GitHub Actions
GitHub Actions doesn't provide workers for Ubuntu arm64 or Mac x64. A paid plan with hosted runners is necessary for those architectures.

Signed-off-by: Julien Vanier <jvanier@gmail.com>
2025-05-02 19:00:09 -04:00
Julien Vanier
c69d9adc76 Compile on Windows in GitHub Actions and save build artifacts
Compile for Linux x64 and arm64, Mac x64 and arm64 and Windows x64 on GitHub Actions. Upload binaries and required libraries for testing on those systems.

Signed-off-by: Julien Vanier <jvanier@gmail.com>
2025-05-02 19:00:09 -04:00
Julien Vanier
b3dccab6a6 Add Windows compatibility
Make build compatible with Windows using MSYS2 MINGW64 compiler. Add a small compatibility file for functions that don't exist in MINGW64.

Signed-off-by: Julien Vanier <jvanier@gmail.com>
2025-05-02 19:00:09 -04:00
Julien Vanier
3a7c00b931 Use ux_info for firehose success
Report successful read and program with ux_info instead of ux_err. This matches firehose_erase

Signed-off-by: Julien Vanier <jvanier@gmail.com>
2025-05-02 16:01:10 -04:00
Julien Vanier
f73656237d Don't fail the last firehose read when the number of bytes read is 0
On Windows, the last firehose read may return 0. Don't fail a firehose read in that situation.

Signed-off-by: Julien Vanier <jvanier@gmail.com>
2025-05-02 09:54:51 -04:00
Julien Vanier
33a2f151a6 Allow erasing all storage types
Erase operations are currently only supported on devices using NAND storage. With this change, erase operations also work on devices with UFS storage.

Signed-off-by: Julien Vanier <julien@particle.io>
2025-05-02 08:12:23 -04:00
Dmitry Baryshkov
136f8e2158 CI: disable Ubuntu 20.04 builds
Ubuntu 20.04 has been disabled on GitHub. Stop using it for building
images.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2025-05-01 19:04:03 +02:00
Dmitry Baryshkov
30ac3a8abc Merge pull request #96 from lumag/version-fix
make: don't rebuild util.o (and dependencies) unnecessary
2025-03-19 16:53:14 +02:00
Dmitry Baryshkov
ab17b2e78d make: don't rebuild util.o (and dependencies) unnecessary
Using fake target name forces make to rebuild all targets that depend on
it. Properly specify version.h as a target name and use double-colon to
let make know that it's a special build target.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2025-03-19 16:02:11 +02:00
Juha Niskanen
c9abbe7aba usb: add new USB pid 0x901d for Qualcomm QCM6490
Signed-off-by: Juha Niskanen <juniskane@gmail.com>
2025-03-16 13:11:35 +02:00
Christopher Obbard
cfdb938111 Use provided VERSION argument before calling git
In some environments where git isn't present (e.g. in Debian pbuilder),
building qdl fails due. Fix the order such that we check if VERSION is
provided first & use that, only if VERSION is not provided then call
git directly to get the version.

Signed-off-by: Christopher Obbard <christopher.obbard@linaro.org>
2025-02-07 14:18:01 -06:00
Christopher Obbard
21966c61d0 Use VERSION instead of GITREF
The variable name VERSION is more descriptive of the code than GITREF.
Use VERSION instead.

Signed-off-by: Christopher Obbard <christopher.obbard@linaro.org>
2025-02-07 14:18:01 -06:00
Christopher Obbard
2872a8ea62 Fix version.h generation
Currently the build fails when parallelised with:

  make[1]: *** No rule to make target 'version.h', needed by 'util.o'.  Stop.

Fix the name of the Makefile dependency to fix the build error.

Fixes: https://github.com/linux-msm/qdl/issues/91
Closes: https://github.com/linux-msm/qdl/pull/92
Signed-off-by: Christopher Obbard <christopher.obbard@linaro.org>
2025-02-07 14:18:01 -06:00
Nicolas Dechesne
ad320a1a66 version: set to 'unknown-version' if unable to use git describe
If for any reasons git describe does not work (git not installed, or
not running from a git workspace), set VERSION to unknown-version.

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@oss.qualcomm.com>
2025-01-21 11:11:13 -06:00
Nicolas Dechesne
8718752d81 ramdump: display version information
* add --version CLI option
* dislay version when running in --debug mode

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@oss.qualcomm.com>
2025-01-21 11:11:13 -06:00
Nicolas Dechesne
20fab24ee0 ks: display version information
* add --version CLI option
* dislay version when running in --debug mode

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@oss.qualcomm.com>
2025-01-21 11:11:13 -06:00
Nicolas Dechesne
4800d4afc2 ks: add --debug option
It was missing , it will be used to show the version when running in
debug mode.

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@oss.qualcomm.com>
2025-01-21 11:11:13 -06:00
Nicolas Dechesne
e6469d9748 qdl: display version information
* add --version CLI option
* dislay version when running in --debug mode

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@oss.qualcomm.com>
2025-01-21 11:11:13 -06:00
Nicolas Dechesne
cc584d4560 Add infrastructure to support version information
In order to implement a proper versioning scheme, let's generate a
version.h file that defines VERSION variable built from git
workspace. The version format will be

v<MAJOR>.<MINOR>-<COMMIT##>-<SHA1>

Where:
* MAJOR and MINOR are from the most recent tag
* COMMIT## is the number of commits since last tag, to ensure
  incremental numbering
* SHA1 is an abbreviated representation of the actual commit SHA.

This requires building from a git workspace, with we are effectively
calling 'git describe' during the build.

We then define print_version() utility function to be used by all
programs.

Ensure that util.c depends on version.h and that we only update
version.h timestamps when the version actually changes to avoid
unnecessary rebuilds.

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@oss.qualcomm.com>
2025-01-21 11:11:13 -06:00
Nicolas Dechesne
a8e3f661d2 firehose: change error message to info for multiple boot partition
On some platforms, we support Boot LUN redundancy, with the boot
partitions duplicated on more than 1 LUN. Only 1 LUN can be boot
active at any time, but the platform can switch on reboot in case of
corruption. As such, when flashing a full system, we end up flashing
boot partition on several LUN, and the "first" LUN with SBL or XBL
will be used as the initial/primary boot device for the
setbootablestoragedrive command.

Up until this commit we displayed an error message in this situation,
but let's turn that into an ux_info() log instead, since it's not an
error.

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@oss.qualcomm.com>
2025-01-16 15:40:47 -06:00
Nicolas Dechesne
7b5d5da48d firehose: do not display 'no boot partition found' message
It is a valid use case to flash a single partition (such as CDT) with
QDL. In such a case when we are not flashing the entire image, we
effectively are not flashing any 'boot' partition (SBL, XBL, ...), and
we don't need to send the setbootablestoragedrive command to the
programmer. Currently we display the 'no boot partition found' message
which is confusing for users, as it looks like an error message even
though it's not. Let's turn this message into a debug log message
instead.

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@oss.qualcomm.com>
2025-01-16 15:40:47 -06:00
Bjorn Andersson
8c32a74086 ux: Introduce progress indicator
Not providing any user feedback during flashing is not very user
friendly, in particular when, in some situations, it can take minutes to
flash very large files.

Introduce a progress bar for the flashing and patching steps to provide
such feedback to the user, when stdout is determined to be a terminal of
sufficient size (i.e. tools programmatically invoking qdl should see no
difference).

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-12-20 11:18:34 -06:00
Bjorn Andersson
a0f977935f ux: Improve log printouts
QDL uses a few different styles when printing logs for the user,
with some inconsistencies, some errors, and some room for improvement.

Revisit all the ux_xyz() invocations to clean up the output from the
tool.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-12-20 11:18:34 -06:00
Bjorn Andersson
0e08e852bf ux: Introduce user experience wrappers
Rather than sprinkling the user experience decisions across the
implementation with prints to stdout, stderr, conditional checks for
qdl_debug etc, consolidate these into a single set of ux wrappers.

Transition all callers of printf() and fprintf() to these new wrappers,
without changing the level of content of the printouts.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-12-20 11:18:34 -06:00
Bjorn Andersson
321e776cb7 firehose: Handle multiple primary bootloaders
Builds with multiple copies of the primary bootloader does not make
sense, but after successfully flashing all the partitions of such build
it makes more sense to make one of them bootable, at least more than
skipping the step and saying that none was found.

Pick the first found primary bootloader and warn the user about the
situation.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-12-20 10:37:08 -06:00
Bjorn Andersson
23c84163aa firehose: Avoid leaking xml properties
In a few places in firehose.c the memory returned from xmlGetProp() is
leaked. Avoid this by freeing it.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-12-17 14:38:49 -06:00
Bjorn Andersson
aa44721fe8 sahara: Avoid closing invalid fd
In the event that no ramdump_path is provided to sahara_run() the
ramdump_dir will remain -1. For good hygiene avoid calling close() on
this invalid file descriptor.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-12-17 14:38:49 -06:00
Bjorn Andersson
8adc9f3192 sahara: Correct size of hello packets
Valgrind correctly reports that the write of 0x30 bytes accesses
uninitialized stack space. Pad the Sahara HELLO request and response
with the expected "reserved" entries to reach the defined 0x30 bytes to
avoid sending random stack content to the device.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-12-17 14:38:49 -06:00
Bjorn Andersson
ceddd78c9d util: Avoid memory leaks in xml parsing helpers
The XML parsing helpers turns libxml strings into standard C-types and
leaks the libxml memory. Fix this by freeing the libxml strings once
they are accessed.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-12-17 14:38:49 -06:00
Bjorn Andersson
0214cbd3b6 firehose: Free the program scratch buffer
For each <program/>  entry int he list, a scratch buffer of "max payload
size" is allocated, and lost. Free this memory instead.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-12-17 14:38:49 -06:00
Bjorn Andersson
b121a92752 program/patch: Free program and patch objects on exit
Continuing the journey to make QDL not leak any memory on a successful
run, introduce  operations to free the program and patch objects on
exit.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-12-17 14:38:49 -06:00
Bjorn Andersson
6fc456da62 usb: Release allocated resources
Every time the USB code attempts to identify and possibly open the EDL
USB device, the libusb device descriptor-object is leaked.

While at it, also introduce qdl_close() to clean up the overall state,
in order to approach not leaking memory in a clean QDL run.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-12-17 14:38:49 -06:00
Nicolas Dechesne
ad13228e6a ufs: add support for UFS WriteBooster feature
WriteBooster is a new feature added in UFS3.1. There are new
paramaters in the UFS header config. Trying to provision a 3.1+ device
without these parameters fail.

Also make sure that we don't send them on older devices.

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@oss.qualcomm.com>
2024-12-12 07:56:49 -06:00
Nicolas Dechesne
fa070e81b4 qdl: fixup usage function
--serial and --out-chunk-size are parameters which were added recently
  to qdl, but the print_usage() function was not updated accordingly.

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@oss.qualcomm.com>
2024-11-26 23:31:25 -06:00
Nicolas Dechesne
f63c4df679 .github: use actions/checkout v4
v2 has been deprecated for a while now, and generates a bunch of
warnings each time an action is executed.

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@oss.qualcomm.com>
2024-11-05 18:16:52 -06:00
Bjorn Andersson
b068cc58d9 firehose: Allow bConfigDescrLock to be passed as 1
During the introduction of UFS provisioning, the author left behind an
additional safety measure of forcing the user to explicitly modify the
source and recompile QDL in order to be able to lock the provisioning,
to avoid users accidentally doing so.

While it does reduce the risk of irreversable mistakes, it's not
suitable when QDL is distributed as a binary - and the user already need
to set bConfigDescrLock both in provided XML files and on command line.

So, let's remove the safety net...

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
2024-10-10 15:17:05 +02:00
Milosz Wasilewski
f8fae69796 qdl: firehose: program: fail on missing file
When parsing XML files the specified binary to be flashed may not be
present. The default behaviour of QDL is to ignore missing file. This is
sometimes undesireble.

This patch changes the default behaviour. If the file to be flashed
can't be found qdl will exit with error. An optional flag --allow-missing
is introduced. It will allow to skip missing files during flashing procedure.
Default value of the flag is false.

Signed-off-by: Milosz Wasilewski <quic_mwasilew@quicinc.com>
2024-10-01 15:19:26 +02:00
Bjorn Andersson
cbd46184d3 usb: Allow overriding bulk write size and increase default
Since commit 760b3dffb0 ("qdl: Rework qdl_write to limit write sizes
to out_maxpktsize") outgoing transfers has been chunked into blocks of
wMaxPacketSize.

As reported by Wiktor Drewniak, Maksim Paimushkin, and Luca Weiss in [1]
there's huge benefits to be found in reverting this change, but out of
caution the limit was untouched.

With the transition to libusb, the throughput dropped another ~15% on my
machine. The numbers for HighSpeed and SuperSpeed are also in the same
ballpark.

With SuperSpeed, benchmarking of different chunk sizes in the megabyte
range shows improvement over these numbers in the range of 15-20x on the
same machine/board combination.

The bug report related to the reduction in size describes a host machine
running out of swiotlb, from the fact that we requested 1MB physically
contiguous memory. It's unclear if attempts was made to correct the
kernel's behavior. libusb does inquiry the capabilities of the kernel
and will split the buffer and submitting multiple URBs at once, as
needed.  While no definitive guidance has been found, multiple sources
seems to recommend passing 1-2MB of buffer to libusb at a time.  So,
let's move the default chunk size back up to 1MB and hope that libusb
resolves the reported problem.

Additionally, introduce a new option --out-chunk-size, which allow the
user to override the chunk size. This would allow any user to reduce the
size if needed, but also allow the value to be increased as needed.

[1] https://github.com/linux-msm/qdl/pull/39

Reported-by: Wiktor Drewniak
Reported-by: Maksim Paimushkin
Reported-by: Luca Weiss
Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-06-10 10:33:19 -05:00
Collin
a1cd535439 qdl: Add support for <read> operations
Being able to read the content of the flash is useful for e.g. making
backups or for testing purposes, add support for a new type of XML
containing <read> tags and execute these operations after
flashing and patching.

[bjorn: Rebased on master, updated commit message, moved read_op_exec after patching]
Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-06-10 10:33:05 -05:00
Bjorn Andersson
a60d45c3b7 usb: Correct libusb timeout handling
The documentation for libusb_bulk_transfer() specifies that in the event
that the read or write request is split into multiple chunks, some of
these may still be transferred despite a LIBUSB_ERROR_TIMEOUT is
returned.

In the transition to libusb this detail was missed and completed
read transfers are sometimes considred to be timeouts and the data
discarded, obviously resulting in failure to continue.

Consider the "transferred" value in the event of timeout, to avoid this.

Although not yet spotted in testing, the same logic is introduced for
the write path.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-06-07 22:19:40 +02:00
Bjorn Andersson
c647d6d9eb firehose: Always free response xmlDoc
The xmlDoc returned by firehose_response_parse() needs to be freed
regardless of what message it contains.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-06-07 22:10:57 +02:00
Bjorn Andersson
b761963272 firehose: Remove unwanted timeout warning
During boot and following the reset, a firehose_read() is performed to
drain any LOG messages from the device, but as there's no response to be
read these operations runs until the defined timeout happens - at which
time "firehose operation timed out" is printed to stderr, confusing
users to believe an error condition has occurred.

The only operation that not already print an error message is
firehose_reset(), so add this and remove the error print from
firehose_read().

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-06-07 22:10:57 +02:00
Bjorn Andersson
adfdcc6b01 firehose: Clean up return values
firehose_read() uses -errno to denote errors, -1 to represent NAK, 1 to
represent ACK and 0 to represent that we got a LOG and should read
again. This choice is unintuitive and choosing to overload errno and NAK
on the negative value space isn't awesome.

Additionally, firehose_run() does in some cases return -errno and others
-1.

Clean this up by defining ACK and NAK in the non-negative value space
and use the negative value space for errno. Use -EAGAIN to signal that
firehose_read() should make another read attempt.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-06-07 22:10:57 +02:00
Bjorn Andersson
1d8a3fff7d usb: Attempt detaching kernel driver
In the event that the kernel have some other driver attached to the
device the attempt claim of the interface will fail.

Lost in the libusb conversion was a call to USBDEVFS_DISCONNECT to first
detach any such drivers. Reintroduce this by invoking
libusb_detach_kernel_driver().

As with some other libusb functions there are multiple return values
denoting "success", so rely on libusb_claim_interface() to catch the
actual errors.

Reported-by: Maxim Akristiniy
Suggested-by: Maxim Akristiniy
Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-06-07 21:50:57 +02:00
Bjorn Andersson
8b01b6254e ci/build: Build across different Ubuntu variants
The transition to libusb was tested on a few different Linux distros,
but apparently not Ubuntu 20.04, which contains a slightly older version
of the libusb includes.

Add Ubuntu 20.04 as a CI target to catch more such issues, and for good
measure also add 24.04.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-06-05 22:34:22 +02:00
Bjorn Andersson
95be64392f usb: Allow building with older libusb
libusb commit f0cce43f882d ("core: Fix definition and use of enum
libusb_transfer_type") split the types of split transfer type and
endpoint transfer, introducing LIBUSB_ENDPOINT_TRANSFER_TYPE_BULK.

The result is that when building with older libusb, such the one
available on Ubuntu 20.04 the build fails with the following error:

usb.c:84:16: error: ‘LIBUSB_ENDPOINT_TRANSFER_TYPE_BULK’ undeclared (first use in this function); did you mean ‘LIBUSB_TRANSFER_TYPE_BULK’?

Introduce an alias using the preprocessor to make available the new
define when building against the older version of libusb headers.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-06-05 22:34:05 +02:00
Konrad Dybcio
aeb70e0645 firehose: Prevent potential overflow in info print
also fixes the improper format specifier i suppose

CodeQL reports:

Multiplication result may overflow 'unsigned int' before it is converted to 'long'.

Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
2024-05-28 10:50:49 -05:00
Konrad Dybcio
b1ec56fc9e firehose: Fix xml_setpropf format for payload_size
CodeQL reports:

This argument should be of type 'int' but is of type 'unsigned long'.

Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
2024-05-28 10:50:49 -05:00
Ricardo Salveti
fac09b2980 Makefile: prefer append on CFLAGS / LDFLAGS
Append allows an external build system to pass custom cflags/ldflags
to the local build system (make).

Useful with Yocto / OE as additional options can be given besides what
is set with a force set in the Makefile.

Signed-off-by: Ricardo Salveti <ricardo@foundries.io>
2024-05-28 10:49:55 -05:00
Konrad Dybcio
b18bca7d28 ci/codeql: Add required permissions
Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
2024-05-10 18:05:06 +02:00
Bjorn Andersson
ba6b6e5b3a github: Add CodeQL workflow
Add CodeQL workflow to get some code analysis.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-05-10 17:58:28 +02:00
Luca Weiss
0132a8eb5a program: Clean up error handling in program_load
Main difference is cleaning up 'doc' in case of errors.
2024-05-10 17:58:01 +02:00
Luca Weiss
7cc2748c61 program: fail correctly on unrecognized tags
Previously the message would be printed that the tag gets ignored but in
reality the 'errors' variable will still be initialized as -EINVAL so
the if below would return an error.

  [PROGRAM] unrecognized tag "zeroout", ignoring
  qdl: program_load rawprogram0.xml failed

But since we want this qdl to error out on unrecognized tags, modify the
message and make it clear in the code that this is an error path.
2024-05-10 17:58:01 +02:00
Bjorn Andersson
25ce7fad22 usb: Allow selecting board by serial number
When working on a host with multiple boards attached being able to
select a specific board by serial number becomes necessary.

In the EDL USB descriptors a device serial number is available as part
of the iProduct string, so this can be used for comparison.

As libusb requires a handle the libusb_open() needs to be moved into the
loop.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-05-10 17:57:18 +02:00
Bjorn Andersson
37b0d0cf69 usb: Replace USBDEVFS interface with libusb
In order to support selecting board based on serial number the iProduct
field needs to be inspected, with the hand-rolled parsing of the USB
descriptors this becomes cumbersome.

Furthermore the direct use of Linux's USBDEVFS creats an unnecessary
dependency on the host OS being Linux.

It's unclear why libusb wasn't choosen in the first place, perhaps it
relates to the faint memory of 0.1 vs 1.0 packaging issues?

Move to libusb-1.0 in order to resolve these issues, as well as clean up
the code a bit.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-05-10 17:57:18 +02:00
Bjorn Andersson
983ec51d02 github: Introduce build workflow
Build the project across Ubuntu and macOS.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-05-09 23:40:58 +02:00
Bjorn Andersson
5f2f82a526 ramdump: Add support for filtering which segments to extract
The typical ramdump covers the entire DDR, which on modern devices can
be huge. But sometimes one is only interested in one or more specific
segments.

Parse the optional, comma-separated, argument to qdl-ramdump, and use
this to skip not requested segments.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-05-08 18:29:38 +02:00
Bjorn Andersson
2fd923ec97 qdl: Add ramdump support
Expose the newly introduce Sahara implementation for ramdump support to
the user, by introducing the qdl-ramdump utility.

The -o option can be used to specify the output directory, where files
will be stored.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-05-08 18:29:38 +02:00
Bjorn Andersson
5b69b112f5 qdl: Extract USB accessor functions
In preparation for the introduction of a new ramdump utility, extract
out the USB functions.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-05-08 18:29:38 +02:00
Bjorn Andersson
74779c7a77 qdl: Clean up unused include files
With this upcoming extraction of USB accessors, the includes should be
cleaned up. Start by first cleaning up the currently unused ones, to
isolate the changes.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-05-08 18:29:38 +02:00
Bjorn Andersson
a10d2bf57b Makefile: Generate compile_commands.json
Introduce a make target for generating compile_commands.json to feed
clangd and the Language Server Protocol, to gain better editor
integration.

Add the relevant files to .gitignore.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-05-08 18:29:38 +02:00
Bjorn Andersson
7cc077d066 sahara: Add ramdump support
Most devices in non-production mode will upon a fatal software fault
enter a ramdump mode, where Sahara can be used to extract the full
content of DDR (and a few other regions), for post-mortem debugging.

Introduce support for this part of the protocol.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-05-08 18:29:38 +02:00
Bjorn Andersson
7d4020fedd sahara: Add defines for commands and lengths
The Sahara implementation was written without defines for any of the
commands or their sizes, making the code harder than necessary to read.
Improve this by introducing such defines.

Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2024-05-08 18:29:38 +02:00
Quincy Fleming
a629f43428 Fix gcc-14 compile errors 2024-04-09 11:36:05 +02:00
Bjorn Andersson
3b22df2bc7 Fix qdl after kickstart introduction
The introduction of kickstart support made the assumption that the EDL
will request image #0, but this is not the case. Return to the old
behavior of ignoring the image number.

The change also made the assumption that the status in done can be
trusted, but e.g. MSM8916 returns done status of 0 upon successful
fetch, so ignore this value as well in the "single payload" case.
2023-04-11 07:27:00 -05:00
Bjorn Andersson
dbcb6fed63 Merge pull request #38 from danielg4/master
Install ks utility
2023-03-22 10:30:53 -05:00
Daniel Gimpelevich
1acf511839 Install ks utility 2023-02-21 04:55:09 +00:00
SunXinzhao
392394086d qdl: Add a fix for read xml error
When xml has no last_sector, qdl will read xml failed. Add check
to see if last_sector exists
2023-01-31 12:37:16 -06:00
Jeffrey Hugo
bdcf93b4a3 Add ks utility
ks (short for kickstart) is a utility which uses sahara to load images
from the host to a device.  This is intended for "flashless boot"
devices like the Qualcomm Cloud AI 100 which rely on obtaining the
runtime firmware from the host instead of storing it on device.

While ks uses sahara, like qdl, it is different enough that a separate
utility is justified.  ks does not need USB support, instead opting for
simple open()/read()/write() operations.  ks does not need firehose.
The set of program arguments that ks needs is vastly different than the
set that qdl supports.

This initial implementation of ks defines two arguments.  Both are
required, but the image specifier argument can be specified more than
one.

A sample invocation -

ks -p /dev/mhi0_QAIC_SAHARA -s 1:/opt/qti-aic/firmware/fw1.bin -s 2:/opt/qti-aic/firmware/fw2.bin

In this example, ks is instructed to use the /dev/mhi0_QAIC_SAHARA
device node file as the "port" which the device is using for the sahara
protocol.  /opt/qti-aic/firmware/fw1.bin is mapped to id 1, and
/opt/qti-aic/firmware/fw2.bin is mapped to id 2.  If the device requests
image id 1, ks will attempt to open and read
/opt/qti-aic/firmware/fw1.bin to send to the device.  Note that
/opt/qti-aic/firmware/fw1.bin does not need to exist on the filesystem.
If ks cannot access the file (perhaps because it does not exist), then
the device will determine the next action.  This is useful for setting
up a single command in a udev rule that can handle multiple
configurations, such as an optional DDR training process.

Signed-off-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
2023-01-31 12:35:20 -06:00
Jeffrey Hugo
e25c981207 sahara: Add support for multiple images
It is possible for a device to request multiple images over the sahara
protocol.  When the device issues the done response packet, the status
field indicates if the device expects to request additional images.  If
so, the protocol goes back to the start and exchanges hello messages
again.  Also, some images may be optional.  The device may be able to
proceed if the host is unable to satisfy the request.

To support this, we need several changes.

First, we need to use the done response packet status field to decide
if we are done with sahara instead of assuming that based on having
transfered a single image.

Second, we need to reference the image id that the device is requesting
and operate on the correct file.  This is a field in the read data
packet.  Since the device could request more than one image, we need
a mapping of ids to files.  Since different devices could have different
mappings, abstract this mapping into the qdl struct.  When we get a read
request from the device, we need to open the correct file, seek to the
required offset, and provide the requested segment.  The implementation
for this chooses simplicity over performance by avoiding the need to
maintain state of what image is currently requested, and if that has
been accessed before, thus we have an open fd to use which needs to be
cleaned up later.

Since the qdl struct is larger with the mapping table, move it off the
stack and instead make it a static global.  We expect to only need one
instance of it, and this gives us the benifit of zero initializing the
struct for free.  We also move the qdl struct definition into the qdl
header so that it can be shared with a similar implementation in a
future development.

Signed-off-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
2023-01-31 12:35:20 -06:00
Andrew Halaney
a8d10da050 readme: Mention libudev requirement
Without libudev installed you'll get the following build error:

    qdl.c:43:10: fatal error: libudev.h: No such file or directory
       43 | #include <libudev.h>
          |          ^~~~~~~~~~~
    compilation terminated.
    make: *** [<builtin>: qdl.o] Error 1

Mention the ubuntu package that brings it in as well similar to how
libxml2 is mentioned.

Signed-off-by: Andrew Halaney <ajhalaney@gmail.com>
2022-07-18 15:52:54 -05:00
Bjorn Andersson
0fcf944ab5 makefile: Use pkg-config instead of xml2-config
Per user request, use pkg-config instead of xml2-config when generating
cflags and ldflags.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-11-10 09:44:50 -06:00
Jonathan Marek
2021b303a8 firehose: fix >4GB lseek file offsets
The byte offset value for lseek can easily exceed 4GB, cast as off_t to
avoid overflow when converting sectors to bytes for lseek.

(and define _FILE_OFFSET_BITS=64 to fix 32-bit builds too)

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
2021-05-07 10:12:46 -07:00
Jonathan Marek
f02ed6abca firehose: call firehose_reset() in ufs provisioning path
Signed-off-by: Jonathan Marek <jonathan@marek.ca>
2021-05-06 19:07:36 -07:00
Jonathan Marek
2e258d9d56 firehose: drain remaining logs in firehose_reset()
Reset will only complete after all logs have been read.

Note this will result in an expected "qdl: firehose operation timed out"
error when draining the logs.

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
2021-05-06 19:07:36 -07:00
Bjorn Andersson
13681fcb35 firehose: Make "start_sector" a string again
Assumed to be a remnant of early development lead to a recent transition
of "start_sector" from being represented as a string to an integer. But
it turns out that "start_sector" might be an expression, e.g. to write
something at the end of the disk.

So transition back to carry "start_sector" as a string.

Fixes: b6e0ea31d7 ("program: Make start_sector unsigned in")
Reported-by: Julien Robin
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-04-29 10:25:55 -05:00
Dmitry Baryshkov
3c0405c03d qdl: bail out with the sensible error if prog.mbn can not be opened
Rather than failing with the cryptic message, return early if prog.mbn
can not be found.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2021-04-18 21:05:17 -07:00
Jonathan Marek
ec6c8a034e util: allow hexadecimal values for attr_as_unsigned (fix ufs provisioning)
dc61f8f79e broke ufs provisioning by requiring base 10 for unsigned
attributes (provisioning xml have some values in hexadecimal). strtoul()
would return 0 for these values and provisioning would fail strangely.

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
2021-04-15 20:42:17 -07:00
Bjorn Andersson
650b477ca5 firehose: Drain logs on write timeout
On db410c writes sometimes fails becasue the device had more log entries
to read after the <response> and refuses writes until these are drained.

Deal with this by attempting a read when write fails with a timeout.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-04-15 21:52:00 -05:00
Bjorn Andersson
00d93b29f5 firehose: Rework firehose_read
WIth the transition from qcserial to USBFS we no longer receive multiple
messages in a single read, so we can remove the code that decode the
buffer piecemeal.

While reworking this, also introduce a mechanism so that the parsers can
pass values back to the caller of the read.

And modify the timeout handling so that the caller always has to pass a
timeout, and bump the timeouts slightly, as they are all fatal anyways.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-04-15 21:49:16 -05:00
Bjorn Andersson
7f75f17c53 fixup! program: Make start_sector unsigned in 2021-04-15 21:15:36 -05:00
Bjorn Andersson
40df480740 usb: Drop ununsed eot argument to qdl_write
qdl_write() is always called with eot=true, so drop the parameter.

As a length of 0 means we're not entering the loop and we're now always
entering the conditonal block at the end we can remove the first chunk.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-04-15 17:42:06 -05:00
Bjorn Andersson
91e609b611 usb: Drop unwanted debug print
A stray print can sometimes be seen from the udev code, drop it.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-04-15 14:23:49 -05:00
Bjorn Andersson
da8dd7139a program: Introduce erase tag support
NAND based devices comes with a few minor tweaks to the program tag and
an additional erase tag, split the program code and add the handling of
the erase tag.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-04-15 14:22:15 -05:00
Bjorn Andersson
b6e0ea31d7 program: Make start_sector unsigned in
For unknown reasons start_sector was a staring, turn it into an unsigned
integer instead.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-04-15 14:20:41 -05:00
Bjorn Andersson
56076936a6 firehose: Revamp read timeout handling
Remove the dummy sleep and reliance on USB read timeout while waiting
for the firehose payload to launch by rolling our own timeout handling
in firehose_read. While at it extend the firehose program timeouts, to
avoid issues seen when these operations for some reason takes a little
bit longer to return.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-04-15 14:15:43 -05:00
Bjorn Andersson
bead963d33 usb: Recognize SDX55
The SDX55 shows up with bInterfaceProtocol of 17, so allow this to get
past the USB filtering routine.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-04-15 12:00:44 -05:00
John Stultz
760b3dffb0 qdl: Rework qdl_write to limit write sizes to out_maxpktsize
On a number of machines, qdl could cause crashes on the host
system it ran on, due to swiotlb exaustion.

This seems to be due to 1M buffers being used during the writes.

In order to avoid this, rework qdl_write to break up the writes
into out_maxpktsize chunks.

With this patch, I no longer see host crashes when running qdl

Cc: Bjorn Andersson <bjorn.andersson@linaro.org>
Cc: Amit Pundir <amit.pundir@linaro.org>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: dragonboard-aosp@lists.96boards.org
Tested-by: Nicolas Dechesne <nicolas.dechesne@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
[bjorn: Dropped change of max_payload_size]
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-05-03 12:18:25 -07:00
Bjorn Andersson
7623ff5e1e firehose: Wait 3 seconds for payload to boot
The downstream tool has a 3 second delay to allow the firehose payload
to boot. Adding the same makes db820c successfully enter firehose mode.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-04-30 11:27:17 -07:00
Bjorn Andersson
fd48f7ce18 firehose: Lower the initial read timeout
Upon booting the firehose payload some platforms will issue log messages
others won't. Rather than waiting for 10 seconds on the ones that
doesn't wait only for a second.

Hopefully this is long enough, but the firmware synchronization and
handling of incoming log messages should be reviewed further.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-02-27 15:25:34 -08:00
Bjorn Andersson
90d3a6fee6 firehose: Remove unused firehose_nop()
We don't send any NOP requests, so remove this function for now.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-02-27 15:17:52 -08:00
Bjorn Andersson
1c958b2bc2 usb: Silence usb helpers
It's perfectly normal to "poll" for incoming messages, so silence the
warning printout in the usb accessor functions.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-02-27 15:08:02 -08:00
Bjorn Andersson
5ec4f210a0 firehose: Continue reading log entries after response
On db410c the target sends log entries after the response and refuse to
serve any subsequent requests until these are consumed, so continue
reading log entries until we get a timeout.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-02-27 15:06:32 -08:00
Nicolas Dechesne
1ac148c4e6 sahara_run: properly propagate error
We should return in case we haven't reached the end of the Sahara
init, which is when we set done to true. If done is not set to true
before returning from sahara_run() , it means something went wrong.

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@linaro.org>
2019-02-27 15:06:12 -08:00
Bjorn Andersson
8456cb2cf5 program: Correct a/b XBL match
A full build will contain both xbl_a and xbl_b, so matching on the
prefix of "xbl" will find two entries which we consider invalid.
Explicitly search for "xbl_a" instead.

Fixes: 5ea1e20c01 ("program: Match xbl in a/b scenarios")
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-02-27 09:10:12 -08:00
Bjorn Andersson
8589513f65 qdl: Wait for missing EDL device
Add support back for waiting for an EDL device to appear. This is useful
when paired with some automation scripts that introduces "arbitrary"
delays in the process of entering EDL mode.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-01-07 21:20:25 -08:00
Bjorn Andersson
ba86b03391 qdl: Remove debug print for claim return code
The USB claim return code was printed to the console for debug purposes,
remove this.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-01-07 21:05:47 -08:00
Bjorn Andersson
59717efcd4 firehose: Remove unnecessary nop request
The nop was added to mitigate the fact that there's a rather long delay
in the response when sending out the first command. Increasing the write
timeout removes this problem and it's possible to just send the
configure as the first command without issues.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-01-07 21:00:42 -08:00
Bjorn Andersson
5ea1e20c01 program: Match xbl in a/b scenarios
On devices implementing a/b updates the xbl partiiton will be named
xbl_a and xbl_b, extend the match for finding the bootable partition to
support this.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-01-07 16:41:39 -08:00
Bjorn Andersson
826a5cd4fd firehose: Send ZLP after each chunk
It was assumed that we should send all the data following a "program"
request to the device, before sending a ZLP. But on SDM845 it's seen
that not sending a ZLP after each chunk sometimes causes the
communication to stall.

Given that the "program" request already carries the information about
how much data will be transferred there should be no issues with sending
additional ZLPs, so do this.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-01-07 16:36:54 -08:00
Bjorn Andersson
8f7987f756 qdl: Communicate using USBFS instead of qcserial
On some newer platforms the device ignore the configure request to
disable ZLP, causing the Firehose program request to stall, when the
device is waiting for a ZLP to end a transfer.

Mitigate this by circumventing the qcserial driver and drive the USB
traffic directly using USBFS. The tool will attempt to detach qcserial
from the device, in case it's already attached, so no changes are needed
in the kernel or system configuration.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2019-01-07 16:36:50 -08:00
Laxman
b338928519 firehose: support for emmc storage
Added qdl support for emmc storage on platforms with UFS support.  Use
option --s emmc or ufs as a argument to qdl command, if not specified
any option the default storage would be ufs

Tested-by: Nicolas Dechesne <nicolas.dechesne@linaro.org>
Signed-off-by: Laxman <itsmelaxman91@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-11-07 21:33:44 -08:00
Daniel Kutik
dc61f8f79e Moved attr_as_unsigned and attr_as_string to util
Moved the two functions to util.c to remove duplicate code.
The previous error handling in some of the implemenations was
incomplete as it caused qdl to crash.
While the variable errors was incremented we still tried to
return the regular result. Now returning 0/NULL in case of error.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-11-05 09:10:00 -08:00
Daniel Kutik
cfce0beeab program: dropped unused attributes
The attributes size_in_KB, sparse and start_byte_hex
are not used and seem to be optional. Some program
xml files do not always contain them which then causes
qdl to crash. Simply removing the unused attributes
fixes this problem.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-11-05 09:09:36 -08:00
Niklas Cassel
a50ec8047c qdl: fix qdl when building for 32-bit
The sahara protocol specification defines the image field
for a read64 request as 8 bytes.
Use the correct type to represent this.

This will not change the behavior when building for 64-bit,
where the compiler already aligned the offset field correctly,
in order to satisfy natural alignment requirements.

However, when building for 32-bit, this change results in a
qdl that can flash a device successfully.

Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-06-12 12:08:01 -07:00
Niklas Cassel
5fc4cdbba4 qdl: fix error message referring to ttyUSB1
Since it is by no means certain that the current tty is ttyUSB1,
do not assume it to be so.

Unfortunately we do not know the current tty in main().
It would be possible to refactor the code so that we could print
the current tty, but since the only consumer of that information
would be this error message, that refactoring seems unjustified.

Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-06-12 12:07:35 -07:00
Niklas Cassel
37edf318b2 qdl: remove superfluous assignment
This assignment is superfluous, since the same assignment is performed
in the for loop's initializer.

Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-06-12 12:07:28 -07:00
Niklas Cassel
d9935e1f54 qdl: use correct printf modifier for uint64_t
printf uses PRIx64 modifier to print uint64_t.

This modifier has to be used outside of double-quotes.

Fixes build warnings on 32-bit systems, e.g. ARMv7.

Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-05-28 22:45:17 -07:00
Niklas Cassel
d77b106a57 qdl: use correct printf modifier for size_t
printf uses z modifier to print size_t.

Also change d modifier to u, since size_t is unsigned.
(ssize_t is the signed version.)

Fixes build warning on 32-bit systems, e.g. ARMv7.

Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-05-28 22:45:15 -07:00
Nicolas Dechesne
45cc3521d8 qdl: add --include to specific optional folder to look for files
Let the programmer search for files beyond the current folder. When --include is
used , the programmmer will first look for files in the specified folder, and it
will then fallback to looking at the current folder.

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-04-18 22:07:36 -07:00
Nicolas Dechesne
5d51472f1c Merge ".gitreview: add new file" 2018-04-06 07:50:40 +00:00
Tanya Finkel
df842101b1 QDL: Fix UFS provision issue
Fix the return value verification and add printf status message

Signed-off-by: Tanya Finkel <tfinkel@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-02-28 14:13:59 -08:00
Bjorn Andersson
44a80b1266 qdl: Remove possibility for uninitialized variable
In the case that we find a "data" tag, but not a "program" or "ufs"
child node type might have been left unitialized. Fix this by
initializing type.

Also fix up the styling of the multiline blocks.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-02-21 22:36:03 -08:00
Kirill Kapranov
d2e791a950 QDL/firehose: Add UFS provisioning functionality
Add UFS provisioning functionality using Firehose.

Signed-off-by: Kirill Kapranov <kkapra@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-02-21 22:29:15 -08:00
Kirill Kapranov
b4c2e8f267 qdl: fix 'usage' message, add missing key 'debug'
Add a mention of command line parameter '--debug' in 'usage' printout

Signed-off-by: Kirill Kapranov <kkapra@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-02-05 09:52:22 -08:00
Nicolas Dechesne
7be48f4fc9 qdl: implement args processing with getopt_long
we preserve the same args as before, however it should now be simpler to
add new options.

Signed-off-by: Nicolas Dechesne <nicolas.dechesne@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-02-02 10:02:56 -08:00
Kirill Kapranov
19e8a2d4ba firehose: Add missing xmlFreeDoc
Each xmlNewDoc should have a matching xmlFreeDoc call in order to avoid
memory leaks.

Signed-off-by: Kirill Kapranov <kkapra@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2018-02-01 22:07:43 -08:00
Nicolas Dechesne
1fc3c04d17 firehose: Don't truncate partitions to 0 sectors
Some program entries has num_partition_sectors=0 but still specifies a
file, don't truncate the size of the file in this case.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2017-11-30 21:38:36 -08:00
Bjorn Andersson
0251833b4d program: Skip entries without a valid filename
Follow the behavior of the other flash tools and skip partitions with no
filename, instead of filling them with zeros. This reduces the flash
time considerably for some set of xml files.

Also clean up firehose_program() as we no longer need to support calling
this function with an invalid fd.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2017-11-29 21:13:10 -08:00
Bjorn Andersson
febbbcc32e firehose: Negotiate max payload size
When the host propose a larger payload size than the device accepts the
device will respond with a NACK, containing the maximum payload size.
Similarily the ACK will contain the supported max if the host requests a
lower value than the device supports.

In both cases we pick the largest possible value and send a second
configure message to select this payload size.

Reported-by: Kirill Kapranov <c_kkapra@qti.qualcomm.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2017-11-29 13:24:29 -08:00
Nicolas Dechesne
922699c4db .gitreview: add new file
Convenient file to be used with git-review to make it simpler to contribute
patches into Linaro Gerrit review.

Change-Id: Ia96d2fea0de031e67f03c4384fb20dc9d5696c28
Signed-off-by: Nicolas Dechesne <nicolas.dechesne@linaro.org>
2017-08-29 13:56:05 +02:00
45 changed files with 5112 additions and 792 deletions

35
.checkpatch.conf Normal file
View File

@@ -0,0 +1,35 @@
--no-tree
--strict
--max-line-length=120
--ignore FILE_PATH_CHANGES
--ignore EMAIL_SUBJECT
--ignore SPLIT_STRING
# NEW_TYPEDEFS reports "do not add new typedefs"
# typedef struct __attribute__((__packed__)) sparse_header {
--ignore NEW_TYPEDEFS
# PREFER_DEFINED_ATTRIBUTE_MACRO reports this kind of messages:
# WARNING: Prefer __packed over __attribute__((__packed__))
--ignore PREFER_DEFINED_ATTRIBUTE_MACRO
# PREFER_KERNEL_TYPES reports this kind of messages (when using --strict):
# "Prefer kernel type 'u32' over 'uint32_t'"
--ignore PREFER_KERNEL_TYPES
# BRACES reports this kind of messages:
# braces {} are not necessary for any arm of this statement
--ignore BRACES
# CAMELCASE reports this kind of messages:
# Avoid CamelCase: <xmlFreeDoc>
--ignore CAMELCASE
# AVOID_EXTERNS reports this kind of messages:
# externs should be avoided in .c files
# extern const char *__progname;
--ignore AVOID_EXTERNS
# COMMIT_LOG_LONG_LINE reports line lengths > 75 in commit log
# Lets ignore this
--ignore COMMIT_LOG_LONG_LINE

155
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,155 @@
name: Buildtest
on:
pull_request:
push:
jobs:
build-linux:
strategy:
fail-fast: false
matrix:
include:
- { arch: x64, os: 24, runner: ubuntu-24.04 }
- { arch: arm64, os: 24, runner: ubuntu-24.04-arm }
- { arch: x64, os: 22, runner: ubuntu-22.04 }
- { arch: arm64, os: 22, runner: ubuntu-22.04-arm }
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Dependencies
run: |
sudo apt-get update
sudo apt-get install -y libxml2-dev libusb-1.0-0-dev
- name: Build
run: make
- name: Run tests
run: make tests
- name: Package
run: |
mkdir dist
cp `pkg-config --variable=libdir libusb-1.0`/libusb-1.0.so.0 dist
chmod 0644 dist/*
cp qdl dist
patchelf --set-rpath '$ORIGIN' dist/qdl
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: qdl-binary-ubuntu-${{matrix.os}}-${{ matrix.arch }}
path: dist/*
build-mac:
strategy:
fail-fast: false
matrix:
include:
- { sys: macos-14, arch: arm64 }
- { sys: macos-13, arch: intel }
runs-on: ${{ matrix.sys }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Dependencies
run: |
brew install libxml2
- name: Build
run: make
- name: Run tests
run: make tests
- name: Package
run: |
set -x
mkdir dist
cp `pkg-config --variable=libdir libusb-1.0`/libusb-1.0.0.dylib dist
cp `pkg-config --variable=libdir liblzma`/liblzma.5.dylib dist
chmod 0644 dist/*
cp qdl dist
if uname -a | grep -q arm64; then
LIBUSB_DIR=/opt/homebrew/opt/libusb/lib
LIBLZMA_DIR=/usr/lib
else
LIBUSB_DIR=/usr/local/opt/libusb/lib
LIBLZMA_DIR=/usr/local/opt/xz/lib
fi
install_name_tool -add_rpath @executable_path dist/qdl
install_name_tool -change $LIBUSB_DIR/libusb-1.0.0.dylib @rpath/libusb-1.0.0.dylib dist/qdl
install_name_tool -change $LIBLZMA_DIR/liblzma.5.dylib @rpath/liblzma.5.dylib dist/qdl
otool -L dist/qdl
dist/qdl || true
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: qdl-binary-macos-${{ matrix.arch }}
path: dist/*
build-windows:
strategy:
fail-fast: false
matrix:
include:
- { sys: windows-latest, arch: x64 }
- { sys: windows-11-arm, arch: arm64 }
runs-on: ${{ matrix.sys }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup MSYS2
id: msys2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
install: >
base-devel
mingw-w64-x86_64-gcc
mingw-w64-x86_64-make
mingw-w64-x86_64-pkg-config
mingw-w64-x86_64-libxml2
mingw-w64-x86_64-libusb
- name: Build
run: make
shell: msys2 {0}
- name: Run tests
run: make tests
shell: msys2 {0}
- name: Package
shell: pwsh
run: |
$MSYS2_LOCATION = "${{ steps.msys2.outputs.msys2-location }}"
$BIN_DIR = Join-Path $MSYS2_LOCATION "mingw64\bin"
$DistDir = "dist"
New-Item -ItemType Directory -Path $DistDir | Out-Null
Copy-Item (Join-Path $BIN_DIR "zlib1.dll") $DistDir
Copy-Item (Join-Path $BIN_DIR "libxml2-16.dll") $DistDir
Copy-Item (Join-Path $BIN_DIR "libusb-1.0.dll") $DistDir
Copy-Item (Join-Path $BIN_DIR "liblzma-5.dll") $DistDir
Copy-Item (Join-Path $BIN_DIR "libiconv-2.dll") $DistDir
Copy-Item "qdl.exe" $DistDir
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: qdl-binary-windows-${{ matrix.arch }}
path: dist/*

15
.github/workflows/checkpatch.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Checkpatch Review
on: [pull_request]
jobs:
check-patch:
name: checkpatch review
runs-on: ubuntu-latest
steps:
- name: 'Calculate PR commits + 1'
run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> $GITHUB_ENV
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Run checkpatch review
uses: webispy/checkpatch-action@v9

36
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: CodeQL
on:
pull_request:
push:
jobs:
codeql:
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Dependencies
run: |
sudo apt-get update
sudo apt-get install -y libxml2-dev libusb-1.0-0-dev
- name: CodeQL init
uses: github/codeql-action/init@v3
with:
languages: c-cpp
build-mode: autobuild
- name: CodeQL build
uses: github/codeql-action/autobuild@v3
- name: CodeQL analysis
uses: github/codeql-action/analyze@v3

11
.github/workflows/markdown-lint.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
name: Markdown Lint
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: DavidAnson/markdownlint-cli2-action@v20
with:
globs: |
README.md

9
.gitignore vendored
View File

@@ -1,2 +1,11 @@
*.o
qdl
qdl-ramdump
ks
*.exe
compile_commands.json
.cache
.version.h
version.h
scripts
.checkpatch-camelcase.git.

4
.gitreview Normal file
View File

@@ -0,0 +1,4 @@
[gerrit]
host=review.linaro.org
port=29418
project=landing-teams/working/qualcomm/qdl

View File

@@ -1,17 +1,83 @@
OUT := qdl
QDL := qdl
RAMDUMP := qdl-ramdump
VERSION := $(or $(VERSION), $(shell git describe --dirty --always --tags 2>/dev/null), "unknown-version")
CFLAGS := -O2 -Wall -g `xml2-config --cflags`
LDFLAGS := `xml2-config --libs`
CFLAGS += -O2 -Wall -g `pkg-config --cflags libxml-2.0 libusb-1.0`
LDFLAGS += `pkg-config --libs libxml-2.0 libusb-1.0`
ifeq ($(OS),Windows_NT)
LDFLAGS += -lws2_32
endif
prefix := /usr/local
SRCS := firehose.c qdl.c sahara.c util.c patch.c program.c
OBJS := $(SRCS:.c=.o)
QDL_SRCS := firehose.c io.c qdl.c sahara.c util.c patch.c program.c read.c sha2.c sim.c ufs.c usb.c ux.c oscompat.c vip.c sparse.c
QDL_OBJS := $(QDL_SRCS:.c=.o)
$(OUT): $(OBJS)
RAMDUMP_SRCS := ramdump.c sahara.c io.c sim.c usb.c util.c ux.c oscompat.c
RAMDUMP_OBJS := $(RAMDUMP_SRCS:.c=.o)
KS_OUT := ks
KS_SRCS := ks.c sahara.c util.c ux.c oscompat.c
KS_OBJS := $(KS_SRCS:.c=.o)
CHECKPATCH_SOURCES := $(shell find . -type f \( -name "*.c" -o -name "*.h" -o -name "*.sh" \) ! -name "sha2.c" ! -name "sha2.h" ! -name "*version.h")
CHECKPATCH_ROOT := https://raw.githubusercontent.com/torvalds/linux/v6.15/scripts
CHECKPATCH_URL := $(CHECKPATCH_ROOT)/checkpatch.pl
CHECKPATCH_SP_URL := $(CHECKPATCH_ROOT)/spelling.txt
CHECKPATCH := ./.scripts/checkpatch.pl
CHECKPATCH_SP := ./.scripts/spelling.txt
default: $(QDL) $(RAMDUMP) $(KS_OUT)
$(QDL): $(QDL_OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -f $(OUT) $(OBJS)
$(RAMDUMP): $(RAMDUMP_OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
install: $(OUT)
install -D -m 755 $< $(DESTDIR)$(prefix)/bin/$<
$(KS_OUT): $(KS_OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
compile_commands.json: $(QDL_SRCS) $(KS_SRCS)
@echo -n $^ | jq -snR "[inputs|split(\" \")[]|{directory:\"$(PWD)\", command: \"$(CC) $(CFLAGS) -c \(.)\", file:.}]" > $@
version.h::
@echo "#define VERSION \"$(VERSION)\"" > .version.h
@cmp -s .version.h version.h || cp .version.h version.h
util.o: version.h
clean:
rm -f $(QDL) $(QDL_OBJS)
rm -f $(RAMDUMP) $(RAMDUMP_OBJS)
rm -f $(KS_OUT) $(KS_OBJS)
rm -f compile_commands.json
rm -f version.h .version.h
rm -f $(CHECKPATCH)
rm -f $(CHECKPATCH_SP)
if [ -d .scripts ]; then rmdir .scripts; fi
install: $(QDL) $(RAMDUMP) $(KS_OUT)
install -d $(DESTDIR)$(prefix)/bin
install -m 755 $^ $(DESTDIR)$(prefix)/bin
tests: default
tests:
@./tests/run_tests.sh
# Target to download checkpatch.pl if not present
$(CHECKPATCH):
@echo "Downloading checkpatch.pl..."
@mkdir -p $(dir $(CHECKPATCH))
@curl -sSfL $(CHECKPATCH_URL) -o $(CHECKPATCH)
@curl -sSfL $(CHECKPATCH_SP_URL) -o $(CHECKPATCH_SP)
@chmod +x $(CHECKPATCH)
check: $(CHECKPATCH)
@echo "Running checkpatch on source files (excluding sha2.c and sha2.h)..."
@for file in $(CHECKPATCH_SOURCES); do \
perl $(CHECKPATCH) --no-tree -f $$file || exit 1; \
done
check-cached: $(CHECKPATCH)
@echo "Running checkpatch on staged changes..."
@git diff --cached -- . | perl $(CHECKPATCH) --no-tree -

16
README
View File

@@ -1,16 +0,0 @@
Qualcomm Download
=================
This tool communicates with USB devices of id 05c6:9008 to upload a flash
loader and use this to flash images.
Usage:
qdl <prog.mbn> [<program> <patch> ...]
Building
========
In order to build the project you need libxml2 headers and libraries, found in
e.g. the libxml2-dev package.
With this installed run:
make

170
README.md Normal file
View File

@@ -0,0 +1,170 @@
# Qualcomm Download
[![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
[![Build on push](https://github.com/linux-msm/qdl/actions/workflows/build.yml/badge.svg)](https://github.com/linux-msm/qdl/actions/workflows/build.yml/badge.svg)
This tool communicates with USB devices of id `05c6:9008` to upload a flash
loader and use this to flash images.
## Build
### Linux
```bash
sudo apt install libxml2 libusb-1.0-0-dev
make
```
### MacOS
```bash
brew install libxml2 pkg-config libusb
make
```
### Windows
First, install the [MSYS2 environment](https://www.msys2.org/). Then, run the
MSYS2 MinGW64 terminal (located at `<msys2-installation-path>\mingw64.exe`) and
install additional packages needed for QDL compilation using the `pacman` tool:
```bash
pacman -S base-devel --needed
pacman -S mingw-w64-x86_64-gcc
pacman -S mingw-w64-x86_64-make
pacman -S mingw-w64-x86_64-pkg-config
pacman -S mingw-w64-x86_64-libusb
pacman -S mingw-w64-x86_64-libxml2
```
Then use the `make` tool to build QDL:
```bash
make
```
## Use QDL
### EDL mode
The device intended for flashing must be booted into **Emergency Download (EDL)**
mode. EDL is a special boot mode available on Qualcomm-based devices that provides
low-level access for firmware flashing and recovery. It bypasses the standard boot
process, allowing operations such as flashing firmware even on unresponsive devices
or those with locked bootloaders.
Please consult your devices documentation for instructions on how to enter EDL mode.
### Flash device
Run QDL with the `--help` option to view detailed usage information.
Below is an example of how to invoke QDL to flash a FLAT build:
```bash
qdl --dry-run prog_firehose_ddr.elf rawprogram*.xml patch*.xml
```
If you have multiple boards connected the host, provide the serial number of
the board to flash through `--serial` param:
```bash
qdl --serial=0AA94EFD prog_firehose_ddr.elf rawprogram*.xml patch*.xml
```
### Validated Image Programming (VIP)
QDL now supports **Validated Image Programming (VIP)** mode , 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.
To use VIP programming, a digest table must be generated prior to flashing the device.
To generate table of digests run QDL with `--create-digests` param,
providing a path to store VIP tables. For example:
```bash
mkdir vip
qdl --create-digests=./vip prog_firehose_ddr.elf rawprogram*.xml patch*.xml
```
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\<n\>.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:
```bash
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.
To flash board using VIP mode provide a path where previously generated and signed
table of digests are stored using `--vip-table-path` param:
```bash
qdl --vip-table-path=./vip prog_firehose_ddr.elf rawprogram*.xml patch*.xml
```
## Run tests
To run the integration test suite for QDL, use the `make tests` target:
```bash
make tests
```
## Contributing
Please submit any patches to the qdl (`master` branch) by using the GitHub pull
request feature. Fork the repo, create a branch, do the work, rebase with upstream,
and submit the pull request.
The preferred coding style for this tool is [Linux kernel coding style](https://www.kernel.org/doc/html/v6.15/process/coding-style.html).
Before creating a commit, please ensure that your changes adhere to the coding style
by using the `make check-cached` target, for example:
```bash
$ git status
On branch improvements
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: qdl.c
modified: qdl.h
$ make check-cached
Running checkpatch on staged changes...
ERROR: trailing whitespace
#28: FILE: qdl.h:32:
+^IQDL_DEVICE_USB, $
total: 1 errors, 0 warnings, 0 checks, 27 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
NOTE: Whitespace errors detected.
You may wish to use scripts/cleanpatch or scripts/cleanfile
Your patch has style problems, please review.
```
## License
This tool is licensed under the BSD 3-Clause licensed. Check out [LICENSE](LICENSE)
for more detais.

File diff suppressed because it is too large Load Diff

49
io.c Normal file
View File

@@ -0,0 +1,49 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <stdlib.h>
#include "qdl.h"
struct qdl_device *qdl_init(enum QDL_DEVICE_TYPE type)
{
if (type == QDL_DEVICE_USB)
return usb_init();
if (type == QDL_DEVICE_SIM)
return sim_init();
return NULL;
}
void qdl_deinit(struct qdl_device *qdl)
{
if (qdl)
free(qdl);
}
void qdl_set_out_chunk_size(struct qdl_device *qdl, long size)
{
qdl->set_out_chunk_size(qdl, size);
}
int qdl_open(struct qdl_device *qdl, const char *serial)
{
return qdl->open(qdl, serial);
}
void qdl_close(struct qdl_device *qdl)
{
qdl->close(qdl);
}
int qdl_read(struct qdl_device *qdl, void *buf, size_t len, unsigned int timeout)
{
return qdl->read(qdl, buf, len, timeout);
}
int qdl_write(struct qdl_device *qdl, const void *buf, size_t len)
{
return qdl->write(qdl, buf, len);
}

131
ks.c Normal file
View File

@@ -0,0 +1,131 @@
// SPDX-License-Identifier: BSD-3-Clause
#include <sys/types.h>
#include <assert.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "qdl.h"
#include "oscompat.h"
#ifdef _WIN32
const char *__progname = "ks";
#endif
static struct qdl_device qdl;
bool qdl_debug;
int qdl_read(struct qdl_device *qdl, void *buf, size_t len, unsigned int timeout)
{
return read(qdl->fd, buf, len);
}
int qdl_write(struct qdl_device *qdl, const void *buf, size_t len)
{
return write(qdl->fd, buf, len);
}
static void print_usage(void)
{
extern const char *__progname;
fprintf(stderr,
"%s -p <sahara dev_node> -s <id:file path> ...\n",
__progname);
fprintf(stderr,
" -p --port Sahara device node to use\n"
" -s <id:file path> --sahara <id:file path> Sahara protocol file mapping\n"
"\n"
"One -p instance is required. One or more -s instances are required.\n"
"\n"
"Example:\n"
"ks -p /dev/mhi0_QAIC_SAHARA -s 1:/opt/qti-aic/firmware/fw1.bin -s 2:/opt/qti-aic/firmware/fw2.bin\n");
}
int main(int argc, char **argv)
{
bool found_mapping = false;
char *dev_node = NULL;
long file_id;
char *colon;
int opt;
int ret;
static struct option options[] = {
{"debug", no_argument, 0, 'd'},
{"version", no_argument, 0, 'v'},
{"port", required_argument, 0, 'p'},
{"sahara", required_argument, 0, 's'},
{0, 0, 0, 0}
};
while ((opt = getopt_long(argc, argv, "dvp:s:", options, NULL)) != -1) {
switch (opt) {
case 'd':
qdl_debug = true;
break;
case 'v':
print_version();
return 0;
case 'p':
dev_node = optarg;
printf("Using port - %s\n", dev_node);
break;
case 's':
found_mapping = true;
file_id = strtol(optarg, NULL, 10);
if (file_id < 0) {
print_usage();
return 1;
}
if (file_id >= MAPPING_SZ) {
fprintf(stderr,
"ID:%ld exceeds the max value of %d\n",
file_id,
MAPPING_SZ - 1);
return 1;
}
colon = strchr(optarg, ':');
if (!colon) {
print_usage();
return 1;
}
qdl.mappings[file_id] = &optarg[colon - optarg + 1];
printf("Created mapping ID:%ld File:%s\n", file_id, qdl.mappings[file_id]);
break;
default:
print_usage();
return 1;
}
}
// -p and -s is required
if (!dev_node || !found_mapping) {
print_usage();
return 1;
}
if (qdl_debug)
print_version();
qdl.fd = open(dev_node, O_RDWR);
if (qdl.fd < 0) {
fprintf(stderr, "Unable to open %s\n", dev_node);
return 1;
}
ret = sahara_run(&qdl, qdl.mappings, false, NULL, NULL);
if (ret < 0)
return 1;
return 0;
}

76
oscompat.c Normal file
View File

@@ -0,0 +1,76 @@
// SPDX-License-Identifier: BSD-3-Clause
#ifdef _WIN32
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "oscompat.h"
extern const char *__progname;
void timeradd(const struct timeval *a, const struct timeval *b, struct timeval *result)
{
result->tv_sec = a->tv_sec + b->tv_sec;
result->tv_usec = a->tv_usec + b->tv_usec;
if (result->tv_usec >= 1000000) {
result->tv_sec += 1;
result->tv_usec -= 1000000;
}
}
void err(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "%s: ", __progname);
if (fmt) {
vfprintf(stderr, fmt, ap);
fprintf(stderr, ": ");
}
fprintf(stderr, "%s\n", strerror(errno));
va_end(ap);
exit(eval);
}
void errx(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "%s: ", __progname);
if (fmt)
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(eval);
}
void warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "%s: ", __progname);
if (fmt) {
vfprintf(stderr, fmt, ap);
fprintf(stderr, ": ");
}
fprintf(stderr, "%s\n", strerror(errno));
va_end(ap);
}
void warnx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "%s: ", __progname);
if (fmt)
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
#endif // _WIN32

25
oscompat.h Normal file
View File

@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: BSD-3-Clause */
#ifndef __OSCOMPAT_H__
#define __OSCOMPAT_H__
#ifndef _WIN32
#include <err.h>
#define O_BINARY 0
#else // _WIN32
#include <sys/time.h>
#include <stdbool.h>
void timeradd(const struct timeval *a, const struct timeval *b, struct timeval *result);
void err(int eval, const char *fmt, ...);
void errx(int eval, const char *fmt, ...);
void warn(const char *fmt, ...);
void warnx(const char *fmt, ...);
#endif
#endif

96
patch.c
View File

@@ -1,65 +1,21 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2016-2017, Linaro Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <unistd.h>
#include "patch.h"
#include "qdl.h"
static struct patch *patches;
static struct patch *patches_last;
static unsigned attr_as_unsigned(xmlNode *node, const char *attr, int *errors)
{
xmlChar *value;
value = xmlGetProp(node, (xmlChar*)attr);
if (!value)
(*errors)++;
return strtoul((char*)value, NULL, 10);
}
static const char *attr_as_string(xmlNode *node, const char *attr, int *errors)
{
xmlChar *value;
value = xmlGetProp(node, (xmlChar*)attr);
if (!value)
(*errors)++;
return strdup((char*)value);
}
int patch_load(const char *patch_file)
{
struct patch *patch;
@@ -70,7 +26,7 @@ int patch_load(const char *patch_file)
doc = xmlReadFile(patch_file, NULL, 0);
if (!doc) {
fprintf(stderr, "[PATCH] failed to parse %s\n", patch_file);
ux_err("failed to parse patch-type file \"%s\"\n", patch_file);
return -EINVAL;
}
@@ -79,8 +35,8 @@ int patch_load(const char *patch_file)
if (node->type != XML_ELEMENT_NODE)
continue;
if (xmlStrcmp(node->name, (xmlChar*)"patch")) {
fprintf(stderr, "[PATCH] unrecognized tag \"%s\", ignoring\n", node->name);
if (xmlStrcmp(node->name, (xmlChar *)"patch")) {
ux_err("unrecognized tag \"%s\" in patch-type file, ignoring\n", node->name);
continue;
}
@@ -98,7 +54,7 @@ int patch_load(const char *patch_file)
patch->what = attr_as_string(node, "what", &errors);
if (errors) {
fprintf(stderr, "[PATCH] errors while parsing patch\n");
ux_err("errors while parsing patch-type file \"%s\"\n", patch_file);
free(patch);
continue;
}
@@ -116,20 +72,48 @@ int patch_load(const char *patch_file)
return 0;
}
int patch_execute(int fd, int (*apply)(int fd, struct patch *patch))
int patch_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct patch *patch))
{
struct patch *patch;
unsigned int count = 0;
unsigned int idx = 0;
int ret;
for (patch = patches; patch; patch = patch->next) {
if (!strcmp(patch->filename, "DISK"))
count++;
}
for (patch = patches; patch; patch = patch->next) {
if (strcmp(patch->filename, "DISK"))
continue;
ret = apply(fd, patch);
ret = apply(qdl, patch);
if (ret)
return ret;
ux_progress("Applying patches", idx++, count);
}
ux_info("%d patches applied\n", idx);
return 0;
}
void free_patches(void)
{
struct patch *patch = patches;
struct patch *next;
for (patch = patches; patch; patch = next) {
next = patch->next;
free((void *)patch->filename);
free((void *)patch->start_sector);
free((void *)patch->value);
free((void *)patch->what);
free(patch);
}
patches = NULL;
}

14
patch.h
View File

@@ -1,12 +1,15 @@
/* SPDX-License-Identifier: BSD-3-Clause */
#ifndef __PATCH_H__
#define __PATCH_H__
struct qdl_device;
struct patch {
unsigned sector_size;
unsigned byte_offset;
unsigned int sector_size;
unsigned int byte_offset;
const char *filename;
unsigned partition;
unsigned size_in_bytes;
unsigned int partition;
unsigned int size_in_bytes;
const char *start_sector;
const char *value;
const char *what;
@@ -15,6 +18,7 @@ struct patch {
};
int patch_load(const char *patch_file);
int patch_execute(int fd, int (*apply)(int fd, struct patch *patch));
int patch_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct patch *patch));
void free_patches(void);
#endif

470
program.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +1,41 @@
/* SPDX-License-Identifier: BSD-3-Clause */
#ifndef __PROGRAM_H__
#define __PROGRAM_H__
#include <sys/types.h>
#include <stdbool.h>
#include <stdint.h>
#include "qdl.h"
struct program {
unsigned sector_size;
unsigned file_offset;
unsigned int pages_per_block;
unsigned int sector_size;
unsigned int file_offset;
const char *filename;
const char *label;
unsigned num_sectors;
unsigned partition;
unsigned size;
unsigned int num_sectors;
unsigned int partition;
bool sparse;
const char *start_bytes;
const char *start_sector;
unsigned int last_sector;
bool is_nand;
bool is_erase;
unsigned int sparse_chunk_type;
uint32_t sparse_fill_value;
off_t sparse_offset;
struct program *next;
};
int program_load(const char *program_file);
int program_execute(int usbfd, int (*apply)(int usbfd, struct program *program, int fd));
int program_find_bootable_partition(void);
int program_load(const char *program_file, bool is_nand);
int program_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct program *program, int fd),
const char *incdir, bool allow_missing);
int erase_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct program *program));
int program_find_bootable_partition(bool *multiple_found);
int program_is_sec_partition_flashed(void);
void free_programs(void);
#endif

421
qdl.c
View File

@@ -1,58 +1,37 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2016-2017, Linaro Ltd.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <assert.h>
#include <ctype.h>
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include "qdl.h"
#include "patch.h"
#include "program.h"
#include "ufs.h"
#include "oscompat.h"
#include "vip.h"
#ifdef _WIN32
const char *__progname = "qdl";
#endif
#define MAX_USBFS_BULK_SIZE (16 * 1024)
enum {
QDL_FILE_UNKNOWN,
QDL_FILE_PATCH,
QDL_FILE_PROGRAM,
QDL_FILE_READ,
QDL_FILE_UFS,
QDL_FILE_CONTENTS,
};
@@ -62,205 +41,245 @@ static int detect_type(const char *xml_file)
{
xmlNode *root;
xmlDoc *doc;
int type;
xmlNode *node;
int type = QDL_FILE_UNKNOWN;
doc = xmlReadFile(xml_file, NULL, 0);
if (!doc) {
fprintf(stderr, "[PATCH] failed to parse %s\n", xml_file);
ux_err("failed to parse XML file \"%s\"\n", xml_file);
return -EINVAL;
}
root = xmlDocGetRootElement(doc);
if (!xmlStrcmp(root->name, (xmlChar*)"patches"))
if (!xmlStrcmp(root->name, (xmlChar *)"patches")) {
type = QDL_FILE_PATCH;
else if (!xmlStrcmp(root->name, (xmlChar*)"data"))
type = QDL_FILE_PROGRAM;
else if (!xmlStrcmp(root->name, (xmlChar*)"contents"))
} else if (!xmlStrcmp(root->name, (xmlChar *)"data")) {
for (node = root->children; node ; node = node->next) {
if (node->type != XML_ELEMENT_NODE)
continue;
if (!xmlStrcmp(node->name, (xmlChar *)"program")) {
type = QDL_FILE_PROGRAM;
break;
}
if (!xmlStrcmp(node->name, (xmlChar *)"read")) {
type = QDL_FILE_READ;
break;
}
if (!xmlStrcmp(node->name, (xmlChar *)"ufs")) {
type = QDL_FILE_UFS;
break;
}
}
} else if (!xmlStrcmp(root->name, (xmlChar *)"contents")) {
type = QDL_FILE_CONTENTS;
else
type = QDL_FILE_UNKNOWN;
}
xmlFreeDoc(doc);
return type;
}
static int readat(int dir, const char *name, char *buf, size_t len)
static void print_usage(FILE *out)
{
ssize_t n;
int fd;
int ret = 0;
extern const char *__progname;
fd = openat(dir, name, O_RDONLY);
if (fd < 0)
return fd;
n = read(fd, buf, len - 1);
if (n < 0) {
warn("failed to read %s", name);
ret = -EINVAL;
goto close_fd;
}
buf[n] = '\0';
buf[strcspn(buf, "\n")] = '\0';
close_fd:
close(fd);
return ret;
}
static int find_qdl_tty(char *dev_name, size_t dev_name_len)
{
struct dirent *de;
int found = -ENOENT;
char vid[5];
char pid[5];
DIR *dir;
int tty;
int fd;
int ret;
tty = open("/sys/class/tty", O_DIRECTORY);
if (tty < 0)
err(1, "failed to open /sys/class/tty");
dir = fdopendir(tty);
if (!dir)
err(1, "failed to opendir /sys/class/tty");
while ((de = readdir(dir)) != NULL) {
if (strncmp(de->d_name, "ttyUSB", 6) != 0)
continue;
fd = openat(tty, de->d_name, O_DIRECTORY);
if (fd < 0)
continue;
ret = readat(fd, "../../../../idVendor", vid, sizeof(vid));
if (ret < 0)
goto close_fd;
ret = readat(fd, "../../../../idProduct", pid, sizeof(pid));
if (ret < 0)
goto close_fd;
if (strcmp(vid, "05c6") || strcmp(pid, "9008"))
goto close_fd;
snprintf(dev_name, dev_name_len, "/dev/%s", de->d_name);
found = 0;
close_fd:
close(fd);
}
closedir(dir);
close(tty);
return found;
}
static int tty_open(struct termios *old)
{
struct termios tios;
char path[PATH_MAX];
int ret;
int fd;
retry:
ret = find_qdl_tty(path, sizeof(path));
if (ret < 0) {
printf("Waiting for QDL tty...\r");
fflush(stdout);
sleep(1);
goto retry;
}
fd = open(path, O_RDWR | O_NOCTTY | O_EXCL);
if (fd < 0) {
err(1, "unable to open \"%s\"", path);
}
ret = tcgetattr(fd, old);
if (ret < 0)
err(1, "unable to retrieve \"%s\" tios", path);
memset(&tios, 0, sizeof(tios));
tios.c_cflag = B115200 | CRTSCTS | CS8 | CLOCAL | CREAD;
tios.c_iflag = IGNPAR;
tios.c_oflag = 0;
tcflush(fd, TCIFLUSH);
ret = tcsetattr(fd, TCSANOW, &tios);
if (ret < 0)
err(1, "unable to update \"%s\" tios", path);
return fd;
fprintf(out, "Usage: %s [options] <prog.mbn> [<program> <patch> ...]\n", __progname);
fprintf(out, " -d, --debug\t\t\tPrint detailed debug info\n");
fprintf(out, " -v, --version\t\t\tPrint the current version and exit\n");
fprintf(out, " -n, --dry-run\t\t\tDry run execution, no device reading or flashing\n");
fprintf(out, " -f, --allow-missing\t\tAllow skipping of missing files during flashing\n");
fprintf(out, " -s, --storage=T\t\tSet target storage type T: <emmc|nand|ufs>\n");
fprintf(out, " -l, --finalize-provisioning\tProvision the target storage\n");
fprintf(out, " -i, --include=T\t\tSet an optional folder T to search for files\n");
fprintf(out, " -S, --serial=T\t\t\tSelect target by serial number T (e.g. <0AA94EFD>)\n");
fprintf(out, " -u, --out-chunk-size=T\t\tOverride chunk size for transaction with T\n");
fprintf(out, " -t, --create-digests=T\t\tGenerate table of digests in the T folder\n");
fprintf(out, " -D, --vip-table-path=T\t\tUse digest tables in the T folder for VIP\n");
fprintf(out, " -h, --help\t\t\tPrint this usage info\n");
fprintf(out, "\n");
fprintf(out, "Example: %s prog_firehose_ddr.elf rawprogram*.xml patch*.xml\n", __progname);
}
int main(int argc, char **argv)
{
extern const char *__progname;
struct termios tios;
char *prog_mbn;
char *prog_mbn, *storage = "ufs";
char *incdir = NULL;
char *serial = NULL;
const char *vip_generate_dir = NULL;
const char *vip_table_path = NULL;
int type;
int ret;
int fd;
int i;
int opt;
bool qdl_finalize_provisioning = false;
bool allow_fusing = false;
bool allow_missing = false;
long out_chunk_size = 0;
struct qdl_device *qdl = NULL;
enum QDL_DEVICE_TYPE qdl_dev_type = QDL_DEVICE_USB;
if (argc >= 2 && strcmp(argv[1], "--debug") == 0) {
qdl_debug = true;
argv++;
argc--;
}
static struct option options[] = {
{"debug", no_argument, 0, 'd'},
{"version", no_argument, 0, 'v'},
{"include", required_argument, 0, 'i'},
{"finalize-provisioning", no_argument, 0, 'l'},
{"out-chunk-size", required_argument, 0, 'u' },
{"serial", required_argument, 0, 'S'},
{"vip-table-path", required_argument, 0, 'D'},
{"storage", required_argument, 0, 's'},
{"allow-missing", no_argument, 0, 'f'},
{"allow-fusing", no_argument, 0, 'c'},
{"dry-run", no_argument, 0, 'n'},
{"create-digests", required_argument, 0, 't'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
if (argc < 3) {
fprintf(stderr, "%s <prog.mbn> [<program> <patch> ...]\n", __progname);
return 1;
}
prog_mbn = argv[1];
for (i = 2; i < argc; i++) {
type = detect_type(argv[i]);
if (type < 0 || type == QDL_FILE_UNKNOWN)
errx(1, "failed to detect file type of %s\n", argv[i]);
switch (type) {
case QDL_FILE_PATCH:
ret = patch_load(argv[i]);
if (ret < 0)
errx(1, "patch_load %s failed", argv[i]);
while ((opt = getopt_long(argc, argv, "dvi:lu:S:D:s:fcnt:h", options, NULL)) != -1) {
switch (opt) {
case 'd':
qdl_debug = true;
break;
case QDL_FILE_PROGRAM:
ret = program_load(argv[i]);
if (ret < 0)
errx(1, "program_load %s failed", argv[i]);
case 'n':
qdl_dev_type = QDL_DEVICE_SIM;
break;
case 't':
vip_generate_dir = optarg;
/* we also enforce dry-run mode */
qdl_dev_type = QDL_DEVICE_SIM;
break;
case 'v':
print_version();
return 0;
case 'f':
allow_missing = true;
break;
case 'i':
incdir = optarg;
break;
case 'l':
qdl_finalize_provisioning = true;
break;
case 'c':
allow_fusing = true;
break;
case 'u':
out_chunk_size = strtol(optarg, NULL, 10);
break;
case 's':
storage = optarg;
break;
case 'S':
serial = optarg;
break;
case 'D':
vip_table_path = optarg;
break;
case 'h':
print_usage(stdout);
return 0;
default:
errx(1, "%s type not yet supported", argv[i]);
break;
print_usage(stderr);
return 1;
}
}
fd = tty_open(&tios);
if (fd < 0)
err(1, "failed to open QDL tty");
/* at least 2 non optional args required */
if ((optind + 2) > argc) {
print_usage(stderr);
return 1;
}
ret = sahara_run(fd, prog_mbn);
qdl = qdl_init(qdl_dev_type);
if (!qdl) {
ret = -1;
goto out_cleanup;
}
if (vip_table_path) {
if (vip_generate_dir)
errx(1, "VIP mode and VIP table generation can't be enabled together\n");
ret = vip_transfer_init(qdl, vip_table_path);
if (ret)
errx(1, "VIP initialization failed\n");
}
if (out_chunk_size)
qdl_set_out_chunk_size(qdl, out_chunk_size);
if (vip_generate_dir) {
ret = vip_gen_init(qdl, vip_generate_dir);
if (ret)
goto out_cleanup;
}
ux_init();
if (qdl_debug)
print_version();
prog_mbn = argv[optind++];
do {
type = detect_type(argv[optind]);
if (type < 0 || type == QDL_FILE_UNKNOWN)
errx(1, "failed to detect file type of %s\n", argv[optind]);
switch (type) {
case QDL_FILE_PATCH:
ret = patch_load(argv[optind]);
if (ret < 0)
errx(1, "patch_load %s failed", argv[optind]);
break;
case QDL_FILE_PROGRAM:
ret = program_load(argv[optind], !strcmp(storage, "nand"));
if (ret < 0)
errx(1, "program_load %s failed", argv[optind]);
if (!allow_fusing && program_is_sec_partition_flashed())
errx(1, "secdata partition to be programmed, which can lead to irreversible"
" changes. Allow explicitly with --allow-fusing parameter");
break;
case QDL_FILE_READ:
ret = read_op_load(argv[optind]);
if (ret < 0)
errx(1, "read_op_load %s failed", argv[optind]);
break;
case QDL_FILE_UFS:
ret = ufs_load(argv[optind], qdl_finalize_provisioning);
if (ret < 0)
errx(1, "ufs_load %s failed", argv[optind]);
break;
default:
errx(1, "%s type not yet supported", argv[optind]);
break;
}
} while (++optind < argc);
ret = qdl_open(qdl, serial);
if (ret)
goto out_cleanup;
qdl->mappings[0] = prog_mbn;
ret = sahara_run(qdl, qdl->mappings, true, NULL, NULL);
if (ret < 0)
goto out;
goto out_cleanup;
ret = firehose_run(fd);
out:
ret = tcsetattr(fd, TCSANOW, &tios);
ret = firehose_run(qdl, incdir, storage, allow_missing);
if (ret < 0)
warn("unable to restore tios of ttyUSB1");
close(fd);
goto out_cleanup;
return 0;
out_cleanup:
if (vip_generate_dir)
vip_gen_finalize(qdl);
qdl_close(qdl);
free_programs();
free_patches();
if (qdl->vip_data.state != VIP_DISABLED)
vip_transfer_deinit(qdl);
qdl_deinit(qdl);
return !!ret;
}

Some files were not shown because too many files have changed in this diff Show More