#!/bin/bash # Customized kernel from system: fetch Distro's kernel sources, patch configuration, recompile # This overrides get_kernel_version from kernel.inc, so the variables will be set properly get_kernel_version() { # Do not use MODULE_DIR here as this function might run when we process another module! [ -n "${TARGET_KERNEL_LONG}" ] && return 0 [ ! -e "${ROOT_DIR}/tmp/work/kernel/ksrc/include/generated/utsrelease.h" ] && pinfo "No UTS information" && return 0 # determine kernel version that will be running in the generated system # declare kernel version stuff declare -rg TARGET_KERNEL_LONG=$(grep 'UTS_RELEASE' "${ROOT_DIR}/tmp/work/kernel/ksrc/include/generated/utsrelease.h" | awk -F '"' '{print $2}') declare -rg TARGET_KERNEL_SHORT=$(echo "$TARGET_KERNEL_LONG" | grep -o -E '^[0-9\.]+') # declare path to kernel headers and modules/firmware declare -rg KERNEL_HEADERS_DIR="${ROOT_DIR}/tmp/work/kernel/ksrc" declare -rg KERNEL_BASE_DIR="${ROOT_DIR}/tmp/work/kernel/build" # print debug info pinfo "TARGET_KERNEL_LONG: '$TARGET_KERNEL_LONG'" pinfo "TARGET_KERNEL_SHORT: '$TARGET_KERNEL_SHORT'" pdebug "KERNEL_BASE_DIR: '$KERNEL_BASE_DIR'" pdebug "KERNEL_HEADERS_DIR: '$KERNEL_HEADERS_DIR'" } fetch_source() { # Fetch all the firmware if ! [ -s "./fw/Makefile" ]; then rm -rf -- "./fw" git clone --depth 1 "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git" "./fw" \ || perror "Could not clone linux-firmware repo." rm -rf -- ./fw/LICENSE.* ./fw/*.txt fi if ! [ -s "./sof/install.sh" ]; then rm -rf -- "./sof" git clone --depth 1 "https://github.com/thesofproject/sof-bin.git" "./sof" \ || perror "Could not clone SOF" fi # Kernel - cached or freshly fetched if nfs_cache_avail; then local id tar id="$( kernel_build_id )" pinfo "Build id is $id" tar="${NFS_CACHE_DIR}/cache/${id}.tar.zstd" if [ -s "$tar" ]; then pinfo "Extracting cached kernel build" if < "$tar" zstd -d -T0 | tar -C "${MODULE_WORK_DIR}" -x; then touch "$tar" # We use last modified as last used, as atime is unreliable return 0 fi pwarning "Extracting cached kernel failed, building..." fi fi fetch_kernel_source } fetch_kernel_source() { pdebug "getting kernel sources via git ...." if grep -q -- "${REQUIRED_GIT}" "./ksrc/.git/config" && grep -q -- "v${REQUIRED_KERNEL}" "./ksrc/.git/config"; then pinfo "Trying to update existing clone" cde ksrc git pull || perror "Could not pull already checked out repo" cde .. else rm -rf "./ksrc" git clone --depth 1 "${REQUIRED_GIT}" -b "v${REQUIRED_KERNEL}" ksrc || perror "Could not clone kernel git." fi if [ -z "$MLTK_INSTALL" ]; then # check for aufs local RSL="$( find ksrc/ -type d -name aufs )" if [ -z "$RSL" ]; then pinfo "aufs not found in kernel sources, patching it..." patch_aufs else pinfo "aufs detected in kernel source :)" fi fi # Other patches local patch cde "$MODULE_WORK_DIR/ksrc" for patch in "${MODULE_DIR}/patches/"*${TARGET_KERNEL_SHORT%.*}*; do [ -f "$patch" ] || continue grep -q -F "$patch" "patches-done" && continue pinfo "Applying $(basename "$patch")" git apply < "$patch" || perror "Could not apply $patch" echo "$patch" >> "patches-done" done } build() { local bf="${MODULE_WORK_DIR}/ksrc/.mltk-build-flag" if ! [ -e "$bf" ]; then local TARGET_CONFIG_FILE="${MODULE_WORK_DIR}/openslx.config" rm -f -- "${TARGET_CONFIG_FILE}" # update config and copy to ksrc pinfo "Updating kernel config..." update_config cp "${TARGET_CONFIG_FILE}" "ksrc/.config" # make kernel with the new config cde ksrc pinfo "Preparing kernel for new config ('make oldconfig')." if [ "x$MLTK_QUIET" = "x1" ]; then make olddefconfig || perror "make oldconfig failed." else make oldconfig || perror "make oldconfig failed." fi pinfo "Compiling kernel... (this will take some time)" # explicitly state number of cores here, as MAKEFLAGS seems to be overridden # also pass CC if set by core/includes/system.inc make $MAKEFLAGS ${CC:+CC=${CC}} || perror "make failed." touch "$bf" if nfs_cache_avail; then local id tar id="$( kernel_build_id )" tar="${NFS_CACHE_DIR}/cache/${id}.tar.zstd" pinfo "Copying built kernel to NFS cache with id $id" mkdir -p "$( dirname "$tar" )" tar -C "${MODULE_WORK_DIR}" -c -k ksrc | zstd -T0 -2 -z > "$tar" \ || pwarning "Could not write kernel to NFS cache" fi fi # install modules to build directory pinfo "Installing kernel modules..." cde "${MODULE_WORK_DIR}/ksrc" if [ -d "${MODULE_BUILD_DIR}/lib/modules" ]; then rm -r "${MODULE_BUILD_DIR}/lib/modules" || pwarning "Could not clean old modules." fi make INSTALL_MOD_PATH="${MODULE_BUILD_DIR}" INSTALL_MOD_STRIP=1 modules_install || perror "make modules_install failed in ${MODULE_BUILD_DIR}." # copy most recent firmware cde "${MODULE_WORK_DIR}" mkdir -p "${MODULE_BUILD_DIR}/lib/firmware/intel" "${MODULE_BUILD_DIR}/usr/bin" rm -rf -- "${MODULE_BUILD_DIR}/lib/firmware/intel/sof" "${MODULE_BUILD_DIR}/lib/firmware/intel/sof-tplg" cp -r ./fw/* "${MODULE_BUILD_DIR}/lib/firmware/" || perror "Could not copy linux-firmware to '${MODULE_BUILD_DIR}/lib/firmware/'" cde sof FW_DEST="${MODULE_BUILD_DIR}/lib/firmware/intel" \ TOOLS_DEST="${MODULE_BUILD_DIR}/usr/bin" \ ./install.sh v2.1.x/v2.1.1 || perror "Installing sof firmware failed" cde .. # copy kernel to build cp ksrc/arch/x86/boot/bzImage "${MODULE_BUILD_DIR}/kernel" || perror "Could not copy bzImage" pinfo "Kernel was successfully built at ${MODULE_BUILD_DIR}/kernel" [ -z "${KERNEL_BUILD_DIR}" ] && KERNEL_BUILD_DIR="${MODULE_BUILD_DIR}" } post_copy() { : } # Get unique ID for this build configuration and environment kernel_build_id() { local conf conf="$( kernel_config_base )" { [ -n "$conf" ] && grep -E '^(# )?CONFIG_' "$conf" # Base config cat "${ROOT_DIR}/data/kernel.wanted.config" # Wanted config gcc --version 2>&1 # gcc version might be important echo "${REQUIRED_KERNEL} ${MLTK_INSTALL}" # wanted kernel version, whether we run install mode cat "${MODULE_DIR}/patches/"* 2> /dev/null # any local patches } | md5sum | cut -c1-32 } # Get path of kernel config zu base this kernel on; empty if none exists kernel_config_base() { local src for src in "/boot/config-mltk" "/boot/config-$(uname -r)"; do if [ -s "$src" ]; then echo "$src" return 0 fi done if [ -f "/proc/config.gz" ]; then zcat "/proc/config.gz" > "${ROOT_DIR}/tmp/kernel-config" echo "${ROOT_DIR}/tmp/kernel-config" fi } # helper function to update the current kernel config with our parameters update_config() { local src_config_file wanted_config_file wanted_line option value current_line # first we need to update the current config src_config_file="$( kernel_config_base )" if [ -n "$src_config_file" ]; then pinfo "Using $src_config_file as a starting point" else pwarning "Using default config in the kernel repository as base config." make -C "${MODULE_WORK_DIR}/ksrc" defconfig [ -e "${MODULE_WORK_DIR}/ksrc/.config" ] || perror "Failed to create default kernel config." src_config_file="${MODULE_WORK_DIR}/ksrc/.config" fi # check for our wanted config parameter wanted_config_file="${ROOT_DIR}/data/kernel.wanted.config" [ -e "${wanted_config_file}" ] || perror "$wanted_config_file does not exist! Please add a list of wanted kernel config parameters." # copy basic config file cp "$src_config_file" "$TARGET_CONFIG_FILE" while read -r wanted_line || [ -n "$wanted_line" ]; do option="${wanted_line%%=*}" value="${wanted_line#*=}" current_line="$( grep -E -m1 "^(# )?${option}[= ]" "$src_config_file" )" [ "$current_line" = "$wanted_line" ] && continue [ "$value" = "n" ] && [ "$current_line" = "# ${option} is not set" ] && continue #echo "Process: $SEARCH_RESULT" # analyse results if [ -z "$current_line" ]; then # no match, add it echo "$wanted_line" >> "$TARGET_CONFIG_FILE" else # match, change to our setting if they differ sed -r -i "s/^(# )?${option}[= ].*\$/${wanted_line}/" "$TARGET_CONFIG_FILE" fi done < "$wanted_config_file" } # helper to patch aufs patch_aufs() { local KERNEL_MAJOR=${REQUIRED_KERNEL%%.*} local AUFS="aufs${KERNEL_MAJOR}" pinfo "Cloning ${AUFS} standalone git" cde "${MODULE_WORK_DIR}" [ -d "${AUFS}-standalone/.git" ] && rm -rf "${AUFS}-standalone" # if already there, kill it. # git: --depth 1 won't work here due to later "checkout origin/branch" if [ "$KERNEL_MAJOR" = "3" ]; then git clone "git://aufs.git.sourceforge.net/gitroot/aufs/${AUFS}-standalone.git" || perror "Cloning ${AUFS} failed." else git clone "https://github.com/sfjro/${AUFS}-standalone.git" || perror "Cloning ${AUFS} failed." #git clone "https://github.com/bnied/${AUFS}-standalone.git" || perror "Cloning ${AUFS} failed." fi # get the needed version cde "${MODULE_WORK_DIR}/${AUFS}-standalone" local branches=( $( git branch -r | grep -oE 'aufs[0-9\.\+]+$' ) ) local major minor patch IFS=. read major minor patch _ <<<"$REQUIRED_KERNEL" if [ -z "$major" ] || [ -z "$minor" ]; then perror "REQUIRED_KERNEL not in properly set, this should not happen!" fi local testvar outer NEEDED_BRANCH while (( minor >= 0 )); do NEEDED_BRANCH="aufs${major}.${minor}" outer=false while (( patch > 0 )); do for testvar in "${branches[@]}"; do if [ "$testvar" = "${NEEDED_BRANCH}.${patch}" ] || [ "$testvar" = "${NEEDED_BRANCH}.${patch}+" ]; then NEEDED_BRANCH="$testvar" break 3 elif [ "$testvar" = "${NEEDED_BRANCH}" ]; then outer=true fi done (( patch-- )) done $outer && break if (( patch == 0 )); then patch=500 (( minor-- )) fi done pinfo "Getting branch origin/$NEEDED_BRANCH" git checkout "origin/$NEEDED_BRANCH" || git checkout "origin/${AUFS}.x-rcN" || perror "Could not checkout needed branch." pinfo "Starting to patch... $NEEDED_BRANCH" tarcopy "Documentation fs" "$MODULE_WORK_DIR/ksrc" # Quick-and-dirty aufs_type.h copying: [ -e "include/linux/aufs_type.h" ] && cp "include/linux/aufs_type.h" "$MODULE_WORK_DIR/ksrc/include/linux/" [ -e "include/uapi/linux/aufs_type.h" ] && cp "include/uapi/linux/aufs_type.h" "$MODULE_WORK_DIR/ksrc/include/uapi/linux/" cde "$MODULE_WORK_DIR/ksrc" local PATCH # Mandatory for PATCH in "${AUFS}-kbuild" "${AUFS}-base" "${AUFS}-mmap"; do patch -p1 < "$MODULE_WORK_DIR/${AUFS}-standalone/${PATCH}.patch" || perror "${PATCH}.patch failed!" pinfo "Applied '$MODULE_WORK_DIR/${AUFS}-standalone/${PATCH}.patch'" done # Optional - should we error too? for PATCH in "${AUFS}-loopback" "tmpfs-idr" "vfs-ino"; do [ -e "$MODULE_WORK_DIR/${AUFS}-standalone/${PATCH}.patch" ] || continue patch -p1 < "$MODULE_WORK_DIR/${AUFS}-standalone/${PATCH}.patch" || pwarning "${PATCH}.patch failed!" pinfo "Applied '$MODULE_WORK_DIR/${AUFS}-standalone/${PATCH}.patch'" done pinfo "Patched kernel source with ${NEEDED_BRANCH}" cde "$MODULE_WORK_DIR" }