mirror of
https://github.com/archr-linux/Arch-R.git
synced 2026-07-12 18:19:42 -07:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 70342ca457 | |||
| b6eff2e748 | |||
| 9c30a92cab | |||
| cbc39b8802 | |||
| 87719600d2 | |||
| baaeb69a19 | |||
| a1efd4fc01 | |||
| e4294ab47b | |||
| 70765e96bd | |||
| 2ccf5383ac | |||
| 476b05cd9a | |||
| a9029b419f |
+20
@@ -71,3 +71,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/
|
||||
@@ -153,11 +153,100 @@ Arch-R/
|
||||
|
||||
## Supported Panels
|
||||
|
||||
Arch R supports 18 display panels via DTBO overlays:
|
||||
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.
|
||||
|
||||
**Original R36S:** Panel 0, Panel 1 (V10), Panel 2 (V12), Panel 3 (V20), Panel 4 (V22, default), Panel 5 (V22 Q8)
|
||||
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.
|
||||
|
||||
**Clones:** Clone Panel 1-10 (ST7703, NV3051D variants), R36 Max, RX6S
|
||||
> **Note:** The numerical panel ordering below is available starting from **beta1.2**. Earlier versions may have a different order.
|
||||
|
||||
### Panel Auto-Detection
|
||||
|
||||
On first boot, Arch R runs a **panel detection wizard** that guides you through selecting your display panel:
|
||||
|
||||
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
|
||||
|
||||
Your selection is saved permanently. To reset it later, **hold X during boot**.
|
||||
|
||||
### R36S Original (6 panels)
|
||||
|
||||
Default: **Panel 4-V22** (~60% of units)
|
||||
|
||||
| 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 |
|
||||
|
||||
### 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 |
|
||||
|
||||
### 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**
|
||||
|
||||
```bash
|
||||
lsblk
|
||||
sudo mount /dev/sdX1 /mnt
|
||||
```
|
||||
|
||||
**Step 2 -- Create panel.txt**
|
||||
|
||||
```bash
|
||||
# Example: Panel 3-V20 (original R36S)
|
||||
echo 'PanelNum=3
|
||||
PanelDTB=kernel-panel3.dtb' | sudo tee /mnt/panel.txt
|
||||
|
||||
# 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
|
||||
|
||||
@@ -165,11 +254,12 @@ Arch R supports 18 display panels via DTBO overlays:
|
||||
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
|
||||
→ systemd → archr-boot-setup (GPU + governors)
|
||||
→ 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)
|
||||
→ emulationstation.service → EmulationStation UI
|
||||
≈ 19 seconds total
|
||||
≈ 19 seconds total (+ wizard on first boot)
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
+824
-153
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+36
-4
@@ -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" ;;
|
||||
@@ -180,13 +184,41 @@ 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)
|
||||
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
|
||||
|
||||
log ""
|
||||
log "═══════════════════════════════════════════════════════════════"
|
||||
log " BUILDING IMAGE (no-panel)"
|
||||
log "═══════════════════════════════════════════════════════════════"
|
||||
"$SCRIPT_DIR/build-image.sh" --variant no-panel
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
+293
-105
File diff suppressed because it is too large
Load Diff
+35
-5
@@ -31,8 +31,9 @@ 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
|
||||
# DTS targets
|
||||
R36S_DTB="rk3326-gameconsole-r36s"
|
||||
CLONE_DTB="rk3326-gameconsole-r36s-clone-type5"
|
||||
|
||||
# Paths
|
||||
KERNEL_SRC="${KERNEL_SRC:-/home/dgateles/Documentos/Projetos/kernel}"
|
||||
@@ -93,6 +94,14 @@ else
|
||||
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
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -164,6 +173,17 @@ 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
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 5: Build Kernel Modules
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -192,6 +212,12 @@ log " Copied: Image"
|
||||
cp "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${R36S_DTB}.dtb" "$BOOT_DIR/"
|
||||
log " Copied: ${R36S_DTB}.dtb"
|
||||
|
||||
# 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)
|
||||
set -o pipefail
|
||||
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
|
||||
@@ -231,9 +257,13 @@ MODULES_SIZE=$(du -sh "$MODULES_DIR" 2>/dev/null | cut -f1 || echo "N/A")
|
||||
|
||||
log "Kernel: $KERNEL_FULL"
|
||||
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 " Modules: $MODULES_DIR/ ($MODULES_SIZE)"
|
||||
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 ""
|
||||
log "Kernel 6.6 ready for R36S!"
|
||||
log "Kernel 6.6 ready for R36S (original + clone)!"
|
||||
|
||||
+82
-12
@@ -123,15 +123,19 @@ 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 mirrors, 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://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)"
|
||||
|
||||
@@ -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,46 @@ 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
|
||||
Before=panel-detect.service
|
||||
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
|
||||
|
||||
# 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.
|
||||
@@ -403,9 +448,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 +531,8 @@ TIMING_EOF
|
||||
|
||||
systemctl enable boot-timing
|
||||
|
||||
# Delete initramfs (not used — extlinux.conf has no INITRD line)
|
||||
# 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 +546,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/bin/kill, /usr/bin/ln, /usr/bin/dmesg, /usr/bin/chvt, /usr/bin/cp, /usr/bin/chmod, /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)
|
||||
@@ -928,8 +977,22 @@ 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, from ROCKNIX)
|
||||
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"
|
||||
else
|
||||
warn "aarch64-linux-gnu-gcc not found — input-merge not compiled"
|
||||
fi
|
||||
# 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
|
||||
@@ -968,6 +1031,13 @@ 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)
|
||||
|
||||
# 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"
|
||||
|
||||
Executable
+174
@@ -0,0 +1,174 @@
|
||||
#!/bin/bash
|
||||
#==============================================================================
|
||||
# Arch R - Build Mainline U-Boot for R36S Clones
|
||||
#==============================================================================
|
||||
# Uses mainline U-Boot v2025.10 + ROCKNIX 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"
|
||||
+65
-35
@@ -1,9 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
#==============================================================================
|
||||
# Arch R - Build U-Boot for R36S
|
||||
# Arch R - U-Boot Build Script for R36S
|
||||
#==============================================================================
|
||||
# Builds U-Boot bootloader for RK3326 (R36S/RG351MP compatible)
|
||||
# Builds custom U-Boot with R36S original/clone auto-detection via eMMC probe.
|
||||
# Cross-compiles for aarch64 (CONFIG_ARM64=y in defconfig).
|
||||
#
|
||||
# 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)
|
||||
#
|
||||
# Prerequisites:
|
||||
# sudo apt install gcc-aarch64-linux-gnu
|
||||
#==============================================================================
|
||||
|
||||
set -e
|
||||
@@ -29,7 +38,10 @@ 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 ==="
|
||||
# U-Boot for RK3326 is aarch64 (CONFIG_ARM64=y in defconfig)
|
||||
CROSS_COMPILE="aarch64-linux-gnu-"
|
||||
|
||||
log "=== Arch R - U-Boot Builder (Custom R36S) ==="
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 1: Clone U-Boot
|
||||
@@ -42,59 +54,77 @@ 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"
|
||||
log " Cloned"
|
||||
else
|
||||
log " ✓ U-Boot source exists"
|
||||
log " Source exists"
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 2: Verify toolchain
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 2: Checking toolchain..."
|
||||
|
||||
if ! command -v ${CROSS_COMPILE}gcc &>/dev/null; then
|
||||
error "aarch64 toolchain not found!\n Install: sudo apt install gcc-aarch64-linux-gnu"
|
||||
fi
|
||||
|
||||
log " $(${CROSS_COMPILE}gcc --version | head -1)"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 3: Build U-Boot
|
||||
#------------------------------------------------------------------------------
|
||||
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 2: Build U-Boot
|
||||
# Step 4: Copy artifacts
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 2: Building U-Boot..."
|
||||
|
||||
# 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
|
||||
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"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Step 3: Copy artifacts
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "Step 3: Copying bootloader files..."
|
||||
log "Step 4: Copying bootloader files..."
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
# Copy the bootloader images
|
||||
if [ -d "sd_fuse" ]; then
|
||||
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 files copied"
|
||||
log " Bootloader binaries copied"
|
||||
else
|
||||
error "sd_fuse directory not found - U-Boot build may have failed"
|
||||
error "sd_fuse directory not found — U-Boot build may have failed"
|
||||
fi
|
||||
|
||||
# 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"
|
||||
fi
|
||||
done
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Summary
|
||||
#------------------------------------------------------------------------------
|
||||
log ""
|
||||
log "=== U-Boot Build Complete ==="
|
||||
log ""
|
||||
log "Bootloader files:"
|
||||
ls -la "$OUTPUT_DIR/"
|
||||
log "Bootloader: $OUTPUT_DIR/"
|
||||
ls -lh "$OUTPUT_DIR/"
|
||||
log ""
|
||||
log "These will be automatically installed by build-image.sh"
|
||||
log ""
|
||||
log "✓ U-Boot ready for R36S!"
|
||||
log "These will be installed by build-image.sh"
|
||||
|
||||
@@ -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"
|
||||
+62
-16
@@ -1,24 +1,70 @@
|
||||
ODROIDGOA-UBOOT-CONFIG
|
||||
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.
|
||||
# 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!).
|
||||
########################################################################
|
||||
|
||||
# Memory addresses — kernel at 0x02008000 (matches working R36S firmware)
|
||||
setenv dtb_loadaddr "0x01f00000"
|
||||
setenv loadaddr "0x02008000"
|
||||
# --- Turn on LED immediately (feedback: device is booting) ---
|
||||
gpio set b5
|
||||
|
||||
# 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"
|
||||
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
|
||||
|
||||
Executable
+152
@@ -0,0 +1,152 @@
|
||||
mupen64plus-alt-map = "False"
|
||||
mupen64plus-aspect = "4:3"
|
||||
mupen64plus-astick-deadzone = "15"
|
||||
mupen64plus-astick-sensitivity = "100"
|
||||
mupen64plus-BackgroundMode = "Stripped"
|
||||
mupen64plus-BilinearMode = "standard"
|
||||
mupen64plus-CorrectTexrectCoords = "Auto"
|
||||
mupen64plus-CountPerOp = "0"
|
||||
mupen64plus-CountPerOpDenomPot = "0"
|
||||
mupen64plus-cpucore = "dynamic_recompiler"
|
||||
mupen64plus-d-cbutton = "C3"
|
||||
mupen64plus-DitheringPattern = "True"
|
||||
mupen64plus-DitheringQuantization = "True"
|
||||
mupen64plus-EnableCopyAuxToRDRAM = "True"
|
||||
mupen64plus-EnableCopyColorToRDRAM = "Async"
|
||||
mupen64plus-EnableCopyDepthToRDRAM = "Software"
|
||||
mupen64plus-EnableEnhancedHighResStorage = "False"
|
||||
mupen64plus-EnableEnhancedTextureStorage = "False"
|
||||
mupen64plus-EnableFBEmulation = "True"
|
||||
mupen64plus-EnableFragmentDepthWrite = "False"
|
||||
mupen64plus-EnableHiResAltCRC = "False"
|
||||
mupen64plus-EnableHWLighting = "True"
|
||||
mupen64plus-EnableInaccurateTextureCoordinates = "False"
|
||||
mupen64plus-EnableLegacyBlending = "False"
|
||||
mupen64plus-EnableLODEmulation = "True"
|
||||
mupen64plus-EnableNativeResFactor = "1"
|
||||
mupen64plus-EnableNativeResTexrects = "Optimized"
|
||||
mupen64plus-EnableOverscan = "Enabled"
|
||||
mupen64plus-EnableTexCoordBounds = "False"
|
||||
mupen64plus-EnableTextureCache = "True"
|
||||
mupen64plus-ForceDisableExtraMem = "False"
|
||||
mupen64plus-FrameDuping = "True"
|
||||
mupen64plus-Framerate = "Original"
|
||||
mupen64plus-FXAA = "0"
|
||||
mupen64plus-GLideN64IniBehaviour = "late"
|
||||
mupen64plus-HybridFilter = "True"
|
||||
mupen64plus-IgnoreTLBExceptions = "False"
|
||||
mupen64plus-l-cbutton = "C2"
|
||||
mupen64plus-MaxHiResTxVramLimit = "0"
|
||||
mupen64plus-MaxTxCacheSize = "8000"
|
||||
mupen64plus-MultiSampling = "0"
|
||||
mupen64plus-OverscanBottom = "0"
|
||||
mupen64plus-OverscanLeft = "0"
|
||||
mupen64plus-OverscanRight = "0"
|
||||
mupen64plus-OverscanTop = "0"
|
||||
mupen64plus-pak1 = "memory"
|
||||
mupen64plus-pak2 = "none"
|
||||
mupen64plus-pak3 = "none"
|
||||
mupen64plus-pak4 = "none"
|
||||
mupen64plus-r-cbutton = "C1"
|
||||
mupen64plus-rdp-plugin = "gliden64"
|
||||
mupen64plus-RDRAMImageDitheringMode = "BlueNoise"
|
||||
mupen64plus-rsp-plugin = "hle"
|
||||
mupen64plus-ThreadedRenderer = "True"
|
||||
mupen64plus-txCacheCompression = "True"
|
||||
mupen64plus-txEnhancementMode = "None"
|
||||
mupen64plus-txFilterIgnoreBG = "True"
|
||||
mupen64plus-txFilterMode = "None"
|
||||
mupen64plus-txHiresEnable = "False"
|
||||
mupen64plus-txHiresFullAlphaChannel = "False"
|
||||
mupen64plus-u-cbutton = "C4"
|
||||
mupen64plus-virefresh = "Auto"
|
||||
pcsx_rearmed_analog_axis_modifier = "circle"
|
||||
pcsx_rearmed_async_cd = "sync"
|
||||
pcsx_rearmed_bios = "auto"
|
||||
pcsx_rearmed_display_internal_fps = "disabled"
|
||||
pcsx_rearmed_dithering = "enabled"
|
||||
pcsx_rearmed_drc = "enabled"
|
||||
pcsx_rearmed_duping_enable = "enabled"
|
||||
pcsx_rearmed_frameskip_type = "disabled"
|
||||
pcsx_rearmed_gteregsunneeded = "disabled"
|
||||
pcsx_rearmed_gunconadjustratiox = "1"
|
||||
pcsx_rearmed_gunconadjustratioy = "1"
|
||||
pcsx_rearmed_gunconadjustx = "0"
|
||||
pcsx_rearmed_gunconadjusty = "0"
|
||||
pcsx_rearmed_idiablofix = "disabled"
|
||||
pcsx_rearmed_input_sensitivity = "1.00"
|
||||
pcsx_rearmed_inuyasha_fix = "disabled"
|
||||
pcsx_rearmed_memcard2 = "disabled"
|
||||
pcsx_rearmed_multitap1 = "auto"
|
||||
pcsx_rearmed_multitap2 = "auto"
|
||||
pcsx_rearmed_negcon_deadzone = "0"
|
||||
pcsx_rearmed_negcon_response = "linear"
|
||||
pcsx_rearmed_neon_enhancement_enable = "disabled"
|
||||
pcsx_rearmed_neon_enhancement_no_main = "disabled"
|
||||
pcsx_rearmed_neon_interlace_enable = "disabled"
|
||||
pcsx_rearmed_nocdaudio = "enabled"
|
||||
pcsx_rearmed_nogteflags = "disabled"
|
||||
pcsx_rearmed_nosmccheck = "disabled"
|
||||
pcsx_rearmed_noxadecoding = "enabled"
|
||||
pcsx_rearmed_pad1type = "standard"
|
||||
pcsx_rearmed_pad2type = "standard"
|
||||
pcsx_rearmed_pad3type = "none"
|
||||
pcsx_rearmed_pad4type = "none"
|
||||
pcsx_rearmed_pad5type = "none"
|
||||
pcsx_rearmed_pad6type = "none"
|
||||
pcsx_rearmed_pad7type = "none"
|
||||
pcsx_rearmed_pad8type = "none"
|
||||
pcsx_rearmed_pe2_fix = "disabled"
|
||||
pcsx_rearmed_psxclock = "57"
|
||||
pcsx_rearmed_region = "auto"
|
||||
pcsx_rearmed_show_bios_bootlogo = "disabled"
|
||||
pcsx_rearmed_show_other_input_settings = "disabled"
|
||||
pcsx_rearmed_spu_interpolation = "simple"
|
||||
pcsx_rearmed_spu_reverb = "enabled"
|
||||
pcsx_rearmed_spuirq = "disabled"
|
||||
pcsx_rearmed_vibration = "enabled"
|
||||
gambatte_gb_colorization = "disabled"
|
||||
gambatte_gb_internal_palette = ""
|
||||
mame2003-plus_analog = "digital"
|
||||
mame2003-plus_art_resolution = "1"
|
||||
mame2003-plus_brightness = "1.0"
|
||||
mame2003-plus_cheat_input_ports = "disabled"
|
||||
mame2003-plus_core_save_subfolder = "enabled"
|
||||
mame2003-plus_core_sys_subfolder = "enabled"
|
||||
mame2003-plus_dcs_speedhack = "enabled"
|
||||
mame2003-plus_deadzone = "20"
|
||||
mame2003-plus_digital_joy_centering = "enabled"
|
||||
mame2003-plus_display_artwork = "enabled"
|
||||
mame2003-plus_display_setup = "disabled"
|
||||
mame2003-plus_four_way_emulation = "disabled"
|
||||
mame2003-plus_frameskip = "0"
|
||||
mame2003-plus_gamma = "1.0"
|
||||
mame2003-plus_input_interface = "retropad"
|
||||
mame2003-plus_machine_timing = "enabled"
|
||||
mame2003-plus_mame_remapping = "enabled"
|
||||
mame2003-plus_mouse_device = "mouse"
|
||||
mame2003-plus_sample_rate = "48000"
|
||||
mame2003-plus_skip_disclaimer = "disabled"
|
||||
mame2003-plus_skip_warnings = "disabled"
|
||||
flycast_internal_resolution = "640x480"
|
||||
flycast_alpha_sorting = "per-strip (fast, least accurate)"
|
||||
flycast_enable_dsp = "disabled"
|
||||
flycast_threaded_rendering = "enabled"
|
||||
flycast_anisotropic_filtering = "off"
|
||||
flycast_synchronous_rendering = "enabled"
|
||||
flycast_enable_rtt = "disabled"
|
||||
flycast_enable_rttb = "disabled"
|
||||
flycast_delay_frame_swapping = "disabled"
|
||||
flycast_div_matching = "auto"
|
||||
flycast_texupscale = "off"
|
||||
flycast_auto_skip_frame = "normal"
|
||||
opera_swi_hle = "enabled"
|
||||
opera_dsp_threaded = "enabled"
|
||||
opera_madam_matrix_engine = "software"
|
||||
puae_deadzone = "25"
|
||||
melonds_screen_layout = "Left/Right"
|
||||
melonds_swapscreen_mode = "Toggle"
|
||||
melonds_threaded_renderer = "enabled"
|
||||
melonds_touch_mode = "Joystick"
|
||||
virtualjaguar_bios = "enabled"
|
||||
virtualjaguar_usefastblitter = "enabled"
|
||||
+17
-8
@@ -1,5 +1,5 @@
|
||||
# Arch R - RetroArch Configuration for R36S
|
||||
# Optimized for 640x480 display
|
||||
# Optimized for 640x480 display, tuned from ROCKNIX RK3326 defaults
|
||||
|
||||
# Video
|
||||
video_driver = "gl"
|
||||
@@ -7,22 +7,22 @@ video_context_driver = ""
|
||||
video_fullscreen = "true"
|
||||
video_windowed_fullscreen = "false"
|
||||
video_vsync = "true"
|
||||
video_max_swapchain_images = "2"
|
||||
video_max_swapchain_images = "3"
|
||||
video_smooth = "false"
|
||||
video_scale_integer = "true"
|
||||
video_scale_integer = "false"
|
||||
video_rotation = "0"
|
||||
video_aspect_ratio_auto = "true"
|
||||
video_fullscreen_x = "640"
|
||||
video_fullscreen_y = "480"
|
||||
|
||||
# Audio — matches dArkOS RG351MP (RK3326) settings
|
||||
# Audio — tuned for RK3326 rk817 codec (48kHz native)
|
||||
# alsathread: non-blocking audio, better for ARM
|
||||
# audio_device empty: uses ALSA default (plug → hw:0,0 from asound.conf)
|
||||
# 48kHz avoids double resampling (RA→44.1k→ALSA→48k)
|
||||
# audio_volume +6dB: software boost to compensate rk817 codec low output level
|
||||
audio_driver = "alsathread"
|
||||
audio_device = ""
|
||||
audio_out_rate = "44100"
|
||||
audio_latency = "128"
|
||||
audio_out_rate = "48000"
|
||||
audio_latency = "64"
|
||||
audio_sync = "true"
|
||||
audio_enable = "true"
|
||||
audio_volume = "6.000000"
|
||||
@@ -31,6 +31,7 @@ audio_mixer_mute_enable = "false"
|
||||
audio_rate_control = "true"
|
||||
audio_rate_control_delta = "0.005000"
|
||||
audio_resampler = "sinc"
|
||||
audio_resampler_quality = "2"
|
||||
audio_max_timing_skew = "0.050000"
|
||||
|
||||
# Microphone — DISABLED (binary built with --disable-microphone, belt-and-suspenders)
|
||||
@@ -41,9 +42,10 @@ input_driver = "udev"
|
||||
input_joypad_driver = "udev"
|
||||
input_autodetect_enable = "true"
|
||||
input_max_users = "1"
|
||||
input_poll_type_behavior = "2"
|
||||
joypad_autoconfig_dir = "/usr/share/retroarch/autoconfig"
|
||||
|
||||
# Menu (rgui — lightweight, better for 640x480 like dArkOS)
|
||||
# Menu (rgui — lightweight, better for 640x480)
|
||||
menu_driver = "rgui"
|
||||
menu_swap_ok_cancel_buttons = "false"
|
||||
|
||||
@@ -55,10 +57,17 @@ libretro_directory = "/usr/lib/libretro"
|
||||
libretro_info_path = "/usr/share/libretro/info"
|
||||
assets_directory = "/usr/share/retroarch/assets"
|
||||
system_directory = "/roms/bios"
|
||||
core_options_path = "/home/archr/.config/retroarch/retroarch-core-options.cfg"
|
||||
|
||||
# Performance
|
||||
video_threaded = "true"
|
||||
video_frame_delay = "0"
|
||||
game_specific_options = "true"
|
||||
auto_overrides_enable = "true"
|
||||
auto_remaps_enable = "true"
|
||||
|
||||
# Save protection (autosave SRAM every 10s, prevents loss on power-off)
|
||||
autosave_interval = "10"
|
||||
|
||||
# Power Saving
|
||||
suspend_screensaver_enable = "false"
|
||||
|
||||
Executable
+139
@@ -0,0 +1,139 @@
|
||||
#!/bin/bash
|
||||
#==============================================================================
|
||||
# Arch R - Flash Mainline U-Boot to Clone SD Card
|
||||
#==============================================================================
|
||||
# Flashes mainline U-Boot binaries to an existing Arch R SD card for clones.
|
||||
# Does NOT touch partitions or rootfs — only U-Boot area.
|
||||
#
|
||||
# Also creates a minimal boot.scr for mainline U-Boot (distro boot).
|
||||
#
|
||||
# Usage:
|
||||
# ./flash-uboot-clone.sh /dev/sdX
|
||||
#==============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() { echo -e "${GREEN}[FLASH-CLONE]${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW}[FLASH-CLONE] WARNING:${NC} $1"; }
|
||||
error() { echo -e "${RED}[FLASH-CLONE] ERROR:${NC} $1"; exit 1; }
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Parse arguments
|
||||
#------------------------------------------------------------------------------
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 /dev/sdX"
|
||||
echo ""
|
||||
echo "Available devices:"
|
||||
lsblk -d -o NAME,SIZE,MODEL,TRAN | grep -E "sd|mmcblk" || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DEVICE="$1"
|
||||
|
||||
if [ ! -b "$DEVICE" ]; then
|
||||
error "Device not found: $DEVICE"
|
||||
fi
|
||||
|
||||
# Safety check
|
||||
if mount | grep -q "^${DEVICE}"; then
|
||||
warn "Device $DEVICE has mounted partitions:"
|
||||
mount | grep "^${DEVICE}" || true
|
||||
echo ""
|
||||
read -p "Continue anyway? (y/N) " -n 1 -r
|
||||
echo
|
||||
[[ $REPLY =~ ^[Yy]$ ]] || exit 1
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Verify binaries
|
||||
#------------------------------------------------------------------------------
|
||||
BUILD_DIR="$SCRIPT_DIR/bootloader/u-boot-clone-build"
|
||||
|
||||
for f in "$BUILD_DIR/idbloader.img" "$BUILD_DIR/uboot.img" "$BUILD_DIR/trust.img"; do
|
||||
[ -f "$f" ] || error "Missing: $f (run build-uboot-clone.sh first)"
|
||||
done
|
||||
|
||||
log "Device: $DEVICE"
|
||||
log "Binaries: $BUILD_DIR"
|
||||
log ""
|
||||
log "Will flash:"
|
||||
log " idbloader.img → sector 64 ($(du -h "$BUILD_DIR/idbloader.img" | cut -f1))"
|
||||
log " uboot.img → sector 16384 ($(du -h "$BUILD_DIR/uboot.img" | cut -f1))"
|
||||
log " trust.img → sector 24576 ($(du -h "$BUILD_DIR/trust.img" | cut -f1))"
|
||||
log ""
|
||||
|
||||
read -p "Flash to $DEVICE? (y/N) " -n 1 -r
|
||||
echo
|
||||
[[ $REPLY =~ ^[Yy]$ ]] || exit 1
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Flash U-Boot binaries (raw sectors)
|
||||
#------------------------------------------------------------------------------
|
||||
log "Flashing idbloader.img..."
|
||||
pkexec dd if="$BUILD_DIR/idbloader.img" of="$DEVICE" bs=512 seek=64 conv=sync,noerror,notrunc 2>/dev/null
|
||||
|
||||
log "Flashing uboot.img..."
|
||||
pkexec dd if="$BUILD_DIR/uboot.img" of="$DEVICE" bs=512 seek=16384 conv=sync,noerror,notrunc 2>/dev/null
|
||||
|
||||
log "Flashing trust.img..."
|
||||
pkexec dd if="$BUILD_DIR/trust.img" of="$DEVICE" bs=512 seek=24576 conv=sync,noerror,notrunc 2>/dev/null
|
||||
|
||||
log "U-Boot binaries flashed"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Create boot.scr on BOOT partition
|
||||
#------------------------------------------------------------------------------
|
||||
BOOT_PART="${DEVICE}1"
|
||||
if [ ! -b "$BOOT_PART" ]; then
|
||||
BOOT_PART="${DEVICE}p1"
|
||||
fi
|
||||
|
||||
if [ ! -b "$BOOT_PART" ]; then
|
||||
warn "BOOT partition not found — boot.scr NOT created"
|
||||
else
|
||||
MOUNT_TMP=$(mktemp -d)
|
||||
pkexec mount "$BOOT_PART" "$MOUNT_TMP"
|
||||
|
||||
# Create boot.scr from boot.ini (strip BSP-specific commands)
|
||||
MKIMAGE="$SCRIPT_DIR/bootloader/u-boot-mainline/tools/mkimage"
|
||||
if [ -x "$MKIMAGE" ] && [ -f "$MOUNT_TMP/boot.ini" ]; then
|
||||
log "Creating boot.scr from boot.ini..."
|
||||
TMP_SCR=$(mktemp)
|
||||
# Strip 'odroidgoa-uboot-config' (BSP command, not in mainline)
|
||||
grep -v '^odroidgoa-uboot-config' "$MOUNT_TMP/boot.ini" > "$TMP_SCR"
|
||||
"$MKIMAGE" -T script -d "$TMP_SCR" "$MOUNT_TMP/boot.scr" 2>/dev/null && \
|
||||
log "boot.scr created" || \
|
||||
warn "boot.scr creation failed"
|
||||
rm -f "$TMP_SCR"
|
||||
fi
|
||||
|
||||
log "BOOT partition contents:"
|
||||
ls "$MOUNT_TMP/" | head -20
|
||||
|
||||
pkexec umount "$MOUNT_TMP"
|
||||
rmdir "$MOUNT_TMP"
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Done
|
||||
#------------------------------------------------------------------------------
|
||||
sync
|
||||
log ""
|
||||
log "=== Mainline U-Boot flashed to $DEVICE ==="
|
||||
log ""
|
||||
log "This is MAINLINE U-Boot (not BSP). Key differences:"
|
||||
log " - Uses go2.c board detection (not hwrev.c)"
|
||||
log " - Boots via boot.scr / extlinux.conf (not boot.ini directly)"
|
||||
log " - Display: mainline DRM (may not show boot logo)"
|
||||
log ""
|
||||
log "If boot fails, restore working clone U-Boot:"
|
||||
log " pkexec dd if=bootloader/u-boot-clone-working/uboot.img of=$DEVICE bs=512 seek=16384 conv=notrunc"
|
||||
log " pkexec dd if=bootloader/u-boot-clone-working/idbloader.img of=$DEVICE bs=512 seek=64 conv=notrunc"
|
||||
log " pkexec dd if=bootloader/u-boot-clone-working/trust.img of=$DEVICE bs=512 seek=24576 conv=notrunc"
|
||||
Executable
+136
@@ -0,0 +1,136 @@
|
||||
#!/bin/bash
|
||||
|
||||
#==============================================================================
|
||||
# Arch R - Flash Custom U-Boot to SD Card
|
||||
#==============================================================================
|
||||
# Flashes custom U-Boot binaries + display DTBs to an existing Arch R SD card.
|
||||
# Does NOT touch partitions or rootfs — only U-Boot area + BOOT partition DTBs.
|
||||
#
|
||||
# Usage:
|
||||
# ./flash-uboot.sh /dev/sdX
|
||||
#==============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() { echo -e "${GREEN}[FLASH]${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW}[FLASH] WARNING:${NC} $1"; }
|
||||
error() { echo -e "${RED}[FLASH] ERROR:${NC} $1"; exit 1; }
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Parse arguments
|
||||
#------------------------------------------------------------------------------
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 /dev/sdX"
|
||||
echo ""
|
||||
echo "Available devices:"
|
||||
lsblk -d -o NAME,SIZE,MODEL,TRAN | grep -E "sd|mmcblk" || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DEVICE="$1"
|
||||
|
||||
if [ ! -b "$DEVICE" ]; then
|
||||
error "Device not found: $DEVICE"
|
||||
fi
|
||||
|
||||
# Safety: refuse whole-disk devices that look like system disks
|
||||
if mount | grep -q "^${DEVICE}"; then
|
||||
warn "Device $DEVICE has mounted partitions:"
|
||||
mount | grep "^${DEVICE}" || true
|
||||
echo ""
|
||||
read -p "Continue anyway? (y/N) " -n 1 -r
|
||||
echo
|
||||
[[ $REPLY =~ ^[Yy]$ ]] || exit 1
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Verify binaries
|
||||
#------------------------------------------------------------------------------
|
||||
SDFUSE="$SCRIPT_DIR/bootloader/u-boot-rk3326/sd_fuse"
|
||||
DTS_DIR="$SCRIPT_DIR/bootloader/u-boot-rk3326/arch/arm/dts"
|
||||
|
||||
for f in "$SDFUSE/idbloader.img" "$SDFUSE/uboot.img" "$SDFUSE/trust.img"; do
|
||||
[ -f "$f" ] || error "Missing: $f"
|
||||
done
|
||||
|
||||
for f in "$DTS_DIR/r36s-uboot.dtb" "$DTS_DIR/r36-uboot.dtb"; do
|
||||
[ -f "$f" ] || error "Missing: $f"
|
||||
done
|
||||
|
||||
log "Device: $DEVICE"
|
||||
log "Binaries: $SDFUSE"
|
||||
log ""
|
||||
log "Will flash:"
|
||||
log " idbloader.img → sector 64 ($(du -h "$SDFUSE/idbloader.img" | cut -f1))"
|
||||
log " uboot.img → sector 16384 ($(du -h "$SDFUSE/uboot.img" | cut -f1))"
|
||||
log " trust.img → sector 24576 ($(du -h "$SDFUSE/trust.img" | cut -f1))"
|
||||
log " r36s-uboot.dtb + r36-uboot.dtb → BOOT partition"
|
||||
log ""
|
||||
|
||||
read -p "Flash to $DEVICE? (y/N) " -n 1 -r
|
||||
echo
|
||||
[[ $REPLY =~ ^[Yy]$ ]] || exit 1
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Flash U-Boot binaries (raw sectors)
|
||||
#------------------------------------------------------------------------------
|
||||
log "Flashing idbloader.img..."
|
||||
pkexec dd if="$SDFUSE/idbloader.img" of="$DEVICE" bs=512 seek=64 conv=sync,noerror,notrunc 2>/dev/null
|
||||
|
||||
log "Flashing uboot.img..."
|
||||
pkexec dd if="$SDFUSE/uboot.img" of="$DEVICE" bs=512 seek=16384 conv=sync,noerror,notrunc 2>/dev/null
|
||||
|
||||
log "Flashing trust.img..."
|
||||
pkexec dd if="$SDFUSE/trust.img" of="$DEVICE" bs=512 seek=24576 conv=sync,noerror,notrunc 2>/dev/null
|
||||
|
||||
log "U-Boot binaries flashed"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Copy display DTBs to BOOT partition
|
||||
#------------------------------------------------------------------------------
|
||||
BOOT_PART="${DEVICE}1"
|
||||
if [ ! -b "$BOOT_PART" ]; then
|
||||
# Try mmcblk style (p1)
|
||||
BOOT_PART="${DEVICE}p1"
|
||||
fi
|
||||
|
||||
if [ ! -b "$BOOT_PART" ]; then
|
||||
warn "BOOT partition not found ($BOOT_PART) — display DTBs NOT copied"
|
||||
warn "Copy manually: r36s-uboot.dtb + r36-uboot.dtb to BOOT partition"
|
||||
else
|
||||
MOUNT_TMP=$(mktemp -d)
|
||||
pkexec mount "$BOOT_PART" "$MOUNT_TMP"
|
||||
|
||||
pkexec cp "$DTS_DIR/r36s-uboot.dtb" "$MOUNT_TMP/"
|
||||
pkexec cp "$DTS_DIR/r36-uboot.dtb" "$MOUNT_TMP/"
|
||||
|
||||
# Verify
|
||||
log "BOOT partition contents:"
|
||||
ls -la "$MOUNT_TMP/"*.dtb 2>/dev/null || true
|
||||
|
||||
pkexec umount "$MOUNT_TMP"
|
||||
rmdir "$MOUNT_TMP"
|
||||
|
||||
log "Display DTBs copied to BOOT partition"
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Done
|
||||
#------------------------------------------------------------------------------
|
||||
sync
|
||||
log ""
|
||||
log "=== Custom U-Boot flashed to $DEVICE ==="
|
||||
log ""
|
||||
log "Test on R36S original → should detect eMMC → r36s-uboot.dtb → logo"
|
||||
log "Test on R36S clone → no eMMC → r36-uboot.dtb → logo"
|
||||
log ""
|
||||
log "If boot fails (red LED blink), restore working U-Boot:"
|
||||
log " Original: bootloader/u-boot-r36s-working/"
|
||||
log " Clone: bootloader/u-boot-clone-working/"
|
||||
File diff suppressed because it is too large
Load Diff
+26
-12
@@ -25,9 +25,12 @@ except ImportError:
|
||||
sys.exit(1)
|
||||
|
||||
# Volume step (percentage per key press)
|
||||
VOL_STEP = 2
|
||||
VOL_STEP = 5
|
||||
# Brightness step (percentage per key press)
|
||||
BRIGHT_STEP = 3
|
||||
BRIGHT_STEP = 5
|
||||
# Minimum interval between volume/brightness actions (seconds)
|
||||
# adc-keys autorepeat fires at ~30Hz — throttle to ~3 events/sec
|
||||
VOL_THROTTLE = 0.3
|
||||
# Minimum brightness percentage (prevent black screen)
|
||||
BRIGHT_MIN = 5
|
||||
# Brightness persistence file
|
||||
@@ -177,6 +180,7 @@ def brightness_up():
|
||||
def brightness_down():
|
||||
if get_brightness_pct() <= BRIGHT_MIN:
|
||||
return
|
||||
log(f"BRIGHT- brightnessctl s {BRIGHT_STEP}%-")
|
||||
run_cmd(f"brightnessctl -q s {BRIGHT_STEP}%-")
|
||||
# Clamp: if we went below minimum, set to minimum
|
||||
if get_brightness_pct() < BRIGHT_MIN:
|
||||
@@ -203,7 +207,7 @@ def find_devices():
|
||||
name = dev.name.lower()
|
||||
caps = dev.capabilities()
|
||||
|
||||
if 'gpio-keys' in name:
|
||||
if 'gpio-keys' in name or 'adc-keys' in name:
|
||||
# Distinguish vol device from gamepad by checking for KEY_VOLUMEUP
|
||||
key_caps = caps.get(ecodes.EV_KEY, [])
|
||||
if ecodes.KEY_VOLUMEUP in key_caps:
|
||||
@@ -253,6 +257,8 @@ def main():
|
||||
|
||||
# Track MODE button state for brightness hotkey combo
|
||||
mode_held = False
|
||||
# Throttle: last time a volume/brightness action was executed
|
||||
last_vol_action = 0.0
|
||||
|
||||
print("Hotkey daemon ready.")
|
||||
# Clear previous log on fresh start
|
||||
@@ -298,18 +304,26 @@ def main():
|
||||
elif val == 0:
|
||||
mode_held = False
|
||||
|
||||
# Volume keys from gpio-keys-vol (grabbed)
|
||||
# Volume keys (grabbed): accept press + repeat,
|
||||
# but throttle to max ~3 events/sec (300ms interval).
|
||||
# adc-keys autorepeat fires at ~30Hz natively.
|
||||
elif key == ecodes.KEY_VOLUMEUP and val in (1, 2):
|
||||
if mode_held:
|
||||
brightness_up()
|
||||
else:
|
||||
volume_up()
|
||||
now = time.monotonic()
|
||||
if now - last_vol_action >= VOL_THROTTLE:
|
||||
last_vol_action = now
|
||||
if mode_held:
|
||||
brightness_up()
|
||||
else:
|
||||
volume_up()
|
||||
|
||||
elif key == ecodes.KEY_VOLUMEDOWN and val in (1, 2):
|
||||
if mode_held:
|
||||
brightness_down()
|
||||
else:
|
||||
volume_down()
|
||||
now = time.monotonic()
|
||||
if now - last_vol_action >= VOL_THROTTLE:
|
||||
last_vol_action = now
|
||||
if mode_held:
|
||||
brightness_down()
|
||||
else:
|
||||
volume_down()
|
||||
|
||||
# Headphone jack switch
|
||||
elif event.type == ecodes.EV_SW:
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* archr-init — initramfs /init for Arch R
|
||||
*
|
||||
* Shows splash on /dev/fb0 IMMEDIATELY after kernel boot (before systemd).
|
||||
* Splash image is EMBEDDED in the binary (no file I/O needed).
|
||||
* Then mounts the real root filesystem and switch_root to /sbin/init.
|
||||
*
|
||||
* Initramfs contents:
|
||||
* /init → this binary (static aarch64, includes splash data)
|
||||
* /dev/ → empty (devtmpfs mounted here)
|
||||
* /proc/ → empty (proc mounted temporarily)
|
||||
* /newroot/ → empty (real root mounted here)
|
||||
*
|
||||
* Build:
|
||||
* xxd -i splash.bmp > splash_data.h
|
||||
* aarch64-linux-gnu-gcc -static -O2 -o archr-init archr-init.c
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/fb.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
/* Embedded splash image (generated by xxd -i splash.bmp) */
|
||||
#include "splash_data.h"
|
||||
|
||||
/* ---- Logging (dmesg + in-memory buffer, flushed to file after root mount) ---- */
|
||||
|
||||
static int kmsg_fd = -1;
|
||||
#define LOG_BUF_SIZE 4096
|
||||
static char log_buf[LOG_BUF_SIZE];
|
||||
static int log_pos = 0;
|
||||
|
||||
/* Simple snprintf — avoid pulling in full stdio */
|
||||
static int fmt_int(char *buf, int val)
|
||||
{
|
||||
if (val < 0) { *buf++ = '-'; val = -val; return 1 + fmt_int(buf, val); }
|
||||
if (val >= 10) { int n = fmt_int(buf, val / 10); return n + fmt_int(buf + n, val % 10); }
|
||||
*buf = '0' + val;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void klog(const char *msg)
|
||||
{
|
||||
/* Save msg pointer before we iterate */
|
||||
const char *saved_msg = msg;
|
||||
|
||||
/* Write to dmesg */
|
||||
if (kmsg_fd < 0)
|
||||
kmsg_fd = open("/dev/kmsg", O_WRONLY);
|
||||
if (kmsg_fd >= 0) {
|
||||
char buf[256];
|
||||
int i = 0;
|
||||
const char *prefix = "archr-init: ";
|
||||
while (*prefix) buf[i++] = *prefix++;
|
||||
while (*msg && i < 250) buf[i++] = *msg++;
|
||||
buf[i++] = '\n';
|
||||
write(kmsg_fd, buf, i);
|
||||
}
|
||||
|
||||
/* Buffer for file log (using saved pointer) */
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
if (log_pos < LOG_BUF_SIZE - 200) {
|
||||
log_pos += fmt_int(log_buf + log_pos, (int)ts.tv_sec);
|
||||
log_buf[log_pos++] = '.';
|
||||
int ms = (int)(ts.tv_nsec / 1000000);
|
||||
if (ms < 100) log_buf[log_pos++] = '0';
|
||||
if (ms < 10) log_buf[log_pos++] = '0';
|
||||
log_pos += fmt_int(log_buf + log_pos, ms);
|
||||
log_buf[log_pos++] = ' ';
|
||||
while (*saved_msg && log_pos < LOG_BUF_SIZE - 2)
|
||||
log_buf[log_pos++] = *saved_msg++;
|
||||
log_buf[log_pos++] = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
static void klog_num(const char *prefix, int val)
|
||||
{
|
||||
char buf[128];
|
||||
int i = 0;
|
||||
while (*prefix && i < 100) buf[i++] = *prefix++;
|
||||
i += fmt_int(buf + i, val);
|
||||
buf[i] = 0;
|
||||
klog(buf);
|
||||
}
|
||||
|
||||
static void flush_log(const char *path)
|
||||
{
|
||||
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd >= 0) {
|
||||
write(fd, log_buf, log_pos);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- BMP parsing (from embedded data) ---- */
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
uint16_t type;
|
||||
uint32_t size;
|
||||
uint16_t reserved1;
|
||||
uint16_t reserved2;
|
||||
uint32_t offset;
|
||||
} BMPFileHeader;
|
||||
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
uint16_t planes;
|
||||
uint16_t bpp;
|
||||
uint32_t compression;
|
||||
uint32_t image_size;
|
||||
int32_t x_ppm;
|
||||
int32_t y_ppm;
|
||||
uint32_t colors_used;
|
||||
uint32_t colors_important;
|
||||
} BMPInfoHeader;
|
||||
#pragma pack(pop)
|
||||
|
||||
/* ---- Splash display (writes embedded BMP to /dev/fb0) ---- */
|
||||
|
||||
static void show_splash(void)
|
||||
{
|
||||
/* Validate embedded BMP data */
|
||||
/* splash_data.h defines: unsigned char splash_bmp[] and unsigned int splash_bmp_len */
|
||||
extern unsigned char splash_bmp[];
|
||||
extern unsigned int splash_bmp_len;
|
||||
|
||||
if (splash_bmp_len < sizeof(BMPFileHeader) + sizeof(BMPInfoHeader)) {
|
||||
klog("splash: embedded data too small");
|
||||
return;
|
||||
}
|
||||
|
||||
BMPFileHeader *fh = (BMPFileHeader *)splash_bmp;
|
||||
BMPInfoHeader *ih = (BMPInfoHeader *)(splash_bmp + sizeof(BMPFileHeader));
|
||||
|
||||
if (fh->type != 0x4D42 || (ih->bpp != 24 && ih->bpp != 32)) {
|
||||
klog("splash: invalid BMP header");
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t bmp_w = ih->width;
|
||||
int32_t bmp_h = ih->height > 0 ? ih->height : -ih->height;
|
||||
int bottom_up = ih->height > 0;
|
||||
uint32_t src_bpp = ih->bpp / 8;
|
||||
uint32_t src_row_padded = (bmp_w * src_bpp + 3) & ~3;
|
||||
uint8_t *pixel_data = splash_bmp + fh->offset;
|
||||
|
||||
klog("splash: BMP parsed from embedded data");
|
||||
|
||||
/* Wait for fb0 (DRM probe might still be finishing) */
|
||||
int fb_fd = -1;
|
||||
int retries;
|
||||
for (retries = 0; retries < 30; retries++) {
|
||||
fb_fd = open("/dev/fb0", O_RDWR);
|
||||
if (fb_fd >= 0) break;
|
||||
usleep(100000); /* 100ms, max 3s */
|
||||
}
|
||||
if (fb_fd < 0) {
|
||||
klog("splash: fb0 NOT FOUND after 3s");
|
||||
return;
|
||||
}
|
||||
klog_num("splash: fb0 opened, retries=", retries);
|
||||
|
||||
struct fb_var_screeninfo vinfo;
|
||||
struct fb_fix_screeninfo finfo;
|
||||
|
||||
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ||
|
||||
ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
|
||||
klog("splash: ioctl failed");
|
||||
close(fb_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t fb_w = vinfo.xres;
|
||||
uint32_t fb_h = vinfo.yres;
|
||||
uint32_t fb_bpp_bytes = vinfo.bits_per_pixel / 8;
|
||||
uint32_t stride = finfo.line_length;
|
||||
uint32_t fb_size = stride * fb_h;
|
||||
|
||||
klog_num("splash: fb width=", (int)fb_w);
|
||||
klog_num("splash: fb height=", (int)fb_h);
|
||||
klog_num("splash: fb bpp=", (int)vinfo.bits_per_pixel);
|
||||
|
||||
/* Write directly to fb0 — row by row to avoid large malloc */
|
||||
/* First: clear the framebuffer (black) */
|
||||
{
|
||||
uint8_t zero[2560]; /* enough for 640px * 4bpp */
|
||||
memset(zero, 0, sizeof(zero));
|
||||
lseek(fb_fd, 0, SEEK_SET);
|
||||
for (uint32_t y = 0; y < fb_h; y++)
|
||||
write(fb_fd, zero, stride < sizeof(zero) ? stride : sizeof(zero));
|
||||
}
|
||||
|
||||
/* Then: write BMP pixels */
|
||||
uint32_t copy_w = (uint32_t)bmp_w < fb_w ? (uint32_t)bmp_w : fb_w;
|
||||
uint32_t copy_h = (uint32_t)bmp_h < fb_h ? (uint32_t)bmp_h : fb_h;
|
||||
|
||||
uint8_t row_buf[2560]; /* enough for 640px * 4bpp */
|
||||
|
||||
for (uint32_t y = 0; y < copy_h; y++) {
|
||||
uint32_t src_y = bottom_up ? (bmp_h - 1 - y) : y;
|
||||
uint8_t *src_row = pixel_data + src_y * src_row_padded;
|
||||
|
||||
memset(row_buf, 0, stride < sizeof(row_buf) ? stride : sizeof(row_buf));
|
||||
|
||||
for (uint32_t x = 0; x < copy_w; x++) {
|
||||
uint8_t b = src_row[x * src_bpp + 0];
|
||||
uint8_t g = src_row[x * src_bpp + 1];
|
||||
uint8_t r = src_row[x * src_bpp + 2];
|
||||
|
||||
if (fb_bpp_bytes == 4) {
|
||||
row_buf[x * 4 + 0] = b;
|
||||
row_buf[x * 4 + 1] = g;
|
||||
row_buf[x * 4 + 2] = r;
|
||||
row_buf[x * 4 + 3] = 0xFF;
|
||||
} else if (fb_bpp_bytes == 2) {
|
||||
uint16_t c = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
|
||||
row_buf[x * 2 + 0] = c & 0xFF;
|
||||
row_buf[x * 2 + 1] = (c >> 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
lseek(fb_fd, y * stride, SEEK_SET);
|
||||
write(fb_fd, row_buf, stride < sizeof(row_buf) ? stride : sizeof(row_buf));
|
||||
}
|
||||
|
||||
klog("splash: written to fb0");
|
||||
close(fb_fd);
|
||||
}
|
||||
|
||||
/* ---- Main: initramfs /init ---- */
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* 1. Mount devtmpfs on /dev (kernel creates device nodes here) */
|
||||
mkdir("/dev", 0755);
|
||||
mount("devtmpfs", "/dev", "devtmpfs", 0, NULL);
|
||||
|
||||
klog("=== INITRAMFS STARTED ===");
|
||||
|
||||
/* 2. Show splash from embedded data — no file I/O needed */
|
||||
show_splash();
|
||||
|
||||
/* 3. Parse root= and rw from kernel cmdline */
|
||||
mkdir("/proc", 0755);
|
||||
mount("proc", "/proc", "proc", 0, NULL);
|
||||
|
||||
char cmdline[4096];
|
||||
memset(cmdline, 0, sizeof(cmdline));
|
||||
int fd = open("/proc/cmdline", O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
read(fd, cmdline, sizeof(cmdline) - 1);
|
||||
close(fd);
|
||||
}
|
||||
umount("/proc");
|
||||
|
||||
/* Extract root= device path */
|
||||
char rootdev[256] = "/dev/mmcblk1p2"; /* default: original R36S */
|
||||
char *p = strstr(cmdline, "root=");
|
||||
if (p) {
|
||||
p += 5;
|
||||
int i = 0;
|
||||
while (*p && *p != ' ' && i < 255)
|
||||
rootdev[i++] = *p++;
|
||||
rootdev[i] = 0;
|
||||
}
|
||||
|
||||
/* Check rw flag */
|
||||
unsigned long mflags = MS_NOATIME;
|
||||
if (strstr(cmdline, " rw"))
|
||||
mflags |= 0; /* rw is default without MS_RDONLY */
|
||||
else
|
||||
mflags |= MS_RDONLY;
|
||||
|
||||
klog(rootdev);
|
||||
|
||||
/* 4. Mount real root (retry — MMC might still be probing) */
|
||||
mkdir("/newroot", 0755);
|
||||
int mounted = 0;
|
||||
int mount_retries;
|
||||
for (mount_retries = 0; mount_retries < 50; mount_retries++) {
|
||||
if (mount(rootdev, "/newroot", "ext4", mflags, NULL) == 0) {
|
||||
mounted = 1;
|
||||
break;
|
||||
}
|
||||
usleep(100000); /* 100ms, max 5s total */
|
||||
}
|
||||
|
||||
if (!mounted) {
|
||||
klog("FATAL: could not mount root!");
|
||||
for (;;) sleep(60);
|
||||
}
|
||||
|
||||
klog_num("root mounted, retries=", mount_retries);
|
||||
|
||||
/* 5. Write diagnostic log to root filesystem */
|
||||
klog("switch_root");
|
||||
flush_log("/newroot/var/log/archr-init.log");
|
||||
|
||||
/* 6. Move /dev to new root */
|
||||
mount("/dev", "/newroot/dev", NULL, MS_MOVE, NULL);
|
||||
|
||||
/* 7. switch_root: pivot to real rootfs and exec systemd */
|
||||
if (kmsg_fd >= 0) close(kmsg_fd);
|
||||
|
||||
chdir("/newroot");
|
||||
mount(".", "/", NULL, MS_MOVE, NULL);
|
||||
chroot(".");
|
||||
chdir("/");
|
||||
|
||||
execl("/sbin/init", "/sbin/init", NULL);
|
||||
|
||||
/* Should never reach here */
|
||||
return 1;
|
||||
}
|
||||
@@ -50,8 +50,8 @@ _bt "after_amixer"
|
||||
|
||||
# === BACKGROUND: Everything else runs parallel with ES SDL init (~2s window) ===
|
||||
(
|
||||
# Framebuffer blank (hides login text, ES takes over via KMSDRM anyway)
|
||||
dd if=/dev/zero of=/dev/fb0 bs=614400 count=1 2>/dev/null
|
||||
# NOTE: fb0 blank removed — archr-splash.service writes splash to fb0,
|
||||
# which persists until ES takes DRM master via KMSDRM.
|
||||
|
||||
# Permissions + governors (single sudo)
|
||||
sudo sh -c '/usr/local/bin/perfmax; chmod 666 /dev/tty1 /dev/dri/* /sys/class/backlight/backlight/brightness' 2>/dev/null
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user