Issue archr-linux/Arch-R#34: ao inserir um segundo cartão SD em TF2,
o boot falha com "cannot find mmcblk1p1" + countdown para poweroff.
Causa:
- Linux enumera os controladores MMC do RK3326 por ordem do DT:
ff380000.mmc -> mmc0 -> /dev/mmcblk0 (TF2, slot secundário)
ff370000.mmc -> mmc1 -> /dev/mmcblk1 (TF1, slot com o OS)
- U-Boot enumera por ordem de probe dos slots; com TF2 populado o
devnum repassado para a sysboot pode acabar diferente do que o
kernel apresenta como /dev/mmcblk1.
- clone_boot.ini e original_boot.ini montavam o kernel cmdline como
`boot=/dev/mmcblk${devnum}p1 root=...p2 disk=...p3`, então a
troca de devnum quebrava o /init busybox.
Fix:
Substituir o path hardcoded por LABEL=@DISTRO_BOOTLABEL@ (sed do
package.mk já existia mas não tinha onde substituir; agora cobre
ARCHR / ARCHR_ROOT / STORAGE). O /init busybox já trata LABEL= via
findfs + fallback de blkid scan em mmcblk0/mmcblk1, então a partição
certa é encontrada independente da ordem de enumeração — sobrevive
a 2-SD, troca de slot, ou qualquer reorder que U-Boot decida fazer.
Kernel cmdline antes:
boot=/dev/mmcblk1p1 root=/dev/mmcblk1p2 disk=/dev/mmcblk1p3
Depois:
boot=LABEL=ARCHR root=LABEL=ARCHR_ROOT disk=LABEL=STORAGE
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Vários edge cases no fluxo de conexão WiFi com caracteres não-ASCII /
metacaracteres causavam o sintoma reportado "trava ao conectar":
1. iwd codifica caracteres não ([A-Za-z0-9._-]) no nome do .psk como
=XX (man iwd.network "Network file names"). wifictl gravava o
profile como /var/lib/iwd/<SSID literal>.psk — quando o SSID tinha
espaço, ç, +, /, etc. iwd não encontrava o arquivo, o iwctl
station connect caía em prompt interativo aguardando passphrase via
stdin e ficava preso até o autoconnect timeout (30+s). encode_iwd_
name aplica a transformação canônica byte-a-byte (validado com
"Café" -> "Caf=C3=A9", "DIRECT-17-HP Douglas" -> "DIRECT-17-HP=20
Douglas").
2. Senhas fora do intervalo válido (WPA-PSK: 8..63 bytes printable ou
64 hex chars) também faziam iwd rejeitar o profile e cair no
mesmo trava-no-prompt-stdin. wifictl agora rejeita cedo com retorno
2 e mensagem em stderr, dando feedback útil para a UI.
3. Profile órfão de tentativa anterior podia conflitar: ao trocar
entre rede aberta e WPA, ou ao mudar a senha, o iwd preferia o
profile antigo (.open / .psk). Agora wifictl remove os dois antes
de regravar.
4. O check de pós-conexão era frouxo: "state=connected" sozinho
retornava sucesso quando a estação já estava em outra rede,
mesmo que a conexão solicitada falhasse silenciosamente. Adicionado
match contra "Connected network" do iwctl show.
5. O heredoc do create_adhoc usava <<EOF (não-quoted) — um $ literal
na passphrase disparava expansão de variável bash. Substituído por
printf %s para preservar a senha byte-a-byte.
6. /var/lib/iwd/*.psk passa a ser criado com umask 077 — a passphrase
está em texto claro no arquivo e não deveria ser legível por nada
além do iwd (rodando como root).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A versão anterior do short-circuit gravava sha256(senha) em
/storage/.cache/.archr-rootpass.sha256 — fingerprint recuperável que
quebraria senhas curtas / dicionário por brute force trivial se o
arquivo vazasse. Revisão de segurança automatizada apontou.
Substituída a comparação por reproduzir o próprio sha512crypt já
armazenado em /storage/.cache/shadow: extrai o salt do campo CURRENT
(formato $6$<salt>$<hash>), chama cryptpw -m sha512 -S "$SALT"
"$ROOTPASS" e compara contra CURRENT. Nenhum novo arquivo é escrito;
o único hash de senha em disco continua sendo o sha512crypt salted
que já existia.
Live no R36S:
- mesma senha: 0.147s (short-circuit)
- senha nova: 1.233s (caminho completo)
- nenhum arquivo extra em /storage/.cache/.archr-rootpass*
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
5 ganhos mensuráveis identificados rodando o sistema vivo:
1. /etc/sysctl.d → /storage/.config/sysctl.d, e systemd-sysctl roda
Before=sysinit.target — /storage só monta em local-fs.target. O
symlink ficava dangling quando systemd-sysctl lia, então archr.conf
(BBR/fq_codel, vm.dirty_writeback_centisecs=1500, ip_forward, etc.)
nunca era aplicado no boot. Verificado: rodando sysctl -p manual
depois do boot, dirty_writeback_centisecs vai de 500 → 1500.
Replicar os defaults da distro em /usr/lib/sysctl.d (rootfs, sempre
disponível) garante aplicação antes de /storage subir; o /etc/
sysctl.d permanece como ponto de override do usuário.
2. enable.turbo-mode=1 em system.cfg padrão. A baseline validada do
R36S inclui CPU turbo @ 1512 MHz via cpufreq/boost (vdd_arm
regulator-max=1.45V), mas o default era 0 — clamp em 1416 MHz
sem opt-in. O nó scaling_max_freq sobe para 1512000 assim que
boost=1, comprovado live no device. Quem precisar do clamp
térmico de 1416 desliga via Settings > Advanced.
3. rpcbind.service rodando idle custava ~11 MB de RAM em um device
com 1 GB total, sem nada usando NFS. O upstream já fornece
rpcbind.socket (Listen :111 + /run/rpcbind.sock) e systemd faz
activation on-demand — mount.nfs dispara o daemon quando o user
realmente monta um share. Trocado enable_service rpcbind.service
por rpcbind.socket.
4. archr-touchscreen-keyboard ficava acordando a cada 5s mesmo em
devices sem touchscreen (R36S, R33S, etc), e com Restart=always
um exit do helper provocava restart infinito. Adicionado bail-out
precoce quando DEVICE_HAS_TOUCHSCREEN != true, e Restart trocado
para on-failure para honrar o exit limpo. Em devices sem
touchscreen o serviço passa a ficar inativo após o primeiro boot.
5. setrootpass cryptpw sha512 + smbpasswd + syncthing generate
custavam ~6s a cada boot — chamado pelo autostart 007-rootpw com a
senha já configurada. Adicionado short-circuit que compara o hash
sha256 da senha contra o cache em /storage/.cache/.archr-rootpass.
sha256: se nada mudou, sai em 20ms.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
001-functions:wait_lock(): o trap rm -f "\$lockfile" referenciava
uma variável inexistente. O lock real está em \${J_CONF_LOCK}. Como
\$lockfile expandia para string vazia, rm -f "" virava no-op e
deixava /tmp/.system.cfg.lock órfão se o script morresse por SIGINT/
SIGTERM antes do rm -f explícito no final.
archr-automount.service: Before=autostart.service apontava para o
nome herdado do JELOS, que ArchR não embarca (a unit real é
archr-autostart.service). Sem o prefixo o ordering virava silently
ignored, perdendo a garantia de que /storage/games-* fosse montado
antes dos scripts de autostart consumirem os paths. Também ajustada
a Description que dizia "user autostart script" (copy-paste do
archr-autostart.service).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sweep encontrou 5 categorias de bugs sutis em arquivos herdados:
1. StartLimitInterval/StartLimitBurst em [Service] em 13 unidades
(avahi, bluez, connman, samba/nmbd/smbd, sshd, tz-data, ledfix,
xorg, fluxbox/windowmanager, samba-config). systemd silenciosamente
ignora StartLimit* fora de [Unit], então a proteção contra
restart-flood nunca foi aplicada. Movidas para [Unit] e renomeadas
para o canônico StartLimitIntervalSec (StartLimitInterval é alias
antigo).
2. Refs dangling para kodi.service em 5 units (entware, locale, sway,
xorg, xwayland-xorg, windowmanager-fluxbox). ArchR não embarca
Kodi; o ordering Before=kodi.service ficava como "not-found" no
systemctl list-units. Trocado por Before=archr.target (alvo real
de boot da UI em ArchR).
3. usercache.service e userconfig.service referenciavam
automount.service e autostart.service sem prefixo archr-. Em ArchR
as unidades reais chamam-se archr-automount.service /
archr-autostart.service, então o Before= era ignorado e o setup
corria paralelo aos mounts.
4. archr-autostart.service tinha Before=weston.service. ArchR roda
sway, não weston. Removido (After=graphical.target já cobre).
5. nmbd.service do override ArchR queria samba-config.service que só
existe no pacote global packages/network/samba (não no override).
O daemons/002-samba já cria /run/samba/smb.conf manualmente, então
Wants/After=samba-config.service eram supérfluos.
Bugs adicionais corrigidos no caminho:
- archr/autostart/050-audio: `if [ -n "/usr/sbin/quantum" ]` testa se
uma string literal é não-vazia (sempre true) em vez de checar se o
binário existe. Trocado para [ -x ].
- avahi: post_makeinstall_target removia /usr/sbin/avahi-dnsconfd mas
deixava a unit avahi-dnsconfd.service órfã. Remove a unit junto.
- system-utils: video.service só faz sentido em devices que embarcam
/usr/bin/video_sense (RK3399/RK3566/S922X). Remove a unit em
devices que não têm o helper.
- xwayland: scripts/xorg-configure não era instalado, deixando
xorg-configure@.service com ExecStart para um path inexistente.
Agora copiado pra /usr/lib/xorg/xorg-configure.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bug crítico no autostart: QUIRK_DEVICE vem de /sys/firmware/devicetree
/base/model e quase sempre tem espaços ("Game Console R36S"). O loop
`for QDIR in ${QUIRK_DIRS}` com string concatenada partia esse path em
3 tokens (Game, Console, R36S) e o glob ${QDIR}/* não casava com nada.
Resultado: nenhum quirk device-specific rodava — 001-device_config
nunca escrevia /storage/.config/profile.d/001-device_config, então
DEVICE_TEMP_SENSOR / DEVICE_PWR_LED_GPIO / DEVICE_PLAYBACK_PATH_*
ficavam vazios em todos os processos. O System Information do ES não
mostrava CPU TEMPERATURE, GPU TEMPERATURE, e os start_*.sh dos
emuladores caíam em fallback de áudio.
Fix usa arrays bash com expansão entre aspas:
QUIRK_DIRS=(...)
for QDIR in "${QUIRK_DIRS[@]}"; do ...
archr-info ganha 5 melhorias:
- DISTRO FAMILY: lê ID_LIKE de /etc/os-release e renderiza
"Arch Linux" (título). OPERATING SYSTEM agora mostra "ArchR Linux"
para deixar a relação com Arch explícita.
- DISK SPACE: detecta quando games-internal e games-external apontam
para o mesmo device e mostra só "INTERNAL" (a UI repetia a linha
idêntica quando não havia SD externo).
- MESA VERSION: sniffa libgallium-X.Y.Z.so para mostrar 26.1.3.
- GPU DRIVER: lsmod identifica panfrost (Mesa) ou mali_kbase (legacy
blob), útil pra debugar quando o user troca via picker.
- info_quirks: protegido contra chamada sem argumento (era o motivo
do exit 127); usa nullglob + iteração quoted para suportar paths com
espaços e diretórios info.d/* ausentes.
Game Console R36S/001-device_config: define DEVICE_GPU_TEMP_SENSOR
apontando para thermal_zone1 (gpu-thermal IP). A linha GPU TEMPERATURE
da seção GPU INFORMATION agora aparece no ES.
Saída final no R36S:
DEVICE: Game Console R36S
OPERATING SYSTEM: ArchR Linux
DISTRO FAMILY: Arch Linux
CPU TEMPERATURE: 54°
GPU TEMPERATURE: 55°
MESA VERSION: 26.1.3
GPU DRIVER: mali_kbase (legacy blob)
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
systemd-analyze verify reclamava em 3 frentes:
1. StartLimitIntervalSec / StartLimitBurst em [Service] são
silenciosamente ignorados, eles têm que ficar em [Unit].
emustation.service e essway.service tinham os dois na seção errada,
então a proteção contra restart-flood (Restart=always) nunca era
aplicada. avahi-daemon.service tinha um StartLimitInterval (alias
antigo, sem 'Sec') também na seção errada. Movidos para [Unit] em
todos os três e renomeados para o key canônico.
2. sixaxis@.service é um template — instâncias são spawnadas sob
demanda por udev (99-sixaxis.rules põe SYSTEMD_WANTS=sixaxis@%E
{DEVNAME}). enable_service criava um symlink do template puro em
multi-user.target.wants/, dangling porque template sem instância
não roda. Removido o enable_service.
3. emulationstation procurava traduções em /usr/share/locale mas o
ArchR embarca os .mo em /usr/config/locale via userconfig rsync,
então o ES nunca encontrava emulationstation2.mo. Patch no fork ES
(commits 8125fdf, 715ea4b no archr-linux/emulationstation-next):
- main.cpp: prefere /usr/config/locale quando ele existe;
- Platform.cpp: getArchString() lê HW_DEVICE do env (já exportado
pelo profile.d/999-export) em vez de /usr/share/batocera/
batocera.arch que nunca embarcamos;
- Scripting.cpp: aceita /run/emulationstation/scripts além do
legado /var/run/emulationstation/scripts.
archr-fhs-bridges.conf cria /run/emulationstation/scripts vazio em
todo boot para usuário poder dropar hooks (game-start, game-end,
system-selected, ...) sem mkdir manual após cada reset do tmpfs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
audio output X gravava o .asoundrc em /userdata/system/, herdado do
Batocera. Em ArchR a homedir de root é /storage, e o ALSA carrega
$HOME/.asoundrc, então o arquivo nunca chegava em lugar útil. Move
para /storage/.asoundrc.
A linha aplay tentava reproduzir /usr/share/sounds/Mallet.wav, que
não embarcamos. Trocar pelo launch.ogg dos retroarch-assets (já no
rootfs) e silenciar o erro com 2>/dev/null para não derrubar o
comando se a saída de áudio acabou de mudar e o aplay falha.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A varredura via SSH no R36S rodando a 20260624 expôs várias
divergências entre rootfs estagiado e tmpfs/runtime. Cada arquivo
deste commit resolve um gap encontrado na investigação.
archr/tmpfiles.d/z_02_archr-fhs-bridges.conf (NEW):
/var é tmpfs (busybox/system.d/var.mount), então todos os bridges
FHS instalados como symlinks no rootfs eram apagados pelo mount.
Republicar a estrutura via systemd-tmpfiles após var.mount. Resolve
/var/lib/pacman, /var/cache/archr/*, /var/lib/archr/{config,data,
games,backup}, /var/lib/{samba/private,tailscale,bluetooth},
/var/spool/cron, /var/cache/pacman/pkg. Inclui também os targets em
/storage (cron, locpath, tailscale, samba, .local/share, fstrim.run,
journald.conf.d, request-key.d) que estavam ausentes.
ui/emulationstation/package.mk:
ln -sf usava \${INSTALL}/usr/config/... como alvo, vazando o caminho
absoluto do builder para o symlink /etc/emulationstation/es_systems.cfg
no SO final. Trocar pelo path do target.
archr/system.d/timers.target.wants/{rocknix→archr}-report-stats.timer:
Symlink apontava para um arquivo inexistente (rocknix-report-stats);
o timer real chama-se archr-report-stats. Renome.
misc/modules/sources/images/install-{rocknix→archr}.svg:
gamelist.xml já referenciava install-archr.svg; o arquivo se chamava
install-rocknix.svg, quebrando o asset.
emulators/.../gamepads/ROCKNIX→ArchR Gamepad.cfg:
Conteúdo já estava com input_device="ArchR Gamepad"; rename casa o
nome de arquivo com a string de matching.
archr/package.mk + profile.d/005-locale:
LANG="" no SO rodando, todas LC_*=POSIX. glibc gera en_US.UTF-8.
Criar /etc/locale.conf e profile.d que source-a para shells de login
e SSH (que não herdam LANG via systemd env).
sysutils/systemd/scripts/userconfig-setup + freej2me-lr/freej2me.sh:
/storage/jdk caiu como arquivo vazio em algumas builds antigas e
transforma o symlink /opt/jdk em "Not a directory". Saneamento
duplo: a cada boot e antes do download do JDK.
devel/crossguid/package.mk + standalone/hypseus-singe/package.mk:
cmake_install.cmake / crossguid-config.cmake embutiam o BUILD path
do host. Remover dos pacotes target (não rodam em runtime).
tools/pyFDT/package.mk + network/samba/package.mk:
setuptools e waf escrevem o python3 do TOOLCHAIN no shebang dos
entry-points (pydtc, samba-gpupdate). Reescrever pra /usr/bin/python3.
sysutils/systemd/package.mk:
systemd-sysroot-fstab-check é um symlink para
systemd-fstab-generator, que removemos para fora dos generators.
Apagar o link junto. Strip também a regra do legacy.conf que cria
/var/log/README apontando para /usr/share/doc (não embarcamos docs).
sysutils/udevil/package.mk:
/etc/udevil/udevil-user-root.conf é symlink para
/storage/.config/udevil.conf que nunca era populado. Copiar a conf
também para /usr/config/udevil.conf, daí o rsync do userconfig-setup
o semeia no primeiro boot.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Live diagnostic on a R36S running the 20260624 image showed:
archr:~ # gpg --version | head -1
gpg (GnuPG) 1.4.23
archr:~ # gpg --list-packets /usr/share/pacman/keyrings/archr.gpg
:public key packet:
...
unknown algorithm 22
GPG 1.4 is the "classic" branch, frozen before Ed25519 (algorithm 22)
was added in 2.1.x (2014). pacman-key 7.x also calls into gpg with
--check-signatures, a 2.x-only flag. With the ArchR master subkey
being Ed25519 the legacy 1.4 binary can neither parse nor verify the
keyring, so pacman -Sy fails with "no valid user IDs" and "signature
... is invalid" no matter how the user populates the keyring.
Fix the build, not the key. JELOS-era pacman packages cap GnuPG at
1.4.23 because that's the minimal-deps branch; ArchR is now an
Arch-family distro that ships pacman 7 as the user-facing update path,
so it has to ship the modern GnuPG runtime that pacman expects.
New packages:
- libksba 1.8.0
- npth 1.8
- pinentry 1.3.2 (built with --enable-pinentry-tty/curses only;
the GUI variants would pull GTK/Qt that the handheld doesn't have)
Updated:
- gnupg 1.4.23 -> 2.4.8 (latest LTS branch)
Configure trims to the bits pacman uses: gpg + gpgsm + gpgconf.
scdaemon, dirmngr, tofu, wks, gpg-card and the historical 1.4-era
ciphers (idea/cast5/md5/rmd160) are disabled to keep the image lean.
pinentry-tty is the configured pinentry program, since the handheld
has no graphical desktop session to use the other variants.
libassuan, libgcrypt and libgpg-error already live in projects/ArchR/
packages/security/ from earlier work — no new dep tree there.
This unblocks the pacman pipeline on R36S: archr-keyring populate will
parse the Ed25519 master, signature verification will accept the
ArchR-signed archr.db, and pacman -Sy lands at the package list.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Upstream pacman ships pacman-key, makepkg, vercmp and friends as bash
scripts whose shebang is built against the configured sbindir (/usr/sbin
on Arch). Arch ships /usr/sbin as a symlink to /usr/bin via the usrmerge
package, so the shebang resolves fine. ArchR (LibreELEC heritage)
does NOT merge sbin: /usr/sbin is a real directory and bash lives at
/usr/bin/bash only. Result on a fresh boot:
archr:~ # pacman-key --init
-sh: /usr/bin/pacman-key: /usr/sbin/bash: bad interpreter: No such
file or directory
which also makes the pacman-init.service silently miss the keyring
populate step.
Post-install pass that rewrites every "#!/usr/sbin/bash" first line
to "#!/usr/bin/bash" anywhere under ${INSTALL}/usr fixes the lot in
one shot. The pkg.tar.zst we ship in the repo will need the same
treatment, but that's handled at build time too because gen-pacman-repo
packages whatever install_pkg holds.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User reported on a freshly flashed R36S:
archr:~ # pacman
error: failed to initialize alpm library:
(root: /, dbpath: /var/lib/pacman/)
could not find or read directory
The package.mk created /var/lib/pacman as a real directory in
post_makeinstall_target (mkdir -p), then in post_install ran
`ln -sf /storage/.pacman/db ${INSTALL}/var/lib/pacman`. When LINK is
an existing directory, ln -sf does not replace it — it creates
LINK/$(basename TARGET). So the installed image ended up with:
/var/lib/pacman/ ← real, empty dir (rootfs, ro)
/var/lib/pacman/db -> /storage/.pacman/db ← child symlink
Pacman reads dbpath=/var/lib/pacman/ from pacman.conf, looks for
local/ and sync/ inside it, finds nothing, and bails.
Fix: install /var/lib/pacman directly as a symlink to
/storage/.pacman/db in one shot, no intermediate mkdir. Same for
/var/cache/pacman/pkg. Move both into post_makeinstall_target so the
file layout is decided in one place; post_install now only enables
the pacman-init service.
Runtime escape hatch on already-installed systems (since the rootfs
is squashfs-ro and can't be patched):
mount --bind /storage/.pacman/db /var/lib/pacman
mount --bind /storage/.pacman/cache /var/cache/pacman/pkg
This commit fixes the build so the next image flashes correctly.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
awk -F'"' '/^PKG_VERSION/ ...' pulls the literal string out of the
package.mk, but a handful of packages set their version dynamically:
PKG_VERSION="$(get_pkg_version gstreamer)"
The build system resolves that at build time and the install_pkg dir
ends up correctly named (gst-libav-1.27.1/). The packager, though, was
storing the raw "$(get_pkg_version gstreamer)" string, which then
went through the charset filter and became ".get_pkg_version.gstreamer."
in the asset name. Five packages slipped through in the first
repo-dev release with broken names (gst-libav, gst-plugins-good,
vitaquake2-{rogue,xatrix,zaero}-lr).
Detect any '$(' or '${' in the version string and treat it as
"unresolved", which trips the existing dirname-suffix fallback.
27 ArchR packages use this pattern; the fix covers all of them.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
repo-dev now exists on archr-linux/archr-repo with all 543 assets
(535 packages + 8 db artifacts) signed via the master subkey we
generated yesterday. SigLevel PackageOptional DatabaseRequired
matches the SteamOS/EndeavourOS/Arch-ARM model.
Open follow-ups noted in the entry:
- CI hook so the publish is no longer a manual one-hour job after
every build.
- Channel promotion (dev -> next -> stable) when v2.0 final lands.
- gen-pacman-repo version parser fails on 5 packages whose
package.mk uses a placeholder (gstreamer family, vitaquake2-lr
variants); not a runtime blocker but the dirnames are ugly.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
First repo-dev release uploaded 1000/1078 assets before hitting
GitHub's documented per-release limit of 1000 assets. The cap is
hit because every package shipped a paired .sig, doubling the
count without adding meaningful security.
The trust path now flows entirely through the database:
- archr-keyring ships the master public key.
- archr.db.sig proves the db came from the maintainer.
- The db records the SHA256 of every package; pacman re-hashes
after download and refuses mismatches.
To compromise a package the attacker would have to publish a
modified db that lists their hash, which requires the signing
subkey. The per-package .sig was redundant against this attack.
This is the same model Arch Linux ARM, EndeavourOS and SteamOS
use in production.
pacman.conf SigLevel flips from "Required DatabaseOptional" to
"PackageOptional DatabaseRequired"; comment expanded so a future
reader sees the why.
gen-pacman-repo drops the `gpg --detach-sign` step inside
build_one_pkg(); repo-add --sign still signs the db at the end.
Asset count shrinks from 1078 to 543 (535 packages + 8 db
artifacts), which fits comfortably in a single GitHub Release.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The ROCKNIX-sourced rewrite of 003-midgard-refactor-power-init-and-
fixed-unbalanced-run.patch (picked up in 5805267f90) targets a
different kbase tree: it patches platform/devicetree/mali_kbase_runtime_pm.c
expecting `else if (!regulator_is_enabled(...))` on line 38.
Our mali_kbase pin (github.com/archr-linux/mali_kbase @ 422e192b)
does not have that line, so the hunk rejects and mali-bifrost:target
fails to install.
Restore the original 199-line patch that targets platform/meson/
mali_kbase_runtime_pm.c, which is the path that exists in our tree.
This was the file as of commit 5805267f90^ — the working pre-sync
state.
The ROCKNIX cleanup will become applicable when (and if) we move to
the same kbase revision they ship, which would itself be a bigger
upgrade.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
In F7 I added explicit bridge symlinks for hatari and openbor:
ln -sf /storage/.hatari /var/lib/archr/data/hatari
ln -sf /storage/openbor /var/lib/archr/games/openbor
That breaks the build at install time. The F5/F6 umbrella bridges
already turn /var/lib/archr/data and /var/lib/archr/games into
symlinks (-> /storage/.local/share and /storage/roms). When the
hatari ln -sf tries to create a child node under
/var/lib/archr/data, it follows the umbrella symlink, hits
/storage/.local/share which does not exist on the rootfs at build
time, and aborts with "No such file or directory".
Resolution: rely on the umbrella alone. /var/lib/archr/data/hatari
resolves to /storage/.local/share/hatari at runtime through the
umbrella; start_hatari.sh and start_OpenBOR.sh already mkdir -p the
final dir on first launch, so the dir materializes when needed.
Keep the /opt/jdk bridge because there is no /opt umbrella to fall
through.
This is the second clean-build fix on top of the wayland patch
rebase (7eff5d02a6).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The 00-fix-wayland-scanner-pkgconfig.patch was anchored on a context
line ('bindir=' + join_paths(...)) that Wayland removed between 1.24
and 1.25. After our F0 bump to 1.25.0 the unpack step rejected the
patch and aborted the build_compat arm pass.
Pull the rebased patch from ROCKNIX (commit a9e464274a in their
graphics/display sync) where the same context shift was already
resolved: the bindir line is gone, the filebase line stays.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three bugs caught while smoke-testing against an existing
build.ArchR-RK3326.aarch64/install_pkg tree:
1. BUILD_DIR auto-detection glob did not include the trailing arch
suffix, so build.ArchR-RK3326.aarch64 never matched. Now matches
build.*-RK3326*aarch64*.
2. Version sanitization used `echo | tr -c '[charset]' '.'` which
turns the trailing newline into a stray '.', producing versions
like "1.0.8." that pacman refuses. Swapped to printf.
3. Package layout was wrong for pacman 7 repo-add:
- .PKGINFO must be the FIRST entry in the tar (pacman streams it).
- No "./" prefix on file names (matches makepkg output).
- .PKGINFO needs `pkgbase` and `xdata = pkgtype=pkg` lines, not
just `pkgname`.
Rewrote the packing block to assemble an explicit file list with
.PKGINFO first, then tar -T.
Also: install_pkg name extraction is more robust now — sed strips
both 40-char git hashes and semver suffixes to recover the real
package name, and the package.mk lookup uses find rather than
literal globbing so packages nested at any depth are found.
Smoke test confirms repo-add accepts the resulting archive, signs
archr.db with the configured signer, and emits the expected
symlinks archr.db -> archr.db.tar.gz.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Master generated 2026-06-23 offline (ed25519 cert-only with ed25519
sign subkey expiring 2028-06-23). Private master lives on encrypted
cold storage; the signer subkey is on the build workstation only.
Revocation certificate kept offline in two physical locations.
Fingerprint: 0CB282379EBB394EF380AEB98A762D5706C602A1
archr.gpg is the binary public keyring that pacman-key --populate archr
walks; archr-trusted gives the master full ownertrust (level 4) so
packages signed by its subkey are accepted; archr-revoked stays empty
until a key is actually revoked.
archr-keyring/package.mk already auto-detects these files (instead of
the empty placeholders it shipped before) and includes them in the
image. With the keyring populated, the next gen-pacman-repo run with
SIGNER set will produce a properly signed archr.db and per-package
.sig files that ArchR clients can verify.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Decision: pacman repo lives on GitHub Releases at
archr-linux/archr-repo. No VPS, no repo.arch-r.io. Google Drive stays
out of runtime (backup/archive only). Cloudflare R2 fallback deferred.
Detail in docs/release-policy.md.
archr-update rewritten end-to-end:
- 188 lines of dead POST-to-update.arch-r.io code replaced by an
87-line wrapper around pacman -Syu. The POST endpoint never existed
so there is no legacy compat to preserve.
- subcommands: check, update, info. system.cfg "updates.branch" maps
to repo-stable / repo-next / repo-dev tags on archr-linux/archr-repo;
the mirrorlist is rewritten on every invocation so channel switches
are immediate.
pacman.conf rebuilt around a single [archr] repo (Arch Linux ARM
upstream removed). SigLevel starts at "Required DatabaseOptional"
during bootstrap; will tighten to "Required" once the production
master key signs the .db.
pacman-init reachability test points at github.com and the keyring
populate target is "archr" instead of "archlinuxarm".
archr-keyring repurposed: the three archlinuxarm keyring files are
removed; package.mk now expects archr.gpg / archr-trusted /
archr-revoked under keys/ and ships empty placeholders until the real
ArchR master key is generated.
scripts/repo/gen-pacman-repo + README: take the build.*-RK3326 tree
that "make docker-RK3326" leaves behind, package each install_pkg/<x>
as a .pkg.tar.zst with synthesized .PKGINFO, run repo-add to build
archr.db, optionally GPG-sign everything. Emits a `gh release create`
command for the publish step. CI hook left as a follow-up.
docs/improvements.md 2.1 marked partial: client and build script are
ready; what blocks the first usable release is generating the GPG
master key, creating archr-linux/archr-repo on GitHub, and one manual
publish for the repo-dev tag to validate the end-to-end loop.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Quirks pruning done in 7644ce26d3 (352 files, 8037 lines). Splash
rename and runemu.sh refactor reclassified as organic follow-ups:
- splash sed stays until upstream archr-splash repo finishes the
internal rename.
- runemu.sh is 578 lines (not 1500+ as the original entry guessed);
refactor still pays in maintainability but is not a blocker.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
projects/ArchR/packages/hardware/quirks/ shipped 50 device dirs and
10 platform dirs inherited from JELOS/ROCKNIX. ArchR only ever
supports RK3326 (one platform), and the per-device quirks are
selected at runtime by reading /sys/firmware/devicetree/base/archr,device_switch/this
— a name that can only match a DTB we compiled in. The 42 device
dirs without a matching DTB and the 9 platform dirs for SoCs we
don't have (H700, RK3399, RK3566, RK3588, S922X, SDM845, SM8250,
SM8550, SM8650) were unreachable code.
Keep: 14 device dirs and 1 platform (RK3326). All correspond to a
DTS file in projects/ArchR/devices/RK3326/linux/dts/rockchip/ so
they can actually be selected at boot.
Cross-references to the dead platforms in other scripts (case
${DEVICE} in RK3399) ...; case ${DEVICE} in SM8250) ...) stay
as harmless dead branches that never trigger when DEVICE=RK3326;
cleaning those up is in scope for a follow-up sweep.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Section 2.2 now reflects what shipped: auditoria + 22 bridges + 7 vars
+ man page + 7 phases all marked done. Open item left explicit: the
1625 hardcoded /storage refs in legacy scripts continue to work via
compat and refactor organically.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>