Skip to content

tools: Flashpack - a tool to flash vamOS#94

Open
mpurnell1 wants to merge 43 commits intocommaai:masterfrom
mpurnell1:flash
Open

tools: Flashpack - a tool to flash vamOS#94
mpurnell1 wants to merge 43 commits intocommaai:masterfrom
mpurnell1:flash

Conversation

@mpurnell1
Copy link
Copy Markdown
Contributor

@mpurnell1 mpurnell1 commented Mar 29, 2026

Summary

Browser-based tool to flash vamOS onto comma devices via WebUSB.

Features

  • Full flash pipeline ported from flash.comma.ai: GPT repair, erase, flash all partitions, set active slot, reboot
  • Device picker (comma 3/3X vs comma four) with product images and device-specific port diagrams
  • Platform-aware wizard: Windows Zadig driver step, Linux qcserial unbind step (3/3X only)
  • Manifest-driven: fetches VERSION from master, loads manifest from v{VERSION} branch
  • Chunk reassembly for images >50MB (system, modem, cache) via OPFS
  • Streaming downloads with retry logic
  • Skips partitions not found on the connected device
  • Stepper navigation to go back to previous steps
  • Built with Bun using @commaai/qdl, deployed via GitHub Pages
  • Tested on device (comma 3X)

Future work

  • Move images to a separate repo to avoid bloating clones (~1.8GB on version branch)
  • Show the commit hash of the fetched images (like flash.comma.ai shows its version)
  • Branch/version selector for flashing dev builds from branches other than master
  • Error messages could be more specific per failure type (like flash.comma.ai's error codes)
  • Debug info / bug report panel for troubleshooting
  • OTA update support (flash only changed partitions)

mpurnell1 and others added 19 commits March 29, 2026 02:06
Static HTML page using qdl.js (WebUSB) to flash boot.img and system.img
onto comma devices. Deployed via GitHub Pages from docs/.

- File picker for boot/system images with nightly.link CI download links
- Flashes boot to both A/B slots, system to slot A
- Sets active slot and reboots
- Linux qcserial unbind instructions
- GitHub Pages deployment workflow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@commaai/qdl is not published to npm, so esm.sh returned 404 and the
entire module script failed to load. Use esm.sh's GitHub source mode
instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
esm.sh's transitive dependency on tiny-struct from npm.jsr.io was served
as application/octet-stream, which browsers reject for ES module imports.
Bundle qdl.js and usblib.js with all dependencies using bun build and
serve them as local static files instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The flash page now auto-downloads all images from the vamOS GitHub
release via a Cloudflare Worker CORS proxy. No more manual file
picking: hit Start, connect device, everything flashes automatically.

Flow: fetch manifest -> connect device -> repair GPT -> flash firmware
-> flash boot (A/B) -> flash system (A) -> set active slot -> reboot

The proxy URL is a single constant to swap to Azure CDN for production.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Proper bun project using @commaai/qdl as a package dependency
- TypeScript source bundled with Bun.build()
- Geocities/oopsiedoodle aesthetic: Comic Neue, starfield, rainbow
  gradients, neon colors, playful copy
- File picker for boot.img and system.img with release download link
- Updated pages workflow to build from tools/flash/dist/
- Removed old docs/flash/ static files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Port the full flash pipeline from commaai/flash:
- FlashManager: connect -> repair GPT -> erase -> flash all partitions
  -> set active slot -> reboot
- ImageManager: OPFS-backed image download and caching
- Manifest fetched from latest GitHub release via API
- Stream utility with retry and progress tracking

Also: more Dora energy throughout the UI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Manifest and image URLs are rewritten to go through the proxy at
PROXY_BASE. One constant to swap to Azure CDN for production.

Worker proxies github.com/commaai/vamOS/releases/download/* and adds
Access-Control-Allow-Origin: *

Deploy: npx wrangler deploy tools/flash/worker.js --name vamos-release-proxy

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Some partitions in the manifest (e.g. splash_cc) don't exist on all
device variants. Check with detectPartition before flashing and skip
if not found.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fetch manifest and images directly from the release-images branch via
raw.githubusercontent.com (CORS-safe). Chunked images are downloaded
sequentially and reassembled in OPFS.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Manifest changed from a flat array to {version, images}. Unwrap
.images before passing to FlashManager, log the version.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Read VERSION from master, then fetch manifest from v{VERSION} branch
to match the new CI branch naming.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mpurnell1
Copy link
Copy Markdown
Contributor Author

Try it out at https://mpurnell1.github.io/vamOS/

mpurnell1 and others added 10 commits March 29, 2026 02:12
The OPFS writable stream wasn't being closed after downloading chunks,
leaving the file incomplete. pipeTo closes it automatically for
single-file downloads, but the chunked path needs an explicit close.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Device picker: comma 3/3X vs comma four with product images
- Device-specific connect instructions with port diagrams from flash repo
- Unbind step: separate screen, only shown on Linux + comma 3/3X
- WebUSB connect is now its own step after connect/unbind
- Dynamic stepper labels based on device + platform

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The rename to tools/flashpack/ accidentally moved the CLI flash scripts
(kernel.sh, system.sh, firmware.sh, gpt.sh). These belong in
tools/flash/ and are used by ./vamos flash.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Clicking a completed step dot navigates back to that step. Only
pre-flash steps (Device, Connect, Unbind) are navigable. Flash and
Done steps can't be navigated to from the stepper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Zadig driver install step shown on Windows between Device and Connect
- Going back to Device resets selectedDevice so stepper recalculates
- All stepper indices use getStepLabels().indexOf() instead of hardcoded numbers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Stepper shows step names (Device, Connect, Unbind, Flash) instead of
numbers, matching flash.comma.ai. Going back to Device preserves the
previous selection so the step count stays stable. Completed steps
are clickable with hover state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Trey Moen <50057480+greatgitsby@users.noreply.github.com>
* Revert "use versioned branch names for release images (commaai#93)"

This reverts commit a4842a7.

* Revert "ci: push release images to branch instead of GitHub release (commaai#90)"

This reverts commit c937d27.
* ci: fix PR comment for fork PRs using pull_request_target

GITHUB_TOKEN for pull_request events from forks only gets read permissions,
so the rootfs profile comment fails. Move the comment posting to a separate
workflow using pull_request_target (which runs in the base repo context with
write permissions), matching openpilot's pattern.

* ci: rename pr-comment.yml to profile.yml
Upgrade wait-on-check-action to v1.6.0 and add checks-discovery-timeout
so it waits up to 5 minutes for build-system to appear instead of
immediately failing when the check doesn't exist yet.
* ci: publish images to vamos-images repo, manifest as release

Images are committed to {owner}/vamos-images with a version tag,
so forks can publish to their own vamos-images repo. The manifest
is published as a GitHub Release on vamOS itself.

* build: restore chunking for large images in package_ota

Files over 50 MB are split into chunks to stay under
raw.githubusercontent.com's 100 MB limit.

* build: derive default IMAGES_URL from VERSION file

* ci: skip publish gracefully when deploy key is missing

Shows setup instructions as workflow warnings instead of failing.

* ci: fix profile workflow race with build-system check

Upgrade wait-on-check-action to v1.6.0 and add checks-discovery-timeout
so it waits up to 5 minutes for build-system to appear instead of
immediately failing when the check doesn't exist yet.

* Revert "ci: fix profile workflow race with build-system check"

This reverts commit b1d74fd.

* ci: fix ambiguous refspec when pushing images tag

Use an unrelated orphan branch name and push with refs/tags/ prefix
to avoid ambiguity between branch and tag with the same name.

* ci: include chunked image files in vamos-images push

The glob *.img missed chunk files (*.img.00, *.img.01, etc.)
produced by the chunking logic for large images like system.

* ci: include manifest in vamos-images, link from release

Manifest needs CORS headers, which raw.githubusercontent.com provides
but release-assets.githubusercontent.com does not.

* ci: fix invalid YAML in release notes multiline string
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

vamOS System Profile

Changes vs master

Metric Change
Used space 3485.6MB → 3485.7MB (+.1MB)
Sparse image 3440.0MB → 3440.2MB (+.2MB)
Package count 524 → 524

Added packages: gi-docgen-2026.1_1, glib-2.88.0_1, glib-devel-2.88.0_1, libglib-devel-2.88.0_1

Removed packages: gi-docgen-2025.4_2, glib-2.86.1_2, glib-devel-2.86.1_2, libglib-devel-2.86.1_2

Directory size changes (>1MB)
Directory Change

Metric Value
Used space 3485.7MB / 5959.5MB
Files 56332
Directories 4762
Symlinks 3602
Packages 524

Top 10 Directories

Directory Size

Category Breakdown

Category Size %
xbps packages 2489.5MB 71.4%
Python venv 655.3MB 18.8%
Firmware 11.5MB .3%
Other 329.2MB 9.4%

Top 10 Packages by Size

Package Size
mit-krb5-libs-1.21.3_1 270.4MB
gawk-5.3.2_1 210.3MB
llvm-21_3 148.6MB
libldns-1.9.0_1 124.3MB
pd-mapper-1.0_1 73.9MB
libclang21-21.1.7_1 70.2MB
glib-2.88.0_1 67.4MB
gcc-14.2.1+20250405_4 65.4MB
libcap-progs-2.77_1 56MB
cmake-4.2.2_1 53.2MB

Top 30 Files by Size

File Size
/usr/lib/llvm/21/lib/libLLVM.so.21.1 124.3MB
/usr/lib/llvm/21/lib/libMLIR.so.21.1 89.7MB
/usr/lib/llvm/21/bin/mlir-transform-opt 82.9MB
/usr/lib/llvm/21/lib/libclang-cpp.so.21.1 56MB
/usr/lib/llvm/21/bin/mlir-translate 53.2MB
/usr/lib/llvm/21/bin/llvm-exegesis 52MB
/usr/lib/llvm/21/bin/llvm-bolt-binary-analysis 50.6MB
/usr/local/venv/lib/python3.12/site-packages/ffmpeg/install/lib/libavcodec.a 50.5MB
/usr/bin/uv 48.1MB
/usr/lib/gcc/aarch64-linux-gnu/14.2/gnat1 40.1MB
/usr/bin/gdb 38.1MB
/usr/lib/gcc/aarch64-linux-gnu/14.2/cc1plus 37.3MB
/usr/lib/libgallium-25.3.3.so 35.4MB
/usr/lib/libllvm-qcom.so 35.2MB
/usr/lib/gcc/aarch64-linux-gnu/14.2/cc1 35.2MB
/usr/lib/gcc/aarch64-linux-gnu/14.2/lto1 33.9MB
/usr/bin/lto-dump 33.9MB
/usr/lib/libRusticlOpenCL.so.1.0.0 32.5MB
/usr/local/venv/bin/ruff 31.8MB
/usr/share/icu/78.2/icudt78l.dat 31.5MB
/usr/lib/llvm/21/lib/libclang.so.21.1.7 30.2MB
/usr/lib/llvm/21/bin/c-index-test 28.6MB
/usr/local/venv/lib/python3.12/site-packages/gcc_arm_none_eabi/toolchain/libexec/gcc/arm-none-eabi/13.2.1/cc1 28.2MB
/usr/lib/libz3.so 27.9MB
/usr/bin/run 26.6MB
/usr/local/venv/lib/python3.12/site-packages/numpy.libs/libscipy_openblas64_-71e1b124.so 23.6MB
/usr/comma/updater 23.5MB
/usr/comma/setup 23.5MB
/usr/comma/reset 23.5MB
/usr/local/uv/python/cpython-3.12.13-linux-aarch64-gnu/bin/python3.12 22.1MB

Copy link
Copy Markdown
Collaborator

@greatgitsby greatgitsby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple feedback, nothing major

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants