mirror of
https://github.com/archr-linux/Arch-R.git
synced 2026-07-12 18:19:42 -07:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9b55f926c0 | |||
| b36a333523 | |||
| c8e7fe99e9 | |||
| 06dc2d16f3 | |||
| 8650d940e2 | |||
| 70342ca457 |
+14
@@ -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
|
||||
|
||||
+610
File diff suppressed because it is too large
Load Diff
@@ -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,122 +173,104 @@ Arch-R/
|
||||
| SoC | Rockchip RK3326 (4x Cortex-A35 @ 1.5GHz) |
|
||||
| GPU | Mali-G31 Bifrost (Mesa Panfrost, 600MHz) |
|
||||
| RAM | 1GB DDR3L (786MHz) |
|
||||
| Display | 640x480 MIPI DSI (18 panel variants) |
|
||||
| Display | 640x480 MIPI DSI (20 panel variants) |
|
||||
| Audio | RK817 codec, speaker + headphone jack |
|
||||
| Storage | MicroSD (boot + rootfs + ROMS) |
|
||||
| Storage | MicroSD (BOOT + rootfs + ROMS) |
|
||||
| Controls | D-pad, ABXY, L1/L2/R1/R2, dual analog sticks |
|
||||
| Battery | 3200mAh Li-Po (RK817 charger) |
|
||||
| USB | OTG with host mode (VBUS power on GPIO0_B7) |
|
||||
| USB | OTG with host/gadget mode switching |
|
||||
|
||||
## Supported Panels
|
||||
## Architecture
|
||||
|
||||
Arch R supports 18 display panels via pre-merged DTBs. Each panel variant has its own DTB file with the correct init sequence and timings applied at build-time.
|
||||
Arch R separates **board configuration** from **panel configuration**:
|
||||
|
||||
There are two separate images: **Original** (for genuine R36S) and **Clone** (for R36S clones like G80CA, K36, etc.). Each image has its own panel list.
|
||||
- **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.
|
||||
|
||||
> **Note:** The numerical panel ordering below is available starting from **beta1.2**. Earlier versions may have a different order.
|
||||
This means the same image works on all boards of a variant — only the panel overlay needs to match your specific display.
|
||||
|
||||
### Panel Auto-Detection
|
||||
### Supported Boards
|
||||
|
||||
On first boot, Arch R runs a **panel detection wizard** that guides you through selecting your display panel:
|
||||
| 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 |
|
||||
|
||||
1. **If your screen works** (you see text on screen): press **A** to confirm the current panel
|
||||
2. **If your screen is black** (wrong panel): listen for audio beeps and use buttons to navigate:
|
||||
- Each panel plays a different number of beeps (Panel 0 = 1 beep, Panel 1 = 2 beeps, etc.)
|
||||
- Press **B** to skip to the next panel
|
||||
- Press **A** to confirm (you'll hear 3 rapid beeps)
|
||||
- The system reboots with the correct panel applied
|
||||
### Supported Panels
|
||||
|
||||
Your selection is saved permanently. To reset it later, **hold X during boot**.
|
||||
#### Original R36S (7 panels)
|
||||
|
||||
### R36S Original (6 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 |
|
||||
|
||||
Default: **Panel 4-V22** (~60% of units)
|
||||
R46H (1024x768): `r46h.dtbo`
|
||||
|
||||
| Beeps | Panel | DTB | Notes |
|
||||
|-------|-------|-----|-------|
|
||||
| 1 | Panel 0 | kernel-panel0.dtb | Early R36S units |
|
||||
| 2 | Panel 1-V10 | kernel-panel1.dtb | V10 board marking |
|
||||
| 3 | Panel 2-V12 | kernel-panel2.dtb | V12 board marking |
|
||||
| 4 | Panel 3-V20 | kernel-panel3.dtb | V20 board marking |
|
||||
| 5 | **Panel 4-V22** *(default)* | kernel.dtb | Most common |
|
||||
| 6 | Panel 5-V22 Q8 | kernel-panel5.dtb | V22 Q8 variant |
|
||||
#### Clone R36S (13 panels)
|
||||
|
||||
### R36S Clone (12 panels)
|
||||
|
||||
Default: **Clone 8 ST7703 G80CA**
|
||||
|
||||
| Beeps | Panel | DTB | Notes |
|
||||
|-------|-------|-----|-------|
|
||||
| 1 | Clone 1 | kernel-clone1.dtb | ST7703 |
|
||||
| 2 | Clone 2 | kernel-clone2.dtb | ST7703 |
|
||||
| 3 | Clone 3 | kernel-clone3.dtb | NV3051D |
|
||||
| 4 | Clone 4 | kernel-clone4.dtb | NV3051D |
|
||||
| 5 | Clone 5 | kernel-clone5.dtb | ST7703 |
|
||||
| 6 | Clone 6 | kernel-clone6.dtb | NV3051D |
|
||||
| 7 | Clone 7 | kernel-clone7.dtb | JD9365DA |
|
||||
| 8 | **Clone 8** *(default)* | kernel.dtb | ST7703 (G80CA-MB) |
|
||||
| 9 | Clone 9 | kernel-clone9.dtb | NV3051D |
|
||||
| 10 | Clone 10 | kernel-clone10.dtb | ST7703 variant |
|
||||
| 11 | R36 Max | kernel-r36max.dtb | 720x720 ST7703 |
|
||||
| 12 | RX6S | kernel-rx6s.dtb | NV3051D variant |
|
||||
| Panel | Overlay file | Controller | Notes |
|
||||
|-------|-------------|------------|-------|
|
||||
| Clone 1 | clone_panel_1.dtbo | ST7703 | |
|
||||
| Clone 2 | clone_panel_2.dtbo | ST7703 | |
|
||||
| Clone 3 | clone_panel_3.dtbo | NV3051D | |
|
||||
| Clone 4 | clone_panel_4.dtbo | NV3051D | |
|
||||
| Clone 5 | clone_panel_5.dtbo | ST7703 | |
|
||||
| Clone 6 | clone_panel_6.dtbo | NV3051D | |
|
||||
| Clone 7 | clone_panel_7.dtbo | JD9365DA | |
|
||||
| Clone 8 | clone_panel_8.dtbo | ST7703 | G80CA — most common |
|
||||
| Clone 9 | clone_panel_9.dtbo | NV3051D | |
|
||||
| Clone 10 | clone_panel_10.dtbo | ST7703 | |
|
||||
| R36 Max | r36_max.dtbo | ST7703 | 720x720 |
|
||||
| RX6S | rx6s.dtbo | NV3051D | |
|
||||
|
||||
### Manual Panel Selection
|
||||
|
||||
If you prefer to set the panel manually (e.g., you know which panel you have from ArkOS/dArkOS):
|
||||
|
||||
**Step 1 -- Mount the BOOT partition on your PC**
|
||||
Mount the BOOT partition and copy the correct overlay as `mipi-panel.dtbo`:
|
||||
|
||||
```bash
|
||||
lsblk
|
||||
sudo mount /dev/sdX1 /mnt
|
||||
```
|
||||
|
||||
**Step 2 -- Create panel.txt**
|
||||
# Example: set Panel 4-V22 (most common original R36S panel)
|
||||
sudo cp /mnt/overlays/panel4-v22.dtbo /mnt/overlays/mipi-panel.dtbo
|
||||
|
||||
```bash
|
||||
# Example: Panel 3-V20 (original R36S)
|
||||
echo 'PanelNum=3
|
||||
PanelDTB=kernel-panel3.dtb' | sudo tee /mnt/panel.txt
|
||||
# Example: set Clone 8 (most common clone panel)
|
||||
sudo cp /mnt/overlays/clone_panel_8.dtbo /mnt/overlays/mipi-panel.dtbo
|
||||
|
||||
# Mark as confirmed (skip wizard on next boot)
|
||||
echo 'confirmed' | sudo tee /mnt/panel-confirmed
|
||||
```
|
||||
|
||||
For default panels (no custom DTB needed):
|
||||
```bash
|
||||
# Original R36S: Panel 4-V22 (default)
|
||||
echo 'PanelNum=4
|
||||
PanelDTB=' | sudo tee /mnt/panel.txt
|
||||
|
||||
# Clone R36S: Clone 8 G80CA (default)
|
||||
echo 'PanelNum=C8
|
||||
PanelDTB=' | sudo tee /mnt/panel.txt
|
||||
|
||||
echo 'confirmed' | sudo tee /mnt/panel-confirmed
|
||||
```
|
||||
|
||||
**Step 3 -- Unmount and boot**
|
||||
|
||||
```bash
|
||||
sudo umount /mnt
|
||||
sync
|
||||
```
|
||||
|
||||
**To reset panel selection:** hold **X** during boot, or delete `panel-confirmed` from the BOOT partition.
|
||||
|
||||
## Boot Flow
|
||||
|
||||
```
|
||||
Power On
|
||||
→ U-Boot (idbloader → trust → uboot.img)
|
||||
→ logo.bmp displayed on screen
|
||||
→ boot.ini: load panel.txt → load pre-merged DTB (kernel-panelN.dtb)
|
||||
→ Kernel 6.6.89 + initramfs splash (0.7s)
|
||||
→ systemd → panel-detect.service (first boot only)
|
||||
→ archr-boot-setup (GPU + governors)
|
||||
→ U-Boot loads (idbloader → trust → uboot.img)
|
||||
→ boot.ini: read SARADC hwrev → select board DTB
|
||||
→ boot.ini: apply overlays/mipi-panel.dtbo (panel init sequence)
|
||||
→ Kernel 6.12.61 + initramfs splash (0.7s)
|
||||
→ systemd → archr-boot-setup (GPU + governors)
|
||||
→ emulationstation.service → EmulationStation UI
|
||||
≈ 19 seconds total (+ wizard on first boot)
|
||||
≈ 19 seconds total
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
+29
-4
@@ -1961,10 +1961,35 @@ The Flasher lives at `archr-linux/archr-flasher` on GitHub. Still ironing out th
|
||||
(first build caught a Tauri 2 schema issue with `app.title` and 16-bit icon PNGs), but the
|
||||
code is feature-complete.
|
||||
|
||||
**beta1.2 image changes:**
|
||||
**beta1.2 system changes — a lot more than "just polish":**
|
||||
|
||||
Published new images with accumulated fixes since beta1.1. Nothing dramatic — mostly polish
|
||||
and small fixes that came out of Flasher development and continued testing.
|
||||
The biggest under-the-hood change was the **input merger daemon**. RetroArch sees multiple input
|
||||
devices (gpio-keys for buttons, adc-joystick for analog sticks) as separate controllers. With
|
||||
`max_users=1`, it would bind to gpio-keys and ignore the joystick entirely. The fix: a small
|
||||
C daemon (`input-merge`) that reads both evdev devices and outputs a single virtual "Arch R
|
||||
Gamepad" via uinput. Now RetroArch sees one unified controller with buttons + analog sticks.
|
||||
`retroarch-launch.sh` starts the merger before RA and kills it after.
|
||||
|
||||
RetroArch itself got a proper config tuning pass, borrowed heavily from ROCKNIX's RK3326
|
||||
profiles. Audio at 48kHz (native DAC rate), triple buffer, late input polling for reduced
|
||||
latency, per-core options for mupen64plus, pcsx_rearmed, flycast, mame2003-plus, melonds,
|
||||
and others. Auto-save enabled, core options path set.
|
||||
|
||||
**Panel wizard rework:** Panels now show in numerical order — the beep count matches the panel
|
||||
position in the list (Panel 1 = 1 beep, Panel 2 = 2 beeps, etc.). Default panel detection
|
||||
uses `dtb_name` matching instead of always falling back to `panels[0]`.
|
||||
|
||||
**Third image variant: no-panel.** For the Flasher app — includes all 18 pre-merged panel DTBs
|
||||
for both original and clone hardware. The Flasher picks the right DTB at write time. Also added
|
||||
`variant-sync` systemd service that copies `/boot/variant` to `/etc/archr/variant` on first
|
||||
boot (necessary because the Flasher writes the variant marker to the FAT32 BOOT partition,
|
||||
not directly into ext4).
|
||||
|
||||
**Mirror list updated:** The old EU mirror was returning 403 errors. Reshuffled to Americas-first
|
||||
ordering (better for Brazil) and added new mirrors (de4, gr, tw, tw2, ca.us).
|
||||
|
||||
**boot.ini fix:** Root device now auto-detected from `mmcdev` variable instead of the hardcoded
|
||||
`__ROOTDEV__` placeholder — one less thing that could break on different boot configurations.
|
||||
|
||||
---
|
||||
|
||||
@@ -2077,4 +2102,4 @@ and small fixes that came out of Flasher development and continued testing.
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 2026-02-25 (build pipeline fixes, boot.scr mystery solved, splash positioning)*
|
||||
*Last updated: 2026-03-01 (beta1.2 release — Flasher app, input merger, RetroArch tuning, no-panel variant)*
|
||||
|
||||
+1
-1
Submodule bootloader/u-boot-rk3326 updated: 5606e804ff...2492a3e467
+9
-7
@@ -129,6 +129,14 @@ log "✓ Prerequisites OK"
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
if [ "$BUILD_KERNEL" = true ]; then
|
||||
# Initramfs must be built BEFORE kernel — kernel embeds it at compile time
|
||||
log ""
|
||||
log "═══════════════════════════════════════════════════════════════"
|
||||
log " BUILDING INITRAMFS"
|
||||
log "═══════════════════════════════════════════════════════════════"
|
||||
chmod +x "$SCRIPT_DIR/build-initramfs.sh"
|
||||
"$SCRIPT_DIR/build-initramfs.sh"
|
||||
|
||||
log ""
|
||||
log "═══════════════════════════════════════════════════════════════"
|
||||
log " BUILDING KERNEL"
|
||||
@@ -184,7 +192,7 @@ log "═════════════════════════
|
||||
chmod +x "$SCRIPT_DIR/scripts/generate-panel-dtbos.sh"
|
||||
"$SCRIPT_DIR/scripts/generate-panel-dtbos.sh"
|
||||
|
||||
# Build custom U-Boot (optional — requires arm-linux-gnueabihf toolchain)
|
||||
# Build U-Boot BSP (requires aarch64 cross-compiler)
|
||||
if [ "$BUILD_UBOOT" = true ] && [ -f "$SCRIPT_DIR/build-uboot.sh" ]; then
|
||||
if command -v aarch64-linux-gnu-gcc &>/dev/null; then
|
||||
log ""
|
||||
@@ -213,12 +221,6 @@ if [ "$BUILD_IMAGE" = true ]; then
|
||||
log " BUILDING IMAGE (clone)"
|
||||
log "═══════════════════════════════════════════════════════════════"
|
||||
"$SCRIPT_DIR/build-image.sh" --variant clone
|
||||
|
||||
log ""
|
||||
log "═══════════════════════════════════════════════════════════════"
|
||||
log " BUILDING IMAGE (no-panel)"
|
||||
log "═══════════════════════════════════════════════════════════════"
|
||||
"$SCRIPT_DIR/build-image.sh" --variant no-panel
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
+102
-298
File diff suppressed because it is too large
Load Diff
Executable
+102
@@ -0,0 +1,102 @@
|
||||
#!/bin/bash
|
||||
|
||||
#==============================================================================
|
||||
# Arch R - Initramfs Builder
|
||||
#==============================================================================
|
||||
# Generates the initramfs directory for kernel embedding (CONFIG_INITRAMFS_SOURCE).
|
||||
# Must run BEFORE build-kernel.sh — the kernel embeds this at compile time.
|
||||
#
|
||||
# Pipeline:
|
||||
# 1. Compile archr-init.c + SVG splash library (static aarch64 binary)
|
||||
# 2. Create initramfs directory tree (init + dev + proc + newroot)
|
||||
#
|
||||
# Logo is rendered from SVG paths at runtime (no ImageMagick needed).
|
||||
#
|
||||
# Output: $OUTPUT_DIR/initramfs/ (directory tree, not cpio)
|
||||
#==============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] WARNING:${NC} $1"; }
|
||||
error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $1"; exit 1; }
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Configuration
|
||||
#------------------------------------------------------------------------------
|
||||
OUTPUT_DIR="$SCRIPT_DIR/output"
|
||||
INITRAMFS_DIR="$OUTPUT_DIR/initramfs"
|
||||
SPLASH_DIR="$SCRIPT_DIR/scripts/splash"
|
||||
|
||||
log "================================================================"
|
||||
log " Arch R - Initramfs Builder (SVG splash)"
|
||||
log "================================================================"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Prerequisites
|
||||
#------------------------------------------------------------------------------
|
||||
if ! command -v aarch64-linux-gnu-gcc &>/dev/null; then
|
||||
error "Cross-compiler not found. Install: sudo apt install gcc-aarch64-linux-gnu"
|
||||
fi
|
||||
|
||||
# Verify splash library files exist
|
||||
for f in fbsplash.c svg_parser.c svg_renderer.c archr-logo.h; do
|
||||
if [ ! -f "$SPLASH_DIR/$f" ]; then
|
||||
error "Missing splash file: $SPLASH_DIR/$f"
|
||||
fi
|
||||
done
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 1: Compile archr-init (static aarch64 binary with SVG splash)
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 1: Compiling archr-init (SVG splash)..."
|
||||
|
||||
TMPDIR=$(mktemp -d)
|
||||
|
||||
aarch64-linux-gnu-gcc -static -O2 \
|
||||
-I"$SPLASH_DIR" \
|
||||
-o "$TMPDIR/archr-init" \
|
||||
"$SCRIPT_DIR/scripts/archr-init.c" \
|
||||
"$SPLASH_DIR/fbsplash.c" \
|
||||
"$SPLASH_DIR/svg_parser.c" \
|
||||
"$SPLASH_DIR/svg_renderer.c" \
|
||||
-lm
|
||||
|
||||
log " archr-init compiled ($(du -h "$TMPDIR/archr-init" | cut -f1))"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 2: Create initramfs directory tree
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 2: Creating initramfs directory..."
|
||||
|
||||
rm -rf "$INITRAMFS_DIR"
|
||||
mkdir -p "$INITRAMFS_DIR"/{dev,proc,newroot}
|
||||
|
||||
cp "$TMPDIR/archr-init" "$INITRAMFS_DIR/init"
|
||||
chmod 755 "$INITRAMFS_DIR/init"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Cleanup
|
||||
#------------------------------------------------------------------------------
|
||||
rm -rf "$TMPDIR"
|
||||
|
||||
INIT_SIZE=$(du -h "$INITRAMFS_DIR/init" | cut -f1)
|
||||
log ""
|
||||
log "================================================================"
|
||||
log " Initramfs Ready"
|
||||
log "================================================================"
|
||||
log ""
|
||||
log " Directory: $INITRAMFS_DIR"
|
||||
log " /init: $INIT_SIZE (static aarch64 + SVG splash)"
|
||||
log ""
|
||||
log " Kernel will embed this via CONFIG_INITRAMFS_SOURCE"
|
||||
+217
-139
@@ -1,9 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
#==============================================================================
|
||||
# Arch R - Kernel 6.6 Build Script for R36S
|
||||
# Arch R - Kernel Build Script
|
||||
#==============================================================================
|
||||
# Builds Linux kernel 6.6.89 (Rockchip BSP) with R36S DTS + systemd support
|
||||
# Builds mainline Linux 6.12.x with Arch R patches for RK3326 R36S
|
||||
# Applies: device patches, 6.12-LTS patches, mainline patches
|
||||
# Builds: kernel Image + ALL DTBs + modules + out-of-tree joypad driver
|
||||
#==============================================================================
|
||||
|
||||
set -e
|
||||
@@ -14,7 +16,6 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1"; }
|
||||
@@ -22,21 +23,18 @@ warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] WARNING:${NC} $1"; }
|
||||
error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $1"; exit 1; }
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Configuration - Kernel 6.6 Rockchip BSP
|
||||
# Configuration
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
KERNEL_VERSION="6.6.89"
|
||||
KERNEL_BRANCH="develop-6.6"
|
||||
KERNEL_REPO="https://github.com/rockchip-linux/kernel.git"
|
||||
DEFCONFIG="rockchip_linux_defconfig"
|
||||
CONFIG_FRAGMENT="$SCRIPT_DIR/config/archr-6.6-r36s.config"
|
||||
|
||||
# DTS targets
|
||||
R36S_DTB="rk3326-gameconsole-r36s"
|
||||
CLONE_DTB="rk3326-gameconsole-r36s-clone-type5"
|
||||
KERNEL_VERSION="6.12.61"
|
||||
KERNEL_URL="https://www.kernel.org/pub/linux/kernel/v6.x/linux-${KERNEL_VERSION}.tar.xz"
|
||||
|
||||
# Paths
|
||||
KERNEL_SRC="${KERNEL_SRC:-/home/dgateles/Documentos/Projetos/kernel}"
|
||||
KERNEL_SRC="$SCRIPT_DIR/kernel/src/linux-${KERNEL_VERSION}"
|
||||
PATCHES_DIR="$SCRIPT_DIR/patches/linux"
|
||||
DTS_DIR="$SCRIPT_DIR/kernel/dts/archr"
|
||||
JOYPAD_DIR="$SCRIPT_DIR/kernel/drivers/archr-joypad"
|
||||
CONFIG_BASE="$SCRIPT_DIR/config/linux-archr-base.config"
|
||||
|
||||
# Output
|
||||
OUTPUT_DIR="$SCRIPT_DIR/output"
|
||||
@@ -50,13 +48,17 @@ export CROSS_COMPILE=aarch64-linux-gnu-
|
||||
# Build parallelism
|
||||
JOBS=$(nproc)
|
||||
|
||||
# DTS target directory inside kernel
|
||||
KERNEL_DTS_DIR="$KERNEL_SRC/arch/arm64/boot/dts/rockchip"
|
||||
|
||||
log "================================================================"
|
||||
log " Arch R - Kernel $KERNEL_VERSION (Rockchip BSP for R36S)"
|
||||
log " Arch R - Kernel $KERNEL_VERSION (Mainline + Arch R patches)"
|
||||
log "================================================================"
|
||||
log ""
|
||||
log "Source: $KERNEL_SRC"
|
||||
log "Branch: $KERNEL_BRANCH"
|
||||
log "DTB: $R36S_DTB"
|
||||
log "Patches: $PATCHES_DIR"
|
||||
log "DTS: $DTS_DIR"
|
||||
log "Config: $CONFIG_BASE"
|
||||
log "Jobs: $JOBS"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -66,11 +68,13 @@ log ""
|
||||
log "Step 1: Checking kernel source..."
|
||||
|
||||
if [ ! -d "$KERNEL_SRC" ]; then
|
||||
log " Cloning kernel 6.6 (rockchip-linux/kernel)..."
|
||||
log " Branch: $KERNEL_BRANCH"
|
||||
git clone --depth 1 --branch "$KERNEL_BRANCH" \
|
||||
"$KERNEL_REPO" "$KERNEL_SRC"
|
||||
log " Kernel cloned"
|
||||
TARBALL="$SCRIPT_DIR/kernel/src/linux-${KERNEL_VERSION}.tar.xz"
|
||||
if [ ! -f "$TARBALL" ]; then
|
||||
log " Downloading kernel $KERNEL_VERSION..."
|
||||
wget -c "$KERNEL_URL" -O "$TARBALL"
|
||||
fi
|
||||
log " Extracting..."
|
||||
tar -xf "$TARBALL" -C "$SCRIPT_DIR/kernel/src/"
|
||||
fi
|
||||
|
||||
if [ ! -f "$KERNEL_SRC/Makefile" ]; then
|
||||
@@ -80,76 +84,130 @@ fi
|
||||
ACTUAL_VERSION=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null)
|
||||
log " Kernel: $ACTUAL_VERSION"
|
||||
|
||||
# Copy R36S DTS from Arch-R repo into kernel source tree
|
||||
DTS_SRC="$SCRIPT_DIR/kernel/dts/rk3326-gameconsole-r36s.dts"
|
||||
DTS_DEST="$KERNEL_SRC/arch/arm64/boot/dts/rockchip/rk3326-gameconsole-r36s.dts"
|
||||
if [ -f "$DTS_SRC" ]; then
|
||||
cp "$DTS_SRC" "$DTS_DEST"
|
||||
log " DTS: copied from repo"
|
||||
else
|
||||
if [ -f "$DTS_DEST" ]; then
|
||||
warn "DTS not in Arch-R repo — using existing kernel source copy"
|
||||
else
|
||||
error "DTS not found! Expected at: $DTS_SRC"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Copy clone DTS (if available)
|
||||
CLONE_DTS_SRC="$SCRIPT_DIR/kernel/dts/${CLONE_DTB}.dts"
|
||||
CLONE_DTS_DEST="$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dts"
|
||||
if [ -f "$CLONE_DTS_SRC" ]; then
|
||||
cp "$CLONE_DTS_SRC" "$CLONE_DTS_DEST"
|
||||
log " DTS (clone): copied from repo"
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 2: Configure Kernel
|
||||
# Step 2: Apply Patches (idempotent — skip already applied)
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 2: Configuring kernel..."
|
||||
log "Step 2: Applying patches..."
|
||||
|
||||
# Apply base defconfig
|
||||
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE $DEFCONFIG
|
||||
log " Base: $DEFCONFIG"
|
||||
PATCH_MARKER="$KERNEL_SRC/.archr-patches-applied"
|
||||
|
||||
# Merge R36S-specific config fragment
|
||||
# IMPORTANT: merge_config.sh writes output to .config in the CURRENT directory,
|
||||
# NOT to the base config path. Must run from kernel source dir.
|
||||
if [ -f "$CONFIG_FRAGMENT" ]; then
|
||||
pushd "$KERNEL_SRC" > /dev/null
|
||||
MERGE_LOG=$(scripts/kconfig/merge_config.sh \
|
||||
-m .config "$CONFIG_FRAGMENT" 2>&1) || true
|
||||
echo "$MERGE_LOG" | grep -E "(^#|Value)" | tail -20 || true
|
||||
popd > /dev/null
|
||||
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE olddefconfig
|
||||
# Verify critical GPU config was applied
|
||||
if grep -q "CONFIG_DRM_PANFROST=y" "$KERNEL_SRC/.config"; then
|
||||
log " Panfrost GPU: ENABLED (built-in)"
|
||||
elif grep -q "CONFIG_DRM_PANFROST=m" "$KERNEL_SRC/.config"; then
|
||||
log " Panfrost GPU: ENABLED (module)"
|
||||
else
|
||||
warn " Panfrost GPU: NOT ENABLED — check config fragment!"
|
||||
fi
|
||||
if grep -q "CONFIG_MALI_MIDGARD=y" "$KERNEL_SRC/.config"; then
|
||||
warn " Mali Midgard: STILL ENABLED (conflict with Panfrost!)"
|
||||
else
|
||||
log " Mali Midgard: disabled (good)"
|
||||
fi
|
||||
log " Merged: $(basename "$CONFIG_FRAGMENT")"
|
||||
if [ -f "$PATCH_MARKER" ]; then
|
||||
log " Patches already applied (marker exists). Skipping."
|
||||
else
|
||||
warn "Config fragment not found: $CONFIG_FRAGMENT"
|
||||
PATCH_COUNT=0
|
||||
|
||||
# Order: mainline first (GPIO API, input-polldev), then 6.12-LTS, then device-specific
|
||||
for PATCH_SUBDIR in mainline 6.12-lts device; do
|
||||
PDIR="$PATCHES_DIR/$PATCH_SUBDIR"
|
||||
if [ ! -d "$PDIR" ]; then
|
||||
warn " Patch dir not found: $PDIR"
|
||||
continue
|
||||
fi
|
||||
for PATCH in $(ls "$PDIR"/*.patch 2>/dev/null | sort); do
|
||||
PNAME=$(basename "$PATCH")
|
||||
log " Applying [$PATCH_SUBDIR] $PNAME..."
|
||||
if ! patch -d "$KERNEL_SRC" -p1 --forward --batch < "$PATCH" 2>&1 | tail -3; then
|
||||
warn " Patch may have failed or already applied: $PNAME"
|
||||
fi
|
||||
PATCH_COUNT=$((PATCH_COUNT + 1))
|
||||
done
|
||||
done
|
||||
|
||||
touch "$PATCH_MARKER"
|
||||
log " Applied $PATCH_COUNT patches"
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 3: Copy DTS files
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 3: Copying DTS files..."
|
||||
|
||||
if [ ! -d "$DTS_DIR" ]; then
|
||||
error "DTS directory not found: $DTS_DIR"
|
||||
fi
|
||||
|
||||
DTS_COUNT=0
|
||||
for DTS_FILE in "$DTS_DIR"/*.dts "$DTS_DIR"/*.dtsi; do
|
||||
[ -f "$DTS_FILE" ] || continue
|
||||
DEST="$KERNEL_DTS_DIR/$(basename "$DTS_FILE")"
|
||||
cp "$DTS_FILE" "$DEST"
|
||||
DTS_COUNT=$((DTS_COUNT + 1))
|
||||
done
|
||||
|
||||
# Add DTS entries to Makefile (for each .dts, ensure dtb- line exists)
|
||||
ROCKCHIP_MAKEFILE="$KERNEL_DTS_DIR/Makefile"
|
||||
for DTS_FILE in "$DTS_DIR"/*.dts; do
|
||||
[ -f "$DTS_FILE" ] || continue
|
||||
DTB_NAME=$(basename "$DTS_FILE" .dts)
|
||||
if ! grep -q "${DTB_NAME}.dtb" "$ROCKCHIP_MAKEFILE"; then
|
||||
# Add before the first empty line or at the end of the dtb list
|
||||
echo "dtb-\$(CONFIG_ARCH_ROCKCHIP) += ${DTB_NAME}.dtb" >> "$ROCKCHIP_MAKEFILE"
|
||||
log " Added to Makefile: ${DTB_NAME}.dtb"
|
||||
fi
|
||||
done
|
||||
|
||||
log " Copied $DTS_COUNT DTS files"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 4: Configure Kernel
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 4: Configuring kernel..."
|
||||
|
||||
if [ ! -f "$CONFIG_BASE" ]; then
|
||||
error "Config base not found: $CONFIG_BASE"
|
||||
fi
|
||||
|
||||
# Copy Arch R base config
|
||||
cp "$CONFIG_BASE" "$KERNEL_SRC/.config"
|
||||
|
||||
# Replace placeholder for initramfs
|
||||
INITRAMFS_DIR="$OUTPUT_DIR/initramfs"
|
||||
if [ -d "$INITRAMFS_DIR" ] && [ -x "$INITRAMFS_DIR/init" ]; then
|
||||
log " Embedding initramfs from: $INITRAMFS_DIR"
|
||||
sed -i "s|@INITRAMFS_SOURCE@|${INITRAMFS_DIR}|" "$KERNEL_SRC/.config"
|
||||
else
|
||||
warn " Initramfs not found at $INITRAMFS_DIR"
|
||||
warn " Run build-initramfs.sh first! Disabling embedded initramfs."
|
||||
sed -i 's|CONFIG_INITRAMFS_SOURCE=.*|CONFIG_INITRAMFS_SOURCE=""|' "$KERNEL_SRC/.config"
|
||||
fi
|
||||
|
||||
# Finalize config
|
||||
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE olddefconfig
|
||||
|
||||
# Verify critical settings
|
||||
log " Verifying config..."
|
||||
check_config() {
|
||||
local key="$1" expected="$2" desc="$3"
|
||||
local val=$(grep "^${key}=" "$KERNEL_SRC/.config" 2>/dev/null | head -1)
|
||||
if [ -z "$val" ]; then
|
||||
val=$(grep "^# ${key} is not set" "$KERNEL_SRC/.config" 2>/dev/null | head -1)
|
||||
fi
|
||||
if echo "$val" | grep -q "$expected"; then
|
||||
log " $desc: OK"
|
||||
else
|
||||
warn " $desc: UNEXPECTED ($val)"
|
||||
fi
|
||||
}
|
||||
|
||||
check_config "CONFIG_DRM_PANFROST" "=m" "Panfrost GPU"
|
||||
check_config "CONFIG_DRM_PANEL_SITRONIX_ST7703" "=y" "ST7703 panel"
|
||||
check_config "CONFIG_FRAMEBUFFER_CONSOLE" "=y" "fbcon"
|
||||
check_config "CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER" "is not set" "No deferred takeover"
|
||||
check_config "CONFIG_EXT4_FS" "=y" "ext4"
|
||||
check_config "CONFIG_DEVTMPFS" "=y" "devtmpfs"
|
||||
|
||||
log " Kernel configured"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 3: Build Kernel Image
|
||||
# Step 5: Build Kernel Image
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 3: Building kernel Image..."
|
||||
log "Step 5: Building kernel Image..."
|
||||
|
||||
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE Image 2>&1 | \
|
||||
tail -5
|
||||
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE Image 2>&1 | tail -5
|
||||
|
||||
if [ ! -f "$KERNEL_SRC/arch/arm64/boot/Image" ]; then
|
||||
error "Kernel Image build failed!"
|
||||
@@ -159,85 +217,104 @@ IMAGE_SIZE=$(du -h "$KERNEL_SRC/arch/arm64/boot/Image" | cut -f1)
|
||||
log " Kernel Image built ($IMAGE_SIZE)"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 4: Build Device Tree
|
||||
# Step 6: Build ALL Device Trees
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 4: Building Device Tree ($R36S_DTB)..."
|
||||
log "Step 6: Building Device Trees..."
|
||||
|
||||
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
|
||||
"rockchip/${R36S_DTB}.dtb" 2>&1 | tail -5
|
||||
# Build dtbs target (compiles all DTBs referenced in Makefile)
|
||||
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE DTC_FLAGS=-@ dtbs 2>&1 | tail -10
|
||||
|
||||
if [ ! -f "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${R36S_DTB}.dtb" ]; then
|
||||
error "DTB build failed: ${R36S_DTB}.dtb"
|
||||
# Verify R36S DTB was built
|
||||
if [ ! -f "$KERNEL_DTS_DIR/rk3326-gameconsole-r36s.dtb" ]; then
|
||||
error "R36S DTB not built!"
|
||||
fi
|
||||
|
||||
log " DTB built: ${R36S_DTB}.dtb"
|
||||
|
||||
# Build clone DTB (if DTS was copied)
|
||||
if [ -f "$CLONE_DTS_DEST" ]; then
|
||||
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
|
||||
"rockchip/${CLONE_DTB}.dtb" 2>&1 | tail -5
|
||||
if [ -f "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dtb" ]; then
|
||||
log " DTB built (clone): ${CLONE_DTB}.dtb"
|
||||
else
|
||||
warn "Clone DTB build failed: ${CLONE_DTB}.dtb"
|
||||
fi
|
||||
fi
|
||||
DTB_COUNT=$(find "$KERNEL_DTS_DIR" -name "rk3326-*.dtb" | wc -l)
|
||||
log " Built $DTB_COUNT RK3326 DTBs"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 5: Build Kernel Modules
|
||||
# Step 7: Build Kernel Modules
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 5: Building kernel modules..."
|
||||
log "Step 7: Building kernel modules..."
|
||||
|
||||
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE modules 2>&1 | \
|
||||
tail -5
|
||||
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE modules 2>&1 | tail -5
|
||||
|
||||
log " Kernel modules built"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 6: Install to Output Directory
|
||||
# Step 8: Build Out-of-Tree Drivers
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 6: Installing artifacts..."
|
||||
log "Step 8: Building out-of-tree drivers..."
|
||||
|
||||
if [ -d "$JOYPAD_DIR" ] && [ -f "$JOYPAD_DIR/Makefile" ]; then
|
||||
log " Building archr-joypad..."
|
||||
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
|
||||
M="$JOYPAD_DIR" modules 2>&1 | tail -5
|
||||
if find "$JOYPAD_DIR" -name "*.ko" | grep -q .; then
|
||||
log " archr-joypad: OK"
|
||||
else
|
||||
warn " archr-joypad: no .ko files produced"
|
||||
fi
|
||||
else
|
||||
warn " Joypad driver not found at: $JOYPAD_DIR"
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 9: Install to Output Directory
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 9: Installing artifacts..."
|
||||
|
||||
mkdir -p "$BOOT_DIR"
|
||||
mkdir -p "$MODULES_DIR"
|
||||
|
||||
# Copy kernel image
|
||||
cp "$KERNEL_SRC/arch/arm64/boot/Image" "$BOOT_DIR/"
|
||||
log " Copied: Image"
|
||||
# Copy kernel image as KERNEL (Arch R naming convention)
|
||||
cp "$KERNEL_SRC/arch/arm64/boot/Image" "$BOOT_DIR/KERNEL"
|
||||
log " Copied: KERNEL"
|
||||
|
||||
# Copy R36S DTB
|
||||
cp "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${R36S_DTB}.dtb" "$BOOT_DIR/"
|
||||
log " Copied: ${R36S_DTB}.dtb"
|
||||
# Copy ALL RK3326 DTBs to dtbs/ subdirectory
|
||||
mkdir -p "$BOOT_DIR/dtbs"
|
||||
for DTB in "$KERNEL_DTS_DIR"/rk3326-*.dtb; do
|
||||
[ -f "$DTB" ] || continue
|
||||
cp "$DTB" "$BOOT_DIR/dtbs/"
|
||||
done
|
||||
log " Copied: $(ls "$BOOT_DIR/dtbs"/rk3326-*.dtb 2>/dev/null | wc -l) DTBs to dtbs/"
|
||||
|
||||
# Copy clone DTB (if built)
|
||||
if [ -f "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dtb" ]; then
|
||||
cp "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dtb" "$BOOT_DIR/"
|
||||
log " Copied: ${CLONE_DTB}.dtb"
|
||||
fi
|
||||
|
||||
# Install modules (use pipefail to catch errors masked by tail)
|
||||
# Install kernel modules
|
||||
set -o pipefail
|
||||
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
|
||||
INSTALL_MOD_PATH="$MODULES_DIR" \
|
||||
modules_install 2>&1 | tail -5
|
||||
set +o pipefail
|
||||
|
||||
# Remove symlinks (save space)
|
||||
# Install joypad driver module
|
||||
if find "$JOYPAD_DIR" -name "*.ko" | grep -q .; then
|
||||
KREL=$(cat "$KERNEL_SRC/include/config/kernel.release" 2>/dev/null)
|
||||
JOYPAD_DEST="$MODULES_DIR/lib/modules/$KREL/extra/archr-joypad"
|
||||
mkdir -p "$JOYPAD_DEST"
|
||||
cp "$JOYPAD_DIR"/*.ko "$JOYPAD_DEST/"
|
||||
log " Installed joypad modules to: extra/archr-joypad/"
|
||||
# Regenerate modules.dep
|
||||
depmod -b "$MODULES_DIR" "$KREL"
|
||||
fi
|
||||
|
||||
# Remove build/source symlinks (save space on target)
|
||||
rm -f "$MODULES_DIR/lib/modules/"*/source 2>/dev/null || true
|
||||
rm -f "$MODULES_DIR/lib/modules/"*/build 2>/dev/null || true
|
||||
|
||||
# Verify critical module was installed
|
||||
KERNEL_FULL=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null)
|
||||
KREL=$(cat "$KERNEL_SRC/include/config/kernel.release" 2>/dev/null || echo "$KERNEL_FULL")
|
||||
if find "$MODULES_DIR/lib/modules/$KREL" -name 'panfrost.ko*' 2>/dev/null | grep -q .; then
|
||||
log " Panfrost module: INSTALLED"
|
||||
else
|
||||
warn " Panfrost module: NOT FOUND in $MODULES_DIR/lib/modules/$KREL/"
|
||||
warn " Check directory permissions (must be writable by build user)"
|
||||
fi
|
||||
# Verify critical modules
|
||||
KREL=$(cat "$KERNEL_SRC/include/config/kernel.release" 2>/dev/null)
|
||||
for MOD in panfrost; do
|
||||
if find "$MODULES_DIR/lib/modules/$KREL" -name "${MOD}.ko*" 2>/dev/null | grep -q .; then
|
||||
log " Module OK: $MOD"
|
||||
else
|
||||
warn " Module MISSING: $MOD"
|
||||
fi
|
||||
done
|
||||
# Note: rockchipdrm is CONFIG_DRM_ROCKCHIP=y (built-in, not a module) — no .ko to check
|
||||
|
||||
log " Modules installed"
|
||||
|
||||
@@ -250,20 +327,21 @@ log " BUILD COMPLETE"
|
||||
log "================================================================"
|
||||
log ""
|
||||
|
||||
KERNEL_FULL=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null || echo "$KERNEL_VERSION")
|
||||
IMAGE_SIZE=$(du -h "$BOOT_DIR/Image" | cut -f1)
|
||||
DTB_SIZE=$(du -h "$BOOT_DIR/${R36S_DTB}.dtb" | cut -f1)
|
||||
MODULES_SIZE=$(du -sh "$MODULES_DIR" 2>/dev/null | cut -f1 || echo "N/A")
|
||||
KERNEL_FULL=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null)
|
||||
KERNEL_SIZE=$(du -h "$BOOT_DIR/KERNEL" | cut -f1)
|
||||
MODULES_SIZE=$(du -sh "$MODULES_DIR" 2>/dev/null | cut -f1)
|
||||
DTB_COUNT=$(ls "$BOOT_DIR/dtbs"/rk3326-*.dtb 2>/dev/null | wc -l)
|
||||
|
||||
log "Kernel: $KERNEL_FULL"
|
||||
log "Kernel: $KERNEL_FULL (mainline + Arch R patches)"
|
||||
log "KERNEL: $BOOT_DIR/KERNEL ($KERNEL_SIZE)"
|
||||
log "DTBs: $DTB_COUNT files in $BOOT_DIR/dtbs/"
|
||||
log "Modules: $MODULES_DIR/ ($MODULES_SIZE)"
|
||||
log ""
|
||||
CLONE_DTB_SIZE="N/A"
|
||||
[ -f "$BOOT_DIR/${CLONE_DTB}.dtb" ] && CLONE_DTB_SIZE=$(du -h "$BOOT_DIR/${CLONE_DTB}.dtb" | cut -f1)
|
||||
|
||||
log "Artifacts:"
|
||||
log " Image: $BOOT_DIR/Image ($IMAGE_SIZE)"
|
||||
log " DTB: $BOOT_DIR/${R36S_DTB}.dtb ($DTB_SIZE)"
|
||||
log " DTB clone: $BOOT_DIR/${CLONE_DTB}.dtb ($CLONE_DTB_SIZE)"
|
||||
log " Modules: $MODULES_DIR/ ($MODULES_SIZE)"
|
||||
log "Key DTBs:"
|
||||
for DTB in rk3326-gameconsole-r36s rk3326-odroid-go2 rk3326-gameconsole-r33s; do
|
||||
if [ -f "$BOOT_DIR/dtbs/${DTB}.dtb" ]; then
|
||||
log " ${DTB}.dtb ($(du -h "$BOOT_DIR/dtbs/${DTB}.dtb" | cut -f1))"
|
||||
fi
|
||||
done
|
||||
log ""
|
||||
log "Kernel 6.6 ready for R36S (original + clone)!"
|
||||
log "Ready for deployment to SD card!"
|
||||
|
||||
+208
-53
@@ -123,10 +123,11 @@ 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 - all official mirrors, Americas first
|
||||
# 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
|
||||
@@ -294,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
|
||||
@@ -378,7 +378,6 @@ cat > /etc/systemd/system/archr-variant-sync.service << 'VARSYNC_EOF'
|
||||
[Unit]
|
||||
Description=Sync variant from BOOT partition
|
||||
After=local-fs.target
|
||||
Before=panel-detect.service
|
||||
RequiresMountsFor=/boot
|
||||
ConditionPathExists=!/etc/archr/variant
|
||||
|
||||
@@ -393,25 +392,6 @@ VARSYNC_EOF
|
||||
|
||||
systemctl enable archr-variant-sync
|
||||
|
||||
# Panel auto-detect wizard (first boot / X-button reset)
|
||||
cat > /etc/systemd/system/panel-detect.service << 'PANELDET_EOF'
|
||||
[Unit]
|
||||
Description=Arch R Panel Detection Wizard
|
||||
After=local-fs.target
|
||||
Before=emulationstation.service
|
||||
RequiresMountsFor=/boot
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/panel-detect.py
|
||||
TimeoutStartSec=600
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
PANELDET_EOF
|
||||
|
||||
systemctl enable panel-detect
|
||||
|
||||
# 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.
|
||||
@@ -531,6 +511,127 @@ TIMING_EOF
|
||||
|
||||
systemctl enable boot-timing
|
||||
|
||||
# Debug dump: comprehensive system info to /boot/debug.log (readable from PC)
|
||||
cat > /etc/systemd/system/archr-debug-dump.service << 'DEBUG_EOF'
|
||||
[Unit]
|
||||
Description=Arch R Debug Dump
|
||||
After=emulationstation.service
|
||||
After=multi-user.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash -c '\
|
||||
sleep 20; \
|
||||
{ \
|
||||
echo "=== Arch R Debug Dump ($(date)) ==="; \
|
||||
echo ""; \
|
||||
echo "--- Kernel ---"; \
|
||||
uname -a; \
|
||||
echo ""; \
|
||||
echo "--- Input Devices ---"; \
|
||||
for d in /dev/input/event*; do \
|
||||
name=$(cat /sys/class/input/$(basename $d)/device/name 2>/dev/null); \
|
||||
echo " $d: $name"; \
|
||||
done; \
|
||||
echo ""; \
|
||||
echo "--- DRM ---"; \
|
||||
for c in /sys/class/drm/card*/status; do \
|
||||
echo " $c: $(cat $c 2>/dev/null)"; \
|
||||
done; \
|
||||
cat /sys/class/drm/card*/modes 2>/dev/null | head -5; \
|
||||
echo ""; \
|
||||
echo "--- Backlight ---"; \
|
||||
for bl in /sys/class/backlight/*/; do \
|
||||
echo " $(basename $bl): cur=$(cat ${bl}brightness 2>/dev/null) max=$(cat ${bl}max_brightness 2>/dev/null)"; \
|
||||
done; \
|
||||
echo ""; \
|
||||
echo "--- ALSA Controls ---"; \
|
||||
amixer scontrols 2>/dev/null || echo " (no ALSA)"; \
|
||||
echo ""; \
|
||||
echo "--- CPU/GPU ---"; \
|
||||
echo " CPU: $(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq 2>/dev/null)kHz ($(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_governor 2>/dev/null))"; \
|
||||
echo " GPU: $(cat /sys/devices/platform/ff400000.gpu/devfreq/ff400000.gpu/cur_freq 2>/dev/null)Hz"; \
|
||||
echo " Temp: $(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null)"; \
|
||||
echo ""; \
|
||||
echo "--- Memory ---"; \
|
||||
free -h; \
|
||||
echo ""; \
|
||||
echo "--- Loaded Modules ---"; \
|
||||
lsmod 2>/dev/null | head -30; \
|
||||
echo ""; \
|
||||
echo "--- Failed Services ---"; \
|
||||
systemctl --failed --no-pager 2>/dev/null; \
|
||||
echo ""; \
|
||||
echo "--- dmesg errors ---"; \
|
||||
dmesg -l err,warn 2>/dev/null | tail -30; \
|
||||
} > /boot/debug.log 2>&1; \
|
||||
chmod 644 /boot/debug.log'
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
DEBUG_EOF
|
||||
|
||||
systemctl enable archr-debug-dump
|
||||
|
||||
# USB auto-mount service (triggered by udev on device insertion)
|
||||
cat > /etc/systemd/system/archr-automount.service << 'AUTOMOUNT_SVC'
|
||||
[Unit]
|
||||
Description=Arch R USB Auto-Mount
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/archr-automount mount
|
||||
AUTOMOUNT_SVC
|
||||
|
||||
# Save config on shutdown (backs up ALSA state, brightness, WiFi to /boot)
|
||||
cat > /etc/systemd/system/archr-save-config.service << 'SAVECONF_SVC'
|
||||
[Unit]
|
||||
Description=Arch R Save Config
|
||||
DefaultDependencies=no
|
||||
Before=shutdown.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/archr-save-config backup
|
||||
|
||||
[Install]
|
||||
WantedBy=shutdown.target
|
||||
SAVECONF_SVC
|
||||
|
||||
systemctl enable archr-save-config
|
||||
|
||||
# Bluetooth auto-pairing agent (runs alongside bluetoothd)
|
||||
cat > /etc/systemd/system/archr-bluetooth-agent.service << 'BTAGENT_SVC'
|
||||
[Unit]
|
||||
Description=Arch R Bluetooth Agent
|
||||
After=bluetooth.service
|
||||
PartOf=bluetooth.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/archr-bluetooth-agent
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=bluetooth.target
|
||||
BTAGENT_SVC
|
||||
|
||||
systemctl enable archr-bluetooth-agent
|
||||
|
||||
# Sleep configuration (suspend disabled by default, user enables via archr-suspend-mode)
|
||||
mkdir -p /etc/systemd/sleep.conf.d
|
||||
cat > /etc/systemd/sleep.conf.d/archr.conf << 'SLEEP_CONF'
|
||||
[Sleep]
|
||||
AllowSuspend=yes
|
||||
SuspendState=mem
|
||||
AllowHibernation=no
|
||||
SLEEP_CONF
|
||||
|
||||
# Modules blacklist for sleep (unloaded before suspend by archr-sleep hook)
|
||||
mkdir -p /etc/archr
|
||||
install -m 644 /tmp/modules.bad /etc/archr/modules.bad 2>/dev/null || true
|
||||
|
||||
# Delete stock ALARM initramfs and kernel (we use our own kernel + initramfs)
|
||||
# Our initramfs.img is built by build-image.sh and placed on BOOT partition
|
||||
rm -f /boot/initramfs-linux.img /boot/Image /boot/Image.gz 2>/dev/null
|
||||
@@ -546,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/local/bin/input-merge, /usr/bin/kill, /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)
|
||||
@@ -597,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
|
||||
@@ -694,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 \
|
||||
@@ -721,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
|
||||
@@ -960,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
|
||||
@@ -977,7 +1085,7 @@ 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 core options (per-core tuning for RK3326, from ROCKNIX)
|
||||
# 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
|
||||
@@ -987,9 +1095,19 @@ if command -v aarch64-linux-gnu-gcc &>/dev/null; then
|
||||
"$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 not compiled"
|
||||
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/"
|
||||
@@ -1011,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
|
||||
@@ -1034,10 +1186,6 @@ log " ✓ First boot script installed"
|
||||
# Boot splash: no binary needed in rootfs — splash is embedded in initramfs /init
|
||||
# (built by build-image.sh: archr-init.c + embedded splash BMP → initramfs.img)
|
||||
|
||||
# Panel detection wizard
|
||||
install -m 755 "$SCRIPT_DIR/scripts/panel-detect.py" "$ROOTFS_DIR/usr/local/bin/panel-detect.py"
|
||||
log " ✓ Panel detection wizard installed"
|
||||
|
||||
# RetroArch config (install to user's config dir where retroarch expects it)
|
||||
mkdir -p "$ROOTFS_DIR/home/archr/.config/retroarch"
|
||||
cp "$SCRIPT_DIR/config/retroarch.cfg" "$ROOTFS_DIR/home/archr/.config/retroarch/retroarch.cfg"
|
||||
@@ -1069,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)"
|
||||
@@ -1082,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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#==============================================================================
|
||||
# Arch R - Build Mainline U-Boot for R36S Clones
|
||||
#==============================================================================
|
||||
# Uses mainline U-Boot v2025.10 + ROCKNIX patches
|
||||
# Uses mainline U-Boot v2025.10 + RK3326 handheld patches
|
||||
# Produces: idbloader.img, uboot.img, trust.img (Rockchip format)
|
||||
#
|
||||
# Usage:
|
||||
|
||||
+125
-79
@@ -1,121 +1,163 @@
|
||||
#!/bin/bash
|
||||
|
||||
#==============================================================================
|
||||
# Arch R - U-Boot Build Script for R36S
|
||||
# Arch R - Build U-Boot BSP for RK3326
|
||||
#==============================================================================
|
||||
# Builds custom U-Boot with R36S original/clone auto-detection via eMMC probe.
|
||||
# Cross-compiles for aarch64 (CONFIG_ARM64=y in defconfig).
|
||||
# Builds U-Boot v2017.09 BSP for all RK3326 handhelds.
|
||||
# Same binary works for both original and clone boards — hwrev.c detects
|
||||
# board variant via SARADC ch0, boot.ini overrides DTB as needed.
|
||||
#
|
||||
# Custom modifications:
|
||||
# - cmd/hwrev.c: R36S detection via eMMC probe (original vs clone)
|
||||
# - r36s-uboot.dts: U-Boot display DTB for original (Panel 4-V22 NV3052C)
|
||||
# - r36s-clone-uboot.dts: U-Boot display DTB for clone (Type5 NV3052C)
|
||||
# Output: bootloader/u-boot-rk3326/sd_fuse/
|
||||
# idbloader.img — DDR init + miniloader
|
||||
# uboot.img — U-Boot proper
|
||||
# trust.img — ARM Trusted Firmware (BL31 + BL32)
|
||||
#
|
||||
# Prerequisites:
|
||||
# sudo apt install gcc-aarch64-linux-gnu
|
||||
# Usage:
|
||||
# ./build-uboot.sh # build for SD card
|
||||
# ./build-uboot.sh --clean # clean build artifacts first
|
||||
#==============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
UBOOT_DIR="$SCRIPT_DIR/bootloader/u-boot-rk3326"
|
||||
RKBIN_DIR="$SCRIPT_DIR/bootloader/rkbin"
|
||||
OUTPUT_DIR="$UBOOT_DIR/sd_fuse"
|
||||
|
||||
# Firmware versions (from rkbin)
|
||||
DDR_BIN="$RKBIN_DIR/bin/rk33/rk3326_ddr_333MHz_v2.11.bin"
|
||||
MINILOADER_BIN="$RKBIN_DIR/bin/rk33/rk3326_miniloader_v1.40.bin"
|
||||
BL31_ELF="$RKBIN_DIR/bin/rk33/rk3326_bl31_v1.34.elf"
|
||||
BL32_BIN="$RKBIN_DIR/bin/rk33/rk3326_bl32_v2.19.bin"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] WARNING:${NC} $1"; }
|
||||
error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $1"; exit 1; }
|
||||
log() { echo -e "${GREEN}[U-BOOT]${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW}[U-BOOT] WARNING:${NC} $1"; }
|
||||
error() { echo -e "${RED}[U-BOOT] ERROR:${NC} $1"; exit 1; }
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Configuration
|
||||
# Parse arguments
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
UBOOT_DIR="$SCRIPT_DIR/bootloader"
|
||||
UBOOT_REPO="https://github.com/christianhaitian/RG351MP-u-boot"
|
||||
UBOOT_SRC="$UBOOT_DIR/u-boot-rk3326"
|
||||
OUTPUT_DIR="$SCRIPT_DIR/output/bootloader"
|
||||
|
||||
# U-Boot for RK3326 is aarch64 (CONFIG_ARM64=y in defconfig)
|
||||
CROSS_COMPILE="aarch64-linux-gnu-"
|
||||
|
||||
log "=== Arch R - U-Boot Builder (Custom R36S) ==="
|
||||
CLEAN=false
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--clean) CLEAN=true; shift ;;
|
||||
*) error "Unknown option: $1\nUsage: $0 [--clean]" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 1: Clone U-Boot
|
||||
# Prerequisites
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 1: Checking U-Boot source..."
|
||||
log "=== Arch R U-Boot Builder ==="
|
||||
|
||||
mkdir -p "$UBOOT_DIR"
|
||||
if ! command -v aarch64-linux-gnu-gcc &>/dev/null; then
|
||||
error "Cross-compiler not found. Install with: sudo apt install gcc-aarch64-linux-gnu"
|
||||
fi
|
||||
|
||||
if [ ! -d "$UBOOT_SRC" ]; then
|
||||
log " Cloning U-Boot for RK3326..."
|
||||
git clone --depth 1 "$UBOOT_REPO" "$UBOOT_SRC"
|
||||
log " Cloned"
|
||||
else
|
||||
log " Source exists"
|
||||
if [ ! -d "$UBOOT_DIR" ]; then
|
||||
error "U-Boot source not found at: $UBOOT_DIR"
|
||||
fi
|
||||
|
||||
if [ ! -f "$DDR_BIN" ]; then
|
||||
error "rkbin firmware not found at: $RKBIN_DIR\nExpected: $DDR_BIN"
|
||||
fi
|
||||
|
||||
GCC_VER=$(aarch64-linux-gnu-gcc -dumpversion)
|
||||
log "Compiler: aarch64-linux-gnu-gcc $GCC_VER"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Clean (optional)
|
||||
#------------------------------------------------------------------------------
|
||||
if [ "$CLEAN" = true ]; then
|
||||
log "Cleaning previous build..."
|
||||
make -C "$UBOOT_DIR" distclean 2>/dev/null || true
|
||||
rm -rf "$OUTPUT_DIR"
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 2: Verify toolchain
|
||||
# Build U-Boot
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 2: Checking toolchain..."
|
||||
log "Step 1: Configuring (odroidgoa_defconfig)..."
|
||||
|
||||
if ! command -v ${CROSS_COMPILE}gcc &>/dev/null; then
|
||||
error "aarch64 toolchain not found!\n Install: sudo apt install gcc-aarch64-linux-gnu"
|
||||
cd "$UBOOT_DIR"
|
||||
|
||||
# GCC 13+ needs these warnings suppressed for 2017.09 codebase
|
||||
export KCFLAGS="-Wno-error=array-bounds -Wno-error=enum-int-mismatch -Wno-error=implicit-function-declaration -Wno-error=format-overflow"
|
||||
|
||||
make odroidgoa_defconfig 2>&1 | tail -3
|
||||
|
||||
log "Step 2: Building U-Boot..."
|
||||
NCPUS=$(nproc 2>/dev/null || echo 4)
|
||||
make CROSS_COMPILE=aarch64-linux-gnu- all --jobs=$NCPUS 2>&1 | tail -5
|
||||
|
||||
if [ ! -f "u-boot.bin" ]; then
|
||||
error "Build failed — u-boot.bin not found"
|
||||
fi
|
||||
|
||||
log " $(${CROSS_COMPILE}gcc --version | head -1)"
|
||||
log " u-boot.bin built OK"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 3: Build U-Boot
|
||||
# Pack images
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 3: Building U-Boot..."
|
||||
|
||||
cd "$UBOOT_SRC"
|
||||
|
||||
# GCC 13+ adds stricter warnings that U-Boot 2017.09 doesn't pass.
|
||||
# Disable specific -Werror flags that break with modern GCC:
|
||||
# address-of-packed-member: disk/part_efi.c (packed struct pointer)
|
||||
# enum-int-mismatch: common/command.c (enum command_ret_t vs int)
|
||||
# maybe-uninitialized: common/edid.c (hdmi_len variable)
|
||||
GCC_COMPAT_FLAGS="-Wno-error=address-of-packed-member -Wno-error=enum-int-mismatch -Wno-error=maybe-uninitialized"
|
||||
|
||||
make CROSS_COMPILE=$CROSS_COMPILE odroidgoa_defconfig
|
||||
make CROSS_COMPILE=$CROSS_COMPILE KCFLAGS="$GCC_COMPAT_FLAGS" -j$(nproc)
|
||||
|
||||
log " Built"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 4: Copy artifacts
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 4: Copying bootloader files..."
|
||||
log "Step 3: Packing images..."
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
if [ -d "sd_fuse" ] && [ -f "sd_fuse/idbloader.img" ]; then
|
||||
cp sd_fuse/idbloader.img "$OUTPUT_DIR/"
|
||||
cp sd_fuse/uboot.img "$OUTPUT_DIR/"
|
||||
cp sd_fuse/trust.img "$OUTPUT_DIR/"
|
||||
log " Bootloader binaries copied"
|
||||
else
|
||||
error "sd_fuse directory not found — U-Boot build may have failed"
|
||||
fi
|
||||
# idbloader.img = DDR init + miniloader
|
||||
"$UBOOT_DIR/tools/mkimage" -n px30 -T rksd -d "$DDR_BIN" "$OUTPUT_DIR/idbloader.img"
|
||||
cat "$MINILOADER_BIN" >> "$OUTPUT_DIR/idbloader.img"
|
||||
log " idbloader.img (DDR v2.11 + miniloader v1.40)"
|
||||
|
||||
# Copy R36S U-Boot DTBs
|
||||
for dtb in r36s-uboot.dtb r36s-clone-uboot.dtb; do
|
||||
if [ -f "arch/arm/dts/$dtb" ]; then
|
||||
cp "arch/arm/dts/$dtb" "$OUTPUT_DIR/"
|
||||
log " DTB copied: $dtb"
|
||||
else
|
||||
warn "DTB not found: $dtb"
|
||||
# uboot.img = packed U-Boot binary
|
||||
UBOOT_LOAD_ADDR=$(grep -r "CONFIG_SYS_TEXT_BASE" include/autoconf.mk 2>/dev/null | cut -d= -f2 || echo "0x00200000")
|
||||
"$RKBIN_DIR/tools/loaderimage" --pack --uboot u-boot.bin "$OUTPUT_DIR/uboot.img" "$UBOOT_LOAD_ADDR" 2>&1 | tail -1
|
||||
log " uboot.img (load addr: $UBOOT_LOAD_ADDR)"
|
||||
|
||||
# trust.img = BL31 + BL32
|
||||
cat > /tmp/archr-trust.ini << TRUST_EOF
|
||||
[VERSION]
|
||||
MAJOR=1
|
||||
MINOR=0
|
||||
[BL30_OPTION]
|
||||
SEC=0
|
||||
[BL31_OPTION]
|
||||
SEC=1
|
||||
PATH=$BL31_ELF
|
||||
ADDR=0x00010000
|
||||
[BL32_OPTION]
|
||||
SEC=1
|
||||
PATH=$BL32_BIN
|
||||
ADDR=0x08400000
|
||||
[BL33_OPTION]
|
||||
SEC=0
|
||||
[OUTPUT]
|
||||
PATH=$OUTPUT_DIR/trust.img
|
||||
TRUST_EOF
|
||||
|
||||
"$RKBIN_DIR/tools/trust_merger" --rsa 3 /tmp/archr-trust.ini 2>&1 | tail -1
|
||||
rm -f /tmp/archr-trust.ini
|
||||
log " trust.img (BL31 v1.34 + BL32 v2.19)"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Verify
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 4: Verifying..."
|
||||
|
||||
for img in idbloader.img uboot.img trust.img; do
|
||||
if [ ! -f "$OUTPUT_DIR/$img" ]; then
|
||||
error "Missing: $OUTPUT_DIR/$img"
|
||||
fi
|
||||
SIZE=$(du -h "$OUTPUT_DIR/$img" | cut -f1)
|
||||
log " $img ($SIZE)"
|
||||
done
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -124,7 +166,11 @@ done
|
||||
log ""
|
||||
log "=== U-Boot Build Complete ==="
|
||||
log ""
|
||||
log "Bootloader: $OUTPUT_DIR/"
|
||||
ls -lh "$OUTPUT_DIR/"
|
||||
log "Output: $OUTPUT_DIR/"
|
||||
log " idbloader.img — DDR v2.11 + miniloader v1.40"
|
||||
log " uboot.img — U-Boot v2017.09 BSP"
|
||||
log " trust.img — BL31 v1.34 + BL32 v2.19"
|
||||
log ""
|
||||
log "These will be installed by build-image.sh"
|
||||
log "Same binary for both original and clone images."
|
||||
log "Board detection: hwrev.c (SARADC ch0)"
|
||||
log "DTB selection: boot.ini (variant A or B)"
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
# ============================================================
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,74 +0,0 @@
|
||||
odroidgoa-uboot-config
|
||||
|
||||
########################################################################
|
||||
# Arch R Boot Configuration
|
||||
#
|
||||
# Auto-detects SD card MMC device AND root partition:
|
||||
# Original R36S: eMMC=mmc0, SD=mmc1 → root=/dev/mmcblk1p2
|
||||
# Clone (no eMMC): SD=mmc0 → root=/dev/mmcblk0p2
|
||||
#
|
||||
# Panel config from panel.txt (managed by panel-detect.py).
|
||||
# Panel reset handled in Linux (panel-detect.py) -- no GPIO check here
|
||||
# because X button GPIO differs between boards (modular!).
|
||||
########################################################################
|
||||
|
||||
# --- Turn on LED immediately (feedback: device is booting) ---
|
||||
gpio set b5
|
||||
|
||||
setenv tmp_loadaddr "0x01e00000"
|
||||
setenv dtb_loadaddr "0x01f00000"
|
||||
setenv loadaddr "0x02000000"
|
||||
|
||||
# --- Auto-detect MMC device (loads kernel Image into memory) ---
|
||||
setenv mmcdev 1
|
||||
if load mmc 1:1 ${loadaddr} Image; then
|
||||
setenv mmcdev 1
|
||||
elif load mmc 0:1 ${loadaddr} Image; then
|
||||
setenv mmcdev 0
|
||||
else
|
||||
sleep 15
|
||||
poweroff
|
||||
fi
|
||||
|
||||
# --- Panel DTB selection (read panel.txt written by panel-detect.py) ---
|
||||
# Pre-merged DTBs: overlay already applied at build-time (no fdt apply needed).
|
||||
# panel.txt contains PanelDTB=kernel-panelN.dtb (or empty for default).
|
||||
setenv PanelDTB ""
|
||||
mw.b ${tmp_loadaddr} 0x00 0x400
|
||||
if load mmc ${mmcdev}:1 ${tmp_loadaddr} panel.txt; then
|
||||
env import -t ${tmp_loadaddr} ${filesize}
|
||||
fi
|
||||
|
||||
# Select DTB: pre-merged panel DTB if set, otherwise default kernel.dtb
|
||||
if test -n "${PanelDTB}"; then
|
||||
setenv dtb_name "${PanelDTB}"
|
||||
echo "Panel DTB: ${PanelDTB}"
|
||||
else
|
||||
setenv dtb_name "kernel.dtb"
|
||||
fi
|
||||
|
||||
# --- Auto-detect root device (SD card partition 2) ---
|
||||
# mmcdev already detected above: 1 = original (eMMC+SD), 0 = clone (SD only)
|
||||
if test "${mmcdev}" = "1"; then
|
||||
setenv rootdev "/dev/mmcblk1p2"
|
||||
else
|
||||
setenv rootdev "/dev/mmcblk0p2"
|
||||
fi
|
||||
|
||||
# --- Load DTB and boot (Image already loaded above) ---
|
||||
if load mmc ${mmcdev}:1 ${dtb_loadaddr} ${dtb_name}; then
|
||||
|
||||
setenv bootargs "root=${rootdev} rootwait rw console=ttyFIQ0 loglevel=0 quiet vt.global_cursor_default=0 consoleblank=0 printk.devkmsg=off fsck.mode=skip"
|
||||
|
||||
# Load initramfs (splash appears immediately after kernel boot, before systemd)
|
||||
setenv initrd_loadaddr "0x04000000"
|
||||
if load mmc ${mmcdev}:1 ${initrd_loadaddr} initramfs.img; then
|
||||
booti ${loadaddr} ${initrd_loadaddr}:${filesize} ${dtb_loadaddr}
|
||||
else
|
||||
booti ${loadaddr} - ${dtb_loadaddr}
|
||||
fi
|
||||
fi
|
||||
|
||||
# Power off if boot fails
|
||||
sleep 15
|
||||
poweroff
|
||||
@@ -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
|
||||
@@ -0,0 +1,20 @@
|
||||
# Arch R — Gamepad mapping for system tools (menus)
|
||||
# D-pad navigates, A=select, B=back, Start=select, Back=back
|
||||
|
||||
# D-pad → arrow keys for menu navigation
|
||||
up = up
|
||||
down = down
|
||||
left = left
|
||||
right = right
|
||||
|
||||
# A button → Enter (select/confirm)
|
||||
a = enter
|
||||
|
||||
# B button → Escape (back/cancel)
|
||||
b = escape
|
||||
|
||||
# Start → Enter (alternate confirm)
|
||||
start = enter
|
||||
|
||||
# Back/Select → Escape (alternate back)
|
||||
back = escape
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user