1
0

Compare commits

...

2 Commits

Author SHA1 Message Date
2e50368bd2 rename config.outputs to config.system.outputs
New rules: everything under "config" that isn't actually configuration
(e.g. build products) will in future live in config.system. This is
the first step.
2023-07-13 19:24:59 +01:00
492317623d more thoughts about modules 2023-07-13 11:54:50 +01:00
14 changed files with 339 additions and 122 deletions

View File

@ -1901,3 +1901,106 @@ Thu Jun 22 23:58:58 BST 2023
Looks like we're missing at least one kernel config setting for Looks like we're missing at least one kernel config setting for
nftables. Would this be a good time to do a derivation for building nftables. Would this be a good time to do a derivation for building
kernel modules? kernel modules?
Sun Jul 9 21:21:17 BST 2023
Tue Jul 11 22:10:17 BST 2023
- s6 cheatsheet, find or write
- could we have > 1 module add to services.default?
- odhcp should parse values from environ and write more files, to save readers
from parsing it
- pkgs.liminix, who knows what thats for any more?
- interface.device, as a general rule, doesn't work because the
device name may be known only at runtime (e.g. for ppp)
- iperf
- figure out wifi regdomain
Tue Jul 11 23:01:59 BST 2023
We can make services depend on kernel modules, however not on bakedin
kernel config
[from March: "Let's think about services and modules."]
Module
+ can change global config
* add users, groups etc
* change kernel config
* change busybox config
+ well-typed parameters
- is a "singleton": can't have the same module included twice
with different config. e.g. can't have two hostap modules running on
different wlan radios.
- can't express dependencies: a depends on b
thought I had then was: modules provide services. requiring the
ppp module causes config.services.ppp to exist, so you can
services.default = [
(config.services.ppp {
tty = "17";
baud = "57600";
secrets = blah;
})
...
]
this might work. also though we should find out how to do type checking on
service params
Wed Jul 12 23:23:02 BST 2023
https://github.com/NixOS/mobile-nixos/pull/406 // why mobile nixos uses
mobile.outputs instead of system.build
suggests that system.build may not be a thing to blindly emulate
if a service is a derivation should we expect to want to be able to call
it with .override? maybe we want to override the package containing the
daemon it runs. How do we best pass service config as well?
Maybe a service template is a function that returns a derivation
imports = [ ./modules/pqmud.nix ];
services.mud = system.services.pqmud {
realm = "A deep cavern";
port = 4067;
users = import ./allowed-users.nix;
# etc etc
};
services.mudBeta = let mud =
system.services.pqmud {
realm = "A very deep cavern";
port = 4068;
users = import ./allowed-users.nix;
};
in mud.overrideAttrs { pqmud = pkgs.pkmudLatest; };
so we have
config.system.services # services provided by modules
config.system.outputs # build artefacts of various types
the services provided by a module must be introspectable in some way
so that we can compile a list of service options per module
service parameters are defined using the module type system.
Something like this?
# mud.nix
system.services.pqmud = args :
let t = {
name = mkOption { type = types.str; };
realm = mkOption { type = types.str; };
port = mkOption { type = types.port; default = 12345; };
users = mkOption { type = types.any; };
};
in assert isType (submodule { options = t; }) args; longrun {
inherit (args) name;
run = "${pkgs.pqmud}/bin/pqmud --port ${port} ....."
};

View File

@ -41,8 +41,8 @@ let
]; ];
}).config.system; }).config.system;
in { in {
outputs = config.outputs // { outputs = config.system.outputs // {
default = config.outputs.${config.hardware.defaultOutput}; default = config.system.outputs.${config.hardware.defaultOutput};
}; };
# 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

@ -59,7 +59,7 @@
}; };
mac80211 = pkgs.mac80211.override { mac80211 = pkgs.mac80211.override {
drivers = ["ath9k" "ath10k_pci"]; drivers = ["ath9k" "ath10k_pci"];
klibBuild = config.outputs.kernel.modulesupport; klibBuild = config.system.outputs.kernel.modulesupport;
}; };
ath10k_cal_data = ath10k_cal_data =
let let

View File

