Compare commits
338 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ab77a7d7e | |||
| c6918fec00 | |||
| d4e46dbe28 | |||
| d1f87a56e0 | |||
| 8c39b47cae | |||
| 2c7a16d792 | |||
| d6b06abb63 | |||
| 6b32aa569e | |||
| 234d1bd87e | |||
| c38f180fb7 | |||
| 9a8b22997c | |||
| c32d09bd83 | |||
| 6649ebeccd | |||
| 929226ed9e | |||
| a98f026210 | |||
| f4dc001b71 | |||
| 024c018262 | |||
| e1293e3778 | |||
| 0c406058e9 | |||
| 19d441333c | |||
| a726c09ae4 | |||
| 7e2b0068e6 | |||
| 13cc5a8992 | |||
| 3f889c7119 | |||
| 7f17125039 | |||
| 4bb081ffcf | |||
| 6587813577 | |||
| 1d780de0f1 | |||
| 8cf602da91 | |||
| c92aacc6fd | |||
| eff255fe12 | |||
| 453baede61 | |||
| 2295ed3110 | |||
| e71d92eb3d | |||
| f77da6f14c | |||
| 61eaaa82eb | |||
| 95dd1a1fab | |||
| 2f9b0f12f9 | |||
| 9fd9b8b878 | |||
| 26f206d0e1 | |||
| 8cd068ea68 | |||
| 350ddde260 | |||
| 13cb8d3692 | |||
| 62b7aea8ab | |||
| 76e3fd9a55 | |||
| 92284fa9ba | |||
| a2bb55e885 | |||
| 74027b44d7 | |||
| ea5370b3f4 | |||
| 55ed365920 | |||
| aa2160dd05 | |||
| df414b796f | |||
| 7377f7ceb2 | |||
| 49432aeda5 | |||
| 3caf8a75bb | |||
| cc94ef57fa | |||
| fd28f0ce04 | |||
| 497307588f | |||
| 788169586f | |||
| 3af9e86624 | |||
| 28d39cd66d | |||
| 9dd169d500 | |||
| 2e513eb4a7 | |||
| f2e4e77d73 | |||
| 48dfbe0c01 | |||
| 6f697db57c | |||
| fe1ee12e3d | |||
| 4d273a9469 | |||
| 40db175b41 | |||
| ab07212a7e | |||
| f5e08ac9d9 | |||
| 0cb18eabcd | |||
| 24151425b8 | |||
| e06295ed83 | |||
| 608d3e3abf | |||
| 3e19f1b927 | |||
| 3f6e9b6384 | |||
| 294492a176 | |||
| 67a1cd3718 | |||
| f8a275d1a3 | |||
| 0ee9c76c33 | |||
| 452aaa2f60 | |||
| 52967f746b | |||
| a89f866bf0 | |||
| f3fadd5cd7 | |||
| bc20f4c6b7 | |||
| 848214d104 | |||
| ede8f12d2b | |||
| 6cd5b90678 | |||
| db4f098c02 | |||
| 1347937345 | |||
| a7b5f80674 | |||
| 5c78338d71 | |||
| ed02d02767 | |||
| f07a38b0fd | |||
| ac189f2977 | |||
| ebb4d4a831 | |||
| 6bfbdf352d | |||
| 4ea1cf7f32 | |||
| f60b74f415 | |||
| 812e35b7b9 | |||
| 172f368633 | |||
| 1af9a39db1 | |||
| 420552ce98 | |||
| 56c667cfd5 | |||
| f9b4f0bc9c | |||
| ba5e4704a0 | |||
| 3357d21d7f | |||
| ffaca615ba | |||
| 77cd4492b2 | |||
| 81f5550bf0 | |||
| b52133a28b | |||
| 1ff779c1a9 | |||
| 44caefcd3b | |||
| 6e6b8790eb | |||
| 2e5a8a572e | |||
| 464d046b5a | |||
| ac8b971cc0 | |||
| 13087d17e3 | |||
| 5572c0ecb0 | |||
| 4cbe3ba683 | |||
| 20f4a12689 | |||
| 33e5c436d5 | |||
| cde30bcd54 | |||
| 1f7d6544e3 | |||
| 1bca072509 | |||
| 7b98724643 | |||
| b1625763ee | |||
| 91bdfc2766 | |||
| 14bfebc5c3 | |||
| 0447ac0ff9 | |||
| e35a1514ab | |||
| 4a0120487c | |||
| 888688ce28 | |||
| 9e3f48768e | |||
| 72171021e3 | |||
| 17517dd34f | |||
| 5112eab4da | |||
| e383f1b3d3 | |||
| da1245432e | |||
| 541b1c61c2 | |||
| 55c7410a55 | |||
| 0f50648157 | |||
| f1c260d4f7 | |||
| 3d611d3ba2 | |||
| e6b7d86381 | |||
| 83fbffb39b | |||
| f8c579b41e | |||
| ca9efc4b26 | |||
| 336fc7e495 | |||
| 4cc0add2ad | |||
| 2d7e6188ac | |||
| b9999857cb | |||
| ba03ddeb38 | |||
| 493c5f69d7 | |||
| 1a915e91ff | |||
| 197e2eb5b1 | |||
| 7ca822c826 | |||
| e5631783e1 | |||
| 635590d37a | |||
| 17630f2678 | |||
| 707a471bc2 | |||
| d3fce5edd4 | |||
| 5771108fed | |||
| 9e5f2d663d | |||
| 21eeb1671e | |||
| 44762d38fc | |||
| 1f6cfc3679 | |||
| 8ec00f1710 | |||
| 6a6dd32dea | |||
| 9b1fc11a59 | |||
| aaa6e353db | |||
| 69bf6cb5fb | |||
| 9f58e7b926 | |||
| 5a5c27ab9f | |||
| 277c91acdf | |||
| e0725489ca | |||
| cc47515cf8 | |||
| 464913cc8f | |||
| e604d628e3 | |||
| e2a597589b | |||
| a139a262c1 | |||
| 6a5fed83dd | |||
| bcf5ab24e8 | |||
| 32bf80c6fa | |||
| 12275f6896 | |||
| a60c2539a6 | |||
| 146a2d9ac0 | |||
| 091d863710 | |||
| c7bcfbfa34 | |||
| 500a3c1025 | |||
| 0c0d0eed8a | |||
| 699cf97206 | |||
| cd0093279c | |||
| 034d6aacc4 | |||
| e590c0ad3f | |||
| 14abdd9998 | |||
| 6287b92000 | |||
| d2215d3e56 | |||
| 3cf2308bee | |||
| 3913989be3 | |||
| 43e5e6876e | |||
| 7d6c80570c | |||
| e745991b9d | |||
| defbfce1fb | |||
| 0df2c83382 | |||
| 01c28de88d | |||
| 2bf197cad8 | |||
| a8a19977ca | |||
| 8a9284af1e | |||
| 7351e143c5 | |||
| 283c3154a7 | |||
| 34f37d60d9 | |||
| fe7b092075 | |||
| b56f121e04 | |||
| d5d621f310 | |||
| da95a9fa62 | |||
| 85071c88e7 | |||
| 74093b7ee3 | |||
| 41733e58d6 | |||
| 9041d5d63a | |||
| 001ebdc601 | |||
| 1f97409474 | |||
| a41839f3d1 | |||
| ff76d854fc | |||
| 81a6480a4f | |||
| c7164a6f4a | |||
| 83ca86fe42 | |||
| 1b4106e2a3 | |||
| 89912c766b | |||
| 9828b007ae | |||
| f34abc85ae | |||
| b475a680fb | |||
| 43612af71a | |||
| 5695c47496 | |||
| e3ec514710 | |||
| 99f68e5421 | |||
| 9c30b6f882 | |||
| dd75322c10 | |||
| 869a508c0a | |||
| e835473945 | |||
| 055268d5d2 | |||
| ff38bcacbb | |||
| a6128955e7 | |||
| 531cb113be | |||
| daede666cb | |||
| 2992771c7e | |||
| 4cc82e1502 | |||
| 21f2320d86 | |||
| d40ada4251 | |||
| 4053ea9481 | |||
| 54d3415885 | |||
| 264d83c98d | |||
| 97defc2076 | |||
| ddaa5476d3 | |||
| bcd9d56624 | |||
| e2c883356c | |||
| d79a941504 | |||
| 2f82e0dab8 | |||
| fc03965915 | |||
| d2d3af2587 | |||
| 310ac30f24 | |||
| 45a7f96bd4 | |||
| 79445fd962 | |||
| a9ddd78482 | |||
| 4fb8253e57 | |||
| ff3a1905a5 | |||
| 3c353e4aff | |||
| ba21384fde | |||
| 2480fdef5b | |||
| 409c1cfb16 | |||
| 9767078878 | |||
| d760c2d27b | |||
| 1e139c22fd | |||
| a1ff07b063 | |||
| 9550772cec | |||
| 64cd1626c6 | |||
| eb79928b37 | |||
| 0a629df48d | |||
| 64afd18e2a | |||
| 47e96ddc15 | |||
| 5db9d7269e | |||
| 985df8792d | |||
| 528afae8b1 | |||
| 384835c89d | |||
| 5051625d31 | |||
| c4d00e062a | |||
| 8fa3443923 | |||
| 8091e207b6 | |||
| 39020607ad | |||
| fe735408a1 | |||
| a9d1582b53 | |||
| eca8e37e7a | |||
| d300373b96 | |||
| 70ca7fac17 | |||
| 79a3a45061 | |||
| 612d6d7a51 | |||
| e1ae986cf6 | |||
| bce0c7ffb6 | |||
| 28ca1e68ab | |||
| acf33a100f | |||
| 7f9cae9d5c | |||
| 3012c91b47 | |||
| 1edf20c08f | |||
| 7195cb10ce | |||
| 135a445672 | |||
| 3899daee56 | |||
| b17f623d03 | |||
| df395a4d5d | |||
| 75e9f8210c | |||
| 1c3242cab1 | |||
| 44ea683391 | |||
| 725d8b608f | |||
| bc9ced5d38 | |||
| 73ae7788b9 | |||
| d34919766a | |||
| 2fe0cd2f48 | |||
| 241f1013ed | |||
| 2ce361d4e3 | |||
| 3f8cc24dcc | |||
| 57e3b449f8 | |||
| 3964505131 | |||
| 941479b144 | |||
| ac551536da | |||
| 6f908156af | |||
| 534a49e827 | |||
| 07a6eb73cd | |||
| 159bfa3057 | |||
| 8f0ab5be40 | |||
| 7f9971512d | |||
| f0f6cc80d7 | |||
| afcc6a6436 | |||
| 2e8e05f31a | |||
| 143137cbc6 | |||
| 8d228f2bef | |||
| 5751058d59 | |||
| 5ac7e1e9b2 | |||
| c75452549b |
@@ -103,3 +103,57 @@ a bit more useful :-)
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
2024-07-16
|
||||
|
||||
* structured parameters are available for the pppoe service
|
||||
|
||||
* The "wan" configuration in modules/profiles/gateway.nix has changed:
|
||||
instead of passing options that are used to create a pppoe interface,
|
||||
callers should create a (pppoe or other) interface and pass that as
|
||||
the value of profile.gateway.wan. For the pppoe case this is now only
|
||||
very slightly more verbose, and it allows using the gateway profile
|
||||
with other kinds of upstream.
|
||||
|
||||
2024-8-16
|
||||
|
||||
As part of implementing log shipping, the default directory for system
|
||||
logs has beenchanged from /run/uncaught-logs to /run/log
|
||||
|
||||
2024-10-09
|
||||
|
||||
liminix-rebuild is being deprecated. From hereon in, the preferred way
|
||||
to do an incremental update on an installed device with a writable
|
||||
filesystem is to build the systemConfiguration output
|
||||
|
||||
nix-build -I liminix-config=hosts/myhost.nix --argstr deviceName turris-omnia -A outputs.systemConfiguration
|
||||
|
||||
and then run the generated `install.sh` script
|
||||
|
||||
result/install.sh root@192.168.8.1
|
||||
|
||||
2024-12-16
|
||||
|
||||
Config options changed: if you had set config.hardware.dts.includes
|
||||
(maybe in an out-of-tree device port) to specify the search paths
|
||||
in which dtc finds include files, you will need to change this to
|
||||
hardware.dts.includePaths.
|
||||
|
||||
The "new" hardware.dts.includes option is now for dtsi files which
|
||||
should be merged into the device tree.
|
||||
|
||||
2024-12-19
|
||||
|
||||
Incremental updates changed again (but not massively). From hereon in,
|
||||
the preferred way to do an incremental update on an installed device
|
||||
with a writable filesystem is to build the updater output
|
||||
|
||||
nix-build -I liminix-config=hosts/myhost.nix --argstr deviceName turris-omnia -A outputs.updater
|
||||
|
||||
and then run the generated `update.sh` script. See
|
||||
https://www.liminix.org/doc/admin.html#updating-an-installed-system
|
||||
|
||||
2024-12-22
|
||||
|
||||
outputs.zimage is now outputs.kernel.zImage. This is unlikely to
|
||||
affect many people at all but I mention it anyway.
|
||||
+2035
File diff suppressed because it is too large
Load Diff
+31
-9
@@ -2,19 +2,41 @@
|
||||
# use expect as its "Script program" instead of runscript. Try
|
||||
# Ctrl+A O -> Filenames and paths -> D
|
||||
|
||||
fconfigure stderr -buffering none
|
||||
fconfigure stdout -buffering none
|
||||
|
||||
proc waitprompt { } {
|
||||
expect {
|
||||
"BusyBox" { puts stderr "DONE\r"; exit 0 }
|
||||
"READY" { puts stderr ";;; READY\r"; }
|
||||
timeout { puts stderr ";;; timed out waiting after $line\r" }
|
||||
}
|
||||
}
|
||||
|
||||
proc sendline { line } {
|
||||
send "$line; echo \$ready \r"
|
||||
sleep 0.1
|
||||
}
|
||||
|
||||
log_user 0
|
||||
log_file -a -open stderr
|
||||
|
||||
set f [open "result/boot.scr"]
|
||||
send "version\r"
|
||||
set timeout 60
|
||||
|
||||
send "setenv ready REA\r"
|
||||
sleep 0.1
|
||||
send "setenv ready \${ready}DY\r"
|
||||
sleep 0.1
|
||||
|
||||
set timeout 300
|
||||
expect_before timeout abort
|
||||
while {[gets $f line] >= 0} {
|
||||
puts stderr "next line $line\r"
|
||||
puts stderr "waiting for prompt\r"
|
||||
expect {
|
||||
"ath>" {}
|
||||
"BusyBox" { puts stderr "DONE"; exit 0 }
|
||||
}
|
||||
send "$line\r\n"
|
||||
puts stderr ";;; next line $line\r"
|
||||
puts stderr ";;; waiting for prompt\r"
|
||||
puts stderr ";;; sending\r"
|
||||
sendline $line
|
||||
waitprompt
|
||||
}
|
||||
|
||||
puts stderr "done\r\n"
|
||||
close $f
|
||||
+71
-15
@@ -1,8 +1,21 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.bordervm;
|
||||
inherit (lib) mkOption mkEnableOption mdDoc types optional optionals;
|
||||
in {
|
||||
inherit (lib)
|
||||
mkOption
|
||||
mkEnableOption
|
||||
mdDoc
|
||||
types
|
||||
optional
|
||||
optionals
|
||||
;
|
||||
in
|
||||
{
|
||||
options.bordervm = {
|
||||
keys = mkOption {
|
||||
type = types.listOf types.str;
|
||||
@@ -89,9 +102,32 @@ in {
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
user = "liminix";
|
||||
virtualHosts.${config.networking.hostName} = {
|
||||
root = "/home/liminix";
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
systemd.services.nginx.serviceConfig.ProtectHome = "read-only";
|
||||
|
||||
systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
|
||||
|
||||
virtualisation = {
|
||||
forwardPorts = [
|
||||
{
|
||||
from = "host";
|
||||
host.port = 7654;
|
||||
# guest.address = "10.0.2.15";
|
||||
guest.port = 7654;
|
||||
}
|
||||
{
|
||||
host.port = 2222;
|
||||
guest.address = "10.0.2.15";
|
||||
guest.port = 22;
|
||||
}
|
||||
];
|
||||
qemu = {
|
||||
networkingOptions = [ ];
|
||||
options =
|
||||
@@ -114,24 +150,44 @@ in {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.tang = {
|
||||
enable = true;
|
||||
ipAddressAllow = [
|
||||
"10.0.0.0/24"
|
||||
"0.0.0.0/0"
|
||||
];
|
||||
};
|
||||
|
||||
environment.systemPackages =
|
||||
let wireshark-nogui = pkgs.wireshark.override { withQt = false ; };
|
||||
in with pkgs; [
|
||||
tcpdump
|
||||
wireshark-nogui
|
||||
socat
|
||||
tufted
|
||||
iptables
|
||||
usbutils
|
||||
busybox
|
||||
];
|
||||
let
|
||||
wireshark-nogui = pkgs.wireshark.override { withQt = false; };
|
||||
in
|
||||
with pkgs;
|
||||
[
|
||||
tcpdump
|
||||
wireshark-nogui
|
||||
socat
|
||||
tufted
|
||||
iptables
|
||||
usbutils
|
||||
busybox
|
||||
clevis
|
||||
];
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
networking = {
|
||||
hostName = "border";
|
||||
firewall = { enable = false; };
|
||||
firewall = {
|
||||
enable = false;
|
||||
};
|
||||
interfaces.eth1 = {
|
||||
useDHCP = false;
|
||||
ipv4.addresses = [ { address = "10.0.0.1"; prefixLength = 24;}];
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "10.0.0.1";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
nat = {
|
||||
enable = true;
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
{
|
||||
nixpkgs,
|
||||
unstable,
|
||||
liminix,
|
||||
...
|
||||
}:
|
||||
let
|
||||
pkgs = (import nixpkgs { });
|
||||
pkgs = import <nixpkgs> { };
|
||||
liminix = <liminix>;
|
||||
borderVmConf = ./bordervm.conf-example.nix;
|
||||
inherit (pkgs.lib.attrsets) genAttrs;
|
||||
devices = [
|
||||
@@ -16,12 +11,16 @@ let
|
||||
"qemu-aarch64"
|
||||
"qemu-armv7l"
|
||||
"tp-archer-ax23"
|
||||
"openwrt-one"
|
||||
"zyxel-nwa50ax"
|
||||
"turris-omnia"
|
||||
"belkin-rt3200"
|
||||
];
|
||||
vanilla = ./vanilla-configuration.nix;
|
||||
for-device = name:
|
||||
for-device =
|
||||
name:
|
||||
(import liminix {
|
||||
inherit nixpkgs borderVmConf;
|
||||
inherit borderVmConf;
|
||||
device = import (liminix + "/devices/${name}");
|
||||
liminix-config = vanilla;
|
||||
}).outputs.default;
|
||||
@@ -32,7 +31,7 @@ let
|
||||
// {
|
||||
buildEnv =
|
||||
(import liminix {
|
||||
inherit nixpkgs borderVmConf;
|
||||
inherit borderVmConf;
|
||||
device = import (liminix + "/devices/qemu");
|
||||
liminix-config = vanilla;
|
||||
}).buildEnv;
|
||||
@@ -40,7 +39,7 @@ let
|
||||
let
|
||||
json =
|
||||
(import liminix {
|
||||
inherit nixpkgs borderVmConf;
|
||||
inherit borderVmConf;
|
||||
device = import (liminix + "/devices/qemu");
|
||||
liminix-config =
|
||||
{ ... }:
|
||||
@@ -59,26 +58,27 @@ let
|
||||
];
|
||||
src = ./.;
|
||||
buildPhase = ''
|
||||
cat ${json} | fennel --correlate doc/parse-options.fnl > doc/modules-generated.rst
|
||||
cat ${json} | fennel --correlate doc/parse-options-outputs.fnl > doc/outputs-generated.rst
|
||||
cat ${json} | fennel --correlate doc/parse-options.fnl > doc/modules-generated.inc.rst
|
||||
cat ${json} | fennel --correlate doc/parse-options-outputs.fnl > doc/outputs-generated.inc.rst
|
||||
cp ${(import ./doc/hardware.nix)} doc/hardware.rst
|
||||
make -C doc html
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out/nix-support $out/share/doc/
|
||||
cd doc
|
||||
cp *-generated.rst $out
|
||||
cp *-generated.inc.rst hardware.rst $out
|
||||
ln -s ${json} $out/options.json
|
||||
cp -a _build/html $out/share/doc/liminix
|
||||
echo "file source-dist \"$out/share/doc/liminix\"" \
|
||||
> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
};
|
||||
with-unstable = (import liminix {
|
||||
nixpkgs = unstable;
|
||||
inherit borderVmConf;
|
||||
device = import (liminix + "/devices/qemu");
|
||||
liminix-config = vanilla;
|
||||
}).outputs.default;
|
||||
};
|
||||
};
|
||||
in jobs
|
||||
in
|
||||
jobs
|
||||
// {
|
||||
all = pkgs.mkShell {
|
||||
name = "all tests";
|
||||
contents = pkgs.lib.collect pkgs.lib.isDerivation jobs;
|
||||
};
|
||||
}
|
||||
|
||||
+34
-24
@@ -2,14 +2,13 @@
|
||||
deviceName ? null,
|
||||
device ? (import ./devices/${deviceName}),
|
||||
liminix-config ? <liminix-config>,
|
||||
nixpkgs ? <nixpkgs>,
|
||||
borderVmConf ? ./bordervm.conf.nix,
|
||||
imageType ? "primary",
|
||||
}:
|
||||
|
||||
let
|
||||
overlay = import ./overlay.nix;
|
||||
pkgs = import nixpkgs (
|
||||
pkgs = import <nixpkgs> (
|
||||
device.system
|
||||
// {
|
||||
overlays = [ overlay ];
|
||||
@@ -28,12 +27,19 @@ let
|
||||
modulesPath = builtins.toString ./modules;
|
||||
};
|
||||
modules = [
|
||||
{ _module.args = { inherit pkgs; inherit (pkgs) lim; }; }
|
||||
{
|
||||
_module.args = {
|
||||
inherit pkgs;
|
||||
inherit (pkgs) lim;
|
||||
};
|
||||
}
|
||||
./modules/hardware.nix
|
||||
./modules/base.nix
|
||||
./modules/busybox.nix
|
||||
./modules/hostname.nix
|
||||
./modules/kernel
|
||||
./modules/logging.nix
|
||||
./modules/klogd.nix
|
||||
device.module
|
||||
liminix-config
|
||||
./modules/s6
|
||||
@@ -46,30 +52,34 @@ let
|
||||
};
|
||||
config = eval.config;
|
||||
|
||||
borderVm = ((import <nixpkgs/nixos/lib/eval-config.nix>) {
|
||||
system = builtins.currentSystem;
|
||||
modules = [
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
(final: prev: {
|
||||
go-l2tp = final.callPackage ./pkgs/go-l2tp {};
|
||||
tufted = final.callPackage ./pkgs/tufted {};
|
||||
})
|
||||
];
|
||||
}
|
||||
(import ./bordervm-configuration.nix)
|
||||
borderVmConf
|
||||
];
|
||||
}).config.system;
|
||||
in {
|
||||
borderVm =
|
||||
((import <nixpkgs/nixos/lib/eval-config.nix>) {
|
||||
system = builtins.currentSystem;
|
||||
modules = [
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
(final: prev: {
|
||||
go-l2tp = final.callPackage ./pkgs/go-l2tp { };
|
||||
tufted = final.callPackage ./pkgs/tufted { };
|
||||
})
|
||||
];
|
||||
}
|
||||
(import ./bordervm-configuration.nix)
|
||||
borderVmConf
|
||||
];
|
||||
}).config.system;
|
||||
in
|
||||
{
|
||||
outputs = config.system.outputs // {
|
||||
default = config.system.outputs.${config.hardware.defaultOutput};
|
||||
optionsJson =
|
||||
let o = import ./doc/extract-options.nix {
|
||||
inherit pkgs eval;
|
||||
lib = pkgs.lib;
|
||||
};
|
||||
in pkgs.writeText "options.json" (builtins.toJSON o);
|
||||
let
|
||||
o = import ./doc/extract-options.nix {
|
||||
inherit pkgs eval;
|
||||
lib = pkgs.lib;
|
||||
};
|
||||
in
|
||||
pkgs.writeText "options.json" (builtins.toJSON o);
|
||||
};
|
||||
|
||||
# this is just here as a convenience, so that we can get a
|
||||
|
||||
+281
-185
@@ -4,15 +4,8 @@
|
||||
******************************
|
||||
|
||||
This device is based on a 64 bit Mediatek MT7622 ARM platform,
|
||||
and is "work in progress" in Liminix.
|
||||
|
||||
.. note:: The factory flash image contains ECC errors that make it
|
||||
incompatible with Liminix: you need to use the `OpenWrt
|
||||
UBI Installer <https://github.com/dangowrt/owrt-ubi-installer>`_ to
|
||||
rewrite the partition layout before you can flash
|
||||
Liminix onto it (or even use it with
|
||||
:ref:`system-outputs-tftpboot`, if you want the wireless
|
||||
to work).
|
||||
and is mostly feature-complete in Liminix but as of Dec 2024
|
||||
has seen very little actual use.
|
||||
|
||||
Hardware summary
|
||||
================
|
||||
@@ -27,10 +20,94 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
Installation is currently a manual process (you need a :ref:`serial <serial>` conection and
|
||||
TFTP) following the instructions at :ref:`system-outputs-ubimage`
|
||||
Liminix on this device uses the UBI volume management system to
|
||||
perform wear leveling on the flash. This is not set up from the
|
||||
factory, so a one-time step is needed to prepare it before Liminix
|
||||
can be installed.
|
||||
|
||||
'';
|
||||
|
||||
Preparation
|
||||
-----------
|
||||
|
||||
To prepare the device for Liminix you first need to use the
|
||||
`OpenWrt UBI Installer
|
||||
<https://github.com/dangowrt/owrt-ubi-installer>`_ image to
|
||||
rewrite the flash layout. As of Jan 2025 there are two versions
|
||||
of the installer available: the release version 1.0.2 and the
|
||||
pre-release 1.1.3 and for Liminix you nee the pre-relese.
|
||||
The release version of the installer creates UBI volumes
|
||||
according to an older layout that is not compatible with
|
||||
the Linux 6.6.67 kernel used in Liminix.
|
||||
|
||||
You can run the installer in one of two ways:
|
||||
either follow the instructions to do it through the vendor web
|
||||
interface, or you can drop to U-Boot and use TFTP
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
MT7622> setenv ipaddr 10.0.0.6
|
||||
MT7622> setenv serverip 10.0.0.1
|
||||
MT7622> tftpboot 0x42000000 openwrt-mediatek-mt7622-linksys_e8450-ubi-initramfs-recovery-installer.itb
|
||||
MT7622> bootm 0x42000000
|
||||
|
||||
This will write the new flash layout and then boot into a
|
||||
"recovery" OpenWrt installation.
|
||||
|
||||
Building/installing Liminix
|
||||
----------------
|
||||
|
||||
The default target for this device is ``outputs.ubimage`` which
|
||||
makes a ubifs image suitable for use with :command:`ubiupdatevol`.
|
||||
To write this to the device we use the OpenWrt recovery system
|
||||
installed in the previous step. In this configuration the
|
||||
device assigns itself the IP address 192.168.1.1/24 on its LAN
|
||||
ports and expects the connected computer to have 192.168.1.254
|
||||
|
||||
.. warning:: The `ubi0_7` device in these instructions is correct
|
||||
as of Dec 2024 (dangowrt/owrt-ubi-installer commit
|
||||
d79e7928). If you are installing some time later, it
|
||||
is important to check the output from
|
||||
:command:`ubinfo -a` and make sure you are updating
|
||||
the "liminix" volume and not some other one which had
|
||||
been introduced since I wrote this.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ nix-build -I liminix-config=./my-configuration.nix --arg device "import ./devices/belkin-rt3200" -A outputs.default
|
||||
$ cat result/rootfs | ssh root@192.168.1.1 "cat > /tmp/rootfs"
|
||||
$ ssh root@192.168.1.1
|
||||
root@OpenWrt:~# ubimkvol /dev/ubi0 --name=liminix --maxavsize
|
||||
root@OpenWrt:~# ubinfo -a
|
||||
[...]
|
||||
Volume ID: 7 (on ubi0)
|
||||
Type: dynamic
|
||||
Alignment: 1
|
||||
Size: 851 LEBs (108056576 bytes, 103.0 MiB)
|
||||
State: OK
|
||||
Name: liminix
|
||||
Character device major/minor: 250:8
|
||||
root@OpenWrt:~# ubiupdatevol /dev/ubi0_7 /tmp/rootfs
|
||||
|
||||
To make the new system bootable we also need to change some U-Boot variables.
|
||||
``boot_production`` needs to mount the filesystem and boot the FIT image
|
||||
found there, and :code:`bootcmd` needs to be told _not_ to boot the rescue
|
||||
image if there are records in pstore, because that interferes with
|
||||
``config.log.persistent``
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
root@OpenWrt:~# fw_setenv orig_boot_production $(fw_printenv -n boot_production)
|
||||
root@OpenWrt:~# fw_setenv orig_bootcmd $(fw_printenv -n bootcmd)
|
||||
root@OpenWrt:~# fw_setenv boot_production 'led $bootled_pwr on ; ubifsmount ubi0:liminix && ubifsload ''${loadaddr} boot/fit && bootm ''${loadaddr}'
|
||||
root@OpenWrt:~# fw_setenv bootcmd 'run boot_ubi'
|
||||
|
||||
For subsequent Liminix reinstalls, just run the
|
||||
:command:`ubiupdatevol` command again. You don't need to repeat
|
||||
the "Preparation" step and in fact should seek to avoid it if
|
||||
possible, as it will reset the erase counters used for write
|
||||
levelling. Using UBI-aware tools is therefore preferred over any
|
||||
kind of "factory" wipe which will reset them.
|
||||
'';
|
||||
|
||||
system = {
|
||||
crossSystem = {
|
||||
@@ -38,199 +115,218 @@
|
||||
};
|
||||
};
|
||||
|
||||
module = {pkgs, config, lib, lim, ... }:
|
||||
let firmware = pkgs.stdenv.mkDerivation {
|
||||
name = "wlan-firmware";
|
||||
phases = ["installPhase"];
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out
|
||||
'';
|
||||
};
|
||||
in {
|
||||
module =
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
lim,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
firmware = pkgs.stdenv.mkDerivation {
|
||||
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 = [
|
||||
../../modules/arch/aarch64.nix
|
||||
../../modules/outputs/tftpboot.nix
|
||||
../../modules/outputs/ubifs.nix
|
||||
];
|
||||
config = {
|
||||
kernel = {
|
||||
src = pkgs.pkgsBuildBuild.fetchurl {
|
||||
name = "linux.tar.gz";
|
||||
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.gz";
|
||||
hash = "sha256-PkdzUKZ0IpBiWe/RS70J76JKnBFzRblWcKlaIFNxnHQ=";
|
||||
};
|
||||
extraPatchPhase = ''
|
||||
${pkgs.openwrt.applyPatches.mediatek}
|
||||
'';
|
||||
config = {
|
||||
PCI = "y";
|
||||
ARCH_MEDIATEK = "y";
|
||||
# ARM_MEDIATEK_CPUFREQ = "y";
|
||||
kernel = {
|
||||
extraPatchPhase = ''
|
||||
${openwrt.applyPatches.mediatek}
|
||||
'';
|
||||
src = openwrt.kernelSrc;
|
||||
version = openwrt.kernelVersion;
|
||||
config = {
|
||||
PCI = "y";
|
||||
ARCH_MEDIATEK = "y";
|
||||
# ARM_MEDIATEK_CPUFREQ = "y";
|
||||
|
||||
# needed for "Cannot find regmap for /infracfg@10000000"
|
||||
MFD_SYSCON = "y";
|
||||
MTK_INFRACFG = "y";
|
||||
# needed for "Cannot find regmap for /infracfg@10000000"
|
||||
MFD_SYSCON = "y";
|
||||
MTK_INFRACFG = "y";
|
||||
|
||||
MTK_PMIC_WRAP = "y";
|
||||
NVMEM_MTK_EFUSE="y";
|
||||
# MTK_HSDMA="y";
|
||||
MTK_SCPSYS="y";
|
||||
MTK_SCPSYS_PM_DOMAINS="y";
|
||||
# MTK_THERMAL="y";
|
||||
MTK_TIMER="y";
|
||||
MTK_PMIC_WRAP = "y";
|
||||
DMADEVICES = "y";
|
||||
MTK_HSDMA = "y";
|
||||
MTK_SCPSYS = "y";
|
||||
MTK_SCPSYS_PM_DOMAINS = "y";
|
||||
# MTK_THERMAL="y";
|
||||
MTK_TIMER = "y";
|
||||
|
||||
COMMON_CLK_MT7622 = "y";
|
||||
COMMON_CLK_MT7622_ETHSYS = "y";
|
||||
COMMON_CLK_MT7622_HIFSYS = "y";
|
||||
COMMON_CLK_MT7622_AUDSYS = "y";
|
||||
PM_CLK="y";
|
||||
COMMON_CLK_MT7622 = "y";
|
||||
COMMON_CLK_MT7622_ETHSYS = "y";
|
||||
COMMON_CLK_MT7622_HIFSYS = "y";
|
||||
COMMON_CLK_MT7622_AUDSYS = "y";
|
||||
PM_CLK = "y";
|
||||
|
||||
REGMAP_MMIO = "y";
|
||||
CLKSRC_MMIO = "y";
|
||||
REGMAP = "y";
|
||||
REGMAP_MMIO = "y";
|
||||
CLKSRC_MMIO = "y";
|
||||
REGMAP = "y";
|
||||
|
||||
MEDIATEK_GE_PHY = "y";
|
||||
# MEDIATEK_MT6577_AUXADC = "y";
|
||||
NET_MEDIATEK_SOC = "y";
|
||||
NET_MEDIATEK_SOC_WED = "y";
|
||||
NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO
|
||||
NET_VENDOR_MEDIATEK = "y";
|
||||
PCIE_MEDIATEK = "y";
|
||||
MEDIATEK_GE_PHY = "y";
|
||||
# MEDIATEK_MT6577_AUXADC = "y";
|
||||
NET_MEDIATEK_SOC = "y";
|
||||
NET_MEDIATEK_SOC_WED = "y";
|
||||
NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO
|
||||
NET_VENDOR_MEDIATEK = "y";
|
||||
PCIE_MEDIATEK = "y";
|
||||
|
||||
BLOCK = "y"; # move this to base option
|
||||
BLOCK = "y"; # move this to base option
|
||||
|
||||
SPI_MASTER = "y";
|
||||
SPI = "y";
|
||||
SPI_MEM="y";
|
||||
SPI_MTK_NOR="y";
|
||||
SPI_MTK_SNFI = "y";
|
||||
SPI_MASTER = "y";
|
||||
SPI = "y";
|
||||
SPI_MEM = "y";
|
||||
SPI_MTK_NOR = "y";
|
||||
SPI_MTK_SNFI = "y";
|
||||
|
||||
MTD = "y";
|
||||
MTD_BLOCK = "y";
|
||||
MTD_RAW_NAND = "y";
|
||||
MTD_NAND_MTK = "y";
|
||||
MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table
|
||||
MTD_NAND_ECC_MEDIATEK= "y";
|
||||
MTD_NAND_ECC_SW_HAMMING= "y";
|
||||
MTD_SPI_NAND= "y";
|
||||
MTD_OF_PARTS = "y";
|
||||
MTD_NAND_CORE= "y";
|
||||
MTD_SPI_NOR= "y";
|
||||
MTD_SPLIT_FIRMWARE= "y";
|
||||
MTD_SPLIT_FIT_FW= "y";
|
||||
MTD = "y";
|
||||
MTD_BLOCK = "y";
|
||||
MTD_RAW_NAND = "y";
|
||||
MTD_NAND_MTK = "y";
|
||||
MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table
|
||||
MTD_NAND_ECC_MEDIATEK = "y";
|
||||
MTD_NAND_ECC_SW_HAMMING = "y";
|
||||
MTD_SPI_NAND = "y";
|
||||
MTD_OF_PARTS = "y";
|
||||
MTD_NAND_CORE = "y";
|
||||
MTD_SPI_NOR = "y";
|
||||
MTD_SPLIT_FIRMWARE = "y";
|
||||
MTD_SPLIT_FIT_FW = "y";
|
||||
|
||||
MTD_UBI_NVMEM = "y";
|
||||
NVMEM_MTK_EFUSE = "y";
|
||||
NVMEM_BLOCK = "y";
|
||||
NVMEM_LAYOUT_ADTRAN = "y";
|
||||
|
||||
MMC = "y";
|
||||
MMC_BLOCK = "y";
|
||||
MMC_CQHCI = "y";
|
||||
MMC_MTK = "y";
|
||||
MMC = "y";
|
||||
MMC_BLOCK = "y";
|
||||
MMC_CQHCI = "y";
|
||||
MMC_MTK = "y";
|
||||
|
||||
# Distributed Switch Architecture is needed
|
||||
# to make the ethernet ports visible
|
||||
NET_DSA="y";
|
||||
NET_DSA_MT7530="y";
|
||||
NET_DSA_TAG_MTK="y";
|
||||
# Distributed Switch Architecture is needed
|
||||
# to make the ethernet ports visible
|
||||
NET_DSA = "y";
|
||||
NET_DSA_MT7530 = "y";
|
||||
NET_DSA_TAG_MTK = "y";
|
||||
NET_DSA_MT7530_MDIO = "y";
|
||||
|
||||
PSTORE = "y";
|
||||
PSTORE_RAM = "y";
|
||||
PSTORE_CONSOLE = "y";
|
||||
PSTORE_DEFLATE_COMPRESS = "n";
|
||||
SERIAL_8250 = "y";
|
||||
SERIAL_8250_CONSOLE = "y";
|
||||
SERIAL_8250_MT6577 = "y";
|
||||
# SERIAL_8250_NR_UARTS="3";
|
||||
# SERIAL_8250_RUNTIME_UARTS="3";
|
||||
SERIAL_OF_PLATFORM = "y";
|
||||
|
||||
SERIAL_8250 = "y";
|
||||
SERIAL_8250_CONSOLE = "y";
|
||||
SERIAL_8250_MT6577="y";
|
||||
# SERIAL_8250_NR_UARTS="3";
|
||||
# SERIAL_8250_RUNTIME_UARTS="3";
|
||||
SERIAL_OF_PLATFORM="y";
|
||||
|
||||
# Must enble hardware watchdog drivers. Else the device reboots after several seconds
|
||||
WATCHDOG = "y";
|
||||
MEDIATEK_WATCHDOG = "y";
|
||||
};
|
||||
conditionalConfig = {
|
||||
WLAN= {
|
||||
MT7615E = "m";
|
||||
MT7622_WMAC = "y";
|
||||
MT7915E = "m";
|
||||
};
|
||||
};
|
||||
};
|
||||
boot = {
|
||||
commandLine = [ "console=ttyS0,115200" ];
|
||||
tftp.loadAddress = lim.parseInt "0x4007ff28";
|
||||
imageFormat = "fit";
|
||||
};
|
||||
filesystem =
|
||||
let inherit (pkgs.pseudofile) dir symlink;
|
||||
in
|
||||
dir {
|
||||
lib = dir {
|
||||
firmware = dir {
|
||||
mediatek = symlink firmware;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hardware =
|
||||
let
|
||||
openwrt = pkgs.openwrt;
|
||||
mac80211 = pkgs.kmodloader.override {
|
||||
targets = ["mt7615e" "mt7915e"];
|
||||
inherit (config.system.outputs) kernel;
|
||||
};
|
||||
in {
|
||||
ubi = {
|
||||
minIOSize = "2048";
|
||||
eraseBlockSize = "126976";
|
||||
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";
|
||||
includes = [
|
||||
"${openwrt.src}/target/linux/mediatek/dts"
|
||||
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
|
||||
];
|
||||
};
|
||||
|
||||
# - 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 ];
|
||||
# Must enble hardware watchdog drivers. Else the device reboots after several seconds
|
||||
WATCHDOG = "y";
|
||||
MEDIATEK_WATCHDOG = "y";
|
||||
};
|
||||
conditionalConfig = {
|
||||
WLAN = {
|
||||
MT7615E = "m";
|
||||
MT7622_WMAC = "y";
|
||||
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 ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/ {
|
||||
reserved-memory {
|
||||
/* make sure address matches upstream */
|
||||
ramoops@42ff0000 {
|
||||
pmsg-size = <0x10000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -5,11 +5,6 @@
|
||||
];
|
||||
config = {
|
||||
kernel = {
|
||||
src = pkgs.pkgsBuildBuild.fetchurl {
|
||||
name = "linux.tar.gz";
|
||||
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.gz";
|
||||
hash = "sha256-PkdzUKZ0IpBiWe/RS70J76JKnBFzRblWcKlaIFNxnHQ=";
|
||||
};
|
||||
config = {
|
||||
MTD = "y";
|
||||
MTD_BLOCK = "y";
|
||||
@@ -24,25 +19,28 @@
|
||||
VIRTIO_NET = "y";
|
||||
};
|
||||
conditionalConfig = {
|
||||
WLAN= {
|
||||
WLAN = {
|
||||
MAC80211_HWSIM = "m";
|
||||
};
|
||||
};
|
||||
};
|
||||
hardware =
|
||||
let
|
||||
mac80211 = pkgs.kmodloader.override {
|
||||
mac80211 = pkgs.kmodloader.override {
|
||||
inherit (config.system.outputs) kernel;
|
||||
targets = ["mac80211_hwsim"];
|
||||
targets = [ "mac80211_hwsim" ];
|
||||
};
|
||||
in {
|
||||
in
|
||||
{
|
||||
defaultOutput = "vmroot";
|
||||
rootDevice = "/dev/mtdblock0";
|
||||
dts.src = pkgs.lib.mkDefault null;
|
||||
flash.eraseBlockSize = 65536;
|
||||
networkInterfaces =
|
||||
let inherit (config.system.service.network) link;
|
||||
in {
|
||||
let
|
||||
inherit (config.system.service.network) link;
|
||||
in
|
||||
{
|
||||
wan = link.build {
|
||||
devpath = "/devices/pci0000:00/0000:00:13.0/virtio0";
|
||||
ifname = "wan";
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
config = "mips-unknown-linux-musl";
|
||||
gcc = {
|
||||
abi = "32";
|
||||
arch = "24kc"; # maybe mips_24kc-
|
||||
arch = "24kc"; # maybe mips_24kc-
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -41,10 +41,11 @@
|
||||
:ref:`system-outputs-mtdimage` can be flashed using the
|
||||
vendor web UI or the U-Boot emergency "unbrick" routine.
|
||||
|
||||
For flashing from an existing Liminix system (we believe that) it
|
||||
is necessary to first boot into a :ref:`system-outputs-kexecboot`
|
||||
system, otherwise you'll be overwriting flash partitions while
|
||||
they're in use - and that might not end well.
|
||||
Flashing over an existing Liminix system is not possible while
|
||||
that system is running, otherwise you'll be overwriting flash
|
||||
partitions while they're in use - and that might not end well.
|
||||
Configure the system with :ref:`levitate` if you need to
|
||||
make it upgradable.
|
||||
|
||||
Vendor web page: https://www.gl-inet.com/products/gl-ar750/
|
||||
|
||||
@@ -52,8 +53,16 @@
|
||||
|
||||
'';
|
||||
|
||||
module = {pkgs, config, lim, ... }:
|
||||
module =
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lim,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
openwrt = pkgs.openwrt;
|
||||
firmwareBlobs = pkgs.pkgsBuildBuild.fetchFromGitHub {
|
||||
owner = "kvalo";
|
||||
@@ -63,7 +72,7 @@
|
||||
};
|
||||
firmware = pkgs.stdenv.mkDerivation {
|
||||
name = "wlan-firmware";
|
||||
phases = ["installPhase"];
|
||||
phases = [ "installPhase" ];
|
||||
installPhase = ''
|
||||
mkdir -p $out/ath10k/QCA9887/hw1.0/
|
||||
blobdir=${firmwareBlobs}/QCA9887/hw1.0
|
||||
@@ -72,7 +81,10 @@
|
||||
'';
|
||||
};
|
||||
mac80211 = pkgs.kmodloader.override {
|
||||
targets = ["ath9k" "ath10k_pci"];
|
||||
targets = [
|
||||
"ath9k"
|
||||
"ath10k_pci"
|
||||
];
|
||||
inherit (config.system.outputs) kernel;
|
||||
dependencies = [ ath10k_cal_data ];
|
||||
};
|
||||
@@ -80,7 +92,8 @@
|
||||
let
|
||||
offset = lim.parseInt "0x5000";
|
||||
size = lim.parseInt "0x844";
|
||||
in pkgs.liminix.services.oneshot rec {
|
||||
in
|
||||
pkgs.liminix.services.oneshot rec {
|
||||
name = "ath10k_cal_data";
|
||||
up = ''
|
||||
part=$(basename $(dirname $(grep -l art /sys/class/mtd/*/name)))
|
||||
@@ -89,10 +102,11 @@
|
||||
(in_outputs ${name}
|
||||
dd if=/dev/$part of=data iflag=skip_bytes,fullblock bs=${toString size} skip=${toString offset} count=1
|
||||
)
|
||||
'';
|
||||
};
|
||||
'';
|
||||
};
|
||||
inherit (pkgs.pseudofile) dir symlink;
|
||||
in {
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
../../modules/network
|
||||
../../modules/arch/mipseb.nix
|
||||
@@ -116,21 +130,26 @@
|
||||
rootDevice = "/dev/mtdblock5";
|
||||
dts = {
|
||||
src = "${openwrt.src}/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts";
|
||||
includes = [
|
||||
includePaths = [
|
||||
"${openwrt.src}/target/linux/ath79/dts"
|
||||
];
|
||||
includes = mkIf config.logging.persistent.enable [
|
||||
./pstore-ramoops.dtsi
|
||||
];
|
||||
};
|
||||
|
||||
networkInterfaces =
|
||||
let inherit (config.system.service.network) link;
|
||||
in {
|
||||
let
|
||||
inherit (config.system.service.network) link;
|
||||
in
|
||||
{
|
||||
lan = link.build {
|
||||
ifname = "lan";
|
||||
devpath = "/devices/platform/ahb/19000000.eth";
|
||||
devpath = "/devices/platform/ahb/1a000000.eth";
|
||||
};
|
||||
wan = link.build {
|
||||
ifname = "wan";
|
||||
devpath = "/devices/platform/ahb/1a000000.eth";
|
||||
devpath = "/devices/platform/ahb/19000000.eth";
|
||||
};
|
||||
wlan = link.build {
|
||||
ifname = "wlan0";
|
||||
@@ -138,7 +157,10 @@
|
||||
};
|
||||
wlan5 = link.build {
|
||||
ifname = "wlan1";
|
||||
dependencies = [ ath10k_cal_data mac80211 ];
|
||||
dependencies = [
|
||||
ath10k_cal_data
|
||||
mac80211
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -157,12 +179,6 @@
|
||||
appendDTB = true;
|
||||
};
|
||||
kernel = {
|
||||
src = pkgs.pkgsBuildBuild.fetchurl {
|
||||
name = "linux.tar.gz";
|
||||
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.gz";
|
||||
hash = "sha256-PkdzUKZ0IpBiWe/RS70J76JKnBFzRblWcKlaIFNxnHQ=";
|
||||
};
|
||||
|
||||
# Mainline linux 5.19 doesn't have device-tree support for
|
||||
# this device or even for the SoC, so we use the extensive
|
||||
# OpenWrt kernel patches
|
||||
@@ -194,31 +210,31 @@
|
||||
NET = "y";
|
||||
ETHERNET = "y";
|
||||
NET_VENDOR_ATHEROS = "y";
|
||||
AG71XX = "y"; # ethernet (qca,qca9530-eth)
|
||||
MFD_SYSCON = "y"; # ethernet (compatible "syscon")
|
||||
AR8216_PHY = "y"; # eth1 is behind a switch
|
||||
AG71XX = "y"; # ethernet (qca,qca9530-eth)
|
||||
MFD_SYSCON = "y"; # ethernet (compatible "syscon")
|
||||
AR8216_PHY = "y"; # eth1 is behind a switch
|
||||
|
||||
MTD_SPI_NOR = "y";
|
||||
|
||||
SPI_ATH79 = "y"; # these are copied from OpenWrt.
|
||||
SPI_MASTER= "y"; # At least one of them is necessary
|
||||
SPI_MEM= "y";
|
||||
SPI_AR934X= "y";
|
||||
SPI_BITBANG= "y";
|
||||
SPI_GPIO= "y";
|
||||
SPI_ATH79 = "y"; # these are copied from OpenWrt.
|
||||
SPI_MASTER = "y"; # At least one of them is necessary
|
||||
SPI_MEM = "y";
|
||||
SPI_AR934X = "y";
|
||||
SPI_BITBANG = "y";
|
||||
SPI_GPIO = "y";
|
||||
|
||||
GPIO_ATH79 = "y";
|
||||
GPIOLIB = "y";
|
||||
EXPERT="y";
|
||||
EXPERT = "y";
|
||||
GPIO_SYSFS = "y"; # required by patches-5.15/0004-phy-add-ath79-usb-phys.patch
|
||||
OF_GPIO = "y";
|
||||
SYSFS = "y";
|
||||
SPI = "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";
|
||||
ATH79_WDT = "y"; # watchdog timer
|
||||
ATH79_WDT = "y"; # watchdog timer
|
||||
|
||||
EARLY_PRINTK = "y";
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/ {
|
||||
reserved-memory {
|
||||
ramoops@03f00000 {
|
||||
compatible = "ramoops";
|
||||
reg = <0x03f00000 0x10000>;
|
||||
pmsg-size = <0x10000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -6,7 +6,7 @@
|
||||
config = "mipsel-unknown-linux-musl";
|
||||
gcc = {
|
||||
abi = "32";
|
||||
arch = "mips32"; # maybe mips_24kc-
|
||||
arch = "mips32"; # maybe mips_24kc-
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -32,10 +32,11 @@
|
||||
binary created by :ref:`system-outputs-mtdimage` can be flashed
|
||||
using the vendor web UI or the U-Boot emergency "unbrick" routine.
|
||||
|
||||
For flashing from an existing Liminix system (we think) it
|
||||
is necessary to first boot into a :ref:`system-outputs-kexecboot`
|
||||
system, otherwise you'll be overwriting flash partitions while
|
||||
they're in use - and that might not end well.
|
||||
Flashing over an existing Liminix system is not possible while
|
||||
that system is running, otherwise you'll be overwriting flash
|
||||
partitions while they're in use - and that might not end well.
|
||||
Configure the system with :ref:`levitate` if you need to
|
||||
make it upgradable.
|
||||
|
||||
Vendor web page: https://www.gl-inet.com/products/gl-mt300a/
|
||||
|
||||
@@ -43,14 +44,22 @@
|
||||
|
||||
'';
|
||||
|
||||
module = { pkgs, config, lib, lim, ...}:
|
||||
module =
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
lim,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (pkgs) openwrt;
|
||||
mac80211 = pkgs.kmodloader.override {
|
||||
targets = ["rt2800soc"];
|
||||
targets = [ "rt2800soc" ];
|
||||
inherit (config.system.outputs) kernel;
|
||||
};
|
||||
in {
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
../../modules/arch/mipsel.nix
|
||||
../../modules/outputs/tftpboot.nix
|
||||
@@ -81,7 +90,7 @@
|
||||
|
||||
dts = {
|
||||
src = "${openwrt.src}/target/linux/ramips/dts/mt7620a_glinet_gl-mt300a.dts";
|
||||
includes = [
|
||||
includePaths = [
|
||||
"${openwrt.src}/target/linux/ramips/dts"
|
||||
];
|
||||
};
|
||||
@@ -89,7 +98,8 @@
|
||||
let
|
||||
inherit (config.system.service.network) link;
|
||||
inherit (config.system.service) vlan;
|
||||
in rec {
|
||||
in
|
||||
rec {
|
||||
eth = link.build { ifname = "eth0"; };
|
||||
# lan and wan ports are both behind a switch on eth0
|
||||
lan = vlan.build {
|
||||
@@ -111,59 +121,56 @@
|
||||
boot.tftp = {
|
||||
loadAddress = lim.parseInt "0x00A00000";
|
||||
appendDTB = true;
|
||||
};
|
||||
};
|
||||
|
||||
kernel = {
|
||||
src = pkgs.fetchurl {
|
||||
name = "linux.tar.gz";
|
||||
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.gz";
|
||||
hash = "sha256-PkdzUKZ0IpBiWe/RS70J76JKnBFzRblWcKlaIFNxnHQ=";
|
||||
};
|
||||
extraPatchPhase = ''
|
||||
${openwrt.applyPatches.ramips}
|
||||
${openwrt.applyPatches.rt2x00}
|
||||
'';
|
||||
config = {
|
||||
config =
|
||||
{
|
||||
|
||||
RALINK = "y";
|
||||
PCI = "y";
|
||||
SOC_MT7620 = "y";
|
||||
RALINK = "y";
|
||||
PCI = "y";
|
||||
SOC_MT7620 = "y";
|
||||
|
||||
SERIAL_8250_CONSOLE = "y";
|
||||
SERIAL_8250 = "y";
|
||||
SERIAL_CORE_CONSOLE = "y";
|
||||
SERIAL_OF_PLATFORM = "y";
|
||||
SERIAL_8250_CONSOLE = "y";
|
||||
SERIAL_8250 = "y";
|
||||
SERIAL_CORE_CONSOLE = "y";
|
||||
SERIAL_OF_PLATFORM = "y";
|
||||
|
||||
CONSOLE_LOGLEVEL_DEFAULT = "8";
|
||||
CONSOLE_LOGLEVEL_QUIET = "4";
|
||||
CONSOLE_LOGLEVEL_DEFAULT = "8";
|
||||
CONSOLE_LOGLEVEL_QUIET = "4";
|
||||
|
||||
NET = "y";
|
||||
ETHERNET = "y";
|
||||
NET_VENDOR_RALINK = "y";
|
||||
NET_RALINK_MDIO = "y";
|
||||
NET_RALINK_MDIO_MT7620 = "y";
|
||||
NET_RALINK_MT7620 = "y";
|
||||
SWPHY = "y";
|
||||
NET = "y";
|
||||
ETHERNET = "y";
|
||||
NET_VENDOR_RALINK = "y";
|
||||
NET_RALINK_MDIO = "y";
|
||||
NET_RALINK_MDIO_MT7620 = "y";
|
||||
NET_RALINK_MT7620 = "y";
|
||||
SWPHY = "y";
|
||||
|
||||
SPI = "y";
|
||||
MTD_SPI_NOR = "y";
|
||||
SPI_MT7621 = "y"; # } probably don't need both of these
|
||||
SPI_RT2880 = "y"; # }
|
||||
SPI_MASTER= "y";
|
||||
SPI_MEM= "y";
|
||||
SPI = "y";
|
||||
MTD_SPI_NOR = "y";
|
||||
SPI_MT7621 = "y"; # } probably don't need both of these
|
||||
SPI_RT2880 = "y"; # }
|
||||
SPI_MASTER = "y";
|
||||
SPI_MEM = "y";
|
||||
|
||||
MTD = "y";
|
||||
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs
|
||||
MTD = "y";
|
||||
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs
|
||||
|
||||
EARLY_PRINTK = "y";
|
||||
EARLY_PRINTK = "y";
|
||||
|
||||
NEW_LEDS = "y";
|
||||
LEDS_CLASS = "y"; # required by rt2x00lib
|
||||
NEW_LEDS = "y";
|
||||
LEDS_CLASS = "y"; # required by rt2x00lib
|
||||
|
||||
PRINTK_TIME = "y";
|
||||
} // lib.optionalAttrs (config.system.service ? vlan) {
|
||||
SWCONFIG = "y";
|
||||
};
|
||||
PRINTK_TIME = "y";
|
||||
}
|
||||
// lib.optionalAttrs (config.system.service ? vlan) {
|
||||
SWCONFIG = "y";
|
||||
};
|
||||
conditionalConfig = {
|
||||
WLAN = {
|
||||
WLAN_VENDOR_RALINK = "y";
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
config = "mipsel-unknown-linux-musl";
|
||||
gcc = {
|
||||
abi = "32";
|
||||
arch = "mips32"; # maybe mips_24kc-
|
||||
arch = "mips32"; # maybe mips_24kc-
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -13,7 +13,7 @@
|
||||
GL.iNet GL-MT300N-v2
|
||||
********************
|
||||
|
||||
The GL-MT300N-v2 "Mango" is is very similar to the :ref:`MT300A <GL.iNet GL-MT300A>, but is
|
||||
The GL-MT300N-v2 "Mango" is is very similar to the :ref:`gl-mt300a`, but is
|
||||
based on the MT7628 chipset instead of MT7620. It's also marginally cheaper
|
||||
and comes in a yellow case not a blue one. Be sure your device is
|
||||
v2 not v1, which is a different animal and has only half as much RAM.
|
||||
@@ -25,10 +25,11 @@
|
||||
binary created by :ref:`system-outputs-mtdimage` can be flashed
|
||||
using the vendor web UI or the U-Boot emergency "unbrick" routine.
|
||||
|
||||
For flashing from an existing Liminix system (we think) it
|
||||
is necessary to first boot into a :ref:`system-outputs-kexecboot`
|
||||
system, otherwise you'll be overwriting flash partitions while
|
||||
they're in use - and that might not end well.
|
||||
Flashing over an existing Liminix system is not possible while
|
||||
that system is running, otherwise you'll be overwriting flash
|
||||
partitions while they're in use - and that might not end well.
|
||||
Configure the system with :ref:`levitate` if you need to
|
||||
make it upgradable.
|
||||
|
||||
Vendor web page: https://www.gl-inet.com/products/gl-mt300n-v2/
|
||||
|
||||
@@ -36,21 +37,29 @@
|
||||
|
||||
'';
|
||||
|
||||
module = { pkgs, config, lib, lim, ...}:
|
||||
module =
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
lim,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (pkgs.liminix.services) oneshot;
|
||||
inherit (pkgs.pseudofile) dir symlink;
|
||||
inherit (pkgs) openwrt;
|
||||
|
||||
mac80211 = pkgs.kmodloader.override {
|
||||
targets = ["mt7603e"];
|
||||
targets = [ "mt7603e" ];
|
||||
inherit (config.system.outputs) kernel;
|
||||
};
|
||||
wlan_firmware = pkgs.fetchurl {
|
||||
url = "https://github.com/openwrt/mt76/raw/f24b56f935392ca1d35fae5fd6e56ef9deda4aad/firmware/mt7628_e2.bin";
|
||||
hash = "sha256:1dkhfznmdz6s50kwc841x3wj0h6zg6icg5g2bim9pvg66as2vmh9";
|
||||
};
|
||||
in {
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
../../modules/arch/mipsel.nix
|
||||
../../modules/outputs/tftpboot.nix
|
||||
@@ -78,7 +87,7 @@
|
||||
|
||||
dts = {
|
||||
src = "${openwrt.src}/target/linux/ramips/dts/mt7628an_glinet_gl-mt300n-v2.dts";
|
||||
includes = [
|
||||
includePaths = [
|
||||
"${openwrt.src}/target/linux/ramips/dts"
|
||||
];
|
||||
};
|
||||
@@ -98,8 +107,12 @@
|
||||
'';
|
||||
down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset";
|
||||
};
|
||||
in rec {
|
||||
eth = link.build { ifname = "eth0"; dependencies = [swconfig]; };
|
||||
in
|
||||
rec {
|
||||
eth = link.build {
|
||||
ifname = "eth0";
|
||||
dependencies = [ swconfig ];
|
||||
};
|
||||
# lan and wan ports are both behind a switch on eth0
|
||||
lan = vlan.build {
|
||||
ifname = "eth0.1";
|
||||
@@ -125,66 +138,64 @@
|
||||
};
|
||||
|
||||
kernel = {
|
||||
src = pkgs.fetchurl {
|
||||
name = "linux.tar.gz";
|
||||
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.gz";
|
||||
hash = "sha256-PkdzUKZ0IpBiWe/RS70J76JKnBFzRblWcKlaIFNxnHQ=";
|
||||
};
|
||||
extraPatchPhase = ''
|
||||
${openwrt.applyPatches.ramips}
|
||||
'';
|
||||
config = {
|
||||
config =
|
||||
{
|
||||
|
||||
RALINK = "y";
|
||||
PCI = "y";
|
||||
SOC_MT7620 = "y";
|
||||
RALINK = "y";
|
||||
PCI = "y";
|
||||
SOC_MT7620 = "y";
|
||||
|
||||
SERIAL_8250_CONSOLE = "y";
|
||||
SERIAL_8250 = "y";
|
||||
SERIAL_CORE_CONSOLE = "y";
|
||||
SERIAL_OF_PLATFORM = "y";
|
||||
SERIAL_8250_CONSOLE = "y";
|
||||
SERIAL_8250 = "y";
|
||||
SERIAL_CORE_CONSOLE = "y";
|
||||
SERIAL_OF_PLATFORM = "y";
|
||||
|
||||
CONSOLE_LOGLEVEL_DEFAULT = "8";
|
||||
CONSOLE_LOGLEVEL_QUIET = "4";
|
||||
CONSOLE_LOGLEVEL_DEFAULT = "8";
|
||||
CONSOLE_LOGLEVEL_QUIET = "4";
|
||||
|
||||
MTD = "y";
|
||||
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev
|
||||
MTD = "y";
|
||||
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev
|
||||
|
||||
SPI = "y";
|
||||
MTD_SPI_NOR = "y";
|
||||
SPI_MT7621 = "y";
|
||||
SPI_MASTER= "y";
|
||||
SPI_MEM= "y";
|
||||
SPI = "y";
|
||||
MTD_SPI_NOR = "y";
|
||||
SPI_MT7621 = "y";
|
||||
SPI_MASTER = "y";
|
||||
SPI_MEM = "y";
|
||||
|
||||
REGULATOR = "y";
|
||||
REGULATOR_FIXED_VOLTAGE = "y";
|
||||
REGULATOR = "y";
|
||||
REGULATOR_FIXED_VOLTAGE = "y";
|
||||
|
||||
NET = "y";
|
||||
ETHERNET = "y";
|
||||
NET = "y";
|
||||
ETHERNET = "y";
|
||||
|
||||
PHYLIB = "y";
|
||||
AT803X_PHY="y";
|
||||
FIXED_PHY="y";
|
||||
GENERIC_PHY="y";
|
||||
NET_VENDOR_RALINK = "y";
|
||||
NET_RALINK_RT3050 = "y";
|
||||
NET_RALINK_SOC="y";
|
||||
SWPHY = "y";
|
||||
PHYLIB = "y";
|
||||
AT803X_PHY = "y";
|
||||
FIXED_PHY = "y";
|
||||
GENERIC_PHY = "y";
|
||||
NET_VENDOR_RALINK = "y";
|
||||
NET_RALINK_RT3050 = "y";
|
||||
NET_RALINK_SOC = "y";
|
||||
SWPHY = "y";
|
||||
|
||||
GPIOLIB="y";
|
||||
GPIO_MT7621 = "y";
|
||||
GPIOLIB = "y";
|
||||
GPIO_MT7621 = "y";
|
||||
|
||||
PHY_RALINK_USB = "y";
|
||||
PHY_RALINK_USB = "y";
|
||||
|
||||
EARLY_PRINTK = "y";
|
||||
EARLY_PRINTK = "y";
|
||||
|
||||
PRINTK_TIME = "y";
|
||||
} // lib.optionalAttrs (config.system.service ? vlan) {
|
||||
SWCONFIG = "y";
|
||||
} // lib.optionalAttrs (config.system.service ? watchdog) {
|
||||
RALINK_WDT = "y"; # watchdog
|
||||
MT7621_WDT = "y"; # or it might be this one
|
||||
};
|
||||
PRINTK_TIME = "y";
|
||||
}
|
||||
// lib.optionalAttrs (config.system.service ? vlan) {
|
||||
SWCONFIG = "y";
|
||||
}
|
||||
// lib.optionalAttrs (config.system.service ? watchdog) {
|
||||
RALINK_WDT = "y"; # watchdog
|
||||
MT7621_WDT = "y"; # or it might be this one
|
||||
};
|
||||
conditionalConfig = {
|
||||
WLAN = {
|
||||
WLAN_VENDOR_RALINK = "y";
|
||||
|
||||
@@ -0,0 +1,751 @@
|
||||
{
|
||||
description = ''
|
||||
OpenWrt One
|
||||
***********
|
||||
|
||||
Hardware summary
|
||||
================
|
||||
|
||||
- MediaTek MT7981B (1300MHz)
|
||||
- 256MB NAND Flash
|
||||
- 1024MB RAM
|
||||
- WLan hardware: Mediatek MT7976C
|
||||
|
||||
Status
|
||||
======
|
||||
|
||||
- Only tested over TFTP so far.
|
||||
- WiFi (2.4G and 5G) works.
|
||||
- 2.5G ethernet port works.
|
||||
|
||||
Limitations
|
||||
===========
|
||||
|
||||
- adding `he_bss_color="128"` causes `Invalid argument` for hostap
|
||||
- nvme support untested
|
||||
- I don't think the front LEDs work yet
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
TODO: add instructions on how to boot directly from TFTP to memory
|
||||
and how to install from TFTP to flash without going through OpenWrt.
|
||||
|
||||
The instructions below assume you can boot and SSH into OpenWrt:
|
||||
|
||||
Boot into OpenWrt and create a 'liminix' UBI partition:
|
||||
|
||||
root@OpenWrt:~# ubimkvol /dev/ubi0 --name=liminix --maxavsize
|
||||
|
||||
Remember the 'Volume ID' that was created for this new partition
|
||||
|
||||
Build the UBI image and write it to this new partition:
|
||||
|
||||
$ nix-build -I liminix-config=./my-configuration.nix --arg device "import ./devices/openwrt-one" -A outputs.default
|
||||
$ cat result/rootfs | ssh root@192.168.1.1 "cat > /tmp/rootfs"
|
||||
$ ssh root@192.168.1.1
|
||||
root@OpenWrt:~# ubiupdatevol /dev/ubi0_X /tmp/rootfs # replace X with the volume id, if needed check with `ubinfo`
|
||||
|
||||
Reboot into the U-Boot prompt and boot with:
|
||||
|
||||
OpenWrt One> ubifsmount ubi0:liminix && ubifsload ''${loadaddr} boot/fit && bootm ''${loadaddr}'
|
||||
|
||||
If this works, reboot into OpenWrt and configure U-Boot to boot ubifs by default:
|
||||
|
||||
root@OpenWrt:~# fw_setenv orig_boot_production $(fw_printenv -n boot_production)
|
||||
root@OpenWrt:~# fw_setenv boot_production 'led white on ; ubifsmount ubi0:liminix && ubifsload ''${loadaddr} boot/fit && bootm ''${loadaddr}'
|
||||
|
||||
Troubleshooting
|
||||
===============
|
||||
|
||||
The instructions above assume you can boot and SSH into the (recovery)
|
||||
OpenWrt installation. If you have broken your device to the point where that
|
||||
is no longer possible, you could re-install OpenWrt, but probably you could
|
||||
also install directly from U-Boot:
|
||||
|
||||
https://github.com/u-boot/u-boot/blob/master/doc/README.ubi
|
||||
'';
|
||||
|
||||
system = {
|
||||
crossSystem = {
|
||||
config = "aarch64-unknown-linux-musl";
|
||||
gcc = {
|
||||
# https://openwrt.org/docs/techref/instructionset/aarch64_cortex-a53
|
||||
# openwrt ./target/linux/mediatek/filogic/target.mk
|
||||
# https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html
|
||||
# https://en.wikipedia.org/wiki/Comparison_of_ARM_processors
|
||||
arch = "armv8-a";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
module =
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
lim,
|
||||
...
|
||||
}:
|
||||
let
|
||||
openwrt = pkgs.openwrt_24_10;
|
||||
mediatek-firmware = pkgs.stdenv.mkDerivation {
|
||||
name = "wlan-firmware";
|
||||
phases = [ "installPhase" ];
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
|
||||
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7986_eeprom_mt7976,mt7981}* $out
|
||||
'';
|
||||
};
|
||||
airoha-firmware = pkgs.stdenv.mkDerivation {
|
||||
name = "airoha-firmware";
|
||||
phases = [ "installPhase" ];
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
|
||||
cp ${pkgs.linux-firmware}/lib/firmware/airoha/* $out
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
../../modules/arch/aarch64.nix
|
||||
../../modules/outputs/tftpboot.nix
|
||||
../../modules/outputs/ubifs.nix
|
||||
];
|
||||
config = {
|
||||
kernel = {
|
||||
src = openwrt.kernelSrc;
|
||||
version = openwrt.kernelVersion;
|
||||
extraPatchPhase = ''
|
||||
${openwrt.applyPatches.mediatek}
|
||||
'';
|
||||
config =
|
||||
{
|
||||
NET = "y"; # unlock NET_XGRESS
|
||||
SERIAL_8250 = "y"; # unlock SERIAL_8250_FSL
|
||||
SERIAL_8250_CONSOLE = "y"; # to get the serial console
|
||||
WATCHDOG = "y"; # unlock WATCHDOG_CORE
|
||||
NEW_LEDS = "y"; # unlock LEDS_PWM
|
||||
LEDS_CLASS = "y"; # unlock LEDS_PWM
|
||||
LEDS_TRIGGERS = "y"; # unlock LEDS_TRIGGER_PATTERN
|
||||
DEFERRED_STRUCT_PAGE_INIT = "y"; # trigger PADATA
|
||||
# Taken from openwrt's ./target/linux/mediatek/filogic/config-6.6
|
||||
"64BIT" = "y";
|
||||
AIROHA_EN8801SC_PHY = "y";
|
||||
ARCH_BINFMT_ELF_EXTRA_PHDRS = "y";
|
||||
ARCH_CORRECT_STACKTRACE_ON_KRETPROBE = "y";
|
||||
ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG = "y";
|
||||
ARCH_DMA_ADDR_T_64BIT = "y";
|
||||
ARCH_FORCE_MAX_ORDER = "10";
|
||||
ARCH_KEEP_MEMBLOCK = "y";
|
||||
ARCH_MEDIATEK = "y";
|
||||
ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE = "y";
|
||||
ARCH_MMAP_RND_BITS = "18";
|
||||
ARCH_MMAP_RND_BITS_MAX = "24";
|
||||
ARCH_MMAP_RND_BITS_MIN = "18";
|
||||
ARCH_MMAP_RND_COMPAT_BITS_MIN = "11";
|
||||
ARCH_PROC_KCORE_TEXT = "y";
|
||||
ARCH_SPARSEMEM_ENABLE = "y";
|
||||
ARCH_STACKWALK = "y";
|
||||
ARCH_SUSPEND_POSSIBLE = "y";
|
||||
ARCH_WANTS_NO_INSTR = "y";
|
||||
ARCH_WANTS_THP_SWAP = "y";
|
||||
ARM64 = "y";
|
||||
ARM64_4K_PAGES = "y";
|
||||
ARM64_ERRATUM_843419 = "y";
|
||||
ARM64_LD_HAS_FIX_ERRATUM_843419 = "y";
|
||||
ARM64_PAGE_SHIFT = "12";
|
||||
ARM64_PA_BITS = "48";
|
||||
ARM64_PA_BITS_48 = "y";
|
||||
ARM64_TAGGED_ADDR_ABI = "y";
|
||||
ARM64_VA_BITS = "39";
|
||||
ARM64_VA_BITS_39 = "y";
|
||||
ARM_AMBA = "y";
|
||||
ARM_ARCH_TIMER = "y";
|
||||
ARM_ARCH_TIMER_EVTSTREAM = "y";
|
||||
ARM_GIC = "y";
|
||||
ARM_GIC_V2M = "y";
|
||||
ARM_GIC_V3 = "y";
|
||||
ARM_GIC_V3_ITS = "y";
|
||||
ARM_GIC_V3_ITS_PCI = "y";
|
||||
ARM_MEDIATEK_CPUFREQ = "y";
|
||||
ARM_PMU = "y";
|
||||
ARM_PMUV3 = "y";
|
||||
ARM_PSCI_FW = "y";
|
||||
ATA = "y";
|
||||
AUDIT_ARCH_COMPAT_GENERIC = "y";
|
||||
BLK_DEV_LOOP = "y";
|
||||
BLK_DEV_SD = "y";
|
||||
BLK_MQ_PCI = "y";
|
||||
BLK_PM = "y";
|
||||
BLOCK_NOTIFIERS = "y";
|
||||
BSD_PROCESS_ACCT = "y";
|
||||
BSD_PROCESS_ACCT_V3 = "y";
|
||||
BUFFER_HEAD = "y";
|
||||
BUILTIN_RETURN_ADDRESS_STRIPS_PAC = "y";
|
||||
CC_HAVE_SHADOW_CALL_STACK = "y";
|
||||
CC_HAVE_STACKPROTECTOR_SYSREG = "y";
|
||||
#CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5";
|
||||
CC_NO_ARRAY_BOUNDS = "y";
|
||||
CLKSRC_MMIO = "y";
|
||||
CLONE_BACKWARDS = "y";
|
||||
CMDLINE_OVERRIDE = "y";
|
||||
COMMON_CLK = "y";
|
||||
COMMON_CLK_MEDIATEK = "y";
|
||||
COMMON_CLK_MT7981 = "y";
|
||||
COMMON_CLK_MT7981_ETHSYS = "y";
|
||||
COMMON_CLK_MT7986 = "y";
|
||||
COMMON_CLK_MT7986_ETHSYS = "y";
|
||||
COMMON_CLK_MT7988 = "y";
|
||||
COMPACT_UNEVICTABLE_DEFAULT = "1";
|
||||
CONFIGFS_FS = "y";
|
||||
CONSOLE_LOGLEVEL_DEFAULT = "15";
|
||||
CONTEXT_TRACKING = "y";
|
||||
CONTEXT_TRACKING_IDLE = "y";
|
||||
CPU_FREQ = "y";
|
||||
CPU_FREQ_DEFAULT_GOV_USERSPACE = "y";
|
||||
CPU_FREQ_GOV_ATTR_SET = "y";
|
||||
CPU_FREQ_GOV_COMMON = "y";
|
||||
CPU_FREQ_GOV_CONSERVATIVE = "y";
|
||||
CPU_FREQ_GOV_ONDEMAND = "y";
|
||||
CPU_FREQ_GOV_PERFORMANCE = "y";
|
||||
CPU_FREQ_GOV_POWERSAVE = "y";
|
||||
CPU_FREQ_GOV_SCHEDUTIL = "y";
|
||||
CPU_FREQ_GOV_USERSPACE = "y";
|
||||
CPU_FREQ_STAT = "y";
|
||||
CPU_LITTLE_ENDIAN = "y";
|
||||
CPU_RMAP = "y";
|
||||
CPU_THERMAL = "y";
|
||||
CRC16 = "y";
|
||||
CRC_CCITT = "y";
|
||||
CRYPTO_AES_ARM64 = "y";
|
||||
CRYPTO_AES_ARM64_CE = "y";
|
||||
CRYPTO_AES_ARM64_CE_BLK = "y";
|
||||
CRYPTO_AES_ARM64_CE_CCM = "y";
|
||||
CRYPTO_CMAC = "y";
|
||||
CRYPTO_CRC32 = "y";
|
||||
CRYPTO_CRC32C = "y";
|
||||
CRYPTO_CRYPTD = "y";
|
||||
CRYPTO_DEFLATE = "y";
|
||||
CRYPTO_DRBG = "y";
|
||||
CRYPTO_DRBG_HMAC = "y";
|
||||
CRYPTO_DRBG_MENU = "y";
|
||||
CRYPTO_ECB = "y";
|
||||
CRYPTO_ECC = "y";
|
||||
CRYPTO_ECDH = "y";
|
||||
CRYPTO_GHASH_ARM64_CE = "y";
|
||||
CRYPTO_HASH_INFO = "y";
|
||||
CRYPTO_HMAC = "y";
|
||||
CRYPTO_JITTERENTROPY = "y";
|
||||
CRYPTO_LIB_BLAKE2S_GENERIC = "y";
|
||||
CRYPTO_LIB_GF128MUL = "y";
|
||||
CRYPTO_LIB_SHA1 = "y";
|
||||
CRYPTO_LIB_SHA256 = "y";
|
||||
CRYPTO_LIB_UTILS = "y";
|
||||
CRYPTO_LZO = "y";
|
||||
CRYPTO_RNG = "y";
|
||||
CRYPTO_RNG2 = "y";
|
||||
CRYPTO_RNG_DEFAULT = "y";
|
||||
CRYPTO_SHA256 = "y";
|
||||
CRYPTO_SHA256_ARM64 = "y";
|
||||
CRYPTO_SHA2_ARM64_CE = "y";
|
||||
CRYPTO_SHA3 = "y";
|
||||
CRYPTO_SHA512 = "y";
|
||||
CRYPTO_SM4 = "y";
|
||||
CRYPTO_SM4_ARM64_CE_BLK = "y";
|
||||
CRYPTO_SM4_ARM64_CE_CCM = "y";
|
||||
CRYPTO_SM4_ARM64_CE_GCM = "y";
|
||||
CRYPTO_ZSTD = "y";
|
||||
DCACHE_WORD_ACCESS = "y";
|
||||
#DEBUG_INFO="y";
|
||||
DEBUG_MISC = "y";
|
||||
DIMLIB = "y";
|
||||
DMADEVICES = "y";
|
||||
DMATEST = "y";
|
||||
DMA_BOUNCE_UNALIGNED_KMALLOC = "y";
|
||||
DMA_DIRECT_REMAP = "y";
|
||||
DMA_ENGINE = "y";
|
||||
DMA_ENGINE_RAID = "y";
|
||||
DMA_OF = "y";
|
||||
DMA_VIRTUAL_CHANNELS = "y";
|
||||
DTC = "y";
|
||||
EDAC_SUPPORT = "y";
|
||||
EINT_MTK = "y";
|
||||
EXCLUSIVE_SYSTEM_RAM = "y";
|
||||
EXT4_FS = "y";
|
||||
F2FS_FS = "y";
|
||||
FIXED_PHY = "y";
|
||||
FIX_EARLYCON_MEM = "y";
|
||||
FRAME_POINTER = "y";
|
||||
FS_IOMAP = "y";
|
||||
FS_MBCACHE = "y";
|
||||
FUNCTION_ALIGNMENT = "4";
|
||||
FUNCTION_ALIGNMENT_4B = "y";
|
||||
FWNODE_MDIO = "y";
|
||||
FW_LOADER_PAGED_BUF = "y";
|
||||
#FW_LOADER_SYSFS="y";
|
||||
#GCC11_NO_ARRAY_BOUNDS="y";
|
||||
#GCC_ASM_GOTO_OUTPUT_WORKAROUND="y";
|
||||
GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS = "y";
|
||||
GENERIC_ALLOCATOR = "y";
|
||||
GENERIC_ARCH_TOPOLOGY = "y";
|
||||
GENERIC_BUG = "y";
|
||||
GENERIC_BUG_RELATIVE_POINTERS = "y";
|
||||
GENERIC_CLOCKEVENTS = "y";
|
||||
GENERIC_CLOCKEVENTS_BROADCAST = "y";
|
||||
GENERIC_CPU_AUTOPROBE = "y";
|
||||
GENERIC_CPU_VULNERABILITIES = "y";
|
||||
GENERIC_CSUM = "y";
|
||||
GENERIC_EARLY_IOREMAP = "y";
|
||||
GENERIC_GETTIMEOFDAY = "y";
|
||||
GENERIC_IDLE_POLL_SETUP = "y";
|
||||
GENERIC_IOREMAP = "y";
|
||||
GENERIC_IRQ_EFFECTIVE_AFF_MASK = "y";
|
||||
GENERIC_IRQ_SHOW = "y";
|
||||
GENERIC_IRQ_SHOW_LEVEL = "y";
|
||||
GENERIC_LIB_DEVMEM_IS_ALLOWED = "y";
|
||||
GENERIC_MSI_IRQ = "y";
|
||||
GENERIC_PCI_IOMAP = "y";
|
||||
GENERIC_PHY = "y";
|
||||
GENERIC_PINCONF = "y";
|
||||
GENERIC_PINCTRL_GROUPS = "y";
|
||||
GENERIC_PINMUX_FUNCTIONS = "y";
|
||||
GENERIC_SCHED_CLOCK = "y";
|
||||
GENERIC_SMP_IDLE_THREAD = "y";
|
||||
GENERIC_STRNCPY_FROM_USER = "y";
|
||||
GENERIC_STRNLEN_USER = "y";
|
||||
GENERIC_TIME_VSYSCALL = "y";
|
||||
GLOB = "y";
|
||||
GPIO_CDEV = "y";
|
||||
GPIO_WATCHDOG = "y";
|
||||
GPIO_WATCHDOG_ARCH_INITCALL = "y";
|
||||
GRO_CELLS = "y";
|
||||
HARDIRQS_SW_RESEND = "y";
|
||||
HAS_DMA = "y";
|
||||
HAS_IOMEM = "y";
|
||||
HAS_IOPORT = "y";
|
||||
HAS_IOPORT_MAP = "y";
|
||||
HWMON = "y";
|
||||
HW_RANDOM = "y";
|
||||
HW_RANDOM_MTK = "y";
|
||||
I2C = "y";
|
||||
I2C_BOARDINFO = "y";
|
||||
I2C_CHARDEV = "y";
|
||||
I2C_MT65XX = "y";
|
||||
ICPLUS_PHY = "y";
|
||||
ILLEGAL_POINTER_VALUE = "0xdead000000000000";
|
||||
#INITRAMFS_SOURCE="""";
|
||||
IRQCHIP = "y";
|
||||
IRQ_DOMAIN = "y";
|
||||
IRQ_DOMAIN_HIERARCHY = "y";
|
||||
IRQ_FORCED_THREADING = "y";
|
||||
IRQ_TIME_ACCOUNTING = "y";
|
||||
IRQ_WORK = "y";
|
||||
JBD2 = "y";
|
||||
JUMP_LABEL = "y";
|
||||
LEDS_PWM = "y";
|
||||
LEDS_SMARTRG_LED = "y";
|
||||
LIBFDT = "y";
|
||||
LOCK_DEBUGGING_SUPPORT = "y";
|
||||
LOCK_SPIN_ON_OWNER = "y";
|
||||
LZO_COMPRESS = "y";
|
||||
LZO_DECOMPRESS = "y";
|
||||
MAGIC_SYSRQ = "y";
|
||||
MAXLINEAR_GPHY = "y";
|
||||
MDIO_BUS = "y";
|
||||
MDIO_DEVICE = "y";
|
||||
MDIO_DEVRES = "y";
|
||||
MEDIATEK_2P5GE_PHY = "y";
|
||||
MEDIATEK_GE_PHY = "y";
|
||||
MEDIATEK_GE_SOC_PHY = "y";
|
||||
MEDIATEK_WATCHDOG = "y";
|
||||
MESSAGE_LOGLEVEL_DEFAULT = "7";
|
||||
MFD_SYSCON = "y";
|
||||
MIGRATION = "y";
|
||||
MMC = "y";
|
||||
MMC_BLOCK = "y";
|
||||
MMC_CQHCI = "y";
|
||||
MMC_MTK = "y";
|
||||
MMU_LAZY_TLB_REFCOUNT = "y";
|
||||
MODULES_TREE_LOOKUP = "y";
|
||||
MODULES_USE_ELF_RELA = "y";
|
||||
MTD_NAND_CORE = "y";
|
||||
MTD_NAND_ECC = "y";
|
||||
MTD_NAND_ECC_MEDIATEK = "y";
|
||||
MTD_NAND_ECC_SW_HAMMING = "y";
|
||||
MTD_NAND_MTK = "y";
|
||||
MTD_NAND_MTK_BMT = "y";
|
||||
MTD_PARSER_TRX = "y";
|
||||
MTD_RAW_NAND = "y";
|
||||
MTD_SPI_NAND = "y";
|
||||
MTD_SPI_NOR = "y";
|
||||
MTD_SPLIT_FIRMWARE = "y";
|
||||
MTD_SPLIT_FIT_FW = "y";
|
||||
MTD_UBI = "y";
|
||||
MTD_UBI_BEB_LIMIT = "20";
|
||||
MTD_UBI_BLOCK = "y";
|
||||
MTD_UBI_FASTMAP = "y";
|
||||
MTD_UBI_NVMEM = "y";
|
||||
MTD_UBI_WL_THRESHOLD = "4096";
|
||||
MTK_CPUX_TIMER = "y";
|
||||
MTK_HSDMA = "y";
|
||||
MTK_INFRACFG = "y";
|
||||
MTK_LVTS_THERMAL = "y";
|
||||
MTK_LVTS_THERMAL_DEBUGFS = "y";
|
||||
MTK_PMIC_WRAP = "y";
|
||||
MTK_REGULATOR_COUPLER = "y";
|
||||
MTK_SCPSYS = "y";
|
||||
MTK_SCPSYS_PM_DOMAINS = "y";
|
||||
MTK_SOC_THERMAL = "y";
|
||||
MTK_THERMAL = "y";
|
||||
MTK_TIMER = "y";
|
||||
MUTEX_SPIN_ON_OWNER = "y";
|
||||
NEED_DMA_MAP_STATE = "y";
|
||||
NEED_SG_DMA_LENGTH = "y";
|
||||
NET_DEVLINK = "y";
|
||||
NET_DSA = "y";
|
||||
NET_DSA_MT7530 = "y";
|
||||
NET_DSA_MT7530_MDIO = "y";
|
||||
NET_DSA_MT7530_MMIO = "y";
|
||||
NET_DSA_TAG_MTK = "y";
|
||||
#NET_EGRESS="y";
|
||||
NET_FLOW_LIMIT = "y";
|
||||
#NET_INGRESS="y";
|
||||
NET_MEDIATEK_SOC = "y";
|
||||
NET_MEDIATEK_SOC_WED = "y";
|
||||
NET_SELFTESTS = "y";
|
||||
NET_SWITCHDEV = "y";
|
||||
NET_VENDOR_MEDIATEK = "y";
|
||||
#NET_XGRESS="y";
|
||||
NLS = "y";
|
||||
NO_HZ_COMMON = "y";
|
||||
NO_HZ_IDLE = "y";
|
||||
NR_CPUS = "4";
|
||||
NVMEM = "y";
|
||||
NVMEM_BLOCK = "y";
|
||||
NVMEM_LAYOUTS = "y";
|
||||
NVMEM_LAYOUT_ADTRAN = "y";
|
||||
NVMEM_MTK_EFUSE = "y";
|
||||
NVMEM_SYSFS = "y";
|
||||
OF = "y";
|
||||
OF_ADDRESS = "y";
|
||||
OF_DYNAMIC = "y";
|
||||
OF_EARLY_FLATTREE = "y";
|
||||
OF_FLATTREE = "y";
|
||||
OF_GPIO = "y";
|
||||
OF_IRQ = "y";
|
||||
OF_KOBJ = "y";
|
||||
OF_MDIO = "y";
|
||||
OF_OVERLAY = "y";
|
||||
OF_RESOLVE = "y";
|
||||
PADATA = "y";
|
||||
PAGE_POOL = "y";
|
||||
PAGE_POOL_STATS = "y";
|
||||
PAGE_SIZE_LESS_THAN_256KB = "y";
|
||||
PAGE_SIZE_LESS_THAN_64KB = "y";
|
||||
#PAHOLE_HAS_LANG_EXCLUDE="y";
|
||||
PARTITION_PERCPU = "y";
|
||||
PCI = "y";
|
||||
PCIEAER = "y";
|
||||
PCIEASPM = "y";
|
||||
PCIEASPM_PERFORMANCE = "y";
|
||||
PCIEPORTBUS = "y";
|
||||
PCIE_MEDIATEK_GEN3 = "y";
|
||||
PCIE_PME = "y";
|
||||
PCI_DEBUG = "y";
|
||||
PCI_DOMAINS = "y";
|
||||
PCI_DOMAINS_GENERIC = "y";
|
||||
PCI_MSI = "y";
|
||||
PCS_MTK_LYNXI = "y";
|
||||
PCS_MTK_USXGMII = "y";
|
||||
PERF_EVENTS = "y";
|
||||
PER_VMA_LOCK = "y";
|
||||
PGTABLE_LEVELS = "3";
|
||||
PHYLIB = "y";
|
||||
PHYLIB_LEDS = "y";
|
||||
PHYLINK = "y";
|
||||
PHYS_ADDR_T_64BIT = "y";
|
||||
PHY_MTK_TPHY = "y";
|
||||
PHY_MTK_XFI_TPHY = "y";
|
||||
PHY_MTK_XSPHY = "y";
|
||||
PINCTRL = "y";
|
||||
PINCTRL_MT7981 = "y";
|
||||
PINCTRL_MT7986 = "y";
|
||||
PINCTRL_MT7988 = "y";
|
||||
PINCTRL_MTK_MOORE = "y";
|
||||
PINCTRL_MTK_V2 = "y";
|
||||
PM = "y";
|
||||
PM_CLK = "y";
|
||||
PM_GENERIC_DOMAINS = "y";
|
||||
PM_GENERIC_DOMAINS_OF = "y";
|
||||
PM_OPP = "y";
|
||||
POLYNOMIAL = "y";
|
||||
POSIX_CPU_TIMERS_TASK_WORK = "y";
|
||||
POWER_RESET = "y";
|
||||
POWER_RESET_SYSCON = "y";
|
||||
POWER_SUPPLY = "y";
|
||||
PREEMPT_NONE_BUILD = "y";
|
||||
PRINTK_TIME = "y";
|
||||
PSTORE = "y";
|
||||
PSTORE_COMPRESS = "y";
|
||||
PSTORE_CONSOLE = "y";
|
||||
PSTORE_PMSG = "y";
|
||||
PSTORE_RAM = "y";
|
||||
PTP_1588_CLOCK_OPTIONAL = "y";
|
||||
PWM = "y";
|
||||
PWM_MEDIATEK = "y";
|
||||
PWM_SYSFS = "y";
|
||||
QUEUED_RWLOCKS = "y";
|
||||
QUEUED_SPINLOCKS = "y";
|
||||
RANDSTRUCT_NONE = "y";
|
||||
RAS = "y";
|
||||
RATIONAL = "y";
|
||||
REALTEK_PHY = "y";
|
||||
REED_SOLOMON = "y";
|
||||
REED_SOLOMON_DEC8 = "y";
|
||||
REED_SOLOMON_ENC8 = "y";
|
||||
REGMAP = "y";
|
||||
REGMAP_I2C = "y";
|
||||
REGMAP_MMIO = "y";
|
||||
REGULATOR = "y";
|
||||
REGULATOR_FIXED_VOLTAGE = "y";
|
||||
REGULATOR_MT6380 = "y";
|
||||
REGULATOR_RT5190A = "y";
|
||||
RESET_CONTROLLER = "y";
|
||||
RESET_TI_SYSCON = "y";
|
||||
RFS_ACCEL = "y";
|
||||
RODATA_FULL_DEFAULT_ENABLED = "y";
|
||||
RPS = "y";
|
||||
RTC_CLASS = "y";
|
||||
RTC_DRV_MT7622 = "y";
|
||||
RTC_I2C_AND_SPI = "y";
|
||||
RWSEM_SPIN_ON_OWNER = "y";
|
||||
SCHED_MC = "y";
|
||||
SCSI = "y";
|
||||
SCSI_COMMON = "y";
|
||||
SERIAL_8250_FSL = "y";
|
||||
SERIAL_8250_MT6577 = "y";
|
||||
SERIAL_8250_NR_UARTS = "3";
|
||||
SERIAL_8250_RUNTIME_UARTS = "3";
|
||||
SERIAL_DEV_BUS = "y";
|
||||
SERIAL_DEV_CTRL_TTYPORT = "y";
|
||||
SERIAL_MCTRL_GPIO = "y";
|
||||
SERIAL_OF_PLATFORM = "y";
|
||||
SGL_ALLOC = "y";
|
||||
SG_POOL = "y";
|
||||
SMP = "y";
|
||||
SOCK_RX_QUEUE_MAPPING = "y";
|
||||
SOFTIRQ_ON_OWN_STACK = "y";
|
||||
SPARSEMEM = "y";
|
||||
SPARSEMEM_EXTREME = "y";
|
||||
SPARSEMEM_VMEMMAP = "y";
|
||||
SPARSEMEM_VMEMMAP_ENABLE = "y";
|
||||
SPARSE_IRQ = "y";
|
||||
SPI = "y";
|
||||
SPI_DYNAMIC = "y";
|
||||
SPI_MASTER = "y";
|
||||
SPI_MEM = "y";
|
||||
SPI_MT65XX = "y";
|
||||
SPI_MTK_SNFI = "y";
|
||||
#SQUASHFS_DECOMP_MULTI_PERCPU="y";
|
||||
SWIOTLB = "y";
|
||||
SWPHY = "y";
|
||||
SYSCTL_EXCEPTION_TRACE = "y";
|
||||
THERMAL = "y";
|
||||
THERMAL_DEFAULT_GOV_STEP_WISE = "y";
|
||||
THERMAL_EMERGENCY_POWEROFF_DELAY_MS = "0";
|
||||
THERMAL_GOV_BANG_BANG = "y";
|
||||
THERMAL_GOV_FAIR_SHARE = "y";
|
||||
THERMAL_GOV_STEP_WISE = "y";
|
||||
THERMAL_GOV_USER_SPACE = "y";
|
||||
THERMAL_HWMON = "y";
|
||||
THERMAL_OF = "y";
|
||||
THERMAL_WRITABLE_TRIPS = "y";
|
||||
THREAD_INFO_IN_TASK = "y";
|
||||
TICK_CPU_ACCOUNTING = "y";
|
||||
TIMER_OF = "y";
|
||||
TIMER_PROBE = "y";
|
||||
TRACE_IRQFLAGS_NMI_SUPPORT = "y";
|
||||
TREE_RCU = "y";
|
||||
TREE_SRCU = "y";
|
||||
UBIFS_FS = "y";
|
||||
UIMAGE_FIT_BLK = "y";
|
||||
USB_SUPPORT = "y";
|
||||
VMAP_STACK = "y";
|
||||
WATCHDOG_CORE = "y";
|
||||
WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC = "y";
|
||||
WATCHDOG_PRETIMEOUT_GOV = "y";
|
||||
WATCHDOG_PRETIMEOUT_GOV_PANIC = "y";
|
||||
WATCHDOG_PRETIMEOUT_GOV_SEL = "m";
|
||||
WATCHDOG_SYSFS = "y";
|
||||
XPS = "y";
|
||||
XXHASH = "y";
|
||||
ZLIB_DEFLATE = "y";
|
||||
ZLIB_INFLATE = "y";
|
||||
ZONE_DMA32 = "y";
|
||||
ZSTD_COMMON = "y";
|
||||
ZSTD_COMPRESS = "y";
|
||||
ZSTD_DECOMPRESS = "y";
|
||||
# from DEVICE_PACKAGES in the openwrt_one section of
|
||||
# openwrt's ./target/linux/mediatek/image/filogic.mk:
|
||||
# chop off the 'kmod-' prefix and search for 'KernelPackage/...'
|
||||
# in ./package/kernel/linux/modules/*.mk, and remember to add
|
||||
# modules to kmodloader targets below
|
||||
AIR_EN8811H_PHY = "m";
|
||||
RTC_DRV_PCF8563 = "m";
|
||||
NVME_CORE = "m";
|
||||
BLK_DEV_NVME = "m";
|
||||
NVME_MULTIPATH = "n";
|
||||
NVME_HWMON = "y";
|
||||
# ???
|
||||
AQUANTIA_PHY = "m";
|
||||
MT798X_WMAC = "y";
|
||||
}
|
||||
// lib.optionalAttrs (config.system.service ? watchdog) {
|
||||
RALINK_WDT = "y"; # watchdog
|
||||
MT7621_WDT = "y"; # or it might be this one
|
||||
};
|
||||
conditionalConfig = {
|
||||
WLAN = {
|
||||
MT7915E = "m";
|
||||
};
|
||||
};
|
||||
};
|
||||
boot = {
|
||||
commandLine = [ "console=ttyS0,115200" ];
|
||||
tftp = {
|
||||
# Should be a segment of free RAM, where the tftp artifact
|
||||
# can be stored before unpacking it to the 'hardware.loadAddress'
|
||||
# The 'hardware.loadAddress' is 0x44000000, and the bootlog
|
||||
# suggests it loads the fit to 0x46000000
|
||||
loadAddress = lim.parseInt "0x46000000";
|
||||
};
|
||||
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 mediatek-firmware;
|
||||
airoha = symlink airoha-firmware;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hardware =
|
||||
let
|
||||
phy = pkgs.kmodloader.override {
|
||||
targets = [
|
||||
"air_en8811h"
|
||||
];
|
||||
inherit (config.system.outputs) kernel;
|
||||
};
|
||||
mac80211 = pkgs.kmodloader.override {
|
||||
targets = [
|
||||
"mt7915e"
|
||||
"rtc-pcf8563"
|
||||
"nvme_core"
|
||||
"nvme"
|
||||
#"mt7996e"
|
||||
"aquantia"
|
||||
];
|
||||
inherit (config.system.outputs) kernel;
|
||||
};
|
||||
in
|
||||
{
|
||||
# from OEM bootlog
|
||||
# Creating 4 MTD partitions on "spi0.0":
|
||||
# 0x000000000000-0x000000040000 : "bl2-nor"
|
||||
# 0x000000040000-0x000000100000 : "factory"
|
||||
# 0x000000100000-0x000000180000 : "fip-nor"
|
||||
# 0x000000180000-0x000000e00000 : "recovery"
|
||||
# spi-nand spi1.1: calibration result: 0x3
|
||||
# spi-nand spi1.1: Winbond SPI NAND was found.
|
||||
# spi-nand spi1.1: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
|
||||
# 2 fixed-partitions partitions found on MTD device spi1.1
|
||||
# Creating 2 MTD partitions on "spi1.1":
|
||||
# 0x000000000000-0x000000100000 : "bl2"
|
||||
# 0x000000100000-0x000010000000 : "ubi"
|
||||
|
||||
flash = {
|
||||
# from the OEM bootlog:
|
||||
# ## Checking Image at 46000000 ...
|
||||
# FIT image found
|
||||
# FIT description: ARM64 OpenWrt FIT (Flattened Image Tree)
|
||||
# Image 0 (kernel-1)
|
||||
# Description: ARM64 OpenWrt Linux-6.6.57
|
||||
# Type: Kernel Image
|
||||
# Compression: gzip compressed
|
||||
# Data Start: 0x46001000
|
||||
# Data Size: 5751840 Bytes = 5.5 MiB
|
||||
# Architecture: AArch64
|
||||
# OS: Linux
|
||||
# Load Address: 0x44000000
|
||||
# Entry Point: 0x44000000
|
||||
|
||||
address = lim.parseInt "0x44000000";
|
||||
size = lim.parseInt "0xf60000";
|
||||
# /proc/mtd on a running system:
|
||||
# dev: size erasesize name
|
||||
# mtd0: 00040000 00010000 "bl2-nor"
|
||||
# mtd1: 000c0000 00010000 "factory"
|
||||
# mtd2: 00080000 00010000 "fip-nor"
|
||||
# mtd3: 00c80000 00010000 "recovery"
|
||||
# mtd4: 00100000 00020000 "bl2"
|
||||
# mtd5: 0ff00000 00020000 "ubi"
|
||||
eraseBlockSize = 65536;
|
||||
};
|
||||
ubi = {
|
||||
# TODO taken from belkin-rt3200, to review
|
||||
minIOSize = "2048";
|
||||
logicalEraseBlockSize = "126976";
|
||||
physicalEraseBlockSize = "131072";
|
||||
maxLEBcount = "1024"; # guessing
|
||||
};
|
||||
|
||||
defaultOutput = "ubimage";
|
||||
loadAddress = lim.parseInt "0x44000000";
|
||||
entryPoint = lim.parseInt "0x44000000";
|
||||
# TODO AFAICT this should be 2048, but I got 'FIT: image rootfs-1 start not aligned to page boundaries' with that...
|
||||
#alignment = 2048;
|
||||
alignment = 4096;
|
||||
rootDevice = "ubi0:liminix";
|
||||
dts = {
|
||||
src = "${openwrt.src}/target/linux/mediatek/dts/mt7981b-openwrt-one.dts";
|
||||
includePaths = [
|
||||
"${openwrt.src}/target/linux/mediatek/dts"
|
||||
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
|
||||
];
|
||||
};
|
||||
|
||||
networkInterfaces =
|
||||
let
|
||||
inherit (config.system.service.network) link;
|
||||
in
|
||||
rec {
|
||||
eth0 = link.build {
|
||||
ifname = "eth0";
|
||||
dependencies = [ phy ];
|
||||
};
|
||||
eth1 = link.build { ifname = "eth1"; };
|
||||
|
||||
wlan0 = link.build {
|
||||
ifname = "wlan0";
|
||||
dependencies = [ mac80211 ];
|
||||
};
|
||||
wlan1 = link.build {
|
||||
ifname = "wlan1";
|
||||
dependencies = [ mac80211 ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -19,33 +19,39 @@
|
||||
ARM targets differ from MIPS in that the kernel format expected
|
||||
by QEMU is an "Image" (raw binary file) rather than an ELF
|
||||
file, but this is taken care of by :command:`run.sh`. Check the
|
||||
documentation for the :ref:`QEMU` (MIPS) target for more information.
|
||||
documentation for the :ref:`qemu` target for more information.
|
||||
|
||||
'';
|
||||
|
||||
# this device is described by the "qemu" device
|
||||
installer = "vmroot";
|
||||
|
||||
module = { config, lim, ... }: {
|
||||
imports = [
|
||||
../../modules/arch/aarch64.nix
|
||||
../families/qemu.nix
|
||||
];
|
||||
kernel = {
|
||||
config = {
|
||||
VIRTUALIZATION = "y";
|
||||
PCI_HOST_GENERIC="y";
|
||||
module =
|
||||
{ config, lim, ... }:
|
||||
{
|
||||
imports = [
|
||||
../../modules/arch/aarch64.nix
|
||||
../families/qemu.nix
|
||||
];
|
||||
kernel = {
|
||||
config = {
|
||||
VIRTUALIZATION = "y";
|
||||
PCI_HOST_GENERIC = "y";
|
||||
|
||||
SERIAL_AMBA_PL011 = "y";
|
||||
SERIAL_AMBA_PL011_CONSOLE = "y";
|
||||
SERIAL_AMBA_PL011 = "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;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{
|
||||
system = {
|
||||
crossSystem = {
|
||||
config = "armv7l-unknown-linux-musleabihf";
|
||||
config = "armv7l-unknown-linux-musleabihf";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -24,30 +24,36 @@
|
||||
'';
|
||||
installer = "vmroot";
|
||||
|
||||
module = { config, lim, ... }: {
|
||||
imports = [
|
||||
../../modules/arch/arm.nix
|
||||
../families/qemu.nix
|
||||
];
|
||||
kernel = {
|
||||
config = {
|
||||
PCI_HOST_GENERIC = "y";
|
||||
ARCH_VIRT = "y";
|
||||
module =
|
||||
{ config, lim, ... }:
|
||||
{
|
||||
imports = [
|
||||
../../modules/arch/arm.nix
|
||||
../families/qemu.nix
|
||||
];
|
||||
kernel = {
|
||||
config = {
|
||||
PCI_HOST_GENERIC = "y";
|
||||
ARCH_VIRT = "y";
|
||||
|
||||
VFP = "y";
|
||||
NEON = "y";
|
||||
AEABI = "y";
|
||||
VFP = "y";
|
||||
NEON = "y";
|
||||
AEABI = "y";
|
||||
|
||||
SERIAL_AMBA_PL011 = "y";
|
||||
SERIAL_AMBA_PL011_CONSOLE = "y";
|
||||
SERIAL_AMBA_PL011 = "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;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
+43
-34
@@ -7,7 +7,7 @@
|
||||
config = "mips-unknown-linux-musl";
|
||||
gcc = {
|
||||
abi = "32";
|
||||
arch = "mips32"; # maybe mips_24kc-
|
||||
arch = "mips32"; # maybe mips_24kc-
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -36,41 +36,50 @@
|
||||
in the Development manual.
|
||||
|
||||
'';
|
||||
module = { config, lib, lim, ... }: {
|
||||
imports = [
|
||||
../../modules/arch/mipseb.nix
|
||||
../families/qemu.nix
|
||||
];
|
||||
kernel = {
|
||||
config = {
|
||||
MIPS_MALTA= "y";
|
||||
CPU_MIPS32_R2= "y";
|
||||
module =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
lim,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
../../modules/arch/mipseb.nix
|
||||
../families/qemu.nix
|
||||
];
|
||||
kernel = {
|
||||
config = {
|
||||
MIPS_MALTA = "y";
|
||||
CPU_MIPS32_R2 = "y";
|
||||
|
||||
POWER_RESET = "y";
|
||||
POWER_RESET_SYSCON = "y";
|
||||
POWER_RESET = "y";
|
||||
POWER_RESET_SYSCON = "y";
|
||||
|
||||
SERIAL_8250= "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";
|
||||
includes = [
|
||||
"${config.system.outputs.kernel.modulesupport}/arch/mips/boot/dts/"
|
||||
];
|
||||
SERIAL_8250 = "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/"
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
+381
-372
@@ -33,16 +33,25 @@
|
||||
};
|
||||
};
|
||||
|
||||
module = {pkgs, config, lib, lim, ... }:
|
||||
let firmware = pkgs.stdenv.mkDerivation {
|
||||
name = "wlan-firmware";
|
||||
phases = ["installPhase"];
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out
|
||||
'';
|
||||
};
|
||||
in {
|
||||
module =
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
lim,
|
||||
...
|
||||
}:
|
||||
let
|
||||
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 = [
|
||||
../../modules/arch/mipsel.nix
|
||||
../../modules/outputs/tftpboot.nix
|
||||
@@ -50,281 +59,278 @@
|
||||
];
|
||||
config = {
|
||||
kernel = {
|
||||
src = pkgs.pkgsBuildBuild.fetchurl {
|
||||
name = "linux.tar.gz";
|
||||
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.gz";
|
||||
hash = "sha256-PkdzUKZ0IpBiWe/RS70J76JKnBFzRblWcKlaIFNxnHQ=";
|
||||
};
|
||||
extraPatchPhase = ''
|
||||
${pkgs.openwrt.applyPatches.ramips}
|
||||
'';
|
||||
config = {
|
||||
# Initially taken from openwrt's ./target/linux/ramips/mt7621/config-5.15,
|
||||
# then tweaked here and there
|
||||
ARCH_32BIT_OFF_T="y";
|
||||
ARCH_HIBERNATION_POSSIBLE="y";
|
||||
ARCH_KEEP_MEMBLOCK="y";
|
||||
ARCH_MMAP_RND_BITS_MAX="15";
|
||||
ARCH_MMAP_RND_COMPAT_BITS_MAX="15";
|
||||
ARCH_SUSPEND_POSSIBLE="y";
|
||||
AT803X_PHY="y";
|
||||
BLK_MQ_PCI="y";
|
||||
BOARD_SCACHE="y";
|
||||
CEVT_R4K="y";
|
||||
CLKSRC_MIPS_GIC="y";
|
||||
CLK_MT7621="y";
|
||||
CLOCKSOURCE_WATCHDOG="y";
|
||||
CLONE_BACKWARDS="y";
|
||||
CMDLINE_BOOL="y";
|
||||
COMMON_CLK="y";
|
||||
COMPAT_32BIT_TIME="y";
|
||||
CPU_GENERIC_DUMP_TLB="y";
|
||||
CPU_HAS_DIEI="y";
|
||||
CPU_HAS_PREFETCH="y";
|
||||
CPU_HAS_RIXI="y";
|
||||
CPU_HAS_SYNC="y";
|
||||
CPU_LITTLE_ENDIAN="y";
|
||||
CPU_MIPS32="y";
|
||||
CPU_MIPS32_R2="y";
|
||||
CPU_MIPSR2="y";
|
||||
CPU_MIPSR2_IRQ_EI="y";
|
||||
CPU_MIPSR2_IRQ_VI="y";
|
||||
CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS="y";
|
||||
CPU_R4K_CACHE_TLB="y";
|
||||
CPU_RMAP="y";
|
||||
CPU_SUPPORTS_32BIT_KERNEL="y";
|
||||
CPU_SUPPORTS_HIGHMEM="y";
|
||||
CPU_SUPPORTS_MSA="y";
|
||||
CRC16="y";
|
||||
CRYPTO_DEFLATE="y";
|
||||
CRYPTO_HASH_INFO="y";
|
||||
CRYPTO_LIB_BLAKE2S_GENERIC="y";
|
||||
CRYPTO_LIB_POLY1305_RSIZE="2";
|
||||
CRYPTO_LZO="y";
|
||||
CRYPTO_ZSTD="y";
|
||||
CSRC_R4K="y";
|
||||
DIMLIB="y";
|
||||
DMA_NONCOHERENT="y";
|
||||
DTB_RT_NONE="y";
|
||||
DTC="y";
|
||||
EARLY_PRINTK="y";
|
||||
FIXED_PHY="y";
|
||||
FWNODE_MDIO="y";
|
||||
FW_LOADER_PAGED_BUF="y";
|
||||
GENERIC_ATOMIC64="y";
|
||||
GENERIC_CLOCKEVENTS="y";
|
||||
GENERIC_CMOS_UPDATE="y";
|
||||
GENERIC_CPU_AUTOPROBE="y";
|
||||
GENERIC_FIND_FIRST_BIT="y";
|
||||
GENERIC_GETTIMEOFDAY="y";
|
||||
GENERIC_IOMAP="y";
|
||||
GENERIC_IRQ_CHIP="y";
|
||||
GENERIC_IRQ_EFFECTIVE_AFF_MASK="y";
|
||||
GENERIC_IRQ_SHOW="y";
|
||||
GENERIC_LIB_ASHLDI3="y";
|
||||
GENERIC_LIB_ASHRDI3="y";
|
||||
GENERIC_LIB_CMPDI2="y";
|
||||
GENERIC_LIB_LSHRDI3="y";
|
||||
GENERIC_LIB_UCMPDI2="y";
|
||||
GENERIC_PCI_IOMAP="y";
|
||||
GENERIC_PHY="y";
|
||||
GENERIC_PINCONF="y";
|
||||
GENERIC_SCHED_CLOCK="y";
|
||||
GENERIC_SMP_IDLE_THREAD="y";
|
||||
GENERIC_TIME_VSYSCALL="y";
|
||||
GLOB="y";
|
||||
GPIOLIB_IRQCHIP="y";
|
||||
GPIO_CDEV="y";
|
||||
GPIO_GENERIC="y";
|
||||
GPIO_MT7621="y";
|
||||
GRO_CELLS="y";
|
||||
HANDLE_DOMAIN_IRQ="y";
|
||||
HARDWARE_WATCHPOINTS="y";
|
||||
HAS_DMA="y";
|
||||
HAS_IOMEM="y";
|
||||
HAS_IOPORT_MAP="y";
|
||||
I2C="y";
|
||||
I2C_ALGOBIT="y";
|
||||
I2C_BOARDINFO="y";
|
||||
I2C_CHARDEV="y";
|
||||
I2C_GPIO="y";
|
||||
I2C_MT7621="y";
|
||||
ICPLUS_PHY="y";
|
||||
IRQCHIP="y";
|
||||
IRQ_DOMAIN="y";
|
||||
IRQ_DOMAIN_HIERARCHY="y";
|
||||
IRQ_FORCED_THREADING="y";
|
||||
IRQ_MIPS_CPU="y";
|
||||
IRQ_WORK="y";
|
||||
LIBFDT="y";
|
||||
LOCK_DEBUGGING_SUPPORT="y";
|
||||
LZO_COMPRESS="y";
|
||||
LZO_DECOMPRESS="y";
|
||||
MDIO_BUS="y";
|
||||
MDIO_DEVICE="y";
|
||||
MDIO_DEVRES="y";
|
||||
MEDIATEK_GE_PHY="y";
|
||||
MEMFD_CREATE="y";
|
||||
MFD_SYSCON="y";
|
||||
MIGRATION="y";
|
||||
MIKROTIK="y";
|
||||
MIKROTIK_RB_SYSFS="y";
|
||||
MIPS="y";
|
||||
MIPS_ASID_BITS="8";
|
||||
MIPS_ASID_SHIFT="0";
|
||||
MIPS_CLOCK_VSYSCALL="y";
|
||||
MIPS_CM="y";
|
||||
MIPS_CPC="y";
|
||||
MIPS_CPS="y";
|
||||
MIPS_CPU_SCACHE="y";
|
||||
MIPS_GIC="y";
|
||||
MIPS_L1_CACHE_SHIFT="5";
|
||||
MIPS_LD_CAN_LINK_VDSO="y";
|
||||
MIPS_MT="y";
|
||||
MIPS_MT_FPAFF="y";
|
||||
MIPS_MT_SMP="y";
|
||||
MIPS_NR_CPU_NR_MAP="4";
|
||||
MIPS_PERF_SHARED_TC_COUNTERS="y";
|
||||
MIPS_SPRAM="y";
|
||||
MODULES_USE_ELF_REL="y";
|
||||
MTD_CMDLINE_PARTS="y";
|
||||
MTD_NAND_CORE="y";
|
||||
MTD_NAND_ECC="y";
|
||||
MTD_NAND_ECC_SW_HAMMING="y";
|
||||
MTD_NAND_MT7621="y";
|
||||
MTD_NAND_MTK_BMT="y";
|
||||
MTD_RAW_NAND="y";
|
||||
MTD_ROUTERBOOT_PARTS="y";
|
||||
MTD_SERCOMM_PARTS="y";
|
||||
MTD_SPI_NOR="y";
|
||||
MTD_SPLIT_FIT_FW="y";
|
||||
MTD_SPLIT_MINOR_FW="y";
|
||||
MTD_SPLIT_SEAMA_FW="y";
|
||||
MTD_SPLIT_TPLINK_FW="y";
|
||||
MTD_SPLIT_TRX_FW="y";
|
||||
MTD_SPLIT_UIMAGE_FW="y";
|
||||
MTD_UBI="y";
|
||||
MTD_UBI_BEB_LIMIT="20";
|
||||
MTD_UBI_BLOCK="y";
|
||||
MTD_UBI_WL_THRESHOLD="4096";
|
||||
MTD_VIRT_CONCAT="y";
|
||||
NEED_DMA_MAP_STATE="y";
|
||||
NET_DEVLINK="y";
|
||||
NET_DSA="y";
|
||||
NET_DSA_MT7530="y";
|
||||
NET_DSA_MT7530_MDIO="y";
|
||||
NET_DSA_TAG_MTK="y";
|
||||
NET_FLOW_LIMIT="y";
|
||||
NET_MEDIATEK_SOC="y";
|
||||
NET_SELFTESTS="y";
|
||||
NET_SWITCHDEV="y";
|
||||
NET_VENDOR_MEDIATEK="y";
|
||||
NO_HZ_COMMON="y";
|
||||
NO_HZ_IDLE="y";
|
||||
NR_CPUS="4";
|
||||
NVMEM="y";
|
||||
OF="y";
|
||||
OF_ADDRESS="y";
|
||||
OF_EARLY_FLATTREE="y";
|
||||
OF_FLATTREE="y";
|
||||
OF_GPIO="y";
|
||||
OF_IRQ="y";
|
||||
OF_KOBJ="y";
|
||||
OF_MDIO="y";
|
||||
PAGE_POOL="y";
|
||||
PAGE_POOL_STATS="y";
|
||||
PCI="y";
|
||||
PCIE_MT7621="y";
|
||||
PCI_DISABLE_COMMON_QUIRKS="y";
|
||||
PCI_DOMAINS="y";
|
||||
PCI_DOMAINS_GENERIC="y";
|
||||
PCI_DRIVERS_GENERIC="y";
|
||||
PCS_MTK_LYNXI="y";
|
||||
PERF_USE_VMALLOC="y";
|
||||
PGTABLE_LEVELS="2";
|
||||
PHYLIB="y";
|
||||
PHYLINK="y";
|
||||
PHY_MT7621_PCI="y";
|
||||
PINCTRL="y";
|
||||
PINCTRL_AW9523="y";
|
||||
PINCTRL_MT7621="y";
|
||||
PINCTRL_RALINK="y";
|
||||
PINCTRL_SX150X="y";
|
||||
POWER_RESET="y";
|
||||
POWER_RESET_GPIO="y";
|
||||
POWER_SUPPLY="y";
|
||||
PTP_1588_CLOCK_OPTIONAL="y";
|
||||
QUEUED_RWLOCKS="y";
|
||||
QUEUED_SPINLOCKS="y";
|
||||
RALINK="y";
|
||||
RATIONAL="y";
|
||||
REGMAP="y";
|
||||
REGMAP_I2C="y";
|
||||
REGMAP_MMIO="y";
|
||||
REGULATOR="y";
|
||||
REGULATOR_FIXED_VOLTAGE="y";
|
||||
RESET_CONTROLLER="y";
|
||||
RFS_ACCEL="y";
|
||||
RPS="y";
|
||||
RTC_CLASS="y";
|
||||
RTC_DRV_BQ32K="y";
|
||||
RTC_DRV_PCF8563="y";
|
||||
RTC_I2C_AND_SPI="y";
|
||||
SCHED_SMT="y";
|
||||
SERIAL_8250="y";
|
||||
SERIAL_8250_CONSOLE="y";
|
||||
SERIAL_8250_NR_UARTS="3";
|
||||
SERIAL_8250_RUNTIME_UARTS="3";
|
||||
SERIAL_MCTRL_GPIO="y";
|
||||
SERIAL_OF_PLATFORM="y";
|
||||
SGL_ALLOC="y";
|
||||
SMP="y";
|
||||
SMP_UP="y";
|
||||
SOCK_RX_QUEUE_MAPPING="y";
|
||||
SOC_BUS="y";
|
||||
SOC_MT7621="y";
|
||||
SPI="y";
|
||||
SPI_MASTER="y";
|
||||
SPI_MEM="y";
|
||||
SPI_MT7621="y";
|
||||
SRCU="y";
|
||||
SWPHY="y";
|
||||
SYNC_R4K="y";
|
||||
SYSCTL_EXCEPTION_TRACE="y";
|
||||
SYS_HAS_CPU_MIPS32_R1="y";
|
||||
SYS_HAS_CPU_MIPS32_R2="y";
|
||||
SYS_HAS_EARLY_PRINTK="y";
|
||||
SYS_SUPPORTS_32BIT_KERNEL="y";
|
||||
SYS_SUPPORTS_ARBIT_HZ="y";
|
||||
SYS_SUPPORTS_HIGHMEM="y";
|
||||
SYS_SUPPORTS_HOTPLUG_CPU="y";
|
||||
SYS_SUPPORTS_LITTLE_ENDIAN="y";
|
||||
SYS_SUPPORTS_MIPS16="y";
|
||||
SYS_SUPPORTS_MIPS_CPS="y";
|
||||
SYS_SUPPORTS_MULTITHREADING="y";
|
||||
SYS_SUPPORTS_SCHED_SMT="y";
|
||||
SYS_SUPPORTS_SMP="y";
|
||||
SYS_SUPPORTS_ZBOOT="y";
|
||||
TARGET_ISA_REV="2";
|
||||
TICK_CPU_ACCOUNTING="y";
|
||||
TIMER_OF="y";
|
||||
TIMER_PROBE="y";
|
||||
TREE_RCU="y";
|
||||
TREE_SRCU="y";
|
||||
UBIFS_FS="y";
|
||||
USB_SUPPORT="y";
|
||||
USE_OF="y";
|
||||
WEAK_ORDERING="y";
|
||||
XPS="y";
|
||||
XXHASH="y";
|
||||
ZLIB_DEFLATE="y";
|
||||
ZLIB_INFLATE="y";
|
||||
ZSTD_COMPRESS="y";
|
||||
ZSTD_DECOMPRESS="y";
|
||||
} // lib.optionalAttrs (config.system.service ? watchdog) {
|
||||
RALINK_WDT = "y"; # watchdog
|
||||
MT7621_WDT = "y"; # or it might be this one
|
||||
};
|
||||
config =
|
||||
{
|
||||
# Initially taken from openwrt's ./target/linux/ramips/mt7621/config-5.15,
|
||||
# then tweaked here and there
|
||||
ARCH_32BIT_OFF_T = "y";
|
||||
ARCH_HIBERNATION_POSSIBLE = "y";
|
||||
ARCH_KEEP_MEMBLOCK = "y";
|
||||
ARCH_MMAP_RND_BITS_MAX = "15";
|
||||
ARCH_MMAP_RND_COMPAT_BITS_MAX = "15";
|
||||
ARCH_SUSPEND_POSSIBLE = "y";
|
||||
AT803X_PHY = "y";
|
||||
BLK_MQ_PCI = "y";
|
||||
BOARD_SCACHE = "y";
|
||||
CEVT_R4K = "y";
|
||||
CLKSRC_MIPS_GIC = "y";
|
||||
CLK_MT7621 = "y";
|
||||
CLOCKSOURCE_WATCHDOG = "y";
|
||||
CLONE_BACKWARDS = "y";
|
||||
CMDLINE_BOOL = "y";
|
||||
COMMON_CLK = "y";
|
||||
COMPAT_32BIT_TIME = "y";
|
||||
CPU_GENERIC_DUMP_TLB = "y";
|
||||
CPU_HAS_DIEI = "y";
|
||||
CPU_HAS_PREFETCH = "y";
|
||||
CPU_HAS_RIXI = "y";
|
||||
CPU_HAS_SYNC = "y";
|
||||
CPU_LITTLE_ENDIAN = "y";
|
||||
CPU_MIPS32 = "y";
|
||||
CPU_MIPS32_R2 = "y";
|
||||
CPU_MIPSR2 = "y";
|
||||
CPU_MIPSR2_IRQ_EI = "y";
|
||||
CPU_MIPSR2_IRQ_VI = "y";
|
||||
CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS = "y";
|
||||
CPU_R4K_CACHE_TLB = "y";
|
||||
CPU_RMAP = "y";
|
||||
CPU_SUPPORTS_32BIT_KERNEL = "y";
|
||||
CPU_SUPPORTS_HIGHMEM = "y";
|
||||
CPU_SUPPORTS_MSA = "y";
|
||||
CRC16 = "y";
|
||||
CRYPTO_DEFLATE = "y";
|
||||
CRYPTO_HASH_INFO = "y";
|
||||
CRYPTO_LIB_BLAKE2S_GENERIC = "y";
|
||||
CRYPTO_LIB_POLY1305_RSIZE = "2";
|
||||
CRYPTO_LZO = "y";
|
||||
CRYPTO_ZSTD = "y";
|
||||
CSRC_R4K = "y";
|
||||
DIMLIB = "y";
|
||||
DMA_NONCOHERENT = "y";
|
||||
DTB_RT_NONE = "y";
|
||||
DTC = "y";
|
||||
EARLY_PRINTK = "y";
|
||||
FIXED_PHY = "y";
|
||||
FWNODE_MDIO = "y";
|
||||
FW_LOADER_PAGED_BUF = "y";
|
||||
GENERIC_ATOMIC64 = "y";
|
||||
GENERIC_CLOCKEVENTS = "y";
|
||||
GENERIC_CMOS_UPDATE = "y";
|
||||
GENERIC_CPU_AUTOPROBE = "y";
|
||||
GENERIC_FIND_FIRST_BIT = "y";
|
||||
GENERIC_GETTIMEOFDAY = "y";
|
||||
GENERIC_IOMAP = "y";
|
||||
GENERIC_IRQ_CHIP = "y";
|
||||
GENERIC_IRQ_EFFECTIVE_AFF_MASK = "y";
|
||||
GENERIC_IRQ_SHOW = "y";
|
||||
GENERIC_LIB_ASHLDI3 = "y";
|
||||
GENERIC_LIB_ASHRDI3 = "y";
|
||||
GENERIC_LIB_CMPDI2 = "y";
|
||||
GENERIC_LIB_LSHRDI3 = "y";
|
||||
GENERIC_LIB_UCMPDI2 = "y";
|
||||
GENERIC_PCI_IOMAP = "y";
|
||||
GENERIC_PHY = "y";
|
||||
GENERIC_PINCONF = "y";
|
||||
GENERIC_SCHED_CLOCK = "y";
|
||||
GENERIC_SMP_IDLE_THREAD = "y";
|
||||
GENERIC_TIME_VSYSCALL = "y";
|
||||
GLOB = "y";
|
||||
GPIOLIB_IRQCHIP = "y";
|
||||
GPIO_CDEV = "y";
|
||||
GPIO_GENERIC = "y";
|
||||
GPIO_MT7621 = "y";
|
||||
GRO_CELLS = "y";
|
||||
HANDLE_DOMAIN_IRQ = "y";
|
||||
HARDWARE_WATCHPOINTS = "y";
|
||||
HAS_DMA = "y";
|
||||
HAS_IOMEM = "y";
|
||||
HAS_IOPORT_MAP = "y";
|
||||
I2C = "y";
|
||||
I2C_ALGOBIT = "y";
|
||||
I2C_BOARDINFO = "y";
|
||||
I2C_CHARDEV = "y";
|
||||
I2C_GPIO = "y";
|
||||
I2C_MT7621 = "y";
|
||||
ICPLUS_PHY = "y";
|
||||
IRQCHIP = "y";
|
||||
IRQ_DOMAIN = "y";
|
||||
IRQ_DOMAIN_HIERARCHY = "y";
|
||||
IRQ_FORCED_THREADING = "y";
|
||||
IRQ_MIPS_CPU = "y";
|
||||
IRQ_WORK = "y";
|
||||
LIBFDT = "y";
|
||||
LOCK_DEBUGGING_SUPPORT = "y";
|
||||
LZO_COMPRESS = "y";
|
||||
LZO_DECOMPRESS = "y";
|
||||
MDIO_BUS = "y";
|
||||
MDIO_DEVICE = "y";
|
||||
MDIO_DEVRES = "y";
|
||||
MEDIATEK_GE_PHY = "y";
|
||||
MEMFD_CREATE = "y";
|
||||
MFD_SYSCON = "y";
|
||||
MIGRATION = "y";
|
||||
MIKROTIK = "y";
|
||||
MIKROTIK_RB_SYSFS = "y";
|
||||
MIPS = "y";
|
||||
MIPS_ASID_BITS = "8";
|
||||
MIPS_ASID_SHIFT = "0";
|
||||
MIPS_CLOCK_VSYSCALL = "y";
|
||||
MIPS_CM = "y";
|
||||
MIPS_CPC = "y";
|
||||
MIPS_CPS = "y";
|
||||
MIPS_CPU_SCACHE = "y";
|
||||
MIPS_GIC = "y";
|
||||
MIPS_L1_CACHE_SHIFT = "5";
|
||||
MIPS_LD_CAN_LINK_VDSO = "y";
|
||||
MIPS_MT = "y";
|
||||
MIPS_MT_FPAFF = "y";
|
||||
MIPS_MT_SMP = "y";
|
||||
MIPS_NR_CPU_NR_MAP = "4";
|
||||
MIPS_PERF_SHARED_TC_COUNTERS = "y";
|
||||
MIPS_SPRAM = "y";
|
||||
MODULES_USE_ELF_REL = "y";
|
||||
MTD_CMDLINE_PARTS = "y";
|
||||
MTD_NAND_CORE = "y";
|
||||
MTD_NAND_ECC = "y";
|
||||
MTD_NAND_ECC_SW_HAMMING = "y";
|
||||
MTD_NAND_MT7621 = "y";
|
||||
MTD_NAND_MTK_BMT = "y";
|
||||
MTD_RAW_NAND = "y";
|
||||
MTD_ROUTERBOOT_PARTS = "y";
|
||||
MTD_SERCOMM_PARTS = "y";
|
||||
MTD_SPI_NOR = "y";
|
||||
MTD_SPLIT_FIT_FW = "y";
|
||||
MTD_SPLIT_MINOR_FW = "y";
|
||||
MTD_SPLIT_SEAMA_FW = "y";
|
||||
MTD_SPLIT_TPLINK_FW = "y";
|
||||
MTD_SPLIT_TRX_FW = "y";
|
||||
MTD_SPLIT_UIMAGE_FW = "y";
|
||||
MTD_UBI = "y";
|
||||
MTD_UBI_BEB_LIMIT = "20";
|
||||
MTD_UBI_BLOCK = "y";
|
||||
MTD_UBI_WL_THRESHOLD = "4096";
|
||||
MTD_VIRT_CONCAT = "y";
|
||||
NEED_DMA_MAP_STATE = "y";
|
||||
NET_DEVLINK = "y";
|
||||
NET_DSA = "y";
|
||||
NET_DSA_MT7530 = "y";
|
||||
NET_DSA_MT7530_MDIO = "y";
|
||||
NET_DSA_TAG_MTK = "y";
|
||||
NET_FLOW_LIMIT = "y";
|
||||
NET_MEDIATEK_SOC = "y";
|
||||
NET_SELFTESTS = "y";
|
||||
NET_SWITCHDEV = "y";
|
||||
NET_VENDOR_MEDIATEK = "y";
|
||||
NO_HZ_COMMON = "y";
|
||||
NO_HZ_IDLE = "y";
|
||||
NR_CPUS = "4";
|
||||
NVMEM = "y";
|
||||
OF = "y";
|
||||
OF_ADDRESS = "y";
|
||||
OF_EARLY_FLATTREE = "y";
|
||||
OF_FLATTREE = "y";
|
||||
OF_GPIO = "y";
|
||||
OF_IRQ = "y";
|
||||
OF_KOBJ = "y";
|
||||
OF_MDIO = "y";
|
||||
PAGE_POOL = "y";
|
||||
PAGE_POOL_STATS = "y";
|
||||
PCI = "y";
|
||||
PCIE_MT7621 = "y";
|
||||
PCI_DISABLE_COMMON_QUIRKS = "y";
|
||||
PCI_DOMAINS = "y";
|
||||
PCI_DOMAINS_GENERIC = "y";
|
||||
PCI_DRIVERS_GENERIC = "y";
|
||||
PCS_MTK_LYNXI = "y";
|
||||
PERF_USE_VMALLOC = "y";
|
||||
PGTABLE_LEVELS = "2";
|
||||
PHYLIB = "y";
|
||||
PHYLINK = "y";
|
||||
PHY_MT7621_PCI = "y";
|
||||
PINCTRL = "y";
|
||||
PINCTRL_AW9523 = "y";
|
||||
PINCTRL_MT7621 = "y";
|
||||
PINCTRL_RALINK = "y";
|
||||
PINCTRL_SX150X = "y";
|
||||
POWER_RESET = "y";
|
||||
POWER_RESET_GPIO = "y";
|
||||
POWER_SUPPLY = "y";
|
||||
PTP_1588_CLOCK_OPTIONAL = "y";
|
||||
QUEUED_RWLOCKS = "y";
|
||||
QUEUED_SPINLOCKS = "y";
|
||||
RALINK = "y";
|
||||
RATIONAL = "y";
|
||||
REGMAP = "y";
|
||||
REGMAP_I2C = "y";
|
||||
REGMAP_MMIO = "y";
|
||||
REGULATOR = "y";
|
||||
REGULATOR_FIXED_VOLTAGE = "y";
|
||||
RESET_CONTROLLER = "y";
|
||||
RFS_ACCEL = "y";
|
||||
RPS = "y";
|
||||
RTC_CLASS = "y";
|
||||
RTC_DRV_BQ32K = "y";
|
||||
RTC_DRV_PCF8563 = "y";
|
||||
RTC_I2C_AND_SPI = "y";
|
||||
SCHED_SMT = "y";
|
||||
SERIAL_8250 = "y";
|
||||
SERIAL_8250_CONSOLE = "y";
|
||||
SERIAL_8250_NR_UARTS = "3";
|
||||
SERIAL_8250_RUNTIME_UARTS = "3";
|
||||
SERIAL_MCTRL_GPIO = "y";
|
||||
SERIAL_OF_PLATFORM = "y";
|
||||
SGL_ALLOC = "y";
|
||||
SMP = "y";
|
||||
SMP_UP = "y";
|
||||
SOCK_RX_QUEUE_MAPPING = "y";
|
||||
SOC_BUS = "y";
|
||||
SOC_MT7621 = "y";
|
||||
SPI = "y";
|
||||
SPI_MASTER = "y";
|
||||
SPI_MEM = "y";
|
||||
SPI_MT7621 = "y";
|
||||
SRCU = "y";
|
||||
SWPHY = "y";
|
||||
SYNC_R4K = "y";
|
||||
SYSCTL_EXCEPTION_TRACE = "y";
|
||||
SYS_HAS_CPU_MIPS32_R1 = "y";
|
||||
SYS_HAS_CPU_MIPS32_R2 = "y";
|
||||
SYS_HAS_EARLY_PRINTK = "y";
|
||||
SYS_SUPPORTS_32BIT_KERNEL = "y";
|
||||
SYS_SUPPORTS_ARBIT_HZ = "y";
|
||||
SYS_SUPPORTS_HIGHMEM = "y";
|
||||
SYS_SUPPORTS_HOTPLUG_CPU = "y";
|
||||
SYS_SUPPORTS_LITTLE_ENDIAN = "y";
|
||||
SYS_SUPPORTS_MIPS16 = "y";
|
||||
SYS_SUPPORTS_MIPS_CPS = "y";
|
||||
SYS_SUPPORTS_MULTITHREADING = "y";
|
||||
SYS_SUPPORTS_SCHED_SMT = "y";
|
||||
SYS_SUPPORTS_SMP = "y";
|
||||
SYS_SUPPORTS_ZBOOT = "y";
|
||||
TARGET_ISA_REV = "2";
|
||||
TICK_CPU_ACCOUNTING = "y";
|
||||
TIMER_OF = "y";
|
||||
TIMER_PROBE = "y";
|
||||
TREE_RCU = "y";
|
||||
TREE_SRCU = "y";
|
||||
UBIFS_FS = "y";
|
||||
USB_SUPPORT = "y";
|
||||
USE_OF = "y";
|
||||
WEAK_ORDERING = "y";
|
||||
XPS = "y";
|
||||
XXHASH = "y";
|
||||
ZLIB_DEFLATE = "y";
|
||||
ZLIB_INFLATE = "y";
|
||||
ZSTD_COMPRESS = "y";
|
||||
ZSTD_DECOMPRESS = "y";
|
||||
}
|
||||
// lib.optionalAttrs (config.system.service ? watchdog) {
|
||||
RALINK_WDT = "y"; # watchdog
|
||||
MT7621_WDT = "y"; # or it might be this one
|
||||
};
|
||||
conditionalConfig = {
|
||||
WLAN = {
|
||||
MT7915E = "m";
|
||||
@@ -345,97 +351,100 @@
|
||||
};
|
||||
};
|
||||
filesystem =
|
||||
let inherit (pkgs.pseudofile) dir symlink;
|
||||
in
|
||||
dir {
|
||||
lib = dir {
|
||||
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";
|
||||
includes = [
|
||||
"${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 ];
|
||||
let
|
||||
inherit (pkgs.pseudofile) dir symlink;
|
||||
in
|
||||
dir {
|
||||
lib = dir {
|
||||
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 ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
+119
-105
@@ -153,11 +153,18 @@
|
||||
};
|
||||
};
|
||||
|
||||
module = {pkgs, config, lib, lim, ... }:
|
||||
module =
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
lim,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (pkgs.liminix.services) oneshot;
|
||||
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";
|
||||
up = ''
|
||||
mkdir -p /dev/mtd/by-name
|
||||
@@ -167,15 +174,18 @@
|
||||
done
|
||||
'';
|
||||
};
|
||||
in {
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
../../modules/arch/arm.nix
|
||||
../../modules/outputs/tftpboot.nix
|
||||
../../modules/outputs/mbrimage.nix
|
||||
../../modules/outputs/extlinux.nix
|
||||
];
|
||||
|
||||
config = {
|
||||
rootfsType = lib.mkDefault "btrfs"; # override this if you are building tftpboot
|
||||
rootOptions = lib.mkDefault "subvol=@";
|
||||
|
||||
services.mtd-name-links = mtd_by_name_links;
|
||||
kernel = {
|
||||
src = pkgs.pkgsBuildBuild.fetchurl {
|
||||
@@ -192,7 +202,7 @@
|
||||
CPU_V7 = "y";
|
||||
ARCH_MULTIPLATFORM = "y";
|
||||
ARCH_MVEBU = "y";
|
||||
ARCH_MULTI_V7= "y";
|
||||
ARCH_MULTI_V7 = "y";
|
||||
PCI_MVEBU = "y";
|
||||
AHCI_MVEBU = "y";
|
||||
|
||||
@@ -202,7 +212,6 @@
|
||||
EXPERT = "y";
|
||||
ALLOW_DEV_COREDUMP = "n";
|
||||
|
||||
|
||||
# dts has a compatible for this but dmesg is not
|
||||
# showing it
|
||||
EEPROM_AT24 = "y"; # atmel,24c64
|
||||
@@ -213,49 +222,44 @@
|
||||
|
||||
MACH_ARMADA_38X = "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
|
||||
# right now how to confgure it to find gmp
|
||||
STACKPROTECTOR_PER_TASK = "n";
|
||||
NR_CPUS = "4";
|
||||
VFP = "y";
|
||||
NEON= "y";
|
||||
NEON = "y";
|
||||
|
||||
# WARNING: unmet direct dependencies detected for ARCH_WANT_LIBATA_LEDS
|
||||
ATA = "y";
|
||||
|
||||
PSTORE = "y";
|
||||
PSTORE_RAM = "y";
|
||||
PSTORE_CONSOLE = "y";
|
||||
# PSTORE_DEFLATE_COMPRESS = "n";
|
||||
|
||||
BLOCK = "y";
|
||||
MMC="y";
|
||||
PWRSEQ_EMMC="y"; # ???
|
||||
PWRSEQ_SIMPLE="y"; # ???
|
||||
MMC_BLOCK="y";
|
||||
MMC = "y";
|
||||
PWRSEQ_EMMC = "y"; # ???
|
||||
PWRSEQ_SIMPLE = "y"; # ???
|
||||
MMC_BLOCK = "y";
|
||||
|
||||
MMC_SDHCI= "y";
|
||||
MMC_SDHCI_PLTFM= "y";
|
||||
MMC_SDHCI_PXAV3= "y";
|
||||
MMC_MVSDIO= "y";
|
||||
MMC_SDHCI = "y";
|
||||
MMC_SDHCI_PLTFM = "y";
|
||||
MMC_SDHCI_PXAV3 = "y";
|
||||
MMC_MVSDIO = "y";
|
||||
|
||||
SERIAL_8250 = "y";
|
||||
SERIAL_8250_CONSOLE = "y";
|
||||
SERIAL_OF_PLATFORM="y";
|
||||
SERIAL_OF_PLATFORM = "y";
|
||||
SERIAL_MVEBU_UART = "y";
|
||||
SERIAL_MVEBU_CONSOLE = "y";
|
||||
|
||||
SERIAL_8250_DMA= "y";
|
||||
SERIAL_8250_DW= "y";
|
||||
SERIAL_8250_EXTENDED= "y";
|
||||
SERIAL_8250_MANY_PORTS= "y";
|
||||
SERIAL_8250_SHARE_IRQ= "y";
|
||||
OF_ADDRESS= "y";
|
||||
OF_MDIO= "y";
|
||||
SERIAL_8250_DMA = "y";
|
||||
SERIAL_8250_DW = "y";
|
||||
SERIAL_8250_EXTENDED = "y";
|
||||
SERIAL_8250_MANY_PORTS = "y";
|
||||
SERIAL_8250_SHARE_IRQ = "y";
|
||||
OF_ADDRESS = "y";
|
||||
OF_MDIO = "y";
|
||||
|
||||
WATCHDOG = "y"; # watchdog is enabled by u-boot
|
||||
ORION_WATCHDOG = "y"; # so is non-optional to keep feeding
|
||||
WATCHDOG = "y"; # watchdog is enabled by u-boot
|
||||
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"
|
||||
MVMDIO = "y";
|
||||
@@ -298,6 +302,7 @@
|
||||
};
|
||||
};
|
||||
boot = {
|
||||
loader.extlinux.enable = lib.mkDefault true; # override this if you are building tftpboot
|
||||
commandLine = [
|
||||
"console=ttyS0,115200"
|
||||
"pcie_aspm=off" # ath9k pci incompatible with PCIe ASPM
|
||||
@@ -308,13 +313,14 @@
|
||||
inherit (pkgs.pseudofile) dir symlink;
|
||||
firmware = pkgs.stdenv.mkDerivation {
|
||||
name = "wlan-firmware";
|
||||
phases = ["installPhase"];
|
||||
phases = [ "installPhase" ];
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
cp -r ${pkgs.linux-firmware}/lib/firmware/ath10k/QCA988X $out
|
||||
'';
|
||||
};
|
||||
in dir {
|
||||
in
|
||||
dir {
|
||||
lib = dir {
|
||||
firmware = dir {
|
||||
ath10k = symlink firmware;
|
||||
@@ -322,10 +328,12 @@
|
||||
};
|
||||
etc = dir {
|
||||
"fw_env.config" =
|
||||
let f = pkgs.writeText "fw_env.config" ''
|
||||
/dev/mtd/by-name/u-boot-env 0x0 0x10000 0x10000
|
||||
'';
|
||||
in symlink f;
|
||||
let
|
||||
f = pkgs.writeText "fw_env.config" ''
|
||||
/dev/mtd/by-name/u-boot-env 0x0 0x10000 0x10000
|
||||
'';
|
||||
in
|
||||
symlink f;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -335,75 +343,81 @@
|
||||
compressRoot = true;
|
||||
};
|
||||
|
||||
hardware = let
|
||||
mac80211 = pkgs.kmodloader.override {
|
||||
inherit (config.system.outputs) kernel;
|
||||
targets = ["ath9k" "ath10k_pci"];
|
||||
};
|
||||
in {
|
||||
defaultOutput = "mtdimage";
|
||||
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";
|
||||
includes = [
|
||||
"${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 ];
|
||||
};
|
||||
hardware =
|
||||
let
|
||||
mac80211 = pkgs.kmodloader.override {
|
||||
inherit (config.system.outputs) kernel;
|
||||
targets = [
|
||||
"ath9k"
|
||||
"ath10k_pci"
|
||||
];
|
||||
};
|
||||
};
|
||||
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 ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
config = "mipsel-unknown-linux-musl";
|
||||
gcc = {
|
||||
abi = "32";
|
||||
arch = "mips32"; # mips32r2?
|
||||
arch = "mips32"; # mips32r2?
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -101,7 +101,14 @@
|
||||
|
||||
'';
|
||||
|
||||
module = { pkgs, config, lib, lim, ...}:
|
||||
module =
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
lim,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (pkgs.pseudofile) dir symlink;
|
||||
inherit (pkgs) openwrt;
|
||||
@@ -123,8 +130,9 @@
|
||||
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_rom_patch.bin";
|
||||
hash = "sha256-ifriAjWzFACrxVWCANZpUaEZgB/0pdbhnTVQytx6ddg=";
|
||||
};
|
||||
in {
|
||||
imports = [
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
# We include it to ensure the bridge functionality
|
||||
# is available on the target kernel.
|
||||
../../modules/bridge
|
||||
@@ -184,7 +192,7 @@
|
||||
# Actually, this is not what we want.
|
||||
# This DTS is insufficient.
|
||||
src = ./mt7621_zyxel_nwa50ax.dtsi;
|
||||
includes = [
|
||||
includePaths = [
|
||||
# Here's one weird trick to make `ubi` detection
|
||||
# out of the box.
|
||||
# We will write ubi on /dev/firmware_a:rootfs location
|
||||
@@ -201,7 +209,8 @@
|
||||
networkInterfaces =
|
||||
let
|
||||
inherit (config.system.service.network) link;
|
||||
in {
|
||||
in
|
||||
{
|
||||
eth = link.build { ifname = "eth0"; };
|
||||
lan = link.build { ifname = "lan"; };
|
||||
wlan0 = link.build {
|
||||
@@ -233,7 +242,7 @@
|
||||
services.zyxel-dual-image = config.boot.zyxel-dual-image.build {
|
||||
ensureActiveImage = "primary";
|
||||
# TODO: use mtd names rather…
|
||||
# primary and secondary are always /dev/mtd3 by virtue of the
|
||||
# primary and secondary are always /dev/mtd3 by virtue of the
|
||||
# dtb being not too wrong…
|
||||
# TODO: remove this hack.
|
||||
primaryMtdPartition = "/dev/mtd3";
|
||||
@@ -250,116 +259,113 @@
|
||||
# IMAGE/ramboot-factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi
|
||||
|
||||
kernel = {
|
||||
src = pkgs.fetchurl {
|
||||
name = "linux.tar.gz";
|
||||
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.gz";
|
||||
hash = "sha256-PkdzUKZ0IpBiWe/RS70J76JKnBFzRblWcKlaIFNxnHQ=";
|
||||
};
|
||||
extraPatchPhase = ''
|
||||
${openwrt.applyPatches.ramips}
|
||||
|
||||
'';
|
||||
config = {
|
||||
config =
|
||||
{
|
||||
|
||||
RALINK = "y";
|
||||
PCI = "y";
|
||||
PHY_MT7621_PCI = "y";
|
||||
PCIE_MT7621 = "y";
|
||||
SOC_MT7621 = "y";
|
||||
CLK_MT7621 = "y";
|
||||
CLOCKSOURCE_WATCHDOG = "y";
|
||||
RALINK = "y";
|
||||
PCI = "y";
|
||||
PHY_MT7621_PCI = "y";
|
||||
PCIE_MT7621 = "y";
|
||||
SOC_MT7621 = "y";
|
||||
CLK_MT7621 = "y";
|
||||
CLOCKSOURCE_WATCHDOG = "y";
|
||||
|
||||
SERIAL_8250_CONSOLE = "y";
|
||||
SERIAL_8250 = "y";
|
||||
SERIAL_CORE_CONSOLE = "y";
|
||||
SERIAL_OF_PLATFORM = "y";
|
||||
SERIAL_8250_NR_UARTS = "3";
|
||||
SERIAL_8250_RUNTIME_UARTS = "3";
|
||||
SERIAL_MCTRL_GPIO = "y";
|
||||
SERIAL_8250_CONSOLE = "y";
|
||||
SERIAL_8250 = "y";
|
||||
SERIAL_CORE_CONSOLE = "y";
|
||||
SERIAL_OF_PLATFORM = "y";
|
||||
SERIAL_8250_NR_UARTS = "3";
|
||||
SERIAL_8250_RUNTIME_UARTS = "3";
|
||||
SERIAL_MCTRL_GPIO = "y";
|
||||
|
||||
CONSOLE_LOGLEVEL_DEFAULT = "8";
|
||||
CONSOLE_LOGLEVEL_QUIET = "4";
|
||||
CONSOLE_LOGLEVEL_DEFAULT = "8";
|
||||
CONSOLE_LOGLEVEL_QUIET = "4";
|
||||
|
||||
# MTD_UBI_BEB_LIMIT = "20";
|
||||
# MTD_UBI_WL_THRESHOLD = "4096";
|
||||
# MTD_UBI_BEB_LIMIT = "20";
|
||||
# MTD_UBI_WL_THRESHOLD = "4096";
|
||||
|
||||
MTD = "y";
|
||||
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev
|
||||
MTD_RAW_NAND = "y";
|
||||
MTD_NAND_MT7621 = "y";
|
||||
MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table
|
||||
MTD_NAND_ECC_SW_HAMMING= "y";
|
||||
MTD_SPI_NAND= "y";
|
||||
MTD_OF_PARTS = "y";
|
||||
MTD_NAND_CORE= "y";
|
||||
MTD_SPLIT_FIRMWARE= "y";
|
||||
MTD_SPLIT_FIT_FW= "y";
|
||||
MTD = "y";
|
||||
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev
|
||||
MTD_RAW_NAND = "y";
|
||||
MTD_NAND_MT7621 = "y";
|
||||
MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table
|
||||
MTD_NAND_ECC_SW_HAMMING = "y";
|
||||
MTD_SPI_NAND = "y";
|
||||
MTD_OF_PARTS = "y";
|
||||
MTD_NAND_CORE = "y";
|
||||
MTD_SPLIT_FIRMWARE = "y";
|
||||
MTD_SPLIT_FIT_FW = "y";
|
||||
|
||||
PINCTRL = "y";
|
||||
PINCTRL_MT7621 = "y";
|
||||
PINCTRL = "y";
|
||||
PINCTRL_MT7621 = "y";
|
||||
|
||||
I2C = "y";
|
||||
I2C_MT7621 = "y";
|
||||
I2C = "y";
|
||||
I2C_MT7621 = "y";
|
||||
|
||||
SPI = "y";
|
||||
MTD_SPI_NOR = "y";
|
||||
SPI_MT7621 = "y";
|
||||
SPI_MASTER = "y";
|
||||
SPI_MEM = "y";
|
||||
SPI = "y";
|
||||
MTD_SPI_NOR = "y";
|
||||
SPI_MT7621 = "y";
|
||||
SPI_MASTER = "y";
|
||||
SPI_MEM = "y";
|
||||
|
||||
REGULATOR = "y";
|
||||
REGULATOR_FIXED_VOLTAGE = "y";
|
||||
RESET_CONTROLLER = "y";
|
||||
POWER_RESET = "y";
|
||||
POWER_RESET_GPIO = "y";
|
||||
POWER_SUPPLY = "y";
|
||||
LED_TRIGGER_PHY = "y";
|
||||
REGULATOR = "y";
|
||||
REGULATOR_FIXED_VOLTAGE = "y";
|
||||
RESET_CONTROLLER = "y";
|
||||
POWER_RESET = "y";
|
||||
POWER_RESET_GPIO = "y";
|
||||
POWER_SUPPLY = "y";
|
||||
LED_TRIGGER_PHY = "y";
|
||||
|
||||
PCI_DISABLE_COMMON_QUIRKS = "y";
|
||||
PCI_DOMAINS = "y";
|
||||
PCI_DOMAINS_GENERIC = "y";
|
||||
PCI_DRIVERS_GENERIC = "y";
|
||||
PCS_MTK_LYNXI = "y";
|
||||
PCI_DISABLE_COMMON_QUIRKS = "y";
|
||||
PCI_DOMAINS = "y";
|
||||
PCI_DOMAINS_GENERIC = "y";
|
||||
PCI_DRIVERS_GENERIC = "y";
|
||||
PCS_MTK_LYNXI = "y";
|
||||
|
||||
SOC_BUS = "y";
|
||||
SOC_BUS = "y";
|
||||
|
||||
NET = "y";
|
||||
ETHERNET = "y";
|
||||
WLAN = "y";
|
||||
NET = "y";
|
||||
ETHERNET = "y";
|
||||
WLAN = "y";
|
||||
|
||||
PHYLIB = "y";
|
||||
AT803X_PHY = "y";
|
||||
FIXED_PHY = "y";
|
||||
GENERIC_PHY = "y";
|
||||
NET_DSA = "y";
|
||||
NET_DSA_MT7530 = "y";
|
||||
NET_DSA_MT7530_MDIO = "y";
|
||||
NET_DSA_TAG_MTK = "y";
|
||||
NET_MEDIATEK_SOC = "y";
|
||||
NET_SWITCHDEV = "y";
|
||||
NET_VENDOR_MEDIATEK = "y";
|
||||
PHYLIB = "y";
|
||||
AT803X_PHY = "y";
|
||||
FIXED_PHY = "y";
|
||||
GENERIC_PHY = "y";
|
||||
NET_DSA = "y";
|
||||
NET_DSA_MT7530 = "y";
|
||||
NET_DSA_MT7530_MDIO = "y";
|
||||
NET_DSA_TAG_MTK = "y";
|
||||
NET_MEDIATEK_SOC = "y";
|
||||
NET_SWITCHDEV = "y";
|
||||
NET_VENDOR_MEDIATEK = "y";
|
||||
|
||||
SWPHY = "y";
|
||||
SWPHY = "y";
|
||||
|
||||
GPIOLIB = "y";
|
||||
GPIO_MT7621 = "y";
|
||||
OF_GPIO = "y";
|
||||
GPIOLIB = "y";
|
||||
GPIO_MT7621 = "y";
|
||||
OF_GPIO = "y";
|
||||
|
||||
EARLY_PRINTK = "y";
|
||||
EARLY_PRINTK = "y";
|
||||
|
||||
NEW_LEDS = "y";
|
||||
LEDS_TRIGGERS = "y";
|
||||
LEDS_CLASS = "y"; # required by rt2x00lib
|
||||
LEDS_CLASS_MULTICOLOR = "y";
|
||||
LEDS_BRIGHTNESS_HW_CHANGED = "y";
|
||||
NEW_LEDS = "y";
|
||||
LEDS_TRIGGERS = "y";
|
||||
LEDS_CLASS = "y"; # required by rt2x00lib
|
||||
LEDS_CLASS_MULTICOLOR = "y";
|
||||
LEDS_BRIGHTNESS_HW_CHANGED = "y";
|
||||
|
||||
PRINTK_TIME = "y";
|
||||
} // lib.optionalAttrs (config.system.service ? vlan) {
|
||||
SWCONFIG = "y";
|
||||
} // lib.optionalAttrs (config.system.service ? watchdog) {
|
||||
RALINK_WDT = "y"; # watchdog
|
||||
MT7621_WDT = "y"; # or it might be this one
|
||||
};
|
||||
PRINTK_TIME = "y";
|
||||
}
|
||||
// lib.optionalAttrs (config.system.service ? vlan) {
|
||||
SWCONFIG = "y";
|
||||
}
|
||||
// lib.optionalAttrs (config.system.service ? watchdog) {
|
||||
RALINK_WDT = "y"; # watchdog
|
||||
MT7621_WDT = "y"; # or it might be this one
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
+312
-139
@@ -4,155 +4,247 @@ System Administration
|
||||
Services on a running system
|
||||
****************************
|
||||
|
||||
* add an s6-rc cheatsheet here
|
||||
Liminix services are built on s6-rc, which is itself layered on s6.
|
||||
Services are defined at build time in your configuration (see
|
||||
:ref:`configuration-services` for information) and can't be added
|
||||
to/changed at runtime, but to monitor
|
||||
events or diagnose problems you may need to inspect them on the
|
||||
running system. Here are some of the most commonly used s6,-rc
|
||||
commands:
|
||||
|
||||
.. list-table:: Service management quick reference
|
||||
:widths: 55 45
|
||||
:header-rows: 1
|
||||
|
||||
* - What
|
||||
- How
|
||||
* - List all running services
|
||||
- ``s6-rc -a list``
|
||||
* - List all services that are **not** running
|
||||
- ``s6-rc -da list``
|
||||
* - List services that ``wombat`` depends on
|
||||
- ``s6-rc-db dependencies wombat``
|
||||
* - ... transitively
|
||||
- ``s6-rc-db all-dependencies wombat``
|
||||
* - List services that depend on service ``wombat``
|
||||
- ``s6-rc-db -d dependencies wombat``
|
||||
* - ... transitively
|
||||
- ``s6-rc-db -d all-dependencies wombat``
|
||||
* - Stop service ``wombat`` and everything depending on it
|
||||
- ``s6-rc -d change wombat``
|
||||
* - Start service ``wombat`` (but not any services depending on it)
|
||||
- ``s6-rc -u change wombat``
|
||||
* - Start service ``wombat`` and all* services depending on it
|
||||
- ``s6-rc-up-tree wombat``
|
||||
|
||||
Flashing and updating
|
||||
*********************
|
||||
:command:`s6-rc-up-tree` brings up a service and all services that
|
||||
depend on it, except for any services that depend on a "controlled"
|
||||
service that is not currently running. Controlled services are not
|
||||
started at boot time but in response to external events (e.g. plugging
|
||||
in a particular piece of hardware) so you probably don't want to be
|
||||
starting them by hand if the conditions aren't there.
|
||||
|
||||
A service may be **up** or **down** (there are no intermediate states
|
||||
like "started" or "stopping" or "dying" or "cogitating"). Some (but
|
||||
not all) services have "readiness" notifications: the dependents of a
|
||||
service with a readiness notification won't be started until the
|
||||
service signals (by writing to a nominated file descriptor) that it's
|
||||
prepared to start work. Most services defined by Liminix also have a
|
||||
``timeout-up`` parameter, which means that if a service has readiness
|
||||
notifications and doesn't become ready in the allotted time (defaults
|
||||
20 seconds) it will be terminated and its state set to **down**.
|
||||
|
||||
If the process providing a service dies, it will be restarted
|
||||
automatically. Liminix does not automatically set it to **down**.
|
||||
|
||||
Flashing from Liminix
|
||||
=====================
|
||||
(If the process providing a service dies without ever notifying
|
||||
readiness, Liminix will restart it as many times as it has to until the
|
||||
timeout period elapses, and then stop it and mark it down.)
|
||||
|
||||
The flash procedure from an existing Liminix-system has two steps.
|
||||
First we reboot the device (using "kexec") into an "ephemeral"
|
||||
RAM-based version of the new configuration, then when we're happy it
|
||||
works we can flash the image - and if it doesn't work we can reboot
|
||||
the device again and it will boot from the old image.
|
||||
Controlled services
|
||||
===================
|
||||
|
||||
**Controlled** services are those which are started/stopped on demand
|
||||
by a **controller** (another service) instead of being started at boot
|
||||
time. For example:
|
||||
|
||||
Building the RAM-based image
|
||||
----------------------------
|
||||
* ``svc.uevent-rule.build`` creates a controlled service which is
|
||||
active when a particular hardware device (identified by uevent/sysfs
|
||||
directory) is present.
|
||||
|
||||
To create the ephemeral image, build ``outputs.kexecboot`` instead of
|
||||
``outputs.default``. This generates a directory containing the root
|
||||
filesystem image and kernel, along with an executable called `kexec`
|
||||
and a `boot.sh` script that runs it with appropriate arguments.
|
||||
* ``svc.round-robin.build`` creates a service controller that
|
||||
invokes two or more services in turn, running the next one when the
|
||||
process providing the previous one exits. We use this for failover
|
||||
from one network connection to a backup connection, for example.
|
||||
|
||||
For example
|
||||
* ``svc.health-check.build`` creates a service controller that
|
||||
runs a controlled service and periodically tests whether it is
|
||||
healthy by running an external health check command or script. If the
|
||||
check command repeatedly fails, the controlled service is
|
||||
restarted.
|
||||
|
||||
The Configuration section of the manual describes controlled
|
||||
services in more detail. Some operational considerations
|
||||
|
||||
* ``round-robin`` detects a service status by looking at its
|
||||
:file:`outputs` directory, so it won't work unless the service
|
||||
creates some outputs. This is considered a bug and will be
|
||||
fixed in a future release
|
||||
|
||||
* ``health-check`` works for longruns but not for oneshots, as it
|
||||
internally relies on ``s6-svc`` to restart the process
|
||||
|
||||
Logs
|
||||
====
|
||||
|
||||
Logs for all services are collated into :file:`/run/log/current`.
|
||||
The log file is rotated when it reaches a threshold size, into another
|
||||
file in the same directory whose name contains a TAI64 timestamp.
|
||||
|
||||
Each log line is prefixed with a TAI64 timestamp and the name of the
|
||||
service, if it is a longrun. If it is a oneshot, a timestamp and the
|
||||
name of some other service. To convert the timestamp into a
|
||||
human-readable format, use :command:`s6-tai64nlocal`.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
nix-build -I liminix-config=./examples/arhcive.nix \
|
||||
--arg device "import ./devices/gl-ar750"
|
||||
-A outputs.kexecboot && \
|
||||
(tar chf - result | ssh root@the-device tar -C /run -xvf -)
|
||||
# ls -l /run/log/
|
||||
-rw-r--r-- 1 0 lock
|
||||
-rw-r--r-- 1 0 state
|
||||
-rwxr--r-- 1 98059 @4000000000025cb629c311ac.s
|
||||
-rwxr--r-- 1 98061 @40000000000260f7309c7fb4.s
|
||||
-rwxr--r-- 1 98041 @40000000000265233a6cc0b6.s
|
||||
-rwxr--r-- 1 98019 @400000000002695d10c06929.s
|
||||
-rwxr--r-- 1 98064 @4000000000026d84189559e0.s
|
||||
-rwxr--r-- 1 98055 @40000000000271ce1e031d91.s
|
||||
-rwxr--r-- 1 98054 @400000000002760229733626.s
|
||||
-rwxr--r-- 1 98104 @4000000000027a2e3b6f4e12.s
|
||||
-rwxr--r-- 1 98023 @4000000000027e6f0ed24a6c.s
|
||||
-rw-r--r-- 1 42374 current
|
||||
|
||||
# tail -2 /run/log/current
|
||||
@40000000000284f130747343 wan.link.pppoe Connect: ppp0 <--> /dev/pts/0
|
||||
@40000000000284f230acc669 wan.link.pppoe sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x667a9594> <pcomp> <accomp>]
|
||||
# tail -2 /run/log/current | s6-tai64nlocal
|
||||
1970-01-02 21:51:45.828598156 wan.link.pppoe sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x667a9594> <pcomp> <accom
|
||||
p>]
|
||||
1970-01-02 21:51:48.832588765 wan.link.pppoe sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x667a9594> <pcomp> <accom
|
||||
p>]
|
||||
|
||||
and then login to the device and run
|
||||
Log persistence
|
||||
---------------
|
||||
|
||||
Logs written to :file:`/run/log/` will not survive a reboot or crash,
|
||||
as it is an ephemeral filesystem.
|
||||
|
||||
On supported hardware you can enable logging to `pstore
|
||||
<https://www.kernel.org/doc/Documentation/ABI/testing/pstore>`_ which
|
||||
means the most recent log messages will be preserved on reboot. Set
|
||||
the config option ``logging.persistent.enable = true`` to log messages
|
||||
to :file:`/dev/pmsg0` as well as to the regular log. This is a
|
||||
circular buffer, so when it fills up newer messages will overwrite the
|
||||
oldest messages.
|
||||
|
||||
Logs found in pstore after a reboot will be moved at startup to
|
||||
:file:`/run/log/previous-boot`
|
||||
|
||||
|
||||
|
||||
Updating an installed system
|
||||
****************************
|
||||
|
||||
If your system has a writable root filesystem (JFFS2, btrfs etc -
|
||||
anything but squashfs), we have mechanisms for in-places updates
|
||||
analogous to :command:`nixos-rebuild`, but the operation is a bit
|
||||
different because it expects to run on a build machine and then copy
|
||||
to the host device using :command:`ssh`.
|
||||
|
||||
To use this, build the ``outputs.updater``
|
||||
target and then run the :command:`update.sh` script it generates.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cd /run/result
|
||||
sh ./boot.sh .
|
||||
nix-build -I liminix-config=./my-configuration.nix \
|
||||
--arg device "import ./devices/mydevice" \
|
||||
-A outputs.updater
|
||||
./result/bin/update.sh root@the-device
|
||||
|
||||
The update script uses min-copy-closure to copy new or changed
|
||||
packages to the device, then (perhaps) reboots it. The reboot
|
||||
behaviour can be affected by flags:
|
||||
|
||||
* `--no-reboot` will cause it not to reboot at all, if you would
|
||||
rather do that yourself. Note that none of the newly-installed or
|
||||
updated services will be running until you do.
|
||||
|
||||
* `--fast` causes it tn not do a full reboot, but instead to restart
|
||||
only the services that have been changed. This will restart all of
|
||||
the services that have updated store paths (and anything that
|
||||
depends on them), but will not affect services that haven't changed.
|
||||
|
||||
It doesn't delete old packages automatically: to do that run
|
||||
:command:`min-collect-garbage`, which will delete any packages not in
|
||||
the current system closure. Note that Liminix does not have the NixOS
|
||||
concept of environments or generations, and there is no way back from
|
||||
this except for building the previous configuration again.
|
||||
|
||||
Caveats
|
||||
-------
|
||||
|
||||
* it needs there to be enough free space on the device for all the new
|
||||
packages in addition to all the packages already on it - which may
|
||||
be a problem if there is little flash storage or if a lot of things
|
||||
have changed (e.g. a new version of nixpkgs).
|
||||
|
||||
* it may not be able to upgrade the kernel: this is device-dependent.
|
||||
If your device boots from a kernel image on a raw MTD partition or
|
||||
or UBI volume, update.sh is unable to alter the kernel partition.
|
||||
If your device boots from a kernel inside the filesystem (e.g. using
|
||||
bootloader.extlinux or bootloder.fit) then the kernel will be
|
||||
upgraded along with the userland
|
||||
|
||||
|
||||
This will load the new kernel and map the root filesystem into a RAM
|
||||
disk, then start executing the new kernel. *This is effectively a
|
||||
reboot - be sure to close all open files and finish anything else
|
||||
you were doing first.*
|
||||
Recovery/downgrades
|
||||
-------------------
|
||||
|
||||
If the new system crashes or is rebooted, then the device will revert
|
||||
to the old configuration it finds in flash.
|
||||
The :command:`update.sh` script also creates a timestamped symlink on
|
||||
the device which points to the system configuration it installs. If
|
||||
you install a configuration that doesn't work, you can revert to any
|
||||
other installed configuration by
|
||||
|
||||
1) booting to some kind of rescue or recovery system (which may be
|
||||
some vendor-provided rescue option, or your own recovery system
|
||||
perhaps based on :file:`examples/recovery.nix`) and mounting
|
||||
your Liminix filesystem on /mnt
|
||||
|
||||
Building the second (permanent) image
|
||||
-------------------------------------
|
||||
|
||||
While running in the kexecboot system, you can build the permanent
|
||||
image and copy it to the device with :command:`ssh`
|
||||
2) picking another previously-installed configuration that _did_ work,
|
||||
and switching back to it:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
build-machine$ nix-build -I liminix-config=./examples/arhcive.nix \
|
||||
--arg device "import ./devices/gl-ar750"
|
||||
-A outputs.default && \
|
||||
(tar chf - result | ssh root@the-device tar -C /run -xvf -)
|
||||
|
||||
build-machine$ tar chf - result/firmware.bin | \
|
||||
ssh root@the-device tar -C /run -xvf -
|
||||
|
||||
Next you need to connect to the device and locate the "firmware"
|
||||
partition, which you can do with a combination of :command:`dmesg`
|
||||
output and the contents of :file:`/proc/mtd`
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
<5>[ 0.469841] Creating 4 MTD partitions on "spi0.0":
|
||||
<5>[ 0.474837] 0x000000000000-0x000000040000 : "u-boot"
|
||||
<5>[ 0.480796] 0x000000040000-0x000000050000 : "u-boot-env"
|
||||
<5>[ 0.487056] 0x000000050000-0x000000060000 : "art"
|
||||
<5>[ 0.492753] 0x000000060000-0x000001000000 : "firmware"
|
||||
|
||||
# cat /proc/mtd
|
||||
dev: size erasesize name
|
||||
mtd0: 00040000 00001000 "u-boot"
|
||||
mtd1: 00010000 00001000 "u-boot-env"
|
||||
mtd2: 00010000 00001000 "art"
|
||||
mtd3: 00fa0000 00001000 "firmware"
|
||||
mtd4: 002a0000 00001000 "kernel"
|
||||
mtd5: 00d00000 00001000 "rootfs"
|
||||
|
||||
Now run (in this example)
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
flashcp -v firmware.bin /dev/mtd3
|
||||
|
||||
# ls -ld /mnt/*configuration
|
||||
lrwxrwxrwx 1 90 /mnt/20252102T182104.configuration -> nix/store/v1w0h4zw65ah4c2r0k7nyy125qrxhq78-system-configuration-aarch64-unknown-linux-musl
|
||||
lrwxrwxrwx 1 90 /mnt/20251802T181822.configuration -> nix/store/wqjl9s9xljl2wg8257292zghws9ssidk-system-configuration-aarch64-unknown-linux-musl
|
||||
# : 20251802T181822 is the working system, so reinstall it
|
||||
# /mnt/20251802T181822.configuration/bin/install /mnt
|
||||
# umount /mnt
|
||||
# reboot
|
||||
|
||||
This will install the previous configuration's activation binary into
|
||||
/bin, and copy its kernel and initramfs into /boot. Note that it
|
||||
depends on the previous system not having been garbage-collected.
|
||||
|
||||
|
||||
"I know my new image is good, can I skip the intermediate step?"
|
||||
----------------------------------------------------------------
|
||||
|
||||
In addition to giving you a chance to see if the new image works, this
|
||||
two-step process ensures that you're not copying the new image over
|
||||
the top of the active root filesystem. Sometimes it works, but you
|
||||
will at least need physical access to the device to power-cycle it
|
||||
because it will be effectively frozen afterwards.
|
||||
|
||||
|
||||
Flashing from the boot monitor
|
||||
==============================
|
||||
|
||||
If you are prepared to open the device and have a TTL serial adaptor
|
||||
of some kind to connect it to, you can probably use U-Boot and a TFTP
|
||||
server to download and flash the image. This is quite
|
||||
hardware-specific, and sometimes involves soldering: please refer
|
||||
to :ref:`serial`.
|
||||
|
||||
|
||||
Flashing from OpenWrt
|
||||
=====================
|
||||
|
||||
.. CAUTION:: Untested! A previous version of these instructions
|
||||
(without the -e flag) led to bricking the device
|
||||
when flashing a jffs2 image. If you are reading
|
||||
this message, nobody has yet reported on whether the
|
||||
new instructions are any better.
|
||||
|
||||
If your device is running OpenWrt then it probably has the
|
||||
:command:`mtd` command installed. After transferring the image onto the
|
||||
device using e.g. :command:`ssh`, you can run it as follows:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
mtd -e -r write /tmp/firmware.bin firmware
|
||||
|
||||
The options to this command are for "erase before writing" and "reboot
|
||||
after writing".
|
||||
|
||||
For more information, please see the `OpenWrt manual <https://openwrt.org/docs/guide-user/installation/sysupgrade.cli>`_ which may also contain (hardware-dependent) instructions on how to flash an image using the vendor firmware - perhaps even from a web interface.
|
||||
|
||||
Updating an installed system (JFFS2)
|
||||
************************************
|
||||
|
||||
.. _levitate:
|
||||
|
||||
Adding packages
|
||||
===============
|
||||
|
||||
If your device is running a JFFS2 root filesystem, you can build
|
||||
extra packages for it on your build system and copy them to the
|
||||
device: any package in Nixpkgs or in the Liminix overlay is available
|
||||
with the ``pkgs`` prefix:
|
||||
If you simply wish to add a package without any change to services,
|
||||
you can call :command:`min-copy-closure` directly to install
|
||||
any package in Nixpkgs or in the Liminix overlay
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
@@ -161,38 +253,119 @@ with the ``pkgs`` prefix:
|
||||
|
||||
nix-shell -p min-copy-closure root@the-device result/
|
||||
|
||||
Note that this only copies the package to the device: it doesn't update
|
||||
any profile to add it to ``$PATH``
|
||||
Note that this only copies the package and its dependencies to the
|
||||
device: it doesn't update any profile to add it to ``$PATH``
|
||||
|
||||
|
||||
Rebuilding the system
|
||||
=====================
|
||||
.. _rebuilding the system:
|
||||
|
||||
:command:`liminix-rebuild` is the Liminix analogue of :command:`nixos-rebuild`, although its operation is a bit different because it expects to run on a build machine and then copy to the host device. Run it with the same ``liminix-config`` and ``device`` parameters as you would run :command:`nix-build`, and it will build any new/changed packages and then copy them to the device using SSH. For example:
|
||||
Reinstalling on a running system
|
||||
********************************
|
||||
|
||||
Liminix is initially installed from a monolithic
|
||||
:file:`firmware.bin` - and unless you're running a writable
|
||||
filesystem, the only way to update it is to build and install a whole
|
||||
new :file:`firmware.bin`. However, you probably would prefer not to
|
||||
have to remove it from its installation site, unplug it from the
|
||||
network and stick serial cables in it all over again.
|
||||
|
||||
It is not (generally) safe to install a new firmware onto the flash
|
||||
partitions that the active system is running on. To address this we
|
||||
have :command:`levitate`, which a way for a running Liminix system to
|
||||
"soft restart" into a ramdisk running only a limited set of services,
|
||||
so that the main partitions can then be safely flashed.
|
||||
|
||||
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Levitate *needs to be configured when you create the initial system*
|
||||
to specify which services/packages/etc to run in maintenance
|
||||
mode. Most likely you want to configure a network interface and an ssh
|
||||
for example so that you can login to reflash it.
|
||||
|
||||
.. code-block:: nix
|
||||
|
||||
defaultProfile.packages = with pkgs; [
|
||||
...
|
||||
(levitate.override {
|
||||
config = {
|
||||
services = {
|
||||
inherit (config.services) dhcpc sshd watchdog;
|
||||
};
|
||||
defaultProfile.packages = [ mtdutils ];
|
||||
users.root = config.users.root;
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
|
||||
|
||||
Use
|
||||
===
|
||||
|
||||
Connect (with ssh, probably) to the running Liminix system that you
|
||||
wish to upgrade.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
liminix-rebuild root@the-device -I liminix-config=./examples/rotuer.nix --arg device "import ./devices/gl-ar750"
|
||||
bash$ ssh root@the-device
|
||||
|
||||
Run :command:`levitate`. This takes a little while (perhaps a few
|
||||
tens of seconds) to execute, and copies all config required for
|
||||
maintenance mode to :file:`/run/maintenance`.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# levitate
|
||||
|
||||
Reboot into maintenance mode. You will be logged out
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
This will
|
||||
# reboot
|
||||
|
||||
Connect to the device again - note that the ssh host key will have changed.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
* build anything that needs building
|
||||
* copy new or changed packages to the device
|
||||
* reboot the device
|
||||
# ssh -o UserKnownHostsFile=/dev/null root@the-device
|
||||
|
||||
Check we're in maintenance mode
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
It doesn't delete old packages automatically: to do that run
|
||||
:command:`min-collect-garbage`, which will delete any packages not in
|
||||
the current system closure. Note that Liminix does not have the NixOS
|
||||
concept of environments or generations, and there is no way back from
|
||||
this except for building the previous configuration again.
|
||||
# cat /etc/banner
|
||||
|
||||
LADIES AND GENTLEMEN WE ARE FLOATING IN SPACE
|
||||
|
||||
Most services are disabled. The system is operating
|
||||
with a ram-based root filesystem, making it safe to
|
||||
overwrite the flash devices in order to perform
|
||||
upgrades and maintenance.
|
||||
|
||||
Don't forget to reboot when you have finished.
|
||||
|
||||
Perform the upgrade, using flashcp. This is an example,
|
||||
your device will differ
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# cat /proc/mtd
|
||||
dev: size erasesize name
|
||||
mtd0: 00030000 00010000 "u-boot"
|
||||
mtd1: 00010000 00010000 "u-boot-env"
|
||||
mtd2: 00010000 00010000 "factory"
|
||||
mtd3: 00f80000 00010000 "firmware"
|
||||
mtd4: 00220000 00010000 "kernel"
|
||||
mtd5: 00d60000 00010000 "rootfs"
|
||||
mtd6: 00010000 00010000 "art"
|
||||
# flashcp -v firmware.bin mtd:firmware
|
||||
|
||||
Caveats
|
||||
-------
|
||||
All done
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
* it needs there to be enough free space on the device for all the new
|
||||
packages in addition to all the packages already on it - which may be
|
||||
a problem if a lot of things have changed (e.g. a new version of
|
||||
nixpkgs).
|
||||
# reboot
|
||||
|
||||
* it cannot upgrade the kernel, only userland
|
||||
|
||||
+3
-3
@@ -7,19 +7,19 @@
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||
|
||||
project = 'Liminix'
|
||||
copyright = '2023, Daniel Barlow'
|
||||
copyright = '2023-2024 Daniel Barlow'
|
||||
author = 'Daniel Barlow'
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autosectionlabel'
|
||||
# 'sphinx.ext.autosectionlabel'
|
||||
]
|
||||
autosectionlabel_prefix_document = True
|
||||
|
||||
templates_path = ['_templates']
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
exclude_patterns = ['*.inc.rst', '_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
|
||||
|
||||
|
||||
+253
-30
@@ -1,27 +1,8 @@
|
||||
.. _configuration:
|
||||
|
||||
Configuration
|
||||
#############
|
||||
|
||||
Liminix uses the Nix language to provide congruent configuration
|
||||
management. This means that to change anything about the way in
|
||||
which a Liminix system works, you make that change in
|
||||
your :file:`configuration.nix` (or one of the other files it references),
|
||||
and rerun :command:`nix-build` or :command:`liminix-rebuild` to action
|
||||
the change. It is not possible (at least, without shenanigans) to make
|
||||
changes by logging into the device and running imperative commands
|
||||
whose effects may later be overridden: :file:`configuration.nix`
|
||||
always describes the entire system and can be used to recreate that
|
||||
system at any time. You can usefully keep it under version control.
|
||||
|
||||
If you are familiar with NixOS, you will notice some similarities
|
||||
between NixOS and Liminix configuration, and also some
|
||||
differences. Sometimes the differences are due to the
|
||||
resource-constrained devices we deploy onto, sometimes due to
|
||||
differences in the uses these devices are put to.
|
||||
|
||||
|
||||
Configuration taxonomy
|
||||
**********************
|
||||
|
||||
There are many things you can specify in a configuration, but these
|
||||
are the ones you most commonly need to change:
|
||||
|
||||
@@ -86,14 +67,166 @@ domains, or you want to run two SSH daemons on different ports.
|
||||
don't use the NixOS modules themselves, because the
|
||||
underlying system is not similar enough for them to work.
|
||||
|
||||
.. _configuration-services:
|
||||
|
||||
Services
|
||||
********
|
||||
|
||||
We use the `s6-rc service manager <https://www.skarnet.org/software/s6-rc/overview.html>`_ to start/stop/restart services and handle
|
||||
service dependencies. Any attribute in `config.services` will become
|
||||
part of the default set of services that s6-rc will try to bring up on
|
||||
boot.
|
||||
In Liminix a service is any kind of long-running task or process on
|
||||
the system, that is managed (started, stopped, and monitored) by a
|
||||
service supervisor. A typical SOHO router might have services to
|
||||
|
||||
* answer DHCP and DNS requests from the LAN
|
||||
* provide a wireless access point
|
||||
* connect using PPPoE or L2TP to an upstream network
|
||||
* start/stop the firewall
|
||||
* enable/disable IP packet forwarding
|
||||
* mount filesystems
|
||||
|
||||
(Some of these might not be considered services using other
|
||||
definitions of the term: for example, this L2TP process would be a
|
||||
"client" in the client/server classification; and enabling packet
|
||||
forwarding doesn't require any long-lived process - just a setting to
|
||||
be toggled. However, there is value in being able to use the same
|
||||
abstractions for all the things to manage them and specify their
|
||||
dependency relationships - so in Liminix "everything is a service")
|
||||
|
||||
The service supervision system enables service health monitoring,
|
||||
restart of unhealthy services, and failover to "backup" services when
|
||||
a primary service fails or its dependencies are unavailable. The
|
||||
intention is that you have a framework in which you can specify policy
|
||||
requirements like "ethernet wan dhcp-client should be restarted if it
|
||||
crashes, but if it can't start because the hardware link is down, then
|
||||
4G ppp service should be started instead".
|
||||
|
||||
Any attribute in `config.services` will become part of the default set
|
||||
of services that s6-rc will try to bring up. Services are usually
|
||||
started at boot time, but **controlled services** are those that are
|
||||
required only in particular contexts. For example, a service to mount
|
||||
a USB backup drive should run only when the drive is attached to the
|
||||
system. Liminix currently implements three kinds of controlled service:
|
||||
|
||||
* "uevent-rule" service controllers use sysfs/uevent to identify when
|
||||
particular hardware devices are present, and start/stop a controlled
|
||||
service appropriately.
|
||||
|
||||
* the "round-robin" service controller is used for service failover:
|
||||
it allows you to specify a list of services and runs each of them
|
||||
in turn until it exits, then runs the next.
|
||||
|
||||
* the "health-check" service wraps another service, and runs a "health
|
||||
check" command at regular intervals. When the health check fails,
|
||||
indicating that the wrapped service is not working, it is terminated
|
||||
and allowed to restart.
|
||||
|
||||
Runtime secrets (external vault)
|
||||
================================
|
||||
|
||||
Secrets (such as wifi passphrases, PPP username/password, SSH keys,
|
||||
etc) that you provide as literal values in :file:`configuration.nix`
|
||||
are processed into into config files and scripts at build time, and
|
||||
eventually end up in various files in the (world-readable)
|
||||
:file:`/nix/store` before being baked into a flashable image. To
|
||||
change a secret - whether due to a compromise, or just as part of to a
|
||||
routine key rotation - you need to rebuild the configuration and
|
||||
potentially reflash the affected devices.
|
||||
|
||||
To avoid this, you may instead use a "secrets service", which is a
|
||||
mechanism for your device to fetch secrets from a source external to
|
||||
the Nix store, and create at runtime the configuration files and
|
||||
scripts that start the services which require them.
|
||||
|
||||
Not every possible parameter to every possible service is configurable
|
||||
using a secrets service. Parameters which can be configured this way
|
||||
are those with the type ``liminix.lib.types.replacable``. At the time
|
||||
this document was written, these include:
|
||||
|
||||
* ppp (pppoe and l2tp): ``username``, ``password``
|
||||
* ssh: ``authorizedKeys``
|
||||
* hostapd: all parameters (most likely to be useful for ``wpa_passphrase``)
|
||||
|
||||
To use a runtime secret for any of these parameters:
|
||||
|
||||
* create a secrets service to specify the source of truth for secrets
|
||||
* use the :code:`outputRef` function in the service parameter to specify the secrets service and path
|
||||
|
||||
For example, given you had an HTTPS server hosting a JSON file with the structure
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
"ssh": {
|
||||
"authorizedKeys": {
|
||||
"root": [ "ssh-rsa ....", "ssh-rsa ....", ... ]
|
||||
"guest": [ "ssh-rsa ....", "ssh-rsa ....", ... ]
|
||||
}
|
||||
}
|
||||
|
||||
you could use a :file:`configuration.nix` fragment something like this
|
||||
to make those keys visible to ssh:
|
||||
|
||||
.. code-block:: nix
|
||||
|
||||
services.secrets = svc.secrets.outboard.build {
|
||||
name = "secret-service";
|
||||
url = "http://10.0.0.1/secrets.json";
|
||||
username = "secrets";
|
||||
password = "liminix";
|
||||
interval = 30; # minutes
|
||||
dependencies = [ config.services.lan ];
|
||||
};
|
||||
services.sshd = svc.ssh.build {
|
||||
authorizedKeys = outputRef config.services.secrets "ssh/authorizedKeys";
|
||||
};
|
||||
|
||||
|
||||
|
||||
There are presently two implementations of a secrets service:
|
||||
|
||||
Outboard secrets (HTTPS)
|
||||
------------------------
|
||||
|
||||
This service expects a URL to a JSON file containing all the secrets.
|
||||
|
||||
You may specify a username and password along with the URL, which are
|
||||
used if the file is password-protected (HTTP Basic
|
||||
authentication). Note that this is not a protection against a
|
||||
malicious local user: the username and password are normal build-time
|
||||
parameters so will be readable in the Nix store. This is a mitigation
|
||||
against the URL being accidentally discovered due to e.g. a log file
|
||||
or error message on the server leaking.
|
||||
|
||||
|
||||
Tang secrets (encrypted local file)
|
||||
-----------------------------------
|
||||
|
||||
Aternatively, secrets may be stored locally on the device, in a file
|
||||
that has been encrypted using `Tang <https://github.com/latchset/tang>`_.
|
||||
|
||||
Tang is a server for binding data to network presence.
|
||||
|
||||
This sounds fancy, but the concept is simple. You have some data, but you only want it to be available when the system containing the data is on a certain, usually secure, network.
|
||||
|
||||
|
||||
.. code-block:: nix
|
||||
|
||||
services.secrets = svc.secrets.tang.build {
|
||||
name = "secret-service";
|
||||
path = "/run/mnt/usbstick/secrets.json.jwe";
|
||||
interval = 30; # minutes
|
||||
dependencies = [ config.services.mount-usbstick ];
|
||||
};
|
||||
|
||||
The encryption uses the
|
||||
same scheme/algorithm as `Clevis <https://github.com/latchset/clevis>`_ : you may use the `Clevis instructions <https://github.com/latchset/clevis?tab=readme-ov-file#pin-tang>`_ to
|
||||
encrypt the file on another host and then copy it to your Liminix
|
||||
device, or you can use :command:`tangc encrypt` to encrypt directly on
|
||||
the device. (That latter approach may pose a chicken/egg problem if
|
||||
the device needs secrets to boot up and run the services you are
|
||||
relying on in order to login).
|
||||
|
||||
|
||||
Writing services
|
||||
================
|
||||
|
||||
For the most part, for common use cases, hopefully the services you
|
||||
need will be defined by modules and you will only have to pass the
|
||||
@@ -141,11 +274,101 @@ Services may have dependencies: as you see above in the ``cowsayd``
|
||||
example, it depends on some service called ``config.services.lan``,
|
||||
meaning that it won't be started until that other service is up.
|
||||
|
||||
..
|
||||
TODO: explain service outputs
|
||||
Service outputs
|
||||
===============
|
||||
|
||||
Outputs are a mechanism by which a service can provide data which may
|
||||
be required by other services. For example:
|
||||
|
||||
* the DHCP client service can expect to receive nameserver address
|
||||
information as one of the fields in the response from the DHCP
|
||||
server: we provide that as an output which a dependent service for a
|
||||
stub name resolver can use to configure its upstream servers.
|
||||
|
||||
* a service that creates a new network interface (e.g. ppp) will
|
||||
provide the name of the interface (:code:`ppp0`, or :code:`ppp1` or
|
||||
:code:`ppp7`) as an output so that a dependent service can reference
|
||||
it to set up a route, or to configure firewall rules.
|
||||
|
||||
A service :code:`myservice` should write its outputs as files in
|
||||
:file:`/run/services/outputs/myservice`: you can look around this
|
||||
directory on a running Liminix system to see how it's used currently.
|
||||
Usually we use the :code:`in_outputs` shell function in the
|
||||
:command:`up` or :command:`run` attributes of the service:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
(in_outputs ${name}
|
||||
for i in lease mask ip router siaddr dns serverid subnet opt53 interface ; do
|
||||
(printenv $i || true) > $i
|
||||
done)
|
||||
|
||||
The outputs are just files, so technically you can read them using
|
||||
anything that can read a file. Liminix has two "preferred"
|
||||
mechanisms, though:
|
||||
|
||||
One-off lookups
|
||||
---------------
|
||||
|
||||
In any context that ends up being evaluated by the shell, use
|
||||
:code:`output` to print the value of an output
|
||||
|
||||
.. code-block:: nix
|
||||
|
||||
services.defaultroute4 = svc.network.route.build {
|
||||
via = "$(output ${services.wan} address)";
|
||||
target = "default";
|
||||
dependencies = [ services.wan ];
|
||||
};
|
||||
|
||||
|
||||
Continuous updates
|
||||
------------------
|
||||
|
||||
The downside of using shell functions in downstream service startup
|
||||
scripts is that they only run when the service starts up: if a service
|
||||
output *changes*, the downstream service would have to be restarted to
|
||||
notice the change. Sometimes this is OK but other times the downstream
|
||||
has no other need to restart, if it can only get its new data.
|
||||
|
||||
For this case, there is the :code:`anoia.svc` Fennel library, which
|
||||
allows you to write a simple loop which is iterated over whenever a
|
||||
service's outputs change. This code is from
|
||||
:file:`modules/dhcp6c/acquire-wan-address.fnl`
|
||||
|
||||
.. code-block:: fennel
|
||||
|
||||
(fn update-addresses [wan-device addresses new-addresses exec]
|
||||
;; run some appropriate "ip address [add|remove]" commands
|
||||
)
|
||||
|
||||
(fn run []
|
||||
(let [[state-directory wan-device] arg
|
||||
dir (svc.open state-directory)]
|
||||
(accumulate [addresses []
|
||||
v (dir:events)]
|
||||
(update-addresses wan-device addresses
|
||||
(or (v:output "address") []) system))))
|
||||
|
||||
The :code:`output` method seen here accepts a filename (relative
|
||||
to the service's output directory), or a directory name. It
|
||||
returns the first line of that file, or for directories it
|
||||
returns a table (Lua's key/value datastructure, similar to
|
||||
a hash/dictionary) of the outputs in that directory.
|
||||
|
||||
|
||||
Output design considerations
|
||||
----------------------------
|
||||
|
||||
For preference, outputs should be short and simple, and not require
|
||||
downstream services to do complicated parsing in order to use them.
|
||||
Shell commands in Liminix are run using the Busybox shell which
|
||||
doesn't have the niceties of an advanced shell like Bash let alone
|
||||
those of a real programming language.
|
||||
|
||||
Note also that the Lua :code:`svc` library only reads the first line
|
||||
of each output.
|
||||
|
||||
..
|
||||
TODO: outputs that change, and services that poll other services
|
||||
|
||||
Module implementation
|
||||
*********************
|
||||
@@ -192,7 +415,7 @@ To expose a service template in a module, it needs the following:
|
||||
|
||||
.. code-block:: nix
|
||||
|
||||
config.system.service.cowsay = liminix.callService ./service.nix {
|
||||
config.system.service.cowsay = config.system.callService ./service.nix {
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
default = "0.0.0.0";
|
||||
|
||||
+4
-67
@@ -88,64 +88,6 @@ time with configurations for RP-PPPoE and/or Accel PPP.`
|
||||
Hardware devices
|
||||
****************
|
||||
|
||||
.. _serial:
|
||||
|
||||
U-Boot and serial shenanigans
|
||||
=============================
|
||||
|
||||
Every device that we have so far encountered in Liminix uses `U-Boot,
|
||||
the "Universal Boot Loader" <https://docs.u-boot.org/en/latest/>`_ so
|
||||
it's worth knowing a bit about it. "Universal" is in this context a
|
||||
bit of a misnomer, though: encountering *mainline* U-Boot is very rare
|
||||
and often you'll find it is a fork from some version last updated
|
||||
in 2008. Upgrading U-Boot is more or less complicated depending on the
|
||||
device and is outside scope for Liminix.
|
||||
|
||||
To speak to U-Boot on your device you'll usually need a serial
|
||||
connection to it. This is device-specific. Usually it involves
|
||||
opening the box, locating the serial header pins (TX, RX and GND) and
|
||||
connecting a USB TTL converter to them.
|
||||
|
||||
The Rolls Royce of USB/UART cables is the `FTDI cable
|
||||
<https://cpc.farnell.com/ftdi/ttl-232r-rpi/cable-debug-ttl-232-usb-rpi/dp/SC12825?st=usb%20to%20uart%20cable>`_,
|
||||
but there are cheaper alternatives based on the PL2303 and CP2102 chipsets. Or
|
||||
get creative and use the `UART GPIO pins <https://pinout.xyz/>`_ on a Raspberry Pi. Whatever you do, make sure
|
||||
that the voltages are compatible: if your device is 3.3V (this is
|
||||
typical but not universal), you don't want to be sending it 5v or
|
||||
(even worse) 12v.
|
||||
|
||||
Run a terminal emulator such as Minicom on the computer at other end
|
||||
of the link. 115200 8N1 is the typical speed.
|
||||
|
||||
.. NOTE::
|
||||
|
||||
TTL serial connections typically have no form of flow control and
|
||||
so don't always like having massive chunks of text pasted into
|
||||
them - and U-Boot may drop characters while it's busy. So don't
|
||||
necessarily expect to copy-paste large chunks of text into the
|
||||
terminal emulator and have it work just like that.
|
||||
|
||||
If using Minicom, you may find it helps to bring up the "Termimal
|
||||
settings" dialog (C^A T), then configure "Newline tx delay" to
|
||||
some small but non-zero value.
|
||||
|
||||
When you turn the router on you should be greeted with some messages
|
||||
from U-Boot, followed by the instruction to hit some key to stop
|
||||
autoboot. Do this and you will get to the prompt. If you didn't see
|
||||
anything, the strong likelihood is that TX and RX are the wrong way
|
||||
around. If you see garbage, try a different speed.
|
||||
|
||||
Interesting commands to try first in U-Boot are :command:`help` and
|
||||
:command:`printenv`.
|
||||
|
||||
To do anything useful with U-Boot you will probably need a way to get
|
||||
large binary files onto the device, and the usual way to do this is by
|
||||
adding a network connection and using TFTP to download them. It's
|
||||
quite common that the device's U-Boot doesn't speak DHCP so it will
|
||||
need a static LAN address. You might also want to keep it away from
|
||||
your "real" LAN: see :ref:`bng` for some potentially useful tooling
|
||||
to use it on an isolated network.
|
||||
|
||||
|
||||
TFTP
|
||||
====
|
||||
@@ -290,18 +232,13 @@ Running tests
|
||||
*************
|
||||
|
||||
You can run all of the tests by evaluating :file:`ci.nix`, which is the
|
||||
input I use in Hydra. Note that it expects Nixpkgs stable `and` unstable
|
||||
as inputs, because it builds the qemu device against both.
|
||||
input I use in Hydra.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
nix-build --argstr liminix `pwd` --arg nixpkgs "<nixpkgs>" \
|
||||
--argstr unstable `pwd`/../unstable-nixpkgs/ ci.nix
|
||||
|
||||
To run a single named test, use the ``-A`` flag. For example, ``-A pppoe``
|
||||
|
||||
|
||||
|
||||
nix-build -I liminix=`pwd` ci.nix -A pppoe # run one job
|
||||
nix-build -I liminix=`pwd` ci.nix -A all # run all jobs
|
||||
|
||||
|
||||
Troubleshooting
|
||||
***************
|
||||
|
||||
+19
-12
@@ -1,4 +1,8 @@
|
||||
{ eval, lib, pkgs }:
|
||||
{
|
||||
eval,
|
||||
lib,
|
||||
pkgs,
|
||||
}:
|
||||
let
|
||||
conf = eval.config;
|
||||
rootDir = builtins.toPath ./..;
|
||||
@@ -7,21 +11,24 @@ let
|
||||
inherit name;
|
||||
description = opt.description or null;
|
||||
default = opt.default or null;
|
||||
visible =
|
||||
if (opt ? visible && opt.visible == "shallow")
|
||||
then true
|
||||
else opt.visible or true;
|
||||
visible = if (opt ? visible && opt.visible == "shallow") then true else opt.visible or true;
|
||||
readOnly = opt.readOnly or false;
|
||||
type = opt.type.description or "unspecified";
|
||||
};
|
||||
spliceServiceDefn = item :
|
||||
if item.type == "parametrisable s6-rc service definition"
|
||||
then
|
||||
let sd = lib.attrByPath item.loc ["not found"] conf;
|
||||
in item // {
|
||||
declarations = map stripAnyPrefixes item.declarations;
|
||||
spliceServiceDefn =
|
||||
item:
|
||||
if item.type == "parametrisable s6-rc service definition" then
|
||||
let
|
||||
sd = lib.attrByPath item.loc [ "not found" ] conf;
|
||||
in
|
||||
item
|
||||
// {
|
||||
declarations = map stripAnyPrefixes item.declarations;
|
||||
parameters =
|
||||
let x = lib.mapAttrsToList optToDoc sd.parameters; in x;
|
||||
let
|
||||
x = lib.mapAttrsToList optToDoc sd.parameters;
|
||||
in
|
||||
x;
|
||||
}
|
||||
else
|
||||
item // { declarations = map stripAnyPrefixes item.declarations; };
|
||||
|
||||
+6
-2
@@ -7,11 +7,15 @@ let
|
||||
n:
|
||||
let
|
||||
d = import ../devices/${n}/default.nix;
|
||||
tag = ".. _${lib.strings.replaceStrings [ " " ] [ "-" ] n}:";
|
||||
d' = {
|
||||
description = "${n}\n${substring 0 (stringLength n) "********************************"}\n";
|
||||
description = ''
|
||||
${n}
|
||||
${substring 0 (stringLength n) "********************************"}
|
||||
'';
|
||||
} // d;
|
||||
in
|
||||
d'.description
|
||||
"${tag}\n\n${d'.description}"
|
||||
) devices;
|
||||
in
|
||||
writeText "hwdoc" ''
|
||||
|
||||
@@ -7,6 +7,7 @@ Liminix
|
||||
|
||||
intro
|
||||
tutorial
|
||||
installation
|
||||
configuration
|
||||
admin
|
||||
development
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
Installation
|
||||
############
|
||||
|
||||
Hardware devices vary wildly in their affordances for installing new
|
||||
operating systems, so it should be no surprise that the Liminix
|
||||
installation procedure is hardware-dependent. This section contains
|
||||
generic instructions, but please refer to the documentation for your
|
||||
device to find whether and how well they apply.
|
||||
|
||||
|
||||
Building a firmware image
|
||||
*************************
|
||||
|
||||
Liminix uses the Nix language to provide congruent configuration
|
||||
management. This means that to change anything about the way in
|
||||
which a Liminix system works, you make that change in
|
||||
your :file:`configuration.nix` (or one of the other files it references),
|
||||
and rerun :command:`nix-build` to action
|
||||
the change. It is not possible (at least, without shenanigans) to make
|
||||
changes by logging into the device and running imperative commands
|
||||
whose effects may later be overridden: :file:`configuration.nix`
|
||||
always describes the entire system and can be used to recreate that
|
||||
system at any time. You can usefully keep it under version control.
|
||||
|
||||
If you are familiar with NixOS, you will notice some similarities
|
||||
between NixOS and Liminix configuration, and also some
|
||||
differences. Sometimes the differences are due to the
|
||||
resource-constrained devices we deploy onto, sometimes due to
|
||||
differences in the uses these devices are put to.
|
||||
|
||||
For a more full description of how to configure Liminix, see
|
||||
:ref:`configuration`. Assuming for the moment that you want a typical
|
||||
home wireless gateway/router, the best way to get started is to copy
|
||||
:file:`examples/rotuer.nix` and edit it for your requirements.
|
||||
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ cp examples/rotuer.nix configuration.nix
|
||||
$ vi configuration.nix # other editors are available
|
||||
$ # adjust this next command for your hardware device
|
||||
$ nix-build -I liminix-config=./configuration.nix \
|
||||
--arg device "import ./devices/gl-mt300a" -A outputs.default
|
||||
|
||||
Usually (not always, *please check the documentation for your device*)
|
||||
this will leave you with a file :file:`result/firmware.bin`
|
||||
which you now need to flash to the device.
|
||||
|
||||
|
||||
Flashing from the boot monitor (TFTP install)
|
||||
*********************************************
|
||||
|
||||
If you are prepared to open the device and have a TTL serial adaptor
|
||||
of some kind to connect it to, you can probably use U-Boot and a TFTP
|
||||
server to download and flash the image.
|
||||
|
||||
This is quite hardware-specific and may even involve soldering - see
|
||||
the documention for your device. However, it is in some ways the most
|
||||
"reliable" option: if you can see what's happening (or not happening)
|
||||
in early boot, the risk of "bricking" is substantially reduced and you
|
||||
have options for recovering if you misstep or flash a bad image.
|
||||
|
||||
|
||||
.. _serial:
|
||||
|
||||
U-Boot and serial shenanigans
|
||||
=============================
|
||||
|
||||
Every device that we have so far encountered in Liminix uses `U-Boot,
|
||||
the "Universal Boot Loader" <https://docs.u-boot.org/en/latest/>`_ so
|
||||
it's worth knowing a bit about it. "Universal" is in this context a
|
||||
bit of a misnomer, though: encountering *mainline* U-Boot is very rare
|
||||
and often you'll find it is a fork from some version last updated
|
||||
in 2008. Upgrading U-Boot is more or less complicated depending on the
|
||||
device and is outside scope for Liminix.
|
||||
|
||||
To speak to U-Boot on your device you'll usually need a serial
|
||||
connection to it. This typically involves opening the box, locating
|
||||
the serial header pins (TX, RX and GND) and connecting a USB TTL
|
||||
converter to them.
|
||||
|
||||
The Rolls Royce of USB/UART cables is the `FTDI cable
|
||||
<https://cpc.farnell.com/ftdi/ttl-232r-rpi/cable-debug-ttl-232-usb-rpi/dp/SC12825?st=usb%20to%20uart%20cable>`_,
|
||||
but there are cheaper alternatives based on the PL2303 and CP2102 chipsets - or you could even
|
||||
get creative and use the `UART GPIO pins <https://pinout.xyz/>`_ on a Raspberry Pi. Whatever you do, make sure
|
||||
that the voltages are compatible: if your device is 3.3V (this is
|
||||
typical but not universal), you don't want to be sending it 5v or
|
||||
(even worse) 12v.
|
||||
|
||||
Run a terminal emulator such as Minicom on the computer at other end
|
||||
of the link. 115200 8N1 is the typical speed.
|
||||
|
||||
.. NOTE::
|
||||
|
||||
TTL serial connections often have no flow control and
|
||||
so don't always like having massive chunks of text pasted into
|
||||
them - and U-Boot may drop characters while it's busy. So don't
|
||||
do that.
|
||||
|
||||
If using Minicom, you may find it helps to bring up the "Termimal
|
||||
settings" dialog (C^A T), then configure "Newline tx delay" to
|
||||
some small but non-zero value.
|
||||
|
||||
When you turn the router on you should be greeted with some messages
|
||||
from U-Boot, followed by the instruction to hit some key to stop
|
||||
autoboot. Do this and you will get to the prompt. If you didn't see
|
||||
anything, the strong likelihood is that TX and RX are the wrong way
|
||||
around. If you see garbage, try a different speed.
|
||||
|
||||
Interesting commands to try first in U-Boot are :command:`help` and
|
||||
:command:`printenv`.
|
||||
|
||||
You will also need to configure a TFTP server on a network that's
|
||||
accessible to the device: how you do that will vary according to which
|
||||
TFTP server you're using and so is out of scope for this document.
|
||||
|
||||
|
||||
|
||||
Building and installing the image
|
||||
=================================
|
||||
|
||||
Follow the device-specific instructions for "TFTP install": usually,
|
||||
the steps are
|
||||
|
||||
* build the `outputs.mtdimage` output
|
||||
* copy :file:`result/firmware.bin` to your TFTP server
|
||||
* copy/paste the commands in :file:`result/flash.scr` one at a time into the U-Boot command line
|
||||
* reset the device
|
||||
|
||||
You should now see messages from U-Boot, then from the Linux kernel
|
||||
and eventually a shell prompt.
|
||||
|
||||
.. NOTE:: Before you reboot, check which networks the device is
|
||||
plugged into, and disconnect as necessary. If you've just
|
||||
installed a DHCP server or anything similar that responds to
|
||||
broadcasts, you may not want it to do that on the network
|
||||
that you temporarily connected it to for installing it.
|
||||
|
||||
|
||||
|
||||
Flashing from OpenWrt
|
||||
*********************
|
||||
|
||||
.. CAUTION:: Untested! A previous version of these instructions
|
||||
(without the -e flag) led to bricking the device
|
||||
when flashing a jffs2 image. If you are reading
|
||||
this message, nobody has yet reported on whether the
|
||||
new instructions are any better.
|
||||
|
||||
If your device is running OpenWrt then it probably has the
|
||||
:command:`mtd` command installed. Build the `outputs.mtdimage` output
|
||||
(as you would for a TFTP install) and then transfer
|
||||
:file:`result/firmware.bin` onto the device using e.g.
|
||||
:command:`scp`. Now flash as follows:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
mtd -e -r write /tmp/firmware.bin firmware
|
||||
|
||||
The options to this command are for "erase before writing" and "reboot
|
||||
after writing".
|
||||
|
||||
For more information, please see the `OpenWrt manual <https://openwrt.org/docs/guide-user/installation/sysupgrade.cli>`_ which may also contain (hardware-dependent) instructions on how to flash an image using the vendor firmware - perhaps even from a web interface.
|
||||
|
||||
|
||||
Flashing from Liminix
|
||||
*********************
|
||||
|
||||
If the device is already running Liminix and has been configured with
|
||||
:command:`levitate`, you can use that to safely flash your new image.
|
||||
Refer to :ref:`levitate` for an explanation.
|
||||
|
||||
If the device is running Liminix but doesn't have :command:`levitate`
|
||||
your options are more limited. You may attempt to use
|
||||
:command:`flashcp` but it doesn't always work: as it copies the new
|
||||
image over the top of the active root filesystem, surprise may ensue.
|
||||
Consider instead using a serial connection: you may need one anyway
|
||||
after trying flashcp if it corrupts the image.
|
||||
|
||||
flashcp (not generally recommended)
|
||||
===================================
|
||||
|
||||
Connect to the device and locate the "firmware" partition, which you
|
||||
can do with a combination of :command:`dmesg` output and the contents
|
||||
of :file:`/proc/mtd`
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
<5>[ 0.469841] Creating 4 MTD partitions on "spi0.0":
|
||||
<5>[ 0.474837] 0x000000000000-0x000000040000 : "u-boot"
|
||||
<5>[ 0.480796] 0x000000040000-0x000000050000 : "u-boot-env"
|
||||
<5>[ 0.487056] 0x000000050000-0x000000060000 : "art"
|
||||
<5>[ 0.492753] 0x000000060000-0x000001000000 : "firmware"
|
||||
|
||||
# cat /proc/mtd
|
||||
dev: size erasesize name
|
||||
mtd0: 00040000 00001000 "u-boot"
|
||||
mtd1: 00010000 00001000 "u-boot-env"
|
||||
mtd2: 00010000 00001000 "art"
|
||||
mtd3: 00fa0000 00001000 "firmware"
|
||||
mtd4: 002a0000 00001000 "kernel"
|
||||
mtd5: 00d00000 00001000 "rootfs"
|
||||
|
||||
Copy :file:`result/firmware.bin` to the device and now run (in this
|
||||
example)
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
flashcp -v firmware.bin /dev/mtd3
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
Module options
|
||||
##############
|
||||
|
||||
.. include:: modules-generated.rst
|
||||
.. include:: modules-generated.inc.rst
|
||||
|
||||
+1
-1
@@ -10,4 +10,4 @@ different artefacts, or have different ways to get that artefact
|
||||
installed. The options available for a particular device are described in
|
||||
the section for that device.
|
||||
|
||||
.. include:: outputs-generated.rst
|
||||
.. include:: outputs-generated.inc.rst
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
(each [_ option (ipairs (sorted-options (yaml.load (io.read "*a"))))]
|
||||
(when (and (output? option) (not option.internal))
|
||||
(print (.. ".. _" (string.gsub option.name "%." "-") ":") "\n")
|
||||
(print option.description)))
|
||||
(print option.description "\n")))
|
||||
|
||||
+6
-3
@@ -71,7 +71,7 @@ stdin/stdout.
|
||||
You should now see Linux boot messages and after a few seconds be
|
||||
presented with a root shell prompt. You can run commands to look at
|
||||
the filesystem, see what processes are running, view log messages (in
|
||||
:file:/run/uncaught-logs.current), etc. To kill the emulator, press ^P
|
||||
:file:/run/log/current), etc. To kill the emulator, press ^P
|
||||
(Control P) then c to enter the "QEMU Monitor", then type ``quit`` at
|
||||
the ``(qemu)`` prompt.
|
||||
|
||||
@@ -293,14 +293,17 @@ the hostname) and then run
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
nix-shell --run "liminix-rebuild root@address-of-the-device -I liminix-config=./my-router.nix --arg device "import ./devices/gl-ar750""
|
||||
nix-build -I liminix-config=./my-router.nix \
|
||||
--arg device "import ./devices/gl-ar750" \
|
||||
-A outputs.systemConfiguration && \
|
||||
result/install.sh root@address-of-the-device
|
||||
|
||||
(This requires the device to be network-accessible from your build
|
||||
machine, which for a test/demo system might involve a second network
|
||||
device in your build system - USB ethernet adapters are cheap - or
|
||||