#!/usr/bin/env zsh # # Copyright (C) 2026 Maria Lisina # SPDX-License-Identifier: Apache-2.0 # # A script for probing basic hardware from /sys/bus on modern laptops set -e dir="${0%/*}" lkddb="${dir}/lkddb.list" defconfig="${dir}/autoprobe.defconfig" if ! [[ -f "${lkddb}" ]] then echo "lkddb.list is not found!" \ "\nPlease download it from \`https://cateee.net/sources/lkddb\` for your kernel version," \ "\nand rename it to lkddb.list in the same directory as this script." exit 1 fi rm -f "${defconfig}" printf "#\n# Automatically generated by ${0##*/}\n#\n" >> "${defconfig}" printf "# This is not a real defconfig file, but a minimal list of kernel\n" >> "${defconfig}" printf "# configurations for a better understanding of your hardware.\n#\n" >> "${defconfig}" printf "# Expect false positives, use with caution!\n#\n" >> "${defconfig}" add_section() { printf '\n# %s\n' "${1}" >> "${defconfig}" } extract_configs_from_lkddb() { if [[ -n "${1}" ]] then grep "${1}" "${lkddb}" | grep -o 'CONFIG_.*:' | sed 's/ .$//' fi } add_config_if_unique() { if [[ -n "${1}" ]] && ! grep -q "${1}" "${defconfig}" then printf '%s\n' "${1}" >> "${defconfig}" fi } extract_driver_from_uevent() { if [[ -f "${1}" ]] then < "${1}" | grep '^DRIVER=' | cut -d '=' -f 2 | sed 's/[-_]/\[-_\]/g' fi } search_and_add_configs() { local configs=($(extract_configs_from_lkddb "${1}")) for config in ${configs[@]} do add_config_if_unique "${config}" done } search_with_module_fallback() { local configs=($(extract_configs_from_lkddb "${1}")) if [[ -n "${2}" && -z "${configs}" ]] then configs=($(extract_configs_from_lkddb "^module ${2} ")) fi for config in ${configs[@]} do add_config_if_unique "${config}" done } echo "Adding ACPI devices to defconfig..." add_section "ACPI" for dev in $(ls -1 /sys/bus/acpi/devices) do if ! [[ -f "/sys/bus/acpi/devices/${dev}/hid" ]] then continue fi search_and_add_configs "^acpi \"$(< "/sys/bus/acpi/devices/${dev}/hid")\"" done echo "Adding PCI devices to defconfig..." add_section "PCI" for dev in $(ls -1 /sys/bus/pci/devices) do if ! [[ -f "/sys/bus/pci/devices/${dev}/vendor" ]] then continue fi pci_id=$(printf '%s %s' \ "$(< "/sys/bus/pci/devices/${dev}/vendor")" \ "$(< "/sys/bus/pci/devices/${dev}/device")" | sed 's/0x//g' ) driver=$(extract_driver_from_uevent "/sys/bus/pci/devices/${dev}/uevent") search_with_module_fallback "^pci ${pci_id} " "${driver}" done echo "Adding HD-audio devices to defconfig..." add_section "HD-audio" for dev in $(ls -1 /sys/bus/hdaudio/devices) do if ! [[ -f "/sys/bus/hdaudio/devices/${dev}/vendor_id" ]] then continue fi vendor_id="$(< "/sys/bus/hdaudio/devices/${dev}/vendor_id" | sed 's/0x//g')" driver=$(extract_driver_from_uevent "/sys/bus/hdaudio/devices/${dev}/uevent") search_with_module_fallback "^hda ${vendor_id} " "${driver}" done echo "Adding HID devices to defconfig..." add_section "HID" for dev in $(ls -1 /sys/bus/hid/devices) do if ! [[ -f "/sys/bus/hid/devices/${dev}/uevent" ]] then continue fi hid_id="$(< "/sys/bus/hid/devices/${dev}/uevent" | grep '^HID_ID=' | cut -d '=' -f 2 | tr ':' ' ' | tr '[:upper:]' '[:lower:]' )" driver=$(extract_driver_from_uevent "/sys/bus/hid/devices/${dev}/uevent") search_with_module_fallback "^hid ${hid_id} " "${driver}" done echo "Adding USB devices to defconfig..." add_section "USB" for dev in $(ls -1 /sys/bus/usb/devices) do if ! [[ -f "/sys/bus/usb/devices/${dev}/uevent" ]] then continue fi driver=$(extract_driver_from_uevent "/sys/bus/usb/devices/${dev}/uevent") search_and_add_configs "^module ${driver} " done echo "Adding I2C devices to defconfig..." add_section "I2C" for dev in $(ls -1 /sys/bus/i2c/devices) do if ! [[ -f "/sys/bus/i2c/devices/${dev}/name" ]] then continue fi modname="$(< "/sys/bus/i2c/devices/${dev}/name")" if [[ -z "${modname}" ]] then continue fi search_and_add_configs "^module.*\"${modname}\"" done echo "Adding PNP devices to defconfig..." add_section "PNP" for dev in $(ls -1 /sys/bus/pnp/devices) do if ! [[ -f "/sys/bus/pnp/devices/${dev}/id" ]] then continue fi search_and_add_configs "^pnp.*\"$(< "/sys/bus/pnp/devices/${dev}/id")\"" done echo "Adding Platform devices to defconfig..." add_section "Platform" for dev in $(ls -1 /sys/bus/platform/devices) do if ! [[ -f "/sys/bus/platform/devices/${dev}/uevent" ]] then continue fi driver=$(extract_driver_from_uevent "/sys/bus/platform/devices/${dev}/uevent") search_and_add_configs "^module ${driver} " done echo "Adding Serial devices to defconfig..." add_section "Serial" for dev in $(ls -1 /sys/bus/serio/devices) do if ! [[ -f "/sys/bus/serio/devices/${dev}/id/type" ]] then continue fi serio_type="$(< "/sys/bus/serio/devices/${dev}/id/type")" serio_proto="$(< "/sys/bus/serio/devices/${dev}/id/proto")" if [[ "${serio_proto}" == "00" ]] then serio_proto=".." fi serio_id=$(printf '%s %s' "${serio_type}" "${serio_proto}") search_and_add_configs "^serio ${serio_id}" done echo "Adding Filesystems to defconfig..." add_section "Filesystems" for fs in $(mount | cut -d ' ' -f 5 | sort) do search_and_add_configs "^fs \"${fs}\"" done echo "Adding CPU features to defconfig..." add_section "CPU Features" if [[ -f "/sys/bus/cpu/devices/cpu0/uevent" ]] then modalias="$(< "/sys/bus/cpu/devices/cpu0/uevent" | grep '^MODALIAS=' | cut -d '=' -f 2 | sed 's/[-_]/\[-_\]/g' )" for modname in $(modprobe -R "${modalias}" | sed 's/[-_]/\[-_\]/g') do search_and_add_configs "^module ${modname} " done fi echo "Adding Modules to defconfig..." add_section "Modules" for module in $(lsmod | sed -e '1d' -e 's/ .*$//g' -e 's/[-_]/\[-_\]/g' | sort) do search_and_add_configs "^module ${module} " done sed -i '/^CONFIG__UNKNOWN__.*$/d' "${defconfig}"