@ -24,7 +24,7 @@
inherit (pkgs) openwrt; inherit (pkgs) openwrt;
mac80211 = pkgs.mac80211.override { mac80211 = pkgs.mac80211.override {
drivers = ["rt2800soc"]; drivers = ["rt2800soc"];
klibBuild = config.outputs.kernel.modulesupport; klibBuild = config.system.outputs.kernel.modulesupport;
}; };
in { in {
hardware = { hardware = {

View File

@ -20,7 +20,7 @@
mac80211 = pkgs.mac80211.override { mac80211 = pkgs.mac80211.override {
drivers = ["mt7603e"]; drivers = ["mt7603e"];
klibBuild = config.outputs.kernel.modulesupport; klibBuild = config.system.outputs.kernel.modulesupport;
}; };
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";

View File

@ -49,7 +49,7 @@
let let
mac80211 = pkgs.mac80211.override { mac80211 = pkgs.mac80211.override {
drivers = ["mac80211_hwsim"]; drivers = ["mac80211_hwsim"];
klibBuild = config.outputs.kernel.modulesupport; klibBuild = config.system.outputs.kernel.modulesupport;
}; };
inherit (pkgs.liminix.networking) interface; inherit (pkgs.liminix.networking) interface;
in { in {

View File

@ -238,8 +238,8 @@ in rec {
let let
script= pkgs.firewallgen "firewall.nft" (import ./rotuer-firewall.nix); script= pkgs.firewallgen "firewall.nft" (import ./rotuer-firewall.nix);
kmodules = pkgs.kernel-modules.override { kmodules = pkgs.kernel-modules.override {
kernelSrc = config.outputs.kernel.src; kernelSrc = config.system.outputs.kernel.src;
modulesupport = config.outputs.kernel.modulesupport; modulesupport = config.system.outputs.kernel.modulesupport;
kconfig = { kconfig = {
NFT_FIB_IPV4 = "m"; NFT_FIB_IPV4 = "m";
NFT_FIB_IPV6 = "m"; NFT_FIB_IPV6 = "m";

View File

@ -8,8 +8,32 @@ let
inherit (lib) mkOption types concatStringsSep; inherit (lib) mkOption types concatStringsSep;
inherit (config.boot) tftp; inherit (config.boot) tftp;
in { in {
options = { options.system.outputs = {
firmware = mkOption {
type = types.package;
internal = true; # component of flashimage
description = ''
Binary image (combining kernel, FDT, rootfs, initramfs
if needed, etc) for the target device.
'';
}; };
flash-scr = mkOption {
type = types.package;
internal = true; # component of flashimage
description = ''
Copy-pastable U-Boot commands to TFTP download the
image and write it to flash
'';
};
flashimage = mkOption {
type = types.package;
description = ''
Flashable image for the target device, and the script to
install it
'';
};
};
config = { config = {
kernel = { kernel = {
config = { config = {
@ -21,14 +45,15 @@ in {
"flashcp" "flashcp"
]; ];
outputs.firmware = system.outputs = {
let o = config.outputs; in firmware =
let o = config.system.outputs; in
pkgs.runCommand "firmware" {} '' pkgs.runCommand "firmware" {} ''
dd if=${o.uimage} of=$out bs=128k conv=sync dd if=${o.uimage} of=$out bs=128k conv=sync
dd if=${o.rootfs} of=$out bs=128k conv=sync,nocreat,notrunc oflag=append dd if=${o.rootfs} of=$out bs=128k conv=sync,nocreat,notrunc oflag=append
''; '';
outputs.flashimage = flashimage =
let o = config.outputs; in let o = config.system.outputs; in
pkgs.runCommand "flashimage" {} '' pkgs.runCommand "flashimage" {} ''
mkdir $out mkdir $out
cd $out cd $out
@ -42,13 +67,13 @@ in {
ln -s ${o.flash-scr} flash.scr ln -s ${o.flash-scr} flash.scr
''; '';
outputs.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.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}
@ -58,6 +83,6 @@ in {
echo command line was ${builtins.toJSON (concatStringsSep " " config.boot.commandLine)} echo command line was ${builtins.toJSON (concatStringsSep " " config.boot.commandLine)}
EOF EOF
''; '';
};
}; };
} }

View File

@ -5,7 +5,7 @@
, ... , ...
}: }:
let let
inherit (lib) mkEnableOption mkIf; inherit (lib) mkEnableOption mkOption mkIf types;
inherit (pkgs) runCommand callPackage writeText; inherit (pkgs) runCommand callPackage writeText;
in in
{ {
@ -14,15 +14,23 @@ in
enable = mkEnableOption "enable initramfs"; enable = mkEnableOption "enable initramfs";
default = false; default = false;
}; };
system.outputs.initramfs = mkOption {
type = types.package;
internal = true;
description = ''
Initramfs image capable of mounting the jffs2 root
filesystem
'';
};
}; };
config = mkIf config.boot.initramfs.enable { config = mkIf config.boot.initramfs.enable {
kernel.config = { kernel.config = {
BLK_DEV_INITRD = "y"; BLK_DEV_INITRD = "y";
INITRAMFS_SOURCE = builtins.toJSON "${config.outputs.initramfs}"; INITRAMFS_SOURCE = builtins.toJSON "${config.system.outputs.initramfs}";
# INITRAMFS_COMPRESSION_LZO = "y"; # INITRAMFS_COMPRESSION_LZO = "y";
}; };
outputs = { system.outputs = {
initramfs = initramfs =
let inherit (pkgs.pkgsBuildBuild) gen_init_cpio; let inherit (pkgs.pkgsBuildBuild) gen_init_cpio;
in runCommand "initramfs.cpio" {} '' in runCommand "initramfs.cpio" {} ''

View File

@ -5,12 +5,23 @@
, ... , ...
}: }:
let let
inherit (lib) mkIf; inherit (lib) mkIf mkOption types;
in in
{ {
imports = [ imports = [
./initramfs.nix ./initramfs.nix
]; ];
options.system.outputs = {
systemConfiguration = mkOption {
type = types.package;
description = ''
pkgs.systemconfig for the configured filesystem,
contains 'activate' and 'init' commands
'';
internal = true;
};
};
config = mkIf (config.rootfsType == "jffs2") { config = mkIf (config.rootfsType == "jffs2") {
kernel.config = { kernel.config = {
JFFS2_FS = "y"; JFFS2_FS = "y";
@ -21,7 +32,7 @@ in
JFFS2_CMODE_SIZE = "y"; JFFS2_CMODE_SIZE = "y";
}; };
boot.initramfs.enable = true; boot.initramfs.enable = true;
outputs = rec { system.outputs = rec {
systemConfiguration = systemConfiguration =
pkgs.systemconfig config.filesystem.contents; pkgs.systemconfig config.filesystem.contents;
rootfs = rootfs =

View File

@ -8,11 +8,27 @@ let
inherit (lib) mkOption mkForce types concatStringsSep; inherit (lib) mkOption mkForce types concatStringsSep;
in { in {
imports = [ ./ramdisk.nix ]; imports = [ ./ramdisk.nix ];
options.system.outputs = {
kexecboot = mkOption {
type = types.package;
description = ''
Directory containing files needed for kexec booting.
Can be copied onto the target device using ssh or similar
'';
};
boot-sh = mkOption {
type = types.package;
description = ''
Shell script to run on the target device that invokes
kexec with appropriate options
'';
};
};
config = { config = {
boot.ramdisk.enable = true; boot.ramdisk.enable = true;
system.outputs = {
outputs.kexecboot = kexecboot =
let o = config.outputs; in let o = config.system.outputs; in
pkgs.runCommand "kexecboot" {} '' pkgs.runCommand "kexecboot" {} ''
mkdir $out mkdir $out
cd $out cd $out
@ -24,10 +40,10 @@ in {
ln -s ${o.dtb} dtb ln -s ${o.dtb} dtb
''; '';
outputs.boot-sh = boot-sh =
let let
inherit (pkgs.lib.trivial) toHexString; inherit (pkgs.lib.trivial) toHexString;
inherit (config.outputs) rootfs kernel; inherit (config.system.outputs) rootfs kernel;
cmdline = concatStringsSep " " config.boot.commandLine; cmdline = concatStringsSep " " config.boot.commandLine;
in in
pkgs.buildPackages.runCommand "boot.sh.sh" { pkgs.buildPackages.runCommand "boot.sh.sh" {
@ -43,4 +59,5 @@ in {
EOF EOF
''; '';
}; };
};
} }

View File

@ -13,14 +13,52 @@ in
./squashfs.nix ./squashfs.nix
]; ];
options = { options = {
outputs = mkOption { system.outputs = {
type = types.attrsOf types.package; kernel = mkOption {
default = {}; type = types.package;
description = ''
Kernel vmlinux file (usually ELF)
'';
};
dtb = mkOption {
type = types.package;
description = ''
Compiled device tree (FDT) for the target device
'';
};
uimage = mkOption {
type = types.package;
description = ''
Combined kernel and FDT in uImage (U-Boot compatible) format
'';
};
vmroot = mkOption {
type = types.package;
description = ''
Directory containing separate kernel and rootfs image for
use with qemu (see mips-vm)
'';
};
manifest = mkOption {
type = types.package;
description = ''
Debugging aid. JSON rendition of config.filesystem, on
which can run "nix-store -q --tree" on it and find
out what's in the image, which is nice if it's unexpectedly huge
'';
};
rootfs = mkOption {
type = types.package;
description = ''
root filesystem (squashfs or jffs2) image
'';
internal = true;
};
}; };
}; };
config = { config = {
outputs = rec { system.outputs = rec {
tftpd = pkgs.buildPackages.tufted; # tftpd = pkgs.buildPackages.tufted;
kernel = liminix.builders.kernel.override { kernel = liminix.builders.kernel.override {
inherit (config.kernel) config src extraPatchPhase; inherit (config.kernel) config src extraPatchPhase;
}; };
@ -40,14 +78,12 @@ in
vmroot = pkgs.runCommand "qemu" {} '' vmroot = pkgs.runCommand "qemu" {} ''
mkdir $out mkdir $out
cd $out cd $out
ln -s ${config.outputs.rootfs} rootfs ln -s ${config.system.outputs.rootfs} rootfs
ln -s ${kernel} vmlinux ln -s ${kernel} vmlinux
ln -s ${manifest} manifest ln -s ${manifest} manifest
ln -s ${kernel.headers} build ln -s ${kernel.headers} build
''; '';
# this exists so that you can run "nix-store -q --tree" on it and find
# out what's in the image, which is nice if it's unexpectedly huge
manifest = writeText "manifest.json" (builtins.toJSON config.filesystem.contents); manifest = writeText "manifest.json" (builtins.toJSON config.filesystem.contents);
}; };
}; };

View File

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

View File

@ -13,11 +13,27 @@ in {
type = types.int; type = types.int;
default = 0; default = 0;
}; };
options.system.outputs = {
tftpboot = mkOption {
type = types.package;
description = ''
Directory containing files needed for TFTP booting
'';
};
boot-scr = mkOption {
type = types.package;
description = ''
U-Boot commands to load and boot a kernel and rootfs over TFTP.
Copy-paste into the device boot monitor
'';
};
};
config = { config = {
boot.ramdisk.enable = true; boot.ramdisk.enable = true;
outputs.tftpboot = system.outputs = rec {
let o = config.outputs; in tftpboot =
let o = config.system.outputs; in
pkgs.runCommand "tftpboot" {} '' pkgs.runCommand "tftpboot" {} ''
mkdir $out mkdir $out
cd $out cd $out
@ -29,14 +45,15 @@ in {
ln -s ${o.boot-scr} boot.scr ln -s ${o.boot-scr} boot.scr
''; '';
outputs.boot-scr = boot-scr =
let let
inherit (pkgs.lib.trivial) toHexString; inherit (pkgs.lib.trivial) toHexString;
o = config.system.outputs;
in in
pkgs.buildPackages.runCommand "boot-scr" {} '' pkgs.buildPackages.runCommand "boot-scr" {} ''
uimageSize=$(($(stat -L -c %s ${config.outputs.uimage}) + 0x1000 &(~0xfff))) uimageSize=$(($(stat -L -c %s ${o.uimage}) + 0x1000 &(~0xfff)))
rootfsStart=0x$(printf %x $((${cfg.loadAddress} + 0x100000 + $uimageSize))) rootfsStart=0x$(printf %x $((${cfg.loadAddress} + 0x100000 + $uimageSize)))
rootfsBytes=$(($(stat -L -c %s ${config.outputs.rootfs}) + 0x100000 &(~0xfffff))) rootfsBytes=$(($(stat -L -c %s ${o.rootfs}) + 0x100000 &(~0xfffff)))
rootfsBytes=$(($rootfsBytes + ${toString cfg.freeSpaceBytes} )) rootfsBytes=$(($rootfsBytes + ${toString cfg.freeSpaceBytes} ))
cmd="mtdparts=phram0:''${rootfsMb}M(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsBytes},${config.hardware.flash.eraseBlockSize} memmap=''${rootfsBytes}\$''${rootfsStart} root=/dev/mtdblock0"; cmd="mtdparts=phram0:''${rootfsMb}M(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsBytes},${config.hardware.flash.eraseBlockSize} memmap=''${rootfsBytes}\$''${rootfsStart} root=/dev/mtdblock0";
@ -49,4 +66,5 @@ in {
EOF EOF
''; '';
}; };
};
} }