No description
  • Shell 99.4%
  • Batchfile 0.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-13 15:18:25 +03:00
blobs Сборка образа Arch Linux ARM для Repka Pi 3: скрипт, блобы, описание 2026-10-12 11:07:31 +03:00
.gitignore Сборка образа Arch Linux ARM для Repka Pi 3: скрипт, блобы, описание 2026-10-12 11:07:31 +03:00
build-image.sh poweroff/reboot без sudo: polkit + правило polkit-1/rules.d/10-poweroff.rules (wheel); дефолт polkit по SSH отказывает; alarm уже в wheel, новому юзеру — usermod -aG wheel; pkexec в восстановление suid 2026-10-13 15:18:25 +03:00
README.md poweroff/reboot без sudo: polkit + правило polkit-1/rules.d/10-poweroff.rules (wheel); дефолт polkit по SSH отказывает; alarm уже в wheel, новому юзеру — usermod -aG wheel; pkexec в восстановление suid 2026-10-13 15:18:25 +03:00

Arch Linux ARM для Repka Pi 3

Сборка загрузочного образа Arch Linux ARM (aarch64) для одноплатника Repka Pi 3 (Allwinner H5, ревизии 1.3–1.6). Проект самодостаточен и предназначен для git: в репозитории лежат только исходники и маленькие блобы (~7 МБ), все тяжёлые зависимости (тарбол ALARM ~800 МБ, пакеты) скачиваются скриптом при сборке в dl/ и в git не попадают.

bash build-image.sh        # собрать образ: out/arch-linux-arm-repka-pi3.img

Состав образа

Компонент Откуда Что именно
Rootfs + ядро Arch Linux ARM aarch64 базовый rootfs, ядро linux-aarch64 (мейнлайн), модули
Загрузчик Repka (npo_rbs/repka-os_boot-loader) u-boot-sunxi-with-spl.bin (SPL+U-Boot+ATF), пишется на 8 KiB
DTB ядра Repka OS + наш патч sun50i-h5-repka-pi3.dtb (OPP до 1416 МГц, WiFi mmc1, BT serdev)
WiFi прошивка linux-firmware (в rootfs) апстрим cyfmac43430-sdio.bin под именами brcmfmac43430-sdio.rbs,repka-pi3.{bin,txt}
BT прошивка blobs/firmware bcm43438a1.hcd → BCM43430A1.hcd (+ фолбэк-имена)
WiFi/BT userspace ALARM repo wpa_supplicant, bluez, bluez-utils (скачиваются и проверяются подписи)
Сеть systemd-networkd + resolved end0 + wlan0 по DHCP

Пакеты поверх base регистрируются в /var/lib/pacman/local с полными списками файлов, так что pacman считает их своими и pacman -Syu работает штатно (см. «Исправления»).

Исправления, запечённые в образ

