С течением времени все устройства устаревают. Вот также устарела Яндекс Станция первого поколения, которая волею судеб досталась мне. Сравнив интерфейс "Мордовия" с новым интерфейсом Яндекс Станции Макс и в очередной раз ужаснувшись его убогости, я решил переделать станцию первого поколения в обычную Андроид ТВ-приставку, пусть и с потерей поддержки, обновлений, доступа к голосовым и онлайн сервисам Яндекс. Но зато теперь я могу поставить на нее свою любимую Лампу, Kodi, а также другие приложения. Плюс, остается возможность возврата в любой момент к родной прошивке в надежде, что Яндекс всё же вспомнит про старичка.
В данной статье я скомпоную найденные мной факты об оборудовании и ПО Яндекс Станции первого поколения, достаточные для установки на нее сторонних приложений. Далее под словом "Станция" в данной статье я подразумеваю Яндекс Станцию первого поколения.
Дисклеймер:
Я ранее уже озвучивал свою позицию. Исследование кода правомерно принадлежащего мне продукта я произвожу исключительно в целях личного развлечения. Я уважаю затраченные компанией Яндекс силы на разработку нравящихся (да и не нравящихся) мне продуктов, и выступаю против использования опубликованной мной информации в целях обхода каких-либо (в том числе неизвестных мне) ограничений.
Также предупрежу, что всё написанное здесь исходит исключительно из моей головы и не является истиной в последней инстанции. Я могу случайно ошибаться или намеренно искажать информацию - так что используйте всё здесь сказанное на свой страх и риск.
Итак, для апгрейда Яндекс Станции первого поколения потребуются:
- Собственно, сама станция,
- Паяльник с тонким жалом,
- Набор тонких проводов,
- USB2UART адаптер на 3.3 вольт,
- Хотя бы один USB-A коннектор типа "мама" для подключения USB устройств,
- USB провод с разъемом "папа", который не жалко порезать, для подключения к ПК,
- USB клавиатура и мышь,
- Bluetooth джойстик/пульт, чтобы не быть привязанным к проводам,
- Хотя бы немного прямые руки, и желательно растущие чуть выше пояса.
Часть первая. Пайка.
Чтобы внести изменения в Яндекс Станцию первого поколения, необходимо подключить ее к компьютеру. Значительная часть дальнейших действий производится в консоли, доступной через UART. Дамп и внесение изменений в прошивку устройства производятся в режиме FEL. Подключение внешних устройств производится через USB и Bluetooth.
Требуется припаяться к следующим тестпоинтам на плате:
136 - UART0 TX
137 - UART0 RX
248 - USB0-DM
249 - USB0-DP
104 - USB1-DP
105 - USB1-DM
191 - +5 вольт
106 - GND
Рекомендую, но не обязательно:
250 - FEL
101 - RESET
Лично я взял 5 вольт с одного из двух конденсаторов, а землю с больших площадок, а не стал тянуться к тестпоинтам.
Тестпоинты 101, 104, 105, 106 - на обратной стороне.
Может попасться другая версия платы (видел фото на 4pda), там номера тестпоинтов те же, но расположены на других местах.
Точки UART0 TX, UART0 RX и землю подключаем к USB2UART адаптеру (RX станции на TX адаптера, и наоборот) - на них мы увидим U-Boot и (когда включим) консоль андроида.
Точки USB0-DM, USB0-DP и землю паяем на USB-A провод "папа" для подключения к ПК (+5 вольт туда подавать не нужно!). Этот порт далее будем использовать для режима FEL.
Точки USB1-DP, USB1-DM, +5 вольт и землю паяем на USB-A "маму". В нее будем включать USB клавиатуру, мышь, флешку и так далее.
Точки FEL и Reset выводим на кнопки, коммутирующие тестпоинты на землю, либо оставляем просто как провода, которые вручную замыкаем на землю, когда требуется перезагрузиться.
FEL находится в таком месте, что его можно не паять, а замыкать тонким пинцетом. А Reset можно делать выдергиванием блока питания из розетки - так что пайка этих точек не обязательна.
После пайки у меня получилось такое:
Я планирую использовать более тонкие провода, чтобы убрать их под радиатор - но они пока еще в доставке с Китая.
После пайки тонкими проводами Станция выглядит намного аккуратнее. Появляется достаточно места, чтобы вернуть радиатор. К тому же я вывел внизу два USB коннектора - левый для подключения флешек/мышек и прочих устройств, а правый для подключения к ПК в режиме ADB или FEL.
Не подключенные никуда толстый синий и тонкий желтый провода справа - будут отпаяны или откушены. Это Reset и FEL. А идущие налево за границы фото 3 провода - UART, они будут спрятаны в дне колонки, так как после завершения всех действий, описанных в данной статье, UART перестанет быть нужен.
Немного оффтопик.
Станция первого поколения заведется даже от блока питания в 5 или 12 вольт - но звука от нее вы не услышите. Два i2s контроллера TAS5751M (включены параллельно, для басов и обычного звука) вообще не запускаются от 5в, а от 12в то работают то нет. Зато от 24 вольт, поданных на вход Станции, они работают, и даже не особо греются. Скорее всего Станция не сгорит при подаче на нее питания до 26 вольт.
Если кто вдруг не знает, родной блок питания = 20 вольт.
У меня блоков питания на один меньше, чем Станций, поэтому приходится использовать что есть.
Часть вторая. Немного теории.
Яндекс Станция первого поколения работает на процессоре Allwinner R18. Как пишут в интернете (я не проверял), он идентичен процессору А64, за исключением наличия в R18 режима доверенной загрузки (secure boot), которую Яндекс, к счастью для нас, решил не использовать.
Я не сильно разбираюсь в видах плат памяти, так что буду называть то, с чего загружается Станция словом EMMC. В Станции стоит модуль памяти на 8 гб, при этом системой видится 7 634 944 байт.
Таблица разделов EMMC имеет следующий вид (выдрано из строки загрузки):
mmcblk0p1 UDISK
mmcblk0p2 bootloader
mmcblk0p3 похоже на таблицу разделов
mmcblk0p4 в /dev/ нет, тут спрятан u-boot
mmcblk0p5 env
mmcblk0p6 boot
mmcblk0p7 system
mmcblk0p8 verity_block
mmcblk0p9 misc
mmcblk0p10 recovery
mmcblk0p11 cache
mmcblk0p12 metadata
mmcblk0p13 private
mmcblk0p14 frp
mmcblk0p15 rescue
mmcblk0p16 tinaos
mmcblk0p17 rback
mmcblk0p18 secret
mmcblk0p19 alog
Ядро Андроид с initrd загружается с двух разделов: либо boot (mmcblk0p6), либо recovery (mmcblk0p10), в зависимости от записи в разделе misc (mmcblk2p9). Есть еще один initrd в rback (mmcblk2p17), но его содержимое записывается в mmcblk0p10 при хард резете (зажатая кнопка при включении), и я его специально не трогаю, чтобы если что, можно было откатиться к заводской прошивке.
Про возможность загрузки в урезанный Tina Linux я писал ранее.
Часть третья. Сброс до заводских настроек.
Эта часть обязательна для выполнения!
Необходимо сбросить устройство до заводских настроек, чтобы получить хоть и старую (factory) версию Андроид - но зато в ней есть почти все нужные (и не нужные) драйвера: на USB, Bluetooth, даже на какие-то камеры.
Для сброса - отключаем Станцию от сети, зажимаем и держим кнопку вызова Алисы, включаем назад. Кольцо зажигается оранжевым - это значит сброс пошел. В UART можно увидеть процесс.
Дожидаемся завершения сброса. Кольцо начинает переливаться белоголубым, Станция озвучивает голосом инструкцию по первоначальной настройке. Не настраиваем станцию! Иначе она загрузит и прошьет ненужную нам свежую версию прошивки.
На экране Станции должна быть такая картинка:
У меня иногда картинка на Станции после включения отдаёт розовым - помогает вынуть/вставить HDMI кабель, либо выключить/включить телевизор. Такое поведение я замечал только на factory версии, так что скорее всего это программный баг и его можно устранить подсунув драйвера из более свежих прошивок, поправив в них версии module_layout и других символов.
Часть четвертая. Делаем бэкап.
Есть два типа системных администраторов: которые не делают бэкапы, и которые уже делают. Я отношусь ко второму.
Перед внесением изменений на ЕММС, необходимо сделать резервную копию его содержимого. Производится это через режим FEL, в котором загружается особенный образ Linux, где производятся все необходимые операции. Ранее я описывал вариант дампа прошивки - но тогда я не знал как подключить к Станции USB флешку, так что старый способ использовать не рекомендую - на флешку дампить и удобнее и быстрее.
Чтобы Яндекс Станция вошла в режим FEL, необходимо либо замкнуть тестпоинт FEL за землю, либо посылать цифру "2" в UART. Я использую тестпоинт, так как при зажатии двойки у меня Станция хоть и определяется компьютером как USB устройство, но утилиты по работе с FEL его не понимают.
Утилиты для работы с FEL в Windows и Linux, а также образ операционной системы для загрузки, можно взять здесь: https://github.com/OtakuNekoP/bpi-fel-mass-storage. Наш вариант - "m64", то есть надо запускать start-m64.bat, либо start-m64.sh. Скрипты загрузят образ мини-Linux с некоторым количеством драйверов в комплекте, и с доступом к командной строке. Изначально, данный образ должен переводить устройство в режим USB накопителя и отдавать его EMMC как USB диск - но у меня ни на Windows 11 ни на Ubuntu не заработало. Возможно, заработает при подключении к Windows XP или 2000 - но это уже не важно. Резервную копию EMMC после загрузки в этот образ можно сделать на USB флешку, и с нее же потом патчить разделы.
Для создания бэкапа нам нужна флешка, отформатированная в FAT, либо EXT2-EXT4. EXT4 предпочтительнее, так как у FAT есть ограничение на размер файла и сдампить флешку одним куском не удастся.
Загружаем станцию в режиме FEL - замыкаем TP250 на землю, перезагружаем устройство (либо Reset на землю, либо по питанию). Подключаем USB0 к компьютеру (три провода, питание не нужно), ПК определяет новое устройство. Драйвера устанавливаем по инструкции с официального сайта.
Далее скрипт start-m64 производит загрузку в Linux:
Загрузившись в систему удостоверяемся, что видны разделы EMMC и USB диск:
Монтируем USB. Я в начале отформатировал флешку на Станции, так как на ней было несколько разделов, причем основной был NTFS.
Делаем бэкап всех разделов.
dd if=/dev/mmcblk2 of=/mnt/mmcblk2 bs=4096
dd if=/dev/mmcblk2p1 of=/mnt/mmcblk2p1 bs=4096
dd if=/dev/mmcblk2p2 of=/mnt/mmcblk2p2 bs=4096
dd if=/dev/mmcblk2p3 of=/mnt/mmcblk2p3 bs=4096
dd if=/dev/mmcblk2p5 of=/mnt/mmcblk2p5 bs=4096
dd if=/dev/mmcblk2p6 of=/mnt/mmcblk2p6 bs=4096
dd if=/dev/mmcblk2p7 of=/mnt/mmcblk2p7 bs=4096
dd if=/dev/mmcblk2p8 of=/mnt/mmcblk2p8 bs=4096
dd if=/dev/mmcblk2p9 of=/mnt/mmcblk2p9 bs=4096
dd if=/dev/mmcblk2p10 of=/mnt/mmcblk2p10 bs=4096
dd if=/dev/mmcblk2p11 of=/mnt/mmcblk2p11 bs=4096
dd if=/dev/mmcblk2p12 of=/mnt/mmcblk2p12 bs=4096
dd if=/dev/mmcblk2p13 of=/mnt/mmcblk2p13 bs=4096
dd if=/dev/mmcblk2p14 of=/mnt/mmcblk2p14 bs=4096
dd if=/dev/mmcblk2p15 of=/mnt/mmcblk2p15 bs=4096
dd if=/dev/mmcblk2p16 of=/mnt/mmcblk2p16 bs=4096
dd if=/dev/mmcblk2p17 of=/mnt/mmcblk2p17 bs=4096
dd if=/dev/mmcblk2p18 of=/mnt/mmcblk2p18 bs=4096
dd if=/dev/mmcblk2p19 of=/mnt/mmcblk2p19 bs=4096
dd if=/dev/mmcblk2boot1 of=/mnt/mmcblk2boot1 bs=4096
dd if=/dev/mmcblk2boot0 of=/mnt/mmcblk2boot0 bs=4096
sync
Дамп самого большого раздела занимает минут 10-20, в зависимости от скорости флешки.
После завершения дампов, обязательно делаем sync, чтобы сбросить кеши на диск.
Восстановить старое содержимое разделов можно командой:
dd if=/mnt/mmcblk2 of=/dev/mmcblk2 bs=4096
sync
Вместо mmcblk2 можно указать любой другой раздел.
Часть пятая. Включаем интерактивный режим U-Boot.
Эта часть не обязательная, но рекомендую сделать для собственного удобства в будущем.
Чтобы было удобно проводить эксперименты, я рекомендую включить интерактивный режим в U-Boot. Я уже описывал, как это сделать - кратко повторюсь тут.
Необходимо взять текущий Environment от U-Boot и поменять в нем "bootdelay=0" на "bootdelay=3" (трёх секунд достаточно, чтобы нажать на клавишу и прервать загрузку). Для этого берем полученный в предыдущей части файл mmcblk2p5 (это 5ый раздел EMMC с названием Env), и любым 16-ричным редактором меняем в нем байты 00 на 0A. Можно ограничиться первой парой килобайт - там где есть текст.
Убираем мусор в первой строке, получаем следующее:
earlyprintk=sunxi-uart,0x01c28000
initcall_debug=0
console=ttyS0,115200
nand_root=/dev/system
mmc_root=/dev/mmcblk0p7
init=/init
loglevel=4
cma=232M
selinux=permissive
need_hw_test=0
setargs_nand=setenv bootargs earlyprintk=${earlyprintk} initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${nand_root} init=${init} partitions=${partitions} cma=${cma} androidboot.selinux=${selinux}
setargs_mmc=if test "${need_hw_test}" != "1"; then echo 'Android is running'; setenv bootargs earlyprintk=${earlyprintk} initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${mmc_root} init=${init} partitions=${partitions} cma=${cma} androidboot.selinux=${selinux}; else echo 'Linux is running'; setenv bootargs rootwait earlyprintk=${earlyprintk} initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${tina_root} init=${init} partitions=${partitions} cma=${cma} androidboot.selinux=${selinux} rdinit=/initstub init=/sbin/init; fi
tina_root=/dev/mmcblk0p16
boot_normal=sunxi_flash read 45000000 boot;boota 45000000 boot
boot_recovery=sunxi_flash read 45000000 recovery;boota 45000000 recovery
boot_fastboot=fastboot
recovery_key_value_max=0x13
recovery_key_value_min=0x10
fastboot_key_value_max=0x8
fastboot_key_value_min=0x2
bootdelay=0
bootcmd=run setargs_nand boot_normal
Правим строки:
loglevel=4 на loglevel=8
bootdelay=0 на bootdelay=3
и сохраняем файл как env.cfg
Загружаем pack-bintools-2016.12.19.tar.bz2 отсюда: https://github.com/tinalinux/dl и выполняем команду:
u_boot_env_gen env.cfg env.fex
Выполнять надо в Linux (например, в WSL для Windows 10/11).
После чего копируем env.fex на флешку, снова загружаем Станцию в мини-Linux через FEL, монтируем флешку и записываем раздел Env исправленными данными:
dd if=/mnt/env.fex of=/dev/mmcblk2p5
sync
Теперь при загрузке мы можем нажать любую клавишу и получить интерактивную консоль U-Boot.
Часть шестая. Готовим новый initrd.
В третьей части данной статьи, Станция была сброшена до factory прошивки. Для внесения дальнейших изменений, необходимо получить доступ к командной строке и права root. Для этого потребуется Android Image Kitchen. Я использовал этот.
Сперва распаковываем раздел boot, это файл mmcblk2p6, полученный в четвертой части:
"T:\Android Image Kitchen\unpackimg.bat" T:\Dump\mmcblk2p6
В папке кухни появляются подпапки ramdisk и split_img.
Открываем файл "ramdisk\default.prop", и находим там строку "ro.bootimage.build.date". Дата должна быть 2020 год.
Если дата новее - необходимо повторно сделать сброс до заводских настроек и снова сдампить раздел mmcblk2p6.
Если дата корректна - необходимо исправить файл "ramdisk\init.rc": удалить в разделе "service console" строку disabled и поменять "user shell" на "user root"
Также по желанию можно внести другие изменения в init.rc и другие файлы, положить дополнительные программы, например, в папку /sbin. После чего перепаковываем образ:
"T:\Android Image Kitchen\repackimg.bat"
Получаем файл image-new.img.
Максимальный размер образа = 16 Мб. Так что положить туда можно не так уж и много.
Файл image-new.img записываем на флешку, загружаем в последний раз Станцию в мини-Linux через FEL, и записываем новый образ поверх старого раздела:
dd if=/mnt/image-new.img of=/dev/mmcblk2p6
sync
И перезагружаемся.
Часть седьмая. Убиваем лишние сервисы Яндекса.
После загрузки, нажав в консоли Enter видим приглашение "root@tulip-d1:/ #", которое сразу же затирается мусором, выводимым ядром:
Чтобы отключить мусор вводим команду:
dmesg -n 1
Следом перемонтируем системный раздел в RW:
mount -o remount,rw /dev/block/by-name/system /system
(почему-то перемонтирование RW работает только в UART консоли - через ADB не даёт даже после su).
Далее редактируем файл /system/vendor/quasar/launch.json:
busybox vi /system/vendor/quasar/launch.json
и удаляем оттуда разделы audiod, authd, firstrund, logcat, updatesd. Останутся только ledd, buttonsd:
Не забудьте удалить запятую в конце секции buttonsd после фигурной скобки.
Возможно, и оставшиеся сервисы также можно исключить, сохранив при этом управление громкостью и подсветку кольца - я не смотрел в эту сторону.
Также можно поправить файл /system/vendor/quasar/run.sh, добавив в его конец вызов /system/vendor/quasar/activate_adb.sh
Тем самым ADB у нас будет включаться автоматически.
Перемонтируем раздел в RO (просто на всякий случай) и перезагружаемся:
sync
mount -o remount,ro /dev/block/by-name/system /system
reboot
После загрузки нас встречает пустой экран.
Подключаем к Станции USB мышь - на экране появляется курсор:
Часть восьмая. Настраиваем WiFi и включаем ADB.
Следующее действие - настройка WiFi. Делается это запуском приложения Settings через консоль UART:
am start -a android.settings.SETTINGS
Идем в раздел WiFi, выбираем свою сеть и мышью на экранной клавиатуре вводим пароль.
Вместо мыши можно использовать USB клавиатуру, устройство "два в одном" - USB клавиатуру со встроенным тачпадом, или беспроводной пульт с USB приемником. Главное, чтобы в USB устройстве не было микрофона - иначе у станции пропадёт звук, если устройство включено в USB до загрузки Андроида (это баг, USB звуковая карта становится первой). Но если включить такое устройство после завершения загрузки, то со звуком всё будет нормально. У меня как раз такое устройство, и по первости я намучался с пропадающим звуком, пока не понял причину. Наверняка есть способы поменять порядок звуковых устройств - возможно, это файл /etc/audio_policy.conf, который отличается от файла из последней прошивки. Я не пробовал.
Если в восьмой части данной статьи была добавлена строка запуска ADB в конец /system/vendor/quasar/run.sh, то после подключения к WiFi, ADB по сети будет доступен автоматически. Если нет - стартуем ADB вручную:
/system/vendor/quasar/activate_adb.sh
IP адрес можно посмотреть стандартно:
ip a
Подключение по сети к ADB как обычно: adb.exe connect ИП_адрес:5555
Часть девятая. Ставим приложения.
Последнее что осталось - установить нужные приложения. Первым делом - Launcher. Я выбрал ProjectivyLauncher, хотя можно использовать любой другой.
Загружаем его с сайта, ставим и перезагружаемся:
adb.exe install ProjectivyLauncher.apk
adb.exe reboot
После перезагрузки нам предложат его установить лаунчером по умолчанию.
Из-за того, что у нас очень старая версия андроид - невозможно использовать только одну мышь для первоначальной настройки. Например, чтобы закрыть меню "Settings", необходимо использовать клавишу ESC клавиатуры. На помощь тут приходить утилита scrcpy, позволяющая с ПК управлять Станцией.
У Projectivity Launcher есть встроенная возможность установки Aptoide TV Store - но в нем большая часть приложений расчитана на более свежие версии Андроид, чем 6.0.1 (Marshmallow), установленный на Станции. Поэтому я себе дополнительно установил Emotn Store. Он как раз рассчитан на старые устройства.
Далее я установил Lampa, Kodi, SmartTube, LeanKey Keyboard. Подключил Bluetooth джойстик, чтобы не быть привязанным к проводам, хотя пришлось попереключать его режимы работы. Bluetooth пульты от ТВ Станции, Модуля, Станции Макс также работают, но отваливаются после перезагрузки, и Bluetooth Auto Connect тут не помогает. Возможно, пульты других производителей, либо универсальные китайские Bluetooth пульты будут вести себя по другому - я не проверял.
Bluetooth мышь почему-то у меня вообще не завелась.
Станция по прежнему может работать в качестве Bluetooth колонки (предварительно нужно включить Bluetooth в настройках Андроида).
Существует утилита Android TV Tools, позволяющая менять настройки на устройствах с Android TV. Желающие могут с ней поиграть самостоятельно.
После подключения Bluetooth джойстика/пульта - Станцию можно отключить от ПК и собрать обратно в кожух.
Эпилог.
Я не выкладываю образы разделов и итоговую прошивку для заливки на устройства, чтобы не нарушать ничьи авторские права. Здесь опубликована информация, которая позволяет самостоятельно настроить Станцию в качестве ТВ приставки.
На обработанной подобным образом Станции всё еще остаются шероховатости, например, автоматически не монтируются вставленные USB флешки, отваливается "родной" пульт Яндекса - но я вряд ли буду дальше заниматься Станцией первого поколения, так есть другие задачи. Если кто-нибудь устранит найденные баги - пишите на 4pda.
P.S.
Комментарии к статье отключаю. Если кому-то интересно пообсуждать - 4pda.