Skip to content
View in the app

A better way to browse. Learn more.

Armbian Community Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Echo_Tinker

Validating
  • Joined

  • Last visited

Everything posted by Echo_Tinker

  1. Same board here (SuperBox S6 Pro = Transpeed 8K618-T, RTL8211F). I got the gigabit port working under Android (SlimBOX), write-up below. A few board findings may help Armbian device trees for this box too: the PI pin drive strength was level 0, working delays are tx 5 / rx 6 (with the RTL8211F's own TX delay off), and fd628 holds PI11/PI12. I may not check back often, so everything is in this post. [FIX] Gigabit Ethernet port working on SuperBox S6 Pro / H618 (Transpeed 8K618-T board, RTL8211F) with SlimBOX Android 12 Short version (for everyone)The problem: on the SuperBox S6 Pro (and other H618 boxes sold as "1000M Ethernet"), the network port looks alive (the light comes on and your router shows a gigabit link) but no data ever goes through. This happens on every firmware I could find. Why: the box has a real gigabit network chip (Realtek RTL8211F), but every firmware is copied from a cheaper 100M board and talks to the wrong chip. The driver also has three bugs that crash the box if you just switch the right chip on. The result: with the fix below, the built-in port runs at about 790 Mbit/s with zero errors, survives reboots, and gets its address from the router normally. You don't need a serial adapter or a new firmware. Who can do this: you need a rooted box (Magisk), adb over the network or USB, and a PC with Python. If "adb" and "dd" are new to you, ask someone who has done it before. It's easy to undo, though: the box can always be reflashed with PhoenixSuit, because burn mode is built into the chip and can't be erased. Important: the kernel part of the fix only fits one firmware build: SlimBOX sbx_transpeed_h618_atv_12_16 (kernel 5.4.125, file sbx_transpeed_h618_aosp_12_16.zip). The script checks this and refuses to change anything on a different build. Nothing gets written in that case. Step by stepWhat you need: the box with SlimBOX atv_12_16 flashed and rooted with Magisk, adb working (adb connect <box-ip>:5555 or USB), and a PC with python3 and device-tree-compiler (Linux: sudo apt install device-tree-compiler). 1. Back up the two partitions (keep these files safe, they're your undo): adb shell "su -c 'cat /dev/block/by-name/boot_a'" > boot_a.img adb shell "su -c 'cat /dev/block/by-name/vendor_boot_a'" > vendor_boot_a.img cp boot_a.img boot_a.ORIGINAL.img; cp vendor_boot_a.img vendor_boot_a.ORIGINAL.img(If your box runs from slot _b, check with adb shell getprop ro.boot.slot_suffix and use _b.) 2. Run the script (below) on your PC: python3 h618_gigabit_fix.py boot_a.img vendor_boot_a.imgIt prints each change and writes boot_a.patched.img and vendor_boot_a.patched.img. If it says STOP, your firmware is a different build. Don't continue. 3. Write them back and reboot: adb push boot_a.patched.img vendor_boot_a.patched.img /data/local/tmp/ adb shell "su -c 'dd if=/data/local/tmp/boot_a.patched.img of=/dev/block/by-name/boot_a bs=1M; dd if=/data/local/tmp/vendor_boot_a.patched.img of=/dev/block/by-name/vendor_boot_a bs=1M; sync; reboot'"4. Check it: plug a cable into the box's port. Settings → Network should show Ethernet connected. Or run adb shell ip addr show eth0. To undo: write the .ORIGINAL.img files back the same way. Or reflash SlimBOX with PhoenixSuit. Magisk note: if you later re-patch boot with Magisk, run the script on the new boot image again. It skips patches that are already in place. Optional: port on a network with no internet (for example a cable straight to a PC). Android only sends replies over its "default" network, and a network with no internet never becomes the default. The box then gets an address but answers nothing (ping/adb time out). This script copies the route into the main table every 5 seconds, so it also survives cable replugs. Change NET to your network. You don't need this if the box is plugged into a normal router with internet. #!/system/bin/sh # Magisk: put in /data/adb/service.d/eth-local.sh, chmod 755 NET=192.168.50 # first three numbers of your network ( while true; do a=$(ip -4 -o addr show eth0 2>/dev/null | grep -o "$NET\.[0-9]*" | head -1) if [ -n "$a" ]; then ip route replace $NET.0/24 dev eth0 src $a table main 2>/dev/null ip rule list | grep -q "from $a lookup main" || ip rule add from $a lookup main pref 97 ip rule list | grep -q "to $NET.0/24 lookup main" || ip rule add to $NET.0/24 lookup main pref 98 fi; sleep 5; done ) &What the fix changes (for the tinkerers)Six problems, found one by one. A box that hard-freezes with no log line was handled with the trick at the end of this section. Wrong port enabled. The device tree has eth@5020000 (gmac0, RGMII to the RTL8211F) disabled and eth@5030000 (gmac1, internal AC300 100M PHY) enabled. Swapped. Wrong pin function name. function = "gmac0" gives unsupported function gmac0 on pin PI0 / gmac pinctrl error! (-22). This kernel calls it emac0. Front display driver steals RGMII pins. fd628_dev claims PI11/PI12 (pin PI11 already requested ... cannot claim for 5020000.eth). Those are TXCK/TXCTL on this board. Set fd628_dev to status = "fail" (the front LED display goes dark). Kernel panic in the MAC code. geth_probe() → get_addr_by_name() sprintfs the address from addr_mgt into mac_str, which points at the string literal "00:00:00:00:00:00" in read-only kernel data. Result: Unable to handle kernel write to read-only memory, every time. Fix: NOP the call, and put mac_addr=02:.. on the vendor_boot boot line (__setup("mac_addr=") copies it in before rodata becomes read-only). PHY scan only accepts the AC300 and crashes on empty addresses. geth_phy_init() calls get_phy_device() on MDIO 0–31 with no IS_ERR check (→ virtual address 00000000000003fd) and only accepts phy_id 0x00441400. Fix: skip get_phy_device (libphy has already registered the RTL8211F at address 0) and accept the first real PHY. Link up, zero frames. The PI pin drive strength was level 0 (PI_DRV0 = 0; drive-strength = <10> maps to level 0 in this kernel). TX worked at once with level 3 (<40>). The RX delay of 31 was also outside the window. Live sweep: with RTL8211F TX delay off (the driver default), EMAC tx-delay 3–7 and rx-delay 0–12 work. Chosen: tx 5, rx 6. Kernel patches (VA, _text = 0xffffffc010080000, file offset = VA − _text + 4096 in boot.img): VA original patched 0xffffffc010786a94 bl get_addr_by_name 94d2fe97 nop 1f2003d5 0xffffffc010788f70 bl get_phy_device cbc4ff97 mov x0,xzr e0031faa 0xffffffc010788f30 b.eq a0030054 b 1d000014 The no-serial-adapter debugging trick: this kernel has CONFIG_PSTORE_RAM=y, but the device tree has no ramoops region. Add one to reserved-memory (ramoops@13ab00000, 1 MB) and start the hardware watchdog before each test (busybox watchdog -t 2 -T 16 /dev/watchdog). Every hard freeze then warm-resets after 16 s, and the full panic is waiting in /sys/fs/pstore/console-ramoops-0. Also useful: /sys/class/sunxi_dump (read/write physical registers as root) and the driver's mii_read / mii_write sysfs files (raw PHY registers). Together those let you sweep RGMII delays live with no reboots. The script leaves the ramoops region in (use --no-ramoops to skip it). Hardware: H618, 4 GB, RTL8211F (25 MHz crystal) + TFS5009 magnetics, Wi-Fi module Cdtech 20AI880-20 (AIC8800, not working yet: aic8800_bsp loads, no wlan0). UART header B/VCC/R/GND at 1500000 baud (not needed). Not fixed: Wi-Fi. Also, a proper fix would be a rebuilt sunxi-gmac.c (IS_ERR check, no AC300-only ID check, writable mac_str). These binary patches only fit this build. On another build, find get_addr_by_name, geth_probe and geth_phy_init in /proc/kallsyms, disassemble, and look for the same three spots. The script (h618_gigabit_fix.py)#!/usr/bin/env python3 """ h618_gigabit_fix.py - enable the RTL8211F gigabit Ethernet port on H618 TV boxes (SuperBox S6 Pro / Transpeed 8K618-T board) running SlimBOX Android 12 build "sbx_transpeed_h618_atv_12_16" (from sbx_transpeed_h618_aosp_12_16.zip) (kernel 5.4.125). It patches two partition images that you pulled off the box: boot_a.img -> 3 four-byte kernel patches (only if the exact original bytes are found) vendor_boot_a.img -> device tree + boot line changes It REFUSES to patch anything that does not match the known build. Needs: python3, and dtc/fdtget/fdtput (package "device-tree-compiler"). Usage: python3 h618_gigabit_fix.py boot_a.img vendor_boot_a.img [--mac 02:xx:xx:xx:xx:xx] [--no-ramoops] Writes boot_a.patched.img and vendor_boot_a.patched.img next to the originals. """ import argparse, hashlib, os, random, struct, subprocess, sys, tempfile TEXT = 0xffffffc010080000 # kernel _text for this build KOFF = 4096 # kernel Image offset inside boot v3 image KPATCH = [ # (virtual address, original bytes, new bytes, what) (0xffffffc010786a94, "94d2fe97", "1f2003d5", "nop: skip get_addr_by_name (writes into read-only memory)"), (0xffffffc010788f70, "cbc4ff97", "e0031faa", "mov x0,xzr: skip get_phy_device (unchecked error pointer)"), (0xffffffc010788f30, "a0030054", "1d000014", "b: accept the RTL8211F, not only the AC300 100M PHY"), ] ETH = "/soc@3000000/eth@5020000" ETH1 = "/soc@3000000/eth@5030000" PIN = "/soc@3000000/pinctrl@300b000/gmac0@0" FD628 = "/soc@3000000/fd628_dev" RAMOOPS = "/reserved-memory/ramoops@13ab00000" DTB_OFF = 6144 # dtb offset in this vendor_boot (header v3, page 2048) def die(msg): sys.exit("STOP: " + msg) def run(*a): r = subprocess.run(a, capture_output=True, text=True) if r.returncode: die(f"{' '.join(a)} failed: {r.stderr.strip()}") return r.stdout.strip() def patch_boot(path): b = bytearray(open(path, "rb").read()) if b[:8] != b"ANDROID!" or struct.unpack("<I", b[40:44])[0] != 3: die(f"{path} is not an Android boot image v3") if b[KOFF + 56:KOFF + 60] != b"ARMd": die("no arm64 kernel Image at offset 4096") for va, old, new, what in KPATCH: o = KOFF + va - TEXT cur = b[o:o + 4].hex() if cur == new: print(f" already patched: {what}") continue if cur != old: die(f"kernel bytes at {va:#x} are {cur}, expected {old}. " "This is a different firmware build - the offsets do not apply. Nothing was written.") b[o:o + 4] = bytes.fromhex(new) print(f" patched: {what}") return b def patch_vendor_boot(path, mac, ramoops): v = bytearray(open(path, "rb").read()) if v[:8] != b"VNDRBOOT" or struct.unpack("<I", v[8:12])[0] != 3: die(f"{path} is not a vendor_boot v3 image") page = struct.unpack("<I", v[12:16])[0] dsize = struct.unpack("<I", v[2100:2104])[0] if v[DTB_OFF:DTB_OFF + 4] != b"\xd0\x0d\xfe\xed": die("device tree not found at offset 6144") end_pad = (DTB_OFF + dsize + page - 1) // page * page with tempfile.TemporaryDirectory() as t: d = os.path.join(t, "vb.dtb") open(d, "wb").write(v[DTB_OFF:DTB_OFF + dsize]) comp = run("fdtget", d, ETH, "compatible") if not comp.startswith("allwinner,sunxi-gma"): die(f"unexpected gmac0 node: {comp}") # gigabit port on, 100M port off run("fdtput", "-t", "s", d, ETH, "compatible", "allwinner,sunxi-gmac") run("fdtput", "-t", "s", d, ETH, "status", "okay") run("fdtput", "-t", "s", d, ETH1, "status", "disabled") run("fdtput", "-t", "i", d, ETH, "use_ephy25m", "0") run("fdtput", "-t", "x", d, ETH, "tx-delay", "5") run("fdtput", "-t", "x", d, ETH, "rx-delay", "6") for p in ("phy-rst", "gmac-power0", "gmac-power1", "gmac-power2"): subprocess.run(["fdtput", "-d", d, ETH, p], capture_output=True) # pins: right function name + full drive strength (10 mA = level 0 in this kernel) run("fdtput", "-t", "s", d, PIN, "function", "emac0") run("fdtput", "-t", "x", d, PIN, "drive-strength", "0x28") # front display driver holds PI11/PI12 (RGMII TXCK/TXCTL) run("fdtput", "-t", "s", d, FD628, "status", "fail") if ramoops: subprocess.run(["fdtput", "-c", d, RAMOOPS], capture_output=True) run("fdtput", "-t", "s", d, RAMOOPS, "compatible", "ramoops") run("fdtput", "-t", "x", d, RAMOOPS, "reg", "1", "0x3ab00000", "0", "0x100000") run("fdtput", "-t", "x", d, RAMOOPS, "console-size", "0x80000") run("fdtput", "-t", "x", d, RAMOOPS, "record-size", "0x20000") run("fdtput", "-t", "x", d, RAMOOPS, "pmsg-size", "0x0") run("fdtput", "-t", "x", d, RAMOOPS, "ecc-size", "0") p = os.path.join(t, "vb2.dtb") run("dtc", "-q", "-I", "dtb", "-O", "dtb", "-o", p, d) nd = open(p, "rb").read() if DTB_OFF + len(nd) > end_pad: die("new device tree does not fit in the padding") v[DTB_OFF:end_pad] = nd + b"\0" * (end_pad - DTB_OFF - len(nd)) v[2100:2104] = struct.pack("<I", len(nd)) # boot line: fixed MAC address (driver needs one, u-boot passes an empty one) cl = bytes(v[28:28 + 2048]).rstrip(b"\0") if b"mac_addr=" not in cl: cl += b" mac_addr=" + mac.encode() if len(cl) >= 2048: die("boot line too long") v[28:28 + 2048] = cl.ljust(2048, b"\0") return v def main(): ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) ap.add_argument("boot"); ap.add_argument("vendor_boot") ap.add_argument("--mac", help="MAC to use (default: random locally administered 02:..)") ap.add_argument("--no-ramoops", action="store_true", help="don't add the crash-log memory region") a = ap.parse_args() mac = a.mac or "02:" + ":".join(f"{random.randint(0, 255):02x}" for _ in range(5)) if len(mac) != 17: die("MAC must look like 02:11:22:33:44:55") print("boot image:") b = patch_boot(a.boot) print("vendor_boot image:") v = patch_vendor_boot(a.vendor_boot, mac, not a.no_ramoops) ob = a.boot.rsplit(".img", 1)[0] + ".patched.img" ov = a.vendor_boot.rsplit(".img", 1)[0] + ".patched.img" open(ob, "wb").write(b); open(ov, "wb").write(v) print(f"\nMAC address: {mac}") for f in (ob, ov): print(f"wrote {f} md5 {hashlib.md5(open(f, 'rb').read()).hexdigest()}") if __name__ == "__main__": main()Tested: run on the original SlimBOX atv_12_16 images, the output kernel is byte-identical to the one running on my box. The device tree matches too, apart from two status strings written the standard way. A box with this fix has been running at ~790 Mbit/s with zero errors through reboots. Questions welcome. If you have a different H618 box with an RTL8211F, the same six problems are probably there.

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.