Мне удалось запустить Armbian сборку Ubuntu на TV-боксе с новым чипсетом RK3528. Используя конфиги для Hinlink H28K, первого поддерживаемого в Armbian устройства на этом чипе.
Это продолжение статьи, где я описал несколько способов достать Device Tree файлы из Андроид установленного на TV-боксе. Нужно для запуска на конкретном устройстве, даже для одной и той же модели - компоненты устройства могут отличаться, эти детали есть в Device Tree. Эта инструкция рассказывает как собрать и запустить Armbian используя полученный Device Tree файл. Написано для пользователей Линукс, средней сложности - почти всё подробно описано по шагам.
Инструкция для запуска в том числе с USB накопителя, что по умолчанию отключено в загрузчике U-Boot.
Сборка Armbian для RK3528
Рекомендую почитать статью по сборке Armbian для TV-бокса на чипе Amlogic, которая мне немного помогла.
Но мы немного отклонимся от инструкций из той статьи.
$ git clone --depth=1 https://github.com/armbian/build armbian-build
$ cd armbian-build
Используйте --depth=1
где можно, вряд ли вам нужна вся история коммитов, а в некоторых репозиториях история занимает в десятки раз больше последнего состояния, достаточного для сборки.
Будем использовать конфиг для мини-роутера Hinlink H28K.
$ ./compile.sh build BOARD=hinlink-h28k EXPERT=yes KERNEL_GIT=shallow
KERNEL_GIT=shallow
означает --depth=1
для исходников ядра, чтобы не потратить много времени на выкачивания их из интернета и кучу места на диске для хранения ~миллиона мелких файлов.
Вам будет предложено выбрать дистрибутив что вам нравится. У меня заработал Ubuntu 20.04 focal с Xfce десктопом. Потом я попробовал Ubuntu 22.04 jammy с Mate десктопом (который мне больше нравится) - не запускается. Подумал, что может быть это из-за jammy, и собрал focal с Mate - тоже не запускается. Собрал jammy с Xfce - запустился! Так что, имейте в виду, что не все варианты сборки Armbian, что можно выбрать - у вас заработают. (причину нашел - добавил решение в конце статьи)
Скрипт напишет как повторить выбранные опции, например:
./compile.sh build BOARD=hinlink-h28k BRANCH=legacy BUILD_DESKTOP=yes BUILD_MINIMAL=no DESKTOP_ENVIRONMENT=xfce DESKTOP_ENVIRONMENT_CONFIG_NAME=config_base EXPERT=yes KERNEL_GIT=shallow RELEASE=jammy
Сборка Armbian будет компилировать только ядро Линукс, остальные пакеты будут скачаны в готовом виде.
Готовые образы дисков будут лежать в output/images
, например с таким именем:
Armbian_23.11.0-trunk_Hinlink-h28k_jammy_legacy_5.10.160_xfce_desktop.img
Добавление своего Device Tree
Как его получить - читайте в моей предыдущей статье.
Можно добавить прямо в образ диска, до записи:
$ sudo mount -o rw,loop,offset=16M <образ-armbian.img> /mnt/loopimage
Или после записи на USB/карту (у меня автоматически раздел не монтируется):
$ sudo mount /dev/sdX1 <директория>
Заходим в примонтированный раздел, в директории dtb/rockchip
хранятся .dtb, сюда надо скопировать свой, полученный из boot раздела Андроид.
Например, с таким именем: dtb/rockchip/rk3528-tvbox.dtb
Настройки бута хранятся в armbianEnv.txt
, будет примерно такое содержимое (UUID раздела меняется для разных сборок Armbian):
verbosity=1
bootlogo=true
overlay_prefix=rk35xx
fdtfile=rockchip/rk3528-hinlink-h28k.dtb
rootdev=UUID=813764a1-91f7-4247-992f-2ade953afa7d
rootfstype=ext4
Надо изменить строку fdtfile=
, указав на .dtb со своего устройства:
fdtfile=rockchip/rk3528-tvbox.dtb
Когда закончили, не забудьте отмонтировать раздел, чтобы все данные сохранились на диск:
$ sudo umount <устройство или директория>
Если на вашем TV-боксе вас есть разъём под карту памяти, то можете вставить карту с записанным образом в него, и пропустить пару следующих разделов этой инструкции.
Порядок загрузки Rockchip устройств
Сначала загрузка идёт с карты памяти, если есть разъём для карты памяти и вставленна карта. Карта памяти подключенная через USB картридер - работает как обычный USB накопитель, поэтому в начальной загрузке не учитывается. Если карта памяти не обнаружена - то загружается с EMMC.
С карты/EMMC должен загрузиться начальный загрузчик SPL, который далее запускает U-Boot, и если U-Boot был собран с опцией CONFIG_ROCKCHIP_USB_BOOT=y
, то пытается загрузиться с первого найденного USB устройства в котором на 64 секторе (0x8000 в байтах) стоит один из заголовков Rockchip загрузчиков. В коде U-Boot есть ограничение, что если загрузка началась с карты, то загружаться с USB накопителей уже не будет. Если был найден USB носитель с системой, то SPL и U-Boot записанные на USB накопитель - не выполняются, U-Boot уже загруженный с EMMC сразу переходит к поиску скриптов для загрузки ядра на USB накопителе.
Сборка своего U-Boot с поддержкой загрузки с USB
Нужно для загрузки Linux с USB носителя или для дампа разделов с EMMC без хаков. Описано в предыдущей статье, но повторю.
$ sudo apt-get install gcc-aarch64-linux-gnu
$ git clone --depth=1 https://github.com/rockchip-linux/u-boot.git
$ git clone --depth=1 https://github.com/rockchip-linux/rkbin.git
$ cd u-boot
Заменяем в начале make.sh
кросс-компилятор на системный, из пакета gcc-aarch64-linux-gnu
: CROSS_COMPILE_ARM64=/usr/bin/aarch64-linux-gnu-
В Armbian есть патчи для hinlink-h28k, лежат они тут:
armbian-build/patch/u-boot/legacy/board_hinlink-h28k
Устанавливаем их находясь в директории u-boot:
$ cat <path-to-armbian-build>/patch/u-boot/legacy/board_hinlink-h28k/*.patch | patch -p1
Патчи добавляют исправления загрузки Линукс и конфиг для Hinlink-H28K. Без этих патчей у вас даже комплектный Андроид из EMMC не станет грузиться.
Перед сборкой сначала уберём ограничение чтения в режиме download:
$ sed -i 's/(blkstart + blkcnt) > RKUSB_READ_LIMIT_ADDR/0/' cmd/rockusb.c
И добавим в конфиг для H28K поддержку загрузки с USB накопителей:
$ sed -i '1i CONFIG_ROCKCHIP_USB_BOOT=y' configs/hinlink_rk3528_defconfig
Можно собирать: $ ./make.sh hinlink_rk3528
Загружаем на устройство: $ rkflashtool w 0x4000 0x2000 < uboot.img
Про rkflashtool
рассказано в предыдущей статье. Для U-Boot на Rockchip есть стандартный адрес на диске - 8МБ от начала (в Андроиде он оформлен как раздел, на Линукс - нет), занимает 4МБ - в которых повторяется два раза.
Первый запуск Armbian
При первом запуске нужно подключить устройство к локальной сети, если нет Ethernet разъёма - то через USB адаптер.
При первом подключении по ssh, с именем root и паролем 1234, вас спросят: новый пароль для рута, имя первого пользователя (с правами рута) и пароль для него, язык и часовой пояс. После этого заработает графическая оболочка.
Нечитаемые флэшки
У меня есть USB 3.0 флэшка Kingston на 32Гб - почему-то она как загрузочная не определяется. А вот новая карта на 32Гб через картридер работает. Правда картридер USB 2.0 - возможно в этом дело.
Скорее всего, U-Boot при проверке USB носителей проверяет на наличие интерфейса USB 1.1, а на упаковке флэшки было написано только про USB 2.0/3.0/3.1/3.2. Даже если ОС сможет эту флэшку читать - всё равно для U-Boot нужна поддержка старого стандарта.
Xfce проблемы
Оказалось, что в Xfce из сборки Armbian не работают программы что должны показывать окно для ввода пароля для получения рута. Это множество системных утилит. Решается установкой этого пакета:
sudo apt-get install policykit-1-gnome
После этого надо сделать logout и войти по новой (перезагрузка системы не нужна).
Другие проблемы
У меня нашелся поддельный USB 2.0 хаб, поддельность в том, что работает он явно не со скоростью USB 2.0, а более низкой. В результате чего загрузка Линукс страшно тормозит. Через него я подключал картридер с картой, на которой был записан Линукс.
Через другой USB 2.0 хаб грузится быстро. У меня худший вариант TV-бокса по количеству портов - разъёма карты памяти нет, и один USB 2.0 порт.
Еще один патч для U-Boot
Добавил в статью после публикации. Решает проблему загрузки, что зависит от каких-то случайностей, наверное от мусора в памяти. Именно из-за этого у меня не загружался Armbian с Mate десктопом. По UART в логе такие ошибки:
No resource file:
VP0 fail to load kernel logo
No resource file:
VP1 fail to load kernel logo
А потом падение, на разыменовании нулевого указателя.
U-Boot для Rockchip если скомпилирован с CONFIG_DRM_ROCKCHIP
(по умолчанию включено) инициализирует дисплей и показывает лого. Лого читается из boot раздела Android, в собственном формате ресурсов от Rockchip. При загрузке Linux с USB накопителя или карты памяти - лого ищется уже в них, и не находится. Они плохо проверяли такой вариант развития событий, может произойти падение в U-Boot.
Данный патч использует вместо лого серый квадрат, который либо рисуется по центру или растягивается на весь экран (зависит от содержимого Device Tree).
--- a/drivers/video/drm/rockchip_display.c
+++ b/drivers/video/drm/rockchip_display.c
@@ -1169,6 +1169,17 @@ static int load_bmp_logo(struct logo_info *logo, const char *bmp_name)
if (!header)
return -ENOMEM;
+#if 1
+ logo->width = logo->height = 256; logo->bpp = 24;
+ dst_size = logo->width * logo->height * logo->bpp >> 3;
+ dst = get_display_buffer(dst_size);
+ if (!dst) { ret = -ENOMEM; goto free_header; }
+ memset(dst, 127, dst_size);
+ logo->offset = logo->ymirror = 0; logo->mem = dst;
+ memcpy(&logo_cache->logo, logo, sizeof(*logo));
+ flush_dcache_range((ulong)dst, ALIGN((ulong)dst + dst_size, CONFIG_SYS_CACHELINE_SIZE));
+ goto free_header;
+#endif
len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE);
if (len != RK_BLK_SIZE) {
ret = -EINVAL;
Не пробовал запускать Линукс на сборке U-Boot без CONFIG_DRM_ROCKCHIP
, но у меня не запускается Андроид без CONFIG_DRM_ROCKCHIP
. Подозреваю, что с экраном инициализируется что-то важное, поэтому лучше не отключать этот код.
Обновить U-Boot в образе Armbian можно так:
dd if=uboot.img of=Armbian.img bs=1M count=4 seek=8
Включение 3D ускорения
В конфиге для <armbian-build>/config/kernel/linux-rk35xx-legacy.config при сборке Armbian включить сборку драйвера под названием Lima, что поддерживает 3D ускорение для Mali-400 и Mali-450. После этого нужно пересобрать образ ОС. (=y
означает собрать в составе ядра, =m
собрать отдельным модулем).
# CONFIG_TINYDRM_ST7735R is not set
# CONFIG_DRM_PL111 is not set
-# CONFIG_DRM_LIMA is not set
-CONFIG_DRM_PANFROST=m
+CONFIG_DRM_LIMA=y
+# CONFIG_DRM_PANFROST is not set
# CONFIG_DRM_TIDSS is not set
# CONFIG_DRM_LEGACY is not set
CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y
Но драйвер Lima ожидает, что в Device Tree будут старые названия. Которые Rockchip переименовал в RK3528, чтобы соответствовали названиям для их более новых GPU. Поэтому декомпилируем .dtb полученный из Android:
$ dtc -I dtb -O dts rk3528.dtb -o rk3528.dts
Далее надо заменить interrupt-names и clock-names на старые. В массиве clocks стало шесть чисел (два числа на одно название). Я оставил новые имена для clocks, добавив старые в конец ("bus", "core"). Также скопировал первые 4 числа из массива clocks и добавил в конец массива (0x07 0x16 0x02 0x113), теперь по старым названиям будут читаться они.
gpu@ff700000 {
compatible = "arm,mali-450";
reg = <0x00 0xff700000 0x00 0x40000>;
interrupts = <0x00 0x58 0x04 0x00 0x59 0x04 0x00 0x56 0x04 0x00 0x5c 0x04 0x00 0x5d 0x04 0x00 0x5a 0x04 0x00 0x5b 0x04>;
- interrupt-names = "Mali_GP_IRQ\0Mali_GP_MMU_IRQ\0IRQPP\0Mali_PP0_IRQ\0Mali_PP0_MMU_IRQ\0Mali_PP1_IRQ\0Mali_PP1_MMU_IRQ";
- clocks = <0x07 0x16 0x02 0x113 0x02 0x10e>;
- clock-names = "clk_mali\0aclk_gpu_mali\0pclk_gpu";
+ interrupt-names = "gp\0gpmmu\0pp\0pp0\0ppmmu0\0pp1\0ppmmu1";
+ clocks = <0x07 0x16 0x02 0x113 0x02 0x10e 0x07 0x16 0x02 0x113>;
+ clock-names = "clk_mali\0aclk_gpu_mali\0pclk_gpu", "bus", "core";
assigned-clocks = <0x07 0x16>;
assigned-clock-rates = <0x11e1a300>;
power-domains = <0x26 0x04>;
Компилируем обратно: $ dtc -I dts -O dtb rk3528.dts -o rk3528-new.dtb
Видеокарта Mali-450 старая (2012-го) и слабая, так что не ожидайте от неё слишком многого. Например, Quake 3 работает с низким FPS. Doom 3 не запустится вообще, драйвер не поддерживает нужные OpenGL расширения.
Дальнейшие доработки
Разместил здесь. Я нашел все расхождения Device Tree с теми что есть в Линукс, в Линуксе представлены конфиги для демо-плат, и названия этих демо-плат в конфигах на TV-боксах поленились менять на название устройства. Конфиги в Линуксе имеют больше информации для правильной работы драйверов. Скомбинировав Device Tree из Линукс и с устройства - я исправил пару падений драйверов, что видел в логе.
Также я добавил в конфиг ядра Линукс все драйвера что заметил в Андроид. Таким образом заработал нужный драйвер для звука и ТВ-выход. HDMI-аудио при этом не работает, хотя драйвер есть, где происходит затык - я не знаю, звук через драйвер воспроизводится, но на колонки монитора ничего не приходит. Звук из выхода на телевизор работает. И видео на телевизор работает.
Также я включил драйвера для аппаратного ускорения декодирования/кодирования видео, но не знаю как их проверить. Также какой-то драйвер для аппаратного ускорения алгоритмов шифрования.
В логах WiFi драйвер многократно жалуется что не может найти прошивку. Пробовал взять прошивку из предустановленного Android, она загружается, но потом следует ошибка что драйвер не может включить устройство, видимо в драйвере (или Device Tree) чего-то не хватает.