nixfmt-rfc-style

There is nothing in this commit except for the changes made by
nix-shell -p nixfmt-rfc-style --run "nixfmt ."

If this has mucked up your open branches then sorry about that. You
can probably nixfmt them to match before merging
This commit is contained in:
Daniel Barlow
2025-02-10 21:55:08 +00:00
parent 13cc5a8992
commit 7e2b0068e6
211 changed files with 6049 additions and 4355 deletions

View File

@@ -1,8 +1,21 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
let let
cfg = config.bordervm; cfg = config.bordervm;
inherit (lib) mkOption mkEnableOption mdDoc types optional optionals; inherit (lib)
in { mkOption
mkEnableOption
mdDoc
types
optional
optionals
;
in
{
options.bordervm = { options.bordervm = {
keys = mkOption { keys = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
@@ -107,13 +120,14 @@ in {
from = "host"; from = "host";
host.port = 7654; host.port = 7654;
# guest.address = "10.0.2.15"; # guest.address = "10.0.2.15";
guest.port =7654; guest.port = 7654;
} }
{ {
host.port = 2222; host.port = 2222;
guest.address = "10.0.2.15"; guest.address = "10.0.2.15";
guest.port = 22; guest.port = 22;
}]; }
];
qemu = { qemu = {
networkingOptions = [ ]; networkingOptions = [ ];
options = options =
@@ -139,28 +153,41 @@ in {
services.tang = { services.tang = {
enable = true; enable = true;
ipAddressAllow = [ "10.0.0.0/24" "0.0.0.0/0" ]; ipAddressAllow = [
"10.0.0.0/24"
"0.0.0.0/0"
];
}; };
environment.systemPackages = environment.systemPackages =
let wireshark-nogui = pkgs.wireshark.override { withQt = false ; }; let
in with pkgs; [ wireshark-nogui = pkgs.wireshark.override { withQt = false; };
tcpdump in
wireshark-nogui with pkgs;
socat [
tufted tcpdump
iptables wireshark-nogui
usbutils socat
busybox tufted
clevis iptables
]; usbutils
busybox
clevis
];
security.sudo.wheelNeedsPassword = false; security.sudo.wheelNeedsPassword = false;
networking = { networking = {
hostName = "border"; hostName = "border";
firewall = { enable = false; }; firewall = {
enable = false;
};
interfaces.eth1 = { interfaces.eth1 = {
useDHCP = false; useDHCP = false;
ipv4.addresses = [ { address = "10.0.0.1"; prefixLength = 24;}]; ipv4.addresses = [
{
address = "10.0.0.1";
prefixLength = 24;
}
];
}; };
nat = { nat = {
enable = true; enable = true;

20
ci.nix
View File

@@ -17,7 +17,8 @@ let
"belkin-rt3200" "belkin-rt3200"
]; ];
vanilla = ./vanilla-configuration.nix; vanilla = ./vanilla-configuration.nix;
for-device = name: for-device =
name:
(import liminix { (import liminix {
inherit borderVmConf; inherit borderVmConf;
device = import (liminix + "/devices/${name}"); device = import (liminix + "/devices/${name}");
@@ -71,12 +72,13 @@ let
echo "file source-dist \"$out/share/doc/liminix\"" \ echo "file source-dist \"$out/share/doc/liminix\"" \
> $out/nix-support/hydra-build-products > $out/nix-support/hydra-build-products
''; '';
}; };
}; };
in jobs // in
{ jobs
all = pkgs.mkShell { // {
name = "all tests"; all = pkgs.mkShell {
contents = pkgs.lib.collect pkgs.lib.isDerivation jobs; name = "all tests";
}; contents = pkgs.lib.collect pkgs.lib.isDerivation jobs;
} };
}

View File

@@ -27,7 +27,12 @@ let
modulesPath = builtins.toString ./modules; modulesPath = builtins.toString ./modules;
}; };
modules = [ modules = [
{ _module.args = { inherit pkgs; inherit (pkgs) lim; }; } {
_module.args = {
inherit pkgs;
inherit (pkgs) lim;
};
}
./modules/hardware.nix ./modules/hardware.nix
./modules/base.nix ./modules/base.nix
./modules/busybox.nix ./modules/busybox.nix
@@ -47,30 +52,34 @@ let
}; };
config = eval.config; config = eval.config;
borderVm = ((import <nixpkgs/nixos/lib/eval-config.nix>) { borderVm =
system = builtins.currentSystem; ((import <nixpkgs/nixos/lib/eval-config.nix>) {
modules = [ system = builtins.currentSystem;
{ modules = [
nixpkgs.overlays = [ {
(final: prev: { nixpkgs.overlays = [
go-l2tp = final.callPackage ./pkgs/go-l2tp {}; (final: prev: {
tufted = final.callPackage ./pkgs/tufted {}; go-l2tp = final.callPackage ./pkgs/go-l2tp { };
}) tufted = final.callPackage ./pkgs/tufted { };
]; })
} ];
(import ./bordervm-configuration.nix) }
borderVmConf (import ./bordervm-configuration.nix)
]; borderVmConf
}).config.system; ];
in { }).config.system;
in
{
outputs = config.system.outputs // { outputs = config.system.outputs // {
default = config.system.outputs.${config.hardware.defaultOutput}; default = config.system.outputs.${config.hardware.defaultOutput};
optionsJson = optionsJson =
let o = import ./doc/extract-options.nix { let
inherit pkgs eval; o = import ./doc/extract-options.nix {
lib = pkgs.lib; inherit pkgs eval;
}; lib = pkgs.lib;
in pkgs.writeText "options.json" (builtins.toJSON o); };
in
pkgs.writeText "options.json" (builtins.toJSON o);
}; };
# this is just here as a convenience, so that we can get a # this is just here as a convenience, so that we can get a

View File

@@ -107,7 +107,7 @@
possible, as it will reset the erase counters used for write possible, as it will reset the erase counters used for write
levelling. Using UBI-aware tools is therefore preferred over any levelling. Using UBI-aware tools is therefore preferred over any
kind of "factory" wipe which will reset them. kind of "factory" wipe which will reset them.
''; '';
system = { system = {
crossSystem = { crossSystem = {
@@ -115,203 +115,218 @@
}; };
}; };
module = {pkgs, config, lib, lim, ... }: module =
let inherit (lib) mkIf; {
firmware = pkgs.stdenv.mkDerivation { pkgs,
name = "wlan-firmware"; config,
phases = ["installPhase"]; lib,
installPhase = '' lim,
mkdir $out ...
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out }:
''; let
}; inherit (lib) mkIf;
openwrt = pkgs.openwrt_24_10; firmware = pkgs.stdenv.mkDerivation {
in { name = "wlan-firmware";
phases = [ "installPhase" ];
installPhase = ''
mkdir $out
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out
'';
};
openwrt = pkgs.openwrt_24_10;
in
{
imports = [ imports = [
../../modules/arch/aarch64.nix ../../modules/arch/aarch64.nix
../../modules/outputs/tftpboot.nix ../../modules/outputs/tftpboot.nix
../../modules/outputs/ubifs.nix ../../modules/outputs/ubifs.nix
]; ];
config = { config = {
kernel = { kernel = {
extraPatchPhase = '' extraPatchPhase = ''
${openwrt.applyPatches.mediatek} ${openwrt.applyPatches.mediatek}
''; '';
src = openwrt.kernelSrc; src = openwrt.kernelSrc;
version = openwrt.kernelVersion; version = openwrt.kernelVersion;
config = { config = {
PCI = "y"; PCI = "y";
ARCH_MEDIATEK = "y"; ARCH_MEDIATEK = "y";
# ARM_MEDIATEK_CPUFREQ = "y"; # ARM_MEDIATEK_CPUFREQ = "y";
# needed for "Cannot find regmap for /infracfg@10000000" # needed for "Cannot find regmap for /infracfg@10000000"
MFD_SYSCON = "y"; MFD_SYSCON = "y";
MTK_INFRACFG = "y"; MTK_INFRACFG = "y";
MTK_PMIC_WRAP = "y"; MTK_PMIC_WRAP = "y";
DMADEVICES = "y"; DMADEVICES = "y";
MTK_HSDMA="y"; MTK_HSDMA = "y";
MTK_SCPSYS="y"; MTK_SCPSYS = "y";
MTK_SCPSYS_PM_DOMAINS="y"; MTK_SCPSYS_PM_DOMAINS = "y";
# MTK_THERMAL="y"; # MTK_THERMAL="y";
MTK_TIMER="y"; MTK_TIMER = "y";
COMMON_CLK_MT7622 = "y"; COMMON_CLK_MT7622 = "y";
COMMON_CLK_MT7622_ETHSYS = "y"; COMMON_CLK_MT7622_ETHSYS = "y";
COMMON_CLK_MT7622_HIFSYS = "y"; COMMON_CLK_MT7622_HIFSYS = "y";
COMMON_CLK_MT7622_AUDSYS = "y"; COMMON_CLK_MT7622_AUDSYS = "y";
PM_CLK="y"; PM_CLK = "y";
REGMAP_MMIO = "y"; REGMAP_MMIO = "y";
CLKSRC_MMIO = "y"; CLKSRC_MMIO = "y";
REGMAP = "y"; REGMAP = "y";
MEDIATEK_GE_PHY = "y"; MEDIATEK_GE_PHY = "y";
# MEDIATEK_MT6577_AUXADC = "y"; # MEDIATEK_MT6577_AUXADC = "y";
NET_MEDIATEK_SOC = "y"; NET_MEDIATEK_SOC = "y";
NET_MEDIATEK_SOC_WED = "y"; NET_MEDIATEK_SOC_WED = "y";
NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO
NET_VENDOR_MEDIATEK = "y"; NET_VENDOR_MEDIATEK = "y";
PCIE_MEDIATEK = "y"; PCIE_MEDIATEK = "y";
BLOCK = "y"; # move this to base option BLOCK = "y"; # move this to base option
SPI_MASTER = "y"; SPI_MASTER = "y";
SPI = "y"; SPI = "y";
SPI_MEM="y"; SPI_MEM = "y";
SPI_MTK_NOR="y"; SPI_MTK_NOR = "y";
SPI_MTK_SNFI = "y"; SPI_MTK_SNFI = "y";
MTD = "y"; MTD = "y";
MTD_BLOCK = "y"; MTD_BLOCK = "y";
MTD_RAW_NAND = "y"; MTD_RAW_NAND = "y";
MTD_NAND_MTK = "y"; MTD_NAND_MTK = "y";
MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table
MTD_NAND_ECC_MEDIATEK= "y"; MTD_NAND_ECC_MEDIATEK = "y";
MTD_NAND_ECC_SW_HAMMING= "y"; MTD_NAND_ECC_SW_HAMMING = "y";
MTD_SPI_NAND= "y"; MTD_SPI_NAND = "y";
MTD_OF_PARTS = "y"; MTD_OF_PARTS = "y";
MTD_NAND_CORE= "y"; MTD_NAND_CORE = "y";
MTD_SPI_NOR= "y"; MTD_SPI_NOR = "y";
MTD_SPLIT_FIRMWARE= "y"; MTD_SPLIT_FIRMWARE = "y";
MTD_SPLIT_FIT_FW= "y"; MTD_SPLIT_FIT_FW = "y";
MTD_UBI_NVMEM = "y"; MTD_UBI_NVMEM = "y";
NVMEM_MTK_EFUSE = "y"; NVMEM_MTK_EFUSE = "y";
NVMEM_BLOCK = "y"; NVMEM_BLOCK = "y";
NVMEM_LAYOUT_ADTRAN = "y"; NVMEM_LAYOUT_ADTRAN = "y";
MMC = "y"; MMC = "y";
MMC_BLOCK = "y"; MMC_BLOCK = "y";
MMC_CQHCI = "y"; MMC_CQHCI = "y";
MMC_MTK = "y"; MMC_MTK = "y";
# Distributed Switch Architecture is needed # Distributed Switch Architecture is needed
# to make the ethernet ports visible # to make the ethernet ports visible
NET_DSA="y"; NET_DSA = "y";
NET_DSA_MT7530="y"; NET_DSA_MT7530 = "y";
NET_DSA_TAG_MTK="y"; NET_DSA_TAG_MTK = "y";
NET_DSA_MT7530_MDIO="y"; NET_DSA_MT7530_MDIO = "y";
SERIAL_8250 = "y"; SERIAL_8250 = "y";
SERIAL_8250_CONSOLE = "y"; SERIAL_8250_CONSOLE = "y";
SERIAL_8250_MT6577="y"; SERIAL_8250_MT6577 = "y";
# SERIAL_8250_NR_UARTS="3"; # SERIAL_8250_NR_UARTS="3";
# SERIAL_8250_RUNTIME_UARTS="3"; # SERIAL_8250_RUNTIME_UARTS="3";
SERIAL_OF_PLATFORM="y"; SERIAL_OF_PLATFORM = "y";
# Must enble hardware watchdog drivers. Else the device reboots after several seconds # Must enble hardware watchdog drivers. Else the device reboots after several seconds
WATCHDOG = "y"; WATCHDOG = "y";
MEDIATEK_WATCHDOG = "y"; MEDIATEK_WATCHDOG = "y";
}; };
conditionalConfig = { conditionalConfig = {
WLAN= { WLAN = {
MT7615E = "m"; MT7615E = "m";
MT7622_WMAC = "y"; MT7622_WMAC = "y";
MT7915E = "m"; MT7915E = "m";
};
};
};
boot = {
commandLine = [ "console=ttyS0,115200" ];
tftp.loadAddress = lim.parseInt "0x48000000";
imageFormat = "fit";
loader.fit.enable = lib.mkDefault true; # override this if you are building tftpboot
};
rootfsType = lib.mkDefault "ubifs"; # override this if you are building tftpboot
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in
dir {
lib = dir {
firmware = dir {
mediatek = symlink firmware;
};
};
};
hardware =
let
mac80211 = pkgs.kmodloader.override {
targets = ["mt7615e" "mt7915e"];
inherit (config.system.outputs) kernel;
};
in {
ubi = {
minIOSize = "2048";
logicalEraseBlockSize = "126976";
physicalEraseBlockSize = "131072";
maxLEBcount = "1024"; # guessing
};
defaultOutput = "ubimage";
# the kernel expects this to be on a 2MB boundary. U-Boot
# (I don't know why) has a default of 0x41080000, which isn't.
# We put it at the 32MB mark so that tftpboot can put its rootfs
# image and DTB underneath, but maybe this is a terrible waste of
# RAM unless the kernel is able to reuse it later. Oh well
loadAddress = lim.parseInt "0x42000000";
entryPoint = lim.parseInt "0x42000000";
rootDevice = "ubi0:liminix";
dts = {
src = "${openwrt.src}/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts";
includePaths = [
"${openwrt.src}/target/linux/mediatek/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
includes = mkIf config.logging.persistent.enable [
./pstore-pmsg.dtsi
];
};
# - 0x000000000000-0x000008000000 : "spi-nand0"
# - 0x000000000000-0x000000080000 : "bl2"
# - 0x000000080000-0x0000001c0000 : "fip"
# - 0x0000001c0000-0x0000002c0000 : "factory"
# - 0x0000002c0000-0x000000300000 : "reserved"
# - 0x000000300000-0x000008000000 : "ubi"
networkInterfaces =
let
inherit (config.system.service.network) link;
in rec {
wan = link.build { ifname = "wan"; };
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
lan = lan3;
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
}; };
}; };
};
boot = {
commandLine = [ "console=ttyS0,115200" ];
tftp.loadAddress = lim.parseInt "0x48000000";
imageFormat = "fit";
loader.fit.enable = lib.mkDefault true; # override this if you are building tftpboot
};
rootfsType = lib.mkDefault "ubifs"; # override this if you are building tftpboot
filesystem =
let
inherit (pkgs.pseudofile) dir symlink;
in
dir {
lib = dir {
firmware = dir {
mediatek = symlink firmware;
};
};
};
hardware =
let
mac80211 = pkgs.kmodloader.override {
targets = [
"mt7615e"
"mt7915e"
];
inherit (config.system.outputs) kernel;
};
in
{
ubi = {
minIOSize = "2048";
logicalEraseBlockSize = "126976";
physicalEraseBlockSize = "131072";
maxLEBcount = "1024"; # guessing
};
defaultOutput = "ubimage";
# the kernel expects this to be on a 2MB boundary. U-Boot
# (I don't know why) has a default of 0x41080000, which isn't.
# We put it at the 32MB mark so that tftpboot can put its rootfs
# image and DTB underneath, but maybe this is a terrible waste of
# RAM unless the kernel is able to reuse it later. Oh well
loadAddress = lim.parseInt "0x42000000";
entryPoint = lim.parseInt "0x42000000";
rootDevice = "ubi0:liminix";
dts = {
src = "${openwrt.src}/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts";
includePaths = [
"${openwrt.src}/target/linux/mediatek/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
includes = mkIf config.logging.persistent.enable [
./pstore-pmsg.dtsi
];
};
# - 0x000000000000-0x000008000000 : "spi-nand0"
# - 0x000000000000-0x000000080000 : "bl2"
# - 0x000000080000-0x0000001c0000 : "fip"
# - 0x0000001c0000-0x0000002c0000 : "factory"
# - 0x0000002c0000-0x000000300000 : "reserved"
# - 0x000000300000-0x000008000000 : "ubi"
networkInterfaces =
let
inherit (config.system.service.network) link;
in
rec {
wan = link.build { ifname = "wan"; };
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
lan = lan3;
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
};
};
}; };
}; };
};
} }

View File

@@ -19,25 +19,28 @@
VIRTIO_NET = "y"; VIRTIO_NET = "y";
}; };
conditionalConfig = { conditionalConfig = {
WLAN= { WLAN = {
MAC80211_HWSIM = "m"; MAC80211_HWSIM = "m";
}; };
}; };
}; };
hardware = hardware =
let let
mac80211 = pkgs.kmodloader.override { mac80211 = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel; inherit (config.system.outputs) kernel;
targets = ["mac80211_hwsim"]; targets = [ "mac80211_hwsim" ];
}; };
in { in
{
defaultOutput = "vmroot"; defaultOutput = "vmroot";
rootDevice = "/dev/mtdblock0"; rootDevice = "/dev/mtdblock0";
dts.src = pkgs.lib.mkDefault null; dts.src = pkgs.lib.mkDefault null;
flash.eraseBlockSize = 65536; flash.eraseBlockSize = 65536;
networkInterfaces = networkInterfaces =
let inherit (config.system.service.network) link; let
in { inherit (config.system.service.network) link;
in
{
wan = link.build { wan = link.build {
devpath = "/devices/pci0000:00/0000:00:13.0/virtio0"; devpath = "/devices/pci0000:00/0000:00:13.0/virtio0";
ifname = "wan"; ifname = "wan";

View File

@@ -4,7 +4,7 @@
config = "mips-unknown-linux-musl"; config = "mips-unknown-linux-musl";
gcc = { gcc = {
abi = "32"; abi = "32";
arch = "24kc"; # maybe mips_24kc- arch = "24kc"; # maybe mips_24kc-
}; };
}; };
}; };
@@ -53,7 +53,14 @@
''; '';
module = {pkgs, config, lim, lib, ... }: module =
{
pkgs,
config,
lim,
lib,
...
}:
let let
inherit (lib) mkIf; inherit (lib) mkIf;
openwrt = pkgs.openwrt; openwrt = pkgs.openwrt;
@@ -65,7 +72,7 @@
}; };
firmware = pkgs.stdenv.mkDerivation { firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware"; name = "wlan-firmware";
phases = ["installPhase"]; phases = [ "installPhase" ];
installPhase = '' installPhase = ''
mkdir -p $out/ath10k/QCA9887/hw1.0/ mkdir -p $out/ath10k/QCA9887/hw1.0/
blobdir=${firmwareBlobs}/QCA9887/hw1.0 blobdir=${firmwareBlobs}/QCA9887/hw1.0
@@ -74,7 +81,10 @@
''; '';
}; };
mac80211 = pkgs.kmodloader.override { mac80211 = pkgs.kmodloader.override {
targets = ["ath9k" "ath10k_pci"]; targets = [
"ath9k"
"ath10k_pci"
];
inherit (config.system.outputs) kernel; inherit (config.system.outputs) kernel;
dependencies = [ ath10k_cal_data ]; dependencies = [ ath10k_cal_data ];
}; };
@@ -82,7 +92,8 @@
let let
offset = lim.parseInt "0x5000"; offset = lim.parseInt "0x5000";
size = lim.parseInt "0x844"; size = lim.parseInt "0x844";
in pkgs.liminix.services.oneshot rec { in
pkgs.liminix.services.oneshot rec {
name = "ath10k_cal_data"; name = "ath10k_cal_data";
up = '' up = ''
part=$(basename $(dirname $(grep -l art /sys/class/mtd/*/name))) part=$(basename $(dirname $(grep -l art /sys/class/mtd/*/name)))
@@ -91,10 +102,11 @@
(in_outputs ${name} (in_outputs ${name}
dd if=/dev/$part of=data iflag=skip_bytes,fullblock bs=${toString size} skip=${toString offset} count=1 dd if=/dev/$part of=data iflag=skip_bytes,fullblock bs=${toString size} skip=${toString offset} count=1
) )
''; '';
}; };
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
in { in
{
imports = [ imports = [
../../modules/network ../../modules/network
../../modules/arch/mipseb.nix ../../modules/arch/mipseb.nix
@@ -118,7 +130,7 @@
rootDevice = "/dev/mtdblock5"; rootDevice = "/dev/mtdblock5";
dts = { dts = {
src = "${openwrt.src}/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts"; src = "${openwrt.src}/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts";
includePaths = [ includePaths = [
"${openwrt.src}/target/linux/ath79/dts" "${openwrt.src}/target/linux/ath79/dts"
]; ];
includes = mkIf config.logging.persistent.enable [ includes = mkIf config.logging.persistent.enable [
@@ -127,8 +139,10 @@
}; };
networkInterfaces = networkInterfaces =
let inherit (config.system.service.network) link; let
in { inherit (config.system.service.network) link;
in
{
lan = link.build { lan = link.build {
ifname = "lan"; ifname = "lan";
devpath = "/devices/platform/ahb/1a000000.eth"; devpath = "/devices/platform/ahb/1a000000.eth";
@@ -143,7 +157,10 @@
}; };
wlan5 = link.build { wlan5 = link.build {
ifname = "wlan1"; ifname = "wlan1";
dependencies = [ ath10k_cal_data mac80211 ]; dependencies = [
ath10k_cal_data
mac80211
];
}; };
}; };
}; };
@@ -193,31 +210,31 @@
NET = "y"; NET = "y";
ETHERNET = "y"; ETHERNET = "y";
NET_VENDOR_ATHEROS = "y"; NET_VENDOR_ATHEROS = "y";
AG71XX = "y"; # ethernet (qca,qca9530-eth) AG71XX = "y"; # ethernet (qca,qca9530-eth)
MFD_SYSCON = "y"; # ethernet (compatible "syscon") MFD_SYSCON = "y"; # ethernet (compatible "syscon")
AR8216_PHY = "y"; # eth1 is behind a switch AR8216_PHY = "y"; # eth1 is behind a switch
MTD_SPI_NOR = "y"; MTD_SPI_NOR = "y";
SPI_ATH79 = "y"; # these are copied from OpenWrt. SPI_ATH79 = "y"; # these are copied from OpenWrt.
SPI_MASTER= "y"; # At least one of them is necessary SPI_MASTER = "y"; # At least one of them is necessary
SPI_MEM= "y"; SPI_MEM = "y";
SPI_AR934X= "y"; SPI_AR934X = "y";
SPI_BITBANG= "y"; SPI_BITBANG = "y";
SPI_GPIO= "y"; SPI_GPIO = "y";
GPIO_ATH79 = "y"; GPIO_ATH79 = "y";
GPIOLIB = "y"; GPIOLIB = "y";
EXPERT="y"; EXPERT = "y";
GPIO_SYSFS = "y"; # required by patches-5.15/0004-phy-add-ath79-usb-phys.patch GPIO_SYSFS = "y"; # required by patches-5.15/0004-phy-add-ath79-usb-phys.patch
OF_GPIO = "y"; OF_GPIO = "y";
SYSFS = "y"; SYSFS = "y";
SPI = "y"; SPI = "y";
MTD = "y"; MTD = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs
WATCHDOG = "y"; WATCHDOG = "y";
ATH79_WDT = "y"; # watchdog timer ATH79_WDT = "y"; # watchdog timer
EARLY_PRINTK = "y"; EARLY_PRINTK = "y";

View File

@@ -6,7 +6,7 @@
config = "mipsel-unknown-linux-musl"; config = "mipsel-unknown-linux-musl";
gcc = { gcc = {
abi = "32"; abi = "32";
arch = "mips32"; # maybe mips_24kc- arch = "mips32"; # maybe mips_24kc-
}; };
}; };
}; };
@@ -44,14 +44,22 @@
''; '';
module = { pkgs, config, lib, lim, ...}: module =
{
pkgs,
config,
lib,
lim,
...
}:
let let
inherit (pkgs) openwrt; inherit (pkgs) openwrt;
mac80211 = pkgs.kmodloader.override { mac80211 = pkgs.kmodloader.override {
targets = ["rt2800soc"]; targets = [ "rt2800soc" ];
inherit (config.system.outputs) kernel; inherit (config.system.outputs) kernel;
}; };
in { in
{
imports = [ imports = [
../../modules/arch/mipsel.nix ../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix ../../modules/outputs/tftpboot.nix
@@ -90,7 +98,8 @@
let let
inherit (config.system.service.network) link; inherit (config.system.service.network) link;
inherit (config.system.service) vlan; inherit (config.system.service) vlan;
in rec { in
rec {
eth = link.build { ifname = "eth0"; }; eth = link.build { ifname = "eth0"; };
# lan and wan ports are both behind a switch on eth0 # lan and wan ports are both behind a switch on eth0
lan = vlan.build { lan = vlan.build {
@@ -112,54 +121,56 @@
boot.tftp = { boot.tftp = {
loadAddress = lim.parseInt "0x00A00000"; loadAddress = lim.parseInt "0x00A00000";
appendDTB = true; appendDTB = true;
}; };
kernel = { kernel = {
extraPatchPhase = '' extraPatchPhase = ''
${openwrt.applyPatches.ramips} ${openwrt.applyPatches.ramips}
${openwrt.applyPatches.rt2x00} ${openwrt.applyPatches.rt2x00}
''; '';
config = { config =
{
RALINK = "y"; RALINK = "y";
PCI = "y"; PCI = "y";
SOC_MT7620 = "y"; SOC_MT7620 = "y";
SERIAL_8250_CONSOLE = "y"; SERIAL_8250_CONSOLE = "y";
SERIAL_8250 = "y"; SERIAL_8250 = "y";
SERIAL_CORE_CONSOLE = "y"; SERIAL_CORE_CONSOLE = "y";
SERIAL_OF_PLATFORM = "y"; SERIAL_OF_PLATFORM = "y";
CONSOLE_LOGLEVEL_DEFAULT = "8"; CONSOLE_LOGLEVEL_DEFAULT = "8";
CONSOLE_LOGLEVEL_QUIET = "4"; CONSOLE_LOGLEVEL_QUIET = "4";
NET = "y"; NET = "y";
ETHERNET = "y"; ETHERNET = "y";
NET_VENDOR_RALINK = "y"; NET_VENDOR_RALINK = "y";
NET_RALINK_MDIO = "y"; NET_RALINK_MDIO = "y";
NET_RALINK_MDIO_MT7620 = "y"; NET_RALINK_MDIO_MT7620 = "y";
NET_RALINK_MT7620 = "y"; NET_RALINK_MT7620 = "y";
SWPHY = "y"; SWPHY = "y";
SPI = "y"; SPI = "y";
MTD_SPI_NOR = "y"; MTD_SPI_NOR = "y";
SPI_MT7621 = "y"; # } probably don't need both of these SPI_MT7621 = "y"; # } probably don't need both of these
SPI_RT2880 = "y"; # } SPI_RT2880 = "y"; # }
SPI_MASTER= "y"; SPI_MASTER = "y";
SPI_MEM= "y"; SPI_MEM = "y";
MTD = "y"; MTD = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs
EARLY_PRINTK = "y"; EARLY_PRINTK = "y";
NEW_LEDS = "y"; NEW_LEDS = "y";
LEDS_CLASS = "y"; # required by rt2x00lib LEDS_CLASS = "y"; # required by rt2x00lib
PRINTK_TIME = "y"; PRINTK_TIME = "y";
} // lib.optionalAttrs (config.system.service ? vlan) { }
SWCONFIG = "y"; // lib.optionalAttrs (config.system.service ? vlan) {
}; SWCONFIG = "y";
};
conditionalConfig = { conditionalConfig = {
WLAN = { WLAN = {
WLAN_VENDOR_RALINK = "y"; WLAN_VENDOR_RALINK = "y";

View File

@@ -4,7 +4,7 @@
config = "mipsel-unknown-linux-musl"; config = "mipsel-unknown-linux-musl";
gcc = { gcc = {
abi = "32"; abi = "32";
arch = "mips32"; # maybe mips_24kc- arch = "mips32"; # maybe mips_24kc-
}; };
}; };
}; };
@@ -37,21 +37,29 @@
''; '';
module = { pkgs, config, lib, lim, ...}: module =
{
pkgs,
config,
lib,
lim,
...
}:
let let
inherit (pkgs.liminix.services) oneshot; inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt; inherit (pkgs) openwrt;
mac80211 = pkgs.kmodloader.override { mac80211 = pkgs.kmodloader.override {
targets = ["mt7603e"]; targets = [ "mt7603e" ];
inherit (config.system.outputs) kernel; inherit (config.system.outputs) kernel;
}; };
wlan_firmware = pkgs.fetchurl { wlan_firmware = pkgs.fetchurl {
url = "https://github.com/openwrt/mt76/raw/f24b56f935392ca1d35fae5fd6e56ef9deda4aad/firmware/mt7628_e2.bin"; url = "https://github.com/openwrt/mt76/raw/f24b56f935392ca1d35fae5fd6e56ef9deda4aad/firmware/mt7628_e2.bin";
hash = "sha256:1dkhfznmdz6s50kwc841x3wj0h6zg6icg5g2bim9pvg66as2vmh9"; hash = "sha256:1dkhfznmdz6s50kwc841x3wj0h6zg6icg5g2bim9pvg66as2vmh9";
}; };
in { in
{
imports = [ imports = [
../../modules/arch/mipsel.nix ../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix ../../modules/outputs/tftpboot.nix
@@ -99,8 +107,12 @@
''; '';
down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset"; down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset";
}; };
in rec { in
eth = link.build { ifname = "eth0"; dependencies = [swconfig]; }; rec {
eth = link.build {
ifname = "eth0";
dependencies = [ swconfig ];
};
# lan and wan ports are both behind a switch on eth0 # lan and wan ports are both behind a switch on eth0
lan = vlan.build { lan = vlan.build {
ifname = "eth0.1"; ifname = "eth0.1";
@@ -129,58 +141,61 @@
extraPatchPhase = '' extraPatchPhase = ''
${openwrt.applyPatches.ramips} ${openwrt.applyPatches.ramips}
''; '';
config = { config =
{
RALINK = "y"; RALINK = "y";
PCI = "y"; PCI = "y";
SOC_MT7620 = "y"; SOC_MT7620 = "y";
SERIAL_8250_CONSOLE = "y"; SERIAL_8250_CONSOLE = "y";
SERIAL_8250 = "y"; SERIAL_8250 = "y";
SERIAL_CORE_CONSOLE = "y"; SERIAL_CORE_CONSOLE = "y";
SERIAL_OF_PLATFORM = "y"; SERIAL_OF_PLATFORM = "y";
CONSOLE_LOGLEVEL_DEFAULT = "8"; CONSOLE_LOGLEVEL_DEFAULT = "8";
CONSOLE_LOGLEVEL_QUIET = "4"; CONSOLE_LOGLEVEL_QUIET = "4";
MTD = "y"; MTD = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev
SPI = "y"; SPI = "y";
MTD_SPI_NOR = "y"; MTD_SPI_NOR = "y";
SPI_MT7621 = "y"; SPI_MT7621 = "y";
SPI_MASTER= "y"; SPI_MASTER = "y";
SPI_MEM= "y"; SPI_MEM = "y";
REGULATOR = "y"; REGULATOR = "y";
REGULATOR_FIXED_VOLTAGE = "y"; REGULATOR_FIXED_VOLTAGE = "y";
NET = "y"; NET = "y";
ETHERNET = "y"; ETHERNET = "y";
PHYLIB = "y"; PHYLIB = "y";
AT803X_PHY="y"; AT803X_PHY = "y";
FIXED_PHY="y"; FIXED_PHY = "y";
GENERIC_PHY="y"; GENERIC_PHY = "y";
NET_VENDOR_RALINK = "y"; NET_VENDOR_RALINK = "y";
NET_RALINK_RT3050 = "y"; NET_RALINK_RT3050 = "y";
NET_RALINK_SOC="y"; NET_RALINK_SOC = "y";
SWPHY = "y"; SWPHY = "y";
GPIOLIB="y"; GPIOLIB = "y";
GPIO_MT7621 = "y"; GPIO_MT7621 = "y";
PHY_RALINK_USB = "y"; PHY_RALINK_USB = "y";
EARLY_PRINTK = "y"; EARLY_PRINTK = "y";
PRINTK_TIME = "y"; PRINTK_TIME = "y";
} // lib.optionalAttrs (config.system.service ? vlan) { }
SWCONFIG = "y"; // lib.optionalAttrs (config.system.service ? vlan) {
} // lib.optionalAttrs (config.system.service ? watchdog) { SWCONFIG = "y";
RALINK_WDT = "y"; # watchdog }
MT7621_WDT = "y"; # or it might be this one // lib.optionalAttrs (config.system.service ? watchdog) {
}; RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};
conditionalConfig = { conditionalConfig = {
WLAN = { WLAN = {
WLAN_VENDOR_RALINK = "y"; WLAN_VENDOR_RALINK = "y";

File diff suppressed because it is too large Load Diff

View File

@@ -26,26 +26,32 @@
# this device is described by the "qemu" device # this device is described by the "qemu" device
installer = "vmroot"; installer = "vmroot";
module = { config, lim, ... }: { module =
imports = [ { config, lim, ... }:
../../modules/arch/aarch64.nix {
../families/qemu.nix imports = [
]; ../../modules/arch/aarch64.nix
kernel = { ../families/qemu.nix
config = { ];
VIRTUALIZATION = "y"; kernel = {
PCI_HOST_GENERIC="y"; config = {
VIRTUALIZATION = "y";
PCI_HOST_GENERIC = "y";
SERIAL_AMBA_PL011 = "y"; SERIAL_AMBA_PL011 = "y";
SERIAL_AMBA_PL011_CONSOLE = "y"; SERIAL_AMBA_PL011_CONSOLE = "y";
};
}; };
boot.commandLine = [
"console=ttyAMA0,38400"
];
hardware =
let
addr = lim.parseInt "0x40010000";
in
{
loadAddress = addr;
entryPoint = addr;
};
}; };
boot.commandLine = [
"console=ttyAMA0,38400"
];
hardware = let addr = lim.parseInt "0x40010000"; in {
loadAddress = addr;
entryPoint = addr;
};
};
} }

View File

@@ -5,7 +5,7 @@
{ {
system = { system = {
crossSystem = { crossSystem = {
config = "armv7l-unknown-linux-musleabihf"; config = "armv7l-unknown-linux-musleabihf";
}; };
}; };
@@ -24,30 +24,36 @@
''; '';
installer = "vmroot"; installer = "vmroot";
module = { config, lim, ... }: { module =
imports = [ { config, lim, ... }:
../../modules/arch/arm.nix {
../families/qemu.nix imports = [
]; ../../modules/arch/arm.nix
kernel = { ../families/qemu.nix
config = { ];
PCI_HOST_GENERIC = "y"; kernel = {
ARCH_VIRT = "y"; config = {
PCI_HOST_GENERIC = "y";
ARCH_VIRT = "y";
VFP = "y"; VFP = "y";
NEON = "y"; NEON = "y";
AEABI = "y"; AEABI = "y";
SERIAL_AMBA_PL011 = "y"; SERIAL_AMBA_PL011 = "y";
SERIAL_AMBA_PL011_CONSOLE = "y"; SERIAL_AMBA_PL011_CONSOLE = "y";
};
}; };
boot.commandLine = [
"console=ttyAMA0"
];
hardware =
let
addr = lim.parseInt "0x40008000";
in
{
loadAddress = addr;
entryPoint = addr;
};
}; };
boot.commandLine = [
"console=ttyAMA0"
];
hardware = let addr = lim.parseInt "0x40008000"; in {
loadAddress = addr;
entryPoint = addr;
};
};
} }

View File

@@ -7,7 +7,7 @@
config = "mips-unknown-linux-musl"; config = "mips-unknown-linux-musl";
gcc = { gcc = {
abi = "32"; abi = "32";
arch = "mips32"; # maybe mips_24kc- arch = "mips32"; # maybe mips_24kc-
}; };
}; };
}; };
@@ -36,41 +36,50 @@
in the Development manual. in the Development manual.
''; '';
module = { config, lib, lim, ... }: { module =
imports = [ {
../../modules/arch/mipseb.nix config,
../families/qemu.nix lib,
]; lim,
kernel = { ...
config = { }:
MIPS_MALTA= "y"; {
CPU_MIPS32_R2= "y"; imports = [
../../modules/arch/mipseb.nix
../families/qemu.nix
];
kernel = {
config = {
MIPS_MALTA = "y";
CPU_MIPS32_R2 = "y";
POWER_RESET = "y"; POWER_RESET = "y";
POWER_RESET_SYSCON = "y"; POWER_RESET_SYSCON = "y";
SERIAL_8250= "y"; SERIAL_8250 = "y";
SERIAL_8250_CONSOLE= "y"; SERIAL_8250_CONSOLE = "y";
};
};
hardware =
# from arch/mips/mti-malta/Platform:load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000
let addr = lim.parseInt "0x80100000";
in {
loadAddress = addr;
entryPoint = addr;
# Unlike the arm qemu targets, we need a static dts when
# running u-boot-using tests, qemu dumpdtb command doesn't
# work for this board. I am not at all sure this dts is
# *correct* but it does at least boot
dts = lib.mkForce {
src = "${config.system.outputs.kernel.modulesupport}/arch/mips/boot/dts/mti/malta.dts";
includePaths = [
"${config.system.outputs.kernel.modulesupport}/arch/mips/boot/dts/"
];
}; };
}; };
}; hardware =
# from arch/mips/mti-malta/Platform:load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000
let
addr = lim.parseInt "0x80100000";
in
{
loadAddress = addr;
entryPoint = addr;
# Unlike the arm qemu targets, we need a static dts when
# running u-boot-using tests, qemu dumpdtb command doesn't
# work for this board. I am not at all sure this dts is
# *correct* but it does at least boot
dts = lib.mkForce {
src = "${config.system.outputs.kernel.modulesupport}/arch/mips/boot/dts/mti/malta.dts";
includePaths = [
"${config.system.outputs.kernel.modulesupport}/arch/mips/boot/dts/"
];
};
};
};
} }

View File

@@ -33,16 +33,25 @@
}; };
}; };
module = {pkgs, config, lib, lim, ... }: module =
let firmware = pkgs.stdenv.mkDerivation { {
name = "wlan-firmware"; pkgs,
phases = ["installPhase"]; config,
installPhase = '' lib,
mkdir $out lim,
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out ...
''; }:
}; let
in { firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = [ "installPhase" ];
installPhase = ''
mkdir $out
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out
'';
};
in
{
imports = [ imports = [
../../modules/arch/mipsel.nix ../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix ../../modules/outputs/tftpboot.nix
@@ -53,273 +62,275 @@
extraPatchPhase = '' extraPatchPhase = ''
${pkgs.openwrt.applyPatches.ramips} ${pkgs.openwrt.applyPatches.ramips}
''; '';
config = { config =
# Initially taken from openwrt's ./target/linux/ramips/mt7621/config-5.15, {
# then tweaked here and there # Initially taken from openwrt's ./target/linux/ramips/mt7621/config-5.15,
ARCH_32BIT_OFF_T="y"; # then tweaked here and there
ARCH_HIBERNATION_POSSIBLE="y"; ARCH_32BIT_OFF_T = "y";
ARCH_KEEP_MEMBLOCK="y"; ARCH_HIBERNATION_POSSIBLE = "y";
ARCH_MMAP_RND_BITS_MAX="15"; ARCH_KEEP_MEMBLOCK = "y";
ARCH_MMAP_RND_COMPAT_BITS_MAX="15"; ARCH_MMAP_RND_BITS_MAX = "15";
ARCH_SUSPEND_POSSIBLE="y"; ARCH_MMAP_RND_COMPAT_BITS_MAX = "15";
AT803X_PHY="y"; ARCH_SUSPEND_POSSIBLE = "y";
BLK_MQ_PCI="y"; AT803X_PHY = "y";
BOARD_SCACHE="y"; BLK_MQ_PCI = "y";
CEVT_R4K="y"; BOARD_SCACHE = "y";
CLKSRC_MIPS_GIC="y"; CEVT_R4K = "y";
CLK_MT7621="y"; CLKSRC_MIPS_GIC = "y";
CLOCKSOURCE_WATCHDOG="y"; CLK_MT7621 = "y";
CLONE_BACKWARDS="y"; CLOCKSOURCE_WATCHDOG = "y";
CMDLINE_BOOL="y"; CLONE_BACKWARDS = "y";
COMMON_CLK="y"; CMDLINE_BOOL = "y";
COMPAT_32BIT_TIME="y"; COMMON_CLK = "y";
CPU_GENERIC_DUMP_TLB="y"; COMPAT_32BIT_TIME = "y";
CPU_HAS_DIEI="y"; CPU_GENERIC_DUMP_TLB = "y";
CPU_HAS_PREFETCH="y"; CPU_HAS_DIEI = "y";
CPU_HAS_RIXI="y"; CPU_HAS_PREFETCH = "y";
CPU_HAS_SYNC="y"; CPU_HAS_RIXI = "y";
CPU_LITTLE_ENDIAN="y"; CPU_HAS_SYNC = "y";
CPU_MIPS32="y"; CPU_LITTLE_ENDIAN = "y";
CPU_MIPS32_R2="y"; CPU_MIPS32 = "y";
CPU_MIPSR2="y"; CPU_MIPS32_R2 = "y";
CPU_MIPSR2_IRQ_EI="y"; CPU_MIPSR2 = "y";
CPU_MIPSR2_IRQ_VI="y"; CPU_MIPSR2_IRQ_EI = "y";
CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS="y"; CPU_MIPSR2_IRQ_VI = "y";
CPU_R4K_CACHE_TLB="y"; CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS = "y";
CPU_RMAP="y"; CPU_R4K_CACHE_TLB = "y";
CPU_SUPPORTS_32BIT_KERNEL="y"; CPU_RMAP = "y";
CPU_SUPPORTS_HIGHMEM="y"; CPU_SUPPORTS_32BIT_KERNEL = "y";
CPU_SUPPORTS_MSA="y"; CPU_SUPPORTS_HIGHMEM = "y";
CRC16="y"; CPU_SUPPORTS_MSA = "y";
CRYPTO_DEFLATE="y"; CRC16 = "y";
CRYPTO_HASH_INFO="y"; CRYPTO_DEFLATE = "y";
CRYPTO_LIB_BLAKE2S_GENERIC="y"; CRYPTO_HASH_INFO = "y";
CRYPTO_LIB_POLY1305_RSIZE="2"; CRYPTO_LIB_BLAKE2S_GENERIC = "y";
CRYPTO_LZO="y"; CRYPTO_LIB_POLY1305_RSIZE = "2";
CRYPTO_ZSTD="y"; CRYPTO_LZO = "y";
CSRC_R4K="y"; CRYPTO_ZSTD = "y";
DIMLIB="y"; CSRC_R4K = "y";
DMA_NONCOHERENT="y"; DIMLIB = "y";
DTB_RT_NONE="y"; DMA_NONCOHERENT = "y";
DTC="y"; DTB_RT_NONE = "y";
EARLY_PRINTK="y"; DTC = "y";
FIXED_PHY="y"; EARLY_PRINTK = "y";
FWNODE_MDIO="y"; FIXED_PHY = "y";
FW_LOADER_PAGED_BUF="y"; FWNODE_MDIO = "y";
GENERIC_ATOMIC64="y"; FW_LOADER_PAGED_BUF = "y";
GENERIC_CLOCKEVENTS="y"; GENERIC_ATOMIC64 = "y";
GENERIC_CMOS_UPDATE="y"; GENERIC_CLOCKEVENTS = "y";
GENERIC_CPU_AUTOPROBE="y"; GENERIC_CMOS_UPDATE = "y";
GENERIC_FIND_FIRST_BIT="y"; GENERIC_CPU_AUTOPROBE = "y";
GENERIC_GETTIMEOFDAY="y"; GENERIC_FIND_FIRST_BIT = "y";
GENERIC_IOMAP="y"; GENERIC_GETTIMEOFDAY = "y";
GENERIC_IRQ_CHIP="y"; GENERIC_IOMAP = "y";
GENERIC_IRQ_EFFECTIVE_AFF_MASK="y"; GENERIC_IRQ_CHIP = "y";
GENERIC_IRQ_SHOW="y"; GENERIC_IRQ_EFFECTIVE_AFF_MASK = "y";
GENERIC_LIB_ASHLDI3="y"; GENERIC_IRQ_SHOW = "y";
GENERIC_LIB_ASHRDI3="y"; GENERIC_LIB_ASHLDI3 = "y";
GENERIC_LIB_CMPDI2="y"; GENERIC_LIB_ASHRDI3 = "y";
GENERIC_LIB_LSHRDI3="y"; GENERIC_LIB_CMPDI2 = "y";
GENERIC_LIB_UCMPDI2="y"; GENERIC_LIB_LSHRDI3 = "y";
GENERIC_PCI_IOMAP="y"; GENERIC_LIB_UCMPDI2 = "y";
GENERIC_PHY="y"; GENERIC_PCI_IOMAP = "y";
GENERIC_PINCONF="y"; GENERIC_PHY = "y";
GENERIC_SCHED_CLOCK="y"; GENERIC_PINCONF = "y";
GENERIC_SMP_IDLE_THREAD="y"; GENERIC_SCHED_CLOCK = "y";
GENERIC_TIME_VSYSCALL="y"; GENERIC_SMP_IDLE_THREAD = "y";
GLOB="y"; GENERIC_TIME_VSYSCALL = "y";
GPIOLIB_IRQCHIP="y"; GLOB = "y";
GPIO_CDEV="y"; GPIOLIB_IRQCHIP = "y";
GPIO_GENERIC="y"; GPIO_CDEV = "y";
GPIO_MT7621="y"; GPIO_GENERIC = "y";
GRO_CELLS="y"; GPIO_MT7621 = "y";
HANDLE_DOMAIN_IRQ="y"; GRO_CELLS = "y";
HARDWARE_WATCHPOINTS="y"; HANDLE_DOMAIN_IRQ = "y";
HAS_DMA="y"; HARDWARE_WATCHPOINTS = "y";
HAS_IOMEM="y"; HAS_DMA = "y";
HAS_IOPORT_MAP="y"; HAS_IOMEM = "y";
I2C="y"; HAS_IOPORT_MAP = "y";
I2C_ALGOBIT="y"; I2C = "y";
I2C_BOARDINFO="y"; I2C_ALGOBIT = "y";
I2C_CHARDEV="y"; I2C_BOARDINFO = "y";
I2C_GPIO="y"; I2C_CHARDEV = "y";
I2C_MT7621="y"; I2C_GPIO = "y";
ICPLUS_PHY="y"; I2C_MT7621 = "y";
IRQCHIP="y"; ICPLUS_PHY = "y";
IRQ_DOMAIN="y"; IRQCHIP = "y";
IRQ_DOMAIN_HIERARCHY="y"; IRQ_DOMAIN = "y";
IRQ_FORCED_THREADING="y"; IRQ_DOMAIN_HIERARCHY = "y";
IRQ_MIPS_CPU="y"; IRQ_FORCED_THREADING = "y";
IRQ_WORK="y"; IRQ_MIPS_CPU = "y";
LIBFDT="y"; IRQ_WORK = "y";
LOCK_DEBUGGING_SUPPORT="y"; LIBFDT = "y";
LZO_COMPRESS="y"; LOCK_DEBUGGING_SUPPORT = "y";
LZO_DECOMPRESS="y"; LZO_COMPRESS = "y";
MDIO_BUS="y"; LZO_DECOMPRESS = "y";
MDIO_DEVICE="y"; MDIO_BUS = "y";
MDIO_DEVRES="y"; MDIO_DEVICE = "y";
MEDIATEK_GE_PHY="y"; MDIO_DEVRES = "y";
MEMFD_CREATE="y"; MEDIATEK_GE_PHY = "y";
MFD_SYSCON="y"; MEMFD_CREATE = "y";
MIGRATION="y"; MFD_SYSCON = "y";
MIKROTIK="y"; MIGRATION = "y";
MIKROTIK_RB_SYSFS="y"; MIKROTIK = "y";
MIPS="y"; MIKROTIK_RB_SYSFS = "y";
MIPS_ASID_BITS="8"; MIPS = "y";
MIPS_ASID_SHIFT="0"; MIPS_ASID_BITS = "8";
MIPS_CLOCK_VSYSCALL="y"; MIPS_ASID_SHIFT = "0";
MIPS_CM="y"; MIPS_CLOCK_VSYSCALL = "y";
MIPS_CPC="y"; MIPS_CM = "y";
MIPS_CPS="y"; MIPS_CPC = "y";
MIPS_CPU_SCACHE="y"; MIPS_CPS = "y";
MIPS_GIC="y"; MIPS_CPU_SCACHE = "y";
MIPS_L1_CACHE_SHIFT="5"; MIPS_GIC = "y";
MIPS_LD_CAN_LINK_VDSO="y"; MIPS_L1_CACHE_SHIFT = "5";
MIPS_MT="y"; MIPS_LD_CAN_LINK_VDSO = "y";
MIPS_MT_FPAFF="y"; MIPS_MT = "y";
MIPS_MT_SMP="y"; MIPS_MT_FPAFF = "y";
MIPS_NR_CPU_NR_MAP="4"; MIPS_MT_SMP = "y";
MIPS_PERF_SHARED_TC_COUNTERS="y"; MIPS_NR_CPU_NR_MAP = "4";
MIPS_SPRAM="y"; MIPS_PERF_SHARED_TC_COUNTERS = "y";
MODULES_USE_ELF_REL="y"; MIPS_SPRAM = "y";
MTD_CMDLINE_PARTS="y"; MODULES_USE_ELF_REL = "y";
MTD_NAND_CORE="y"; MTD_CMDLINE_PARTS = "y";
MTD_NAND_ECC="y"; MTD_NAND_CORE = "y";
MTD_NAND_ECC_SW_HAMMING="y"; MTD_NAND_ECC = "y";
MTD_NAND_MT7621="y"; MTD_NAND_ECC_SW_HAMMING = "y";
MTD_NAND_MTK_BMT="y"; MTD_NAND_MT7621 = "y";
MTD_RAW_NAND="y"; MTD_NAND_MTK_BMT = "y";
MTD_ROUTERBOOT_PARTS="y"; MTD_RAW_NAND = "y";
MTD_SERCOMM_PARTS="y"; MTD_ROUTERBOOT_PARTS = "y";
MTD_SPI_NOR="y"; MTD_SERCOMM_PARTS = "y";
MTD_SPLIT_FIT_FW="y"; MTD_SPI_NOR = "y";
MTD_SPLIT_MINOR_FW="y"; MTD_SPLIT_FIT_FW = "y";
MTD_SPLIT_SEAMA_FW="y"; MTD_SPLIT_MINOR_FW = "y";
MTD_SPLIT_TPLINK_FW="y"; MTD_SPLIT_SEAMA_FW = "y";
MTD_SPLIT_TRX_FW="y"; MTD_SPLIT_TPLINK_FW = "y";
MTD_SPLIT_UIMAGE_FW="y"; MTD_SPLIT_TRX_FW = "y";
MTD_UBI="y"; MTD_SPLIT_UIMAGE_FW = "y";
MTD_UBI_BEB_LIMIT="20"; MTD_UBI = "y";
MTD_UBI_BLOCK="y"; MTD_UBI_BEB_LIMIT = "20";
MTD_UBI_WL_THRESHOLD="4096"; MTD_UBI_BLOCK = "y";
MTD_VIRT_CONCAT="y"; MTD_UBI_WL_THRESHOLD = "4096";
NEED_DMA_MAP_STATE="y"; MTD_VIRT_CONCAT = "y";
NET_DEVLINK="y"; NEED_DMA_MAP_STATE = "y";
NET_DSA="y"; NET_DEVLINK = "y";
NET_DSA_MT7530="y"; NET_DSA = "y";
NET_DSA_MT7530_MDIO="y"; NET_DSA_MT7530 = "y";
NET_DSA_TAG_MTK="y"; NET_DSA_MT7530_MDIO = "y";
NET_FLOW_LIMIT="y"; NET_DSA_TAG_MTK = "y";
NET_MEDIATEK_SOC="y"; NET_FLOW_LIMIT = "y";
NET_SELFTESTS="y"; NET_MEDIATEK_SOC = "y";
NET_SWITCHDEV="y"; NET_SELFTESTS = "y";
NET_VENDOR_MEDIATEK="y"; NET_SWITCHDEV = "y";
NO_HZ_COMMON="y"; NET_VENDOR_MEDIATEK = "y";
NO_HZ_IDLE="y"; NO_HZ_COMMON = "y";
NR_CPUS="4"; NO_HZ_IDLE = "y";
NVMEM="y"; NR_CPUS = "4";
OF="y"; NVMEM = "y";
OF_ADDRESS="y"; OF = "y";
OF_EARLY_FLATTREE="y"; OF_ADDRESS = "y";
OF_FLATTREE="y"; OF_EARLY_FLATTREE = "y";
OF_GPIO="y"; OF_FLATTREE = "y";
OF_IRQ="y"; OF_GPIO = "y";
OF_KOBJ="y"; OF_IRQ = "y";
OF_MDIO="y"; OF_KOBJ = "y";
PAGE_POOL="y"; OF_MDIO = "y";
PAGE_POOL_STATS="y"; PAGE_POOL = "y";
PCI="y"; PAGE_POOL_STATS = "y";
PCIE_MT7621="y"; PCI = "y";
PCI_DISABLE_COMMON_QUIRKS="y"; PCIE_MT7621 = "y";
PCI_DOMAINS="y"; PCI_DISABLE_COMMON_QUIRKS = "y";
PCI_DOMAINS_GENERIC="y"; PCI_DOMAINS = "y";
PCI_DRIVERS_GENERIC="y"; PCI_DOMAINS_GENERIC = "y";
PCS_MTK_LYNXI="y"; PCI_DRIVERS_GENERIC = "y";
PERF_USE_VMALLOC="y"; PCS_MTK_LYNXI = "y";
PGTABLE_LEVELS="2"; PERF_USE_VMALLOC = "y";
PHYLIB="y"; PGTABLE_LEVELS = "2";
PHYLINK="y"; PHYLIB = "y";
PHY_MT7621_PCI="y"; PHYLINK = "y";
PINCTRL="y"; PHY_MT7621_PCI = "y";
PINCTRL_AW9523="y"; PINCTRL = "y";
PINCTRL_MT7621="y"; PINCTRL_AW9523 = "y";
PINCTRL_RALINK="y"; PINCTRL_MT7621 = "y";
PINCTRL_SX150X="y"; PINCTRL_RALINK = "y";
POWER_RESET="y"; PINCTRL_SX150X = "y";
POWER_RESET_GPIO="y"; POWER_RESET = "y";
POWER_SUPPLY="y"; POWER_RESET_GPIO = "y";
PTP_1588_CLOCK_OPTIONAL="y"; POWER_SUPPLY = "y";
QUEUED_RWLOCKS="y"; PTP_1588_CLOCK_OPTIONAL = "y";
QUEUED_SPINLOCKS="y"; QUEUED_RWLOCKS = "y";
RALINK="y"; QUEUED_SPINLOCKS = "y";
RATIONAL="y"; RALINK = "y";
REGMAP="y"; RATIONAL = "y";
REGMAP_I2C="y"; REGMAP = "y";
REGMAP_MMIO="y"; REGMAP_I2C = "y";
REGULATOR="y"; REGMAP_MMIO = "y";
REGULATOR_FIXED_VOLTAGE="y"; REGULATOR = "y";
RESET_CONTROLLER="y"; REGULATOR_FIXED_VOLTAGE = "y";
RFS_ACCEL="y"; RESET_CONTROLLER = "y";
RPS="y"; RFS_ACCEL = "y";
RTC_CLASS="y"; RPS = "y";
RTC_DRV_BQ32K="y"; RTC_CLASS = "y";
RTC_DRV_PCF8563="y"; RTC_DRV_BQ32K = "y";
RTC_I2C_AND_SPI="y"; RTC_DRV_PCF8563 = "y";
SCHED_SMT="y"; RTC_I2C_AND_SPI = "y";
SERIAL_8250="y"; SCHED_SMT = "y";
SERIAL_8250_CONSOLE="y"; SERIAL_8250 = "y";
SERIAL_8250_NR_UARTS="3"; SERIAL_8250_CONSOLE = "y";
SERIAL_8250_RUNTIME_UARTS="3"; SERIAL_8250_NR_UARTS = "3";
SERIAL_MCTRL_GPIO="y"; SERIAL_8250_RUNTIME_UARTS = "3";
SERIAL_OF_PLATFORM="y"; SERIAL_MCTRL_GPIO = "y";
SGL_ALLOC="y"; SERIAL_OF_PLATFORM = "y";
SMP="y"; SGL_ALLOC = "y";
SMP_UP="y"; SMP = "y";
SOCK_RX_QUEUE_MAPPING="y"; SMP_UP = "y";
SOC_BUS="y"; SOCK_RX_QUEUE_MAPPING = "y";
SOC_MT7621="y"; SOC_BUS = "y";
SPI="y"; SOC_MT7621 = "y";
SPI_MASTER="y"; SPI = "y";
SPI_MEM="y"; SPI_MASTER = "y";
SPI_MT7621="y"; SPI_MEM = "y";
SRCU="y"; SPI_MT7621 = "y";
SWPHY="y"; SRCU = "y";
SYNC_R4K="y"; SWPHY = "y";
SYSCTL_EXCEPTION_TRACE="y"; SYNC_R4K = "y";
SYS_HAS_CPU_MIPS32_R1="y"; SYSCTL_EXCEPTION_TRACE = "y";
SYS_HAS_CPU_MIPS32_R2="y"; SYS_HAS_CPU_MIPS32_R1 = "y";
SYS_HAS_EARLY_PRINTK="y"; SYS_HAS_CPU_MIPS32_R2 = "y";
SYS_SUPPORTS_32BIT_KERNEL="y"; SYS_HAS_EARLY_PRINTK = "y";
SYS_SUPPORTS_ARBIT_HZ="y"; SYS_SUPPORTS_32BIT_KERNEL = "y";
SYS_SUPPORTS_HIGHMEM="y"; SYS_SUPPORTS_ARBIT_HZ = "y";
SYS_SUPPORTS_HOTPLUG_CPU="y"; SYS_SUPPORTS_HIGHMEM = "y";
SYS_SUPPORTS_LITTLE_ENDIAN="y"; SYS_SUPPORTS_HOTPLUG_CPU = "y";
SYS_SUPPORTS_MIPS16="y"; SYS_SUPPORTS_LITTLE_ENDIAN = "y";
SYS_SUPPORTS_MIPS_CPS="y"; SYS_SUPPORTS_MIPS16 = "y";
SYS_SUPPORTS_MULTITHREADING="y"; SYS_SUPPORTS_MIPS_CPS = "y";
SYS_SUPPORTS_SCHED_SMT="y"; SYS_SUPPORTS_MULTITHREADING = "y";
SYS_SUPPORTS_SMP="y"; SYS_SUPPORTS_SCHED_SMT = "y";
SYS_SUPPORTS_ZBOOT="y"; SYS_SUPPORTS_SMP = "y";
TARGET_ISA_REV="2"; SYS_SUPPORTS_ZBOOT = "y";
TICK_CPU_ACCOUNTING="y"; TARGET_ISA_REV = "2";
TIMER_OF="y"; TICK_CPU_ACCOUNTING = "y";
TIMER_PROBE="y"; TIMER_OF = "y";
TREE_RCU="y"; TIMER_PROBE = "y";
TREE_SRCU="y"; TREE_RCU = "y";
UBIFS_FS="y"; TREE_SRCU = "y";
USB_SUPPORT="y"; UBIFS_FS = "y";
USE_OF="y"; USB_SUPPORT = "y";
WEAK_ORDERING="y"; USE_OF = "y";
XPS="y"; WEAK_ORDERING = "y";
XXHASH="y"; XPS = "y";
ZLIB_DEFLATE="y"; XXHASH = "y";
ZLIB_INFLATE="y"; ZLIB_DEFLATE = "y";
ZSTD_COMPRESS="y"; ZLIB_INFLATE = "y";
ZSTD_DECOMPRESS="y"; ZSTD_COMPRESS = "y";
} // lib.optionalAttrs (config.system.service ? watchdog) { ZSTD_DECOMPRESS = "y";
RALINK_WDT = "y"; # watchdog }
MT7621_WDT = "y"; # or it might be this one // lib.optionalAttrs (config.system.service ? watchdog) {
}; RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};
conditionalConfig = { conditionalConfig = {
WLAN = { WLAN = {
MT7915E = "m"; MT7915E = "m";
@@ -340,97 +351,100 @@
}; };
}; };
filesystem = filesystem =
let inherit (pkgs.pseudofile) dir symlink; let
in inherit (pkgs.pseudofile) dir symlink;
dir { in
lib = dir { dir {
firmware = dir { lib = dir {
mediatek = symlink firmware; firmware = dir {
}; mediatek = symlink firmware;
};
};
hardware =
let
openwrt = pkgs.openwrt;
mac80211 = pkgs.kmodloader.override {
targets = [
"mt7915e"
];
inherit (config.system.outputs) kernel;
};
in {
# from OEM bootlog (openwrt wiki):
# 4 cmdlinepart partitions found on MTD device raspi
# Creating 4 MTD partitions on "raspi":
# 0x000000000000-0x000000040000 : "uboot"
# 0x000000040000-0x000000440000 : "uImage"
# 0x000000440000-0x000000ff0000 : "rootfs"
# 0x000000ff0000-0x000001000000 : "ART"
# from openwrt bootlog (openwrt wiki):
# 5 fixed-partitions partitions found on MTD device spi0.0
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# Creating 5 MTD partitions on "spi0.0":
# 0x000000000000-0x000000040000 : "u-boot"
# 0x000000040000-0x000000fa0000 : "firmware"
# 2 uimage-fw partitions found on MTD device firmware
# Creating 2 MTD partitions on "firmware":
# 0x000000000000-0x0000002c0000 : "kernel"
# 0x0000002c0000-0x000000f60000 : "rootfs"
# mtd: setting mtd3 (rootfs) as root device
# 1 squashfs-split partitions found on MTD device rootfs
# 0x000000640000-0x000000f60000 : "rootfs_data"
# 0x000000fa0000-0x000000fb0000 : "config"
# 0x000000fb0000-0x000000ff0000 : "tplink"
# 0x000000ff0000-0x000001000000 : "radio"
flash = {
# from the OEM bootlog 'Booting image at bc040000'
# (0x40000 from 0xbc000000)
address = lim.parseInt "0xbc040000";
# 0x000000040000-0x000000fa0000
size = lim.parseInt "0xf60000";
# TODO: find in /proc/mtd on a running system
eraseBlockSize = 65536;
};
# since this is mentioned in the partition table as well?
defaultOutput = "tplink-safeloader";
# taken from openwrt sysupgrade image:
# openwrt-23.05.2-ramips-mt7621-tplink_archer-ax23-v1-squashfs-sysupgrade.bin: u-boot legacy uImage, MIPS OpenWrt Linux-5.15.137, Linux/MIPS, OS Kernel Image (lzma), 2797386 bytes, Tue Nov 14 13:38:11 2023, Load Address: 0X80001000, Entry Point: 0X80001000, Header CRC: 0X19F74C5B, Data CRC: 0XF685563C
loadAddress = lim.parseInt "0x80001000";
entryPoint = lim.parseInt "0x80001000";
rootDevice = "/dev/mtdblock3";
dts = {
src = "${openwrt.src}/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts";
includePaths = [
"${openwrt.src}/target/linux/ramips/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
};
networkInterfaces =
let
inherit (config.system.service.network) link;
in rec {
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
wan = link.build { ifname = "wan"; };
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
}; };
}; };
}; };
};
hardware =
let
openwrt = pkgs.openwrt;
mac80211 = pkgs.kmodloader.override {
targets = [
"mt7915e"
];
inherit (config.system.outputs) kernel;
};
in
{
# from OEM bootlog (openwrt wiki):
# 4 cmdlinepart partitions found on MTD device raspi
# Creating 4 MTD partitions on "raspi":
# 0x000000000000-0x000000040000 : "uboot"
# 0x000000040000-0x000000440000 : "uImage"
# 0x000000440000-0x000000ff0000 : "rootfs"
# 0x000000ff0000-0x000001000000 : "ART"
# from openwrt bootlog (openwrt wiki):
# 5 fixed-partitions partitions found on MTD device spi0.0
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# Creating 5 MTD partitions on "spi0.0":
# 0x000000000000-0x000000040000 : "u-boot"
# 0x000000040000-0x000000fa0000 : "firmware"
# 2 uimage-fw partitions found on MTD device firmware
# Creating 2 MTD partitions on "firmware":
# 0x000000000000-0x0000002c0000 : "kernel"
# 0x0000002c0000-0x000000f60000 : "rootfs"
# mtd: setting mtd3 (rootfs) as root device
# 1 squashfs-split partitions found on MTD device rootfs
# 0x000000640000-0x000000f60000 : "rootfs_data"
# 0x000000fa0000-0x000000fb0000 : "config"
# 0x000000fb0000-0x000000ff0000 : "tplink"
# 0x000000ff0000-0x000001000000 : "radio"
flash = {
# from the OEM bootlog 'Booting image at bc040000'
# (0x40000 from 0xbc000000)
address = lim.parseInt "0xbc040000";
# 0x000000040000-0x000000fa0000
size = lim.parseInt "0xf60000";
# TODO: find in /proc/mtd on a running system
eraseBlockSize = 65536;
};
# since this is mentioned in the partition table as well?
defaultOutput = "tplink-safeloader";
# taken from openwrt sysupgrade image:
# openwrt-23.05.2-ramips-mt7621-tplink_archer-ax23-v1-squashfs-sysupgrade.bin: u-boot legacy uImage, MIPS OpenWrt Linux-5.15.137, Linux/MIPS, OS Kernel Image (lzma), 2797386 bytes, Tue Nov 14 13:38:11 2023, Load Address: 0X80001000, Entry Point: 0X80001000, Header CRC: 0X19F74C5B, Data CRC: 0XF685563C
loadAddress = lim.parseInt "0x80001000";
entryPoint = lim.parseInt "0x80001000";
rootDevice = "/dev/mtdblock3";
dts = {
src = "${openwrt.src}/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts";
includePaths = [
"${openwrt.src}/target/linux/ramips/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
};
networkInterfaces =
let
inherit (config.system.service.network) link;
in
rec {
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
wan = link.build { ifname = "wan"; };
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
};
};
};
}; };
} }

View File

@@ -153,11 +153,18 @@
}; };
}; };
module = {pkgs, config, lib, lim, ... }: module =
{
pkgs,
config,
lib,
lim,
...
}:
let let
inherit (pkgs.liminix.services) oneshot; inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix; inherit (pkgs) liminix;
mtd_by_name_links = pkgs.liminix.services.oneshot rec { mtd_by_name_links = pkgs.liminix.services.oneshot rec {
name = "mtd_by_name_links"; name = "mtd_by_name_links";
up = '' up = ''
mkdir -p /dev/mtd/by-name mkdir -p /dev/mtd/by-name
@@ -167,7 +174,8 @@
done done
''; '';
}; };
in { in
{
imports = [ imports = [
../../modules/arch/arm.nix ../../modules/arch/arm.nix
../../modules/outputs/tftpboot.nix ../../modules/outputs/tftpboot.nix
@@ -194,7 +202,7 @@
CPU_V7 = "y"; CPU_V7 = "y";
ARCH_MULTIPLATFORM = "y"; ARCH_MULTIPLATFORM = "y";
ARCH_MVEBU = "y"; ARCH_MVEBU = "y";
ARCH_MULTI_V7= "y"; ARCH_MULTI_V7 = "y";
PCI_MVEBU = "y"; PCI_MVEBU = "y";
AHCI_MVEBU = "y"; AHCI_MVEBU = "y";
@@ -204,7 +212,6 @@
EXPERT = "y"; EXPERT = "y";
ALLOW_DEV_COREDUMP = "n"; ALLOW_DEV_COREDUMP = "n";
# dts has a compatible for this but dmesg is not # dts has a compatible for this but dmesg is not
# showing it # showing it
EEPROM_AT24 = "y"; # atmel,24c64 EEPROM_AT24 = "y"; # atmel,24c64
@@ -215,44 +222,44 @@
MACH_ARMADA_38X = "y"; MACH_ARMADA_38X = "y";
SMP = "y"; SMP = "y";
# this is disabled for the moment because it relies on a # this is disabled for the moment because it relies on a
# GCC plugin that requires gmp.h to build, and I can't see # GCC plugin that requires gmp.h to build, and I can't see
# right now how to confgure it to find gmp # right now how to confgure it to find gmp
STACKPROTECTOR_PER_TASK = "n"; STACKPROTECTOR_PER_TASK = "n";
NR_CPUS = "4"; NR_CPUS = "4";
VFP = "y"; VFP = "y";
NEON= "y"; NEON = "y";
# WARNING: unmet direct dependencies detected for ARCH_WANT_LIBATA_LEDS # WARNING: unmet direct dependencies detected for ARCH_WANT_LIBATA_LEDS
ATA = "y"; ATA = "y";
BLOCK = "y"; BLOCK = "y";
MMC="y"; MMC = "y";
PWRSEQ_EMMC="y"; # ??? PWRSEQ_EMMC = "y"; # ???
PWRSEQ_SIMPLE="y"; # ??? PWRSEQ_SIMPLE = "y"; # ???
MMC_BLOCK="y"; MMC_BLOCK = "y";
MMC_SDHCI= "y"; MMC_SDHCI = "y";
MMC_SDHCI_PLTFM= "y"; MMC_SDHCI_PLTFM = "y";
MMC_SDHCI_PXAV3= "y"; MMC_SDHCI_PXAV3 = "y";
MMC_MVSDIO= "y"; MMC_MVSDIO = "y";
SERIAL_8250 = "y"; SERIAL_8250 = "y";
SERIAL_8250_CONSOLE = "y"; SERIAL_8250_CONSOLE = "y";
SERIAL_OF_PLATFORM="y"; SERIAL_OF_PLATFORM = "y";
SERIAL_MVEBU_UART = "y"; SERIAL_MVEBU_UART = "y";
SERIAL_MVEBU_CONSOLE = "y"; SERIAL_MVEBU_CONSOLE = "y";
SERIAL_8250_DMA= "y"; SERIAL_8250_DMA = "y";
SERIAL_8250_DW= "y"; SERIAL_8250_DW = "y";
SERIAL_8250_EXTENDED= "y"; SERIAL_8250_EXTENDED = "y";
SERIAL_8250_MANY_PORTS= "y"; SERIAL_8250_MANY_PORTS = "y";
SERIAL_8250_SHARE_IRQ= "y"; SERIAL_8250_SHARE_IRQ = "y";
OF_ADDRESS= "y"; OF_ADDRESS = "y";
OF_MDIO= "y"; OF_MDIO = "y";
WATCHDOG = "y"; # watchdog is enabled by u-boot WATCHDOG = "y"; # watchdog is enabled by u-boot
ORION_WATCHDOG = "y"; # so is non-optional to keep feeding ORION_WATCHDOG = "y"; # so is non-optional to keep feeding
MVEBU_DEVBUS = "y"; # "Device Bus controller ... flash devices such as NOR, NAND, SRAM, and FPGA" MVEBU_DEVBUS = "y"; # "Device Bus controller ... flash devices such as NOR, NAND, SRAM, and FPGA"
MVMDIO = "y"; MVMDIO = "y";
@@ -306,13 +313,14 @@
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
firmware = pkgs.stdenv.mkDerivation { firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware"; name = "wlan-firmware";
phases = ["installPhase"]; phases = [ "installPhase" ];
installPhase = '' installPhase = ''
mkdir $out mkdir $out
cp -r ${pkgs.linux-firmware}/lib/firmware/ath10k/QCA988X $out cp -r ${pkgs.linux-firmware}/lib/firmware/ath10k/QCA988X $out
''; '';
}; };
in dir { in
dir {
lib = dir { lib = dir {
firmware = dir { firmware = dir {
ath10k = symlink firmware; ath10k = symlink firmware;
@@ -320,10 +328,12 @@
}; };
etc = dir { etc = dir {
"fw_env.config" = "fw_env.config" =
let f = pkgs.writeText "fw_env.config" '' let
/dev/mtd/by-name/u-boot-env 0x0 0x10000 0x10000 f = pkgs.writeText "fw_env.config" ''
''; /dev/mtd/by-name/u-boot-env 0x0 0x10000 0x10000
in symlink f; '';
in
symlink f;
}; };
}; };
@@ -333,75 +343,81 @@
compressRoot = true; compressRoot = true;
}; };
hardware = let hardware =
mac80211 = pkgs.kmodloader.override { let
inherit (config.system.outputs) kernel; mac80211 = pkgs.kmodloader.override {
targets = ["ath9k" "ath10k_pci"]; inherit (config.system.outputs) kernel;
}; targets = [
in { "ath9k"
defaultOutput = "updater"; "ath10k_pci"
loadAddress = lim.parseInt "0x00800000"; # "0x00008000"; ];
entryPoint = lim.parseInt "0x00800000"; # "0x00008000";
rootDevice = "/dev/mmcblk0p1";
dts = {
src = "${config.system.outputs.kernel.modulesupport}/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts";
includePaths = [
"${config.system.outputs.kernel.modulesupport}/arch/arm/boot/dts/marvell/"
];
};
flash.eraseBlockSize = 65536; # only used for tftpboot
networkInterfaces =
let
inherit (config.system.service.network) link;
in rec {
en70000 = link.build {
# in armada-38x.dtsi this is eth0.
# It's connected to port 5 of the 88E6176 switch
devpath = "/devices/platform/soc/soc:internal-regs/f1070000.ethernet";
# name is unambiguous but not very semantic
ifname = "en70000";
};
en30000 = link.build {
# in armada-38x.dtsi this is eth1
# It's connected to port 6 of the 88E6176 switch
devpath = "/devices/platform/soc/soc:internal-regs/f1030000.ethernet";
# name is unambiguous but not very semantic
ifname = "en30000";
};
# the default (from the dts? I'm guessing) behavour for
# lan ports on the switch is to attach them to
# en30000. It should be possible to do something better,
# per
# https://www.kernel.org/doc/html/latest/networking/dsa/configuration.html#affinity-of-user-ports-to-cpu-ports
# but apparently OpenWrt doesn't either so maybe it's more
# complicated than it looks.
wan = link.build {
# in armada-38x.dtsi this is eth2. It may be connected to
# an ethernet phy or to the SFP cage, depending on a gpio
devpath = "/devices/platform/soc/soc:internal-regs/f1034000.ethernet";
ifname = "wan";
};
lan0 = link.build { ifname = "lan0"; };
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
lan5 = link.build { ifname = "lan5"; };
lan = lan0; # maybe we should build a bridge?
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
}; };
}; in
{
defaultOutput = "updater";
loadAddress = lim.parseInt "0x00800000"; # "0x00008000";
entryPoint = lim.parseInt "0x00800000"; # "0x00008000";
rootDevice = "/dev/mmcblk0p1";
dts = {
src = "${config.system.outputs.kernel.modulesupport}/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts";
includePaths = [
"${config.system.outputs.kernel.modulesupport}/arch/arm/boot/dts/marvell/"
];
};
flash.eraseBlockSize = 65536; # only used for tftpboot
networkInterfaces =
let
inherit (config.system.service.network) link;
in
rec {
en70000 = link.build {
# in armada-38x.dtsi this is eth0.
# It's connected to port 5 of the 88E6176 switch
devpath = "/devices/platform/soc/soc:internal-regs/f1070000.ethernet";
# name is unambiguous but not very semantic
ifname = "en70000";
};
en30000 = link.build {
# in armada-38x.dtsi this is eth1
# It's connected to port 6 of the 88E6176 switch
devpath = "/devices/platform/soc/soc:internal-regs/f1030000.ethernet";
# name is unambiguous but not very semantic
ifname = "en30000";
};
# the default (from the dts? I'm guessing) behavour for
# lan ports on the switch is to attach them to
# en30000. It should be possible to do something better,
# per
# https://www.kernel.org/doc/html/latest/networking/dsa/configuration.html#affinity-of-user-ports-to-cpu-ports
# but apparently OpenWrt doesn't either so maybe it's more
# complicated than it looks.
wan = link.build {
# in armada-38x.dtsi this is eth2. It may be connected to
# an ethernet phy or to the SFP cage, depending on a gpio
devpath = "/devices/platform/soc/soc:internal-regs/f1034000.ethernet";
ifname = "wan";
};
lan0 = link.build { ifname = "lan0"; };
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
lan5 = link.build { ifname = "lan5"; };
lan = lan0; # maybe we should build a bridge?
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
};
};
}; };
}; };
} }

