Compare commits

..

1 commit

Author SHA1 Message Date
Raito Bezarius
54bcc78a96 limiswitch: init
All checks were successful
build liminix / build_vm_qemu_mips (pull_request) Successful in 29s
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-09-17 13:48:38 +02:00
38 changed files with 1287 additions and 199 deletions

View file

@ -17,34 +17,4 @@ jobs:
- name: Build VM QEMU MIPS
run: |
# Enter the shell
nix-build ci.nix -A qemu
build_zyxel-nwa50ax_mips:
runs-on: nix
steps:
- uses: actions/checkout@v3
- name: Build VM QEMU MIPS
run: |
# Enter the shell
nix-build ci.nix -A qemu
test_hostapd:
runs-on: nix
steps:
- uses: actions/checkout@v3
- name: Build VM QEMU MIPS
run: |
# Enter the shell
nix-build ci.nix -A wlan
test_shell_customization:
runs-on: nix
steps:
- uses: actions/checkout@v3
- name: Build VM QEMU MIPS
run: |
# Enter the shell
nix-build ci.nix -A custom-shell
nix-build -I liminix-config=./examples/hello-from-qemu.nix --arg device "import ./devices/qemu" -A outputs.default

4
ci.nix
View file

@ -7,7 +7,7 @@
let
pkgs = (import nixpkgs { });
borderVmConf = ./bordervm.conf-example.nix;
inherit (pkgs.lib.attrsets) genAttrs mapAttrs;
inherit (pkgs.lib.attrsets) genAttrs;
devices = [
"qemu"
"zyxel-nwa50ax"
@ -19,7 +19,7 @@ let
device = import (liminix + "/devices/${name}");
liminix-config = vanilla;
}).outputs.default;
tests = mapAttrs (_: v: v { inherit liminix nixpkgs; }) (import ./tests/ci.nix);
tests = import ./tests/ci.nix;
jobs =
(genAttrs devices for-device) //
tests //

View file

