Skip to content

About

Qualcomm Linux Debian build scripts

Resources

Code of conduct

Contributing

Security policy

Stars

66 stars

Watchers

11 watching

Forks

Repository files navigation

Qualcomm Linux deb images

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:

We are also working towards providing ready-to-use, pre-built images – stay tuned!

CI Status

Variant Image build & test status
Qualcomm Linux QLI images
Debian Debian images
Reference upstream kernels linux-next images mainline images
Project-specific builds arduino images qcom-7.2 qcom-laptops

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.

Vulnerability assessments

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.

Requirements

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.

Steps

(optional) Build and flash U-Boot

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 mkbootimg

To build U-Boot for the RB1, run:

scripts/build-u-boot-rb1.sh

(optional) Build custom kernel

By 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.

Build the image

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-defusedxml

To build flashable assets for all supported boards, follow these steps:

  1. 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
  2. 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
  3. 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
  4. 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

Debos tips

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.yaml

Options for debos recipes

A 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 to console. See the Supported variants section below.
  • xfcedesktop, gnomedesktop, westonsession, multimedia: deprecated, superseded by variant; still accepted for backwards compatibility (with a 10 second warning) and mapped onto the equivalent variant value. Setting any of these together with variant, or combining them in a way that doesn't correspond to a supported variant (e.g. two desktops at once, or multimedia without westonsession), fails at render time.
  • overlays: a ,-separated list of rootfs overlays to add from debos-recipes/overlays/. See the Supported overlays section below.
  • kernelpackages: a ,-separated list of kernel packages to install from apt; defaults to linux-image-qcom-next,linux-headers-qcom-next. Set it to linux-image-arm64 to install the kernel from Debian, or to none when you are installing a locally built kernel package. See the Kernel section below for more information.
  • kernelpackage: deprecated, superseded by kernelpackages; still accepted as a single package name for backwards compatibility.
  • extract_dbg_vmlinux: extract the unstripped kernel binary (vmlinux) from the installed kernel's -dbg package to the artifact directory, so oops and panic backtraces can be symbolised later; defaults to false. Not every kernel has a -dbg package; 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 to true. Set it to false to leave the image with no Qualcomm Linux APT sources.
  • suite: Debian suite to use, defaults to trixie.
  • snapshot: use snapshot apt archives for a reproducible build (YYYYMMDDTHHMMSSZ); logged to /etc/buildinfo as SNAPSHOT=<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 override
  • imagetype: either ufs (the default) or sdcard; 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 sectors
  • imagesize: set the output disk image size; default: 8GiB
  • profile: select the intended runtime configuration of the image; defaults to default; recorded in /etc/buildinfo as PROFILE=<profile> when it is not default. 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. Use target_boards instead 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.yaml

Note 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

Supported overlays

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.

Supported profiles

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.img

If 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: appends quiet systemd.tty.term.console=dumb to 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's ci/performance.yml configuration.

  • debug: intended to be built with the linux-image-qcom-next-debug and linux-headers-qcom-next-debug kernel packages (the kernel is a build matrix option, independent of the profile; see build.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=1 to the kernel command line, so that a crash leaves a memory dump to collect rather than silently rebooting;
    • set RuntimeWatchdogSec=10s in /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.yml configuration and ci/base.yml.

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.

Supported variants

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.tar

If 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, sudo and the debian user. 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 on trixie for now; see issue #416.
  • weston: a Weston (Wayland) session, using greetd/agreety to log in and start Weston.
  • weston-multimedia: weston plus 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.

Flash the image

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.xml

Make 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.

Emergency Download Mode (EDL)

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:

  1. remove power to the board
  2. remove any cable from the USB type-C port
  3. on some boards, it's necessary to set some DIP switches
  4. press the F_DL button while turning the power on
  5. connect a cable from the flashing host to the USB type-C port on the board
  6. 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.

Boot the image

Login

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.

Kernel

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 coreutils

Note 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/*.config

Other 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/*.config

To 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.tar

Build a vanilla Debian image

The 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.tar

The 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.

Development

Want to join in the development? Changes welcome! See CONTRIBUTING.md file for step by step instructions.

Boot an image locally with QEMU (helper script)

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.img nor disk-sdcard.img is found and --image is 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 uses share/qemu/edk2-aarch64-code.fd from the qemu formula.
  • The overlay is cleaned up automatically when QEMU exits. Use --no-cow to make changes persistent on the base image.

Reporting Issues

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.

License

This project is licensed under the BSD-3-clause License. See LICENSE.txt for the full license text.

About

Qualcomm Linux Debian build scripts

Resources

Code of conduct

Contributing

Security policy

Stars

66 stars

Watchers

11 watching

Forks

Releases

Packages

Used by

Contributors

Languages