liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }