build/lib/functions/compilation/patch/drivers-harness.sh

203 lines
7.7 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
#
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (c) 2013-2023 Igor Pecovnik, igor@armbian.com
#
# This file is a part of the Armbian Build Framework
# https://github.com/armbian/build/
function kernel_drivers_create_patches_hash_only() {
hash_only="yes" kernel_drivers_create_patches "${@}"
}
function kernel_drivers_create_patches() {
if [[ "${EXTRAWIFI}" == "no" ]]; then
display_alert "Skipping driver harness as requested" "EXTRAWIFI = ${EXTRAWIFI} - returning" "debug"
return 0
fi
kernel_drivers_patch_hash="undetermined" # outer scope
kernel_drivers_patch_file="undetermined" # outer scope
declare hash_files # any changes in these files will trigger a cache miss; also any changes in misc .patch with "wireless" at start or "wifi" anywhere in the name
calculate_hash_for_files "${SRC}/lib/functions/compilation/patch/drivers_network.sh" "${SRC}/lib/functions/compilation/patch/drivers-harness.sh" "${SRC}"/patch/misc/wireless*.patch
declare hash_variables="undetermined"
do_normalize_src_path="no" calculate_hash_for_variables "${KERNEL_DRIVERS_SKIP[*]}"
declare hash_variables_short="${hash_variables:0:8}"
# Sanity check, the KERNEL_GIT_SHA1 gotta be sane.
[[ "${KERNEL_GIT_SHA1}" =~ ^[0-9a-f]{40}$ ]] || exit_with_error "KERNEL_GIT_SHA1 is not sane: '${KERNEL_GIT_SHA1}'"
declare cache_key_base="sha1_${KERNEL_GIT_SHA1}_${LINUXFAMILY}_${BRANCH}"
declare cache_key="${cache_key_base}_${hash_files}-${hash_variables_short}"
display_alert "Cache key base:" "$cache_key_base" "debug"
display_alert "Cache key:" "$cache_key" "debug"
declare cache_dir_base="${SRC}/cache/patch/kernel-drivers"
mkdir -p "${cache_dir_base}"
declare cache_target_file="${cache_dir_base}/${cache_key}.patch"
# outer scope variables:
kernel_drivers_patch_file="${cache_target_file}" # outer scope
kernel_drivers_patch_hash="${hash_files}" # outer scope
if [[ "${hash_only:-"no"}" == "yes" ]]; then
display_alert "Hash-only kernel driver requested" "$kernel_drivers_patch_hash - returning" "debug"
return 0
fi
declare kernel_work_dir="${1}"
declare kernel_git_revision="${2}"
# If the target file exists, we can skip the patch creation.
if [[ -f "${cache_target_file}" ]]; then
# Make sure the file is larger than 512 bytes. Old versions of this code left small/empty files on failure.
if [[ $(stat -c%s "${cache_target_file}") -gt 512 ]]; then
display_alert "Using cached drivers patch file for ${LINUXFAMILY}-${BRANCH}" "${cache_key}" "cachehit"
return
else
display_alert "Removing invalid/small cached drivers patch file for ${LINUXFAMILY}-${BRANCH}" "${cache_key}" "warn"
run_host_command_logged rm -fv "${cache_target_file}"
fi
fi
display_alert "Creating patches for kernel drivers" "version: 'sha1_${KERNEL_GIT_SHA1}' family: '${LINUXFAMILY}-${BRANCH}'" "info"
# if it does _not_ exist, fist clear the base, so no old patches are left over
run_host_command_logged rm -fv "${cache_dir_base}/*_${LINUXFAMILY}_${BRANCH}*"
# also clean up old-style cache base, used before we introduced KERNEL_GIT_SHA1
run_host_command_logged rm -fv "${cache_dir_base}/${KERNEL_MAJOR_MINOR}_${LINUXFAMILY}*"
# since it does not exist, go create it. this requires working tree.
declare target_patch_file="${cache_target_file}"
display_alert "Preparing patch for drivers" "version: sha1_${KERNEL_GIT_SHA1} kernel_work_dir: ${kernel_work_dir}" "debug"
kernel_drivers_prepare_harness "${kernel_work_dir}" "${kernel_git_revision}"
}
function kernel_drivers_prepare_harness() {
declare kernel_work_dir="${1}"
declare kernel_git_revision="${2}"
# outer scope variable: target_patch_file
declare -a all_drivers=(
driver_generic_bring_back_ipx
driver_mt7921u_add_pids
driver_rtl8152_rtl8153
driver_rtl8189ES
driver_rtl8189FS
driver_rtl8192EU
driver_rtl8811_rtl8812_rtl8814_rtl8821
driver_xradio_xr819
driver_rtl8811CU_rtl8821C
driver_rtl8188EU_rtl8188ETV
driver_rtl88x2bu
driver_rtw88
driver_rtl88x2cs
driver_rtl8822cs_bt
driver_rtl8723DS
driver_rtl8723DU
driver_rtl8822BS
driver_uwe5622_allwinner
driver_rtl8723cs
)
declare -a skip_drivers=("${KERNEL_DRIVERS_SKIP[@]}")
declare -a drivers=()
# Produce 'drivers' array by removing any drivers in 'skip_drivers' from 'all_drivers'
for driver in "${all_drivers[@]}"; do
for skip in "${skip_drivers[@]}"; do
if [[ "${driver}" == "${skip}" ]]; then
display_alert "Skipping kernel driver as instructed by KERNEL_DRIVERS_SKIP" "${driver}" "info"
continue 2 # 2: continue the _outer_ loop
fi
done
drivers+=("${driver}")
done
# change cwd to the kernel working dir
cd "${kernel_work_dir}" || exit_with_error "Failed to change directory to ${kernel_work_dir}"
#run_host_command_logged git status
run_host_command_logged git reset --hard "${kernel_git_revision}"
# git: remove tracked files, but not those in .gitignore
run_host_command_logged git clean -fd # no -x here
for driver in "${drivers[@]}"; do
display_alert "Preparing driver" "${driver}" "info"
# reset variables used by each driver
declare version="${KERNEL_MAJOR_MINOR}"
declare kernel_work_dir="${1}"
declare kernel_git_revision="${2}"
# for compatibility with `master`-based code
declare kerneldir="${kernel_work_dir}"
# change cwd to the kernel working dir
cd "${kernel_work_dir}" || exit_with_error "Failed to change directory to ${kernel_work_dir}"
# invoke the driver; non-armbian-next code.
"${driver}"
# recover from possible cwd changes in the driver code
cd "${kernel_work_dir}" || exit_with_error "Failed to change directory to ${kernel_work_dir}"
done
# git: check if there are modifications
if [[ -n "$(git status --porcelain)" ]]; then
display_alert "Drivers have modifications" "exporting patch into ${target_patch_file}" "info"
export_changes_as_patch_via_git_format_patch
else
exit_with_error "Applying drivers didn't produce changes."
fi
}
function export_changes_as_patch_via_git_format_patch() {
# git: add all modifications
run_host_command_logged git add .
declare -a common_envs=(
"HOME=${HOME}"
"PATH=${PATH}"
)
# git: commit the changes
declare -a git_params=(
"-c" "commit.gpgsign=false" # force gpgsign off; the user might have it enabled and it will fail.
)
declare -a commit_params=(
"--quiet" # otherwise too much output
-m "drivers for ${LINUXFAMILY}-${BRANCH} version ${KERNEL_MAJOR_MINOR} git sha1 ${KERNEL_GIT_SHA1}"
--author="${MAINTAINER} <${MAINTAINERMAIL}>"
)
declare -a commit_envs=(
"GIT_COMMITTER_NAME=${MAINTAINER}"
"GIT_COMMITTER_EMAIL=${MAINTAINERMAIL}"
)
run_host_command_logged env -i "${common_envs[@]@Q}" "${commit_envs[@]@Q}" git "${git_params[@]@Q}" commit "${commit_params[@]@Q}"
# export the commit as a patch
declare formatpatch_params=(
"-1" "--stdout"
"--unified=3" # force 3 lines of diff context
"--keep-subject" # do not add a prefix to the subject "[PATCH] "
# "--no-encode-email-headers" # do not encode email headers - @TODO does not exist under focal, disable
'--signature' "Armbian generated patch from drivers for kernel ${version} and family ${LINUXFAMILY}"
'--stat=120' # 'wider' stat output; default is 80
'--stat-graph-width=10' # shorten the diffgraph graph part, it's too long
"--zero-commit" # Output an all-zero hash in each patchs From header instead of the hash of the commit.
)
declare target_patch_file_tmp="${target_patch_file}.tmp"
# The redirect ">" is escaped here, so it's run inside the subshell, not in the current shell.
run_host_command_logged env -i "${common_envs[@]@Q}" git format-patch "${formatpatch_params[@]@Q}" ">" "${target_patch_file_tmp}"
# move the tmp to final, if it worked.
run_host_command_logged mv -v "${target_patch_file_tmp}" "${target_patch_file}"
}