Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit 0e02db4

Browse files
authored
Merge pull request #339 from jumpstarter-dev/flasher-driver
Flasher driver
2 parents 74d142c + e2bcc59 commit 0e02db4

32 files changed

Lines changed: 1808 additions & 64 deletions

File tree

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
# Flashers
2+
3+
The flasher drivers are used to flash images to DUTs via network,
4+
typically using TFTP and HTTP. It is designed to interact with
5+
the target bootloader and busybox shell to flash the DUT.
6+
7+
All flasher drivers inherit from the `jumpstarter_driver_flashers.driver.BaseFlasher`
8+
class, referencing their own bundle of binary artifacts necessary to flash the DUT,
9+
like kernel/initram/dtbs. See the [bundle](#oci-bundles) section for more details.
10+
11+
## Available drivers and bundles
12+
13+
| Driver | Bundle |
14+
|-----------------|---------------------------------------------------------------|
15+
| TIJ784S4Flasher | quay.io/jumpstarter-dev/jumpstarter-flasher-ti-j784s4:latest |
16+
17+
18+
## Driver configuration
19+
**driver**: `jumpstarter_driver_flashers.driver.${DRIVER}`
20+
21+
```yaml
22+
export:
23+
storage:
24+
type: "jumpstarter_driver_flashers.driver.TIJ784S4Flasher"
25+
children:
26+
serial:
27+
ref: "serial"
28+
power:
29+
ref: "power"
30+
serial:
31+
type: "jumpstarter_driver_pyserial.driver.PySerial"
32+
config:
33+
url: "/dev/serial/by-id/usb-FTDI_USB__-__Serial_Converter_112214101760A-if00-port0"
34+
baudrate: 115200
35+
power:
36+
type: jumpstarter_driver_yepkit.driver.Ykush
37+
config:
38+
serial: "YK112233"
39+
port: "1"
40+
```
41+
42+
flasher drivers require four children drivers:
43+
| Child Driver | Description | Auto-created |
44+
|--------------|-------------|--------------|
45+
| serial | To communicate with the DUT via serial and drive the bootloader and busybox shell | No |
46+
| power | To power on and off the DUT | No |
47+
| tftp | To serve binaries via TFTP | Yes |
48+
| http | To serve the images via HTTP | Yes |
49+
50+
In the above example we provide the serial and power children by [reference](./proxy.md), so those
51+
remain also available on the root of the exporter.
52+
53+
The power driver is used to control power cycling of the DUT, and the serial interface
54+
is used to communicate with the DUT bootloader via serial. TFTP and HTTP servers are
55+
used to serve images to the DUT bootloader and busybox shell.
56+
57+
### Config parameters
58+
59+
| Parameter | Description | Type | Required | Default |
60+
|-----------|-------------|------|----------|---------|
61+
| flasher_bundle | The OCI bundle to use for the flasher | str | yes | |
62+
| cache_dir | The directory to cache the images | str | no | /var/lib/jumpstarter/flasher |
63+
| tftp_dir | The directory to serve the images via TFTP | str | no | /var/lib/tftpboot |
64+
| http_dir | The directory to serve the images via HTTP | str | no | /var/www/html |
65+
66+
67+
## BaseFlasher API
68+
69+
The `BaseFlasher` class provides a set of methods to flash the DUT,
70+
```{eval-rst}
71+
.. autoclass:: jumpstarter_driver_flashers.client.BaseFlasherClient()
72+
:members: flash, busybox_shell, bootloader_shell, use_dtb, use_initram, use_kernel
73+
```
74+
75+
## CLI
76+
77+
The flasher driver provides a CLI to perform flashing, access to busybox shell and uboot.
78+
79+
<!--
80+
This doesn't work with sphinx-click, so we'll just use the raw CLI
81+
```
82+
.. click:: jumpstarter_driver_flashers.client:BaseFlasherClient.cli
83+
:prog: flasher
84+
:nested: full
85+
```
86+
-->
87+
```bash
88+
$ jmp client shell -l board ti-03
89+
INFO:jumpstarter.client.lease:Created lease request for labels {'board': 'ti-03'} for 0:30:00
90+
jumpstarter ⚡remote ➤ j storage
91+
Usage: j storage [OPTIONS] COMMAND [ARGS]...
92+
93+
Software-defined flasher interface
94+
95+
Options:
96+
--help Show this message and exit.
97+
98+
Commands:
99+
bootloader-shell Start a uboot/bootloader interactive console
100+
busybox-shell Start a busybox shell
101+
flash Flash image to DUT from file
102+
103+
```
104+
105+
### flash
106+
```bash
107+
Usage: j storage flash [OPTIONS] FILE
108+
109+
Flash image to DUT from file
110+
111+
Options:
112+
--partition TEXT
113+
--os-image-checksum TEXT SHA256 checksum of OS image (direct value)
114+
--os-image-checksum-file FILE File containing SHA256 checksum of OS image
115+
--force-exporter-http Force use of exporter HTTP
116+
--force-flash-bundle TEXT Force use of a specific flasher OCI bundle
117+
--console-debug Enable console debug mode
118+
--help Show this message and exit.
119+
```
120+
121+
Example:
122+
```
123+
jumpstarter ⚡remote ➤ j storage flash https://autosd.sig.centos.org/AutoSD-9/nightly/TI/auto-osbuild-am69sk-autosd9-qa-regular-aarch64-1716106242.66b4d866.raw.xz
124+
BaseFlasherClient - INFO - Writing image to storage in the background: /AutoSD-9/nightly/TI/auto-osbuild-am69sk-autosd9-qa-regular-aarch64-1716106242.66b4d866.raw.xz
125+
BaseFlasherClient - INFO - Setting up flasher bundle files in exporter
126+
BaseFlasherClient - INFO - Writing image from storage, with metadata: md5=None,size=592736176 etag="23546fb0-63045567a5b80"
127+
SNMPServerClient - INFO - Starting power cycle sequence
128+
SNMPServerClient - INFO - Waiting 2 seconds...
129+
SNMPServerClient - INFO - Power cycle sequence complete
130+
BaseFlasherClient - INFO - Waiting for U-Boot prompt...
131+
BaseFlasherClient - INFO - Running DHCP to obtain network configuration...
132+
BaseFlasherClient - INFO - Running command: dhcp
133+
BaseFlasherClient - INFO - Running command: printenv netmask
134+
BaseFlasherClient - INFO - discovered dhcp details: DhcpInfo(ip_address='x.x.x.x', gateway='x.x.x.x', netmask='255.255.255.0')
135+
BaseFlasherClient - INFO - Image written to storage: /AutoSD-9/nightly/TI/auto-osbuild-am69sk-autosd9-qa-regular-aarch64-1716106242.66b4d866.raw.xz
136+
BaseFlasherClient - INFO - Running command: setenv serverip 'x.x.x.x'
137+
BaseFlasherClient - INFO - Running command: tftpboot 0x82000000 J784S4XEVM.flasher.img
138+
BaseFlasherClient - INFO - Running command: tftpboot 0x84000000 k3-j784s4-evm.dtb
139+
BaseFlasherClient - INFO - Running boot command: booti 0x82000000 - 0x84000000
140+
BaseFlasherClient - INFO - Using target block device: /dev/mmcblk1
141+
BaseFlasherClient - INFO - Running preflash command: dd if=/dev/zero of=/dev/mmcblk0 bs=512 count=34
142+
BaseFlasherClient - INFO - Running preflash command: dd if=/dev/zero of=/dev/mmcblk1 bs=512 count=34
143+
BaseFlasherClient - INFO - Waiting until the http image preparation in storage is completed
144+
BaseFlasherClient - INFO - Flash progress: 25.00 MB, Speed: 15.78 MB/s
145+
...
146+
...
147+
BaseFlasherClient - INFO - Flash progress: 5086.12 MB, Speed: 13.77 MB/s
148+
BaseFlasherClient - INFO - Flash progress: 5102.94 MB, Speed: 12.93 MB/s
149+
BaseFlasherClient - INFO - Flushing buffers
150+
BaseFlasherClient - INFO - Flashing completed in 7:26
151+
BaseFlasherClient - INFO - Powering off target
152+
```
153+
154+
### bootloader-shell
155+
```bash
156+
Usage: j storage bootloader-shell [OPTIONS]
157+
158+
Start a uboot/bootloader interactive console
159+
160+
Options:
161+
--console-debug Enable console debug mode
162+
--help Show this message and exit.
163+
```
164+
165+
Example
166+
```
167+
jumpstarter ⚡remote ➤ j storage bootloader-shell
168+
BaseFlasherClient - INFO - Setting up flasher bundle files in exporter
169+
SNMPServerClient - INFO - Starting power cycle sequence
170+
SNMPServerClient - INFO - Waiting 2 seconds...
171+
SNMPServerClient - INFO - Power cycle sequence complete
172+
BaseFlasherClient - INFO - Waiting for U-Boot prompt...
173+
=> version
174+
U-Boot 2024.01-rc3 (Jan 09 2024 - 00:00:00 +0000)
175+
176+
gcc (GCC) 11.4.1 20231218 (Red Hat 11.4.1-3)
177+
GNU ld version 2.35.2-42.el9
178+
```
179+
### busybox-shell
180+
```bash
181+
Usage: j storage busybox-shell [OPTIONS]
182+
183+
Start a busybox interactive console
184+
185+
Options:
186+
--console-debug Enable console debug mode
187+
--help Show this message and exit.
188+
```
189+
190+
Example
191+
```
192+
jumpstarter ⚡remote ➤ j storage busybox-shell
193+
BaseFlasherClient - INFO - Setting up flasher bundle files in exporter
194+
SNMPServerClient - INFO - Starting power cycle sequence
195+
SNMPServerClient - INFO - Waiting 2 seconds...
196+
SNMPServerClient - INFO - Power cycle sequence complete
197+
BaseFlasherClient - INFO - Waiting for U-Boot prompt...
198+
BaseFlasherClient - INFO - Running DHCP to obtain network configuration...
199+
BaseFlasherClient - INFO - Running command: dhcp
200+
BaseFlasherClient - INFO - Running command: printenv netmask
201+
BaseFlasherClient - INFO - discovered dhcp details: DhcpInfo(ip_address='10.26.28.138', gateway='10.26.28.254', netmask='255.255.255.0')
202+
BaseFlasherClient - INFO - Running command: setenv serverip '10.26.28.62'
203+
BaseFlasherClient - INFO - Running command: tftpboot 0x82000000 J784S4XEVM.flasher.img
204+
BaseFlasherClient - INFO - Running command: tftpboot 0x84000000 k3-j784s4-evm.dtb
205+
BaseFlasherClient - INFO - Running boot command: booti 0x82000000 - 0x84000000
206+
# uname -a
207+
Linux buildroot 6.1.46-dirty #2 SMP PREEMPT Thu Mar 14 14:37:01 UTC 2024 aarch64 GNU/Linux
208+
#
209+
```
210+
211+
## Examples
212+
213+
Flash the device with a specific image
214+
```python
215+
flasherclient.flash("/path/to/image.raw.xz")
216+
```
217+
218+
Flash the device with a specific image from a remote URL
219+
```python
220+
flasherclient.flash("https://autosd.sig.centos.org/AutoSD-9/nightly/TI/auto-osbuild-j784s4evm-autosd9-qa-regular-aarch64-1716106242.66b4d866.raw.xz")
221+
```
222+
223+
Flash into a specific partition
224+
```python
225+
flasherclient.flash("/path/to/image.raw.xz", partition="emmc")
226+
```
227+
228+
229+
## Examples of utility consoles
230+
231+
In addition to the flashing mechanisms, the flasher drivers also provide a way to
232+
access the DUT bootloader and busybox shell for convenience and debugging, when using
233+
the `busybox_shell` and `bootloader_shell` methods the embedded http and tftp servers
234+
will be online and serving the images from the flasher bundle.
235+
236+
Get the busybox shell on the device
237+
```python
238+
with flasherclient.busybox_shell() as serial:
239+
serial.send("ls -la\n")
240+
serial.expect("#")
241+
print(serial.before)
242+
```
243+
244+
Get the bootloader shell on the device
245+
```python
246+
with flasherclient.bootloader_shell() as serial:
247+
serial.send("version\n")
248+
serial.expect("=>")
249+
print(serial.before)
250+
```
251+
252+
# oci-bundles
253+
The flasher drivers require some artifacts and basic information about the target device
254+
to operate. To make this easy to distribute and use, we use OCI bundles to package the
255+
artifacts and metadata.
256+
257+
The bundle is a container that uses [oras](https://oras.land/) to transport the artifacts
258+
and metadata. It is a container that contains the following:
259+
- `manifest.yaml`: The manifest file that describes the bundle
260+
- `data/*`: The artifacts, including kernel, initram, dtbs, etc.
261+
262+
## The format of the manifest is as follows:
263+
264+
```{literalinclude} ../../../../packages/jumpstarter-driver-flashers/oci_bundles/test/manifest.yaml
265+
:language: yaml
266+
```
267+
## Table with the spec fields of the manifest:
268+
| Field | Description | Default |
269+
|-------|-------------|---------|
270+
| `manufacturer` | Name of the device manufacturer | |
271+
| `link` | URL to device documentation or manufacturer website | |
272+
| `bootcmd` | Command used to boot the device (e.g. booti, bootz) | |
273+
| `default_target` | Default target device to flash to if none specified | |
274+
| `targets` | Map of target names to device paths | |
275+
| `login.type` | Type of login shell | busybox |
276+
| `login.login_prompt` | Expected login prompt string | login: |
277+
| `login.username` | Username to log in with, leave empty if not needed | |
278+
| `login.password` | Password for login, leave empty if not needed | |
279+
| `login.prompt` | Shell prompt after successful login | # |
280+
| `preflash_commands` | List of commands to run before flashing, useful to clear boot entries, etc | |
281+
| `kernel.file` | Path to kernel image within bundle |
282+
| `kernel.address` | Memory address to load kernel to | |
283+
| `initram.file` | Path to initramfs within bundle (if any)| |
284+
| `initram.address` | Memory address to load initramfs to (if any) | |
285+
| `dtb.default` | Default DTB variant to use | |
286+
| `dtb.address` | Memory address to load DTB to | |
287+
| `dtb.variants` | Map of DTB variant names to files |
288+
289+
290+
## Examples
291+
292+
An example bundle for the TI J784S4XEVM looks like this:
293+
294+
```{literalinclude} ../../../../packages/jumpstarter-driver-flashers/oci_bundles/ti_j784s4xevm/manifest.yaml
295+
:language: yaml
296+
```
297+
298+
You can find a script to build and push a bundle to a registry here:
299+
[oci_bundles](https://github.com/jumpstarter-dev/jumpstarter/tree/main/packages/jumpstarter-driver-flashers/oci_bundles)
300+

docs/source/api-reference/drivers/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Drivers packages from the [drivers](https://github.com/jumpstarter-dev/jumpstart
1010
:maxdepth: 2
1111
can.md
1212
dbus.md
13+
flashers.md
1314
network.md
1415
opendal.md
1516
proxy.md

docs/source/api-reference/drivers/pyserial.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
**driver**: `jumpstarter_driver_pyserial.driver.PySerial`
44

5-
The methods of this client are dynamic, and they are generated from
6-
the `methods` field of the exporter driver configuration.
7-
85
## Driver configuration
96
```yaml
107
export:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
__pycache__/
2+
.coverage
3+
coverage.xml
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Jumpstarter Driver for Software driven flashing
2+
3+
Some platforms provide on-board storage which cannot be externally tapped
4+
or flashed. Flashing those devices during testing requires driving
5+
the DUT into the right state through the bootloader or other means so the
6+
storage contents can be transferred through network into the internal storage.
7+
8+
This driver provides a set of base drivers and clients to implement
9+
the FlasherInterface for those target platforms, as well as some specific
10+
implementations.
11+
12+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
apiVersion: jumpstarter.dev/v1alpha1
2+
kind: ExporterConfig
3+
metadata:
4+
namespace: default
5+
name: demo
6+
endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
7+
token: "<token>"
8+
export:
9+
storage:
10+
type: "jumpstarter_driver_flashers.driver.TIJ784S4Flasher"
11+
children:
12+
serial:
13+
ref: "serial"
14+
power:
15+
ref: "power"
16+
# tftp and http driver are automatically created when not specified, cannot be specified via ref
17+
# tftp:
18+
# type: "jumpstarter_driver_tftp.driver.TftpServer"
19+
# http
20+
serial:
21+
type: "jumpstarter_driver_pyserial.driver.PySerial"
22+
config:
23+
url: "/dev/serial/by-id/usb-FTDI_USB__-__Serial_Converter_112214101760A-if00-port0"
24+
baudrate: 115200
25+
power:
26+
type: jumpstarter_driver_yepkit.driver.Ykush
27+
config:
28+
serial: "YK112233"
29+
port: "1"

packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)