2
0

1 Commits

Author SHA1 Message Date
dan d7d2fb361a er, don\'t know? 2024-12-03 19:30:52 +00:00
52 changed files with 441 additions and 640 deletions
-24
View File
@@ -132,28 +132,4 @@ 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.
-131
View File
@@ -6539,134 +6539,3 @@ using a Makefile
idea 2: when a configuration contains levitate, something similar
but necessarily more "manual" to do the analogous thing
Sun Dec 15 18:55:55 GMT 2024
Where we left off with this, rotuer was crashing randomly or failing
to boot every time we tried to add log shipping, which is not very
ideal. I started doing something with logging to /dev/pmsg0
(CONFIG_PSTORE_PMSG) but I think (there seems not to be anything
written down :-( ) that the gl-ar750 kernel needs it added to kconfig and device tree
https://wiki.postmarketos.org/wiki/User:Knuxify/Enabling_pstore_and_ramoops
we could add a new hardware.dts.dtsi = [] option so that any module
could add a new chunk of dts. (Ideally we'd call it `includes`
but that conflicts with the existing use of `includes` to specify
search path. Maybe rename?)
would we ever use it except in a hardware device definition?
(Or user config?) I guess if we were consistent with names
then we could set up nodes in the device file with status="disabled"
and enable them in the module, except that dt doesn't consistently
use status and in fact there isn't one for reserved-memory
we could use global config to enable pstore_msg and check it in
the device module to enable the needed hw support
Tue Dec 17 23:39:28 GMT 2024
I think we can just stick a tee in the fallback logger pipeline that
writes to /dev/pmsg0
Need to check it's a circular buffer
do we want to do anything about recovering the log on boot?
- we could just copy it to /run/log
- if we have backfilling for shipped logs (we don't yet)
then we might want to ship it - but that may result in duplicate
logs if some of it was shipped before the crash
perhaps we should truncate pmsg0 on orderly shutdown? or maybe it's
good to see the late shutdown logs.
Thu Dec 19 13:40:39 GMT 2024
although we have PSTORE_foo in the omnia kconfig, I think this might
be just because I copied it from RT3200
Thu Dec 19 14:15:43 GMT 2024
Omnia is not in ci.nix, and it's not trivial to add it because there
is no output in the ci.nix configuration that makes sense for omnia.
... OK, fixed by adding system-configuration as an independent module
and importing in device config
Thu Dec 19 21:59:47 GMT 2024
The build-system shell script in outputs.systemConfiguration
is ugly and requires we do bad things to avoid sucking build
system stuff into the config
I propose we make it a separate derivation.
But first maybe we could improve some names
Sun Dec 22 14:23:02 GMT 2024
MT7622> echo $boot_default
if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_for
ever
MT7622> echo $bootcmd
if pstore check ; then run boot_recovery ; else run boot_ubi ; fi
MT7622> echo $boot_ubi
ubi part ubi && run boot_production ; run boot_recovery
MT7622> echo $boot_production
led $bootled_pwr on ; run ubi_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off
MT7622> echo $ubi_read_production
ubi read $loadaddr fit && iminfo $loadaddr && run ubi_prepare_rootfs
MT7622> echo $ubi_prepare_rootfs
if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi
MT7622> echo $bootconf
config-1
MT7622> run boot_ubi
UBI partition 'ubi' already selected
No size specified -> Using max size (126976)
Read 126976 bytes from volume fit to 0000000048000000
## Checking Image at 48000000 ...
Unknown image format!
No size specified -> Using max size (7491584)
Read 7491584 bytes from volume recovery to 0000000048000000
## Loading kernel from FIT Image at 48000000 ...
Using 'config-1' configuration
Trying 'kernel-1' kernel subimage
Description: ARM64 OpenWrt Linux-6.6.45
Sun Dec 22 17:39:56 GMT 2024
From the output above it looks like the device I have plugged in has
an openwrt "recovery" image but not a "production" image
It also looks like it will be quite hard work to persuade it to boot
from usb or anything. It doesn't have any of the extlinux stuff
but it does have uefi for what that's worth
default boot_production command reads a ubi volume called 'fit' and
calls bootm on what it finds
we could define boot_production to ubifsmount liminix; ubifs load
<addr> <filename> (which is a fit) and bootm it. *presumably* we could
do this from the openwrt recovery image
but could we install the whole system using said recovery image? I
expect we could do, it only requires getting a tarball onto it and
unpacking it
however, extlinux is not going to be helpful
(actually it might be a bit, if we ask it to write the fit as
well as/instead of the individual files)
maybe we need separate concepts of "the filesystem contains
stuff we need for boot" and "the stuff we need is the stuff
that extlinux needs"
each bootloader makes an output called bootfiles, and
the bootablerootdir output copies from bootfiles
Mon Dec 23 18:28:50 GMT 2024
it might be worth moving ubi option decls into the hardware module, if
they're hardware-dependent
+6 -12
View File
@@ -102,18 +102,12 @@ in {
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;
}];
forwardPorts = [ {
from = "host";
host.port = 7654;
# guest.address = "10.0.2.15";
guest.port =7654;
} ];
qemu = {
networkingOptions = [ ];
options =
-1
View File
@@ -12,7 +12,6 @@ let
"qemu-armv7l"
"tp-archer-ax23"
"zyxel-nwa50ax"
"turris-omnia"
];
vanilla = ./vanilla-configuration.nix;
for-device = name:
+14 -34
View File
@@ -7,10 +7,12 @@
and is "work in progress" in Liminix.
.. note:: The factory flash image contains ECC errors that make it
incompatible with Liminix: use the `OpenWrt
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 use
Liminix with it
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).
Hardware summary
================
@@ -25,33 +27,8 @@
Installation
============
Installation is currently a manual process.
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. You can do this in onw 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. Once it's finished booting into
Linux you can safely reboot
Installing Liminix
------------------
This is a manual process: you need a :ref:`serial <serial>` conection and TFTP : follow the instructions at :ref:`system-outputs-ubimage`
Installation is currently a manual process (you need a :ref:`serial <serial>` conection and
TFTP) following the instructions at :ref:`system-outputs-ubimage`
'';
@@ -75,10 +52,14 @@
../../modules/arch/aarch64.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/ubifs.nix
../../modules/outputs/ubimage.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}
'';
@@ -201,8 +182,7 @@
in {
ubi = {
minIOSize = "2048";
logicalEraseBlockSize = "126976";
physicalEraseBlockSize = "131072";
eraseBlockSize = "126976";
maxLEBcount = "1024"; # guessing
};
@@ -217,7 +197,7 @@
rootDevice = "ubi0:liminix";
dts = {
src = "${openwrt.src}/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts";
includePaths = [
includes = [
"${openwrt.src}/target/linux/mediatek/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
+5
View File
@@ -5,6 +5,11 @@
];
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";
+28 -11
View File
@@ -52,9 +52,8 @@
'';
module = {pkgs, config, lim, lib, ... }:
module = {pkgs, config, lim, ... }:
let
inherit (lib) mkIf;
openwrt = pkgs.openwrt;
firmwareBlobs = pkgs.pkgsBuildBuild.fetchFromGitHub {
owner = "kvalo";
@@ -115,15 +114,27 @@
eraseBlockSize = 65536;
};
rootDevice = "/dev/mtdblock5";
dts = {
src = "${openwrt.src}/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts";
includePaths = [
"${openwrt.src}/target/linux/ath79/dts"
];
includes = mkIf config.logging.persistent.enable [
./pstore-ramoops.dtsi
];
};
dts =
let
upstream = {
src = "${openwrt.src}/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts";
includes = [
"${openwrt.src}/target/linux/ath79/dts"
];
};
cppDtSearchFlags = builtins.concatStringsSep " " (map (f: "-I${f}") upstream.includes);
dtcSearchFlags = builtins.concatStringsSep " " (map (f: "-i${f}") upstream.includes);
patched = pkgs.runCommand "patch-dts" {
nativeBuildInputs = with pkgs.pkgsBuildBuild; [pkgs.stdenv.cc dtc ];
}
''
echo patching dts
${pkgs.stdenv.cc.targetPrefix}cpp -nostdinc -x assembler-with-cpp ${cppDtSearchFlags} -undef -D__DTS__ -o dts.tmp ${upstream.src}
dtc -I dts ${dtcSearchFlags} -o $out -O dts dts.tmp
'';
in upstream // { src = patched; };
networkInterfaces =
let inherit (config.system.service.network) link;
@@ -161,6 +172,12 @@
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
-9
View File
@@ -1,9 +0,0 @@
/ {
reserved-memory {
ramoops@03f00000 {
compatible = "ramoops";
reg = <0x03f00000 0x10000>;
pmsg-size = <0x10000>;
};
};
};
+6 -1
View File
@@ -81,7 +81,7 @@
dts = {
src = "${openwrt.src}/target/linux/ramips/dts/mt7620a_glinet_gl-mt300a.dts";
includePaths = [
includes = [
"${openwrt.src}/target/linux/ramips/dts"
];
};
@@ -114,6 +114,11 @@
};
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}
+6 -1
View File
@@ -78,7 +78,7 @@
dts = {
src = "${openwrt.src}/target/linux/ramips/dts/mt7628an_glinet_gl-mt300n-v2.dts";
includePaths = [
includes = [
"${openwrt.src}/target/linux/ramips/dts"
];
};
@@ -125,6 +125,11 @@
};
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}
'';
+1 -1
View File
@@ -66,7 +66,7 @@
# *correct* but it does at least boot
dts = lib.mkForce {
src = "${config.system.outputs.kernel.modulesupport}/arch/mips/boot/dts/mti/malta.dts";
includePaths = [
includes = [
"${config.system.outputs.kernel.modulesupport}/arch/mips/boot/dts/"
];
};
+6 -1
View File
@@ -50,6 +50,11 @@
];
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}
'';
@@ -405,7 +410,7 @@
rootDevice = "/dev/mtdblock3";
dts = {
src = "${openwrt.src}/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts";
includePaths = [
includes = [
"${openwrt.src}/target/linux/ramips/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
+8 -2
View File
@@ -172,6 +172,7 @@
../../modules/arch/arm.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/mbrimage.nix
../../modules/outputs/extlinux.nix
];
config = {
@@ -223,6 +224,11 @@
# 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"; # ???
@@ -335,14 +341,14 @@
targets = ["ath9k" "ath10k_pci"];
};
in {
defaultOutput = "updater";
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";
includePaths = [
includes = [
"${config.system.outputs.kernel.modulesupport}/arch/arm/boot/dts/marvell/"
];
};
+9 -3
View File
@@ -124,7 +124,7 @@
hash = "sha256-ifriAjWzFACrxVWCANZpUaEZgB/0pdbhnTVQytx6ddg=";
};
in {
imports = [
imports = [
# We include it to ensure the bridge functionality
# is available on the target kernel.
../../modules/bridge
@@ -184,7 +184,7 @@
# Actually, this is not what we want.
# This DTS is insufficient.
src = ./mt7621_zyxel_nwa50ax.dtsi;
includePaths = [
includes = [
# Here's one weird trick to make `ubi` detection
# out of the box.
# We will write ubi on /dev/firmware_a:rootfs location
@@ -233,7 +233,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,8 +250,14 @@
# 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 = {
+29 -52
View File
@@ -131,54 +131,50 @@ human-readable format, use :command:`s6-tai64nlocal`.
1970-01-02 21:51:48.832588765 wan.link.pppoe sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x667a9594> <pcomp> <accom
p>]
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.
Updating an installed system (JFFS2)
************************************
To check the previous messages after a (planned or forced) reboot,
you need to mooun the pstore filesystem.
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:
.. code-block:: console
# mount -t pstore pstore /sys/fs/pstore/
# ls -l /sys/fs/pstore/
-r--r--r-- 1 43071 pmsg-ramoops-0
# cat /sys/fs/pstore/pmsg-ramoops-0
@40000000000000282c997d29 mydevice klogd <6>[ 30.793756] int: port 2(wlan0) entered blocking state
[log messages from before the reboot follow]
nix-build -I liminix-config=./my-configuration.nix \
--arg device "import ./devices/mydevice" -A pkgs.tcpdump
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``
.. _rebuilding the system:
Updating an installed system
****************************
Rebuilding the 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.
Liminix has a mechanism for in-place updates of a running system which
is analogous to :command:`nixos-rebuild`, but its operation is a
bit different because it expects to run on a build machine and then
copy to the host device. To use this, build the `outputs.systemConfiguration`
target and then run the :command:`result/install.sh` script it generates.
.. code-block:: console
nix-build -I liminix-config=./my-configuration.nix \
--arg device "import ./devices/mydevice" \
-A outputs.updater
./result/bin/update.sh root@the-device
-A outputs.systemConfiguration
./result/install.sh root@the-device
The update script uses min-copy-closure to copy new or changed
The install 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:
@@ -191,6 +187,7 @@ behaviour can be affected by flags:
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
@@ -210,26 +207,6 @@ Caveats
.. _levitate:
Adding packages
===============
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
nix-build -I liminix-config=./my-configuration.nix \
--arg device "import ./devices/mydevice" -A pkgs.tcpdump
nix-shell -p min-copy-closure root@the-device result/
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:
Reinstalling on a running system
********************************
+47 -2
View File
@@ -1,12 +1,14 @@
{ config, pkgs, ... } :
{ config, pkgs, lib, ... } :
let
svc = config.system.service;
inherit (pkgs.liminix.services) longrun oneshot ;
in rec {
imports = [
../modules/network
../modules/dnsmasq
../modules/ssh
../modules/tls-certificate
];
hostname = "hello";
@@ -17,8 +19,51 @@ in rec {
family = "inet"; address ="10.3.0.1"; prefixLength = 16;
};
filesystem =
let inherit (pkgs.pseudofile) file dir symlink;
in dir {
etc = dir {
hosts = {
type = "f";
file = "127.0.0.1 localhost\n10.0.2.2 loaclhost.telent.net\n";
mode = "0444";
};
};
};
services.sshd = svc.ssh.build { };
services.lan-address-for-secrets =
svc.network.address.build {
interface = config.hardware.networkInterfaces.lan;
family = "inet"; address ="10.0.2.15"; prefixLength = 24;
};
# services.client-cert = svc.tls-certificate.certifix-client.build {
# caCertificate = builtins.readFile /var/lib/certifix/certs/ca.crt;
# subject = "C=GB,ST=London,O=Telent,OU=devices,CN=${config.hostname}";
# secret = builtins.readFile ../challengePassword;
# serviceUrl = "https://loaclhost.telent.net:19613/sign";
# };
# logging.shipping = {
# enable = true;
# service = longrun {
# name = "ship-logs";
# dependencies = [ config.services.client-cert ];
# run =
# let path = lib.makeBinPath (with pkgs; [ s6-networking s6 ]);
# in ''
# PATH=${path}:$PATH \
# CAFILE=${/var/lib/certifix/certs/ca.crt} \
# KEYFILE=$(output_path ${services.client-cert} key) \
# CERTFILE=$(output_path ${services.client-cert} cert) \
# s6-tlsclient -k loaclhost.telent.net -h -y loaclhost.telent.net 19612 \
# fdmove -c 1 7 cat
# '';
# };
# };
users.root = {
# the password is "secret". Use mkpasswd -m sha512crypt to
# create this hashed password string
@@ -38,6 +83,6 @@ in rec {
};
defaultProfile.packages = with pkgs; [
figlet
figlet openssl
];
}
+1
View File
@@ -22,6 +22,7 @@ in rec {
../modules/outputs/ubimage.nix
../modules/outputs/jffs2.nix
../modules/outputs/ext4fs.nix
../modules/outputs/extlinux.nix
];
kernel.config = {
+65 -4
View File
@@ -16,11 +16,11 @@ let
inherit (secrets) wpa_passphrase;
wmm_enabled = 1;
};
inherit (pkgs.liminix.services) longrun;
in rec {
boot = {
tftp = {
freeSpaceBytes = 3 * 1024 * 1024;
freeSpaceBytes = 2 * 1024 * 1024;
serverip = "10.0.0.1";
ipaddr = "10.0.0.8";
};
@@ -28,8 +28,24 @@ in rec {
imports = [
"${modulesPath}/profiles/gateway.nix"
"${modulesPath}/tls-certificate"
];
hostname = "rotuer";
# rootfsType = "jffs2";
filesystem =
let inherit (pkgs.pseudofile) file dir symlink;
in dir {
mnt = dir {};
etc = dir {
hosts = {
type = "f";
file = "127.0.0.1 localhost\n10.0.0.1 loaclhost.telent.net\n";
mode = "0444";
};
};
};
profile.gateway = {
lan = {
@@ -106,9 +122,11 @@ in rec {
defaultProfile.packages = with pkgs; [
min-collect-garbage
nftables
strace
tcpdump
# strace
# tcpdump
s6
dtc
# certifix-client
];
programs.busybox = {
@@ -119,4 +137,47 @@ in rec {
FEATURE_FANCY_TAIL = "y";
};
};
services.wan-address-for-secrets =
let
interface = config.hardware.networkInterfaces.wan;
addr =
svc.network.address.build {
inherit interface;
family = "inet"; address ="10.0.0.10"; prefixLength = 24;
};
in svc.network.route.build {
target = "10.0.0.1";
inherit interface;
via = "10.0.0.10";
metric = 1;
dependencies = [ addr ];
};
# services.client-cert = svc.tls-certificate.certifix-client.build {
# caCertificate = builtins.readFile /var/lib/certifix/certs/ca.crt;
# subject = "C=GB,ST=London,O=Telent,OU=devices,CN=${config.hostname}";
# secret = builtins.readFile ../challengePassword;
# serviceUrl = "https://loaclhost.telent.net:19613/sign";
# dependencies = [ services.wan-address-for-secrets ];
# };
logging.pstore = true;
logging.shipping = {
enable = false;
service = longrun {
name = "ship-logs";
dependencies = [ config.services.client-cert ];
run =
let path = lib.makeBinPath (with pkgs; [ s6-networking s6 ]);
in ''
PATH=${path}:$PATH \
CAFILE=${/var/lib/certifix/certs/ca.crt} \
KEYFILE=$(output_path ${services.client-cert} key) \
CERTFILE=$(output_path ${services.client-cert} cert) \
s6-tlsclient -k loaclhost.telent.net -h -y loaclhost.telent.net 19612 \
fdmove -c 1 7 cat
'';
};
};
}
+1
View File
@@ -30,6 +30,7 @@
./outputs/vmroot.nix
./ppp
./ramdisk.nix
./squashfs.nix
./ssh
./users.nix
./vlan
+1 -12
View File
@@ -13,12 +13,6 @@ in
options = {
boot = { };
hardware = {
ubi = {
minIOSize = mkOption { type = types.str; };
logicalEraseBlockSize = mkOption { type = types.str; }; # LEB
physicalEraseBlockSize = mkOption { type = types.str; }; # PEB
maxLEBcount = mkOption { type = types.str; }; # LEB
};
dts = {
src = mkOption {
type = types.nullOr types.path;
@@ -30,14 +24,9 @@ in
only for QEMU.
'';
};
includePaths = mkOption {
default = [ ];
description = "List of directories to search for DTS includes (.dtsi files)";
type = types.listOf types.path;
};
includes = mkOption {
default = [ ];
description = "\"dtsi\" fragments to include in the generated device tree";
description = "List of directories to search for DTS includes (.dtsi files)";
type = types.listOf types.path;
};
};
+12 -8
View File
@@ -6,7 +6,7 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types ;
inherit (pkgs) liminix openwrt;
inherit (pkgs) liminix;
mergeConditionals = conf : conditions :
# for each key in conditions, if it is present in conf
@@ -21,8 +21,8 @@ let
in {
options = {
kernel = {
src = mkOption { type = types.path; default = openwrt.kernelSrc; } ;
version = mkOption { type = types.str; default = openwrt.kernelVersion;} ;
src = mkOption { type = types.path; } ;
version = mkOption { type = types.str; default = "5.15.137";} ;
modular = mkOption {
type = types.bool;
default = true;
@@ -68,15 +68,19 @@ in {
};
};
config = {
system.outputs.kernel =
system.outputs =
let
mergedConfig = mergeConditionals
config.kernel.config
config.kernel.conditionalConfig;
in liminix.builders.kernel.override {
config = mergedConfig;
inherit (config.kernel) version src extraPatchPhase;
targets = config.kernel.makeTargets;
k = liminix.builders.kernel.override {
config = mergedConfig;
inherit (config.kernel) version src extraPatchPhase;
targets = config.kernel.makeTargets;
};
in {
kernel = k.vmlinux;
zimage = k.zImage;
};
kernel = rec {
+34 -16
View File
@@ -11,12 +11,9 @@ let
in
{
imports = [
./outputs/squashfs.nix
./squashfs.nix
./outputs/vmroot.nix
./outputs/boot-extlinux.nix
./outputs/boot-fit.nix
./outputs/uimage.nix
./outputs/updater
./outputs/extlinux.nix
];
options = {
system.outputs = {
@@ -30,7 +27,17 @@ in
kernel
******
Kernel package (multi-output derivation)
Kernel vmlinux file (usually ELF)
'';
};
zimage = mkOption {
type = types.package;
internal = true;
description = ''
zimage
******
Kernel in compressed self-extracting package
'';
};
dtb = mkOption {
@@ -43,6 +50,16 @@ in
Compiled device tree (FDT) for the target device
'';
};
uimage = mkOption {
type = types.package;
internal = true;
description = ''
uimage
******
Combined kernel and FDT in uImage (U-Boot compatible) format
'';
};
tplink-safeloader = mkOption {
type = types.package;
};
@@ -65,12 +82,6 @@ in
directory of files to package into root filesystem
'';
};
bootfiles = mkOption {
type = types.nullOr types.package;
internal = true;
default = null;
# description = "";
};
bootablerootdir = mkOption {
type = types.package;
internal = true;
@@ -93,11 +104,18 @@ in
system.outputs = rec {
dtb = liminix.builders.dtb {
inherit (config.boot) commandLine;
dts = [config.hardware.dts.src] ++ config.hardware.dts.includes;
includes = config.hardware.dts.includePaths ++ [
dts = config.hardware.dts.src;
includes = config.hardware.dts.includes ++ [
"${o.kernel.headers}/include"
];
};
uimage = liminix.builders.uimage {
commandLine = concatStringsSep " " config.boot.commandLine;
inherit (config.boot) commandLineDtbNode;
inherit (config.hardware) loadAddress entryPoint alignment;
inherit (config.boot) imageFormat;
inherit (o) kernel dtb;
};
rootdir =
let
inherit (pkgs.pkgsBuildBuild) runCommand;
@@ -114,8 +132,8 @@ in
let inherit (pkgs.pkgsBuildBuild) runCommand;
in runCommand "add-slash-boot" { } ''
cp -a ${o.rootdir} $out
${if o.bootfiles != null
then "(cd $out && chmod -R +w . && rmdir boot && cp -a ${o.bootfiles} boot)"
${if config.boot.loader.extlinux.enable
then "(cd $out && chmod -R +w . && rmdir boot && cp -a ${o.extlinux} boot)"
else ""
}
'';
-27
View File
@@ -1,27 +0,0 @@
{
config
, pkgs
, lib
, ...
}:
let
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep;
inherit (pkgs.pseudofile) dir symlink;
cfg = config.boot.loader.fit;
o = config.system.outputs;
cmdline = concatStringsSep " " config.boot.commandLine;
wantsDtb = config.hardware.dts ? src && config.hardware.dts.src != null;
in {
options.boot.loader.fit.enable = mkEnableOption "FIT in /boot";
config = mkIf cfg.enable {
system.outputs.bootfiles = pkgs.runCommand "boot-fit" {} ''
mkdir $out
cd $out
cp ${o.uimage} fit
'';
filesystem = dir {
boot = symlink config.system.outputs.bootfiles;
};
};
}
@@ -12,15 +12,19 @@ let
cmdline = concatStringsSep " " config.boot.commandLine;
wantsDtb = config.hardware.dts ? src && config.hardware.dts.src != null;
in {
options.system.outputs.extlinux = mkOption {
type = types.package;
# description = "";
};
options.boot.loader.extlinux.enable = mkEnableOption "extlinux";
config = mkIf cfg.enable {
system.outputs.bootfiles = pkgs.runCommand "extlinux" {} ''
system.outputs.extlinux = pkgs.runCommand "extlinux" {} ''
mkdir $out
cd $out
${if wantsDtb then "cp ${o.dtb} dtb" else "true"}
cp ${o.initramfs} initramfs
cp ${o.kernel.zImage} kernel
cp ${o.zimage} kernel
mkdir extlinux
cat > extlinux/extlinux.conf << _EOF
menu title Liminix
@@ -33,7 +37,7 @@ in {
_EOF
'';
filesystem = dir {
boot = symlink config.system.outputs.bootfiles;
boot = symlink config.system.outputs.extlinux;
};
};
}
+10 -1
View File
@@ -9,7 +9,6 @@ let
inherit (pkgs) runCommand;
in
{
imports = [ ./system-configuration.nix ];
options = {
boot.initramfs = {
enable = mkEnableOption "initramfs";
@@ -23,6 +22,14 @@ in
filesystem
'';
};
systemConfiguration = mkOption {
type = types.package;
description = ''
pkgs.systemconfig for the configured filesystem,
contains 'activate' and 'init' commands
'';
internal = true;
};
};
};
config = mkIf config.boot.initramfs.enable {
@@ -46,6 +53,8 @@ in
file /init ${pkgs.preinit}/bin/preinit 0755 0 0
SPECIALS
'';
systemConfiguration =
pkgs.systemconfig config.filesystem.contents;
};
};
}
-28
View File
@@ -1,28 +0,0 @@
{
config
, pkgs
, lib
, ...
}:
let
inherit (lib) mkEnableOption mkOption mkIf types;
inherit (pkgs) runCommand;
in
{
options = {
system.outputs = {
systemConfiguration = mkOption {
type = types.package;
description = ''
pkgs.systemconfig for the configured filesystem,
contains 'activate' and 'init' commands
'';
internal = true;
};
};
};
config = {
system.outputs.systemConfiguration =
pkgs.systemconfig config.filesystem.contents;
};
}
+1 -1
View File
@@ -61,7 +61,7 @@ in {
o = config.system.outputs;
image = let choices = {
uimage = o.uimage;
zimage = o.kernel.zImage;
zimage = o.zimage;
}; in choices.${cfg.kernelFormat};
bootCommand = let choices = {
uimage = "bootm";
+13 -1
View File
@@ -13,6 +13,18 @@ in
./initramfs.nix
];
options.system.outputs.rootubifs = mkOption {
type = types.package;
internal = true;
};
options.hardware.ubi = {
minIOSize = mkOption { type = types.str; };
logicalEraseBlockSize = mkOption { type = types.str; }; # LEB
physicalEraseBlockSize = mkOption { type = types.str; }; # PEB
maxLEBcount = mkOption { type = types.str; }; # LEB
};
config = mkIf (config.rootfsType == "ubifs") {
kernel.config = {
MTD_UBI="y";
@@ -21,7 +33,7 @@ in
};
boot.initramfs.enable = true;
system.outputs = {
rootfs =
rootubifs =
let
inherit (pkgs.pkgsBuildBuild) runCommand mtdutils;
cfg = config.hardware.ubi;
+16 -15
View File
@@ -82,11 +82,12 @@ automatically, you can try booting it by hand to see if it works:
.. code-block:: console
uboot> ubifsmount ubi0:liminix
uboot> ubifsload ''${loadaddr} boot/fit
uboot> ubifsload ''${loadaddr} boot/uimage
uboot> bootm ''${loadaddr}
Once you've done this and you're happy with it, reset the device to
return to U-Boot.
U-Boot. You don't need to recreate the volume but you do need to
repeat step 3.
5) Instructions for configuring autoboot are likely to be very
device-dependent. On the Linksys E8450/Belkin RT3200, the environment
@@ -95,10 +96,7 @@ you could do
.. code-block:: console
uboot> setenv orig_boot_production $boot_production
uboot> setenv boot_production 'led $bootled_pwr on ; ubifsmount ubi0:liminix && ubifsload ''${loadaddr} boot/fit && bootm ''${loadaddr}'
uboot> saveenv
uboot> reset
uboot> setenv boot_production 'led $bootled_pwr on ; ubifsmount ubi0:liminix; ubifsload ''${loadaddr} boot/uimage; bootm ''${loadaddr}'
On other devices, some detective work may be needed. Try running
`printenv` and look for likely commands, try looking at the existing
@@ -113,13 +111,16 @@ boot process, maybe even try looking for documentation for that device.
};
};
config.system.outputs.ubimage =
assert config.rootfsType == "ubifs";
let o = config.system.outputs; in
pkgs.runCommand "ubimage" {} ''
mkdir $out
cd $out
ln -s ${o.rootfs} rootfs
ln -s ${instructions} env.scr
'';
config = mkIf (config.rootfsType == "ubifs") {
system.outputs = {
ubimage =
let o = config.system.outputs; in
pkgs.runCommand "ubimage" {} ''
mkdir $out
cd $out
ln -s ${o.rootfs} rootfs
ln -s ${instructions} env.scr
'';
};
};
}
+2 -5
View File
@@ -18,9 +18,6 @@ in
eraseBlockSize = mkOption { type = types.str; }; # LEB
maxLEBcount = mkOption { type = types.str; }; # LEB
};
options.system.outputs.ubivolume = mkOption {
type = types.package;
};
config = mkIf (config.rootfsType == "ubifs") {
kernel.config = {
@@ -31,7 +28,7 @@ in
};
boot.initramfs.enable = true;
system.outputs.ubivolume =
system.outputs.rootfs =
let
inherit (pkgs.pkgsBuildBuild) runCommand;
ubiVolume = ({ name, volumeId, image, flags ? [] }:
@@ -84,7 +81,7 @@ in
]);
disk = ubiDisk {
initramfs = config.system.outputs.rootfs; # ???
initramfs = config.system.outputs.rootubifs; # liminix.builders.squashfs config.filesystem.contents; # # assert this is a proper FIT.
};
in
-30
View File
@@ -1,30 +0,0 @@
{
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkOption types concatStringsSep;
inherit (pkgs) liminix writeText;
o = config.system.outputs;
in
{
options.system.outputs.uimage = mkOption {
type = types.package;
internal = true;
description = ''
uimage
******
Combined kernel and FDT in uImage (U-Boot compatible) format
'';
};
config.system.outputs.uimage = liminix.builders.uimage {
commandLine = concatStringsSep " " config.boot.commandLine;
inherit (config.boot) commandLineDtbNode;
inherit (config.hardware) loadAddress entryPoint alignment;
inherit (config.boot) imageFormat;
inherit (o) kernel dtb;
};
}
-36
View File
@@ -1,36 +0,0 @@
{
config
, pkgs
, lib
, ...
}:
let
inherit (lib) mkIf;
o = config.system.outputs;
inherit (pkgs) runCommand;
inherit (lib) mkOption types;
inherit (pkgs.buildPackages) min-copy-closure;
in
{
imports = [ ../system-configuration.nix ];
options.system.outputs.updater = mkOption {
type = types.package;
description = ''
updater
******
For configurations with a writable filesystem, create a shell
script that runs on the build system and updates the device
over the network to the new configuration
'';
};
config.system.outputs.updater =
runCommand "buildUpdater" { } ''
mkdir -p $out/bin
substitute ${./update.sh} $out/bin/update.sh \
--subst-var-by toplevel ${o.systemConfiguration} \
--subst-var-by min_copy_closure ${min-copy-closure}
chmod +x $out/bin/update.sh
'';
}
+2 -2
View File
@@ -31,7 +31,7 @@ on a system with pre-existing firmware and OS.
config = mkIf (config.rootfsType == "ubifs") {
system.outputs.zyxel-nwa-fit =
let
let
o = config.system.outputs;
# 8129kb padding.
paddedKernel = pkgs.runCommand "padded-kernel" {} ''
@@ -39,7 +39,7 @@ on a system with pre-existing firmware and OS.
dd if=/dev/zero of=$out bs=1 count=1 seek=8388607
'';
firmwareImage = pkgs.runCommand "firmware-image" {} ''
cat ${paddedKernel} ${o.ubivolume} > $out
cat ${paddedKernel} ${o.rootfs} > $out
'';
dts = pkgs.writeText "image.its" ''
/dts-v1/;
+7 -3
View File
@@ -24,17 +24,21 @@ let
echo $4 > address
echo $5 > peer-address
set +o nounset
set +o errexit
if test -n "''${DNS1}" ;then echo ''${DNS1} > ns1 ; fi
if test -n "''${DNS2}" ;then echo ''${DNS2} > ns2 ; fi
test -e ipv6-address && echo >/proc/self/fd/10
set +o pipefail
ls -l /proc/self/fd
echo >/proc/self/fd/10
'';
ip6-up = writeAshScript "ip6-up" {} ''
exec >&5 2>&5
. ${serviceFns}
in_outputs ${name}
set +o nounset
set +o errexit
echo $4 > ipv6-address
echo $5 > ipv6-peer-address
test -e ifname && echo >/proc/self/fd/10
'';
literal_or_output =
let v = o: ({
@@ -73,7 +77,7 @@ let
chmod 0700 /run/${name}
in_outputs ${name}
echo ${escapeShellArgs ppp-options'} | ${output-template}/bin/output-template '{{' '}}' > /run/${name}/ppp-options
fdmove -c 5 2 \
exec fdmove -c 5 2 \
${command}
'';
notification-fd = 10;
+1 -1
View File
@@ -24,7 +24,7 @@ let
in common {
inherit name debug username password lcpEcho ppp-options;
command = ''
exec ${ppp}/bin/pppd pty "${pppoe}/bin/pppoe ${timeoutOpt} -I $(output ${interface} ifname)" file /run/${name}/ppp-options
${ppp}/bin/pppd pty "${pppoe}/bin/pppoe ${timeoutOpt} -I $(output ${interface} ifname)" file /run/${name}/ppp-options
'';
dependencies = [ interface ];
}
+24 -23
View File
@@ -7,27 +7,10 @@ let
s6-linux-init
stdenvNoCC;
inherit (lib.lists) unique concatMap;
inherit (lib) concatStrings;
inherit (builtins) map;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.services) oneshot bundle longrun;
inherit (lib) mkIf mkEnableOption mkOption types;
cfg = config.logging;
logger =
let pipecmds =
["${s6}/bin/s6-log -bpd3 -- ${cfg.script} 1"] ++
(lib.optional cfg.persistent.enable
"/bin/tee /dev/pmsg0") ++
(lib.optional cfg.shipping.enable
"${pkgs.logshipper}/bin/logtap ${cfg.shipping.socket} logshipper-socket-event");
in ''
#!${execline}/bin/execlineb -P
${execline}/bin/redirfd -w 1 /dev/null
${execline}/bin/redirfd -rnb 0 fifo
${concatStrings (map (l: "pipeline { ${l} }\n") pipecmds)}
${s6}/bin/s6-log -- ${cfg.directory}
'';
s6-rc-db =
let
# In the default bundle we need to have all the services
@@ -123,7 +106,26 @@ let
mode = "0600";
};
notification-fd = { file = "3"; };
run = { file = logger; mode = "0755"; };
run = {
file =
let pstore = if cfg.pstore then "pipeline { tee /dev/pmsg0 }" else "";
in ''
#!${execline}/bin/execlineb -P
${execline}/bin/redirfd -w 1 /dev/null
${execline}/bin/redirfd -rnb 0 fifo
${if cfg.shipping.enable then ''
pipeline { ${s6}/bin/s6-log -bpd3 -- ${cfg.script} 1 }
pipeline { ${pkgs.logshipper}/bin/logtap ${cfg.shipping.socket} logshipper-socket-event }
${pstore}
${s6}/bin/s6-log -- ${cfg.directory}
'' else ''
pipeline { ${s6}/bin/s6-log -bpd3 -- ${cfg.script} 1 }
${pstore}
${s6}/bin/s6-log -- ${cfg.directory}
''}
'';
mode = "0755";
};
};
getty = dir {
run = {
@@ -215,9 +217,7 @@ let
in {
options = {
logging = {
persistent = {
enable = mkEnableOption "store logs across reboots";
};
pstore = mkEnableOption "system logs in pstore for retention after reboot";
shipping = {
enable = mkEnableOption "unix socket for log shipping";
socket = mkOption {
@@ -269,11 +269,12 @@ in {
)];
config = {
kernel.config = mkIf config.logging.persistent.enable {
kernel.config = mkIf cfg.pstore {
PSTORE = "y";
PSTORE_PMSG = "y";
PSTORE_RAM = "y";
};
programs.busybox.applets = mkIf cfg.pstore [ "tee" ];
filesystem = dir {
etc = dir {
s6-rc = dir {
+6 -7
View File
@@ -5,7 +5,7 @@ let
extraPkgs = import ./pkgs/default.nix {
inherit (final) lib callPackage;
};
inherit (final) fetchpatch lib;
inherit (final) fetchpatch;
luaHost =
let
l = prev.lua5_3.overrideAttrs(o: {
@@ -73,15 +73,14 @@ extraPkgs // {
});
in chrony'.override {
gnutls = null;
nss = null;
nspr = null;
readline = null;
libedit = null;
libseccomp = null;
# should texinfo be in nativeBuildInputs instead of
# buildInputs?
texinfo = null;
} // lib.optionalAttrs (lib.versionOlder lib.version "24.10") {
nss = null;
nspr = null;
readline = null;
};
# clevis without luks/tpm
@@ -218,11 +217,11 @@ extraPkgs // {
] ++ final.lib.optionals (o ? patches) o.patches;
});
mtdutils = (prev.mtdutils.overrideAttrs(o: {
mtdutils = prev.mtdutils.overrideAttrs(o: {
patches = (if o ? patches then o.patches else []) ++ [
./pkgs/mtdutils/0001-mkfs.jffs2-add-graft-option.patch
];
})).override { util-linux = final.util-linux-small ; };
});
nftables = prev.nftables.overrideAttrs(o: {
configureFlags = [
+1
View File
@@ -3,6 +3,7 @@
;; e.g. (import-macros { : expect= } :anoia.assert)
(fn expect [assertion]
(let [msg (.. "expectation failed: " (view assertion))]
`(when (not ,assertion)
+1
View File
@@ -82,6 +82,7 @@
(let [p (find-executable "yes" (os.getenv "PATH"))]
(expect (string.match p "coreutils.+bin/yes$"))))
{
: mktree
: rmtree
+22 -41
View File
@@ -1,4 +1,8 @@
(import-macros { : define-tests : expect : expect= } :anoia.assert)
;; importing assert.fnl macros here would be circular, so we can't use
;; the full test functionality
(macro define-tests [& body]
(when _G.RUNNING_TESTS
`(do ,(unpack body))))
(fn assoc [tbl k v & more]
(tset tbl k v)
@@ -28,18 +32,6 @@
(fn dirname [path]
(string.match path "(.*)/[^/]-$"))
(fn append-path [dirname filename]
(let [base (or (string.match dirname "(.*)/$") dirname)
result []]
(each [component (string.gmatch filename "([^/]+)")]
(if (and (= component "..") (> (# result) 0))
(table.remove result)
(= component "..")
(error "path traversal attempt")
true
(table.insert result component)))
(.. base "/" (table.concat result "/"))))
(fn system [s]
(match (os.execute s)
res (do (print (.. "Executed \"" s "\", exit code " (tostring res))) res)
@@ -67,28 +59,16 @@
(and present (. a k))))))
(define-tests
(expect (table= {:a 1 :b 2} {:b 2 :a 1}))
(expect (not (table= {:a 1 :b 2 :k :l} {:b 2 :a 1})))
(expect (not (table= {:a 1 :b 2} {:b 2 :a 1 :k :l})))
(assert (table= {:a 1 :b 2} {:b 2 :a 1}))
(assert (not (table= {:a 1 :b 2 :k :l} {:b 2 :a 1})))
(assert (not (table= {:a 1 :b 2} {:b 2 :a 1 :k :l})))
(expect (table= {:a 1 :b {:l 17}} {:b {:l 17} :a 1}))
(expect (table= {:a [4 5 6 7] } {:a [4 5 6 7]}))
(expect (not (table= {:a [4 5 6 7] } {:a [4 5 6 7 8]})))
(expect (not (table= {:a [4 5 7 6] } {:a [4 5 6 7 ]})))
(assert (table= {:a 1 :b {:l 17}} {:b {:l 17} :a 1}))
(assert (table= {:a [4 5 6 7] } {:a [4 5 6 7]}))
(assert (not (table= {:a [4 5 6 7] } {:a [4 5 6 7 8]})))
(assert (not (table= {:a [4 5 7 6] } {:a [4 5 6 7 ]})))
(expect (table= {} {}))
(let [traps (fn [b p]
(match (pcall append-path b p)
(true f) (error "didn't trap path traversal")
(false err) (expect (string.match err "path traversal"))))]
(expect= (append-path "/tmp" "hello") "/tmp/hello")
(expect= (append-path "/tmp/" "hello") "/tmp/hello")
(expect= (append-path "/tmp/" "///hello") "/tmp/hello")
(expect= (append-path "/tmp/" "///hello/../fish") "/tmp/fish")
(traps "/tmp/" "../hello")
(expect= (append-path "/tmp/" "hello/../goodbye") "/tmp/goodbye")
(traps "/tmp/" "hello/../../goodbye"))
(assert (table= {} {}))
)
(fn dig [tree path]
@@ -197,17 +177,17 @@
b64 (base64 :url)]
(let [a (b64:decode "YWxsIHlvdXIgYmFzZQ==")]
(expect= a "all your base"))
(assert (= a "all your base") (view a)))
(let [a (b64:decode "ZmVubmVsIHRoaW5n")]
(expect= a "fennel thing"))
(assert (= a "fennel thing") a))
(let [a (b64:decode "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms=")]
(expect= a "Many hands make light work"))
(assert (= a "Many hands make light work") (view a)))
(let [a (b64:encode "hello world")]
(expect= a "aGVsbG8gd29ybGQ="))
(assert (= a "aGVsbG8gd29ybGQ=") a))
(fn check [plain enc]
(let [a (b64:encode plain)] (expect (= a enc) (.. "encode " a)))
(let [a (b64:decode enc)] (expect (= a plain) (.. "decode " a))))
(let [a (b64:encode plain)] (assert (= a enc) (.. "encode " a)))
(let [a (b64:decode enc)] (assert (= a plain) (.. "decode " a))))
(check "" "")
(check "f" "Zg==")
@@ -218,10 +198,12 @@
(check "foobar" "Zm9vYmFy")
(let [x (b64:decode "REtOdUtNS05BNEJWLXdfcUhtNU9YV2liOUxkX3RTdVJTQWVUR0dkWldBdVEyaURObDZ2b3pSbEJwMzlzOEltdkhWdmpzZmMiLCJ5IjoiQVlDY1QwOGZrNFZWZ2lZSVIxbkU4UlJGaGZOSGdBUEFzckRITmJtRGNfUGtWZmdDR0xTMTIweU5SNncwdjd5RUY4WDN1OGpvazhkU0pqN0hnWjZCZHAzcSJ9LCJraWQiOiJlalVDaXBCUE9BeDRWQ1dQdUtkVGlYNDNadW5XTDNjSWN6V1h1RVZyTVNFIn0")]
(expect (string.match x "}$") x))
(assert (string.match x "}$") x))
))
;; doesn't work if the padding is missing
;; (let [a (from-base64 "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms")]
;; (assert (= a "Many hands make light work") (view a)))
@@ -230,7 +212,6 @@
{
: append-path
: assoc
: base64
: base64url
+2 -10
View File
@@ -2,8 +2,6 @@
stdenv
, dtc
, lib
, runCommand
, writeText
}:
{ dts
, includes
@@ -12,20 +10,14 @@
cppDtSearchFlags = builtins.concatStringsSep " " (map (f: "-I${f}") includes);
dtcSearchFlags = builtins.concatStringsSep " " (map (f: "-i${f}") includes);
cmdline = lib.concatStringsSep " " commandLine;
chosen = writeText "chosen.dtsi" "/{ chosen { bootargs = ${builtins.toJSON cmdline}; }; };";
combined = writeText "combined-dts-fragments"
(lib.concatStrings
(builtins.map
(f: "#include \"${f}\"\n")
(dts ++ [ chosen ])));
in stdenv.mkDerivation {
name = "dtb";
phases = [ "buildPhase" ];
nativeBuildInputs = [ dtc ];
buildPhase = ''
${stdenv.cc.targetPrefix}cpp -nostdinc -x assembler-with-cpp ${cppDtSearchFlags} -undef -D__DTS__ -o dtb.tmp ${combined}
${stdenv.cc.targetPrefix}cpp -nostdinc -x assembler-with-cpp ${cppDtSearchFlags} -undef -D__DTS__ -o dtb.tmp ${dts}
echo '/{ chosen { bootargs = ${builtins.toJSON cmdline}; }; };' >> dtb.tmp
dtc ${dtcSearchFlags} -I dts -O dtb -o $out dtb.tmp
# dtc -I dtb -O dts $out
test -e $out
'';
}
-11
View File
@@ -29,17 +29,6 @@ let
'';
in {
inherit src;
# The kernel sources typically used with this version of openwrt
# You can find this in `include/kernel-5.15` or similar in the
# openwrt sources
kernelSrc = 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=";
};
kernelVersion = "5.15.137";
applyPatches.ath79 = doPatch "ath79";
applyPatches.ramips = doPatch "ramips";
applyPatches.mediatek = doPatch "mediatek"; # aarch64
@@ -1,19 +1,22 @@
#!/usr/bin/env bash
# this shell script is run on the build system to min-copy-closure the
# system configuration onto the device and reboot/restart services as
# requested
# this shell script can be run on the build system to
# min-copy-closure the system configuration onto the device
# and reboot/restart services as requested
die() {
echo "$@"
exit 1
}
# add min-copy-closure to the path. removing junk characters
# inserted by default.nix (q.v.)
min_copy_closure=@min-copy-closure@; PATH=${min_copy_closure//_/}/bin:$PATH
PATH=@min_copy_closure@/bin:$PATH
ssh_command=${SSH_COMMAND-ssh}
reboot="reboot"
case "$1" in
"--no-reboot")
unset reboot
@@ -31,11 +34,10 @@ shift
test -n "$target_host" || \
die "Usage: $0 [--no-reboot] [--fast] target-host"
toplevel=$(realpath @toplevel@)
toplevel=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && readlink `pwd` )
test -e $toplevel/etc/nix-store-paths || die "missing etc/nix-store-paths, is this really a system configuration?"
echo installing from systemConfiguration $toplevel to host $target_host
$ssh_command $target_host uname -a || die "Can't ssh to $target_host"
min-copy-closure $target_host $toplevel
set -x
$ssh_command $target_host $toplevel/bin/install
+18 -13
View File
@@ -56,33 +56,38 @@ let
else "";
in "unlink(${qpathname}); ${cmd} ${chown}";
in mapAttrsToList (makeFile prefix) attrset;
activateScript = attrset: writeText "makedevs.c" ''
#include "defs.h"
int main(int argc, char* argv[]) {
chdir(argv[1]);
${(builtins.concatStringsSep "\n" (visit "." attrset))}
}
'';
in attrset:
let
activateScript = writeText "activate.c" ''
#include "defs.h"
int main(int argc, char* argv[]) {
chdir(argv[1]);
${(builtins.concatStringsSep "\n" (visit "." attrset))}
}
'';
let makedevs = activateScript attrset;
in stdenv.mkDerivation {
name="system-configuration";
name="make-stuff";
src = ./.;
CFLAGS = "-Os";
LDFLAGS = "-static -Xlinker -static";
postConfigure = ''
cp ${activateScript} activate.c
cp ${makedevs} makedevs.c
'';
makeFlags = ["activate"];
makeFlags = ["makedevs"];
installPhase = ''
closure=${closureInfo { rootPaths = [ activateScript ]; }}
closure=${closureInfo { rootPaths = [ makedevs ]; }}
mkdir -p $out/bin $out/etc
cp $closure/store-paths $out/etc/nix-store-paths
$STRIP --remove-section=.note --remove-section=.comment --strip-all activate -o $out/bin/activate
$STRIP --remove-section=.note --remove-section=.comment --strip-all makedevs -o $out/bin/activate
ln -s ${s6-init-bin}/bin/init $out/bin/init
cp -p ${writeFennel "restart-services" {} ./restart-services.fnl} $out/bin/restart-services
# obfuscate the store path of min-copy-closure so that the output
# closure doesn't include a bunch of build system stuff
f=${buildPackages.min-copy-closure}; f=$(echo $f | sed 's/\(.....\)/\1_/g')
substitute ${./build-system-install.sh} $out/install.sh --subst-var-by min-copy-closure $f
chmod +x $out/install.sh
cat > $out/bin/install <<EOF
#!/bin/sh -e
prefix=\''${1-/}
+4 -12
View File
@@ -16,18 +16,10 @@
(print (.. "TFTP serving from " options.base-directory))
;; this is a copy of anoia append-path
(fn merge-pathname [dirname filename]
(let [base (or (string.match dirname "(.*)/$") dirname)
result []]
(each [component (string.gmatch filename "([^/]+)")]
(if (and (= component "..") (> (# result) 0))
(table.remove result)
(= component "..")
(error "path traversal attempt")
true
(table.insert result component)))
(.. base "/" (table.concat result "/"))))
(fn merge-pathname [directory filename]
(if (directory:match "/$")
(.. directory filename)
(.. directory "/" filename)))
(->
(tftp:listen
+3 -3
View File
@@ -1,4 +1,4 @@
(local { : system : assoc : split : dup : table= : dig : append-path } (require :anoia))
(local { : system : assoc : split : dup : table= : dig } (require :anoia))
(local svc (require :anoia.svc))
(import-macros { : define-tests : expect : expect= } :anoia.assert)
@@ -13,14 +13,14 @@
(when (not (table= old-tree new-tree))
(io.stderr:write "new ssh keys\n")
(each [username pubkeys (pairs new-tree)]
(with-open [f (assert (io.open (append-path path username) :w))]
(with-open [f (assert (io.open (.. path "/" username) :w))]
;; the keys are "1" "2" "3" etc, so pairs not ipairs
(each [_ k (pairs pubkeys)]
(f:write k)
(f:write "\n")))))
(each [k v (pairs old-tree)]
(when (not (. new-tree k))
(os.remove (append-path path k))))
(os.remove (.. path "/" k))))
new-tree)
(define-tests
+1
View File
@@ -3,6 +3,7 @@ let
liminix = (import ./default.nix {
device = (import ./devices/qemu);
liminix-config = ./vanilla-configuration.nix;
inherit nixpkgs;
});
here = builtins.toString ./.;
in liminix.buildEnv.overrideAttrs (o: {
+12 -29
View File
@@ -1,18 +1,12 @@
set timeout 40
fconfigure stdout -buffering none
set timeout 10
set when [lindex $argv 0];
send_user "\n\n\n\n#################################\n running $when"
spawn socat -,echo=0,icanon=1 unix-connect:vm/monitor
set monitor_id $spawn_id
fconfigure $monitor_id -buffering none
spawn socat unix-connect:vm/console -
set console_id $spawn_id
fconfigure $console_id -buffering none
proc chat {instr outstr} {
expect {
@@ -25,20 +19,14 @@ proc adddevice { } {
global monitor_id console_id spawn_id
set spawn_id $monitor_id
send_user "\n#### inserting usb device"
send "\r\n"
chat "QEMU" "device_add usb-storage,bus=xhci.0,drive=usbstick\n"
chat "(qemu)" "version\r"
set spawn_id $console_id
expect {
"sda: sda1" { }
timeout {
puts stderr "timeout waiting for disk"
exit 1
}
timeout { exit 1 }
}
send_user "done inserting usb device"
}
if { $when eq "early" } {
@@ -47,25 +35,20 @@ if { $when eq "early" } {
expect "BusyBox"
chat "#" "PS1=RE\\ADY_\\ ; stty -echo \r"
# script needs klogd output to tell when sda1 appears. Then
# run s6-rc -b -a list to wait for booting to finish
chat "READY_" "tail -f /run/log/current & \rs6-rc -b -a list\r"
chat "mount" "\r"
if { $when eq "late" } {
adddevice
}
send_user "\n\n\nwaiting for mount to happen"
send "\r"
set timeout 20
set FINISHED 0
set EXIT "1"
while { $FINISHED < 10 } {
chat "READY_" "grep /srv /proc/mounts\r\n"
expect {
"backup-disk" { set FINISHED 20; set EXIT 0; }
"READY_" { send_user "waiting ...\n" ; send "\r\n"; sleep 6 }
}
set FINISHED [ expr $FINISHED + 1 ]
chat "READY_" "sleep 5; grep /srv /proc/mounts && hostname\r"
expect {
"inout" { }
timeout { exit 1 }
}
exit $EXIT
-4
View File
@@ -18,17 +18,13 @@ mkfs.ext2 -L backup-disk ./vm/stick.e2fs
dd if=/dev/zero of=./vm/stick.img bs=1M count=38
dd if=./vm/stick.e2fs of=./vm/stick.img bs=512 seek=34 conv=notrunc
parted -s ./vm/stick.img -- mklabel gpt mkpart backup-disk ext2 34s -0M
sync
cp ./vm/stick.img ./vm/stick.img.orig
{
${img}/run.sh --background ./vm --flag -device --flag usb-ehci,id=xhci --flag -drive --flag if=none,id=usbstick,format=raw,file=$(pwd)/vm/stick.img
expect ${./script.expect} late
kill $(cat ./vm/pid)
cp ./vm/stick.img.orig ./vm/stick.img
${img}/run.sh --background ./vm --flag -device --flag usb-ehci,id=xhci --flag -drive --flag if=none,id=usbstick,format=raw,file=$(pwd)/vm/stick.img
expect ${./script.expect} early
+1 -1
View File
@@ -4,7 +4,7 @@ let
in {
imports = [
../../vanilla-configuration.nix
../../modules/outputs/squashfs.nix
../../modules/squashfs.nix
../../modules/outputs/jffs2.nix
];
config.rootfsType = "jffs2";
-2
View File
@@ -17,8 +17,6 @@ serverstatedir=$(mktemp -d -t routeros-XXXXXX)
# python scapy drags in matplotlib which doesn't enjoy running in
# a sandbox with no $HOME, hence this environment variable
export MPLCONFIGDIR=$(mktemp -d -t routeros-XXXXXX)
export XDG_CONFIG_HOME=/tmp
export XDG_CACHE_HOME=/tmp
. ${../test-helpers.sh}