From 0a8343be664bf4af0ec56df9daa7e30b999fe61b Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sat, 17 Feb 2024 02:16:20 +0100 Subject: [PATCH 01/23] pkgs/kernel/uimage: introduce `commandLineDtbNode` Certain devices like the Zyxel NWA50AX will pass information on the command-line to explain what is the current image (`bootImage=1` vs. `bootImage=0`). Unfortunately, if we set the `chosen/bootargs` node, this will be overridden forcibly by U-Boot. To avoid this problem, it's easier to simply just use another DTB node like `bootargs-override` which is what OpenWRT does [1]. [1]: https://git.openwrt.org/?p=openwrt/openwrt.git;a=blob;f=target/linux/ramips/patches-5.15/314-MIPS-add-bootargs-override-property.patch;h=e7dca7af886e8c0b69ba2b23f5855ddfeeb0d4a1;hb=refs/heads/main Signed-off-by: Raito Bezarius --- pkgs/kernel/uimage.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/kernel/uimage.nix b/pkgs/kernel/uimage.nix index eca50d5..83d9031 100644 --- a/pkgs/kernel/uimage.nix +++ b/pkgs/kernel/uimage.nix @@ -15,6 +15,7 @@ let in { kernel , commandLine +, commandLineDtbNode ? "bootargs" , entryPoint , extraName ? "" # e.g. socFamily , loadAddress @@ -39,7 +40,7 @@ in { ''; mungeDtbPhase = '' dtc -I dtb -O dts -o tmp.dts ${dtb} - echo '/{ chosen { bootargs = ${builtins.toJSON commandLine}; }; };' >> tmp.dts + echo '/{ chosen { ${commandLineDtbNode} = ${builtins.toJSON commandLine}; }; };' >> tmp.dts dtc -I dts -O dtb -o tmp.dtb tmp.dts ''; From b76c5b4abef377d8cffeca8165843c4f8abf86fc Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 4 Dec 2023 14:11:53 +0100 Subject: [PATCH 02/23] modules/ubifs: revamp to offer directly access to the UBIfs partition Adds the LEB and PEB option and let the user remove the boot image in case where U-Boot does not support UBI boot. --- modules/outputs/ubifs.nix | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/outputs/ubifs.nix b/modules/outputs/ubifs.nix index cfa27b9..11c879c 100644 --- a/modules/outputs/ubifs.nix +++ b/modules/outputs/ubifs.nix @@ -12,9 +12,16 @@ in imports = [ ./initramfs.nix ]; + + options.system.outputs.rootubifs = mkOption { + type = types.package; + internal = true; + }; + options.hardware.ubi = { minIOSize = mkOption { type = types.str; }; - eraseBlockSize = mkOption { type = types.str; }; # LEB + logicalEraseBlockSize = mkOption { type = types.str; }; # LEB + physicalEraseBlockSize = mkOption { type = types.str; }; # PEB maxLEBcount = mkOption { type = types.str; }; # LEB }; @@ -35,7 +42,7 @@ in } '' mkdir tmp tree=${o.bootablerootdir} - mkfs.ubifs -x favor_lzo -c ${cfg.maxLEBcount} -m ${cfg.minIOSize} -e ${cfg.eraseBlockSize} -y -r $tree --output $out --squash-uids -o $out + mkfs.ubifs -x favor_lzo -c ${cfg.maxLEBcount} -m ${cfg.minIOSize} -e ${cfg.logicalEraseBlockSize} -y -r $tree --output $out --squash-uids -o $out ''; }; }; From c59364d6239c6e7f514a22289498d484a5d433f9 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sat, 17 Feb 2024 02:18:09 +0100 Subject: [PATCH 03/23] modules/outputs/ubifs: expose `rootubifs` rather than `rootfs` I believe there should be another module exposing `rootubifs` as `rootfs` or let any other module just subsume that component like `zyxel-nwa-fit` output. Signed-off-by: Raito Bezarius --- modules/outputs/ubifs.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/outputs/ubifs.nix b/modules/outputs/ubifs.nix index 11c879c..b7a7c61 100644 --- a/modules/outputs/ubifs.nix +++ b/modules/outputs/ubifs.nix @@ -33,7 +33,7 @@ in }; boot.initramfs.enable = true; system.outputs = { - rootfs = + rootubifs = let inherit (pkgs.pkgsBuildBuild) runCommand mtdutils; cfg = config.hardware.ubi; From dde8386f7583cbb4145b9b484c39c737cb3c1578 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 4 Dec 2023 14:07:30 +0100 Subject: [PATCH 04/23] builders/uimage: support aligning the FIT This is necessary when writing to a MTD partition with a certain erasesize. --- modules/hardware.nix | 1 + modules/outputs.nix | 2 +- pkgs/kernel/uimage.nix | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/hardware.nix b/modules/hardware.nix index 598038d..44afc3a 100644 --- a/modules/hardware.nix +++ b/modules/hardware.nix @@ -67,6 +67,7 @@ in { }; loadAddress = mkOption { type = types.ints.unsigned; default = null; }; entryPoint = mkOption { type = types.ints.unsigned; }; + alignment = mkOption { type = types.ints.unsigned; default = null; description = "Alignment passed to `mkimage` for FIT"; }; radios = mkOption { description = '' Kernel modules (from mac80211 package) required for the diff --git a/modules/outputs.nix b/modules/outputs.nix index f60e146..d7861d9 100644 --- a/modules/outputs.nix +++ b/modules/outputs.nix @@ -111,7 +111,7 @@ in }; uimage = liminix.builders.uimage { commandLine = concatStringsSep " " config.boot.commandLine; - inherit (config.hardware) loadAddress entryPoint; + inherit (config.hardware) loadAddress entryPoint alignment; inherit (config.boot) imageFormat; inherit (o) kernel dtb; }; diff --git a/pkgs/kernel/uimage.nix b/pkgs/kernel/uimage.nix index 83d9031..96123a4 100644 --- a/pkgs/kernel/uimage.nix +++ b/pkgs/kernel/uimage.nix @@ -20,6 +20,7 @@ in { , extraName ? "" # e.g. socFamily , loadAddress , imageFormat +, alignment ? null , dtb ? null } : stdenv.mkDerivation { name = "kernel.image"; @@ -70,7 +71,7 @@ in { }; }; _VARS - mkimage -f mkimage.its kernel.uimage + mkimage -f mkimage.its ${lib.optionalString (alignment != null) "-B 0x${lib.toHexString alignment}"} kernel.uimage mkimage -l kernel.uimage ''; From 3dc58de0eb343d058c082388069bc5659a610216 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sat, 17 Feb 2024 02:16:57 +0100 Subject: [PATCH 05/23] modules/outputs: expose `commandLineDtbNode` option We allow `bootargs` and `bootargs-override` for now only. Signed-off-by: Raito Bezarius --- modules/base.nix | 5 +++++ modules/outputs.nix | 1 + 2 files changed, 6 insertions(+) diff --git a/modules/base.nix b/modules/base.nix index 352fa82..f64c817 100644 --- a/modules/base.nix +++ b/modules/base.nix @@ -58,6 +58,11 @@ in { default = []; description = "Kernel command line"; }; + commandLineDtbNode = mkOption { + type = types.enum [ "bootargs" "bootargs-override" ]; + default = "bootargs"; + description = "Kernel command line's devicetree node"; + }; imageFormat = mkOption { type = types.enum ["fit" "uimage"]; default = "uimage"; diff --git a/modules/outputs.nix b/modules/outputs.nix index d7861d9..84199a2 100644 --- a/modules/outputs.nix +++ b/modules/outputs.nix @@ -111,6 +111,7 @@ in }; uimage = liminix.builders.uimage { commandLine = concatStringsSep " " config.boot.commandLine; + inherit (config.boot) commandLineDtbNode; inherit (config.hardware) loadAddress entryPoint alignment; inherit (config.boot) imageFormat; inherit (o) kernel dtb; From e9ab8d71837c6b16295578dbcbeb7375ea31fb69 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 4 Dec 2023 14:08:13 +0100 Subject: [PATCH 06/23] modules/outputs/ubivolume: introduce ubinization It creates an UBI image based on an UBI volume configuration. For now, it creates only an empty rootfs. --- modules/all-modules.nix | 2 + modules/outputs/ubivolume.nix | 91 +++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 modules/outputs/ubivolume.nix diff --git a/modules/all-modules.nix b/modules/all-modules.nix index 6b432ce..f6a8908 100644 --- a/modules/all-modules.nix +++ b/modules/all-modules.nix @@ -31,6 +31,8 @@ ./ssh ./outputs/tftpboot.nix ./outputs/ubifs.nix + ./ubifs.nix + ./ubinize.nix ./users.nix ./vlan ./watchdog diff --git a/modules/outputs/ubivolume.nix b/modules/outputs/ubivolume.nix new file mode 100644 index 0000000..45aa889 --- /dev/null +++ b/modules/outputs/ubivolume.nix @@ -0,0 +1,91 @@ +{ + config +, pkgs +, lib +, ... +}: +let + inherit (pkgs) liminix; + inherit (lib) mkIf mkOption types concatStringsSep optionalString; +in + { + imports = [ + ./initramfs.nix + ./ubifs.nix + ]; + + options.hardware.ubi = { + minIOSize = mkOption { type = types.str; }; + eraseBlockSize = mkOption { type = types.str; }; # LEB + maxLEBcount = mkOption { type = types.str; }; # LEB + }; + + config = mkIf (config.rootfsType == "ubifs") { + kernel.config = { + MTD_UBI="y"; + + UBIFS_FS = "y"; + UBIFS_FS_SECURITY = "n"; + }; + boot.initramfs.enable = true; + + system.outputs.rootfs = + let + inherit (pkgs.pkgsBuildBuild) runCommand; + ubiVolume = ({ name, volumeId, image, flags ? [] }: + '' + [${name}] + mode=ubi + vol_id=${toString volumeId} + vol_type=dynamic + vol_name=${name} + vol_alignment=1 + ${optionalString (image != null) '' + image=${image} + ''} + ${optionalString (image == null) '' + vol_size=1MiB + ''} + ${optionalString (flags != []) '' + vol_flags=${concatStringsSep "," flags} + ''} + ''); + + ubiImage = (volumes: + let + ubinizeConfig = pkgs.writeText "ubinize.conf" (concatStringsSep "\n" volumes); + inherit (pkgs.pkgsBuildBuild) mtdutils; + in + runCommand "ubinize" { + depsBuildBuild = [ mtdutils ]; + # block size := 128kb + # page size := 2048 + # ubninize opts := -E 5 + } '' + ubinize -Q "$SOURCE_DATE_EPOCH" -o $out \ + -p ${config.hardware.ubi.physicalEraseBlockSize} -m ${config.hardware.ubi.minIOSize} \ + -e ${config.hardware.ubi.logicalEraseBlockSize} \ + ${ubinizeConfig} + ''); + + ubiDisk = ({ initramfs }: + let + initramfsUbi = ubiVolume { + name = "rootfs"; + volumeId = 0; + image = initramfs; + flags = [ "autoresize" ]; + }; + in + ubiImage [ + initramfsUbi + ]); + + disk = ubiDisk { + initramfs = config.system.outputs.rootubifs; # liminix.builders.squashfs config.filesystem.contents; # # assert this is a proper FIT. + }; + + in + disk; + }; +} From 63007859c26c6c1d7210cab5b04f88b5e2d62243 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sat, 17 Feb 2024 02:21:50 +0100 Subject: [PATCH 07/23] modules/outputs/zyxel-nwa-fit: init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zyxel "firmware" format is just… a FIT with some metadata on the models. This FIT is like this: -------------------------- uImage FIT header -------------------------- Linux kernel -------------------------- FDT DTB -------------------------- Padding so that this makes 8192kb [1] -------------------------- UBI volume as a root filesystem -------------------------- We just reproduce this in a very brutal and naive way. In the future, this seems worth to generalize and modularize this idea so that zyxel-nwa-fit is just an instance of a more general output. [1]: https://git.openwrt.org/?p=openwrt/openwrt.git;a=blob;f=target/linux/ramips/image/mt7621.mk;h=ab1b829ba0086cb9fc9ca8cbbf3cbc14735034d6;hb=refs/heads/main#l3097 Signed-off-by: Raito Bezarius --- modules/outputs/zyxel-nwa-fit.nix | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 modules/outputs/zyxel-nwa-fit.nix diff --git a/modules/outputs/zyxel-nwa-fit.nix b/modules/outputs/zyxel-nwa-fit.nix new file mode 100644 index 0000000..d6f894e --- /dev/null +++ b/modules/outputs/zyxel-nwa-fit.nix @@ -0,0 +1,71 @@ +{ + config +, pkgs +, lib +, ... +}: +let + inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep; + models = "6b e1 6f e1 ff ff ff ff ff ff"; +in { + options.system.outputs = { + zyxel-nwa-fit = mkOption { + type = types.package; + description = '' +zyxel-nwa-fit +************* + +This output provides a FIT image for Zyxel NWA series +containing a kernel image and an UBIFS rootfs. + +It can usually be used as a factory image to install Liminix +on a system with pre-existing firmware and OS. + ''; + }; + }; + + imports = [ + ./ubivolume.nix + ]; + + config = mkIf (config.rootfsType == "ubifs") { + + system.outputs.zyxel-nwa-fit = + let + o = config.system.outputs; + # 8129kb padding. + paddedKernel = pkgs.runCommand "padded-kernel" {} '' + cp --no-preserve=mode ${o.uimage} $out + dd if=/dev/zero of=$out bs=1 count=1 seek=8388607 + ''; + firmwareImage = pkgs.runCommand "firmware-image" {} '' + cat ${paddedKernel} ${o.rootfs} > $out + ''; + dts = pkgs.writeText "image.its" '' + /dts-v1/; + + / { + description = "Zyxel FIT (Flattened Image Tree)"; + compat-models = [${models}]; + #address-cells = <1>; + + images { + firmware { + data = /incbin/("${firmwareImage}"); + type = "firmware"; + compression = "none"; + hash@1 { + algo = "sha1"; + }; + }; + }; + }; + ''; + in + pkgs.runCommand "zyxel-nwa-fit" { + nativeBuildInputs = [ pkgs.pkgsBuildBuild.ubootTools pkgs.pkgsBuildBuild.dtc ]; + } '' + mkimage -f ${dts} $out + ''; + }; +} From 019fef6929007c7ab0bec2912190afe2a24348f3 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 4 Dec 2023 16:04:24 +0100 Subject: [PATCH 08/23] zyxel-bootconfig: init at no version This tool is useful for manipulating the A/B boot status of the image. --- pkgs/default.nix | 1 + pkgs/zyxel-bootconfig/default.nix | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 pkgs/zyxel-bootconfig/default.nix diff --git a/pkgs/default.nix b/pkgs/default.nix index 558e266..e2257b6 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -79,6 +79,7 @@ in { lzma = callPackage ./lzma {}; mac80211 = callPackage ./mac80211 {}; + zyxel-bootconfig = callPackage ./zyxel-bootconfig {}; min-collect-garbage = callPackage ./min-collect-garbage {}; min-copy-closure = callPackage ./min-copy-closure {}; netlink-lua = callPackage ./netlink-lua {}; diff --git a/pkgs/zyxel-bootconfig/default.nix b/pkgs/zyxel-bootconfig/default.nix new file mode 100644 index 0000000..ead47e6 --- /dev/null +++ b/pkgs/zyxel-bootconfig/default.nix @@ -0,0 +1,13 @@ +{ + stdenv +, openwrt +}: +stdenv.mkDerivation { + name = "zyxel-bootconfig"; + inherit (openwrt) src; + sourceRoot = "openwrt-source/package/utils/zyxel-bootconfig/src"; + installPhase = '' + mkdir -p $out/bin + install -Dm644 zyxel-bootconfig $out/bin/zyxel-bootconfig + ''; +} From 13f1bb9f5284e1d9c0bf4ffd9b8a13852a0745ff Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sun, 3 Dec 2023 01:23:17 +0100 Subject: [PATCH 09/23] devices/zyxel-nwa50ax: init --- devices/zyxel-nwa50ax/default.nix | 306 ++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 devices/zyxel-nwa50ax/default.nix diff --git a/devices/zyxel-nwa50ax/default.nix b/devices/zyxel-nwa50ax/default.nix new file mode 100644 index 0000000..7c5e09b --- /dev/null +++ b/devices/zyxel-nwa50ax/default.nix @@ -0,0 +1,306 @@ +{ + system = { + crossSystem = { + config = "mipsel-unknown-linux-musl"; + gcc = { + abi = "32"; + arch = "mips32"; # mips32r2? + }; + }; + }; + + description = '' + Zyxel NWA50AX + ******************** + + Zyxel NWA50AX is quite close to the GL-MT300N-v2 "Mango" device, but it is based on the MT7621 + chipset instead of the MT7628. + + Installation + ============ + + Wow, this device is a handful. + + The stock vendor firmware is a downstream fork of U-Boot (insert link to source code) + with restricted boot commands. Fortunately, OpenWrt folks figured out trivial command injections, + so you can use most of the OpenWrt commands without trouble by just command injecting + atns, atna or atnf, e.g. atns "; $real_command". + + From factory web UI, this has not been tested yet. + From serial, you have two choices: + + - boot from an existing Liminix system, e.g. TFTPBOOT image. + - boot from an OpenWrt system, i.e. follow OpenWrt steps. + + Once you are in a Linux system, understand that this device has A/B boot. + + OpenWrt provides you with `zyxel-bootconfig` to set/unset the image status and choice. + The kernel is booted with `bootImage=` which tells you which slot are you on. + + You should find yourself with 10ish MTD partitions, the most interesting ones are two: + + - firmware: 40MB + - firmware_1: 40MB + + In the current setup, they are split further into kernel (8MB) and ubi (32MB). + + You will write the FIT uImage in the kernel MTD partition directly, via `mtd write kernel.uimage /dev/mtd4` + (if `/dev/mtd4` is the kernel MTD partition) or `flashcp` can be used similarly. + + Then, you will install the UBI image, via `ubiformat -f ubi.image /dev/mtd5` (if `/dev/mtd4` was your kernel MTD partition, 5 must be the UBI). + + Once you are done, you will have to reboot and modify your bootargs in U-Boot + because they are currently overridden. + + It is enough to do: + atns "; setenv bootargs 'liminix console=ttyS0,115200 panic=10 oops=panic init=/bin/init loglevel=8 fw_devlink=off ubi.mtd=ubi root=ubi0:rootfs rootfstype=ubifs'" + atns "; saveenv" + + Once you are done, you can enjoy booting on slot A unattended for now. To make use of the A/B feature, this is a TODO :). + Upgrades are TODO too. + + Vendor web page: https://www.zyxel.com/fr/fr/products/wireless/ax1800-wifi-6-dual-radio-nebulaflex-access-point-nwa50ax + + OpenWrt web page: https://openwrt.org/inbox/toh/zyxel/nwa50ax + OpenWrt tech data: https://openwrt.org/toh/hwdata/zyxel/zyxel_nwa50ax + + ''; + + module = { pkgs, config, lib, lim, ...}: + let + inherit (pkgs.liminix.networking) interface; + inherit (pkgs.liminix.services) oneshot; + inherit (pkgs.pseudofile) dir symlink; + inherit (pkgs) openwrt; + + mac80211 = pkgs.mac80211.override { + drivers = [ "mt7915e" ]; + klibBuild = config.system.outputs.kernel.modulesupport; + }; + wlan_firmware = pkgs.fetchurl { + url = "https://github.com/openwrt/mt76/raw/2afc7285f75dca5a0583fd917285bf33f1429cc6/firmware/mt7915_wa.bin"; + hash = "sha256-wooyefzb0i8640+lwq3vNhcBXRFCtGuo+jiL7afZaKA="; + }; + wlan_firmware' = pkgs.fetchurl { + url = "https://github.com/openwrt/mt76/raw/2afc7285f75dca5a0583fd917285bf33f1429cc6/firmware/mt7915_wm.bin"; + hash = "sha256-k62nQewRuKjBLd5R3RxU4F74YKnQx5zr6gqMMImqVQw="; + }; + wlan_firmware'' = pkgs.fetchurl { + url = "https://github.com/openwrt/mt76/raw/2afc7285f75dca5a0583fd917285bf33f1429cc6/firmware/mt7915_rom_patch.bin"; + hash = "sha256-ifriAjWzFACrxVWCANZpUaEZgB/0pdbhnTVQytx6ddg="; + }; + in { + imports = [ + ../../modules/arch/mipsel.nix + ../../modules/outputs/tftpboot.nix + ../../modules/outputs/zyxel-nwa-fit.nix + ]; + + filesystem = dir { + lib = dir { + firmware = dir { + mediatek = dir { + "mt7915_wa.bin" = symlink wlan_firmware; + "mt7915_wm.bin" = symlink wlan_firmware'; + "mt7915_rom_patch.bin" = symlink wlan_firmware''; + }; + }; + }; + }; + + rootfsType = "ubifs"; + hardware = { + # Taken from OpenWRT + # root@OpenWrt:/# ubinfo /dev/ubi0 + # ubi0 + # Volumes count: 2 + # Logical eraseblock size: 126976 bytes, 124.0 KiB + # Total amount of logical eraseblocks: 256 (32505856 bytes, 31.0 MiB) + # Amount of available logical eraseblocks: 0 (0 bytes) + # Maximum count of volumes 128 + # Count of bad physical eraseblocks: 0 + # Count of reserved physical eraseblocks: 19 + # Current maximum erase counter value: 2 + # Minimum input/output unit size: 2048 bytes + # Character device major/minor: 250:0 + # Present volumes: 0, 1 + ubi = { + minIOSize = "2048"; + logicalEraseBlockSize = "126976"; + physicalEraseBlockSize = "128KiB"; + maxLEBcount = "256"; + }; + + # This is a FIT containing a kernel padded and + # a UBI volume rootfs. + defaultOutput = "zyxel-nwa-fit"; + loadAddress = lim.parseInt "0x80001000"; + entryPoint = lim.parseInt "0x80001000"; + # Aligned on 2kb. + alignment = 2048; + + flash = { + address = lim.parseInt "0xbc050000"; + size = lim.parseInt "0xfb0000"; + eraseBlockSize = 65536; + }; + rootDevice = "ubi0:rootfs"; + + dts = { + src = "${openwrt.src}/target/linux/ramips/dts/mt7621_zyxel_nwa50ax.dts"; + includes = [ + "${openwrt.src}/target/linux/ramips/dts" + ]; + }; + networkInterfaces = + let + inherit (config.system.service.network) link; + in { + eth = link.build { ifname = "eth0"; }; + lan = link.build { ifname = "lan"; }; + wlan0 = link.build { + ifname = "wlan0"; + dependencies = [ mac80211 ]; + }; + wlan1 = link.build { + ifname = "wlan1"; + dependencies = [ mac80211 ]; + }; + }; + }; + boot = { + # Critical because NWA50AX will extend your cmdline with the image number booted. + # and some bootloader version. + # You don't want to find yourself being overridden. + commandLineDtbNode = "bootargs-override"; + + imageFormat = "fit"; + tftp = { + # 5MB is nice. + freeSpaceBytes = 5 * 1024 * 1024; + loadAddress = lim.parseInt "0x2000000"; + }; + }; + + # DEVICE_VENDOR := ZyXEL + # KERNEL_SIZE := 8192k + # DEVICE_PACKAGES := kmod-mt7915-firmware zyxel-bootconfig + # KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + # IMAGES += factory.bin ramboot-factory.bin + # IMAGE/factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | zyxel-nwa-fit + # IMAGE/ramboot-factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi + + kernel = { + src = pkgs.fetchurl { + name = "linux.tar.gz"; + url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.gz"; + hash = "sha256-PkdzUKZ0IpBiWe/RS70J76JKnBFzRblWcKlaIFNxnHQ="; + }; + extraPatchPhase = '' + ${openwrt.applyPatches.ramips} + + ''; + config = { + + RALINK = "y"; + PCI = "y"; + PHY_MT7621_PCI = "y"; + PCIE_MT7621 = "y"; + SOC_MT7621 = "y"; + CLK_MT7621 = "y"; + CLOCKSOURCE_WATCHDOG = "y"; + + SERIAL_8250_CONSOLE = "y"; + SERIAL_8250 = "y"; + SERIAL_CORE_CONSOLE = "y"; + SERIAL_OF_PLATFORM = "y"; + SERIAL_8250_NR_UARTS = "3"; + SERIAL_8250_RUNTIME_UARTS = "3"; + SERIAL_MCTRL_GPIO = "y"; + + CONSOLE_LOGLEVEL_DEFAULT = "8"; + CONSOLE_LOGLEVEL_QUIET = "4"; + + # MTD_UBI_BEB_LIMIT = "20"; + # MTD_UBI_WL_THRESHOLD = "4096"; + + MTD = "y"; + MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev + MTD_RAW_NAND = "y"; + MTD_NAND_MT7621 = "y"; + MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table + MTD_NAND_ECC_SW_HAMMING= "y"; + MTD_SPI_NAND= "y"; + MTD_OF_PARTS = "y"; + MTD_NAND_CORE= "y"; + MTD_SPLIT_FIRMWARE= "y"; + MTD_SPLIT_FIT_FW= "y"; + + PINCTRL = "y"; + PINCTRL_MT7621 = "y"; + + I2C = "y"; + I2C_MT7621 = "y"; + + SPI = "y"; + MTD_SPI_NOR = "y"; + SPI_MT7621 = "y"; + SPI_MASTER = "y"; + SPI_MEM = "y"; + + REGULATOR = "y"; + REGULATOR_FIXED_VOLTAGE = "y"; + RESET_CONTROLLER = "y"; + POWER_RESET = "y"; + POWER_RESET_GPIO = "y"; + POWER_SUPPLY = "y"; + LED_TRIGGER_PHY = "y"; + + PCI_DISABLE_COMMON_QUIRKS = "y"; + PCI_DOMAINS = "y"; + PCI_DOMAINS_GENERIC = "y"; + PCI_DRIVERS_GENERIC = "y"; + PCS_MTK_LYNXI = "y"; + + SOC_BUS = "y"; + + NET = "y"; + ETHERNET = "y"; + WLAN = "y"; + + PHYLIB = "y"; + AT803X_PHY = "y"; + FIXED_PHY = "y"; + GENERIC_PHY = "y"; + NET_DSA = "y"; + NET_DSA_MT7530 = "y"; + NET_DSA_MT7530_MDIO = "y"; + NET_DSA_TAG_MTK = "y"; + NET_MEDIATEK_SOC = "y"; + NET_SWITCHDEV = "y"; + NET_VENDOR_MEDIATEK = "y"; + + SWPHY = "y"; + + GPIOLIB = "y"; + GPIO_MT7621 = "y"; + OF_GPIO = "y"; + + EARLY_PRINTK = "y"; + + NEW_LEDS = "y"; + LEDS_TRIGGERS = "y"; + LEDS_CLASS = "y"; # required by rt2x00lib + LEDS_CLASS_MULTICOLOR = "y"; + LEDS_BRIGHTNESS_HW_CHANGED = "y"; + + PRINTK_TIME = "y"; + } // lib.optionalAttrs (config.system.service ? vlan) { + SWCONFIG = "y"; + } // lib.optionalAttrs (config.system.service ? watchdog) { + RALINK_WDT = "y"; # watchdog + MT7621_WDT = "y"; # or it might be this one + }; + }; + }; +} From cdafff2095421d4c3b6c04de08eb7efc58864570 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sat, 17 Feb 2024 04:34:30 +0100 Subject: [PATCH 10/23] examples/nwa50ax-ap: init This is a quite comprehensive example using maximally the hardware available to reach nice performance. In the future, I will even add RADIUS examples. Signed-off-by: Raito Bezarius --- examples/nwa50ax-ap.nix | 107 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 examples/nwa50ax-ap.nix diff --git a/examples/nwa50ax-ap.nix b/examples/nwa50ax-ap.nix new file mode 100644 index 0000000..e33abad --- /dev/null +++ b/examples/nwa50ax-ap.nix @@ -0,0 +1,107 @@ +{ config, pkgs, ... } : +let + inherit (pkgs.liminix.services) oneshot longrun bundle target; + inherit (pkgs) writeText; + svc = config.system.service; + secrets-1 = { + ssid = "Zyxel 2G (N)"; + wpa_passphrase = "diamond dogs"; + }; + secrets-2 = { + ssid = "Zyxel 5G (AX)"; + wpa_passphrase = "diamond dogs"; + }; + baseParams = { + country_code = "FR"; + hw_mode = "g"; + channel = 6; + wmm_enabled = 1; + ieee80211n = 1; + ht_capab = "[LDPC][GF][HT40-][HT40+][SHORT-GI-40][MAX-AMSDU-7935][TX-STBC]"; + auth_algs = 1; + wpa = 2; + wpa_key_mgmt = "WPA-PSK"; + wpa_pairwise = "TKIP CCMP"; + rsn_pairwise = "CCMP"; + }; + + modernParams = { + hw_mode = "a"; + he_su_beamformer = 1; + he_su_beamformee = 1; + he_mu_beamformer = 1; + preamble = 1; + # Allow radar detection. + ieee80211d = 1; + ieee80211h = 1; + ieee80211ac = 1; + ieee80211ax = 1; + vht_capab = "[MAX-MPDU-7991][SU-BEAMFORMEE][SU-BEAMFORMER][RXLDPC][SHORT-GI-80][MAX-A-MPDU-LEN-EXP3][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN][TX-STBC-2BY1][RX-STBC-1][MU-BEAMFORMER]"; + vht_oper_chwidth = 1; + he_oper_chwidth = 1; + channel = 36; + vht_oper_centr_freq_seg0_idx = 42; + he_oper_centr_freq_seg0_idx = 42; + require_vht = 1; + }; + mkWifiSta = params: interface: secrets: svc.hostapd.build { + inherit interface; + params = params // { + inherit (secrets) ssid wpa_passphrase; + }; + }; +in rec { + imports = [ + ../modules/wlan.nix + ../modules/network + ../modules/hostapd + ../modules/ssh + ../modules/ntp + ../modules/vlan + ]; + + hostname = "zyxel"; + + users.root = { + # EDIT: choose a root password and then use + # "mkpasswd -m sha512crypt" to determine the hash. + # It should start wirh $6$. + passwd = "$y$j9T$f8GhLiqYmr3lc58eKhgyD0$z7P/7S9u.kq/cANZExxhS98bze/6i7aBxU6tbl7RMi."; + openssh.authorizedKeys.keys = [ + # EDIT: you can add your ssh pubkey here + # "ssh-rsa AAAAB3NzaC1....H6hKd user@example.com"; + ]; + }; + + + services.dhcpv4 = + let iface = config.hardware.networkInterfaces.lan; + in svc.network.dhcp.client.build { interface = iface; }; + + services.defaultroute4 = svc.network.route.build { + via = "$(output ${services.dhcpv4} address)"; + target = "default"; + dependencies = [ services.dhcpv4 ]; + }; + + services.packet_forwarding = svc.network.forward.build { }; + services.sshd = svc.ssh.build { + allowRoot = true; + }; + + services.ntp = config.system.service.ntp.build { + pools = { "pool.ntp.org" = ["iburst"] ; }; + }; + + boot.tftp = { + serverip = "192.0.2.10"; + ipaddr = "192.0.2.12"; + }; + + # wlan0 is the 2.4GHz interface. + services.hostap-1 = mkWifiSta baseParams config.hardware.networkInterfaces.wlan0 secrets-1; + # wlan1 is the 5GHz interface, e.g. AX capable. + services.hostap-2 = mkWifiSta (baseParams // modernParams) config.hardware.networkInterfaces.wlan1 secrets-2; + + defaultProfile.packages = with pkgs; [ zyxel-bootconfig iw ]; +} From c14b2f6356b7718742cc66f0e5b494288627ef54 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sun, 18 Feb 2024 20:30:07 +0100 Subject: [PATCH 11/23] modules/busybox: add `dhcprelay` This enables to run a DHCP relay from multiple interfaces. Signed-off-by: Raito Bezarius --- modules/busybox.nix | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/modules/busybox.nix b/modules/busybox.nix index 2f21f11..718cafd 100644 --- a/modules/busybox.nix +++ b/modules/busybox.nix @@ -32,23 +32,21 @@ let (a: symlink "${busybox}/bin/busybox"); minimalApplets = [ # this is probably less minimal than it could be - "arch" "ash" "base64" "basename" "bc" "brctl" "bunzip2" "bzcat" - "bzip2" "cal" "cat" "chattr" "chgrp" "chmod" "chown" "chpst" - "chroot" "clear" "cmp" "comm" "cp" "cpio" "cut" "date" "dd" "df" - "dirname" "dmesg" "du" "echo" "egrep" "env" "expand" "expr" - "false" "fdisk" "fgrep" "find" "free" "fuser" "grep" "gunzip" - "gzip" "head" "hexdump" "hostname" "hwclock" "ifconfig" "ip" - "ipaddr" "iplink" "ipneigh" "iproute" "iprule" "kill" "killall" - "killall5" "less" "ln" "ls" "lsattr" "lsof" "md5sum" "mkdir" - "mknod" "mktemp" "mount" "mv" "nc" "netstat" "nohup" "od" "pgrep" - "pidof" "ping" "ping6" "pkill" "pmap" "printenv" "printf" "ps" - "pwd" "readlink" "realpath" "reset" "rm" "rmdir" "route" "sed" - "seq" "setsid" "sha1sum" "sha256sum" "sha512sum" "sleep" "sort" - "stat" "strings" "stty" "su" "sum" "swapoff" "swapon" "sync" - "tail" "tee" "test" "time" "touch" "tr" "traceroute" "traceroute6" - "true" "truncate" "tty" "udhcpc" "umount" "uname" - "unexpand" "uniq" "unlink" "unlzma" "unxz" "unzip" "uptime" - "watch" "wc" "whoami" "xargs" "xxd" "xz" "xzcat" "yes" "zcat" + "arch" "ash" "base64" "basename" "bc" "brctl" "bunzip2" "bzcat" "bzip2" + "cal" "cat" "chattr" "chgrp" "chmod" "chown" "chpst" "chroot" "clear" "cmp" + "comm" "cp" "cpio" "cut" "date" "dhcprelay" "dd" "df" "dirname" "dmesg" + "du" "echo" "egrep" "env" "expand" "expr" "false" "fdisk" "fgrep" "find" + "free" "fuser" "grep" "gunzip" "gzip" "head" "hexdump" "hostname" "hwclock" + "ifconfig" "ip" "ipaddr" "iplink" "ipneigh" "iproute" "iprule" "kill" + "killall" "killall5" "less" "ln" "ls" "lsattr" "lsof" "md5sum" "mkdir" + "mknod" "mktemp" "mount" "mv" "nc" "netstat" "nohup" "od" "pgrep" "pidof" + "ping" "ping6" "pkill" "pmap" "printenv" "printf" "ps" "pwd" "readlink" + "realpath" "reset" "rm" "rmdir" "route" "sed" "seq" "setsid" "sha1sum" + "sha256sum" "sha512sum" "sleep" "sort" "stat" "strings" "stty" "su" "sum" + "swapoff" "swapon" "sync" "tail" "tee" "test" "time" "touch" "tr" + "traceroute" "traceroute6" "true" "truncate" "tty" "udhcpc" "umount" + "uname" "unexpand" "uniq" "unlink" "unlzma" "unxz" "unzip" "uptime" "watch" + "wc" "whoami" "xargs" "xxd" "xz" "xzcat" "yes" "zcat" ]; in { options = { From 422f3edab1136871f79b8579643fe0fb922fac3a Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sun, 18 Feb 2024 22:35:27 +0100 Subject: [PATCH 12/23] modules/zyxel-dual-image: init This adds a simple boot blessing module, to be used, with the Zyxel NWA50AX. There's a lot of elephant in the rooms: how do you upgrade kernel, etc. Signed-off-by: Raito Bezarius --- devices/zyxel-nwa50ax/default.nix | 11 +++++ modules/zyxel-dual-image/default.nix | 60 ++++++++++++++++++++++++++++ modules/zyxel-dual-image/service.nix | 33 +++++++++++++++ pkgs/zyxel-bootconfig/default.nix | 3 ++ 4 files changed, 107 insertions(+) create mode 100644 modules/zyxel-dual-image/default.nix create mode 100644 modules/zyxel-dual-image/service.nix diff --git a/devices/zyxel-nwa50ax/default.nix b/devices/zyxel-nwa50ax/default.nix index 7c5e09b..a6c77c6 100644 --- a/devices/zyxel-nwa50ax/default.nix +++ b/devices/zyxel-nwa50ax/default.nix @@ -94,6 +94,7 @@ ../../modules/arch/mipsel.nix ../../modules/outputs/tftpboot.nix ../../modules/outputs/zyxel-nwa-fit.nix + ../../modules/zyxel-dual-image ]; filesystem = dir { @@ -168,6 +169,7 @@ }; }; }; + boot = { # Critical because NWA50AX will extend your cmdline with the image number booted. # and some bootloader version. @@ -182,6 +184,15 @@ }; }; + # Dual image management service in userspace. + services.zyxel-dual-image = config.boot.zyxel-dual-image.build { + ensureActiveImage = "primary"; + # TODO: use mtd names rather… + primaryMtdPartition = "/dev/mtd3"; + secondaryMtdPartition = "/dev/mtd6"; + bootConfigurationMtdPartition = "/dev/mtd10"; + }; + # DEVICE_VENDOR := ZyXEL # KERNEL_SIZE := 8192k # DEVICE_PACKAGES := kmod-mt7915-firmware zyxel-bootconfig diff --git a/modules/zyxel-dual-image/default.nix b/modules/zyxel-dual-image/default.nix new file mode 100644 index 0000000..91ed48e --- /dev/null +++ b/modules/zyxel-dual-image/default.nix @@ -0,0 +1,60 @@ +## Boot blessing via Zyxel +## ======================= +## Boot blessing is the process to bless a particular boot configuration +## It is commonly encountered in devices with redundant partitions +## for automatic recovery of broken upgrades. +## This is also known as A/B schemas, where A represents the primary partition +## and B the secondary partition used for recovery. +## To use boot blessing on Liminix, you need to have the support of +## your bootloader to help you boot on the secondary partition in case of +## failure on the primary partition. The exact details are specifics to your device. +## See the Zyxel NWA50AX for an example. +## TODO: generalize this module. +{ config, lib, pkgs, ... }: +let + inherit (lib) mkOption types; + inherit (pkgs) liminix; +in +{ + options.boot.zyxel-dual-image = mkOption { + type = liminix.lib.types.serviceDefn; + }; + + config.boot.zyxel-dual-image = liminix.callService ./service.nix { + ensureActiveImage = mkOption { + type = types.enum [ "primary" "secondary" ]; + default = "primary"; + description = ''At boot, ensure that the active image is the one specified. + + If you are already on a broken image, you need to manually boot + into the right image via `atgo ` in U-Boot. + ''; + }; + + kernelCommandLineSource = mkOption { + type = types.enum [ "/proc/cmdline" "/proc/device-tree/chosen/bootargs" ]; + default = "/proc/device-tree/chosen/bootargs"; + description = ''Kernel command line arguments source file. + On MIPS, Liminix embeds the kernel command line in /proc/device-tree/chosen/bootargs-override. + + In this instance, it does not get concatenated with `/proc/cmdline`. + Therefore you may prefer to source it from another place, like `/proc/device-tree/chosen/bootargs`. + ''; + }; + + primaryMtdPartition = mkOption { + type = types.str; + description = "Primary MTD partition device node, i.e. for image 0."; + }; + + secondaryMtdPartition = mkOption { + type = types.str; + description = "Secondary MTD partition device node, i.e. for image 1."; + }; + + bootConfigurationMtdPartition = mkOption { + type = types.str; + description = "Boot configuration MTD partition device node."; + }; + }; +} diff --git a/modules/zyxel-dual-image/service.nix b/modules/zyxel-dual-image/service.nix new file mode 100644 index 0000000..3edd642 --- /dev/null +++ b/modules/zyxel-dual-image/service.nix @@ -0,0 +1,33 @@ +{ + liminix +, lib +, zyxel-bootconfig +}: +{ ensureActiveImage, primaryMtdPartition, secondaryMtdPartition, bootConfigurationMtdPartition, kernelCommandLineSource }: +let + inherit (liminix.services) oneshot; + activeImageIndex = if ensureActiveImage == "primary" then 0 else 1; +in oneshot { + name = "zyxel-boot-configure"; + up = '' + set -- $(cat /proc/device-tree/chosen/bootargs) + for x in "$@"; do + case "$x" in + bootImage=*) + BOOT_IMAGE="''${x#bootImage=}" + echo "Current boot image is $BOOT_IMAGE." + ;; + esac + done + + if test -z "$BOOT_IMAGE"; then + echo "No valid image was provided in the kernel command line." + exit 1 + else + ${lib.getExe zyxel-bootconfig} ${bootConfigurationMtdPartition} set-image-status "$BOOT_IMAGE" valid + ${lib.getExe zyxel-bootconfig} ${bootConfigurationMtdPartition} set-active-image ${toString activeImageIndex} + + echo "Active image is now ${ensureActiveImage}" + fi + ''; +} diff --git a/pkgs/zyxel-bootconfig/default.nix b/pkgs/zyxel-bootconfig/default.nix index ead47e6..ce148ae 100644 --- a/pkgs/zyxel-bootconfig/default.nix +++ b/pkgs/zyxel-bootconfig/default.nix @@ -10,4 +10,7 @@ stdenv.mkDerivation { mkdir -p $out/bin install -Dm644 zyxel-bootconfig $out/bin/zyxel-bootconfig ''; + meta = { + mainProgram = "zyxel-bootconfig"; + }; } From 3c70a0d037c7e85380bd4b8e2aea1d147808012c Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 19 Feb 2024 01:20:01 +0100 Subject: [PATCH 13/23] devices/zyxel-nwa50ax: ensure bridge is always available Signed-off-by: Raito Bezarius --- devices/zyxel-nwa50ax/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/devices/zyxel-nwa50ax/default.nix b/devices/zyxel-nwa50ax/default.nix index a6c77c6..a21b125 100644 --- a/devices/zyxel-nwa50ax/default.nix +++ b/devices/zyxel-nwa50ax/default.nix @@ -91,6 +91,9 @@ }; in { imports = [ + # We include it to ensure the bridge functionality + # is available on the target kernel. + ../../modules/bridge ../../modules/arch/mipsel.nix ../../modules/outputs/tftpboot.nix ../../modules/outputs/zyxel-nwa-fit.nix From 0e81953b670e3806e8f07c5ab02d12ecb8c59b46 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 19 Feb 2024 01:20:19 +0100 Subject: [PATCH 14/23] devices/zyxel-nwa50ax: cleanup of `flash` attribute and `rootDevice` Signed-off-by: Raito Bezarius --- devices/zyxel-nwa50ax/default.nix | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/devices/zyxel-nwa50ax/default.nix b/devices/zyxel-nwa50ax/default.nix index a21b125..a5f7dff 100644 --- a/devices/zyxel-nwa50ax/default.nix +++ b/devices/zyxel-nwa50ax/default.nix @@ -138,17 +138,13 @@ # This is a FIT containing a kernel padded and # a UBI volume rootfs. defaultOutput = "zyxel-nwa-fit"; + loadAddress = lim.parseInt "0x80001000"; entryPoint = lim.parseInt "0x80001000"; # Aligned on 2kb. alignment = 2048; - flash = { - address = lim.parseInt "0xbc050000"; - size = lim.parseInt "0xfb0000"; - eraseBlockSize = 65536; - }; - rootDevice = "ubi0:rootfs"; + rootDevice = "ubi:rootfs"; dts = { src = "${openwrt.src}/target/linux/ramips/dts/mt7621_zyxel_nwa50ax.dts"; From 3ec29dc1b9b871fe47a2841b92267da95756851b Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 19 Feb 2024 01:20:31 +0100 Subject: [PATCH 15/23] examples/nwa50ax-ap: ensure `mtdutils` is available for further flashing Signed-off-by: Raito Bezarius --- examples/nwa50ax-ap.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/nwa50ax-ap.nix b/examples/nwa50ax-ap.nix index e33abad..e121d8a 100644 --- a/examples/nwa50ax-ap.nix +++ b/examples/nwa50ax-ap.nix @@ -73,7 +73,6 @@ in rec { ]; }; - services.dhcpv4 = let iface = config.hardware.networkInterfaces.lan; in svc.network.dhcp.client.build { interface = iface; }; @@ -103,5 +102,5 @@ in rec { # wlan1 is the 5GHz interface, e.g. AX capable. services.hostap-2 = mkWifiSta (baseParams // modernParams) config.hardware.networkInterfaces.wlan1 secrets-2; - defaultProfile.packages = with pkgs; [ zyxel-bootconfig iw ]; + defaultProfile.packages = with pkgs; [ zyxel-bootconfig iw min-collect-garbage mtdutils ]; } From a893c0dc4c0956f5b9b4db025bfc641362ad95a2 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 19 Feb 2024 01:19:46 +0100 Subject: [PATCH 16/23] devices/zyxel-nwa50ax: use our own more advanced DTB OpenWRT had a DTB for the NWA50AX LEDs that I didn't pick up. Anyway, we need to include our own special DTB for the NWA platform in general to support A/B operations, because OpenWRT original one just mark everything else read-only. Signed-off-by: Raito Bezarius --- devices/zyxel-nwa50ax/default.nix | 5 +- .../mt7621_zyxel_nwa-ax-for-ab.dtsi | 171 ++++++++++++++++++ .../zyxel-nwa50ax/mt7621_zyxel_nwa50ax.dtsi | 56 ++++++ 3 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 devices/zyxel-nwa50ax/mt7621_zyxel_nwa-ax-for-ab.dtsi create mode 100644 devices/zyxel-nwa50ax/mt7621_zyxel_nwa50ax.dtsi diff --git a/devices/zyxel-nwa50ax/default.nix b/devices/zyxel-nwa50ax/default.nix index a5f7dff..468487b 100644 --- a/devices/zyxel-nwa50ax/default.nix +++ b/devices/zyxel-nwa50ax/default.nix @@ -147,8 +147,11 @@ rootDevice = "ubi:rootfs"; dts = { - src = "${openwrt.src}/target/linux/ramips/dts/mt7621_zyxel_nwa50ax.dts"; + # Actually, this is not what we want. + # This DTS is insufficient. + src = ./mt7621_zyxel_nwa50ax.dtsi; includes = [ + "${./.}" "${openwrt.src}/target/linux/ramips/dts" ]; }; diff --git a/devices/zyxel-nwa50ax/mt7621_zyxel_nwa-ax-for-ab.dtsi b/devices/zyxel-nwa50ax/mt7621_zyxel_nwa-ax-for-ab.dtsi new file mode 100644 index 0000000..250bc04 --- /dev/null +++ b/devices/zyxel-nwa50ax/mt7621_zyxel_nwa-ax-for-ab.dtsi @@ -0,0 +1,171 @@ +#include "mt7621.dtsi" + +#include +#include + +/ { + aliases { + label-mac-device = &gmac0; + }; +}; + +&nand { + status = "okay"; + + mediatek,nmbm; + mediatek,bmt-max-ratio = <15>; + mediatek,bmt-max-reserved-blocks = <64>; + mediatek,bmt-remap-range = + <0x0 0x980000>, + <0x2980000 0x7800000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "u-boot-env"; + reg = <0x80000 0x80000>; + read-only; + }; + + factory: partition@100000 { + label = "factory"; + reg = <0x100000 0x80000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + }; + }; + + partition@180000 { + label = "firmware_a"; + reg = <0x180000 0x2800000>; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "kernel_a"; + reg = <0x0 0x800000>; + }; + + partition@400000 { + label = "ubi_a"; + reg = <0x800000 0x2000000>; + }; + }; + + partition@2980000 { + label = "firmware_b"; + reg = <0x2980000 0x2800000>; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "kernel_b"; + reg = <0x0 0x800000>; + }; + + partition@400000 { + label = "ubi_b"; + reg = <0x800000 0x2000000>; + }; + }; + + partition@5180000 { + label = "rootfs_data"; + reg = <0x5180000 0x1400000>; + }; + + partition@6580000 { + label = "logs"; + reg = <0x6580000 0xd00000>; + }; + + partition@7280000 { + label = "vendor-myzyxel"; + reg = <0x7280000 0x480000>; + read-only; + }; + + partition@7700000 { + label = "bootconfig"; + reg = <0x7700000 0x80000>; + }; + + mrd: partition@7780000 { + label = "mrd"; + reg = <0x7780000 0x80000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_mrd_1fff8: macaddr@1fff8 { + reg = <0x1fff8 0x6>; + }; + }; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&pcie1 { + wlan_5g: wifi@0,0 { + reg = <0x0 0 0 0 0>; + compatible = "mediatek,mt76"; + + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; + + /* MAC-Address set in userspace */ + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_mrd_1fff8>; + nvmem-cell-names = "mac-address"; +}; + +&switch0 { + ports { + port@4 { + status = "okay"; + label = "lan"; + }; + }; +}; + +&state_default { + gpio { + groups = "uart3"; + function = "gpio"; + }; +}; diff --git a/devices/zyxel-nwa50ax/mt7621_zyxel_nwa50ax.dtsi b/devices/zyxel-nwa50ax/mt7621_zyxel_nwa50ax.dtsi new file mode 100644 index 0000000..02b6ba4 --- /dev/null +++ b/devices/zyxel-nwa50ax/mt7621_zyxel_nwa50ax.dtsi @@ -0,0 +1,56 @@ +#include "mt7621_zyxel_nwa-ax-for-ab.dtsi" + +#include +#include + +/ { + compatible = "zyxel,nwa50ax", "mediatek,mt7621-soc"; + model = "ZyXEL NWA50AX"; + + aliases { + led-boot = &led_system_green; + led-failsafe = &led_system_red; + led-running = &led_system_green; + led-upgrade = &led_system_red; + }; + + leds { + compatible = "gpio-leds"; + + led_system_red: system_red { + label = "red:system"; + gpios = <&gpio 6 GPIO_ACTIVE_HIGH>; + }; + + led_system_green: system_green { + label = "green:system"; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; + }; + + system_blue { + label = "blue:system"; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&gpio 30 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +ðernet { + pinctrl-0 = <&mdio_pins>, <&rgmii1_pins>; +}; + +&state_default { + gpio { + groups = "uart3", "rgmii2"; + function = "gpio"; + }; +}; From 985f982435ce35a70b07fb1ca101d9ff8f822861 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 19 Feb 2024 01:37:30 +0100 Subject: [PATCH 17/23] examples/nwa50ax-ap: support bridge between lan and ethernet Signed-off-by: Raito Bezarius --- examples/nwa50ax-ap.nix | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/examples/nwa50ax-ap.nix b/examples/nwa50ax-ap.nix index e121d8a..6a3989a 100644 --- a/examples/nwa50ax-ap.nix +++ b/examples/nwa50ax-ap.nix @@ -58,6 +58,7 @@ in rec { ../modules/ssh ../modules/ntp ../modules/vlan + ../modules/bridge ]; hostname = "zyxel"; @@ -73,8 +74,21 @@ in rec { ]; }; + services.int = svc.bridge.primary.build { + ifname = "int"; + }; + + services.bridge = svc.bridge.members.build { + primary = services.int; + members = with config.hardware.networkInterfaces; [ + lan + wlan0 + wlan1 + ]; + }; + services.dhcpv4 = - let iface = config.hardware.networkInterfaces.lan; + let iface = services.int; in svc.network.dhcp.client.build { interface = iface; }; services.defaultroute4 = svc.network.route.build { From d6ffdd7be69889e7375ebb1a91b5991c9f382603 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 19 Feb 2024 02:48:15 +0100 Subject: [PATCH 18/23] devices/zyxel-nwa50ax: expose primary and secondary images To support A/B a bit better. Signed-off-by: Raito Bezarius --- default.nix | 4 + .../mt7621_zyxel_nwa-ax-for-ab.dtsi | 20 +-- .../b_image/mt7621_zyxel_nwa-ax-for-ab.dtsi | 155 ++++++++++++++++++ devices/zyxel-nwa50ax/default.nix | 11 +- modules/base.nix | 4 + modules/outputs/zyxel-nwa-fit.nix | 2 +- 6 files changed, 176 insertions(+), 20 deletions(-) rename devices/zyxel-nwa50ax/{ => a_image}/mt7621_zyxel_nwa-ax-for-ab.dtsi (86%) create mode 100644 devices/zyxel-nwa50ax/b_image/mt7621_zyxel_nwa-ax-for-ab.dtsi diff --git a/default.nix b/default.nix index 2bd91c5..acfce7c 100644 --- a/default.nix +++ b/default.nix @@ -3,6 +3,7 @@ , liminix-config ? , nixpkgs ? , borderVmConf ? ./bordervm.conf.nix +, imageType ? "primary" }: let @@ -30,6 +31,9 @@ let ./modules/s6 ./modules/users.nix ./modules/outputs.nix + { + boot.imageType = imageType; + } ]; }; config = eval.config; diff --git a/devices/zyxel-nwa50ax/mt7621_zyxel_nwa-ax-for-ab.dtsi b/devices/zyxel-nwa50ax/a_image/mt7621_zyxel_nwa-ax-for-ab.dtsi similarity index 86% rename from devices/zyxel-nwa50ax/mt7621_zyxel_nwa-ax-for-ab.dtsi rename to devices/zyxel-nwa50ax/a_image/mt7621_zyxel_nwa-ax-for-ab.dtsi index 250bc04..6c75b0b 100644 --- a/devices/zyxel-nwa50ax/mt7621_zyxel_nwa-ax-for-ab.dtsi +++ b/devices/zyxel-nwa50ax/a_image/mt7621_zyxel_nwa-ax-for-ab.dtsi @@ -40,20 +40,6 @@ label = "factory"; reg = <0x100000 0x80000>; read-only; - - nvmem-layout { - compatible = "fixed-layout"; - #address-cells = <1>; - #size-cells = <1>; - - eeprom_factory_0: eeprom@0 { - reg = <0x0 0xe00>; - }; - - precal_factory_e10: precal@e10 { - reg = <0xe10 0x19c10>; - }; - }; }; partition@180000 { @@ -70,7 +56,7 @@ }; partition@400000 { - label = "ubi_a"; + label = "ubi"; reg = <0x800000 0x2000000>; }; }; @@ -142,9 +128,7 @@ reg = <0x0 0 0 0 0>; compatible = "mediatek,mt76"; - nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; - nvmem-cell-names = "eeprom", "precal"; - + mediatek,mtd-eeprom = <&factory 0x0>; /* MAC-Address set in userspace */ }; }; diff --git a/devices/zyxel-nwa50ax/b_image/mt7621_zyxel_nwa-ax-for-ab.dtsi b/devices/zyxel-nwa50ax/b_image/mt7621_zyxel_nwa-ax-for-ab.dtsi new file mode 100644 index 0000000..c35d362 --- /dev/null +++ b/devices/zyxel-nwa50ax/b_image/mt7621_zyxel_nwa-ax-for-ab.dtsi @@ -0,0 +1,155 @@ +#include "mt7621.dtsi" + +#include +#include + +/ { + aliases { + label-mac-device = &gmac0; + }; +}; + +&nand { + status = "okay"; + + mediatek,nmbm; + mediatek,bmt-max-ratio = <15>; + mediatek,bmt-max-reserved-blocks = <64>; + mediatek,bmt-remap-range = + <0x0 0x980000>, + <0x2980000 0x7800000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "u-boot-env"; + reg = <0x80000 0x80000>; + read-only; + }; + + factory: partition@100000 { + label = "factory"; + reg = <0x100000 0x80000>; + read-only; + }; + + partition@2980000 { + label = "firmware_b"; + reg = <0x2980000 0x2800000>; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "kernel_b"; + reg = <0x0 0x800000>; + }; + + partition@400000 { + label = "ubi"; + reg = <0x800000 0x2000000>; + }; + }; + + partition@180000 { + label = "firmware_a"; + reg = <0x180000 0x2800000>; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "kernel_a"; + reg = <0x0 0x800000>; + }; + + partition@400000 { + label = "ubi_a"; + reg = <0x800000 0x2000000>; + }; + }; + + partition@5180000 { + label = "rootfs_data"; + reg = <0x5180000 0x1400000>; + }; + + partition@6580000 { + label = "logs"; + reg = <0x6580000 0xd00000>; + }; + + partition@7280000 { + label = "vendor-myzyxel"; + reg = <0x7280000 0x480000>; + read-only; + }; + + partition@7700000 { + label = "bootconfig"; + reg = <0x7700000 0x80000>; + }; + + mrd: partition@7780000 { + label = "mrd"; + reg = <0x7780000 0x80000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_mrd_1fff8: macaddr@1fff8 { + reg = <0x1fff8 0x6>; + }; + }; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&pcie1 { + wlan_5g: wifi@0,0 { + reg = <0x0 0 0 0 0>; + compatible = "mediatek,mt76"; + + mediatek,mtd-eeprom = <&factory 0x0>; + /* MAC-Address set in userspace */ + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_mrd_1fff8>; + nvmem-cell-names = "mac-address"; +}; + +&switch0 { + ports { + port@4 { + status = "okay"; + label = "lan"; + }; + }; +}; + +&state_default { + gpio { + groups = "uart3"; + function = "gpio"; + }; +}; diff --git a/devices/zyxel-nwa50ax/default.nix b/devices/zyxel-nwa50ax/default.nix index 468487b..2e8fd2a 100644 --- a/devices/zyxel-nwa50ax/default.nix +++ b/devices/zyxel-nwa50ax/default.nix @@ -151,7 +151,16 @@ # This DTS is insufficient. src = ./mt7621_zyxel_nwa50ax.dtsi; includes = [ - "${./.}" + # Here's one weird trick to make `ubi` detection + # out of the box. + # We will write ubi on /dev/firmware_a:rootfs location + # and same for /dev/firmware_b:rootfs. + # How do we distinguish both? + # We can just use the DTS to point ubi at A or B. + # This, unfortunately, means that we have "two images". + # But they are really just 1 image with 2 different DTS. + # TODO: improve this hack in preinit? + (if config.boot.imageType == "primary" then "${./a_image}" else "${./b_image}") "${openwrt.src}/target/linux/ramips/dts" ]; }; diff --git a/modules/base.nix b/modules/base.nix index f64c817..8f53df2 100644 --- a/modules/base.nix +++ b/modules/base.nix @@ -63,6 +63,10 @@ in { default = "bootargs"; description = "Kernel command line's devicetree node"; }; + imageType = mkOption { + type = types.enum [ "primary" "secondary" ]; + default = "primary"; + }; imageFormat = mkOption { type = types.enum ["fit" "uimage"]; default = "uimage"; diff --git a/modules/outputs/zyxel-nwa-fit.nix b/modules/outputs/zyxel-nwa-fit.nix index d6f894e..a68dd39 100644 --- a/modules/outputs/zyxel-nwa-fit.nix +++ b/modules/outputs/zyxel-nwa-fit.nix @@ -62,7 +62,7 @@ on a system with pre-existing firmware and OS. }; ''; in - pkgs.runCommand "zyxel-nwa-fit" { + pkgs.runCommand "zyxel-nwa-fit-${config.boot.imageType}" { nativeBuildInputs = [ pkgs.pkgsBuildBuild.ubootTools pkgs.pkgsBuildBuild.dtc ]; } '' mkimage -f ${dts} $out From c0a9571a1305fe3006e60c7dbdc109d2bda98753 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 19 Feb 2024 02:48:40 +0100 Subject: [PATCH 19/23] devices/zyxel-nwa50ax: upgrade MT7915 firmware from OpenWRT repository Signed-off-by: Raito Bezarius --- devices/zyxel-nwa50ax/default.nix | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/devices/zyxel-nwa50ax/default.nix b/devices/zyxel-nwa50ax/default.nix index 2e8fd2a..0d7e1f6 100644 --- a/devices/zyxel-nwa50ax/default.nix +++ b/devices/zyxel-nwa50ax/default.nix @@ -77,16 +77,17 @@ drivers = [ "mt7915e" ]; klibBuild = config.system.outputs.kernel.modulesupport; }; + # v204520220929 wlan_firmware = pkgs.fetchurl { - url = "https://github.com/openwrt/mt76/raw/2afc7285f75dca5a0583fd917285bf33f1429cc6/firmware/mt7915_wa.bin"; + url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_wa.bin"; hash = "sha256-wooyefzb0i8640+lwq3vNhcBXRFCtGuo+jiL7afZaKA="; }; wlan_firmware' = pkgs.fetchurl { - url = "https://github.com/openwrt/mt76/raw/2afc7285f75dca5a0583fd917285bf33f1429cc6/firmware/mt7915_wm.bin"; + url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_wm.bin"; hash = "sha256-k62nQewRuKjBLd5R3RxU4F74YKnQx5zr6gqMMImqVQw="; }; wlan_firmware'' = pkgs.fetchurl { - url = "https://github.com/openwrt/mt76/raw/2afc7285f75dca5a0583fd917285bf33f1429cc6/firmware/mt7915_rom_patch.bin"; + url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_rom_patch.bin"; hash = "sha256-ifriAjWzFACrxVWCANZpUaEZgB/0pdbhnTVQytx6ddg="; }; in { From da59e2a34946984a3410f26088c37d8211824f51 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 19 Feb 2024 02:57:29 +0100 Subject: [PATCH 20/23] devices/zyxel-nwa50ax: complete documentation It covers everything I know more or less. Signed-off-by: Raito Bezarius --- devices/zyxel-nwa50ax/default.nix | 52 +++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/devices/zyxel-nwa50ax/default.nix b/devices/zyxel-nwa50ax/default.nix index 0d7e1f6..fe7504a 100644 --- a/devices/zyxel-nwa50ax/default.nix +++ b/devices/zyxel-nwa50ax/default.nix @@ -19,22 +19,36 @@ Installation ============ - Wow, this device is a handful. + This device is pretty, but, due to its A/B capabilities, can be a bit hard + to use completely. - The stock vendor firmware is a downstream fork of U-Boot (insert link to source code) + The stock vendor firmware is a downstream fork of U-Boot: with restricted boot commands. Fortunately, OpenWrt folks figured out trivial command injections, so you can use most of the OpenWrt commands without trouble by just command injecting atns, atna or atnf, e.g. atns "; $real_command". - From factory web UI, this has not been tested yet. + From factory web UI, you can upload the result of the zyxel-nwa-fit output. + From another operating system, you need to `dumpimage -T flat_dt -p 0 $zyxel-nwa-fit -o firmware.bin`, + `flash_erase $(mtd partition of the target partition firmware or zy_firmware) 0 0`, then you complete by + `nandwrite -p $(mtd partition of the target partition firmware or zy_firmware) firmware.bin`. + + How to put the firmware.bin on the machine is left to you as an exercise, e.g. SSH, TFTP, whatever. + From serial, you have two choices: + - Flash this system via U-Boot: + same reasoning as from an existing Linux system, two choices: + - ymodem the binary, perform the write manually, you can inspire yourself + from the `script` contained in the vendor firmware, those are just a FIT containing a script. + - prepare a FIT containing a script executing your commands, tftpboot this. + - boot from an existing Liminix system, e.g. TFTPBOOT image. - boot from an OpenWrt system, i.e. follow OpenWrt steps. Once you are in a Linux system, understand that this device has A/B boot. OpenWrt provides you with `zyxel-bootconfig` to set/unset the image status and choice. + The kernel is booted with `bootImage=` which tells you which slot are you on. You should find yourself with 10ish MTD partitions, the most interesting ones are two: @@ -44,20 +58,32 @@ In the current setup, they are split further into kernel (8MB) and ubi (32MB). - You will write the FIT uImage in the kernel MTD partition directly, via `mtd write kernel.uimage /dev/mtd4` - (if `/dev/mtd4` is the kernel MTD partition) or `flashcp` can be used similarly. + Once you are done with first installation, note that if you want to use the A/B feature, + you need to write a _secondary_ image on the slot B. There is no proper flashing code + that will set the being-updated slot to `new` and boot on it to verify if it's working. + This is a WIP. - Then, you will install the UBI image, via `ubiformat -f ubi.image /dev/mtd5` (if `/dev/mtd4` was your kernel MTD partition, 5 must be the UBI). + Upgrading your system can be achieved via: - Once you are done, you will have to reboot and modify your bootargs in U-Boot - because they are currently overridden. + - `liminix-rebuild` for the userspace. + - `flash_erase` + `nandwrite` for the kernelspace to the other slot than the one you are booted on, + note that you can just nandwrite the mtd partition corresponding to the *kernel* and not the whole firmware. - It is enough to do: - atns "; setenv bootargs 'liminix console=ttyS0,115200 panic=10 oops=panic init=/bin/init loglevel=8 fw_devlink=off ubi.mtd=ubi root=ubi0:rootfs rootfstype=ubifs'" - atns "; saveenv" + If you soft-bricked your AP, i.e. you cannot boot anything in U-Boot, no worries, just plug the serial console, + prepare a TFTP server (via `tufted` for example), download vendor firmware, set up `atns`, `atnf`, etc. and run `atnz`. - Once you are done, you can enjoy booting on slot A unattended for now. To make use of the A/B feature, this is a TODO :). - Upgrades are TODO too. + This will reflash everything back to normal via TFTP. + + If you hard-bricked your AP, i.e. U-Boot is telling you to transfer a valid bootloader via ymodem, just extract + a U-Boot from the vendor OS, send it via ymodem and use the previous operations to perform a full flash this time + of all partitions. + + Note that if you erased your MRD partition, you lost your serial and MAC address. There's no way to recover the original one + except by reading the physical label on your… device! + + If you super-hard-bricked your AP, i.e. no output on serial console, congratulations, you reached one of the rare state + of this device. You need an external NAND flasher to repair it and write the first stage from Mediatek to continue the previous + recovery operations. Vendor web page: https://www.zyxel.com/fr/fr/products/wireless/ax1800-wifi-6-dual-radio-nebulaflex-access-point-nwa50ax From 628f4dfdbe9487f5bb05ed23fbf3fcb4ab77ef43 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 19 Feb 2024 03:05:22 +0100 Subject: [PATCH 21/23] devices/zyxel-nwa50ax: developer todo Signed-off-by: Raito Bezarius --- devices/zyxel-nwa50ax/default.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/devices/zyxel-nwa50ax/default.nix b/devices/zyxel-nwa50ax/default.nix index fe7504a..e991a9d 100644 --- a/devices/zyxel-nwa50ax/default.nix +++ b/devices/zyxel-nwa50ax/default.nix @@ -85,6 +85,15 @@ of this device. You need an external NAND flasher to repair it and write the first stage from Mediatek to continue the previous recovery operations. + Development TODO list: + + - Better support for upgrade automation w.r.t. to A/B, e.g. automagic scripts. + - Mount the logs partition, mount / as overlayfs of firmware ? rootfs and rootfs_data for extended data. + - Jitter-based entropy injection? Device can be slow to initialize its CRNG and hostapd will reject few clients at the start because of that. + - Defaults for hostapd based on MT7915 capabilities? See the example for one possible list. + - Remove primary/secondary hack and put it in preinit. + - Offer ways to reflash the *bootloader* itself to support direct boot via UBI and kernel upgrades via filesystem rewrite. + Vendor web page: https://www.zyxel.com/fr/fr/products/wireless/ax1800-wifi-6-dual-radio-nebulaflex-access-point-nwa50ax OpenWrt web page: https://openwrt.org/inbox/toh/zyxel/nwa50ax From c5145b5fc9359d6ac6ddfe86fd16d3272872473d Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 19 Feb 2024 03:07:34 +0100 Subject: [PATCH 22/23] devices/zyxel-nwa50ax: make `zyxel-bootconfig` executable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise, it doesn't work well… Signed-off-by: Raito Bezarius --- pkgs/zyxel-bootconfig/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/zyxel-bootconfig/default.nix b/pkgs/zyxel-bootconfig/default.nix index ce148ae..4b72ccf 100644 --- a/pkgs/zyxel-bootconfig/default.nix +++ b/pkgs/zyxel-bootconfig/default.nix @@ -8,7 +8,7 @@ stdenv.mkDerivation { sourceRoot = "openwrt-source/package/utils/zyxel-bootconfig/src"; installPhase = '' mkdir -p $out/bin - install -Dm644 zyxel-bootconfig $out/bin/zyxel-bootconfig + install -Dm544 zyxel-bootconfig $out/bin/zyxel-bootconfig ''; meta = { mainProgram = "zyxel-bootconfig"; From baf3cf741301e696a5f614f8fb98d182a0ab0f1d Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 19 Feb 2024 03:13:35 +0100 Subject: [PATCH 23/23] devices/zyxel-nwa50ax: fix dual image mgmt after DTB expansion Signed-off-by: Raito Bezarius --- devices/zyxel-nwa50ax/default.nix | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/devices/zyxel-nwa50ax/default.nix b/devices/zyxel-nwa50ax/default.nix index e991a9d..23a394a 100644 --- a/devices/zyxel-nwa50ax/default.nix +++ b/devices/zyxel-nwa50ax/default.nix @@ -235,9 +235,12 @@ services.zyxel-dual-image = config.boot.zyxel-dual-image.build { ensureActiveImage = "primary"; # TODO: use mtd names rather… + # primary and secondary are always /dev/mtd3 by virtue of the + # dtb being not too wrong… + # TODO: remove this hack. primaryMtdPartition = "/dev/mtd3"; - secondaryMtdPartition = "/dev/mtd6"; - bootConfigurationMtdPartition = "/dev/mtd10"; + secondaryMtdPartition = "/dev/mtd3"; + bootConfigurationMtdPartition = "/dev/mtd12"; }; # DEVICE_VENDOR := ZyXEL