2
0

61 Commits

Author SHA1 Message Date
dan 3f889c7119 default firewall zones in gateway profile 2025-02-10 21:21:08 +00:00
dan 7f17125039 firewall: update zones with interface names as they appear 2025-02-10 21:21:08 +00:00
dan 4bb081ffcf export anoia.svc:fileno so it can be used with event loops 2025-02-10 21:21:08 +00:00
dan 6587813577 WIP add zones to firewall module
- zones are an attrset of name -> [interface-service]

- the firewall will create empty "ifname" sets for each zone name
 in each address family (ip, ip6)

- then watch the interface services, and add the "ifname" outputs
to the corresponding sets when they appear

This commit only adds the empty sets
2025-02-10 21:21:08 +00:00
dan 1d780de0f1 add (very basic) set support in firewallgen
and add sets for lan/wan/dmz/guest interface names to default
firewall rules
2025-02-10 21:17:43 +00:00
dan 8cf602da91 think 2025-02-10 21:17:43 +00:00
dan c92aacc6fd firewall rules: use @lan and @wan sets instead of ifnames
we don't have anything yet to create or populate the sets
2025-02-06 09:22:41 +00:00
dan eff255fe12 boot.expect: sleep more, for gl-ar750
the bootloader on gl-ar750 loses characters if we shovel them too fast
2025-02-05 20:35:04 +00:00
dan 453baede61 rt3200: add installer compatibility note 2025-02-05 20:35:04 +00:00
dan 2295ed3110 Merge pull request 'OpenWrt One device support' (#13) from raboof/liminix:openwrt-one into main
Reviewed-on: #13
2025-01-08 13:57:39 +00:00
Arnout Engelen e71d92eb3d OpenWrt One support
https://openwrt.org/toh/openwrt/one
2025-01-07 16:10:04 +01:00
dan f77da6f14c remove remaining refs to kexecboot 2025-01-05 17:22:30 +00:00
dan 61eaaa82eb drivel 2025-01-05 17:17:44 +00:00
dan 95dd1a1fab add missing code-block 2025-01-05 15:45:04 +00:00
dan 2f9b0f12f9 switch uid 2025-01-05 12:57:51 +00:00
dan 9fd9b8b878 rt3200 kconfig for 6.6.x
* DMA stuff needed for wired ethernet

* DSA MDIO _probably_ (based on guessing from openwrt dmesg) needed
for wired ethernet

* some or all of NVMEM so that wireless drivers can read their eeprom
2025-01-05 00:16:03 +00:00
dan 26f206d0e1 phram dtb reserved-memory needs no-map
c.f. 69429404ab

Co-authored-by: Arnout Engelen <arnout@bzzt.net>
2025-01-04 23:50:44 +00:00
dan 8cd068ea68 belkin rt3200: set tftp loadAddress to match u-boot
the old value of 0x4007ff28 was originally copied from something
upstreamy but I have no record of what. 0x48000000 is $loadaddr
in u-boot so let's use that instead
2025-01-04 23:48:19 +00:00
dan 350ddde260 add pkgs.openwrt_24_10
is needed by Belkin RT3200 and might also be handy for OpenWrt One?

this is very copy-pastey, will tidy it up after it
stops being a moving target
2025-01-03 23:52:08 +00:00
dan 13cb8d3692 sort imports 2025-01-03 15:41:22 +00:00
dan 62b7aea8ab add btrfs.nix to outputs imports 2025-01-03 15:40:33 +00:00
dan 76e3fd9a55 add rt3200 to CI 2025-01-03 15:39:08 +00:00
dan 92284fa9ba mtdimage can't be a default import
it adds kernel config that depend on openwrt patches,
which aren't used/needed on all devices
2025-01-03 00:19:17 +00:00
dan a2bb55e885 oops fix syntax error 2025-01-03 00:07:00 +00:00
dan 74027b44d7 extract log persistence config from s6 to new module
because it frobs kernel config, it breaks levitate
as levitate evalModules doesn't include the kernel
2025-01-02 23:56:49 +00:00
dan ea5370b3f4 import mtdimage in outputs 2025-01-02 23:37:07 +00:00
dan 55ed365920 turris omnia: default rootfs and bootloader settings 2025-01-02 23:36:15 +00:00
dan aa2160dd05 logtap: fix indentation
spaces not tabs
2025-01-02 22:45:00 +00:00
dan df414b796f drivel 2025-01-02 22:19:49 +00:00
dan 7377f7ceb2 implement mechanism for reverting from update.sh 2025-01-02 22:19:49 +00:00
dan 49432aeda5 Merge pull request 'Fix typo: Buildiing -> Building' (#15) from raboof/liminix:typo into main
Reviewed-on: #15
Reviewed-by: dan <dan@telent.net>
2025-01-02 14:46:36 +00:00
Arnout Engelen 3caf8a75bb Fix typo: Buildiing -> Building 2025-01-02 10:53:38 +01:00
dan cc94ef57fa in rc.init copy log from previous boot to place of safety 2025-01-01 18:22:45 +00:00
dan fd28f0ce04 rt3200 needs pmsg-size set in its dts for persistent logging 2025-01-01 14:11:22 +00:00
dan 497307588f automate ubimage instructions a little 2025-01-01 12:38:08 +00:00
dan 788169586f /boot is a directory, copy files instead of replacing it with symlink
for the record, u-boot doesn't like having /boot/fit -> ../nix/store/..../fit
symlinks so we don't use symlinks inside /boot either
2025-01-01 12:29:25 +00:00
dan 3af9e86624 rt3200: replace bootcmd variable
the default is to boot to recovery if there's anything in pstore, but
this doesn't interact well with persstent logging
2025-01-01 11:56:54 +00:00
dan 28d39cd66d provide etc/kconfig in updater output
this is for debugging/documentation purposes and isn't copied to the
device
2025-01-01 11:55:33 +00:00
dan 9dd169d500 add "config" output to kernel derivation 2025-01-01 11:54:46 +00:00
dan 2e513eb4a7 example sni proxy using nginx 2024-12-29 23:34:15 +00:00
dan f2e4e77d73 firewall: don't use oifname in input rules
because it's empty, these are input rules for the local machine
2024-12-29 23:17:31 +00:00
dan 48dfbe0c01 add nginx-small : nginx with finegrained configure options 2024-12-29 20:47:03 +00:00
dan 6f697db57c remove PSTORE from rt3200 default kconfig
we have config.logging.persistent.enable at home
2024-12-29 13:33:55 +00:00
dan fe1ee12e3d swap strchr for strchrnul in dropbear authkeyfile patch
The strchrnul version was giving weird crashes on aarch64
belkin-rt3200. I haven't figured out why but this one doesn't
2024-12-29 13:30:21 +00:00
dan 4d273a9469 dropbear would like /etc/shells to exist 2024-12-29 13:27:49 +00:00
dan 40db175b41 complain if user attempting to tftpboot a ubifs 2024-12-29 13:26:45 +00:00
dan ab07212a7e include jffs2 module per default
it has no effect unless enabled
2024-12-29 13:26:06 +00:00
dan f5e08ac9d9 rt3200 default to loader.fit 2024-12-29 13:25:26 +00:00
dan 0cb18eabcd boot.expect: improve reliability
don't depend on seeing u-boot prompt, it's just too easy to get
out of sync
2024-12-27 18:08:01 +00:00
dan 24151425b8 and fix quoting 2024-12-24 14:29:01 +00:00
dan e06295ed83 rt3200: add fw_setenv commands to update boot_production 2024-12-24 14:19:29 +00:00
dan 608d3e3abf proofread 2024-12-24 14:01:30 +00:00
dan 3e19f1b927 Merge branch 'runciter' 2024-12-24 13:47:27 +00:00
dan 3f6e9b6384 rt3200 defaults to ubifs 2024-12-24 13:46:36 +00:00
dan 294492a176 jiggle imports 2024-12-24 13:46:19 +00:00
dan 67a1cd3718 improve install instructions for belkin rt3200 2024-12-24 13:45:11 +00:00
dan 452aaa2f60 Merge pull request 'use Linux kernel sources associated with openwrt by default' (#12) from raboof/liminix:linux-version-with-openwrt into main
Reviewed-on: #12
2024-12-24 12:24:31 +00:00
dan 52967f746b Merge branch 'main' into linux-version-with-openwrt 2024-12-24 12:24:13 +00:00
Arnout Engelen a89f866bf0 use Linux kernel sources associated with openwrt by default 2024-12-24 12:21:28 +00:00
dan f3fadd5cd7 think 2024-12-24 12:20:48 +00:00
Arnout Engelen 1ff779c1a9 use Linux kernel sources associated with openwrt by default 2024-12-17 20:24:14 +01:00
45 changed files with 1940 additions and 292 deletions
+350
View File
@@ -6670,3 +6670,353 @@ 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
Tue Dec 24 16:14:50 GMT 2024
Where next?
a config for haproxy would be good
> a connection or request arrives on a frontend, then the
information carried with this request or connection are processed, and
at this point it is possible to write ACLs-based conditions making use
of these information to decide what backend will process the request.
http://docs.haproxy.org/3.1/intro.html#3.4.4
listen foo
bind :443
frontend foo
mode tcp
Thu Dec 26 14:27:26 GMT 2024
What's the plan?
1) build the updater target for rotuer
2) ssh forward through bordervm to install it
3) carve the ngix sni proxy into examples/module-sniproxy
with a fat warning comment
3.5) should we add the examples to ci?
4) see if it builds
5) using curl on bordervm, see if it forwards
5000) swap the real rotuer hardware
Sun Dec 29 18:22:42 GMT 2024
To make sniproxy work it needs dns, which means it needs an upstream.
But if we move the bordervm cable from lan to wan, we won't be able to
rebuild over ssh unless it's sufficiently unbroken for pppoe to be working
... unless we add a "management" address to the wan interface along with pppoe
to permit wan stuff through the firewall, now that we've fixed the
firewall :embarrassed:, do
/nix/store/*nftables*/bin/nft insert rule table-ip input-ip4 position 19 iifname "wan" jump incoming-allowed-ip4
What else do we need to try rt3200 as prod rotuer?
- pstore logging
- log shipping (maybe via wan to bordervm for now)
- enable sniproxy module
zcat /proc/config.gz | grep PSTORE
Tue Dec 31 22:45:33 GMT 2024
/nix/store/i1khbsqpyx020xrhvfbdazc1bnmirc72-kernel-aarch64-unknown-linux-musl-modulesupport/vmlinux
these 3 derivations will be built:
/nix/store/fvxrvyx64cm86cc4na0584qj9xw6s406-kernel-aarch64-unknown-linux-musl.drv
/nix/store/ksg93bd8x2z1xpfmj24ixm2srg547mjx-dtb-aarch64-unknown-linux-musl.drv
/nix/store/n33ij1npzwjmlsw23sz6yhyrh9hgxwaw-kernel.image-aarch64-unknown-linux-musl.drv
building '/nix/store/fvxrvyx64cm86cc4na0584qj9xw6s406-kernel-aarch64-unknown-linux-musl.drv'...
zcat /proc/config.gz | grep PSTORE
we think tftpboot works (check!)
build the FIT from the updater target with squashfs added in rotuer.nix
boot it with tftp by copy-pasting the boot.scr and changing it
setenv serverip 10.0.0.1
setenv ipaddr 10.0.0.8
tftpboot 0x4007ff28 r2/rootfs; tftpboot 0x41086f28 r2/image; tftpboot 0x4107ff28 r2/dtb
bootm 0x41086f28 - 0x4107ff28
tftpboot works
tftpboot with outputs.uimage works
1458ed2cdeaa6bf4c02c6511a6d7369d /nix/store/4n3jc4n7lsp73yc2ccnmgibc7079rxms-kernel.image-aarch64-unknown-linux-musl
$ grep fit /nix/store/ihi7vski37b9ph4xcyqpabymc5nsngjd-system-configuration-aarch64-unknown-linux-musl/etc/nix-store-paths
/nix/store/5jphs9mnb8hzhvwfi2z8h6cnaz6qx4y6-boot-fit
$ md5sum /nix/store/5jphs9mnb8hzhvwfi2z8h6cnaz6qx4y6-boot-fit/fit
1458ed2cdeaa6bf4c02c6511a6d7369d /nix/store/5jphs9mnb8hzhvwfi2z8h6cnaz6qx4y6-boot-fit/fit
something is changing /persist/boot from a symlink to a directory and I don't know what
... plot twist: or is it? maybe it's ubimage that makes it a directory
rt3200 has no pmsg-size according to dtc -I fs /proc/device-tree/ -O dts
should be more like
reserved-memory {
ramoops@03f00000 {
compatible = "ramoops";
reg = <0x03f00000 0x10000>;
pmsg-size = <0x10000>;
};
};
};
Wed Jan 1 14:57:35 GMT 2025
At last I have working persistent logging.
I think we need to do something at boot time to move the persistent logs into
the regular s6 log thing
foreground {
redirfd -w 1 /run/prior-boot2
elglob file /sys/fs/pstore/* cat $file
}
Thu Jan 2 14:31:11 GMT 2025
to change to a previous "generation" we could run any of
"/nix/store/*system-configuration*/bin/install /mnt" from a rescue
system. It would populate /boot and bin/activate
supposing we are in such a rescue system, how do we find *which*
system-configuration is the one we want to revert to? The derivation
should be pure, so if we're going to timestamp anything we have to do
that in the imperative step i.e. update.sh
perhaps a symlink from /persist/configuration/yyyymmddtmmhhss -> /nix/store/eeee-blah
Thu Jan 2 23:38:59 GMT 2025
Stuff we should tidy up:
1) all devices to set credible default output, rootfs, etc
2) expunge remaining references to kexecboot
3) dynamic uid assigment for users
4) lessen logging noise from firewall
5) update.sh --fast sends wlan services for a spin
Fri Jan 3 16:05:10 GMT 2025
* build actual rotuer config and install on rt3200
* find usb ethernet dongle for laptop
* plug it in?
Sat Jan 4 15:32:03 GMT 2025
didn't work so well, because the installer version is coupled with the
dtb and the dtb can't be upgraded without upgrading the kenrel
kernel 6.6.67 builds and boots but seems to have no wired ethernet.
looking through the openwrt config changes ...
+CONFIG_MTD_UBI_NVMEM=y
+CONFIG_NVMEM_BLOCK=y
+CONFIG_NVMEM_LAYOUT_ADTRAN=y
+CONFIG_PHYLIB_LEDS=y
+CONFIG_MTK_REGULATOR_COUPLER=y
+CONFIG_FW_LOADER_SYSFS=y
Sun Jan 5 12:58:52 GMT 2025
We are running with rt3200 and everything appears to work :-)
Sun Jan 5 20:34:18 GMT 2025
what customization do we want from the firewall?
- what's allowed wan->lan
- what's allowed lan->wan
- which dropped packets get logged or don't
plus fix whatever it was RoS found
plus stop hardcoding the interface names
Q: if pppd _makes_ an interface, how do we know what the name of it
is going to be before it's up and passing packets so that we can
have the firewall active before it starts
or could we have ppp service install a "drop everything" firewall
before it starts? what if there's more than one upstream interface,
they shouldn't wipe each other out
so can we have a "default deny" firewall in which every allowed flow
is qualified by the interface name, and any service that brings up an
interface is required to add firewall rules for it according to its
role
or maybe the firewall service could watch for interfaces being added
(and removed) and update the ruleset as appropriate for the interface
role (lan, wan, dmz, management, guest, ???). but how does it know
the role based on the interface name?
Tue Jan 14 19:33:28 GMT 2025
each interface can add its own chain when it comes up, and then we can
figure out some way to jump to the correct chain (vmaps) based on
interface name
% nft add map filter mydict { type ipv4_addr : verdict\; }
% nft add element filter mydict { 192.168.0.10 : drop, 192.168.0.11 : accept }
% nft add rule filter input ip saddr vmap @mydict
_but_ we might be better off declaring static "zones" (lan, world,
dmz, guest, etc etc) with a map for each, and then replace the hardcoded
interface names with a map lookup
% nft add map filter ifzone { type ifname : string ; }
zones { type ifname: ipv4_addr\; }
... and presumably we also need identical maps for nat and
... any other chain type where we need to distinguish
... inside from outside
% nft add element nat porttoip { 80 : 192.168.1.100, 8888 : 192.168.1.101 }
% nft add rule ip nat postrouting snat to tcp dport map @porttoip
Mon Jan 20 20:32:58 GMT 2025
1) maybe we can add a type="chain" or type="set" attribute to the
firewallgen input, then we cna have sets in the default firewall rules
2) then we convert the default firewall rules to use sets instead of
hardcoding ifname
3) then find a nice place to hook "new interface is available" and
add it to the appropriate zone (separately for ip4 and ip6, gah)
4) and how do we find
# nft add element ip table-ip lan { int }
# nft add element ip table-ip wan { ppp0 }
# nft add element ip6 table-ip6 lan { int }
# nft add element ip6 table-ip6 wan { ppp0 }
Tue Jan 28 21:51:46 GMT 2025
Going back and forth on the firewall stuff, in respect of where to aim
for with "general" vs "useful". Specifically, if we have hooks
every time interfaces are added/removed that
expect some specific sets to (a) exist and (b) have particular
semantics, there is necessary coupling between those hooks and the
firewall definition. So, practically speaking, the "a new interface
appears" rules need to be bundled with the firewall ruleset
Which also means that the firewall needs to know which zone the
interface is assigned to, which is a problem if it can't tell from the
name (for example wg0 wg1 wg2 ... could be wan or lan or dmz or
anything)
So the service that owns the interface needs to communicate "another
one for the lan zone" to the firewall and it can't do that by adding
to sets directly unless it knows what the sets are called. Implying we
need an interface between the interface service that knows "new
interface ppp7 added in wan zone" and the firewall service that knows
how to accommodate this. For extra credit this actually should be more
like pubsub: the interface shouldn't really have to know the firewall
exists.
outputs?
- what if each interface wrote a "zone" output and the firewall
subscribed to them? would need the firewall to know which of all the
available services were interfaces
- a zone service that every interface in the zone depends on. it
doesn't do much in itself but it means the interface updown scripts
know a service directory where they can touch lan-zone/eth0 or
whatever. This could work. The firewall service definition specifies
the zone services and uses inotify watcher thingies to update
interface sets when contents change.
Wed Jan 29 17:19:24 GMT 2025
1) make a zone service defn that can be instantiated for each zone.
it should create $output/interfaces
2) add a `zone` attribute to interface definitions, causing
- the zone service to be added to the dependencies
- the interface "up" script to include writing to the zone/interfaces output
2b) any other service that creates an interface (e.g. ppp) needs to also
have `zone` and do the same
3) firewallgen to be able to make sets
4) firewall service to watch the zone outputs
Fri Jan 31 17:11:16 GMT 2025
Do we need zone services? I think we could put zones in the outputs of
the firewall service?
Sun Feb 2 20:59:56 GMT 2025
What's the smallest first step?
- [done] how can we make firewallgen output sets (or could we
make the firewall service tack them on afterwards)
- make a longrun that watches its own zones output and updates the
appropriate sets
The sticking point is that if you give the firewall `rules` instead of
`extraRules` then the longrun may or may not work depending on (1)
whether you made the zone sets; (2) whether your rules use
them. Conclusion: if you supply `rules` then you also have to say
whether you want the longrun or not. So add a param
watchForInterfaceUpdates which defaults true
Mon Feb 3 21:12:55 GMT 2025
the thing that updates sets has to know they exist, so the interface watcher
service must live in the firewall module
the firewall service defn should return the firewall service after
adding the interface watcher as a dependency of it. Or: the watcher
should make the sets and then the firewall service could depend on _it_.
That would mean that the firewall service would fail if it used sets
that the watcher didn't make, is that good or bad or indifferent?
the interface services have to know about the watcher as well in order
to write into its outputs, so it can't be hidden inside the module
maybe the watcher service should _be_ the firewall service.
we could add a "notify" param to an interface which would be an output
reference to (the firewall service / zones / lan ) that the interface would
write its ifname into when the service is up
Wed Feb 5 00:14:29 GMT 2025
another thought: the firewall service could have params to say
which interface services are in which zones
we'd have to ensure that the interface services did not end up as
dependencies of the firewall
then the firewall could
- create the sets
- watch each interface service for the ifname output and add it to the right zone
Sun Feb 9 21:33:57 GMT 2025
nft update set @lan
echo 'flush set table-ip lan; add element table-ip lan { eth0,lo }' | nft -f -
+31 -9
View File
@@ -2,19 +2,41 @@
# use expect as its "Script program" instead of runscript. Try
# Ctrl+A O -> Filenames and paths -> D
fconfigure stderr -buffering none
fconfigure stdout -buffering none
proc waitprompt { } {
expect {
"BusyBox" { puts stderr "DONE\r"; exit 0 }
"READY" { puts stderr ";;; READY\r"; }
timeout { puts stderr ";;; timed out waiting after $line\r" }
}
}
proc sendline { line } {
send "$line; echo \$ready \r"
sleep 0.1
}
log_user 0
log_file -a -open stderr
set f [open "result/boot.scr"]
send "version\r"
set timeout 60
send "setenv ready REA\r"
sleep 0.1
send "setenv ready \${ready}DY\r"
sleep 0.1
set timeout 300
expect_before timeout abort
while {[gets $f line] >= 0} {
puts stderr "next line $line\r"
puts stderr "waiting for prompt\r"
expect {
"ath>" {}
"BusyBox" { puts stderr "DONE"; exit 0 }
}
send "$line\r\n"
puts stderr ";;; next line $line\r"
puts stderr ";;; waiting for prompt\r"
puts stderr ";;; sending\r"
sendline $line
waitprompt
}
puts stderr "done\r\n"
close $f
+2
View File
@@ -11,8 +11,10 @@ let
"qemu-aarch64"
"qemu-armv7l"
"tp-archer-ax23"
"openwrt-one"
"zyxel-nwa50ax"
"turris-omnia"
"belkin-rt3200"
];
vanilla = ./vanilla-configuration.nix;
for-device = name:
+1
View File
@@ -33,6 +33,7 @@ let
./modules/busybox.nix
./modules/hostname.nix
./modules/kernel
./modules/logging.nix
./modules/klogd.nix
device.module
liminix-config
+90 -29
View File
@@ -4,13 +4,8 @@
******************************
This device is based on a 64 bit Mediatek MT7622 ARM platform,
and is "work in progress" in Liminix.
.. note:: The factory flash image contains ECC errors that make it
incompatible with Liminix: use the `OpenWrt
UBI Installer <https://github.com/dangowrt/owrt-ubi-installer>`_ to
rewrite the partition layout before you can use
Liminix with it
and is mostly feature-complete in Liminix but as of Dec 2024
has seen very little actual use.
Hardware summary
================
@@ -25,7 +20,11 @@
Installation
============
Installation is currently a manual process.
Liminix on this device uses the UBI volume management system to
perform wear leveling on the flash. This is not set up from the
factory, so a one-time step is needed to prepare it before Liminix
can be installed.
Preparation
-----------
@@ -33,9 +32,16 @@
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:
rewrite the flash layout. As of Jan 2025 there are two versions
of the installer available: the release version 1.0.2 and the
pre-release 1.1.3 and for Liminix you nee the pre-relese.
The release version of the installer creates UBI volumes
according to an older layout that is not compatible with
the Linux 6.6.67 kernel used in Liminix.
You can run the installer in one of two ways:
either follow the instructions to do it through the vendor web
interface, or you can drop to U-boot and use TFTP
interface, or you can drop to U-Boot and use TFTP
.. code-block:: console
@@ -44,16 +50,64 @@
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
This will write the new flash layout and then boot into a
"recovery" OpenWrt installation.
Installing Liminix
------------------
Building/installing Liminix
----------------
This is a manual process: you need a :ref:`serial <serial>` conection and TFTP : follow the instructions at :ref:`system-outputs-ubimage`
The default target for this device is ``outputs.ubimage`` which
makes a ubifs image suitable for use with :command:`ubiupdatevol`.
To write this to the device we use the OpenWrt recovery system
installed in the previous step. In this configuration the
device assigns itself the IP address 192.168.1.1/24 on its LAN
ports and expects the connected computer to have 192.168.1.254
'';
.. warning:: The `ubi0_7` device in these instructions is correct
as of Dec 2024 (dangowrt/owrt-ubi-installer commit
d79e7928). If you are installing some time later, it
is important to check the output from
:command:`ubinfo -a` and make sure you are updating
the "liminix" volume and not some other one which had
been introduced since I wrote this.
.. code-block:: console
$ nix-build -I liminix-config=./my-configuration.nix --arg device "import ./devices/belkin-rt3200" -A outputs.default
$ cat result/rootfs | ssh root@192.168.1.1 "cat > /tmp/rootfs"
$ ssh root@192.168.1.1
root@OpenWrt:~# ubimkvol /dev/ubi0 --name=liminix --maxavsize
root@OpenWrt:~# ubinfo -a
[...]
Volume ID: 7 (on ubi0)
Type: dynamic
Alignment: 1
Size: 851 LEBs (108056576 bytes, 103.0 MiB)
State: OK
Name: liminix
Character device major/minor: 250:8
root@OpenWrt:~# ubiupdatevol /dev/ubi0_7 /tmp/rootfs
To make the new system bootable we also need to change some U-Boot variables.
``boot_production`` needs to mount the filesystem and boot the FIT image
found there, and :code:`bootcmd` needs to be told _not_ to boot the rescue
image if there are records in pstore, because that interferes with
``config.log.persistent``
.. code-block:: console
root@OpenWrt:~# fw_setenv orig_boot_production $(fw_printenv -n boot_production)
root@OpenWrt:~# fw_setenv orig_bootcmd $(fw_printenv -n bootcmd)
root@OpenWrt:~# fw_setenv boot_production 'led $bootled_pwr on ; ubifsmount ubi0:liminix && ubifsload ''${loadaddr} boot/fit && bootm ''${loadaddr}'
root@OpenWrt:~# fw_setenv bootcmd 'run boot_ubi'
For subsequent Liminix reinstalls, just run the
:command:`ubiupdatevol` command again. You don't need to repeat
the "Preparation" step and in fact should seek to avoid it if
possible, as it will reset the erase counters used for write
levelling. Using UBI-aware tools is therefore preferred over any
kind of "factory" wipe which will reset them.
'';
system = {
crossSystem = {
@@ -62,7 +116,8 @@
};
module = {pkgs, config, lib, lim, ... }:
let firmware = pkgs.stdenv.mkDerivation {
let inherit (lib) mkIf;
firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = ["installPhase"];
installPhase = ''
@@ -70,18 +125,20 @@
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out
'';
};
openwrt = pkgs.openwrt_24_10;
in {
imports = [
../../modules/arch/aarch64.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/ubifs.nix
../../modules/outputs/ubimage.nix
];
config = {
kernel = {
extraPatchPhase = ''
${pkgs.openwrt.applyPatches.mediatek}
${openwrt.applyPatches.mediatek}
'';
src = openwrt.kernelSrc;
version = openwrt.kernelVersion;
config = {
PCI = "y";
ARCH_MEDIATEK = "y";
@@ -92,8 +149,8 @@
MTK_INFRACFG = "y";
MTK_PMIC_WRAP = "y";
NVMEM_MTK_EFUSE="y";
# MTK_HSDMA="y";
DMADEVICES = "y";
MTK_HSDMA="y";
MTK_SCPSYS="y";
MTK_SCPSYS_PM_DOMAINS="y";
# MTK_THERMAL="y";
@@ -139,6 +196,10 @@
MTD_SPLIT_FIRMWARE= "y";
MTD_SPLIT_FIT_FW= "y";
MTD_UBI_NVMEM = "y";
NVMEM_MTK_EFUSE = "y";
NVMEM_BLOCK = "y";
NVMEM_LAYOUT_ADTRAN = "y";
MMC = "y";
MMC_BLOCK = "y";
@@ -150,11 +211,7 @@
NET_DSA="y";
NET_DSA_MT7530="y";
NET_DSA_TAG_MTK="y";
PSTORE = "y";
PSTORE_RAM = "y";
PSTORE_CONSOLE = "y";
PSTORE_DEFLATE_COMPRESS = "n";
NET_DSA_MT7530_MDIO="y";
SERIAL_8250 = "y";
SERIAL_8250_CONSOLE = "y";
@@ -177,9 +234,11 @@
};
boot = {
commandLine = [ "console=ttyS0,115200" ];
tftp.loadAddress = lim.parseInt "0x4007ff28";
tftp.loadAddress = lim.parseInt "0x48000000";
imageFormat = "fit";
loader.fit.enable = lib.mkDefault true; # override this if you are building tftpboot
};
rootfsType = lib.mkDefault "ubifs"; # override this if you are building tftpboot
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in
@@ -193,7 +252,6 @@
hardware =
let
openwrt = pkgs.openwrt;
mac80211 = pkgs.kmodloader.override {
targets = ["mt7615e" "mt7915e"];
inherit (config.system.outputs) kernel;
@@ -221,6 +279,9 @@
"${openwrt.src}/target/linux/mediatek/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
includes = mkIf config.logging.persistent.enable [
./pstore-pmsg.dtsi
];
};
# - 0x000000000000-0x000008000000 : "spi-nand0"
+8
View File
@@ -0,0 +1,8 @@
/ {
reserved-memory {
/* make sure address matches upstream */
ramoops@42ff0000 {
pmsg-size = <0x10000>;
};
};
};
+5 -4
View File
@@ -41,10 +41,11 @@
:ref:`system-outputs-mtdimage` can be flashed using the
vendor web UI or the U-Boot emergency "unbrick" routine.
For flashing from an existing Liminix system (we believe that) it
is necessary to first boot into a :ref:`system-outputs-kexecboot`
system, otherwise you'll be overwriting flash partitions while
they're in use - and that might not end well.
Flashing over an existing Liminix system is not possible while
that system is running, otherwise you'll be overwriting flash
partitions while they're in use - and that might not end well.
Configure the system with :ref:`levitate` if you need to
make it upgradable.
Vendor web page: https://www.gl-inet.com/products/gl-ar750/
+5 -4
View File
@@ -32,10 +32,11 @@
binary created by :ref:`system-outputs-mtdimage` can be flashed
using the vendor web UI or the U-Boot emergency "unbrick" routine.
For flashing from an existing Liminix system (we think) it
is necessary to first boot into a :ref:`system-outputs-kexecboot`
system, otherwise you'll be overwriting flash partitions while
they're in use - and that might not end well.
Flashing over an existing Liminix system is not possible while
that system is running, otherwise you'll be overwriting flash
partitions while they're in use - and that might not end well.
Configure the system with :ref:`levitate` if you need to
make it upgradable.
Vendor web page: https://www.gl-inet.com/products/gl-mt300a/
+5 -4
View File
@@ -25,10 +25,11 @@
binary created by :ref:`system-outputs-mtdimage` can be flashed
using the vendor web UI or the U-Boot emergency "unbrick" routine.
For flashing from an existing Liminix system (we think) it
is necessary to first boot into a :ref:`system-outputs-kexecboot`
system, otherwise you'll be overwriting flash partitions while
they're in use - and that might not end well.
Flashing over an existing Liminix system is not possible while
that system is running, otherwise you'll be overwriting flash
partitions while they're in use - and that might not end well.
Configure the system with :ref:`levitate` if you need to
make it upgradable.
Vendor web page: https://www.gl-inet.com/products/gl-mt300n-v2/
+739
View File
@@ -0,0 +1,739 @@
{
description = ''
OpenWrt One
***********
Hardware summary
================
- MediaTek MT7981B (1300MHz)
- 256MB NAND Flash
- 1024MB RAM
- WLan hardware: Mediatek MT7976C
Status
======
- Only tested over TFTP so far.
- WiFi (2.4G and 5G) works.
- 2.5G ethernet port works.
Limitations
===========
- adding `he_bss_color="128"` causes `Invalid argument` for hostap
- nvme support untested
- I don't think the front LEDs work yet
Installation
============
TODO: add instructions on how to boot directly from TFTP to memory
and how to install from TFTP to flash without going through OpenWrt.
The instructions below assume you can boot and SSH into OpenWrt:
Boot into OpenWrt and create a 'liminix' UBI partition:
root@OpenWrt:~# ubimkvol /dev/ubi0 --name=liminix --maxavsize
Remember the 'Volume ID' that was created for this new partition
Build the UBI image and write it to this new partition:
$ nix-build -I liminix-config=./my-configuration.nix --arg device "import ./devices/openwrt-one" -A outputs.default
$ cat result/rootfs | ssh root@192.168.1.1 "cat > /tmp/rootfs"
$ ssh root@192.168.1.1
root@OpenWrt:~# ubiupdatevol /dev/ubi0_X /tmp/rootfs # replace X with the volume id, if needed check with `ubinfo`
Reboot into the U-Boot prompt and boot with:
OpenWrt One> ubifsmount ubi0:liminix && ubifsload ''${loadaddr} boot/fit && bootm ''${loadaddr}'
If this works, reboot into OpenWrt and configure U-Boot to boot ubifs by default:
root@OpenWrt:~# fw_setenv orig_boot_production $(fw_printenv -n boot_production)
root@OpenWrt:~# fw_setenv boot_production 'led white on ; ubifsmount ubi0:liminix && ubifsload ''${loadaddr} boot/fit && bootm ''${loadaddr}'
Troubleshooting
===============
The instructions above assume you can boot and SSH into the (recovery)
OpenWrt installation. If you have broken your device to the point where that
is no longer possible, you could re-install OpenWrt, but probably you could
also install directly from U-Boot:
https://github.com/u-boot/u-boot/blob/master/doc/README.ubi
'';
system = {
crossSystem = {
config = "aarch64-unknown-linux-musl";
gcc = {
# https://openwrt.org/docs/techref/instructionset/aarch64_cortex-a53
# openwrt ./target/linux/mediatek/filogic/target.mk
# https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html
# https://en.wikipedia.org/wiki/Comparison_of_ARM_processors
arch = "armv8-a";
};
};
};
module = {pkgs, config, lib, lim, ... }:
let
openwrt = pkgs.openwrt_24_10;
mediatek-firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = ["installPhase"];
installPhase = ''
mkdir $out
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7986_eeprom_mt7976,mt7981}* $out
'';
};
airoha-firmware = pkgs.stdenv.mkDerivation {
name = "airoha-firmware";
phases = ["installPhase"];
installPhase = ''
mkdir $out
cp ${pkgs.linux-firmware}/lib/firmware/airoha/* $out
'';
};
in {
imports = [
../../modules/arch/aarch64.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/ubifs.nix
];
config = {
kernel = {
src = openwrt.kernelSrc;
version = openwrt.kernelVersion;
extraPatchPhase = ''
${openwrt.applyPatches.mediatek}
'';
config = {
NET="y"; # unlock NET_XGRESS
SERIAL_8250="y"; # unlock SERIAL_8250_FSL
SERIAL_8250_CONSOLE="y"; # to get the serial console
WATCHDOG="y"; # unlock WATCHDOG_CORE
NEW_LEDS="y"; # unlock LEDS_PWM
LEDS_CLASS="y"; # unlock LEDS_PWM
LEDS_TRIGGERS="y"; # unlock LEDS_TRIGGER_PATTERN
DEFERRED_STRUCT_PAGE_INIT="y"; # trigger PADATA
# Taken from openwrt's ./target/linux/mediatek/filogic/config-6.6
"64BIT"="y";
AIROHA_EN8801SC_PHY="y";
ARCH_BINFMT_ELF_EXTRA_PHDRS="y";
ARCH_CORRECT_STACKTRACE_ON_KRETPROBE="y";
ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG="y";
ARCH_DMA_ADDR_T_64BIT="y";
ARCH_FORCE_MAX_ORDER="10";
ARCH_KEEP_MEMBLOCK="y";
ARCH_MEDIATEK="y";
ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE="y";
ARCH_MMAP_RND_BITS="18";
ARCH_MMAP_RND_BITS_MAX="24";
ARCH_MMAP_RND_BITS_MIN="18";
ARCH_MMAP_RND_COMPAT_BITS_MIN="11";
ARCH_PROC_KCORE_TEXT="y";
ARCH_SPARSEMEM_ENABLE="y";
ARCH_STACKWALK="y";
ARCH_SUSPEND_POSSIBLE="y";
ARCH_WANTS_NO_INSTR="y";
ARCH_WANTS_THP_SWAP="y";
ARM64="y";
ARM64_4K_PAGES="y";
ARM64_ERRATUM_843419="y";
ARM64_LD_HAS_FIX_ERRATUM_843419="y";
ARM64_PAGE_SHIFT="12";
ARM64_PA_BITS="48";
ARM64_PA_BITS_48="y";
ARM64_TAGGED_ADDR_ABI="y";
ARM64_VA_BITS="39";
ARM64_VA_BITS_39="y";
ARM_AMBA="y";
ARM_ARCH_TIMER="y";
ARM_ARCH_TIMER_EVTSTREAM="y";
ARM_GIC="y";
ARM_GIC_V2M="y";
ARM_GIC_V3="y";
ARM_GIC_V3_ITS="y";
ARM_GIC_V3_ITS_PCI="y";
ARM_MEDIATEK_CPUFREQ="y";
ARM_PMU="y";
ARM_PMUV3="y";
ARM_PSCI_FW="y";
ATA="y";
AUDIT_ARCH_COMPAT_GENERIC="y";
BLK_DEV_LOOP="y";
BLK_DEV_SD="y";
BLK_MQ_PCI="y";
BLK_PM="y";
BLOCK_NOTIFIERS="y";
BSD_PROCESS_ACCT="y";
BSD_PROCESS_ACCT_V3="y";
BUFFER_HEAD="y";
BUILTIN_RETURN_ADDRESS_STRIPS_PAC="y";
CC_HAVE_SHADOW_CALL_STACK="y";
CC_HAVE_STACKPROTECTOR_SYSREG="y";
#CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5";
CC_NO_ARRAY_BOUNDS="y";
CLKSRC_MMIO="y";
CLONE_BACKWARDS="y";
CMDLINE_OVERRIDE="y";
COMMON_CLK="y";
COMMON_CLK_MEDIATEK="y";
COMMON_CLK_MT7981="y";
COMMON_CLK_MT7981_ETHSYS="y";
COMMON_CLK_MT7986="y";
COMMON_CLK_MT7986_ETHSYS="y";
COMMON_CLK_MT7988="y";
COMPACT_UNEVICTABLE_DEFAULT="1";
CONFIGFS_FS="y";
CONSOLE_LOGLEVEL_DEFAULT="15";
CONTEXT_TRACKING="y";
CONTEXT_TRACKING_IDLE="y";
CPU_FREQ="y";
CPU_FREQ_DEFAULT_GOV_USERSPACE="y";
CPU_FREQ_GOV_ATTR_SET="y";
CPU_FREQ_GOV_COMMON="y";
CPU_FREQ_GOV_CONSERVATIVE="y";
CPU_FREQ_GOV_ONDEMAND="y";
CPU_FREQ_GOV_PERFORMANCE="y";
CPU_FREQ_GOV_POWERSAVE="y";
CPU_FREQ_GOV_SCHEDUTIL="y";
CPU_FREQ_GOV_USERSPACE="y";
CPU_FREQ_STAT="y";
CPU_LITTLE_ENDIAN="y";
CPU_RMAP="y";
CPU_THERMAL="y";
CRC16="y";
CRC_CCITT="y";
CRYPTO_AES_ARM64="y";
CRYPTO_AES_ARM64_CE="y";
CRYPTO_AES_ARM64_CE_BLK="y";
CRYPTO_AES_ARM64_CE_CCM="y";
CRYPTO_CMAC="y";
CRYPTO_CRC32="y";
CRYPTO_CRC32C="y";
CRYPTO_CRYPTD="y";
CRYPTO_DEFLATE="y";
CRYPTO_DRBG="y";
CRYPTO_DRBG_HMAC="y";
CRYPTO_DRBG_MENU="y";
CRYPTO_ECB="y";
CRYPTO_ECC="y";
CRYPTO_ECDH="y";
CRYPTO_GHASH_ARM64_CE="y";
CRYPTO_HASH_INFO="y";
CRYPTO_HMAC="y";
CRYPTO_JITTERENTROPY="y";
CRYPTO_LIB_BLAKE2S_GENERIC="y";
CRYPTO_LIB_GF128MUL="y";
CRYPTO_LIB_SHA1="y";
CRYPTO_LIB_SHA256="y";
CRYPTO_LIB_UTILS="y";
CRYPTO_LZO="y";
CRYPTO_RNG="y";
CRYPTO_RNG2="y";
CRYPTO_RNG_DEFAULT="y";
CRYPTO_SHA256="y";
CRYPTO_SHA256_ARM64="y";
CRYPTO_SHA2_ARM64_CE="y";
CRYPTO_SHA3="y";
CRYPTO_SHA512="y";
CRYPTO_SM4="y";
CRYPTO_SM4_ARM64_CE_BLK="y";
CRYPTO_SM4_ARM64_CE_CCM="y";
CRYPTO_SM4_ARM64_CE_GCM="y";
CRYPTO_ZSTD="y";
DCACHE_WORD_ACCESS="y";
#DEBUG_INFO="y";
DEBUG_MISC="y";
DIMLIB="y";
DMADEVICES="y";
DMATEST="y";
DMA_BOUNCE_UNALIGNED_KMALLOC="y";
DMA_DIRECT_REMAP="y";
DMA_ENGINE="y";
DMA_ENGINE_RAID="y";
DMA_OF="y";
DMA_VIRTUAL_CHANNELS="y";
DTC="y";
EDAC_SUPPORT="y";
EINT_MTK="y";
EXCLUSIVE_SYSTEM_RAM="y";
EXT4_FS="y";
F2FS_FS="y";
FIXED_PHY="y";
FIX_EARLYCON_MEM="y";
FRAME_POINTER="y";
FS_IOMAP="y";
FS_MBCACHE="y";
FUNCTION_ALIGNMENT="4";
FUNCTION_ALIGNMENT_4B="y";
FWNODE_MDIO="y";
FW_LOADER_PAGED_BUF="y";
#FW_LOADER_SYSFS="y";
#GCC11_NO_ARRAY_BOUNDS="y";
#GCC_ASM_GOTO_OUTPUT_WORKAROUND="y";
GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS="y";
GENERIC_ALLOCATOR="y";
GENERIC_ARCH_TOPOLOGY="y";
GENERIC_BUG="y";
GENERIC_BUG_RELATIVE_POINTERS="y";
GENERIC_CLOCKEVENTS="y";
GENERIC_CLOCKEVENTS_BROADCAST="y";
GENERIC_CPU_AUTOPROBE="y";
GENERIC_CPU_VULNERABILITIES="y";
GENERIC_CSUM="y";
GENERIC_EARLY_IOREMAP="y";
GENERIC_GETTIMEOFDAY="y";
GENERIC_IDLE_POLL_SETUP="y";
GENERIC_IOREMAP="y";
GENERIC_IRQ_EFFECTIVE_AFF_MASK="y";
GENERIC_IRQ_SHOW="y";
GENERIC_IRQ_SHOW_LEVEL="y";
GENERIC_LIB_DEVMEM_IS_ALLOWED="y";
GENERIC_MSI_IRQ="y";
GENERIC_PCI_IOMAP="y";
GENERIC_PHY="y";
GENERIC_PINCONF="y";
GENERIC_PINCTRL_GROUPS="y";
GENERIC_PINMUX_FUNCTIONS="y";
GENERIC_SCHED_CLOCK="y";
GENERIC_SMP_IDLE_THREAD="y";
GENERIC_STRNCPY_FROM_USER="y";
GENERIC_STRNLEN_USER="y";
GENERIC_TIME_VSYSCALL="y";
GLOB="y";
GPIO_CDEV="y";
GPIO_WATCHDOG="y";
GPIO_WATCHDOG_ARCH_INITCALL="y";
GRO_CELLS="y";
HARDIRQS_SW_RESEND="y";
HAS_DMA="y";
HAS_IOMEM="y";
HAS_IOPORT="y";
HAS_IOPORT_MAP="y";
HWMON="y";
HW_RANDOM="y";
HW_RANDOM_MTK="y";
I2C="y";
I2C_BOARDINFO="y";
I2C_CHARDEV="y";
I2C_MT65XX="y";
ICPLUS_PHY="y";
ILLEGAL_POINTER_VALUE="0xdead000000000000";
#INITRAMFS_SOURCE="""";
IRQCHIP="y";
IRQ_DOMAIN="y";
IRQ_DOMAIN_HIERARCHY="y";
IRQ_FORCED_THREADING="y";
IRQ_TIME_ACCOUNTING="y";
IRQ_WORK="y";
JBD2="y";
JUMP_LABEL="y";
LEDS_PWM="y";
LEDS_SMARTRG_LED="y";
LIBFDT="y";
LOCK_DEBUGGING_SUPPORT="y";
LOCK_SPIN_ON_OWNER="y";
LZO_COMPRESS="y";
LZO_DECOMPRESS="y";
MAGIC_SYSRQ="y";
MAXLINEAR_GPHY="y";
MDIO_BUS="y";
MDIO_DEVICE="y";
MDIO_DEVRES="y";
MEDIATEK_2P5GE_PHY="y";
MEDIATEK_GE_PHY="y";
MEDIATEK_GE_SOC_PHY="y";
MEDIATEK_WATCHDOG="y";
MESSAGE_LOGLEVEL_DEFAULT="7";
MFD_SYSCON="y";
MIGRATION="y";
MMC="y";
MMC_BLOCK="y";
MMC_CQHCI="y";
MMC_MTK="y";
MMU_LAZY_TLB_REFCOUNT="y";
MODULES_TREE_LOOKUP="y";
MODULES_USE_ELF_RELA="y";
MTD_NAND_CORE="y";
MTD_NAND_ECC="y";
MTD_NAND_ECC_MEDIATEK="y";
MTD_NAND_ECC_SW_HAMMING="y";
MTD_NAND_MTK="y";
MTD_NAND_MTK_BMT="y";
MTD_PARSER_TRX="y";
MTD_RAW_NAND="y";
MTD_SPI_NAND="y";
MTD_SPI_NOR="y";
MTD_SPLIT_FIRMWARE="y";
MTD_SPLIT_FIT_FW="y";
MTD_UBI="y";
MTD_UBI_BEB_LIMIT="20";
MTD_UBI_BLOCK="y";
MTD_UBI_FASTMAP="y";
MTD_UBI_NVMEM="y";
MTD_UBI_WL_THRESHOLD="4096";
MTK_CPUX_TIMER="y";
MTK_HSDMA="y";
MTK_INFRACFG="y";
MTK_LVTS_THERMAL="y";
MTK_LVTS_THERMAL_DEBUGFS="y";
MTK_PMIC_WRAP="y";
MTK_REGULATOR_COUPLER="y";
MTK_SCPSYS="y";
MTK_SCPSYS_PM_DOMAINS="y";
MTK_SOC_THERMAL="y";
MTK_THERMAL="y";
MTK_TIMER="y";
MUTEX_SPIN_ON_OWNER="y";
NEED_DMA_MAP_STATE="y";
NEED_SG_DMA_LENGTH="y";
NET_DEVLINK="y";
NET_DSA="y";
NET_DSA_MT7530="y";
NET_DSA_MT7530_MDIO="y";
NET_DSA_MT7530_MMIO="y";
NET_DSA_TAG_MTK="y";
#NET_EGRESS="y";
NET_FLOW_LIMIT="y";
#NET_INGRESS="y";
NET_MEDIATEK_SOC="y";
NET_MEDIATEK_SOC_WED="y";
NET_SELFTESTS="y";
NET_SWITCHDEV="y";
NET_VENDOR_MEDIATEK="y";
#NET_XGRESS="y";
NLS="y";
NO_HZ_COMMON="y";
NO_HZ_IDLE="y";
NR_CPUS="4";
NVMEM="y";
NVMEM_BLOCK="y";
NVMEM_LAYOUTS="y";
NVMEM_LAYOUT_ADTRAN="y";
NVMEM_MTK_EFUSE="y";
NVMEM_SYSFS="y";
OF="y";
OF_ADDRESS="y";
OF_DYNAMIC="y";
OF_EARLY_FLATTREE="y";
OF_FLATTREE="y";
OF_GPIO="y";
OF_IRQ="y";
OF_KOBJ="y";
OF_MDIO="y";
OF_OVERLAY="y";
OF_RESOLVE="y";
PADATA="y";
PAGE_POOL="y";
PAGE_POOL_STATS="y";
PAGE_SIZE_LESS_THAN_256KB="y";
PAGE_SIZE_LESS_THAN_64KB="y";
#PAHOLE_HAS_LANG_EXCLUDE="y";
PARTITION_PERCPU="y";
PCI="y";
PCIEAER="y";
PCIEASPM="y";
PCIEASPM_PERFORMANCE="y";
PCIEPORTBUS="y";
PCIE_MEDIATEK_GEN3="y";
PCIE_PME="y";
PCI_DEBUG="y";
PCI_DOMAINS="y";
PCI_DOMAINS_GENERIC="y";
PCI_MSI="y";
PCS_MTK_LYNXI="y";
PCS_MTK_USXGMII="y";
PERF_EVENTS="y";
PER_VMA_LOCK="y";
PGTABLE_LEVELS="3";
PHYLIB="y";
PHYLIB_LEDS="y";
PHYLINK="y";
PHYS_ADDR_T_64BIT="y";
PHY_MTK_TPHY="y";
PHY_MTK_XFI_TPHY="y";
PHY_MTK_XSPHY="y";
PINCTRL="y";
PINCTRL_MT7981="y";
PINCTRL_MT7986="y";
PINCTRL_MT7988="y";
PINCTRL_MTK_MOORE="y";
PINCTRL_MTK_V2="y";
PM="y";
PM_CLK="y";
PM_GENERIC_DOMAINS="y";
PM_GENERIC_DOMAINS_OF="y";
PM_OPP="y";
POLYNOMIAL="y";
POSIX_CPU_TIMERS_TASK_WORK="y";
POWER_RESET="y";
POWER_RESET_SYSCON="y";
POWER_SUPPLY="y";
PREEMPT_NONE_BUILD="y";
PRINTK_TIME="y";
PSTORE="y";
PSTORE_COMPRESS="y";
PSTORE_CONSOLE="y";
PSTORE_PMSG="y";
PSTORE_RAM="y";
PTP_1588_CLOCK_OPTIONAL="y";
PWM="y";
PWM_MEDIATEK="y";
PWM_SYSFS="y";
QUEUED_RWLOCKS="y";
QUEUED_SPINLOCKS="y";
RANDSTRUCT_NONE="y";
RAS="y";
RATIONAL="y";
REALTEK_PHY="y";
REED_SOLOMON="y";
REED_SOLOMON_DEC8="y";
REED_SOLOMON_ENC8="y";
REGMAP="y";
REGMAP_I2C="y";
REGMAP_MMIO="y";
REGULATOR="y";
REGULATOR_FIXED_VOLTAGE="y";
REGULATOR_MT6380="y";
REGULATOR_RT5190A="y";
RESET_CONTROLLER="y";
RESET_TI_SYSCON="y";
RFS_ACCEL="y";
RODATA_FULL_DEFAULT_ENABLED="y";
RPS="y";
RTC_CLASS="y";
RTC_DRV_MT7622="y";
RTC_I2C_AND_SPI="y";
RWSEM_SPIN_ON_OWNER="y";
SCHED_MC="y";
SCSI="y";
SCSI_COMMON="y";
SERIAL_8250_FSL="y";
SERIAL_8250_MT6577="y";
SERIAL_8250_NR_UARTS="3";
SERIAL_8250_RUNTIME_UARTS="3";
SERIAL_DEV_BUS="y";
SERIAL_DEV_CTRL_TTYPORT="y";
SERIAL_MCTRL_GPIO="y";
SERIAL_OF_PLATFORM="y";
SGL_ALLOC="y";
SG_POOL="y";
SMP="y";
SOCK_RX_QUEUE_MAPPING="y";
SOFTIRQ_ON_OWN_STACK="y";
SPARSEMEM="y";
SPARSEMEM_EXTREME="y";
SPARSEMEM_VMEMMAP="y";
SPARSEMEM_VMEMMAP_ENABLE="y";
SPARSE_IRQ="y";
SPI="y";
SPI_DYNAMIC="y";
SPI_MASTER="y";
SPI_MEM="y";
SPI_MT65XX="y";
SPI_MTK_SNFI="y";
#SQUASHFS_DECOMP_MULTI_PERCPU="y";
SWIOTLB="y";
SWPHY="y";
SYSCTL_EXCEPTION_TRACE="y";
THERMAL="y";
THERMAL_DEFAULT_GOV_STEP_WISE="y";
THERMAL_EMERGENCY_POWEROFF_DELAY_MS="0";
THERMAL_GOV_BANG_BANG="y";
THERMAL_GOV_FAIR_SHARE="y";
THERMAL_GOV_STEP_WISE="y";
THERMAL_GOV_USER_SPACE="y";
THERMAL_HWMON="y";
THERMAL_OF="y";
THERMAL_WRITABLE_TRIPS="y";
THREAD_INFO_IN_TASK="y";
TICK_CPU_ACCOUNTING="y";
TIMER_OF="y";
TIMER_PROBE="y";
TRACE_IRQFLAGS_NMI_SUPPORT="y";
TREE_RCU="y";
TREE_SRCU="y";
UBIFS_FS="y";
UIMAGE_FIT_BLK="y";
USB_SUPPORT="y";
VMAP_STACK="y";
WATCHDOG_CORE="y";
WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC="y";
WATCHDOG_PRETIMEOUT_GOV="y";
WATCHDOG_PRETIMEOUT_GOV_PANIC="y";
WATCHDOG_PRETIMEOUT_GOV_SEL="m";
WATCHDOG_SYSFS="y";
XPS="y";
XXHASH="y";
ZLIB_DEFLATE="y";
ZLIB_INFLATE="y";
ZONE_DMA32="y";
ZSTD_COMMON="y";
ZSTD_COMPRESS="y";
ZSTD_DECOMPRESS="y";
# from DEVICE_PACKAGES in the openwrt_one section of
# openwrt's ./target/linux/mediatek/image/filogic.mk:
# chop off the 'kmod-' prefix and search for 'KernelPackage/...'
# in ./package/kernel/linux/modules/*.mk, and remember to add
# modules to kmodloader targets below
AIR_EN8811H_PHY="m";
RTC_DRV_PCF8563="m";
NVME_CORE="m";
BLK_DEV_NVME="m";
NVME_MULTIPATH="n";
NVME_HWMON="y";
# ???
AQUANTIA_PHY="m";
MT798X_WMAC="y";
} // lib.optionalAttrs (config.system.service ? watchdog) {
RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};
conditionalConfig = {
WLAN = {
MT7915E = "m";
};
};
};
boot = {
commandLine = [ "console=ttyS0,115200" ];
tftp = {
# Should be a segment of free RAM, where the tftp artifact
# can be stored before unpacking it to the 'hardware.loadAddress'
# The 'hardware.loadAddress' is 0x44000000, and the bootlog
# suggests it loads the fit to 0x46000000
loadAddress = lim.parseInt "0x46000000";
};
imageFormat = "fit";
loader.fit.enable = lib.mkDefault true; # override this if you are building tftpboot
};
rootfsType = lib.mkDefault "ubifs"; # override this if you are building tftpboot
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in
dir {
lib = dir {
firmware = dir {
mediatek = symlink mediatek-firmware;
airoha = symlink airoha-firmware;
};
};
};
hardware =
let
phy = pkgs.kmodloader.override {
targets = [
"air_en8811h"
];
inherit (config.system.outputs) kernel;
};
mac80211 = pkgs.kmodloader.override {
targets = [
"mt7915e"
"rtc-pcf8563"
"nvme_core"
"nvme"
#"mt7996e"
"aquantia"
];
inherit (config.system.outputs) kernel;
};
in {
# from OEM bootlog
# Creating 4 MTD partitions on "spi0.0":
# 0x000000000000-0x000000040000 : "bl2-nor"
# 0x000000040000-0x000000100000 : "factory"
# 0x000000100000-0x000000180000 : "fip-nor"
# 0x000000180000-0x000000e00000 : "recovery"
# spi-nand spi1.1: calibration result: 0x3
# spi-nand spi1.1: Winbond SPI NAND was found.
# spi-nand spi1.1: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
# 2 fixed-partitions partitions found on MTD device spi1.1
# Creating 2 MTD partitions on "spi1.1":
# 0x000000000000-0x000000100000 : "bl2"
# 0x000000100000-0x000010000000 : "ubi"
flash = {
# from the OEM bootlog:
# ## Checking Image at 46000000 ...
# FIT image found
# FIT description: ARM64 OpenWrt FIT (Flattened Image Tree)
# Image 0 (kernel-1)
# Description: ARM64 OpenWrt Linux-6.6.57
# Type: Kernel Image
# Compression: gzip compressed
# Data Start: 0x46001000
# Data Size: 5751840 Bytes = 5.5 MiB
# Architecture: AArch64
# OS: Linux
# Load Address: 0x44000000
# Entry Point: 0x44000000
address = lim.parseInt "0x44000000";
size = lim.parseInt "0xf60000";
# /proc/mtd on a running system:
# dev: size erasesize name
# mtd0: 00040000 00010000 "bl2-nor"
# mtd1: 000c0000 00010000 "factory"
# mtd2: 00080000 00010000 "fip-nor"
# mtd3: 00c80000 00010000 "recovery"
# mtd4: 00100000 00020000 "bl2"
# mtd5: 0ff00000 00020000 "ubi"
eraseBlockSize = 65536;
};
ubi = {
# TODO taken from belkin-rt3200, to review
minIOSize = "2048";
logicalEraseBlockSize = "126976";
physicalEraseBlockSize = "131072";
maxLEBcount = "1024"; # guessing
};
defaultOutput = "ubimage";
loadAddress = lim.parseInt "0x44000000";
entryPoint = lim.parseInt "0x44000000";
# TODO AFAICT this should be 2048, but I got 'FIT: image rootfs-1 start not aligned to page boundaries' with that...
#alignment = 2048;
alignment = 4096;
rootDevice = "ubi0:liminix";
dts = {
src = "${openwrt.src}/target/linux/mediatek/dts/mt7981b-openwrt-one.dts";
includePaths = [
"${openwrt.src}/target/linux/mediatek/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
};
networkInterfaces =
let
inherit (config.system.service.network) link;
in rec {
eth0 = link.build {
ifname = "eth0";
dependencies = [ phy ];
};
eth1 = link.build { ifname = "eth1"; };
wlan0 = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan1 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
};
};
};
};
}
+4
View File
@@ -175,6 +175,9 @@
];
config = {
rootfsType = lib.mkDefault "btrfs"; # override this if you are building tftpboot
rootOptions = lib.mkDefault "subvol=@";
services.mtd-name-links = mtd_by_name_links;
kernel = {
src = pkgs.pkgsBuildBuild.fetchurl {
@@ -292,6 +295,7 @@
};
};
boot = {
loader.extlinux.enable = lib.mkDefault true; # override this if you are building tftpboot
commandLine = [
"console=ttyS0,115200"
"pcie_aspm=off" # ath9k pci incompatible with PCIe ASPM
+45 -16
View File
@@ -145,17 +145,8 @@ 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.
To check the previous messages after a (planned or forced) reboot,
you need to mooun the pstore filesystem.
.. 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]
Logs found in pstore after a reboot will be moved at startup to
:file:`/run/log/previous-boot`
@@ -197,16 +188,54 @@ the current system closure. Note that Liminix does not have the NixOS
concept of environments or generations, and there is no way back from
this except for building the previous configuration again.
Caveats
-------
* it needs there to be enough free space on the device for all the new
packages in addition to all the packages already on it - which may be
a problem if a lot of things have changed (e.g. a new version of
nixpkgs).
packages in addition to all the packages already on it - which may
be a problem if there is little flash storage or if a lot of things
have changed (e.g. a new version of nixpkgs).
* it may not be able to upgrade the kernel: this is device-dependent.
If your device boots from a kernel image on a raw MTD partition or
or UBI volume, update.sh is unable to alter the kernel partition.
If your device boots from a kernel inside the filesystem (e.g. using
bootloader.extlinux or bootloder.fit) then the kernel will be
upgraded along with the userland
Recovery/downgrades
-------------------
The :command:`update.sh` script also creates a timestamped symlink on
the device which points to the system configuration it installs. If
you install a configuration that doesn't work, you can revert to any
other installed configuration by
1) booting to some kind of rescue or recovery system (which may be
some vendor-provided rescue option, or your own recovery system
perhaps based on :file:`examples/recovery.nix`) and mounting
your Liminix filesystem on /mnt
2) picking another previously-installed configuration that _did_ work,
and switching back to it:
.. code-block:: console
# ls -ld /mnt/*configuration
lrwxrwxrwx 1 90 /mnt/20252102T182104.configuration -> nix/store/v1w0h4zw65ah4c2r0k7nyy125qrxhq78-system-configuration-aarch64-unknown-linux-musl
lrwxrwxrwx 1 90 /mnt/20251802T181822.configuration -> nix/store/wqjl9s9xljl2wg8257292zghws9ssidk-system-configuration-aarch64-unknown-linux-musl
# : 20251802T181822 is the working system, so reinstall it
# /mnt/20251802T181822.configuration/bin/install /mnt
# umount /mnt
# reboot
This will install the previous configuration's activation binary into
/bin, and copy its kernel and initramfs into /boot. Note that it
depends on the previous system not having been garbage-collected.
* it cannot upgrade the kernel, only userland
.. _levitate:
+2 -2
View File
@@ -116,8 +116,8 @@ TFTP server you're using and so is out of scope for this document.
Buildiing and installing the image
==================================
Building and installing the image
=================================
Follow the device-specific instructions for "TFTP install": usually,
the steps are
+82
View File
@@ -0,0 +1,82 @@
# This is "contrib"-level code. This module solves a particular
# problem for my particular setup and is provided as is, as an example
# of how you might write something similar if you had a similar
# problem. Don't expect it to work unmolested in your setup (you will
# at the absolute minimum have to change the domain name), nor even to
# continue to exist without possibly being changed beyond recognition.
# The computers on my LAN have globally unique routable IPv6
# addresses, but I have only one public IPv4 address. I want to expose
# HTTPS services to the Internet _whatever_ machine is hosting them,
# so I publish an AAAA record to the machine itself, and an A record
# to the public v4 address of the router which is running this nginx.
# This nginx checks the SNI in the incoming connection and forwards
# the connection to the (IPv6 address of the) same hostname
# See https://ww.telent.net/2020/12/2/six_into_4_won_t_go for
# the original solution to this problem, which used sniproxy (now
# unmaintained) instead of nginx
{ config, pkgs, ... }:
let
inherit (pkgs.liminix.services) longrun;
inherit (pkgs) writeText;
nginx_uid = 62;
in {
config = {
users.nginx = {
uid = nginx_uid; gid= nginx_uid;
dir = "/run/";
shell = "/bin/false";
};
groups.nginx = {
gid= nginx_uid;
usernames = ["nginx"];
};
services.sniproxy =
let
nginx = pkgs.nginx-small.override {
pcre = null;
zlib = null;
options = [
"stream"
"stream_ssl_module" "stream_ssl_preread_module"
"stream_map_module"
];
};
conf = writeText "nginx.conf" ''
worker_processes auto;
error_log /proc/self/fd/1 info;
pid /dev/null;
user nginx;
daemon off;
events {
worker_connections 1024;
}
stream {
log_format proxy '$remote_addr -> $ssl_target';
access_log /proc/self/fd/1 proxy;
map $ssl_preread_server_name $ssl_target {
hostnames;
.telent.net $ssl_preread_server_name:443;
}
server {
listen 443;
resolver 127.0.0.1 ipv6=on ipv4=off;
resolver_timeout 1s;
proxy_pass $ssl_target;
ssl_preread on;
}
}
'';
in longrun {
name = "sniproxy";
run = ''
${nginx}/bin/nginx -c ${conf}
'';
};
};
}
-1
View File
@@ -22,7 +22,6 @@
./outputs/ext4fs.nix
./outputs/initramfs.nix
./outputs/jffs2.nix
./outputs/kexecboot.nix
./outputs/mtdimage.nix
./outputs/tftpboot.nix
./outputs/ubifs.nix
+26 -26
View File
@@ -62,8 +62,8 @@ in {
# https://www.mankier.com/8/nft#Payload_Expressions-Raw_Payload_Expression
"@nh,192,8 eq 0xff @nh,204,4 le ${toString mcast-scope}")
(accept "oifname \"int\" iifname \"ppp0\" meta l4proto udp ct state established,related")
(accept "iifname \"int\" oifname \"ppp0\" meta l4proto udp")
(accept "oifname @lan iifname @wan meta l4proto udp ct state established,related")
(accept "iifname @lan oifname @wan meta l4proto udp")
(accept "meta l4proto icmpv6")
(accept "meta l4proto ah")
@@ -71,31 +71,31 @@ in {
# does this ever get used or does the preceding general udp accept
# already grab anything that might get here?
(accept "oifname \"ppp0\" udp dport 500") # IKE Protocol [RFC5996]. haha zyxel
(accept "oifname @wan udp dport 500") # IKE Protocol [RFC5996]. haha zyxel
(accept "ip6 nexthdr 139") # Host Identity Protocol
## FIXME no support yet for recs 27-30 Mobility Header
(accept "oifname \"int\" iifname \"ppp0\" meta l4proto tcp ct state established,related")
(accept "iifname \"int\" oifname \"ppp0\" meta l4proto tcp")
(accept "oifname @lan iifname @wan meta l4proto tcp ct state established,related")
(accept "iifname @lan oifname @wan meta l4proto tcp")
(accept "oifname \"int\" iifname \"ppp0\" meta l4proto sctp ct state established,related")
(accept "iifname \"int\" oifname \"ppp0\" meta l4proto sctp")
(accept "oifname @lan iifname @wan meta l4proto sctp ct state established,related")
(accept "iifname @lan oifname @wan meta l4proto sctp")
(accept "oifname \"int\" iifname \"ppp0\" meta l4proto dccp ct state established,related")
(accept "iifname \"int\" oifname \"ppp0\" meta l4proto dccp")
(accept "oifname @lan iifname @wan meta l4proto dccp ct state established,related")
(accept "iifname @lan oifname @wan meta l4proto dccp")
# we can allow all reasonable inbound, or we can use an explicit
# allowlist to enumerate the endpoints that are allowed to
# accept inbound from the WAN
(if allow-incoming
then accept "oifname \"int\" iifname \"ppp0\""
else "iifname \"ppp0\" jump incoming-allowed-ip6"
then accept "oifname @lan iifname @wan"
else "iifname @wan jump incoming-allowed-ip6"
)
# allow all outbound and any inbound that's part of a
# recognised (outbound-initiated) flow
(accept "oifname \"int\" iifname \"ppp0\" ct state established,related")
(accept "iifname \"int\" oifname \"ppp0\" ")
(accept "oifname @lan iifname @wan ct state established,related")
(accept "iifname @lan oifname @wan ")
"log prefix \"DENIED CHAIN=forward-ip6 \""
];
@@ -128,15 +128,15 @@ in {
hook = "input";
rules = [
(accept "meta l4proto icmpv6")
"iifname int jump input-ip6-lan"
"iifname ppp0 jump input-ip6-wan"
"iifname @lan jump input-ip6-lan"
"iifname @wan jump input-ip6-wan"
(if allow-incoming
then accept "oifname \"int\" iifname \"ppp0\""
else "oifname \"int\" iifname \"ppp0\" jump incoming-allowed-ip6"
then accept "iifname @wan"
else "iifname @wan jump incoming-allowed-ip6"
)
# how does this even make sense in an input chain?
(accept "oifname \"int\" iifname \"ppp0\" ct state established,related")
(accept "iifname \"int\" oifname \"ppp0\" ")
(accept "iifname @wan ct state established,related")
(accept "iifname @lan ")
"log prefix \"DENIED CHAIN=input-ip6 \""
];
};
@@ -146,7 +146,7 @@ in {
family = "ip6";
rules = [
# this is where you put permitted incoming connections
# "oifname \"int\" ip6 daddr 2001:8b0:de3a:40de::e9d tcp dport 22"
# "oifname @lan ip6 daddr 2001:8b0:de3a:40de::e9d tcp dport 22"
];
};
@@ -157,7 +157,7 @@ in {
policy = "accept";
family = "ip";
rules = [
"oifname \"ppp0\" masquerade"
"oifname @wan masquerade"
];
};
@@ -208,9 +208,9 @@ in {
rules = [
"iifname lo accept"
"icmp type { echo-request, echo-reply } accept"
"iifname int jump input-ip4-lan"
"iifname ppp0 jump input-ip4-wan"
"iifname ppp0 jump incoming-allowed-ip4"
"iifname @lan jump input-ip4-lan"
"iifname @wan jump input-ip4-wan"
"iifname @wan jump incoming-allowed-ip4"
"ct state established,related accept"
"log prefix \"DENIED CHAIN=input-ip4 \""
];
@@ -222,9 +222,9 @@ in {
policy = "drop";
hook = "forward";
rules = [
"iifname \"int\" accept"
"iifname @lan accept"
"ct state established,related accept"
"oifname \"int\" iifname \"ppp0\" jump incoming-allowed-ip4"
"oifname @lan iifname @wan jump incoming-allowed-ip4"
"log prefix \"DENIED CHAIN=forward-ip4 \""
];
};
+10
View File
@@ -60,6 +60,16 @@ in
description = "firewall ruleset";
default = {};
};
zones = mkOption {
type = types.attrsOf (types.listOf liminix.lib.types.service);
default = {};
example = lib.literalExpression ''
{
lan = with config.hardware.networkInterfaces; [ int ];
wan = [ config.services.ppp0 ];
}
'';
};
rules = mkOption {
type = types.attrsOf types.attrs; # we could usefully tighten this a bit :-)
default = import ./default-rules.nix;
+63
View File
@@ -0,0 +1,63 @@
(local { : system : join } (require :anoia))
(local svc (require :anoia.svc))
(local ll (require :lualinux))
;; ifwatch.fnl wan:/nix/store/eee/.outputs/ifname wan:/nix/store/ffff/.outputs/ifname lan:/nix/store/abc123/.outputs/ifname
(fn parse-options [cmdline]
(let [interfaces {}]
(each [_ s (ipairs cmdline)]
(let [(zone service) (string.match s "(.-):(.+)")]
(tset interfaces (svc.open service) zone)))
interfaces))
(local POLLIN 1)
(local POLLHUP 16)
(fn zone-contents [interfaces]
(accumulate [zones {}
intf zone (pairs interfaces)]
(let [ifs (or (. zones zone) [])]
(table.insert ifs (intf:output "ifname"))
(tset zones zone ifs)
zones)))
(fn wait-for-change [interfaces]
(let [pollfds (icollect [k _ (pairs interfaces)]
(bor (lshift (k:fileno) 32)
(lshift (bor POLLIN POLLHUP) 16)))]
(ll.poll pollfds)))
(fn fail [msg]
(io.stderr:write (.. "ERROR: " msg "\n")))
(macro with-popen [[handle command mode] & body]
`(let [,handle (assert (io.popen ,command ,mode))
val# (do ,(unpack body))]
(case (: ,handle :close)
ok# val#
(nil :exit code#) (fail (.. ,command " exited " code#))
(nil :signal sig#) (fail (.. ,command " killed by " sig#)))))
(fn update-zone-str [zone ifnames]
(if (> (# ifnames) 0)
(..
"flush set ip table-ip " zone " ; add element ip table-ip " zone " { " (table.concat ifnames ", ") " };\n"
"flush set ip6 table-ip6 " zone " ; add element ip6 table-ip6 " zone " { " (table.concat ifnames ", ") " };\n"
)
(..
"flush set ip table-ip " zone "; \n"
"flush set ip6 table-ip6 " zone "; \n"
)))
(fn run []
(while true
(let [interfaces (parse-options arg)]
(with-popen [nft "nft -f -" :w]
(each [zone ifnames (pairs (zone-contents interfaces))]
(nft:write (update-zone-str zone ifnames))))
(wait-for-change interfaces)
(each [k _ (pairs interfaces)]
(k:close)))))
{ : run }
+33 -6
View File
@@ -3,13 +3,40 @@
, lib
, firewallgen
, nftables
, writeFennel
, anoia
, lualinux
, linotify
}:
{ rules, extraRules }:
{ rules, extraRules, zones }:
let
inherit (liminix.services) oneshot;
script = firewallgen "firewall.nft" (lib.recursiveUpdate rules extraRules);
in oneshot {
inherit (liminix.services) longrun;
inherit (lib.attrsets) mapAttrs' nameValuePair mapAttrsToList;
inherit (lib.strings) concatStringsSep;
inherit (lib.lists) flatten;
mkSet = family : name :
nameValuePair
"${name}-set-${family}"
{
kind = "set";
inherit name family;
type = "ifname";
};
sets = (mapAttrs' (n : _ : mkSet "ip" n) zones) //
(mapAttrs' (n : _ : mkSet "ip6" n) zones);
allRules = lib.recursiveUpdate extraRules (lib.recursiveUpdate (builtins.trace sets sets) rules);
script = firewallgen "firewall1.nft" allRules;
ifwatch = writeFennel "ifwatch" {
packages = [anoia lualinux linotify];
mainFunction = "run";
} ./ifwatch.fnl ;
watchArg = z : intfs : map (i: "${z}:${i}/.outputs") intfs;
in longrun {
name = "firewall";
up = script;
down = "${nftables}/bin/nft flush ruleset";
run = ''
${script}
PATH=${nftables}/bin:$PATH
${ifwatch} ${concatStringsSep " " (flatten (mapAttrsToList watchArg zones))}
'';
finish = "${nftables}/bin/nft flush ruleset";
}
+19
View File
@@ -0,0 +1,19 @@
{ config, lib, ... }:
let
inherit (lib) mkIf mkEnableOption mkOption types;
in {
options = {
logging = {
persistent = {
enable = mkEnableOption "store logs across reboots";
};
};
};
config = {
kernel.config = mkIf config.logging.persistent.enable {
PSTORE = "y";
PSTORE_PMSG = "y";
PSTORE_RAM = "y";
};
};
}
+6 -2
View File
@@ -11,12 +11,16 @@ let
in
{
imports = [
./outputs/squashfs.nix
./outputs/vmroot.nix
./outputs/boot-extlinux.nix
./outputs/boot-fit.nix
./outputs/btrfs.nix
./outputs/jffs2.nix
# ./outputs/mtdimage.nix
./outputs/squashfs.nix
./outputs/ubimage.nix
./outputs/uimage.nix
./outputs/updater
./outputs/vmroot.nix
];
options = {
system.outputs = {
-65
View File
@@ -1,65 +0,0 @@
{
config
, pkgs
, lib
, ...
}:
let
inherit (lib) mkOption types concatStringsSep;
in {
imports = [ ../ramdisk.nix ];
options.system.outputs = {
kexecboot = mkOption {
type = types.package;
description = ''
kexecboot
*********
Directory containing files needed for kexec booting.
Can be copied onto the target device using ssh or similar
'';
};
boot-sh = mkOption {
type = types.package;
description = ''
Shell script to run on the target device that invokes
kexec with appropriate options
'';
};
};
config = {
boot.ramdisk.enable = true;
system.outputs = {
kexecboot =
let o = config.system.outputs; in
pkgs.runCommand "kexecboot" {} ''
mkdir $out
cd $out
ln -s ${o.rootfs} rootfs
ln -s ${o.kernel} kernel
ln -s ${o.manifest} manifest
ln -s ${o.boot-sh} boot.sh
ln -s ${pkgs.kexec-tools-static}/bin/kexec ./kexec
ln -s ${o.dtb} dtb
'';
boot-sh =
let
inherit (config.system.outputs) rootfs;
cmdline = concatStringsSep " " config.boot.commandLine;
in
pkgs.buildPackages.runCommand "boot.sh.sh" {
} ''
rootfsStart=${toString (100 * 1024 * 1024)}
rootfsBytes=$(stat -L -c %s ${rootfs})
append_cmd="mtdparts=phram0:''${rootfsBytes}(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsBytes} memmap=''${rootfsBytes}\$''${rootfsStart}";
cat > $out <<EOF
#!/bin/sh
test -d \$1
cd \$1
./kexec -f -d --map-file rootfs@$rootfsStart --dtb dtb --command-line '${cmdline} $append_cmd' kernel
EOF
'';
};
};
}
+3 -1
View File
@@ -34,7 +34,8 @@ in {
This creates an image called :file:`firmware.bin` suitable for
squashfs or jffs2 systems. It can be flashed from U-Boot (if
you have a serial console connection), or on some devices from
the vendor firmware, or from a Liminix kexecboot system.
the vendor firmware, or from Liminix when using
:ref:`levitate`
If you are flashing from U-Boot, the file
:file:`flash.scr` is a sequence of commands
@@ -60,6 +61,7 @@ in {
config = {
kernel = {
config = {
# this needs to be conditional on "not qemu"
MTD_SPLIT_UIMAGE_FW = "y";
} // lib.optionalAttrs (pkgs.stdenv.isMips) {
# https://stackoverflow.com/questions/26466470/can-the-logical-erase-block-size-of-an-mtd-device-be-increased
+3
View File
@@ -57,6 +57,8 @@ in {
system.outputs = rec {
tftpboot =
# no ubifs on an mtd directly, it needs ubi volumes
assert config.rootfsType != "ubifs";
let
o = config.system.outputs;
image = let choices = {
@@ -119,6 +121,7 @@ in {
node=$(printf "phram-rootfs@%x" $rootfsStart)
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)
fdtput -p dtb /reserved-memory/$node no-map
cmd="liminix ${cmdline} mtdparts=phram0:''${rootfsSize}(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsSize},${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0";
fdtput -t s dtb /chosen ${config.boot.commandLineDtbNode} "$cmd"
+18 -23
View File
@@ -7,10 +7,12 @@
let
inherit (lib) mkIf mkOption types;
cfg = config.boot.tftp;
instructions = pkgs.writeText "env.scr" ''
instructions = pkgs.writeText "flash.scr" ''
setenv serverip ${cfg.serverip}
setenv ipaddr ${cfg.ipaddr}
setenv loadaddr ${lib.toHexString cfg.loadAddress}
tftpboot $loadaddr result/rootfs
ubi write $loadaddr liminix $filesize
'';
in {
options.system.outputs = {
@@ -63,18 +65,20 @@ Now we can make our new root volume
uboot> ubi create liminix -
3) transfer the root filesystem from the build system and write it
to the new volume. Paste the environment variable settings from
:file:`result/env.scr` into U-Boot, then run
3) transfer the root filesystem from the build system and write it to
the new volume. Paste the contents of :file:`result/flash.scr` one line at a time
into U-Boot:
.. code-block:: console
uboot> tftpboot ''${loadaddr} result/rootfs
uboot> ubi write ''${loadaddr} liminix $filesize
uboot> setenv serverip 10.0.0.1
uboot> setenv ipaddr 10.0.0.8
uboot> setenv loadaddr 4007FF28
uboot> tftpboot $loadaddr result/rootfs
uboot> ubi write $loadaddr liminix $filesize
Now we have the root filesystem installed on the device. You
can even mount it and poke around using ``ubifsmount ubi0:liminix;
ubifsls /``
can even mount it and poke around using :command:`ubifsmount ubi0:liminix; ubifsls /`
4) optional: before you configure the device to boot into Liminix
automatically, you can try booting it by hand to see if it works:
@@ -89,20 +93,11 @@ Once you've done this and you're happy with it, reset the device to
return to U-Boot.
5) Instructions for configuring autoboot are likely to be very
device-dependent. On the Linksys E8450/Belkin RT3200, the environment
variable `boot_production` governs what happens on a normal boot, so
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
On other devices, some detective work may be needed. Try running
`printenv` and look for likely commands, try looking at the existing
boot process, maybe even try looking for documentation for that device.
device-dependent and you should consult the Liminix documentation for
your device. (If you're bringing up a new device, some detective work
may be needed. Try running `printenv` and trace through the flow of
execution from (probably) :command:`$bootcmd` and look for a suitable
variable to change)
6) Now you can reboot the device into Liminix
@@ -120,6 +115,6 @@ boot process, maybe even try looking for documentation for that device.
mkdir $out
cd $out
ln -s ${o.rootfs} rootfs
ln -s ${instructions} env.scr
ln -s ${instructions} flash.scr
'';
}
+2 -1
View File
@@ -27,7 +27,8 @@ in
config.system.outputs.updater =
runCommand "buildUpdater" { } ''
mkdir -p $out/bin
mkdir -p $out/bin $out/etc
cp ${o.kernel.config} $out/etc/kconfig
substitute ${./update.sh} $out/bin/update.sh \
--subst-var-by toplevel ${o.systemConfiguration} \
--subst-var-by min_copy_closure ${min-copy-closure}
+2 -2
View File
@@ -37,8 +37,8 @@ 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
ts=$(date +%Y%m%dT%H%M%S)
$ssh_command $target_host "$toplevel/bin/install && ln -s $(realpath --relative-to / $toplevel) /persist/${ts}.configuration"
case "$reboot" in
reboot)
$ssh_command $target_host "sync; source /etc/profile; reboot"
+8
View File
@@ -48,6 +48,13 @@ in {
firewall = {
enable = mkEnableOption "firewall";
rules = mkOption { type = types.attrsOf types.attrs; };
zones = mkOption {
type = types.attrsOf (types.listOf liminix.lib.types.service);
default = {
lan = [ config.services.int ];
wan = [ config.services.wan ];
};
};
};
wan = {
@@ -143,6 +150,7 @@ in {
services.firewall = mkIf cfg.firewall.enable
(svc.firewall.build {
extraRules = cfg.firewall.rules;
inherit (cfg.firewall) zones;
});
services.resolvconf = oneshot rec {
+1 -2
View File
@@ -7,8 +7,7 @@ in {
ramdisk = {
enable = mkEnableOption ''
reserving part of memory as
an MTD-based RAM disk. Needed for TFTP booting or for
kexec-based revertable upgrade
an MTD-based RAM disk. Needed for TFTP booting
'';
};
};
+1 -9
View File
@@ -17,7 +17,7 @@ let
logger =
let pipecmds =
["${s6}/bin/s6-log -bpd3 -- ${cfg.script} 1"] ++
(lib.optional cfg.persistent.enable
(lib.optional (cfg ? persistent && cfg.persistent.enable)
"/bin/tee /dev/pmsg0") ++
(lib.optional cfg.shipping.enable
"${pkgs.logshipper}/bin/logtap ${cfg.shipping.socket} logshipper-socket-event");
@@ -215,9 +215,6 @@ let
in {
options = {
logging = {
persistent = {
enable = mkEnableOption "store logs across reboots";
};
shipping = {
enable = mkEnableOption "unix socket for log shipping";
socket = mkOption {
@@ -269,11 +266,6 @@ in {
)];
config = {
kernel.config = mkIf config.logging.persistent.enable {
PSTORE = "y";
PSTORE_PMSG = "y";
PSTORE_RAM = "y";
};
filesystem = dir {
etc = dir {
s6-rc = dir {
+5
View File
@@ -22,6 +22,11 @@ mount -t tmpfs none /tmp
mkdir /dev/pts
mount -t devpts none /dev/pts
if test -c /dev/pmsg0 ; then
mount -t pstore none /sys/fs/pstore
(cat /sys/fs/pstore/* && rm /sys/fs/pstore/*) > /run/log/previous-boot
fi
mkdir -m 0751 -p /run/services/outputs
chgrp system /run/services/outputs
+8
View File
@@ -7,6 +7,7 @@
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
inherit (pkgs.pseudofile) dir file;
mkBoolOption = description : mkOption {
type = types.bool;
inherit description;
@@ -20,6 +21,13 @@ in {
};
};
config.programs.busybox.options.FEATURE_FANCY_ECHO = "y";
config.filesystem = dir {
etc = dir {
shells = {
file = "/bin/sh\n";
};
};
};
config.system.service = {
ssh = config.system.callService ./ssh.nix {
address = mkOption {
+1
View File
@@ -60,6 +60,7 @@
(write-value (.. directory "/" filename) new-value)
(read-value (.. directory "/" filename))))
:close #(watcher:close)
:fileno #(watcher:fileno)
: events
}))
+2
View File
@@ -96,9 +96,11 @@ in {
minisock = callPackage ./minisock { };
nellie = callPackage ./nellie { };
netlink-lua = callPackage ./netlink-lua { };
nginx-small = callPackage ./nginx-small { };
odhcp-script = callPackage ./odhcp-script { };
odhcp6c = callPackage ./odhcp6c { };
openwrt = callPackage ./openwrt { };
openwrt_24_10 = callPackage ./openwrt/2410.nix { };
output-template = callPackage ./output-template { };
ppp = callPackage ./ppp { };
pppoe = callPackage ./pppoe { };
+49 -21
View File
@@ -1,20 +1,28 @@
commit bd51aae2e40814ac2ae5801fd9f83f6a4a886fb1
Author: Daniel Barlow <dan@telent.net>
Date: Fri Aug 23 11:33:24 2024 +0100
From 9c0ac9e41a393e0f16a57e36d9369d61d39e9aa5 Mon Sep 17 00:00:00 2001
From: Daniel Barlow <dan@telent.net>
Date: Fri, 23 Aug 2024 11:33:24 +0100
Subject: [PATCH] add -U otion to set path to authorized_keys file
add -U otion to set path to authorized_keys file
based on https://github.com/mkj/dropbear/pull/35
by Salvador Fandino sfandino@yahoo.com
- Allow authorized keys inside dirs with the sticky bit set
- Add option -U for customizing authorized_keys path
- Updated for dropbear 2024.85 (source files moved to src/)
- allow %u, %d, %n "format specifiers" in pathname so that the user's
username/homedir/uid can be embedded into the path
based on https://github.com/mkj/dropbear/pull/35
by Salvador Fandino sfandino@yahoo.com
- Allow authorized keys inside dirs with the sticky bit set
- Add option -U for customizing authorized_keys path
- Updated for dropbear 2024.85 (source files moved to src/)
- allow %u, %d, %n "format specifiers" in pathname so that the user's
username/homedir/uid can be embedded into the path
---
Makefile.in | 2 +-
manpages/dropbear.8 | 3 +
src/pathexpand.c | 149 +++++++++++++++++++++++++++++++++++++++++++
src/runopts.h | 3 +-
src/svr-authpubkey.c | 86 +++++++++++--------------
src/svr-runopts.c | 10 +++
6 files changed, 203 insertions(+), 50 deletions(-)
create mode 100644 src/pathexpand.c
diff --git a/Makefile.in b/Makefile.in
index 5ebfca2..686fbfb 100644
@@ -45,15 +53,16 @@ index bdb2ea0..c8d450d 100644
.TP
diff --git a/src/pathexpand.c b/src/pathexpand.c
new file mode 100644
index 0000000..2028733
index 0000000..07e6955
--- /dev/null
+++ b/src/pathexpand.c
@@ -0,0 +1,132 @@
@@ -0,0 +1,149 @@
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef TEST_PATHEXPAND
+#include <stdlib.h>
+
+/* to run tests:
+ gcc -Wall -o pathexpand -D TEST_PATHEXPAND=1 src/pathexpand.c && ./pathexpand
@@ -64,6 +73,17 @@ index 0000000..2028733
+
+#define m_malloc(c) malloc(c)
+#define m_strdup(c) strdup(c)
+#define TRACE(c) dropbear_trace1 c
+#include <stdarg.h>
+
+inline static void dropbear_trace1(const char* format, ...) {
+ va_list param;
+
+ va_start(param, format);
+ /* vfprintf(stderr, format, param); */
+ /* fprintf(stderr, "\n"); */
+}
+
+
+struct session {
+ struct AuthState {
@@ -124,6 +144,8 @@ index 0000000..2028733
+ /* unrecognised specifiers are discarded */
+ expect_expansion("/hi/%q/.ssh", "/hi//.ssh");
+
+
+ expect_expansion("%d/.ssh/authorized_keys", "/home/dan/.ssh/authorized_keys");
+ exit(exit_status);
+}
+
@@ -155,10 +177,13 @@ index 0000000..2028733
+ char *out = filename;
+ char *p = relfilename;
+ do {
+ p = strchrnul(start, '%');
+ strncat(out, start, p - start);
+ p = strchr(start, '%');
+
+ if(*p == '\0') break;
+ if(!p) {
+ strcat(out, start);
+ break;
+ }
+ strncat(out, start, p - start);
+
+ switch(*(p+1)) {
+ case '\0':
@@ -384,3 +409,6 @@ index c4f83c1..faddfa2 100644
}
}
--
2.47.0
+20 -2
View File
@@ -43,15 +43,33 @@ let
${concatStringsSep "\n" rules}
}
'';
doset = { name, type, elements ? [], ... } : ''
set ${name} {
type ${type}
${if elements != []
then "elements = { ${concatStringsSep ", " elements } }"
else ""
}
}
'';
dochainorset =
{ kind ? "chain", ... } @ params :
{
chain = dochain;
set = doset;
}.${kind} params;
dotable = family : chains : ''
table ${family} table-${family} {
${concatStringsSep "\n" (map dochain chains)}
${concatStringsSep "\n" (map dochainorset chains)}
}
'';
categorise = chains :
groupBy
({ family, ... } : family)
(mapAttrsToList (n : v : v // { name = n; }) chains);
(mapAttrsToList (n : v : { name = n; } // v ) chains);
in writeScript name ''
#!${nftables}/sbin/nft -f
+19
View File
@@ -121,4 +121,23 @@ let
};
in {
inherit input-ip6 forward-ip6 bogons-ip6 incoming-allowed-ip6;
lan-set-ip = {
kind = "set";
family = "ip";
type = "ifname";
elements = [
"eth0" "eth1"
];
};
# honours timeout flags gc-interval size policy counter auto-merge
lan-set-ip6 = {
kind = "set";
family = "ip6";
type = "ifname";
elements = [
"eth0" "eth1"
];
};
}
+2 -1
View File
@@ -45,7 +45,7 @@ stdenv.mkDerivation rec {
dontStrip = true;
dontPatchELF = true;
outputs = ["out" "headers" "modulesupport"] ++ targetNames;
outputs = ["out" "headers" "modulesupport" "config"] ++ targetNames;
phases = [
"unpackPhase"
"butcherPkgconfig"
@@ -114,5 +114,6 @@ stdenv.mkDerivation rec {
mkdir -p $modulesupport
make modules
cp -a . $modulesupport
cp .config $config
'';
}
+7 -3
View File
@@ -23,7 +23,7 @@
hash-2 {
algo = "sha1";
};
};
};
fdt-1 {
description = "Flattened Device Tree blob";
// data = /incbin/("./target.dtb");
@@ -40,8 +40,12 @@
};
configurations {
default = "conf-1";
conf-1 {
// The OpenWRT One wants this to be 'config-1' specifically. For now it's
// easy to just choose that, if there's another device that has a
// different restriction then we should probably add 'if not found
// select default' logic and/or make this configurable.
default = "config-1";
config-1 {
description = "Boot Linux kernel with FDT blob";
kernel = "kernel";
fdt = "fdt-1";
+1 -1
View File
@@ -71,7 +71,7 @@ in {
};
};
_VARS
mkimage -f mkimage.its ${lib.optionalString (alignment != null) "-B 0x${lib.toHexString alignment}"} kernel.uimage
mkimage -f mkimage.its -E ${lib.optionalString (alignment != null) "-B 0x${lib.toHexString alignment}"} kernel.uimage
mkimage -l kernel.uimage
'';
+56 -56
View File
@@ -35,24 +35,24 @@ int open_shipper_socket(char *pathname) {
static int fail_count = 0;
struct sockaddr_un sa = {
.sun_family = AF_LOCAL
.sun_family = AF_LOCAL
};
strncpy(sa.sun_path, pathname, sizeof(sa.sun_path) - 1);
fd = socket(AF_LOCAL, SOCK_STREAM, 0);
if(fd >= 0) {
if(connect(fd, (struct sockaddr *) &sa, sizeof sa)) {
if((fail_count % 30) == 0)
printf(PROGRAM_NAME ": cannot connect socket \"%s\": %s\n",
pathname,
strerror(errno));
fail_count++;
close(fd);
return -1;
}
int flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
if(connect(fd, (struct sockaddr *) &sa, sizeof sa)) {
if((fail_count % 30) == 0) {
printf(PROGRAM_NAME ": cannot connect socket \"%s\": %s\n",
pathname,
strerror(errno));
}
fail_count++;
close(fd);
return -1;
}
int flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
return fd;
}
@@ -75,7 +75,7 @@ int main(int argc, char * argv[]) {
int tee_bytes = 0;
if(argc != 3) {
error(1, 0, "usage: " PROGRAM_NAME " /path/to/socket cookie-text");
error(1, 0, "usage: " PROGRAM_NAME " /path/to/socket cookie-text");
}
char * socket_pathname = argv[1];
char * cookie = argv[2];
@@ -83,8 +83,8 @@ int main(int argc, char * argv[]) {
char * stop_cookie = malloc(strlen(cookie) + 7);
if(strlen(socket_pathname) > 108) {
error(1, 0, "socket pathname \"%s\" is too long, max 108 bytes",
socket_pathname);
error(1, 0, "socket pathname \"%s\" is too long, max 108 bytes",
socket_pathname);
};
strcpy(start_cookie, cookie); strcat(start_cookie, " START\n");
@@ -97,46 +97,46 @@ int main(int argc, char * argv[]) {
int quitting = 0;
while(! quitting) {
int nfds = poll(fds, 3, 2000);
if(nfds > 0) {
if((fds[0].revents & (POLLIN|POLLHUP)) &&
(out_bytes == 0) &&
(tee_bytes == 0)) {
out_bytes = read(fds[0].fd, buf, 8192);
if(out_bytes == 0) {
quitting = 1;
buf = PROGRAM_NAME " detected eof of file on stdin, exiting\n";
out_bytes = strlen(buf);
};
if(is_connected()) tee_bytes = out_bytes;
};
int nfds = poll(fds, 3, 2000);
if(nfds > 0) {
if((fds[0].revents & (POLLIN|POLLHUP)) &&
(out_bytes == 0) &&
(tee_bytes == 0)) {
out_bytes = read(fds[0].fd, buf, 8192);
if(out_bytes == 0) {
quitting = 1;
buf = PROGRAM_NAME " detected eof of file on stdin, exiting\n";
out_bytes = strlen(buf);
};
if(is_connected()) tee_bytes = out_bytes;
};
if(out_bytes) {
out_bytes -= write(fds[1].fd, buf, out_bytes);
};
if(fds[1].revents & (POLLERR|POLLHUP)) {
exit(1); // can't even log an error if the logging stream fails
};
if(is_connected()) {
if(tee_bytes) {
tee_bytes -= write(fds[2].fd, buf, tee_bytes);
};
if(fds[2].revents & (POLLERR|POLLHUP)) {
close(fds[2].fd);
fds[2].fd = -1;
(void) write(1, stop_cookie, strlen(stop_cookie));
};
};
} else {
if(! is_connected()) {
fds[2].fd = open_shipper_socket(argv[1]);
if(is_connected()) {
/* write cookie to stdout so that the backfill
* process knows we are now logging realtime
*/
write(fds[1].fd, start_cookie, strlen(start_cookie));
}
}
};
if(out_bytes) {
out_bytes -= write(fds[1].fd, buf, out_bytes);
};
if(fds[1].revents & (POLLERR|POLLHUP)) {
exit(1); // can't even log an error if the logging stream fails
};
if(is_connected()) {
if(tee_bytes) {
tee_bytes -= write(fds[2].fd, buf, tee_bytes);
};
if(fds[2].revents & (POLLERR|POLLHUP)) {
close(fds[2].fd);
fds[2].fd = -1;
(void) write(1, stop_cookie, strlen(stop_cookie));
};
};
} else {
if(! is_connected()) {
fds[2].fd = open_shipper_socket(argv[1]);
if(is_connected()) {
/* write cookie to stdout so that the backfill
* process knows we are now logging realtime
*/
write(fds[1].fd, start_cookie, strlen(start_cookie));
}
}
};
};
}
+118
View File
@@ -0,0 +1,118 @@
# There is stuff in the nixpkgs nginx that's quite difficult to
# disable if you want the smallest possible nginx for a single use, so
# herewith a derivation that allows fine-grained control of all the
# --with and --without options. The patches are from nixpkgs (or from
# openwrt via nixpkgs, it looks like) and at least one of them is
# essential for making the package cross-compilable
{
stdenv
, openssl
, fetchzip
, fetchpatch
, pcre
, zlib
, lib
, options ? []
}:
let
# nginx configure script does not accept a with-foo_module flag for
# a foo_module that's already included, nor a without-foo_module
# for a module that isn't. Ho hum
# grep -E 'without.+\)' auto/options | sed -e 's/).*$//g' -e 's/.*--without-//g'
defaultEnabled = [
"select_module"
"poll_module"
"quic_bpf_module"
"http"
"http-cache"
"http_charset_module"
"http_gzip_module"
"http_ssi_module"
"http_userid_module"
"http_access_module"
"http_auth_basic_module"
"http_mirror_module"
"http_autoindex_module"
"http_status_module"
"http_geo_module"
"http_map_module"
"http_split_clients_module"
"http_referer_module"
"http_rewrite_module"
"http_proxy_module"
"http_fastcgi_module"
"http_uwsgi_module"
"http_scgi_module"
"http_grpc_module"
"http_memcached_module"
"http_limit_conn_module"
"http_limit_req_module"
"http_empty_gif_module"
"http_browser_module"
"http_upstream_hash_module"
"http_upstream_ip_hash_module"
"http_upstream_least_conn_module"
"http_upstream_random_module"
"http_upstream_keepalive_module"
"http_upstream_zone_module"
"mail_pop3_module"
"mail_imap_module"
"mail_smtp_module"
"stream_limit_conn_module"
"stream_access_module"
"stream_geo_module"
"stream_map_module"
"stream_split_clients_module"
"stream_return_module"
"stream_pass_module"
"stream_set_module"
"stream_upstream_hash_module"
"stream_upstream_least_conn_module"
"stream_upstream_random_module"
"stream_upstream_zone_module"
"pcre"
"pcre2"
];
# for each in defaultEnabled that are not in withFlags,
# add a --without option
# for each in withFlags that are not in defaultEnabled,
# add a --with option
withouts = lib.subtractLists options defaultEnabled;
withs = lib.subtractLists defaultEnabled options;
in stdenv.mkDerivation {
pname = "nginx-small";
version = "";
buildInputs = [ openssl pcre zlib ];
configureFlags =
(map (f: "--with-${f}") withs)
++ (map (f: "--without-${f}") withouts)
++ lib.optional (pcre == null)
"--without-http_rewrite_module"
++ lib.optional (zlib == null)
"--without-http_gzip_module";
env.NIX_CFLAGS_COMPILE = "-Wno-error=cpp"; # musl
configurePlatforms = [];
patches = [
(fetchpatch {
url = "https://raw.githubusercontent.com/openwrt/packages/c057dfb09c7027287c7862afab965a4cd95293a3/net/nginx/patches/102-sizeof_test_fix.patch";
sha256 = "0i2k30ac8d7inj9l6bl0684kjglam2f68z8lf3xggcc2i5wzhh8a";
})
(fetchpatch {
url = "https://raw.githubusercontent.com/openwrt/packages/c057dfb09c7027287c7862afab965a4cd95293a3/net/nginx/patches/101-feature_test_fix.patch";
sha256 = "0v6890a85aqmw60pgj3mm7g8nkaphgq65dj4v9c6h58wdsrc6f0y";
})
(fetchpatch {
url = "https://raw.githubusercontent.com/openwrt/packages/c057dfb09c7027287c7862afab965a4cd95293a3/net/nginx/patches/103-sys_nerr.patch";
sha256 = "0s497x6mkz947aw29wdy073k8dyjq8j99lax1a1mzpikzr4rxlmd";
})
];
src = fetchzip {
url = "https://nginx.org/download/nginx-1.26.2.tar.gz";
hash = "sha256-CQbvqISgca+LBpmTUuF8IuJZC9GNn8kT0hQwzfz+wH8=";
};
}
+68
View File
@@ -0,0 +1,68 @@
{ fetchFromGitHub, pkgsBuildBuild, lib }:
let
src = fetchFromGitHub {
name = "openwrt-source";
repo = "openwrt";
owner = "openwrt";
rev = "refs/tags/v24.10.0-rc4";
hash = "sha256-7edkUCTfGnZeMWr/aXoQrP4I47iXhMi/gUxO2SR+Ylc=";
};
kernelVersion = "6.6.67";
kernelSeries = lib.versions.majorMinor kernelVersion;
doPatch = family: ''
cp -av ${src}/target/linux/generic/files/* .
chmod -R u+w .
cp -av ${src}/target/linux/${family}/files/* .
chmod -R u+w .
test -d ${src}/target/linux/${family}/files-${kernelSeries}/ && cp -av ${src}/target/linux/${family}/files-${kernelSeries}/* .
chmod -R u+w .
patches() {
for i in $* ; do patch --batch --forward -p1 < $i ;done
}
patches ${src}/target/linux/generic/backport-${kernelSeries}/*.patch
patches ${src}/target/linux/generic/pending-${kernelSeries}/*.patch
patches ${src}/target/linux/generic/hack-${kernelSeries}/*.patch
patches ${src}/target/linux/${family}/patches-${kernelSeries}/*.patch
patches \
${./make-mtdsplit-jffs2-endian-agnostic.patch} \
${./fix-mtk-wed-bm-desc-ptr.patch}
'';
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/v${lib.versions.major kernelVersion}.x/linux-${kernelVersion}.tar.gz";
hash = "sha256-Vj6O6oa83xzAF3FPl6asQK2Zrl7PaBCVjcUDq93caL4=";
};
inherit kernelVersion;
applyPatches.ath79 = doPatch "ath79";
applyPatches.ramips = doPatch "ramips";
applyPatches.mediatek = doPatch "mediatek"; # aarch64
applyPatches.mvebu = doPatch "mvebu"; # arm
applyPatches.rt2x00 = ''
PATH=${pkgsBuildBuild.patchutils}/bin:$PATH
for i in ${src}/package/kernel/mac80211/patches/rt2x00/6*.patch ; do
fixed=$(basename $i).fixed
sed '/depends on m/d' < $i | sed 's/CPTCFG_/CONFIG_/g' | recountdiff | filterdiff -x '*/local-symbols' > $fixed
case $fixed in
606-*)
;;
611-*)
filterdiff -x '*/rt2x00.h' < $fixed | patch --forward -p1
;;
601-*|607-*)
filterdiff -x '*/rt2x00_platform.h' < $fixed | patch --forward -p1
;;
*)
cat $fixed | patch --forward -p1
;;
esac
done
'';
}
@@ -0,0 +1,16 @@
From: Arnout Engelen <arnout@bzzt.net>
Date: Wed, 18 Dec 2024 14:17:46 +0100
Partial patch from https://gti.telent.net/raboof/liminix/commit/641409230051b82616c6feb35f2c0e730e46f614
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c 2024-12-18 11:08:00.598231122 +0100
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c 2024-12-18 11:08:29.845100034 +0100
@@ -625,7 +625,7 @@
static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
{
- struct mtk_rxbm_desc *desc = wed->rx_buf_ring.desc;
+ struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc;
struct mt76_txwi_cache *t = NULL;
struct mt7915_dev *dev;
struct mt76_queue *q;
+4 -2
View File
@@ -99,8 +99,10 @@ in attrset:
cp -v -fP \$src/bin/* \$src/etc/* \$dest
${if attrset ? boot then ''
(cd \$dest
if test -e boot ; then rm boot ; fi
ln -sf ${lib.strings.removePrefix "/" attrset.boot.target} ./boot
test -d boot || mkdir boot
cd boot
cp ../${lib.strings.removePrefix "/" attrset.boot.target}/* .
sync; sync
)
'' else ""}
EOF