Подзабросил я свой сайт - его никто не читает, да и мне лень тратить время чтобы что-то сюда писать. Тем не менее, жизнь не стоит на месте, и интересного происходил довольно-таки много.
Листал я авито от нечего делать, и увидел интересный лот - какая-то контора продает сотню абсолютно новых Depo Sky A60 тонких клиентов по 600 рублей. Я бы прошел мимо, но два гигабитных порта уж очень приглянулись за такой прайс.
Железо за такие деньги более чем:
SoC: Marvell Kirkwood 88F6282 (1.6Ghz, armv5, 1 core)
RAM: 1Gb DDR2-667 (4x256 Hynix H5PS2G83AFR)
Flash: 1Gb NAND (TSOP-48 Samgung K9K8G08U0D)
LAN: 1Gbit x2 (Marvell 88E1121R-TFE1)
Video: XGI Volari Z11 (распаяно на PCI-E, 64MB VRAM DDR2 Hynix H5PS5182GFR)
Audio: Realtek ALC5621 (i2с/i2s) (+пассивный buzzer на одном из выходов)
USB: USB2.0 x6 (HUB: Microchip USB2517)
PCI-E: mini-PCIe на плате
COM: через DB9
RTC на плате (с батарейкой).
Девайс сделала Promwad для AK-Systems, и по итогу получился тонкий клиент AK-Systems AK1100. А Depo по сути просто взяла плату от AK-Systems (не потрудившись даже заклеить AK-Systems), и запихала в свой корпус, назвав девайс Depo Sky A60.





