summaryrefslogtreecommitdiff
path: root/autoprobe.zsh
diff options
context:
space:
mode:
Diffstat (limited to 'autoprobe.zsh')
-rwxr-xr-xautoprobe.zsh271
1 files changed, 271 insertions, 0 deletions
diff --git a/autoprobe.zsh b/autoprobe.zsh
new file mode 100755
index 0000000..b23fae3
--- /dev/null
+++ b/autoprobe.zsh
@@ -0,0 +1,271 @@
+#!/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
+
+lkddb="$(dirname "${0}")/lkddb.list"
+defconfig="$(dirname "${0}")/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}"