Збираємо u-boot для Андроїд-ТВ приставки на s805!

Опубліковано 09.12.2025, 12:39 в категорії Гайди

Пролог

"Arch Linux ARM на s805 приставці"

Є в мене ось такий Android-TV бокс, на SoC - s805. Доволі довгий час на ньому стояв або Armbian або Arch Linux, і там крутились деякі мої невеличкі проєкти. І от одного разу, я вирішив випаяти звідти NAND пам'ять, щоб впаяти її в USB перехідник, і тим самим сдампити прошивку, тобто зробити повний образ наявної там системи, бо з під Armbian-а NAND пам'ять не була доступна, а з іншими способами возитись мені було лінь. Нічого гарного з цього не вийшло, і в решті решт я залишився з мертвим NAND чіпом, та цегляним Android-TV боксом :D

"Місце під мікросхему пам'яті"

Linux стояв на SD картці, чому ж тоді бокс перетворився на цеглу? А все просто - в NAND пам'яті був bootloader - u-boot, який і завантажував систему з SD картки.

Пошукавши в інтернеті образи для прошивки таких ТВ-боксів, звідти можна легко витягти bootloader, та записати його в початок картки пам'яті, і ТВ-бокс магічним чином оживе. Але є одна проблема - bootloader з тих образів компілювався таким чином, що він очікує побачити певний Recovery скрипт в пам'яті. Там же він шукає і налаштування для себе, і тому змінити їх як на звичайному u-boot-і неможливо. Тобто такий bootloader ніяким чином (мабуть) не зможе автоматично завантажити систему з SD картки, і при кожному запуску ТВ-бокса, треба буде підключатись до нього по UART, та робити запуск системи руцями. Погодьтесь, таке собі. Тому сьогодні я розповім, як налаштувати та скомпілювати u-boot власноруч!

Компілюємо u-boot

Підготовка build environment-у

Перш за все, треба підготувати ваш Linux для того щоб збирати та компілювати код. Велика вірогідність того, що в вас вже встановлені всі необхідні пакети. Якщо ні, то зазвичай більшість речей можна встановити, встановивши відповідний пакет - наприклад base-devel якщо у вас Arch Linux, або build-essential якщо Ubuntu/Debian. Туди входять різного роду інструменти, наприклад gcc, make, bison, flex, і тд, які знадобляться для того, щоб скомпілювати u-boot. Також треба ще встановити git, wget, тощо. Через варіативність дистрибутивів, детально я на цьому зупинятись не буду - ви можете знайти інформацію для вашого дистрибутива в інтернеті.

Також в подальшому будуть використовуватись 32х бітні бінарники, і щоб ваша система могла їх запустити, так як у вас скоріше за все х64, треба провести певні маніпуляції. Наприклад на Arch Linux треба встановити два пакети - lib32-glibc та lib32-gcc-libs:

sudo pacman -S lib32-glibc lib32-gcc-libs

Також довелось ще встановити lib32-zlib з репозиторія Multilib. Тож все дуже ситуативно, і залежить від вашого дистрибутиву, а також системи - щось у вас вже встановлено, щось ні. Так чи інакше, в подальшому по помилкам це можна буде побачити.

Встановлюємо toolchain

Наступна задача - встановити toolchain. Це ще один набір інструментів, необхідних для компіляції u-boot. Але разом з цим, він виконує ще одну важливу роль, а саме забезпечує умови для кросскомпіляції - справа в тому що ви скоріше за все використовуєте комп'ютер/ноутбук з архітектурою x64, в той час як u-boot ви збираєте під ARMv7-A.

Завантажуємо архів з необхідними бінарниками toolchain-а:

wget http://releases.linaro.org/archive/14.04/components/toolchain/binaries/gcc-linaro-arm-none-eabi-4.8-2014.04_linux.tar.xz

Разархівовуємо його в зручне місце на системі:

sudo mkdir -p /opt/toolchains
sudo tar xJvf gcc-linaro-arm-none-eabi-4.8-2014.04_linux.tar.xz -C /opt/toolchains/

Та додаємо в $PATH, щоб користувач або скрипти могли використовувати бінарники не прописуючи шлях до них. Це можна зробити двома способами - тимчасово та постійно.


Тимчасово:

export PATH=/opt/toolchains/gcc-linaro-arm-none-eabi-4.8-2014.04_linux/bin:$PATH

Тимчасовий спосіб додасть бінарники в $PATH лише для поточного вікна терміналу. Якщо ви його закриєте, або відкриєте інший, треба буде знову виконувати команду вище.


Постійно:

Щоб уникнути цього, можна додати цю команду в кінець вашого .bashrc файлу, який знаходиться в $HOME директорії. Це можна зробити вручну через текстовий редактор, а можна виконати наступну команду:

echo "export PATH=/opt/toolchains/gcc-linaro-arm-none-eabi-4.8-2014.04_linux/bin:\$PATH" | tee --append ~/.bashrc 

Тепер треба оновити зміни за допомогою наступної команди:

source ~/.bashrc

