Skip to content

Update build-rockchip-driver-debs.yml #6

Update build-rockchip-driver-debs.yml

Update build-rockchip-driver-debs.yml #6

name: Build Rockchip Driver Packages
on:
workflow_dispatch:
inputs:
targets:
description: Comma-separated OpenHD-ImageBuilder targets
required: false
default: radxa-rock3a_base,rock5a_base,rock5b_base
push:
paths:
- ".github/workflows/build-rockchip-driver-debs.yml"
- "**"
pull_request:
paths:
- ".github/workflows/build-rockchip-driver-debs.yml"
- "**"
jobs:
resolve-targets:
runs-on: ubuntu-22.04
outputs:
targets: ${{ steps.targets.outputs.targets }}
steps:
- id: targets
shell: bash
run: |
targets="${{ github.event.inputs.targets || 'radxa-rock3a_base,rock5a_base,rock5b_base' }}"
json="$(printf '%s' "$targets" | jq -Rc 'split(",") | map(gsub("^\\s+|\\s+$"; "")) | map(select(length > 0))')"
echo "targets=${json}" >> "$GITHUB_OUTPUT"
build:
name: Build ${{ matrix.target }}
needs: resolve-targets
runs-on: ubuntu-22.04
timeout-minutes: 360
strategy:
fail-fast: false
matrix:
target: ${{ fromJson(needs.resolve-targets.outputs.targets) }}
steps:
- name: Checkout driver
uses: actions/checkout@v4
with:
path: driver
- name: Checkout OpenHD ImageBuilder
uses: actions/checkout@v4
with:
repository: OpenHD/OpenHD-ImageBuilder
ref: dev-release
path: imagebuilder
- name: Cache base image archive
uses: actions/cache@v4
with:
path: work/${{ matrix.target }}/*.img.xz
key: rockchip-base-${{ matrix.target }}-${{ hashFiles('imagebuilder/images/**') }}
restore-keys: |
rockchip-base-${{ matrix.target }}-
- name: Build deb package
shell: bash
env:
TARGET: ${{ matrix.target }}
run: |
set -euo pipefail
case "${GITHUB_REPOSITORY##*/}" in
rtl8812au)
DRIVER_PACKAGE="rtl8812au"
MODULE_NAME="88XXau_ohd"
USER_MODULE_NAME_VALUE="88XXau"
;;
rtl88x2bu)
DRIVER_PACKAGE="rtl88x2bu"
MODULE_NAME="88x2bu_ohd"
USER_MODULE_NAME_VALUE="88x2bu"
;;
rtl88x2cu)
DRIVER_PACKAGE="rtl88x2cu"
MODULE_NAME="88x2cu_ohd"
USER_MODULE_NAME_VALUE=""
;;
rtl88x2eu)
DRIVER_PACKAGE="rtl88x2eu"
MODULE_NAME="rtl88x2eu_ohd"
USER_MODULE_NAME_VALUE="rtl88x2eu_ohd"
;;
*)
echo "Unsupported driver repo: ${GITHUB_REPOSITORY}" >&2
exit 1
;;
esac
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
ca-certificates curl xz-utils parted e2fsprogs util-linux rsync \
qemu-user-static binfmt-support file
REQUESTED_TARGET="${TARGET}"
CONFIG="imagebuilder/images/${TARGET}"
if [[ ! -f "${CONFIG}" && "${TARGET}" == *_base ]]; then
TARGET="${TARGET%_base}"
CONFIG="imagebuilder/images/${TARGET}"
fi
if [[ ! -f "${CONFIG}" ]]; then
echo "No OpenHD-ImageBuilder config for target ${REQUESTED_TARGET}" >&2
echo "Available targets:" >&2
ls -1 imagebuilder/images >&2
exit 1
fi
# shellcheck disable=SC1090
source "${CONFIG}"
clean_value() { printf '%s' "${1:-}" | tr -d '\r'; }
BASE_IMAGE_URL="$(clean_value "${BASE_IMAGE_URL}")"
BASE_IMAGE="$(clean_value "${BASE_IMAGE}")"
BASE_IMAGE_SHA256="$(clean_value "${BASE_IMAGE_SHA256:-}")"
BASE_IMAGE_SHA512="$(clean_value "${BASE_IMAGE_SHA512:-}")"
OS="$(clean_value "${OS}")"
DISTRO="$(clean_value "${DISTRO}")"
echo "CLOUDSMITH_RELEASE=${DISTRO}" >> "$GITHUB_ENV"
ROOT_PART="$(clean_value "${ROOT_PART}")"
HAVE_CONF_PART="$(clean_value "${HAVE_CONF_PART:-false}")"
CONF_PART="$(clean_value "${CONF_PART:-}")"
KERNEL_PACKAGES="$(clean_value "${KERNEL_PACKAGES:-}")"
WORK_DIR="${GITHUB_WORKSPACE}/work/${TARGET}"
OUT_DIR="${GITHUB_WORKSPACE}/out/${TARGET}"
MNT_DIR="${WORK_DIR}/mnt"
mkdir -p "${WORK_DIR}" "${OUT_DIR}" "${MNT_DIR}"
archive="${WORK_DIR}/${BASE_IMAGE}"
image="${WORK_DIR}/${BASE_IMAGE%.xz}"
if [[ ! -f "${archive}" ]]; then
separator="/"
[[ "${BASE_IMAGE_URL}" == */ ]] && separator=""
curl -L --fail --retry 3 -o "${archive}" "${BASE_IMAGE_URL}${separator}${BASE_IMAGE}"
fi
[[ -n "${BASE_IMAGE_SHA256}" ]] && echo "${BASE_IMAGE_SHA256} ${archive}" | sha256sum -c -
[[ -n "${BASE_IMAGE_SHA512}" ]] && echo "${BASE_IMAGE_SHA512} ${archive}" | sha512sum -c -
[[ -f "${image}" ]] || xz -dk "${archive}"
partition_field() {
local part="$1"
local field="$2"
sudo parted -s "${image}" unit b print | awk -v p="${part}" -v f="${field}" '$1 == p {gsub(/B/, "", $f); print $f}'
}
cleanup() {
sudo sync || true
sudo mountpoint -q "${MNT_DIR}/etc/resolv.conf" && sudo umount -l "${MNT_DIR}/etc/resolv.conf" || true
sudo mountpoint -q "${MNT_DIR}/sys" && sudo umount -l "${MNT_DIR}/sys" || true
sudo mountpoint -q "${MNT_DIR}/dev/pts" && sudo umount -l "${MNT_DIR}/dev/pts" || true
sudo mountpoint -q "${MNT_DIR}/dev" && sudo umount -l "${MNT_DIR}/dev" || true
sudo mountpoint -q "${MNT_DIR}/proc" && sudo umount -l "${MNT_DIR}/proc" || true
sudo mountpoint -q "${MNT_DIR}/conf" && sudo umount -l "${MNT_DIR}/conf" || true
sudo mountpoint -q "${MNT_DIR}" && sudo umount -l "${MNT_DIR}" || true
}
trap cleanup EXIT
root_offset="$(partition_field "${ROOT_PART}" 2)"
root_size="$(partition_field "${ROOT_PART}" 4)"
sudo mount -o "loop,offset=${root_offset},sizelimit=${root_size},rw" "${image}" "${MNT_DIR}"
if [[ "${HAVE_CONF_PART}" == "true" && -n "${CONF_PART}" ]]; then
conf_offset="$(partition_field "${CONF_PART}" 2)"
conf_size="$(partition_field "${CONF_PART}" 4)"
sudo mkdir -p "${MNT_DIR}/conf"
sudo mount -o "loop,offset=${conf_offset},sizelimit=${conf_size},rw" "${image}" "${MNT_DIR}/conf"
fi
sudo mkdir -p "${MNT_DIR}/opt/openhd-driver-build/src" "${MNT_DIR}/opt/openhd-driver-build/out"
sudo rsync -a --delete --exclude='.git' --exclude='.github' --exclude='*.o' --exclude='*.ko' \
--exclude='*.mod' --exclude='*.mod.c' --exclude='Module.symvers' --exclude='modules.order' \
driver/ "${MNT_DIR}/opt/openhd-driver-build/src/"
sudo cp /usr/bin/qemu-aarch64-static "${MNT_DIR}/usr/bin/" || true
sudo tee "${MNT_DIR}/opt/openhd-driver-build/build.sh" >/dev/null <<'CHROOT_SCRIPT'
#!/usr/bin/env bash
set -euo pipefail
: "${TARGET:?}"
: "${OS:?}"
: "${DISTRO:?}"
: "${DRIVER_PACKAGE:?}"
: "${MODULE_NAME:?}"
: "${USER_MODULE_NAME_VALUE:=}"
: "${KERNEL_PACKAGES:=}"
SRC_DIR="/opt/openhd-driver-build/src"
OUT_DIR="/opt/openhd-driver-build/out"
short_sha="${GITHUB_SHA:-local}"
short_sha="${short_sha:0:7}"
VERSION="2.6.openhd.${GITHUB_RUN_NUMBER:-0}.${short_sha}"
DEB_TARGET="$(echo "${TARGET}" | tr '[:upper:]_' '[:lower:]-' | sed -E 's/[^a-z0-9+.-]+/-/g')"
export DEBIAN_FRONTEND=noninteractive
apt_update_tolerant() {
apt-get -o Acquire::Check-Valid-Until=false -o Acquire::Retries=2 \
-o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30 update
}
disable_stale_apt_sources() {
find /etc/apt -type f \( -name '*.list' -o -name '*.sources' \) -print0 \
| xargs -0 -r sed -i -E \
-e '/dl\.cloudsmith\.io\/public\/openhd\/release/s/^/# disabled by driver CI: /' \
-e '/bullseye-security/s/^[[:space:]]*deb/# disabled by driver CI: &/' \
-e '/bullseye-backports/s/^[[:space:]]*deb/# disabled by driver CI: &/'
}
if [[ "${DISTRO}" == "bullseye" ]]; then
sed -i -E \
-e 's|https?://deb\.debian\.org/debian|http://archive.debian.org/debian|g' \
-e 's|https?://security\.debian\.org/debian-security|http://archive.debian.org/debian-security|g' \
/etc/apt/sources.list 2>/dev/null || true
find /etc/apt/sources.list.d -name '*.list' -print0 2>/dev/null \
| xargs -0 -r sed -i -E \
-e 's|https?://deb\.debian\.org/debian|http://archive.debian.org/debian|g' \
-e 's|https?://security\.debian\.org/debian-security|http://archive.debian.org/debian-security|g' || true
fi
disable_stale_apt_sources
apt_update_tolerant
apt-get install -y --no-install-recommends build-essential make gcc bc bison flex kmod dkms ca-certificates
curl -1sLf "https://dl.cloudsmith.io/public/openhd/dev-release/setup.deb.sh" | bash || true
apt_update_tolerant
if [[ -n "${KERNEL_PACKAGES}" ]]; then
apt-get install -y --allow-downgrades --no-install-recommends ${KERNEL_PACKAGES}
fi
case "${TARGET}" in
rock5a|rock5a_base)
apt-get install -y --allow-downgrades --no-install-recommends linux-headers-rock-5a || true
;;
rock5b|rock5b_base)
apt-get install -y --allow-downgrades --no-install-recommends linux-headers-rock-5b || true
;;
radxa-rock3a|radxa-rock3a_base)
apt-get install -y --allow-downgrades --no-install-recommends linux-headers-rock-3a || true
;;
esac
ensure_headers() {
local kver="$1"
local build_dir="/lib/modules/${kver}/build"
case "${kver}" in
*azure*|*microsoft*|*generic*|*aws*|*gcp*)
return 1
;;
esac
[[ -e "${build_dir}/Makefile" ]] || apt-get install -y --no-install-recommends "linux-headers-${kver}" || true
if [[ ! -e "${build_dir}/Makefile" && "${kver}" =~ ^[0-9].*-([A-Za-z0-9._-]+)$ ]]; then
local kernel_suffix="${BASH_REMATCH[1]}"
for header_pkg in \
"linux-headers-current-${kernel_suffix}" \
"linux-headers-vendor-${kernel_suffix}" \
"linux-headers-legacy-${kernel_suffix}" \
"linux-headers-edge-${kernel_suffix}"; do
apt-get install -y --no-install-recommends "${header_pkg}" && break || true
done
fi
if [[ ! -e "/lib/modules/${kver}/build/Makefile" ]]; then
header_dir="$(find /usr/src -maxdepth 1 -type d \( -name "linux-headers-${kver}" -o -name "*${kver}*" \) | head -n1 || true)"
[[ -n "${header_dir}" ]] && ln -sfn "${header_dir}" "/lib/modules/${kver}/build"
fi
[[ -e "${build_dir}/Makefile" ]] || return 1
kbuild_tool_is_usable() {
local tool="$1"
local status=0
[[ -x "${tool}" ]] || return 1
"${tool}" >/dev/null 2>&1 || status=$?
[[ "${status}" -ne 126 && "${status}" -ne 127 ]]
}
if ! kbuild_tool_is_usable "${build_dir}/scripts/basic/fixdep"; then
rm -f "${build_dir}/scripts/basic/fixdep"
make -C "${build_dir}" scripts/basic/fixdep || make -C "${build_dir}" scripts || true
if ! kbuild_tool_is_usable "${build_dir}/scripts/basic/fixdep" && [[ -f "${build_dir}/scripts/basic/fixdep.c" ]]; then
gcc -O2 -Wall -Wmissing-prototypes -Wstrict-prototypes \
-o "${build_dir}/scripts/basic/fixdep" "${build_dir}/scripts/basic/fixdep.c"
fi
if ! kbuild_tool_is_usable "${build_dir}/scripts/basic/fixdep"; then
while IFS= read -r fixdep_candidate; do
cp "${fixdep_candidate}" "${build_dir}/scripts/basic/fixdep"
chmod +x "${build_dir}/scripts/basic/fixdep"
kbuild_tool_is_usable "${build_dir}/scripts/basic/fixdep" && break
done < <(find /usr/src /lib/modules -path '*/scripts/basic/fixdep' -type f -executable 2>/dev/null)
fi
[[ -f "${build_dir}/scripts/basic/fixdep" ]] && chmod +x "${build_dir}/scripts/basic/fixdep"
fi
kbuild_tool_is_usable "${build_dir}/scripts/basic/fixdep"
if [[ ! -f "${build_dir}/include/generated/autoconf.h" || ! -f "${build_dir}/include/config/auto.conf" || ! -f "${build_dir}/include/config/auto.conf.cmd" ]]; then
if [[ ! -f "${build_dir}/.config" && -f "/boot/config-${kver}" ]]; then
cp "/boot/config-${kver}" "${build_dir}/.config"
fi
[[ -f "${build_dir}/.config" ]] || return 1
mkdir -p "${build_dir}/include/generated" "${build_dir}/include/config"
awk '
/^CONFIG_[A-Za-z0-9_]+=y$/ {
name=$1
sub(/=y$/, "", name)
print "#define " name " 1"
next
}
/^CONFIG_[A-Za-z0-9_]+=m$/ {
name=$1
sub(/=m$/, "", name)
print "#define " name "_MODULE 1"
next
}
/^CONFIG_[A-Za-z0-9_]+=/ {
split($0, parts, "=")
print "#define " parts[1] " " parts[2]
}
' "${build_dir}/.config" > "${build_dir}/include/generated/autoconf.h"
cp "${build_dir}/.config" "${build_dir}/include/config/auto.conf"
printf '%s\n' \
'# Automatically generated by OpenHD driver CI for incomplete vendor headers.' \
'deps_config := \' \
' .config' \
'' \
'include/config/auto.conf: $(deps_config)' \
'' \
'$(deps_config):' \
> "${build_dir}/include/config/auto.conf.cmd"
touch -r "${build_dir}/include/config/auto.conf" "${build_dir}/include/generated/autoconf.h" "${build_dir}/include/config/auto.conf.cmd"
fi
[[ -f "${build_dir}/include/generated/autoconf.h" && -f "${build_dir}/include/config/auto.conf" && -f "${build_dir}/include/config/auto.conf.cmd" ]]
if ! kbuild_tool_is_usable "${build_dir}/scripts/mod/modpost"; then
rm -f "${build_dir}/scripts/mod/modpost"
make -C "${build_dir}" ARCH=arm64 scripts/mod/modpost || make -C "${build_dir}" ARCH=arm64 scripts || true
if ! kbuild_tool_is_usable "${build_dir}/scripts/mod/modpost"; then
while IFS= read -r modpost_candidate; do
cp "${modpost_candidate}" "${build_dir}/scripts/mod/modpost"
chmod +x "${build_dir}/scripts/mod/modpost"
kbuild_tool_is_usable "${build_dir}/scripts/mod/modpost" && break
done < <(find /usr/src /lib/modules -path '*/scripts/mod/modpost' -type f -executable 2>/dev/null)
fi
[[ -f "${build_dir}/scripts/mod/modpost" ]] && chmod +x "${build_dir}/scripts/mod/modpost"
fi
kbuild_tool_is_usable "${build_dir}/scripts/mod/modpost"
}
package_driver() {
local kver="$1"
local ko="$2"
local package_name="${DRIVER_PACKAGE}-${DEB_TARGET}-${kver}"
package_name="$(echo "${package_name}" | tr '[:upper:]_' '[:lower:]-' | sed -E 's/[^a-z0-9+.-]+/-/g')"
local pkg_dir="/opt/openhd-driver-build/pkg/${package_name}"
rm -rf "${pkg_dir}"
mkdir -p "${pkg_dir}/DEBIAN" "${pkg_dir}/lib/modules/${kver}/kernel/drivers/net/wireless"
install -m 0644 "${ko}" "${pkg_dir}/lib/modules/${kver}/kernel/drivers/net/wireless/${MODULE_NAME}.ko"
cat > "${pkg_dir}/DEBIAN/control" <<EOF
Package: ${package_name}
Version: ${VERSION}
Section: kernel
Priority: optional
Architecture: arm64
Maintainer: OpenHD <maintainers@openhd.org>
Depends: kmod
Description: OpenHD ${DRIVER_PACKAGE} kernel module for ${TARGET} ${kver}
Built by GitHub Actions from ${GITHUB_REPOSITORY:-local}.
EOF
cat > "${pkg_dir}/DEBIAN/postinst" <<EOF
#!/bin/sh
set -e
depmod -a ${kver} || true
exit 0
EOF
chmod 0755 "${pkg_dir}/DEBIAN/postinst"
dpkg-deb --build "${pkg_dir}" "${OUT_DIR}/${package_name}_${VERSION}_arm64.deb"
}
supported_warning_flags() {
local flags=()
local flag
for flag in \
-Wno-error=implicit-fallthrough \
-Wno-error=stringop-overread \
-Wno-error=misleading-indentation; do
if printf 'int main(void) { return 0; }\n' | gcc -Werror "${flag}" -x c -c - -o /tmp/openhd-cc-flag-test.o >/dev/null 2>&1; then
flags+=("${flag}")
fi
done
rm -f /tmp/openhd-cc-flag-test.o
printf '%s ' "${flags[@]}"
}
for header_dir in /usr/src/linux-headers-*; do
[[ -d "${header_dir}" ]] || continue
kver="${header_dir##*/linux-headers-}"
mkdir -p "/lib/modules/${kver}"
[[ -e "/lib/modules/${kver}/build" ]] || ln -sfn "${header_dir}" "/lib/modules/${kver}/build"
done
mapfile -t kernels < <(find /lib/modules -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort)
[[ "${#kernels[@]}" -gt 0 ]]
built_count=0
warning_flags="$(supported_warning_flags)"
for kver in "${kernels[@]}"; do
if ! ensure_headers "${kver}"; then
echo "::warning::Skipping ${kver}; kernel headers are unavailable"
continue
fi
make -C "${SRC_DIR}" ARCH=arm64 KVER="${kver}" KSRC="/lib/modules/${kver}/build" clean || true
make_args=(-C "${SRC_DIR}" -j"$(nproc)" ARCH=arm64 KVER="${kver}" KSRC="/lib/modules/${kver}/build" KCFLAGS="${warning_flags}" USER_EXTRA_CFLAGS="${warning_flags}")
[[ -n "${USER_MODULE_NAME_VALUE}" ]] && make_args+=(USER_MODULE_NAME="${USER_MODULE_NAME_VALUE}")
make "${make_args[@]}" modules
ko="${SRC_DIR}/${MODULE_NAME}.ko"
[[ -f "${ko}" ]] || ko="$(find "${SRC_DIR}" -maxdepth 1 -name '*.ko' | head -n1)"
package_driver "${kver}" "${ko}"
built_count=$((built_count + 1))
done
[[ "${built_count}" -gt 0 ]] || { echo "No kernel modules were packaged; no usable kernel headers found" >&2; exit 1; }
CHROOT_SCRIPT
sudo chmod 0755 "${MNT_DIR}/opt/openhd-driver-build/build.sh"
sudo mount -t proc proc "${MNT_DIR}/proc"
sudo mount --bind /dev "${MNT_DIR}/dev"
sudo mount --bind /dev/pts "${MNT_DIR}/dev/pts"
sudo mount --bind /sys "${MNT_DIR}/sys"
sudo rm -f "${MNT_DIR}/etc/resolv.conf"
sudo touch "${MNT_DIR}/etc/resolv.conf"
sudo mount --bind /etc/resolv.conf "${MNT_DIR}/etc/resolv.conf"
export TARGET OS DISTRO DRIVER_PACKAGE MODULE_NAME USER_MODULE_NAME_VALUE KERNEL_PACKAGES
export GITHUB_SHA GITHUB_RUN_NUMBER GITHUB_REPOSITORY
sudo --preserve-env=TARGET,OS,DISTRO,DRIVER_PACKAGE,MODULE_NAME,USER_MODULE_NAME_VALUE,KERNEL_PACKAGES,GITHUB_SHA,GITHUB_RUN_NUMBER,GITHUB_REPOSITORY \
chroot "${MNT_DIR}" /usr/bin/qemu-aarch64-static /bin/bash /opt/openhd-driver-build/build.sh
sudo cp -v "${MNT_DIR}"/opt/openhd-driver-build/out/*.deb "${OUT_DIR}/"
- name: Upload deb packages
uses: actions/upload-artifact@v4
with:
name: ${{ github.event.repository.name }}-${{ matrix.target }}-debs
path: out/${{ matrix.target }}/*.deb
if-no-files-found: error
- name: Push deb packages to Cloudsmith
if: github.event_name != 'pull_request'
shell: bash
env:
CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }}
run: |
set -euo pipefail
python3 -m pip install --user --upgrade cloudsmith-cli
export PATH="${HOME}/.local/bin:${PATH}"
for deb in out/${{ matrix.target }}/*.deb; do
cloudsmith push deb --api-key "${CLOUDSMITH_API_KEY}" --republish "openhd/dev-release/debian/${CLOUDSMITH_RELEASE}" "${deb}"
done