Commit Graph

51658 Commits

Author SHA1 Message Date
Douglas Teles 33014076b4 Stop building panel overlays at image-build time
Strategic continuation of the flasher refactor: the SO no longer
generates or ships pre-built panel DTBOs. Users generate their own
mipi-panel.dtbo at https://arch-r.io/overlay-generator/ and drop it
into /flash/overlays/.

- config/overlays/README.txt rewritten with the same instruction in
  6 languages (pt-BR, en, fr, es, zh, ru), one per line.
- u-boot/package.mk: removed the mipi-generator invocation and the
  per-SUBDEVICE overlays_{original,clone,soysauce} install blocks.
  Only the generic overlays/ dir (README) is shipped under
  /usr/share/bootloader/.
- bootloader/mkimage: removed the RK3326-specific overlays_${SUBDEVICE}
  and overlays_soysauce branches; the generic overlays/ copy at the
  end of mkimage_dtb now covers RK3326 too.
- Deleted config/mipi-generator/ (generator.sh + archr-dtbo.py) and
  config/archr-dts/ (vendor DTBs that were only consumed by the
  generator).

Net: -8503 LOC + ~120 binary DTBs removed from the tree.
2026-06-24 12:57:02 -03:00
Douglas Teles 226cea083e mipi-generator: SDCLONE flag para R36S Clone sem default sound card
Issue archr-linux/Arch-R#35 (R36S Clone V20 batch 2551 sem áudio).

A DTS base rk3326-gameconsole-eeclone.dts NÃO inclui r3xs.dtsi —
diferente de rk3326-gameconsole-r36s.dts (original) e
rk3326-gameconsole-soysauce.dts (Y3506). Como r3xs.dtsi é onde o
node `rk817-sound` padrão fica ativo, o eeclone vai pro kernel só
com as duas variantes `rk817-sound-amplified` e `rk817-sound-simple`,
ambas com `status="disabled"`.

Para R36S Clone V20+ o vendor BSP 4.4 não publica `spk-con-gpio` nem
`rockchip,codec/spk-ctl-gpios` no rk817-sound (o widget de speaker
nem aparece no DTB), então a detecção atual do gerador caía no
ramo "keep default" e o overlay ficava sem habilitar nenhum sound
card. Resultado: `aplay -l` retornava "no soundcards found" em todo
clone V20 / V21.

generator.sh agora emite `sd_prefix="SDCLONE"` para subdevice=clone
(antes só emitia SDORIG para original/soysauce). archr-dtbo.py
trata SDCLONE como sinal de que a base DTS não tem default sound
card ativo e força o `rk817-sound-amplified` como fallback safe —
caso clone V20+ que carrega amp externo via GPIO não exposto no
DTB. Clones sem amp explícito (raros) podem usar a variante _SRs
para forçar `simple` ou o flag NAm para `spko-direct`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-24 12:30:17 -03:00
Douglas Teles e1c50c04f9 RTL8188EUS: out-of-tree driver para resolver auth fail (#19)
Issue archr-linux/Arch-R#19: dongles USB com chipset RTL8188EUS (TP-
Link TL-WN722N v3, Edimax EW-7811Un, vários no-name) escaneiam SSIDs
mas falham na autenticação WPA2 — handshake 4-way não completa, ESS
fica em "Connecting..." até timeout.

Histórico: tentamos antes o ajuste de IWD (UseDefaultInterface,
AddressRandomization), bump IWD 3.9 → 3.10, e o patch upstream
rtl8xxxu de firmware upload block size 128 → 196 (`projects/ArchR/
packages/linux/patches/6.12-LTS/0050-wifi-rtl8xxxu-Fix-RTL8188EU-
firmware-upload-block-size.patch`). Nenhum desses resolveu para os
usuários que reportaram — o rtl8xxxu in-tree continuamente trava no
handshake nesse chip específico.

A solução conhecida em outras distros (Arch, Debian, Manjaro, Kali,
TWRP, Postmarket) é usar o fork `aircrack-ng/rtl8188eus` mantido
especificamente para esse chip. Ele tem o handshake testado com iwd
e wpa_supplicant.

Pacote adicionado:
  projects/ArchR/packages/linux-drivers/RTL8188EUS/
    ├── package.mk            (build out-of-tree 8188eu.ko)
    ├── modprobe.d/
    │   └── 00-rtl8188eus.conf (tunables: LED on, no double MAC random)
    └── udev.d/
        └── 99-rtl8188eus.rules  (unbind rtl8xxxu da interface USB
                                   específica nos USB IDs do 8188EUS
                                   e force-load 8188eu)

