Yocto Kernel Configuration - Part 4: Advanced Management and Automation
This is the final part of our Yocto kernel configuration series. In this article, we’ll cover advanced techniques for automating configuration management, validation, and troubleshooting.
Overview
In this part, you’ll learn how to:
- ✅ Automate patch generation with scripts
- ✅ Validate configurations automatically
- ✅ Create testing workflows for multiple machines
- ✅ Troubleshoot common issues effectively
- ✅ Set up CI/CD integration for configuration changes
Prerequisites
Before starting this part, make sure you’ve completed:
- Part 1: Getting Started with Devshell
- Part 2: Machine-Specific defconfig and bbappend
- Part 3: Git Patches and Version Control
- You understand shell scripting basics
Automated Patch Generation
Script 1: Automated Configuration Patch Generator
#!/bin/bash
# save as: generate-config-patch.sh
set -e
SCRIPT_NAME=$(basename "$0")
KERNEL_DIR="$1"
CONFIG_NAME="$2"
PATCH_DIR="$3"
usage() {
echo "Usage: $SCRIPT_NAME <kernel_dir> <config_name> <patch_dir>"
echo "Example: $SCRIPT_NAME ~/linux-variscite-work tof-camera ~/patches"
echo ""
echo "This script will:"
echo "1. Set up cross-compilation environment"
echo "2. Run menuconfig for interactive configuration"
echo "3. Generate defconfig and create git patch"
echo "4. Validate patch format and application"
exit 1
}
if [ $# -ne 3 ]; then
usage
fi
if [ ! -d "$KERNEL_DIR" ]; then
echo "Error: Kernel directory '$KERNEL_DIR' does not exist"
exit 1
fi
cd "$KERNEL_DIR"
# Set up environment
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
echo "=== Automated Kernel Configuration Patch Generator ==="
echo "Kernel directory: $KERNEL_DIR"
echo "Configuration name: $CONFIG_NAME"
echo "Patch output directory: $PATCH_DIR"
echo ""
# Ensure git is initialized
if [ ! -d ".git" ]; then
echo "Initializing git repository..."
git init
git add .
git commit -m "Initial kernel source"
fi
# Start with base configuration
echo "Loading base configuration..."
make imx8mp_var_defconfig
make olddefconfig
echo "Starting interactive configuration..."
echo "Configure your kernel options and save when done."
read -p "Press Enter to continue to menuconfig..."
make menuconfig
# Generate defconfig and patch
echo "Generating defconfig..."
make savedefconfig
cp defconfig arch/arm64/configs/imx8mp_var_defconfig
# Create git commit
git add arch/arm64/configs/imx8mp_var_defconfig
git commit -m "arm64: defconfig: Enable $CONFIG_NAME support
Automatically generated configuration patch for $CONFIG_NAME
Signed-off-by: $(git config user.name) <$(git config user.email)>"
# Generate patch
mkdir -p "$PATCH_DIR"
git format-patch -1 HEAD --output-directory="$PATCH_DIR"
# Validate patch
PATCH_FILE=$(ls "$PATCH_DIR"/*.patch | tail -1)
echo "Validating patch: $PATCH_FILE"
git apply --check "$PATCH_FILE"
echo "✅ Patch generated successfully: $PATCH_FILE"
echo "✅ Patch validation passed"Script 2: Configuration Validation Script
#!/bin/bash
# save as: validate-config-patch.sh
PATCH_FILE="$1"
KERNEL_DIR="$2"
usage() {
echo "Usage: $0 <patch_file> <kernel_dir>"
echo "Example: $0 patches/0001-*.patch ~/linux-variscite-work"
exit 1
}
if [ $# -ne 2 ]; then
usage
fi
if [ ! -f "$PATCH_FILE" ]; then
echo "Error: Patch file '$PATCH_FILE' not found"
exit 1
fi
if [ ! -d "$KERNEL_DIR" ]; then
echo "Error: Kernel directory '$KERNEL_DIR' not found"
exit 1
fi
cd "$KERNEL_DIR"
echo "=== Configuration Patch Validator ==="
echo "Patch file: $PATCH_FILE"
echo "Kernel directory: $KERNEL_DIR"
echo ""
# Test patch application
echo "Testing patch application..."
git apply --check "$PATCH_FILE"
if [ $? -eq 0 ]; then
echo "✅ Patch applies cleanly"
else
echo "❌ Patch application failed"
exit 1
fi
# Apply patch temporarily
echo "Applying patch temporarily..."
git stash push -m "Backup before patch test"
git apply "$PATCH_FILE"
# Test configuration build
echo "Testing configuration build..."
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make olddefconfig
if [ $? -eq 0 ]; then
echo "✅ Configuration builds successfully"
else
echo "❌ Configuration build failed"
git stash pop
exit 1
fi
# Restore original state
git stash pop
echo "✅ Patch validation successful"Multi-Machine Testing Automation
Script 3: Multi-Machine Build Tester
#!/bin/bash
# save as: test-multi-machine.sh
YOCTO_BUILD_DIR="$1"
shift
MACHINES=("$@")
usage() {
echo "Usage: $0 <yocto_build_dir> <machine1> [machine2] [machine3]..."
echo "Example: $0 ~/yocto-build imx8mp-var-som-dev imx8mp-var-som-prod"
exit 1
}
if [ $# -lt 2 ]; then
usage
fi
if [ ! -d "$YOCTO_BUILD_DIR" ]; then
echo "Error: Yocto build directory '$YOCTO_BUILD_DIR' not found"
exit 1
fi
cd "$YOCTO_BUILD_DIR"
source oe-init-build-env
echo "=== Multi-Machine Kernel Configuration Tester ==="
echo "Build directory: $YOCTO_BUILD_DIR"
echo "Machines to test: ${MACHINES[*]}"
echo ""
RESULTS=()
for machine in "${MACHINES[@]}"; do
echo "========================================="
echo "Testing machine: $machine"
echo "========================================="
# Set machine
export MACHINE=$machine
# Clean and build
echo "Cleaning previous build..."
bitbake -c cleansstate linux-variscite
echo "Building kernel for $machine..."
START_TIME=$(date +%s)
if bitbake linux-variscite; then
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
echo "✅ $machine: Build successful (${DURATION}s)"
RESULTS+=("✅ $machine: SUCCESS (${DURATION}s)")
# Verify configuration
echo "Verifying configuration..."
bitbake -c devshell linux-variscite << 'EOF'
grep -E "CONFIG_VIDEO_MLX7502X|CONFIG_MXC_MIPI_CSI" .config
exit
EOF
else
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
echo "❌ $machine: Build failed (${DURATION}s)"
RESULTS+=("❌ $machine: FAILED (${DURATION}s)")
fi
echo ""
done
echo "========================================="
echo "SUMMARY"
echo "========================================="
for result in "${RESULTS[@]}"; do
echo "$result"
doneConfiguration Validation Workflows
Script 4: Comprehensive Configuration Validator
#!/bin/bash
# save as: validate-kernel-config.sh
CONFIG_FILE="$1"
EXPECTED_OPTIONS="$2"
usage() {
echo "Usage: $0 <config_file> <expected_options_file>"
echo ""
echo "expected_options_file format:"
echo "CONFIG_VIDEO_MLX7502X=m"
echo "CONFIG_MXC_MIPI_CSI=m"
echo "# CONFIG_DEBUG_KERNEL is not set"
exit 1
}
if [ $# -ne 2 ]; then
usage
fi
if [ ! -f "$CONFIG_FILE" ]; then
echo "Error: Config file '$CONFIG_FILE' not found"
exit 1
fi
if [ ! -f "$EXPECTED_OPTIONS" ]; then
echo "Error: Expected options file '$EXPECTED_OPTIONS' not found"
exit 1
fi
echo "=== Kernel Configuration Validator ==="
echo "Config file: $CONFIG_FILE"
echo "Expected options: $EXPECTED_OPTIONS"
echo ""
FAILED_CHECKS=0
TOTAL_CHECKS=0
while IFS= read -r expected_line; do
# Skip empty lines and comments
[[ -z "$expected_line" || "$expected_line" =~ ^#.*$ ]] && continue
TOTAL_CHECKS=$((TOTAL_CHECKS + 1))
if grep -Fxq "$expected_line" "$CONFIG_FILE"; then
echo "✅ Found: $expected_line"
else
echo "❌ Missing: $expected_line"
FAILED_CHECKS=$((FAILED_CHECKS + 1))
fi
done < "$EXPECTED_OPTIONS"
echo ""
echo "========================================="
echo "VALIDATION SUMMARY"
echo "========================================="
echo "Total checks: $TOTAL_CHECKS"
echo "Passed: $((TOTAL_CHECKS - FAILED_CHECKS))"
echo "Failed: $FAILED_CHECKS"
if [ $FAILED_CHECKS -eq 0 ]; then
echo "✅ All configuration checks passed!"
exit 0
else
echo "❌ Configuration validation failed!"
exit 1
fiAdvanced Troubleshooting Techniques
Common Issues and Automated Solutions
#!/bin/bash
# save as: troubleshoot-kernel-config.sh
ISSUE_TYPE="$1"
KERNEL_DIR="$2"
usage() {
echo "Usage: $0 <issue_type> <kernel_dir>"
echo ""
echo "Issue types:"
echo " missing-deps - Check for missing dependencies"
echo " config-conflict - Check for configuration conflicts"
echo " build-failure - Analyze build failure logs"
echo " patch-reject - Analyze patch rejection issues"
exit 1
}
if [ $# -ne 2 ]; then
usage
fi
cd "$KERNEL_DIR"
case "$ISSUE_TYPE" in
"missing-deps")
echo "=== Checking for Missing Dependencies ==="
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
# Check cross-compiler
if ! command -v aarch64-linux-gnu-gcc &> /dev/null; then
echo "❌ Cross-compiler not found: aarch64-linux-gnu-gcc"
echo "Install with: sudo apt-get install gcc-aarch64-linux-gnu"
else
echo "✅ Cross-compiler found"
fi
# Check required tools
TOOLS=("bc" "flex" "bison" "libssl-dev" "libncurses5-dev")
for tool in "${TOOLS[@]}"; do
if dpkg -l | grep -q "$tool"; then
echo "✅ $tool installed"
else
echo "❌ $tool missing - install with: sudo apt-get install $tool"
fi
done
;;
"config-conflict")
echo "=== Checking for Configuration Conflicts ==="
make olddefconfig 2>&1 | grep -E "(warning|error|conflict)" || echo "✅ No conflicts found"
;;
"build-failure")
echo "=== Analyzing Build Failure ==="
if [ -f ".config" ]; then
echo "Checking problematic configurations..."
grep -E "CONFIG_.*=m" .config | head -10
echo ""
echo "Try building with these options as built-in (=y) instead of modules (=m)"
else
echo "❌ No .config file found"
fi
;;
"patch-reject")
echo "=== Analyzing Patch Rejection ==="
echo "Common patch issues:"
echo "1. Line ending differences (DOS vs Unix)"
echo "2. Whitespace differences"
echo "3. Context changes in source files"
echo ""
echo "Solutions:"
echo "- Run: dos2unix patch-file.patch"
echo "- Check: git apply --whitespace=fix patch-file.patch"
echo "- Regenerate patch from current source"
;;
*)
echo "Unknown issue type: $ISSUE_TYPE"
usage
;;
esacCI/CD Integration
GitHub Actions Workflow
# save as: .github/workflows/kernel-config-test.yml
name: Kernel Configuration Test
on:
push:
paths:
- 'recipes-kernel/linux/linux-variscite/**'
pull_request:
paths:
- 'recipes-kernel/linux/linux-variscite/**'
jobs:
validate-patches:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu bc flex bison libssl-dev libncurses5-dev
- name: Set up kernel source
run: |
# Download and set up linux-variscite source
# This would be specific to your setup
- name: Validate patches
run: |
for patch in recipes-kernel/linux/linux-variscite/*.patch; do
echo "Validating $patch"
./scripts/validate-config-patch.sh "$patch" linux-variscite-work/
done
- name: Test multi-machine builds
run: |
# Set up Yocto environment and test builds
./scripts/test-multi-machine.sh build/ imx8mp-var-som-dev imx8mp-var-som-prodBest Practices Summary
1. Automation Workflow
# Complete automation workflow:
# 1. Generate patches
./generate-config-patch.sh ~/linux-variscite-work tof-camera ~/patches
# 2. Validate patches
./validate-config-patch.sh ~/patches/0001-*.patch ~/linux-variscite-work
# 3. Test multi-machine builds
./test-multi-machine.sh ~/yocto-build imx8mp-var-som-dev imx8mp-var-som-prod
# 4. Validate final configuration
./validate-kernel-config.sh .config expected-tof-options.txt2. Directory Structure
# Recommended project structure:
project/
├── scripts/
│ ├── generate-config-patch.sh
│ ├── validate-config-patch.sh
│ ├── test-multi-machine.sh
│ └── troubleshoot-kernel-config.sh
├── patches/
│ ├── 0001-arm64-defconfig-Enable-media-framework.patch
│ └── 0002-arm64-defconfig-Enable-ToF-sensor.patch
├── configs/
│ ├── expected-dev-options.txt
│ └── expected-prod-options.txt
└── meta-layer/
└── recipes-kernel/linux/linux-variscite/
├── defconfig-dev
├── defconfig-prod
└── linux-variscite_%.bbappend3. Testing Strategy
# Multi-level testing approach:
# Level 1: Patch validation
for patch in patches/*.patch; do
./validate-config-patch.sh "$patch" linux-variscite-work/
done
# Level 2: Configuration validation
./validate-kernel-config.sh .config configs/expected-options.txt
# Level 3: Multi-machine builds
./test-multi-machine.sh build/ machine1 machine2 machine3
# Level 4: Runtime testing (manual)
# Boot test images and verify ToF camera functionalityQuick Reference
Essential Scripts Usage
# Generate new configuration patch
./generate-config-patch.sh <kernel_dir> <config_name> <patch_dir>
# Validate existing patch
./validate-config-patch.sh <patch_file> <kernel_dir>
# Test multiple machines
./test-multi-machine.sh <yocto_build_dir> <machine1> [machine2] ...
# Troubleshoot issues
./troubleshoot-kernel-config.sh <issue_type> <kernel_dir>
# Validate configuration
./validate-kernel-config.sh <config_file> <expected_options_file>Common Issue Types
# Troubleshooting commands:
./troubleshoot-kernel-config.sh missing-deps <kernel_dir>
./troubleshoot-kernel-config.sh config-conflict <kernel_dir>
./troubleshoot-kernel-config.sh build-failure <kernel_dir>
./troubleshoot-kernel-config.sh patch-reject <kernel_dir>Series Conclusion
This completes our comprehensive 4-part series on Yocto kernel configuration management:
- Part 1: Basic devshell operations and configuration workflow
- Part 2: Machine-specific defconfig files and bbappend management
- Part 3: Professional git patches and version control
- Part 4: Advanced automation and troubleshooting
With these tools and techniques, you now have a complete, professional workflow for managing kernel configurations in Yocto projects. The automation scripts provided will save you time and ensure consistency across your development and production builds.
Key Takeaways
✅ Automate repetitive tasks with scripts ✅ Validate configurations before deployment ✅ Test multiple machines systematically ✅ Troubleshoot issues efficiently ✅ Integrate with CI/CD for continuous validation
This approach scales from simple single-machine projects to complex multi-machine production environments, ensuring your kernel configuration management remains maintainable and professional.
