Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions buildroot-external/Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ config BR2_RETROSTONE_VERSION
release tag (v0.2.0 -> 0.2.0; scripts/ci/build-board.sh).
Development builds get "-dev" appended.

config BR2_RETROSTONE_UPDATE_REPO
string "Update repository (GitHub owner/name)"
help
The GitHub repository whose releases Settings > System update
looks in (docs/updates.md). Empty: PaddleStroke/RetroStoneOS.
A fork that publishes its own update packages sets it, with
its own signing key (BR2_RETROSTONE_UPDATE_PUBKEY).

config BR2_RETROSTONE_UPDATE_PUBKEY
string "Update signing public key"
help
The signify public key the system updater trusts, installed as
/usr/share/rsos/update.pub. Empty: frontend/assets/update.pub
(the RetroStoneOS release key). For a fork's own key, e.g.
$(BR2_EXTERNAL_RETROSTONE_PATH)/../frontend/assets/update-fork.pub.

choice
prompt "Shell on the debug UART"
default BR2_RETROSTONE_UART_SHELL_OPEN
Expand Down
16 changes: 16 additions & 0 deletions buildroot-external/board/common/rootfs-overlay/etc/init.d/rcS
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,19 @@ read -r CMDLINE < /proc/cmdline
[ -r /usr/libexec/rsos/board.sh ] && . /usr/libexec/rsos/board.sh
# for data-partition (it then skips reading the board files again)
export RSOS_DISK RSOS_BOARD_DATA_PARTITION RSOS_BOARD_FIRSTBOOT_TRACE_KIB
# /dev/rsos-disk: the disk with U-Boot's environment, for /etc/fw_env.config:
# the one U-Boot started from (rsos.envdev=mmcblk<N> from boot.scr), else the
# system disk. They differ on a RetroStone2 Pro started by its starter card
# (the system on the eMMC, U-Boot and its environment on the microSD).
_rsos_env=$RSOS_DISK
case " $CMDLINE " in
*" rsos.envdev=mmcblk"[0-9]" "*)
_rsos_env=${CMDLINE##*rsos.envdev=}
_rsos_env=/dev/${_rsos_env%% *}
;;
esac
ln -sf "$_rsos_env" /dev/rsos-disk
unset _rsos_env
iost; IO_START=$IO

# --- Prefetch (boot round 3): the frontend and the libraries it maps (and
Expand Down Expand Up @@ -116,6 +129,9 @@ ts "governor"
# Only on a board with that PMIC (board.ini: boot_reason = axp209).
[ "$RSOS_BOARD_BOOT_REASON" = axp209 ] && [ -x /usr/bin/rsos-bootreason ] &&
/usr/bin/rsos-bootreason -w /run/rsos/bootreason
# The AXP209's data registers as they are now, before the boot logger clears
# them (the RetroStone2 Pro's eMMC boot breadcrumbs, rsos-storage's report)
[ -x /usr/libexec/rsos/axpstamp ] && /usr/libexec/rsos/axpstamp raw > /run/rsos/axp-data 2> /dev/null
ts "bootreason"

# --- User data partition (exFAT) on /data. Created on the first boot.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,34 @@ refund() {
case "$_f" in [1-9]) fw_setenv rsos_fails $((_f - 1)) ;; esac
fi
[ "$(get rsos_lowvolt)" != trial ] || fw_setenv rsos_lowvolt
# a faster memory trial: try it again at the next start (an orderly
# shutdown is no failure)
[ -x "$AXP" ] && "$AXP" dram-retry 2> /dev/null
echo refunded > "$RUN/boot-state"
}

# The RetroStone2's faster memory (Settings > Power > Memory speed): U-Boot's
# SPL runs every start at the chosen DRAM clock as a trial (AXP209 REG0D,
# /usr/libexec/rsos/axpstamp). Once the start is stable, a memory test; then
# the trial is confirmed, or marked failed and the console restarts at the
# normal speed (data must not be written with a memory that flips bits).
AXP=/usr/libexec/rsos/axpstamp
dram_trial() {
[ -x "$AXP" ] && [ -x /usr/libexec/rsos/memtest ] || return 0
set -- $("$AXP" dram-get 2> /dev/null)
[ "$1" = trial ] || return 0
if /usr/libexec/rsos/memtest 96 2 > "$RUN/memtest.txt" 2>&1; then
"$AXP" dram-ok
msg "memory at $3 MHz: test passed, confirmed"
return 0
fi
"$AXP" dram-fail
msg "memory at $3 MHz: test FAILED ($(cat "$RUN/memtest.txt")): back to the normal speed, restarting"
sync
reboot
exit 1
}

case "$1" in
now)
confirm
Expand Down Expand Up @@ -193,4 +218,5 @@ if [ -n "$fe" ] && ! kill -0 "$fe" 2> /dev/null; then
msg "the frontend restarted, not confirming (its new instance starts over)"
exit 1
fi
dram_trial
confirm
89 changes: 78 additions & 11 deletions buildroot-external/board/retrostone2/boot.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,15 @@
#
# Optional settings, also in the U-Boot environment (fw_setenv):
# rsos_overlays e.g. "emmc sata": /boot/overlays/<name>.dtbo to apply
# (Settings > Storage writes it through rsos-storage;
# "emmc" is implied when booted from the eMMC)
# "cpu-lowvolt" (a test that may freeze the board) is
# one-shot: applied with rsos_lowvolt=trial, which
# rsos-boot-ok clears when that boot is confirmed (or given
# back); a boot that finds "trial" still set skips it and
# sets rsos_lowvolt=failed (skipped until
# "fw_setenv rsos_lowvolt")
# rsos_model pro|regular, probed at the first start (see below)
# rsos_extraargs appended to the kernel command line (e.g. "initcall_debug")
# rsos_verbose 1: U-Boot prints on the UART (silent otherwise, see bootcmd)
#
Expand All @@ -92,7 +95,71 @@

bootstage mark boot.scr

# The disk of the system (bootcmd's rsos_sysdev: 0 = microSD, 1 = the Pro's
# eMMC after Settings > Storage > Install to internal storage; the eMMC also
# when U-Boot started from a starter card, a microSD with only the boot
# loader and games). Linux names them the same way (DT aliases: mmcblk0 =
# microSD, mmcblk1 = eMMC). With the system on the eMMC, its overlay is always
# applied: the base DT has mmc2 disabled, and Linux could not find its root
# filesystem without it. U-Boot's environment is on the disk it started from
# (mmc_bootdev): rsos.envdev tells Linux (rcS: /dev/rsos-disk).
l_dev=0
if test "${rsos_sysdev}" = 1; then
l_dev=1
elif test "${mmc_bootdev}" = 1; then
l_dev=1
fi
l_envdev=0
if test "${mmc_bootdev}" = 1; then
l_envdev=1
fi

l_save=0
# The model: the RetroStone2 Pro has the 16 GB eMMC U23 (and the M.2 slot
# J1), the regular RetroStone2 has neither. The first start (rsos_model
# empty) probes U-Boot's mmc 1 (the eMMC) once and saves rsos_model=pro or
# regular. A Pro gets the overlays "emmc" and "sata" (Settings > Storage can
# switch them off), a regular unit loses "emmc" (the menu then hides the
# internal storage). "rsos-storage redetect" (Settings > Storage > Detect the
# model again) clears rsos_model: the next start probes again.
if test -z "${rsos_model}"; then
if test ${l_dev} = 1; then
setenv rsos_model pro
elif mmc dev 1; then
setenv rsos_model pro
else
setenv rsos_model regular
fi
mmc dev ${l_envdev}
l_new=
for l_ov in ${rsos_overlays}; do
if test "${l_ov}" != "emmc" && test "${l_ov}" != "sata"; then
l_new="${l_new} ${l_ov}"
elif test "${l_ov}" = "sata" && test "${rsos_model}" = "regular"; then
l_new="${l_new} ${l_ov}"
fi
done
if test "${rsos_model}" = "pro"; then
l_new="${l_new} emmc sata"
fi
setenv rsos_overlays ${l_new}
echo "rsos: model ${rsos_model}, overlays: ${rsos_overlays}"
l_save=1
fi

l_ovs="${rsos_overlays}"
if test ${l_dev} = 1; then
l_hasemmc=0
for l_ov in ${rsos_overlays}; do
if test "${l_ov}" = "emmc"; then
l_hasemmc=1
fi
done
if test ${l_hasemmc} = 0; then
l_ovs="emmc ${rsos_overlays}"
fi
fi

