default.nix (11221B)
1 { 2 description = '' 3 4 == Belkin RT-3200 / Linksys E8450 5 6 This device is based on a 64 bit Mediatek MT7622 ARM platform, and has 7 been powering my (Daniel's) home network since February 2025. 8 9 === Hardware summary 10 11 * MediaTek MT7622BV (1350MHz) 12 * 128MB NAND flash 13 * 512MB RAM 14 * b/g/n wireless using MediaTek MT7622BV (MT7615E driver) 15 * a/n/ac/ax wireless using MediaTek MT7915E 16 17 === Installation 18 19 Liminix on this device uses the UBI volume management system to perform 20 wear leveling on the flash. This is not set up from the factory, so a 21 one-time step is needed to prepare it before Liminix can be installed. 22 23 ==== Preparation 24 25 To prepare the device for Liminix you first need to use the 26 https://github.com/dangowrt/owrt-ubi-installer[OpenWrt UBI Installer] 27 image to rewrite the flash layout. As of Jan 2025 there are two versions 28 of the installer available: the release version 1.0.2 and the 29 pre-release 1.1.3 and for Liminix you nee the pre-release. The release 30 version of the installer creates UBI volumes according to an older 31 layout that is not compatible with the Linux 6.6.67 kernel used in 32 Liminix. 33 34 You can run the installer in one of two ways: either follow the 35 instructions to do it through the vendor web interface, or you can drop 36 to U-Boot and use TFTP 37 38 [source,console] 39 ---- 40 MT7622> setenv ipaddr 10.0.0.6 41 MT7622> setenv serverip 10.0.0.1 42 MT7622> tftpboot 0x42000000 openwrt-mediatek-mt7622-linksys_e8450-ubi-initramfs-recovery-installer.itb 43 MT7622> bootm 0x42000000 44 ---- 45 46 This will write the new flash layout and then boot into a "recovery" 47 OpenWrt installation. 48 49 ==== Building/installing Liminix 50 51 The default target for this device is `+outputs.ubimage+` which makes a 52 ubifs image suitable for use with `+ubiupdatevol+`. To write this to the 53 device we use the OpenWrt recovery system installed in the previous 54 step. In this configuration the device assigns itself the IP address 55 192.168.1.1/24 on its LAN ports and expects the connected computer to 56 have 192.168.1.254 57 58 [WARNING] 59 ==== 60 The [.title-ref]#ubi0_7# device in these instructions is correct as of 61 Dec 2024 (dangowrt/owrt-ubi-installer commit d79e7928). If you are 62 installing some time later, it is important to check the output from 63 `+ubinfo -a+` and make sure you are updating the "liminix" volume and 64 not some other one which had been introduced since I wrote this. 65 ==== 66 67 [source,console] 68 ---- 69 $ nix-build -I liminix-config=./my-configuration.nix --arg device "import ./devices/belkin-rt3200" -A outputs.default 70 $ cat result/rootfs | ssh root@192.168.1.1 "cat > /tmp/rootfs" 71 $ ssh root@192.168.1.1 72 root@OpenWrt:~# ubimkvol /dev/ubi0 --name=liminix --maxavsize 73 root@OpenWrt:~# ubinfo -a 74 [...] 75 Volume ID: 7 (on ubi0) 76 Type: dynamic 77 Alignment: 1 78 Size: 851 LEBs (108056576 bytes, 103.0 MiB) 79 State: OK 80 Name: liminix 81 Character device major/minor: 250:8 82 root@OpenWrt:~# ubiupdatevol /dev/ubi0_7 /tmp/rootfs 83 ---- 84 85 To make the new system bootable we also need to change some U-Boot 86 variables. `+boot_production+` needs to mount the filesystem and boot 87 the FIT image found there, and `+bootcmd+` needs to be told not to boot 88 the rescue image if there are records in pstore, because that interferes 89 with `+config.log.persistent+` 90 91 [source,console] 92 ---- 93 root@OpenWrt:~# fw_setenv orig_boot_production $(fw_printenv -n boot_production) 94 root@OpenWrt:~# fw_setenv orig_bootcmd $(fw_printenv -n bootcmd) 95 root@OpenWrt:~# fw_setenv boot_production 'led $bootled_pwr on ; ubifsmount ubi0:liminix && ubifsload ''${loadaddr} boot/fit && bootm ''${loadaddr}' 96 root@OpenWrt:~# fw_setenv bootcmd 'run boot_ubi' 97 ---- 98 99 For subsequent Liminix reinstalls, just run the `+ubiupdatevol+` command 100 again. You don't need to repeat the "Preparation" step and in fact 101 should seek to avoid it if possible, as it will reset the erase counters 102 used for write levelling. Using UBI-aware tools is therefore preferred 103 over any kind of "factory" wipe which will reset them. 104 105 ''; 106 107 system = { 108 crossSystem = { 109 config = "aarch64-unknown-linux-musl"; 110 }; 111 }; 112 113 module = 114 { 115 pkgs, 116 config, 117 lib, 118 lim, 119 ... 120 }: 121 let 122 inherit (lib) mkIf; 123 firmware = pkgs.stdenv.mkDerivation { 124 name = "wlan-firmware"; 125 phases = [ "installPhase" ]; 126 installPhase = '' 127 mkdir $out 128 cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out 129 ''; 130 }; 131 openwrt = pkgs.openwrt_24_10; 132 in 133 { 134 imports = [ 135 ../../modules/arch/aarch64.nix 136 ../../modules/outputs/tftpboot.nix 137 ../../modules/outputs/ubifs.nix 138 ]; 139 config = { 140 kernel = { 141 extraPatchPhase = '' 142 ${openwrt.applyPatches.mediatek} 143 ''; 144 src = openwrt.kernelSrc; 145 version = openwrt.kernelVersion; 146 config = { 147 PCI = "y"; 148 ARCH_MEDIATEK = "y"; 149 # ARM_MEDIATEK_CPUFREQ = "y"; 150 151 # needed for "Cannot find regmap for /infracfg@10000000" 152 MFD_SYSCON = "y"; 153 MTK_INFRACFG = "y"; 154 155 MTK_PMIC_WRAP = "y"; 156 DMADEVICES = "y"; 157 MTK_HSDMA = "y"; 158 MTK_SCPSYS = "y"; 159 MTK_SCPSYS_PM_DOMAINS = "y"; 160 # MTK_THERMAL="y"; 161 MTK_TIMER = "y"; 162 163 COMMON_CLK_MT7622 = "y"; 164 COMMON_CLK_MT7622_ETHSYS = "y"; 165 COMMON_CLK_MT7622_HIFSYS = "y"; 166 COMMON_CLK_MT7622_AUDSYS = "y"; 167 PM_CLK = "y"; 168 169 REGMAP_MMIO = "y"; 170 CLKSRC_MMIO = "y"; 171 REGMAP = "y"; 172 173 MEDIATEK_GE_PHY = "y"; 174 # MEDIATEK_MT6577_AUXADC = "y"; 175 NET_MEDIATEK_SOC = "y"; 176 NET_MEDIATEK_SOC_WED = "y"; 177 NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO 178 NET_VENDOR_MEDIATEK = "y"; 179 PCIE_MEDIATEK = "y"; 180 181 BLOCK = "y"; # move this to base option 182 183 SPI_MASTER = "y"; 184 SPI = "y"; 185 SPI_MEM = "y"; 186 SPI_MTK_NOR = "y"; 187 SPI_MTK_SNFI = "y"; 188 189 MTD = "y"; 190 MTD_BLOCK = "y"; 191 MTD_RAW_NAND = "y"; 192 MTD_NAND_MTK = "y"; 193 MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table 194 MTD_NAND_ECC_MEDIATEK = "y"; 195 MTD_NAND_ECC_SW_HAMMING = "y"; 196 MTD_SPI_NAND = "y"; 197 MTD_OF_PARTS = "y"; 198 MTD_NAND_CORE = "y"; 199 MTD_SPI_NOR = "y"; 200 MTD_SPLIT_FIRMWARE = "y"; 201 MTD_SPLIT_FIT_FW = "y"; 202 203 MTD_UBI_NVMEM = "y"; 204 NVMEM_MTK_EFUSE = "y"; 205 NVMEM_BLOCK = "y"; 206 NVMEM_LAYOUT_ADTRAN = "y"; 207 208 MMC = "y"; 209 MMC_BLOCK = "y"; 210 MMC_CQHCI = "y"; 211 MMC_MTK = "y"; 212 213 # Distributed Switch Architecture is needed 214 # to make the ethernet ports visible 215 NET_DSA = "y"; 216 NET_DSA_MT7530 = "y"; 217 NET_DSA_TAG_MTK = "y"; 218 NET_DSA_MT7530_MDIO = "y"; 219 220 SERIAL_8250 = "y"; 221 SERIAL_8250_CONSOLE = "y"; 222 SERIAL_8250_MT6577 = "y"; 223 # SERIAL_8250_NR_UARTS="3"; 224 # SERIAL_8250_RUNTIME_UARTS="3"; 225 SERIAL_OF_PLATFORM = "y"; 226 227 # Must enble hardware watchdog drivers. Else the device reboots after several seconds 228 WATCHDOG = "y"; 229 MEDIATEK_WATCHDOG = "y"; 230 }; 231 conditionalConfig = { 232 WLAN = { 233 MT7615E = "m"; 234 MT7622_WMAC = "y"; 235 MT7915E = "m"; 236 }; 237 }; 238 }; 239 boot = { 240 commandLine = [ "console=ttyS0,115200" ]; 241 tftp.loadAddress = lim.parseInt "0x48000000"; 242 imageFormat = "fit"; 243 loader.fit.enable = lib.mkDefault true; # override this if you are building tftpboot 244 }; 245 rootfsType = lib.mkDefault "ubifs"; # override this if you are building tftpboot 246 filesystem = 247 let 248 inherit (pkgs.pseudofile) dir symlink; 249 in 250 dir { 251 lib = dir { 252 firmware = dir { 253 mediatek = symlink firmware; 254 }; 255 }; 256 }; 257 258 hardware = 259 let 260 mac80211 = pkgs.kmodloader.override { 261 targets = [ 262 "mt7615e" 263 "mt7915e" 264 ]; 265 inherit (config.system.outputs) kernel; 266 }; 267 in 268 { 269 ubi = { 270 minIOSize = "2048"; 271 logicalEraseBlockSize = "126976"; 272 physicalEraseBlockSize = "131072"; 273 maxLEBcount = "1400"; # guessing 274 }; 275 276 defaultOutput = "ubimage"; 277 # the kernel expects this to be on a 2MB boundary. U-Boot 278 # (I don't know why) has a default of 0x41080000, which isn't. 279 # We put it at the 32MB mark so that tftpboot can put its rootfs 280 # image and DTB underneath, but maybe this is a terrible waste of 281 # RAM unless the kernel is able to reuse it later. Oh well 282 loadAddress = lim.parseInt "0x42000000"; 283 entryPoint = lim.parseInt "0x42000000"; 284 rootDevice = "ubi0:liminix"; 285 dts = { 286 src = "${openwrt.src}/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts"; 287 includePaths = [ 288 "${openwrt.src}/target/linux/mediatek/dts" 289 "${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/" 290 ]; 291 includes = mkIf config.logging.persistent.enable [ 292 ./pstore-pmsg.dtsi 293 ]; 294 }; 295 296 # - 0x000000000000-0x000008000000 : "spi-nand0" 297 # - 0x000000000000-0x000000080000 : "bl2" 298 # - 0x000000080000-0x0000001c0000 : "fip" 299 # - 0x0000001c0000-0x0000002c0000 : "factory" 300 # - 0x0000002c0000-0x000000300000 : "reserved" 301 # - 0x000000300000-0x000008000000 : "ubi" 302 303 networkInterfaces = 304 let 305 inherit (config.system.service.network) link; 306 in 307 rec { 308 wan = link.build { ifname = "wan"; }; 309 lan1 = link.build { ifname = "lan1"; }; 310 lan2 = link.build { ifname = "lan2"; }; 311 lan3 = link.build { ifname = "lan3"; }; 312 lan4 = link.build { ifname = "lan4"; }; 313 lan = lan3; 314 315 wlan = link.build { 316 ifname = "wlan0"; 317 dependencies = [ mac80211 ]; 318 }; 319 wlan5 = link.build { 320 ifname = "wlan1"; 321 dependencies = [ mac80211 ]; 322 }; 323 }; 324 }; 325 }; 326 }; 327 }