І можна впевнитись в тому що система бачить бінарники, перевіривши їх версію:

arm-none-eabi-gcc -v

Повинно вивестись багато інформації:

Using built-in specs.
COLLECT_GCC=arm-none-eabi-gcc
COLLECT_LTO_WRAPPER=/opt/toolchains/gcc-linaro-arm-none-eabi-4.8-2014.04_linux/bin/../libexec/gcc/arm-none-eabi/4.8.3/lto-wrapper
Target: arm-none-eabi
Configured with: /cbuild/slaves/oorts/crosstool-ng/builds/arm-none-eabi-linux/.build/src/gcc-linaro-4.8-2014.04/configure --build=i686-build_pc-linux-gnu --host=i686-build_pc-linux-gnu --target=arm-none-eabi --prefix=/cbuild/slaves/oorts/crosstool-ng/builds/arm-none-eabi-linux/install --with-local-prefix=/cbuild/slaves/oorts/crosstool-ng/builds/arm-none-eabi-linux/install/arm-none-eabi --without-headers --with-newlib --enable-threads=no --disable-shared --with-pkgversion='crosstool-NG linaro-1.13.1-4.8-2014.04 - Linaro GCC 4.8-2014.04' --with-bugurl=https://bugs.launchpad.net/gcc-linaro --disable-__cxa_atexit --with-gmp=/cbuild/slaves/oorts/crosstool-ng/builds/arm-none-eabi-linux/.build/arm-none-eabi/build/static --with-mpfr=/cbuild/slaves/oorts/crosstool-ng/builds/arm-none-eabi-linux/.build/arm-none-eabi/build/static --with-mpc=/cbuild/slaves/oorts/crosstool-ng/builds/arm-none-eabi-linux/.build/arm-none-eabi/build/static --with-isl=/cbuild/slaves/oorts/crosstool-ng/builds/arm-none-eabi-linux/.build/arm-none-eabi/build/static --with-cloog=/cbuild/slaves/oorts/crosstool-ng/builds/arm-none-eabi-linux/.build/arm-none-eabi/build/static --with-libelf=/cbuild/slaves/oorts/crosstool-ng/builds/arm-none-eabi-linux/.build/arm-none-eabi/build/static --enable-lto --enable-linker-build-id --enable-libmudflap --disable-libgomp --enable-libssp --disable-libstdcxx-pch --enable-multilib --enable-languages=c,c++,fortran --with-multilib-list=aprofile
Thread model: single
gcc version 4.8.3 20140401 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2014.04 - Linaro GCC 4.8-2014.04) 

Якщо у вас такий самий вивід - все зроблено правильно. Якщо пише щось на кшталт - command not found - переконайтесь що ви правильно додали все в $PATH. Якщо cannot execute: required file not found - переконайтеся що забезпечили всі умови для виконання 32х бітних бінарників на вашій 64х бітній системі.

Завантажуємо вихідний код та компілюємо

В якості джерела вихідного коду для u-boot під s805 я раджу вам обрати ось цей репозиторій. Клонуємо та відкриваємо його:

git clone https://github.com/hzyitc/u-boot-onecloud
cd u-boot-onecloud

Виправляємо баг з sha1.h

В цій версії u-boot присутній баг, через який компілятор буде намагатись використати системний файл sha1.h за шляхом /usr/include/sha1.h, в той час як в репозиторії лежить інший, який йому необхідно використати. Найлегше що можна зробити - забекапити, за наявності, системний файл:

sudo mv /usr/include/sha1.h /usr/include/sha1.hBAK

І додати на його місце файл з репозиторія:

sudo cp include/sha1.h /usr/include/

Після компіляції можна повернути все назад:

sudo rm /usr/include/sha1.h
sudo mv /usr/include/sha1.hBAK /usr/include/sha1.h

В цілому, тепер можна компілювати u-boot - для цього готуємо конфіг файл для нашої плати, та запускаємо процес компіляції:

make m8b_onecloud_config
make -j$(nproc)

Бінарник u-boot з'явиться в папці build, про що свідчить кінець логів команди make:

uclpack: using block-size of 262144 bytes
uclpack: algorithm NRV2D-99/7, compressed 639608 into 313205 bytes
/home/ctl/u-boot-onecloud/build/tools/convert --soc m8b  -s /home/ctl/u-boot-onecloud/build/firmware.bin -i /home/ctl/u-boot-onecloud/build/u-boot-comp.bin -o /home/ctl/u-boot-onecloud/build/u-boot.bin

Якщо процес компіляції обривається помилкою, запустіть make без флагу -j, та шукайте більш детальну помилку - скоріше за все відсутні якісь 32х бітні бібліотеки чи щось таке.

make

Тож, u-boot готовий, але для моїх цілей він не підходить через відсутність NAND пам'яті, і на відміну від u-boot витягнутого з образів для прошивки - взагалі висне і не запускається :0

Налаштовуємо u-boot

Більшість налаштувань можна змінити у відповідному .h файлі для нашого ТВ бокса. Цей файл знаходиться за шляхом board/amlogic/configs/m8b_onecloud.h.