# First boot (no saved environment yet): store the defaults, so that
# fw_setenv in Linux always finds a valid environment written by this U-Boot
# (otherwise it would start from its own built-in default environment,
Expand Down Expand Up @@ -167,7 +234,7 @@ if test ${l_fallback} = 1; then
l_off=1
elif test "${rsos_bad}" = "${l_other}"; then
echo "rsos: slot ${rsos_slot} failed too often, slot ${l_other} is marked bad: staying on ${rsos_slot}"
elif test -e mmc 0:${l_opart} /boot/zImage; then
elif test -e mmc ${l_dev}:${l_opart} /boot/zImage; then
if test "${rsos_fallback}" != "${l_other}" || test "${rsos_good}" = "${l_other}"; then
echo "rsos: slot ${rsos_slot} failed too often, falling back to slot ${l_other}"
setenv rsos_fallback ${rsos_slot}
Expand Down Expand Up @@ -218,8 +285,8 @@ fi
# cpu-lowvolt: one boot at a time until a boot with it is confirmed (a
# freeze at 1.0 V must not come back after every watchdog reset).
l_lowvolt=0
if test -n "${rsos_overlays}"; then
for l_ov in ${rsos_overlays}; do
if test -n "${l_ovs}"; then
for l_ov in ${l_ovs}; do
if test "${l_ov}" = "cpu-lowvolt"; then
l_lowvolt=1
fi
Expand Down Expand Up @@ -271,26 +338,26 @@ fi
# tens of ms in total, spread over the initcalls). The release build
# (BR2_RETROSTONE_RELEASE, docs/build.md "Release build") removes both words:
# post-build.sh deletes " initcall_debug log_buf_len=1M" from this line.
setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk0p${l_part} rootfstype=ext4 rootwait ro quiet panic=10 consoleblank=0 driver_async_probe=dw-apb-uart,musb-sunxi,sun4i-ts,axp20x-i2c initcall_debug log_buf_len=1M rsos.slot=${rsos_slot} rsos.boot=${l_state} ${rsos_extraargs}"
setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk${l_dev}p${l_part} rootfstype=ext4 rootwait ro quiet panic=10 consoleblank=0 driver_async_probe=dw-apb-uart,musb-sunxi,sun4i-ts,axp20x-i2c initcall_debug log_buf_len=1M rsos.slot=${rsos_slot} rsos.boot=${l_state} rsos.envdev=mmcblk${l_envdev} ${rsos_extraargs}"

bootstage mark load-zImage
if load mmc 0:${l_part} ${kernel_addr_r} /boot/zImage; then
if load mmc ${l_dev}:${l_part} ${kernel_addr_r} /boot/zImage; then
bootstage mark zImage-loaded
if load mmc 0:${l_part} ${fdt_addr_r} /boot/sun7i-a20-retrostone2.dtb; then
if load mmc ${l_dev}:${l_part} ${fdt_addr_r} /boot/sun7i-a20-retrostone2.dtb; then
bootstage mark dtb-loaded
if test -n "${rsos_overlays}"; then
if test -n "${l_ovs}"; then
fdt addr ${fdt_addr_r}
fdt resize 65536
for l_ov in ${rsos_overlays}; do
for l_ov in ${l_ovs}; do
if test "${l_ov}" = "cpu-lowvolt" && test ${l_lowvolt} = 0; then
true
elif load mmc 0:${l_part} ${fdtoverlay_addr_r} /boot/overlays/${l_ov}.dtbo; then
elif load mmc ${l_dev}:${l_part} ${fdtoverlay_addr_r} /boot/overlays/${l_ov}.dtbo; then
if fdt apply ${fdtoverlay_addr_r}; then
echo "rsos: overlay ${l_ov} applied"
else
# A failed fdt apply leaves the DT in an undefined state
echo "rsos: overlay ${l_ov} failed, reloading the base DT"
load mmc 0:${l_part} ${fdt_addr_r} /boot/sun7i-a20-retrostone2.dtb
load mmc ${l_dev}:${l_part} ${fdt_addr_r} /boot/sun7i-a20-retrostone2.dtb
fdt addr ${fdt_addr_r}
fdt resize 65536
fi
Expand Down Expand Up @@ -319,7 +386,7 @@ setenv rsos_ok 1
setenv rsos_tries 0
setenv rsos_fails 0
setenv rsos_p
if test ${rsos_rounds} -lt ${l_maxrounds} && test "${rsos_bad}" != "${l_other}" && test -e mmc 0:${l_opart} /boot/zImage; then
if test ${rsos_rounds} -lt ${l_maxrounds} && test "${rsos_bad}" != "${l_other}" && test -e mmc ${l_dev}:${l_opart} /boot/zImage; then
echo "rsos: switching to slot ${l_other}"
setenv rsos_fallback ${rsos_slot}
setenv rsos_slot ${l_other}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
From: RetroStoneOS <noreply@example.invalid>
Subject: [PATCH] sunxi: eMMC boot breadcrumbs in the AXP209 data registers

