Kernel/build disabled module
Сборка модуля ядра, который есть, но не был сконфигурирован
Иногда случается так, что желаемый модуль есть, но не был сконфигурирован при сборке ядра.
Можно было бы попросить мейнтейнера ядра изменить config-файл ядра, добавив туда желаемую фичу, и ждать пересборки из Сизифа. Однако это доступно не всем, долго и, вообще говоря, можно поступить иначе!
Дособрать такой модуль достаточно просто.
Разберём данную ситуацию на примере одноплатного компьютера RBS_RepkaPi_3, aarch64. Компьютер используется в проекте и работает на относительно старом, стабильном по состоянию на 2025 год ядре rbs-def.
Возникла необходимость подключить к компьютеру внешний I2C датчик температуры TMP117. Исходный код драйвера есть в ядре (см. исходники в git), однако отключён в конфигурации ядра:
$ cat config|grep TMP117
CONFIG_TMP117 is not set
Постановка задачи
Собрать и подключить модуль ядра .ko с минимальными затратами и изменениями в существующей системе.
Решение
Будем собирать модуль ядра изнутри самой системы. После сборки, если заголовки и компиляторы мешают - можно попросту извлечь собранный .ko файл и откатиться на чистую систему (бекап SD-карты).
Установить среду для сборки и заголовки ядра:
apt-get install build-essential kernel-headers-modules-rbs-def
Скачать исходники ядра (можно на десктопе, чтобы не тащить всё это на одноплатник)
git clone https://git.altlinux.org/gears/k/kernel-image-rbs-def.git
Нужные нам исходники находятся в папке: drivers/iio/temperature/. Нас интересуют файлы:
tmp117.c Makefile Kconfig
В файле Kconfig находится строка, описывающая наш модуль:
config TMP117
tristate "TMP117 Digital temperature sensor with integrated NV memory"
depends on I2C
help
If you say yes here you get support for the Texas Instruments
TMP117 Digital temperature sensor with integrated NV memory.
This driver can also be built as a module. If so, the module will
be called tmp117.
Тут написано, что модуль называется tmp117.ko
Открываем Makefile:
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for industrial I/O temperature drivers
#
obj-$(CONFIG_IQS620AT_TEMP) += iqs620at-temp.o
obj-$(CONFIG_LTC2983) += ltc2983.o
obj-$(CONFIG_HID_SENSOR_TEMP) += hid-sensor-temperature.o
obj-$(CONFIG_MAXIM_THERMOCOUPLE) += maxim_thermocouple.o
obj-$(CONFIG_MAX31856) += max31856.o
obj-$(CONFIG_MLX90614) += mlx90614.o
obj-$(CONFIG_MLX90632) += mlx90632.o
obj-$(CONFIG_TMP006) += tmp006.o
obj-$(CONFIG_TMP007) += tmp007.o
obj-$(CONFIG_TMP117) += tmp117.o
obj-$(CONFIG_TSYS01) += tsys01.o
obj-$(CONFIG_TSYS02D) += tsys02d.o
Получается, когда при конфигурации ядра устанавливается переменная CONFIG_TMP117=m, к переменной obj-m добавляется наш модуль tmp117.o, а иначе он уходит в "отвал" - переменную obj-.
Скопируем папку drivers/iio/temperature/ на одноплатный компьютер. Другие исходники нам не нужны. На одноплатном компьютере:
cd temperature/
make CONFIG_TMP117=m -C /lib/modules/`uname -r`/build M=`pwd` -j 4 modules
# модули собрались, устанавливаем
cp tmp117.ko /lib/modules/`uname -r`/
depmod
# очищаем директорию сборки
make CONFIG_TMP117=m -C /lib/modules/`uname -r`/build M=`pwd` clean
# проверяем, что модуль подцепился
cat /lib/modules/`uname -r`/modules.dep | grep tmp117
# tmp117.ko: kernel/drivers/iio/industrialio.ko
modprobe tmp117
В результате модуль установился. Его загрузка будет происходить автоматически при правильном объявлении термометра на I2C контроллере в dtb/dts файлах, см. Device_Tree.
Как это работает?
Пакет kernel-headers-modules-rbs-def содержит в себе снимок среды сборки ядра, которая была создана во время его компиляции. Этот снимок хранится в /lib/modules/`uname -r`/build. Это достаточно большой нетривиальный набор файлов и в том числе вспомогательных утилит, собираемых системой сборки ядра из исходников прямо на месте. Воспроизвести это вне системы сборки затруднительно. Таким образом всё, что нужно для сборки модуля, уже есть там и берётся оттуда.
Замечания:
- Наш локальный Make-файл содержит только условное присвоение переменных.
- Директива M=`pwd` указывает основному make-файлу ядра подцепить наш из нашей папки.
- Ключ CONFIG_TMP117=m включает сборку нужного нам модуля, кроме него соберутся другие модули, которые были включены в конфиге ядра. Они собираются быстро, это не проблема.
- Ключ -j указывает число параллельных процессов, чтобы собиралось ещё быстрее. По опыту памяти одноплатника должно хватить.
А также можно "хакнуть" локальный Make-файл, удалив лишние модули оттуда.