Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 28 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Build on push to branch](https://github.com/qualcomm-linux/qcom-deb-images/actions/workflows/build-on-push.yml/badge.svg)](https://github.com/qualcomm-linux/qcom-deb-images/actions/workflows/build-on-push.yml)
[![Daily Build](https://github.com/qualcomm-linux/qcom-deb-images/actions/workflows/build-daily.yml/badge.svg)](https://github.com/qualcomm-linux/qcom-deb-images/actions/workflows/build-daily.yml)

A collection of recipes to build Qualcomm Linux images for deb based operating systems. The current focus 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 continuous testing efforts.
A collection of recipes to build Qualcomm Linux images for deb based operating systems. The current focus 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 continuous testing efforts.

Initially, this repository provides [debos](https://github.com/go-debos/debos) recipes based on Debian trixie for boards such as the Qualcomm RB3 Gen 2.

Expand All @@ -15,7 +15,7 @@ On standard Linux distros like Debian, firmware updates are generally delivered

### Firmware delivery

On a Desktop system, its usually GNOME Software which monitors LVFS for any firmware updates and pushes to fwupd if any. On a headless system like most embedded devices, the fwupdmgr command line tool can be used to monitor LVFS for firmware updates as follows:
On a Desktop system, it's usually GNOME Software which monitors LVFS for any firmware updates and pushes to fwupd if any. On a headless system like most embedded devices, the fwupdmgr command-line tool can be used to monitor LVFS for firmware updates as follows:

```bash
# Download latest metadata from LVFS
Expand All @@ -30,10 +30,10 @@ fwupdmgr update

### Firmware on devices supported by Qualcomm Linux

The firmware on Qualcomm devices is expected to support UEFI UpdateCapsule plugin for fwupd daemon. However, currently firmware for Qualcomm devices in not available in LVFS which is a work in progress as of now. In order to play with UEFI firmware capsule updates, one can use fwupdtool to locally update firmware like on RB1 as follows:
The firmware on Qualcomm devices is expected to support UEFI UpdateCapsule plugin for fwupd daemon. However, currently firmware for Qualcomm devices is not available in LVFS which is a work in progress as of now. In order to play with UEFI firmware capsule updates, one can use fwupdtool to locally update firmware like on RB1 as follows:

```bash
# Transfer U-Boot firmware cabinet archive build from scripts/build-u-boot-rb1.sh to RB1
# Transfer U-Boot firmware cabinet archive built by scripts/build-u-boot-rb1.sh to RB1
sudo fwupdtool install u-boot.cab
# It will ask for a reboot for the UEFI firmware capsule update to happen
```
Expand Down Expand Up @@ -85,7 +85,7 @@ To build flashable assets for all supported boards, follow these steps:

1. build disk and filesystem images from the root filesystem tarball
```bash
# the default is to build an UFS image
# the default is to build a UFS image
debos debos-recipes/qualcomm-linux-debian-image.yaml

# (optional) if you want SD card images or support for eMMC boards, run
Expand All @@ -99,12 +99,15 @@ To build flashable assets for all supported boards, follow these steps:

# (optional) if you've built U-Boot for the RB1, run this instead:
#debos -t u_boot_rb1:u-boot/rb1-boot.img debos-recipes/qualcomm-linux-debian-flash.yaml

# (optional) build only a subset of boards:
#debos -t target_boards:qcs615-adp-air-sa6155p,qcs6490-rb3gen2-vision-kit debos-recipes/qualcomm-linux-debian-flash.yaml
```

1. enter Emergency Download Mode (see section below) and flash the resulting images with QDL
```bash
# for RB3 Gen2 Vision Kit or UFS boards in general
cd flash_rb3gen2-vision-kit
cd flash_qcs6490-rb3gen2-vision-kit
qdl --storage ufs prog_firehose_ddr.elf rawprogram[0-9].xml patch[0-9].xml

# for RB1 or eMMC boards in general
Expand All @@ -113,7 +116,7 @@ To build flashable assets for all supported boards, follow these steps:

### 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 an 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.
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:
```bash
Expand All @@ -124,32 +127,42 @@ debos --fakemachine-backend qemu --memory 1GiB --scratchsize 4GiB 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)
- `xfcedesktop`: install a Xfce desktop environment; default: console only environment
- `xfcedesktop`: install an Xfce desktop environment; default: console only environment

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 bytes sectors and SD card images are named disk-sdcard.img and use 512 bytes sectors
- `imagesize`: set the output disk image size; default: `4.5GiB`
- `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: `4GiB`

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-adp-air-sa6155p`, `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:
```bash
# build the root filesystem with Xfce and a kernel from experimental
debos -t xfcedesktop:true -t experimentalkernel:true debos-recipes/qualcomm-linux-debian-rootfs.yaml
# build the root filesystem with Xfce
debos -t xfcedesktop:true 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-adp-air-sa6155p,qcs6490-rb3gen2-vision-kit debos-recipes/qualcomm-linux-debian-flash.yaml
```

### Flashing tips

The `disk-sdcard.img` disk image can simply be written to a 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.
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](https://github.com/linux-msm/qdl). Create a `rawprogram-ufs.xml` file as follows:
```xml
Expand All @@ -176,7 +189,7 @@ To enter EDL mode:
1. connect a cable from the flashing host to the USB type-C port on the board
1. run qdl to flash the board

NB: It's also possible to run qdl from the host while the baord is not connected, and starting the board directly in EDL mode.
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.

## Development

Expand Down
49 changes: 49 additions & 0 deletions debos-recipes/qualcomm-linux-debian-flash.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
{{- $build_rb1 = "true" }}
{{- end -}}

{{- $target_boards := or .target_boards "all" }}

architecture: arm64

actions:
Expand Down Expand Up @@ -165,11 +167,50 @@ actions:
# path to unpacked qcom-ptool tarball
QCOM_PTOOL="$(ls -d "${ROOTDIR}/../qcom-ptool.tar.gz.d/qcom-ptool-"*)"

# build a list of supported dtbs from the dtbs tarball
dtbs_file="build/dtbs.txt"
: >"${dtbs_file}"
if [ -f "${ARTIFACTDIR}/dtbs.tar.gz" ]; then
tar -tzf "${ARTIFACTDIR}/dtbs.tar.gz" --wildcards '*.dtb' \
>>"$dtbs_file"
fi

# optional list of board names to build
targets_file="build/targets.txt"
rm -f "${targets_file}"
case "{{ $target_boards }}" in
all)
# no override; build all possible boards (default)
Copy link
Contributor

Choose a reason for hiding this comment

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

You already have $boards defined, right? Could you make the later code simpler by unconditionally writing build/targets.txt, so the "all" magic is restricted to here, rather than needing to be understood elsewhere? I think that would avoid surprising semantics of when build/targets.txt doesn't exist.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let me try to repeat what I understand you're suggesting: have the go template logic at the top to generate a targets.txt table based on the data from $boards, then have a pure shell script reading through that table afterwards. Is that correct?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that matches, yes, if by "at the top" you mean in the code area highlighted here?

I think you could write $board.name for $board in $boards to build/targets.txt in the area of code highlighted here in the case that $target_boards is set to "all". Then below the if [ -e "${targets_file}" ]; then can go away - it'd be unconditionally setting skip_board to true if $board.name (in the iteration below) isn't present in build/targets.txt.

This would take away the special handling when build/targets.txt isn't present, because it'd always be present, making the logic simpler and less surprising from my POV.

;;
*)
echo "{{ $target_boards }}" |
tr ',' '\n' |
sed '/^$/d' |
sort -u >"${targets_file}"
;;
esac

{{- range $board := $boards }}
### board: {{ $board.name }}
### platform: {{ $board.platform }}
### silicon family: {{ $board.silicon_family }}

# set skip_board if target list present and board isn't listed
skip_board=false
if [ -e "${targets_file}" ]; then
if ! grep -Fxq "{{ $board.name }}" "${targets_file}"; then
skip_board=true
echo "Skipping board {{ $board.name }}: not in target list"
fi
fi
{{- if $board.dtb }}
# set skip_board if board has a dtb and dtb isn't present
if ! grep -Fxq "{{ $board.dtb }}" "${dtbs_file}"; then
skip_board=true
echo "Skipping board {{ $board.name }}: dtb not available"
fi
{{- end }}

# unpack boot binaries
mkdir -v build/{{ $board.name }}_boot-binaries
unzip "${ROOTDIR}/../{{ $board.boot_binaries_download.filename }}" \
Expand Down Expand Up @@ -256,6 +297,7 @@ actions:
"${QCOM_PTOOL}/ptool.py" -x ptool-partitions.xml
)

if [ "${skip_board}" = false ]; then
Copy link
Contributor

Choose a reason for hiding this comment

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

Do the following lines need indenting, or is GitHub hiding that from me? Same question for the other if statements below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It does, but then I have to indent the whole file, becoming hard to read and review :)

happy to do that though!

Copy link
Contributor

Choose a reason for hiding this comment

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

My opinion: especially because there are many matching if/fi close together, it's easier to read with the expected indentation and if someone is debugging in this area then your intent will be clearer.

Factoring some of these into functions might help with readability too, but that's another can of worms so maybe not worth it.

This is subjective of course so I'll leave it to you.

# create board-specific flash directory
flash_dir="${ARTIFACTDIR}/flash_{{ $board.name }}"
rm -rf "${flash_dir}"
Expand Down Expand Up @@ -287,24 +329,30 @@ actions:
-or -name '*.mbn' \
\) \
-exec cp --preserve=mode,timestamps -v '{}' "${flash_dir}" \;
fi
{{- if $board.u_boot_file }}
if [ "${skip_board}" = false ]; then
# copy U-Boot binary to boot.img;
# qcom-ptool/platforms/*/partitions.conf uses filename=boot.img
# boot_a and boot_b partitions
cp --preserve=mode,timestamps -v "${ARTIFACTDIR}/{{ $board.u_boot_file }}" \
"${flash_dir}/boot.img"
fi
{{- end }}

{{- if $board.cdt_download }}
if [ "${skip_board}" = false ]; then
# unpack board CDT
unzip "${ROOTDIR}/../{{ $board.cdt_download.filename }}" \
-d build/{{ $board.name }}_cdt
# copy just the CDT data; no partition or flashing files
cp --preserve=mode,timestamps -v build/{{ $board.name }}_cdt/{{ $board.cdt_filename }} \
"${flash_dir}"
fi
{{- end }}

{{- if $board.dtb }}
if [ "${skip_board}" = false ]; then
# generate a dtb.bin FAT partition with just a single dtb for the current
# board; long-term this should really be a set of dtbs and overlays as to
# share dtb.bin across boards
Expand All @@ -321,6 +369,7 @@ actions:
tar -C build -xvf "${ARTIFACTDIR}/dtbs.tar.gz" "{{ $board.dtb }}"
# copy into the FAT as combined-dtb.dtb
mcopy -vmp -i "${dtb_bin}" "build/{{ $board.dtb }}" ::/combined-dtb.dtb
fi
{{- end }}
{{- end }}

Expand Down
Loading