Все вошли после реальной отладки на железе (2026-10-10…12):

  1. Адреса загрузки в boot.cmd: ядро 0x42000000, DTB 0x48000000. Старая схема Repka (0x41000000/0x44000000) вешала плату после обновления ядра ALARM ≥ 7.2: Image вырос с 44 до ~50 МБ и при загрузке накрывал DTB, лежащий на 0x44000000 (симптом: после pacman -Syu обрыв по UART сразу после «Starting kernel...»). Новые адреса — стандартные distro-адреса sunxi.
  2. Патч DTB: убран дубль фиксированного клока ext_osc32k в /clocks. Вендорский DTB объявлял его дважды (один раз с phandle) — второй экземпляр ломал регистрацию часовника RTC/LPO (32 кГц), без которого serdev-BT (brcm,bcm43438-bt) не поднимался. С патчем Bluetooth работает (hci0, патч BCM43430A1.hcd грузится). Оригинал — blobs/dtb/*.orig.dtb.
  3. Полные списки файлов в pacman-базе для пакетов, распакованных в rootfs напрямую. Пустая заглушка %FILES% делала запись «битой»: любое pacman -Syu, трогающее такие пакеты или их окружение, падало «exists in filesystem». Теперь списки генерируются из исходных .pkg.tar.xz, имя каталога базы — с epoch (wpa_supplicant-2:2.12-1). Внимание: сборщик ALARM в момент сборки отдавал часть пакетов пустыми (size = 0: gcc-libs, libgcc, ca-certificates, linux-firmware) — у них в базе корректно пустой список, а сами файлы в rootfs есть из тарбола. Когда ALARM починит сборщик и эти пакеты обновятся, первый такой -Syu может попросить --overwrite — это штатно: pacman -Syu --overwrite '*'.
  4. Зеркало pacman в образе: fl.us.mirror.archlinuxarm.org → Yandex. Замер с платы (2026-10-13): fl.us — 3-4 МБ/с, Yandex просел до ~0.3 МБ/с (TTFB до 13 с), de.mirror.archlinuxarm.org отдаёт ошибку на extra.db. Дефолтный mirror.archlinuxarm.org по GeoIP ненадёжен, а os.archlinuxarm.org отдаёт чужой TLS-сертификат — не использовать.
  5. Статус-LED выключен: /etc/tmpfiles.d/repka-leds.conf ставит trigger=none, brightness=0 при каждой загрузке (синяя лампочка не мигает). Вернуть: echo heartbeat > /sys/class/leds/rbs:red:status/trigger.
  6. Root по SSH — только по ключу (PermitRootLogin prohibit-password в sshd_config.d/10-root.conf); стоковый ALARM пускает root по паролю root. Как получить root по SSH после прошивки — см. «Первый вход».
  7. MTU 1492 на end0 (10-end0.network): за PPPoE-роутером пакеты 1500 без работающего PMTUD душат TCP до КБ/с.
  8. Локаль en_US.UTF-8 (locale.gen + locale.conf + /etc/environment — последняя нужна, чтобы локаль видели SSH-сессии; генерация локали и pacman-ключница — на первой загрузке, юнит first-boot-setup.service).
  9. SSH host-ключи генерируются при сборке (sshd готов сразу), suid-биты и владелец root в ФС восстанавливаются (fakeroot/docker) — иначе на плате отваливаются sshd/su/pacman-ключница.
  10. Pacman-хук контроля размера ядра: после установки/обновления ядра /usr/local/bin/check-kernel-size.sh сверяет размер /boot/Image с зазором до адреса DTB из boot.cmd (сейчас 96 МиБ при ядре ~50 МБ). Всегда печатает запас; с 80% зазора — ВНИМАНИЕ, при перекрытии — КРИТИЧНО с рецептом лечения (поднять адрес DTB, пересобрать boot.scr), плюс запись в журнал (logger -t kernel-size, journalctl -t kernel-size).
  11. poweroff/reboot без sudo: в образе есть polkit и правило /etc/polkit-1/rules.d/10-poweroff.rules, разрешающее выключение и перезагрузку членам группы wheel (alarm в ней состоит из коробки). Без правила polkit по SSH отвечает «Access denied» — его дефолт пускает выключение только из локальной консоли. Пользователю, созданному после прошивки: usermod -aG wheel <имя>.

Разметка образа

offset 8 KiB    u-boot-sunxi-with-spl.bin (SPL Repka)
offset 10 MiB   p1: ext4 «rootfs» (метка rootfs), до конца образа
                /boot: Image, sun50i-h5-repka-pi3.dtb, boot.cmd, boot.scr

Раздел один — /dev/mmcblk0p1 — и есть корень. boot.scr грузит /boot/Image + /boot/sun50i-h5-repka-pi3.dtb, root=/dev/mmcblk0p1 rw rootwait, без initramfs (драйверы MMC/EXT4 в ядре ALARM встроены). При обновлении ядра следите за размером /boot/Image относительно адреса DTB (см. исправление 1).

Структура репозитория

build-image.sh        сборка (bash build-image.sh; IMG_SIZE=8G bash … — другой размер)
README.md             этот файл
blobs/
  bootloader/         u-boot-sunxi-with-spl.bin — сборка из npo_rbs/repka-os_boot-loader (2024)
  dtb/                патченный DTB + оригинал + boot.cmd/boot.scr (адреса 0x42000000/0x48000000)
  firmware/           bcm43438a1.hcd (BT-патч AP6212), nvram.txt (запасной nvram, в rootfs есть AP6212.txt)
  uboot-variants/     вендорные загрузчики Repka OS: клоки DRAM 672/696/744/768, с UART и «тихие» (nottys0)
dl/                   (gitignore) скачанные зависимости: тарбол ALARM + пакеты с подписями
work/                 (gitignore) распакованный rootfs, промежуточные файлы
out/                  (gitignore) готовый образ, sha256, boot.cmd, uboot-variants/

Прошивки A0 (fw_bcm43438a0.bin, bcm43438a0.hcd) из Repka OS не используются: на плате чип rev A1 (BCM43430A1), ему нужна апстримная прошивка. Осторожно: brcmfmac43430-sdio.bin в linux-firmware — симлинк на cypress/cyfmac43430-sdio.bin, запись «через» симлинк затирает цель.

Зависимости сборки (хост)

  • утилиты: bsdtar (libarchive), e2fsprogs (mkfs.ext4, debugfs), sfdisk, curl, xxd, readelf (binutils)
  • владелец root в ФС: fakeroot (пакет fakeroot) или docker — без них образ соберётся от uid 1000 и на плате не поднимется sshd
  • mkimage (u-boot-tools) — для boot.scr; если нет, используется docker (alpine + u-boot-tools), иначе готовый blobs/dtb/boot.scr

Скачивание идёт с MIRROR (по умолчанию http://fl.us.mirror.archlinuxarm.org, фолбэк — Yandex); переопределить: MIRROR=http://… bash build-image.sh.

Прошивка

# заменить sdX на карту (проверить lsblk!)
dd if=out/arch-linux-arm-repka-pi3.img of=/dev/sdX bs=4M conv=fsync status=progress
# или графически: Repka image-writer / balenaEtcher

Образ 6 ГиБ (реально ~2 ГиБ — файл разрежённый). Под карту большего объёма раздел расширяют после первой загрузки (см. ниже). Заменить загрузчик на вариант из out/uboot-variants/: dd if=<bin> of=/dev/sdX bs=1024 seek=8 conv=notrunc.

Первый вход

Учётки по умолчанию ALARM: root / root и alarm / alarm — сменить пароли сразу. В базе ALARM нет sudo — используй su -.

  • UART-консоль: пины 8/10 (UART0 TX/RX), 115200 8N1
  • SSH: ssh alarm@<ip-по-dhcp> (сразу работает)
passwd && passwd alarm            # сменить пароли (root, потом alarm)

# свой пользователь вместо/вместе с alarm; wheel даёт poweroff/reboot без sudo
# (правило polkit в образе пускает выключение всем из wheel):
useradd -m -G wheel -s /bin/bash <имя> && passwd <имя>

# расширить раздел на всю карту (под root):
sfdisk --no-reread -N1 /dev/mmcblk0 <<< ',+' && partx -u /dev/mmcblk0
resize2fs /dev/mmcblk0p1          # онлайн, без ребута

# root по SSH (PermitRootLogin prohibit-password — только по ключу):
mkdir -p /root/.ssh && chmod 700 /root/.ssh
echo 'ssh-ed25519 AAAA…' > /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys
# на десктопе: ssh-copy-id -i ~/.ssh/<ключ>.pub root@<ip>  — но сначала положи ключ по схеме выше

Первые ~минуты после старта платa занята first-boot-setup.service (pacman-key --init/--populate, locale-gen) — pacman заработает после него.

WiFi и Bluetooth

Bluetooth работает из коробки (serdev + DTB-патч, см. исправление 2):

bluetoothctl power on && bluetoothctl scan on

WiFi (wlan0) может не подняться на ядрах ≥ 7.2 — известная регрессия pwrseq_simple: для однопинового reset-gpios (PL8) драйвер требует reset-controller и получает -ENOENT → mmc1 «Failed to initialize a non-removable card». Обходы (gpio-hog в DTB, userspace-рескан) не помогли. Варианты: ждать фикс ядра (pacman -Syu), USB-WiFi донгл, откат ядра. Когда ядро починят, настройка обычная:

wpa_passphrase 'ИМЯ_СЕТИ' 'пароль' >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
systemctl restart wpa_supplicant@wlan0

Диагностика: dmesg | grep -E 'brcmf|mmc1'. HT Avail timeout = не подошли прошивка/nvram.

Сеть

Интерфейс называется end0 (не eth0 — так его называет DTB Repka). MTU 1492 зашит в 10-end0.network (PPPoE-путь). Если плата внезапно отдаёт ~40 кбит/с на всех WAN-соединениях при нормальном LAN и чистых пингах — проверьте роутер: Keenetic троттлит устройства по записям с лимитом (лечится удалением записи устройства или сменой MAC: ip link set end0 address … + закрепить в /etc/systemd/network/*.link).

GPIO (40 pin, распиновка как у Raspberry Pi)

Библиотеки Repka (ставить на самой плате):

Логика 3,3 В, пин ≤ 40 мА (кратковременно). В v1.6 на разъём выведен I2S.

Известные нюансы

  • Владение файлами: сборка без fakeroot/docker даёт ФС от uid 1000 — на плате отвалятся sshd (/usr/share/empty.sshd must be owned by root), su, pacman-ключница. Лечение после прошивки: chown -R 0:0 корня (кроме /home/alarm) + suid-биты.
  • Обновления: pacman -Syu обновит и ядро — DTB в /boot не трогается, загрузчик на карте не меняется, адреса в boot.scr уже безопасные (исправление 1). Если после обновления плата не грузится — по UART смотрите, дошёл ли «Starting kernel...», и проверьте размер Image (ls -lh /boot/Image).
  • DTB собран под ядро 6.1 (Feb 2024), но работает с мейнлайном (проверено на 6.9, 7.2.9, 7.2.10); таблица OPP до 1416 МГц. Если новое ядро поменяет биндинги — пересобрать из исходников Repka (repka-os_boot-loader).
  • GPU Mali-450 — ускорения OpenGL нет (KMS-консоль и программный рендер). Видео-декодирование — cedrus (V4L2).
  • Журнал персистентный: journalctl -p 3 на плате или journalctl --directory=<смонтированная карта>/var/log/journal -p 3.