11 Commits

Author SHA1 Message Date
Douglas Teles 9b55f926c0 Update README for mainline kernel and overlay architecture
Rewrite to reflect current state: kernel 6.12.61 mainline LTS, board DTB
auto-selection via SARADC, panel overlay system (20 panels), two image
variants (original + clone), Flasher app for panel selection, updated
boot flow, build pipeline, and project structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:23:15 -03:00
Douglas Teles b36a333523 Add Flasher app specification
Complete spec for the Arch R Flasher desktop app: console type selection,
panel identification wizard, image download from GitHub releases, SD card
flashing with panel overlay auto-configuration. Supports Windows/macOS/Linux.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:23:03 -03:00
Douglas Teles c8e7fe99e9 Add ES Tools menu scripts and gptokeyb configs (WIP)
Interactive tool scripts for EmulationStation's OPTIONS menu at /opt/system/:
system-info, wifi-setup, bluetooth-setup, performance-mode, suspend-mode,
usb-mode, factory-reset. Uses shared menu-lib.sh with fbcon rendering.

Gamepad configs: default.gptk (RetroArch), tools.gptk (menu navigation
with D-pad arrows, A=enter, B=escape).

Note: scripts need further testing on hardware — left disabled for now.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:22:49 -03:00
Douglas Teles 06dc2d16f3 Add system scripts, services, and boot splash
System daemons: hotkeys (volume/brightness), automount, bluetooth agent,
memory manager, sleep/suspend, USB gadget mode, save-config persistence.

Boot splash: initramfs SVG renderer (fbsplash + svg_parser) for 0.7s splash.

Panel tools: generate-panel-dtbos.sh rewrite, convert-panel.py for ROCKNIX
panel data extraction, archr-dtbo.py for runtime overlay management.

Input: archr-gptokeyb.c gamepad-to-keyboard mapper via uinput.

Launch wrappers: emulationstation.sh and retroarch-launch.sh updated for
KMS/DRM + Mesa 26 Panfrost environment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:22:30 -03:00
Douglas Teles 8650d940e2 Migrate to mainline kernel 6.12.61 + board/overlay architecture
Major architecture change: move from BSP kernel 6.6 with pre-merged panel
DTBs to mainline kernel 6.12.61 LTS with separated board DTBs + panel
overlays.

- Board DTB = hardware profile (GPIOs, PMIC, joypad, audio). 16 boards.
  Auto-selected by U-Boot via SARADC ADC reading (hwrev).
- Panel overlay = display init sequence. 20 panels. Applied at boot time
  via boot.ini fdt apply.
- Two image variants: original (a_boot.ini) and clone (b_boot.ini)
- Kernel cross-compiles from x86 host (no ARM chroot needed)
- Initramfs boot splash with SVG rendering at 0.7s
- Out-of-tree joypad driver (singleadc-joypad) for clone boards
- Panel generic-dsi driver with archr,generic-dsi compatible

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:20:09 -03:00
Douglas Teles 70342ca457 ROADMAP: detail beta1.2 system changes and update last-updated
Input merger, RetroArch tuning, panel ordering, no-panel variant,
mirror list, boot.ini autodetect.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 02:24:00 -03:00
Douglas Teles b6eff2e748 ROADMAP: beta1.1 pre-merged DTBs + beta1.2 Flasher diary entries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 02:20:21 -03:00
Douglas Teles 9c30a92cab Add variant-sync service, update mirrors, native DTB names
- build-rootfs.sh: archr-variant-sync.service copies /boot/variant
  to /etc/archr/variant on first boot (for Flasher no-panel images).
  Runs once via ConditionPathExists, Before=panel-detect.service
- build-rootfs.sh: update ALARM mirror list (remove eu.mirror/403,
  add de4/gr/tw/tw2/ca.us, reorder Americas first for Brazil)
- build-image.sh: no-panel variant uses native DTB names
  (kernel-panel4.dtb, kernel-clone8.dtb) instead of inherited
  kernel-original.dtb / kernel-clone.dtb

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 00:11:28 -03:00
Douglas Teles cbc39b8802 Add no-panel universal image variant for Flasher app
Third build variant (--variant no-panel) that includes all 18 panel
DTBs for both original and clone hardware. Designed for the future
Arch R Flasher app to inject the correct kernel.dtb at flash time.

- boot.ini: auto-detect root device from mmcdev (no more __ROOTDEV__)
- build-image.sh: no-panel uses mainline U-Boot, copies all DTBs
- panel-detect.py: wizard disabled for no-panel variant
- build-all.sh: generates third image (ArchR-R36S-no-panel)
2026-03-01 22:11:37 -03:00
Douglas Teles 87719600d2 Update README: split panel list by variant, fix panel.txt format
Separate panel tables into Original (6 panels) and Clone (12 panels)
with numerical ordering and beep counts. Update manual selection to
use PanelDTB= format (pre-merged DTBs). Note: ordering available
from beta1.2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:54:37 -03:00
Douglas Teles baaeb69a19 Input merger, RetroArch tuning, panel ordering fix
- input-merge daemon: combines gpio-keys + adc-joystick into single
  virtual "Arch R Gamepad" via uinput so RetroArch sees one device
  (fixes analog sticks ignored due to max_users=1)
- retroarch-launch.sh: start/stop input-merge, VT blank on launch
- retroarch.cfg: ROCKNIX-based tuning (48kHz audio, triple buffer,
  late input polling, autosave, core options path)
- retroarch-core-options.cfg: per-core tuning from ROCKNIX RK3326
  (mupen64plus, pcsx_rearmed, flycast, mame2003-plus, melonds, etc.)
- archr-gamepad.cfg: autoconfig for merged virtual device
- panel-detect.py: panels in numerical order (beep count = position),
  default_panel searches by empty dtb_name instead of panels[0]
- build-rootfs.sh: compile input-merge, install core options and
  autoconfig, add input-merge and kill to sudoers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:48:49 -03:00