View File

@@ -4,7 +4,7 @@
config = "mipsel-unknown-linux-musl"; config = "mipsel-unknown-linux-musl";
gcc = { gcc = {
abi = "32"; abi = "32";
arch = "mips32"; # mips32r2? arch = "mips32"; # mips32r2?
}; };
}; };
}; };
@@ -101,7 +101,14 @@
''; '';
module = { pkgs, config, lib, lim, ...}: module =
{
pkgs,
config,
lib,
lim,
...
}:
let let
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt; inherit (pkgs) openwrt;
@@ -123,7 +130,8 @@
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_rom_patch.bin"; url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_rom_patch.bin";
hash = "sha256-ifriAjWzFACrxVWCANZpUaEZgB/0pdbhnTVQytx6ddg="; hash = "sha256-ifriAjWzFACrxVWCANZpUaEZgB/0pdbhnTVQytx6ddg=";
}; };
in { in
{
imports = [ imports = [
# We include it to ensure the bridge functionality # We include it to ensure the bridge functionality
# is available on the target kernel. # is available on the target kernel.
@@ -201,7 +209,8 @@
networkInterfaces = networkInterfaces =
let let
inherit (config.system.service.network) link; inherit (config.system.service.network) link;
in { in
{
eth = link.build { ifname = "eth0"; }; eth = link.build { ifname = "eth0"; };
lan = link.build { ifname = "lan"; }; lan = link.build { ifname = "lan"; };
wlan0 = link.build { wlan0 = link.build {
@@ -253,107 +262,110 @@
extraPatchPhase = '' extraPatchPhase = ''
${openwrt.applyPatches.ramips} ${openwrt.applyPatches.ramips}
''; '';
config = { config =
{
RALINK = "y"; RALINK = "y";
PCI = "y"; PCI = "y";
PHY_MT7621_PCI = "y"; PHY_MT7621_PCI = "y";
PCIE_MT7621 = "y"; PCIE_MT7621 = "y";
SOC_MT7621 = "y"; SOC_MT7621 = "y";
CLK_MT7621 = "y"; CLK_MT7621 = "y";
CLOCKSOURCE_WATCHDOG = "y"; CLOCKSOURCE_WATCHDOG = "y";
SERIAL_8250_CONSOLE = "y"; SERIAL_8250_CONSOLE = "y";
SERIAL_8250 = "y"; SERIAL_8250 = "y";
SERIAL_CORE_CONSOLE = "y"; SERIAL_CORE_CONSOLE = "y";
SERIAL_OF_PLATFORM = "y"; SERIAL_OF_PLATFORM = "y";
SERIAL_8250_NR_UARTS = "3"; SERIAL_8250_NR_UARTS = "3";
SERIAL_8250_RUNTIME_UARTS = "3"; SERIAL_8250_RUNTIME_UARTS = "3";
SERIAL_MCTRL_GPIO = "y"; SERIAL_MCTRL_GPIO = "y";
CONSOLE_LOGLEVEL_DEFAULT = "8"; CONSOLE_LOGLEVEL_DEFAULT = "8";
CONSOLE_LOGLEVEL_QUIET = "4"; CONSOLE_LOGLEVEL_QUIET = "4";
# MTD_UBI_BEB_LIMIT = "20"; # MTD_UBI_BEB_LIMIT = "20";
# MTD_UBI_WL_THRESHOLD = "4096"; # MTD_UBI_WL_THRESHOLD = "4096";
MTD = "y"; MTD = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev
MTD_RAW_NAND = "y"; MTD_RAW_NAND = "y";
MTD_NAND_MT7621 = "y"; MTD_NAND_MT7621 = "y";
MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table
MTD_NAND_ECC_SW_HAMMING= "y"; MTD_NAND_ECC_SW_HAMMING = "y";
MTD_SPI_NAND= "y"; MTD_SPI_NAND = "y";
MTD_OF_PARTS = "y"; MTD_OF_PARTS = "y";
MTD_NAND_CORE= "y"; MTD_NAND_CORE = "y";
MTD_SPLIT_FIRMWARE= "y"; MTD_SPLIT_FIRMWARE = "y";
MTD_SPLIT_FIT_FW= "y"; MTD_SPLIT_FIT_FW = "y";
PINCTRL = "y"; PINCTRL = "y";
PINCTRL_MT7621 = "y"; PINCTRL_MT7621 = "y";
I2C = "y"; I2C = "y";
I2C_MT7621 = "y"; I2C_MT7621 = "y";
SPI = "y"; SPI = "y";
MTD_SPI_NOR = "y"; MTD_SPI_NOR = "y";
SPI_MT7621 = "y"; SPI_MT7621 = "y";
SPI_MASTER = "y"; SPI_MASTER = "y";
SPI_MEM = "y"; SPI_MEM = "y";
REGULATOR = "y"; REGULATOR = "y";
REGULATOR_FIXED_VOLTAGE = "y"; REGULATOR_FIXED_VOLTAGE = "y";
RESET_CONTROLLER = "y"; RESET_CONTROLLER = "y";
POWER_RESET = "y"; POWER_RESET = "y";
POWER_RESET_GPIO = "y"; POWER_RESET_GPIO = "y";
POWER_SUPPLY = "y"; POWER_SUPPLY = "y";
LED_TRIGGER_PHY = "y"; LED_TRIGGER_PHY = "y";
PCI_DISABLE_COMMON_QUIRKS = "y"; PCI_DISABLE_COMMON_QUIRKS = "y";
PCI_DOMAINS = "y"; PCI_DOMAINS = "y";
PCI_DOMAINS_GENERIC = "y"; PCI_DOMAINS_GENERIC = "y";
PCI_DRIVERS_GENERIC = "y"; PCI_DRIVERS_GENERIC = "y";
PCS_MTK_LYNXI = "y"; PCS_MTK_LYNXI = "y";
SOC_BUS = "y"; SOC_BUS = "y";
NET = "y"; NET = "y";
ETHERNET = "y"; ETHERNET = "y";
WLAN = "y"; WLAN = "y";
PHYLIB = "y"; PHYLIB = "y";
AT803X_PHY = "y"; AT803X_PHY = "y";
FIXED_PHY = "y"; FIXED_PHY = "y";
GENERIC_PHY = "y"; GENERIC_PHY = "y";
NET_DSA = "y"; NET_DSA = "y";
NET_DSA_MT7530 = "y"; NET_DSA_MT7530 = "y";
NET_DSA_MT7530_MDIO = "y"; NET_DSA_MT7530_MDIO = "y";
NET_DSA_TAG_MTK = "y"; NET_DSA_TAG_MTK = "y";
NET_MEDIATEK_SOC = "y"; NET_MEDIATEK_SOC = "y";
NET_SWITCHDEV = "y"; NET_SWITCHDEV = "y";
NET_VENDOR_MEDIATEK = "y"; NET_VENDOR_MEDIATEK = "y";
SWPHY = "y"; SWPHY = "y";
GPIOLIB = "y"; GPIOLIB = "y";
GPIO_MT7621 = "y"; GPIO_MT7621 = "y";
OF_GPIO = "y"; OF_GPIO = "y";
EARLY_PRINTK = "y"; EARLY_PRINTK = "y";
NEW_LEDS = "y"; NEW_LEDS = "y";
LEDS_TRIGGERS = "y"; LEDS_TRIGGERS = "y";
LEDS_CLASS = "y"; # required by rt2x00lib LEDS_CLASS = "y"; # required by rt2x00lib
LEDS_CLASS_MULTICOLOR = "y"; LEDS_CLASS_MULTICOLOR = "y";
LEDS_BRIGHTNESS_HW_CHANGED = "y"; LEDS_BRIGHTNESS_HW_CHANGED = "y";
PRINTK_TIME = "y"; PRINTK_TIME = "y";
} // lib.optionalAttrs (config.system.service ? vlan) { }
SWCONFIG = "y"; // lib.optionalAttrs (config.system.service ? vlan) {
} // lib.optionalAttrs (config.system.service ? watchdog) { SWCONFIG = "y";
RALINK_WDT = "y"; # watchdog }
MT7621_WDT = "y"; # or it might be this one // lib.optionalAttrs (config.system.service ? watchdog) {
}; RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};
}; };
}; };
} }

