17 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
Douglas Teles a1efd4fc01 Pre-merged panel DTBs: eliminate U-Boot fdt apply bugs
Users reported that non-default panel overlays caused broken display,
audio, and controls. Root cause: BSP U-Boot's fdt apply has bugs with
property replacement of different-sized data, corrupting the DTB.

Fix: apply overlays at build-time using fdtoverlay (verified working)
instead of at boot-time. Each panel now gets a pre-merged kernel-*.dtb.
U-Boot simply loads the right DTB by name — no fdt apply needed.

- generate-panel-dtbos.sh: add fdtoverlay pre-merge step
- build-image.sh: copy pre-merged DTBs instead of ScreenFiles
- boot.ini: load PanelDTB by name, remove fdt addr/resize/apply
- panel-detect.py: write DTB filename instead of DTBO overlay path
2026-02-28 00:14:54 -03:00
Douglas Teles e4294ab47b Two-image build pipeline, clone support, initramfs splash
- Clone variant: mainline U-Boot v2025.10, boot.scr, clone DTS (type5)
- Initramfs splash: archr-init.c with embedded BMP, sub-second display
- Panel wizard: auto-detect with fsync persistence, evdev X-button reset
- Hotkeys: adc-keys volume for clone, HP jack detection, brightness persist
- Boot.ini: ASCII-only (no Unicode), GPIO check removed
- ES wrapper: removed framebuffer blanking (preserves splash)
- Build pipeline: both variants, splash generation, panel DTBOs
- .gitignore: exclude large bootloader trees and build artifacts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 22:38:47 -03:00
Douglas Teles 70765e96bd update 26.02.25 2026-02-25 17:22:34 -03:00
Douglas Teles 2ccf5383ac update 26.02.23 2026-02-23 03:03:09 -03:00
Douglas Teles 476b05cd9a fix roadmap 2026-02-22 14:46:19 -03:00
Douglas Teles a9029b419f Fix ROADMAP.md diary timeline ordering
Move Day 17-18 entry to correct chronological position
(before "What's Left for v1.0 Stable", not after it).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:43:37 -03:00
146 changed files with 69514 additions and 1369 deletions
+34
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
@@ -71,3 +85,23 @@ restore-mesa26-gbm.sh
# Website (separate project)
website/
# Environment secrets
.env
# Bootloader source trees (cloned/downloaded during build)
bootloader/rkbin/
bootloader/u-boot-mainline/
bootloader/u-boot-rk3326-clone/
# Pre-built U-Boot backups (working binaries, not part of build pipeline)
bootloader/u-boot-clone-working/
# Extracted DTBs (debugging artifacts)
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
+164 -63
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,29 +173,101 @@ 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:
Arch R separates **board configuration** from **panel configuration**:
**Original R36S:** Panel 0, Panel 1 (V10), Panel 2 (V12), Panel 3 (V20), Panel 4 (V22, default), Panel 5 (V22 Q8)
- **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.
**Clones:** Clone Panel 1-10 (ST7703, NV3051D variants), R36 Max, RX6S
This means the same image works on all boards of a variant — only the panel overlay needs to match your specific display.
### Supported Boards
| 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 |
### Supported Panels
#### 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
Mount the BOOT partition and copy the correct overlay as `mipi-panel.dtbo`:
```bash
sudo mount /dev/sdX1 /mnt
# Example: set Panel 4-V22 (most common original R36S panel)
sudo cp /mnt/overlays/panel4-v22.dtbo /mnt/overlays/mipi-panel.dtbo
# Example: set Clone 8 (most common clone panel)
sudo cp /mnt/overlays/clone_panel_8.dtbo /mnt/overlays/mipi-panel.dtbo
sudo umount /mnt
sync
```
## Boot Flow
```
Power On
→ U-Boot (idbloader → trust → uboot.img)
logo.bmp displayed on screen
extlinux/extlinux.conf loaded (primary)
→ Kernel 6.6.89 + rk3326-gameconsole-r36s.dtb
→ 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
+824 -153
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
Submodule bootloader/u-boot-rk3326 updated: 5606e804ff...2492a3e467
+38 -4
View File
@@ -44,6 +44,7 @@ usage() {
echo "Options:"
echo " --kernel Build kernel only"
echo " --rootfs Build rootfs only"
echo " --uboot Build U-Boot only"
echo " --image Build image only"
echo " --all Build everything (default)"
echo " --clean Clean all build artifacts"
@@ -53,6 +54,7 @@ usage() {
BUILD_KERNEL=false
BUILD_ROOTFS=false
BUILD_UBOOT=false
BUILD_IMAGE=false
CLEAN=false
@@ -60,14 +62,16 @@ CLEAN=false
if [ $# -eq 0 ]; then
BUILD_KERNEL=true
BUILD_ROOTFS=true
BUILD_UBOOT=true
BUILD_IMAGE=true
else
while [[ $# -gt 0 ]]; do
case $1 in
--kernel) BUILD_KERNEL=true; shift ;;
--rootfs) BUILD_ROOTFS=true; shift ;;
--uboot) BUILD_UBOOT=true; shift ;;
--image) BUILD_IMAGE=true; shift ;;
--all) BUILD_KERNEL=true; BUILD_ROOTFS=true; BUILD_IMAGE=true; shift ;;
--all) BUILD_KERNEL=true; BUILD_ROOTFS=true; BUILD_UBOOT=true; BUILD_IMAGE=true; shift ;;
--clean) CLEAN=true; shift ;;
--help) usage; exit 0 ;;
*) error "Unknown option: $1" ;;
@@ -125,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"
@@ -180,13 +192,35 @@ log "═════════════════════════
chmod +x "$SCRIPT_DIR/scripts/generate-panel-dtbos.sh"
"$SCRIPT_DIR/scripts/generate-panel-dtbos.sh"
# 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 ""
log "═══════════════════════════════════════════════════════════════"
log " BUILDING U-BOOT"
log "═══════════════════════════════════════════════════════════════"
chmod +x "$SCRIPT_DIR/build-uboot.sh"
"$SCRIPT_DIR/build-uboot.sh"
else
warn "Skipping U-Boot build: aarch64-linux-gnu-gcc not found"
warn "Install: sudo apt install gcc-aarch64-linux-gnu"
fi
fi
if [ "$BUILD_IMAGE" = true ]; then
chmod +x "$SCRIPT_DIR/build-image.sh"
log ""
log "═══════════════════════════════════════════════════════════════"
log " BUILDING IMAGE"
log " BUILDING IMAGE (original)"
log "═══════════════════════════════════════════════════════════════"
chmod +x "$SCRIPT_DIR/build-image.sh"
"$SCRIPT_DIR/build-image.sh"
"$SCRIPT_DIR/build-image.sh" --variant original
log ""
log "═══════════════════════════════════════════════════════════════"
log " BUILDING IMAGE (clone)"
log "═══════════════════════════════════════════════════════════════"
"$SCRIPT_DIR/build-image.sh" --variant clone
fi
#------------------------------------------------------------------------------
+154 -162
View File
@@ -3,7 +3,18 @@
#==============================================================================
# Arch R - SD Card Image Builder
#==============================================================================
# Creates a flashable SD card image for R36S
# 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 # 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
@@ -20,18 +31,52 @@ 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; }
#------------------------------------------------------------------------------
# Parse arguments
#------------------------------------------------------------------------------
VARIANT="original"
while [[ $# -gt 0 ]]; do
case $1 in
--variant)
VARIANT="$2"
shift 2
;;
*)
error "Unknown option: $1\nUsage: $0 --variant original|clone"
;;
esac
done
if [ "$VARIANT" != "original" ] && [ "$VARIANT" != "clone" ]; then
error "Invalid variant: $VARIANT (must be 'original' or 'clone')"
fi
#------------------------------------------------------------------------------
# Variant-specific configuration
#------------------------------------------------------------------------------
if [ "$VARIANT" = "original" ]; then
IMAGE_SUFFIX="R36S"
BOOT_INI="$SCRIPT_DIR/config/a_boot.ini"
else
IMAGE_SUFFIX="R36S-clone"
BOOT_INI="$SCRIPT_DIR/config/b_boot.ini"
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-R36S-$(date +%Y%m%d).img"
IMAGE_NAME="ArchR-${IMAGE_SUFFIX}-$(date +%Y%m%d).img"
# CRITICAL: Always clean up loop devices and mounts on exit (success OR failure).
# Without this trap, a build error leaves loop devices and mounts dangling —
# loop device holds the image file, mounts prevent cleanup.
# Cleanup on exit
LOOP_DEV=""
cleanup_image() {
echo "[IMAGE] Cleaning up mounts and loop devices..."
@@ -44,14 +89,11 @@ 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
# ROMS partition will use remaining space on actual SD card
BOOT_SIZE=128
ROOTFS_SIZE=6144
IMAGE_SIZE=$((BOOT_SIZE + ROOTFS_SIZE + 32))
# Total image size
IMAGE_SIZE=$((BOOT_SIZE + ROOTFS_SIZE + 32)) # +32MB for partition table
log "=== Arch R Image Builder ==="
log "=== Arch R Image Builder (variant: $VARIANT) ==="
#------------------------------------------------------------------------------
# Root check
@@ -67,31 +109,54 @@ log ""
log "Step 1: Checking prerequisites..."
if [ ! -d "$ROOTFS_DIR" ]; then
error "Rootfs not found at: $ROOTFS_DIR"
error "Run build-rootfs.sh first!"
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
# Validate kernel Image size (kernel 6.6 trimmed is ~18MB, stale 4.4 was ~5MB)
IMAGE_BYTES=$(stat -c%s "$ROOTFS_DIR/boot/Image")
if [ "$IMAGE_BYTES" -lt 10000000 ]; then
warn "Kernel Image is only $(($IMAGE_BYTES / 1024 / 1024))MB — expected ~18MB for kernel 6.6!"
warn "This may be a stale kernel 4.4 build. Run build-kernel.sh first."
error "Aborting: kernel Image too small (likely wrong version)"
fi
log " Kernel Image: $(($IMAGE_BYTES / 1024 / 1024))MB (OK)"
log " Kernel modules: OK"
fi
# Check required tools
# 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
fi
# 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"
# Tools
for tool in parted mkfs.vfat mkfs.ext4 losetup; do
if ! command -v $tool &> /dev/null; then
error "Required tool not found: $tool"
fi
done
log " Prerequisites OK"
log " Prerequisites OK"
#------------------------------------------------------------------------------
# Step 2: Create Image File
@@ -100,97 +165,54 @@ log ""
log "Step 2: Creating image file..."
mkdir -p "$IMAGE_DIR"
rm -f "$IMAGE_DIR"/ArchR-${IMAGE_SUFFIX}-*.img "$IMAGE_DIR"/ArchR-${IMAGE_SUFFIX}-*.img.xz
# Remove old images (current date and any previous builds)
rm -f "$IMAGE_DIR"/ArchR-R36S-*.img "$IMAGE_DIR"/ArchR-R36S-*.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"
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..."
# Search for U-Boot binaries — prefer R36S-u-boot-builder (known working)
UBOOT_DIR=""
for dir in "$SCRIPT_DIR/bootloader/u-boot-r36s-working" \
"$OUTPUT_DIR/bootloader" \
"$SCRIPT_DIR/bootloader/u-boot-rk3326/sd_fuse" \
"$SCRIPT_DIR/bootloader/sd_fuse"; do
if [ -f "$dir/idbloader.img" ] && [ -f "$dir/uboot.img" ] && [ -f "$dir/trust.img" ]; then
UBOOT_DIR="$dir"
break
fi
done
if [ -n "$UBOOT_DIR" ]; then
dd if="$UBOOT_DIR/idbloader.img" of="$IMAGE_FILE" bs=512 seek=64 conv=sync,noerror,notrunc 2>/dev/null
dd if="$UBOOT_DIR/uboot.img" of="$IMAGE_FILE" bs=512 seek=16384 conv=sync,noerror,notrunc 2>/dev/null
dd if="$UBOOT_DIR/trust.img" of="$IMAGE_FILE" bs=512 seek=24576 conv=sync,noerror,notrunc 2>/dev/null
log " ✓ U-Boot installed from $UBOOT_DIR"
else
warn "U-Boot files not found!"
warn "Run build-uboot.sh first for bootable image!"
fi
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"
#------------------------------------------------------------------------------
# Step 3: Create Partitions
# Step 4: Create and Format Partitions
#------------------------------------------------------------------------------
log ""
log "Step 3: Creating partitions..."
log "Step 4: Creating partitions..."
# Create partition table
parted -s "$IMAGE_FILE" mklabel msdos
# Calculate partition boundaries
BOOT_START=16 # Start at 16MB for U-Boot space
BOOT_START=16
BOOT_END=$((BOOT_START + BOOT_SIZE))
ROOTFS_START=$BOOT_END
ROOTFS_END=$((ROOTFS_START + ROOTFS_SIZE))
# Create partitions
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"
# Wait for partitions to appear
sleep 1
log " Loop device: $LOOP_DEV"
log " Boot: $BOOT_PART"
log " Root: $ROOT_PART"
#------------------------------------------------------------------------------
# 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"
@@ -199,128 +221,98 @@ mkdir -p "$MOUNT_ROOT" "$MOUNT_BOOT"
mount "$ROOT_PART" "$MOUNT_ROOT"
mount "$BOOT_PART" "$MOUNT_BOOT"
# Copy rootfs (excluding /boot)
# --- Rootfs (excluding /boot) ---
log " Copying rootfs..."
rsync -aHxS --exclude='/boot' "$ROOTFS_DIR/" "$MOUNT_ROOT/"
# Copy boot files
log " Copying boot files..."
if [ -d "$ROOTFS_DIR/boot" ]; then
cp "$ROOTFS_DIR/boot/Image" "$MOUNT_BOOT/"
# Only copy the R36S DTB — extra DTBs (r35s, rg351mp-linux) are not needed
cp "$ROOTFS_DIR/boot/rk3326-gameconsole-r36s.dtb" "$MOUNT_BOOT/" 2>/dev/null || true
fi
# --- Variant marker ---
mkdir -p "$MOUNT_ROOT/etc/archr"
echo "$VARIANT" > "$MOUNT_ROOT/etc/archr/variant"
# Copy U-Boot DTB (required for U-Boot display initialization)
# Default: Panel 4 V22 — most common R36S panel
UBOOT_DTB="$SCRIPT_DIR/kernel/dts/R36S-DTB/R36S/Panel 4 - V22/rg351mp-kernel.dtb"
if [ ! -f "$UBOOT_DTB" ]; then
# Fallback to Panel 0 if Panel 4 V22 not available
UBOOT_DTB="$SCRIPT_DIR/kernel/dts/R36S-DTB/R36S/Panel 0/rg351mp-kernel.dtb"
fi
if [ -f "$UBOOT_DTB" ]; then
cp "$UBOOT_DTB" "$MOUNT_BOOT/rg351mp-kernel.dtb"
log " ✓ U-Boot DTB installed ($(basename "$(dirname "$UBOOT_DTB")")/rg351mp-kernel.dtb)"
else
warn "U-Boot DTB not found! U-Boot may not initialize display."
fi
# --- First-boot flag ---
rm -f "$MOUNT_ROOT/var/lib/archr/.first-boot-done"
# boot.ini (fallback — extlinux.conf is primary boot method)
if [ -f "$SCRIPT_DIR/config/boot.ini" ]; then
cp "$SCRIPT_DIR/config/boot.ini" "$MOUNT_BOOT/boot.ini"
log " ✓ boot.ini installed (fallback boot method)"
else
error "boot.ini not found at config/boot.ini!"
fi
# --- BOOT partition: KERNEL ---
cp "$BOOT_OUTPUT/KERNEL" "$MOUNT_BOOT/KERNEL"
log " KERNEL installed"
# --- 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/"
# --- BOOT partition: Panel overlays ---
mkdir -p "$MOUNT_BOOT/overlays"
overlay_count=0
# Panel DTBO overlays (ScreenFiles/)
PANELS_DIR="$OUTPUT_DIR/panels/ScreenFiles"
if [ -d "$PANELS_DIR" ]; then
cp -r "$PANELS_DIR" "$MOUNT_BOOT/"
panel_count=$(find "$MOUNT_BOOT/ScreenFiles" -name "*.dtbo" | wc -l)
log " ✓ Panel DTBOs installed (${panel_count} panels)"
for dtbo in "$PANELS_DIR"/*.dtbo; do
[ -f "$dtbo" ] || continue
cp "$dtbo" "$MOUNT_BOOT/overlays/"
overlay_count=$((overlay_count + 1))
done
log " Panel overlays: $overlay_count shipped (no default — Flasher selects panel)"
else
warn "Panel DTBOs not found! Run scripts/generate-panel-dtbos.sh first"
warn "No panel overlays found — display may not work without mipi-panel.dtbo!"
fi
# U-Boot logo (BMP format — U-Boot displays logo.bmp natively during boot)
log " Converting boot logo..."
LOGO_SRC="$SCRIPT_DIR/ArchR.png"
# --- BOOT partition: boot.ini (BSP U-Boot reads directly) ---
cp "$BOOT_INI" "$MOUNT_BOOT/boot.ini"
log " boot.ini installed"
if [ -f "$LOGO_SRC" ]; then
if command -v convert &>/dev/null; then
convert "$LOGO_SRC" -resize 640x480! -alpha remove -type TrueColor BMP3:"$MOUNT_BOOT/logo.bmp"
log " ✓ logo.bmp created ($(du -h "$MOUNT_BOOT/logo.bmp" | cut -f1))"
elif command -v ffmpeg &>/dev/null; then
ffmpeg -y -loglevel error -i "$LOGO_SRC" -vf "scale=640:480" -pix_fmt bgr24 "$MOUNT_BOOT/logo.bmp"
log " ✓ logo.bmp created via ffmpeg"
else
warn "Neither imagemagick nor ffmpeg found — logo.bmp skipped"
warn "Install with: sudo apt install imagemagick"
fi
else
warn "ArchR.png not found — logo.bmp skipped (U-Boot will show no logo)"
fi
# --- Initramfs is embedded in kernel (no separate file needed) ---
# Create extlinux.conf (primary boot method — U-Boot loads this first)
mkdir -p "$MOUNT_BOOT/extlinux"
cat > "$MOUNT_BOOT/extlinux/extlinux.conf" << 'EXTLINUX_EOF'
LABEL ArchR
LINUX /Image
FDT /rk3326-gameconsole-r36s.dtb
APPEND root=/dev/mmcblk1p2 rootwait rw console=ttyFIQ0 loglevel=0 quiet vt.global_cursor_default=0 consoleblank=0 printk.devkmsg=off fsck.mode=skip
EXTLINUX_EOF
log " ✓ extlinux.conf installed (primary boot method)"
# Create 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
# Mounts and loop device cleaned up by EXIT trap (cleanup_image)
log " ✓ Sync complete"
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"
xz -9 -k "$IMAGE_FILE"
COMPRESSED="${IMAGE_FILE}.xz"
COMPRESSED_SIZE=$(du -h "$COMPRESSED" | cut -f1)
log " Compressed: $COMPRESSED ($COMPRESSED_SIZE)"
log " Compressed: $COMPRESSED ($COMPRESSED_SIZE)"
fi
#------------------------------------------------------------------------------
# Summary
#------------------------------------------------------------------------------
log ""
log "=== Image Build Complete ==="
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 "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!"
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 -109
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,20 +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 target
R36S_DTB="rk3326-gameconsole-r36s"
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"
@@ -49,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"
#------------------------------------------------------------------------------
@@ -65,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
@@ -79,68 +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
#------------------------------------------------------------------------------
# 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!"
@@ -150,68 +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"
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/"
# 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"
@@ -224,16 +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 ""
log "Artifacts:"
log " Image: $BOOT_DIR/Image ($IMAGE_SIZE)"
log " DTB: $BOOT_DIR/${R36S_DTB}.dtb ($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!"
log "Ready for deployment to SD card!"
+262 -37
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
@@ -353,6 +357,7 @@ fi
cat > /etc/systemd/system/firstboot.service << 'FB_EOF'
[Unit]
Description=Arch R First Boot Setup
After=local-fs.target
Before=emulationstation.service
ConditionPathExists=!/var/lib/archr/.first-boot-done
@@ -367,6 +372,26 @@ FB_EOF
systemctl enable firstboot
# 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=Sync variant from BOOT partition
After=local-fs.target
RequiresMountsFor=/boot
ConditionPathExists=!/etc/archr/variant
[Service]
Type=oneshot
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
VARSYNC_EOF
systemctl enable archr-variant-sync
# EmulationStation launch — PRIMARY: systemd service (created by build-emulationstation.sh)
# FALLBACK: autologin + .bash_profile (if ES service not installed)
# The emulationstation.service Conflicts with getty@tty1, so only one runs.
@@ -403,9 +428,12 @@ fi
PROFILE_EOF
chown archr:archr /home/archr/.bash_profile
# Disable old custom splash if it exists
# Boot splash: handled by initramfs (archr-init with embedded BMP).
# Initramfs displays splash at ~0.7s after kernel start, before systemd.
# No systemd service needed — splash persists until ES takes DRM master.
systemctl disable splash 2>/dev/null || true
rm -f /etc/systemd/system/splash.service
systemctl disable archr-splash 2>/dev/null || true
rm -f /etc/systemd/system/splash.service /etc/systemd/system/archr-splash.service
# Battery LED warning service
cat > /etc/systemd/system/battery-led.service << 'BATT_EOF'
@@ -483,7 +511,129 @@ TIMING_EOF
systemctl enable boot-timing
# Delete initramfs (not used — extlinux.conf has no INITRD line)
# 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
# Clean kernel modules: remove media tuners (154 modules, 13MB — useless for gaming)
@@ -497,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)
@@ -548,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
@@ -645,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 \
@@ -672,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
@@ -911,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
@@ -928,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
@@ -948,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
@@ -968,6 +1183,9 @@ log " ✓ Distro version installed (text.plymouth)"
install -m 755 "$SCRIPT_DIR/scripts/first-boot.sh" "$ROOTFS_DIR/usr/local/bin/first-boot.sh"
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)
# 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"
@@ -999,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)"
@@ -1012,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
+174
View File
@@ -0,0 +1,174 @@
#!/bin/bash
#==============================================================================
# Arch R - Build Mainline U-Boot for R36S Clones
#==============================================================================
# Uses mainline U-Boot v2025.10 + RK3326 handheld patches
# Produces: idbloader.img, uboot.img, trust.img (Rockchip format)
#
# Usage:
# ./build-uboot-clone.sh [--uart5]
#
# --uart5: Build for K36 clones that use UART5 instead of UART2
#==============================================================================
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
UBOOT_SRC="$SCRIPT_DIR/bootloader/u-boot-mainline"
RKBIN_DIR="$SCRIPT_DIR/bootloader/rkbin"
OUTPUT_DIR="$SCRIPT_DIR/bootloader/u-boot-clone-build"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log() { echo -e "${GREEN}[UBOOT-CLONE]${NC} $1"; }
warn() { echo -e "${YELLOW}[UBOOT-CLONE] WARNING:${NC} $1"; }
error() { echo -e "${RED}[UBOOT-CLONE] ERROR:${NC} $1"; exit 1; }
#------------------------------------------------------------------------------
# Parse arguments
#------------------------------------------------------------------------------
UART5=0
for arg in "$@"; do
case "$arg" in
--uart5) UART5=1 ;;
esac
done
#------------------------------------------------------------------------------
# Verify prerequisites
#------------------------------------------------------------------------------
CROSS_COMPILE="aarch64-linux-gnu-"
if ! command -v ${CROSS_COMPILE}gcc &>/dev/null; then
error "Cross-compiler not found. Install: sudo apt install gcc-aarch64-linux-gnu"
fi
if ! python3 -c "import elftools" 2>/dev/null; then
error "pyelftools not found. Install: pip3 install pyelftools"
fi
if ! command -v swig &>/dev/null; then
error "swig not found. Install: sudo apt install swig"
fi
[ -d "$UBOOT_SRC" ] || error "Mainline U-Boot source not found: $UBOOT_SRC"
[ -d "$RKBIN_DIR" ] || error "rkbin not found: $RKBIN_DIR"
#------------------------------------------------------------------------------
# Rockchip firmware binaries
#------------------------------------------------------------------------------
PKG_DDR_BIN="$RKBIN_DIR/bin/rk33/rk3326_ddr_333MHz_v2.11.bin"
PKG_MINILOADER="$RKBIN_DIR/bin/rk33/rk3326_miniloader_v1.40.bin"
PKG_BL31="$RKBIN_DIR/bin/rk33/rk3326_bl31_v1.34.elf"
[ -f "$PKG_DDR_BIN" ] || error "DDR binary not found: $PKG_DDR_BIN"
[ -f "$PKG_MINILOADER" ] || error "Miniloader not found: $PKG_MINILOADER"
[ -f "$PKG_BL31" ] || error "BL31 not found: $PKG_BL31"
#------------------------------------------------------------------------------
# UART5 DDR binary (for K36 clones)
#------------------------------------------------------------------------------
if [ "$UART5" -eq 1 ]; then
log "Building UART5 variant for K36 clones"
PKG_DDR_BIN_UART5="$RKBIN_DIR/rk3326_ddr_uart5.bin"
if [ ! -f "$PKG_DDR_BIN_UART5" ]; then
log "Creating UART5-tuned DDR binary..."
DDRBIN_TOOL="$RKBIN_DIR/tools/ddrbin_tool"
if [ ! -x "$DDRBIN_TOOL" ]; then
error "ddrbin_tool not found or not executable: $DDRBIN_TOOL"
fi
cp "$PKG_DDR_BIN" "$PKG_DDR_BIN_UART5"
"$DDRBIN_TOOL" rk3326 -g "$RKBIN_DIR/rk3326_ddr_uart5.txt" "$PKG_DDR_BIN_UART5"
sed -i 's|uart id=.*$|uart id=5|' "$RKBIN_DIR/rk3326_ddr_uart5.txt"
"$DDRBIN_TOOL" rk3326 "$RKBIN_DIR/rk3326_ddr_uart5.txt" "$PKG_DDR_BIN_UART5" >/dev/null
log "UART5 DDR binary created"
fi
PKG_DDR_BIN="$PKG_DDR_BIN_UART5"
fi
#------------------------------------------------------------------------------
# Build U-Boot
#------------------------------------------------------------------------------
JOBS=$(nproc)
DEFCONFIG="rk3326-handheld_defconfig"
log "=== Building Mainline U-Boot v2025.10 for R36S Clone ==="
log "Cross-compiler: $(${CROSS_COMPILE}gcc --version | head -1)"
log "Defconfig: $DEFCONFIG"
log "Jobs: $JOBS"
[ "$UART5" -eq 1 ] && log "UART: UART5 (0xFF178000)" || log "UART: UART2 (0xFF160000)"
cd "$UBOOT_SRC"
log "Step 1: Clean..."
make CROSS_COMPILE="$CROSS_COMPILE" ARCH=arm mrproper 2>&1 | tail -1
log "Step 2: Configure..."
make CROSS_COMPILE="$CROSS_COMPILE" ARCH=arm "$DEFCONFIG" 2>&1 | tail -1
# UART5 variant: override config
if [ "$UART5" -eq 1 ]; then
./scripts/config --set-val CONFIG_DEBUG_UART_BASE 0xFF178000
./scripts/config --set-str CONFIG_DEVICE_TREE_INCLUDES "rk3326-odroid-go2-emmc.dtsi rk3326-odroid-go2-uart5.dtsi"
log "UART5 config applied"
fi
log "Step 3: Compile..."
make CROSS_COMPILE="$CROSS_COMPILE" ARCH=arm -j"$JOBS" u-boot-dtb.bin 2>&1 | tail -20
[ -f "u-boot-dtb.bin" ] || error "Build failed: u-boot-dtb.bin not found"
log "u-boot-dtb.bin built: $(du -h u-boot-dtb.bin | cut -f1)"
#------------------------------------------------------------------------------
# Package: idbloader.img
#------------------------------------------------------------------------------
log "Step 4: Creating idbloader.img..."
"$UBOOT_SRC/tools/mkimage" -n px30 -T rksd -d "$PKG_DDR_BIN" -C bzip2 idbloader.img
cat "$PKG_MINILOADER" >> idbloader.img
log "idbloader.img: $(du -h idbloader.img | cut -f1)"
#------------------------------------------------------------------------------
# Package: uboot.img
#------------------------------------------------------------------------------
log "Step 5: Creating uboot.img..."
"$RKBIN_DIR/tools/loaderimage" --pack --uboot u-boot-dtb.bin uboot.img 0x00200000 2>&1 | tail -3
log "uboot.img: $(du -h uboot.img | cut -f1)"
#------------------------------------------------------------------------------
# Package: trust.img
#------------------------------------------------------------------------------
log "Step 6: Creating trust.img..."
cat >trust.ini <<EOF
[BL30_OPTION]
SEC=0
[BL31_OPTION]
SEC=1
PATH=${PKG_BL31}
ADDR=0x00010000
[BL32_OPTION]
SEC=0
[BL33_OPTION]
SEC=0
[OUTPUT]
PATH=trust.img
EOF
"$RKBIN_DIR/tools/trust_merger" --verbose trust.ini 2>&1 | tail -5
log "trust.img: $(du -h trust.img | cut -f1)"
#------------------------------------------------------------------------------
# Copy to output directory
#------------------------------------------------------------------------------
mkdir -p "$OUTPUT_DIR"
cp idbloader.img uboot.img trust.img "$OUTPUT_DIR/"
log ""
log "=== Build Complete ==="
log "Output: $OUTPUT_DIR/"
ls -lh "$OUTPUT_DIR/"*.img
log ""
log "Flash with:"
log " ./flash-uboot-clone.sh /dev/sdX"
+129 -53
View File
@@ -1,90 +1,164 @@
#!/bin/bash
#==============================================================================
# Arch R - Build U-Boot for R36S
# Arch R - Build U-Boot BSP for RK3326
#==============================================================================
# Builds U-Boot bootloader for RK3326 (R36S/RG351MP compatible)
# 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.
#
# Output: bootloader/u-boot-rk3326/sd_fuse/
# idbloader.img — DDR init + miniloader
# uboot.img — U-Boot proper
# trust.img — ARM Trusted Firmware (BL31 + BL32)
#
# 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"
log "=== Arch R - Build U-Boot ==="
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 [ ! -d "$UBOOT_SRC" ]; then
log " Cloning U-Boot for RK3326..."
git clone --depth 1 "$UBOOT_REPO" "$UBOOT_SRC"
log " ✓ U-Boot cloned"
else
log " ✓ U-Boot source exists"
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
cd "$UBOOT_SRC"
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"
#------------------------------------------------------------------------------
# Step 2: Build U-Boot
# Clean (optional)
#------------------------------------------------------------------------------
if [ "$CLEAN" = true ]; then
log "Cleaning previous build..."
make -C "$UBOOT_DIR" distclean 2>/dev/null || true
rm -rf "$OUTPUT_DIR"
fi
#------------------------------------------------------------------------------
# Build U-Boot
#------------------------------------------------------------------------------
log ""
log "Step 1: Configuring (odroidgoa_defconfig)..."
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
# Set up cross-compiler (use Linaro if available, otherwise system)
if [ -d "/opt/toolchains/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu" ]; then
export PATH=/opt/toolchains/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin:$PATH
if [ ! -f "u-boot.bin" ]; then
error "Build failed — u-boot.bin not found"
fi
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
# Build for OdroidGoA (compatible with R36S/RG351MP)
./make.sh odroidgoa 2>&1 | tail -20 || true
log " ✓ U-Boot built"
log " u-boot.bin built OK"
#------------------------------------------------------------------------------
# Step 3: Copy artifacts
# Pack images
#------------------------------------------------------------------------------
log ""
log "Step 3: Copying bootloader files..."
log "Step 3: Packing images..."
mkdir -p "$OUTPUT_DIR"
# Copy the bootloader images
if [ -d "sd_fuse" ]; then
cp sd_fuse/idbloader.img "$OUTPUT_DIR/"
cp sd_fuse/uboot.img "$OUTPUT_DIR/"
cp sd_fuse/trust.img "$OUTPUT_DIR/"
log " ✓ Bootloader files 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)"
# 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
#------------------------------------------------------------------------------
# Summary
@@ -92,9 +166,11 @@ fi
log ""
log "=== U-Boot Build Complete ==="
log ""
log "Bootloader files:"
ls -la "$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 automatically installed by build-image.sh"
log ""
log "✓ U-Boot ready for R36S!"
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
-28
View File
@@ -1,28 +0,0 @@
ODROIDGOA-UBOOT-CONFIG
########################################################################
# Arch R Boot Configuration for R36S — Kernel 6.6 + Systemd
# Default panel: Panel 4-V22 (hardcoded in base DTB, no overlay needed)
# Primary boot: extlinux/extlinux.conf (U-Boot tries it first)
# This boot.ini is a fallback if extlinux is missing.
########################################################################
# Memory addresses — kernel at 0x02008000 (matches working R36S firmware)
setenv dtb_loadaddr "0x01f00000"
setenv loadaddr "0x02008000"
# Load kernel Image
if load mmc 1:1 ${loadaddr} Image
then
# Load DTB
if load mmc 1:1 ${dtb_loadaddr} rk3326-gameconsole-r36s.dtb
then
# Boot without initrd — use device path directly
setenv bootargs "root=/dev/mmcblk1p2 rootwait rw console=ttyFIQ0 loglevel=0 quiet vt.global_cursor_default=0 consoleblank=0 printk.devkmsg=off fsck.mode=skip"
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

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