# Сборка ядра Linux для Orange Pi 5 Plus (и других устройств на Rockchip RK3588) с поддержкой iSCSI Для моего проекта (k3s на Orange Pi 5 Plus) потребовалась поддержка система управления блочным хранилищем 'longhorn' (longhorn.io). _Longhorn_ позволяет создавать надёжные тома для контейнеров, автоматически реплицируя их между узлами и обеспечения высокую доступности приложений (если один узел выходит из строя, данные остаются доступны на репликах на других узлах). Для _longhorn_ нужен `iSCSI` (**Internet Small Computer System Interface**) — сетевой протокол, который по TCP/IP подсоединяет удалённые диски так, будто они подключены физически. Longhorn через iSCSI обеспечивает передачу данных между узлами по сети. В ядре Linux поддержка _iSCSI_ реализована через модули, такие как `iscsi_tcp` и `scsi_transport_iscsi`. Однако, в большинстве дистрибутивов для одноплатных компьютеров, включая и Orange Pi 5 Plus, эти модули отключены. Это делают для экономии ресурсов, да и в целом, это нетипичный сценарий использования Orange Pi. В версии Ubuntu 22.04 для Orange Pi 5 Plus (в ядре от Xunlong), поддержка iSCSI тоже отключена, и это делает невозможным запуск Longhorn из коробки. **А значит нужно компиляция ядра (сбока)** Мы вручную включим поддержку _iSCSI_ (модули `iscsi_tcp` и `scsi_transport_iscsi`), и cможем настроить ядро под свои задачи. Однако компиляция и его замена требует осторожности и внимательности, ошибка в процессе может привести к тому, что система не загрузится (но мы сделаем резервную копию текущего ядра, загрузчика, чтобы можно было восстановить систему). Обновления системы (например, через `apt`) с новым ядром будет проходить, как обычно: пакеты, утилиты и приложения обновятся без проблем. Однако пересобранное ядро больше не будет автоматически обновляться через стандартные средства дистрибутива. Если выйдет новая версия ядра, то придётся вручную повторить процесс компиляции. К счастью, поставщик (это Xunlong) обновляет ядро не часто. | ✎ Заметка | |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Orange Pi 5 Plus использует процессор **Rockchip RK3588** (как и многие другие устройства под брендом Orange). Процесс компиляции ядра для всех RK35xx почти идентичен, и базируется на одном и том же дистрибутиве. Однако, разные периферийные устройства: например, GPIO, USB или Ethernet-контроллеры могут отличаться. Мы будем использовать `.config` от текущего, рабочего ядра, так что настройки будут актуальны. Но следует иметь в виду, что возможно, в будущем могут появиться изменения в конфигурации, дистрибутива и т.п. Следует учитывать, это и **никто ничего не гарантирует**. | ## План сборки ядра с iSCSI * Резервное копирование текущего ядра, загрузчика, дерева устройств, /boot и т.п. * Установить инструментарий для настройки и компиляции ядра * Скачать исходники. * Настроить конфиг для включения модулей iSCSI (и мониторинга NVMe). * Скомпилировать ядро и модули. * Установить новое ядро. * Перезагрузиться в новое ядро. * Проверка. ## Резервное копирование текущего ядра и /boot Архивируем том `/boot` на нашем Orange Pi 5 Plus во временный каталог `/tmp`: ```bash sudo tar -czf /tmp/boot-backup.tar.gz /boot ``` Проверим, что архив создался: ```bash ls -al /tmp/boot-backup.tar.gz ``` Увидим что архив создался: ```text -rw-r--r-- 1 root root 62116591 мар 23 20:33 /tmp/boot-backup.tar.gz ``` Теперь нам нужно скопировать его на какой-нибудь внешний хост (или носитель, но я буду копировать на хост другого компьютера). Если что-то пойдёт не так (например, после обновления ядра система не загрузится) можно будет восстановить файлы из этого архива. Мой Orange Pi 5 Plus, на котором я буду компилировать ядро имеет хост — `opi5plus-3` (замени на свой хост), а имя пользователя от которого я работаю — `opi` (замени на свой). На рабочем компьютере, с которого я захожу по SSH на Orange, у меня есть папка `~/backup/` (`mkdir -p ~/backup`). Скачиваю в неё архив: ```bash scp opi@opi5plus-3.local:/tmp/boot-backup.tar.gz ~/backup/opi5plus-3-boot-backup.tar.gz ``` ### Что в архиве? Если что-то пойдет не так, нам надо знать какие файлы в `/boot` важны и для чего предназначены. Вот список файлов ('ls -al /boot'): ```text drwxr-xr-x 4 root root 4096 янв 1 1970 ./ drwxr-xr-x 19 root root 4096 фев 16 19:59 ../ -rwxr-xr-x 1 root root 230456 ноя 21 09:56 boot.bmp* -rwxr-xr-x 1 root root 3341 ноя 21 09:55 boot.cmd* -rwxr-xr-x 1 root root 3413 ноя 21 10:04 boot.scr* -rwxr-xr-x 1 root root 230393 ноя 21 07:08 config-6.1.43-rockchip-rk3588* drwxr-xr-x 3 root root 4096 ноя 21 09:55 dtb/ drwxr-xr-x 3 root root 4096 ноя 21 09:55 dtb-6.1.43-rockchip-rk3588/ -rwxr-xr-x 1 root root 40579584 ноя 21 07:08 Image* -rwxr-xr-x 1 root root 15462140 мар 21 16:36 initrd.img-6.1.43-rockchip-rk3588* -rwxr-xr-x 1 root root 1152056 ноя 21 09:56 logo.bmp* -rwxr-xr-x 1 root root 0 ноя 21 09:55 .next* -rwxr-xr-x 1 root root 178 фев 16 19:59 orangepiEnv.txt* -rwxr-xr-x 1 root root 1542 ноя 21 09:56 orangepi_first_run.txt.template* -rwxr-xr-x 1 root root 6209932 ноя 21 07:08 System.map-6.1.43-rockchip-rk3588* -rwxr-xr-x 1 root root 15462204 мар 21 16:36 uInitrd* -rwxr-xr-x 1 root root 40579584 ноя 21 07:08 vmlinuz-6.1.43-rockchip-rk3588* ``` Ключевые файлы: * `Image` — собственно ядро Linux (в данном случае версия 6.1.43 для Rockchip RK3588). При старте компьютера загрузчик U-Boot загрузит его в память и передаст ему управление. Без этого файла система не запустится. * `vmlinuz-6.1.43-rockchip-rk3588` — копия ядра (в системе уже есть резервная копия). * `dtb/` — Каталог файлами **Device Tree Blob** (`DTB`). Это бинарные файлы, описывающие аппаратное обеспечение устройства. Для Orange Pi 5 Plus используется файл вроде `rk3588-orangepi-5-plus.dtb` (находится в подкаталоге `dtb/rockchip/`). DTB передаётся ядру, чтобы оно знало, как работать с процессором (количество ядер, частоты), памятью (RAM, её объём и адреса), периферией (UART, I2C, SPI, Ethernet, USB, GPIO, прерывания и тому подобное). На ARM-устройствах (в отличие от x86, где есть ACPI) нет стандартного способа обнаружения оборудования. DTB решает эту проблему, предоставляя ядру "карту" железа. U-Boot загружает DTB из `/boot/dtb/ `и передаёт его ядру при старте. Кстати, в подкаталоге dtb/rockchip/ есть `overlay/` — это дополнительные файлы, которые могут использоваться для добавления и/или изменения функциональности устройства. Например, можно добавить поддержку новых периферийных устройств (камеру, дисплей и т.п.). * `uInitrd` — Начальный RAM-диск (initrd), адаптированный для U-Boot. Содержит модули и скрипты, необходимые для пред-загрузки (выбор накопителя, монтирование корневой файловой системы и т.п.). Если он повреждён или несовместим с ядром, загрузка может упасть на этапе инициализации. * `orangepiEnv.txt` — Конфигурационный файл для U-Boot. Здесь задаются параметры загрузки, такие как путь расположение дерева DTB, UUID корневой файловой системы, тип файловой системы… Без правильных настроек в этом файле U-Boot не найдёт нужные для загрузки файлы. * `boot.scr` — Скрипт загрузки для U-Boot. Содержит команды для загрузки ядра, initrd и DTB. U-Boot выполняет его при старте системы. Этот файл создаётся из `boot.cmd` с помощью утилиты `mkimage`. Если он повреждён или отсутствует, U-Boot не сможет загрузить систему. * `dtb-6.1.43-rockchip-rk3588/` — Копия каталога `dtb/`, обычно появляется, когда ядро устанавливается или обновляется через пакетный менеджер (например, `apt`). Она привязана к конкретной версии ядра — в данном случае `6.1.43-rockchip-rk3588`, для того, чтобы: Хранить DTB-файлы, соответствующие этой версии ядра и избегать конфликты между DTB от разных версий ядра (если используется несколько ядер на одной системе). Менее критичные, но полезные файлы: * `config-6.1.43-rockchip-rk3588` — Конфигурация ядра, использованная при его сборке (он нам понадобится, чтобы пересобрать ядро с iSCSI). * `System.map-6.1.43-rockchip-rk3588` — Карта меток (символов) ядра, полезна для отладки. * `initrd.img-6.1.43-rockchip-rk3588` — Обычный initrd, из которого генерируется uInitrd. * `boot.bmp` и `logo.bmp` — Изображения для экрана загрузки (не влияют на работу системы). ## Устанавливать инструменты для сборки ядра Обновим репозитории и установим минимальный инструментарий для сборки ядра: ```bash sudo apt update sudo apt install -y build-essential bc flex bison libssl-dev libncurses-dev git ``` Нам понадобятся следующие пакеты: * `build-essential` — Включает `gcc` (для ARM64, make и другие базовые инструменты компиляции. * `bc` — Утилита для точных математических вычислений в командной строке. Используется для вычислений в скриптах сборки ядра. * `flex` и `bison` — генератор лексических анализаторов и парсер. Нужны для обработки конфигурационных файлов ядра. * `libssl-dev` — Для поддержки криптографии в ядре и `OpenSSL`. * `libncurses-dev` — Библиотека для создания текстовых интерфейсов в терминале. Необходимо для работы интерфейса `menuconfig` при настройке параметров ядра. * `git` — Для клонирования исходного кода ядра из репозитория Xunlong. > **Примечание:** Если вы хотите собрать ядро на x86-системе, установите кросс-компилятор `gcc-aarch64-linux-gnu` (`sudo apt install gcc-aarch64-linux-gnu`) и используйте его вместо обычного gcc в командах сборки. Он позволит собрать ядро для ARM64-архитектуры на x86-системе. ## Скачивание и подготавливаем исходники ядра Клонируем репозиторий Orange Pi для ядра 6.1 из репозитория Xunlong. Мы будем брать ветку (branch) `orange-pi-6.1-rk35xx`. Это ветка с исходниками для всех устройств на базе Rockchip RK35xx (включая Orange Pi 5 Plus): ```bash git clone --depth 1 https://github.com/orangepi-xunlong/linux-orangepi -b orange-pi-6.1-rk35xx ~/linux-orangepi ``` После клонирования репозитория, переходим в каталог с ним: ```bash cd ~/linux-orangepi ``` И первым делом в `Makefile` установим `EXTRAVERSION` (модификатор версии ядра). Узнаем текущую версию ядра: ```bash uname -r ``` Я на своем Orange Pi 5 Plus вижу (у вас может быть другая версия): ```text 6.1.43-rockchip-rk3588 ``` Открываем `Makefile` в текстовом редакторе: ```bash nano Makefile ``` И устанавливаем модификатор версии ядра, строку `XTRAVERSION =` (у меня это пятая строчка): ```text EXTRAVERSION = -rockchip-rk3588 ``` Затем копируем конфиг текущего ядра в конфиг для сборки. ```bash zcat /proc/config.gz > .config ``` `.config` содержит все текущие настройки ядра. Это очень удобно, так как нужно добавить только поддержку нужных модулей (в нашем случае `iSCSI`), а не настраивать всё с нуля. ## Настройка конфига с iSCSI Теперь нужно отредактировать, `.config` чтобы включить `iSCSI`. Заходим в интерфейс конфигуратора ядра `menuconfig`: ```bash make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig ``` Используя стрелки на клавиатуре, чтобы двигаться по пунктам меню. 1. Перейди в `Device Drivers` → `SCSI device support` → `SCSI Transports`. 2. Найти внутри `iSCSI Transport Attributes`, с помощью стрелок выбрать его. 3. Нажимает `M` (для модуля) — появится `` рядом с пунктом. Это означает, что модуль будет собираться как модуль, а не встраиваться в ядро. Модуль (`iscsi_tcp.ko`) проще протестировать без перезагрузки. 4. В нижнем меню выбрать `` и подтвердим сохранение в `.config`. 6. Вернуться в меню выше `SCSI device support` (через нижнее меню ``). 7. Зайти в раздел `SCSI low-level drivers`. 8. Выбрать `iSCSI Initiator over TCP/IP` и нажать `M` (для модуля). 9. Снова сохраняем конфиг в `.config` (через нижнее меню ``). 10. Выйти из `menuconfig` (через нижнее меню ``, три раза). | ✎ Может быть полезно: | |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | На моём Orange Pi 5 Plus загрузка идет с NVMe диска ([см. как настроить](opi5plus-move-system-to-nvme-or-emmc.md)), и мне было полезно так же включить ещё и систему мониторинга NVMe: `Device Drivers` → `NVME Support`, найти пункт `SNVMe hardware monitoring` и включить его. В нижнем меню выбрать `` и подтвердим сохранение в `.config`. Выйти из `menuconfig` (через нижнее меню ``, три раза). Теперь у меня будет возможность отслеживать состояние NVMe-диска (температуру, износ и т.д.) через инструменты вроде `nvme-cli`. | Проверим, что iSCSI включён: ```bash grep -E "ISCSI_TCP|SCSI_ISCSI_ATTRS|ISCSI_BOOT" .config ``` Должны увидеть что-то типа: ```text CONFIG_SCSI_ISCSI_ATTRS=m CONFIG_ISCSI_TCP=m # CONFIG_ISCSI_BOOT_SYSFS is not set ``` | ✎ Проверка, что включен мониторинг NVMe (если включали): | |---------------------------------------------------------------| | `grep -E "NVME_HWMON" .config` и увидим `CONFIG_NVME_HWMON=y` | ## Компиляция ядра и модулей Запускаем компиляцию ядра и модулей: ```bash make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j8 ``` `-j8` — это количество потоков, используем столько, сколько у нас ядер. На Orange Pi 5 Plus восемь ядер. Но, например, если у вас четыре ядра, то `-j4`. Компиляция займёт 20-40 минут (Orange Pi 5 Plus). Установим модули ядра: ```bash sudo make modules_install ``` После завершения ядро будет находиться в каталоге `~/linux-orangepi/arch/arm64/boot/` (файл `Image`), а дерево описания устройства в `~/linux-orangepi/arch/arm64/boot/dts/rockchip/` (наш файл для Orange Pi 5 Plus -- `rk3588-orangepi-5-plus.dtb`, дле версий 5, 5 Max, AI, Ultra соответствующие файлы там же). Проверим, что ядро скомпилировалось: ```bash ls -l arch/arm64/boot/Image ``` Ожидаемый размер: около 40 МБ: ```text -rw-rw-r-- 1 opi opi 40579584 Mar 22 19:09 arch/arm64/boot/Image ``` Размер должен почти совпасть (или полностью совпадать) с размером текущего ядра: ```bash ls -l /boot/Image ``` ```text -rwxr-xr-x 1 root root 40579584 Nov 21 07:08 /boot/Image ``` И это не ошибка. Мы добавили только `CONFIG_ISCSI_TCP=m` и `CONFIG_SCSI_ISCSI_ATTRS=m`. Это подключит модули (`iscsi_tcp.ko`), но само ядро (`Image`) почти не увеличивается, ведь `.ko`-модуль iSCSI не встраивается в ядро (мы выбрали ``, а не `<*>`). Кроме того, Linux выравнивает размеры файлов по блокам (например, 4 Кб), и добавление пары небольших модулей могут не повлиять на итоговый размер. ## Устанавливаем новое ядро рядом со старым Мы должны скопировать два файла в `/boot`. Первый — это `Image`. Это само ядро, и оно скомпилировалось в каталог `~/linux-orangepi/arch/arm64/boot/`. Второй файл — это `rk3588-orangepi-5-plus.dtb`. Он находится в `~/linux-orangepi/arch/arm64/boot/dts/rockchip/`. Как было сказано выше, это дерево описания оборудования (Device Tree Blob), и нужно при загрузке ядра. Кстати, при компиляции мы получили `.dtb` для всех моделей Orange Pi 5 (5, 5 Plus, 5 Max, AI, Ultra). Для моей модели (Orange Pi 5 Plus) нужен `rk3588-orangepi-5-plus.dtb`, а вы можете взять другой, для своей модели. Копируем новые файлы в `/boot` с уникальными именами (с суффиксом `-iscsi`): ```bash sudo cp ~/linux-orangepi/arch/arm64/boot/Image /boot/Image-iscsi sudo cp ~/linux-orangepi/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dtb /boot/dtb/rockchip/rk3588-orangepi-5-plus.dtb-iscsi ``` Старое ядро и дерево описания переименуем (это будет резервная копия, с суффиксом `-original`): ```bash sudo mv /boot/Image /boot/Image-original sudo mv /boot/dtb/rockchip/rk3588-orangepi-5-plus.dtb /boot/dtb/rockchip/rk3588-orangepi-5-plus.dtb-original ``` Устанавливаем новые ядро и дерево: ```bash sudo cp /boot/Image-iscsi /boot/Image sudo cp /boot/dtb/rockchip/rk3588-orangepi-5-plus.dtb-iscsi /boot/dtb/rockchip/rk3588-orangepi-5-plus.dtb ``` > **Важно**: Не обновляйте `uInitrd`, если текущий работает, — его замена может сломать загрузку системы. Все готово. ## Перезагрузка в новое ядро Тут все просто: ```bash sudo reboot ``` #### Если что-то пошло не так и система не загрузилась Если вы все делали правильно, то такого быть не должно. Но, тем не менее, если загрузка не произошла, то это может выглядеть двумя способами: * Система зависает на этапе загрузки: синенький огонек на Orange Pi не загорается и Ethernet тоже не мигает — _вы неправильно собрали ядро или испортили загрузчик. * Система, вроде как, грузится, но все никак… огоньки весело мигают, но не получается подключиться ни по SSH, ни другим способом, пинги на IP-адрес не проходят — вы забыли подключить модули, накосячили с конфигом или с `.dtb`_. Чтобы починить, загружайтесь с MicroSD-карты (не забудьте отключить питание перед тем как вставить MicroSD-карту). Затем смонтируйте, в зависимости где у вас система, eMMC: ```bash mkdir -p /mnt/emmc mount /dev/mmcblk2p1 /mnt/emmc cd /mnt/emmc ``` …или NVMe: ```bash mkdir -p /mnt/nvme mount /dev/nvme0n1p1 /mnt/nvme cd /mnt/nvme ``` И восстанавливаем старое ядро и дерево описания: ```bash sudo cp Image-original Image sudo cp dtb/rockchip/rk3588-orangepi-5-plus.dtb-original dtb/rockchip/rk3588-orangepi-5-plus.dtb ``` Выключаем систему: ```bash sudo poweroff ``` Вынимаем MicroSD-карту, включаем, и загрузиться старая система. ## Проверка нового ядра Если же иситма поле обновления ядра загрузилась, проверим текущую версию ядра: ```bash uname -r ``` Она должна остаться той же: ```text 6.1.43-rockchip-rk3588 ``` Проверим, работает ли iSCSI: ```bash sudo systemctl status iscsid ``` Увидим что-то вроде: ```text ● iscsid.service - iSCSI initiator daemon (iscsid) Loaded: loaded (/lib/systemd/system/iscsid.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2025-03-24 17:51:59 MSK; 28min ago TriggeredBy: ● iscsid.socket Docs: man:iscsid(8) Main PID: 1070 (iscsid) Tasks: 2 (limit: 18977) Memory: 4.6M CPU: 94ms CGroup: /system.slice/iscsid.service ├─1069 /sbin/iscsid └─1070 /sbin/iscsid мар 24 17:51:58 opi5plus-3 systemd[1]: Starting iSCSI initiator daemon (iscsid)... мар 24 17:51:59 opi5plus-3 iscsid[1061]: iSCSI logger with pid=1069 started! мар 24 17:51:59 opi5plus-3 iscsid[1069]: iSCSI daemon with pid=1070 started! мар 24 17:51:59 opi5plus-3 systemd[1]: Started iSCSI initiator daemon (iscsid). ``` Как видим, `active (running)`, значит iSCSI работает. | ✎ Заметка | |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Если вы включили мониторинг NVMe, то проверим и его. Установим nvme-cli: `sudo apt install nvme-cli` и проверим состояние нашего накопителя `sudo nvme smart-log /dev/nvme0n1`. | **ВСË!** А, да, не забудьте удалить репозиторий с исходниками ядра, если он вам больше не нужен: ```bash rm -rf ~/linux-orangepi ```