View File

@@ -1,4 +1,8 @@
{ eval, lib, pkgs }: {
eval,
lib,
pkgs,
}:
let let
conf = eval.config; conf = eval.config;
rootDir = builtins.toPath ./..; rootDir = builtins.toPath ./..;
@@ -7,21 +11,24 @@ let
inherit name; inherit name;
description = opt.description or null; description = opt.description or null;
default = opt.default or null; default = opt.default or null;
visible = visible = if (opt ? visible && opt.visible == "shallow") then true else opt.visible or true;
if (opt ? visible && opt.visible == "shallow")
then true
else opt.visible or true;
readOnly = opt.readOnly or false; readOnly = opt.readOnly or false;
type = opt.type.description or "unspecified"; type = opt.type.description or "unspecified";
}; };
spliceServiceDefn = item : spliceServiceDefn =
if item.type == "parametrisable s6-rc service definition" item:
then if item.type == "parametrisable s6-rc service definition" then
let sd = lib.attrByPath item.loc ["not found"] conf; let
in item // { sd = lib.attrByPath item.loc [ "not found" ] conf;
declarations = map stripAnyPrefixes item.declarations; in
item
// {
declarations = map stripAnyPrefixes item.declarations;
parameters = parameters =
let x = lib.mapAttrsToList optToDoc sd.parameters; in x; let
x = lib.mapAttrsToList optToDoc sd.parameters;
in
x;
} }
else else
item // { declarations = map stripAnyPrefixes item.declarations; }; item // { declarations = map stripAnyPrefixes item.declarations; };

View File

@@ -7,7 +7,7 @@ let
n: n:
let let
d = import ../devices/${n}/default.nix; d = import ../devices/${n}/default.nix;
tag = ".. _${lib.strings.replaceStrings [" "] ["-"] n}:"; tag = ".. _${lib.strings.replaceStrings [ " " ] [ "-" ] n}:";
d' = { d' = {
description = '' description = ''
${n} ${n}
@@ -15,7 +15,7 @@ let
''; '';
} // d; } // d;
in in
"${tag}\n\n${d'.description}" "${tag}\n\n${d'.description}"
) devices; ) devices;
in in
writeText "hwdoc" '' writeText "hwdoc" ''

View File

