Одноплатные компьютеры своим появлением взяли на себя огромное количество задач и с каждым днём решают всё больше наших проблем. Но многие окружающие нас бытовые устройства являются одноплатными компьютерами с практически идентичной начинкой и телевизионные приставки классический тому пример.
Когда-то я приобрел ТВ приставку X96 Max Plus 100W на Android, чтобы потестить вдоль и поперек и скоро пришел к тому, что классическое ее применение для просмотра мультиков и Android игр мне не интересно. Очень захотелось установить Linux и использовать приставку как обычный мини-компьютер. Вот для таких энтузиастов, кто хочет установить Linux на телевизионную приставку, превратив ее в сервер или даже в десктопный компьютер, я и расскажу свою историю. История отличается от всех остальных подобных реалистичностью, когда результата по инструкции достичь не удается.
Этот эксперимент можно повторить даже не затрагивая работоспособность установленной системы Android лишь подготовив загрузочный носитель и загрузившись с него.
Если вдруг читатель не знает зачем нужен такой мини-компьютер, поясню: такой тихий и экономичный гаджет превосходен как сервер умного дома на HomeAssistant, домашний веб-сервер на nginx, сервер телефонии на Asterisk, для сбора статистики с метеостанции, рутер, игровая консоль на Retro-Pi, медиацентр, для конвертирования RTSP видеопотока с камеры в HLS для встраивания на веб-страницу, TorrServer для просмотра фильмов прямо с торрентов. Благо, ресурсов у современных приставок более чем достаточно для большинства подобных задач.
Читать далее
Представьте себе сколько таких телевизионных приставок выбрасывается провайдерами по истечении контракта, ведь пользователи по контракту зачастую обязаны ее вернуть. Но даже купить ТВ приставку, такую как Transpeed 6k (на Алиэкспресс называется H616 по имени процессора), как минимум не дороже, чем ее клон-одноплатник Orange Pi Zero 2 на том же процессоре. Такой компьютер будет в красивом корпусе и с плюшками вроде пульта, HDMI кабеляи и БП. Вот описание незначительных различий между этими устройствами: http://nskhuman.ru/allwinner/fdt/basefdt.php
Но вернемся к приставке, которая у меня была и над которой я проводил свои эксперименты. Исследование и вскрытие показало что внутри приставки X96 Max Plus 100W:
CPU: Amlogic S905X3 quad-core ARM Cortex A55
GPU: ARM Mali-G31MP
Radio module: W522A
Memory: DDR3 4GB, FLASH 64GB
Support 10/100M Ethernet, 2.4 and 5G WiFi, BT4.0;
USB3.0 x 1, USB2.0 x 1, TF Card
HDMI, AV, SPDIF
Фото с форума Armbian похожей приставки, с абсолютно тем же названием. Даже на плате кодовое название совпадает: Q53X_141 V4.1 20112. Но моя плата отличается тем, что на борту 64 гига EMMC и отсутствует гигабитный PHY чип неподалеку от ethernet интерфейса. Вместо внешнего PHY чипа для сети используются встроенные возможности SoC. Это важно и к этому вопросу еще вернемся.
Обозреваемая приставка очень близка по характеристикам к одноплатнику Banana Pi M2 Pro и Banana M5. Но использование официальной прошивки Armbian под эту платформу я на приставке даже не проверял и пошел другим путем. Было бы интересно узнать, если кто пробовал подобное.
Armbian
За небогатым выбором ОС остановился на Armbian - Debian для ARM компьютеров. Взял готовый образ под свой процессор, но "искаропки" он конечно-же не завелся:
https://github.com/ophub/amlogic-s9xxx-armbian/releases/
Пришлось разбираться во всех нюансах ARM платформы, которая совсем уж не похожа на столь привычный и знакомый нам с детства x86. Самое первое - это отсутствие привычного меню для настройки BIOS/UEFI. Зато на таких платах всегда есть UART контакты RX/TX, к которым можно подпаяться и подключиться USB UART адаптером, получив доступ к консоли устройства. Если вам повезет и подготовленный загрузочный носитель заработает, то паять UART не придется.
По инструкции установки Armbian на приставку все выглядит очень просто: скачать образ, записать его на носитель, вставить носитель в слот приставки, загрузиться в Андроид и выбрать обновление с внешнего носителя, перезагрузиться, подключиться через ssh к своему новому мини-компьютеру на Armbian и начать настраивать под себя. Увы, на практике по этой инструкции моя приставка не показывала абсолютно никаких признаков жизни ни через HDMI, ни на своем встроенном дисплее с часиками. Выглядит как кирпич.
Чтобы заставить приставку грузиться с флэшки у меня прошел следующий трюк: выключаю питание приставки, зубочисткой зажимаю кнопку внутри входа AV (mini-jack 3.5), включаю питание. Но официальная рекомендация по установке Armbian твердит что нужно это делать через режим разработчика Android (позже будет о том, как это сделать).
Попытку загрузки с флэшки я распознаю по тому факту, что перестает загружаться Android. Чтобы сделать носитель загрузочным, скрипты должны найти файл u-boot.ext. Изначально такого файла нет, потому что образ системы универсален: есть коллекция таких файлов под различные устройства. Я попробовал переименовывать имеющиеся файлы u-boot-x96maxplus.bin и u-boot-x96max.bin, как наиболее подходящие по имени приставки. Забегая вперед, скажу, что это подходящие файлы. Любой из них можно использовать для загрузки этой приставки. Я пробовал подключать различные DTB файлы. Но система в сети не появлялась. Попытки тыкаться носом как слепой котенок начинали казаться тупиковыми. Нужно было увидеть логи чтобы выявить в чем ошибка.
Вообще, эти эксперименты я начал еще год назад и подопытная приставка была довольно сложным кейсом за счет огромного количества отличающихся ревизий с новым оборудованием и отсутствующими открытыми драйверами. Тогда она еще не поддерживалась в Armbian и приходилось мудрить. Cо многими другими приставками дела обстояли несколько проще. Если вам тупо установить Linux и не вникать во внутренности загрузчика и ядра, то стоит выбрать нечто более обкатанное вроде приставок на процессоре Amlogic S905X2. В таком случае вы можете просто скачать готовый образ системы и сделать все по инструкции, а мой пост вам даже не понадобится. Пошаговых инструкций в интернете миллион. Впрочем, сейчас моя приставка уже поддерживается и, скорее всего, со всеми приведенными граблями вы не столкнетесь. Но мой опыт вполне может пригодиться.
Подключение UART консоли
Чтобы выяснить суть проблемы и увидеть логи нужно подключиться к консоли через предусмотренный для этого UART интерфейс. Для этого понадобится UART USB адаптер и паяльник, чтобы подпаять три проводка: RX (receive), TX (transmit), GND. Мой адаптер CH340G позволяет переключать уровень сигнала между 3.3в. или 5в. Но подойдет любой другой на 3.3в. Соединять нужно перекрестно: RX приставки на TX адаптера и TX приставки на RX адаптера. Контакт 3.3в. не подключаем никуда. После подключения адаптера на десктопном Linux должно появиться устройство /dev/ttyUSB0, которое говорит, что адаптер распознался и готов к использованию.
picocom -b 115200 -r -l /dev/ttyUSB0
Как только включим питание приставки, окно picocom должно показать логи загрузки системы. Тут всё нужно внимательно прочесть и выявить ошибки. Усложняется все тем, что большинство ошибок являются нормой, так как скрипты прорабатывают различные варианты загрузки и вываливают всю информацию по этому поводу.
Еще очень полезно подключить UART консоль тем, кто хочет попасть в шел-консоль Android. На моей прошивке не понадобился ни логин ни пароль: сразу после загрузки я мог писать команды.
console:/ $ uname -a
Linux localhost 4.9.113 #3 SMP PREEMPT Fri Apr 15 18:28:24 CST 2022 armv7l
console:/ $ lsmod
lsmod
Module Size Used by
sdio_bt 20480 0
vlsicomm 1576960 0
aml_sdio 28672 2 sdio_bt,vlsicomm
galcore 372736 0
aml_hardware_dmx 135168 0
amvdec_mavs 40960 0
vpu 45056 0
encoder 49152 0
amvdec_avs2 192512 0
amvdec_vp9 110592 0
amvdec_vc1 57344 0
amvdec_real 40960 0
amvdec_mmpeg4 40960 0
amvdec_mpeg4 57344 0
amvdec_mmpeg12 40960 0
amvdec_mpeg12 102400 0
amvdec_mmjpeg 28672 0
amvdec_mjpeg 40960 0
amvdec_h265 135168 0
amvdec_h264mvc 53248 0
amvdec_mh264 155648 0
amvdec_h264 135168 0
amvdec_avs 65536 0
stream_input 159744 12 aml_hardware_dmx,amvdec_mavs,amvdec_avs2,amvdec_vp9,amvdec_real,amvdec_mmpeg12,amvdec_mpeg12,amvdec_h265,amvdec_h264mvc,amvdec_mh264,amvdec_h264,amvdec_avs
decoder_common 172032 18 amvdec_mavs,encoder,amvdec_avs2,amvdec_vp9,amvdec_vc1,amvdec_real,amvdec_mmpeg4,amvdec_mpeg4,amvdec_mmpeg12,amvdec_mpeg12,amvdec_mmjpeg,amvdec_mjpeg,amvdec_h265,amvdec_h264mvc,amvdec_mh264,amvdec_h264,amvdec_avs,stream_input
firmware 24576 19 amvdec_mavs,encoder,amvdec_avs2,amvdec_vp9,amvdec_vc1,amvdec_real,amvdec_mmpeg4,amvdec_mpeg4,amvdec_mmpeg12,amvdec_mpeg12,amvdec_mmjpeg,amvdec_mjpeg,amvdec_h265,amvdec_h264mvc,amvdec_mh264,amvdec_h264,amvdec_avs,stream_input,decoder_common
media_clock 36864 14 aml_hardware_dmx,amvdec_mavs,vpu,encoder,amvdec_avs2,amvdec_vp9,amvdec_mpeg12,amvdec_h265,amvdec_mh264,amvdec_h264,amvdec_avs,stream_input,decoder_common,firmware
tb_detect 20480 0
atbm8881_fe_32 122880 0
mali_kbase 471040 11
При попытке загрузки с флэшки мне эта консоль навалила огромную кучу текста, которая сначала ошарашила. Но, покопавшись некоторое время, я понял суть первой проблемы: флэшка не загрузочная лишь потому, что она тупо не совместима с загрузчиком. Позже я выяснил, что с сменой флэшки на более другую (брэнд не имеет значения) можно перейти к решению последующих проблем, одной из которых являлся неработающий сетевой адаптер. Но к этому я пришел позже. А пока я хотел понять, что дает самостоятельная сборка Armbian, какие проблемы можно с ее помощью решить.
Получение исходников Armbian и компиляция
Сборка Armbian невероятно просто и надежно сделана. Никакой установки стороннего софта мне делать не пришлось потому что все собирается в контейнере-песочнице, скачивая все необходимые зависимости. Сборку я делал в системе Gentoo, где отсутствуют такие команды как apt или deb, используемые в большинстве скриптов для установки. Главное выделить под эту вакханалию по меньшей мере 35 гигабайт места.
git clone https://github.com/armbian/build
cd build
/compile.sh EXPERT="yes"
Параметр EXPERT="yes" нужен чтобы нам, как экспертам, открылись недоступные для нубов экспериментальные платформы. Я выбрал x96maxplus - "Amlogic S905X3 quad core 2-4GB RAM SoC eMMC GBE USB3 SPI". Дальше выбираем по очереди:
"Do not change the kernel configuration" выбрать не грешно если вы не настоящий эксперт. А настоящий эксперт на этом этапе сможет к примеру включить дополнительные драйвера в компилируемом ядре.
x96maxplus - выбираем если у вас процессор Amlogic s905x3 как у меня, иначе разбирайтесь какая платформа вам подойдет.
current или edge (latest). Я остановился на current чтобы выбрать не самые экспериментальные базовые системы. Но это совсем не значит, что этим выбором можно защититься от неприятностей, которые вас давно ждут, как только вы назвались экспертом.
Выбираем базовую ОС.
У меня заработала только Ubuntu Jammy 22.04 LTS. Заставить kde-plasma нормально работать в Debian 11 и 12 у меня не получилось как я ее не пытался удалять и ставить заново через apt (о подобных неприятностях я и говорил).Desktop Environment.
Я выбрал kde-plasma. И да, использование kde-plasma на приставке - это ошибка (тормозит жутко).config-base - лишь одна опция
Выбираете нужный вам софт
Дальше идет процесс компиляции, повторить который можно не проходя заново все этапы через меню. Меню конфигурации лишь сформировало вот такую команду, запуск которой нам соберет образ для загрузочного носителя:
./compile.sh build BOARD=x96maxplus BRANCH=current BUILD_DESKTOP=yes BUILD_MINIMAL=no DESKTOP_APPGROUPS_SELECTED='3dsupport browsers' DESKTOP_ENVIRONMENT=kde-plasma DESKTOP_ENVIRONMENT_CONFIG_NAME=config_base EXPERT=yes KERNEL_CONFIGURE=no RELEASE=jammy
К сожалению, компиляция не решила проблем неработоспособности сетевого интерфейса eth0, но в будущем позволила опробовать различные версии различных дистрибутивов Debian и Ubuntu в то время как выбор готовых сборок очень ограничен. Если вас не толкают возникшие трудности на эксперименты как меня, смело пропускайте самостоятельную сборку. Одной из таких трудностей для меня оказалась установка kde-plasma через apt. Понятия не имею, почему такое происходит, но заметил, что иногда программы, скомпилированные локально через сборщик работают корректно, а установленные через apt глючат. Конкретно, в KDE не отображались иконки и меню.
Запись образа на носитель
Если ошибок при компиляции не было, то в директории ./output/images/ загрузочный образ диска будет ждать записи на носитель. Используйте Rufus или Balena Etcher для записи образа на флэшку, а я сделаю старым дедовским методом:
dd if=output/images/Armbian_23.08.0_amlogic_s905x3_lunar_6.1.55_server_2023.10.02.img of=/dev/sde bs=1M
В качестве загрузочного носителя можно использовать как USB флэшку, так и MicroSD карточку. Но, имейте ввиду, что загрузчик может закапризничать независимо от брендовости. Так у меня он отказался работать с MicroSD Samsung на 32Гб. и Transcend 16Гб., но заработал с древней ноунейм карточкой 16Гб. с надписью Taiwan и с обычной древней USB флэшкой Transcend 8Гб. Выглядят эти ошибки вот так:
emmc/sd response crc error, cmd16, cmd->cmdarg=0x200, status=0x1ff2400
** Unrecognized filesystem type **
Правки полученного носителя
Этот этап для меня был самым сложным и занял больше всего времени. По сути на этом этапе вы находитесь будто в самом начале поста скачали готовый образ носителя. Мне же чтобы добиться работоспособности пришлось вникнуть в суть происходящих процессов, о которых я вам и поведаю.
Дело в том, что эта инструкция - хак. Никакой загрузки другой операционной системы с флэшки в ТВ приставке, конечно же, не предусмотрено, как и официальных альтернативных систем кроме Android от поставщика. Но есть возможность обновления с внешнего носителя. Такой носитель нам и нужно сделать, а потом перейти в режим разработчика или зубочисткой заставить плату загрузиться с него.
Основная проблема заключается в том, что приставки даже на одном и том же процессоре могут отличаться без предупреждений производителей (ведь одинаковые модели производят в разных китайских подвалах, как мы догадываемся). Заменят микросхему сети Realtek на Ampak или решат не паять внешний PHY, в свою прошивку внесут изменения в драйверах, но акцентировать внимание на этом не будут. А это нужно знать чтобы выбрать подходящий загрузчик и настроить эти устройства.
Итак, для корректной загрузки нам нужно найти подходящий для нашей платформы загрузчик u-boot и, специфический для ARM платформы, файл DTB (device tree blob).
Усложняется ситуация тем, что на приставке название пишется не полное. Например, на моей написано X96 Max+. А вот, чтобы выяснить что она "100W" пришлось потрудиться. Ведь именно у этой модели на борту микросхема радиомодуля, отвечающего за BT и Wifi малораспространенная W522A. Можно взять прошивку от похожей платы, но радиомодуль там работать не будет. Впрочем, как спойлер, скажу что у меня в Armbian он так и не заработал.
Во встраиваемых системах на ARM для того чтобы инициализировать устройства платы, которые не могут быть определены автоматически, используют Device Tree структуры. К таким устройствам относятся процессор, память. В исходных файлах Device Tree Source (DTS) текстом описываются устройства, частоты, адреса. Эти человекочитаемые файлы компилируются в бинарные DTB (Device Tree Blob), которые уже понимает ядро Linux. Чтобы не утонуть в дебрях деревьев устройств нам нужно просто подобрать подходящие к нашей плате DTB файлы. Откройте на полученной после записи образа флэшке раздел armbi_boot. В директории ./dtb/amlogic есть коллекция файлов, из которых нам нужно выбрать подходящий к нашей плате. Казалось бы, берем meson-sm1-h96-max.dtb или meson-g12a-x96-max.dtb и вписываем в ./extlinux/extlinux.conf . Но не тут-то было! Ни с одним из них не работает сеть:
root@aml-s9xx-box:/home/oper# ifconfig eth0 192.168.1.4/24
SIOCSIFFLAGS: Connection timed out
Если без wifi/BT я еще готов мириться, то вот без ethernet мне этот микрокомпьютер совсем не годится. Коллекция DTB файлов лежит на флэшке в разделе armbi_boot в директории ./dtb/amlogic.
Почитав форумы Armbian, все у кого такая приставка, как у меня X96 Max Plus 100W использовали файл meson-sm1-x96-max-plus-100m.dtb. Но у меня и с ним сеть не заработала. А весь секрет оказался в том, что у них на приставке была запаяна микросхема PHY для гигабитной сети, фото которой я показал в самом начале. Мне же понадобится встроенная в SOC подсистема, которая называется RMII и есть файл DTB, который ее поддерживает: meson-g12a-x96-max-rmii.dtb. Вот это и есть тот файл DTB, который позволил мне использовать eth0 в Armbian. Выяснить эту проблему и проблему с несовместимой флэшкой без UART консоли было бы невозможно.
Уроки u-boot
Пришло время рассказать, как я выяснил что флэшка просто несовместима с загрузчиком. Решение простое, но чтобы его увидеть мне пришлось потратить кучу времени и разобраться с загрузчиком u-boot, скриптами загрузки и с теми сообщениями что он мне вываливал. Всё как в байке про специалиста, который брал 1$ за удар молотком и 999$ за то, что знал куда ударить. Делюсь рецептом как выяснять куда нужно ударить.
Нажимаем в консоли сразу после включения много раз Ctrl+C и попадаем в командную строку загрузчика u-boot. Это совсем не Linux, но работать в нем с периферийными устройствами придется. И чтобы вы могли докопаться до сути в случае проблемы с загрузкой покажу несколько приемов для затравки.
Команда help напишет вам список поддерживаемых команд. Из этих команд можно составлять скрипты, которые несколько напоминают bash.
g12a_u212_v1#help
? - alias for 'help'
aml_sysrecovery- Burning with amlogic format package from partition sysrecovery
amlmmc - AMLMMC sub system
amlnf - aml mtd nand sub-system
autoscr - run script from memory
avb - avb
base - print or set address offset
bcb - bcb
bmp - manipulate BMP image data
boot_cooling- cpu temp-system
booti - boot arm64 Linux Image image from memory
bootm - boot application image from memory
bootp - boot image via network using BOOTP/TFTP protocol
cbusreg - cbus register read/write
chpart - change active partition
clkmsr - Amlogic measure clock
cmp - memory compare
cp - memory copy
crc32 - checksum calculation
cvbs - CVBS sub-system
dcache - enable or disable data cache
defenv_reserv- reserve some specified envs after defaulting env
dhcp - boot image via network using DHCP/TFTP protocol
dovi - Dolby_vision sub-system
dtimg - manipulate dtb/dtbo Android image
echo - echo args to console
efuse - efuse commands
efuse_user- efuse user space read write ops
emmc - EMMC sub system
env - environment handling commands
ethloop - ethloop - loopback test using ethernet test package
exit - exit script
ext4load- load binary file from a Ext4 filesystem
ext4ls - list files in a directory (default /)
ext4size- determine a file's size
false - do nothing, unsuccessfully
fastboot- use USB Fastboot protocol
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls - list files in a directory (default /)
fatsize - determine a file's size
fdt - flattened device tree utility commands
forceupdate- forceupdate
get_avb_mode- get_avb_mode
get_bootloaderversion- print bootloader version
get_rebootmode- get reboot mode
get_system_as_root_mode- get_system_as_root_mode
get_valid_slot- get_valid_slot
go - start application at address 'addr'
gpio - query and control gpio pins
gpt - GUID Partition Table
guid - GUID - generate Globally Unique Identifier based on random UUID
hdmitx - HDMITX sub-system 20190123
help - print command description/usage
i2c - I2C sub-system
icache - enable or disable instruction cache
img_osd - image osd sub-system
imgread - Read the image from internal flash with actual size
itest - return true/false on integer compare
jtagoff - disable jtag
jtagon - enable jtag
keyman - Unify key ops interfaces based dts cfg
keyunify- key unify sub-system
ld_bl40 - load bl40 and run bl40.bin from bl33
loadb - load binary file over serial line (kermit mode)
loadx - load binary file over serial line (xmodem mode)
loady - load binary file over serial line (ymodem mode)
loop - infinite loop on address range
macreg - ethernet mac register read/write/dump
md - memory display
mm - memory modify (auto-incrementing address)
mmc - MMC sub system
mmcinfo - display MMC info
mtdparts- define flash/nand partitions
mw - memory write (fill)
mwm - mw mask function
nand - NAND sub-system
nboot - boot from NAND device
nm - memory modify (constant address)
open_scp_log- print SCP messgage
osd - osd sub-system
phyreg - ethernet phy register read/write/dump
ping - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
query - SoC query commands
rarpboot- boot image via network using RARP/TFTP protocol
readMetadata- readMetadata
read_temp- cpu temp-system
reboot - set reboot mode and reboot system
reset - Perform RESET of the CPU
ringmsr - Amlogic measure ring
rpmb_state- RPMB sub-system
rsvmem - reserve memory
run - run commands in an environment variable
saradc - saradc sub-system
saradc_12bit- saradc sub-system
saveenv - save environment variables to persistent storage
sdc_burn- Burning with amlogic format package in sdmmc
sdc_update- Burning a partition with image file in sdmmc card
set_active_slot- set_active_slot
set_trim_base- cpu temp-system
set_usb_boot- set usb boot mode
setenv - set environment variables
sf - SPI flash sub-system
showvar - print local hushshell variables
sleep - delay execution for some time
sspi - SPI utility command
store - STORE sub-system
systemoff- system off
tee_log_level- update tee log level
temp_triming- cpu temp-system
test - minimal test like /bin/sh
tftpboot- boot image via network using TFTP protocol
true - do nothing, successfully
ubi - ubi commands
ubifsload- load file from an UBIFS filesystem
ubifsls - list files in a directory
ubifsmount- mount UBIFS volume
ubifsumount- unmount UBIFS volume
ui - ui sub-system
unpackimg- un pack logo image into pictures
update - Enter v2 usbburning mode
usb - USB sub-system
usb_burn- Burning with amlogic format package in usb
usb_update- Burning a partition with image file in usb host
usbboot - boot from USB device
uuid - UUID - generate random Universally Unique Identifier
version - print monitor, compiler and linker version
viu_probe- enable viu probe in no secure chip
vout - VOUT sub-system
vout2 - VOUT2 sub-system
vpp - vpp sub-system
vpu - vpu sub-system
write_trim- cpu temp-system
write_version- cpu temp-system
Кроме команд в u-boot очень важно понимать суть переменных.
setenv - создает, переопределяет или стирает переменную если значение не указано.
Примеры.
Установить 'a' равной '123':
setenv a 123
Стереть переменную 'a'
setenv a
Напечатать значение 'a'
printenv a
После манипуляций с переменными можно сохранить значения чтобы после перезагрузки они не забылись командой save или saveenv.
Загрузка с внешнего носителя начинается со скрипта в корневой директории первого раздела (armbi_boot) этого носителя в файле aml_autoscript. Это бинарный файл, который напрямую не стоит редактировать, хотя код при открытии этого файла можно разобрать в текстовом виде. Начинается код так:
if printenv bootfromsd; then exit; else setenv ab 0; fi;
Одной из важных переменных, которая используется многими скриптами является 'bootfromsd'. Не поверите, но чтобы загрузиться с внешнего носителя эта переменная должна быть стерта как мы видим из этого кода. Вы можете взять куски кода из этого скрипта и проверить в командной строке u-boot. Но чтобы проверить эти куски кода, нужно понять еще несколько моментов, которые умеет u-boot.
Подсистема usb позволяет работать с USB флэшкой:
usb start - инициализировать подсистему
Вставьте флэшку и введите:
fatls usb 0 - показать файлы на USB устройстве с индексом 0.
Эта команда работает как с FAT, так и с EXT4 разделами. Так что можно не беспокоиться о том, что BOOT раздел Armbian хранится в ext4. Дальше считаем файл boot.scr в область памяти по адресу 0x1000000:
g12a_u212_v1# fatload usb 0 0x1000000 boot.scr
reading boot.scr
8147 bytes read in 27 ms (293.9 KiB/s)
Дальше запустим загруженный скрипт командой autoscr:
autoscr 0x1000000
Аналогично можно работать с подсистемой mmc только для ее инциализации нужно запускать команду
mmc rescan
В общем, суть всех скриптов u-boot попробовать инициализировать очередную подсистему и загрузить какой-либо файл, а дальше действовать в зависимости от результата этих действий и выставленных переменных.
После усвоения вышеприведенной информации есть смысл заглянуть в следующую переменную среды u-boot, которая содержат сценарий загрузки с карточки:
recovery_from_sdcard=if fatload mmc 0 ${loadaddr} aml_autoscript; then autoscr ${loadaddr}; fi;if fatload mmc 0 ${loadaddr} recovery.img; then if fatload mmc 0 ${dtb_mem_addr} dtb.img; then echo sd dtb.img loaded; fi;wipeisb; setenv bootargs ${bootargs} ${fs_type};bootm ${loadaddr};fi;
Этот скрипт пытается загрузить с mmc под индексом 0 файл aml_autoscript и запустить его. В случае неудачи пытается загрузить recovery.img и dtb.img, и если они загрузились, сообщает об этом, модифицирует переменную bootargs и загружает приложение по адресу загрузки командой bootm. Этот скрипт, сохраненный в переменную recovery_from_sdcard можно запустить следующей командой:
run recovery_from_sdcard
Именно этот скрипт и используется для запуска нашей системы с SD карты. Если что-то во время загрузки пошло не так, проверьте все шаги из командной строки u-boot.
Когда я запортачил загрузку, убив систему на EMMC, я тупо переопределил эту переменную:
setenv recovery_from_sdcard 'usb start;fatload usb 0 0x1000000 u-boot.ext;go 0x1000000'
Проверить что все сохранилось:
g12a_u212_v1#printenv recovery_from_sdcard
recovery_from_sdcard=usb start;fatload usb 0 0x1000000 u-boot.ext;go 0x1000000
Дальше надо сохранить эти настройки (вы ведь сохранили себе предыдущее значение чтобы вернуть как было когда надоест!?) Но тут и вылезла еще одна моя проблема:
g12a_u212_v1#saveenv
Saving Environment to aml-storage...
get partition info failed !!
Мой u-boot не умеет работать с EMMC. На этом этапе костыли начинают надоедать. Хочется сесть, досканально разобраться в этом вопросе и написать нормальный загрузчик для приставки. Но пока я лишь в начале пути.
А теперь вишенка на торте - из u-boot можно запустить другой u-boot тремя шагами загрузив в память и запустив бинарный код по адресу командой go. Вот так выглядит запуск u-boot из файла u-boot-x96maxplus.bin:
usb start
fatload usb 0 0x1000000 u-boot-x96maxplus.bin
g12a_u212_v1#go 0x1000000
## Starting application at 0x01000000 ...
U-Boot 2021.07-rc3-00183-gd6e1cdad51-dirty (May 31 2021 - 22:33:28 +0800) x96-max-plus
Model: AMedia X96 Max+
SoC: Amlogic Meson SM1 (Unknown) Revision 2b:b (1:2)
DRAM: 3.8 GiB
MMC: sd@ffe03000: 0, sd@ffe05000: 1, mmc@ffe07000: 2
Loading Environment from nowhere... OK
In: serial
Out: serial
Err: serial
Net: eth0: ethernet@ff3f0000
Hit any key to stop autoboot: 0
starting USB...
Bus usb@ff500000: Register 3000140 NbrPorts 3
Starting the controller
USB XHCI 1.10
scanning bus usb@ff500000 for devices... 2 USB Device(s) found
scanning usb for storage devices... 1 Storage Device(s) found
Device 0: Vendor: JetFlash Rev: 1100 Prod: Transcend 8GB
Type: Removable Hard Disk
Capacity: 7722.0 MB = 7.5 GB (15814656 x 512)
... is now current device
Scanning usb 0:1...
Found /extlinux/extlinux.conf
Retrieving file: /extlinux/extlinux.conf
577 bytes read in 12 ms (46.9 KiB/s)
1: Armbian
Retrieving file: /uInitrd
23401755 bytes read in 966 ms (23.1 MiB/s)
Retrieving file: /Image
27363840 bytes read in 1133 ms (23 MiB/s)
append: root=UUID=1fa9b58c-1f95-468b-868f-6dbc919d31f3 rootflags=data=writeback console=ttyAML0,115200n8 console=tty0 rw no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 splash plymouth.ignore-serial-consoles
Retrieving file: /dtb/amlogic/meson-g12a-x96-max-rmii.dtb
74923 bytes read in 16 ms (4.5 MiB/s)
Moving Image from 0x8080000 to 0x8200000, end=9cb0000
## Loading init Ramdisk from Legacy Image at 13000000 ...
Image Name: uInitrd
Image Type: AArch64 Linux RAMDisk Image (gzip compressed)
Data Size: 23401691 Bytes = 22.3 MiB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum ... OK
## Flattened Device Tree blob at 08008000
Booting using the fdt blob at 0x8008000
Loading Ramdisk to 3e9ae000, end 3ffff4db ... OK
Loading Device Tree to 000000003e998000, end 000000003e9ad4aa ... OK
Starting kernel ...
...
Так если не получается найт годный u-boot с поддержкой EMMC, то можно решить проблему в лоб и работать только с флэшки с тем бутом, который есть. Для этого создаем на компьютере файл aml_autoscript.cmd с содержимым:
usb start
fatload usb 0 0x1000000 u-boot.ext
go 0x1000000
Для загрузки с MMC карты код должен выглядеть так:
mmc rescan
fatload mmc 0 0x1000000 u-boot.ext
go 0x1000000
Конечно же вместо u-boot.ext нужно подставить имя файла загрузчика с вашей флэшки или переименовать его в u-boot.ext . Компилируем aml_autoscript.cmd в бинарь и кладем полученый aml_autoscript на флэшку в бут раздел:
mkimage -C none -A arm -T script -d aml_autoscript.cmd aml_autoscript
mkimage - это программа из пакета u-boot-tools.
На этом этапе нужно убедиться что в файле extlinux/extlinux.conf прописан верно подходящий FDT. Если extlinux.conf по этому адресу переименован в extlinux.conf.bak, то изменять FDT уже нужно в файле uEnv.txt (для Armbian 6).
Запуск
Как я говорил, загрузка с флэшки включается зубочисткой, но есть другой вариант.
Вставить внешний носитель с системой, загрузиться в Android и переключаемся в режим разработчика. Для этого заходим в настройки, выбираем информацию о версии и кликаем по ней пять раз. Должно появиться сообщение о том что режим активирован.
Установить adb (обычно пакет android-tools-adb) и запустив по сети две команды IP адреса вашей приставки через сеть:
adb connect x.x.x.x adb shell reboot update
В итоге система загружается. Если были выбраны дисплейный менеджер и среда рабочего стола, то она загрузится и попросит пароль. Первоначальный пароль системы Armbian root:1234, но меня система заставила создать всех пользователей с паролями при первой загрузке. Использовать как десктопный компьютер телевизионную приставку - идея не из лучших не смотря на то, что сейчас даже драйвер Panfrost, имплементирующий OpenGL для ARM, уже встроен в систему. В лучшем случае, как тонкий клиент. Youtube показывает видео без тормозов, но сама система по отзывчивости оставляет желать лучшего. Возможно, использование быстрых носителей исправит ситуацию, но у меня с этим какая-то беда и невезение.
Резюме
Итак, подводя итог для установки Armbian на TV-box нам достаточно лишь подготовить загрузочный носитель и заставить приставку загрузиться с него:
скачать образ системы Armbian;
записать образ на USB флэшку или карточку памяти;
прописать DTB файлы в ./extlinux/extlinux.conf или uEnv.txt в зависимости от версии Armbian
переименовать выбранный файл u-boot именно от этой платы загрузчика в u-boot.ext;
прописать файл с настройками сети /etc/network/interfaces.d/eth0;
переключиться в режим обновления с нашего носителя одним из двух способов: режим разработчика или зубочисткой;
загрузиться, убедиться что устройство появилось в сети и приступить к настройке;
Ссылки
Репозиторий Armbian:
https://github.com/armbian/build
Труды по запуску Armbian на ТВ-приставках самых различных моделей:
https://github.com/ophub/amlogic-s9xxx-armbian
Некоторые пояснения ситации на github по поводу приставки X96 Max Plus 100W:
https://github.com/ophub/amlogic-s9xxx-armbian/issues/909
Раскирпичивание приставки X96 Max Plus после порчи EMMC системы через замыкание boot контакта на плате:
https://www.youtube.com/watch?v=3do6lDOj2LU