A collection of recipes to build Qualcomm Linux images for deb based operating systems.
The main goal of this project is to provide mainline-centric images for Qualcomm® IoT platforms as to demonstrate the state of upstream open source software, help developers getting started, and support continuous development and testing efforts.
Initially, this repository provides debos recipes based on Debian trixie for boards such as:
- Qualcomm RB1 (QRB2210)
- Qualcomm RB3 Gen 2 (QCS6490)
- ...and more!
We are also working towards providing ready-to-use, pre-built images – stay tuned!
| Variant | Image build & test status |
|---|---|
| Qualcomm Linux | |
| Debian | |
| Reference upstream kernels | |
| Project-specific builds |
Every image is flashed onto real boards and tested in the LAVA lab; see docs/testing.md for which boards run which tests and how to change that. See docs/workflows.md for when the scheduled builds run and why.
OpenVEX data, its validation tooling, and authoring instructions live on the
security-tracker branch.
The debos workflow fetches vex/ from that branch's HEAD and passes the
documents to Grype. Pull requests targeting security-tracker validate the
data before merging.
The workflow also uses the tracker's vex-check.py --coverage-only to report
missing binaries and outdated version pins against the image SBOM. These
warnings appear in the job log and summary; they do not fail the build.
debos is required to build the debos recipes. Recent debos packages should be available in Debian and Ubuntu repositories; there are debos installation instructions on the project's page, notably for Docker images and to build debos from source. Make sure to use at least version 1.1.5 which supports setting the sector size.
qdl is typically used for flashing. While recent versions are available in Debian and Ubuntu, make sure to use at least version 2.1 as it contains important fixes.
U-Boot is needed for the RB1 board. If you are not targeting this board, you can go to the next section.
Building U-Boot for the RB1 requires the following extra build-dependencies:
apt -y install git crossbuild-essential-arm64 make bison flex bc libssl-dev gnutls-dev xxd coreutils gzip mkbootimgTo build U-Boot for the RB1, run:
scripts/build-u-boot-rb1.shBy default the image recipes install linux-image-qcom-next, the Qualcomm
Linux kernel package; see the Kernel section for details.
Build a custom kernel if you want to run your own qcom-next tree, mainline
or linux-next instead. See the Kernel section for the
build-dependencies and the build instructions, then come back here.
Building the image requires the following build-dependencies:
apt -y install debian-archive-keyring make mmdebstrap mtools python3-pexpect python3-pytest qemu-efi-aarch64 qemu-system-arm xmlstarlet python3-defusedxmlTo build flashable assets for all supported boards, follow these steps:
-
build tarballs of the root filesystem and DTBs
make rootfs.tar # (optional) if you've built a local kernel, copy it to `debos-recipes/local-debs/` # and run this instead: #EXTRA_DEBOS_OPTS="-t localdebs:local-debs/ -t kernelpackages:none" make rootfs.tar
-
build disk and filesystem images from the root filesystem tarball
# the default is to build a UFS image make disk-ufs.img # (optional) if you want SD card images or support for eMMC boards, run # this as well: make disk-sdcard.img
-
build flashable assets from downloaded boot binaries, the DTBs, and pointing at the UFS/SD card disk images
make flash # (optional) if you've built U-Boot for the RB1, run this instead: #EXTRA_DEBOS_OPTS="-t u_boot_rb1:u-boot/rb1-boot.img" make flash # (optional) build only a subset of boards: #EXTRA_DEBOS_OPTS="-t target_boards:qcs615-ride,qcs6490-rb3gen2-vision-kit" make flash
-
enter Emergency Download Mode (see section below) and flash the resulting images with QDL
# for RB3 Gen2 Vision Kit or UFS boards in general cd flash_qcs6490-rb3gen2-vision-kit_ufs qdl --storage ufs prog_firehose_ddr.elf rawprogram[0-9].xml patch[0-9].xml # for RB1 or eMMC boards in general cd flash_qrb2210-rb1_emmc qdl --allow-missing --storage emmc prog_firehose_ddr.elf rawprogram[0-9].xml patch[0-9].xml
By default, debos will try to pick a fast build backend. It will prefer to use its KVM backend (-b kvm) when available, and otherwise a UML environment (-b uml). If none of these work, a solid backend is QEMU (-b qemu). Because the target images are arm64, building under QEMU can be really slow, especially when building from another architecture such as amd64.
To build large images, the debos resource defaults might not be sufficient. Consider raising the default debos memory and scratchsize settings. This should provide a good set of minimum defaults:
debos --fakemachine-backend qemu --memory 1GiB --scratchsize 12GiB debos-recipes/qualcomm-linux-debian-image.yamlA few options are provided in the debos recipes; for the root filesystem recipe:
localdebs: path to a directory with local deb packages to install (NB: debos expects relative pathnames)variant: select the rootfs content to install; defaults toconsole. See the Supported variants section below.xfcedesktop,gnomedesktop,westonsession,multimedia: deprecated, superseded byvariant; still accepted for backwards compatibility (with a 10 second warning) and mapped onto the equivalentvariantvalue. Setting any of these together withvariant, or combining them in a way that doesn't correspond to a supported variant (e.g. two desktops at once, ormultimediawithoutwestonsession), fails at render time.overlays: a,-separated list of rootfs overlays to add fromdebos-recipes/overlays/. See the Supported overlays section below.kernelpackages: a,-separated list of kernel packages to install from apt; defaults tolinux-image-qcom-next,linux-headers-qcom-next. Set it tolinux-image-arm64to install the kernel from Debian, or tononewhen you are installing a locally built kernel package. See the Kernel section below for more information.kernelpackage: deprecated, superseded bykernelpackages; still accepted as a single package name for backwards compatibility.extract_dbg_vmlinux: extract the unstripped kernel binary (vmlinux) from the installed kernel's-dbgpackage to the artifact directory, so oops and panic backtraces can be symbolised later; defaults tofalse. Not every kernel has a-dbgpackage; the step is skipped without failing the build when one isn't available.qliaptrepo: configure the Qualcomm Linux APT repository in the root filesystem; defaults totrue. Set it tofalseto leave the image with no Qualcomm Linux APT sources.suite: Debian suite to use, defaults totrixie.snapshot: use snapshot apt archives for a reproducible build (YYYYMMDDTHHMMSSZ); logged to/etc/buildinfoasSNAPSHOT=<date>. Live mirrors are restored in the final image to allow upgrades. See docs/snapshot.md for full usage and internals.
For the image recipe:
dtb: override the firmware provided device tree with one from the Linux kernel, e.g.qcom/qcs6490-rb3gen2.dtb; default: don't overrideimagetype: eitherufs(the default) orsdcard; UFS images are named disk-ufs.img and use 4096-byte sectors and SD card images are named disk-sdcard.img and use 512-byte sectorsimagesize: set the output disk image size; default:8GiBprofile: select the intended runtime configuration of the image; defaults todefault; recorded in/etc/buildinfoasPROFILE=<profile>when it is notdefault. See the Supported profiles section below.
For the flash recipe:
u_boot_rb1: prebuilt U-Boot binary for RB1 in Android boot image format -- see below (NB: debos expects relative pathnames)target_boards: comma-separated list of board names to build (default:all). Accepted values are the board names defined in the flash recipe, e.g.qcs615-ride,qcs6490-rb3gen2-vision-kit,qcs8300-ride,qcs9100-ride-r3,qrb2210-rb1.
Note: Boards whose required device tree (.dtb) is not present in dtbs.tar.gz are automatically skipped during flash asset generation.
Deprecated flash options:
build_qcs615,build_qcm6490,build_qcs8300,build_qcs9100,build_rb1: these per-family/per-board toggles are deprecated and will be removed. Usetarget_boardsinstead to select which boards to build.
Here are some example invocations:
# build the root filesystem with Xfce
debos -t variant:xfce debos-recipes/qualcomm-linux-debian-rootfs.yaml
# build an image where systemd overrides the firmware device tree with the one
# for RB3 Gen2
debos -t dtb:qcom/qcs6490-rb3gen2.dtb debos-recipes/qualcomm-linux-debian-image.yaml
# build an SD card image
debos -t imagetype:sdcard debos-recipes/qualcomm-linux-debian-image.yaml
# build flash assets for a subset of boards
# (see flash recipe for accepted board names)
debos -t target_boards:qcs615-ride,qcs6490-rb3gen2-vision-kit debos-recipes/qualcomm-linux-debian-flash.yamlNote that these manual invocations may fail because the debos defaults, like scratchsize, are too small for some recipes. We encourage you to stick to the existing Makefile targets instead.
Under the hood, the Makefile just calls debos on recipes from the debos-recipes
directory, notably to set large enough memory and scratchsize settings. To pass
extra options to debos invocations, use EXTRA_DEBOS_OPTS, e.g.:
make EXTRA_DEBOS_OPTS="-t variant:xfce" disk-ufs.img
Multiple overlays are available to include additional files not provided by
Debian packages into the image’s root file system. They are located in
debos-recipes/overlays/.
By default, no overlays are used. Overlays can be selected with the
-t overlays:<value> option; multiple overlays can be specified, separated by a
comma (,).
Here is the list of supported overlays:
- none
- Special value to disable all overlays; this is the default.
A profile selects the intended runtime configuration of the image. It is passed
to the image recipe with -t profile:<profile>, e.g.:
make EXTRA_DEBOS_OPTS="-t profile:<profile>" disk-ufs.imgIf no profile is passed, the default profile is used; there is no need to pass
-t profile:default. The root filesystem is profile-independent, so the same
rootfs.tar can be used to build every profile.
The following profiles are supported:
-
default: the default profile; no additional configuration is applied. -
performance: appendsquiet systemd.tty.term.console=dumbto the kernel command line, so that the kernel doesn't print the boot log to the (slow) console. It uses the default kernel configuration. Based on meta-qcom'sci/performance.ymlconfiguration. -
debug: intended to be built with thelinux-image-qcom-next-debugandlinux-headers-qcom-next-debugkernel packages (the kernel is a build matrix option, independent of the profile; seebuild.yml). What the profile does is:- enable ftrace at boot by appending
ftrace=tracing_on trace_buf_size=5M trace_event=<events>to the kernel command line, where<events>covers the timer, irq, workqueue, sched, power, regulator, thermal and rpmh tracepoints of interest; see the image recipe for the exact list; - append
qcom_scm.download_mode=1to the kernel command line, so that a crash leaves a memory dump to collect rather than silently rebooting; - set
RuntimeWatchdogSec=10sin/etc/systemd/system.conf.d/, so that systemd pings the hardware watchdog and a hang resets the board (and, with download mode above, produces a dump).
Note that with download mode enabled a board that crashes comes back up in EDL waiting for a host to collect the dump, rather than rebooting; recover it with a power cycle.
Based on meta-qcom's
ci/debug.ymlconfiguration andci/base.yml. - enable ftrace at boot by appending
build.yml builds the default, performance and debug profiles, but for
now only the default profile is LAVA-tested, to avoid multiplying the LAVA
jobs the workflow submits.
A variant selects the rootfs content to install. It is passed to the root
filesystem recipe with -t variant:<variant>, e.g.:
make EXTRA_DEBOS_OPTS="-t variant:<variant>" rootfs.tarIf no variant is passed, the recipe builds console; there is no need to pass
-t variant:console.
The following variants are supported; the list lives in
debos-recipes/qualcomm-linux-debian-rootfs-variant.yaml, which fails the
build on any other name:
minimal: only what is needed to boot, connect to a network and use APT: the kernel and firmware, NetworkManager (nmcli) and wpa_supplicant for Ethernet, USB Ethernet and Wi-Fi,systemd-timesyncd,sudoand thedebianuser. Everything else is left for the user to install with APT.console: the default; no graphical environment is installed.xfce: an Xfce desktop environment.gnome: a GNOME desktop environment. Only supported ontrixiefor now; see issue #416.weston: a Weston (Wayland) session, using greetd/agreety to log in and start Weston.weston-multimedia:westonplus the Qualcomm accelerated multimedia stack (GPU, camera, audio, video codec and related user-space tools).
Every variant other than minimal also installs a common set of useful
packages on top: Bluetooth, PipeWire, fwupd, the DSP binaries and FastRPC
support, adbd, thermald, the Debian important and standard packages and
some command-line tools.
CI also builds console when no variant is passed to the workflow, and
publishes its artifacts without a variant suffix, e.g.
trixie-disk-ufs.img.gz. Artifacts of any other variant are suffixed with the
variant name, e.g. trixie-weston-multimedia-disk-ufs.img.gz. The Xfce image,
previously published without a suffix, is now trixie-xfce-disk-ufs.img.gz.
build.yml builds the minimal, console, xfce, gnome and
weston-multimedia variants (minimal for trixie and forky only), but
for now only console is LAVA-tested, to avoid multiplying the LAVA jobs the
workflow submits.
The disk-sdcard.img disk image can simply be written to an SD card, albeit most Qualcomm boards boot from internal storage by default. With an SD card, the board will use boot firmware from internal storage (eMMC or UFS) and do an EFI boot from the SD card if the firmware can't boot from internal storage.
For UFS boards, if there is no need to update the boot firmware, the disk-ufs.img disk image can also be flashed on the first LUN of the internal UFS storage with qdl and the provided rawprogram-ufs.xml file.
Put the board in "emergency download mode" (EDL; see next section) and run:
qdl --storage ufs prog_firehose_ddr.elf rawprogram-ufs.xmlMake sure to use prog_firehose_ddr.elf for the target platform, such as this version from the QCM6490 boot binaries or this version from the RB1 rescue image.
In EDL mode, the board will receive a flashing program over its USB type-C cable, and that program will receive data to flash on the internal storage. This is a lower level mode than fastboot which is implemented by a higher-level bootloader.
To enter EDL mode:
- remove power to the board
- remove any cable from the USB type-C port
- on some boards, it's necessary to set some DIP switches
- press the
F_DLbutton while turning the power on - connect a cable from the flashing host to the USB type-C port on the board
- run qdl to flash the board
NB: It's also possible to run qdl from the host while the board is not connected, then start the board directly in EDL mode.
Once the image has booted, you can log in as the debian user, with the
default debian password. The image should then ask you to change this default
password to a safe one.
The default kernel, installed by the recipes and by every CI-built image, is
the linux-image-qcom-next package from the Qualcomm Linux APT repository. The
corrosponding kernel headers are also installed. It is the default because it
carries additional hardware support for Qualcomm devices, on top of what the
kernel in the Debian archive provides.
The package is built from qcom-next, the Qualcomm Linux integration branch of
the Qualcomm Linux kernel tree, by
its own packaging repository.
That repository is maintained separately from this one and decides which
revision of the tree it packages and publishes, so the version of
linux-image-qcom-next an image installs does not necessarily correspond to
the newest qcom-next-* tag; run apt policy linux-image-qcom-next in an
image to see which version it has.
To install the kernel from the Debian archive instead, see Build a vanilla Debian image below.
You can also build a kernel yourself, for instance to test a local change or to
compare qcom-next against mainline or linux-next.
Building a Linux kernel deb requires the following build-dependencies:
apt -y install git crossbuild-essential-arm64 make flex bison bc libdw-dev libelf-dev libssl-dev libssl-dev:arm64 dpkg-dev debhelper-compat kmod python3 rsync coreutilsNote that to install libssl-dev:arm64 on a non-arm64 host, you will need to
enable arm64 as a foreign architecture first by running
dpkg --add-architecture arm64 && apt update.
Then build qcom-next with the recommended config fragments:
# this builds the latest qcom-next-* tag; pass --ref to build a specific tag
# or the qcom-next branch tip instead
scripts/build-linux-deb.py --qcom-next prune.config qcom.config kernel-configs/*.configOther trees can be built for comparison, for instance to check whether a problem also affects upstream:
# mainline
scripts/build-linux-deb.py kernel-configs/*.config
# linux-next
scripts/build-linux-deb.py --linux-next kernel-configs/*.configTo build an image with a locally-built kernel, copy the resulting debs to
debos-recipes/local-debs/ and disable the apt-installed kernel when building
the root filesystem:
EXTRA_DEBOS_OPTS="-t localdebs:local-debs/ -t kernelpackages:none" make rootfs.tarThe images built by default are Debian plus the Qualcomm Linux additions:
additional Qualcomm-provided packages and the linux-image-qcom-next kernel
package from the Qualcomm Linux APT repository, which the image keeps
configured so that it can be upgraded from later on.
To build an image without the Qualcomm-provided packages or the Qualcomm Linux APT repository configured and the kernel from the Debian archive, run:
EXTRA_DEBOS_OPTS="-t kernelpackages:linux-image-arm64 -t qliaptrepo:false" make rootfs.tarThe result is a plain Debian root filesystem: every package in it comes from
the Debian archive and the image has no Qualcomm Linux APT sources so it will
never pull a Qualcomm Linux package on upgrade. Expect reduced hardware support
compared to the default image, as the Debian kernel does not carry the
Qualcomm platform patches which linux-image-qcom-next does.
Want to join in the development? Changes welcome! See CONTRIBUTING.md file for step by step instructions.
Use the scripts/run-qemu.py helper to boot generated disk images under QEMU. It automatically:
- Detects your OS and locates an aarch64 UEFI firmware (Debian/Ubuntu: qemu-efi-aarch64; macOS Homebrew: edk2-aarch64).
- Presents the image via SCSI with the correct sector size (4096 for UFS, 512 for SD/eMMC).
- Creates a temporary qcow2 copy-on-write overlay by default (your base image remains unchanged).
- Provides GUI display by default (Gtk on Linux, Cocoa on macOS) and headless mode with
--headless.
Dependencies:
- Debian/Ubuntu:
sudo apt install qemu-efi-aarch64 qemu-system-arm qemu-utils - macOS (Homebrew):
brew install qemu
Basic usage:
# Auto-detects disk-ufs.img or disk-sdcard.img in the current directory
scripts/run-qemu.py
# Explicit storage type (sector size set accordingly)
scripts/run-qemu.py --storage ufs
scripts/run-qemu.py --storage sdcard
# Use a specific image path
scripts/run-qemu.py --image /path/to/disk-ufs.img
# Run headless (no GUI), with serial console on stdio
scripts/run-qemu.py --headless
# Disable the COW overlay to persist changes to the image
scripts/run-qemu.py --no-cow
# Pass extra QEMU arguments (example: 4 vCPUs and 4 GiB RAM)
scripts/run-qemu.py --qemu-args "-smp 4 -m 4096"Notes:
- If neither
disk-ufs.imgnordisk-sdcard.imgis found and--imageis not provided, the script will exit with an error. - On Linux, the script looks for
/usr/share/qemu-efi-aarch64/QEMU_EFI.fd. On macOS with Homebrew, it usesshare/qemu/edk2-aarch64-code.fdfrom theqemuformula. - The overlay is cleaned up automatically when QEMU exits. Use
--no-cowto make changes persistent on the base image.
We'd love to hear if you run into issues or have ideas for improvements. Report an Issue on GitHub to discuss, and try to include as much information as possible on your specific environment.
This project is licensed under the BSD-3-clause License. See LICENSE.txt for the full license text.