@@ -9,13 +9,15 @@
pkgs, pkgs,
lib, lib,
... ...
}: let }:
let
secrets = import ./extneder-secrets.nix; secrets = import ./extneder-secrets.nix;
inherit (pkgs.liminix.services) oneshot longrun target; inherit (pkgs.liminix.services) oneshot longrun target;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) writeText serviceFns; inherit (pkgs) writeText serviceFns;
svc = config.system.service; svc = config.system.service;
in rec { in
rec {
boot = { boot = {
tftp = { tftp = {
serverip = "10.0.0.1"; serverip = "10.0.0.1";
@@ -34,10 +36,11 @@ in rec {
]; ];
hostname = "arhcive"; hostname = "arhcive";
services.dhcpc = services.dhcpc =
let iface = config.hardware.networkInterfaces.lan; let
in svc.network.dhcp.client.build { iface = config.hardware.networkInterfaces.lan;
in
svc.network.dhcp.client.build {
interface = iface; interface = iface;
dependencies = [ config.services.hostname ]; dependencies = [ config.services.hostname ];
}; };
@@ -45,7 +48,10 @@ in rec {
services.sshd = svc.ssh.build { }; services.sshd = svc.ssh.build { };
services.watchdog = svc.watchdog.build { services.watchdog = svc.watchdog.build {
watched = with config.services ; [ sshd dhcpc ]; watched = with config.services; [
sshd
dhcpc
];
}; };
services.resolvconf = oneshot rec { services.resolvconf = oneshot rec {
@@ -63,17 +69,20 @@ in rec {
etc = dir { etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf"; "resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
}; };
srv = dir {}; srv = dir { };
}; };
services.defaultroute4 = svc.network.route.build { services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.dhcpc} router)"; via = "$(output ${services.dhcpc} router)";
target = "default"; target = "default";
dependencies = [services.dhcpc]; dependencies = [ services.dhcpc ];
}; };
programs.busybox = { programs.busybox = {
applets = ["lsusb" "tar"]; applets = [
"lsusb"
"tar"
];
options = { options = {
FEATURE_LS_TIMESTAMPS = "y"; FEATURE_LS_TIMESTAMPS = "y";
FEATURE_LS_SORTFILES = "y"; FEATURE_LS_SORTFILES = "y";
@@ -108,7 +117,8 @@ in rec {
gid = backup gid = backup
secrets file = ${secrets_file}/.outputs/secrets secrets file = ${secrets_file}/.outputs/secrets
''; '';
in longrun { in
longrun {
name = "rsync"; name = "rsync";
run = '' run = ''
${pkgs.rsyncSmall}/bin/rsync --no-detach --daemon --config=${configFile} ${pkgs.rsyncSmall}/bin/rsync --no-detach --daemon --config=${configFile}

View File

@@ -14,7 +14,8 @@ let
ipv4LocalNet = "10.8.0"; ipv4LocalNet = "10.8.0";
svc = config.system.service; svc = config.system.service;
in rec { in
rec {
boot = { boot = {
tftp = { tftp = {
freeSpaceBytes = 3 * 1024 * 1024; freeSpaceBytes = 3 * 1024 * 1024;
@@ -99,8 +100,10 @@ in rec {
}; };
services.dns = services.dns =
let interface = services.int; let
in svc.dnsmasq.build { interface = services.int;
in
svc.dnsmasq.build {
resolvconf = services.resolvconf; resolvconf = services.resolvconf;
inherit interface; inherit interface;
ranges = [ ranges = [
@@ -124,12 +127,16 @@ in rec {
services.wan = svc.pppoe.build { services.wan = svc.pppoe.build {
interface = config.hardware.networkInterfaces.wan; interface = config.hardware.networkInterfaces.wan;
ppp-options = [ ppp-options = [
"debug" "+ipv6" "noauth" "debug"
"+ipv6"
"noauth"
# EDIT: change the strings "chap-username" # EDIT: change the strings "chap-username"
# and "chap-secret" to match the username/password # and "chap-secret" to match the username/password
# provided by your ISP for PPP logins # provided by your ISP for PPP logins
"name" "chap-username" "name"
"password" "chap-secret" "chap-username"
"password"
"chap-secret"
]; ];
}; };
@@ -146,8 +153,10 @@ in rec {
}; };
filesystem = filesystem =
let inherit (pkgs.pseudofile) dir symlink; let
in dir { inherit (pkgs.pseudofile) dir symlink;
in
dir {
etc = dir { etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf"; "resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
}; };
@@ -176,10 +185,12 @@ in rec {
# LAN interfaces respectively. # LAN interfaces respectively.
services.dhcp6c = services.dhcp6c =
let client = svc.dhcp6c.client.build { let
interface = services.wan; client = svc.dhcp6c.client.build {
}; interface = services.wan;
in bundle { };
in
bundle {
name = "dhcp6c"; name = "dhcp6c";
contents = [ contents = [
(svc.dhcp6c.prefix.build { (svc.dhcp6c.prefix.build {

View File

@@ -10,10 +10,12 @@
lib, lib,
modulesPath, modulesPath,
... ...
}: let }:
let
secrets = import ./extneder-secrets.nix; secrets = import ./extneder-secrets.nix;
svc = config.system.service; svc = config.system.service;
in rec { in
rec {
boot = { boot = {
tftp = { tftp = {
serverip = "192.168.8.148"; serverip = "192.168.8.148";
@@ -30,7 +32,7 @@ in rec {
hostname = "extneder"; hostname = "extneder";
profile.wap = { profile.wap = {
interfaces = with config.hardware.networkInterfaces; [ interfaces = with config.hardware.networkInterfaces; [
lan lan
wlan wlan
]; ];
@@ -47,7 +49,12 @@ in rec {
}; };
}; };
services.sshd = svc.ssh.build {}; services.sshd = svc.ssh.build { };
users.root.passwd = lib.mkForce secrets.root.passwd; users.root.passwd = lib.mkForce secrets.root.passwd;
defaultProfile.packages = with pkgs; [nftables strace tcpdump swconfig]; defaultProfile.packages = with pkgs; [
nftables
strace
tcpdump
swconfig
];
} }

View File

@@ -1,8 +1,9 @@
{ config, pkgs, ... } : { config, pkgs, ... }:
let let
svc = config.system.service; svc = config.system.service;
in rec { in
rec {
imports = [ imports = [
../modules/network ../modules/network
../modules/ssh ../modules/ssh

View File

@@ -1,8 +1,9 @@
{ config, pkgs, ... } : { config, pkgs, ... }:
let let
svc = config.system.service; svc = config.system.service;
in rec { in
rec {
imports = [ imports = [
../modules/network ../modules/network
../modules/dnsmasq ../modules/dnsmasq
@@ -14,7 +15,9 @@ in rec {
# configure the internal network (LAN) with an address # configure the internal network (LAN) with an address
services.int = svc.network.address.build { services.int = svc.network.address.build {
interface = config.hardware.networkInterfaces.lan; interface = config.hardware.networkInterfaces.lan;
family = "inet"; address ="10.3.0.1"; prefixLength = 16; family = "inet";
address = "10.3.0.1";
prefixLength = 16;
}; };
services.sshd = svc.ssh.build { }; services.sshd = svc.ssh.build { };
@@ -26,8 +29,10 @@ in rec {
}; };
services.dns = services.dns =
let interface = services.int; let
in svc.dnsmasq.build { interface = services.int;
in
svc.dnsmasq.build {
inherit interface; inherit interface;
ranges = [ ranges = [
"10.3.0.10,10.3.0.240" "10.3.0.10,10.3.0.240"

View File

@@ -19,19 +19,21 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
let let
inherit (pkgs.liminix.services) longrun; inherit (pkgs.liminix.services) longrun;
inherit (pkgs) writeText; inherit (pkgs) writeText;
nginx_uid = 62; nginx_uid = 62;
in { in
{
config = { config = {
users.nginx = { users.nginx = {
uid = nginx_uid; gid= nginx_uid; uid = nginx_uid;
gid = nginx_uid;
dir = "/run/"; dir = "/run/";
shell = "/bin/false"; shell = "/bin/false";
}; };
groups.nginx = { groups.nginx = {
gid= nginx_uid; gid = nginx_uid;
usernames = ["nginx"]; usernames = [ "nginx" ];
}; };
services.sniproxy = services.sniproxy =
@@ -41,7 +43,8 @@ in {
zlib = null; zlib = null;
options = [ options = [
"stream" "stream"
"stream_ssl_module" "stream_ssl_preread_module" "stream_ssl_module"
"stream_ssl_preread_module"
"stream_map_module" "stream_map_module"
]; ];
}; };
@@ -71,8 +74,9 @@ in {
ssl_preread on; ssl_preread on;
} }
} }
''; '';
in longrun { in
longrun {
name = "sniproxy"; name = "sniproxy";
run = '' run = ''
${nginx}/bin/nginx -c ${conf} ${nginx}/bin/nginx -c ${conf}

View File

@@ -1,4 +1,4 @@
{ config, pkgs, ... } : { config, pkgs, ... }:
let let
inherit (pkgs.liminix.services) target; inherit (pkgs.liminix.services) target;
svc = config.system.service; svc = config.system.service;
@@ -43,13 +43,16 @@ let
he_oper_centr_freq_seg0_idx = 42; he_oper_centr_freq_seg0_idx = 42;
require_vht = 1; require_vht = 1;
}; };
mkWifiSta = params: interface: secrets: svc.hostapd.build { mkWifiSta =
inherit interface; params: interface: secrets:
svc.hostapd.build {
inherit interface;
params = params // { params = params // {
inherit (secrets) ssid wpa_passphrase; inherit (secrets) ssid wpa_passphrase;
}; };
}; };
in rec { in
rec {
imports = [ imports = [
../modules/wlan.nix ../modules/wlan.nix
../modules/network ../modules/network
@@ -87,8 +90,10 @@ in rec {
}; };
services.dhcpv4 = services.dhcpv4 =
let iface = services.int; let
in svc.network.dhcp.client.build { interface = iface; }; iface = services.int;
in
svc.network.dhcp.client.build { interface = iface; };
services.defaultroute4 = svc.network.route.build { services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.dhcpv4} address)"; via = "$(output ${services.dhcpv4} address)";
@@ -102,7 +107,9 @@ in rec {
}; };
services.ntp = config.system.service.ntp.build { services.ntp = config.system.service.ntp.build {
pools = { "pool.ntp.org" = ["iburst"] ; }; pools = {
"pool.ntp.org" = [ "iburst" ];
};
}; };
boot.tftp = { boot.tftp = {
@@ -113,7 +120,14 @@ in rec {
# wlan0 is the 2.4GHz interface. # wlan0 is the 2.4GHz interface.
services.hostap-1 = mkWifiSta baseParams config.hardware.networkInterfaces.wlan0 secrets-1; services.hostap-1 = mkWifiSta baseParams config.hardware.networkInterfaces.wlan0 secrets-1;
# wlan1 is the 5GHz interface, e.g. AX capable. # wlan1 is the 5GHz interface, e.g. AX capable.
services.hostap-2 = mkWifiSta (baseParams // modernParams) config.hardware.networkInterfaces.wlan1 secrets-2; services.hostap-2 = mkWifiSta (
baseParams // modernParams
) config.hardware.networkInterfaces.wlan1 secrets-2;
defaultProfile.packages = with pkgs; [ zyxel-bootconfig iw min-collect-garbage mtdutils ]; defaultProfile.packages = with pkgs; [
zyxel-bootconfig
iw
min-collect-garbage
mtdutils
];
} }

View File

@@ -1,4 +1,9 @@
{ config, pkgs, lib, ... } : {
config,
pkgs,
lib,
...
}:
let let
inherit (pkgs) serviceFns; inherit (pkgs) serviceFns;
svc = config.system.service; svc = config.system.service;
@@ -9,7 +14,8 @@ let
cd ${pkgs.util-linux-small}/bin cd ${pkgs.util-linux-small}/bin
cp fdisk sfdisk mkswap $out/bin cp fdisk sfdisk mkswap $out/bin
''; '';
in rec { in
rec {
imports = [ imports = [
../modules/network ../modules/network
../modules/ssh ../modules/ssh
@@ -67,19 +73,23 @@ in rec {
''; '';
}; };
services.growfs = let name = "growfs"; in oneshot { services.growfs =
inherit name; let
up = '' name = "growfs";
device=$(grep /persist /proc/1/mountinfo | cut -f9 -d' ') in
${pkgs.e2fsprogs}/bin/resize2fs $device oneshot {
''; inherit name;
}; up = ''
device=$(grep /persist /proc/1/mountinfo | cut -f9 -d' ')
${pkgs.e2fsprogs}/bin/resize2fs $device
'';
};
filesystem = dir { filesystem = dir {
etc = dir { etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf"; "resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
}; };
mnt = dir {}; mnt = dir { };
}; };
rootfsType = "ext4"; rootfsType = "ext4";
@@ -92,20 +102,20 @@ in rec {
# create this hashed password string # create this hashed password string
passwd = "$6$y7WZ5hM6l5nriLmo$5AJlmzQZ6WA.7uBC7S8L4o19ESR28Dg25v64/vDvvCN01Ms9QoHeGByj8lGlJ4/b.dbwR9Hq2KXurSnLigt1W1"; passwd = "$6$y7WZ5hM6l5nriLmo$5AJlmzQZ6WA.7uBC7S8L4o19ESR28Dg25v64/vDvvCN01Ms9QoHeGByj8lGlJ4/b.dbwR9Hq2KXurSnLigt1W1";
openssh.authorizedKeys.keys = openssh.authorizedKeys.keys =
let fromBuild = let
(builtins.readFile fromBuild = (
((builtins.toPath (builtins.getEnv "HOME")) + "/.ssh/authorized_keys") builtins.readFile ((builtins.toPath (builtins.getEnv "HOME")) + "/.ssh/authorized_keys")
); );
in lib.splitString "\n" fromBuild; in
lib.splitString "\n" fromBuild;
}; };
defaultProfile.packages = with pkgs; [ defaultProfile.packages = with pkgs; [
e2fsprogs # ext4 e2fsprogs # ext4
btrfs-progs btrfs-progs
mtdutils # mtd, jffs2, ubifs mtdutils # mtd, jffs2, ubifs
dtc # you never know when you might need device tree stuff dtc # you never know when you might need device tree stuff
some-util-linux some-util-linux
libubootenv # fw_{set,print}env libubootenv # fw_{set,print}env
pciutils pciutils

View File

@@ -4,7 +4,13 @@
# devices: mostly you will need to attend to the number of wlan and lan # devices: mostly you will need to attend to the number of wlan and lan
# interfaces # interfaces
{ config, pkgs, lib, modulesPath, ... } : {
config,
pkgs,
lib,
modulesPath,
...
}:
let let
secrets = { secrets = {
domainName = "fake.liminix.org"; domainName = "fake.liminix.org";
@@ -17,7 +23,8 @@ let
wmm_enabled = 1; wmm_enabled = 1;
}; };
in rec { in
rec {
boot = { boot = {
tftp = { tftp = {
freeSpaceBytes = 3 * 1024 * 1024; freeSpaceBytes = 3 * 1024 * 1024;
@@ -33,22 +40,26 @@ in rec {
profile.gateway = { profile.gateway = {
lan = { lan = {
interfaces = with config.hardware.networkInterfaces; interfaces = with config.hardware.networkInterfaces; [
[ # EDIT: these are the interfaces exposed by the gl.inet gl-ar750:
# EDIT: these are the interfaces exposed by the gl.inet gl-ar750: # if your device has more or differently named lan interfaces,
# if your device has more or differently named lan interfaces, # specify them here
# specify them here wlan
wlan wlan5 wlan5
lan lan
]; ];
inherit (secrets.lan) prefix; inherit (secrets.lan) prefix;
address = { address = {
family = "inet"; address ="${secrets.lan.prefix}.1"; prefixLength = 24; family = "inet";
address = "${secrets.lan.prefix}.1";
prefixLength = 24;
}; };
dhcp = { dhcp = {
start = 10; start = 10;
end = 240; end = 240;
hosts = { } // lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix); hosts =
{ }
// lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
localDomain = "lan"; localDomain = "lan";
}; };
}; };
@@ -95,8 +106,13 @@ in rec {
}; };
services.ntp = svc.ntp.build { services.ntp = svc.ntp.build {
pools = { "pool.ntp.org" = ["iburst"]; }; pools = {
makestep = { threshold = 1.0; limit = 3; }; "pool.ntp.org" = [ "iburst" ];
};
makestep = {
threshold = 1.0;
limit = 3;
};
}; };
services.sshd = svc.ssh.build { }; services.sshd = svc.ssh.build { };
@@ -113,7 +129,8 @@ in rec {
programs.busybox = { programs.busybox = {
applets = [ applets = [
"fdisk" "sfdisk" "fdisk"
"sfdisk"
]; ];
options = { options = {
FEATURE_FANCY_TAIL = "y"; FEATURE_FANCY_TAIL = "y";

View File

@@ -6,7 +6,8 @@
pkgs, pkgs,
lib, lib,
... ...
}: let }:
let
secrets = import ./extneder-secrets.nix; secrets = import ./extneder-secrets.nix;
rsecrets = import ./rotuer-secrets.nix; rsecrets = import ./rotuer-secrets.nix;
@@ -27,7 +28,10 @@
# to start l2tp unless the expected lns address is one of the # to start l2tp unless the expected lns address is one of the
# addresses returned. I think this satisfies "do check the DNS" # addresses returned. I think this satisfies "do check the DNS"
lns = { hostname = "l2tp.aaisp.net.uk"; address = "194.4.172.12"; }; lns = {
hostname = "l2tp.aaisp.net.uk";
address = "194.4.172.12";
};
inherit (pkgs.liminix.services) oneshot longrun target; inherit (pkgs.liminix.services) oneshot longrun target;
inherit (pkgs.liminix) outputRef; inherit (pkgs.liminix) outputRef;
@@ -39,7 +43,8 @@
inherit (rsecrets) wpa_passphrase; inherit (rsecrets) wpa_passphrase;
wmm_enabled = 1; wmm_enabled = 1;
}; };
in rec { in
rec {
boot = { boot = {
tftp = { tftp = {
serverip = "10.0.0.1"; serverip = "10.0.0.1";
@@ -62,7 +67,9 @@ in rec {
services.wan-address-for-secrets = svc.network.address.build { services.wan-address-for-secrets = svc.network.address.build {
interface = config.hardware.networkInterfaces.wan; interface = config.hardware.networkInterfaces.wan;
family = "inet"; address ="10.0.0.10"; prefixLength = 24; family = "inet";
address = "10.0.0.10";
prefixLength = 24;
}; };
services.secrets = svc.secrets.outboard.build { services.secrets = svc.secrets.outboard.build {
@@ -83,22 +90,26 @@ in rec {
profile.gateway = { profile.gateway = {
lan = { lan = {
interfaces = with config.hardware.networkInterfaces; interfaces = with config.hardware.networkInterfaces; [
[ # EDIT: these are the interfaces exposed by the gl.inet gl-ar750:
# EDIT: these are the interfaces exposed by the gl.inet gl-ar750: # if your device has more or differently named lan interfaces,
# if your device has more or differently named lan interfaces, # specify them here
# specify them here wlan
wlan wlan5 wlan5
lan lan
]; ];
inherit (rsecrets.lan) prefix; inherit (rsecrets.lan) prefix;
address = { address = {
family = "inet"; address ="${rsecrets.lan.prefix}.1"; prefixLength = 24; family = "inet";
address = "${rsecrets.lan.prefix}.1";
prefixLength = 24;
}; };
dhcp = { dhcp = {
start = 10; start = 10;
end = 240; end = 240;
hosts = { } // lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix); hosts =
{ }
// lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
localDomain = "lan"; localDomain = "lan";
}; };
}; };
@@ -107,7 +118,8 @@ in rec {
secret = outputRef config.services.secrets; secret = outputRef config.services.secrets;
username = secret "ppp/username"; username = secret "ppp/username";
password = secret "ppp/password"; password = secret "ppp/password";
in { in
{
interface = interface =
let let
pppoe = svc.pppoe.build { pppoe = svc.pppoe.build {
@@ -126,21 +138,29 @@ in rec {
route = svc.network.route.build { route = svc.network.route.build {
via = "$(output ${services.bootstrap-dhcpc} router)"; via = "$(output ${services.bootstrap-dhcpc} router)";
target = lns.address; target = lns.address;
dependencies = [services.bootstrap-dhcpc check-address]; dependencies = [
services.bootstrap-dhcpc
check-address
];
}; };
l2tpd= svc.l2tp.build { l2tpd = svc.l2tp.build {
lns = lns.address; lns = lns.address;
inherit username password; inherit username password;
dependencies = [config.services.lns-address route check-address]; dependencies = [
config.services.lns-address
route
check-address
];
}; };
in in
svc.health-check.build { svc.health-check.build {
service = l2tpd; service = l2tpd;
threshold = 3; threshold = 3;
interval = 2; interval = 2;
healthCheck = pkgs.writeAshScript "ping-check" {} "ping 1.1.1.1"; healthCheck = pkgs.writeAshScript "ping-check" { } "ping 1.1.1.1";
}; };
in svc.round-robin.build { in
svc.round-robin.build {
name = "wan"; name = "wan";
services = [ services = [
pppoe pppoe
@@ -151,27 +171,33 @@ in rec {
}; };
wireless.networks = { wireless.networks = {
"${rsecrets.ssid}" = { "${rsecrets.ssid}" =
interface = config.hardware.networkInterfaces.wlan; {
hw_mode = "g"; interface = config.hardware.networkInterfaces.wlan;
channel = "6"; hw_mode = "g";
ieee80211n = 1; channel = "6";
} // wirelessConfig // { ieee80211n = 1;
wpa_passphrase = outputRef config.services.secrets "wpa_passphrase"; }
}; // wirelessConfig
// {
wpa_passphrase = outputRef config.services.secrets "wpa_passphrase";
};
"${rsecrets.ssid}5" = rec { "${rsecrets.ssid}5" =
interface = config.hardware.networkInterfaces.wlan5; rec {
hw_mode = "a"; interface = config.hardware.networkInterfaces.wlan5;
channel = 36; hw_mode = "a";
ht_capab = "[HT40+]"; channel = 36;
vht_oper_chwidth = 1; ht_capab = "[HT40+]";
vht_oper_centr_freq_seg0_idx = channel + 6; vht_oper_chwidth = 1;
ieee80211n = 1; vht_oper_centr_freq_seg0_idx = channel + 6;
ieee80211ac = 1; ieee80211n = 1;
} // wirelessConfig // { ieee80211ac = 1;
wpa_passphrase = outputRef config.services.secrets "wpa_passphrase"; }
}; // wirelessConfig
// {
wpa_passphrase = outputRef config.services.secrets "wpa_passphrase";
};
}; };
}; };
@@ -184,23 +210,28 @@ in rec {
authorizedKeys = outputRef config.services.secrets "ssh/authorizedKeys"; authorizedKeys = outputRef config.services.secrets "ssh/authorizedKeys";
}; };
services.lns-address = let services.lns-address =
ns = "$(output_word ${services.bootstrap-dhcpc} dns 1)"; let
route-to-bootstrap-nameserver = svc.network.route.build { ns = "$(output_word ${services.bootstrap-dhcpc} dns 1)";
via = "$(output ${services.bootstrap-dhcpc} router)"; route-to-bootstrap-nameserver = svc.network.route.build {
target = ns; via = "$(output ${services.bootstrap-dhcpc} router)";
dependencies = [services.bootstrap-dhcpc]; target = ns;
dependencies = [ services.bootstrap-dhcpc ];
};
in
oneshot rec {
name = "resolve-l2tp-server";
dependencies = [
services.bootstrap-dhcpc
route-to-bootstrap-nameserver
];
up = ''
(in_outputs ${name}
DNSCACHEIP="${ns}" ${pkgs.s6-dns}/bin/s6-dnsip4 ${lns.hostname} \
> addresses
)
'';
}; };
in oneshot rec {
name = "resolve-l2tp-server";
dependencies = [ services.bootstrap-dhcpc route-to-bootstrap-nameserver ];
up = ''
(in_outputs ${name}
DNSCACHEIP="${ns}" ${pkgs.s6-dns}/bin/s6-dnsip4 ${lns.hostname} \
> addresses
)
'';
};
users.root = rsecrets.root; users.root = rsecrets.root;

View File

@@ -1,8 +1,14 @@
{ config, pkgs, lim, ... } : {
config,
pkgs,
lim,
...
}:
let let
svc = config.system.service; svc = config.system.service;
in rec { in
rec {
imports = [ imports = [
../modules/network ../modules/network
../modules/ssh ../modules/ssh
@@ -29,12 +35,14 @@ in rec {
hostname = "omnia"; hostname = "omnia";
services.hostap = services.hostap =
let secrets = { let
ssid = "not-the-internet"; secrets = {
channel = 4; ssid = "not-the-internet";
wpa_passphrase = "diamond dogs"; channel = 4;
}; wpa_passphrase = "diamond dogs";
in svc.hostapd.build { };
in
svc.hostapd.build {
interface = config.hardware.networkInterfaces.wlan; interface = config.hardware.networkInterfaces.wlan;
params = { params = {
country_code = "GB"; country_code = "GB";
@@ -51,12 +59,14 @@ in rec {
}; };
services.hostap5 = services.hostap5 =
let secrets = { let
ssid = "not-the-internet"; secrets = {
channel = 36; ssid = "not-the-internet";
wpa_passphrase = "diamond dogs"; channel = 36;
}; wpa_passphrase = "diamond dogs";
in svc.hostapd.build { };
in
svc.hostapd.build {
interface = config.hardware.networkInterfaces.wlan5; interface = config.hardware.networkInterfaces.wlan5;
params = { params = {
country_code = "GB"; country_code = "GB";
@@ -103,6 +113,7 @@ in rec {
}; };
defaultProfile.packages = with pkgs; [ defaultProfile.packages = with pkgs; [
figlet pciutils figlet
pciutils
]; ];
} }

View File

@@ -4,35 +4,35 @@
{ {
imports = [ imports = [
./base.nix ./base.nix
./bridge ./bridge
./busybox.nix ./busybox.nix
./dhcp6c ./dhcp6c
./dnsmasq ./dnsmasq
./firewall ./firewall
./hardware.nix ./hardware.nix
./hostapd ./hostapd
./hostname.nix ./hostname.nix
./kernel ./kernel
./mdevd.nix ./mdevd.nix
./mount ./mount
./network ./network
./ntp ./ntp
./outputs.nix ./outputs.nix
./outputs/ext4fs.nix ./outputs/ext4fs.nix
./outputs/initramfs.nix ./outputs/initramfs.nix
./outputs/jffs2.nix ./outputs/jffs2.nix
./outputs/mtdimage.nix ./outputs/mtdimage.nix
./outputs/tftpboot.nix ./outputs/tftpboot.nix
./outputs/ubifs.nix ./outputs/ubifs.nix
./outputs/ubimage.nix ./outputs/ubimage.nix
./outputs/vmroot.nix ./outputs/vmroot.nix
./ppp ./ppp
./ramdisk.nix ./ramdisk.nix
./ssh ./ssh
./users.nix ./users.nix
./vlan ./vlan
./watchdog ./watchdog
./wlan.nix ./wlan.nix
]; ];
} }

View File

@@ -1,12 +1,17 @@
{ lim, pkgs, config, ...}: {
lim,
pkgs,
config,
...
}:
{ {
config = { config = {
kernel.config = { kernel.config = {
CPU_LITTLE_ENDIAN= "y"; CPU_LITTLE_ENDIAN = "y";
CPU_BIG_ENDIAN= "n"; CPU_BIG_ENDIAN = "n";
# CMDLINE_FROM_BOOTLOADER availability is conditional # CMDLINE_FROM_BOOTLOADER availability is conditional
# on CMDLINE being set to something non-empty # on CMDLINE being set to something non-empty
CMDLINE="\"empty=false\""; CMDLINE = "\"empty=false\"";
CMDLINE_FROM_BOOTLOADER = "y"; CMDLINE_FROM_BOOTLOADER = "y";
OF = "y"; OF = "y";

View File

@@ -1,10 +1,15 @@
{ lim, pkgs, config, ...}: {
lim,
pkgs,
config,
...
}:
{ {
config = { config = {
kernel.config = { kernel.config = {
OF = "y"; OF = "y";
}; };
kernel.makeTargets = ["arch/arm/boot/zImage"]; kernel.makeTargets = [ "arch/arm/boot/zImage" ];
hardware.ram.startAddress = lim.parseInt "0x40000000"; hardware.ram.startAddress = lim.parseInt "0x40000000";
system.outputs.u-boot = pkgs.ubootQemuArm; system.outputs.u-boot = pkgs.ubootQemuArm;
}; };

View File

@@ -1,4 +1,4 @@
{ config, lim, ...}: { config, lim, ... }:
{ {
config = { config = {
kernel.config = { kernel.config = {

View File

@@ -1,4 +1,4 @@
{ pkgs, config, ...}: { pkgs, config, ... }:
{ {
imports = [ ./mips.nix ]; imports = [ ./mips.nix ];
config = { config = {

View File

@@ -1,4 +1,4 @@
{ config, ...}: { config, ... }:
{ {
imports = [ ./mips.nix ]; imports = [ ./mips.nix ];
config = { config = {

View File

@@ -1,15 +1,20 @@
## Base options ## Base options
## ============ ## ============
{
{ lib, pkgs, config, ...}: lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
type_service = pkgs.liminix.lib.types.service; type_service = pkgs.liminix.lib.types.service;
in { in
{
options = { options = {
defaultProfile = { defaultProfile = {
packages = mkOption { packages = mkOption {
@@ -109,8 +114,13 @@ in {
}; };
}; };
config = { config = {
defaultProfile.packages = with pkgs; defaultProfile.packages = with pkgs; [
[ s6 s6-init-bin execline s6-linux-init s6-rc ]; s6
s6-init-bin
execline
s6-linux-init
s6-rc
];
boot.commandLine = [ boot.commandLine = [
"panic=10 oops=panic init=/bin/init loglevel=8" "panic=10 oops=panic init=/bin/init loglevel=8"
@@ -119,69 +129,98 @@ in {
"fw_devlink=off" "fw_devlink=off"
] ++ lib.optional (config.rootOptions != null) "rootflags=${config.rootOptions}"; ] ++ lib.optional (config.rootOptions != null) "rootflags=${config.rootOptions}";
system.callService = path : parameters : system.callService =
path: parameters:
let let
typeChecked = caller: type: value: typeChecked =
caller: type: value:
let let
inherit (lib) types mergeDefinitions; inherit (lib) types mergeDefinitions;
defs = [{ file = caller; inherit value; }]; defs = [
{
file = caller;
inherit value;
}
];
type' = types.submodule { options = type; }; type' = types.submodule { options = type; };
in (mergeDefinitions [] type' defs).mergedValue; in
cp = lib.callPackageWith(pkgs // { svc = config.system.service; }); (mergeDefinitions [ ] type' defs).mergedValue;
pkg = cp path {}; cp = lib.callPackageWith (pkgs // { svc = config.system.service; });
checkTypes = t : p : typeChecked (builtins.toString path) t p; pkg = cp path { };
in { checkTypes = t: p: typeChecked (builtins.toString path) t p;
in
{
inherit parameters; inherit parameters;
build = { dependencies ? [], ... } @ args : build =
{
dependencies ? [ ],
...
}@args:
let let
s = pkg (checkTypes parameters s = pkg (checkTypes parameters (builtins.removeAttrs args [ "dependencies" ]));
(builtins.removeAttrs args ["dependencies"])); in
in s.overrideAttrs (o: { s.overrideAttrs (o: {
dependencies = dependencies ++ o.dependencies; dependencies = dependencies ++ o.dependencies;
buildInputs = dependencies ++ o.buildInputs; buildInputs = dependencies ++ o.buildInputs;
}); });
}; };
users.root = { users.root = {
uid = 0; gid= 0; gecos = "Root of all evaluation"; uid = 0;
gid = 0;
gecos = "Root of all evaluation";
dir = "/home/root/"; dir = "/home/root/";
passwd = lib.mkDefault ""; passwd = lib.mkDefault "";
shell = "/bin/sh"; shell = "/bin/sh";
}; };
groups = { groups = {
root = { root = {
gid = 0; usernames = ["root"]; gid = 0;
usernames = [ "root" ];
}; };
system = { system = {
gid = 1; usernames = ["root"]; gid = 1;
usernames = [ "root" ];
}; };
}; };
filesystem = dir { filesystem = dir {
dev = dev =
let node = type: major: minor: mode : { inherit type major minor mode; }; let
in dir { node = type: major: minor: mode: {
null = node "c" "1" "3" "0666"; inherit
zero = node "c" "1" "5" "0666"; type
tty = node "c" "5" "0" "0666"; major
minor
mode
;
};
in
dir {
null = node "c" "1" "3" "0666";
zero = node "c" "1" "5" "0666";
tty = node "c" "5" "0" "0666";
console = node "c" "5" "1" "0600"; console = node "c" "5" "1" "0600";
pts = dir {}; pts = dir { };
};
etc =
let
profile = symlink (
pkgs.writeScript ".profile" ''
PATH=${lib.makeBinPath config.defaultProfile.packages}:/bin
export PATH
''
);
in
dir {
inherit profile;
ashrc = profile;
}; };
etc = let
profile = symlink
(pkgs.writeScript ".profile" ''
PATH=${lib.makeBinPath config.defaultProfile.packages}:/bin
export PATH
'');
in dir {
inherit profile;
ashrc = profile;
};
proc = dir {}; proc = dir { };
run = dir {}; run = dir { };
sys = dir {}; sys = dir { };
tmp = dir {}; tmp = dir { };
}; };
}; };
} }

View File

@@ -6,8 +6,12 @@
## with one or more WLANs so that several local devices appear to be ## with one or more WLANs so that several local devices appear to be
## on the same network. ## on the same network.
{
{ lib, pkgs, config, ...}: lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;
@@ -40,13 +44,15 @@ in
}; };
}; };
}; };
config.kernel.config = { config.kernel.config =
BRIDGE = "y"; {
BRIDGE_IGMP_SNOOPING = "y"; BRIDGE = "y";
} // lib.optionalAttrs (config.system.service ? vlan) { BRIDGE_IGMP_SNOOPING = "y";
# depends on bridge _and_ vlan. I would like there to be }
# a better way to test for the existence of vlan config: // lib.optionalAttrs (config.system.service ? vlan) {
# maybe the module should set an `enabled` attribute? # depends on bridge _and_ vlan. I would like there to be
BRIDGE_VLAN_FILTERING = "y"; # a better way to test for the existence of vlan config:
}; # maybe the module should set an `enabled` attribute?
BRIDGE_VLAN_FILTERING = "y";
};
} }

View File

@@ -1,21 +1,25 @@
{ {
liminix liminix,
, ifwait ifwait,
, svc svc,
}: }:
{ members, primary } : { members, primary }:
let let
inherit (liminix.networking) interface; inherit (liminix.networking) interface;
inherit (liminix.services) bundle oneshot; inherit (liminix.services) bundle oneshot;
addif = member : addif =
member:
# how do we get sight of services from here? maybe we need to # how do we get sight of services from here? maybe we need to
# implement ifwait as a regualr derivation instead of a # implement ifwait as a regualr derivation instead of a
# servicedefinition # servicedefinition
svc.ifwait.build { svc.ifwait.build {
state = "running"; state = "running";
interface = member; interface = member;
dependencies = [ primary member ]; dependencies = [
primary
member
];
service = oneshot { service = oneshot {
name = "${primary.name}.member.${member.name}"; name = "${primary.name}.member.${member.name}";
up = '' up = ''
@@ -24,7 +28,8 @@ let
down = "ip link set dev $(output ${member} ifname) nomaster"; down = "ip link set dev $(output ${member} ifname) nomaster";
}; };
}; };
in bundle { in
bundle {
name = "${primary.name}.members"; name = "${primary.name}.members";
contents = map addif members; contents = map addif members;
} }

View File

@@ -1,11 +1,12 @@
{ {
liminix liminix,
, lib lib,
}: }:
{ ifname } : { ifname }:
let let
inherit (liminix.services) oneshot; inherit (liminix.services) oneshot;
in oneshot rec { in
oneshot rec {
name = "${ifname}.link"; name = "${ifname}.link";
up = '' up = ''
ip link add name ${ifname} type bridge ip link add name ${ifname} type bridge

View File

@@ -6,19 +6,26 @@
## the commands (termed "applets") required by the user or ## the commands (termed "applets") required by the user or
## by other included modules. ## by other included modules.
{ lib, pkgs, config, ...}: {
lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types mapAttrsToList; inherit (lib) mkOption types mapAttrsToList;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
inherit (lib.strings) toUpper; inherit (lib.strings) toUpper;
attrs = { options, applets } : attrs =
{ options, applets }:
let let
extraOptions = builtins.concatStringsSep "\n" extraOptions = builtins.concatStringsSep "\n" (
(mapAttrsToList (n: v: "CONFIG_${toUpper n} ${toString v}") options); mapAttrsToList (n: v: "CONFIG_${toUpper n} ${toString v}") options
appletOptions = builtins.concatStringsSep "\n" );
(map (n: "CONFIG_${toUpper n} y") applets); appletOptions = builtins.concatStringsSep "\n" (map (n: "CONFIG_${toUpper n} y") applets);
in { in
{
enableMinimal = true; enableMinimal = true;
extraConfig = '' extraConfig = ''
${extraOptions} ${extraOptions}
@@ -26,44 +33,171 @@ let
''; '';
}; };
cfg = config.programs.busybox; cfg = config.programs.busybox;
busybox = pkgs.busybox.override (attrs { inherit (cfg) applets options; }); busybox = pkgs.busybox.override (attrs {
makeLinks = lib.attrsets.genAttrs inherit (cfg) applets options;
cfg.applets });
(a: symlink "${busybox}/bin/busybox"); makeLinks = lib.attrsets.genAttrs cfg.applets (a: symlink "${busybox}/bin/busybox");
minimalApplets = [ minimalApplets = [
# this is probably less minimal than it could be # this is probably less minimal than it could be
"arch" "ash" "base64" "basename" "bc" "brctl" "bunzip2" "bzcat" "bzip2" "arch"
"cal" "cat" "chattr" "chgrp" "chmod" "chown" "chpst" "chroot" "clear" "cmp" "ash"
"comm" "cp" "cpio" "cut" "date" "dhcprelay" "dd" "df" "dirname" "dmesg" "base64"
"du" "echo" "egrep" "env" "expand" "expr" "false" "fdisk" "fgrep" "find" "basename"
"free" "fuser" "grep" "gunzip" "gzip" "head" "hexdump" "hostname" "hwclock" "bc"
"ifconfig" "ip" "ipaddr" "iplink" "ipneigh" "iproute" "iprule" "kill" "brctl"
"killall" "killall5" "less" "ln" "ls" "lsattr" "lsof" "md5sum" "mkdir" "bunzip2"
"mknod" "mktemp" "mount" "mv" "nc" "netstat" "nohup" "od" "pgrep" "pidof" "bzcat"
"ping" "ping6" "pkill" "pmap" "printenv" "printf" "ps" "pwd" "readlink" "bzip2"
"realpath" "reset" "rm" "rmdir" "route" "sed" "seq" "setsid" "sha1sum" "cal"
"sha256sum" "sha512sum" "sleep" "sort" "stat" "strings" "stty" "su" "sum" "cat"
"swapoff" "swapon" "sync" "tail" "tee" "test" "time" "touch" "tr" "chattr"
"traceroute" "traceroute6" "true" "truncate" "tty" "udhcpc" "umount" "chgrp"
"uname" "unexpand" "uniq" "unlink" "unlzma" "unxz" "unzip" "uptime" "watch" "chmod"
"wc" "whoami" "xargs" "xxd" "xz" "xzcat" "yes" "zcat" "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 { in
{
options = { options = {
programs.busybox = { programs.busybox = {
applets = mkOption { applets = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
description = "Applets required"; description = "Applets required";
default = []; default = [ ];
example = ["sh" "getty" "login"]; example = [
"sh"
"getty"
"login"
];
}; };
options = mkOption { options = mkOption {
# mostly the values are y n or m, but sometimes # mostly the values are y n or m, but sometimes
# other strings are also used # other strings are also used
description = "Other busybox config flags that do not map directly to applet names (often prefixed FEATURE_)"; description = "Other busybox config flags that do not map directly to applet names (often prefixed FEATURE_)";
type = types.attrsOf types.nonEmptyStr; type = types.attrsOf types.nonEmptyStr;
default = { }; default = { };
example = { FEATURE_DD_IBS_OBS = "y"; }; example = {
FEATURE_DD_IBS_OBS = "y";
};
}; };
}; };
}; };

View File

@@ -1,10 +1,14 @@
{ {
writeFennel writeFennel,
, linotify linotify,
, anoia anoia,
, lualinux lualinux,
}: }:
writeFennel "acquire-delegated-prefix" { writeFennel "acquire-delegated-prefix" {
packages = [ linotify anoia lualinux ]; packages = [
linotify
anoia
lualinux
];
mainFunction = "run"; mainFunction = "run";
} ./acquire-delegated-prefix.fnl } ./acquire-delegated-prefix.fnl

View File

@@ -1,10 +1,14 @@
{ {
writeFennel writeFennel,
, linotify linotify,
, anoia anoia,
, lualinux lualinux,
}: }:
writeFennel "acquire-wan-address" { writeFennel "acquire-wan-address" {
packages = [ linotify anoia lualinux ]; packages = [
linotify
anoia
lualinux
];
mainFunction = "run"; mainFunction = "run";
} ./acquire-wan-address.fnl } ./acquire-wan-address.fnl

View File

@@ -1,14 +1,18 @@
{ {
liminix liminix,
, callPackage callPackage,
}: }:
{ client, interface } : { client, interface }:
let let
inherit (liminix.services) longrun; inherit (liminix.services) longrun;
name = "dhcp6c.addr.${client.name}.${interface.name}"; name = "dhcp6c.addr.${client.name}.${interface.name}";
script = callPackage ./acquire-wan-address.nix { }; script = callPackage ./acquire-wan-address.nix { };
in longrun { in
longrun {
inherit name; inherit name;
run = "${script} $SERVICE_OUTPUTS/${client.name} $(output ${interface} ifname)"; run = "${script} $SERVICE_OUTPUTS/${client.name} $(output ${interface} ifname)";
dependencies = [ client interface ]; dependencies = [
client
interface
];
} }

View File

@@ -1,13 +1,14 @@
{ {
liminix liminix,
, odhcp6c odhcp6c,
, odhcp-script odhcp-script,
}: }:
{ interface } : { interface }:
let let
inherit (liminix.services) longrun; inherit (liminix.services) longrun;
name = "dhcp6c.${interface.name}"; name = "dhcp6c.${interface.name}";
in longrun { in
longrun {
inherit name; inherit name;
notification-fd = 10; notification-fd = 10;
run = '' run = ''

View File

@@ -9,7 +9,12 @@
## addresses of network interfaces that you want to assign those ## addresses of network interfaces that you want to assign those
## prefixes to ## prefixes to
{ lib, pkgs, config, ...}: {
lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;

View File

@@ -1,14 +1,18 @@
{ {
liminix liminix,
, callPackage callPackage,
}: }:
{ client, interface } : { client, interface }:
let let
inherit (liminix.services) longrun; inherit (liminix.services) longrun;
name = "dhcp6c.prefix.${client.name}.${interface.name}"; name = "dhcp6c.prefix.${client.name}.${interface.name}";
script = callPackage ./acquire-delegated-prefix.nix { }; script = callPackage ./acquire-delegated-prefix.nix { };
in longrun { in
longrun {
inherit name; inherit name;
run = "${script} $SERVICE_OUTPUTS/${client.name} $(output ${interface} ifname)"; run = "${script} $SERVICE_OUTPUTS/${client.name} $(output ${interface} ifname)";
dependencies = [ client interface ]; dependencies = [
client
interface
];
} }

View File

@@ -4,12 +4,17 @@
## This module includes a service to provide DNS, DHCP, and IPv6 ## This module includes a service to provide DNS, DHCP, and IPv6
## router advertisement for the local network. ## router advertisement for the local network.
{
{ lib, pkgs, config, ...}: lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;
in { in
{
options = { options = {
system.service.dnsmasq = mkOption { system.service.dnsmasq = mkOption {
type = liminix.lib.types.serviceDefn; type = liminix.lib.types.serviceDefn;
@@ -20,12 +25,12 @@ in {
user = mkOption { user = mkOption {
type = types.str; type = types.str;
default = "dnsmasq"; default = "dnsmasq";
description = "Specifies the unix user which dnsmasq will run as" ; description = "Specifies the unix user which dnsmasq will run as";
}; };
group = mkOption { group = mkOption {
type = types.str; type = types.str;
default = "dnsmasq"; default = "dnsmasq";
description = "Specifies the unix group which dnsmasq will run as" ; description = "Specifies the unix group which dnsmasq will run as";
}; };
resolvconf = mkOption { resolvconf = mkOption {
type = types.nullOr liminix.lib.types.service; type = types.nullOr liminix.lib.types.service;
@@ -37,42 +42,47 @@ in {
}; };
upstreams = mkOption { upstreams = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = []; default = [ ];
}; };
ranges = mkOption { ranges = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
}; };
hosts = mkOption { hosts = mkOption {
default = {}; default = { };
type = types.attrsOf (types.submodule { type = types.attrsOf (
options = { types.submodule {
mac = mkOption { options = {
description = '' mac = mkOption {
MAC or other hardware address to match on. For Ethernet description = ''
this is a 48 bit address represented as colon-separated MAC or other hardware address to match on. For Ethernet
hex bytes, or "id:clientid" to match a presented this is a 48 bit address represented as colon-separated
client id (IPv6 DUID) hex bytes, or "id:clientid" to match a presented
''; client id (IPv6 DUID)
type = types.str; '';
example = "01:20:31:4a:50"; type = types.str;
example = "01:20:31:4a:50";
};
v4 = mkOption {
description = "IPv4 address to assign to this client";
example = "192.0.2.1";
type = types.str;
};
v6 = mkOption {
type = types.listOf types.str;
description = "IPv6 addresses or interface-ids to assign to this client";
default = [ ];
example = [
"fe80::42:1eff:fefd:b341"
"::1234"
];
};
leasetime = mkOption {
type = types.int;
default = 86400;
};
}; };
v4 = mkOption { }
description = "IPv4 address to assign to this client"; );
example = "192.0.2.1";
type = types.str;
};
v6 = mkOption {
type = types.listOf types.str;
description = "IPv6 addresses or interface-ids to assign to this client";
default = [];
example = [ "fe80::42:1eff:fefd:b341" "::1234"];
};
leasetime = mkOption {
type = types.int;
default = 86400;
};
};
});
}; };
domain = mkOption { domain = mkOption {
# this can be given multiple times so probably should be # this can be given multiple times so probably should be
@@ -83,13 +93,16 @@ in {
}; };
}; };
users.dnsmasq = { users.dnsmasq = {
uid = 51; gid= 51; gecos = "DNS/DHCP service user"; uid = 51;
gid = 51;
gecos = "DNS/DHCP service user";
dir = "/run/dnsmasq"; dir = "/run/dnsmasq";
shell = "/bin/false"; shell = "/bin/false";
}; };
groups.dnsmasq = { groups.dnsmasq = {
gid = 51; usernames = ["dnsmasq"]; gid = 51;
usernames = [ "dnsmasq" ];
}; };
groups.system.usernames = ["dnsmasq"]; groups.system.usernames = [ "dnsmasq" ];
}; };
} }

View File

@@ -1,26 +1,35 @@
{ {
liminix liminix,
, dnsmasq dnsmasq,
, serviceFns serviceFns,
, lib lib,
}: }:
{ {
interface interface,
, user user,
, domain domain,
, group group,
, ranges ranges,
, hosts hosts,
, upstreams upstreams,
, resolvconf resolvconf,
}: }:
let let
name = "${interface.name}.dnsmasq"; name = "${interface.name}.dnsmasq";
inherit (liminix.services) longrun; inherit (liminix.services) longrun;
inherit (lib) concatStrings concatStringsSep mapAttrsToList; inherit (lib) concatStrings concatStringsSep mapAttrsToList;
hostOpt = name : { mac, v4, v6, leasetime }: hostOpt =
let v6s = concatStrings (map (a : ",[${a}]") v6); name:
in "--dhcp-host=${mac},${v4}${v6s},${name},${builtins.toString leasetime}"; {
mac,
v4,
v6,
leasetime,
}:
let
v6s = concatStrings (map (a: ",[${a}]") v6);
in
"--dhcp-host=${mac},${v4}${v6s},${name},${builtins.toString leasetime}";
in in
longrun { longrun {
inherit name; inherit name;
@@ -35,7 +44,12 @@ longrun {
${lib.concatStringsSep " " (builtins.map (r: "--server=${r}") upstreams)} \ ${lib.concatStringsSep " " (builtins.map (r: "--server=${r}") upstreams)} \
--keep-in-foreground \ --keep-in-foreground \
--dhcp-authoritative \ --dhcp-authoritative \
${if resolvconf != null then "--resolv-file=$(output_path ${resolvconf} resolv.conf)" else "--no-resolv"} \ ${
if resolvconf != null then
"--resolv-file=$(output_path ${resolvconf} resolv.conf)"
else
"--no-resolv"
} \
${lib.concatStringsSep " " (mapAttrsToList hostOpt hosts)} \ ${lib.concatStringsSep " " (mapAttrsToList hostOpt hosts)} \
--no-hosts \ --no-hosts \
--log-dhcp \ --log-dhcp \
@@ -44,7 +58,7 @@ longrun {
--dhcp-leasefile=$(mkstate ${name})/leases \ --dhcp-leasefile=$(mkstate ${name})/leases \
--pid-file=/run/${name}.pid --pid-file=/run/${name}.pid
''; '';
# --log-debug \ # --log-debug \
# --log-queries \ # --log-queries \
} }

View File

@@ -1,9 +1,10 @@
let let
drop = expr : "${expr} drop"; drop = expr: "${expr} drop";
accept = expr : "${expr} accept"; accept = expr: "${expr} accept";
mcast-scope = 8; mcast-scope = 8;
allow-incoming = false; allow-incoming = false;
in { in
{
bogons-ip6 = { bogons-ip6 = {
type = "filter"; type = "filter";
family = "ip6"; family = "ip6";
@@ -44,7 +45,7 @@ in {
rules = [ rules = [
(drop "ip6 saddr ::1/128") # loopback address [RFC4291] (drop "ip6 saddr ::1/128") # loopback address [RFC4291]
(drop "ip6 daddr ::1/128") (drop "ip6 daddr ::1/128")
(drop "ip6 saddr ::FFFF:0:0/96")# IPv4-mapped addresses (drop "ip6 saddr ::FFFF:0:0/96") # IPv4-mapped addresses
(drop "ip6 daddr ::FFFF:0:0/96") (drop "ip6 daddr ::FFFF:0:0/96")
(drop "ip6 saddr fe80::/10") # link-local unicast (drop "ip6 saddr fe80::/10") # link-local unicast
(drop "ip6 daddr fe80::/10") (drop "ip6 daddr fe80::/10")
@@ -60,7 +61,8 @@ in {
(drop (drop
# dest addr first byte 0xff, low nibble of second byte <= scope # dest addr first byte 0xff, low nibble of second byte <= scope
# https://www.mankier.com/8/nft#Payload_Expressions-Raw_Payload_Expression # https://www.mankier.com/8/nft#Payload_Expressions-Raw_Payload_Expression
"@nh,192,8 eq 0xff @nh,204,4 le ${toString mcast-scope}") "@nh,192,8 eq 0xff @nh,204,4 le ${toString mcast-scope}"
)
(accept "oifname @lan iifname @wan meta l4proto udp ct state established,related") (accept "oifname @lan iifname @wan meta l4proto udp ct state established,related")
(accept "iifname @lan oifname @wan meta l4proto udp") (accept "iifname @lan oifname @wan meta l4proto udp")
@@ -72,7 +74,7 @@ in {
# does this ever get used or does the preceding general udp accept # does this ever get used or does the preceding general udp accept
# already grab anything that might get here? # already grab anything that might get here?
(accept "oifname @wan udp dport 500") # IKE Protocol [RFC5996]. haha zyxel (accept "oifname @wan udp dport 500") # IKE Protocol [RFC5996]. haha zyxel
(accept "ip6 nexthdr 139") # Host Identity Protocol (accept "ip6 nexthdr 139") # Host Identity Protocol
## FIXME no support yet for recs 27-30 Mobility Header ## FIXME no support yet for recs 27-30 Mobility Header
@@ -88,9 +90,11 @@ in {
# we can allow all reasonable inbound, or we can use an explicit # we can allow all reasonable inbound, or we can use an explicit
# allowlist to enumerate the endpoints that are allowed to # allowlist to enumerate the endpoints that are allowed to
# accept inbound from the WAN # accept inbound from the WAN
(if allow-incoming (
then accept "oifname @lan iifname @wan" if allow-incoming then
else "iifname @wan jump incoming-allowed-ip6" accept "oifname @lan iifname @wan"
else
"iifname @wan jump incoming-allowed-ip6"
) )
# allow all outbound and any inbound that's part of a # allow all outbound and any inbound that's part of a
# recognised (outbound-initiated) flow # recognised (outbound-initiated) flow
@@ -130,10 +134,7 @@ in {
(accept "meta l4proto icmpv6") (accept "meta l4proto icmpv6")
"iifname @lan jump input-ip6-lan" "iifname @lan jump input-ip6-lan"
"iifname @wan jump input-ip6-wan" "iifname @wan jump input-ip6-wan"
(if allow-incoming (if allow-incoming then accept "iifname @wan" else "iifname @wan jump incoming-allowed-ip6")
then accept "iifname @wan"
else "iifname @wan jump incoming-allowed-ip6"
)
# how does this even make sense in an input chain? # how does this even make sense in an input chain?
(accept "iifname @wan ct state established,related") (accept "iifname @wan ct state established,related")
(accept "iifname @lan ") (accept "iifname @lan ")
@@ -185,9 +186,9 @@ in {
family = "ip"; family = "ip";
rules = [ rules = [
(accept "udp dport 67") # dhcp (accept "udp dport 67") # dhcp
(accept "udp dport 53") # dns (accept "udp dport 53") # dns
(accept "tcp dport 22") # ssh (accept "tcp dport 22") # ssh
]; ];
}; };

View File

@@ -4,7 +4,12 @@
## Provides a service to create an nftables ruleset based on ## Provides a service to create an nftables ruleset based on
## configuration supplied to it. ## configuration supplied to it.
{ lib, pkgs, config, ...}: {
lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;
@@ -54,37 +59,44 @@ in
}; };
config = { config = {
system.service.firewall = system.service.firewall =
let svc = config.system.callService ./service.nix { let
extraRules = mkOption { svc = config.system.callService ./service.nix {
type = types.attrsOf types.attrs; extraRules = mkOption {
description = "firewall ruleset"; type = types.attrsOf types.attrs;
default = {}; description = "firewall ruleset";
}; default = { };
zones = mkOption {
type = types.attrsOf (types.listOf liminix.lib.types.service);
default = {};
example = lib.literalExpression ''
{
lan = with config.hardware.networkInterfaces; [ int ];
wan = [ config.services.ppp0 ];
}
'';
};
rules = mkOption {
type = types.attrsOf types.attrs; # we could usefully tighten this a bit :-)
default = import ./default-rules.nix;
description = "firewall ruleset";
};
}; };
in svc // { zones = mkOption {
build = args : type = types.attrsOf (types.listOf liminix.lib.types.service);
let args' = args // { default = { };
dependencies = (args.dependencies or []) ++ [kmodules]; example = lib.literalExpression ''
}; {
in svc.build args' ; lan = with config.hardware.networkInterfaces; [ int ];
wan = [ config.services.ppp0 ];
}
'';
};
rules = mkOption {
type = types.attrsOf types.attrs; # we could usefully tighten this a bit :-)
default = import ./default-rules.nix;
description = "firewall ruleset";
};
};
in
svc
// {
build =
args:
let
args' = args // {
dependencies = (args.dependencies or [ ]) ++ [ kmodules ];
};
in
svc.build args';
}; };
programs.busybox.applets = [ programs.busybox.applets = [
"insmod" "rmmod" "insmod"
"rmmod"
]; ];
kernel.config = { kernel.config = {
NETFILTER = "y"; NETFILTER = "y";
@@ -94,7 +106,7 @@ in
NETLINK_DIAG = "y"; NETLINK_DIAG = "y";
IP6_NF_IPTABLES= "m"; IP6_NF_IPTABLES = "m";
IP_NF_IPTABLES = "m"; IP_NF_IPTABLES = "m";
IP_NF_NAT = "m"; IP_NF_NAT = "m";
IP_NF_TARGET_MASQUERADE = "m"; IP_NF_TARGET_MASQUERADE = "m";

View File

@@ -1,37 +1,44 @@
{ {
liminix liminix,
, lib lib,
, firewallgen firewallgen,
, nftables nftables,
, writeFennel writeFennel,
, anoia anoia,
, lualinux lualinux,
, linotify linotify,
}:
{
rules,
extraRules,
zones,
}: }:
{ rules, extraRules, zones }:
let let
inherit (liminix.services) longrun; inherit (liminix.services) longrun;
inherit (lib.attrsets) mapAttrs' nameValuePair mapAttrsToList; inherit (lib.attrsets) mapAttrs' nameValuePair mapAttrsToList;
inherit (lib.strings) concatStringsSep; inherit (lib.strings) concatStringsSep;
inherit (lib.lists) flatten; inherit (lib.lists) flatten;
mkSet = family : name : mkSet =
nameValuePair family: name:
"${name}-set-${family}" nameValuePair "${name}-set-${family}" {
{ kind = "set";
kind = "set"; inherit name family;
inherit name family; type = "ifname";
type = "ifname"; };
}; sets = (mapAttrs' (n: _: mkSet "ip" n) zones) // (mapAttrs' (n: _: mkSet "ip6" n) zones);
sets = (mapAttrs' (n : _ : mkSet "ip" n) zones) //
(mapAttrs' (n : _ : mkSet "ip6" n) zones);
allRules = lib.recursiveUpdate extraRules (lib.recursiveUpdate (builtins.trace sets sets) rules); allRules = lib.recursiveUpdate extraRules (lib.recursiveUpdate (builtins.trace sets sets) rules);
script = firewallgen "firewall1.nft" allRules; script = firewallgen "firewall1.nft" allRules;
ifwatch = writeFennel "ifwatch" { ifwatch = writeFennel "ifwatch" {
packages = [anoia lualinux linotify]; packages = [
anoia
lualinux
linotify
];
mainFunction = "run"; mainFunction = "run";
} ./ifwatch.fnl ; } ./ifwatch.fnl;
watchArg = z : intfs : map (i: "${z}:${i}/.outputs") intfs; watchArg = z: intfs: map (i: "${z}:${i}/.outputs") intfs;
in longrun { in
longrun {
name = "firewall"; name = "firewall";
run = '' run = ''
${script} ${script}

View File

@@ -75,17 +75,27 @@ in
type = types.ints.unsigned; type = types.ints.unsigned;
}; };
}; };
loadAddress = mkOption { type = types.ints.unsigned; default = null; }; loadAddress = mkOption {
type = types.ints.unsigned;
default = null;
};
entryPoint = mkOption { type = types.ints.unsigned; }; entryPoint = mkOption { type = types.ints.unsigned; };
alignment = mkOption { type = types.nullOr types.ints.unsigned; default = null; description = "Alignment passed to `mkimage` for FIT"; }; alignment = mkOption {
type = types.nullOr types.ints.unsigned;
default = null;
description = "Alignment passed to `mkimage` for FIT";
};
radios = mkOption { radios = mkOption {
description = '' description = ''
Kernel modules (from mac80211 package) required for the Kernel modules (from mac80211 package) required for the
wireless devices on this board wireless devices on this board
''; '';
type = types.listOf types.str; type = types.listOf types.str;
default = []; default = [ ];
example = ["ath9k" "ath10k"]; example = [
"ath9k"
"ath10k"
];
}; };
rootDevice = mkOption { rootDevice = mkOption {
description = "Full path to preferred root device"; description = "Full path to preferred root device";

View File

@@ -6,13 +6,18 @@
## have other behaviours by e.g. combining this service with a round-robin ## have other behaviours by e.g. combining this service with a round-robin
## for failover) ## for failover)
{
{ lib, pkgs, config, ...}: lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;
in
# inherit (pkgs.liminix.services) longrun; # inherit (pkgs.liminix.services) longrun;
in { {
options = { options = {
system.service.health-check = mkOption { system.service.health-check = mkOption {
description = "run a service while periodically checking it is healthy"; description = "run a service while periodically checking it is healthy";
@@ -23,13 +28,13 @@ in {
service = mkOption { service = mkOption {
type = liminix.lib.types.service; type = liminix.lib.types.service;
}; };
interval = mkOption { interval = mkOption {
description = "interval between checks, in seconds"; description = "interval between checks, in seconds";
type = types.int; type = types.int;
default = 10; default = 10;
example = 10; example = 10;
}; };
threshold = mkOption { threshold = mkOption {
description = "number of consecutive failures required for the service to be kicked"; description = "number of consecutive failures required for the service to be kicked";
type = types.int; type = types.int;
example = 3; example = 3;
@@ -39,5 +44,5 @@ in {
type = types.path; type = types.path;
}; };
}; };
config.programs.busybox.applets = ["expr"]; config.programs.busybox.applets = [ "expr" ];
} }

View File

@@ -1,37 +1,50 @@
{ {
liminix, lib, lim, s6 liminix,
lib,
lim,
s6,
}:
{
service,
interval,
threshold,
healthCheck,
}: }:
{ service, interval, threshold, healthCheck } :
let let
inherit (liminix.services) oneshot longrun; inherit (liminix.services) oneshot longrun;
inherit (builtins) toString; inherit (builtins) toString;
inherit (service) name; inherit (service) name;
checker = let name' = "check-${name}"; in longrun { checker =
name = name'; let
run = '' name' = "check-${name}";
fails=0 in
echo waiting for /run/service/${name} longrun {
${s6}/bin/s6-svwait -U /run/service/${name} || exit name = name';
while sleep ${toString interval} ; do run = ''
${healthCheck} fails=0
if test $? -gt 0; then echo waiting for /run/service/${name}
fails=$(expr $fails + 1) ${s6}/bin/s6-svwait -U /run/service/${name} || exit
else while sleep ${toString interval} ; do
fails=0 ${healthCheck}
fi if test $? -gt 0; then
echo fails $fails/${toString threshold} for ${name} fails=$(expr $fails + 1)
if test "$fails" -gt "${toString threshold}" ; then else
echo time to die fails=0
${s6}/bin/s6-svc -r /run/service/${name} fi
echo bounced echo fails $fails/${toString threshold} for ${name}
fails=0 if test "$fails" -gt "${toString threshold}" ; then
echo waiting for /run/service/${name} echo time to die
${s6}/bin/s6-svwait -U /run/service/${name} ${s6}/bin/s6-svc -r /run/service/${name}
fi echo bounced
done fails=0
''; echo waiting for /run/service/${name}
}; ${s6}/bin/s6-svwait -U /run/service/${name}
in service.overrideAttrs(o: { fi
buildInputs = (lim.orEmpty o.buildInputs) ++ [ checker ]; done
'';
};
in
service.overrideAttrs (o: {
buildInputs = (lim.orEmpty o.buildInputs) ++ [ checker ];
dependencies = (lim.orEmpty o.dependencies) ++ [ checker ]; dependencies = (lim.orEmpty o.dependencies) ++ [ checker ];
}) })

View File

@@ -11,11 +11,17 @@
## If you have more than one wireless network interface (e.g. ## If you have more than one wireless network interface (e.g.
## wlan0, wlan1) you can run an instance of hostapd on each of them. ## wlan0, wlan1) you can run an instance of hostapd on each of them.
{ lib, pkgs, config, ...}: {
lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;
in { in
{
imports = [ ../secrets ]; imports = [ ../secrets ];
options = { options = {
system.service.hostapd = mkOption { system.service.hostapd = mkOption {

View File

@@ -1,16 +1,23 @@
{ {
liminix liminix,
, svc svc,
, hostapd hostapd,
, output-template output-template,
, writeText writeText,
, lib lib,
}: }:
{ interface, params} : { interface, params }:
let let
inherit (liminix.services) longrun; inherit (liminix.services) longrun;
inherit (lib) concatStringsSep mapAttrsToList unique ; inherit (lib) concatStringsSep mapAttrsToList unique;
inherit (builtins) map filter attrValues length head typeOf; inherit (builtins)
map
filter
attrValues
length
head
typeOf
;
# This is not a friendly interface to configuring a wireless AP: it # This is not a friendly interface to configuring a wireless AP: it
# just passes everything straight through to the hostapd config. # just passes everything straight through to the hostapd config.
@@ -19,27 +26,31 @@ let
# extraParams # extraParams
name = "${interface.name}.hostapd"; name = "${interface.name}.hostapd";
defaults = { defaults = {
driver = "nl80211"; driver = "nl80211";
logger_syslog = "-1"; logger_syslog = "-1";
logger_syslog_level = 1; logger_syslog_level = 1;
ctrl_interface = "/run/${name}"; ctrl_interface = "/run/${name}";
ctrl_interface_group = 0; ctrl_interface_group = 0;
}; };
attrs = defaults // params ; attrs = defaults // params;
literal_or_output = o: ({ literal_or_output =
string = builtins.toJSON; o:
int = builtins.toJSON; (
lambda = (o: "output(${builtins.toJSON (o "service")}, ${builtins.toJSON (o "path")})"); {
}.${builtins.typeOf o}) o; string = builtins.toJSON;
int = builtins.toJSON;
lambda = (o: "output(${builtins.toJSON (o "service")}, ${builtins.toJSON (o "path")})");
}
.${builtins.typeOf o}
)
o;
conf = conf = (
(writeText "hostapd.conf.in" writeText "hostapd.conf.in" (
((concatStringsSep (concatStringsSep "\n" (mapAttrsToList (n: v: "${n}={{ ${literal_or_output v} }}") attrs)) + "\n"
"\n" )
(mapAttrsToList );
(n : v : "${n}={{ ${literal_or_output v} }}")
attrs)) + "\n"));
service = longrun { service = longrun {
inherit name; inherit name;
dependencies = [ interface ]; dependencies = [ interface ];
@@ -51,7 +62,8 @@ let
''; '';
}; };
watch = filter (f: typeOf f == "lambda") (attrValues attrs); watch = filter (f: typeOf f == "lambda") (attrValues attrs);
in svc.secrets.subscriber.build { in
svc.secrets.subscriber.build {
inherit service watch; inherit service watch;
action = "restart-all"; action = "restart-all";
} }

View File

@@ -1,8 +1,14 @@
{ lib, pkgs, config, ...}: {
lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot; inherit (pkgs.liminix.services) oneshot;
in { in
{
options = { options = {
hostname = mkOption { hostname = mkOption {
description = '' description = ''

View File

@@ -1,10 +1,15 @@
{ config, pkgs, lib, ... } : {
config,
pkgs,
lib,
...
}:
let let
inherit (pkgs) liminix; inherit (pkgs) liminix;
inherit (lib) mkOption types; inherit (lib) mkOption types;
in { in
options.system.service.ifwait = {
mkOption { type = liminix.lib.types.serviceDefn; }; options.system.service.ifwait = mkOption { type = liminix.lib.types.serviceDefn; };
config.system.service.ifwait = config.system.callService ./ifwait.nix { config.system.service.ifwait = config.system.callService ./ifwait.nix {
state = mkOption { type = types.str; }; state = mkOption { type = types.str; };

View File

@@ -1,12 +1,13 @@
{ ifwait, liminix } : { ifwait, liminix }:
{ {
state state,
, interface interface,
, service service,
}: }:
let let
inherit (liminix.services) longrun; inherit (liminix.services) longrun;
in longrun { in
longrun {
name = "ifwait.${interface.name}"; name = "ifwait.${interface.name}";
buildInputs = [ service ]; buildInputs = [ service ];
restart-on-upgrade = true; restart-on-upgrade = true;

View File

@@ -3,26 +3,36 @@
## ##
## ##
{ lib, pkgs, config, ...}: {
lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types ; inherit (lib) mkOption types;
inherit (pkgs) liminix openwrt; inherit (pkgs) liminix openwrt;
mergeConditionals = conf : conditions : mergeConditionals =
conf: conditions:
# for each key in conditions, if it is present in conf # for each key in conditions, if it is present in conf
# then merge the associated value into conf # then merge the associated value into conf
lib.foldlAttrs lib.foldlAttrs (
(acc: name: value: acc: name: value:
if (conf ? ${name}) && (conf.${name} != "n") if (conf ? ${name}) && (conf.${name} != "n") then acc // value else acc
then acc // value ) conf conditions;
else acc) in
conf {
conditions;
in {
options = { options = {
kernel = { kernel = {
src = mkOption { type = types.path; default = openwrt.kernelSrc; } ; src = mkOption {
version = mkOption { type = types.str; default = openwrt.kernelVersion;} ; type = types.path;
default = openwrt.kernelSrc;
};
version = mkOption {
type = types.str;
default = openwrt.kernelVersion;
};
modular = mkOption { modular = mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
@@ -54,7 +64,7 @@ in {
some other option is present. some other option is present.
''; '';
type = types.attrsOf (types.attrsOf types.nonEmptyStr); type = types.attrsOf (types.attrsOf types.nonEmptyStr);
default = {}; default = { };
example = { example = {
USB = { USB = {
USB_XHCI_MVEBU = "y"; USB_XHCI_MVEBU = "y";
@@ -70,10 +80,9 @@ in {
config = { config = {
system.outputs.kernel = system.outputs.kernel =
let let
mergedConfig = mergeConditionals mergedConfig = mergeConditionals config.kernel.config config.kernel.conditionalConfig;
config.kernel.config in
config.kernel.conditionalConfig; liminix.builders.kernel.override {
in liminix.builders.kernel.override {
config = mergedConfig; config = mergedConfig;
inherit (config.kernel) version src extraPatchPhase; inherit (config.kernel) version src extraPatchPhase;
targets = config.kernel.makeTargets; targets = config.kernel.makeTargets;
@@ -81,7 +90,7 @@ in {
kernel = rec { kernel = rec {
modular = true; # disabling this is not yet supported modular = true; # disabling this is not yet supported
makeTargets = ["vmlinux"]; makeTargets = [ "vmlinux" ];
config = { config = {
IKCONFIG = "y"; IKCONFIG = "y";
IKCONFIG_PROC = "y"; IKCONFIG_PROC = "y";
@@ -96,10 +105,10 @@ in {
UNIX = "y"; UNIX = "y";
INET = "y"; INET = "y";
IPV6 = "y"; IPV6 = "y";
PACKET = "y"; # for ppp, tcpdump ... PACKET = "y"; # for ppp, tcpdump ...
SYSVIPC= "y"; SYSVIPC = "y";
NETDEVICES = "y"; # even PPP needs this NETDEVICES = "y"; # even PPP needs this
# disabling this option causes the kernel to use an "empty" # disabling this option causes the kernel to use an "empty"
# initramfs instead: it has a /dev/console node and not much # initramfs instead: it has a /dev/console node and not much

View File

@@ -1,7 +1,13 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
inherit (pkgs.liminix.services) longrun; inherit (pkgs.liminix.services) longrun;
in { in
{
config.services.klogd = longrun { config.services.klogd = longrun {
name = "klogd"; name = "klogd";
run = '' run = ''

View File

@@ -1,7 +1,13 @@
{ config, lib, ... }: { config, lib, ... }:
let let
inherit (lib) mkIf mkEnableOption mkOption types; inherit (lib)
in { mkIf
mkEnableOption
mkOption
types
;
in
{
options = { options = {
logging = { logging = {
persistent = { persistent = {
@@ -9,11 +15,11 @@ in {
}; };
}; };
}; };
config = { config = {
kernel.config = mkIf config.logging.persistent.enable { kernel.config = mkIf config.logging.persistent.enable {
PSTORE = "y"; PSTORE = "y";
PSTORE_PMSG = "y"; PSTORE_PMSG = "y";
PSTORE_RAM = "y"; PSTORE_RAM = "y";
}; };
}; };
} }

View File

@@ -1,6 +1,8 @@
{ config, pkgs, ...} : { config, pkgs, ... }:
let inherit (pkgs.liminix.services) oneshot longrun; let
in { inherit (pkgs.liminix.services) oneshot longrun;
in
{
config = { config = {
services = rec { services = rec {
mdevd = longrun { mdevd = longrun {

View File

@@ -2,53 +2,74 @@
## ##
## Mount filesystems ## Mount filesystems
{
{ lib, pkgs, config, ...}: lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;
in { in
{
options = { options = {
system.service.mount = mkOption { system.service.mount = mkOption {
type = liminix.lib.types.serviceDefn; type = liminix.lib.types.serviceDefn;
}; };
}; };
imports = [ ../mdevd.nix ../uevent-rule ]; imports = [
../mdevd.nix
../uevent-rule
];
config.system.service.mount = config.system.service.mount =
let svc = config.system.callService ./service.nix { let
partlabel = mkOption { svc = config.system.callService ./service.nix {
type = types.str; partlabel = mkOption {
example = "my-usb-stick"; type = types.str;
}; example = "my-usb-stick";
mountpoint = mkOption {
type = types.str;
example = "/mnt/media";
};
options = mkOption {
type = types.listOf types.str;
default = [];
example = ["noatime" "ro" "sync"];
};
fstype = mkOption {
type = types.str;
default = "auto";
example = "vfat";
};
}; };
in svc // { mountpoint = mkOption {
build = args: type = types.str;
let args' = args // { example = "/mnt/media";
dependencies = (args.dependencies or []) ++ [ };
config.services.mdevd options = mkOption {
config.services.devout type = types.listOf types.str;
]; default = [ ];
}; example = [
in svc.build args' ; "noatime"
"ro"
"sync"
];
};
fstype = mkOption {
type = types.str;
default = "auto";
example = "vfat";
};
};
in
svc
// {
build =
args:
let
args' = args // {
dependencies = (args.dependencies or [ ]) ++ [
config.services.mdevd
config.services.devout
];
};
in
svc.build args';
}; };
config.programs.busybox = { config.programs.busybox = {
applets = ["blkid" "findfs"]; applets = [
"blkid"
"findfs"
];
options = { options = {
FEATURE_BLKID_TYPE = "y"; FEATURE_BLKID_TYPE = "y";
FEATURE_MOUNT_FLAGS = "y"; FEATURE_MOUNT_FLAGS = "y";

View File

@@ -1,15 +1,19 @@
{ {
liminix liminix,
, lib lib,
, svc svc,
}:
{
partlabel,
mountpoint,
options,
fstype,
}: }:
{ partlabel, mountpoint, options, fstype }:
let let
inherit (liminix.services) oneshot; inherit (liminix.services) oneshot;
device = "/dev/disk/by-partlabel/${partlabel}"; device = "/dev/disk/by-partlabel/${partlabel}";
name = "mount.${lib.strings.sanitizeDerivationName (lib.escapeURL mountpoint)}"; name = "mount.${lib.strings.sanitizeDerivationName (lib.escapeURL mountpoint)}";
options_string = options_string = if options == [ ] then "" else "-o ${lib.concatStringsSep "," options}";
if options == [] then "" else "-o ${lib.concatStringsSep "," options}";
controller = svc.uevent-rule.build { controller = svc.uevent-rule.build {
serviceName = name; serviceName = name;
symlink = device; symlink = device;
@@ -18,7 +22,8 @@ let
devtype = "partition"; devtype = "partition";
}; };
}; };
in oneshot { in
oneshot {
inherit name; inherit name;
timeout-up = 3600; timeout-up = 3600;
up = "mount -t ${fstype} ${options_string} ${device} ${mountpoint}"; up = "mount -t ${fstype} ${options_string} ${device} ${mountpoint}";

View File

@@ -1,9 +1,14 @@
{ {
liminix liminix,
, serviceFns serviceFns,
, lib lib,
}:
{
interface,
family,
address,
prefixLength,
}: }:
{interface, family, address, prefixLength} :
let let
inherit (liminix.services) oneshot; inherit (liminix.services) oneshot;
# rather depending on the assumption that nobody will # rather depending on the assumption that nobody will
@@ -20,8 +25,9 @@ let
echo $dev > ifname echo $dev > ifname
) )
''; '';
in oneshot { in
oneshot {
inherit name up; inherit name up;
down = "true"; # this has been broken for ~ ages down = "true"; # this has been broken for ~ ages
dependencies = [ interface ]; dependencies = [ interface ];
} }

View File

@@ -4,13 +4,18 @@
## Basic network services for creating hardware ethernet devices ## Basic network services for creating hardware ethernet devices
## and adding addresses ## and adding addresses
{
{ lib, pkgs, config, ...}: lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;
inherit (pkgs.liminix.services) bundle; inherit (pkgs.liminix.services) bundle;
in { in
{
options = { options = {
system.service.network = { system.service.network = {
link = mkOption { link = mkOption {
@@ -42,17 +47,18 @@ in {
lo = lo =
let let
net = config.system.service.network; net = config.system.service.network;
iface = net.link.build { ifname = "lo";}; iface = net.link.build { ifname = "lo"; };
in bundle { in
bundle {
name = "loopback"; name = "loopback";
contents = [ contents = [
( net.address.build { (net.address.build {
interface = iface; interface = iface;
family = "inet"; family = "inet";
address ="127.0.0.1"; address = "127.0.0.1";
prefixLength = 8; prefixLength = 8;
}) })
( net.address.build { (net.address.build {
interface = iface; interface = iface;
family = "inet6"; family = "inet6";
address = "::1"; address = "::1";
@@ -82,7 +88,8 @@ in {
Path to the sysfs node of the device. If you provide this Path to the sysfs node of the device. If you provide this
and the ifname option, the device will be renamed to the and the ifname option, the device will be renamed to the
name given by ifname. name given by ifname.
''; }; '';
};
# other "ip link add" options could go here as well # other "ip link add" options could go here as well
mtu = mkOption { mtu = mkOption {
type = types.nullOr types.int; type = types.nullOr types.int;
@@ -94,7 +101,10 @@ in {
type = liminix.lib.types.service; type = liminix.lib.types.service;
}; };
family = mkOption { family = mkOption {
type = types.enum [ "inet" "inet6" ]; type = types.enum [
"inet"
"inet6"
];
}; };
address = mkOption { address = mkOption {
type = types.str; type = types.str;

View File

@@ -1,14 +1,14 @@
{ {
liminix liminix,
, writeAshScript writeAshScript,
, serviceFns serviceFns,
, lib lib,
} : }:
{ interface }: { interface }:
let let
inherit (liminix.services) longrun; inherit (liminix.services) longrun;
name = "${interface.name}.dhcpc"; name = "${interface.name}.dhcpc";
script = writeAshScript "dhcp-notify" { } '' script = writeAshScript "dhcp-notify" { } ''
. ${serviceFns} . ${serviceFns}
exec 2>&1 exec 2>&1
action=$1 action=$1
@@ -38,7 +38,8 @@ let
;; ;;
esac esac
''; '';
in longrun { in
longrun {
inherit name; inherit name;
run = "exec /bin/udhcpc -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}"; run = "exec /bin/udhcpc -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
notification-fd = 10; notification-fd = 10;

View File

@@ -1,6 +1,6 @@
{ {
liminix liminix,
, lib lib,
}: }:
{ enableIPv4, enableIPv6 }: { enableIPv4, enableIPv6 }:
let let
@@ -8,11 +8,9 @@ let
ip4 = "/proc/sys/net/ipv4/conf/all/forwarding"; ip4 = "/proc/sys/net/ipv4/conf/all/forwarding";
ip6 = "/proc/sys/net/ipv6/conf/all/forwarding"; ip6 = "/proc/sys/net/ipv6/conf/all/forwarding";
opt = lib.optionalString; opt = lib.optionalString;
sysctls = b : sysctls = b: "" + opt enableIPv4 "echo ${b} > ${ip4}\n" + opt enableIPv6 "echo ${b} > ${ip6}\n";
"" in
+ opt enableIPv4 "echo ${b} > ${ip4}\n" oneshot {
+ opt enableIPv6 "echo ${b} > ${ip6}\n";
in oneshot {
name = "forwarding${opt enableIPv4 "4"}${opt enableIPv6 "6"}"; name = "forwarding${opt enableIPv4 "4"}${opt enableIPv6 "6"}";
up = sysctls "1"; up = sysctls "1";
down = sysctls "0"; down = sysctls "0";

View File

@@ -1,23 +1,27 @@
{ {
liminix liminix,
, lib lib,
}: }:
{ {
ifname ifname,
, devpath ? null devpath ? null,
, mtu} : mtu,
}:
# if devpath is supplied, we rename the interface at that # if devpath is supplied, we rename the interface at that
# path to have the specified name. # path to have the specified name.
let let
inherit (liminix.services) oneshot; inherit (liminix.services) oneshot;
name = "${ifname}.link"; name = "${ifname}.link";
rename = if devpath != null rename =
then '' if devpath != null then
oldname=$(cd /sys${devpath} && cd net/ && echo *) ''
ip link set ''${oldname} name ${ifname} oldname=$(cd /sys${devpath} && cd net/ && echo *)
'' ip link set ''${oldname} name ${ifname}
else ""; ''
in oneshot { else
"";
in
oneshot {
inherit name; inherit name;
up = '' up = ''
${rename} ${rename}

View File

@@ -1,20 +1,30 @@
{ {
liminix liminix,
, lib lib,
}:
{
target,
via,
interface ? null,
metric,
}: }:
{ target, via, interface ? null, metric }:
let let
inherit (liminix.services) oneshot; inherit (liminix.services) oneshot;
with_dev = if interface != null then "dev $(output ${interface} ifname)" else ""; with_dev = if interface != null then "dev $(output ${interface} ifname)" else "";
target_hash = builtins.substring 0 12 (builtins.hashString "sha256" target); target_hash = builtins.substring 0 12 (builtins.hashString "sha256" target);
via_hash = builtins.substring 0 12 (builtins.hashString "sha256" via); via_hash = builtins.substring 0 12 (builtins.hashString "sha256" via);
in oneshot { in
name = "route-${target_hash}-${builtins.substring 0 12 (builtins.hashString "sha256" "${via_hash}-${if interface!=null then interface.name else ""}")}"; oneshot {
name = "route-${target_hash}-${
builtins.substring 0 12 (
builtins.hashString "sha256" "${via_hash}-${if interface != null then interface.name else ""}"
)
}";
up = '' up = ''
ip route add ${target} via ${via} metric ${toString metric} ${with_dev} ip route add ${target} via ${via} metric ${toString metric} ${with_dev}
''; '';
down = '' down = ''
ip route del ${target} via ${via} ${with_dev} ip route del ${target} via ${via} ${with_dev}
''; '';
dependencies = [] ++ lib.optional (interface != null) interface; dependencies = [ ] ++ lib.optional (interface != null) interface;
} }

View File

@@ -6,12 +6,18 @@
## optionally also provide time service to its peers. The ## optionally also provide time service to its peers. The
## implementation used in Liminix is Chrony ## implementation used in Liminix is Chrony
{ lib, pkgs, config, ...}: {
lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;
serverOpts = types.listOf types.str; serverOpts = types.listOf types.str;
in { in
{
options = { options = {
system.service.ntp = mkOption { system.service.ntp = mkOption {
type = liminix.lib.types.serviceDefn; type = liminix.lib.types.serviceDefn;
@@ -23,23 +29,36 @@ in {
type = types.str; type = types.str;
default = "ntp"; default = "ntp";
}; };
servers = mkOption { type = types.attrsOf serverOpts; default = {}; }; servers = mkOption {
pools = mkOption { type = types.attrsOf serverOpts; default = {}; }; type = types.attrsOf serverOpts;
peers = mkOption { type = types.attrsOf serverOpts; default = {}; }; default = { };
};
pools = mkOption {
type = types.attrsOf serverOpts;
default = { };
};
peers = mkOption {
type = types.attrsOf serverOpts;
default = { };
};
makestep = mkOption { makestep = mkOption {
default = null; default = null;
type = types.nullOr type = types.nullOr (
(types.submodule { types.submodule {
options = { options = {
threshold = mkOption { type = types.number; default = null;}; threshold = mkOption {
type = types.number;
default = null;
};
limit = mkOption { type = types.number; }; limit = mkOption { type = types.number; };
}; };
}); }
);
}; };
allow = mkOption { allow = mkOption {
description = "subnets from which NTP clients are allowed to access the server"; description = "subnets from which NTP clients are allowed to access the server";
type = types.listOf types.str; type = types.listOf types.str;
default = []; default = [ ];
}; };
bindaddress = mkOption { bindaddress = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
@@ -60,7 +79,9 @@ in {
}; };
}; };
users.ntp = { users.ntp = {
uid = 52; gid= 52; gecos = "Unprivileged NTP user"; uid = 52;
gid = 52;
gecos = "Unprivileged NTP user";
dir = "/run/ntp"; dir = "/run/ntp";
shell = "/bin/false"; shell = "/bin/false";
}; };

View File

@@ -1,25 +1,23 @@
{ {
liminix liminix,
, chrony chrony,
, lib lib,
, writeText writeText,
}: }:
params: params:
let let
name = "ntp"; # bad name, needs to be unique name = "ntp"; # bad name, needs to be unique
inherit (liminix.services) longrun; inherit (liminix.services) longrun;
inherit (lib) concatStringsSep mapAttrsToList; inherit (lib) concatStringsSep mapAttrsToList;
configFile = p: configFile =
(mapAttrsToList (name: opts: "server ${name} ${concatStringsSep "" opts}") p:
p.servers) (mapAttrsToList (name: opts: "server ${name} ${concatStringsSep "" opts}") p.servers)
++ ++ (mapAttrsToList (name: opts: "pool ${name} ${concatStringsSep "" opts}") p.pools)
(mapAttrsToList (name: opts: "pool ${name} ${concatStringsSep "" opts}") ++ (mapAttrsToList (name: opts: "peer ${name} ${concatStringsSep "" opts}") p.peers)
p.pools)
++
(mapAttrsToList (name: opts: "peer ${name} ${concatStringsSep "" opts}")
p.peers)
++ lib.optional (p.user != null) "user ${p.user}" ++ lib.optional (p.user != null) "user ${p.user}"
++ (lib.optional (p.makestep != null) "makestep ${toString p.makestep.threshold} ${toString p.makestep.limit}") ++ (lib.optional (
p.makestep != null
) "makestep ${toString p.makestep.threshold} ${toString p.makestep.limit}")
++ (map (n: "allow ${n}") p.allow) ++ (map (n: "allow ${n}") p.allow)
++ (lib.optional (p.bindaddress != null) "bindaddress ${p.bindaddress}") ++ (lib.optional (p.bindaddress != null) "bindaddress ${p.bindaddress}")
++ (lib.optional (p.binddevice != null) "binddevice ${p.binddevice}") ++ (lib.optional (p.binddevice != null) "binddevice ${p.binddevice}")
@@ -28,11 +26,11 @@ let
"bindcmdaddress /" # disable unix socket "bindcmdaddress /" # disable unix socket
"pidfile /run/${name}.pid" "pidfile /run/${name}.pid"
] ]
++ [p.extraConfig]; ++ [ p.extraConfig ];
config = writeText "chrony.conf" config = writeText "chrony.conf" (concatStringsSep "\n" (configFile params));
(concatStringsSep "\n" (configFile params)); in
in longrun { longrun {
inherit name; inherit name;
run = "${chrony}/bin/chronyd -f ${config} -d"; run = "${chrony}/bin/chronyd -f ${config} -d";
} }

View File

@@ -97,7 +97,7 @@ in
system.outputs = rec { system.outputs = rec {
dtb = liminix.builders.dtb { dtb = liminix.builders.dtb {
inherit (config.boot) commandLine; inherit (config.boot) commandLine;
dts = [config.hardware.dts.src] ++ config.hardware.dts.includes; dts = [ config.hardware.dts.src ] ++ config.hardware.dts.includes;
includes = config.hardware.dts.includePaths ++ [ includes = config.hardware.dts.includePaths ++ [
"${o.kernel.headers}/include" "${o.kernel.headers}/include"
]; ];
@@ -105,7 +105,8 @@ in
rootdir = rootdir =
let let
inherit (pkgs.pkgsBuildBuild) runCommand; inherit (pkgs.pkgsBuildBuild) runCommand;
in runCommand "mktree" { } '' in
runCommand "mktree" { } ''
mkdir -p $out/nix/store/ $out/secrets $out/boot mkdir -p $out/nix/store/ $out/secrets $out/boot
cp ${o.systemConfiguration}/bin/activate $out/activate cp ${o.systemConfiguration}/bin/activate $out/activate
ln -s ${pkgs.s6-init-bin}/bin/init $out/init ln -s ${pkgs.s6-init-bin}/bin/init $out/init
@@ -115,14 +116,18 @@ in
done done
''; '';
bootablerootdir = bootablerootdir =
let inherit (pkgs.pkgsBuildBuild) runCommand; let
in runCommand "add-slash-boot" { } '' inherit (pkgs.pkgsBuildBuild) runCommand;
in
runCommand "add-slash-boot" { } ''
cp -a ${o.rootdir} $out cp -a ${o.rootdir} $out
${if o.bootfiles != null ${
then "(cd $out && chmod -R +w . && rmdir boot && cp -a ${o.bootfiles} boot)" if o.bootfiles != null then
else "" "(cd $out && chmod -R +w . && rmdir boot && cp -a ${o.bootfiles} boot)"
} else
''; ""
}
'';
manifest = writeText "manifest.json" (builtins.toJSON config.filesystem.contents); manifest = writeText "manifest.json" (builtins.toJSON config.filesystem.contents);
}; };
}; };

View File

@@ -1,21 +1,28 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep; inherit (lib)
mkIf
mkEnableOption
mkOption
types
concatStringsSep
;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
cfg = config.boot.loader.extlinux; cfg = config.boot.loader.extlinux;
o = config.system.outputs; o = config.system.outputs;
cmdline = concatStringsSep " " config.boot.commandLine; cmdline = concatStringsSep " " config.boot.commandLine;
wantsDtb = config.hardware.dts ? src && config.hardware.dts.src != null; wantsDtb = config.hardware.dts ? src && config.hardware.dts.src != null;
in { in
{
options.boot.loader.extlinux.enable = mkEnableOption "extlinux"; options.boot.loader.extlinux.enable = mkEnableOption "extlinux";
config = mkIf cfg.enable { config = mkIf cfg.enable {
system.outputs.bootfiles = pkgs.runCommand "extlinux" {} '' system.outputs.bootfiles = pkgs.runCommand "extlinux" { } ''
mkdir $out mkdir $out
cd $out cd $out
${if wantsDtb then "cp ${o.dtb} dtb" else "true"} ${if wantsDtb then "cp ${o.dtb} dtb" else "true"}

View File

@@ -1,21 +1,28 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep; inherit (lib)
mkIf
mkEnableOption
mkOption
types
concatStringsSep
;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
cfg = config.boot.loader.fit; cfg = config.boot.loader.fit;
o = config.system.outputs; o = config.system.outputs;
cmdline = concatStringsSep " " config.boot.commandLine; cmdline = concatStringsSep " " config.boot.commandLine;
wantsDtb = config.hardware.dts ? src && config.hardware.dts.src != null; wantsDtb = config.hardware.dts ? src && config.hardware.dts.src != null;
in { in
{
options.boot.loader.fit.enable = mkEnableOption "FIT in /boot"; options.boot.loader.fit.enable = mkEnableOption "FIT in /boot";
config = mkIf cfg.enable { config = mkIf cfg.enable {
system.outputs.bootfiles = pkgs.runCommand "boot-fit" {} '' system.outputs.bootfiles = pkgs.runCommand "boot-fit" { } ''
mkdir $out mkdir $out
cd $out cd $out
cp ${o.uimage} fit cp ${o.uimage} fit

View File

@@ -1,8 +1,8 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkIf; inherit (lib) mkIf;
@@ -21,17 +21,20 @@ in
rootfs = rootfs =
let let
inherit (pkgs.pkgsBuildBuild) runCommand e2fsprogs; inherit (pkgs.pkgsBuildBuild) runCommand e2fsprogs;
in runCommand "mkfs.btrfs" { in
depsBuildBuild = [ e2fsprogs ]; runCommand "mkfs.btrfs"
} '' {
tree=${o.bootablerootdir} depsBuildBuild = [ e2fsprogs ];
size=$(du -s --apparent-size --block-size 1024 $tree |cut -f1) }
# add 25% for filesystem overhead ''
size=$(( 5 * $size / 4)) tree=${o.bootablerootdir}
dd if=/dev/zero of=$out bs=1024 count=$size size=$(du -s --apparent-size --block-size 1024 $tree |cut -f1)
echo "not implemented" ; exit 1 # add 25% for filesystem overhead
# mke2fs -t ext4 -j -d $tree $out size=$(( 5 * $size / 4))
''; dd if=/dev/zero of=$out bs=1024 count=$size
echo "not implemented" ; exit 1
# mke2fs -t ext4 -j -d $tree $out
'';
}; };
}; };
} }

View File

@@ -1,8 +1,8 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkIf; inherit (lib) mkIf;
@@ -23,16 +23,19 @@ in
rootfs = rootfs =
let let
inherit (pkgs.pkgsBuildBuild) runCommand e2fsprogs; inherit (pkgs.pkgsBuildBuild) runCommand e2fsprogs;
in runCommand "mkfs.ext4" { in
depsBuildBuild = [ e2fsprogs ]; runCommand "mkfs.ext4"
} '' {
tree=${o.bootablerootdir} depsBuildBuild = [ e2fsprogs ];
size=$(du -s --apparent-size --block-size 1024 $tree |cut -f1) }
# add 25% for filesystem overhead ''
size=$(( 5 * $size / 4)) tree=${o.bootablerootdir}
dd if=/dev/zero of=$out bs=1024 count=$size size=$(du -s --apparent-size --block-size 1024 $tree |cut -f1)
mke2fs -t ext4 -j -d $tree $out # add 25% for filesystem overhead
''; size=$(( 5 * $size / 4))
dd if=/dev/zero of=$out bs=1024 count=$size
mke2fs -t ext4 -j -d $tree $out
'';
}; };
}; };
} }

View File

@@ -1,11 +1,16 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkEnableOption mkOption mkIf types; inherit (lib)
mkEnableOption
mkOption
mkIf
types
;
inherit (pkgs) runCommand; inherit (pkgs) runCommand;
in in
{ {
@@ -29,13 +34,15 @@ in
kernel.config = { kernel.config = {
BLK_DEV_INITRD = "y"; BLK_DEV_INITRD = "y";
INITRAMFS_SOURCE = builtins.toJSON "${config.system.outputs.initramfs}"; INITRAMFS_SOURCE = builtins.toJSON "${config.system.outputs.initramfs}";
# INITRAMFS_COMPRESSION_LZO = "y"; # INITRAMFS_COMPRESSION_LZO = "y";
}; };
system.outputs = { system.outputs = {
initramfs = initramfs =
let inherit (pkgs.pkgsBuildBuild) gen_init_cpio; let
in runCommand "initramfs.cpio" {} '' inherit (pkgs.pkgsBuildBuild) gen_init_cpio;
in
runCommand "initramfs.cpio" { } ''
cat << SPECIALS | ${gen_init_cpio}/bin/gen_init_cpio /dev/stdin > $out cat << SPECIALS | ${gen_init_cpio}/bin/gen_init_cpio /dev/stdin > $out
dir /proc 0755 0 0 dir /proc 0755 0 0
dir /dev 0755 0 0 dir /dev 0755 0 0

View File

@@ -1,8 +1,8 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkIf; inherit (lib) mkIf;
@@ -27,14 +27,16 @@ in
rootfs = rootfs =
let let
inherit (pkgs.pkgsBuildBuild) runCommand mtdutils; inherit (pkgs.pkgsBuildBuild) runCommand mtdutils;
endian = if pkgs.stdenv.isBigEndian endian = if pkgs.stdenv.isBigEndian then "--big-endian" else "--little-endian";
then "--big-endian" else "--little-endian"; in
in runCommand "make-jffs2" { runCommand "make-jffs2"
depsBuildBuild = [ mtdutils ]; {
} '' depsBuildBuild = [ mtdutils ];
tree=${o.bootablerootdir} }
(cd $tree && mkfs.jffs2 --compression-mode=size ${endian} -e ${toString config.hardware.flash.eraseBlockSize} --enable-compressor=lzo --pad --root . --output $out --squash --faketime ) ''
''; tree=${o.bootablerootdir}
(cd $tree && mkfs.jffs2 --compression-mode=size ${endian} -e ${toString config.hardware.flash.eraseBlockSize} --enable-compressor=lzo --pad --root . --output $out --squash --faketime )
'';
}; };
}; };
} }

View File

@@ -1,14 +1,15 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
o = config.system.outputs; o = config.system.outputs;
phram_address = lib.toHexString (config.hardware.ram.startAddress + 256 * 1024 * 1024); phram_address = lib.toHexString (config.hardware.ram.startAddress + 256 * 1024 * 1024);
in { in
{
options.system.outputs = { options.system.outputs = {
mbrimage = mkOption { mbrimage = mkOption {
type = types.package; type = types.package;
@@ -20,7 +21,7 @@ in {
the contents of ``outputs.rootfs`` as its only partition. the contents of ``outputs.rootfs`` as its only partition.
''; '';
}; };
vmdisk = mkOption { type = types.package; }; vmdisk = mkOption { type = types.package; };
}; };
config = { config = {
@@ -28,15 +29,18 @@ in {
mbrimage = mbrimage =
let let
o = config.system.outputs; o = config.system.outputs;
in pkgs.runCommand "mbrimage" { in
depsBuildBuild = [ pkgs.pkgsBuildBuild.util-linux ]; pkgs.runCommand "mbrimage"
} '' {
# leave 4 sectors at start for partition table depsBuildBuild = [ pkgs.pkgsBuildBuild.util-linux ];
# and alignment to 2048 bytes (does that help?) }
dd if=${o.rootfs} of=$out bs=512 seek=4 conv=sync ''
echo '4,-,L,*' | sfdisk $out # leave 4 sectors at start for partition table
''; # and alignment to 2048 bytes (does that help?)
vmdisk = pkgs.runCommand "vmdisk" {} '' dd if=${o.rootfs} of=$out bs=512 seek=4 conv=sync
echo '4,-,L,*' | sfdisk $out
'';
vmdisk = pkgs.runCommand "vmdisk" { } ''
mkdir $out mkdir $out
cd $out cd $out
ln -s ${o.mbrimage} ./mbrimage ln -s ${o.mbrimage} ./mbrimage

View File

@@ -1,17 +1,18 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkOption types concatStringsSep; inherit (lib) mkOption types concatStringsSep;
inherit (config.boot) tftp; inherit (config.boot) tftp;
in { in
{
options.system.outputs = { options.system.outputs = {
firmware = mkOption { firmware = mkOption {
type = types.package; type = types.package;
internal = true; # component of mtdimage internal = true; # component of mtdimage
description = '' description = ''
Binary image (combining kernel, FDT, rootfs, initramfs Binary image (combining kernel, FDT, rootfs, initramfs
if needed, etc) for the target device. if needed, etc) for the target device.
@@ -19,7 +20,7 @@ in {
}; };
flash-scr = mkOption { flash-scr = mkOption {
type = types.package; type = types.package;
internal = true; # component of mtdimage internal = true; # component of mtdimage
description = '' description = ''
Copy-pastable U-Boot commands to TFTP download the Copy-pastable U-Boot commands to TFTP download the
image and write it to flash image and write it to flash
@@ -60,13 +61,15 @@ in {
config = { config = {
kernel = { kernel = {
config = { config =
# this needs to be conditional on "not qemu" {
MTD_SPLIT_UIMAGE_FW = "y"; # this needs to be conditional on "not qemu"
} // lib.optionalAttrs (pkgs.stdenv.isMips) { MTD_SPLIT_UIMAGE_FW = "y";
# https://stackoverflow.com/questions/26466470/can-the-logical-erase-block-size-of-an-mtd-device-be-increased }
MTD_SPI_NOR_USE_4K_SECTORS = "n"; // lib.optionalAttrs (pkgs.stdenv.isMips) {
}; # https://stackoverflow.com/questions/26466470/can-the-logical-erase-block-size-of-an-mtd-device-be-increased
MTD_SPI_NOR_USE_4K_SECTORS = "n";
};
}; };
programs.busybox.applets = [ programs.busybox.applets = [
@@ -78,14 +81,17 @@ in {
let let
o = config.system.outputs; o = config.system.outputs;
bs = toString config.hardware.flash.eraseBlockSize; bs = toString config.hardware.flash.eraseBlockSize;
in pkgs.runCommand "firmware" {} '' in
pkgs.runCommand "firmware" { } ''
dd if=${o.uimage} of=$out bs=${bs} conv=sync dd if=${o.uimage} of=$out bs=${bs} conv=sync
dd if=${o.rootfs} of=$out bs=${bs} conv=sync,nocreat,notrunc oflag=append dd if=${o.rootfs} of=$out bs=${bs} conv=sync,nocreat,notrunc oflag=append
''; '';
mtdimage = mtdimage =
let o = config.system.outputs; in let
o = config.system.outputs;
in
# could use trivial-builders.linkFarmFromDrvs here? # could use trivial-builders.linkFarmFromDrvs here?
pkgs.runCommand "mtdimage" {} '' pkgs.runCommand "mtdimage" { } ''
mkdir $out mkdir $out
cd $out cd $out
ln -s ${o.firmware} firmware.bin ln -s ${o.firmware} firmware.bin
@@ -96,24 +102,24 @@ in {
ln -s ${o.uimage} uimage ln -s ${o.uimage} uimage
ln -s ${o.dtb} dtb ln -s ${o.dtb} dtb
ln -s ${o.flash-scr} flash.scr ln -s ${o.flash-scr} flash.scr
''; '';
flash-scr = flash-scr =
let let
inherit (pkgs.lib.trivial) toHexString; inherit (pkgs.lib.trivial) toHexString;
inherit (config.hardware) flash; inherit (config.hardware) flash;
in in
pkgs.buildPackages.runCommand "" {} '' pkgs.buildPackages.runCommand "" { } ''
imageSize=$(stat -L -c %s ${config.system.outputs.firmware}) imageSize=$(stat -L -c %s ${config.system.outputs.firmware})
cat > $out << EOF cat > $out << EOF
setenv serverip ${tftp.serverip} setenv serverip ${tftp.serverip}
setenv ipaddr ${tftp.ipaddr} setenv ipaddr ${tftp.ipaddr}
tftp 0x${toHexString tftp.loadAddress} result/firmware.bin tftp 0x${toHexString tftp.loadAddress} result/firmware.bin
erase 0x${toHexString flash.address} +0x${toHexString flash.size} erase 0x${toHexString flash.address} +0x${toHexString flash.size}
cp.b 0x${toHexString tftp.loadAddress} 0x${toHexString flash.address} \''${filesize} cp.b 0x${toHexString tftp.loadAddress} 0x${toHexString flash.address} \''${filesize}
echo command line was ${builtins.toJSON (concatStringsSep " " config.boot.commandLine)} echo command line was ${builtins.toJSON (concatStringsSep " " config.boot.commandLine)}
EOF EOF
''; '';
}; };
}; };
} }

View File

@@ -10,8 +10,7 @@ let
in in
{ {
config = mkIf (config.rootfsType == "squashfs") { config = mkIf (config.rootfsType == "squashfs") {
system.outputs.rootfs = system.outputs.rootfs = liminix.builders.squashfs config.filesystem.contents;
liminix.builders.squashfs config.filesystem.contents;
kernel.config = { kernel.config = {
SQUASHFS = "y"; SQUASHFS = "y";
SQUASHFS_XZ = "y"; SQUASHFS_XZ = "y";

View File

@@ -1,11 +1,16 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkEnableOption mkOption mkIf types; inherit (lib)
mkEnableOption
mkOption
mkIf
types
;
inherit (pkgs) runCommand; inherit (pkgs) runCommand;
in in
{ {
@@ -22,7 +27,6 @@ in
}; };
}; };
config = { config = {
system.outputs.systemConfiguration = system.outputs.systemConfiguration = pkgs.systemconfig config.filesystem.contents;
pkgs.systemconfig config.filesystem.contents;
}; };
} }

View File

@@ -1,15 +1,16 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkOption types concatStringsSep; inherit (lib) mkOption types concatStringsSep;
cfg = config.boot.tftp; cfg = config.boot.tftp;
hw = config.hardware; hw = config.hardware;
arch = pkgs.stdenv.hostPlatform.linuxArch; arch = pkgs.stdenv.hostPlatform.linuxArch;
in { in
{
imports = [ ../ramdisk.nix ]; imports = [ ../ramdisk.nix ];
options.boot.tftp = { options.boot.tftp = {
freeSpaceBytes = mkOption { freeSpaceBytes = mkOption {
@@ -17,7 +18,10 @@ in {
default = 0; default = 0;
}; };
kernelFormat = mkOption { kernelFormat = mkOption {
type = types.enum [ "zimage" "uimage" ]; type = types.enum [
"zimage"
"uimage"
];
default = "uimage"; default = "uimage";
}; };
compressRoot = mkOption { compressRoot = mkOption {
@@ -61,14 +65,22 @@ in {
assert config.rootfsType != "ubifs"; assert config.rootfsType != "ubifs";
let let
o = config.system.outputs; o = config.system.outputs;
image = let choices = { image =
uimage = o.uimage; let
zimage = o.kernel.zImage; choices = {
}; in choices.${cfg.kernelFormat}; uimage = o.uimage;
bootCommand = let choices = { zimage = o.kernel.zImage;
uimage = "bootm"; };
zimage = "bootz"; in
}; in choices.${cfg.kernelFormat}; choices.${cfg.kernelFormat};
bootCommand =
let
choices = {
uimage = "bootm";
zimage = "bootz";
};
in
choices.${cfg.kernelFormat};
cmdline = concatStringsSep " " config.boot.commandLine; cmdline = concatStringsSep " " config.boot.commandLine;
objcopy = "${pkgs.stdenv.cc.bintools.targetPrefix}objcopy"; objcopy = "${pkgs.stdenv.cc.bintools.targetPrefix}objcopy";
@@ -77,7 +89,16 @@ in {
rm -f vmlinux.bin.lzma ; lzma -k -z vmlinux.bin rm -f vmlinux.bin.lzma ; lzma -k -z vmlinux.bin
''; '';
in in
pkgs.runCommand "tftpboot" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ lzma dtc pkgs.stdenv.cc ubootTools ]; } '' pkgs.runCommand "tftpboot"
{
nativeBuildInputs = with pkgs.pkgsBuildBuild; [
lzma
dtc
pkgs.stdenv.cc
ubootTools
];
}
''
mkdir $out mkdir $out
cd $out cd $out
binsize() { local s=$(stat -L -c %s $1); echo $(($s + 0x1000 &(~0xfff))); } binsize() { local s=$(stat -L -c %s $1); echo $(($s + 0x1000 &(~0xfff))); }
@@ -97,17 +118,19 @@ in {
# end of the kernel is free # end of the kernel is free
dtbStart=$(($rootfsStart + $rootfsSize)) dtbStart=$(($rootfsStart + $rootfsSize))
${if cfg.compressRoot ${
then '' if cfg.compressRoot then
lzma -z9cv ${o.rootfs} > rootfs.lz ''
rootfsLzStart=$dtbStart lzma -z9cv ${o.rootfs} > rootfs.lz
rootfsLzSize=$(binsize rootfs.lz) rootfsLzStart=$dtbStart
dtbStart=$(($dtbStart + $rootfsLzSize)) rootfsLzSize=$(binsize rootfs.lz)
'' dtbStart=$(($dtbStart + $rootfsLzSize))
else '' ''
ln -s ${o.rootfs} rootfs else
'' ''
} ln -s ${o.rootfs} rootfs
''
}
cat ${o.dtb} > dtb cat ${o.dtb} > dtb
address_cells=$(fdtget dtb / '#address-cells') address_cells=$(fdtget dtb / '#address-cells')
@@ -128,37 +151,40 @@ in {
dtbSize=$(binsize ./dtb ) dtbSize=$(binsize ./dtb )
${if cfg.appendDTB then '' ${
imageStart=$dtbStart if cfg.appendDTB then
# re-package image with updated dtb ''
cat ${o.kernel} > vmlinux.elf imageStart=$dtbStart
${objcopy} --update-section .appended_dtb=dtb vmlinux.elf # re-package image with updated dtb
${stripAndZip} cat ${o.kernel} > vmlinux.elf
mkimage -A ${arch} -O linux -T kernel -C lzma -a $(hex ${toString hw.loadAddress}) -e $(hex ${toString hw.entryPoint}) -n '${lib.toUpper arch} Liminix Linux tftpboot' -d vmlinux.bin.lzma image ${objcopy} --update-section .appended_dtb=dtb vmlinux.elf
# dtc -I dtb -O dts -o /dev/stdout dtb | grep -A10 chosen ; exit 1 ${stripAndZip}
tftpcmd="tftpboot $(hex $imageStart) result/image " mkimage -A ${arch} -O linux -T kernel -C lzma -a $(hex ${toString hw.loadAddress}) -e $(hex ${toString hw.entryPoint}) -n '${lib.toUpper arch} Liminix Linux tftpboot' -d vmlinux.bin.lzma image
bootcmd="bootm $(hex $imageStart)" # dtc -I dtb -O dts -o /dev/stdout dtb | grep -A10 chosen ; exit 1
'' else '' tftpcmd="tftpboot $(hex $imageStart) result/image "
imageStart=$(($dtbStart + $dtbSize)) bootcmd="bootm $(hex $imageStart)"
tftpcmd="tftpboot $(hex $imageStart) result/image; tftpboot $(hex $dtbStart) result/dtb " ''
ln -s ${image} image else
bootcmd="${bootCommand} $(hex $imageStart) - $(hex $dtbStart)" ''
''} imageStart=$(($dtbStart + $dtbSize))
tftpcmd="tftpboot $(hex $imageStart) result/image; tftpboot $(hex $dtbStart) result/dtb "
ln -s ${image} image
bootcmd="${bootCommand} $(hex $imageStart) - $(hex $dtbStart)"
''
}
cat > boot.scr << EOF cat > boot.scr << EOF
setenv serverip ${cfg.serverip} setenv serverip ${cfg.serverip}
setenv ipaddr ${cfg.ipaddr} setenv ipaddr ${cfg.ipaddr}
${ ${
if cfg.compressRoot if cfg.compressRoot then
then "tftpboot $(hex $rootfsLzStart) result/rootfs.lz" "tftpboot $(hex $rootfsLzStart) result/rootfs.lz"
else "tftpboot $(hex $rootfsStart) result/rootfs" else
"tftpboot $(hex $rootfsStart) result/rootfs"
}; $tftpcmd }; $tftpcmd
${if cfg.compressRoot ${if cfg.compressRoot then "lzmadec $(hex $rootfsLzStart) $(hex $rootfsStart); " else ""} $bootcmd
then "lzmadec $(hex $rootfsLzStart) $(hex $rootfsStart); "
else ""
} $bootcmd
EOF EOF
''; '';
}; };
}; };

View File

@@ -1,14 +1,15 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
o = config.system.outputs; o = config.system.outputs;
cfg = config.tplink-safeloader; cfg = config.tplink-safeloader;
in { in
{
options.tplink-safeloader = { options.tplink-safeloader = {
board = mkOption { board = mkOption {
type = types.str; type = types.str;
@@ -53,9 +54,10 @@ in {
config = { config = {
system.outputs = rec { system.outputs = rec {
tplink-safeloader = tplink-safeloader =
pkgs.runCommand "tplink" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ firmware-utils ]; } '' pkgs.runCommand "tplink" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ firmware-utils ]; }
tplink-safeloader -B "${cfg.board}" -k "${o.uimage}" -r "${o.rootfs}" -o $out ''
''; tplink-safeloader -B "${cfg.board}" -k "${o.uimage}" -r "${o.rootfs}" -o $out
'';
}; };
}; };
} }

View File

@@ -1,8 +1,8 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkIf mkOption types; inherit (lib) mkIf mkOption types;
@@ -15,7 +15,7 @@ in
config = mkIf (config.rootfsType == "ubifs") { config = mkIf (config.rootfsType == "ubifs") {
kernel.config = { kernel.config = {
MTD_UBI="y"; MTD_UBI = "y";
UBIFS_FS = "y"; UBIFS_FS = "y";
UBIFS_FS_SECURITY = "n"; UBIFS_FS_SECURITY = "n";
}; };
@@ -25,13 +25,16 @@ in
let let
inherit (pkgs.pkgsBuildBuild) runCommand mtdutils; inherit (pkgs.pkgsBuildBuild) runCommand mtdutils;
cfg = config.hardware.ubi; cfg = config.hardware.ubi;
in runCommand "mkfs.ubifs" { in
depsBuildBuild = [ mtdutils ]; runCommand "mkfs.ubifs"
} '' {
mkdir tmp depsBuildBuild = [ mtdutils ];
tree=${o.bootablerootdir} }
mkfs.ubifs -x favor_lzo -c ${cfg.maxLEBcount} -m ${cfg.minIOSize} -e ${cfg.logicalEraseBlockSize} -y -r $tree --output $out --squash-uids -o $out ''
''; mkdir tmp
tree=${o.bootablerootdir}
mkfs.ubifs -x favor_lzo -c ${cfg.maxLEBcount} -m ${cfg.minIOSize} -e ${cfg.logicalEraseBlockSize} -y -r $tree --output $out --squash-uids -o $out
'';
}; };
}; };
} }

View File

@@ -1,8 +1,8 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkIf mkOption types; inherit (lib) mkIf mkOption types;
@@ -13,108 +13,111 @@ let
setenv loadaddr ${lib.toHexString cfg.loadAddress} setenv loadaddr ${lib.toHexString cfg.loadAddress}
tftpboot $loadaddr result/rootfs tftpboot $loadaddr result/rootfs
ubi write $loadaddr liminix $filesize ubi write $loadaddr liminix $filesize
''; '';
in { in
{
options.system.outputs = { options.system.outputs = {
ubimage = mkOption { ubimage = mkOption {
type = types.package; type = types.package;
description = '' description = ''
ubimage ubimage
******* *******
This output provides a UBIFS filesystem image and a small U-Boot script This output provides a UBIFS filesystem image and a small U-Boot script
to make the manual installation process very slightly simpler. You will to make the manual installation process very slightly simpler. You will
need a serial connection and a network connection to a TFTP server need a serial connection and a network connection to a TFTP server
containing the filesystem image it creates. containing the filesystem image it creates.
.. warning:: These steps were tested on a Belkin RT3200 (also known as .. warning:: These steps were tested on a Belkin RT3200 (also known as
Linksys E8450). Other devices may be set up differently, Linksys E8450). Other devices may be set up differently,
so use them as inspiration and don't just paste them so use them as inspiration and don't just paste them
blindly. blindly.
1) determine which MTD device is being used for UBI, and the partition name: 1) determine which MTD device is being used for UBI, and the partition name:
.. code-block:: console .. code-block:: console
uboot> ubi part uboot> ubi part
Device 0: ubi0, MTD partition ubi Device 0: ubi0, MTD partition ubi
In this case the important value is ``ubi0`` In this case the important value is ``ubi0``
2) list the available volumes and create a new one on which to install Liminix 2) list the available volumes and create a new one on which to install Liminix
.. code-block:: console .. code-block:: console
uboot> ubi info l uboot> ubi info l
[ copious output scrolls past ] [ copious output scrolls past ]
Expect there to be existing volumes and for some or all of them to be Expect there to be existing volumes and for some or all of them to be
important. Unless you know what you're doing, don't remove anything important. Unless you know what you're doing, don't remove anything
whose name suggests it's related to uboot, or any kind of backup or whose name suggests it's related to uboot, or any kind of backup or
recovery partition. To see how much space is free: recovery partition. To see how much space is free:
.. code-block:: console .. code-block:: console
uboot> ubi info uboot> ubi info
[ ... ] [ ... ]
UBI: available PEBs: 823 UBI: available PEBs: 823
Now we can make our new root volume Now we can make our new root volume
.. code-block:: console .. code-block:: console
uboot> ubi create liminix - uboot> ubi create liminix -
3) transfer the root filesystem from the build system and write it to 3) transfer the root filesystem from the build system and write it to
the new volume. Paste the contents of :file:`result/flash.scr` one line at a time the new volume. Paste the contents of :file:`result/flash.scr` one line at a time
into U-Boot: into U-Boot:
.. code-block:: console .. code-block:: console
uboot> setenv serverip 10.0.0.1 uboot> setenv serverip 10.0.0.1
uboot> setenv ipaddr 10.0.0.8 uboot> setenv ipaddr 10.0.0.8
uboot> setenv loadaddr 4007FF28 uboot> setenv loadaddr 4007FF28
uboot> tftpboot $loadaddr result/rootfs uboot> tftpboot $loadaddr result/rootfs
uboot> ubi write $loadaddr liminix $filesize uboot> ubi write $loadaddr liminix $filesize
Now we have the root filesystem installed on the device. You Now we have the root filesystem installed on the device. You
can even mount it and poke around using :command:`ubifsmount ubi0:liminix; ubifsls /` can even mount it and poke around using :command:`ubifsmount ubi0:liminix; ubifsls /`
4) optional: before you configure the device to boot into Liminix 4) optional: before you configure the device to boot into Liminix
automatically, you can try booting it by hand to see if it works: automatically, you can try booting it by hand to see if it works:
.. code-block:: console .. code-block:: console
uboot> ubifsmount ubi0:liminix uboot> ubifsmount ubi0:liminix
uboot> ubifsload ''${loadaddr} boot/fit uboot> ubifsload ''${loadaddr} boot/fit
uboot> bootm ''${loadaddr} uboot> bootm ''${loadaddr}
Once you've done this and you're happy with it, reset the device to Once you've done this and you're happy with it, reset the device to
return to U-Boot. return to U-Boot.
5) Instructions for configuring autoboot are likely to be very 5) Instructions for configuring autoboot are likely to be very
device-dependent and you should consult the Liminix documentation for device-dependent and you should consult the Liminix documentation for
your device. (If you're bringing up a new device, some detective work your device. (If you're bringing up a new device, some detective work
may be needed. Try running `printenv` and trace through the flow of may be needed. Try running `printenv` and trace through the flow of
execution from (probably) :command:`$bootcmd` and look for a suitable execution from (probably) :command:`$bootcmd` and look for a suitable
variable to change) variable to change)
6) Now you can reboot the device into Liminix 6) Now you can reboot the device into Liminix
.. code-block:: console .. code-block:: console
uboot> reset uboot> reset
''; '';
}; };
}; };
config.system.outputs.ubimage = config.system.outputs.ubimage =
assert config.rootfsType == "ubifs"; assert config.rootfsType == "ubifs";
let o = config.system.outputs; in let
pkgs.runCommand "ubimage" {} '' o = config.system.outputs;
in
pkgs.runCommand "ubimage" { } ''
mkdir $out mkdir $out
cd $out cd $out
ln -s ${o.rootfs} rootfs ln -s ${o.rootfs} rootfs
ln -s ${instructions} flash.scr ln -s ${instructions} flash.scr
''; '';
} }

View File

@@ -1,93 +1,112 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkIf mkOption types concatStringsSep optionalString; inherit (lib)
mkIf
mkOption
types
concatStringsSep
optionalString
;
in in
{ {
imports = [ imports = [
./initramfs.nix ./initramfs.nix
./ubifs.nix ./ubifs.nix
]; ];
options.hardware.ubi = { options.hardware.ubi = {
minIOSize = mkOption { type = types.str; }; minIOSize = mkOption { type = types.str; };
eraseBlockSize = mkOption { type = types.str; }; # LEB eraseBlockSize = mkOption { type = types.str; }; # LEB
maxLEBcount = mkOption { type = types.str; }; # LEB maxLEBcount = mkOption { type = types.str; }; # LEB
}; };
options.system.outputs.ubivolume = mkOption { options.system.outputs.ubivolume = mkOption {
type = types.package; type = types.package;
};
config = mkIf (config.rootfsType == "ubifs") {
kernel.config = {
MTD_UBI = "y";
UBIFS_FS = "y";
UBIFS_FS_SECURITY = "n";
}; };
boot.initramfs.enable = true;
config = mkIf (config.rootfsType == "ubifs") { system.outputs.ubivolume =
kernel.config = {
MTD_UBI="y";
UBIFS_FS = "y";
UBIFS_FS_SECURITY = "n";
};
boot.initramfs.enable = true;
system.outputs.ubivolume =
let let
inherit (pkgs.pkgsBuildBuild) runCommand; inherit (pkgs.pkgsBuildBuild) runCommand;
ubiVolume = ({ name, volumeId, image, flags ? [] }: ubiVolume = (
'' {
[${name}] name,
mode=ubi volumeId,
vol_id=${toString volumeId} image,
vol_type=dynamic flags ? [ ],
vol_name=${name} }:
vol_alignment=1 ''
${optionalString (image != null) '' [${name}]
image=${image} mode=ubi
''} vol_id=${toString volumeId}
${optionalString (image == null) '' vol_type=dynamic
vol_size=1MiB vol_name=${name}
''} vol_alignment=1
${optionalString (flags != []) '' ${optionalString (image != null) ''
vol_flags=${concatStringsSep "," flags} image=${image}
''} ''}
''); ${optionalString (image == null) ''
vol_size=1MiB
''}
${optionalString (flags != [ ]) ''
vol_flags=${concatStringsSep "," flags}
''}
''
);
ubiImage = (volumes: ubiImage = (
let volumes:
ubinizeConfig = pkgs.writeText "ubinize.conf" (concatStringsSep "\n" volumes); let
inherit (pkgs.pkgsBuildBuild) mtdutils; ubinizeConfig = pkgs.writeText "ubinize.conf" (concatStringsSep "\n" volumes);
in inherit (pkgs.pkgsBuildBuild) mtdutils;
runCommand "ubinize" { in
depsBuildBuild = [ mtdutils ]; runCommand "ubinize"
# block size := 128kb {
# page size := 2048 depsBuildBuild = [ mtdutils ];
# ubninize opts := -E 5 # block size := 128kb
} '' # page size := 2048
ubinize -Q "$SOURCE_DATE_EPOCH" -o $out \ # ubninize opts := -E 5
-p ${config.hardware.ubi.physicalEraseBlockSize} -m ${config.hardware.ubi.minIOSize} \ }
-e ${config.hardware.ubi.logicalEraseBlockSize} \ ''
${ubinizeConfig} 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 }: ubiDisk = (
let { initramfs }:
initramfsUbi = ubiVolume { let
name = "rootfs"; initramfsUbi = ubiVolume {
volumeId = 0; name = "rootfs";
image = initramfs; volumeId = 0;
flags = [ "autoresize" ]; image = initramfs;
}; flags = [ "autoresize" ];
in };
in
ubiImage [ ubiImage [
initramfsUbi initramfsUbi
]); ]
);
disk = ubiDisk { disk = ubiDisk {
initramfs = config.system.outputs.rootfs; # ??? initramfs = config.system.outputs.rootfs; # ???
}; };
in in
disk; disk;
}; };
} }

View File

@@ -1,8 +1,8 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkIf; inherit (lib) mkIf;
@@ -25,13 +25,12 @@ in
''; '';
}; };
config.system.outputs.updater = config.system.outputs.updater = runCommand "buildUpdater" { } ''
runCommand "buildUpdater" { } '' mkdir -p $out/bin $out/etc
mkdir -p $out/bin $out/etc cp ${o.kernel.config} $out/etc/kconfig
cp ${o.kernel.config} $out/etc/kconfig substitute ${./update.sh} $out/bin/update.sh \
substitute ${./update.sh} $out/bin/update.sh \ --subst-var-by toplevel ${o.systemConfiguration} \
--subst-var-by toplevel ${o.systemConfiguration} \ --subst-var-by min_copy_closure ${min-copy-closure}
--subst-var-by min_copy_closure ${min-copy-closure} chmod +x $out/bin/update.sh
chmod +x $out/bin/update.sh '';
'';
} }

View File

@@ -1,8 +1,8 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkOption types concatStringsSep; inherit (lib) mkOption types concatStringsSep;
@@ -49,12 +49,15 @@ in
let let
inherit (config.system.outputs) rootfs kernel manifest; inherit (config.system.outputs) rootfs kernel manifest;
cmdline = builtins.toJSON (concatStringsSep " " config.boot.commandLine); cmdline = builtins.toJSON (concatStringsSep " " config.boot.commandLine);
makeBootableImage = pkgs.runCommandCC "objcopy" {} makeBootableImage = pkgs.runCommandCC "objcopy" { } (
(if pkgs.stdenv.hostPlatform.isAarch if pkgs.stdenv.hostPlatform.isAarch then
then "${pkgs.stdenv.cc.targetPrefix}objcopy -O binary -R .comment -S ${kernel} $out" "${pkgs.stdenv.cc.targetPrefix}objcopy -O binary -R .comment -S ${kernel} $out"
else "cp ${kernel} $out"); else
"cp ${kernel} $out"
);
phram_address = lib.toHexString (config.hardware.ram.startAddress + 256 * 1024 * 1024); phram_address = lib.toHexString (config.hardware.ram.startAddress + 256 * 1024 * 1024);
in pkgs.runCommand "vmroot" {} '' in
pkgs.runCommand "vmroot" { } ''
mkdir $out mkdir $out
cd $out cd $out
ln -s ${rootfs} rootfs ln -s ${rootfs} rootfs
@@ -67,7 +70,7 @@ in
${pkgs.pkgsBuildBuild.run-liminix-vm}/bin/run-liminix-vm --command-line ${cmdline} --arch ${pkgs.stdenv.hostPlatform.qemuArch} --phram-address 0x${phram_address} \$* ${makeBootableImage} ${config.system.outputs.rootfs} ${pkgs.pkgsBuildBuild.run-liminix-vm}/bin/run-liminix-vm --command-line ${cmdline} --arch ${pkgs.stdenv.hostPlatform.qemuArch} --phram-address 0x${phram_address} \$* ${makeBootableImage} ${config.system.outputs.rootfs}
EOF EOF
chmod +x run.sh chmod +x run.sh
''; '';
}; };
}; };
} }

View File

@@ -1,25 +1,26 @@
{ {
config config,
, pkgs pkgs,
, lib lib,
, ... ...
}: }:
let let
inherit (lib) mkIf mkOption types; inherit (lib) mkIf mkOption types;
models = "6b e1 6f e1 ff ff ff ff ff ff"; models = "6b e1 6f e1 ff ff ff ff ff ff";
in { in
{
options.system.outputs = { options.system.outputs = {
zyxel-nwa-fit = mkOption { zyxel-nwa-fit = mkOption {
type = types.package; type = types.package;
description = '' description = ''
zyxel-nwa-fit zyxel-nwa-fit
************* *************
This output provides a FIT image for Zyxel NWA series This output provides a FIT image for Zyxel NWA series
containing a kernel image and an UBIFS rootfs. containing a kernel image and an UBIFS rootfs.
It can usually be used as a factory image to install Liminix It can usually be used as a factory image to install Liminix
on a system with pre-existing firmware and OS. on a system with pre-existing firmware and OS.
''; '';
}; };
}; };
@@ -34,38 +35,43 @@ on a system with pre-existing firmware and OS.
let let
o = config.system.outputs; o = config.system.outputs;
# 8129kb padding. # 8129kb padding.
paddedKernel = pkgs.runCommand "padded-kernel" {} '' paddedKernel = pkgs.runCommand "padded-kernel" { } ''
cp --no-preserve=mode ${o.uimage} $out cp --no-preserve=mode ${o.uimage} $out
dd if=/dev/zero of=$out bs=1 count=1 seek=8388607 dd if=/dev/zero of=$out bs=1 count=1 seek=8388607
''; '';
firmwareImage = pkgs.runCommand "firmware-image" {} '' firmwareImage = pkgs.runCommand "firmware-image" { } ''
cat ${paddedKernel} ${o.ubivolume} > $out cat ${paddedKernel} ${o.ubivolume} > $out
''; '';
dts = pkgs.writeText "image.its" '' dts = pkgs.writeText "image.its" ''
/dts-v1/; /dts-v1/;
/ { / {
description = "Zyxel FIT (Flattened Image Tree)"; description = "Zyxel FIT (Flattened Image Tree)";
compat-models = [${models}]; compat-models = [${models}];
#address-cells = <1>; #address-cells = <1>;
images { images {
firmware { firmware {
data = /incbin/("${firmwareImage}"); data = /incbin/("${firmwareImage}");
type = "firmware"; type = "firmware";
compression = "none"; compression = "none";
hash@1 { hash@1 {
algo = "sha1"; algo = "sha1";
};
}; };
}; };
}; };
}; '';
'';
in in
pkgs.runCommand "zyxel-nwa-fit-${config.boot.imageType}" { pkgs.runCommand "zyxel-nwa-fit-${config.boot.imageType}"
nativeBuildInputs = [ pkgs.pkgsBuildBuild.ubootTools pkgs.pkgsBuildBuild.dtc ]; {
} '' nativeBuildInputs = [
mkimage -f ${dts} $out pkgs.pkgsBuildBuild.ubootTools
''; pkgs.pkgsBuildBuild.dtc
];
}
''
mkimage -f ${dts} $out
'';
}; };
} }

View File

@@ -1,20 +1,32 @@
{ writeAshScript, liminix, svc, lib, serviceFns, output-template }: {
writeAshScript,
liminix,
svc,
lib,
serviceFns,
output-template,
}:
{ {
command, command,
name, name,
debug debug,
, username, username,
password, password,
lcpEcho, lcpEcho,
ppp-options, ppp-options,
dependencies ? [] dependencies ? [ ],
} : }:
let let
inherit (lib) optional optionals escapeShellArgs concatStringsSep; inherit (lib)
optional
optionals
escapeShellArgs
concatStringsSep
;
inherit (liminix.services) longrun; inherit (liminix.services) longrun;
inherit (builtins) toJSON toString typeOf; inherit (builtins) toJSON toString typeOf;
ip-up = writeAshScript "ip-up" {} '' ip-up = writeAshScript "ip-up" { } ''
exec >&5 2>&5 exec >&5 2>&5
. ${serviceFns} . ${serviceFns}
in_outputs ${name} in_outputs ${name}
@@ -28,7 +40,7 @@ let
if test -n "''${DNS2}" ;then echo ''${DNS2} > ns2 ; fi if test -n "''${DNS2}" ;then echo ''${DNS2} > ns2 ; fi
test -e ipv6-address && echo >/proc/self/fd/10 test -e ipv6-address && echo >/proc/self/fd/10
''; '';
ip6-up = writeAshScript "ip6-up" {} '' ip6-up = writeAshScript "ip6-up" { } ''
exec >&5 2>&5 exec >&5 2>&5
. ${serviceFns} . ${serviceFns}
in_outputs ${name} in_outputs ${name}
@@ -37,35 +49,61 @@ let
test -e ifname && echo >/proc/self/fd/10 test -e ifname && echo >/proc/self/fd/10
''; '';
literal_or_output = literal_or_output =
let v = o: ({ let
string = toJSON; v =
int = toJSON; o:
lambda = (o: "output(${toJSON (o "service")}, ${toJSON (o "path")})"); (
}.${typeOf o}) o; {
in o: "{{ ${v o} }}"; string = toJSON;
int = toJSON;
lambda = (o: "output(${toJSON (o "service")}, ${toJSON (o "path")})");
}
.${typeOf o}
)
o;
in
o: "{{ ${v o} }}";
ppp-options' = ppp-options' =
["+ipv6" "noauth"] [
"+ipv6"
"noauth"
]
++ optional debug "debug" ++ optional debug "debug"
++ optionals (username != null) ["name" (literal_or_output username)] ++ optionals (username != null) [
++ optionals (password != null) ["password" (literal_or_output password)] "name"
(literal_or_output username)
]
++ optionals (password != null) [
"password"
(literal_or_output password)
]
++ optional lcpEcho.adaptive "lcp-echo-adaptive" ++ optional lcpEcho.adaptive "lcp-echo-adaptive"
++ optionals (lcpEcho.interval != null) ++ optionals (lcpEcho.interval != null) [
["lcp-echo-interval" (toString lcpEcho.interval)] "lcp-echo-interval"
++ optionals (lcpEcho.failure != null) (toString lcpEcho.interval)
["lcp-echo-failure" (toString lcpEcho.failure)] ]
++ optionals (lcpEcho.failure != null) [
"lcp-echo-failure"
(toString lcpEcho.failure)
]
++ ppp-options ++ ppp-options
++ ["ip-up-script" ip-up ++ [
"ipv6-up-script" ip6-up "ip-up-script"
"ipparam" name ip-up
"nodetach" "ipv6-up-script"
# usepeerdns requests DNS servers from peer (which is good), ip6-up
# then attempts to write them to /nix/store/xxxx/ppp/resolv.conf "ipparam"
# which causes an unsightly but inconsequential error message name
"usepeerdns" "nodetach"
"nodefaultroute" # usepeerdns requests DNS servers from peer (which is good),
"logfd" "2" # then attempts to write them to /nix/store/xxxx/ppp/resolv.conf
]; # which causes an unsightly but inconsequential error message
"usepeerdns"
"nodefaultroute"
"logfd"
"2"
];
service = longrun { service = longrun {
inherit name; inherit name;
run = '' run = ''
@@ -77,12 +115,15 @@ let
${command} ${command}
''; '';
notification-fd = 10; notification-fd = 10;
timeout-up = if lcpEcho.failure != null timeout-up =
then (10 + lcpEcho.failure * lcpEcho.interval) * 1000 if lcpEcho.failure != null then (10 + lcpEcho.failure * lcpEcho.interval) * 1000 else 60 * 1000;
else 60 * 1000;
inherit dependencies; inherit dependencies;
}; };
in svc.secrets.subscriber.build { in
watch = lib.filter (n: typeOf n=="lambda") [ username password ]; svc.secrets.subscriber.build {
watch = lib.filter (n: typeOf n == "lambda") [
username
password
];
inherit service; inherit service;
} }

View File

@@ -13,18 +13,24 @@
## conjunction with a DHCP uplink, or other more creative forms of ## conjunction with a DHCP uplink, or other more creative forms of
## network connection ## network connection
{
{ lib, pkgs, config, ...}: lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;
mkStringOption = mkStringOption =
description: mkOption { description:
mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
inherit description; inherit description;
}; };
in { in
{
imports = [ ../secrets ]; imports = [ ../secrets ];
options = { options = {
system.service.pppoe = mkOption { system.service.pppoe = mkOption {
@@ -61,7 +67,7 @@ in {
default = 3; default = 3;
description = "send an LCP echo-request frame to the peer every n seconds"; description = "send an LCP echo-request frame to the peer every n seconds";
}; };
failure = mkOption { failure = mkOption {
type = types.nullOr types.int; type = types.nullOr types.int;
default = 3; default = 3;
description = "terminate connection if n LCP echo-requests are sent without receiving a valid LCP echo-reply"; description = "terminate connection if n LCP echo-requests are sent without receiving a valid LCP echo-reply";
@@ -75,7 +81,7 @@ in {
ppp-options = mkOption { ppp-options = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
description = "options supplied on ppp command line"; description = "options supplied on ppp command line";
default = []; default = [ ];
}; };
}; };
system.service.l2tp = config.system.callService ./l2tp.nix { system.service.l2tp = config.system.callService ./l2tp.nix {
@@ -104,7 +110,7 @@ in {
default = 3; default = 3;
description = "send an LCP echo-request frame to the peer every n seconds"; description = "send an LCP echo-request frame to the peer every n seconds";
}; };
failure = mkOption { failure = mkOption {
type = types.nullOr types.int; type = types.nullOr types.int;
default = 3; default = 3;
description = "terminate connection if n LCP echo-requests are sent without receiving a valid LCP echo-reply"; description = "terminate connection if n LCP echo-requests are sent without receiving a valid LCP echo-reply";
@@ -117,7 +123,7 @@ in {
}; };
ppp-options = mkOption { ppp-options = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = []; default = [ ];
description = "options supplied on ppp command line"; description = "options supplied on ppp command line";
}; };
}; };

View File

@@ -7,14 +7,15 @@
writeAshScript, writeAshScript,
writeText, writeText,
xl2tpd, xl2tpd,
callPackage callPackage,
} : }:
{ lns, {
lns,
ppp-options, ppp-options,
lcpEcho, lcpEcho,
username, username,
password, password,
debug debug,
}: }:
let let
name = "${lns}.l2tp"; name = "${lns}.l2tp";
@@ -31,8 +32,16 @@ let
max redials = 2 # this gives 1 actual retry, as xl2tpd can't count max redials = 2 # this gives 1 actual retry, as xl2tpd can't count
''; '';
control = "/run/${name}/control"; control = "/run/${name}/control";
in common { in
inherit name debug username password lcpEcho ppp-options; common {
inherit
name
debug
username
password
lcpEcho
ppp-options
;
command = '' command = ''
touch ${control} touch ${control}
exec ${xl2tpd}/bin/xl2tpd -D -p /run/${name}/${name}.pid -c ${conf} -C ${control} exec ${xl2tpd}/bin/xl2tpd -D -p /run/${name}/${name}.pid -c ${conf} -C ${control}

View File

@@ -7,22 +7,32 @@
serviceFns, serviceFns,
svc, svc,
writeAshScript, writeAshScript,
callPackage callPackage,
} : }:
{ interface, {
interface,
ppp-options, ppp-options,
lcpEcho, lcpEcho,
username, username,
password, password,
debug debug,
}: }:
let let
name = "${interface.name}.pppoe"; name = "${interface.name}.pppoe";
common = callPackage ./common.nix { inherit svc; }; common = callPackage ./common.nix { inherit svc; };
timeoutOpt = if lcpEcho.interval != null then "-T ${builtins.toString (4 * lcpEcho.interval)}" else ""; timeoutOpt =
in common { if lcpEcho.interval != null then "-T ${builtins.toString (4 * lcpEcho.interval)}" else "";
inherit name debug username password lcpEcho ppp-options; in
common {
inherit
name
debug
username
password
lcpEcho
ppp-options
;
command = '' command = ''
exec ${ppp}/bin/pppd pty "${pppoe}/bin/pppoe ${timeoutOpt} -I $(output ${interface} ifname)" file /run/${name}/ppp-options exec ${ppp}/bin/pppd pty "${pppoe}/bin/pppoe ${timeoutOpt} -I $(output ${interface} ifname)" file /run/${name}/ppp-options
''; '';

View File

@@ -1,8 +1,18 @@
{ config, pkgs, lib, ... } : {
config,
pkgs,
lib,
...
}:
let let
svc = config.system.service; svc = config.system.service;
cfg = config.profile.gateway; cfg = config.profile.gateway;
inherit (lib) mkOption mkEnableOption mkIf types; inherit (lib)
mkOption
mkEnableOption
mkIf
types
;
inherit (pkgs) liminix serviceFns; inherit (pkgs) liminix serviceFns;
inherit (liminix.services) bundle oneshot; inherit (liminix.services) bundle oneshot;
hostaps = hostaps =
@@ -14,24 +24,27 @@ let
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?) wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2 rsn_pairwise = "CCMP"; # auth for wpa2
}; };
in lib.mapAttrs' in
(name : value : lib.mapAttrs' (
let name: value:
attrs = defaults // { ssid = name; } // value; let
in lib.nameValuePair attrs = defaults // { ssid = name; } // value;
"hostap-${name}" in
(svc.hostapd.build { lib.nameValuePair "hostap-${name}" (
interface = attrs.interface; svc.hostapd.build {
params = lib.filterAttrs (k: v: k != "interface") attrs; interface = attrs.interface;
})) params = lib.filterAttrs (k: v: k != "interface") attrs;
cfg.wireless.networks; }
in { )
) cfg.wireless.networks;
in
{
options.profile.gateway = { options.profile.gateway = {
lan = { lan = {
interfaces = mkOption { interfaces = mkOption {
type = types.listOf liminix.lib.types.interface; type = types.listOf liminix.lib.types.interface;
default = []; default = [ ];
}; };
address = mkOption { address = mkOption {
type = types.attrs; type = types.attrs;
@@ -49,7 +62,7 @@ in {
enable = mkEnableOption "firewall"; enable = mkEnableOption "firewall";
rules = mkOption { type = types.attrsOf types.attrs; }; rules = mkOption { type = types.attrsOf types.attrs; };
zones = mkOption { zones = mkOption {
type = types.attrsOf (types.listOf liminix.lib.types.service); type = types.attrsOf (types.listOf liminix.lib.types.service);
default = { default = {
lan = [ config.services.int ]; lan = [ config.services.int ];
wan = [ config.services.wan ]; wan = [ config.services.wan ];
@@ -82,11 +95,14 @@ in {
]; ];
config = { config = {
services.int = svc.network.address.build ({ services.int = svc.network.address.build (
interface = svc.bridge.primary.build { ifname = "int"; }; {
} // cfg.lan.address); interface = svc.bridge.primary.build { ifname = "int"; };
}
// cfg.lan.address
);
services.bridge = svc.bridge.members.build { services.bridge = svc.bridge.members.build {
primary = config.services.int; primary = config.services.int;
members = cfg.lan.interfaces; members = cfg.lan.interfaces;
}; };
@@ -113,12 +129,15 @@ in {
}) })
]; ];
}; };
in mkIf cfg.wan.dhcp6.enable bundl; in
mkIf cfg.wan.dhcp6.enable bundl;
services.dns = services.dns =
let interface = config.services.int; let
dcfg = cfg.lan.dhcp; interface = config.services.int;
in svc.dnsmasq.build { dcfg = cfg.lan.dhcp;
in
svc.dnsmasq.build {
resolvconf = config.services.resolvconf; resolvconf = config.services.resolvconf;
inherit interface; inherit interface;
ranges = [ ranges = [
@@ -147,11 +166,12 @@ in {
interface = config.services.wan; interface = config.services.wan;
}; };
services.firewall = mkIf cfg.firewall.enable services.firewall = mkIf cfg.firewall.enable (
(svc.firewall.build { svc.firewall.build {
extraRules = cfg.firewall.rules; extraRules = cfg.firewall.rules;
inherit (cfg.firewall) zones; inherit (cfg.firewall) zones;
}); }
);
services.resolvconf = oneshot rec { services.resolvconf = oneshot rec {
dependencies = [ config.services.wan ]; dependencies = [ config.services.wan ];
@@ -166,11 +186,13 @@ in {
}; };
filesystem = filesystem =
let inherit (pkgs.pseudofile) dir symlink; let
in dir { inherit (pkgs.pseudofile) dir symlink;
in
dir {
etc = dir { etc = dir {
"resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf"; "resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf";
}; };
}; };
}; };
} }

View File

@@ -3,9 +3,10 @@
pkgs, pkgs,
lib, lib,
... ...
}: let }:
let
inherit (pkgs) liminix; inherit (pkgs) liminix;
inherit (lib) mkOption types ; inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot target; inherit (pkgs.liminix.services) oneshot target;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
@@ -22,19 +23,22 @@
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?) wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2 rsn_pairwise = "CCMP"; # auth for wpa2
}; };
in lib.mapAttrs' in
(name : value : lib.mapAttrs' (
let name: value:
attrs = defaults // { ssid = name; } // value; let
in lib.nameValuePair attrs = defaults // { ssid = name; } // value;
"hostap-${name}" in
(svc.hostapd.build { lib.nameValuePair "hostap-${name}" (
interface = attrs.interface; svc.hostapd.build {
params = lib.filterAttrs (k: v: k != "interface") attrs; interface = attrs.interface;
})) params = lib.filterAttrs (k: v: k != "interface") attrs;
cfg.wireless.networks; }
)
) cfg.wireless.networks;
in { in
{
imports = [ imports = [
../wlan.nix ../wlan.nix
../network ../network
@@ -46,7 +50,7 @@ in {
options.profile.wap = { options.profile.wap = {
interfaces = mkOption { interfaces = mkOption {
type = types.listOf liminix.lib.types.interface; type = types.listOf liminix.lib.types.interface;
default = []; default = [ ];
}; };
wireless = mkOption { wireless = mkOption {
type = types.attrsOf types.anything; type = types.attrsOf types.anything;
@@ -71,7 +75,7 @@ in {
services.defaultroute4 = svc.network.route.build { services.defaultroute4 = svc.network.route.build {
via = "$(output ${config.services.dhcpc} router)"; via = "$(output ${config.services.dhcpc} router)";
target = "default"; target = "default";
dependencies = [config.services.dhcpc]; dependencies = [ config.services.dhcpc ];
}; };
services.resolvconf = oneshot rec { services.resolvconf = oneshot rec {

View File

@@ -1,7 +1,8 @@
{ config, lib, ... }: { config, lib, ... }:
let let
inherit (lib) mkIf mkEnableOption; # types concatStringsSep; inherit (lib) mkIf mkEnableOption; # types concatStringsSep;
in { in
{
options = { options = {
boot = { boot = {
ramdisk = { ramdisk = {

View File

@@ -3,13 +3,18 @@
## Given a list of services, run each in turn until it exits, then ## Given a list of services, run each in turn until it exits, then
## runs the next. ## runs the next.
{
{ lib, pkgs, config, ...}: lib,
pkgs,
config,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;
inherit (pkgs.liminix.services) longrun; inherit (pkgs.liminix.services) longrun;
in { in
{
options = { options = {
system.service.round-robin = mkOption { system.service.round-robin = mkOption {
description = "run services one at a time and failover to next"; description = "run services one at a time and failover to next";
@@ -18,9 +23,9 @@ in {
}; };
config.system.service.round-robin = config.system.callService ./service.nix { config.system.service.round-robin = config.system.callService ./service.nix {
services = mkOption { services = mkOption {
type = types.listOf liminix.lib.types.service; type = types.listOf liminix.lib.types.service;
}; };
name = mkOption { name = mkOption {
type = types.str; type = types.str;
}; };
}; };

View File

@@ -1,22 +1,30 @@
{ {
liminix, lib, s6-rc-round-robin liminix,
lib,
s6-rc-round-robin,
}: }:
{ services, name} : { services, name }:
let let
inherit (liminix.services) oneshot longrun; inherit (liminix.services) oneshot longrun;
controlled-services = builtins.map controlled-services = builtins.map (
(s: s.overrideAttrs(o: { inherit controller; })) s:
services; s.overrideAttrs (o: {
controller = let name' = "control-${name}"; in longrun { inherit controller;
name = name'; })
run = '' ) services;
in_outputs ${name'} controller =
exec ${s6-rc-round-robin}/bin/s6-rc-round-robin \ let
-p ${proxy.name} \ name' = "control-${name}";
${lib.concatStringsSep " " in
(builtins.map (f: f.name) controlled-services)} longrun {
''; name = name';
}; run = ''
in_outputs ${name'}
exec ${s6-rc-round-robin}/bin/s6-rc-round-robin \
-p ${proxy.name} \
${lib.concatStringsSep " " (builtins.map (f: f.name) controlled-services)}
'';
};
proxy = oneshot rec { proxy = oneshot rec {
inherit name; inherit name;
inherit controller; inherit controller;
@@ -29,4 +37,5 @@ let
) )
''; '';
}; };
in proxy in
proxy

Some files were not shown because too many files have changed in this diff Show More