tftp: introduce an alternative command line for TFTP #8
23 changed files with 384 additions and 61 deletions
|
@ -170,7 +170,7 @@
|
|||
maxLEBcount = "256";
|
||||
};
|
||||
|
||||
flash.eraseBlockSize = 65536;
|
||||
flash.eraseBlockSize = 64 * 1024;
|
||||
|
||||
# This is a FIT containing a kernel padded and
|
||||
# a UBI volume rootfs.
|
||||
|
@ -181,8 +181,8 @@
|
|||
# Aligned on 2kb.
|
||||
alignment = 2048;
|
||||
|
||||
rootDevice = "ubi:rootfs";
|
||||
alternativeRootDevice = "ubi:rootfs";
|
||||
rootDevice = "ubi0:rootfs";
|
||||
alternativeRootDevice = "ubi1:rootfs";
|
||||
|
||||
# Auto-attach MTD devices: ubi_a then ubi_b.
|
||||
ubi.mtds = [ "ubi_a" "ubi_b" ];
|
||||
|
@ -224,6 +224,7 @@
|
|||
tftp = {
|
||||
# 5MB is nice.
|
||||
freeSpaceBytes = 5 * 1024 * 1024;
|
||||
appendDTB = true;
|
||||
loadAddress = lim.parseInt "0x2000000";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
./bridge
|
||||
./busybox.nix
|
||||
./dhcp6c
|
||||
./jitter-rng
|
||||
./dnsmasq
|
||||
./firewall
|
||||
./hardware.nix
|
||||
|
|
|
@ -14,5 +14,8 @@
|
|||
boot.commandLine = [
|
||||
"console=ttyS0,115200" # true of all mips we've yet encountered
|
||||
];
|
||||
boot.tftp.commandLine = [
|
||||
"console=ttyS0,115200" # true of all mips we've yet encountered
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -109,7 +109,13 @@ in {
|
|||
]
|
||||
++ (map (mtd: "ubi.mtd=${mtd}") config.hardware.ubi.mtds)
|
||||
++ lib.optional (config.rootOptions != null) "rootflags=${config.rootOptions}"
|
||||
++ lib.optional (config.hardware.alternativeRootDevice != null) "altroot=${config.hardware.alternativeRootDevice}";
|
||||
++ lib.optional (config.hardware.alternativeRootDevice != null) "rootalt=${config.hardware.alternativeRootDevice}";
|
||||
|
||||
boot.tftp.commandLine = [
|
||||
"panic=10 oops=panic init=/bin/init loglevel=8"
|
||||
"fw_devlink=off"
|
||||
"rootfstype=${config.rootfsType}"
|
||||
];
|
||||
|
||||
system.callService = path : parameters :
|
||||
let
|
||||
|
|
|
@ -20,6 +20,7 @@ in
|
|||
system.service.bridge = {
|
||||
primary = mkOption { type = liminix.lib.types.serviceDefn; };
|
||||
members = mkOption { type = liminix.lib.types.serviceDefn; };
|
||||
ready = mkOption { type = liminix.lib.types.serviceDefn; };
|
||||
};
|
||||
};
|
||||
config.system.service.bridge = {
|
||||
|
@ -28,6 +29,12 @@ in
|
|||
type = types.str;
|
||||
description = "bridge interface name to create";
|
||||
};
|
||||
|
||||
macAddressFromInterface = mkOption {
|
||||
type = types.nullOr liminix.lib.types.service;
|
||||
default = null;
|
||||
description = "reuse mac address from an existing interface service";
|
||||
};
|
||||
};
|
||||
members = config.system.callService ./members.nix {
|
||||
primary = mkOption {
|
||||
|
@ -40,6 +47,19 @@ in
|
|||
description = "interfaces to add to the bridge";
|
||||
};
|
||||
};
|
||||
|
||||
# TODO: generalize it outside
|
||||
ready = config.system.callService ./ready.nix {
|
||||
primary = mkOption {
|
||||
type = liminix.lib.types.service;
|
||||
description = "primary bridge interface";
|
||||
};
|
||||
|
||||
members = mkOption {
|
||||
type = liminix.lib.types.service;
|
||||
description = "members service";
|
||||
};
|
||||
};
|
||||
};
|
||||
config.kernel.config = {
|
||||
BRIDGE = "y";
|
||||
|
|
|
@ -10,21 +10,20 @@ let
|
|||
inherit (liminix.networking) interface;
|
||||
inherit (liminix.services) bundle oneshot;
|
||||
inherit (lib) mkOption types;
|
||||
addif = member :
|
||||
# how do we get sight of services from here? maybe we need to
|
||||
# implement ifwait as a regualr derivation instead of a
|
||||
# servicedefinition
|
||||
svc.ifwait.build {
|
||||
state = "running";
|
||||
interface = member;
|
||||
dependencies = [ primary member ];
|
||||
service = oneshot {
|
||||
addif = member : oneshot {
|
||||
name = "${primary.name}.member.${member.name}";
|
||||
up = ''
|
||||
echo "waiting for bridge $(output ${primary} ifname) to be ready"
|
||||
${ifwait}/bin/ifwait -v $(output ${primary} ifname) running
|
||||
echo "attaching $(output ${member} ifname) to $(output ${primary} ifname) bridge"
|
||||
ip link set dev $(output ${member} ifname) master $(output ${primary} ifname)
|
||||
'';
|
||||
down = "ip link set dev $(output ${member} ifname) nomaster";
|
||||
};
|
||||
down = ''
|
||||
echo "detaching $(output ${member} ifname) from any bridge"
|
||||
ip link set dev $(output ${member} ifname) nomaster
|
||||
'';
|
||||
|
||||
dependencies = [ primary member ];
|
||||
};
|
||||
in bundle {
|
||||
name = "${primary.name}.members";
|
||||
|
|
|
@ -3,15 +3,24 @@
|
|||
, ifwait
|
||||
, lib
|
||||
}:
|
||||
{ ifname } :
|
||||
{ ifname, macAddressFromInterface ? null } :
|
||||
let
|
||||
inherit (liminix.services) bundle oneshot;
|
||||
inherit (lib) mkOption types;
|
||||
inherit (lib) mkOption types optional;
|
||||
in oneshot rec {
|
||||
name = "${ifname}.link";
|
||||
up = ''
|
||||
ip link add name ${ifname} type bridge
|
||||
${liminix.networking.ifup name ifname}
|
||||
${if macAddressFromInterface == null then
|
||||
"ip link add name ${ifname} type bridge"
|
||||
else
|
||||
"ip link add name ${ifname} address $(output ${macAddressFromInterface} ether) type bridge"}
|
||||
|
||||
(in_outputs ${name}
|
||||
echo ${ifname} > ifname
|
||||
cat /sys/class/net/${ifname}/address > ether
|
||||
)
|
||||
'';
|
||||
down = "ip link set down dev ${ifname}";
|
||||
down = "ip link delete ${ifname}";
|
||||
|
||||
dependencies = optional (macAddressFromInterface != null) macAddressFromInterface;
|
||||
}
|
||||
|
|
18
modules/bridge/ready.nix
Normal file
18
modules/bridge/ready.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
liminix
|
||||
, ifwait
|
||||
, lib
|
||||
}:
|
||||
{ primary, members } :
|
||||
let
|
||||
inherit (liminix.services) oneshot;
|
||||
in oneshot {
|
||||
name = "${primary.name}.oper";
|
||||
up = ''
|
||||
ip link set up dev $(output ${primary} ifname)
|
||||
${ifwait}/bin/ifwait -v $(output ${primary} ifname) running
|
||||
'';
|
||||
down = "ip link set down dev $(output ${primary} ifname)";
|
||||
|
||||
dependencies = [ members ];
|
||||
}
|
|
@ -26,6 +26,10 @@ in {
|
|||
interface = mkOption {
|
||||
type = liminix.lib.types.service;
|
||||
};
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.hostapd;
|
||||
};
|
||||
params = mkOption {
|
||||
type = types.attrs;
|
||||
};
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
{
|
||||
liminix
|
||||
, hostapd
|
||||
, writeText
|
||||
, lib
|
||||
}:
|
||||
{ interface, params} :
|
||||
{ package, interface, params } :
|
||||
let
|
||||
inherit (liminix.services) longrun;
|
||||
inherit (lib) concatStringsSep mapAttrsToList;
|
||||
|
@ -35,5 +34,5 @@ let
|
|||
in longrun {
|
||||
inherit name;
|
||||
dependencies = [ interface ];
|
||||
run = "${hostapd}/bin/hostapd -i $(output ${interface} ifname) -P /run/${name}.pid -S ${conf}";
|
||||
run = "${package}/bin/hostapd -i $(output ${interface} ifname) -P /run/${name}.pid -S ${conf}";
|
||||
}
|
||||
|
|
21
modules/jitter-rng/default.nix
Normal file
21
modules/jitter-rng/default.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
## CPU Jitter RNG
|
||||
## ==============
|
||||
##
|
||||
## CPU Jitter RNG is a random number generator # providing non-physical true
|
||||
## random generation # that works equally for kernel and user-land. It relies
|
||||
## on the availability of a high-resolution timer.
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
inherit (pkgs) liminix;
|
||||
in {
|
||||
options.system.service.jitter-rng = mkOption {
|
||||
type = liminix.lib.types.serviceDefn;
|
||||
};
|
||||
|
||||
config = {
|
||||
system.service.jitter-rng = pkgs.liminix.callService ./jitter-rng.nix {
|
||||
};
|
||||
};
|
||||
}
|
||||
|
18
modules/jitter-rng/jitter-rng.nix
Normal file
18
modules/jitter-rng/jitter-rng.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
liminix
|
||||
, lib
|
||||
, jitterentropy-rngd
|
||||
}:
|
||||
{ }:
|
||||
let
|
||||
inherit (liminix.services) longrun;
|
||||
name = "jitterentropy-rngd";
|
||||
in
|
||||
longrun {
|
||||
# Does it need to be unique?
|
||||
inherit name;
|
||||
run = ''
|
||||
mkdir -p /run/jitterentropy-rngd
|
||||
${jitterentropy-rngd}/bin/jitterentropy-rngd -v -p /run/jitterentropy-rngd/${name}.pid
|
||||
'';
|
||||
}
|
|
@ -17,7 +17,7 @@ let
|
|||
ip address replace $ip/$mask dev $interface
|
||||
(in_outputs ${name}
|
||||
for i in lease mask ip router siaddr dns serverid subnet opt53 interface ; do
|
||||
printenv $i > $i
|
||||
(printenv $i || true) > $i
|
||||
done)
|
||||
}
|
||||
case $action in
|
||||
|
@ -40,7 +40,7 @@ let
|
|||
'';
|
||||
in longrun {
|
||||
inherit name;
|
||||
run = "/bin/udhcpc -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
|
||||
run = "exec /bin/udhcpc -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
|
||||
notification-fd = 10;
|
||||
dependencies = [ interface ];
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
, ...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkIf mkOption types;
|
||||
inherit (pkgs) liminix;
|
||||
inherit (lib) mkIf;
|
||||
o = config.system.outputs;
|
||||
in
|
||||
{
|
||||
|
@ -24,17 +25,10 @@ in
|
|||
};
|
||||
boot.initramfs.enable = true;
|
||||
system.outputs = {
|
||||
rootfs =
|
||||
let
|
||||
inherit (pkgs.pkgsBuildBuild) runCommand mtdutils;
|
||||
endian = if pkgs.stdenv.isBigEndian
|
||||
then "--big-endian" else "--little-endian";
|
||||
in runCommand "make-jffs2" {
|
||||
depsBuildBuild = [ mtdutils ];
|
||||
} ''
|
||||
tree=${o.bootablerootdir}
|
||||
(cd $tree && mkfs.jffs2 --compression-mode=size ${endian} -e ${toString config.hardware.flash.eraseBlockSize} --enable-compressor=lzo --pad --root . --output $out --squash --faketime )
|
||||
'';
|
||||
rootfs = liminix.builders.jffs2 {
|
||||
bootableRootDirectory = o.bootablerootdir;
|
||||
inherit (config.hardware.flash) eraseBlockSize;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
14
modules/outputs/tftpboot-fit.its
Normal file
14
modules/outputs/tftpboot-fit.its
Normal file
|
@ -0,0 +1,14 @@
|
|||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Liminix TFTP bootscript";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
bootscript {
|
||||
description = "Bootscript";
|
||||
data = /incbin/("boot.scr");
|
||||
type = "script";
|
||||
compression = "none";
|
||||
};
|
||||
};
|
|
@ -5,10 +5,18 @@
|
|||
, ...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkOption types concatStringsSep;
|
||||
inherit (lib) mkOption mkIf types concatStringsSep;
|
||||
inherit (pkgs) liminix;
|
||||
cfg = config.boot.tftp;
|
||||
hw = config.hardware;
|
||||
arch = pkgs.stdenv.hostPlatform.linuxArch;
|
||||
|
||||
# UBI cannot run on the top of phram.
|
||||
needsSquashfs = config.rootfsType == "ubifs";
|
||||
rootfstype = if needsSquashfs then "squashfs" else config.rootfsType;
|
||||
rootfs = if needsSquashfs then
|
||||
liminix.builders.squashfs config.filesystem.contents
|
||||
else config.system.outputs.rootfs;
|
||||
in {
|
||||
imports = [ ../ramdisk.nix ];
|
||||
options.boot.tftp = {
|
||||
|
@ -28,6 +36,14 @@ in {
|
|||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
commandLine = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = config.boot.commandLine;
|
||||
description = ''
|
||||
TFTP-specific command line.
|
||||
Defaults to the classical one if unset.
|
||||
'';
|
||||
};
|
||||
};
|
||||
options.system.outputs = {
|
||||
tftpboot = mkOption {
|
||||
|
@ -51,11 +67,52 @@ in {
|
|||
It uses the Linux `phram <https://github.com/torvalds/linux/blob/master/drivers/mtd/devices/phram.c>`_ driver to emulate a flash device using a segment of physical RAM.
|
||||
'';
|
||||
};
|
||||
|
||||
tftpboot-fit = mkOption {
|
||||
type = types.package;
|
||||
description = ''
|
||||
tftpboot-fit
|
||||
************
|
||||
|
||||
This output is a variant that encloses the `boot.scr` in a FIT
|
||||
if that's simpler to transfer for you.
|
||||
'';
|
||||
};
|
||||
};
|
||||
config = {
|
||||
boot.ramdisk.enable = true;
|
||||
|
||||
kernel.config = mkIf needsSquashfs {
|
||||
SQUASHFS = "y";
|
||||
SQUASHFS_XZ = "y";
|
||||
};
|
||||
|
||||
system.outputs = rec {
|
||||
tftpboot-fit =
|
||||
let
|
||||
tftpboot-fit = pkgs.writeText "tftpboot.its" ''
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Liminix TFTP bootscript";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
bootscript {
|
||||
description = "Bootscript";
|
||||
data = /incbin/("${tftpboot}/boot.scr");
|
||||
type = "script";
|
||||
compression = "none";
|
||||
};
|
||||
};
|
||||
};
|
||||
'';
|
||||
in
|
||||
pkgs.runCommand "tftpboot-fit" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ ubootTools ]; } ''
|
||||
mkdir -p $out/
|
||||
cp -rf ${tftpboot}/* $out/
|
||||
mkimage -f ${tftpboot-fit} $out/script.ub
|
||||
'';
|
||||
tftpboot =
|
||||
let
|
||||
inherit (pkgs.lib.trivial) toHexString;
|
||||
|
@ -69,7 +126,7 @@ in {
|
|||
zimage = "bootz";
|
||||
}; in choices.${cfg.kernelFormat};
|
||||
|
||||
cmdline = concatStringsSep " " config.boot.commandLine;
|
||||
cmdline = concatStringsSep " " config.boot.tftp.commandLine;
|
||||
objcopy = "${pkgs.stdenv.cc.bintools.targetPrefix}objcopy";
|
||||
stripAndZip = ''
|
||||
${objcopy} -O binary -R .reginfo -R .notes -R .note -R .comment -R .mdebug -R .note.gnu.build-id -S vmlinux.elf vmlinux.bin
|
||||
|
@ -84,7 +141,7 @@ in {
|
|||
hex() { printf "0x%x" $1; }
|
||||
|
||||
rootfsStart=${toString cfg.loadAddress}
|
||||
rootfsSize=$(binsize64k ${o.rootfs} )
|
||||
rootfsSize=$(binsize64k ${rootfs} )
|
||||
rootfsSize=$(($rootfsSize + ${toString cfg.freeSpaceBytes} ))
|
||||
|
||||
ln -s ${o.manifest} manifest
|
||||
|
@ -98,13 +155,13 @@ in {
|
|||
dtbStart=$(($rootfsStart + $rootfsSize))
|
||||
${if cfg.compressRoot
|
||||
then ''
|
||||
lzma -z9cv ${o.rootfs} > rootfs.lz
|
||||
lzma -z9cv ${rootfs} > rootfs.lz
|
||||
rootfsLzStart=$dtbStart
|
||||
rootfsLzSize=$(binsize rootfs.lz)
|
||||
dtbStart=$(($dtbStart + $rootfsLzSize))
|
||||
''
|
||||
else ''
|
||||
ln -s ${o.rootfs} rootfs
|
||||
ln -s ${rootfs} rootfs
|
||||
''
|
||||
}
|
||||
|
||||
|
@ -121,7 +178,7 @@ in {
|
|||
fdtput -p -t s dtb /reserved-memory/$node compatible phram
|
||||
fdtput -p -t lx dtb /reserved-memory/$node reg $ac_prefix $(hex $rootfsStart) $sz_prefix $(hex $rootfsSize)
|
||||
|
||||
cmd="liminix ${cmdline} mtdparts=phram0:''${rootfsSize}(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsSize},${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0";
|
||||
cmd="liminix ${cmdline} mtdparts=phram0:''${rootfsSize}(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsSize},${toString config.hardware.flash.eraseBlockSize} rootfstype=${rootfstype} root=/dev/mtdblock0";
|
||||
fdtput -t s dtb /chosen ${config.boot.commandLineDtbNode} "$cmd"
|
||||
|
||||
dtbSize=$(binsize ./dtb )
|
||||
|
|
83
modules/pki/default.nix
Normal file
83
modules/pki/default.nix
Normal file
|
@ -0,0 +1,83 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
# Inspired from nixpkgs/NixOS.
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
inherit (pkgs.pseudofile) dir symlink;
|
||||
cfg = config.security.pki;
|
||||
|
||||
cacertPackage = pkgs.cacert.override {
|
||||
blacklist = [ ];
|
||||
extraCertificateFiles = cfg.certificateFiles;
|
||||
extraCertificateStrings = cfg.certificates;
|
||||
};
|
||||
caBundleName = "ca-bundle.crt";
|
||||
caBundle = "${cacertPackage}/etc/ssl/certs/${caBundleName}";
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
options = {
|
||||
security.pki.installCACerts = mkEnableOption "installing CA certificates to the system" // {
|
||||
default = false;
|
||||
};
|
||||
|
||||
security.pki.certificateFiles = mkOption {
|
||||
type = types.listOf types.path;
|
||||
default = [];
|
||||
example = literalExpression ''[ "''${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ]'';
|
||||
description = ''
|
||||
A list of files containing trusted root certificates in PEM
|
||||
format. These are concatenated to form
|
||||
{file}`/etc/ssl/certs/ca-certificates.crt`, which is
|
||||
used by many programs that use OpenSSL, such as
|
||||
{command}`curl` and {command}`git`.
|
||||
'';
|
||||
};
|
||||
|
||||
security.pki.certificates = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = literalExpression ''
|
||||
[ '''
|
||||
NixOS.org
|
||||
=========
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGUDCCBTigAwIBAgIDD8KWMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
|
||||
TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
|
||||
...
|
||||
-----END CERTIFICATE-----
|
||||
'''
|
||||
]
|
||||
'';
|
||||
description = ''
|
||||
A list of trusted root certificates in PEM format.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.installCACerts {
|
||||
# NixOS canonical location + Debian/Ubuntu/Arch/Gentoo compatibility.
|
||||
filesystem = dir {
|
||||
etc = dir {
|
||||
ssl = dir {
|
||||
certs = dir {
|
||||
"ca-certificates.crt" = symlink caBundle;
|
||||
"ca-bundle.crt" = symlink caBundle;
|
||||
};
|
||||
};
|
||||
|
||||
# CentOS/Fedora compatibility.
|
||||
pki = dir {
|
||||
certs = dir {
|
||||
"ca-bundle.crt" = symlink caBundle;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
41
overlay.nix
41
overlay.nix
|
@ -143,6 +143,42 @@ extraPkgs // {
|
|||
});
|
||||
in h.override { openssl = null; sqlite = null; };
|
||||
|
||||
hostapd-radius =
|
||||
let
|
||||
config = [
|
||||
"CONFIG_DRIVER_NL80211=y"
|
||||
"CONFIG_DRIVER_WIRED=y"
|
||||
"CONFIG_EAP=y"
|
||||
"CONFIG_EAP_PEAP=y"
|
||||
"CONFIG_RADIUS_SERVER=y"
|
||||
"CONFIG_FULL_DYNAMIC_VLAN=y"
|
||||
"CONFIG_IAPP=y"
|
||||
"CONFIG_IEEE80211AC=y"
|
||||
"CONFIG_IEEE80211AX=y"
|
||||
"CONFIG_IEEE80211N=y"
|
||||
"CONFIG_IEEE80211W=y"
|
||||
"CONFIG_INTERNAL_LIBTOMMATH=y"
|
||||
"CONFIG_INTERNAL_LIBTOMMATH_FAST=y"
|
||||
"CONFIG_IPV6=y"
|
||||
"CONFIG_LIBNL32=y"
|
||||
"CONFIG_PKCS12=y"
|
||||
"CONFIG_RSN_PREAUTH=y"
|
||||
# Required to read the key material for RADIUS.
|
||||
"CONFIG_TLS=openssl"
|
||||
];
|
||||
h = prev.hostapd.overrideAttrs(o: {
|
||||
extraConfig = "";
|
||||
configurePhase = ''
|
||||
cat > hostapd/defconfig <<EOF
|
||||
${builtins.concatStringsSep "\n" config}
|
||||
EOF
|
||||
${o.configurePhase}
|
||||
'';
|
||||
});
|
||||
in h.override { sqlite = null; };
|
||||
|
||||
|
||||
|
||||
kexec-tools-static = prev.kexec-tools.overrideAttrs(o: {
|
||||
# For kexecboot we copy kexec into a ramdisk on the system being
|
||||
# upgraded from. This is more likely to work if kexec is
|
||||
|
@ -168,6 +204,11 @@ extraPkgs // {
|
|||
patches = (if o ? patches then o.patches else []) ++ [
|
||||
./pkgs/mtdutils/0001-mkfs.jffs2-add-graft-option.patch
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
# Testing programs which we don't need. We save a lot of space!
|
||||
rm -rf $out/libexec
|
||||
'';
|
||||
});
|
||||
|
||||
nftables = prev.nftables.overrideAttrs(o: {
|
||||
|
|
|
@ -13,6 +13,7 @@ in {
|
|||
liminix = {
|
||||
builders = {
|
||||
squashfs = callPackage ./liminix-tools/builders/squashfs.nix {};
|
||||
jffs2 = callPackage ./liminix-tools/builders/jffs2.nix {};
|
||||
dtb = callPackage ./kernel/dtb.nix {};
|
||||
uimage = callPackage ./kernel/uimage.nix {};
|
||||
kernel = callPackage ./kernel {};
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
(match v
|
||||
;; - up: Reflects the administrative state of the interface (IFF_UP)
|
||||
;; - running: Reflects the operational state (IFF_RUNNING).
|
||||
{:event "newlink" :name params.link :up :yes :running :yes}
|
||||
{:event "newlink" :name params.link :up "yes" :running "yes"}
|
||||
{:present true :up true :running true}
|
||||
|
||||
{:event "newlink" :name params.link :up :yes}
|
||||
{:present :true :up true}
|
||||
{:event "newlink" :name params.link :up "yes"}
|
||||
{:present true :up true}
|
||||
|
||||
{:event "newlink" :name params.link}
|
||||
{:present true }
|
||||
|
|
17
pkgs/liminix-tools/builders/jffs2.nix
Normal file
17
pkgs/liminix-tools/builders/jffs2.nix
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
stdenv
|
||||
, busybox
|
||||
, buildPackages
|
||||
, callPackage
|
||||
, pseudofile
|
||||
, runCommand
|
||||
, writeText
|
||||
} : { eraseBlockSize, bootableRootDirectory }:
|
||||
let
|
||||
endian = if stdenv.isBigEndian then "--big-endian" else "--little-endian";
|
||||
in runCommand "frob-jffs2" {
|
||||
depsBuildBuild = [ buildPackages.mtdutils ];
|
||||
} ''
|
||||
tree=${bootableRootDirectory}
|
||||
(cd $tree && mkfs.jffs2 --compression-mode=size ${endian} -e ${toString eraseBlockSize} --enable-compressor=lzo --pad --root . --output $out --squash --faketime)
|
||||
''
|
|
@ -9,6 +9,7 @@
|
|||
ip link set up dev ${ifname}
|
||||
(in_outputs ${name}
|
||||
echo ${ifname} > ifname
|
||||
cat /sys/class/net/${ifname}/address > ether
|
||||
)
|
||||
'';
|
||||
}
|
||||
|
|
|
@ -65,13 +65,18 @@ static char * eat_param(char *p, char *param_name, char **out)
|
|||
return p;
|
||||
}
|
||||
|
||||
#define SCAN_CMDLINE(cmdline, identifier, field) do { \
|
||||
for (char* p = strdup(cmdline); *p; p++) { \
|
||||
p = eat_param(p, identifier, &(opts->field)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
void parseopts(char * cmdline, struct root_opts *opts) {
|
||||
for(char *p = cmdline; *p; p++) {
|
||||
p = eat_param(p, "root=", &(opts->device));
|
||||
p = eat_param(p, "rootfstype=", &(opts->fstype));
|
||||
p = eat_param(p, "rootflags=", &(opts->mount_opts));
|
||||
p = eat_param(p, "altroot=", &(opts->altdevice));
|
||||
};
|
||||
SCAN_CMDLINE(cmdline, "root=", device);
|
||||
SCAN_CMDLINE(cmdline, "rootfstype=", fstype);
|
||||
SCAN_CMDLINE(cmdline, "rootflags=", mount_opts);
|
||||
SCAN_CMDLINE(cmdline, "rootalt=", altdevice);
|
||||
}
|
||||
|
||||
#ifdef TESTS
|
||||
|
@ -85,6 +90,8 @@ void parseopts(char * cmdline, struct root_opts *opts) {
|
|||
#define S(x) #x
|
||||
#define expect_equal(actual, expected) \
|
||||
if(!actual || strcmp(actual, expected)) die("%d: expected \"%s\", got \"%s\"", __LINE__, expected, actual);
|
||||
#define expect_null(actual) \
|
||||
if (actual) die("%d: expected null, got \"%s\"", __LINE__, actual);
|
||||
|
||||
|
||||
int main()
|
||||
|
@ -92,6 +99,7 @@ int main()
|
|||
struct root_opts opts = {
|
||||
.device = "/dev/hda1",
|
||||
.fstype = "xiafs",
|
||||
.altdevice = NULL,
|
||||
.mount_opts = NULL
|
||||
};
|
||||
char *buf;
|
||||
|
@ -103,14 +111,22 @@ int main()
|
|||
expect_equal(opts.fstype, "ubifs");
|
||||
expect_equal(opts.mount_opts, "subvol=1");
|
||||
|
||||
// finds altroot= options
|
||||
buf = strdup("liminix console=ttyS0,115200 panic=10 oops=panic init=/bin/init loglevel=8 root=/dev/ubi0_4 rootfstype=ubifs rootflags=subvol=1 fw_devlink=off mtdparts=phram0:18M(rootfs) phram.phram=phram0,0x40400000,18874368,65536 root=/dev/mtdblock0 altroot=/dev/mtdblock6 foo");
|
||||
// finds rootalt= options
|
||||
buf = strdup("liminix console=ttyS0,115200 panic=10 oops=panic init=/bin/init loglevel=8 root=/dev/ubi0_4 rootfstype=ubifs rootflags=subvol=1 fw_devlink=off mtdparts=phram0:18M(rootfs) phram.phram=phram0,0x40400000,18874368,65536 root=/dev/mtdblock0 rootalt=/dev/mtdblock6 foo");
|
||||
memset(&opts, '\0', sizeof opts); parseopts(buf, &opts);
|
||||
expect_equal(opts.device, "/dev/mtdblock0");
|
||||
expect_equal(opts.altdevice, "/dev/mtdblock6");
|
||||
expect_equal(opts.fstype, "ubifs");
|
||||
expect_equal(opts.mount_opts, "subvol=1");
|
||||
|
||||
// Ensure that `altdevice` is NULL.
|
||||
buf = strdup("liminix console=ttyS0,115200 panic=10 oops=panic init=/bin/init loglevel=8 fw_devlink=off rootfstype=ubifs mtdparts=phram0:19791872(rootfs) phram.phram=phram0,33554432,19791872,65536 rootfstype=jffs2 root=/dev/mtdblock0");
|
||||
memset(&opts, '\0', sizeof opts); parseopts(buf, &opts);
|
||||
expect_equal(opts.device, "/dev/mtdblock0");
|
||||
expect_null(opts.altdevice);
|
||||
expect_equal(opts.fstype, "jffs2");
|
||||
expect_null(opts.mount_opts);
|
||||
|
||||
// in case of duplicates, chooses the latter
|
||||
// also: works if the option is end of string
|
||||
buf = strdup("liminix console=ttyS0,115200 panic=10 oops=panic init=/bin/init loglevel=8 root=/dev/ubi0_4 rootfstype=ubifs fw_devlink=off mtdparts=phram0:18M(rootfs) phram.phram=phram0,0x40400000,18874368,65536 root=/dev/mtdblock0");
|
||||
|
@ -146,12 +162,12 @@ int main()
|
|||
if(opts.altdevice) die("expected null altdevice, got \"%s\"", opts.altdevice);
|
||||
|
||||
// provides empty strings for empty options
|
||||
buf = strdup("liminix rootfstype= fw_devlink=off root= altroot= /dev/hda1");
|
||||
buf = strdup("liminix rootfstype= fw_devlink=off root= rootalt= /dev/hda1");
|
||||
memset(&opts, '\0', sizeof opts); parseopts(buf, &opts);
|
||||
|
||||
if(strlen(opts.fstype)) die("expected empty rootfstype, got \"%s\"", opts.fstype);
|
||||
if(strlen(opts.device)) die("expected empty root, got \"%s\"", opts.device);
|
||||
if(strlen(opts.altdevice)) die("expected empty altroot, got \"%s\"", opts.altdevice);
|
||||
if(strlen(opts.altdevice)) die("expected empty rootalt, got \"%s\"", opts.altdevice);
|
||||
|
||||
expect_equal("01", pr_u32(1));
|
||||
expect_equal("ab", pr_u32(0xab));
|
||||
|
|
Loading…
Reference in a new issue