Мені наприклад треба вимкнути параметр CONFIG_STORE_COMPATIBLE. Наскільки я розумію - він відповідає за можливість зберігання конфігу/змінних для u-boot на накопичувачі. І через те, що в мене відсутня nand пам'ять - u-boot висне через цей параметр. Тож я знайшов його і закоментував:

//#define CONFIG_STORE_COMPATIBLE

Також, раз вже ми модифікуємо файл плати, можна поглянути і на параметр CONFIG_BOOTCOMMAND. Цей параметр, як видно з назви, вказує як саме u-boot буде намагатись запустити ядро Linux при старті. Стандартний виглядає так:

#define CONFIG_BOOTCOMMAND "print 'Autobooting...'; run boot_usb_armbian; run boot_sdcard_armbian; run boot_emmc_armbian; print 'Failed to boot'; "

Тобто він:

  • Пише по UART "Autobooting..."
  • Намагається запуститись з USB (boot_usb_armbian)
  • Далі намагається запуститись з SD карти (boot_sdcard_armbian)
  • Потім намагається запуститись з eMMC/NAND (boot_emmc_armbian)
  • Пише "Failed to boot"

З USB я запускати систему не планую. З NAND пам'яті - вочевидь, теж. Тому я модифікував цей параметр, залишивши лише запуск з SD картки:

#define CONFIG_BOOTCOMMAND  "print 'Autobooting...'; run boot_sdcard_armbian; print 'Failed to boot'; "

Чудово. Але, що ж таке цей boot_sdcard_armbian? А це не що інше, як така собі умовна функція, записана в параметр CONFIG_EXTRA_ENV_SETTINGS.

Там можна знайти, і подивитись, що саме вона робить:

        "boot_sdcard_armbian=" \
                "print -n 'Try to boot from SDCard...'; " \
                "mmc rescan 0; " \
                "setenv bootdev 'mmc 0'; " \
                "fatload ${bootdev} ${loadaddr} boot.scr && autoscr ${loadaddr}; " \
                "print 'Fail'; " \
                "\0" \

Тобто вона:

  • Пише по UART "Try to boot from SDCard..."
  • Сканує доступні MMC девайси (0 - це наче режим роботи MMC, legacy)
  • Встановлює змінну середовища bootdev яка містить "mmc 0", тобто найперший MMC девайс, з якого і буде здійснюватись запуск
  • Завантажує за допомогою команди fatload з FAT розділу на MMC скрипт boot.src в пам'ять за адресою loadaddr, після чого запускає його за допомогою autoscr (наче в більш нових версіях u-boot autoscr замінили командою source)
  • Відповідно цей скрипт і завантажує ядро Linux, тобто якщо все гаразд - ви потрапили в Linux. Якщо запустити Linux не вдалось, по UART виводиться "Fail"

Тож тепер ви хоч трохи знаєте, що там відбувається під капотом, та що і де можна якщо що підлаштувати під себе!

Записуємо U-Boot на SD картку

Тепер найцікавіше - а як же записати U-Boot на картку пам'яті? Адже він повинен знаходитись на початку карти пам'яті, і якщо просто записати його поверх записаного туди Armbian-а або Arch Linux-а, ми просто зітремо таблицю розділів, і нічого не буде працювати (ну, окрім U-Boot :D).

Щоб уникнути затирання таблиці з розділами, нам треба записати bootloader в два місця - невеличку частину в спеціально призначене для цього місце (перші 442 байти MBR сектору), і потім весь bootloader повністю, після таблиці з розділами. Зробити це можна таким чином:

sudo umount /dev/sdX
sudo dd if=u-boot.bin of=/dev/sdX bs=1 count=442
sudo dd if=u-boot.bin of=/dev/sdX seek=1 skip=1 bs=512
sync

Де sdX - ваша SD картка. Правильну назву можна подивитись, виконавши команду lsblk, але ДУЖЕ ВАЖЛИВО не переплутати SD картку з іншим девайсом, адже іншим девайсом може бути ваш системний диск (якщо ви використовуєте SATA SSD/HDD, а не NVMe), і якщо записати bootloader туди, це може призвести до втрати даних.


Епілог

Більшість інформації для цієї статті я взяв з Wiki ODROID-C1. В них навіть є свій форк u-boot для процесора s805. Чого ж ми тоді використали інший? Справа в тому, що в них є спеціальний "1st stage bootloader", який потрібен для нормального функціонування їх u-boot-у:

  • The 1st stage bootloader, bl1.bin.hardkernel, is provided as prebuilt binary only.

І от що цей bl1 робить, так це перевіряє умовний Serial Number (в процесорі, або десь на платі, не впевнений), і порівнює його зі своїм якимось списком та/або ключами. Якщо серійний номер не співпадає - bootloader не запуститься :D А він звісно не співпаде, так як в нас не ODROID плата, а AndroidTV приставка.

"u-boot від ODROID"

Тому й довелось використовувати сторонній форк u-boot від onecloud - якоїсь іншої китайської AndoidTV приставки чи чогось схожого