The RetroStone2 Pro starts from its eMMC once RetroStoneOS is installed
there. With no serial console, the SPL and U-Boot proper leave a marker in
the AXP209 data registers REG0E/REG0F when they run from the eMMC, read at
the next start from the microSD (rsos-storage report).
---
--- a/board/sunxi/board.c 2026-10-20 13:30:49.965329560 -0400
+++ b/board/sunxi/board.c 2026-10-20 13:30:49.981921451 -0400
@@ -589,6 +589,18 @@
defined CONFIG_AXP803_POWER
power_failed = axp_init();

+ /*
+ * RetroStone2: started from the eMMC (Settings > Storage > Install to
+ * internal storage): a breadcrumb in the AXP209's last data registers,
+ * which keep it while the battery is in. With no serial console, the
+ * next start from the microSD shows how far it got (rsos-storage's
+ * eMMC report): 5a e1 = this SPL ran, 5a e2 = U-Boot proper ran.
+ */
+ if (!power_failed && sunxi_get_boot_device() == BOOT_DEVICE_MMC2) {
+ pmic_bus_write(0x0e, 0x5a);
+ pmic_bus_write(0x0f, 0xe1);
+ }
+
if (IS_ENABLED(CONFIG_AXP_DISABLE_BOOT_ON_POWERON) && !power_failed) {
u8 boot_reason;

@@ -849,6 +861,11 @@
env_set("mmc_bootdev", "0");
} else if (boot == BOOT_DEVICE_MMC2) {
env_set("mmc_bootdev", "1");
+ /* RetroStone2: the eMMC breadcrumb, U-Boot proper reached */
+ if (!pmic_bus_init()) {
+ pmic_bus_write(0x0e, 0x5a);
+ pmic_bus_write(0x0f, 0xe2);
+ }
}

/* Set fdtfile to match the FIT configuration chosen in SPL. */
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
From: RetroStoneOS <noreply@example.invalid>
Subject: [PATCH] sunxi: A20 DRAM clock chosen at every start, with a trial

The RetroStone2 can run its DRAM faster than the Lime defaults (384 MHz):
the SPL reads the wanted level from an AXP209 data register, uses the
matching DDR3-1066F timings, and falls back by itself when Linux did not
confirm the last start at that speed.
---
--- a/board/sunxi/dram_sun5i_auto.c 2026-10-20 18:12:20.740264918 -0400
+++ b/board/sunxi/dram_sun5i_auto.c 2026-10-20 18:12:20.792886645 -0400
@@ -32,7 +32,68 @@
.dqs_gating_delay = CONFIG_DRAM_DQS_GATING_DELAY,
};