Сначала были мысли типа "а спрятали ли/закрыли ли разработчики uart в который пишет uboot, или есть шансы что он все-таки будет на плате?", но при копании с тонким я был приятно удивлен - uboot пишет прямо на внешний COM порт. Вот такой кабель потребуется для подключения к uboot консоли. Можно взять на озоне за три сотки. Параметры подключения классические - 115200n8.
Сразу же возникла идея ставить такую штуку с Openwrt до роутера для прозрачного rutube+adguardhome для всей локалки. Но обломчик - поиск кастомов для железки ничего не дал.
Поиск стоковых прошивок тоже был нелегким, но все-таки я наткнулся на эту тему на doozan форуме. В ней человек с таким же устройством выкладывает стоковые прошивки + жалуется, что не может запустить на этом клиенте образы debian с doozan форума. "Хм, под этот старый тонкий есть актуальное ядро?" подумал я. Начал шерстить doozan форум, и понял, что этот SoC уже в mainline linux, поэтому нет проблемы взять: ванильное ядро + кастомный конфиг (c dozan форума) + rootfs любого дистра для armv5 = и получить полноценную ОС для этого тонкого. Только вот нужен еще dts для моего девайса, которого у меня конечно же не было. В стоковой прошивке его тоже не было (ибо там старое ядро 2.6.39). Надеясь на быстрое решение проблемы (чтобы кто-то подкинул мне готовый dts 😄), я создал эту тему на все том же doozan форуме.
Довольно быстро мы подобрали нормальный dts от похожего устройства. А дальше:
- Сетевухи заработали сразу (как и serial)
- Для работы PCI-e прошлось поиграться в dts с gpio (исходя из board файла платы из сорцов стокового ядра) (upd: 09.2025)
Для работы светодиодов и кнопки - аналогично (upd: 09.2025) - Для работы звука пришлось его объявить в dts с верной i2c шиной (i2c0)/i2s шиной/адресом(1a)/драйвером/и фиксированной частотой тактирования для 48кГц (динамику на плате не реализовали) + добавить аудио виджеты и маршруты - опять же, все это помог сделать board файл из сорцов стока + сделал в ОС включение каналов при старте и ресемплнинг всего на 48кГц в альсе. По итогу в debian полет нормальный, а в openwrt нужно собирать свои kmods (может как-нибудь потом..). И кстати, на плате есть пьезопищалка, что идет из аудиокодека, так что можно выводить звук не на джеки, а на нее. (upd: 09.2025)
- Для работы видео пришлось портировать xgifb драйвер в новое ядро. Этот драйвер был в ядре 5.0.21, а из 5.1 его уже выпилили. Я довольно легко донес его до 6.15.2 с минимальными правками в несколько строк, только вот он не заработал - писал io error. Начал шерстить код драйвера - увидел, что в начале для обнаружения он долбит в обычные io ports. Стал пробовать xgifb и старые ядра - и оно работает на 5.16.20, а на 5.17 ломается с io errors. Нашел причину - коммит c1aa4b55aae4c283e57c07e71968504bfa7d4a13, в котором из драйвера pci-mvebu выкинули специфичную для arm функцию pci_ioremap_io(). Но в отличии от x86 - на arm нет настоящих io ports (делается эмуляцией), вот и валится оно. Я пробовал переписать xgifb видео драйвер, чтобы он не юзал io ports (а юзал альтернативные методы) - но ошибка не менялась чтобы я не делал. Тогда я решил вернуть старое поведение для pci-mvebu драйвера - впихнул участки совместимости из pci-mvebu 5.16.20 в pci-mvebu 5.17 - это проканало и все заработало. Теперь эти правки надо нести до 6.15.2, но я увидел, что код pci-mvebu активно менялся чуть ли не каждый релиз - а значит для честного фикса я буду должен убить месяц, чтобы пройти правками все версии ядра до актуального. Времени на это выделить я не могу, так что пошел более тупым методом - взял мой рабочий фикшенный pci-mvebu из 5.17 и просто портанул его на 6.15.2. Да, некоторые pci-e плюшки пропали, но едва ли обычный юзер заметит разницу - зато видео работает😁. Но на всякий случай оставил сборку debian без видео с актуальным pci-mvebu драйвером тоже. Ну а для openwrt по поводу видео заморачиваться не стал - ибо для 23.05.6 потребуется собирать свой kmod, а для 24.10.х потребуется собирать свой kmod + ковырять ядро, что сделает нерабочими kmod пакеты с репозиториев. (upd: 10.2025)
- Для работы usb пришлось поломать голову - хаб USB2517 по i2c не отвечает, соответственно не конфигурируется и висит в воздухе с VID/PID 0000:0000, объявляя максимально допустимый ток для устройств - 0мА. Как итог - практически все устройства отказываются работать. В стоковой прошивке поведение аналогичное, разве что устройства все-таки работают (старым ядрам было пофиг на ограничения по току). И вишенка - в сорцах стоковой прошивки блок инициализации хаба закоментирован. Хм, больше похоже на косяк вендора... Читаю даташит - и реально, вендор выставил страпы (резисторами) в положение "бери конфиг с i2c флешки 24й серии" (которой около хаба нет), а надо было в положение "бери конфиг по i2c от soc". Ради теста перевел CFG_SEL1 страп резистор из pullup в pulldown - и хаб увиделся на i2c1 по 2c. Далее повесил хаб в dts с верной шиной/адресом/параметрами питания - и все заработало. Но паять резисторы 0603 не каждый захочет - так что стал искать альтернативы методы починки usb без пайки - и нашел. Судя по даташиту - этот пин хаба конфигурацию ловит только после ресета, а остальное время - он служит для индикации HS_IND, а судя по board файлу из сорцов стоковой прошивки - к нему из SoC идет gpio чтобы считывать этот самый HS_IND. Я подумал - знать HS состояние для usb upstream мне не к чему. А вот сделать свою правильную "подтяжку" с помощью этого gpio (чтобы избежать пайки) - самое то. По итогу - этот gpio добавил в dts в нулевое состояние при старте - хаб видит этот 0 сразу после ресета драйвером, и понимает что надо ловить конфиг по i2c. А после запуска ОС этот gpio освобождается (переводится в direction = in), чтобы не было драки между 0 на gpio у SoC и 1 на HS_IND пине у хаба. И все работает.
Ну а далее для debian я собрал ядро на основе конфига от bodhi, дописал его скелет dts, и собрал ubi контейнер с ubifs rootfs с параметрами для моей nand (которые подсмотрел в даташите + в логах стоковых прошивок) - и после правки envs в uboot (из-за новой разметки) - последний debian со свежим ядром завелся. Также владелец doozan форума (bodhi) добавил этот тонкий клиент в список поддерживаемых для своих сборок.
Поиграв немного с debian я решил впихнуть на девайс openwrt, ибо для описанной выше цели она будет поудобнее. Сначала я взял mainline ядро + rootfs от похожего девайса (разве что пересобрал ubi контейнер+ubifs для текущей nand) + положил модули ядра в rootfs. Все работало, но не нравились ошибки при установки kmod пакетов, ибо модули с репозиториев openwrt к кастомному ядру не подходили. Немного погуглив я выяснил, что текущий SoC kirkwood в openwrt и так поддерживается, но образов для этого тонкого клиента конечно же никто не делал. Ну значит сделаю я🙂.
Нашел девайс максимально похожий на тонкий клиент с поддержкой openwrt - им оказался cisco on100. Далее тестовая "сборка" openwrt для тонкого делалась из образа для cisco on100, она заключалась в замене dtb для тонкого + перепаковка rootfs в ubi под текущую nand. Но потом народ на форуме попросил сборку в нормальном виде (с обновлениями через sysupgrade из веб интерфейса + фичей сброса в дефолт) - сделал и их, согласно этому мануалу (+немного правок в сборочных рецептах, ибо по сути сорцы openwrt = buildroot система сборки) (upd. 10.2025). Как итог - Openwrt работает, репы включая kmod пакеты тоже работают. Но подлянку принесли разрабы openwrt - они собирают ядра для kirkwood без highmem, поэтому видно только 768МБ ОЗУ.
И кстати, девайс не имеет аппаратного нат (hardware nat offload) в нормальном понимании, но это компенсируется софтовым костылем в ядре в драйвере платформы (NFP), так что если ставить девайс до роутера для прозрачного rutube - скорости приличные, все 500MBit от провайдера отдает как минимум (по WireGuard, другие протоколы сильно медленней из-за старого SoC). И не забывайте врубать софтовое ускорение средствами ядра (software offload), тоже будет побыстрее.
Также без nat я протестировал скорость между двумя компами через тонкий клиент - получил цифры в районе 800+MBit.

