When the kernel minidump backend is active, the Sahara debug table
contains a KELF region — a complete ELF core header describing the
physical address and output offset of every other kernel region.
Detect KELF after download and stitch all kernel regions into a single
minidump.elf, ready for crash or gdb, without any manual concatenation.
Devices without minidump enabled are unaffected.
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
The .gitreview file configured git-review to push changes for code
review to a Gerrit instance at review.linaro.org. The project's review
workflow has since moved to GitHub pull requests against
github.com/linux-msm/qdl, and the Linaro Gerrit project is no longer
used. Remove the stale config so contributors are not misled into
sending patches to an abandoned review server.
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
The recently added free() calls in load_erase_tag() pass
program->start_sector directly to free(), but the field is declared
as const char * in struct firehose_op. GCC emits a
-Wdiscarded-qualifiers warning for both call sites.
Cast through (void *) to match the pattern already used at the other
free sites for the same field (program.c, patch.c, firehose.c).
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
Both directions of host/device VIP misconfiguration currently surface
as opaque failures that operators in the field have to diagnose from
raw byte-stream errors, when the right answer is fully derivable from
the programmer's own startup logs. Do the detection here so customers
don't have to debug this manually on every new platform.
The Firehose programmer announces VIP activation by emitting an
"INFO: VIP is enabled, receiving the signed table of size N" log line
during startup. Watch for that marker in firehose_read() and use it in
firehose_detect_and_configure() to handle the two mismatch cases:
- --vip-table-path missing, programmer requires VIP: previously qdl
would send configure, the programmer would wait silently for a
signed table that never comes, and the user would see only a
generic 5s configure timeout. Now bail out immediately with an
explicit error pointing at the missing option.
- --vip-table-path given, programmer not in VIP mode: previously qdl
would push the signed digest table at the programmer, which tried
to parse those binary bytes as XML and bailed out with "Failed to
parse xml at offset 4090, 4096". Now detect the absence of the
marker after the startup-log drain, print a warning, demote
vip_data.state to VIP_DISABLED so the table is never sent, and
continue flashing normally.
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
When running on modern platforms it's observed that the Qualcomm USB
Drivers will discard the HELLO request from the device, so we're forced
to speculatively send a HELLO response on an initial timeout.
In the event that the device is already in Firehose mode (from a
previous --skip-reset run), the HELLO response will result in a XML
parse error in the programmer, for which we catch the "<?xml" prefix and
return to Firehose mode.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
The contents.xml provides two different "root path" tags, one with Linux
and one with Windows path delimiters. Use the Windows tag to avoid
issues related to path traversal.
Extend the tests as necessary.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
Sending an <erase> request without start_sector and num_sector
attributes, is considered by the programmer as a request to erase the
entire specified physical partition.
Encode the "erase all" as a erase op with zero num_sector to allow this.
The result is that "qdl firehose.elf erase 0" now erases the full first
physical partition.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
Requesting an erase of 0 sectors does not make logical sense, so in the
upcoming change this is made to represent an erase of the whole selected
physical partition - which is done by omitting num_sector and
start_sector from the <erase> sent to the programmer.
To avoid unexpected erasure of the full physical partition due to a
invalid <erase> tags in rawprogram.xml files, reject such entries during
parsing.
It's conceivable that it should be possible to express that request in
the rawprogram.xml, but until the semantics for that has been clarified,
reject requests with a zero-length erase.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
When the parsing any of the erase-tag attributes fails, the start_sector
might be leaked. Free the memory in the error path.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
Automated flashing pipelines often re-program identical content on every
run, which dominates total flash time on slow storage like spinor. With
the <getsha256digest> primitive now exposed, qdl can ask the device for
the SHA-256 of the target region before each <program> and skip the
write when it already matches what would have been sent.
Add --skipblock=<none|sha256>, defaulting to none. When sha256 is
selected, firehose_program() hashes the bytes it would otherwise stream
to the device - reading num_partition_sectors * SECTOR_SIZE_IN_BYTES
from the file with zero-padding for the trailing partial sector, exactly
matching what the existing chunked write path puts on the wire - then
asks the device for the digest of the same region via
firehose_getsha256digest(), reusing the op->digest field that the
sha256 subcommand path also reads. On a match, the <program> is skipped
entirely and "skipped \"<label>\" (sha256 match)" is logged in place of
the usual flashed-at-rate line.
The optimization is gated on three conditions, all enforced silently:
- !program->sparse: each sparse chunk would need its own digest;
keeping sparse images on the normal program path avoids per-chunk
round trips and the bookkeeping that would come with them.
- !program->is_nand: NAND spare/OOB byte semantics differ across
programmers, so the digest the device returns is not guaranteed to
correspond to the bytes qdl would compute locally.
- VIP disabled: <getsha256digest> is not part of pre-built VIP
digest tables, so issuing it under VIP would cause a hash mismatch
on the device.
Any failure on the optimization path - file read error, query failure,
digest absent, or digest mismatch - falls through to the normal program
flow. The file position is restored unconditionally by the existing
qdl_file_seek() at the top of the write loop, so the fall-through path
is byte-identical to --skipblock=none.
[1] https://github.com/linux-msm/qdl/issues/237
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
firehose.c is the firehose protocol layer; deciding what to do with a
digest (print it for the user, compare it to a locally-computed one)
is qdl policy. Move the result back onto struct firehose_op so the
parser can fill it directly, drop the local intermediate result struct,
and let firehose_run() return without emitting anything to stdout.
For the `sha256` subcommand, format and print each filled digest in
qdl_flash() once firehose_run() succeeds. The visible output for the
subcommand is unchanged.
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
The dependencies has been extended, but necessary dll files was not
added to the list of artifacts. Fix this to make it possible to run the
artifacts.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
Expose the FIREHOSE_OP_GET_SHA256_DIGEST primitive as a user-facing
verb. The syntax mirrors the existing read / write / erase verbs and
reuses parse_storage_address(), so addresses can be expressed as
<P>/<S>+<L>, by GPT partition name, or any of the other supported
forms.
Each invocation prints one lowercase 64-character hex digest per region
to stdout, so the output can be diffed against a sha256sum(1) line or
piped into other tooling without further parsing.
Typical use is verifying that what is on the device matches a known
local image - useful on shared bench machines where multiple people
flash the same board:
$ qdl prog_firehose_ddr.elf sha256 xbl_a
...
c288e50a94687a130a64db608c83678777ce5e7f9229248696c6f0dc41406cc9
$ qdl prog_firehose_ddr.elf read xbl_a xbl_a.bin
...
$ sha256sum xbl_a.bin
c288e50a94687a130a64db608c83678777ce5e7f9229248696c6f0dc41406cc9
Multiple sha256 verbs can be chained in a single invocation, with one
digest line emitted per region in order.
[1] https://github.com/linux-msm/qdl/issues/237
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
Firehose programmers can compute a SHA-256 over a region of flash on the
target side via the <getsha256digest> command, but qdl currently has no
way to issue it. Bench workflows that want to answer "what's actually
flashed on this board?" today have to read the partition back over USB
and hash it locally - slow on every storage type and particularly bad on
spinor.
Introduce a new firehose op type, FIREHOSE_OP_GET_SHA256_DIGEST, and a
matching firehose_getsha256digest() that builds the XML request with the
same address attributes used by <read> / <program> / <erase>
(SECTOR_SIZE_IN_BYTES, num_partition_sectors, physical_partition_number,
start_sector, and slot when applicable).
The digest response format is not consistent across Firehose variants.
Most implementations emit the digest inside a <log value="..."/> stream
prior to the ACK, but some attach it as an attribute on the <response>
itself. Add firehose_sha256_parser() which scans every incoming log
payload for a 64-hex-character run bounded by non-hex characters and,
as a fallback, probes the response node for Digest / SHA256 / sha256
attributes. The parser still defers ACK / NAK / rawmode handling to
firehose_generic_parser() so behaviour is identical to other commands
on the control path.
On success the digest is printed to stdout as a single lowercase
64-character hex line, separate from the ux_info / ux_log channels, so
it can be cleanly captured or piped without stripping prefixes.
gpt_resolve_deferrals() learns about the new op type so callers can
address regions by GPT partition name, matching the ergonomics of
<read>.
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
The libusb_open() call in usb_list() fails routinely on Windows
because the QDLoader 9008 driver claims matched devices. Printing a
warning per failing match drowns the actual rows that qdl list emits.
The open-attempt path in usb_open_attempt() still warns, so the
diagnostic survives where it is actionable.
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
Add a meta-backend QDL_DEVICE_AUTO that defers the transport choice
to qdl_open(): instead of picking libusb or QUD upfront, its open()
runs a unified wait loop and binds whichever transport first reaches
an EDL device. The "auto" --backend token (and the default) maps to
it.
Each 250 ms tick the loop does:
1. usb_open_attempt() - one libusb scan-and-open. On success the
libusb device is bound as the inner transport.
2. On Windows, if libusb saw the device but could not open it
(-EBUSY: the QDLoader 9008 driver has claimed the interface)
or SetupAPI sees a Qualcomm COM port libusb missed, calls
qud_open(). On success the QUD device is bound as the inner.
3. Otherwise sleeps and retries. No timeout: the loop waits
indefinitely, same cadence as the prior libusb-only loop.
qdl_read/write/close on the outer auto wrapper forward to the inner.
Pre-open out_chunk_size is stashed on the wrapper and applied at
bind time; vip_data and slot live on the outer where firehose
accesses them, so no forwarding is needed for those.
usb_open_attempt() (factored out of usb_open()) returns
0 / -ENODEV / -EBUSY / -EIO. The --backend usb path loops over it
with visibility-transition messaging. The auto loop owns its own
messaging and never emits the -EBUSY diagnostic because that
condition triggers the QUD attempt in the same tick.
qdl-ramdump now uses QDL_DEVICE_AUTO so Windows users with the
official driver can collect crash dumps without re-binding the USB
driver to WinUSB.
QDL_DEVICE_AUTO is explicitly a meta-backend, not a peer of the USB
and QUD backends: its job is to defer the transport choice to the
moment a probe reaches a device. The libusb and QUD backends remain
standalone and selectable via --backend usb / --backend qud.
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
firehose_read() previously assumed each qdl_read() returns a single
Firehose XML document. That holds on libusb (each USB bulk-in
transfer surfaces as its own read return), but not on stream-oriented
transports. The Windows COM port driver behind the QUD backend just
streams bytes into its RX buffer, and a single ReadFile() can deliver
several back-to-back Firehose responses concatenated; on top of that
the binary payload of a rawmode response (e.g. the sector data that
follows a <read> ACK) can be spliced onto the same buffer right after
the closing </data> tag.
Walk the read buffer using "<?xml" as the document start and
"</data>" as the envelope end, then dispatch each XML chunk through
the existing firehose_response_parse() + response_parser path.
<log/> and <response/> elements are still honoured in arrival order,
and rawmode is observed on whichever chunk carries it. When that
chunk is followed by trailing bytes, those bytes are the first
sectors of the binary payload: hand them to qdl_push_back() so the
next qdl_read() picks them up before the transport is touched again.
firehose_issue_read() now accumulates each sector-chunk across
qdl_read() calls instead of requiring a single full-sized return,
since on a stream transport the rawmode tail and the remaining
sector bytes generally arrive in several reads. libusb keeps
delivering an entire bulk transfer in one call, so the inner loop
runs once there.
The change is a no-op on libusb where each read already contains
exactly one document and the rawmode payload arrives in its own
bulk transfer; it unblocks all current and future stream-oriented
transports without touching the libusb path's behaviour.
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
Wire up an actual transport for the QUD backend on Windows. The
official QDLoader 9008 driver exposes a Qualcomm EDL device as a
serial port (\\.\COMx). The Sahara/Firehose framing on top is
identical to the libusb backend; this patch only deals with how
user space reaches the underlying bulk pipes.
Non-Windows hosts keep the stub from the previous patch.
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
Introduce QDL_DEVICE_QUD as a third device-transport flavour alongside
the libusb-based USB backend and the SIM backend used by --dry-run.
After this patch --backend=qud parses successfully but errors out at
init time on every host. The actual transport is added in a follow-up.
The intent is to support kernel-mode drivers that expose the EDL
device as a character file (e.g. the official QDLoader 9008 driver on
Windows, where the device shows up as \\.\COMx), so libusb is not
required on hosts where claiming the USB interface from user space is
inconvenient.
Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
The single-file format of the flashmap zip lends itself very well for
distributing builds, but the tools for generating one isn't broadly
available.
Implement a new "create-zip" operation in QDL, which parses a build from
a contents.xml, generates a flashmap.json and packages all the files
into a flashmap zip file.
The internal structure is flattened and file names are adjusted to avoid
conflicts.
Sparse files are written to the file by storing the relevant chunks in
their decoded form, rather than storing the sparse file (or full
unsparsed file). From an implementation point of view this is easier, as
we don't keep the sparsed program entry around, but it has the two
benefits of us not storing DONT_CARE entries, and it avoids the need for
seeking as we flash the zip file.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
Newer targets require multiple programmers to be used, and while the
current flashmap format does specify an array of programmers it does not
allow the Sahara id to be specified.
Replace the flat array with an object, keyed on the Sahara image id to
allow specifying the arbitrary number of programmers the platform might
need.
As this change has not made it into the formal specification, the
version is forked with a "-qdl" suffix.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
Introduce two initial set of test cases for the newly introduced
contents.xml handling.
One is used to validate the storage and flavor selector logic, and the
other more broadly the loading of contents.xml files.
Extract the common operation of creating a temporary directory to a new
file that is shared across tests.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
The typical usage of QDL so far has been for the user to manually
specify a programmer, as well as one or more program and patch XML
files, a so called "flat build". Some targets are built around multiple
storage medias (e.g. spinor + nvme), and some targets have a plethora of
sahara programmer files.
This puts a burden on the user to invoke qdl with the right combination
of storage selector, programmer(s), program and patch XML files. It also
adds an extra step to the build, in form of flattening the Qualcomm
builds.
The Qualcomm builds are described by a toplevel contents.xml file, which
describes to the various tools (e.g. the flattening tool) what
programmer, rawprogram, and patch files to use, and it provides mapping
of each referred file into the build directory structure.
The format also allow multiple "flavors" of flashable content to be
described, across multiple storage types.
Introduce support for parsing contents.xml files to allow the user to
flash non-flattened builds, across one or more storage devices and
filtered by select flavors.
The "qdl flash" operation is overloaded, to create a coherent user
experience. The filter/specifier interpretation is extended to allow
each, comma-separated, entry to describe storage types and flavors.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
There is a growing number of path concatenation cases, each built on
some memory allocation scheme and some variant of sprintf.
Introduce a pathbuf type and a few primitive operations to reset the
pathbuf, clone a pathbuf, push a path/filename to the pathbuf, get the
path, and truncate the path by dirname().
Also provide a convenient qdl_path_exist() operation to test if the
pathbuf refers to an existing file.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
The patch introducing the flash support updated the README, but didn't
update the usage printout. Fix this.
Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>