-
Notifications
You must be signed in to change notification settings - Fork 35
feat(ridesx): add QDL platform flasher for Qualcomm automotive SoCs #1028
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,4 +16,7 @@ def PexpectAdapter(*, client: DriverClient, method: str = "connect"): | |
| try: | ||
| yield fdspawn(sock) | ||
| finally: | ||
| sock.close() | ||
| try: | ||
| sock.close() | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we were hitting this |
||
| except OSError: | ||
| pass # fd already closed by fdspawn | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| __pycache__/ | ||
| .coverage | ||
| coverage.xml | ||
| htmlcov/ | ||
| .pytest_cache/ |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,8 +1,11 @@ | ||||||
| # RideSX Driver | ||||||
|
|
||||||
| `jumpstarter-driver-ridesx` provides functionality for Qualcomm RideSX devices, | ||||||
| supporting fastboot flashing operations and power control through serial communication. | ||||||
| It includes automatic compression handling (`.gz`, `.gzip`, `.xz`), built-in storage | ||||||
| `jumpstarter-driver-ridesx` provides functionality for Qualcomm automotive platforms: | ||||||
|
|
||||||
| - **RideSX** fastboot partition flashing | ||||||
| - **QDL platform flashing** (`QualcommFlasher`) for full firmware/bootloader updates on SA8775P, SA8650P, and related SoCs | ||||||
|
|
||||||
| RideSX support includes automatic compression handling (`.gz`, `.gzip`, `.xz`), built-in storage | ||||||
| for firmware images with upload/download capabilities, and direct access to the | ||||||
| underlying serial interface for custom commands. | ||||||
|
|
||||||
|
|
@@ -19,6 +22,8 @@ automotive-image-builder build --target ridesx4 --export aboot.simg --mode packa | |||||
| $ pip3 install --extra-index-url {{index_url}} jumpstarter-driver-ridesx | ||||||
| ``` | ||||||
|
|
||||||
| The QDL platform flasher (`QualcommFlasher`) is included in this package. The exporter host must provide `qdl` and `fastboot`. | ||||||
|
|
||||||
| ## Configuration | ||||||
|
|
||||||
| The RideSX driver supports two main components: | ||||||
|
|
@@ -154,3 +159,194 @@ power_client.cycle(wait=5) # Wait 5 seconds between off/on | |||||
| .. autoclass:: jumpstarter_driver_ridesx.client.RideSXPowerClient() | ||||||
| :members: on, off, cycle, rescue, serial | ||||||
| ``` | ||||||
|
|
||||||
| ## QDL platform flashing (`QualcommFlasher`) | ||||||
|
|
||||||
| Manifest-driven QDL/fastboot flashing for vendor firmware packages (ES13, ES21, ES22, CS4, CS5, …). | ||||||
| See `examples/exporter-platform.yaml` and reference manifests in | ||||||
| `jumpstarter_driver_ridesx/qdl/examples/manifests/`. | ||||||
|
|
||||||
| **driver**: `jumpstarter_driver_ridesx.qdl.driver.QualcommFlasher` | ||||||
|
|
||||||
| TAC serial handles power on/off and mode switching (EDL/fastboot). Export as `firmware` with | ||||||
| `tac`, `serial`, and `sail` children for identification. | ||||||
|
|
||||||
|
mangelajo marked this conversation as resolved.
mangelajo marked this conversation as resolved.
|
||||||
| ### Example exporter configuration | ||||||
|
|
||||||
| ```yaml | ||||||
| apiVersion: jumpstarter.dev/v1alpha1 | ||||||
| kind: ExporterConfig | ||||||
| metadata: | ||||||
| namespace: jumpstarter-lab | ||||||
| name: qualcomm-sa8775p | ||||||
| endpoint: | ||||||
| token: | ||||||
| export: | ||||||
| firmware: | ||||||
| type: "jumpstarter_driver_ridesx.qdl.driver.QualcommFlasher" | ||||||
| config: | ||||||
| soc_type: sa8775p | ||||||
| work_dir: /var/lib/jumpstarter/qualcomm | ||||||
| board_revision: v3 | ||||||
| power_cycle_delay: 2.0 | ||||||
| children: | ||||||
| tac: | ||||||
| ref: tac | ||||||
| serial: | ||||||
| ref: serial | ||||||
| sail: | ||||||
| ref: sail | ||||||
| tac: | ||||||
| type: "jumpstarter_driver_pyserial.driver.PySerial" | ||||||
| config: | ||||||
| url: "/dev/ttyACM0" | ||||||
| baudrate: 115200 | ||||||
| serial: | ||||||
| type: "jumpstarter_driver_pyserial.driver.PySerial" | ||||||
| config: | ||||||
| url: "/dev/ttyUSB1" | ||||||
| baudrate: 115200 | ||||||
| sail: | ||||||
| type: "jumpstarter_driver_pyserial.driver.PySerial" | ||||||
| config: | ||||||
| url: "/dev/ttyUSB2" | ||||||
| baudrate: 115200 | ||||||
| ``` | ||||||
|
|
||||||
| ### Config parameters | ||||||
|
|
||||||
| | Parameter | Description | Type | Required | Default | | ||||||
| | -------------------- | ---------------------------------------------------- | ----- | -------- | ------------------------------ | | ||||||
| | soc_type | SoC profile (`sa8775p`, `sa8540p1`, `sa8540p2`) | str | no | sa8775p | | ||||||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| | work_dir | Base directory for firmware extraction | str | no | /var/lib/jumpstarter/qualcomm | | ||||||
| | board_revision | Board revision for CDT image selection (`v1`–`v4`) | str | no | | | ||||||
| | qdl_timeout | Timeout for QDL subprocess steps (seconds) | int | no | 1800 | | ||||||
| | fastboot_timeout | Timeout for fastboot subprocess steps (seconds) | int | no | 600 | | ||||||
| | power_cycle_delay | Delay between power off/on (seconds) | float | no | 2.0 | | ||||||
| | tac_command_timeout | Timeout for TAC command acknowledgement (seconds) | float | no | 10.0 | | ||||||
|
|
||||||
| ### Required children | ||||||
|
|
||||||
| | Child | Description | Required for flash | Required for `id` | | ||||||
| | ------ | -------------------------------------- | ------------------ | ----------------- | | ||||||
| | tac | TAC serial for power and mode control | Yes | Yes | | ||||||
| | serial | Main boot serial console | No | Yes | | ||||||
| | sail | SAIL boot serial console | No | Yes | | ||||||
|
|
||||||
| ### CLI | ||||||
|
|
||||||
| Both the firmware archive and `--manifest` accept local paths or `http://` / `https://` URLs. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Read the repository layout guidance when present.
if [[ -f project-structure.md ]]; then
sed -n '1,180p' project-structure.md
fi
# Verify that HTTP is rejected before retrieval, or that trusted integrity
# verification occurs before QDL/fastboot execution.
rg -n -C 5 'urlopen|http://|https://|urlparse|hashlib|sha256|digest|signature|qdl|fastboot' \
python/packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/qdl/client.py \
python/packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/qdl/driver.py \
python/packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/qdl/client_test.pyRepository: jumpstarter-dev/jumpstarter Length of output: 22697 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Inspect the bounded download-to-flash path and its direct helpers.
rg -n -C 12 'def (_http_url_adapter|_manifest_data_from_source|flash_stream|_check_firmware)|execute_manifest|urlopen|url=' \
python/packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/qdl/client.py \
python/packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/qdl/driver.pyRepository: jumpstarter-dev/jumpstarter Length of output: 20873 Other (CWE-494): Download of Code Without Integrity Check Reachability: External · Exploitability: Moderate Do not support plaintext firmware or manifest URLs. Remove 🤖 Prompt for AI Agents |
||||||
| Firmware URLs are downloaded on the exporter. Manifest URLs are fetched by the client. | ||||||
|
|
||||||
| ```bash | ||||||
| # Flash firmware (manifest auto-discovered from archive) | ||||||
| j firmware flash https://example.com/firmware/sx4-r00021.1a.tar.xz | ||||||
|
|
||||||
| # Flash with explicit manifest | ||||||
| j firmware flash https://example.com/firmware/sx4-r00021.1a.tar.xz --manifest ./es22.yaml | ||||||
|
|
||||||
| # Cache firmware on the exporter for faster re-flashing | ||||||
| j firmware flash ./sx4-r00021.1a.tar.xz --cached | ||||||
|
|
||||||
| # Force re-download when cache is incomplete or corrupted | ||||||
| j firmware flash ./sx4-r00021.1a.tar.xz --cached --force-download | ||||||
|
|
||||||
| # Identify running firmware | ||||||
| j firmware id -v | ||||||
|
|
||||||
| # Check firmware matches expected variant | ||||||
| j firmware check ES22 --hypervisor prod --sail-fw-version 1.3.0 | ||||||
|
|
||||||
| # Boot into specific modes | ||||||
| j firmware boot-to-edl | ||||||
| j firmware boot-to-fastboot | ||||||
| ``` | ||||||
|
|
||||||
| Use `--cached` to keep extracted firmware on the exporter and reuse it on subsequent | ||||||
| flashes. Each source URL gets its own cache directory (namespaced by a hash of the URL) | ||||||
| under `work_dir/`, so different firmware archives never overwrite each other. | ||||||
|
|
||||||
| If a download is interrupted, the cache may be left in an incomplete state. Use | ||||||
| `--force-download` with `--cached` to clear the existing cache and re-download. | ||||||
|
|
||||||
| Archives may embed `jumpstarter_manifest.yaml`. See `examples/exporter-platform.yaml` for | ||||||
| exporter configuration and the QDL module for manifest schema details. | ||||||
|
|
||||||
| ### Board revision and CDT flash | ||||||
|
|
||||||
| Fastboot flash operations in the manifest can include a `revision` field to conditionally | ||||||
| flash based on the board hardware revision. The board revision is set via the | ||||||
| `board_revision` field in the exporter driver config. | ||||||
|
|
||||||
| When a flash operation has `revision` set and no board revision is configured, the | ||||||
| flash command fails with an error. | ||||||
|
|
||||||
| ### Manifest example | ||||||
|
|
||||||
| ABL and CDT flashing are regular fastboot steps in the manifest, giving full control over | ||||||
| ordering, retries, and device mode switching: | ||||||
|
|
||||||
| ```yaml | ||||||
| name: "SA8650P CS4 Firmware" | ||||||
| data: | ||||||
| folder: "r00010.1" | ||||||
| steps: | ||||||
| - set_mode: edl | ||||||
| check_dmesg: "qcserial" | ||||||
| - sleep: 5 | ||||||
| - name: "UFS provisioning" | ||||||
| retry_mode: edl | ||||||
| qdl: | ||||||
| storage: ufs | ||||||
| programmer: prog_firehose_ddr.elf | ||||||
| files: | ||||||
| - provision_default.xml | ||||||
| - sleep: 10 | ||||||
| - set_mode: edl | ||||||
| check_dmesg: "qcserial" | ||||||
| - name: "Flash UFS" | ||||||
| retry_mode: edl | ||||||
| qdl: | ||||||
| storage: ufs | ||||||
| programmer: prog_firehose_ddr.elf | ||||||
| files: | ||||||
| - "rawprogram*.xml" | ||||||
| - "patch*.xml" | ||||||
| - sleep: 30 | ||||||
| - set_mode: fastboot | ||||||
| check_dmesg: "Product: Android" | ||||||
| - name: "Flash ABL" | ||||||
| fastboot: | ||||||
| flash: | ||||||
| - partition: abl_a | ||||||
| file: qam8650p_abl_signed.elf | ||||||
| - partition: abl_b | ||||||
| file: qam8650p_abl_signed.elf | ||||||
| - name: "Flash CDT" | ||||||
| fastboot: | ||||||
| flash: | ||||||
| - partition: cdt | ||||||
| file: ufs/LEMANSAU_QAM_1.1.0.bin | ||||||
| revision: v1 | ||||||
| - partition: cdt | ||||||
| file: ufs/LEMANSAU_QAM_1.1.0.bin | ||||||
| revision: v2 | ||||||
| - partition: cdt | ||||||
| file: ufs/LEMANSAU_QAM_1.2.0.bin | ||||||
| revision: v3 | ||||||
| - partition: cdt | ||||||
| file: ufs/LEMANSAU_QAM_1.2.0.bin | ||||||
| revision: v4 | ||||||
| continue: true | ||||||
| ``` | ||||||
|
|
||||||
| The `revision` field on flash operations filters by board revision — only the matching | ||||||
| entry is flashed, the rest are skipped. The `continue: true` on the last fastboot step | ||||||
| tells the device to boot after flashing. | ||||||
|
|
||||||
| ### Requirements on exporter host | ||||||
|
|
||||||
| - `qdl` (Qualcomm download tool) | ||||||
| - `fastboot` | ||||||
| - USB access to the DUT in EDL/fastboot modes | ||||||
| - TAC serial device for mode switching | ||||||
|
mangelajo marked this conversation as resolved.
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| apiVersion: jumpstarter.dev/v1alpha1 | ||
| kind: ExporterConfig | ||
| metadata: | ||
| namespace: jumpstarter-lab | ||
| name: qualcomm-sa8775p | ||
| endpoint: <endpoint> | ||
| token: <token> | ||
| export: | ||
| firmware: | ||
| type: "jumpstarter_driver_ridesx.qdl.driver.QualcommFlasher" | ||
| config: | ||
| soc_type: sa8775p | ||
| work_dir: /var/lib/jumpstarter/qualcomm | ||
| board_revision: v3 | ||
| power_cycle_delay: 2.0 | ||
| children: | ||
| tac: | ||
| ref: tac | ||
| serial: | ||
| ref: serial | ||
| sail: | ||
| ref: sail | ||
| tac: | ||
| type: "jumpstarter_driver_pyserial.driver.PySerial" | ||
| config: | ||
| url: "/dev/ttyACM0" | ||
| baudrate: 115200 | ||
| serial: | ||
| type: "jumpstarter_driver_pyserial.driver.PySerial" | ||
| config: | ||
| url: "/dev/ttyUSB1" | ||
| baudrate: 115200 | ||
| sail: | ||
| type: "jumpstarter_driver_pyserial.driver.PySerial" | ||
| config: | ||
| url: "/dev/ttyUSB2" | ||
| baudrate: 115200 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """QDL platform firmware flashing for Qualcomm automotive SoCs.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we were hitting this problem on the firmware id.