A udev rule cobre os IDs comuns:
  0bda:0179 / 0bda:8179 / 0bda:8189 — Realtek de fábrica
  7392:7811                          — Edimax EW-7811Un
  056e:4008                          — Elecom WDC-150SU2M

Não fazemos blacklist global do rtl8xxxu — ele continua sendo o
driver de RTL8192EU, RTL8723BU, RTL8188CU etc. (que funcionam bem
com ele). Só desbinda do device USB específico quando um 8188EUS
aparece e load o 8188eu in its place.

RTL8188EUS adicionado a ADDITIONAL_DRIVERS em projects/ArchR/devices/
RK3326/options para que a build inclua o módulo no rootfs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-24 12:11:20 -03:00
Douglas Teles 0689a89c47 u-boot: boot.ini usa LABEL= em vez de /dev/mmcblkN paths
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>
2026-06-24 12:02:09 -03:00
Douglas Teles e48e9675a9 wifictl: corrigir trava de conexão com senha/SSID especiais
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>
2026-06-24 11:50:04 -03:00
Douglas Teles 44dfbad623 setrootpass: short-circuit via sha512crypt sem novo artefato sensível
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>
2026-06-24 11:40:02 -03:00
Douglas Teles e8fd3a6c43 perf: corrigir gaps detectados via SSH no R36S
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>
2026-06-24 11:37:36 -03:00
Douglas Teles e696461f7d 001-functions + archr-automount: corrigir refs herdadas
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>
2026-06-24 11:14:38 -03:00
Douglas Teles e90a0708c8 units + scripts: corrigir bugs herdados de JELOS no boot
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>
2026-06-24 11:09:58 -03:00
Douglas Teles fd1398b472 System Information: corrigir lacunas e adicionar Mesa/Arch info
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>
2026-06-24 10:31:54 -03:00
Douglas Teles abba87d061 ES + units: corrigir warnings do systemd-analyze e localizar .mo
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>
2026-06-24 10:18:44 -03:00
Douglas Teles fcc56ec635 archr-config: corrigir paths Batocera no comando audio output
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>
2026-06-24 09:58:46 -03:00
Douglas Teles d06e18a2ad gaps: ampla varredura de bugs herdados + pré-pacman repo-stable
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>
2026-06-24 02:44:45 -03:00
Douglas Teles 199e9a5ee4 security: bump gnupg to 2.4.8, add libksba/npth/pinentry deps
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>
2026-06-24 01:59:24 -03:00
Douglas Teles cceafdaca0 pacman: rewrite /usr/sbin/bash shebangs to /usr/bin/bash
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>
2026-06-24 01:51:41 -03:00
Douglas Teles 6ce926d537 pacman: install /var/lib/pacman as symlink, not dir + child symlink
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>
2026-06-24 01:30:02 -03:00
Douglas Teles 2bb9ebb50a gen-pacman-repo: fall back to dirname when PKG_VERSION is a shell expr
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>
2026-06-24 00:32:18 -03:00
Douglas Teles 190469075f docs: 2.1 marked complete after the first repo-dev release
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>
2026-06-24 00:27:34 -03:00
Douglas Teles 7addeb691a pacman: drop per-package signing, sign only the repo db
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>
2026-06-23 23:27:27 -03:00
Douglas Teles be19e9ec47 mali-bifrost: revert 003 patch to the pre-sync ArchR version
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>
2026-06-23 21:03:58 -03:00
Douglas Teles 70fb40de43 archr: drop F7 hatari/openbor bridges, fall through umbrellas
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>
2026-06-23 20:27:23 -03:00
Douglas Teles 7eff5d02a6 wayland: rebase pkgconfig patch for 1.25.0
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>
2026-06-23 17:59:44 -03:00
Douglas Teles 41d376a029 gen-pacman-repo: fix package layout for pacman 7 repo-add
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>
2026-06-23 17:43:08 -03:00
Douglas Teles 43e464525f archr-keyring: ship the production ArchR master public key
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>
2026-06-23 17:35:06 -03:00
Douglas Teles b6ceea9347 2.1: pacman as real update mechanism (client side)
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>
2026-06-23 17:03:35 -03:00