[PATCH 1/2] scripts: add mod-to-kconfig.sh

From: Brian Masney
Date: Tue Aug 01 2023 - 13:50:33 EST


Add a useful script that can be used to convert a kernel module path
to the relevant Kconfig symbol name. Examples showing how to use this
is in the help at the top of the script.

Signed-off-by: Brian Masney <bmasney@xxxxxxxxxx>
---
scripts/kconfig/mod-to-kconfig.sh | 93 +++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)
create mode 100755 scripts/kconfig/mod-to-kconfig.sh

diff --git a/scripts/kconfig/mod-to-kconfig.sh b/scripts/kconfig/mod-to-kconfig.sh
new file mode 100755
index 000000000000..1b69b638ebf5
--- /dev/null
+++ b/scripts/kconfig/mod-to-kconfig.sh
@@ -0,0 +1,93 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2023 Red Hat, Inc. All Rights Reserved.
+# Written by Brian Masney <bmasney@xxxxxxxxxx>
+#
+# This script takes as input one or more kernel module names, and outputs
+# the relevant Kconfig symbol name. This script was originally intended to help
+# identify which Kconfig options are enabled inside an initramfs.
+#
+# x1:~/src/linux$ find /usr/lib/modules/`uname -r` -name *.ko.xz | \
+# ./scripts/kconfig/mod-to-kconfig.sh
+# CONFIG_CRYPTO_USER
+# CONFIG_CRYPTO_ESSIV
+# CONFIG_CRYPTO_CHACHA20
+# CONFIG_CRYPTO_TWOFISH
+# ...
+#
+# You can also use this to walk the modules.builtin file:
+#
+# x1:~/src/linux$ ./scripts/kconfig/mod-to-kconfig.sh < \
+# /usr/lib/modules/`uname -r`/modules.builtin
+#
+# Pipe the output of this script into scripts/kconfig/lookup.sh if you want to
+# view the full Kconfig entries.
+#
+# Note that there is a fair bit of variability in the Makefiles across the
+# kernel and this script won't match everything. It's only been written to
+# cover the 95% use case.
+
+process_module()
+{
+ # We may have a full path, like /usr/lib/modules/`uname -r`/kernel/...`,
+ # or a relative path, like kernel/... that's found in modules.builtin.
+ local DIR
+ DIR=$(dirname "$1")
+ if [[ "${DIR}" =~ ^/ ]] ; then
+ DIR=${DIR##*/kernel/}
+ else
+ DIR=${DIR##kernel/}
+ fi
+
+ # Handle compressed module names
+ local MOD_NAME
+ MOD_NAME=$(basename "$1")
+ MOD_NAME="${MOD_NAME/.xz/}" # CONFIG_FW_LOADER_COMPRESS_XZ
+ MOD_NAME="${MOD_NAME/.zst/}" # CONFIG_FW_LOADER_COMPRESS_ZSTD
+ MOD_NAME="${MOD_NAME/.ko/}"
+ MOD_NAME="${MOD_NAME/.c/}"
+
+ local MAKEFILE
+ MAKEFILE="${DIR}/Makefile"
+ if [ ! -f "${MAKEFILE}" ] ; then
+ echo "Skipping $1 since ${MAKEFILE} is not found" >&2
+ return 1
+ fi
+
+ # There's probably a more elegant way you could do this with sed or awk,
+ # however personally I find this approach more readable in this
+ # particular case.
+ local CONFIG
+ CONFIG=$(grep --before-context=200 -w -E "${MOD_NAME}(\.o|/)" \
+ "${DIR}/Makefile" | grep CONFIG_ | tail -n 1 | \
+ awk -F\( '{print $2}' | awk -F\) '{print $1}')
+ if [ "${CONFIG}" = "" ] ; then
+ echo "Skipping $1 since CONFIG cannot be determined" >&2
+ return 1
+ fi
+ echo "${CONFIG}"
+}
+
+# Run this script from the toplevel kernel source directory.
+SCRIPT_PATH=$(readlink -f "$0")
+cd "$(dirname "${SCRIPT_PATH}")/../.." || exit 1
+
+RET=0
+if [[ $# == 0 ]] ; then
+ # Read module paths from stdin
+ while read -r MODULE_PATH ; do
+ if ! process_module "${MODULE_PATH}" ; then
+ RET=1
+ fi
+ done
+else
+ # Read module paths from the command line arguments
+ for NUM in $(seq 1 "$#") ; do
+ if ! process_module "${!NUM}" ; then
+ RET=1
+ fi
+ done
+fi
+
+exit "${RET}"
--
2.41.0