+#ifdef CONFIG_MACH_SUN7I
+#include <asm/arch/pmic_bus.h>
+
+/*
+ * RetroStone2: the memory clock is chosen at every start (Settings > Power >
+ * Memory speed in RetroStoneOS), through the AXP209 data register REG0D,
+ * which the PMIC keeps while the battery is in: <state> << 4 | <level>.
+ * Level 1 = 432 MHz, 2 = 480 MHz, each with the DDR3-1066F timings of
+ * dram_timings_sun4i.h for that clock (those of the A20 boards that run
+ * there, Cubietruck, Bananapi). States: A requested, B trial running, C
+ * confirmed by Linux after a stable start and a memory test, F failed.
+ * A and C start the level as a trial (B), so any start that Linux does not
+ * confirm (freeze, crash, power cut) finds B at the next start: the normal
+ * clock and timings are used, and F is stored. Anything else (0 after the
+ * battery was out): the normal clock, untouched.
+ */
+#define RSOS_DRAM_REG 0x0d
+
+static const struct {
+ u16 clock;
+ u8 cas;
+ u32 tpr0, tpr1, tpr2, emr2;
+} rsos_dram_levels[3] = {
+ [1] = { 432, 7, 0x2cb16690, 0xa0b0, 0x22e00, 0x8 }, /* DDR3-1066F 7-6-6-17 */
+ [2] = { 480, 7, 0x32b27790, 0xa0c0, 0x23200, 0x8 }, /* DDR3-1066F 7-7-7-18 */
+};
+
+static void rsos_dram_choose(struct dram_para *para)
+{
+ u8 v, lvl;
+
+ if (pmic_bus_read(RSOS_DRAM_REG, &v))
+ return;
+ lvl = v & 0x0f;
+ if (lvl < 1 || lvl > 2)
+ return;
+ switch (v & 0xf0) {
+ case 0xa0:
+ case 0xc0:
+ if (pmic_bus_write(RSOS_DRAM_REG, 0xb0 | lvl))
+ return; /* no trial without its marker */
+ break;
+ case 0xb0:
+ pmic_bus_write(RSOS_DRAM_REG, 0xf0 | lvl);
+ return;
+ default:
+ return;
+ }
+ para->clock = rsos_dram_levels[lvl].clock;
+ para->cas = rsos_dram_levels[lvl].cas;
+ para->tpr0 = rsos_dram_levels[lvl].tpr0;
+ para->tpr1 = rsos_dram_levels[lvl].tpr1;
+ para->tpr2 = rsos_dram_levels[lvl].tpr2;
+ para->emr2 = rsos_dram_levels[lvl].emr2;
+ para->active_windowing = 1;
+}
+#endif
+
unsigned long sunxi_dram_init(void)
{
+#ifdef CONFIG_MACH_SUN7I
+ rsos_dram_choose(&dram_para);
+#endif
return dramc_init(&dram_para);
}
20 changes: 20 additions & 0 deletions buildroot-external/board/retrostone2/post-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,26 @@ mkdir -p "$TARGET/usr/libexec/rsos"
# them to shutdown.txt on the next boot (tools/rsos-axpstamp.c).
"$CC" -O2 -s -Wall -Wextra -Werror -o "$TARGET/usr/libexec/rsos/axpstamp" \
"$BOARD_DIR/tools/rsos-axpstamp.c"
# /usr/libexec/rsos/memtest: the quick DRAM check of the faster memory trial
# (Settings > Power > Memory speed; rsos-boot-ok, tools/rsos-memtest.c).
"$CC" -O2 -s -Wall -Wextra -Werror -o "$TARGET/usr/libexec/rsos/memtest" \
"$BOARD_DIR/tools/rsos-memtest.c"

# --- The boot loader, for "Install to internal storage" on the Pro
# (rsos-storage install writes it at 8 KiB on the eMMC): the image's own
# U-Boot, built before the root filesystem is finalised. Its sha256 sits next
# to it, so the installer can check its copy and the write.
UBOOT_BIN=$BINARIES_DIR/u-boot-sunxi-with-spl.bin
if [ ! -f "$UBOOT_BIN" ]; then
echo "post-build.sh: $UBOOT_BIN missing (the eMMC installer needs it)" >&2
exit 1
fi
# rsos-storage: Settings > Storage on the Pro (eMMC, M.2 SATA, game disks).
# (Windows checkouts lose the executable bit: board/common/post-build.sh.)
chmod 0755 "$TARGET/usr/bin/rsos-storage"
mkdir -p "$TARGET/usr/share/rsos/bootloader"
cp "$UBOOT_BIN" "$TARGET/usr/share/rsos/bootloader/u-boot-sunxi-with-spl.bin"
(cd "$TARGET/usr/share/rsos/bootloader" && sha256sum u-boot-sunxi-with-spl.bin > u-boot-sunxi-with-spl.bin.sha256)

# --- WiFi/BT firmware names.
# brcmfmac asks for brcm/brcmfmac<chip>-sdio.<board compatible>.{bin,txt},
Expand Down
Loading