@ -26,13 +26,9 @@ let
eval = evalModules {
modules = [
{
nixpkgs = {
source = nixpkgs;
overlays = [ overlay ];
config.permittedInsecurePackages = [
"python-2.7.18.8"
];
};
nixpkgs.overlays = [
overlay
];
}
device.module
liminix-config

View file

@ -4,13 +4,11 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr concatStringsSep mapAttrsToList;
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.networking) address interface;
inherit (pkgs.liminix.services) bundle;
# TODO: escape shell argument.
exportVar = name: value: "export ${name}=\"${value}\"";
type_service = pkgs.liminix.lib.types.service;
in {
@ -24,24 +22,6 @@ in {
/run/current-system, we just add the paths in /etc/profile
'';
};
environmentVariables = mkOption {
type = types.attrsOf types.str;
description = ''
Attribute set of environment variables to make available
in a login shell.
The value is assumed to be escaped and the name to be valid.
'';
};
prompt = mkOption {
type = types.str;
default = "$(whoami)@$(hostname) # ";
description = ''
Prompt string (PS1) for the shell.
'';
};
};
services = mkOption {
type = types.attrsOf type_service;
@ -131,8 +111,6 @@ in {
defaultProfile.packages = with pkgs;
[ s6 s6-init-bin execline s6-linux-init s6-rc ];
# Set the useful PS1 prompt by default.
defaultProfile.environmentVariables.PS1 = lib.mkDefault config.defaultProfile.prompt;
boot.commandLine = [
"panic=10 oops=panic init=/bin/init loglevel=8"
@ -203,10 +181,9 @@ in {
etc = let
profile = symlink
(pkgs.writeScript ".profile" ''
PATH=${lib.makeBinPath config.defaultProfile.packages}:/bin
PATH=${lib.makeBinPath config.defaultProfile.packages}:/bin
export PATH
${concatStringsSep "\n" (mapAttrsToList exportVar config.defaultProfile.environmentVariables)}
'');
'');
in dir {
inherit profile;
ashrc = profile;

View file

@ -1,6 +1,7 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
in {
options = {
hostname = mkOption {
@ -11,21 +12,12 @@ in {
default = "liminix";
type = types.nonEmptyStr;
};
hostname-script = mkOption {
description = ''
Script that outputs the system hostname on stdin.
'';
default = pkgs.writeScript "hostname-gen" ''
#!/bin/sh
echo ${config.hostname}
'';
defaultText = ''
pkgs.writeScript "hostname-gen" '''
#!/bin/sh
echo ''${config.hostname}
'''
'';
type = types.package;
};
config = {
services.hostname = oneshot {
name = "hostname-${builtins.substring 0 12 (builtins.hashString "sha256" config.hostname)}";
up = "echo ${config.hostname} > /proc/sys/kernel/hostname";
down = "true";
};
};
}

View file

@ -30,8 +30,6 @@ let
installPhase = ''
mkdir $out
cp -r $src $out/scripts
substituteInPlace $out/scripts/rc.init \
--replace-fail 'config.hostname' "${config.hostname-script}"
chmod -R +w $out
'';
};

View file

@ -36,7 +36,6 @@ fi
### (replace /run/service with your scandir)
s6-rc-init -d -c /etc/s6-rc/compiled /run/service
config.hostname > /proc/sys/kernel/hostname
### 2. Starting the wanted set of services
### This is also called every time you change runlevels with telinit.

View file

@ -194,11 +194,7 @@ extraPkgs // {
});
in h.override { openssl = null; sqlite = null; };
wpa_supplicant = prev.wpa_supplicant.override {
dbusSupport = false;
withPcsclite = false;
wpa_supplicant_gui = null;
};
kexec-tools-static = prev.kexec-tools.overrideAttrs(o: {
# For kexecboot we copy kexec into a ramdisk on the system being

1
pkgs/limiswitch/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
target/

539
pkgs/limiswitch/Cargo.lock generated Normal file
View file

@ -0,0 +1,539 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anstream"
version = "0.6.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
[[package]]
name = "anstyle-parse"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
[[package]]
name = "colorchoice"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
[[package]]
name = "console"
version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"unicode-width",
"windows-sys",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "indicatif"
version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3"
dependencies = [
"console",
"instant",
"number_prefix",
"portable-atomic",
"unicode-width",
"vt100",
]
[[package]]
name = "instant"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
dependencies = [
"cfg-if",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "limiswitch"
version = "0.1.0"
dependencies = [
"clap",
"thiserror",
"tracing",
"tracing-indicatif",
]
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]]
name = "number_prefix"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "portable-atomic"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265"
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]]
name = "tracing"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-indicatif"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "069580424efe11d97c3fef4197fa98c004fa26672cc71ad8770d224e23b1951d"
dependencies = [
"indicatif",
"tracing",
"tracing-core",
"tracing-subscriber",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
dependencies = [
"nu-ansi-term",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-width"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "vt100"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84cd863bf0db7e392ba3bd04994be3473491b31e66340672af5d11943c6274de"
dependencies = [
"itoa",
"log",
"unicode-width",
"vte",
]
[[package]]
name = "vte"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197"
dependencies = [
"arrayvec",
"utf8parse",
"vte_generate_state_changes",
]
[[package]]
name = "vte_generate_state_changes"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

View file

@ -0,0 +1,10 @@
[package]
name = "limiswitch"
version = "0.1.0"
edition = "2021"
[dependencies]
clap = { version = "4.5.17", features = ["derive"] }
thiserror = "1.0.63"
tracing = { version = "0.1.40", features = ["max_level_debug", "release_max_level_info"] }
tracing-indicatif = "0.3.6"

View file

@ -0,0 +1,28 @@
use std::path::Path;
use super::state::OSOperState;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ChannelError {
}
pub type Result<V> = std::result::Result<V, ChannelError>;
/// An interaction channel enable the program to communicate with the target device
/// and perform side-effects, e.g. gather information, write bytes to some flash, etc.
pub trait InteractionChannel {
fn execute(&self, cmd: &str) -> String;
fn read_file(&self, path: &Path) -> String;
fn has_executable_in_path(&self, executable: &str) -> bool;
fn has_directory(&self, path: &Path) -> bool;
fn infer_operational_state(&self) -> Result<Option<OSOperState>>;
fn get_kernel_log(&self) -> String;
}
// struct SSH;
// impl InteractionChannel for SSH {}
//
// struct Serial;
// impl InteractionChannel for Serial {}
//
// struct Agent;
// impl InteractionChannel for Agent {}

View file

@ -0,0 +1,184 @@
use super::channels::InteractionChannel;
use super::state::{OSOperState, DistributionType};
use thiserror::Error;
pub struct Device {
channel: Box<dyn InteractionChannel>,
operational_state: Option<OSOperState>,
}
#[derive(Debug, Error)]
pub enum DeviceError {
#[error("The device is in an unknown operational state at the operating system level")]
UnknownOperationalState,
#[error("The device is in an unsupported operational state at the operating system level: {0:?}")]
UnsupportedOperationalState(OSOperState),
#[error("The device type could not be inferred: unsupported device?")]
UnknownDeviceType,
#[error("This device does not have a MTD-based partition layout: this is unsupported")]
UnsupportedPartitionLayout,
#[error("This device has an unexpected partition layout with respect to its device type")]
UnexpectedPartitionLayout,
}
pub type Result<V> = std::result::Result<V, DeviceError>;
impl Device {
pub fn open_uri(uri: String) -> Self {
}
pub fn new(channel: Box<dyn InteractionChannel>) -> Self {
Device {
channel,
operational_state: None
}
}
fn gather_os_operational_state(&self) -> Result<OSOperState> {
// 1. Ask the underlying layer if it can know what is the current operational state.
// Returns it.
let inferred_oper_state = self.channel.infer_operational_state()?;
// 2. If it cannot guess, it means it's either a recovery or a userspace.
// 3. Run a command to determine if we have a busybox.
let has_busybox: bool = self.channel.has_executable_in_path("busybox");
// 4. If we have no busybox, fail by explaining that we have unknown OS oper state.
if !has_busybox {
return Err(DeviceError::UnknownOperationalState);
}
// 5. If we have a busybox,
// (1) check for the existence of /nix/store → Liminix.
let has_nix_store: bool = self.channel.has_directory("/nix/store");
if has_nix_store {
return Ok(OSOperState::Userspace(DistributionType::Liminix {
revision: self.channel.read_file("/etc/liminix-version".into()),
nixpkgs_revision: self.channel.read_file("/etc/nixpkgs-version".into()),
}))
}
// TODO: (2) check for the existence of OpenWrt specific → ...
// (3) return unknown.
Ok(OSOperState::Userspace(DistributionType::Unknown))
}
fn gather_device_type(&self) -> Result<crate::state::DeviceType> {
// Assert we are in Liminix or OpenWRT.
if !matches!(self.operational_state, Some(OSOperState::Userspace(DistributionType::Liminix { .. })) | Some(OSOperState::Userspace(DistributionType::OpenWrt { .. }))) {
if self.operational_state.is_some() {
return Err(DeviceError::UnsupportedOperationalState(self.operational_state.unwrap()));
} else {
return Err(DeviceError::UnknownOperationalState);
}
}
// Read the kernel log and find "Machine is XYZ".
let kernel_log = self.channel.get_kernel_log();
// Use a regex to find "Machine is ..."
let machine_name: String = "";
match machine_name.as_str() {
"Zyxel NWA50AX" => Ok(crate::state::DeviceType::NWA50AX),
_ => Ok(crate::state::DeviceType::Custom(machine_name))
}
}
fn gather_partition_layout(&self) -> Result<super::state::PartitionLayout> {
let mtd_data = self.channel.execute("cat /proc/mtd");
// Assert this is a MTD-based system.
// Parse: cat /proc/mtd
}
fn gather_running_image_type(&self) -> Result<super::state::ImageType> {
// Assert we know at least one ABSchemeConfiguration partition.
// If not, warn about this.
//
// Assume primary.
//
// If we have an ABSchemeConfiguration partition, look for it.
// Perform static dispatch for every device, parse the result.
}
pub fn gather_runtime_state(&mut self) -> Result<super::state::RuntimeState> {
// 1. Determine OS operational state
// If it's in any of the wrong state, report error.
let os_oper_state = self.gather_os_operational_state()?;
match os_oper_state {
OSOperState::UBoot | OSOperState::Recovery | OSOperState::KernelPanicked(_) => return Err(DeviceError::UnsupportedOperationalState(os_oper_state)),
_ => {}
}
self.operational_state = Some(os_oper_state);
// 2. Determine device type.
let dtype = self.gather_device_type()?;
// 3. Determine partition layout
let playout = self.gather_partition_layout()?;
// and match it with one of the known partition layouts for that device type.
if !dtype.is_compatible_with(playout) {
return Err(DeviceError::UnexpectedPartitionLayout);
}
// 4. Determine running image type given the device type.
let running_itype = self.gather_running_image_type()?;
Ok(crate::state::RuntimeState::new(dtype, playout, running_itype))
}
}
#[cfg(test)]
mod tests {
use std::collections::{HashMap, HashSet};
use crate::{channels::InteractionChannel, state::OSOperState};
use super::Device;
#[derive(Default)]
struct FakeChannel {
pub oper_state: Option<OSOperState>,
pub file_contents: HashMap<std::path::PathBuf, String>,
pub kernel_log: Option<String>,
pub available_executables: HashSet<String>,
pub available_directories: HashSet<std::path::PathBuf>
}
impl InteractionChannel for FakeChannel {
fn infer_operational_state(&self) -> Result<Option<crate::state::OSOperState>, crate::channels::ChannelError> {
Ok(self.oper_state.clone())
}
fn execute(&self, cmd: &str) -> String {
""
}
fn has_executable_in_path(&self, executable: &str) -> bool {
self.available_executables.contains(executable)
}
fn get_kernel_log(&self) -> String {
self.kernel_log
}
fn read_file(&self, path: &std::path::Path) -> String {
self.file_contents.get(path).unwrap().to_string()
}
fn has_directory(&self, path: &std::path::Path) -> bool {
self.available_directories.contains(path)
}
}
// Create a fake interaction channel that can mock things.
fn test_parse_kernel_log_for_machine_type() {
let channel = Box::new(FakeChannel {
oper_state: None,
kernel_log: include_str!("tests/kernel.log"),
..Default::default()
});
let device = Device::new(channel);
let dtype = device.gather_device_type()?;
}
fn test_parse_mtd_partition_layout() {
}
fn test_parse_disk_state() {
}
fn test_parse_memory_state() {
}
}

View file

@ -0,0 +1,83 @@
use thiserror::Error;
use clap::Parser;
mod channels;
mod interaction;
mod state;
#[derive(Debug, Error)]
enum DeploymentError {
#[error("During information gathering error, we encountered a device-specific error: {0}")]
InformationGatheringError(
#[source]
interaction::DeviceError
),
#[error("Delta closure does not fit on the target partition, levitation is needed but cannot be enabled automatically yet")]
LevitationRequired,
}
struct Toplevel {
made_for: state::DeviceType,
path: String
}
#[derive(Parser, Debug)]
#[command(version, about)]
struct Args {
/// Top-level path for the deployment
toplevel_path: String,
/// Connection URI to the target
/// e.g. `serial:///dev/ttyUSB0`
/// e.g. `ssh://root@...`
connection_uri: String,
#[arg(long, default_value_t = false)]
dry_run: bool,
}
fn main() {
let args = Args::parse();
// 1. Open the toplevel_path
// Obtain the theoretical target information, e.g. what device is it.
// Populate a `Toplevel` structure.
// 2. Connect to the connection URI
let device = Device::open_uri(args.connection_uri)?;
// Run information gathering procedure.
let runtime_state = device.gather_runtime_state()?;
// Compare theoretical target information with actual target information.
// toplevel.is_compatible_with(runtime_state);
// Fail if it's wrong.
// 3. Compute the delta closure to send.
// let store_paths = device.get_store_paths_for(ImageState::Secondary);
// let delta = toplevel.delta(store_paths);
// 4. Compute the size of the delta closure
// let size = delta.size();
// Verify if it fits in the RAM, if not, fail.
// Verify if it fits in the target disk, if not, warn.
//
// 5. If it doesn't fit in the target disk, verify if levitation is available.
// If not, fail.
//
// 6. If it doesn't fit and levitation is available, propose levitation as a deployment method
// and go back to 2 with a levitation parameter, i.e. `?actual-system=/mnt` or something
// like that.
//
// 7. If it fits in the target disk, copy the contents of the store in the target.
// Under A/B:
// - Identify which image are we running, whether there's a success image and are we on it, if
// not, propose to reboot in the success image and wait for the device to be available again.
//
// - Instead of writing the contents of the store in the target, propose to mount the B store,
// write the contents over there, there's no need for levitation anymore.
//
// - Write the kernel image to the B partition as well and verify that its size fits the MTD
// sizes.
//
// - Put the new image under test, reboot into it, let the bootloader handle it. Wait for
// successful boot to the new image, if not, signal that deployment failed to pass A/B checks.
tracing::info!("Test {}", args.toplevel_path);
}

View file

@ -0,0 +1,91 @@
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub enum DistributionType {
Liminix {
revision: String,
nixpkgs_revision: String
},
OpenWrt {
version: String
},
Unknown
}
#[derive(Debug, Clone)]
pub enum OSOperState {
UBoot,
Recovery,
Userspace(DistributionType),
KernelPanicked(String),
}
pub enum ImageType {
Primary,
Secondary
}
pub enum DeviceType {
NWA50AX,
Custom(String)
}
pub enum FilesystemType {
UBI,
JFFS2,
}
pub enum ABSchemeType {
Zyxel
}
pub enum PartitionType {
UBootFirmware,
UBootConfig,
/// kernel + rootfs concatenated.
Image {
variant: ImageType
},
Kernel {
variant: ImageType
},
RootFs {
fs_type: FilesystemType,
variant: ImageType
},
UserData,
Logs,
Vendor,
ABSchemeConfiguration {
variant: ABSchemeType
},
DeviceSpecificData
}
pub struct Partition {
size: u64,
offset: u64,
name: String,
r#type: PartitionType
}
pub type PartitionLayout = HashMap<String, Partition>;
pub struct RuntimeState {
device_type: DeviceType,
partition_layout: PartitionLayout,
running_image: ImageType,
memory_state: MemoryState,
disk_state: DiskState
}
impl RuntimeState {
pub fn new(device_type: DeviceType, partition_layout: PartitionLayout, running_image: ImageType) -> Self {
Self {
device_type,
partition_layout,
running_image
}
}
}

View file

@ -0,0 +1,3 @@
total used free shared buff/cache available
Mem: 250920 36056 201556 1452 13308 205368
Swap: 0 0 0

View file

@ -0,0 +1,295 @@
<5>[ 0.000000] Linux version 5.15.137 (nixbld@liminix.builder) (mipsel-unknown-linux-musl-gcc (GCC) 13.3.0, GNU ld (GNU Binutils) 2.42) #1 SMP Mon Aug 26 18:09:43 UTC 2024
<6>[ 0.000000] SoC Type: MediaTek MT7621 ver:1 eco:3
<6>[ 0.000000] printk: bootconsole [early0] enabled
<6>[ 0.000000] CPU0 revision is: 0001992f (MIPS 1004Kc)
<6>[ 0.000000] MIPS: machine is ZyXEL NWA50AX
<6>[ 0.000000] Initrd not found or empty - disabling initrd
<6>[ 0.000000] Detected 1 available secondary CPU(s)
<6>[ 0.000000] Primary instruction cache 32kB, VIPT, 4-way, linesize 32 bytes.
<6>[ 0.000000] Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes
<4>[ 0.000000] MIPS secondary cache 256kB, 8-way, linesize 32 bytes.
<6>[ 0.000000] Zone ranges:
<6>[ 0.000000] Normal [mem 0x0000000000000000-0x000000000fffffff]
<6>[ 0.000000] Movable zone start for each node
<6>[ 0.000000] Early memory node ranges
<6>[ 0.000000] node 0: [mem 0x0000000000000000-0x000000000fffffff]
<6>[ 0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x000000000fffffff]
<6>[ 0.000000] percpu: Embedded 10 pages/cpu s11184 r8192 d21584 u40960
<7>[ 0.000000] pcpu-alloc: s11184 r8192 d21584 u40960 alloc=10*4096
<7>[ 0.000000] pcpu-alloc: [0] 0 [0] 1
<6>[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 65024
<5>[ 0.000000] Kernel command line: console=ttyS0,115200 panic=10 oops=panic init=/bin/init loglevel=8 root=ubi0:rootfs rootfstype=ubifs fw_devlink=off ubi.mtd=ubi_a ubi.mtd=ubi_b rootalt=ubi1:rootfs
<5>[ 0.000000] Unknown kernel command line parameters "rootalt=ubi1:rootfs", will be passed to user space.
<6>[ 0.000000] Dentry cache hash table entries: 32768 (order: 5, 131072 bytes, linear)
<6>[ 0.000000] Inode-cache hash table entries: 16384 (order: 4, 65536 bytes, linear)
<6>[ 0.000000] Writing ErrCtl register=000307c0
<6>[ 0.000000] Readback ErrCtl register=000307c0
<6>[ 0.000000] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
<6>[ 0.000000] Memory: 249660K/262144K available (6690K kernel code, 620K rwdata, 1272K rodata, 1260K init, 215K bss, 12484K reserved, 0K cma-reserved)
<6>[ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
<6>[ 0.000000] rcu: Hierarchical RCU implementation.
<6>[ 0.000000] rcu: RCU event tracing is enabled.
<6>[ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
<6>[ 0.000000] NR_IRQS: 256
<6>[ 0.000000] clocksource: GIC: mask: 0xffffffffffffffff max_cycles: 0xcaf478abb4, max_idle_ns: 440795247997 ns
<6>[ 0.000004] sched_clock: 64 bits at 880MHz, resolution 1ns, wraps every 4398046511103ns
<6>[ 0.008218] Console: colour dummy device 80x25
<6>[ 0.012632] Calibrating delay loop... 583.68 BogoMIPS (lpj=1167360)
<6>[ 0.046814] pid_max: default: 32768 minimum: 301
<6>[ 0.051583] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
<6>[ 0.058813] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
<6>[ 0.068777] rcu: Hierarchical SRCU implementation.
<6>[ 0.074116] smp: Bringing up secondary CPUs ...
<6>[ 0.079353] Primary instruction cache 32kB, VIPT, 4-way, linesize 32 bytes.
<6>[ 0.079374] Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes
<4>[ 0.079388] MIPS secondary cache 256kB, 8-way, linesize 32 bytes.
<6>[ 0.079433] CPU1 revision is: 0001992f (MIPS 1004Kc)
<6>[ 0.106815] Synchronize counters for CPU 1: done.
<6>[ 0.137415] smp: Brought up 1 node, 2 CPUs
<6>[ 0.142174] devtmpfs: initialized
<6>[ 0.149141] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
<6>[ 0.158851] futex hash table entries: 512 (order: 2, 16384 bytes, linear)
<6>[ 0.165686] pinctrl core: initialized pinctrl subsystem
<6>[ 0.172363] NET: Registered PF_NETLINK/PF_ROUTE protocol family
<7>[ 0.195326] FPU Affinity set after 4688 emulations
<6>[ 0.210941] vgaarb: loaded
<6>[ 0.213833] pps_core: LinuxPPS API ver. 1 registered
<6>[ 0.218718] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
<6>[ 0.227852] PTP clock support registered
<6>[ 0.232996] clocksource: Switched to clocksource GIC
<6>[ 0.247916] NET: Registered PF_INET protocol family
<6>[ 0.253106] IP idents hash table entries: 4096 (order: 3, 32768 bytes, linear)
<6>[ 0.261109] tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 6144 bytes, linear)
<6>[ 0.269438] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
<6>[ 0.277109] TCP established hash table entries: 2048 (order: 1, 8192 bytes, linear)
<6>[ 0.284734] TCP bind hash table entries: 2048 (order: 2, 16384 bytes, linear)
<6>[ 0.291833] TCP: Hash tables configured (established 2048 bind 2048)
<6>[ 0.298233] UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
<6>[ 0.304728] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
<6>[ 0.311863] NET: Registered PF_UNIX/PF_LOCAL protocol family
<6>[ 0.317488] PCI: CLS 0 bytes, default 32
<5>[ 0.322010] Initialise system trusted keyrings
<6>[ 0.326848] workingset: timestamp_bits=30 max_order=16 bucket_order=0
<6>[ 0.338689] squashfs: version 4.0 (2009/01/31) Phillip Lougher
<6>[ 0.344647] NET: Registered PF_ALG protocol family
<5>[ 0.349383] Key type asymmetric registered
<5>[ 0.353437] Asymmetric key parser 'x509' registered
<6>[ 0.358339] io scheduler mq-deadline registered
<6>[ 0.362797] io scheduler kyber registered
<6>[ 0.368367] mt7621_gpio 1e000600.gpio: registering 32 gpios
<6>[ 0.374144] mt7621_gpio 1e000600.gpio: registering 32 gpios
<6>[ 0.379906] mt7621_gpio 1e000600.gpio: registering 32 gpios
<6>[ 0.385758] mt7621-pci 1e140000.pcie: host bridge /pcie@1e140000 ranges:
<6>[ 0.392397] mt7621-pci 1e140000.pcie: No bus range found for /pcie@1e140000, using [bus 00-ff]
<6>[ 0.401153] mt7621-pci 1e140000.pcie: MEM 0x0060000000..0x006fffffff -> 0x0060000000
<6>[ 0.409262] mt7621-pci 1e140000.pcie: IO 0x001e160000..0x001e16ffff -> 0x0000000000
<6>[ 0.740953] mt7621-pci 1e140000.pcie: pcie2 no card, disable it (RST & CLK)
<6>[ 0.747846] mt7621-pci 1e140000.pcie: PCIE0 enabled
<6>[ 0.752676] mt7621-pci 1e140000.pcie: PCIE1 enabled
<6>[ 0.757535] PCI coherence region base: 0x60000000, mask/settings: 0xf0000002
<6>[ 0.764608] mt7621-pci 1e140000.pcie: PCI host bridge to bus 0000:00
<6>[ 0.770890] pci_bus 0000:00: root bus resource [bus 00-ff]
<6>[ 0.776323] pci_bus 0000:00: root bus resource [mem 0x60000000-0x6fffffff]
<6>[ 0.783159] pci_bus 0000:00: root bus resource [io 0x0000-0xffff]
<6>[ 0.789337] pci 0000:00:00.0: [0e8d:0801] type 01 class 0x060400
<6>[ 0.795285] pci 0000:00:00.0: reg 0x10: [mem 0x00000000-0x7fffffff]
<6>[ 0.801504] pci 0000:00:00.0: reg 0x14: [mem 0x60600000-0x6060ffff]
<6>[ 0.807784] pci 0000:00:00.0: supports D1
<6>[ 0.811724] pci 0000:00:00.0: PME# supported from D0 D1 D3hot
<6>[ 0.817750] pci 0000:00:01.0: [0e8d:0801] type 01 class 0x060400
<6>[ 0.823698] pci 0000:00:01.0: reg 0x10: [mem 0x00000000-0x7fffffff]
<6>[ 0.829912] pci 0000:00:01.0: reg 0x14: [mem 0x60610000-0x6061ffff]
<6>[ 0.836183] pci 0000:00:01.0: supports D1
<6>[ 0.840122] pci 0000:00:01.0: PME# supported from D0 D1 D3hot
<6>[ 0.847184] pci 0000:01:00.0: [14c3:7916] type 00 class 0x000280
<6>[ 0.853151] pci 0000:01:00.0: reg 0x10: [mem 0x00000000-0x000fffff 64bit pref]
<6>[ 0.860308] pci 0000:01:00.0: reg 0x18: [mem 0x00000000-0x00003fff 64bit pref]
<6>[ 0.867491] pci 0000:01:00.0: reg 0x20: [mem 0x00000000-0x00000fff 64bit pref]
<6>[ 0.874765] pci 0000:01:00.0: supports D1 D2
<6>[ 0.878963] pci 0000:01:00.0: PME# supported from D0 D1 D2 D3hot D3cold
<6>[ 0.885579] pci 0000:01:00.0: 2.000 Gb/s available PCIe bandwidth, limited by 2.5 GT/s PCIe x1 link at 0000:00:00.0 (capable of 4.000 Gb/s with 5.0 GT/s PCIe x1 link)
<6>[ 0.900515] pci 0000:00:00.0: ASPM: current common clock configuration is inconsistent, reconfiguring
<6>[ 0.922057] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
<6>[ 0.927222] pci 0000:00:00.0: bridge window [io 0x0000-0x0fff]
<6>[ 0.933266] pci 0000:00:00.0: bridge window [mem 0x60000000-0x600fffff]
<6>[ 0.940002] pci 0000:00:00.0: bridge window [mem 0x60100000-0x602fffff pref]
<6>[ 0.947179] pci_bus 0000:01: busn_res: [bus 01-ff] end is updated to 01
<6>[ 0.953911] pci 0000:02:00.0: [14c3:7915] type 00 class 0x000280
<6>[ 0.959871] pci 0000:02:00.0: reg 0x10: [mem 0x00000000-0x000fffff 64bit pref]
<6>[ 0.967032] pci 0000:02:00.0: reg 0x18: [mem 0x00000000-0x00003fff 64bit pref]
<6>[ 0.974204] pci 0000:02:00.0: reg 0x20: [mem 0x00000000-0x00000fff 64bit pref]
<6>[ 0.981494] pci 0000:02:00.0: supports D1 D2
<6>[ 0.985692] pci 0000:02:00.0: PME# supported from D0 D1 D2 D3hot D3cold
<6>[ 0.992301] pci 0000:02:00.0: 2.000 Gb/s available PCIe bandwidth, limited by 2.5 GT/s PCIe x1 link at 0000:00:01.0 (capable of 4.000 Gb/s with 5.0 GT/s PCIe x1 link)
<6>[ 1.007240] pci 0000:00:01.0: ASPM: current common clock configuration is inconsistent, reconfiguring
<6>[ 1.026047] pci 0000:00:01.0: PCI bridge to [bus 02-ff]
<6>[ 1.031209] pci 0000:00:01.0: bridge window [io 0x0000-0x0fff]
<6>[ 1.037254] pci 0000:00:01.0: bridge window [mem 0x60300000-0x603fffff]
<6>[ 1.043989] pci 0000:00:01.0: bridge window [mem 0x60400000-0x605fffff pref]
<6>[ 1.051164] pci_bus 0000:02: busn_res: [bus 02-ff] end is updated to 02
<6>[ 1.057780] pci 0000:00:00.0: BAR 0: no space for [mem size 0x80000000]
<6>[ 1.064319] pci 0000:00:00.0: BAR 0: failed to assign [mem size 0x80000000]
<6>[ 1.071234] pci 0000:00:01.0: BAR 0: no space for [mem size 0x80000000]
<6>[ 1.077796] pci 0000:00:01.0: BAR 0: failed to assign [mem size 0x80000000]
<6>[ 1.084709] pci 0000:00:00.0: BAR 8: assigned [mem 0x60000000-0x600fffff]
<6>[ 1.091459] pci 0000:00:00.0: BAR 9: assigned [mem 0x60100000-0x602fffff pref]
<6>[ 1.098629] pci 0000:00:01.0: BAR 8: assigned [mem 0x60300000-0x603fffff]
<6>[ 1.105363] pci 0000:00:01.0: BAR 9: assigned [mem 0x60400000-0x605fffff pref]
<6>[ 1.112529] pci 0000:00:00.0: BAR 1: assigned [mem 0x60600000-0x6060ffff]
<6>[ 1.119276] pci 0000:00:01.0: BAR 1: assigned [mem 0x60610000-0x6061ffff]
<6>[ 1.126014] pci 0000:00:00.0: BAR 7: assigned [io 0x0000-0x0fff]
<6>[ 1.132055] pci 0000:00:01.0: BAR 7: assigned [io 0x1000-0x1fff]
<6>[ 1.138119] pci 0000:01:00.0: BAR 0: assigned [mem 0x60100000-0x601fffff 64bit pref]
<6>[ 1.145810] pci 0000:01:00.0: BAR 2: assigned [mem 0x60200000-0x60203fff 64bit pref]
<6>[ 1.153506] pci 0000:01:00.0: BAR 4: assigned [mem 0x60204000-0x60204fff 64bit pref]
<6>[ 1.161188] pci 0000:00:00.0: PCI bridge to [bus 01]
<6>[ 1.166096] pci 0000:00:00.0: bridge window [io 0x0000-0x0fff]
<6>[ 1.172144] pci 0000:00:00.0: bridge window [mem 0x60000000-0x600fffff]
<6>[ 1.178887] pci 0000:00:00.0: bridge window [mem 0x60100000-0x602fffff pref]
<6>[ 1.186066] pci 0000:02:00.0: BAR 0: assigned [mem 0x60400000-0x604fffff 64bit pref]
<6>[ 1.193762] pci 0000:02:00.0: BAR 2: assigned [mem 0x60500000-0x60503fff 64bit pref]
<6>[ 1.201457] pci 0000:02:00.0: BAR 4: assigned [mem 0x60504000-0x60504fff 64bit pref]
<6>[ 1.209139] pci 0000:00:01.0: PCI bridge to [bus 02]
<6>[ 1.214053] pci 0000:00:01.0: bridge window [io 0x1000-0x1fff]
<6>[ 1.220095] pci 0000:00:01.0: bridge window [mem 0x60300000-0x603fffff]
<6>[ 1.226838] pci 0000:00:01.0: bridge window [mem 0x60400000-0x605fffff pref]
<6>[ 1.293553] Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
<6>[ 1.301659] printk: console [ttyS0] disabled
<6>[ 1.305989] 1e000c00.uartlite: ttyS0 at MMIO 0x1e000c00 (irq = 15, base_baud = 3125000) is a 16550A
<6>[ 1.315005] printk: console [ttyS0] enabled
<6>[ 1.323276] printk: bootconsole [early0] disabled
<6>[ 1.334191] nand: device found, Manufacturer ID: 0xc2, Chip ID: 0xf1
<6>[ 1.340589] nand: Macronix MX30LF1G28AD
<6>[ 1.344427] nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 128
<6>[ 1.352085] mt7621-nand 1e003000.nand: ECC strength adjusted to 12 bits
<6>[ 1.361726] Signature found at block 1023 [0x07fe0000]
<6>[ 1.366867] NMBM management region starts at block 960 [0x07800000]
<6>[ 1.378961] First info table with writecount 23 found in block 960
<6>[ 1.402451] Second info table with writecount 23 found in block 963
<6>[ 1.408777] NMBM has been successfully attached
<5>[ 1.413459] 10 fixed-partitions partitions found on MTD device mt7621-nand
<5>[ 1.420736] Creating 10 MTD partitions on "mt7621-nand":
<5>[ 1.426060] 0x000000000000-0x000000080000 : "u-boot"
<5>[ 1.439414] 0x000000080000-0x000000100000 : "u-boot-env"
<5>[ 1.453035] 0x000000100000-0x000000180000 : "factory"
<5>[ 1.466309] 0x000000180000-0x000002980000 : "firmware_a"
<5>[ 2.085213] 2 fixed-partitions partitions found on MTD device firmware_a
<5>[ 2.091937] Creating 2 MTD partitions on "firmware_a":
<5>[ 2.097081] 0x000000000000-0x000000800000 : "kernel_a"
<5>[ 2.225386] 0x000000800000-0x000002800000 : "ubi_a"
<5>[ 2.721495] 0x000002980000-0x000005180000 : "firmware_b"
<5>[ 3.340246] 2 fixed-partitions partitions found on MTD device firmware_b
<5>[ 3.346968] Creating 2 MTD partitions on "firmware_b":
<5>[ 3.352107] 0x000000000000-0x000000800000 : "kernel_b"
<5>[ 3.480263] 0x000000800000-0x000002800000 : "ubi_b"
<5>[ 3.975666] 0x000005180000-0x000006580000 : "rootfs_data"
<5>[ 4.287830] 0x000006580000-0x000007280000 : "logs"
<5>[ 4.492219] 0x000007280000-0x000007700000 : "vendor-myzyxel"
<5>[ 4.567305] 0x000007700000-0x000007780000 : "bootconfig"
<5>[ 4.580784] 0x000007780000-0x000007800000 : "mrd"
<6>[ 4.728861] mt7530-mdio mdio-bus:1f: MT7530 adapts as multi-chip module
<6>[ 4.739452] mtk_soc_eth 1e100000.ethernet eth0: mediatek frame engine at 0xbe100000, irq 17
<6>[ 4.749780] NET: Registered PF_INET6 protocol family
<6>[ 4.756356] Segment Routing with IPv6
<6>[ 4.760155] In-situ OAM (IOAM) with IPv6
<6>[ 4.764191] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
<6>[ 4.770812] NET: Registered PF_PACKET protocol family
<6>[ 4.776330] 8021q: 802.1Q VLAN Support v1.8
<5>[ 4.781230] Loading compiled-in X.509 certificates
<5>[ 4.797729] Loaded X.509 cert 'Build time autogenerated kernel key: 3cb1578c6bb232a0582cf98f15a4972f913c1af3'
<3>[ 4.807668] Problem parsing in-kernel X.509 certificate list
<5>[ 4.817397] Key type encrypted registered
<6>[ 4.824007] mt7530-mdio mdio-bus:1f: MT7530 adapts as multi-chip module
<6>[ 4.846395] mt7530-mdio mdio-bus:1f: configuring for fixed/rgmii link mode
<6>[ 4.854154] mt7530-mdio mdio-bus:1f: Link is Up - 1Gbps/Full - flow control rx/tx
<6>[ 4.859149] mt7530-mdio mdio-bus:1f lan (uninitialized): PHY [mt7530-0:04] driver [MediaTek MT7530 PHY] (irq=19)
<6>[ 4.873461] DSA: tree 0 setup
<5>[ 4.876884] ubi0: attaching mtd5
<5>[ 5.863729] ubi0: scanning is finished
<5>[ 5.890726] ubi0: attached mtd5 (name "ubi_a", size 32 MiB)
<5>[ 5.896336] ubi0: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
<5>[ 5.903205] ubi0: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
<5>[ 5.909985] ubi0: VID header offset: 2048 (aligned 2048), data offset: 4096
<5>[ 5.916945] ubi0: good PEBs: 256, bad PEBs: 0, corrupted PEBs: 0
<5>[ 5.922942] ubi0: user volume: 1, internal volumes: 1, max. volumes count: 128
<5>[ 5.930154] ubi0: max/mean erase counter: 126998/126988, WL threshold: 4096, image sequence number: 315532800
<5>[ 5.940050] ubi0: available PEBs: 0, total reserved PEBs: 256, PEBs reserved for bad PEB handling: 19
<5>[ 5.949276] ubi0: background thread "ubi_bgt0d" started, PID 68
<5>[ 5.953015] ubi1: attaching mtd8
<5>[ 6.941903] ubi1: scanning is finished
<5>[ 6.968852] ubi1: attached mtd8 (name "ubi_b", size 32 MiB)
<5>[ 6.974477] ubi1: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
<5>[ 6.981349] ubi1: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
<5>[ 6.988131] ubi1: VID header offset: 2048 (aligned 2048), data offset: 4096
<5>[ 6.995089] ubi1: good PEBs: 256, bad PEBs: 0, corrupted PEBs: 0
<5>[ 7.001103] ubi1: user volume: 1, internal volumes: 1, max. volumes count: 128
<5>[ 7.008317] ubi1: max/mean erase counter: 126977/126976, WL threshold: 4096, image sequence number: 315532800
<5>[ 7.018222] ubi1: available PEBs: 0, total reserved PEBs: 256, PEBs reserved for bad PEB handling: 19
<5>[ 7.027455] ubi1: background thread "ubi_bgt1d" started, PID 69
<6>[ 7.038626] Freeing unused kernel image (initmem) memory: 1260K
<4>[ 7.044612] This architecture does not have kernel memory protection.
<6>[ 7.051070] Run /init as init process
<7>[ 7.054740] with arguments:
<7>[ 7.057711] /init
<7>[ 7.059974] with environment:
<7>[ 7.063118] HOME=/
<7>[ 7.065486] TERM=linux
<7>[ 7.068180] rootalt=ubi1:rootfs
<5>[ 7.075382] UBIFS (ubi0:0): Mounting in unauthenticated mode
<5>[ 7.082662] UBIFS (ubi0:0): background thread "ubifs_bgt0_0" started, PID 70
<5>[ 7.204958] UBIFS (ubi0:0): recovery needed
<5>[ 7.601923] UBIFS (ubi0:0): recovery completed
<5>[ 7.606622] UBIFS (ubi0:0): UBIFS: mounted UBI device 0, volume 0, name "rootfs"
<5>[ 7.614056] UBIFS (ubi0:0): LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes
<5>[ 7.623958] UBIFS (ubi0:0): FS size: 28315648 bytes (27 MiB, 223 LEBs), max 256 LEBs, journal size 4444160 bytes (4 MiB, 35 LEBs)
<5>[ 7.635596] UBIFS (ubi0:0): reserved for root: 0 bytes (0 KiB)
<5>[ 7.641430] UBIFS (ubi0:0): media format: w4/r0 (latest is w5/r0), UUID A68EAB38-9D1E-4184-AEFB-63A0740A6A2D, small LPT model
<4>[ 9.842286] compat: loading out-of-tree module taints kernel.
<5>[ 9.857452] compat: module verification failed: signature and/or required key missing - tainting kernel
<6>[ 9.967488] Loading modules backported from Linux version e2c1a934fd8
<6>[ 9.974025] Backport generated by backports.git dfe0f60ca8a
<5>[ 11.676238] random: chronyd: uninitialized urandom read (1027 bytes read)
<6>[ 11.685221] mtk_soc_eth 1e100000.ethernet eth0: configuring for fixed/rgmii link mode
<6>[ 11.695046] mtk_soc_eth 1e100000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
<6>[ 11.723238] mt7530-mdio mdio-bus:1f lan: configuring for phy/gmii link mode
<6>[ 11.747231] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
<6>[ 12.360030] int: port 1(lan) entered blocking state
<6>[ 12.364996] int: port 1(lan) entered disabled state
<6>[ 12.371531] device lan entered promiscuous mode
<6>[ 12.376119] device eth0 entered promiscuous mode
<6>[ 12.509793] pci 0000:00:00.0: enabling device (0006 -> 0007)
<6>[ 12.515560] mt7915e_hif 0000:01:00.0: enabling device (0000 -> 0002)
<6>[ 12.522443] pci 0000:00:01.0: enabling device (0006 -> 0007)
<6>[ 12.528197] mt7915e 0000:02:00.0: enabling device (0000 -> 0002)
<6>[ 12.630121] mt7915e 0000:02:00.0: HW/SW Version: 0x8a108a10, Build Time: 20220929104113a
<6>[ 12.630121]
<6>[ 13.117498] mt7915e 0000:02:00.0: WM Firmware Version: ____000000, Build Time: 20220929104145
<6>[ 13.225464] mt7915e 0000:02:00.0: WA Firmware Version: DEV_000000, Build Time: 20220929104205
<6>[ 14.924294] mt7530-mdio mdio-bus:1f lan: Link is Up - 1Gbps/Full - flow control off
<5>[ 15.854162] random: crng init done
<6>[ 18.497431] IPv6: ADDRCONF(NETDEV_CHANGE): lan: link becomes ready
<6>[ 18.503953] int: port 1(lan) entered blocking state
<6>[ 18.508961] int: port 1(lan) entered forwarding state
<6>[ 18.520882] IPv6: ADDRCONF(NETDEV_CHANGE): int: link becomes ready
<6>[ 19.726486] int: port 2(wlan0) entered blocking state
<6>[ 19.731712] int: port 2(wlan0) entered disabled state
<6>[ 19.737934] device wlan0 entered promiscuous mode
<6>[ 19.750519] int: port 3(wlan1) entered blocking state
<6>[ 19.755784] int: port 3(wlan1) entered disabled state
<6>[ 19.762121] device wlan1 entered promiscuous mode
<6>[ 19.860627] IPv6: ADDRCONF(NETDEV_CHANGE): wlan1: link becomes ready
<6>[ 19.867243] int: port 3(wlan1) entered blocking state
<6>[ 19.872311] int: port 3(wlan1) entered forwarding state
<6>[ 21.167370] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
<6>[ 21.174100] int: port 2(wlan0) entered blocking state
<6>[ 21.179211] int: port 2(wlan0) entered forwarding state
<6>[319860.057754] mt7530-mdio mdio-bus:1f lan: Link is Down
<6>[319860.071078] int: port 1(lan) entered disabled state
<6>[332932.024408] mt7530-mdio mdio-bus:1f lan: Link is Up - 1Gbps/Full - flow control off
<6>[332932.032293] int: port 1(lan) entered blocking state
<6>[332932.037277] int: port 1(lan) entered forwarding state
<6>[658890.171767] mt7530-mdio mdio-bus:1f lan: Link is Down
<6>[658890.177373] int: port 1(lan) entered disabled state
<6>[751678.748021] mt7530-mdio mdio-bus:1f lan: Link is Up - 1Gbps/Full - flow control off
<6>[751678.755994] int: port 1(lan) entered blocking state
<6>[751678.760989] int: port 1(lan) entered forwarding state

View file

@ -0,0 +1,6 @@
Filesystem 1024-blocks Used Available Use% Mounted on
ubi0:rootfs 24884 20216 4668 81% /persist
ubi0:rootfs 24884 20216 4668 81% /nix
dev 124828 0 124828 0% /dev
tmpfs 125460 1452 124008 1% /run
none 125460 0 125460 0% /tmp

View file

@ -0,0 +1,15 @@
dev: size erasesize name
mtd0: 00080000 00020000 "u-boot"
mtd1: 00080000 00020000 "u-boot-env"
mtd2: 00080000 00020000 "factory"
mtd3: 02800000 00020000 "firmware_a"
mtd4: 00800000 00020000 "kernel_a"
mtd5: 02000000 00020000 "ubi_a"
mtd6: 02800000 00020000 "firmware_b"
mtd7: 00800000 00020000 "kernel_b"
mtd8: 02000000 00020000 "ubi_b"
mtd9: 01400000 00020000 "rootfs_data"
mtd10: 00d00000 00020000 "logs"
mtd11: 00480000 00020000 "vendor-myzyxel"
mtd12: 00080000 00020000 "bootconfig"
mtd13: 00080000 00020000 "mrd"

View file

@ -10,5 +10,4 @@
tftpboot = import ./tftpboot/test.nix;
updown = import ./updown/test.nix;
inout = import ./inout/test.nix;
custom-shell = import ./custom-shell/test.nix;
}

View file

@ -1,7 +0,0 @@
set timeout 60
spawn socat unix-connect:vm/console -
expect {
"root@liminix blah blah > " { exit 0 }
timeout { exit 1 }
}

View file

@ -1,13 +0,0 @@
{ config, pkgs, lib, ... } :
let
inherit (pkgs.liminix.networking) interface address hostapd route dnsmasq;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
in rec {
imports = [
../../modules/network
];
defaultProfile.prompt = "$(whoami)@$(hostname) blah blah > ";
defaultProfile.packages = with pkgs; [ ];
}

View file

@ -1,21 +0,0 @@
{
liminix
, nixpkgs
}:
let img = (import liminix {
inherit nixpkgs;
device = import "${liminix}/devices/qemu/";
liminix-config = ./configuration.nix;
}).outputs.default;
pkgs = import nixpkgs { overlays = [(import ../../overlay.nix)]; };
in pkgs.runCommand "check" {
nativeBuildInputs = with pkgs; [
expect socat
] ;
} ''
. ${../test-helpers.sh}
mkdir vm
${img}/run.sh --background ./vm
expect ${./check-prompt.expect} |tee output && mv output $out
''

View file

@ -6,7 +6,7 @@ let img = (import liminix {
device = import "${liminix}/devices/qemu/";
liminix-config = ./configuration.nix;
}).outputs.vmroot;
pkgs = import nixpkgs { overlays = [(import ../../overlay.nix)]; };
pkgs = import <nixpkgs> { overlays = [(import ../../overlay.nix)]; };
in pkgs.runCommand "check" {
nativeBuildInputs = with pkgs; [
expect

View file

@ -4,7 +4,7 @@
}:
let
overlay = import "${liminix}/overlay.nix";
pkgs = import nixpkgs { overlays = [overlay]; };
pkgs = import <nixpkgs> { overlays = [overlay]; };
script = pkgs.writeFennelScript "foo" [] ./hello.fnl;
inherit (pkgs.lua.pkgs) fifo;
netlink = pkgs.netlink-lua;

View file

@ -6,7 +6,7 @@ let img = (import liminix {
device = import "${liminix}/devices/qemu/";
liminix-config = ./configuration.nix;
}).outputs.vmroot;
pkgs = import nixpkgs { overlays = [(import ../../overlay.nix)]; };
pkgs = import <nixpkgs> { overlays = [(import ../../overlay.nix)]; };
in pkgs.runCommand "check" {
nativeBuildInputs = with pkgs; [
expect

View file

@ -5,6 +5,7 @@ in {
imports = [
../../vanilla-configuration.nix
../../modules/squashfs.nix
../../modules/outputs/jffs2.nix
];
config.rootfsType = "jffs2";
config.filesystem = dir {

View file

@ -6,7 +6,7 @@ let img = (import liminix {
device = import "${liminix}/devices/qemu/";
liminix-config = ./configuration.nix;
}).outputs.vmroot;
pkgs = import nixpkgs { overlays = [(import ../../overlay.nix)]; };
pkgs = import <nixpkgs> { overlays = [(import ../../overlay.nix)]; };
in pkgs.runCommand "check" {
nativeBuildInputs = with pkgs; [
expect

View file

@ -13,6 +13,7 @@ let
in {
imports = [
../../vanilla-configuration.nix
../../modules/outputs/jffs2.nix
];
config = {
services.sshd = longrun {

View file

@ -8,7 +8,7 @@ let lmx = (import liminix {
});
rogue = lmx.pkgs.rogue;
img = lmx.outputs.vmroot;
pkgs = import nixpkgs { overlays = [(import ../../overlay.nix)]; };
pkgs = import <nixpkgs> { overlays = [(import ../../overlay.nix)]; };
in pkgs.runCommand "check" {
nativeBuildInputs = with pkgs; [
expect

View file

@ -6,7 +6,7 @@ let img = (import liminix {
device = import "${liminix}/devices/qemu";
liminix-config = ./configuration.nix;
}).outputs.default;
pkgs = import nixpkgs { overlays = [(import ../../overlay.nix)]; };
pkgs = import <nixpkgs> { overlays = [(import ../../overlay.nix)]; };
inherit (pkgs.pkgsBuildBuild) routeros;
in pkgs.runCommand "check" {
nativeBuildInputs = with pkgs; [

View file

@ -1,6 +1,5 @@
{
liminix,
...
liminix
}:
let check = deviceName : config :
let derivation = (import liminix {

View file

@ -6,7 +6,7 @@ let img = (import liminix {
device = import "${liminix}/devices/qemu/";
liminix-config = ./configuration.nix;
}).outputs.vmroot;
pkgs = import nixpkgs { overlays = [(import ../../overlay.nix)]; };
pkgs = import <nixpkgs> { overlays = [(import ../../overlay.nix)]; };
in pkgs.runCommand "check" {
nativeBuildInputs = with pkgs; [
expect

View file

@ -7,7 +7,6 @@ in rec {
../../modules/wlan.nix
../../modules/hostapd
../../modules/network
./wpa_supplicant.nix
];
services.hostap = config.system.service.hostapd.build {
@ -28,21 +27,5 @@ in rec {
};
};
services.wpa_supplicant = config.system.service.wpa_supplicant.build {
interface = "wlan1";
driver = "nl80211";
config-file = pkgs.writeText "wpa_supplicant.conf" ''
country=us
update_config=1
ctrl_interface=/run/wpa_supplicant
network={
scan_ssid=1
ssid="liminix"
psk="colourless green ideas"
}
'';
};
defaultProfile.packages = with pkgs; [ tcpdump wpa_supplicant ];
defaultProfile.packages = with pkgs; [ tcpdump ] ;
}

View file

@ -3,11 +3,10 @@
, nixpkgs
}:
let img = (import liminix {
inherit nixpkgs;
device = import "${liminix}/devices/qemu/";
device = import "${liminix}/devices/qemu-armv7l/";
liminix-config = ./configuration.nix;
}).outputs.default;
pkgs = import nixpkgs { overlays = [(import ../../overlay.nix)]; };
pkgs = import <nixpkgs> { overlays = [(import ../../overlay.nix)]; };
in pkgs.runCommand "check" {
nativeBuildInputs = with pkgs; [
expect socat

View file

@ -14,10 +14,10 @@ expect {
}
expect "#"
while { $FINISHED < 10 } {
send "date && grep CTRL-EVENT-CONNECTED /run/uncaught-logs/* || echo \$NOT\r\n"
send "date && grep AP-ENABLED /run/uncaught-logs/* || echo \$NOT\r\n"
expect {
"wlan1: CTRL-EVENT-CONNECTED" { set FINISHED 999; set EXIT 0; }
"wlan0: AP-ENABLED" { set FINISHED 999; set EXIT 0; }
"not_present" { send_user "waiting ...\n" ; sleep 5 }
}
set FINISHED [ expr $FINISHED + 1 ]

View file

@ -1,21 +0,0 @@
{
liminix,
wpa_supplicant,
lib,
}:
{
interface,
driver,
config-file,
}:
let
inherit (liminix.services) longrun;
inherit (lib.strings) escapeShellArg;
in
longrun {
name = "wpa_supplicant";
run =
''
${wpa_supplicant}/bin/wpa_supplicant -D${driver} -i${interface} -c ${config-file}
'';
}

View file

@ -1,15 +0,0 @@
{ config, lib, pkgs, ... }:
with lib; {
options.system.service.wpa_supplicant = mkOption { type = pkgs.liminix.lib.types.serviceDefn; };
config.system.service.wpa_supplicant = config.system.callService ./wpa_service.nix {
interface = mkOption {
type = types.str;
};
driver = mkOption {
type = types.str;
};
config-file = mkOption {
type = types.package;
};
};
}