142 changed files with 66903 additions and 1836 deletions
+17
View File
@@ -3,6 +3,20 @@ output/
# Kernel and bootloader source (cloned during build)
kernel/src/
# Kernel module build artifacts (compiled .ko/.o are not source)
kernel/drivers/**/*.o
kernel/drivers/**/*.ko
kernel/drivers/**/*.mod
kernel/drivers/**/*.mod.c
kernel/drivers/**/*.mod.o
kernel/drivers/**/*.cmd
kernel/drivers/**/Module.symvers
kernel/drivers/**/modules.order
kernel/drivers/**/.module-common.o
# Compiled DTBs in source tree (use output/boot/dtbs/ instead)
kernel/dts/*.dtb
bootloader/src/
# Build cache
@@ -88,3 +102,6 @@ bootloader/u-boot-r36s-working/extracted_dtb_*.dtb
# Clone U-Boot build output
bootloader/u-boot-clone-build/
# Others
feedback/
+610
View File
File diff suppressed because it is too large Load Diff
+150 -120
View File
@@ -8,22 +8,32 @@
>
> Leve como uma pluma.
Arch R is a custom Linux distribution built from scratch for the R36S handheld gaming console (RK3326 SoC, Mali-G31 GPU, 640x480 MIPI DSI display). It supports all R36S variants and clones with 18 different display panels.
Arch R is a custom Linux distribution built from scratch for the R36S handheld gaming console (RK3326 SoC, Mali-G31 GPU, 640x480 MIPI DSI display). It supports all R36S variants and clones — 16 board profiles and 20 display panels.
## Features
- **Kernel 6.6.89** (Rockchip BSP) — custom DTS with joypad, panel init sequences, audio, USB OTG
- **Kernel 6.12.61** (Mainline LTS) — board auto-detection via SARADC, 16 board DTBs, panel overlays
- **Mesa 26 Panfrost** — open-source GPU driver, GLES 1.0/2.0/3.1, no proprietary blobs
- **EmulationStation** (fcamod fork) — 78fps stable, GLES 1.0 native rendering
- **RetroArch 1.22.2** — KMS/DRM + EGL, 18+ cores pre-installed
- **19-second boot** — U-Boot logo → kernel → systemd EmulationStation
- **Full audio** — ALSA, speaker + headphone auto-switch, volume hotkeys
- **Battery monitoring** — LED warning, capacity/voltage/temp reporting
- **Multi-panel support** — 18 panel DTBOs (6 original R36S + 12 clones)
- **19-second boot** — initramfs splash at 0.7s, systemd to EmulationStation
- **Full audio** — ALSA, speaker + headphone auto-switch, volume/brightness hotkeys
- **Battery monitoring** — capacity/voltage reporting, LED warning
- **Multi-panel support** — 20 panel overlays (7 original + 13 clone variants)
- **Two images** — Original R36S and Clone boards, both auto-detect hardware
## Quick Start — Flash a Pre-built Image
## Quick Start
Download the latest image from [Releases](../../releases), then:
Download the latest images from [Releases](../../releases):
- **`ArchR-R36S-*.img.xz`** — for genuine R36S, OGA, OGS, RG351V/M, Chi, R33S
- **`ArchR-R36S-clone-*.img.xz`** — for K36 clones, RGB20S, RGB10X, XU-Mini-M, R36Max
### Using Arch R Flasher (recommended)
Download the [Arch R Flasher](https://github.com/archr-linux/archr-flasher) app, select your console type and display panel, and flash directly. The Flasher handles image download, panel overlay selection, and SD card writing.
### Manual Flash
```bash
xz -d ArchR-R36S-*.img.xz
@@ -31,7 +41,16 @@ sudo dd if=ArchR-R36S-*.img of=/dev/sdX bs=4M status=progress
sync
```
Insert the SD card into your R36S and power on. First boot creates a ROMS partition automatically.
After flashing, mount the BOOT partition and copy your panel overlay:
```bash
sudo mount /dev/sdX1 /mnt
sudo cp /mnt/overlays/panel4-v22.dtbo /mnt/overlays/mipi-panel.dtbo
sudo umount /mnt
sync
```
Insert the SD card and power on. The correct board DTB is selected automatically.
## Building from Source
@@ -40,7 +59,6 @@ Insert the SD card into your R36S and power on. First boot creates a ROMS partit
- **OS:** Ubuntu 22.04+ (or any Linux with QEMU user-static support)
- **Disk:** 30GB+ free space
- **RAM:** 4GB+ recommended
- **Time:** ~3-4 hours (first build), ~1 hour (incremental)
### Install Dependencies
@@ -66,21 +84,22 @@ sudo apt install -y \
### Build Everything
```bash
git clone --recurse-submodules https://github.com/user/Arch-R.git
git clone --recurse-submodules https://github.com/archr-linux/Arch-R.git
cd Arch-R
# Full build (kernel + rootfs + mesa + ES + retroarch + panels + image)
# Full build: kernel + rootfs + mesa + ES + retroarch + panels + both images
sudo ./build-all.sh
```
The flashable image will be at `output/images/ArchR-R36S-YYYYMMDD.img.xz` (~860MB compressed).
Output: `output/images/ArchR-R36S-YYYYMMDD.img.xz` and `ArchR-R36S-clone-YYYYMMDD.img.xz`
### Build Individual Components
```bash
sudo ./build-all.sh --kernel # Kernel only (~10 min)
sudo ./build-all.sh --rootfs # Rootfs + Mesa + ES + RetroArch (~3 hours)
sudo ./build-all.sh --image # Image assembly only (~2 min)
sudo ./build-all.sh --kernel # Kernel + initramfs (~10 min, cross-compile)
sudo ./build-all.sh --rootfs # Rootfs + Mesa + ES + RetroArch (~3 hours, QEMU chroot)
sudo ./build-all.sh --uboot # U-Boot (~2 min)
sudo ./build-all.sh --image # Image assembly only (~2 min per variant)
sudo ./build-all.sh --clean # Remove all build artifacts
```
@@ -88,53 +107,63 @@ sudo ./build-all.sh --clean # Remove all build artifacts
```
build-all.sh
├── build-kernel.sh # Cross-compile kernel 6.6.89 (~10 min)
├── build-rootfs.sh # Arch Linux ARM rootfs in QEMU chroot (~45 min)
├── build-mesa.sh # Mesa 26 with Panfrost + GLES 1.0 (~30 min)
├── build-emulationstation.sh # ES-fcamod with 21 patches (~20 min)
├── build-retroarch.sh # RetroArch + cores (~40 min)
├── generate-panel-dtbos.sh # 18 panel DTBO overlays (~10 sec)
── build-image.sh # Assemble SD card image (~2 min)
├── build-initramfs.sh # Boot splash (SVG rendering, ~648KB)
├── build-kernel.sh # Cross-compile kernel 6.12.61 (~10 min)
├── build-rootfs.sh # Arch Linux ARM in QEMU chroot (~45 min)
├── build-mesa.sh # Mesa 26 Panfrost + GLES 1.0 (~30 min)
├── build-emulationstation.sh # ES-fcamod with patches (~20 min)
├── build-retroarch.sh # RetroArch + cores (~40 min)
── generate-panel-dtbos.sh # 20 panel overlays (~10 sec)
├── build-uboot.sh # BSP U-Boot for original boards
├── build-uboot-clone.sh # Mainline U-Boot for clone boards
└── build-image.sh # SD card image (×2 variants)
```
All builds happen inside a QEMU aarch64 chroot — no cross-compilation issues.
## Project Structure
```
Arch-R/
├── build-all.sh # Master build orchestrator
├── build-kernel.sh # Kernel compilation
├── build-rootfs.sh # Root filesystem (Arch Linux ARM + services)
├── build-mesa.sh # Mesa 26 GPU driver
├── build-emulationstation.sh # EmulationStation frontend
├── build-retroarch.sh # RetroArch + cores
├── build-image.sh # SD card image assembly
├── build-all.sh # Master build orchestrator
├── build-kernel.sh # Kernel 6.12.61 cross-compilation
├── build-initramfs.sh # Initramfs with boot splash
├── build-rootfs.sh # Root filesystem (Arch Linux ARM)
├── build-mesa.sh # Mesa 26 GPU driver
├── build-emulationstation.sh # EmulationStation frontend
├── build-retroarch.sh # RetroArch + cores
├── build-uboot.sh # BSP U-Boot (original boards)
├── build-uboot-clone.sh # Mainline U-Boot (clone boards)
├── build-image.sh # SD card image assembly
├── config/
│ ├── archr-6.6-r36s.config # Kernel config fragment (393 options)
│ ├── boot.ini # U-Boot fallback boot script
│ ├── es_systems.cfg # EmulationStation system definitions
│ ├── retroarch.cfg # RetroArch base configuration
│ ├── asound.conf # ALSA audio configuration
── autoconfig/ # RetroArch controller autoconfig
│ ├── linux-archr-base.config # Kernel config (mainline 6.12)
│ ├── a_boot.ini # Boot script — original variant
│ ├── b_boot.ini # Boot script — clone variant
│ ├── es_systems.cfg # EmulationStation systems
│ ├── retroarch.cfg # RetroArch base config
── asound.conf # ALSA audio config
│ ├── gptokeyb/ # Gamepad-to-keyboard mappings
│ ├── udev/ # udev rules (automount, USB gadget)
│ └── autoconfig/ # RetroArch controller autoconfig
├── kernel/
── dts/
├── rk3326-gameconsole-r36s.dts # Custom R36S device tree
│ └── R36S-DTB/ # Reference panel DTBs
── dts/archr/ # Board device trees (16 boards)
└── drivers/ # Out-of-tree joypad driver
├── patches/ # Kernel patches (mainline + device)
├── scripts/
│ ├── emulationstation.sh # ES launch wrapper
│ ├── retroarch-launch.sh # RetroArch launch wrapper
│ ├── archr-hotkeys.py # Volume/brightness hotkey daemon
│ ├── first-boot.sh # First boot setup (ROMS partition)
│ ├── generate-panel-dtbos.sh # Panel overlay generator
│ ├── pmic-poweroff # PMIC shutdown handler
── vlc-stub.c # VLC stub library for ES build
│ ├── emulationstation.sh # ES launch wrapper
│ ├── retroarch-launch.sh # RetroArch launch wrapper
│ ├── archr-hotkeys.py # Volume/brightness hotkey daemon
│ ├── archr-init.c # Initramfs splash (static binary)
│ ├── archr-gptokeyb.c # Gamepad-to-keyboard mapper
│ ├── panel-detect.py # Panel detection
── generate-panel-dtbos.sh # Panel overlay generator
│ ├── pmic-poweroff # PMIC shutdown handler
│ └── opt-system/ # ES Tools menu scripts
├── bootloader/
│ └── u-boot-r36s-working/ # Pre-built U-Boot binaries
│ └── u-boot-rk3326/ # U-Boot source (submodule)
├── prebuilt/
│ └── cores/ # Pre-built RetroArch cores (FBNeo, MAME, N64, PSP)
├── ArchR.png # Boot logo source
── ROADMAP.md # Development diary
│ └── cores/ # Pre-built RetroArch cores
├── ArchR.png # Boot logo
── ROADMAP.md # Development diary
└── FLASHER.md # Flasher app specification
```
## Hardware
@@ -144,103 +173,104 @@ Arch-R/
| SoC | Rockchip RK3326 (4x Cortex-A35 @ 1.5GHz) |
| GPU | Mali-G31 Bifrost (Mesa Panfrost, 600MHz) |
| RAM | 1GB DDR3L (786MHz) |
| Display | 640x480 MIPI DSI (18 panel variants) |
| Display | 640x480 MIPI DSI (20 panel variants) |
| Audio | RK817 codec, speaker + headphone jack |
| Storage | MicroSD (boot + rootfs + ROMS) |
| Storage | MicroSD (BOOT + rootfs + ROMS) |
| Controls | D-pad, ABXY, L1/L2/R1/R2, dual analog sticks |
| Battery | 3200mAh Li-Po (RK817 charger) |
| USB | OTG with host mode (VBUS power on GPIO0_B7) |
| USB | OTG with host/gadget mode switching |
## Supported Panels
## Architecture
Arch R supports 18 display panels via DTBO overlays. The default image boots with **Panel 4-V22** (the most common R36S panel).
Arch R separates **board configuration** from **panel configuration**:
### Panel Auto-Detection
- **Board DTB** = hardware profile (GPIOs, PMIC, joypad, audio codec). One per board variant. Selected automatically by U-Boot via SARADC ADC reading.
- **Panel overlay** = display init sequence and timings. One per panel type. Applied on top of the board DTB at boot time.
On first boot, Arch R runs a **panel detection wizard** that guides you through selecting your display panel:
This means the same image works on all boards of a variant — only the panel overlay needs to match your specific display.
1. **If your screen works** (you see text on screen): press **A** to confirm the current panel
2. **If your screen is black** (wrong panel): listen for audio beeps and use buttons to navigate:
- Each panel plays a different number of beeps (1 beep = first panel, 2 beeps = second, etc.)
- Press **B** to skip to the next panel
- Press **A** to confirm (you'll hear 3 rapid beeps)
- The system reboots with the correct panel applied
### Supported Boards
Your selection is saved permanently. To reset it later, **hold X during boot**.
| Board | DTB | Image |
|-------|-----|-------|
| R36S (original) | rk3326-gameconsole-r36s | Original |
| Odroid Go Advance | rk3326-odroid-go2 | Original |
| Odroid Go Advance v1.1 | rk3326-odroid-go2-v11 | Original |
| Odroid Go Super | rk3326-odroid-go3 | Original |
| Anbernic RG351V | rk3326-anbernic-rg351v | Original |
| Anbernic RG351M | rk3326-anbernic-rg351m | Original |
| GameForce Chi | rk3326-gameforce-chi | Original |
| R33S | rk3326-gameconsole-r33s | Original |
| MagicX XU10 | rk3326-magicx-xu10 | Original |
| K36 / R36S clone | rk3326-gameconsole-r36max | Clone |
| EE clone | rk3326-gameconsole-eeclone | Clone |
| Powkiddy RGB10 | rk3326-powkiddy-rgb10 | Clone |
| Powkiddy RGB10X | rk3326-powkiddy-rgb10x | Clone |
| Powkiddy RGB20S | rk3326-powkiddy-rgb20s | Clone |
| MagicX XU-Mini-M | rk3326-magicx-xu-mini-m | Clone |
| BatLexp G350 | rk3326-batlexp-g350 | Clone |
### Panel List
### Supported Panels
| # | Panel | Notes |
|---|-------|-------|
| 1 | **Panel 4-V22** *(default)* | Most common (~60% of R36S units) |
| 2 | Panel 3-V20 | V20 board marking |
| 3 | Panel 5-V22 Q8 | V22 Q8 variant |
| 4 | Clone Panel 8 | ST7703 (G80CA-MB) |
| 5 | Panel 0 | Early R36S units |
| 6 | Panel 1-V10 | V10 board marking |
| 7 | Panel 2-V12 | V12 board marking |
| 8 | Clone Panel 1 | ST7703 |
| 9 | Clone Panel 3 | NV3051D |
| 10 | Clone Panel 7 | JD9365DA |
| 11 | Clone Panel 9 | NV3051D |
| 12 | Clone Panel 10 | ST7703 variant |
| 13 | Clone Panel 2 | ST7703 |
| 14 | Clone Panel 4 | NV3051D |
| 15 | Clone Panel 5 | ST7703 |
| 16 | Clone Panel 6 | NV3051D |
| 17 | R36 Max | 720x720 ST7703 |
| 18 | RX6S | NV3051D variant |
#### Original R36S (7 panels)
| Panel | Overlay file | Controller | Notes |
|-------|-------------|------------|-------|
| Panel 0 | panel0.dtbo | ST7703 | Early R36S units |
| Panel 1 | panel1.dtbo | ST7703 | V10 board |
| Panel 2 | panel2.dtbo | ST7703 | V12 board |
| Panel 3 | panel3.dtbo | ST7703 | V20 board |
| Panel 4 | panel4.dtbo | ST7703 | V22 board |
| Panel 4-V22 | panel4-v22.dtbo | ST7703 | Most common (~60%) |
| Panel 5 | panel5.dtbo | ST7703 | V22 Q8 variant |
R46H (1024x768): `r46h.dtbo`
#### Clone R36S (13 panels)
| Panel | Overlay file | Controller | Notes |
|-------|-------------|------------|-------|
| Clone 1 | clone_panel_1.dtbo | ST7703 | |
| Clone 2 | clone_panel_2.dtbo | ST7703 | |
| Clone 3 | clone_panel_3.dtbo | NV3051D | |
| Clone 4 | clone_panel_4.dtbo | NV3051D | |
| Clone 5 | clone_panel_5.dtbo | ST7703 | |
| Clone 6 | clone_panel_6.dtbo | NV3051D | |
| Clone 7 | clone_panel_7.dtbo | JD9365DA | |
| Clone 8 | clone_panel_8.dtbo | ST7703 | G80CA — most common |
| Clone 9 | clone_panel_9.dtbo | NV3051D | |
| Clone 10 | clone_panel_10.dtbo | ST7703 | |
| R36 Max | r36_max.dtbo | ST7703 | 720x720 |
| RX6S | rx6s.dtbo | NV3051D | |
### Manual Panel Selection
If you prefer to set the panel manually (e.g., you know which panel you have from ArkOS/dArkOS):
**Step 1 — Mount the BOOT partition on your PC**
Mount the BOOT partition and copy the correct overlay as `mipi-panel.dtbo`:
```bash
lsblk
sudo mount /dev/sdX1 /mnt
```
**Step 2 — Create panel.txt**
# Example: set Panel 4-V22 (most common original R36S panel)
sudo cp /mnt/overlays/panel4-v22.dtbo /mnt/overlays/mipi-panel.dtbo
```bash
# Example: Panel 3-V20
echo 'PanelNum=3
PanelDTBO=ScreenFiles/Panel 3/mipi-panel.dtbo' | sudo tee /mnt/panel.txt
# Example: set Clone 8 (most common clone panel)
sudo cp /mnt/overlays/clone_panel_8.dtbo /mnt/overlays/mipi-panel.dtbo
# Mark as confirmed (skip wizard on next boot)
echo 'confirmed' | sudo tee /mnt/panel-confirmed
```
For default Panel 4-V22 (no overlay needed):
```bash
echo 'PanelNum=4
PanelDTBO=' | sudo tee /mnt/panel.txt
echo 'confirmed' | sudo tee /mnt/panel-confirmed
```
**Step 3 — Unmount and boot**
```bash
sudo umount /mnt
sync
```
**To reset panel selection:** hold **X** during boot, or delete `panel-confirmed` from the BOOT partition.
## Boot Flow
```
Power On
→ U-Boot (idbloader → trust → uboot.img)
logo.bmp displayed on screen
→ boot.ini: load panel.txt → apply DTBO overlay (if non-default panel)
→ Kernel 6.6.89 + rk3326-gameconsole-r36s.dtb
→ systemd → panel-detect.service (first boot only)
→ archr-boot-setup (GPU + governors)
→ U-Boot loads (idbloader → trust → uboot.img)
boot.ini: read SARADC hwrev → select board DTB
→ boot.ini: apply overlays/mipi-panel.dtbo (panel init sequence)
→ Kernel 6.12.61 + initramfs splash (0.7s)
→ systemd → archr-boot-setup (GPU + governors)
→ emulationstation.service → EmulationStation UI
≈ 19 seconds total (+ wizard on first boot)
≈ 19 seconds total
```
## Contributing
+80 -2
View File
@@ -1915,6 +1915,84 @@ The panel wizard can only write config for the NEXT boot — no hot-swapping pan
---
### 2026-02-27 — Pre-merged Panel DTBs (beta1.1)
The biggest pain point since beta1 was panel selection. BSP U-Boot's `fdt apply` was silently
corrupting DTBs whenever an overlay tried to replace a property with different-sized data — the
init-sequence byte arrays vary per panel, so any non-default panel produced a broken DTB and a
black screen.
The fix was surprisingly clean: run `fdtoverlay` at **build time** instead of at boot time.
`generate-panel-dtbos.sh` now pre-merges each panel overlay with the kernel DTB, producing
`kernel-panel0.dtb` through `kernel-panel5.dtb` (original) and 12 clone variants. The boot
script reads `PanelDTB=kernel-panel3.dtb` from `panel.txt` and loads the complete DTB directly —
no `fdt apply` at all. Published as v1.0-beta1.1 and pushed to the community for testing.
---
### 2026-03-01 — Arch R Flasher & beta1.2
Two things happened in parallel this week: the Flasher app was born, and the distro itself
got some housekeeping.
**Arch R Flasher — feature-complete.**
Built the desktop flashing tool (Tauri 2 — Rust backend, vanilla HTML/CSS/JS frontend) that
was "Plano C" in case pre-merged DTBs didn't fully work. Turns out having a proper Flasher is
valuable regardless — it eliminates the dd-to-SD-card ceremony and lets users select their
console type (Original vs Clone) and panel before flashing. The Flasher injects the correct
kernel DTB, U-Boot, and panel config into the image at write time. Zero runtime detection needed.
Feature set:
- Console selection (Original: 6 panels, Clone: 12 panels)
- Panel picker with defaults marked
- In-app image download from GitHub Releases (with progress bar + SHA256 verification)
- Local file picker (.img / .xz) with XZ decompression
- SD card detection (Linux: sysfs, macOS: diskutil, Windows: PowerShell)
- System disk protection (never lists /, /home, /boot disks)
- Privileged flash (pkexec on Linux, osascript on macOS, UAC on Windows)
- Real-time flash progress via dd monitoring
- Post-flash eject (Linux + macOS)
- Auto-update via tauri-plugin-updater + GitHub Releases (with minisign signing)
- i18n: English, Portuguese, Spanish, Chinese
- CI/CD: GitHub Actions builds for Linux (.deb/.rpm/.AppImage), macOS (.dmg), Windows (.msi/.exe)
The Flasher lives at `archr-linux/archr-flasher` on GitHub. Still ironing out the CI signing
(first build caught a Tauri 2 schema issue with `app.title` and 16-bit icon PNGs), but the
code is feature-complete.
**beta1.2 system changes — a lot more than "just polish":**
The biggest under-the-hood change was the **input merger daemon**. RetroArch sees multiple input
devices (gpio-keys for buttons, adc-joystick for analog sticks) as separate controllers. With
`max_users=1`, it would bind to gpio-keys and ignore the joystick entirely. The fix: a small
C daemon (`input-merge`) that reads both evdev devices and outputs a single virtual "Arch R
Gamepad" via uinput. Now RetroArch sees one unified controller with buttons + analog sticks.
`retroarch-launch.sh` starts the merger before RA and kills it after.
RetroArch itself got a proper config tuning pass, borrowed heavily from ROCKNIX's RK3326
profiles. Audio at 48kHz (native DAC rate), triple buffer, late input polling for reduced
latency, per-core options for mupen64plus, pcsx_rearmed, flycast, mame2003-plus, melonds,
and others. Auto-save enabled, core options path set.
**Panel wizard rework:** Panels now show in numerical order — the beep count matches the panel
position in the list (Panel 1 = 1 beep, Panel 2 = 2 beeps, etc.). Default panel detection
uses `dtb_name` matching instead of always falling back to `panels[0]`.
**Third image variant: no-panel.** For the Flasher app — includes all 18 pre-merged panel DTBs
for both original and clone hardware. The Flasher picks the right DTB at write time. Also added
`variant-sync` systemd service that copies `/boot/variant` to `/etc/archr/variant` on first
boot (necessary because the Flasher writes the variant marker to the FAT32 BOOT partition,
not directly into ext4).
**Mirror list updated:** The old EU mirror was returning 403 errors. Reshuffled to Americas-first
ordering (better for Brazil) and added new mirrors (de4, gr, tw, tw2, ca.us).
**boot.ini fix:** Root device now auto-detected from `mmcdev` variable instead of the hardcoded
`__ROOTDEV__` placeholder — one less thing that could break on different boot configurations.
---
## What's Left for v1.0 Stable
### Critical — Must Work Before Release
@@ -1950,7 +2028,7 @@ The panel wizard can only write config for the NEXT boot — no hot-swapping pan
| 15 | Bluetooth pairing | Not tested | bluez installed |
| 16 | Battery LED indicator | Installed | Python service, needs hardware test |
| 17 | Sleep/wake | Not implemented | PMIC sleep pinctrl in DTS |
| 18 | OTA updates | Not implemented | Future feature |
| 18 | OTA updates | Not implemented | Future feature (Flasher has self-update) |
| 19 | Theme customization | Default only | ES-fcamod default theme |
| 20 | Headphone detection | Not tested | archr-hotkeys.py ALSA switch |
@@ -2024,4 +2102,4 @@ The panel wizard can only write config for the NEXT boot — no hot-swapping pan
---
*Last updated: 2026-02-25 (build pipeline fixes, boot.scr mystery solved, splash positioning)*
*Last updated: 2026-03-01 (beta1.2 release — Flasher app, input merger, RetroArch tuning, no-panel variant)*
Submodule bootloader/u-boot-rk3326 updated: 5606e804ff...2492a3e467
+9 -1
View File
@@ -129,6 +129,14 @@ log "✓ Prerequisites OK"
START_TIME=$(date +%s)
if [ "$BUILD_KERNEL" = true ]; then
# Initramfs must be built BEFORE kernel — kernel embeds it at compile time
log ""
log "═══════════════════════════════════════════════════════════════"
log " BUILDING INITRAMFS"
log "═══════════════════════════════════════════════════════════════"
chmod +x "$SCRIPT_DIR/build-initramfs.sh"
"$SCRIPT_DIR/build-initramfs.sh"
log ""
log "═══════════════════════════════════════════════════════════════"
log " BUILDING KERNEL"
@@ -184,7 +192,7 @@ log "═════════════════════════
chmod +x "$SCRIPT_DIR/scripts/generate-panel-dtbos.sh"
"$SCRIPT_DIR/scripts/generate-panel-dtbos.sh"
# Build custom U-Boot (optional — requires arm-linux-gnueabihf toolchain)
# Build U-Boot BSP (requires aarch64 cross-compiler)
if [ "$BUILD_UBOOT" = true ] && [ -f "$SCRIPT_DIR/build-uboot.sh" ]; then
if command -v aarch64-linux-gnu-gcc &>/dev/null; then
log ""
+97 -270
View File
@@ -3,12 +3,18 @@
#==============================================================================
# Arch R - SD Card Image Builder
#==============================================================================
# Creates a flashable SD card image for R36S (original or clone)
# Creates a flashable SD card image for Arch R.
#
# BOOT partition layout:
# /KERNEL ← kernel Image
# /boot.ini ← boot script (BSP reads directly, hwrev→DTB)
# /dtbs/rk3326-*.dtb ← ALL board DTBs (selected by boot.ini hwrev mapping)
# /overlays/*.dtbo ← all available panel overlays (no default — Flasher selects)
#
# Usage:
# sudo ./build-image.sh --variant original # R36S original
# sudo ./build-image.sh --variant clone # R36S clone (G80CA-MB etc)
# sudo ./build-image.sh # defaults to original
# sudo ./build-image.sh --variant original # Original R36S, OGA, OGS, RG351, etc.
# sudo ./build-image.sh --variant clone # K36 clones, RGB20S, RGB10X, etc.
# sudo ./build-image.sh # defaults to original
#==============================================================================
set -e
@@ -51,49 +57,26 @@ fi
#------------------------------------------------------------------------------
if [ "$VARIANT" = "original" ]; then
IMAGE_SUFFIX="R36S"
KERNEL_DTB_NAME="rk3326-gameconsole-r36s.dtb"
ROOT_DEV="/dev/mmcblk1p2"
BOOT_INI="$SCRIPT_DIR/config/a_boot.ini"
else
IMAGE_SUFFIX="R36S-clone"
KERNEL_DTB_NAME="rk3326-gameconsole-r36s-clone-type5.dtb"
ROOT_DEV="/dev/mmcblk0p2"
BOOT_INI="$SCRIPT_DIR/config/b_boot.ini"
fi
# U-Boot binaries per variant:
# Original: BSP Rockchip U-Boot (custom build or pre-built)
# Clone: Mainline U-Boot v2025.10 (custom build or pre-built)
UBOOT_TYPE=""
UBOOT_BSP_DIR="$SCRIPT_DIR/bootloader/u-boot-rk3326/sd_fuse"
UBOOT_MAINLINE_DIR="$SCRIPT_DIR/bootloader/u-boot-clone-build"
if [ "$VARIANT" = "clone" ] && [ -f "$UBOOT_MAINLINE_DIR/uboot.img" ]; then
UBOOT_BIN_DIR="$UBOOT_MAINLINE_DIR"
UBOOT_TYPE="mainline"
log " U-Boot: mainline v2025.10 (clone)"
elif [ "$VARIANT" = "original" ] && [ -f "$UBOOT_BSP_DIR/uboot.img" ]; then
UBOOT_BIN_DIR="$UBOOT_BSP_DIR"
UBOOT_TYPE="bsp"
log " U-Boot: BSP custom build (original)"
elif [ "$VARIANT" = "original" ]; then
UBOOT_BIN_DIR="$SCRIPT_DIR/bootloader/u-boot-r36s-working"
UBOOT_TYPE="bsp"
log " U-Boot: BSP pre-built (original)"
else
UBOOT_BIN_DIR="$SCRIPT_DIR/bootloader/u-boot-clone-working"
UBOOT_TYPE="bsp"
log " U-Boot: BSP pre-built (clone fallback)"
fi
# U-Boot binaries (same BSP build for both variants)
UBOOT_BIN_DIR="$SCRIPT_DIR/bootloader/u-boot-rk3326/sd_fuse"
#------------------------------------------------------------------------------
# Configuration
#------------------------------------------------------------------------------
OUTPUT_DIR="$SCRIPT_DIR/output"
ROOTFS_DIR="$OUTPUT_DIR/rootfs"
BOOT_OUTPUT="$OUTPUT_DIR/boot"
PANELS_DIR="$OUTPUT_DIR/panels"
IMAGE_DIR="$OUTPUT_DIR/images"
IMAGE_NAME="ArchR-${IMAGE_SUFFIX}-$(date +%Y%m%d).img"
# CRITICAL: Always clean up loop devices and mounts on exit (success OR failure).
# Cleanup on exit
LOOP_DEV=""
cleanup_image() {
echo "[IMAGE] Cleaning up mounts and loop devices..."
@@ -106,11 +89,9 @@ trap cleanup_image EXIT
IMAGE_FILE="$IMAGE_DIR/$IMAGE_NAME"
# Partition sizes (in MB)
BOOT_SIZE=128 # Boot partition (FAT32)
ROOTFS_SIZE=6144 # Root filesystem (ext4) - 6GB for full Arch + gaming stack
# Total image size
IMAGE_SIZE=$((BOOT_SIZE + ROOTFS_SIZE + 32)) # +32MB for partition table
BOOT_SIZE=128
ROOTFS_SIZE=6144
IMAGE_SIZE=$((BOOT_SIZE + ROOTFS_SIZE + 32))
log "=== Arch R Image Builder (variant: $VARIANT) ==="
@@ -131,29 +112,44 @@ if [ ! -d "$ROOTFS_DIR" ]; then
error "Rootfs not found at: $ROOTFS_DIR\nRun build-rootfs.sh first!"
fi
if [ ! -f "$ROOTFS_DIR/boot/Image" ]; then
warn "Kernel Image not found in rootfs. Make sure kernel is installed."
# Kernel
if [ ! -f "$BOOT_OUTPUT/KERNEL" ]; then
error "Kernel not found at: $BOOT_OUTPUT/KERNEL\nRun build-kernel.sh first!"
fi
KERNEL_BYTES=$(stat -c%s "$BOOT_OUTPUT/KERNEL")
log " KERNEL: $(($KERNEL_BYTES / 1024 / 1024))MB"
# Board DTBs
if [ ! -d "$BOOT_OUTPUT/dtbs" ]; then
error "DTBs not found at: $BOOT_OUTPUT/dtbs/\nRun build-kernel.sh first!"
fi
DTB_COUNT=$(ls "$BOOT_OUTPUT/dtbs"/rk3326-*.dtb 2>/dev/null | wc -l)
log " Board DTBs: $DTB_COUNT files"
# Kernel modules in rootfs
if [ ! -d "$ROOTFS_DIR/lib/modules" ] || [ -z "$(ls "$ROOTFS_DIR/lib/modules/" 2>/dev/null)" ]; then
warn "Kernel modules not found in rootfs! Run build-rootfs.sh after build-kernel.sh."
else
IMAGE_BYTES=$(stat -c%s "$ROOTFS_DIR/boot/Image")
if [ "$IMAGE_BYTES" -lt 10000000 ]; then
error "Kernel Image is only $(($IMAGE_BYTES / 1024 / 1024))MB — expected ~18MB for kernel 6.6!"
log " Kernel modules: OK"
fi
# Panel overlays (generate if missing)
if [ ! -d "$PANELS_DIR" ] || [ -z "$(ls "$PANELS_DIR"/*.dtbo 2>/dev/null)" ]; then
log " Panel overlays not found — generating..."
if [ -x "$SCRIPT_DIR/scripts/generate-panel-dtbos.sh" ]; then
"$SCRIPT_DIR/scripts/generate-panel-dtbos.sh"
else
warn "Panel overlays not found and generate-panel-dtbos.sh not executable!"
fi
log " Kernel Image: $(($IMAGE_BYTES / 1024 / 1024))MB (OK)"
fi
# Check variant-specific DTB
if [ ! -f "$ROOTFS_DIR/boot/$KERNEL_DTB_NAME" ]; then
error "Kernel DTB not found: $ROOTFS_DIR/boot/$KERNEL_DTB_NAME\nRun build-kernel.sh first!"
fi
log " DTB ($VARIANT): $KERNEL_DTB_NAME (OK)"
# Check U-Boot binaries
# U-Boot
if [ ! -d "$UBOOT_BIN_DIR" ] || [ ! -f "$UBOOT_BIN_DIR/idbloader.img" ]; then
error "U-Boot binaries not found at: $UBOOT_BIN_DIR"
fi
log " U-Boot: $UBOOT_BIN_DIR (OK)"
log " U-Boot: $UBOOT_BIN_DIR"
# Check required tools
# Tools
for tool in parted mkfs.vfat mkfs.ext4 losetup; do
if ! command -v $tool &> /dev/null; then
error "Required tool not found: $tool"
@@ -169,30 +165,27 @@ log ""
log "Step 2: Creating image file..."
mkdir -p "$IMAGE_DIR"
# Remove old images for this variant only
rm -f "$IMAGE_DIR"/ArchR-${IMAGE_SUFFIX}-*.img "$IMAGE_DIR"/ArchR-${IMAGE_SUFFIX}-*.img.xz
# Create sparse image file
dd if=/dev/zero of="$IMAGE_FILE" bs=1M count=0 seek=$IMAGE_SIZE 2>/dev/null
log " Created ${IMAGE_SIZE}MB image: $IMAGE_NAME"
#------------------------------------------------------------------------------
# Step 2.5: Install U-Boot Bootloader
# Step 3: Install U-Boot Bootloader
#------------------------------------------------------------------------------
log ""
log "Step 2.5: Installing U-Boot bootloader..."
log "Step 3: Installing U-Boot bootloader..."
dd if="$UBOOT_BIN_DIR/idbloader.img" of="$IMAGE_FILE" bs=512 seek=64 conv=sync,noerror,notrunc 2>/dev/null
dd if="$UBOOT_BIN_DIR/uboot.img" of="$IMAGE_FILE" bs=512 seek=16384 conv=sync,noerror,notrunc 2>/dev/null
dd if="$UBOOT_BIN_DIR/trust.img" of="$IMAGE_FILE" bs=512 seek=24576 conv=sync,noerror,notrunc 2>/dev/null
log " U-Boot installed from $UBOOT_BIN_DIR"
log " U-Boot installed"
#------------------------------------------------------------------------------
# Step 3: Create Partitions
# Step 4: Create and Format Partitions
#------------------------------------------------------------------------------
log ""
log "Step 3: Creating partitions..."
log "Step 4: Creating partitions..."
parted -s "$IMAGE_FILE" mklabel msdos
@@ -205,38 +198,21 @@ parted -s "$IMAGE_FILE" mkpart primary fat32 ${BOOT_START}MiB ${BOOT_END}MiB
parted -s "$IMAGE_FILE" mkpart primary ext4 ${ROOTFS_START}MiB ${ROOTFS_END}MiB
parted -s "$IMAGE_FILE" set 1 boot on
log " Partitions created"
#------------------------------------------------------------------------------
# Step 4: Setup Loop Devices
#------------------------------------------------------------------------------
log ""
log "Step 4: Setting up loop devices..."
LOOP_DEV=$(losetup -fP --show "$IMAGE_FILE")
BOOT_PART="${LOOP_DEV}p1"
ROOT_PART="${LOOP_DEV}p2"
sleep 1
log " Loop device: $LOOP_DEV"
#------------------------------------------------------------------------------
# Step 5: Format Partitions
#------------------------------------------------------------------------------
log ""
log "Step 5: Formatting partitions..."
mkfs.vfat -F 32 -n BOOT "$BOOT_PART"
mkfs.ext4 -L ROOTFS -O ^metadata_csum "$ROOT_PART"
mkfs.ext4 -L STORAGE -O ^metadata_csum "$ROOT_PART"
log " Partitions formatted"
log " Partitions: BOOT (${BOOT_SIZE}MB FAT32) + STORAGE (${ROOTFS_SIZE}MB ext4)"
#------------------------------------------------------------------------------
# Step 6: Mount and Copy Files
# Step 5: Mount and Copy Files
#------------------------------------------------------------------------------
log ""
log "Step 6: Copying files..."
log "Step 5: Copying files..."
MOUNT_ROOT="$OUTPUT_DIR/mnt_root"
MOUNT_BOOT="$OUTPUT_DIR/mnt_boot"
@@ -249,220 +225,71 @@ mount "$BOOT_PART" "$MOUNT_BOOT"
log " Copying rootfs..."
rsync -aHxS --exclude='/boot' "$ROOTFS_DIR/" "$MOUNT_ROOT/"
# --- Write variant marker (for panel-detect.py and other scripts) ---
# --- Variant marker ---
mkdir -p "$MOUNT_ROOT/etc/archr"
echo "$VARIANT" > "$MOUNT_ROOT/etc/archr/variant"
log " Variant marker: /etc/archr/variant = $VARIANT"
# --- Ensure first-boot runs on actual first boot ---
# The rootfs may contain a stale flag from the build process
# --- First-boot flag ---
rm -f "$MOUNT_ROOT/var/lib/archr/.first-boot-done"
# --- Boot partition: kernel Image ---
log " Copying boot files..."
cp "$ROOTFS_DIR/boot/Image" "$MOUNT_BOOT/"
# --- BOOT partition: KERNEL ---
cp "$BOOT_OUTPUT/KERNEL" "$MOUNT_BOOT/KERNEL"
log " KERNEL installed"
# --- Boot partition: kernel DTB (as kernel.dtb) ---
cp "$ROOTFS_DIR/boot/$KERNEL_DTB_NAME" "$MOUNT_BOOT/kernel.dtb"
log " kernel.dtb <- $KERNEL_DTB_NAME"
# --- BOOT partition: Board DTBs (ALL rk3326-*.dtb) ---
mkdir -p "$MOUNT_BOOT/dtbs"
cp "$BOOT_OUTPUT/dtbs"/rk3326-*.dtb "$MOUNT_BOOT/dtbs/"
dtb_count=$(ls "$MOUNT_BOOT/dtbs"/rk3326-*.dtb | wc -l)
log " DTBs: $dtb_count board DTBs in /dtbs/"
# --- Generate pre-merged panel DTBs (overlay applied at build-time) ---
# Runs generate-panel-dtbos.sh to create DTBOs + pre-merged DTBs in one step.
log " Generating panel DTBs..."
"$SCRIPT_DIR/scripts/generate-panel-dtbos.sh"
# --- BOOT partition: Panel overlays ---
mkdir -p "$MOUNT_BOOT/overlays"
overlay_count=0
# --- Boot partition: Pre-merged panel DTBs ---
# Each panel gets its own kernel-*.dtb with the overlay already merged.
# No fdt apply needed at boot — U-Boot just loads the right DTB by name.
MERGED_DIR="$OUTPUT_DIR/panels/merged"
if [ -d "$MERGED_DIR" ]; then
panel_count=0
if [ -d "$PANELS_DIR" ]; then
for dtbo in "$PANELS_DIR"/*.dtbo; do
[ -f "$dtbo" ] || continue
cp "$dtbo" "$MOUNT_BOOT/overlays/"
overlay_count=$((overlay_count + 1))
done
if [ "$VARIANT" = "original" ]; then
# R36S original: kernel-panel0.dtb through kernel-panel5.dtb
for dtb in "$MERGED_DIR"/kernel-panel*.dtb; do
[ -f "$dtb" ] && cp "$dtb" "$MOUNT_BOOT/" && panel_count=$((panel_count + 1))
done
else
# R36S clone: kernel-clone*.dtb + kernel-r36max.dtb + kernel-rx6s.dtb
for dtb in "$MERGED_DIR"/kernel-clone*.dtb "$MERGED_DIR"/kernel-r36max.dtb "$MERGED_DIR"/kernel-rx6s.dtb; do
[ -f "$dtb" ] && cp "$dtb" "$MOUNT_BOOT/" && panel_count=$((panel_count + 1))
done
fi
log " Panel DTBs: ${panel_count} pre-merged ($VARIANT)"
log " Panel overlays: $overlay_count shipped (no default — Flasher selects panel)"
else
warn "Pre-merged panel DTBs not found! Run scripts/generate-panel-dtbos.sh first"
warn "No panel overlays found — display may not work without mipi-panel.dtbo!"
fi
# --- Boot partition: U-Boot display DTB ---
# BSP U-Boot: hwrev.c loads display DTB from FAT partition (init_kernel_dtb).
# Mainline U-Boot: uses built-in DTS, no separate display DTB needed.
if [ "$UBOOT_TYPE" = "mainline" ]; then
log " U-Boot display DTB: not needed (mainline)"
else
UBOOT_DTS_DIR="$SCRIPT_DIR/bootloader/u-boot-rk3326/arch/arm/dts"
display_dtb_copied=0
# --- BOOT partition: boot.ini (BSP U-Boot reads directly) ---
cp "$BOOT_INI" "$MOUNT_BOOT/boot.ini"
log " boot.ini installed"
if [ "$UBOOT_BIN_DIR" = "$UBOOT_BSP_DIR" ]; then
# BSP custom build: copy variant-specific DTB as uboot-display.dtb
if [ "$VARIANT" = "original" ]; then
UBOOT_SRC_DTB="$UBOOT_DTS_DIR/r36s-uboot.dtb"
else
UBOOT_SRC_DTB="$UBOOT_DTS_DIR/r36-uboot.dtb"
fi
if [ -f "$UBOOT_SRC_DTB" ]; then
cp "$UBOOT_SRC_DTB" "$MOUNT_BOOT/uboot-display.dtb"
display_dtb_copied=1
log " uboot-display.dtb <- $(basename $UBOOT_SRC_DTB) (custom)"
fi
else
# Legacy pre-built: copy variant-specific DTB under its original name
if [ "$VARIANT" = "original" ]; then
UBOOT_DISPLAY_DTB="rg351mp-uboot.dtb"
else
UBOOT_DISPLAY_DTB="arkos4clone-uboot.dtb"
fi
for dtb_dir in "$UBOOT_BIN_DIR" "$UBOOT_DTS_DIR"; do
if [ -f "$dtb_dir/$UBOOT_DISPLAY_DTB" ]; then
cp "$dtb_dir/$UBOOT_DISPLAY_DTB" "$MOUNT_BOOT/$UBOOT_DISPLAY_DTB"
display_dtb_copied=1
log " U-Boot display DTB: $UBOOT_DISPLAY_DTB (legacy)"
break
fi
done
fi
# --- Initramfs is embedded in kernel (no separate file needed) ---
if [ "$display_dtb_copied" -eq 0 ]; then
warn "No U-Boot display DTB found — init_kernel_dtb() WILL FAIL!"
fi
fi
# --- Boot partition: boot script (with root device substituted) ---
if [ -f "$SCRIPT_DIR/config/boot.ini" ]; then
sed "s|__ROOTDEV__|$ROOT_DEV|" "$SCRIPT_DIR/config/boot.ini" > "$MOUNT_BOOT/boot.ini"
log " boot.ini installed (root=$ROOT_DEV)"
# Mainline U-Boot: also create boot.scr (compiled boot script)
# Mainline uses distro boot flow → scans for boot.scr, not boot.ini
if [ "$UBOOT_TYPE" = "mainline" ]; then
MKIMAGE="$SCRIPT_DIR/bootloader/u-boot-mainline/tools/mkimage"
if [ -x "$MKIMAGE" ]; then
# mkimage doesn't support stdin pipe (-d -) reliably — use temp file
BOOT_SCR_SRC=$(mktemp)
grep -v '^odroidgoa-uboot-config' "$MOUNT_BOOT/boot.ini" > "$BOOT_SCR_SRC"
"$MKIMAGE" -T script -d "$BOOT_SCR_SRC" "$MOUNT_BOOT/boot.scr" >/dev/null 2>&1
rm -f "$BOOT_SCR_SRC"
log " boot.scr created (mainline distro boot)"
else
warn "mkimage not found — boot.scr not created! Mainline U-Boot may not find boot script."
fi
fi
else
error "boot.ini not found at config/boot.ini!"
fi
# --- Boot splash: initramfs with embedded splash (appears <1s after kernel start) ---
# Splash is embedded in initramfs /init binary — no file I/O needed at boot time.
# Pipeline: generate splash.bmp → xxd → compile archr-init → cpio → initramfs.img
log " Building boot splash initramfs..."
SPLASH_FONT="$SCRIPT_DIR/assets/fonts/Quantico-Regular.ttf"
SPLASH_TMPDIR=$(mktemp -d)
BUILD_DATE=$(date +%Y%m%d)
ARCHR_VERSION="v1.0"
if command -v convert &>/dev/null && [ -f "$SPLASH_FONT" ] && command -v aarch64-linux-gnu-gcc &>/dev/null; then
# Step 1: Generate splash.bmp (Quantico font, glow effect, version+build)
convert -size 640x480 xc:black "$SPLASH_TMPDIR/base.png"
# ARCH glow (blue, blurred) — offset -33 centers "ARCH R" as a unit
convert -size 640x480 xc:transparent -font "$SPLASH_FONT" -pointsize 72 -fill '#1793D1' \
-gravity center -annotate -33+0 "ARCH" -channel RGBA -blur 0x8 "$SPLASH_TMPDIR/arch-glow.png"
# ARCH text (blue, sharp)
convert -size 640x480 xc:transparent -font "$SPLASH_FONT" -pointsize 72 -fill '#1793D1' \
-gravity center -annotate -33+0 "ARCH" "$SPLASH_TMPDIR/arch-text.png"
# R glow (white, blurred) — offset +107 gives proper spacing after ARCH
convert -size 640x480 xc:transparent -font "$SPLASH_FONT" -pointsize 72 -fill white \
-gravity center -annotate +107+0 "R" -channel RGBA -blur 0x8 "$SPLASH_TMPDIR/r-glow.png"
# R text (white, sharp)
convert -size 640x480 xc:transparent -font "$SPLASH_FONT" -pointsize 72 -fill white \
-gravity center -annotate +107+0 "R" "$SPLASH_TMPDIR/r-text.png"
# Version + build date
convert -size 640x480 xc:transparent -font "$SPLASH_FONT" -pointsize 14 -fill '#666666' \
-gravity center -annotate +0+50 "${ARCHR_VERSION} BUILD ${BUILD_DATE}" "$SPLASH_TMPDIR/version.png"
# Composite all layers
convert "$SPLASH_TMPDIR/base.png" \
"$SPLASH_TMPDIR/arch-glow.png" -composite \
"$SPLASH_TMPDIR/r-glow.png" -composite \
"$SPLASH_TMPDIR/arch-text.png" -composite \
"$SPLASH_TMPDIR/r-text.png" -composite \
"$SPLASH_TMPDIR/version.png" -composite \
-alpha remove -type TrueColor BMP3:"$SPLASH_TMPDIR/splash.bmp"
log " splash.bmp created ($(du -h "$SPLASH_TMPDIR/splash.bmp" | cut -f1))"
# Step 2: Generate splash_data.h (embedded BMP data for archr-init)
cd "$SPLASH_TMPDIR"
xxd -i splash.bmp > splash_data.h
cd "$SCRIPT_DIR"
log " splash_data.h generated ($(wc -l < "$SPLASH_TMPDIR/splash_data.h") lines)"
# Step 3: Compile archr-init with embedded splash (static aarch64 binary)
aarch64-linux-gnu-gcc -static -O2 -I"$SPLASH_TMPDIR" \
-o "$SPLASH_TMPDIR/archr-init" "$SCRIPT_DIR/scripts/archr-init.c"
log " archr-init compiled ($(du -h "$SPLASH_TMPDIR/archr-init" | cut -f1))"
# Step 4: Create initramfs (cpio + gzip)
mkdir -p "$SPLASH_TMPDIR/initramfs"/{dev,proc,newroot}
cp "$SPLASH_TMPDIR/archr-init" "$SPLASH_TMPDIR/initramfs/init"
chmod 755 "$SPLASH_TMPDIR/initramfs/init"
(cd "$SPLASH_TMPDIR/initramfs" && find . | cpio -o -H newc 2>/dev/null | gzip -9 > "$MOUNT_BOOT/initramfs.img")
log " initramfs.img created ($(du -h "$MOUNT_BOOT/initramfs.img" | cut -f1))"
# Also copy splash.bmp to BOOT (for reference / fallback)
cp "$SPLASH_TMPDIR/splash.bmp" "$MOUNT_BOOT/splash.bmp"
else
if ! command -v convert &>/dev/null; then
warn "ImageMagick not found — initramfs splash skipped"
elif [ ! -f "$SPLASH_FONT" ]; then
warn "Quantico font not found at $SPLASH_FONT — initramfs splash skipped"
else
warn "aarch64-linux-gnu-gcc not found — initramfs splash skipped"
fi
fi
rm -rf "$SPLASH_TMPDIR"
# NOTE: extlinux.conf is NOT created — boot.ini / boot.scr is the primary boot method.
log " (no extlinux.conf — boot.ini is primary boot method)"
# --- Rootfs: fstab (overrides rootfs fstab with correct entries) ---
# --- Rootfs: fstab ---
cat > "$MOUNT_ROOT/etc/fstab" << 'FSTAB_EOF'
# Arch R fstab — optimized for fast boot
# fsck disabled (fsck.mode=skip in cmdline + pass=0 here)
LABEL=BOOT /boot vfat defaults,noatime 0 0
LABEL=ROOTFS / ext4 defaults,noatime 0 0
LABEL=STORAGE / ext4 defaults,noatime 0 0
LABEL=ROMS /roms vfat defaults,utf8,noatime,uid=1001,gid=1001,nofail,x-systemd.device-timeout=10s 0 0
tmpfs /tmp tmpfs defaults,nosuid,nodev,size=128M 0 0
tmpfs /var/log tmpfs defaults,nosuid,nodev,noexec,size=16M 0 0
FSTAB_EOF
log " Files copied"
log " fstab installed"
#------------------------------------------------------------------------------
# Step 7: Cleanup
# Step 6: Sync and Unmount
#------------------------------------------------------------------------------
log ""
log "Step 7: Syncing filesystem..."
log "Step 6: Syncing filesystem..."
sync
log " Sync complete"
#------------------------------------------------------------------------------
# Step 8: Compress (optional)
# Step 7: Compress
#------------------------------------------------------------------------------
log ""
log "Step 8: Compressing image..."
log "Step 7: Compressing image..."
if command -v xz &> /dev/null; then
rm -f "${IMAGE_FILE}.xz"
@@ -480,12 +307,12 @@ log "=== Image Build Complete ($VARIANT) ==="
log ""
IMAGE_SIZE_ACTUAL=$(du -h "$IMAGE_FILE" | cut -f1)
log "Image: $IMAGE_FILE"
log "Size: $IMAGE_SIZE_ACTUAL"
log "Variant: $VARIANT"
log "Root: $ROOT_DEV"
log "Image: $IMAGE_FILE ($IMAGE_SIZE_ACTUAL)"
log "Variant: $VARIANT"
log "DTBs: $dtb_count board DTBs"
log "Overlays: $overlay_count panel overlays"
log ""
log "To flash to SD card:"
log " sudo dd if=$IMAGE_FILE of=/dev/sdX bs=4M status=progress"
log ""
log "Arch R image ready ($VARIANT)!"
log "Arch R image ready!"
+102
View File
@@ -0,0 +1,102 @@
#!/bin/bash
#==============================================================================
# Arch R - Initramfs Builder
#==============================================================================
# Generates the initramfs directory for kernel embedding (CONFIG_INITRAMFS_SOURCE).
# Must run BEFORE build-kernel.sh — the kernel embeds this at compile time.
#
# Pipeline:
# 1. Compile archr-init.c + SVG splash library (static aarch64 binary)
# 2. Create initramfs directory tree (init + dev + proc + newroot)
#
# Logo is rendered from SVG paths at runtime (no ImageMagick needed).
#
# Output: $OUTPUT_DIR/initramfs/ (directory tree, not cpio)
#==============================================================================
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
log() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1"; }
warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] WARNING:${NC} $1"; }
error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $1"; exit 1; }
#------------------------------------------------------------------------------
# Configuration
#------------------------------------------------------------------------------
OUTPUT_DIR="$SCRIPT_DIR/output"
INITRAMFS_DIR="$OUTPUT_DIR/initramfs"
SPLASH_DIR="$SCRIPT_DIR/scripts/splash"
log "================================================================"
log " Arch R - Initramfs Builder (SVG splash)"
log "================================================================"
#------------------------------------------------------------------------------
# Prerequisites
#------------------------------------------------------------------------------
if ! command -v aarch64-linux-gnu-gcc &>/dev/null; then
error "Cross-compiler not found. Install: sudo apt install gcc-aarch64-linux-gnu"
fi
# Verify splash library files exist
for f in fbsplash.c svg_parser.c svg_renderer.c archr-logo.h; do
if [ ! -f "$SPLASH_DIR/$f" ]; then
error "Missing splash file: $SPLASH_DIR/$f"
fi
done
#------------------------------------------------------------------------------
# Step 1: Compile archr-init (static aarch64 binary with SVG splash)
#------------------------------------------------------------------------------
log ""
log "Step 1: Compiling archr-init (SVG splash)..."
TMPDIR=$(mktemp -d)
aarch64-linux-gnu-gcc -static -O2 \
-I"$SPLASH_DIR" \
-o "$TMPDIR/archr-init" \
"$SCRIPT_DIR/scripts/archr-init.c" \
"$SPLASH_DIR/fbsplash.c" \
"$SPLASH_DIR/svg_parser.c" \
"$SPLASH_DIR/svg_renderer.c" \
-lm
log " archr-init compiled ($(du -h "$TMPDIR/archr-init" | cut -f1))"
#------------------------------------------------------------------------------
# Step 2: Create initramfs directory tree
#------------------------------------------------------------------------------
log ""
log "Step 2: Creating initramfs directory..."
rm -rf "$INITRAMFS_DIR"
mkdir -p "$INITRAMFS_DIR"/{dev,proc,newroot}
cp "$TMPDIR/archr-init" "$INITRAMFS_DIR/init"
chmod 755 "$INITRAMFS_DIR/init"
#------------------------------------------------------------------------------
# Cleanup
#------------------------------------------------------------------------------
rm -rf "$TMPDIR"
INIT_SIZE=$(du -h "$INITRAMFS_DIR/init" | cut -f1)
log ""
log "================================================================"
log " Initramfs Ready"
log "================================================================"
log ""
log " Directory: $INITRAMFS_DIR"
log " /init: $INIT_SIZE (static aarch64 + SVG splash)"
log ""
log " Kernel will embed this via CONFIG_INITRAMFS_SOURCE"
+217 -139
View File
@@ -1,9 +1,11 @@
#!/bin/bash
#==============================================================================
# Arch R - Kernel 6.6 Build Script for R36S
# Arch R - Kernel Build Script
#==============================================================================
# Builds Linux kernel 6.6.89 (Rockchip BSP) with R36S DTS + systemd support
# Builds mainline Linux 6.12.x with Arch R patches for RK3326 R36S
# Applies: device patches, 6.12-LTS patches, mainline patches
# Builds: kernel Image + ALL DTBs + modules + out-of-tree joypad driver
#==============================================================================
set -e
@@ -14,7 +16,6 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
log() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1"; }
@@ -22,21 +23,18 @@ warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] WARNING:${NC} $1"; }
error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $1"; exit 1; }
#------------------------------------------------------------------------------
# Configuration - Kernel 6.6 Rockchip BSP
# Configuration
#------------------------------------------------------------------------------
KERNEL_VERSION="6.6.89"
KERNEL_BRANCH="develop-6.6"
KERNEL_REPO="https://github.com/rockchip-linux/kernel.git"
DEFCONFIG="rockchip_linux_defconfig"
CONFIG_FRAGMENT="$SCRIPT_DIR/config/archr-6.6-r36s.config"
# DTS targets
R36S_DTB="rk3326-gameconsole-r36s"
CLONE_DTB="rk3326-gameconsole-r36s-clone-type5"
KERNEL_VERSION="6.12.61"
KERNEL_URL="https://www.kernel.org/pub/linux/kernel/v6.x/linux-${KERNEL_VERSION}.tar.xz"
# Paths
KERNEL_SRC="${KERNEL_SRC:-/home/dgateles/Documentos/Projetos/kernel}"
KERNEL_SRC="$SCRIPT_DIR/kernel/src/linux-${KERNEL_VERSION}"
PATCHES_DIR="$SCRIPT_DIR/patches/linux"
DTS_DIR="$SCRIPT_DIR/kernel/dts/archr"
JOYPAD_DIR="$SCRIPT_DIR/kernel/drivers/archr-joypad"
CONFIG_BASE="$SCRIPT_DIR/config/linux-archr-base.config"
# Output
OUTPUT_DIR="$SCRIPT_DIR/output"
@@ -50,13 +48,17 @@ export CROSS_COMPILE=aarch64-linux-gnu-
# Build parallelism
JOBS=$(nproc)
# DTS target directory inside kernel
KERNEL_DTS_DIR="$KERNEL_SRC/arch/arm64/boot/dts/rockchip"
log "================================================================"
log " Arch R - Kernel $KERNEL_VERSION (Rockchip BSP for R36S)"
log " Arch R - Kernel $KERNEL_VERSION (Mainline + Arch R patches)"
log "================================================================"
log ""
log "Source: $KERNEL_SRC"
log "Branch: $KERNEL_BRANCH"
log "DTB: $R36S_DTB"
log "Patches: $PATCHES_DIR"
log "DTS: $DTS_DIR"
log "Config: $CONFIG_BASE"
log "Jobs: $JOBS"
#------------------------------------------------------------------------------
@@ -66,11 +68,13 @@ log ""
log "Step 1: Checking kernel source..."
if [ ! -d "$KERNEL_SRC" ]; then
log " Cloning kernel 6.6 (rockchip-linux/kernel)..."
log " Branch: $KERNEL_BRANCH"
git clone --depth 1 --branch "$KERNEL_BRANCH" \
"$KERNEL_REPO" "$KERNEL_SRC"
log " Kernel cloned"
TARBALL="$SCRIPT_DIR/kernel/src/linux-${KERNEL_VERSION}.tar.xz"
if [ ! -f "$TARBALL" ]; then
log " Downloading kernel $KERNEL_VERSION..."
wget -c "$KERNEL_URL" -O "$TARBALL"
fi
log " Extracting..."
tar -xf "$TARBALL" -C "$SCRIPT_DIR/kernel/src/"
fi
if [ ! -f "$KERNEL_SRC/Makefile" ]; then
@@ -80,76 +84,130 @@ fi
ACTUAL_VERSION=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null)
log " Kernel: $ACTUAL_VERSION"
# Copy R36S DTS from Arch-R repo into kernel source tree
DTS_SRC="$SCRIPT_DIR/kernel/dts/rk3326-gameconsole-r36s.dts"
DTS_DEST="$KERNEL_SRC/arch/arm64/boot/dts/rockchip/rk3326-gameconsole-r36s.dts"
if [ -f "$DTS_SRC" ]; then
cp "$DTS_SRC" "$DTS_DEST"
log " DTS: copied from repo"
else
if [ -f "$DTS_DEST" ]; then
warn "DTS not in Arch-R repo — using existing kernel source copy"
else
error "DTS not found! Expected at: $DTS_SRC"
fi
fi
# Copy clone DTS (if available)
CLONE_DTS_SRC="$SCRIPT_DIR/kernel/dts/${CLONE_DTB}.dts"
CLONE_DTS_DEST="$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dts"
if [ -f "$CLONE_DTS_SRC" ]; then
cp "$CLONE_DTS_SRC" "$CLONE_DTS_DEST"
log " DTS (clone): copied from repo"
fi
#------------------------------------------------------------------------------
# Step 2: Configure Kernel
# Step 2: Apply Patches (idempotent — skip already applied)
#------------------------------------------------------------------------------
log ""
log "Step 2: Configuring kernel..."
log "Step 2: Applying patches..."
# Apply base defconfig
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE $DEFCONFIG
log " Base: $DEFCONFIG"
PATCH_MARKER="$KERNEL_SRC/.archr-patches-applied"
# Merge R36S-specific config fragment
# IMPORTANT: merge_config.sh writes output to .config in the CURRENT directory,
# NOT to the base config path. Must run from kernel source dir.
if [ -f "$CONFIG_FRAGMENT" ]; then
pushd "$KERNEL_SRC" > /dev/null
MERGE_LOG=$(scripts/kconfig/merge_config.sh \
-m .config "$CONFIG_FRAGMENT" 2>&1) || true
echo "$MERGE_LOG" | grep -E "(^#|Value)" | tail -20 || true
popd > /dev/null
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE olddefconfig
# Verify critical GPU config was applied
if grep -q "CONFIG_DRM_PANFROST=y" "$KERNEL_SRC/.config"; then
log " Panfrost GPU: ENABLED (built-in)"
elif grep -q "CONFIG_DRM_PANFROST=m" "$KERNEL_SRC/.config"; then
log " Panfrost GPU: ENABLED (module)"
else
warn " Panfrost GPU: NOT ENABLED — check config fragment!"
fi
if grep -q "CONFIG_MALI_MIDGARD=y" "$KERNEL_SRC/.config"; then
warn " Mali Midgard: STILL ENABLED (conflict with Panfrost!)"
else
log " Mali Midgard: disabled (good)"
fi
log " Merged: $(basename "$CONFIG_FRAGMENT")"
if [ -f "$PATCH_MARKER" ]; then
log " Patches already applied (marker exists). Skipping."
else
warn "Config fragment not found: $CONFIG_FRAGMENT"
PATCH_COUNT=0
# Order: mainline first (GPIO API, input-polldev), then 6.12-LTS, then device-specific
for PATCH_SUBDIR in mainline 6.12-lts device; do
PDIR="$PATCHES_DIR/$PATCH_SUBDIR"
if [ ! -d "$PDIR" ]; then
warn " Patch dir not found: $PDIR"
continue
fi
for PATCH in $(ls "$PDIR"/*.patch 2>/dev/null | sort); do
PNAME=$(basename "$PATCH")
log " Applying [$PATCH_SUBDIR] $PNAME..."
if ! patch -d "$KERNEL_SRC" -p1 --forward --batch < "$PATCH" 2>&1 | tail -3; then
warn " Patch may have failed or already applied: $PNAME"
fi
PATCH_COUNT=$((PATCH_COUNT + 1))
done
done
touch "$PATCH_MARKER"
log " Applied $PATCH_COUNT patches"
fi
#------------------------------------------------------------------------------
# Step 3: Copy DTS files
#------------------------------------------------------------------------------
log ""
log "Step 3: Copying DTS files..."
if [ ! -d "$DTS_DIR" ]; then
error "DTS directory not found: $DTS_DIR"
fi
DTS_COUNT=0
for DTS_FILE in "$DTS_DIR"/*.dts "$DTS_DIR"/*.dtsi; do
[ -f "$DTS_FILE" ] || continue
DEST="$KERNEL_DTS_DIR/$(basename "$DTS_FILE")"
cp "$DTS_FILE" "$DEST"
DTS_COUNT=$((DTS_COUNT + 1))
done
# Add DTS entries to Makefile (for each .dts, ensure dtb- line exists)
ROCKCHIP_MAKEFILE="$KERNEL_DTS_DIR/Makefile"
for DTS_FILE in "$DTS_DIR"/*.dts; do
[ -f "$DTS_FILE" ] || continue
DTB_NAME=$(basename "$DTS_FILE" .dts)
if ! grep -q "${DTB_NAME}.dtb" "$ROCKCHIP_MAKEFILE"; then
# Add before the first empty line or at the end of the dtb list
echo "dtb-\$(CONFIG_ARCH_ROCKCHIP) += ${DTB_NAME}.dtb" >> "$ROCKCHIP_MAKEFILE"
log " Added to Makefile: ${DTB_NAME}.dtb"
fi
done
log " Copied $DTS_COUNT DTS files"
#------------------------------------------------------------------------------
# Step 4: Configure Kernel
#------------------------------------------------------------------------------
log ""
log "Step 4: Configuring kernel..."
if [ ! -f "$CONFIG_BASE" ]; then
error "Config base not found: $CONFIG_BASE"
fi
# Copy Arch R base config
cp "$CONFIG_BASE" "$KERNEL_SRC/.config"
# Replace placeholder for initramfs
INITRAMFS_DIR="$OUTPUT_DIR/initramfs"
if [ -d "$INITRAMFS_DIR" ] && [ -x "$INITRAMFS_DIR/init" ]; then
log " Embedding initramfs from: $INITRAMFS_DIR"
sed -i "s|@INITRAMFS_SOURCE@|${INITRAMFS_DIR}|" "$KERNEL_SRC/.config"
else
warn " Initramfs not found at $INITRAMFS_DIR"
warn " Run build-initramfs.sh first! Disabling embedded initramfs."
sed -i 's|CONFIG_INITRAMFS_SOURCE=.*|CONFIG_INITRAMFS_SOURCE=""|' "$KERNEL_SRC/.config"
fi
# Finalize config
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE olddefconfig
# Verify critical settings
log " Verifying config..."
check_config() {
local key="$1" expected="$2" desc="$3"
local val=$(grep "^${key}=" "$KERNEL_SRC/.config" 2>/dev/null | head -1)
if [ -z "$val" ]; then
val=$(grep "^# ${key} is not set" "$KERNEL_SRC/.config" 2>/dev/null | head -1)
fi
if echo "$val" | grep -q "$expected"; then
log " $desc: OK"
else
warn " $desc: UNEXPECTED ($val)"
fi
}
check_config "CONFIG_DRM_PANFROST" "=m" "Panfrost GPU"
check_config "CONFIG_DRM_PANEL_SITRONIX_ST7703" "=y" "ST7703 panel"
check_config "CONFIG_FRAMEBUFFER_CONSOLE" "=y" "fbcon"
check_config "CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER" "is not set" "No deferred takeover"
check_config "CONFIG_EXT4_FS" "=y" "ext4"
check_config "CONFIG_DEVTMPFS" "=y" "devtmpfs"
log " Kernel configured"
#------------------------------------------------------------------------------
# Step 3: Build Kernel Image
# Step 5: Build Kernel Image
#------------------------------------------------------------------------------
log ""
log "Step 3: Building kernel Image..."
log "Step 5: Building kernel Image..."
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE Image 2>&1 | \
tail -5
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE Image 2>&1 | tail -5
if [ ! -f "$KERNEL_SRC/arch/arm64/boot/Image" ]; then
error "Kernel Image build failed!"
@@ -159,85 +217,104 @@ IMAGE_SIZE=$(du -h "$KERNEL_SRC/arch/arm64/boot/Image" | cut -f1)
log " Kernel Image built ($IMAGE_SIZE)"
#------------------------------------------------------------------------------
# Step 4: Build Device Tree
# Step 6: Build ALL Device Trees
#------------------------------------------------------------------------------
log ""
log "Step 4: Building Device Tree ($R36S_DTB)..."
log "Step 6: Building Device Trees..."
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
"rockchip/${R36S_DTB}.dtb" 2>&1 | tail -5
# Build dtbs target (compiles all DTBs referenced in Makefile)
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE DTC_FLAGS=-@ dtbs 2>&1 | tail -10
if [ ! -f "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${R36S_DTB}.dtb" ]; then
error "DTB build failed: ${R36S_DTB}.dtb"
# Verify R36S DTB was built
if [ ! -f "$KERNEL_DTS_DIR/rk3326-gameconsole-r36s.dtb" ]; then
error "R36S DTB not built!"
fi
log " DTB built: ${R36S_DTB}.dtb"
# Build clone DTB (if DTS was copied)
if [ -f "$CLONE_DTS_DEST" ]; then
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
"rockchip/${CLONE_DTB}.dtb" 2>&1 | tail -5
if [ -f "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dtb" ]; then
log " DTB built (clone): ${CLONE_DTB}.dtb"
else
warn "Clone DTB build failed: ${CLONE_DTB}.dtb"
fi
fi
DTB_COUNT=$(find "$KERNEL_DTS_DIR" -name "rk3326-*.dtb" | wc -l)
log " Built $DTB_COUNT RK3326 DTBs"
#------------------------------------------------------------------------------
# Step 5: Build Kernel Modules
# Step 7: Build Kernel Modules
#------------------------------------------------------------------------------
log ""
log "Step 5: Building kernel modules..."
log "Step 7: Building kernel modules..."
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE modules 2>&1 | \
tail -5
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE modules 2>&1 | tail -5
log " Kernel modules built"
#------------------------------------------------------------------------------
# Step 6: Install to Output Directory
# Step 8: Build Out-of-Tree Drivers
#------------------------------------------------------------------------------
log ""
log "Step 6: Installing artifacts..."
log "Step 8: Building out-of-tree drivers..."
if [ -d "$JOYPAD_DIR" ] && [ -f "$JOYPAD_DIR/Makefile" ]; then
log " Building archr-joypad..."
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
M="$JOYPAD_DIR" modules 2>&1 | tail -5
if find "$JOYPAD_DIR" -name "*.ko" | grep -q .; then
log " archr-joypad: OK"
else
warn " archr-joypad: no .ko files produced"
fi
else
warn " Joypad driver not found at: $JOYPAD_DIR"
fi
#------------------------------------------------------------------------------
# Step 9: Install to Output Directory
#------------------------------------------------------------------------------
log ""
log "Step 9: Installing artifacts..."
mkdir -p "$BOOT_DIR"
mkdir -p "$MODULES_DIR"
# Copy kernel image
cp "$KERNEL_SRC/arch/arm64/boot/Image" "$BOOT_DIR/"
log " Copied: Image"
# Copy kernel image as KERNEL (Arch R naming convention)
cp "$KERNEL_SRC/arch/arm64/boot/Image" "$BOOT_DIR/KERNEL"
log " Copied: KERNEL"
# Copy R36S DTB
cp "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${R36S_DTB}.dtb" "$BOOT_DIR/"
log " Copied: ${R36S_DTB}.dtb"
# Copy ALL RK3326 DTBs to dtbs/ subdirectory
mkdir -p "$BOOT_DIR/dtbs"
for DTB in "$KERNEL_DTS_DIR"/rk3326-*.dtb; do
[ -f "$DTB" ] || continue
cp "$DTB" "$BOOT_DIR/dtbs/"
done
log " Copied: $(ls "$BOOT_DIR/dtbs"/rk3326-*.dtb 2>/dev/null | wc -l) DTBs to dtbs/"
# Copy clone DTB (if built)
if [ -f "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dtb" ]; then
cp "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dtb" "$BOOT_DIR/"
log " Copied: ${CLONE_DTB}.dtb"
fi
# Install modules (use pipefail to catch errors masked by tail)
# Install kernel modules
set -o pipefail
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
INSTALL_MOD_PATH="$MODULES_DIR" \
modules_install 2>&1 | tail -5
set +o pipefail
# Remove symlinks (save space)
# Install joypad driver module
if find "$JOYPAD_DIR" -name "*.ko" | grep -q .; then
KREL=$(cat "$KERNEL_SRC/include/config/kernel.release" 2>/dev/null)
JOYPAD_DEST="$MODULES_DIR/lib/modules/$KREL/extra/archr-joypad"
mkdir -p "$JOYPAD_DEST"
cp "$JOYPAD_DIR"/*.ko "$JOYPAD_DEST/"
log " Installed joypad modules to: extra/archr-joypad/"
# Regenerate modules.dep
depmod -b "$MODULES_DIR" "$KREL"
fi
# Remove build/source symlinks (save space on target)
rm -f "$MODULES_DIR/lib/modules/"*/source 2>/dev/null || true
rm -f "$MODULES_DIR/lib/modules/"*/build 2>/dev/null || true
# Verify critical module was installed
KERNEL_FULL=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null)
KREL=$(cat "$KERNEL_SRC/include/config/kernel.release" 2>/dev/null || echo "$KERNEL_FULL")
if find "$MODULES_DIR/lib/modules/$KREL" -name 'panfrost.ko*' 2>/dev/null | grep -q .; then
log " Panfrost module: INSTALLED"
else
warn " Panfrost module: NOT FOUND in $MODULES_DIR/lib/modules/$KREL/"
warn " Check directory permissions (must be writable by build user)"
fi
# Verify critical modules
KREL=$(cat "$KERNEL_SRC/include/config/kernel.release" 2>/dev/null)
for MOD in panfrost; do
if find "$MODULES_DIR/lib/modules/$KREL" -name "${MOD}.ko*" 2>/dev/null | grep -q .; then
log " Module OK: $MOD"
else
warn " Module MISSING: $MOD"
fi
done
# Note: rockchipdrm is CONFIG_DRM_ROCKCHIP=y (built-in, not a module) — no .ko to check
log " Modules installed"
@@ -250,20 +327,21 @@ log " BUILD COMPLETE"
log "================================================================"
log ""
KERNEL_FULL=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null || echo "$KERNEL_VERSION")
IMAGE_SIZE=$(du -h "$BOOT_DIR/Image" | cut -f1)
DTB_SIZE=$(du -h "$BOOT_DIR/${R36S_DTB}.dtb" | cut -f1)
MODULES_SIZE=$(du -sh "$MODULES_DIR" 2>/dev/null | cut -f1 || echo "N/A")
KERNEL_FULL=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null)
KERNEL_SIZE=$(du -h "$BOOT_DIR/KERNEL" | cut -f1)
MODULES_SIZE=$(du -sh "$MODULES_DIR" 2>/dev/null | cut -f1)
DTB_COUNT=$(ls "$BOOT_DIR/dtbs"/rk3326-*.dtb 2>/dev/null | wc -l)
log "Kernel: $KERNEL_FULL"
log "Kernel: $KERNEL_FULL (mainline + Arch R patches)"
log "KERNEL: $BOOT_DIR/KERNEL ($KERNEL_SIZE)"
log "DTBs: $DTB_COUNT files in $BOOT_DIR/dtbs/"
log "Modules: $MODULES_DIR/ ($MODULES_SIZE)"
log ""
CLONE_DTB_SIZE="N/A"
[ -f "$BOOT_DIR/${CLONE_DTB}.dtb" ] && CLONE_DTB_SIZE=$(du -h "$BOOT_DIR/${CLONE_DTB}.dtb" | cut -f1)
log "Artifacts:"
log " Image: $BOOT_DIR/Image ($IMAGE_SIZE)"
log " DTB: $BOOT_DIR/${R36S_DTB}.dtb ($DTB_SIZE)"
log " DTB clone: $BOOT_DIR/${CLONE_DTB}.dtb ($CLONE_DTB_SIZE)"
log " Modules: $MODULES_DIR/ ($MODULES_SIZE)"
log "Key DTBs:"
for DTB in rk3326-gameconsole-r36s rk3326-odroid-go2 rk3326-gameconsole-r33s; do
if [ -f "$BOOT_DIR/dtbs/${DTB}.dtb" ]; then
log " ${DTB}.dtb ($(du -h "$BOOT_DIR/dtbs/${DTB}.dtb" | cut -f1))"
fi
done
log ""
log "Kernel 6.6 ready for R36S (original + clone)!"
log "Ready for deployment to SD card!"
+240 -46
View File
@@ -123,15 +123,20 @@ log " ✓ Pacman CheckSpace disabled (QEMU chroot compatibility)"
# Add multiple fallback mirrors (default mirror often has stale/404 packages)
cat > "$ROOTFS_DIR/etc/pacman.d/mirrorlist" << 'MIRRORS_EOF'
# Arch Linux ARM mirrors - multiple fallbacks for reliability
Server = http://de.mirror.archlinuxarm.org/$arch/$repo
Server = http://eu.mirror.archlinuxarm.org/$arch/$repo
Server = http://dk.mirror.archlinuxarm.org/$arch/$repo
Server = http://de3.mirror.archlinuxarm.org/$arch/$repo
Server = http://hu.mirror.archlinuxarm.org/$arch/$repo
Server = http://mirror.archlinuxarm.org/$arch/$repo
# Arch Linux ARM mirrors - all official, Americas first
Server = http://fl.us.mirror.archlinuxarm.org/$arch/$repo
Server = http://nj.us.mirror.archlinuxarm.org/$arch/$repo
Server = http://ca.us.mirror.archlinuxarm.org/$arch/$repo
Server = http://eu.mirror.archlinuxarm.org/$arch/$repo
Server = http://de.mirror.archlinuxarm.org/$arch/$repo
Server = http://de4.mirror.archlinuxarm.org/$arch/$repo
Server = http://dk.mirror.archlinuxarm.org/$arch/$repo
Server = http://hu.mirror.archlinuxarm.org/$arch/$repo
Server = http://gr.mirror.archlinuxarm.org/$arch/$repo
Server = http://de3.mirror.archlinuxarm.org/$arch/$repo
Server = http://tw.mirror.archlinuxarm.org/$arch/$repo
Server = http://tw2.mirror.archlinuxarm.org/$arch/$repo
Server = http://mirror.archlinuxarm.org/$arch/$repo
MIRRORS_EOF
log " ✓ Multiple ALARM mirrors configured (fallback for 404s)"
@@ -290,34 +295,33 @@ kernel.sched_latency_ns=1000000
kernel.sched_min_granularity_ns=500000
SYSCTL_EOF
# ZRAM swap — via timer, NOT in multi-user.target!
# Type=oneshot + WantedBy=multi-user.target means systemd WAITS for mkswap to finish
# before reaching multi-user.target. This adds 2.4s to boot critical path.
# Fix: use a timer that fires at boot+15s (ES is already running by then).
cat > /etc/systemd/system/zram-swap.service << 'ZRAM_EOF'
# Memory manager — ZRAM swap with delayed start (15s after boot)
# Timer avoids blocking multi-user.target (ES is already running by then)
cat > /etc/systemd/system/archr-memory-manager.service << 'MEM_SVC'
[Unit]
Description=ZRAM Swap
Description=Arch R Memory Manager
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c 'modprobe zram num_devices=1 2>/dev/null; echo lzo > /sys/block/zram0/comp_algorithm; echo 134217728 > /sys/block/zram0/disksize && mkswap /dev/zram0 && swapon -p 100 /dev/zram0'
ExecStop=/bin/bash -c 'swapoff /dev/zram0 2>/dev/null; echo 1 > /sys/block/zram0/reset 2>/dev/null'
ZRAM_EOF
ExecStart=/usr/local/bin/archr-memory-manager setup
ExecStop=/usr/local/bin/archr-memory-manager stop
ExecReload=/usr/local/bin/archr-memory-manager reload
MEM_SVC
cat > /etc/systemd/system/zram-swap.timer << 'ZRAM_TIMER'
cat > /etc/systemd/system/archr-memory-manager.timer << 'MEM_TIMER'
[Unit]
Description=Delayed ZRAM Swap Setup
Description=Delayed Memory Manager Setup
[Timer]
OnBootSec=15s
Unit=zram-swap.service
Unit=archr-memory-manager.service
[Install]
WantedBy=timers.target
ZRAM_TIMER
MEM_TIMER
systemctl enable zram-swap.timer
systemctl enable archr-memory-manager.timer
# Create directories
mkdir -p /home/archr/.config/retroarch/cores
@@ -368,24 +372,25 @@ FB_EOF
systemctl enable firstboot
# Panel auto-detect wizard (first boot / X-button reset)
cat > /etc/systemd/system/panel-detect.service << 'PANELDET_EOF'
# Variant sync: copies variant marker from BOOT → /etc/archr/variant
# Only runs if /etc/archr/variant doesn't exist yet (no-panel images flashed by Flasher)
cat > /etc/systemd/system/archr-variant-sync.service << 'VARSYNC_EOF'
[Unit]
Description=Arch R Panel Detection Wizard
Description=Sync variant from BOOT partition
After=local-fs.target
Before=emulationstation.service
RequiresMountsFor=/boot
ConditionPathExists=!/etc/archr/variant
[Service]
Type=oneshot
ExecStart=/usr/local/bin/panel-detect.py
TimeoutStartSec=600
ExecStart=/bin/sh -c 'test -f /boot/variant && mkdir -p /etc/archr && cp /boot/variant /etc/archr/variant'
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
PANELDET_EOF
VARSYNC_EOF
systemctl enable panel-detect
systemctl enable archr-variant-sync
# EmulationStation launch — PRIMARY: systemd service (created by build-emulationstation.sh)
# FALLBACK: autologin + .bash_profile (if ES service not installed)
@@ -506,6 +511,127 @@ TIMING_EOF
systemctl enable boot-timing
# Debug dump: comprehensive system info to /boot/debug.log (readable from PC)
cat > /etc/systemd/system/archr-debug-dump.service << 'DEBUG_EOF'
[Unit]
Description=Arch R Debug Dump
After=emulationstation.service
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/bin/bash -c '\
sleep 20; \
{ \
echo "=== Arch R Debug Dump ($(date)) ==="; \
echo ""; \
echo "--- Kernel ---"; \
uname -a; \
echo ""; \
echo "--- Input Devices ---"; \
for d in /dev/input/event*; do \
name=$(cat /sys/class/input/$(basename $d)/device/name 2>/dev/null); \
echo " $d: $name"; \
done; \
echo ""; \
echo "--- DRM ---"; \
for c in /sys/class/drm/card*/status; do \
echo " $c: $(cat $c 2>/dev/null)"; \
done; \
cat /sys/class/drm/card*/modes 2>/dev/null | head -5; \
echo ""; \
echo "--- Backlight ---"; \
for bl in /sys/class/backlight/*/; do \
echo " $(basename $bl): cur=$(cat ${bl}brightness 2>/dev/null) max=$(cat ${bl}max_brightness 2>/dev/null)"; \
done; \
echo ""; \
echo "--- ALSA Controls ---"; \
amixer scontrols 2>/dev/null || echo " (no ALSA)"; \
echo ""; \
echo "--- CPU/GPU ---"; \
echo " CPU: $(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq 2>/dev/null)kHz ($(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_governor 2>/dev/null))"; \
echo " GPU: $(cat /sys/devices/platform/ff400000.gpu/devfreq/ff400000.gpu/cur_freq 2>/dev/null)Hz"; \
echo " Temp: $(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null)"; \
echo ""; \
echo "--- Memory ---"; \
free -h; \
echo ""; \
echo "--- Loaded Modules ---"; \
lsmod 2>/dev/null | head -30; \
echo ""; \
echo "--- Failed Services ---"; \
systemctl --failed --no-pager 2>/dev/null; \
echo ""; \
echo "--- dmesg errors ---"; \
dmesg -l err,warn 2>/dev/null | tail -30; \
} > /boot/debug.log 2>&1; \
chmod 644 /boot/debug.log'
[Install]
WantedBy=multi-user.target
DEBUG_EOF
systemctl enable archr-debug-dump
# USB auto-mount service (triggered by udev on device insertion)
cat > /etc/systemd/system/archr-automount.service << 'AUTOMOUNT_SVC'
[Unit]
Description=Arch R USB Auto-Mount
[Service]
Type=oneshot
ExecStart=/usr/local/bin/archr-automount mount
AUTOMOUNT_SVC
# Save config on shutdown (backs up ALSA state, brightness, WiFi to /boot)
cat > /etc/systemd/system/archr-save-config.service << 'SAVECONF_SVC'
[Unit]
Description=Arch R Save Config
DefaultDependencies=no
Before=shutdown.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/archr-save-config backup
[Install]
WantedBy=shutdown.target
SAVECONF_SVC
systemctl enable archr-save-config
# Bluetooth auto-pairing agent (runs alongside bluetoothd)
cat > /etc/systemd/system/archr-bluetooth-agent.service << 'BTAGENT_SVC'
[Unit]
Description=Arch R Bluetooth Agent
After=bluetooth.service
PartOf=bluetooth.service
[Service]
Type=simple
ExecStart=/usr/local/bin/archr-bluetooth-agent
Restart=on-failure
RestartSec=10
[Install]
WantedBy=bluetooth.target
BTAGENT_SVC
systemctl enable archr-bluetooth-agent
# Sleep configuration (suspend disabled by default, user enables via archr-suspend-mode)
mkdir -p /etc/systemd/sleep.conf.d
cat > /etc/systemd/sleep.conf.d/archr.conf << 'SLEEP_CONF'
[Sleep]
AllowSuspend=yes
SuspendState=mem
AllowHibernation=no
SLEEP_CONF
# Modules blacklist for sleep (unloaded before suspend by archr-sleep hook)
mkdir -p /etc/archr
install -m 644 /tmp/modules.bad /etc/archr/modules.bad 2>/dev/null || true
# Delete stock ALARM initramfs and kernel (we use our own kernel + initramfs)
# Our initramfs.img is built by build-image.sh and placed on BOOT partition
rm -f /boot/initramfs-linux.img /boot/Image /boot/Image.gz 2>/dev/null
@@ -521,7 +647,7 @@ dd if=/dev/urandom of=/var/lib/systemd/random-seed bs=512 count=1 2>/dev/null
chmod 600 /var/lib/systemd/random-seed
# Sudoers for perfmax/perfnorm/pmic-poweroff (allow archr to run without password)
echo "archr ALL=(ALL) NOPASSWD: /usr/local/bin/perfmax, /usr/local/bin/perfnorm, /usr/local/bin/pmic-poweroff, /usr/bin/ln, /usr/bin/dmesg, /usr/bin/chvt, /usr/bin/cp, /usr/bin/chmod, /bin/bash" > /etc/sudoers.d/archr-perf
echo "archr ALL=(ALL) NOPASSWD: /usr/local/bin/perfmax, /usr/local/bin/perfnorm, /usr/local/bin/pmic-poweroff, /usr/local/bin/input-merge, /usr/local/bin/archr-gptokeyb, /usr/local/bin/archr-factory-reset, /usr/local/bin/archr-suspend-mode, /usr/local/bin/archr-usbgadget, /usr/bin/kill, /usr/bin/ln, /usr/bin/dmesg, /usr/bin/chvt, /usr/bin/cp, /usr/bin/chmod, /usr/bin/tee, /usr/bin/systemctl, /bin/bash" > /etc/sudoers.d/archr-perf
chmod 440 /etc/sudoers.d/archr-perf
# Allow archr to use negative nice values (needed for nice -n -19 in ES launch commands)
@@ -572,8 +698,8 @@ cat > /etc/systemd/logind.conf.d/fast.conf << 'LOGIND_EOF'
[Login]
NAutoVTs=1
ReserveVT=0
HandlePowerKey=ignore
HandleSuspendKey=ignore
HandlePowerKey=suspend
HandleSuspendKey=suspend
HandleHibernateKey=ignore
HandleLidSwitch=ignore
KillUserProcesses=no
@@ -669,6 +795,7 @@ for sock in \
systemd-mute-console.socket systemd-bootctl.socket \
systemd-creds.socket systemd-repart.socket \
systemd-importd.socket systemd-machined.socket \
systemd-hostnamed.socket \
systemd-rfkill.socket dm-event.socket \
systemd-coredump.socket systemd-sysext.socket \
systemd-ask-password-wall.socket \
@@ -696,6 +823,9 @@ for rule in 60-cdrom_id 60-dmi-id 60-fido-id 60-infiniband \
ln -sf /dev/null "/etc/udev/rules.d/${rule}.rules"
done
# Allow input group to use /dev/uinput (needed by archr-gptokeyb and input-merge)
echo 'KERNEL=="uinput", GROUP="input", MODE="0660"' > /etc/udev/rules.d/99-archr-uinput.rules
# Pre-build caches NOW (inside chroot) so masks are safe
ldconfig 2>/dev/null || true
journalctl --update-catalog 2>/dev/null || true
@@ -935,6 +1065,9 @@ chmod +x "$ROOTFS_DIR/tmp/setup.sh"
# Copy libvlc stub into chroot (needed by bloat cleanup — ES links against libvlc.so.5)
cp "$SCRIPT_DIR/scripts/libvlc-stub-aarch64.so" "$ROOTFS_DIR/tmp/libvlc-stub.so"
# Copy modules.bad into chroot (installed by setup.sh to /etc/archr/)
cp "$SCRIPT_DIR/config/modules.bad" "$ROOTFS_DIR/tmp/modules.bad"
# Run setup inside chroot
log " Running setup inside chroot..."
chroot "$ROOTFS_DIR" /tmp/setup.sh
@@ -952,8 +1085,32 @@ install -m 755 "$SCRIPT_DIR/scripts/perfmax" "$ROOTFS_DIR/usr/local/bin/perfmax"
install -m 755 "$SCRIPT_DIR/scripts/perfnorm" "$ROOTFS_DIR/usr/local/bin/perfnorm"
install -m 755 "$SCRIPT_DIR/scripts/pmic-poweroff" "$ROOTFS_DIR/usr/local/bin/pmic-poweroff"
install -m 755 "$SCRIPT_DIR/scripts/retroarch-launch.sh" "$ROOTFS_DIR/usr/local/bin/retroarch-launch"
# RetroArch joypad autoconfig (gpio-keys buttons + adc-joystick analog sticks)
# RetroArch core options (per-core tuning for RK3326)
install -m 644 "$SCRIPT_DIR/config/retroarch-core-options.cfg" "$ROOTFS_DIR/home/archr/.config/retroarch/retroarch-core-options.cfg"
log " ✓ RetroArch core options installed"
# Input merger daemon: combines gpio-keys + adc-joystick into single virtual device
# RetroArch needs all inputs on one device (udev driver assigns each to separate port)
if command -v aarch64-linux-gnu-gcc &>/dev/null; then
aarch64-linux-gnu-gcc -static -O2 -o "$ROOTFS_DIR/usr/local/bin/input-merge" \
"$SCRIPT_DIR/scripts/input-merge.c"
chmod 755 "$ROOTFS_DIR/usr/local/bin/input-merge"
log " ✓ input-merge compiled and installed"
# Gamepad-to-keyboard mapper for Linux ports (compatible with ROCKNIX .gptk configs)
aarch64-linux-gnu-gcc -static -O2 -o "$ROOTFS_DIR/usr/local/bin/archr-gptokeyb" \
"$SCRIPT_DIR/scripts/archr-gptokeyb.c"
chmod 755 "$ROOTFS_DIR/usr/local/bin/archr-gptokeyb"
log " ✓ archr-gptokeyb compiled and installed"
else
warn "aarch64-linux-gnu-gcc not found — input-merge/gptokeyb not compiled"
fi
# gptokeyb config files
mkdir -p "$ROOTFS_DIR/etc/archr/gptokeyb"
install -m 644 "$SCRIPT_DIR/config/gptokeyb/default.gptk" "$ROOTFS_DIR/etc/archr/gptokeyb/default.gptk"
install -m 644 "$SCRIPT_DIR/config/gptokeyb/tools.gptk" "$ROOTFS_DIR/etc/archr/gptokeyb/tools.gptk"
log " ✓ gptokeyb configs installed (default + tools)"
# RetroArch joypad autoconfig (merged device + individual fallbacks)
mkdir -p "$ROOTFS_DIR/usr/share/retroarch/autoconfig/udev"
install -m 644 "$SCRIPT_DIR/config/autoconfig/udev/archr-gamepad.cfg" "$ROOTFS_DIR/usr/share/retroarch/autoconfig/udev/"
install -m 644 "$SCRIPT_DIR/config/autoconfig/udev/gpio-keys.cfg" "$ROOTFS_DIR/usr/share/retroarch/autoconfig/udev/"
install -m 644 "$SCRIPT_DIR/config/autoconfig/udev/adc-joystick.cfg" "$ROOTFS_DIR/usr/share/retroarch/autoconfig/udev/"
# systemd shutdown hook — runs pmic-poweroff at the very end of shutdown sequence
@@ -972,6 +1129,40 @@ install -m 755 "$SCRIPT_DIR/scripts/timezones" "$ROOTFS_DIR/usr/local/bin/timezo
install -m 755 "$SCRIPT_DIR/scripts/auto_suspend_update.sh" "$ROOTFS_DIR/usr/local/bin/auto_suspend_update.sh"
log " ✓ ES compatibility scripts installed (timezones, auto_suspend_update.sh)"
# System management scripts
install -m 755 "$SCRIPT_DIR/scripts/archr-automount" "$ROOTFS_DIR/usr/local/bin/archr-automount"
install -m 755 "$SCRIPT_DIR/scripts/archr-usbgadget" "$ROOTFS_DIR/usr/local/bin/archr-usbgadget"
install -m 755 "$SCRIPT_DIR/scripts/archr-bluetooth-agent" "$ROOTFS_DIR/usr/local/bin/archr-bluetooth-agent"
install -m 755 "$SCRIPT_DIR/scripts/archr-factory-reset" "$ROOTFS_DIR/usr/local/bin/archr-factory-reset"
install -m 755 "$SCRIPT_DIR/scripts/archr-suspend-mode" "$ROOTFS_DIR/usr/local/bin/archr-suspend-mode"
install -m 755 "$SCRIPT_DIR/scripts/archr-save-config" "$ROOTFS_DIR/usr/local/bin/archr-save-config"
install -m 755 "$SCRIPT_DIR/scripts/archr-memory-manager" "$ROOTFS_DIR/usr/local/bin/archr-memory-manager"
log " ✓ System management scripts installed"
# System sleep hook (called by systemd on suspend/resume)
mkdir -p "$ROOTFS_DIR/usr/lib/systemd/system-sleep"
install -m 755 "$SCRIPT_DIR/scripts/archr-sleep" "$ROOTFS_DIR/usr/lib/systemd/system-sleep/archr-sleep"
log " ✓ Sleep hook installed"
# ES Tools shared menu library (sourced by tool scripts)
mkdir -p "$ROOTFS_DIR/usr/lib/archr"
install -m 644 "$SCRIPT_DIR/scripts/opt-system/menu-lib.sh" "$ROOTFS_DIR/usr/lib/archr/menu-lib.sh"
# ES Tools menu scripts (shown in ES OPTIONS menu via GuiTools)
mkdir -p "$ROOTFS_DIR/opt/system"
for script in "$SCRIPT_DIR/scripts/opt-system/"*.sh; do
[ -f "$script" ] || continue
[ "$(basename "$script")" = "menu-lib.sh" ] && continue
install -m 755 "$script" "$ROOTFS_DIR/opt/system/$(basename "$script")"
done
log " ✓ ES Tools menu scripts installed (/opt/system/)"
# Udev rules
mkdir -p "$ROOTFS_DIR/etc/udev/rules.d"
install -m 644 "$SCRIPT_DIR/config/udev/99-archr-automount.rules" "$ROOTFS_DIR/etc/udev/rules.d/99-archr-automount.rules"
install -m 644 "$SCRIPT_DIR/config/udev/80-archr-usbgadget.rules" "$ROOTFS_DIR/etc/udev/rules.d/80-archr-usbgadget.rules"
log " ✓ Udev rules installed (automount, usbgadget)"
# Install prebuilt libretro cores (not available in ALARM repos)
PREBUILT_CORES="$SCRIPT_DIR/prebuilt/cores"
if [ -d "$PREBUILT_CORES" ]; then
@@ -995,10 +1186,6 @@ log " ✓ First boot script installed"
# Boot splash: no binary needed in rootfs — splash is embedded in initramfs /init
# (built by build-image.sh: archr-init.c + embedded splash BMP → initramfs.img)
# Panel detection wizard
install -m 755 "$SCRIPT_DIR/scripts/panel-detect.py" "$ROOTFS_DIR/usr/local/bin/panel-detect.py"
log " ✓ Panel detection wizard installed"
# RetroArch config (install to user's config dir where retroarch expects it)
mkdir -p "$ROOTFS_DIR/home/archr/.config/retroarch"
cp "$SCRIPT_DIR/config/retroarch.cfg" "$ROOTFS_DIR/home/archr/.config/retroarch/retroarch.cfg"
@@ -1030,6 +1217,9 @@ log " ✓ Battery LED script installed"
install -m 755 "$SCRIPT_DIR/scripts/archr-hotkeys.py" "$ROOTFS_DIR/usr/local/bin/archr-hotkeys.py"
log " ✓ Hotkey daemon installed"
# Screenshots directory (used by MODE+B hotkey)
mkdir -p "$ROOTFS_DIR/home/archr/screenshots"
# Fix ownership of archr home directory (files installed by root in Step 5)
chown -R 1001:1001 "$ROOTFS_DIR/home/archr"
log " ✓ archr home ownership fixed (UID 1001)"
@@ -1043,18 +1233,22 @@ log "Step 6: Installing kernel and modules..."
KERNEL_BOOT="$OUTPUT_DIR/boot"
KERNEL_MODULES="$OUTPUT_DIR/modules/lib/modules"
if [ -f "$KERNEL_BOOT/Image" ]; then
if [ -f "$KERNEL_BOOT/KERNEL" ]; then
mkdir -p "$ROOTFS_DIR/boot"
cp "$KERNEL_BOOT/Image" "$ROOTFS_DIR/boot/"
log " ✓ Kernel Image installed"
cp "$KERNEL_BOOT/KERNEL" "$ROOTFS_DIR/boot/"
log " ✓ Kernel installed to rootfs/boot/"
# Copy R36S DTB
for dtb in "$KERNEL_BOOT"/*.dtb; do
[ -f "$dtb" ] && cp "$dtb" "$ROOTFS_DIR/boot/" && \
log " ✓ DTB installed: $(basename "$dtb")"
done
# Copy board DTBs (build-image.sh handles BOOT partition separately)
if [ -d "$KERNEL_BOOT/dtbs" ]; then
mkdir -p "$ROOTFS_DIR/boot/dtbs"
for dtb in "$KERNEL_BOOT/dtbs"/rk3326-*.dtb; do
[ -f "$dtb" ] && cp "$dtb" "$ROOTFS_DIR/boot/dtbs/"
done
dtb_count=$(ls "$ROOTFS_DIR/boot/dtbs"/rk3326-*.dtb 2>/dev/null | wc -l)
log "$dtb_count DTBs installed to rootfs/boot/dtbs/"
fi
else
warn "Kernel Image not found. Run build-kernel.sh first!"
warn "Kernel not found at $KERNEL_BOOT/KERNEL. Run build-kernel.sh first!"
fi
if [ -d "$KERNEL_MODULES" ]; then
+1 -1
View File
@@ -2,7 +2,7 @@
#==============================================================================
# Arch R - Build Mainline U-Boot for R36S Clones
#==============================================================================
# Uses mainline U-Boot v2025.10 + ROCKNIX patches
# Uses mainline U-Boot v2025.10 + RK3326 handheld patches
# Produces: idbloader.img, uboot.img, trust.img (Rockchip format)
#
# Usage:
+125 -79
View File
@@ -1,121 +1,163 @@
#!/bin/bash
#==============================================================================
# Arch R - U-Boot Build Script for R36S
# Arch R - Build U-Boot BSP for RK3326
#==============================================================================
# Builds custom U-Boot with R36S original/clone auto-detection via eMMC probe.
# Cross-compiles for aarch64 (CONFIG_ARM64=y in defconfig).
# Builds U-Boot v2017.09 BSP for all RK3326 handhelds.
# Same binary works for both original and clone boards — hwrev.c detects
# board variant via SARADC ch0, boot.ini overrides DTB as needed.
#
# Custom modifications:
# - cmd/hwrev.c: R36S detection via eMMC probe (original vs clone)
# - r36s-uboot.dts: U-Boot display DTB for original (Panel 4-V22 NV3052C)
# - r36s-clone-uboot.dts: U-Boot display DTB for clone (Type5 NV3052C)
# Output: bootloader/u-boot-rk3326/sd_fuse/
# idbloader.img — DDR init + miniloader
# uboot.img — U-Boot proper
# trust.img — ARM Trusted Firmware (BL31 + BL32)
#
# Prerequisites:
# sudo apt install gcc-aarch64-linux-gnu
# Usage:
# ./build-uboot.sh # build for SD card
# ./build-uboot.sh --clean # clean build artifacts first
#==============================================================================
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
UBOOT_DIR="$SCRIPT_DIR/bootloader/u-boot-rk3326"
RKBIN_DIR="$SCRIPT_DIR/bootloader/rkbin"
OUTPUT_DIR="$UBOOT_DIR/sd_fuse"
# Firmware versions (from rkbin)
DDR_BIN="$RKBIN_DIR/bin/rk33/rk3326_ddr_333MHz_v2.11.bin"
MINILOADER_BIN="$RKBIN_DIR/bin/rk33/rk3326_miniloader_v1.40.bin"
BL31_ELF="$RKBIN_DIR/bin/rk33/rk3326_bl31_v1.34.elf"
BL32_BIN="$RKBIN_DIR/bin/rk33/rk3326_bl32_v2.19.bin"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m'
log() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1"; }
warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] WARNING:${NC} $1"; }
error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $1"; exit 1; }
log() { echo -e "${GREEN}[U-BOOT]${NC} $1"; }
warn() { echo -e "${YELLOW}[U-BOOT] WARNING:${NC} $1"; }
error() { echo -e "${RED}[U-BOOT] ERROR:${NC} $1"; exit 1; }
#------------------------------------------------------------------------------
# Configuration
# Parse arguments
#------------------------------------------------------------------------------
UBOOT_DIR="$SCRIPT_DIR/bootloader"
UBOOT_REPO="https://github.com/christianhaitian/RG351MP-u-boot"
UBOOT_SRC="$UBOOT_DIR/u-boot-rk3326"
OUTPUT_DIR="$SCRIPT_DIR/output/bootloader"
# U-Boot for RK3326 is aarch64 (CONFIG_ARM64=y in defconfig)
CROSS_COMPILE="aarch64-linux-gnu-"
log "=== Arch R - U-Boot Builder (Custom R36S) ==="
CLEAN=false
while [[ $# -gt 0 ]]; do
case $1 in
--clean) CLEAN=true; shift ;;
*) error "Unknown option: $1\nUsage: $0 [--clean]" ;;
esac
done
#------------------------------------------------------------------------------
# Step 1: Clone U-Boot
# Prerequisites
#------------------------------------------------------------------------------
log ""
log "Step 1: Checking U-Boot source..."
log "=== Arch R U-Boot Builder ==="
mkdir -p "$UBOOT_DIR"
if ! command -v aarch64-linux-gnu-gcc &>/dev/null; then
error "Cross-compiler not found. Install with: sudo apt install gcc-aarch64-linux-gnu"
fi
if [ ! -d "$UBOOT_SRC" ]; then
log " Cloning U-Boot for RK3326..."
git clone --depth 1 "$UBOOT_REPO" "$UBOOT_SRC"
log " Cloned"
else
log " Source exists"
if [ ! -d "$UBOOT_DIR" ]; then
error "U-Boot source not found at: $UBOOT_DIR"
fi
if [ ! -f "$DDR_BIN" ]; then
error "rkbin firmware not found at: $RKBIN_DIR\nExpected: $DDR_BIN"
fi
GCC_VER=$(aarch64-linux-gnu-gcc -dumpversion)
log "Compiler: aarch64-linux-gnu-gcc $GCC_VER"
#------------------------------------------------------------------------------
# Clean (optional)
#------------------------------------------------------------------------------
if [ "$CLEAN" = true ]; then
log "Cleaning previous build..."
make -C "$UBOOT_DIR" distclean 2>/dev/null || true
rm -rf "$OUTPUT_DIR"
fi
#------------------------------------------------------------------------------
# Step 2: Verify toolchain
# Build U-Boot
#------------------------------------------------------------------------------
log ""
log "Step 2: Checking toolchain..."
log "Step 1: Configuring (odroidgoa_defconfig)..."
if ! command -v ${CROSS_COMPILE}gcc &>/dev/null; then
error "aarch64 toolchain not found!\n Install: sudo apt install gcc-aarch64-linux-gnu"
cd "$UBOOT_DIR"
# GCC 13+ needs these warnings suppressed for 2017.09 codebase
export KCFLAGS="-Wno-error=array-bounds -Wno-error=enum-int-mismatch -Wno-error=implicit-function-declaration -Wno-error=format-overflow"
make odroidgoa_defconfig 2>&1 | tail -3
log "Step 2: Building U-Boot..."
NCPUS=$(nproc 2>/dev/null || echo 4)
make CROSS_COMPILE=aarch64-linux-gnu- all --jobs=$NCPUS 2>&1 | tail -5
if [ ! -f "u-boot.bin" ]; then
error "Build failed — u-boot.bin not found"
fi
log " $(${CROSS_COMPILE}gcc --version | head -1)"
log " u-boot.bin built OK"
#------------------------------------------------------------------------------
# Step 3: Build U-Boot
# Pack images
#------------------------------------------------------------------------------
log ""
log "Step 3: Building U-Boot..."
cd "$UBOOT_SRC"
# GCC 13+ adds stricter warnings that U-Boot 2017.09 doesn't pass.
# Disable specific -Werror flags that break with modern GCC:
# address-of-packed-member: disk/part_efi.c (packed struct pointer)
# enum-int-mismatch: common/command.c (enum command_ret_t vs int)
# maybe-uninitialized: common/edid.c (hdmi_len variable)
GCC_COMPAT_FLAGS="-Wno-error=address-of-packed-member -Wno-error=enum-int-mismatch -Wno-error=maybe-uninitialized"
make CROSS_COMPILE=$CROSS_COMPILE odroidgoa_defconfig
make CROSS_COMPILE=$CROSS_COMPILE KCFLAGS="$GCC_COMPAT_FLAGS" -j$(nproc)
log " Built"
#------------------------------------------------------------------------------
# Step 4: Copy artifacts
#------------------------------------------------------------------------------
log ""
log "Step 4: Copying bootloader files..."
log "Step 3: Packing images..."
mkdir -p "$OUTPUT_DIR"
if [ -d "sd_fuse" ] && [ -f "sd_fuse/idbloader.img" ]; then
cp sd_fuse/idbloader.img "$OUTPUT_DIR/"
cp sd_fuse/uboot.img "$OUTPUT_DIR/"
cp sd_fuse/trust.img "$OUTPUT_DIR/"
log " Bootloader binaries copied"
else
error "sd_fuse directory not found — U-Boot build may have failed"
fi
# idbloader.img = DDR init + miniloader
"$UBOOT_DIR/tools/mkimage" -n px30 -T rksd -d "$DDR_BIN" "$OUTPUT_DIR/idbloader.img"
cat "$MINILOADER_BIN" >> "$OUTPUT_DIR/idbloader.img"
log " idbloader.img (DDR v2.11 + miniloader v1.40)"
# Copy R36S U-Boot DTBs
for dtb in r36s-uboot.dtb r36s-clone-uboot.dtb; do
if [ -f "arch/arm/dts/$dtb" ]; then
cp "arch/arm/dts/$dtb" "$OUTPUT_DIR/"
log " DTB copied: $dtb"
else
warn "DTB not found: $dtb"
# uboot.img = packed U-Boot binary
UBOOT_LOAD_ADDR=$(grep -r "CONFIG_SYS_TEXT_BASE" include/autoconf.mk 2>/dev/null | cut -d= -f2 || echo "0x00200000")
"$RKBIN_DIR/tools/loaderimage" --pack --uboot u-boot.bin "$OUTPUT_DIR/uboot.img" "$UBOOT_LOAD_ADDR" 2>&1 | tail -1
log " uboot.img (load addr: $UBOOT_LOAD_ADDR)"
# trust.img = BL31 + BL32
cat > /tmp/archr-trust.ini << TRUST_EOF
[VERSION]
MAJOR=1
MINOR=0
[BL30_OPTION]
SEC=0
[BL31_OPTION]
SEC=1
PATH=$BL31_ELF
ADDR=0x00010000
[BL32_OPTION]
SEC=1
PATH=$BL32_BIN
ADDR=0x08400000
[BL33_OPTION]
SEC=0
[OUTPUT]
PATH=$OUTPUT_DIR/trust.img
TRUST_EOF
"$RKBIN_DIR/tools/trust_merger" --rsa 3 /tmp/archr-trust.ini 2>&1 | tail -1
rm -f /tmp/archr-trust.ini
log " trust.img (BL31 v1.34 + BL32 v2.19)"
#------------------------------------------------------------------------------
# Verify
#------------------------------------------------------------------------------
log ""
log "Step 4: Verifying..."
for img in idbloader.img uboot.img trust.img; do
if [ ! -f "$OUTPUT_DIR/$img" ]; then
error "Missing: $OUTPUT_DIR/$img"
fi
SIZE=$(du -h "$OUTPUT_DIR/$img" | cut -f1)
log " $img ($SIZE)"
done
#------------------------------------------------------------------------------
@@ -124,7 +166,11 @@ done
log ""
log "=== U-Boot Build Complete ==="
log ""
log "Bootloader: $OUTPUT_DIR/"
ls -lh "$OUTPUT_DIR/"
log "Output: $OUTPUT_DIR/"
log " idbloader.img — DDR v2.11 + miniloader v1.40"
log " uboot.img — U-Boot v2017.09 BSP"
log " trust.img — BL31 v1.34 + BL32 v2.19"
log ""
log "These will be installed by build-image.sh"
log "Same binary for both original and clone images."
log "Board detection: hwrev.c (SARADC ch0)"
log "DTB selection: boot.ini (variant A or B)"
+61
View File
@@ -0,0 +1,61 @@
odroidgoa-uboot-config
########################################################################
# Arch R Boot Configuration — Variant A (BSP U-Boot)
#
# For: Original R36S, OGA, OGA v1.1, OGS, R33S, RG351V, RG351M,
# GameForce Chi, MagicX XU10
#
# BSP U-Boot reads this file directly.
# hwrev is set by BSP's hwrev.c from SARADC ch0 before this runs.
#
# We ALWAYS load our DTB from partition (not U-Boot embedded) because
# our DTBs have archr-* compatible strings for joypad/panel drivers.
########################################################################
# Memory addresses
setenv loadaddr "0x02000000"
setenv dtb_loadaddr "0x01f00000"
setenv dtbo_loadaddr "0x01e00000"
# Load kernel
load mmc 1:1 ${loadaddr} KERNEL
# Map hwrev to board DTB (always load from partition)
if test ${hwrev} = 'v10-go3'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-odroid-go3.dtb
elif test ${hwrev} = 'r33s'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-gameconsole-r33s.dtb
elif test ${hwrev} = 'chi'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-gameforce-chi.dtb
elif test ${hwrev} = 'rg351v'; then
gpio input b6
if test $? -eq 0; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-anbernic-rg351v.dtb
else
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-gameconsole-r36s.dtb
fi
elif test ${hwrev} = 'v11'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-odroid-go2-v11.dtb
elif test ${hwrev} = 'v10'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-odroid-go2.dtb
elif test ${hwrev} = 'xu10'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-magicx-xu10.dtb
else
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-odroid-go2.dtb
fi
# Apply panel overlay
if load mmc 1:1 ${dtbo_loadaddr} overlays/mipi-panel.dtbo; then
fdt addr ${dtb_loadaddr}
fdt resize 8192
fdt apply ${dtbo_loadaddr}
fi
# Boot
setenv bootargs "boot=LABEL=BOOT disk=LABEL=STORAGE rw console=ttyS2,115200 console=tty0 quiet loglevel=0 vt.global_cursor_default=0 consoleblank=0 fsck.mode=skip"
booti ${loadaddr} - ${dtb_loadaddr}
# Power off if boot fails
sleep 15
poweroff
+12 -4
View File
@@ -67,16 +67,19 @@ CONFIG_DRM_PANFROST=m
# ============================================================
# Framebuffer: fb0 via DRM emulation + fbcon
# DEFERRED_TAKEOVER=y: fbcon waits for text output before clearing
# screen. With quiet+ttyFIQ0, U-Boot logo persists until Plymouth
# takes DRM master. Plymouth handles splash via KMS/DRM natively.
# DEFERRED_TAKEOVER DISABLED: With deferred takeover, fbcon does
# NOT trigger DRM modeset until text is written to console.
# On clone R36S (mainline U-Boot, no BSP display init), this
# means display stays BLACK. ROCKNIX explicitly disables this.
# FRAMEBUFFER_CONSOLE_ROTATION: Display rotation support.
# ============================================================
CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_FBDEV_OVERALLOC=200
CONFIG_FB=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set
# CONFIG_LOGO is not set
# ============================================================
@@ -209,6 +212,11 @@ CONFIG_DEBUG_INFO_NONE=y
# CONFIG_MEDIA_TEST_SUPPORT is not set
# CONFIG_DVB_CORE is not set
# ============================================================
# Panel driver: Arch R Generic DSI (panel_description strings)
# ============================================================
CONFIG_DRM_PANEL_ARCHR_DSI=y
# ============================================================
# SIZE TRIM: Display drivers — R36S uses ONLY MIPI DSI (~500KB-1MB)
# ============================================================
+10
View File
@@ -0,0 +1,10 @@
# Arch R fragment — applied on top of ROCKNIX base config
# Only contains overrides specific to Arch Linux
# Initramfs: embedded in kernel (path set by build-kernel.sh)
# CONFIG_INITRAMFS_SOURCE is set dynamically
# Compression
CONFIG_INITRAMFS_COMPRESSION_GZIP=y
CONFIG_INITRAMFS_ROOT_UID=0
CONFIG_INITRAMFS_ROOT_GID=0
+73
View File
@@ -0,0 +1,73 @@
# Arch R Gamepad (merged gpio-keys + adc-joystick)
# Created by input-merge daemon — combines buttons and analog sticks
# into a single virtual device for RetroArch.
input_driver = "udev"
input_device = "Arch R Gamepad"
input_device_display_name = "Arch R Gamepad"
# Face buttons
input_b_btn = "0"
input_a_btn = "1"
input_y_btn = "2"
input_x_btn = "3"
# Shoulders
input_l_btn = "4"
input_r_btn = "5"
input_l2_btn = "6"
input_r2_btn = "7"
# Select / Start / Hotkey
input_select_btn = "8"
input_start_btn = "9"
input_enable_hotkey_btn = "10"
# Thumbstick clicks
input_l3_btn = "11"
input_r3_btn = "12"
# D-Pad
input_up_btn = "13"
input_down_btn = "14"
input_left_btn = "15"
input_right_btn = "16"
# Left analog stick
input_l_x_plus_axis = "+0"
input_l_x_minus_axis = "-0"
input_l_y_plus_axis = "+1"
input_l_y_minus_axis = "-1"
# Right analog stick
input_r_x_plus_axis = "+2"
input_r_x_minus_axis = "-2"
input_r_y_plus_axis = "+3"
input_r_y_minus_axis = "-3"
# Labels
input_b_btn_label = "B"
input_a_btn_label = "A"
input_y_btn_label = "Y"
input_x_btn_label = "X"
input_l_btn_label = "L1"
input_r_btn_label = "R1"
input_l2_btn_label = "L2"
input_r2_btn_label = "R2"
input_select_btn_label = "Select"
input_start_btn_label = "Start"
input_enable_hotkey_btn_label = "Mode"
input_l3_btn_label = "L3"
input_r3_btn_label = "R3"
input_up_btn_label = "D-Pad Up"
input_down_btn_label = "D-Pad Down"
input_left_btn_label = "D-Pad Left"
input_right_btn_label = "D-Pad Right"
input_l_x_plus_axis_label = "LS Right"
input_l_x_minus_axis_label = "LS Left"
input_l_y_plus_axis_label = "LS Down"
input_l_y_minus_axis_label = "LS Up"
input_r_x_plus_axis_label = "RS Right"
input_r_x_minus_axis_label = "RS Left"
input_r_y_plus_axis_label = "RS Down"
input_r_y_minus_axis_label = "RS Up"
+48
View File
@@ -0,0 +1,48 @@
odroidgoa-uboot-config
########################################################################
# Arch R Boot Configuration — Variant B (Clone boards)
#
# For: K36 clones, Powkiddy RGB20S, Powkiddy RGB10X, MagicX XU-Mini-M
#
# hwrev is set by U-Boot's board file from SARADC ch0 before this runs.
# This script overrides the kernel DTB for boards that need a different
# DTB than what U-Boot loaded internally.
#
# hwrev mappings (clone boards):
# r33s = Powkiddy RGB10X (shares ADC range with R33S)
# xu10 = MagicX XU-Mini-M (shares ADC range with XU10)
# rg351v = K36 clone / R36Max / EE clone boards
########################################################################
# Memory addresses
setenv loadaddr "0x02000000"
setenv dtb_loadaddr "0x01f00000"
setenv dtbo_loadaddr "0x01e00000"
# Load kernel
load mmc 1:1 ${loadaddr} KERNEL
# Override DTB for clone boards
if test ${hwrev} = 'r33s'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-powkiddy-rgb10x.dtb
elif test ${hwrev} = 'xu10'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-magicx-xu-mini-m.dtb
elif test ${hwrev} = 'rg351v'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-gameconsole-r36max.dtb
fi
# Apply panel overlay
if load mmc 1:1 ${dtbo_loadaddr} overlays/mipi-panel.dtbo; then
fdt addr ${dtb_loadaddr}
fdt resize 8192
fdt apply ${dtbo_loadaddr}
fi
# Boot
setenv bootargs "boot=LABEL=BOOT disk=LABEL=STORAGE rw console=ttyS2,115200 console=tty0 quiet loglevel=0 vt.global_cursor_default=0 consoleblank=0 fsck.mode=skip"
booti ${loadaddr} - ${dtb_loadaddr}
# Power off if boot fails
sleep 15
poweroff
-67
View File
@@ -1,67 +0,0 @@
odroidgoa-uboot-config
########################################################################
# Arch R Boot Configuration
#
# Auto-detects SD card MMC device:
# Original R36S: eMMC=mmc0, SD=mmc1
# Clone (no eMMC): SD=mmc0
#
# Root device (__ROOTDEV__) substituted by build-image.sh per variant.
# Panel config from panel.txt (managed by panel-detect.py).
# Panel reset handled in Linux (panel-detect.py) -- no GPIO check here
# because X button GPIO differs between boards (modular!).
########################################################################
# --- Turn on LED immediately (feedback: device is booting) ---
gpio set b5
setenv tmp_loadaddr "0x01e00000"
setenv dtb_loadaddr "0x01f00000"
setenv loadaddr "0x02000000"
# --- Auto-detect MMC device (loads kernel Image into memory) ---
setenv mmcdev 1
if load mmc 1:1 ${loadaddr} Image; then
setenv mmcdev 1
elif load mmc 0:1 ${loadaddr} Image; then
setenv mmcdev 0
else
sleep 15
poweroff
fi
# --- Panel DTB selection (read panel.txt written by panel-detect.py) ---
# Pre-merged DTBs: overlay already applied at build-time (no fdt apply needed).
# panel.txt contains PanelDTB=kernel-panelN.dtb (or empty for default).
setenv PanelDTB ""
mw.b ${tmp_loadaddr} 0x00 0x400
if load mmc ${mmcdev}:1 ${tmp_loadaddr} panel.txt; then
env import -t ${tmp_loadaddr} ${filesize}
fi
# Select DTB: pre-merged panel DTB if set, otherwise default kernel.dtb
if test -n "${PanelDTB}"; then
setenv dtb_name "${PanelDTB}"
echo "Panel DTB: ${PanelDTB}"
else
setenv dtb_name "kernel.dtb"
fi
# --- Load DTB and boot (Image already loaded above) ---
if load mmc ${mmcdev}:1 ${dtb_loadaddr} ${dtb_name}; then
setenv bootargs "root=__ROOTDEV__ rootwait rw console=ttyFIQ0 loglevel=0 quiet vt.global_cursor_default=0 consoleblank=0 printk.devkmsg=off fsck.mode=skip"
# Load initramfs (splash appears immediately after kernel boot, before systemd)
setenv initrd_loadaddr "0x04000000"
if load mmc ${mmcdev}:1 ${initrd_loadaddr} initramfs.img; then
booti ${loadaddr} ${initrd_loadaddr}:${filesize} ${dtb_loadaddr}
else
booti ${loadaddr} - ${dtb_loadaddr}
fi
fi
# Power off if boot fails
sleep 15
poweroff
+36
View File
@@ -0,0 +1,36 @@
# Arch R — Default gamepad-to-keyboard mapping
# Used by archr-gptokeyb for Linux ports that need keyboard input.
# Per-game overrides: /etc/archr/gptokeyb/<game>.gptk
# Format: button_name = key_name (compatible with ROCKNIX .gptk)
# Action buttons
a = space
b = backspace
x = c
y = v
# Shoulder buttons
l1 = a
r1 = s
l2 = q
r2 = e
# Menu
back = esc
start = enter
guide = f1
# D-pad
up = up
down = down
left = left
right = right
# Left analog → mouse movement
left_analog_as_mouse = true
# Right analog → arrow keys
right_analog_up = up
right_analog_down = down
right_analog_left = left
right_analog_right = right
+20
View File
@@ -0,0 +1,20 @@
# Arch R — Gamepad mapping for system tools (menus)
# D-pad navigates, A=select, B=back, Start=select, Back=back
# D-pad → arrow keys for menu navigation
up = up
down = down
left = left
right = right
# A button → Enter (select/confirm)
a = enter
# B button → Escape (back/cancel)
b = escape
# Start → Enter (alternate confirm)
start = enter
# Back/Select → Escape (alternate back)
back = escape

Some files were not shown because too many files have changed in this diff Show More