Итог своей работы я бы и не выкладывал, но один человек попросил создать отдельную тему и выложить - вот я и выложил в этой теме на все том-же doozan форуме. После этого девайс заметили ребята с 4pda (вот моё сообщение, а болтали они о тонком еще раньше), и понеслось - сборку скачали около сотни раз, и оригинальный лот довольно-таки быстро раскупили с avito, но до сих пор этот тонкий новым можно найти на все том же авито от других продавцов за < 1000 рублей.
Даже нашелся "особо одаренный" барыга, который перепродавал эти тонкие с моей сборкой openwrt на авито в три раза дороже (вроде бы он барижит до сих пор). Я такое не поддерживаю, ибо драть втридорога за то, что ты просто существуешь и смог прошить чужую сборку по инструкции - тупо, да и других ребят лишаешь дешевого товара (который бы они могли купить для себя). Не покупайте у него ничего.
Ниже ссылки для скачивания сборок и мануалы (частично взял из своего поста с doozan форума):
ВНИМАНИЕ! НЕ ШЕЙТЕ ДРУГИЕ ДЕВАЙСЫ ЭТИМ ОБРАЗОМ! Он предназначен только для девайсов с флешкой Samsung NAND 1GiB 3,3V 8-bit, Manufacturer ID: 0xec, Chip ID: 0xd3.
1) Debian (rootfs сделал через debootstrap, systemd логи лежат в ОЗУ) с конфигами ядра от bodhi
Ссылка (образы и инструкции)
2) OpenWRT с официальным ядром (kmod пакеты работают)
(официальное ядро без highmem, так что будет доступно только 768МБ ОЗУ)
Ссылка (образы и инструкции)
3) Стоковые прошивки и исходники (а также руководство с паролями)
Ссылка, зеркало, зеркало
Дополнительные ссылки:
Тема, в которой мы работает над деревом устройств
Тема с ядрами и rootfs debian от bodhi (если вас не чем-то не устраивает эта сборка)
Сборка legacy тупых образов (не умеют веб обновки и сброс в дефолт):
me@pc:~/tmpdir$ wget https://downloads.openwrt.org/releases/24.10.3/targets/kirkwood/generic/openwrt-24.10.3-kirkwood-generic-cisco_on100-squashfs-sysupgrade.bin
me@pc:~/tmpdir$ tar xf openwrt-24.10.3-kirkwood-generic-cisco_on100-squashfs-sysupgrade.bin
me@pc:~/tmpdir$ cd sysupgrade-cisco_on100/
#find out where the uImage header and FTD are in order to delete
me@pc:~/tmpdir/sysupgrade-cisco_on100$ binwalk kernel
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 uImage header, header size: 64 bytes, header CRC: 0xE1BDA1E8, created: 2025-09-19 21:19:38, image size: 3131648 bytes, Data Address: 0x8000, Entry Point: 0x8000, data CRC: 0x4C1E645B, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: "ARM OpenWrt Linux-6.6.104"
64 0x40 Linux kernel ARM boot executable zImage (little-endian)
30424 0x76D8 xz compressed data
30948 0x78E4 xz compressed data
3119768 0x2F9A98 Flattened device tree, size: 11944 bytes, version: 17
me@pc:~/tmpdir/sysupgrade-cisco_on100$ dd if=kernel of=zImage-baddtb bs=64 skip=1
me@pc:~/tmpdir/sysupgrade-cisco_on100$ binwalk zImage-baddtb
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 Linux kernel ARM boot executable zImage (little-endian)
30360 0x7698 xz compressed data
30884 0x78A4 xz compressed data
3119704 0x2F9A58 Flattened device tree, size: 11944 bytes, version: 17
me@pc:~/tmpdir/sysupgrade-cisco_on100$ dd if=zImage-baddtb of=zImage bs=3119704 count=1
#make uImage with our FDT
me@pc:~/tmpdir/sysupgrade-cisco_on100$ cat kirkwood-promwad-thin-client.dtb >> zImage
me@pc:~/tmpdir/sysupgrade-cisco_on100$ mkimage -A arm -O linux -T kernel -C none -a 0x8000 -e 0x8000 -n Linux-6.6.104 -d zImage uImage6.6.104
#we need to be root when creating a rootfs so that there are no permissions issues
me@pc:~/tmpdir/sysupgrade-cisco_on100$ sudo -s
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# unsquashfs root
#enable ttyS0 console for login and shell
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# echo 'ttyS0::askfirst:/usr/libexec/login.sh' >> squashfs-root/etc/inittab
#mark ports for luci
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# echo -e '{\n\t"model": {\n\t\t"id": "promwad,wtplug-tc",\n\t\t"name": "Promwad WTPlug Thin Client"\n\t},\n\t"network": {\n\t\t"lan": {\n\t\t\t"device": "eth0",\n\t\t\t"protocol": "static"\n\t\t},\n\t\t"wan": {\n\t\t\t"device": "eth1",\n\t\t\t"protocol": "dhcp"\n\t\t}\n\t}\n}' > squashfs-root/etc/board.json
#set safely off for usb strap
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# chmod +x squashfs-root/etc/rc.local
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# echo -e '#!/bin/ash\n\nsleep 20 && echo in > /sys/class/gpio/usb_strap/direction &\necho usb strap released\n\nexit 0\n' > squashfs-root/etc/rc.local
#usb drivers
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# echo 'usb251xb' > squashfs-root/etc/modules.d/70-usb251xb
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# echo 'usb251xb' > squashfs-root/etc/modules-boot.d/70-usb251xb
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# cp usb251xb.ko squashfs-root/lib/modules/6.6.104
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# chown root.root squashfs-root/lib/modules/6.6.104/usb251xb.ko
#set general ubi parametrs
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# echo -e '[ubifs]\nmode=ubi\nimage=ow.tmp\nvol_id=0\nvol_size=900MiB\nvol_type=dynamic\nvol_name=rootfs\nvol_flags=autoresize' > ubinize.cfg
#set nand parametrs
#erase block, page, and subpage parameters are taken from the nand flash datasheet
#logical UBIFS block parameters calculated according to the formula, and matches the value in the stock firmware
#the count of logical UBIFS blocks is calculated for the UBIFS size of 900M
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# mkfs.ubifs -q -r squashfs-root/ -m 2048 -e 129024 -c 8191 -o ow.tmp
#mke ubi container with ubifs partition
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# ubinize -o ow24.10.3.ubi -m 2048 -p 128KiB -s 512 ubinize.cfg
root@pc:/home/me/tmpdir/sysupgrade-cisco_on100# chown me.me ow24.10.3.ubi
Сборка нормальных образов:
prepairing:
git clone https://github.com/openwrt/openwrt.git
cd openwrt
git pull
git branch -a
git tag
#openwrt version
git checkout v24.10.3
./scripts/feeds update -a; ./scripts/feeds install -a
#url for you openwrt version
wget https://downloads.openwrt.org/releases/24.10.3/targets/kirkwood/generic/config.buildinfo -O .config
1) Makefile or mk file
nano target/linux/kirkwood/image/Makefile
replace similar device (cisco on100) with
define Device/promwad_wtplug-tc
DEVICE_VENDOR := Promwad
DEVICE_MODEL := wtplug-tc
KERNEL_IN_UBI := 0
KERNEL_SIZE := 10240k
PAGESIZE := 2048
BLOCKSIZE := 128k
VID_HDR_OFFSET := 512
SUBPAGESIZE := 512
UBIFS_OPTS := -m $(PAGESIZE) -e 129024 -c 8191
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
DEVICE_PACKAGES := kmod-mvsdio kmod-rtc-mv
SUPPORTED_DEVICES += promwad,wtplug-tc cisco,on100
endef
TARGET_DEVICES += promwad_wtplug-tc
and platform file:
nano target/linux/kirkwood/base-files/lib/upgrade/platform.sh
in platform_do_upgrade()
in case "$board" in
promwad,wtplug-tc)
CI_KERNPART="uImage"
CI_UBIPART="ubi"
nand_do_upgrade "$1"
;;
2) dts
#path for you kernel
nano target/linux/kirkwood/files-6.6/arch/arm/boot/dts/marvell/kirkwood-wtplug-tc.dts
3) create files files
mkdir -p files/etc
echo -e '::sysinit:/etc/init.d/rcS S boot\n::shutdown:/etc/init.d/rcS K shutdown\n::askconsole:/usr/libexec/login.sh\nttyS0::askfirst:/usr/libexec/login.sh' > files/etc/inittab
echo -e '{\n\t"model": {\n\t\t"id": "promwad,wtplug-tc",\n\t\t"name": "Promwad WTPlug Thin Client"\n\t},\n\t"network": {\n\t\t"lan": {\n\t\t\t"device": "eth0",\n\t\t\t"protocol": "static"\n\t\t},\n\t\t"wan": {\n\t\t\t"device": "eth1",\n\t\t\t"protocol": "dhcp"\n\t\t}\n\t}\n}' > files/etc/board.json
echo -e '#!/bin/ash\n\nsleep 20 && echo in > /sys/class/gpio/usb_strap/direction &\necho usb strap released\n\nexit 0\n' > files/etc/rc.local
chmod +x files/etc/rc.local
mkdir -p files/etc/modules.d
echo 'usb251xb' > files/etc/modules.d/70-usb251xb
mkdir -p files/etc/modules-boot.d
echo 'usb251xb' > files/etc/modules-boot.d/70-usb251xb
#path for you kernel modules
mkdir -p files/lib/modules/6.6.104
cp usb251xb.ko files/lib/modules/6.6.104
#check
tree files
4) choose device and compile in tmux
make menuconfig
make -j $(nproc) download world V=sc
Сборка модуля для хаба usb2715:
If you want compile kmod for usb by youself:
0) Download sdk for you openwrt version for kirkwood (e.g. https://downloads.openwrt.org/releases/24.10.3/targets/kirkwood/generic/openwrt-sdk-24.10.3-kirkwood-generic_gcc-13.3.0_musl_eabi.Linux-x86_64.tar.zst)
1) Update indexes/install packages sources
./scripts/feeds update -a; ./scripts/feeds install -a
2) create usb251x dir
mkdir -p package/kernel/usb251xb/src
and makefile package/kernel/usb251xb/Makefile
include $(TOPDIR)/rules.mk
PKG_NAME:=kmod-usb251xb
PKG_RELEASE:=1
PKG_LICENSE:=GPL-2.0
PKG_MAINTAINER:=me <me@lol.com>
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
PKG_SOURCE_VERSION:=v6.6.104
PKG_MIRROR_HASH:=skip
include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/package.mk
define KernelPackage/usb251xb
SUBMENU:=USB Support
TITLE:=Microchip USB251xB SMBus/I2C configuration driver
DEPENDS:=+kmod-usb-core +kmod-i2c-core
FILES:=$(PKG_BUILD_DIR)/out/usb251xb.ko
AUTOLOAD:=$(call AutoLoad,70,usb251xb,1)
endef
define KernelPackage/usb251xb/description
Out-of-tree build of the upstream usb251xb driver to configure Microchip USB251xB/USB351xB hubs over SMBus/I2C.
endef
define Build/Prepare
$(call Build/Prepare/Default)
mkdir -p $(PKG_BUILD_DIR)/out
$(CP) $(PKG_BUILD_DIR)/drivers/usb/misc/usb251xb.c $(PKG_BUILD_DIR)/out/
echo 'obj-m += usb251xb.o' > $(PKG_BUILD_DIR)/out/Makefile
endef
define Build/Compile
$(KERNEL_MAKE) M="$(PKG_BUILD_DIR)/out" \
EXTRA_CFLAGS="$(TARGET_CFLAGS)" \
modules
endef
$(eval $(call KernelPackage,usb251xb))
3) save config
make menuconfig
Kernel modules → USB Support → [M] kmod-usb251xb
4) compile kmod package
make package/kernel/usb251xb/compile -j $(nproc)
5) find package
ls ./bin/targets/kirkwood/generic/packages/kmod-usb251xb_6.6.104.0~v6.6.104-r1_arm_xscale.ipk
6) copy package to thin client /tmp (via scp -O) and install it (need internet for deps!)
opkg update
opkg install /tmp/kmod-usb251xb_6.6.104.0\~v6.6.104-r1_arm_xscale.ipk
(or manually install kmod-i2c-core before installation, if without internet)