forked from dan/liminix
Compare commits
10 Commits
main
...
mainline-o
Author | SHA1 | Date | |
---|---|---|---|
3792ec1f39 | |||
f71e8d5710 | |||
d3bde4533b | |||
0e941a8686 | |||
f023f7a0de | |||
6c61d88a3a | |||
bbce605a14 | |||
e6705c4d06 | |||
6684d34a43 | |||
a8c6d5d8a4 |
51
NEWS
51
NEWS
@ -31,56 +31,5 @@ Upstream changes that have led to incompatible Liminix changes are:
|
|||||||
* newer U-Boot version
|
* newer U-Boot version
|
||||||
* util-linux can now be built (previously depended on systemd)
|
* util-linux can now be built (previously depended on systemd)
|
||||||
|
|
||||||
2024-01-30
|
|
||||||
|
|
||||||
New port! Thanks to Arnout Engelen <arnout@bzzt.net>, Liminix
|
|
||||||
now runs on the TP-Link Archer AX23.
|
|
||||||
|
|
||||||
2024-02-12
|
|
||||||
|
|
||||||
* We now build wifi drivers (mac80211) from the same kernel source as
|
|
||||||
the running kernel, instead of using drivers from the linux-backports
|
|
||||||
project. This may be a regression on some devices that depend on
|
|
||||||
OpenWrt patches for wireless functionality: if you have a device that
|
|
||||||
used to work and now doesn't, refer to OpenWrt
|
|
||||||
package/kernel/mac80211/patches/ to see if there's something in there
|
|
||||||
that needs to be applied.
|
|
||||||
|
|
||||||
* in general, we build kernel modules (e.g. for nftables) at the same
|
|
||||||
time as the kernel itself instead of expecting to be able to build
|
|
||||||
them afterwards as though they were "out of tree". Refer to commit
|
|
||||||
b9c0d93670275e69df24902b05bf4aa4f0fcbe96 for a fuller explanation
|
|
||||||
of how this simplifies things.
|
|
||||||
|
|
||||||
2024-02-13
|
|
||||||
|
|
||||||
So that we can be more consistent about services that would like their
|
|
||||||
state to be preserved across boots (assuming a writable filesystem)
|
|
||||||
these changes have been made
|
|
||||||
|
|
||||||
* /run/service-state has been moved to /run/services/outputs
|
|
||||||
to better reflect what it's used for
|
|
||||||
* /run/services/state is either a symlink to /persist/services/state
|
|
||||||
(if there's a writeable fs on /persist) or a directory (if there
|
|
||||||
isn't)
|
|
||||||
|
|
||||||
The change will lose your ssh host key(s) unless you copy them from
|
|
||||||
the old location to the new one before rebooting into the new system
|
|
||||||
|
|
||||||
mkdir -m 02751 -p /run/services/state/dropbear
|
|
||||||
cp /persist/secrets/dropbear/* /run/services/state/dropbear
|
|
||||||
|
|
||||||
The `output`, `mkoutputs` functions defined by ${serviceFns}
|
|
||||||
have been updated for the new location.
|
|
||||||
|
|
||||||
2024-02-16
|
|
||||||
|
|
||||||
New (or at least, previously unreported) port! Liminix now runs on the
|
|
||||||
Turris Omnia and has been serving my family's internet needs for most
|
|
||||||
of this week. Thanks to NGI0 Entrust and the NLnet Foundation for
|
|
||||||
sponsoring this development (and funding the hardware)
|
|
||||||
|
|
||||||
2024-02-21
|
|
||||||
|
|
||||||
New port! Thanks to Raito Bezarius, Liminix now runs on the Zyxel NWA50AX,
|
|
||||||
an MT7621 (MIPS EL) dual radio WiFi AP.
|
|
336
THOUGHTS.txt
336
THOUGHTS.txt
@ -3953,6 +3953,31 @@ I can actually use it as a CPE. This means
|
|||||||
- would be quite cool to run sniproxy instead of forwarding to
|
- would be quite cool to run sniproxy instead of forwarding to
|
||||||
loaclhost (extra credit)
|
loaclhost (extra credit)
|
||||||
|
|
||||||
|
Sat Feb 10 12:41:12 GMT 2024
|
||||||
|
|
||||||
|
s6-linux-init version 1.1.2.0
|
||||||
|
|
||||||
|
nfnetlink: module verification failed: signature and/or required key missing - tainting kernel
|
||||||
|
------------[ cut here ]------------
|
||||||
|
kernel BUG at net/wireless/core.h:125!
|
||||||
|
Internal error: Oops - BUG: 0 [#1] SMP ARM
|
||||||
|
Modules linked in: cfg80211(E+) nfnetlink(E)
|
||||||
|
CPU: 0 PID: 197 Comm: insmod Tainted: G E 6.7.4 #1
|
||||||
|
Hardware name: Marvell Armada 380/385 (Device Tree)
|
||||||
|
PC is at cfg80211_netdev_notifier_call+0x2cc/0x3e0 [cfg80211]
|
||||||
|
LR is at call_netdevice_register_net_notifiers+0x4c/0xec
|
||||||
|
pc : [<bf010024>] lr : [<c0672e30>] psr: 60000013
|
||||||
|
sp : f0ba5c10 ip : fffffffb fp : c328df00
|
||||||
|
r10: c15c4170 r9 : c328df00 r8 : 00000000
|
||||||
|
r7 : 00000000 r6 : bf04c620 r5 : c10c9000 r4 : c11ff414
|
||||||
|
r3 : 00000000 r2 : f0ba5df4 r1 : 00000005 r0 : bf04c620
|
||||||
|
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
|
||||||
|
Control: 10c5387d Table: 0320804a DAC: 00000051
|
||||||
|
R
|
||||||
|
cfg80211_netdev_notifier_call [cfg80211] from call_netdevice_register_net_notifiers+0x4c/0xec
|
||||||
|
|
||||||
|
setenv omnia_reset 1; run bootcmd_rescue
|
||||||
|
|
||||||
Sat Feb 10 18:23:54 GMT 2024
|
Sat Feb 10 18:23:54 GMT 2024
|
||||||
|
|
||||||
ARGH KERNEL
|
ARGH KERNEL
|
||||||
@ -3976,316 +4001,15 @@ AP advertised VHT without HT, disabling HT/VHT/HE
|
|||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
- [done] support kernel version as parameter to builder pkgs/kernel/default.nix
|
- support kernel version as parameter to builder pkgs/kernel/default.nix
|
||||||
- [done] extract the change in how module loading works from omnia device config,
|
- extract the change in how module loading works from omnia device config,
|
||||||
and fix the other thing that uses it
|
and fix the other thing that uses it
|
||||||
- [axed] wlan module to take 'backported' as a parameter
|
- wlan module to take 'backported' as a parameter
|
||||||
half of the omnia conditionalConfig can go into the module
|
half of the omnia conditionalConfig can go into the module
|
||||||
- [done] upgrade omnia to kernel v6
|
- upgrade omnia to kernel v6
|
||||||
- figure out what mdns we need for local hostname resolution
|
- figure out what mdns we need for local hostname resolution
|
||||||
(maybe bridging lan/wlan)?
|
(maybe bridging lan/wlan)?
|
||||||
- [DONE] slow wifi because "AP advertised VHT without HT, disabling HT/VHT/HE"
|
- [DONE] slow wifi because "AP advertised VHT without HT, disabling HT/VHT/HE"
|
||||||
- [DONE] add local domain to secrets
|
- [DONE] add local domain to secrets
|
||||||
- run sniproxy instead of forwarding
|
- run sniproxy instead of forwarding
|
||||||
- [test] forward some port to loaclhost 22 for inbound ipv4 ssh
|
- forward some port to loaclhost 22 for inbound ipv4 ssh
|
||||||
|
|
||||||
|
|
||||||
Mon Feb 12 21:50:35 GMT 2024
|
|
||||||
|
|
||||||
# find /run/service-state/dhcp6c.wan.link.pppoe/address/
|
|
||||||
/run/service-state/dhcp6c.wan.link.pppoe/address/
|
|
||||||
/run/service-state/dhcp6c.wan.link.pppoe/address/2001-8b0-1111-1111-0-ffff-51bb-4cf2_LFoo015bSsM
|
|
||||||
/run/service-state/dhcp6c.wan.link.pppoe/address/2001-8b0-1111-1111-0-ffff-51bb-4cf2_LFoo015bSsM/valid
|
|
||||||
/run/service-state/dhcp6c.wan.link.pppoe/address/2001-8b0-1111-1111-0-ffff-51bb-4cf2_LFoo015bSsM/preferred
|
|
||||||
/run/service-state/dhcp6c.wan.link.pppoe/address/2001-8b0-1111-1111-0-ffff-51bb-4cf2_LFoo015bSsM/len
|
|
||||||
/run/service-state/dhcp6c.wan.link.pppoe/address/2001-8b0-1111-1111-0-ffff-51bb-4cf2_LFoo015bSsM/address
|
|
||||||
#
|
|
||||||
|
|
||||||
valid 7199 preferred 3599
|
|
||||||
|
|
||||||
Tue Feb 13 19:44:57 GMT 2024
|
|
||||||
|
|
||||||
Before we put this back live, would be good to
|
|
||||||
|
|
||||||
[done] 1) move the leases file into /persist
|
|
||||||
|
|
||||||
I think we'll do /persist/service/<name>/ and change ssh to use the same
|
|
||||||
scheme.
|
|
||||||
|
|
||||||
we could put mkpersist() in serviceFns which would check for /persist
|
|
||||||
and return a directory in /persist/service/ or /run/service-state
|
|
||||||
|
|
||||||
(will something bad happen if we use /run/service-state? it will also
|
|
||||||
expose the thingy as an output, but whether it's accessible that way
|
|
||||||
will depend on whether there's a writable fs or not, which is unexpected)
|
|
||||||
|
|
||||||
: rename service-state to /run/services/outputs
|
|
||||||
: on boot
|
|
||||||
: if /persist
|
|
||||||
: create /persist/services/state and symlink /run/services/state to it
|
|
||||||
: else create /run/services/state
|
|
||||||
|
|
||||||
|
|
||||||
[done] 2) maybe change the local domain back to .lan? setting up
|
|
||||||
systemd-networkd with search domains is an awful faff
|
|
||||||
|
|
||||||
[done] 3) work out what to do with incoming ssh from wan
|
|
||||||
|
|
||||||
- For noetbook and thinkpad we have a vpn anyway so can expect to
|
|
||||||
reach loaclhost directly using ipv6
|
|
||||||
|
|
||||||
- stop ssh from ever trying to get to our ipv4 address.
|
|
||||||
- we could get rid of A record for loaclhost.telent.net but
|
|
||||||
there are a bunch of CNAMES pointing at it for web servers.
|
|
||||||
- we could reject incoming connections to tcp4 port 22 in firewall
|
|
||||||
and then there is a clear signal to Dont Do That Then
|
|
||||||
|
|
||||||
- for emergency use, dnat ipv4 2200 and 2201 to rotuer and loaclhost
|
|
||||||
|
|
||||||
Tue Feb 13 22:31:03 GMT 2024
|
|
||||||
|
|
||||||
* the reason we can't reboot is that there is a service to add each
|
|
||||||
lan device to the bridge which does ifwait $dev running, which doesn't
|
|
||||||
return until there's something plugged in. So s6-rc hangs indefinitely
|
|
||||||
until the lan switch is fully populated. This is definitely a "next
|
|
||||||
milestone" thing.
|
|
||||||
|
|
||||||
* another example of "thing that depends on other thing but which it
|
|
||||||
is actually OK if neither of them happen" might be "mount a
|
|
||||||
filesystem if there is a usb mass storage device attached"
|
|
||||||
|
|
||||||
* I don't know if failover also fits into the model we don't quite
|
|
||||||
have. LTE route depends on pppoe not being healthy
|
|
||||||
|
|
||||||
we can have services (or bundles) that aren't part of the default target,
|
|
||||||
and plumb them into events of some kind (netlink?) to bring them up/down?
|
|
||||||
|
|
||||||
we can use s6-rc instanced services:
|
|
||||||
https://skarnet.org/software/s6/instances.html
|
|
||||||
|
|
||||||
"s6-instance-create and s6-instance-delete are relatively expensive operations, because they have to recursively copy or delete directories and use the synchronization mechanism with the instance supervisor, compared to s6-instance-control which only has to send commands to already existing supervisors. If you are going to turn instances on and off on a regular basis, it is more efficient to keep the instance existing and control it with s6-instance-control than it is to repeatedly create and delete it. "
|
|
||||||
|
|
||||||
Probably we need something that reads netlink messages and converts
|
|
||||||
them to a format that we can use to control services. Is there a
|
|
||||||
benefit to using services here and not just running commands? it means
|
|
||||||
the system state change we desire will stay changed.
|
|
||||||
|
|
||||||
TODO items not to lose track of
|
|
||||||
|
|
||||||
- speed testing (iperf)
|
|
||||||
- make gl-ar750 tftpboot build again
|
|
||||||
- finish belkin
|
|
||||||
- install sniproxy
|
|
||||||
- is there something simple we can do to make it reboot again?
|
|
||||||
- turn rotuer,extneder examples into "profiles" that don't embed
|
|
||||||
hardware specifics
|
|
||||||
|
|
||||||
Thu Feb 15 11:50:56 GMT 2024
|
|
||||||
|
|
||||||
1) to make tftpboot work with old bootm implementations we need
|
|
||||||
|
|
||||||
- compressed root
|
|
||||||
- uncompressed root
|
|
||||||
- kernel with dtb
|
|
||||||
dtb needs to know where uncompressed rootfs is and how big
|
|
||||||
|
|
||||||
2) if the image is a zImage (arm32) or an Image (arm64) we have to stick
|
|
||||||
with the three-arg bootz, and the dtb has to be lower in ram than the kernel
|
|
||||||
|
|
||||||
Fri Feb 16 15:43:32 GMT 2024
|
|
||||||
|
|
||||||
DHCP6c refresh is still wrong. We get updates for an address that
|
|
||||||
hasn't changed prefix or length, when the expiry times have changed,
|
|
||||||
and we can't action that by remove;add because remove will wipe out
|
|
||||||
any routes through the interface but add won't put them back
|
|
||||||
|
|
||||||
We can use "change" for both adds and changes, but we need to know that
|
|
||||||
a change is not a delete
|
|
||||||
|
|
||||||
The "identity" of an address is the address itself: kernel won't
|
|
||||||
let you add the same address with two different prefixes.
|
|
||||||
|
|
||||||
Keeping it simple, we could call "change" on every address in the
|
|
||||||
new-addresses list and "del" on every address in old-addresses
|
|
||||||
that is no longer in new-addresses
|
|
||||||
|
|
||||||
If the upstream has changed length, "ip addr change" is ignored,
|
|
||||||
so it needs to be in deleted as well as added/changed
|
|
||||||
|
|
||||||
Fri Feb 16 19:37:08 GMT 2024
|
|
||||||
|
|
||||||
[ 3.839775] cfg80211: module verification failed: signature and/or required key missing - tainting kernel
|
|
||||||
[ 4.156952] ath10k_pci 0000:00:00.0: enabling device (0000 -> 0002)
|
|
||||||
[ 4.165756] ath10k_pci 0000:00:00.0: pci irq legacy oper_irq_mode 1 irq_mode 0 reset_mode 0
|
|
||||||
[ 4.399285] ath10k_pci 0000:00:00.0: qca9887 hw1.0 target 0x4100016d chip_id 0x004000ff sub 0000:0000
|
|
||||||
[ 4.408906] ath10k_pci 0000:00:00.0: kconfig debug 1 debugfs 0 tracing 0 dfs 0 testmode 0
|
|
||||||
[ 4.420096] ath10k_pci 0000:00:00.0: firmware ver 10.2.4-1.0-00047 api 5 features no-p2p,ignore-otp,ski
|
|
||||||
p-clock-init,mfp,allows-mesh-bcast crc32 62f7565f
|
|
||||||
[ 4.467443] ath10k_pci 0000:00:00.0: board_file api 1 bmi_id N/A crc32 546cca0d
|
|
||||||
[ 5.472096] ath10k_pci 0000:00:00.0: htt-ver 2.1 wmi-op 5 htt-op 2 cal file max-sta 128 raw 0 hwcrypto
|
|
||||||
[ 5.585796] ath: EEPROM regdomain: 0x0
|
|
||||||
[ 5.589712] ath: EEPROM indicates default country code should be used
|
|
||||||
[ 5.596364] ath: doing EEPROM country->regdmn map search
|
|
||||||
[ 5.601875] ath: country maps to regdmn code: 0x3a
|
|
||||||
[ 5.606831] ath: Country alpha2 being used: US
|
|
||||||
[ 5.611425] ath: Regpair used: 0x3a
|
|
||||||
[ 6.742365] ath10k_pci 0000:00:00.0: pdev param 0 not supported by firmware
|
|
||||||
[ 6.903389] random: hostapd: uninitialized urandom read (1027 bytes read)
|
|
||||||
[ 8.169901] ath10k_pci 0000:00:00.0: pdev param 0 not supported by firmware
|
|
||||||
[ 14.450193] ath10k_pci 0000:00:00.0: pdev param 0 not supported by firmware
|
|
||||||
[ 15.518682] random: hostapd: uninitialized urandom read (1027 bytes read)
|
|
||||||
[ 16.762697] ath10k_pci 0000:00:00.0: pdev param 0 not supported by firmware
|
|
||||||
[ 23.030622] ath10k_pci 0000:00:00.0: pdev param 0 not supported by firmware
|
|
||||||
[
|
|
||||||
|
|
||||||
|
|
||||||
Tue Feb 27 23:16:27 GMT 2024
|
|
||||||
|
|
||||||
We made it a full week with rotuer running internet chez nous and no
|
|
||||||
need for an intervention, so I am happy to call it "production". There are
|
|
||||||
still things that need fixing but they're mostly within scope for
|
|
||||||
a services refresh
|
|
||||||
|
|
||||||
I have embarked on "profiles" by creating a wap.nix
|
|
||||||
|
|
||||||
I think we could have a service module for resolvconf
|
|
||||||
|
|
||||||
It would be good to build a wap.nix example for the belkin and we
|
|
||||||
could start looking at ubifs
|
|
||||||
|
|
||||||
I've lost a chunk of notes about using events to drive desired service
|
|
||||||
state. There is probably only going to be one udev listener, so
|
|
||||||
what if we have udev as a config key thusly
|
|
||||||
|
|
||||||
udev.rules = [
|
|
||||||
{
|
|
||||||
match = {
|
|
||||||
SUBSYSTEM = "rpmsg";
|
|
||||||
ATTR.name = "DATA5_CNTL";
|
|
||||||
};
|
|
||||||
|
|
||||||
service = longrun {
|
|
||||||
name = "lte-modem";
|
|
||||||
run = "blah blah blah";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
# this one would be provided by the bridge module instead of
|
|
||||||
# adding bridge member services to the default target
|
|
||||||
|
|
||||||
{
|
|
||||||
match = {
|
|
||||||
SUBSYSTEM="net";
|
|
||||||
ID_PATH="pci-0000:04:00.0";
|
|
||||||
ATTR.operstate = "up";
|
|
||||||
};
|
|
||||||
|
|
||||||
service = oneshot {
|
|
||||||
up = "ip link set dev $dev master $(output ${primary} ifname)";
|
|
||||||
down = "ip link set dev $(output ${member} ifname) nomaster";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
This works for udev/sysfs, but we want a similar architecture(sic) for
|
|
||||||
user-generated target state so we could have services that run on e.g.
|
|
||||||
"is the ppp0 service healthy" or not. Probably there isn't a top-level
|
|
||||||
config key for each service though
|
|
||||||
|
|
||||||
services.wan = svc.ppoe.build { .... };
|
|
||||||
services.lte = watcher.build {
|
|
||||||
watching = services.wan;
|
|
||||||
match = {
|
|
||||||
# an expression matching the outputs of the service
|
|
||||||
# to be watched
|
|
||||||
health = "failing";
|
|
||||||
};
|
|
||||||
service = oneshot {
|
|
||||||
run = "start_lte_blah";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
thing is, we could use this syntax also for sysfs watches, but not vice versa
|
|
||||||
|
|
||||||
... but it's not quite the same because here we're doing static matches
|
|
||||||
on contents of files, whereas the udev one is a query expression on the
|
|
||||||
sysfs database. we might need that flexibiity to implement "mount the
|
|
||||||
backup drive no matter _which_ damn sda_n_ device it appears as". I don't
|
|
||||||
know if there's the same need for service outputs - postulate the
|
|
||||||
existence of a collection of services which are all similar enough that
|
|
||||||
some other service can watch them all and do $something when one of
|
|
||||||
the changes state. Or a single service with very complicated outputs.
|
|
||||||
For example, something could watch the snmp database and update service
|
|
||||||
status depending on what it finds. Or something something mqtt...
|
|
||||||
|
|
||||||
we find that the "match" needs to be interpreted differently according
|
|
||||||
to the thing being watched. perhaps the service being watched needs to
|
|
||||||
provide a "watch me" interface somehow which accepts match criteria and
|
|
||||||
outputs a true/false. Something else then needs to
|
|
||||||
|
|
||||||
|
|
||||||
services.addmember = services.udev.watch {
|
|
||||||
match = {
|
|
||||||
SUBSYSTEM = "net";
|
|
||||||
ID_PATH = "pci-0000:04:00.0";
|
|
||||||
ATTR.operstate = "up";
|
|
||||||
};
|
|
||||||
|
|
||||||
service = oneshot {
|
|
||||||
up = "ip link set dev $dev master $(output ${primary} ifname)";
|
|
||||||
down = "ip link set dev $(output ${member} ifname) nomaster";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Sat Mar 2 15:37:29 GMT 2024
|
|
||||||
|
|
||||||
Simply put, what I think it boils down to is that we want a service
|
|
||||||
which acts as an actuator or control switch for another service,
|
|
||||||
and will start/stop that controlled service according to some
|
|
||||||
criteria.
|
|
||||||
|
|
||||||
services.addmember = svc.network.ifwatch.build {
|
|
||||||
interface = config.hardware.networkInterfaces.lan1;
|
|
||||||
|
|
||||||
# this should be part of the definition not the params
|
|
||||||
service = oneshot {
|
|
||||||
name = "member-${bridge}-${interface}";
|
|
||||||
up = "ip link set dev $dev master $(output ${primary} ifname)";
|
|
||||||
down = "ip link set dev $(output ${member} ifname) nomaster";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
we could start by writing this. we need to adapt ifwait
|
|
||||||
|
|
||||||
Sun Mar 3 17:09:21 GMT 2024
|
|
||||||
|
|
||||||
this is annoyingly hard to test. the tests we'd like to write are
|
|
||||||
|
|
||||||
1) when it gets events that don't match the requirement, nothing happens
|
|
||||||
2) when it gets an event that should start the service, the
|
|
||||||
service starts
|
|
||||||
3) when stop should stop
|
|
||||||
4) when start and already started, nothing happens
|
|
||||||
5) when stop and already stopped, nothing happens
|
|
||||||
|
|
||||||
what do we do if service fails to start? s6-rc will eventually reset it
|
|
||||||
to "down", I think: do we need to take action?
|
|
||||||
|
|
||||||
Mon Mar 4 20:46:55 GMT 2024
|
|
||||||
|
|
||||||
# relevant but not correct for this model: https://www.forked.net/forums/viewtopic.php?f=13&t=3490
|
|
||||||
|
|
||||||
# power on port 5
|
|
||||||
snmpset -v 1 -c private 192.168.5.14 .1.3.6.1.4.1.318.1.1.4.4.2.1.3.5 integer 1
|
|
||||||
|
|
||||||
# power off port 5
|
|
||||||
snmpset -v 1 -c private 192.168.5.14 .1.3.6.1.4.1.318.1.1.4.4.2.1.3.5 integer 2
|
|
||||||
|
|
||||||
# toggle off/on port 5
|
|
||||||
snmpset -v 1 -c private 192.168.5.14 .1.3.6.1.4.1.318.1.1.4.4.2.1.3.5 integer 3
|
|
||||||
|
|
||||||
Wed Mar 6 18:24:29 GMT 2024
|
|
||||||
|
|
||||||
What happens when we attempt to start the service but it fails? We
|
|
||||||
assume the start was successful so we won't try and restart it again
|
|
||||||
next time we get an event that should cause it to start.
|
|
||||||
|
9
ci.nix
9
ci.nix
@ -9,14 +9,9 @@ let
|
|||||||
borderVmConf = ./bordervm.conf-example.nix;
|
borderVmConf = ./bordervm.conf-example.nix;
|
||||||
inherit (pkgs.lib.attrsets) genAttrs;
|
inherit (pkgs.lib.attrsets) genAttrs;
|
||||||
devices = [
|
devices = [
|
||||||
"gl-ar750"
|
"gl-ar750" "gl-mt300n-v2" "gl-mt300a"
|
||||||
"gl-mt300a"
|
"qemu" "qemu-aarch64" "qemu-armv7l"
|
||||||
"gl-mt300n-v2"
|
|
||||||
"qemu"
|
|
||||||
"qemu-aarch64"
|
|
||||||
"qemu-armv7l"
|
|
||||||
"tp-archer-ax23"
|
"tp-archer-ax23"
|
||||||
"zyxel-nwa50ax"
|
|
||||||
];
|
];
|
||||||
vanilla = ./vanilla-configuration.nix;
|
vanilla = ./vanilla-configuration.nix;
|
||||||
for-device = name:
|
for-device = name:
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
, liminix-config ? <liminix-config>
|
, liminix-config ? <liminix-config>
|
||||||
, nixpkgs ? <nixpkgs>
|
, nixpkgs ? <nixpkgs>
|
||||||
, borderVmConf ? ./bordervm.conf.nix
|
, borderVmConf ? ./bordervm.conf.nix
|
||||||
, imageType ? "primary"
|
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
@ -31,9 +30,6 @@ let
|
|||||||
./modules/s6
|
./modules/s6
|
||||||
./modules/users.nix
|
./modules/users.nix
|
||||||
./modules/outputs.nix
|
./modules/outputs.nix
|
||||||
{
|
|
||||||
boot.imageType = imageType;
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
config = eval.config;
|
config = eval.config;
|
||||||
|
@ -73,7 +73,7 @@
|
|||||||
MTK_INFRACFG = "y";
|
MTK_INFRACFG = "y";
|
||||||
|
|
||||||
MTK_PMIC_WRAP = "y";
|
MTK_PMIC_WRAP = "y";
|
||||||
NVMEM_MTK_EFUSE="y";
|
MTK_EFUSE="y";
|
||||||
# MTK_HSDMA="y";
|
# MTK_HSDMA="y";
|
||||||
MTK_SCPSYS="y";
|
MTK_SCPSYS="y";
|
||||||
MTK_SCPSYS_PM_DOMAINS="y";
|
MTK_SCPSYS_PM_DOMAINS="y";
|
||||||
@ -92,6 +92,7 @@
|
|||||||
|
|
||||||
MEDIATEK_GE_PHY = "y";
|
MEDIATEK_GE_PHY = "y";
|
||||||
# MEDIATEK_MT6577_AUXADC = "y";
|
# MEDIATEK_MT6577_AUXADC = "y";
|
||||||
|
# MEDIATEK_WATCHDOG = "y";
|
||||||
NET_MEDIATEK_SOC = "y";
|
NET_MEDIATEK_SOC = "y";
|
||||||
NET_MEDIATEK_SOC_WED = "y";
|
NET_MEDIATEK_SOC_WED = "y";
|
||||||
NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO
|
NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO
|
||||||
@ -148,13 +149,6 @@
|
|||||||
WATCHDOG = "y";
|
WATCHDOG = "y";
|
||||||
MEDIATEK_WATCHDOG = "y";
|
MEDIATEK_WATCHDOG = "y";
|
||||||
};
|
};
|
||||||
conditionalConfig = {
|
|
||||||
WLAN= {
|
|
||||||
MT7615E = "m";
|
|
||||||
MT7622_WMAC = "y";
|
|
||||||
MT7915E = "m";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
boot = {
|
boot = {
|
||||||
commandLine = [ "console=ttyS0,115200" ];
|
commandLine = [ "console=ttyS0,115200" ];
|
||||||
@ -175,9 +169,12 @@
|
|||||||
hardware =
|
hardware =
|
||||||
let
|
let
|
||||||
openwrt = pkgs.openwrt;
|
openwrt = pkgs.openwrt;
|
||||||
mac80211 = pkgs.kmodloader.override {
|
mac80211 = pkgs.mac80211.override {
|
||||||
targets = ["mt7615e" "mt7915e"];
|
drivers = [
|
||||||
inherit (config.system.outputs) kernel;
|
"mt7615e"
|
||||||
|
"mt7915e"
|
||||||
|
];
|
||||||
|
klibBuild = config.system.outputs.kernel.modulesupport;
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
ubi = {
|
ubi = {
|
||||||
|
@ -71,10 +71,9 @@
|
|||||||
cp $blobdir/board.bin $out/ath10k/QCA9887/hw1.0/
|
cp $blobdir/board.bin $out/ath10k/QCA9887/hw1.0/
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
mac80211 = pkgs.kmodloader.override {
|
mac80211 = pkgs.mac80211.override {
|
||||||
targets = ["ath9k" "ath10k_pci"];
|
drivers = ["ath9k" "ath10k_pci"];
|
||||||
inherit (config.system.outputs) kernel;
|
klibBuild = config.system.outputs.kernel.modulesupport;
|
||||||
dependencies = [ ath10k_cal_data ];
|
|
||||||
};
|
};
|
||||||
ath10k_cal_data =
|
ath10k_cal_data =
|
||||||
let
|
let
|
||||||
@ -133,7 +132,7 @@
|
|||||||
};
|
};
|
||||||
wlan5 = link.build {
|
wlan5 = link.build {
|
||||||
ifname = "wlan1";
|
ifname = "wlan1";
|
||||||
dependencies = [ ath10k_cal_data mac80211 ];
|
dependencies = [ mac80211 ath10k_cal_data ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -162,8 +161,6 @@
|
|||||||
# OpenWrt kernel patches
|
# OpenWrt kernel patches
|
||||||
extraPatchPhase = ''
|
extraPatchPhase = ''
|
||||||
${openwrt.applyPatches.ath79}
|
${openwrt.applyPatches.ath79}
|
||||||
sed -i.bak -e '\,include <linux/hw_random.h>,a #include <linux/gpio/driver.h>' drivers/net/wireless/ath/ath9k/ath9k.h # context reqd for next patch
|
|
||||||
patch -p1 < ${openwrt.src}/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
@ -214,21 +211,14 @@
|
|||||||
WATCHDOG = "y";
|
WATCHDOG = "y";
|
||||||
ATH79_WDT = "y"; # watchdog timer
|
ATH79_WDT = "y"; # watchdog timer
|
||||||
|
|
||||||
|
# this is all copied from nixwrt ath79 config. Clearly not all
|
||||||
|
# of it is device config, some of it is wifi config or
|
||||||
|
# installation method config or ...
|
||||||
|
|
||||||
EARLY_PRINTK = "y";
|
EARLY_PRINTK = "y";
|
||||||
|
|
||||||
PRINTK_TIME = "y";
|
PRINTK_TIME = "y";
|
||||||
};
|
};
|
||||||
conditionalConfig = {
|
|
||||||
WLAN = {
|
|
||||||
WLAN_VENDOR_ATH = "y";
|
|
||||||
ATH_COMMON = "m";
|
|
||||||
ATH9K = "m";
|
|
||||||
ATH9K_AHB = "y";
|
|
||||||
ATH10K = "m";
|
|
||||||
ATH10K_PCI = "m";
|
|
||||||
ATH10K_DEBUG = "y";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -47,9 +47,9 @@
|
|||||||
let
|
let
|
||||||
inherit (pkgs.liminix.networking) interface;
|
inherit (pkgs.liminix.networking) interface;
|
||||||
inherit (pkgs) openwrt;
|
inherit (pkgs) openwrt;
|
||||||
mac80211 = pkgs.kmodloader.override {
|
mac80211 = pkgs.mac80211.override {
|
||||||
targets = ["rt2800soc"];
|
drivers = ["rt2800soc"];
|
||||||
inherit (config.system.outputs) kernel;
|
klibBuild = config.system.outputs.kernel.modulesupport;
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
imports = [
|
imports = [
|
||||||
@ -178,14 +178,6 @@
|
|||||||
} // lib.optionalAttrs (config.system.service ? vlan) {
|
} // lib.optionalAttrs (config.system.service ? vlan) {
|
||||||
SWCONFIG = "y";
|
SWCONFIG = "y";
|
||||||
};
|
};
|
||||||
conditionalConfig = {
|
|
||||||
WLAN = {
|
|
||||||
WLAN_VENDOR_RALINK = "y";
|
|
||||||
RT2800SOC = "m";
|
|
||||||
RT2X00 = "m";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -43,9 +43,9 @@
|
|||||||
inherit (pkgs.pseudofile) dir symlink;
|
inherit (pkgs.pseudofile) dir symlink;
|
||||||
inherit (pkgs) openwrt;
|
inherit (pkgs) openwrt;
|
||||||
|
|
||||||
mac80211 = pkgs.kmodloader.override {
|
mac80211 = pkgs.mac80211.override {
|
||||||
targets = ["mt7603e"];
|
drivers = ["mt7603e"];
|
||||||
inherit (config.system.outputs) kernel;
|
klibBuild = config.system.outputs.kernel.modulesupport;
|
||||||
};
|
};
|
||||||
wlan_firmware = pkgs.fetchurl {
|
wlan_firmware = pkgs.fetchurl {
|
||||||
url = "https://github.com/openwrt/mt76/raw/f24b56f935392ca1d35fae5fd6e56ef9deda4aad/firmware/mt7628_e2.bin";
|
url = "https://github.com/openwrt/mt76/raw/f24b56f935392ca1d35fae5fd6e56ef9deda4aad/firmware/mt7628_e2.bin";
|
||||||
@ -185,15 +185,6 @@
|
|||||||
RALINK_WDT = "y"; # watchdog
|
RALINK_WDT = "y"; # watchdog
|
||||||
MT7621_WDT = "y"; # or it might be this one
|
MT7621_WDT = "y"; # or it might be this one
|
||||||
};
|
};
|
||||||
conditionalConfig = {
|
|
||||||
WLAN = {
|
|
||||||
WLAN_VENDOR_RALINK = "y";
|
|
||||||
WLAN_VENDOR_MEDIATEK = "y";
|
|
||||||
MT7603E = "m";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -322,14 +322,9 @@
|
|||||||
ZSTD_COMPRESS="y";
|
ZSTD_COMPRESS="y";
|
||||||
ZSTD_DECOMPRESS="y";
|
ZSTD_DECOMPRESS="y";
|
||||||
} // lib.optionalAttrs (config.system.service ? watchdog) {
|
} // lib.optionalAttrs (config.system.service ? watchdog) {
|
||||||
RALINK_WDT = "y"; # watchdog
|
RALINK_WDT = "y"; # watchdog
|
||||||
MT7621_WDT = "y"; # or it might be this one
|
MT7621_WDT = "y"; # or it might be this one
|
||||||
};
|
};
|
||||||
conditionalConfig = {
|
|
||||||
WLAN = {
|
|
||||||
MT7915E = "m";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
tplink-safeloader.board = "ARCHER-AX23-V1";
|
tplink-safeloader.board = "ARCHER-AX23-V1";
|
||||||
boot = {
|
boot = {
|
||||||
@ -358,11 +353,11 @@
|
|||||||
hardware =
|
hardware =
|
||||||
let
|
let
|
||||||
openwrt = pkgs.openwrt;
|
openwrt = pkgs.openwrt;
|
||||||
mac80211 = pkgs.kmodloader.override {
|
mac80211 = pkgs.mac80211.override {
|
||||||
targets = [
|
drivers = [
|
||||||
"mt7915e"
|
"mt7915e"
|
||||||
];
|
];
|
||||||
inherit (config.system.outputs) kernel;
|
klibBuild = config.system.outputs.kernel.modulesupport;
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
# from OEM bootlog (openwrt wiki):
|
# from OEM bootlog (openwrt wiki):
|
||||||
|
@ -289,6 +289,14 @@
|
|||||||
USB_XHCI_HCD = "y";
|
USB_XHCI_HCD = "y";
|
||||||
};
|
};
|
||||||
WLAN = {
|
WLAN = {
|
||||||
|
CFG80211 = "m";
|
||||||
|
MAC80211 = "m";
|
||||||
|
|
||||||
|
CFG80211_CERTIFICATION_ONUS = "y";
|
||||||
|
CFG80211_REQUIRE_SIGNED_REGDB = "n"; # depends on ONUS
|
||||||
|
|
||||||
|
CFG80211_CRDA_SUPPORT = "n";
|
||||||
|
|
||||||
WLAN_VENDOR_ATH = "y";
|
WLAN_VENDOR_ATH = "y";
|
||||||
ATH_COMMON = "m";
|
ATH_COMMON = "m";
|
||||||
ATH9K = "m";
|
ATH9K = "m";
|
||||||
@ -338,10 +346,41 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
hardware = let
|
hardware = let
|
||||||
mac80211 = pkgs.kmodloader.override {
|
mac80211 =
|
||||||
inherit (config.system.outputs) kernel;
|
let
|
||||||
targets = ["ath9k" "ath10k_pci"];
|
targets = [
|
||||||
};
|
"ath9k"
|
||||||
|
"ath10k_pci"
|
||||||
|
];
|
||||||
|
kmodules = pkgs.runCommand "modules" {
|
||||||
|
nativeBuildInputs = with pkgs.pkgsBuildBuild ;[
|
||||||
|
kmod cpio gawk
|
||||||
|
];
|
||||||
|
} ''
|
||||||
|
kernel=${config.system.outputs.kernel.modulesupport}
|
||||||
|
mkdir -p lib/modules/0.0
|
||||||
|
(cd $kernel && find . -name \*.ko | cpio --verbose --make-directories -p $NIX_BUILD_TOP/lib/modules/0.0)
|
||||||
|
cp $kernel/modules.* lib/modules/0.0
|
||||||
|
depmod -b . 0.0
|
||||||
|
|
||||||
|
(for i in ${lib.concatStringsSep " " targets}; do
|
||||||
|
modprobe -S 0.0 -d $NIX_BUILD_TOP --show-depends $i | sed "s,^insmod $NIX_BUILD_TOP/lib/modules/0.0/,,g"
|
||||||
|
done) | awk '!a[$0]++' > load-order
|
||||||
|
|
||||||
|
mkdir $out
|
||||||
|
for i in $(cat load-order); do
|
||||||
|
install -v $NIX_BUILD_TOP/lib/modules/0.0/$i -D $out/$i
|
||||||
|
done
|
||||||
|
echo "O=$out" > $out/load.sh
|
||||||
|
sed "s,^,insmod \$O/,g" < load-order >> $out/load.sh
|
||||||
|
echo "O=$out" > $out/unload.sh
|
||||||
|
tac load-order | sed "s,^,rmmod \$O/,g" > $out/unload.sh
|
||||||
|
''; in
|
||||||
|
oneshot {
|
||||||
|
name = "mac80211-modules";
|
||||||
|
up = "sh ${kmodules}/load.sh";
|
||||||
|
down = "sh ${kmodules}/unload.sh";
|
||||||
|
};
|
||||||
in {
|
in {
|
||||||
defaultOutput = "mtdimage";
|
defaultOutput = "mtdimage";
|
||||||
loadAddress = lim.parseInt "0x00800000"; # "0x00008000";
|
loadAddress = lim.parseInt "0x00800000"; # "0x00008000";
|
||||||
|
@ -1,155 +0,0 @@
|
|||||||
#include "mt7621.dtsi"
|
|
||||||
|
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
|
||||||
#include <dt-bindings/input/input.h>
|
|
||||||
|
|
||||||
/ {
|
|
||||||
aliases {
|
|
||||||
label-mac-device = &gmac0;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&nand {
|
|
||||||
status = "okay";
|
|
||||||
|
|
||||||
mediatek,nmbm;
|
|
||||||
mediatek,bmt-max-ratio = <15>;
|
|
||||||
mediatek,bmt-max-reserved-blocks = <64>;
|
|
||||||
mediatek,bmt-remap-range =
|
|
||||||
<0x0 0x980000>,
|
|
||||||
<0x2980000 0x7800000>;
|
|
||||||
|
|
||||||
partitions {
|
|
||||||
compatible = "fixed-partitions";
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <1>;
|
|
||||||
|
|
||||||
partition@0 {
|
|
||||||
label = "u-boot";
|
|
||||||
reg = <0x0 0x80000>;
|
|
||||||
read-only;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@80000 {
|
|
||||||
label = "u-boot-env";
|
|
||||||
reg = <0x80000 0x80000>;
|
|
||||||
read-only;
|
|
||||||
};
|
|
||||||
|
|
||||||
factory: partition@100000 {
|
|
||||||
label = "factory";
|
|
||||||
reg = <0x100000 0x80000>;
|
|
||||||
read-only;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@180000 {
|
|
||||||
label = "firmware_a";
|
|
||||||
reg = <0x180000 0x2800000>;
|
|
||||||
|
|
||||||
compatible = "fixed-partitions";
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <1>;
|
|
||||||
|
|
||||||
partition@0 {
|
|
||||||
label = "kernel_a";
|
|
||||||
reg = <0x0 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@400000 {
|
|
||||||
label = "ubi";
|
|
||||||
reg = <0x800000 0x2000000>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@2980000 {
|
|
||||||
label = "firmware_b";
|
|
||||||
reg = <0x2980000 0x2800000>;
|
|
||||||
|
|
||||||
compatible = "fixed-partitions";
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <1>;
|
|
||||||
|
|
||||||
partition@0 {
|
|
||||||
label = "kernel_b";
|
|
||||||
reg = <0x0 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@400000 {
|
|
||||||
label = "ubi_b";
|
|
||||||
reg = <0x800000 0x2000000>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@5180000 {
|
|
||||||
label = "rootfs_data";
|
|
||||||
reg = <0x5180000 0x1400000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@6580000 {
|
|
||||||
label = "logs";
|
|
||||||
reg = <0x6580000 0xd00000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@7280000 {
|
|
||||||
label = "vendor-myzyxel";
|
|
||||||
reg = <0x7280000 0x480000>;
|
|
||||||
read-only;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@7700000 {
|
|
||||||
label = "bootconfig";
|
|
||||||
reg = <0x7700000 0x80000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
mrd: partition@7780000 {
|
|
||||||
label = "mrd";
|
|
||||||
reg = <0x7780000 0x80000>;
|
|
||||||
read-only;
|
|
||||||
|
|
||||||
nvmem-layout {
|
|
||||||
compatible = "fixed-layout";
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <1>;
|
|
||||||
|
|
||||||
macaddr_mrd_1fff8: macaddr@1fff8 {
|
|
||||||
reg = <0x1fff8 0x6>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&pcie {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&pcie1 {
|
|
||||||
wlan_5g: wifi@0,0 {
|
|
||||||
reg = <0x0 0 0 0 0>;
|
|
||||||
compatible = "mediatek,mt76";
|
|
||||||
|
|
||||||
mediatek,mtd-eeprom = <&factory 0x0>;
|
|
||||||
/* MAC-Address set in userspace */
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&gmac0 {
|
|
||||||
nvmem-cells = <&macaddr_mrd_1fff8>;
|
|
||||||
nvmem-cell-names = "mac-address";
|
|
||||||
};
|
|
||||||
|
|
||||||
&switch0 {
|
|
||||||
ports {
|
|
||||||
port@4 {
|
|
||||||
status = "okay";
|
|
||||||
label = "lan";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&state_default {
|
|
||||||
gpio {
|
|
||||||
groups = "uart3";
|
|
||||||
function = "gpio";
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,155 +0,0 @@
|
|||||||
#include "mt7621.dtsi"
|
|
||||||
|
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
|
||||||
#include <dt-bindings/input/input.h>
|
|
||||||
|
|
||||||
/ {
|
|
||||||
aliases {
|
|
||||||
label-mac-device = &gmac0;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&nand {
|
|
||||||
status = "okay";
|
|
||||||
|
|
||||||
mediatek,nmbm;
|
|
||||||
mediatek,bmt-max-ratio = <15>;
|
|
||||||
mediatek,bmt-max-reserved-blocks = <64>;
|
|
||||||
mediatek,bmt-remap-range =
|
|
||||||
<0x0 0x980000>,
|
|
||||||
<0x2980000 0x7800000>;
|
|
||||||
|
|
||||||
partitions {
|
|
||||||
compatible = "fixed-partitions";
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <1>;
|
|
||||||
|
|
||||||
partition@0 {
|
|
||||||
label = "u-boot";
|
|
||||||
reg = <0x0 0x80000>;
|
|
||||||
read-only;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@80000 {
|
|
||||||
label = "u-boot-env";
|
|
||||||
reg = <0x80000 0x80000>;
|
|
||||||
read-only;
|
|
||||||
};
|
|
||||||
|
|
||||||
factory: partition@100000 {
|
|
||||||
label = "factory";
|
|
||||||
reg = <0x100000 0x80000>;
|
|
||||||
read-only;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@2980000 {
|
|
||||||
label = "firmware_b";
|
|
||||||
reg = <0x2980000 0x2800000>;
|
|
||||||
|
|
||||||
compatible = "fixed-partitions";
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <1>;
|
|
||||||
|
|
||||||
partition@0 {
|
|
||||||
label = "kernel_b";
|
|
||||||
reg = <0x0 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@400000 {
|
|
||||||
label = "ubi";
|
|
||||||
reg = <0x800000 0x2000000>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@180000 {
|
|
||||||
label = "firmware_a";
|
|
||||||
reg = <0x180000 0x2800000>;
|
|
||||||
|
|
||||||
compatible = "fixed-partitions";
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <1>;
|
|
||||||
|
|
||||||
partition@0 {
|
|
||||||
label = "kernel_a";
|
|
||||||
reg = <0x0 0x800000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@400000 {
|
|
||||||
label = "ubi_a";
|
|
||||||
reg = <0x800000 0x2000000>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@5180000 {
|
|
||||||
label = "rootfs_data";
|
|
||||||
reg = <0x5180000 0x1400000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@6580000 {
|
|
||||||
label = "logs";
|
|
||||||
reg = <0x6580000 0xd00000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@7280000 {
|
|
||||||
label = "vendor-myzyxel";
|
|
||||||
reg = <0x7280000 0x480000>;
|
|
||||||
read-only;
|
|
||||||
};
|
|
||||||
|
|
||||||
partition@7700000 {
|
|
||||||
label = "bootconfig";
|
|
||||||
reg = <0x7700000 0x80000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
mrd: partition@7780000 {
|
|
||||||
label = "mrd";
|
|
||||||
reg = <0x7780000 0x80000>;
|
|
||||||
read-only;
|
|
||||||
|
|
||||||
nvmem-layout {
|
|
||||||
compatible = "fixed-layout";
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <1>;
|
|
||||||
|
|
||||||
macaddr_mrd_1fff8: macaddr@1fff8 {
|
|
||||||
reg = <0x1fff8 0x6>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&pcie {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&pcie1 {
|
|
||||||
wlan_5g: wifi@0,0 {
|
|
||||||
reg = <0x0 0 0 0 0>;
|
|
||||||
compatible = "mediatek,mt76";
|
|
||||||
|
|
||||||
mediatek,mtd-eeprom = <&factory 0x0>;
|
|
||||||
/* MAC-Address set in userspace */
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&gmac0 {
|
|
||||||
nvmem-cells = <&macaddr_mrd_1fff8>;
|
|
||||||
nvmem-cell-names = "mac-address";
|
|
||||||
};
|
|
||||||
|
|
||||||
&switch0 {
|
|
||||||
ports {
|
|
||||||
port@4 {
|
|
||||||
status = "okay";
|
|
||||||
label = "lan";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&state_default {
|
|
||||||
gpio {
|
|
||||||
groups = "uart3";
|
|
||||||
function = "gpio";
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,367 +0,0 @@
|
|||||||
{
|
|
||||||
system = {
|
|
||||||
crossSystem = {
|
|
||||||
config = "mipsel-unknown-linux-musl";
|
|
||||||
gcc = {
|
|
||||||
abi = "32";
|
|
||||||
arch = "mips32"; # mips32r2?
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
description = ''
|
|
||||||
Zyxel NWA50AX
|
|
||||||
********************
|
|
||||||
|
|
||||||
Zyxel NWA50AX is quite close to the GL-MT300N-v2 "Mango" device, but it is based on the MT7621
|
|
||||||
chipset instead of the MT7628.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
============
|
|
||||||
|
|
||||||
This device is pretty, but, due to its A/B capabilities, can be a bit hard
|
|
||||||
to use completely.
|
|
||||||
|
|
||||||
The stock vendor firmware is a downstream fork of U-Boot: <https://github.com/RaitoBezarius/uboot-nwa50ax>
|
|
||||||
with restricted boot commands. Fortunately, OpenWrt folks figured out trivial command injections,
|
|
||||||
so you can use most of the OpenWrt commands without trouble by just command injecting
|
|
||||||
atns, atna or atnf, e.g. atns "; $real_command".
|
|
||||||
|
|
||||||
From factory web UI, you can upload the result of the zyxel-nwa-fit output.
|
|
||||||
From another operating system, you need to `dumpimage -T flat_dt -p 0 $zyxel-nwa-fit -o firmware.bin`,
|
|
||||||
`flash_erase $(mtd partition of the target partition firmware or zy_firmware) 0 0`, then you complete by
|
|
||||||
`nandwrite -p $(mtd partition of the target partition firmware or zy_firmware) firmware.bin`.
|
|
||||||
|
|
||||||
How to put the firmware.bin on the machine is left to you as an exercise, e.g. SSH, TFTP, whatever.
|
|
||||||
|
|
||||||
From serial, you have two choices:
|
|
||||||
|
|
||||||
- Flash this system via U-Boot:
|
|
||||||
same reasoning as from an existing Linux system, two choices:
|
|
||||||
- ymodem the binary, perform the write manually, you can inspire yourself
|
|
||||||
from the `script` contained in the vendor firmware, those are just a FIT containing a script.
|
|
||||||
- prepare a FIT containing a script executing your commands, tftpboot this.
|
|
||||||
|
|
||||||
- boot from an existing Liminix system, e.g. TFTPBOOT image.
|
|
||||||
- boot from an OpenWrt system, i.e. follow OpenWrt steps.
|
|
||||||
|
|
||||||
Once you are in a Linux system, understand that this device has A/B boot.
|
|
||||||
|
|
||||||
OpenWrt provides you with `zyxel-bootconfig` to set/unset the image status and choice.
|
|
||||||
|
|
||||||
The kernel is booted with `bootImage=<number>` which tells you which slot are you on.
|
|
||||||
|
|
||||||
You should find yourself with 10ish MTD partitions, the most interesting ones are two:
|
|
||||||
|
|
||||||
- firmware: 40MB
|
|
||||||
- firmware_1: 40MB
|
|
||||||
|
|
||||||
In the current setup, they are split further into kernel (8MB) and ubi (32MB).
|
|
||||||
|
|
||||||
Once you are done with first installation, note that if you want to use the A/B feature,
|
|
||||||
you need to write a _secondary_ image on the slot B. There is no proper flashing code
|
|
||||||
that will set the being-updated slot to `new` and boot on it to verify if it's working.
|
|
||||||
This is a WIP.
|
|
||||||
|
|
||||||
Upgrading your system can be achieved via:
|
|
||||||
|
|
||||||
- `liminix-rebuild` for the userspace.
|
|
||||||
- `flash_erase` + `nandwrite` for the kernelspace to the other slot than the one you are booted on,
|
|
||||||
note that you can just nandwrite the mtd partition corresponding to the *kernel* and not the whole firmware.
|
|
||||||
|
|
||||||
If you soft-bricked your AP, i.e. you cannot boot anything in U-Boot, no worries, just plug the serial console,
|
|
||||||
prepare a TFTP server (via `tufted` for example), download vendor firmware, set up `atns`, `atnf`, etc. and run `atnz`.
|
|
||||||
|
|
||||||
This will reflash everything back to normal via TFTP.
|
|
||||||
|
|
||||||
If you hard-bricked your AP, i.e. U-Boot is telling you to transfer a valid bootloader via ymodem, just extract
|
|
||||||
a U-Boot from the vendor OS, send it via ymodem and use the previous operations to perform a full flash this time
|
|
||||||
of all partitions.
|
|
||||||
|
|
||||||
Note that if you erased your MRD partition, you lost your serial and MAC address. There's no way to recover the original one
|
|
||||||
except by reading the physical label on your… device!
|
|
||||||
|
|
||||||
If you super-hard-bricked your AP, i.e. no output on serial console, congratulations, you reached one of the rare state
|
|
||||||
of this device. You need an external NAND flasher to repair it and write the first stage from Mediatek to continue the previous
|
|
||||||
recovery operations.
|
|
||||||
|
|
||||||
Development TODO list:
|
|
||||||
|
|
||||||
- Better support for upgrade automation w.r.t. to A/B, e.g. automagic scripts.
|
|
||||||
- Mount the logs partition, mount / as overlayfs of firmware ? rootfs and rootfs_data for extended data.
|
|
||||||
- Jitter-based entropy injection? Device can be slow to initialize its CRNG and hostapd will reject few clients at the start because of that.
|
|
||||||
- Defaults for hostapd based on MT7915 capabilities? See the example for one possible list.
|
|
||||||
- Remove primary/secondary hack and put it in preinit.
|
|
||||||
- Offer ways to reflash the *bootloader* itself to support direct boot via UBI and kernel upgrades via filesystem rewrite.
|
|
||||||
|
|
||||||
Vendor web page: https://www.zyxel.com/fr/fr/products/wireless/ax1800-wifi-6-dual-radio-nebulaflex-access-point-nwa50ax
|
|
||||||
|
|
||||||
OpenWrt web page: https://openwrt.org/inbox/toh/zyxel/nwa50ax
|
|
||||||
OpenWrt tech data: https://openwrt.org/toh/hwdata/zyxel/zyxel_nwa50ax
|
|
||||||
|
|
||||||
'';
|
|
||||||
|
|
||||||
module = { pkgs, config, lib, lim, ...}:
|
|
||||||
let
|
|
||||||
inherit (pkgs.liminix.networking) interface;
|
|
||||||
inherit (pkgs.liminix.services) oneshot;
|
|
||||||
inherit (pkgs.pseudofile) dir symlink;
|
|
||||||
inherit (pkgs) openwrt;
|
|
||||||
|
|
||||||
mac80211 = pkgs.mac80211.override {
|
|
||||||
drivers = [ "mt7915e" ];
|
|
||||||
klibBuild = config.system.outputs.kernel.modulesupport;
|
|
||||||
};
|
|
||||||
# v204520220929
|
|
||||||
wlan_firmware = pkgs.fetchurl {
|
|
||||||
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_wa.bin";
|
|
||||||
hash = "sha256-wooyefzb0i8640+lwq3vNhcBXRFCtGuo+jiL7afZaKA=";
|
|
||||||
};
|
|
||||||
wlan_firmware' = pkgs.fetchurl {
|
|
||||||
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_wm.bin";
|
|
||||||
hash = "sha256-k62nQewRuKjBLd5R3RxU4F74YKnQx5zr6gqMMImqVQw=";
|
|
||||||
};
|
|
||||||
wlan_firmware'' = pkgs.fetchurl {
|
|
||||||
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_rom_patch.bin";
|
|
||||||
hash = "sha256-ifriAjWzFACrxVWCANZpUaEZgB/0pdbhnTVQytx6ddg=";
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
imports = [
|
|
||||||
# We include it to ensure the bridge functionality
|
|
||||||
# is available on the target kernel.
|
|
||||||
../../modules/bridge
|
|
||||||
../../modules/arch/mipsel.nix
|
|
||||||
../../modules/outputs/tftpboot.nix
|
|
||||||
../../modules/outputs/zyxel-nwa-fit.nix
|
|
||||||
../../modules/zyxel-dual-image
|
|
||||||
];
|
|
||||||
|
|
||||||
filesystem = dir {
|
|
||||||
lib = dir {
|
|
||||||
firmware = dir {
|
|
||||||
mediatek = dir {
|
|
||||||
"mt7915_wa.bin" = symlink wlan_firmware;
|
|
||||||
"mt7915_wm.bin" = symlink wlan_firmware';
|
|
||||||
"mt7915_rom_patch.bin" = symlink wlan_firmware'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
rootfsType = "ubifs";
|
|
||||||
hardware = {
|
|
||||||
# Taken from OpenWRT
|
|
||||||
# root@OpenWrt:/# ubinfo /dev/ubi0
|
|
||||||
# ubi0
|
|
||||||
# Volumes count: 2
|
|
||||||
# Logical eraseblock size: 126976 bytes, 124.0 KiB
|
|
||||||
# Total amount of logical eraseblocks: 256 (32505856 bytes, 31.0 MiB)
|
|
||||||
# Amount of available logical eraseblocks: 0 (0 bytes)
|
|
||||||
# Maximum count of volumes 128
|
|
||||||
# Count of bad physical eraseblocks: 0
|
|
||||||
# Count of reserved physical eraseblocks: 19
|
|
||||||
# Current maximum erase counter value: 2
|
|
||||||
# Minimum input/output unit size: 2048 bytes
|
|
||||||
# Character device major/minor: 250:0
|
|
||||||
# Present volumes: 0, 1
|
|
||||||
ubi = {
|
|
||||||
minIOSize = "2048";
|
|
||||||
logicalEraseBlockSize = "126976";
|
|
||||||
physicalEraseBlockSize = "128KiB";
|
|
||||||
maxLEBcount = "256";
|
|
||||||
};
|
|
||||||
|
|
||||||
# This is a FIT containing a kernel padded and
|
|
||||||
# a UBI volume rootfs.
|
|
||||||
defaultOutput = "zyxel-nwa-fit";
|
|
||||||
|
|
||||||
loadAddress = lim.parseInt "0x80001000";
|
|
||||||
entryPoint = lim.parseInt "0x80001000";
|
|
||||||
# Aligned on 2kb.
|
|
||||||
alignment = 2048;
|
|
||||||
|
|
||||||
rootDevice = "ubi:rootfs";
|
|
||||||
|
|
||||||
dts = {
|
|
||||||
# Actually, this is not what we want.
|
|
||||||
# This DTS is insufficient.
|
|
||||||
src = ./mt7621_zyxel_nwa50ax.dtsi;
|
|
||||||
includes = [
|
|
||||||
# Here's one weird trick to make `ubi` detection
|
|
||||||
# out of the box.
|
|
||||||
# We will write ubi on /dev/firmware_a:rootfs location
|
|
||||||
# and same for /dev/firmware_b:rootfs.
|
|
||||||
# How do we distinguish both?
|
|
||||||
# We can just use the DTS to point ubi at A or B.
|
|
||||||
# This, unfortunately, means that we have "two images".
|
|
||||||
# But they are really just 1 image with 2 different DTS.
|
|
||||||
# TODO: improve this hack in preinit?
|
|
||||||
(if config.boot.imageType == "primary" then "${./a_image}" else "${./b_image}")
|
|
||||||
"${openwrt.src}/target/linux/ramips/dts"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
networkInterfaces =
|
|
||||||
let
|
|
||||||
inherit (config.system.service.network) link;
|
|
||||||
in {
|
|
||||||
eth = link.build { ifname = "eth0"; };
|
|
||||||
lan = link.build { ifname = "lan"; };
|
|
||||||
wlan0 = link.build {
|
|
||||||
ifname = "wlan0";
|
|
||||||
dependencies = [ mac80211 ];
|
|
||||||
};
|
|
||||||
wlan1 = link.build {
|
|
||||||
ifname = "wlan1";
|
|
||||||
dependencies = [ mac80211 ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
boot = {
|
|
||||||
# Critical because NWA50AX will extend your cmdline with the image number booted.
|
|
||||||
# and some bootloader version.
|
|
||||||
# You don't want to find yourself being overridden.
|
|
||||||
commandLineDtbNode = "bootargs-override";
|
|
||||||
|
|
||||||
imageFormat = "fit";
|
|
||||||
tftp = {
|
|
||||||
# 5MB is nice.
|
|
||||||
freeSpaceBytes = 5 * 1024 * 1024;
|
|
||||||
loadAddress = lim.parseInt "0x2000000";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Dual image management service in userspace.
|
|
||||||
services.zyxel-dual-image = config.boot.zyxel-dual-image.build {
|
|
||||||
ensureActiveImage = "primary";
|
|
||||||
# TODO: use mtd names rather…
|
|
||||||
# primary and secondary are always /dev/mtd3 by virtue of the
|
|
||||||
# dtb being not too wrong…
|
|
||||||
# TODO: remove this hack.
|
|
||||||
primaryMtdPartition = "/dev/mtd3";
|
|
||||||
secondaryMtdPartition = "/dev/mtd3";
|
|
||||||
bootConfigurationMtdPartition = "/dev/mtd12";
|
|
||||||
};
|
|
||||||
|
|
||||||
# DEVICE_VENDOR := ZyXEL
|
|
||||||
# KERNEL_SIZE := 8192k
|
|
||||||
# DEVICE_PACKAGES := kmod-mt7915-firmware zyxel-bootconfig
|
|
||||||
# KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb
|
|
||||||
# IMAGES += factory.bin ramboot-factory.bin
|
|
||||||
# IMAGE/factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | zyxel-nwa-fit
|
|
||||||
# IMAGE/ramboot-factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi
|
|
||||||
|
|
||||||
kernel = {
|
|
||||||
src = pkgs.fetchurl {
|
|
||||||
name = "linux.tar.gz";
|
|
||||||
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.gz";
|
|
||||||
hash = "sha256-PkdzUKZ0IpBiWe/RS70J76JKnBFzRblWcKlaIFNxnHQ=";
|
|
||||||
};
|
|
||||||
extraPatchPhase = ''
|
|
||||||
${openwrt.applyPatches.ramips}
|
|
||||||
|
|
||||||
'';
|
|
||||||
config = {
|
|
||||||
|
|
||||||
RALINK = "y";
|
|
||||||
PCI = "y";
|
|
||||||
PHY_MT7621_PCI = "y";
|
|
||||||
PCIE_MT7621 = "y";
|
|
||||||
SOC_MT7621 = "y";
|
|
||||||
CLK_MT7621 = "y";
|
|
||||||
CLOCKSOURCE_WATCHDOG = "y";
|
|
||||||
|
|
||||||
SERIAL_8250_CONSOLE = "y";
|
|
||||||
SERIAL_8250 = "y";
|
|
||||||
SERIAL_CORE_CONSOLE = "y";
|
|
||||||
SERIAL_OF_PLATFORM = "y";
|
|
||||||
SERIAL_8250_NR_UARTS = "3";
|
|
||||||
SERIAL_8250_RUNTIME_UARTS = "3";
|
|
||||||
SERIAL_MCTRL_GPIO = "y";
|
|
||||||
|
|
||||||
CONSOLE_LOGLEVEL_DEFAULT = "8";
|
|
||||||
CONSOLE_LOGLEVEL_QUIET = "4";
|
|
||||||
|
|
||||||
# MTD_UBI_BEB_LIMIT = "20";
|
|
||||||
# MTD_UBI_WL_THRESHOLD = "4096";
|
|
||||||
|
|
||||||
MTD = "y";
|
|
||||||
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev
|
|
||||||
MTD_RAW_NAND = "y";
|
|
||||||
MTD_NAND_MT7621 = "y";
|
|
||||||
MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table
|
|
||||||
MTD_NAND_ECC_SW_HAMMING= "y";
|
|
||||||
MTD_SPI_NAND= "y";
|
|
||||||
MTD_OF_PARTS = "y";
|
|
||||||
MTD_NAND_CORE= "y";
|
|
||||||
MTD_SPLIT_FIRMWARE= "y";
|
|
||||||
MTD_SPLIT_FIT_FW= "y";
|
|
||||||
|
|
||||||
PINCTRL = "y";
|
|
||||||
PINCTRL_MT7621 = "y";
|
|
||||||
|
|
||||||
I2C = "y";
|
|
||||||
I2C_MT7621 = "y";
|
|
||||||
|
|
||||||
SPI = "y";
|
|
||||||
MTD_SPI_NOR = "y";
|
|
||||||
SPI_MT7621 = "y";
|
|
||||||
SPI_MASTER = "y";
|
|
||||||
SPI_MEM = "y";
|
|
||||||
|
|
||||||
REGULATOR = "y";
|
|
||||||
REGULATOR_FIXED_VOLTAGE = "y";
|
|
||||||
RESET_CONTROLLER = "y";
|
|
||||||
POWER_RESET = "y";
|
|
||||||
POWER_RESET_GPIO = "y";
|
|
||||||
POWER_SUPPLY = "y";
|
|
||||||
LED_TRIGGER_PHY = "y";
|
|
||||||
|
|
||||||
PCI_DISABLE_COMMON_QUIRKS = "y";
|
|
||||||
PCI_DOMAINS = "y";
|
|
||||||
PCI_DOMAINS_GENERIC = "y";
|
|
||||||
PCI_DRIVERS_GENERIC = "y";
|
|
||||||
PCS_MTK_LYNXI = "y";
|
|
||||||
|
|
||||||
SOC_BUS = "y";
|
|
||||||
|
|
||||||
NET = "y";
|
|
||||||
ETHERNET = "y";
|
|
||||||
WLAN = "y";
|
|
||||||
|
|
||||||
PHYLIB = "y";
|
|
||||||
AT803X_PHY = "y";
|
|
||||||
FIXED_PHY = "y";
|
|
||||||
GENERIC_PHY = "y";
|
|
||||||
NET_DSA = "y";
|
|
||||||
NET_DSA_MT7530 = "y";
|
|
||||||
NET_DSA_MT7530_MDIO = "y";
|
|
||||||
NET_DSA_TAG_MTK = "y";
|
|
||||||
NET_MEDIATEK_SOC = "y";
|
|
||||||
NET_SWITCHDEV = "y";
|
|
||||||
NET_VENDOR_MEDIATEK = "y";
|
|
||||||
|
|
||||||
SWPHY = "y";
|
|
||||||
|
|
||||||
GPIOLIB = "y";
|
|
||||||
GPIO_MT7621 = "y";
|
|
||||||
OF_GPIO = "y";
|
|
||||||
|
|
||||||
EARLY_PRINTK = "y";
|
|
||||||
|
|
||||||
NEW_LEDS = "y";
|
|
||||||
LEDS_TRIGGERS = "y";
|
|
||||||
LEDS_CLASS = "y"; # required by rt2x00lib
|
|
||||||
LEDS_CLASS_MULTICOLOR = "y";
|
|
||||||
LEDS_BRIGHTNESS_HW_CHANGED = "y";
|
|
||||||
|
|
||||||
PRINTK_TIME = "y";
|
|
||||||
} // lib.optionalAttrs (config.system.service ? vlan) {
|
|
||||||
SWCONFIG = "y";
|
|
||||||
} // lib.optionalAttrs (config.system.service ? watchdog) {
|
|
||||||
RALINK_WDT = "y"; # watchdog
|
|
||||||
MT7621_WDT = "y"; # or it might be this one
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
#include "mt7621_zyxel_nwa-ax-for-ab.dtsi"
|
|
||||||
|
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
|
||||||
#include <dt-bindings/input/input.h>
|
|
||||||
|
|
||||||
/ {
|
|
||||||
compatible = "zyxel,nwa50ax", "mediatek,mt7621-soc";
|
|
||||||
model = "ZyXEL NWA50AX";
|
|
||||||
|
|
||||||
aliases {
|
|
||||||
led-boot = &led_system_green;
|
|
||||||
led-failsafe = &led_system_red;
|
|
||||||
led-running = &led_system_green;
|
|
||||||
led-upgrade = &led_system_red;
|
|
||||||
};
|
|
||||||
|
|
||||||
leds {
|
|
||||||
compatible = "gpio-leds";
|
|
||||||
|
|
||||||
led_system_red: system_red {
|
|
||||||
label = "red:system";
|
|
||||||
gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
|
|
||||||
};
|
|
||||||
|
|
||||||
led_system_green: system_green {
|
|
||||||
label = "green:system";
|
|
||||||
gpios = <&gpio 7 GPIO_ACTIVE_HIGH>;
|
|
||||||
};
|
|
||||||
|
|
||||||
system_blue {
|
|
||||||
label = "blue:system";
|
|
||||||
gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
keys {
|
|
||||||
compatible = "gpio-keys";
|
|
||||||
|
|
||||||
reset {
|
|
||||||
label = "reset";
|
|
||||||
gpios = <&gpio 30 GPIO_ACTIVE_LOW>;
|
|
||||||
linux,code = <KEY_RESTART>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
ðernet {
|
|
||||||
pinctrl-0 = <&mdio_pins>, <&rgmii1_pins>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&state_default {
|
|
||||||
gpio {
|
|
||||||
groups = "uart3", "rgmii2";
|
|
||||||
function = "gpio";
|
|
||||||
};
|
|
||||||
};
|
|
@ -233,11 +233,9 @@ in {
|
|||||||
type = "filter";
|
type = "filter";
|
||||||
family = "ip";
|
family = "ip";
|
||||||
rules = [
|
rules = [
|
||||||
# This is where you put permitted incoming connections. If
|
# this is where you put permitted incoming
|
||||||
# you're using NAT and want to forward a port from outside to
|
# connections. Practically there's not a lot of use for this
|
||||||
# devices on the LAN, then you need a DNAT rule in nat-rx chain
|
# chain unless you have routable ipv4 addresses
|
||||||
# *and* to accept the packet in this chain (specifying the
|
|
||||||
# internal (RFC1918) address).
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
secrets = import ./extneder-secrets.nix;
|
secrets = import ./extneder-secrets.nix;
|
||||||
|
inherit (pkgs.liminix.services) oneshot longrun bundle target;
|
||||||
|
inherit (pkgs.pseudofile) dir symlink;
|
||||||
|
inherit (pkgs) dropbear ifwait serviceFns;
|
||||||
|
svc = config.system.service;
|
||||||
in rec {
|
in rec {
|
||||||
boot = {
|
boot = {
|
||||||
tftp = {
|
tftp = {
|
||||||
@ -20,8 +24,12 @@ in rec {
|
|||||||
};
|
};
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
../modules/profiles/wap.nix
|
../modules/wlan.nix
|
||||||
../modules/vlan
|
../modules/vlan
|
||||||
|
../modules/network
|
||||||
|
../modules/hostapd
|
||||||
|
../modules/bridge
|
||||||
|
../modules/ssh
|
||||||
];
|
];
|
||||||
|
|
||||||
hostname = "extneder";
|
hostname = "extneder";
|
||||||
@ -61,24 +69,68 @@ in rec {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
profile.wap = {
|
services.hostap = svc.hostapd.build {
|
||||||
interfaces = with config.hardware.networkInterfaces; [
|
interface = config.hardware.networkInterfaces.wlan;
|
||||||
|
params = {
|
||||||
|
country_code = "GB";
|
||||||
|
hw_mode = "g";
|
||||||
|
wmm_enabled = 1;
|
||||||
|
ieee80211n = 1;
|
||||||
|
inherit (secrets) ssid channel wpa_passphrase;
|
||||||
|
auth_algs = 1; # 1=wpa2, 2=wep, 3=both
|
||||||
|
wpa = 2; # 1=wpa, 2=wpa2, 3=both
|
||||||
|
wpa_key_mgmt = "WPA-PSK";
|
||||||
|
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
|
||||||
|
rsn_pairwise = "CCMP"; # auth for wpa2
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.int = svc.bridge.primary.build {
|
||||||
|
ifname = "int";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.dhcpc = svc.network.dhcp.client.build {
|
||||||
|
interface = services.int;
|
||||||
|
dependencies = [ config.services.hostname ];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.bridge = svc.bridge.members.build {
|
||||||
|
primary = services.int;
|
||||||
|
members = with config.hardware.networkInterfaces; [
|
||||||
lan
|
lan
|
||||||
wlan
|
wlan
|
||||||
];
|
];
|
||||||
|
};
|
||||||
|
|
||||||
wireless = {
|
services.sshd = svc.ssh.build {};
|
||||||
networks.${secrets.ssid} = {
|
|
||||||
interface = config.hardware.networkInterfaces.wlan;
|
services.resolvconf = oneshot rec {
|
||||||
inherit (secrets) channel wpa_passphrase;
|
dependencies = [ services.dhcpc ];
|
||||||
country_code = "GB";
|
name = "resolvconf";
|
||||||
hw_mode = "g";
|
# CHECK: https://udhcp.busybox.net/README.udhcpc says
|
||||||
wmm_enabled = 1;
|
# 'A list of DNS server' but doesn't say what separates the
|
||||||
ieee80211n = 1;
|
# list members. Assuming it's a space or other IFS character
|
||||||
};
|
up = ''
|
||||||
|
. ${serviceFns}
|
||||||
|
( in_outputs ${name}
|
||||||
|
for i in $(output ${services.dhcpc} dns); do
|
||||||
|
echo "nameserver $i" > resolv.conf
|
||||||
|
done
|
||||||
|
)
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
filesystem = dir {
|
||||||
|
etc = dir {
|
||||||
|
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.defaultroute4 = svc.network.route.build {
|
||||||
|
via = "$(output ${services.dhcpc} router)";
|
||||||
|
target = "default";
|
||||||
|
dependencies = [services.dhcpc];
|
||||||
|
};
|
||||||
|
|
||||||
users.root.passwd = lib.mkForce secrets.root.passwd;
|
users.root.passwd = lib.mkForce secrets.root.passwd;
|
||||||
defaultProfile.packages = with pkgs; [nftables strace tcpdump swconfig];
|
defaultProfile.packages = with pkgs; [nftables strace tcpdump swconfig];
|
||||||
}
|
}
|
||||||
|
@ -1,120 +0,0 @@
|
|||||||
{ config, pkgs, ... } :
|
|
||||||
let
|
|
||||||
inherit (pkgs.liminix.services) oneshot longrun bundle target;
|
|
||||||
inherit (pkgs) writeText;
|
|
||||||
svc = config.system.service;
|
|
||||||
secrets-1 = {
|
|
||||||
ssid = "Zyxel 2G (N)";
|
|
||||||
wpa_passphrase = "diamond dogs";
|
|
||||||
};
|
|
||||||
secrets-2 = {
|
|
||||||
ssid = "Zyxel 5G (AX)";
|
|
||||||
wpa_passphrase = "diamond dogs";
|
|
||||||
};
|
|
||||||
baseParams = {
|
|
||||||
country_code = "FR";
|
|
||||||
hw_mode = "g";
|
|
||||||
channel = 6;
|
|
||||||
wmm_enabled = 1;
|
|
||||||
ieee80211n = 1;
|
|
||||||
ht_capab = "[LDPC][GF][HT40-][HT40+][SHORT-GI-40][MAX-AMSDU-7935][TX-STBC]";
|
|
||||||
auth_algs = 1;
|
|
||||||
wpa = 2;
|
|
||||||
wpa_key_mgmt = "WPA-PSK";
|
|
||||||
wpa_pairwise = "TKIP CCMP";
|
|
||||||
rsn_pairwise = "CCMP";
|
|
||||||
};
|
|
||||||
|
|
||||||
modernParams = {
|
|
||||||
hw_mode = "a";
|
|
||||||
he_su_beamformer = 1;
|
|
||||||
he_su_beamformee = 1;
|
|
||||||
he_mu_beamformer = 1;
|
|
||||||
preamble = 1;
|
|
||||||
# Allow radar detection.
|
|
||||||
ieee80211d = 1;
|
|
||||||
ieee80211h = 1;
|
|
||||||
ieee80211ac = 1;
|
|
||||||
ieee80211ax = 1;
|
|
||||||
vht_capab = "[MAX-MPDU-7991][SU-BEAMFORMEE][SU-BEAMFORMER][RXLDPC][SHORT-GI-80][MAX-A-MPDU-LEN-EXP3][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN][TX-STBC-2BY1][RX-STBC-1][MU-BEAMFORMER]";
|
|
||||||
vht_oper_chwidth = 1;
|
|
||||||
he_oper_chwidth = 1;
|
|
||||||
channel = 36;
|
|
||||||
vht_oper_centr_freq_seg0_idx = 42;
|
|
||||||
he_oper_centr_freq_seg0_idx = 42;
|
|
||||||
require_vht = 1;
|
|
||||||
};
|
|
||||||
mkWifiSta = params: interface: secrets: svc.hostapd.build {
|
|
||||||
inherit interface;
|
|
||||||
params = params // {
|
|
||||||
inherit (secrets) ssid wpa_passphrase;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in rec {
|
|
||||||
imports = [
|
|
||||||
../modules/wlan.nix
|
|
||||||
../modules/network
|
|
||||||
../modules/hostapd
|
|
||||||
../modules/ssh
|
|
||||||
../modules/ntp
|
|
||||||
../modules/vlan
|
|
||||||
../modules/bridge
|
|
||||||
];
|
|
||||||
|
|
||||||
hostname = "zyxel";
|
|
||||||
|
|
||||||
users.root = {
|
|
||||||
# EDIT: choose a root password and then use
|
|
||||||
# "mkpasswd -m sha512crypt" to determine the hash.
|
|
||||||
# It should start wirh $6$.
|
|
||||||
passwd = "$y$j9T$f8GhLiqYmr3lc58eKhgyD0$z7P/7S9u.kq/cANZExxhS98bze/6i7aBxU6tbl7RMi.";
|
|
||||||
openssh.authorizedKeys.keys = [
|
|
||||||
# EDIT: you can add your ssh pubkey here
|
|
||||||
# "ssh-rsa AAAAB3NzaC1....H6hKd user@example.com";
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.int = svc.bridge.primary.build {
|
|
||||||
ifname = "int";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.bridge = svc.bridge.members.build {
|
|
||||||
primary = services.int;
|
|
||||||
members = with config.hardware.networkInterfaces; [
|
|
||||||
lan
|
|
||||||
wlan0
|
|
||||||
wlan1
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.dhcpv4 =
|
|
||||||
let iface = services.int;
|
|
||||||
in svc.network.dhcp.client.build { interface = iface; };
|
|
||||||
|
|
||||||
services.defaultroute4 = svc.network.route.build {
|
|
||||||
via = "$(output ${services.dhcpv4} address)";
|
|
||||||
target = "default";
|
|
||||||
dependencies = [ services.dhcpv4 ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.packet_forwarding = svc.network.forward.build { };
|
|
||||||
services.sshd = svc.ssh.build {
|
|
||||||
allowRoot = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.ntp = config.system.service.ntp.build {
|
|
||||||
pools = { "pool.ntp.org" = ["iburst"] ; };
|
|
||||||
};
|
|
||||||
|
|
||||||
boot.tftp = {
|
|
||||||
serverip = "192.0.2.10";
|
|
||||||
ipaddr = "192.0.2.12";
|
|
||||||
};
|
|
||||||
|
|
||||||
# wlan0 is the 2.4GHz interface.
|
|
||||||
services.hostap-1 = mkWifiSta baseParams config.hardware.networkInterfaces.wlan0 secrets-1;
|
|
||||||
# wlan1 is the 5GHz interface, e.g. AX capable.
|
|
||||||
services.hostap-2 = mkWifiSta (baseParams // modernParams) config.hardware.networkInterfaces.wlan1 secrets-2;
|
|
||||||
|
|
||||||
defaultProfile.packages = with pkgs; [ zyxel-bootconfig iw min-collect-garbage mtdutils ];
|
|
||||||
}
|
|
@ -26,6 +26,7 @@ let
|
|||||||
wmm_enabled = 1;
|
wmm_enabled = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
in rec {
|
in rec {
|
||||||
boot = {
|
boot = {
|
||||||
tftp = {
|
tftp = {
|
||||||
@ -87,7 +88,8 @@ in rec {
|
|||||||
services.bridge = svc.bridge.members.build {
|
services.bridge = svc.bridge.members.build {
|
||||||
primary = services.int;
|
primary = services.int;
|
||||||
members = with config.hardware.networkInterfaces;
|
members = with config.hardware.networkInterfaces;
|
||||||
[ wlan
|
[
|
||||||
|
wlan
|
||||||
wlan5
|
wlan5
|
||||||
lan0
|
lan0
|
||||||
lan1
|
lan1
|
||||||
@ -200,15 +202,9 @@ in rec {
|
|||||||
nftables
|
nftables
|
||||||
strace
|
strace
|
||||||
tcpdump
|
tcpdump
|
||||||
s6
|
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.busybox = {
|
programs.busybox.applets = [
|
||||||
applets = [
|
"fdisk" "sfdisk"
|
||||||
"fdisk" "sfdisk"
|
];
|
||||||
];
|
|
||||||
options = {
|
|
||||||
FEATURE_FANCY_TAIL = "y";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
./hostname.nix
|
./hostname.nix
|
||||||
./outputs/initramfs.nix
|
./outputs/initramfs.nix
|
||||||
./outputs/jffs2.nix
|
./outputs/jffs2.nix
|
||||||
./kernel
|
./kernel.nix
|
||||||
./outputs/kexecboot.nix
|
./outputs/kexecboot.nix
|
||||||
./mount
|
./mount
|
||||||
./network
|
./network
|
||||||
@ -31,7 +31,6 @@
|
|||||||
./ssh
|
./ssh
|
||||||
./outputs/tftpboot.nix
|
./outputs/tftpboot.nix
|
||||||
./outputs/ubifs.nix
|
./outputs/ubifs.nix
|
||||||
./ubinize.nix
|
|
||||||
./users.nix
|
./users.nix
|
||||||
./vlan
|
./vlan
|
||||||
./watchdog
|
./watchdog
|
||||||
|
@ -13,7 +13,7 @@ let
|
|||||||
|
|
||||||
in {
|
in {
|
||||||
imports = [
|
imports = [
|
||||||
./kernel # kernel is a separate module for doc purposes
|
./kernel.nix # kernel is a separate module for doc purposes
|
||||||
];
|
];
|
||||||
options = {
|
options = {
|
||||||
defaultProfile = {
|
defaultProfile = {
|
||||||
@ -58,15 +58,6 @@ in {
|
|||||||
default = [];
|
default = [];
|
||||||
description = "Kernel command line";
|
description = "Kernel command line";
|
||||||
};
|
};
|
||||||
commandLineDtbNode = mkOption {
|
|
||||||
type = types.enum [ "bootargs" "bootargs-override" ];
|
|
||||||
default = "bootargs";
|
|
||||||
description = "Kernel command line's devicetree node";
|
|
||||||
};
|
|
||||||
imageType = mkOption {
|
|
||||||
type = types.enum [ "primary" "secondary" ];
|
|
||||||
default = "primary";
|
|
||||||
};
|
|
||||||
imageFormat = mkOption {
|
imageFormat = mkOption {
|
||||||
type = types.enum ["fit" "uimage"];
|
type = types.enum ["fit" "uimage"];
|
||||||
default = "uimage";
|
default = "uimage";
|
||||||
|
@ -32,21 +32,23 @@ let
|
|||||||
(a: symlink "${busybox}/bin/busybox");
|
(a: symlink "${busybox}/bin/busybox");
|
||||||
minimalApplets = [
|
minimalApplets = [
|
||||||
# this is probably less minimal than it could be
|
# this is probably less minimal than it could be
|
||||||
"arch" "ash" "base64" "basename" "bc" "brctl" "bunzip2" "bzcat" "bzip2"
|
"arch" "ash" "base64" "basename" "bc" "brctl" "bunzip2" "bzcat"
|
||||||
"cal" "cat" "chattr" "chgrp" "chmod" "chown" "chpst" "chroot" "clear" "cmp"
|
"bzip2" "cal" "cat" "chattr" "chgrp" "chmod" "chown" "chpst"
|
||||||
"comm" "cp" "cpio" "cut" "date" "dhcprelay" "dd" "df" "dirname" "dmesg"
|
"chroot" "clear" "cmp" "comm" "cp" "cpio" "cut" "date" "dd" "df"
|
||||||
"du" "echo" "egrep" "env" "expand" "expr" "false" "fdisk" "fgrep" "find"
|
"dirname" "dmesg" "du" "echo" "egrep" "env" "expand" "expr"
|
||||||
"free" "fuser" "grep" "gunzip" "gzip" "head" "hexdump" "hostname" "hwclock"
|
"false" "fdisk" "fgrep" "find" "free" "fuser" "grep" "gunzip"
|
||||||
"ifconfig" "ip" "ipaddr" "iplink" "ipneigh" "iproute" "iprule" "kill"
|
"gzip" "head" "hexdump" "hostname" "hwclock" "ifconfig" "ip"
|
||||||
"killall" "killall5" "less" "ln" "ls" "lsattr" "lsof" "md5sum" "mkdir"
|
"ipaddr" "iplink" "ipneigh" "iproute" "iprule" "kill" "killall"
|
||||||
"mknod" "mktemp" "mount" "mv" "nc" "netstat" "nohup" "od" "pgrep" "pidof"
|
"killall5" "less" "ln" "ls" "lsattr" "lsof" "md5sum" "mkdir"
|
||||||
"ping" "ping6" "pkill" "pmap" "printenv" "printf" "ps" "pwd" "readlink"
|
"mknod" "mktemp" "mount" "mv" "nc" "netstat" "nohup" "od" "pgrep"
|
||||||
"realpath" "reset" "rm" "rmdir" "route" "sed" "seq" "setsid" "sha1sum"
|
"pidof" "ping" "ping6" "pkill" "pmap" "printenv" "printf" "ps"
|
||||||
"sha256sum" "sha512sum" "sleep" "sort" "stat" "strings" "stty" "su" "sum"
|
"pwd" "readlink" "realpath" "reset" "rm" "rmdir" "route" "sed"
|
||||||
"swapoff" "swapon" "sync" "tail" "tee" "test" "time" "touch" "tr"
|
"seq" "setsid" "sha1sum" "sha256sum" "sha512sum" "sleep" "sort"
|
||||||
"traceroute" "traceroute6" "true" "truncate" "tty" "udhcpc" "umount"
|
"stat" "strings" "stty" "su" "sum" "swapoff" "swapon" "sync"
|
||||||
"uname" "unexpand" "uniq" "unlink" "unlzma" "unxz" "unzip" "uptime" "watch"
|
"tail" "tee" "test" "time" "touch" "tr" "traceroute" "traceroute6"
|
||||||
"wc" "whoami" "xargs" "xxd" "xz" "xzcat" "yes" "zcat"
|
"true" "truncate" "tty" "udhcpc" "umount" "uname"
|
||||||
|
"unexpand" "uniq" "unlink" "unlzma" "unxz" "unzip" "uptime"
|
||||||
|
"watch" "wc" "whoami" "xargs" "xxd" "xz" "xzcat" "yes" "zcat"
|
||||||
];
|
];
|
||||||
in {
|
in {
|
||||||
options = {
|
options = {
|
||||||
|
@ -1,32 +1,31 @@
|
|||||||
(local { : system } (require :anoia))
|
(local { : system } (require :anoia))
|
||||||
(local svc (require :anoia.svc))
|
(local svc (require :anoia.svc))
|
||||||
|
|
||||||
(fn deletions [old-addresses new-addresses]
|
(fn changes [old-addresses new-addresses]
|
||||||
(let [deleted {}]
|
(let [added {}
|
||||||
|
deleted {}]
|
||||||
|
(each [n address (pairs new-addresses)]
|
||||||
|
(if (not (. old-addresses n))
|
||||||
|
(table.insert added address)))
|
||||||
(each [n address (pairs old-addresses)]
|
(each [n address (pairs old-addresses)]
|
||||||
(let [now (. new-addresses n)]
|
(if (not (. new-addresses n))
|
||||||
(if (or (not now) (not (= now.len address.len)))
|
(table.insert deleted address)))
|
||||||
(table.insert deleted address))))
|
(values added deleted)))
|
||||||
deleted))
|
|
||||||
|
|
||||||
(fn update-prefixes [wan-device addresses new-addresses exec]
|
(fn update-prefixes [device prefixes new-prefixes]
|
||||||
(each [_ p (ipairs (deletions addresses new-addresses))]
|
(let [(added deleted) (changes prefixes new-prefixes)]
|
||||||
(exec
|
(each [_ p (ipairs added)]
|
||||||
(.. "ip address del " p.address "1/" p.len " dev " wan-device)))
|
(system
|
||||||
(each [_ p (pairs new-addresses)]
|
(.. "ip address add " p.address "1/" p.len " dev " device)))
|
||||||
(exec
|
(each [_ p (ipairs deleted)]
|
||||||
(.. "ip address change " p.address "1/" p.len
|
(system
|
||||||
" dev " wan-device
|
(.. "ip address del " p.address "1/" p.len " dev " device)))))
|
||||||
" valid_lft " p.valid
|
|
||||||
" preferred_lft " p.preferred
|
|
||||||
)))
|
|
||||||
new-addresses)
|
|
||||||
|
|
||||||
(fn run []
|
(fn run []
|
||||||
(let [[state-directory lan-device] arg
|
(let [[state-directory lan-device] arg
|
||||||
dir (svc.open state-directory)]
|
dir (svc.open state-directory)]
|
||||||
(accumulate [addresses []
|
(accumulate [addresses []
|
||||||
v (dir:events)]
|
v (dir:events)]
|
||||||
(update-prefixes lan-device addresses (v:output "prefix") system))))
|
(update-prefixes lan-device addresses (v:output "prefix")))))
|
||||||
|
|
||||||
{ : changes : run }
|
{ : changes : run }
|
||||||
|
@ -5,45 +5,23 @@
|
|||||||
|
|
||||||
(local a1
|
(local a1
|
||||||
{
|
{
|
||||||
"2001-ab-cd-ef" {
|
"2001-ab-cd-ef_hjgKHGhKJH" {
|
||||||
:address "2001:ab:cd:ef"
|
:address "2001:ab:cd:ef"
|
||||||
:len "64"
|
:len "64"
|
||||||
:preferred "3600"
|
:preferred "200"
|
||||||
:valid "7200"
|
:valid "200"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
(local a156
|
|
||||||
{
|
|
||||||
"2001-ab-cd-ef" {
|
|
||||||
:address "2001:ab:cd:ef"
|
|
||||||
:len "56"
|
|
||||||
:preferred "3600"
|
|
||||||
:valid "7200"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
(local a2
|
(local a2
|
||||||
{
|
{
|
||||||
"2001-0-1-2-3" {
|
"2001-0-1-2-3_aNteBnb" {
|
||||||
:address "2001:0:1:2:3"
|
:address "2001:0:1:2:3"
|
||||||
:len "64"
|
:len "64"
|
||||||
:preferred "3600"
|
:preferred "200"
|
||||||
:valid "7200"
|
:valid "200"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
(local a21
|
|
||||||
{
|
|
||||||
"2001-0-1-2-3" {
|
|
||||||
:address "2001:0:1:2:3"
|
|
||||||
:len "64"
|
|
||||||
:preferred "1800"
|
|
||||||
:valid "5400"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,85 +30,39 @@
|
|||||||
`(when (not ,assertion)
|
`(when (not ,assertion)
|
||||||
(assert false ,msg))))
|
(assert false ,msg))))
|
||||||
|
|
||||||
(macro expect= [actual expected]
|
|
||||||
`(let [ve# (view ,expected)
|
|
||||||
va# (view ,actual)]
|
|
||||||
(when (not (= ve# va#))
|
|
||||||
(assert false
|
|
||||||
(.. "\nexpected " ve# "\ngot " va#)
|
|
||||||
))))
|
|
||||||
|
|
||||||
(fn first-address []
|
(fn first-address []
|
||||||
(let [deleted
|
(let [(add del)
|
||||||
(subject.deletions
|
(subject.changes
|
||||||
{ }
|
{ }
|
||||||
a1
|
a1
|
||||||
)]
|
)]
|
||||||
(expect= deleted [])))
|
(expect (= (# del) 0))
|
||||||
|
(expect (= (# add) 1))
|
||||||
|
(let [[first] add]
|
||||||
|
(expect (= first.address "2001:ab:cd:ef")))))
|
||||||
|
|
||||||
(fn second-address []
|
(fn second-address []
|
||||||
(let [del
|
(let [(add del)
|
||||||
(subject.deletions
|
(subject.changes
|
||||||
a1
|
a1
|
||||||
(merge (dup a1) a2)
|
(merge (dup a1) a2)
|
||||||
)]
|
)]
|
||||||
(expect= del [])))
|
(expect (= (# del) 0))
|
||||||
|
(expect (= (# add) 1))
|
||||||
|
(let [[first] add] (expect (= first.address "2001:0:1:2:3")))))
|
||||||
|
|
||||||
(fn old-address-is-deleted []
|
(fn less-address []1
|
||||||
(let [del
|
(let [(add del)
|
||||||
(subject.deletions
|
(subject.changes
|
||||||
(merge (dup a1) a2)
|
(merge (dup a1) a2)
|
||||||
a1
|
a1
|
||||||
)]
|
)]
|
||||||
(expect= (. del 1) (. a2 "2001-0-1-2-3"))
|
(expect (= (# add) 0))
|
||||||
))
|
(expect (= (# del) 1))
|
||||||
|
|
||||||
(fn changed-lifetime-not-deleted []
|
(let [[first] del] (expect (= first.address "2001:0:1:2:3")))))
|
||||||
(let [del
|
|
||||||
(subject.deletions
|
|
||||||
(merge (dup a1) a2)
|
|
||||||
(merge (dup a1) a21)
|
|
||||||
)]
|
|
||||||
;; when an address lifetime changes, "ip address change"
|
|
||||||
;; will update that so it need not (should not) be deleted
|
|
||||||
(expect= del [])))
|
|
||||||
|
|
||||||
(fn changed-prefix-is-deleted []
|
|
||||||
(let [del
|
|
||||||
(subject.deletions a1 a156)]
|
|
||||||
;; when an address prefix changes, "ip address change"
|
|
||||||
;; ignores that cjhange, so we have to remove the
|
|
||||||
;; address before reinstating it
|
|
||||||
(expect= del [(. a1 "2001-ab-cd-ef")])))
|
|
||||||
|
|
||||||
(first-address)
|
(first-address)
|
||||||
(second-address)
|
(second-address)
|
||||||
(old-address-is-deleted)
|
(less-address)
|
||||||
(changed-lifetime-not-deleted)
|
|
||||||
(changed-prefix-is-deleted)
|
|
||||||
|
|
||||||
(let [cmds []]
|
|
||||||
(subject.update-addresses
|
|
||||||
"ppp0" a1 (merge (dup a1) a2)
|
|
||||||
(fn [a] (table.insert cmds a)))
|
|
||||||
(expect=
|
|
||||||
(doto cmds table.sort)
|
|
||||||
[
|
|
||||||
;; order of changes is unimportant
|
|
||||||
"ip address change 2001:0:1:2:3/64 dev ppp0 valid_lft 7200 preferred_lft 3600"
|
|
||||||
"ip address change 2001:ab:cd:ef/64 dev ppp0 valid_lft 7200 preferred_lft 3600"
|
|
||||||
]))
|
|
||||||
|
|
||||||
(let [cmds []]
|
|
||||||
(subject.update-addresses
|
|
||||||
"ppp0" (merge (dup a1) a2) a1
|
|
||||||
(fn [a] (table.insert cmds a)))
|
|
||||||
(expect=
|
|
||||||
cmds
|
|
||||||
[
|
|
||||||
;; deletes are executed before changes
|
|
||||||
"ip address del 2001:0:1:2:3/64 dev ppp0"
|
|
||||||
"ip address change 2001:ab:cd:ef/64 dev ppp0 valid_lft 7200 preferred_lft 3600"
|
|
||||||
]))
|
|
||||||
|
|
||||||
(print "OK")
|
|
||||||
|
@ -1,32 +1,35 @@
|
|||||||
(local { : system } (require :anoia))
|
(local { : system } (require :anoia))
|
||||||
(local svc (require :anoia.svc))
|
(local svc (require :anoia.svc))
|
||||||
|
|
||||||
(fn deletions [old-addresses new-addresses]
|
;; acquire-delegated-prefix has very similar code: we'd like to move
|
||||||
(let [deleted {}]
|
;; this to anoia.svc when we see what the general form would look like
|
||||||
(each [n address (pairs old-addresses)]
|
|
||||||
(let [now (. new-addresses n)]
|
|
||||||
(if (or (not now) (not (= now.len address.len)))
|
|
||||||
(table.insert deleted address))))
|
|
||||||
deleted))
|
|
||||||
|
|
||||||
(fn update-addresses [wan-device addresses new-addresses exec]
|
(fn changes [old-addresses new-addresses]
|
||||||
(each [_ p (ipairs (deletions addresses new-addresses))]
|
(let [added {}
|
||||||
(exec
|
deleted {}]
|
||||||
(.. "ip address del " p.address "/" p.len " dev " wan-device)))
|
(each [n address (pairs new-addresses)]
|
||||||
(each [_ p (pairs new-addresses)]
|
(if (not (. old-addresses n))
|
||||||
(exec
|
(table.insert added address)))
|
||||||
(.. "ip address change " p.address "/" p.len
|
(each [n address (pairs old-addresses)]
|
||||||
" dev " wan-device
|
(if (not (. new-addresses n))
|
||||||
" valid_lft " p.valid
|
(table.insert deleted address)))
|
||||||
" preferred_lft " p.preferred
|
(values added deleted)))
|
||||||
)))
|
|
||||||
new-addresses)
|
(fn update-addresses [wan-device addresses new-addresses]
|
||||||
|
(let [(added deleted) (changes addresses new-addresses)]
|
||||||
|
(each [_ p (ipairs added)]
|
||||||
|
(system
|
||||||
|
(.. "ip address add " p.address "/" p.len " dev " wan-device)))
|
||||||
|
(each [_ p (ipairs deleted)]
|
||||||
|
(system
|
||||||
|
(.. "ip address del " p.address "/" p.len " dev " wan-device)))
|
||||||
|
new-addresses))
|
||||||
|
|
||||||
(fn run []
|
(fn run []
|
||||||
(let [[state-directory wan-device] arg
|
(let [[state-directory wan-device] arg
|
||||||
dir (svc.open state-directory)]
|
dir (svc.open state-directory)]
|
||||||
(accumulate [addresses []
|
(accumulate [addresses []
|
||||||
v (dir:events)]
|
v (dir:events)]
|
||||||
(update-addresses wan-device addresses (v:output "address") system))))
|
(update-addresses wan-device addresses (v:output "address")))))
|
||||||
|
|
||||||
{ : update-addresses : deletions : run }
|
{ : update-addresses : changes : run }
|
||||||
|
@ -11,6 +11,6 @@ let
|
|||||||
script = callPackage ./acquire-wan-address.nix { };
|
script = callPackage ./acquire-wan-address.nix { };
|
||||||
in longrun {
|
in longrun {
|
||||||
inherit name;
|
inherit name;
|
||||||
run = "${script} $SERVICE_OUTPUTS/${client.name} $(output ${interface} ifname)";
|
run = "${script} /run/service-state/${client.name} $(output ${interface} ifname)";
|
||||||
dependencies = [ client interface ];
|
dependencies = [ client interface ];
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ in longrun {
|
|||||||
inherit name;
|
inherit name;
|
||||||
notification-fd = 10;
|
notification-fd = 10;
|
||||||
run = ''
|
run = ''
|
||||||
export SERVICE_STATE=$SERVICE_OUTPUTS/${name}
|
export SERVICE_STATE=/run/service-state/${name}
|
||||||
${odhcp6c}/bin/odhcp6c -s ${odhcp-script} -e -v -p /run/${name}.pid -P0 $(output ${interface} ifname)
|
${odhcp6c}/bin/odhcp6c -s ${odhcp-script} -e -v -p /run/${name}.pid -P0 $(output ${interface} ifname)
|
||||||
)
|
)
|
||||||
'';
|
'';
|
||||||
|
@ -11,6 +11,6 @@ let
|
|||||||
script = callPackage ./acquire-delegated-prefix.nix { };
|
script = callPackage ./acquire-delegated-prefix.nix { };
|
||||||
in longrun {
|
in longrun {
|
||||||
inherit name;
|
inherit name;
|
||||||
run = "${script} $SERVICE_OUTPUTS/${client.name} $(output ${interface} ifname)";
|
run = "${script} /run/service-state/${client.name} $(output ${interface} ifname)";
|
||||||
dependencies = [ client interface ];
|
dependencies = [ client interface ];
|
||||||
}
|
}
|
||||||
|
@ -41,11 +41,10 @@ longrun {
|
|||||||
--no-hosts \
|
--no-hosts \
|
||||||
--log-dhcp \
|
--log-dhcp \
|
||||||
--enable-ra \
|
--enable-ra \
|
||||||
|
--log-debug \
|
||||||
|
--log-queries \
|
||||||
--log-facility=- \
|
--log-facility=- \
|
||||||
--dhcp-leasefile=$(mkstate ${name})/leases \
|
--dhcp-leasefile=/run/${name}.leases \
|
||||||
--pid-file=/run/${name}.pid
|
--pid-file=/run/${name}.pid
|
||||||
'';
|
'';
|
||||||
# --log-debug \
|
|
||||||
# --log-queries \
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,45 @@ let
|
|||||||
inherit (pkgs) liminix;
|
inherit (pkgs) liminix;
|
||||||
inherit (pkgs.liminix.services) oneshot;
|
inherit (pkgs.liminix.services) oneshot;
|
||||||
|
|
||||||
kmodules = pkgs.kmodloader.override {
|
kconf = isModule :
|
||||||
inherit (config.system.outputs) kernel;
|
# setting isModule false is utterly untested and mostly
|
||||||
|
# unimplemented: I say this to preempt any "how on earth is this
|
||||||
|
# even supposed to work?" questions
|
||||||
|
let yes = if isModule then "m" else "y";
|
||||||
|
in {
|
||||||
|
NETFILTER = "y";
|
||||||
|
NETFILTER_ADVANCED = "y";
|
||||||
|
NETFILTER_NETLINK = yes;
|
||||||
|
NF_CONNTRACK = yes;
|
||||||
|
|
||||||
|
IP6_NF_IPTABLES= yes;
|
||||||
|
IP_NF_IPTABLES = yes;
|
||||||
|
IP_NF_NAT = yes;
|
||||||
|
IP_NF_TARGET_MASQUERADE = yes;
|
||||||
|
|
||||||
|
NFT_CT = yes;
|
||||||
|
NFT_FIB_IPV4 = yes;
|
||||||
|
NFT_FIB_IPV6 = yes;
|
||||||
|
NFT_LOG = yes;
|
||||||
|
NFT_MASQ = yes;
|
||||||
|
NFT_NAT = yes;
|
||||||
|
NFT_REJECT = yes;
|
||||||
|
NFT_REJECT_INET = yes;
|
||||||
|
|
||||||
|
NF_CT_PROTO_DCCP = "y";
|
||||||
|
NF_CT_PROTO_SCTP = "y";
|
||||||
|
NF_CT_PROTO_UDPLITE = "y";
|
||||||
|
NF_LOG_SYSLOG = yes;
|
||||||
|
NF_NAT = yes;
|
||||||
|
NF_NAT_MASQUERADE = "y";
|
||||||
|
NF_TABLES = yes;
|
||||||
|
NF_TABLES_INET = "y";
|
||||||
|
NF_TABLES_IPV4 = "y";
|
||||||
|
NF_TABLES_IPV6 = "y";
|
||||||
|
};
|
||||||
|
kmodules = pkgs.kernel-modules.override {
|
||||||
|
kernelSrc = config.system.outputs.kernel.src;
|
||||||
|
modulesupport = config.system.outputs.kernel.modulesupport;
|
||||||
targets = [
|
targets = [
|
||||||
"nft_fib_ipv4"
|
"nft_fib_ipv4"
|
||||||
"nft_fib_ipv6"
|
"nft_fib_ipv6"
|
||||||
@ -45,6 +82,12 @@ let
|
|||||||
"xt_nat"
|
"xt_nat"
|
||||||
"xt_tcpudp"
|
"xt_tcpudp"
|
||||||
];
|
];
|
||||||
|
kconfig = kconf true;
|
||||||
|
};
|
||||||
|
loadModules = oneshot {
|
||||||
|
name = "firewall-modules";
|
||||||
|
up = "sh ${kmodules}/load.sh";
|
||||||
|
down = "sh ${kmodules}/unload.sh";
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@ -64,41 +107,11 @@ in
|
|||||||
in svc // {
|
in svc // {
|
||||||
build = args :
|
build = args :
|
||||||
let args' = args // {
|
let args' = args // {
|
||||||
dependencies = (args.dependencies or []) ++ [kmodules];
|
dependencies = (args.dependencies or []) ++ [loadModules];
|
||||||
};
|
};
|
||||||
in svc.build args' ;
|
in svc.build args' ;
|
||||||
};
|
};
|
||||||
|
|
||||||
kernel.config = {
|
kernel.config = kconf true;
|
||||||
NETFILTER = "y";
|
|
||||||
NETFILTER_ADVANCED = "y";
|
|
||||||
NETFILTER_NETLINK = "m";
|
|
||||||
NF_CONNTRACK = "m";
|
|
||||||
|
|
||||||
IP6_NF_IPTABLES= "m";
|
|
||||||
IP_NF_IPTABLES = "m";
|
|
||||||
IP_NF_NAT = "m";
|
|
||||||
IP_NF_TARGET_MASQUERADE = "m";
|
|
||||||
|
|
||||||
NFT_CT = "m";
|
|
||||||
NFT_FIB_IPV4 = "m";
|
|
||||||
NFT_FIB_IPV6 = "m";
|
|
||||||
NFT_LOG = "m";
|
|
||||||
NFT_MASQ = "m";
|
|
||||||
NFT_NAT = "m";
|
|
||||||
NFT_REJECT = "m";
|
|
||||||
NFT_REJECT_INET = "m";
|
|
||||||
|
|
||||||
NF_CT_PROTO_DCCP = "y";
|
|
||||||
NF_CT_PROTO_SCTP = "y";
|
|
||||||
NF_CT_PROTO_UDPLITE = "y";
|
|
||||||
NF_LOG_SYSLOG = "m";
|
|
||||||
NF_NAT = "m";
|
|
||||||
NF_NAT_MASQUERADE = "y";
|
|
||||||
NF_TABLES = "m";
|
|
||||||
NF_TABLES_INET = "y";
|
|
||||||
NF_TABLES_IPV4 = "y";
|
|
||||||
NF_TABLES_IPV6 = "y";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,6 @@ in {
|
|||||||
};
|
};
|
||||||
loadAddress = mkOption { type = types.ints.unsigned; default = null; };
|
loadAddress = mkOption { type = types.ints.unsigned; default = null; };
|
||||||
entryPoint = mkOption { type = types.ints.unsigned; };
|
entryPoint = mkOption { type = types.ints.unsigned; };
|
||||||
alignment = mkOption { type = types.nullOr types.ints.unsigned; default = null; description = "Alignment passed to `mkimage` for FIT"; };
|
|
||||||
radios = mkOption {
|
radios = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
Kernel modules (from mac80211 package) required for the
|
Kernel modules (from mac80211 package) required for the
|
||||||
|
@ -80,7 +80,8 @@ in {
|
|||||||
config.kernel.conditionalConfig;
|
config.kernel.conditionalConfig;
|
||||||
k = liminix.builders.kernel.override {
|
k = liminix.builders.kernel.override {
|
||||||
config = mergedConfig;
|
config = mergedConfig;
|
||||||
inherit (config.kernel) version src extraPatchPhase;
|
version = builtins.trace config.kernel.version config.kernel.version;
|
||||||
|
inherit (config.kernel) src extraPatchPhase;
|
||||||
targets = config.kernel.makeTargets;
|
targets = config.kernel.makeTargets;
|
||||||
};
|
};
|
||||||
in {
|
in {
|
@ -111,8 +111,7 @@ in
|
|||||||
};
|
};
|
||||||
uimage = liminix.builders.uimage {
|
uimage = liminix.builders.uimage {
|
||||||
commandLine = concatStringsSep " " config.boot.commandLine;
|
commandLine = concatStringsSep " " config.boot.commandLine;
|
||||||
inherit (config.boot) commandLineDtbNode;
|
inherit (config.hardware) loadAddress entryPoint;
|
||||||
inherit (config.hardware) loadAddress entryPoint alignment;
|
|
||||||
inherit (config.boot) imageFormat;
|
inherit (config.boot) imageFormat;
|
||||||
inherit (o) kernel dtb;
|
inherit (o) kernel dtb;
|
||||||
};
|
};
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
let
|
let
|
||||||
inherit (lib) mkOption types concatStringsSep;
|
inherit (lib) mkOption types concatStringsSep;
|
||||||
cfg = config.boot.tftp;
|
cfg = config.boot.tftp;
|
||||||
hw = config.hardware;
|
|
||||||
arch = pkgs.stdenv.hostPlatform.linuxArch;
|
|
||||||
in {
|
in {
|
||||||
imports = [ ../ramdisk.nix ];
|
imports = [ ../ramdisk.nix ];
|
||||||
options.boot.tftp = {
|
options.boot.tftp = {
|
||||||
@ -24,10 +22,6 @@ in {
|
|||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
};
|
};
|
||||||
appendDTB = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
options.system.outputs = {
|
options.system.outputs = {
|
||||||
tftpboot = mkOption {
|
tftpboot = mkOption {
|
||||||
@ -68,46 +62,32 @@ in {
|
|||||||
uimage = "bootm";
|
uimage = "bootm";
|
||||||
zimage = "bootz";
|
zimage = "bootz";
|
||||||
}; in choices.${cfg.kernelFormat};
|
}; in choices.${cfg.kernelFormat};
|
||||||
|
|
||||||
cmdline = concatStringsSep " " config.boot.commandLine;
|
cmdline = concatStringsSep " " config.boot.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
|
|
||||||
rm -f vmlinux.bin.lzma ; lzma -k -z vmlinux.bin
|
|
||||||
'';
|
|
||||||
in
|
in
|
||||||
pkgs.runCommand "tftpboot" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ lzma dtc pkgs.stdenv.cc ubootTools ]; } ''
|
pkgs.runCommand "tftpboot" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ lzma dtc ]; } ''
|
||||||
mkdir $out
|
mkdir $out
|
||||||
cd $out
|
cd $out
|
||||||
binsize() { local s=$(stat -L -c %s $1); echo $(($s + 0x1000 &(~0xfff))); }
|
binsize() { local s=$(stat -L -c %s $1); echo $(($s + 0x1000 &(~0xfff))); }
|
||||||
binsize64k() { local s=$(stat -L -c %s $1); echo $(($s + 0x10000 &(~0xffff))); }
|
binsize64k() { local s=$(stat -L -c %s $1); echo $(($s + 0x10000 &(~0xffff))); }
|
||||||
hex() { printf "0x%x" $1; }
|
hex() { printf "0x%x" $1; }
|
||||||
|
|
||||||
rootfsStart=${toString cfg.loadAddress}
|
rootfsStart=${toString cfg.loadAddress}
|
||||||
rootfsSize=$(binsize64k ${o.rootfs} )
|
rootfsSize=$(binsize64k ${o.rootfs} )
|
||||||
rootfsSize=$(($rootfsSize + ${toString cfg.freeSpaceBytes} ))
|
rootfsSize=$(($rootfsSize + ${toString cfg.freeSpaceBytes} ))
|
||||||
|
dtbStart=$(($rootfsStart + $rootfsSize))
|
||||||
|
imageSize=$(binsize ${image})
|
||||||
|
|
||||||
ln -s ${o.manifest} manifest
|
ln -s ${o.manifest} manifest
|
||||||
|
ln -s ${image} image
|
||||||
ln -s ${o.kernel} vmlinux # handy for gdb
|
ln -s ${o.kernel} vmlinux # handy for gdb
|
||||||
|
|
||||||
# if we are transferring kernel and dtb separately, the
|
|
||||||
# dtb has to precede the kernel in ram, because zimage
|
|
||||||
# decompression code will assume that any memory after the
|
|
||||||
# end of the kernel is free
|
|
||||||
|
|
||||||
dtbStart=$(($rootfsStart + $rootfsSize))
|
|
||||||
${if cfg.compressRoot
|
${if cfg.compressRoot
|
||||||
then ''
|
then ''
|
||||||
lzma -z9cv ${o.rootfs} > rootfs.lz
|
lzma -z9cv ${o.rootfs} > rootfs.lz
|
||||||
rootfsLzStart=$dtbStart
|
rootfsLzStart=$(($imageStart + $imageSize))
|
||||||
rootfsLzSize=$(binsize rootfs.lz)
|
rootfsLzSize=$(binsize rootfs.lz)
|
||||||
dtbStart=$(($dtbStart + $rootfsLzSize))
|
|
||||||
''
|
|
||||||
else ''
|
|
||||||
ln -s ${o.rootfs} rootfs
|
|
||||||
''
|
''
|
||||||
|
else "ln -s ${o.rootfs} rootfs"
|
||||||
}
|
}
|
||||||
|
|
||||||
cat ${o.dtb} > dtb
|
cat ${o.dtb} > dtb
|
||||||
address_cells=$(fdtget dtb / '#address-cells')
|
address_cells=$(fdtget dtb / '#address-cells')
|
||||||
size_cells=$(fdtget dtb / '#size-cells')
|
size_cells=$(fdtget dtb / '#size-cells')
|
||||||
@ -121,40 +101,26 @@ in {
|
|||||||
fdtput -p -t s dtb /reserved-memory/$node compatible phram
|
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 -t lx dtb /reserved-memory/$node reg $ac_prefix $(hex $rootfsStart) $sz_prefix $(hex $rootfsSize)
|
||||||
|
|
||||||
|
dtbSize=$(binsize ./dtb )
|
||||||
|
imageStart=$(($dtbStart + $dtbSize))
|
||||||
|
|
||||||
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} root=/dev/mtdblock0";
|
||||||
fdtput -t s dtb /chosen bootargs "$cmd"
|
fdtput -t s dtb /chosen bootargs "$cmd"
|
||||||
|
|
||||||
dtbSize=$(binsize ./dtb )
|
# dtc -I dtb -O dts -o /dev/stdout dtb | grep -A10 chosen ; exit 1
|
||||||
|
|
||||||
${if cfg.appendDTB then ''
|
|
||||||
imageStart=$dtbStart
|
|
||||||
# re-package image with updated dtb
|
|
||||||
cat ${o.kernel} > vmlinux.elf
|
|
||||||
${objcopy} --update-section .appended_dtb=dtb vmlinux.elf
|
|
||||||
${stripAndZip}
|
|
||||||
mkimage -A ${arch} -O linux -T kernel -C lzma -a $(hex ${toString hw.loadAddress}) -e $(hex ${toString hw.entryPoint}) -n '${lib.toUpper arch} Liminix Linux tftpboot' -d vmlinux.bin.lzma image
|
|
||||||
# dtc -I dtb -O dts -o /dev/stdout dtb | grep -A10 chosen ; exit 1
|
|
||||||
tftpcmd="tftpboot $(hex $imageStart) result/image "
|
|
||||||
bootcmd="bootm $(hex $imageStart)"
|
|
||||||
'' else ''
|
|
||||||
imageStart=$(($dtbStart + $dtbSize))
|
|
||||||
tftpcmd="tftpboot $(hex $imageStart) result/image; tftpboot $(hex $dtbStart) result/dtb "
|
|
||||||
ln -s ${image} image
|
|
||||||
bootcmd="${bootCommand} $(hex $imageStart) - $(hex $dtbStart)"
|
|
||||||
''}
|
|
||||||
|
|
||||||
cat > boot.scr << EOF
|
cat > boot.scr << EOF
|
||||||
setenv serverip ${cfg.serverip}
|
setenv serverip ${cfg.serverip}
|
||||||
setenv ipaddr ${cfg.ipaddr}
|
setenv ipaddr ${cfg.ipaddr}
|
||||||
${
|
tftpboot $(hex $imageStart) result/image ; ${
|
||||||
if cfg.compressRoot
|
if cfg.compressRoot
|
||||||
then "tftpboot $(hex $rootfsLzStart) result/rootfs.lz"
|
then "tftpboot $(hex $rootfsLzStart) result/rootfs.lz"
|
||||||
else "tftpboot $(hex $rootfsStart) result/rootfs"
|
else "tftpboot $(hex $rootfsStart) result/rootfs"
|
||||||
}; $tftpcmd
|
}; tftpboot $(hex $dtbStart) result/dtb
|
||||||
${if cfg.compressRoot
|
${if cfg.compressRoot
|
||||||
then "lzmadec $(hex $rootfsLzStart) $(hex $rootfsStart); "
|
then "lzmadec $(hex $rootfsLzStart) $(hex $rootfsStart); "
|
||||||
else ""
|
else ""
|
||||||
} $bootcmd
|
} ${bootCommand} $(hex $imageStart) - $(hex $dtbStart)
|
||||||
EOF
|
EOF
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
@ -12,16 +12,9 @@ in
|
|||||||
imports = [
|
imports = [
|
||||||
./initramfs.nix
|
./initramfs.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
options.system.outputs.rootubifs = mkOption {
|
|
||||||
type = types.package;
|
|
||||||
internal = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
options.hardware.ubi = {
|
options.hardware.ubi = {
|
||||||
minIOSize = mkOption { type = types.str; };
|
minIOSize = mkOption { type = types.str; };
|
||||||
logicalEraseBlockSize = mkOption { type = types.str; }; # LEB
|
eraseBlockSize = mkOption { type = types.str; }; # LEB
|
||||||
physicalEraseBlockSize = mkOption { type = types.str; }; # PEB
|
|
||||||
maxLEBcount = mkOption { type = types.str; }; # LEB
|
maxLEBcount = mkOption { type = types.str; }; # LEB
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,7 +26,7 @@ in
|
|||||||
};
|
};
|
||||||
boot.initramfs.enable = true;
|
boot.initramfs.enable = true;
|
||||||
system.outputs = {
|
system.outputs = {
|
||||||
rootubifs =
|
rootfs =
|
||||||
let
|
let
|
||||||
inherit (pkgs.pkgsBuildBuild) runCommand mtdutils;
|
inherit (pkgs.pkgsBuildBuild) runCommand mtdutils;
|
||||||
cfg = config.hardware.ubi;
|
cfg = config.hardware.ubi;
|
||||||
@ -42,7 +35,7 @@ in
|
|||||||
} ''
|
} ''
|
||||||
mkdir tmp
|
mkdir tmp
|
||||||
tree=${o.bootablerootdir}
|
tree=${o.bootablerootdir}
|
||||||
mkfs.ubifs -x favor_lzo -c ${cfg.maxLEBcount} -m ${cfg.minIOSize} -e ${cfg.logicalEraseBlockSize} -y -r $tree --output $out --squash-uids -o $out
|
mkfs.ubifs -x favor_lzo -c ${cfg.maxLEBcount} -m ${cfg.minIOSize} -e ${cfg.eraseBlockSize} -y -r $tree --output $out --squash-uids -o $out
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
{
|
|
||||||
config
|
|
||||||
, pkgs
|
|
||||||
, lib
|
|
||||||
, ...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
inherit (pkgs) liminix;
|
|
||||||
inherit (lib) mkIf mkOption types concatStringsSep optionalString;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./initramfs.nix
|
|
||||||
./ubifs.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
options.hardware.ubi = {
|
|
||||||
minIOSize = mkOption { type = types.str; };
|
|
||||||
eraseBlockSize = mkOption { type = types.str; }; # LEB
|
|
||||||
maxLEBcount = mkOption { type = types.str; }; # LEB
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf (config.rootfsType == "ubifs") {
|
|
||||||
kernel.config = {
|
|
||||||
MTD_UBI="y";
|
|
||||||
|
|
||||||
UBIFS_FS = "y";
|
|
||||||
UBIFS_FS_SECURITY = "n";
|
|
||||||
};
|
|
||||||
boot.initramfs.enable = true;
|
|
||||||
|
|
||||||
system.outputs.rootfs =
|
|
||||||
let
|
|
||||||
inherit (pkgs.pkgsBuildBuild) runCommand;
|
|
||||||
ubiVolume = ({ name, volumeId, image, flags ? [] }:
|
|
||||||
''
|
|
||||||
[${name}]
|
|
||||||
mode=ubi
|
|
||||||
vol_id=${toString volumeId}
|
|
||||||
vol_type=dynamic
|
|
||||||
vol_name=${name}
|
|
||||||
vol_alignment=1
|
|
||||||
${optionalString (image != null) ''
|
|
||||||
image=${image}
|
|
||||||
''}
|
|
||||||
${optionalString (image == null) ''
|
|
||||||
vol_size=1MiB
|
|
||||||
''}
|
|
||||||
${optionalString (flags != []) ''
|
|
||||||
vol_flags=${concatStringsSep "," flags}
|
|
||||||
''}
|
|
||||||
'');
|
|
||||||
|
|
||||||
ubiImage = (volumes:
|
|
||||||
let
|
|
||||||
ubinizeConfig = pkgs.writeText "ubinize.conf" (concatStringsSep "\n" volumes);
|
|
||||||
inherit (pkgs.pkgsBuildBuild) mtdutils;
|
|
||||||
in
|
|
||||||
runCommand "ubinize" {
|
|
||||||
depsBuildBuild = [ mtdutils ];
|
|
||||||
# block size := 128kb
|
|
||||||
# page size := 2048
|
|
||||||
# ubninize opts := -E 5
|
|
||||||
} ''
|
|
||||||
ubinize -Q "$SOURCE_DATE_EPOCH" -o $out \
|
|
||||||
-p ${config.hardware.ubi.physicalEraseBlockSize} -m ${config.hardware.ubi.minIOSize} \
|
|
||||||
-e ${config.hardware.ubi.logicalEraseBlockSize} \
|
|
||||||
${ubinizeConfig}
|
|
||||||
'');
|
|
||||||
|
|
||||||
ubiDisk = ({ initramfs }:
|
|
||||||
let
|
|
||||||
initramfsUbi = ubiVolume {
|
|
||||||
name = "rootfs";
|
|
||||||
volumeId = 0;
|
|
||||||
image = initramfs;
|
|
||||||
flags = [ "autoresize" ];
|
|
||||||
};
|
|
||||||
in
|
|
||||||
ubiImage [
|
|
||||||
initramfsUbi
|
|
||||||
]);
|
|
||||||
|
|
||||||
disk = ubiDisk {
|
|
||||||
initramfs = config.system.outputs.rootubifs; # liminix.builders.squashfs config.filesystem.contents; # # assert this is a proper FIT.
|
|
||||||
};
|
|
||||||
|
|
||||||
in
|
|
||||||
disk;
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
{
|
|
||||||
config
|
|
||||||
, pkgs
|
|
||||||
, lib
|
|
||||||
, ...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep;
|
|
||||||
models = "6b e1 6f e1 ff ff ff ff ff ff";
|
|
||||||
in {
|
|
||||||
options.system.outputs = {
|
|
||||||
zyxel-nwa-fit = mkOption {
|
|
||||||
type = types.package;
|
|
||||||
description = ''
|
|
||||||
zyxel-nwa-fit
|
|
||||||
*************
|
|
||||||
|
|
||||||
This output provides a FIT image for Zyxel NWA series
|
|
||||||
containing a kernel image and an UBIFS rootfs.
|
|
||||||
|
|
||||||
It can usually be used as a factory image to install Liminix
|
|
||||||
on a system with pre-existing firmware and OS.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
imports = [
|
|
||||||
./ubivolume.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
config = mkIf (config.rootfsType == "ubifs") {
|
|
||||||
|
|
||||||
system.outputs.zyxel-nwa-fit =
|
|
||||||
let
|
|
||||||
o = config.system.outputs;
|
|
||||||
# 8129kb padding.
|
|
||||||
paddedKernel = pkgs.runCommand "padded-kernel" {} ''
|
|
||||||
cp --no-preserve=mode ${o.uimage} $out
|
|
||||||
dd if=/dev/zero of=$out bs=1 count=1 seek=8388607
|
|
||||||
'';
|
|
||||||
firmwareImage = pkgs.runCommand "firmware-image" {} ''
|
|
||||||
cat ${paddedKernel} ${o.rootfs} > $out
|
|
||||||
'';
|
|
||||||
dts = pkgs.writeText "image.its" ''
|
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
description = "Zyxel FIT (Flattened Image Tree)";
|
|
||||||
compat-models = [${models}];
|
|
||||||
#address-cells = <1>;
|
|
||||||
|
|
||||||
images {
|
|
||||||
firmware {
|
|
||||||
data = /incbin/("${firmwareImage}");
|
|
||||||
type = "firmware";
|
|
||||||
compression = "none";
|
|
||||||
hash@1 {
|
|
||||||
algo = "sha1";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
pkgs.runCommand "zyxel-nwa-fit-${config.boot.imageType}" {
|
|
||||||
nativeBuildInputs = [ pkgs.pkgsBuildBuild.ubootTools pkgs.pkgsBuildBuild.dtc ];
|
|
||||||
} ''
|
|
||||||
mkimage -f ${dts} $out
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
inherit (pkgs) liminix;
|
|
||||||
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
|
|
||||||
|
|
||||||
inherit (pkgs.liminix.services) oneshot longrun bundle target;
|
|
||||||
inherit (pkgs.pseudofile) dir symlink;
|
|
||||||
inherit (pkgs) serviceFns;
|
|
||||||
svc = config.system.service;
|
|
||||||
cfg = config.profile.wap;
|
|
||||||
|
|
||||||
hostaps =
|
|
||||||
let
|
|
||||||
defaults = {
|
|
||||||
auth_algs = 1; # 1=wpa2, 2=wep, 3=both
|
|
||||||
wpa = 2; # 1=wpa, 2=wpa2, 3=both
|
|
||||||
wpa_key_mgmt = "WPA-PSK";
|
|
||||||
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
|
|
||||||
rsn_pairwise = "CCMP"; # auth for wpa2
|
|
||||||
};
|
|
||||||
in lib.mapAttrs'
|
|
||||||
(name : value :
|
|
||||||
let
|
|
||||||
attrs = defaults // { ssid = name; } // value;
|
|
||||||
in lib.nameValuePair
|
|
||||||
"hostap-${name}"
|
|
||||||
(svc.hostapd.build {
|
|
||||||
interface = attrs.interface;
|
|
||||||
params = lib.filterAttrs (k: v: k != "interface") attrs;
|
|
||||||
}))
|
|
||||||
cfg.wireless.networks;
|
|
||||||
|
|
||||||
in {
|
|
||||||
imports = [
|
|
||||||
../wlan.nix
|
|
||||||
../network
|
|
||||||
../hostapd
|
|
||||||
../bridge
|
|
||||||
../ssh
|
|
||||||
{ config.services = hostaps; }
|
|
||||||
];
|
|
||||||
|
|
||||||
options.profile.wap = {
|
|
||||||
interfaces = mkOption {
|
|
||||||
type = types.listOf liminix.lib.types.interface;
|
|
||||||
default = [];
|
|
||||||
};
|
|
||||||
wireless = mkOption {
|
|
||||||
type = types.attrsOf types.anything;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = {
|
|
||||||
services.sshd = svc.ssh.build {};
|
|
||||||
|
|
||||||
services.int = svc.bridge.primary.build {
|
|
||||||
ifname = "int";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.bridge = svc.bridge.members.build {
|
|
||||||
primary = config.services.int;
|
|
||||||
members = cfg.interfaces;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.dhcpc = svc.network.dhcp.client.build {
|
|
||||||
interface = config.services.int;
|
|
||||||
dependencies = [ config.services.hostname ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.defaultroute4 = svc.network.route.build {
|
|
||||||
via = "$(output ${config.services.dhcpc} router)";
|
|
||||||
target = "default";
|
|
||||||
dependencies = [config.services.dhcpc];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.resolvconf = oneshot rec {
|
|
||||||
dependencies = [ config.services.dhcpc ];
|
|
||||||
name = "resolvconf";
|
|
||||||
# CHECK: https://udhcp.busybox.net/README.udhcpc says
|
|
||||||
# 'A list of DNS server' but doesn't say what separates the
|
|
||||||
# list members. Assuming it's a space or other IFS character
|
|
||||||
up = ''
|
|
||||||
. ${serviceFns}
|
|
||||||
( in_outputs ${name}
|
|
||||||
for i in $(output ${config.services.dhcpc} dns); do
|
|
||||||
echo "nameserver $i" > resolv.conf
|
|
||||||
done
|
|
||||||
)
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
filesystem = dir {
|
|
||||||
etc = dir {
|
|
||||||
"resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@ -22,15 +22,8 @@ mount -t tmpfs none /tmp
|
|||||||
mkdir /dev/pts
|
mkdir /dev/pts
|
||||||
mount -t devpts none /dev/pts
|
mount -t devpts none /dev/pts
|
||||||
|
|
||||||
mkdir -m 0751 -p /run/services/outputs
|
mkdir -m 0751 /run/service-state
|
||||||
chgrp system /run/services/outputs
|
chgrp system /run/service-state
|
||||||
|
|
||||||
if test -d /persist; then
|
|
||||||
mkdir -m 0751 -p /persist/services/state
|
|
||||||
(cd /run/services && ln -s ../../persist/services/state .)
|
|
||||||
else
|
|
||||||
mkdir -m 0751 -p /run/services/state
|
|
||||||
fi
|
|
||||||
|
|
||||||
### If your services are managed by s6-rc:
|
### If your services are managed by s6-rc:
|
||||||
### (replace /run/service with your scandir)
|
### (replace /run/service with your scandir)
|
||||||
|
@ -29,12 +29,15 @@ let
|
|||||||
in
|
in
|
||||||
longrun {
|
longrun {
|
||||||
name = "sshd";
|
name = "sshd";
|
||||||
# we need /run/dropbear to point to hostkey storage, as that
|
|
||||||
# pathname is hardcoded into the binary.
|
|
||||||
# env -i clears the environment so we don't pass anything weird to
|
# env -i clears the environment so we don't pass anything weird to
|
||||||
# ssh sessions
|
# ssh sessions
|
||||||
run = ''
|
run = ''
|
||||||
ln -s $(mkstate dropbear) /run
|
if test -d /persist; then
|
||||||
|
mkdir -p /persist/secrets/dropbear
|
||||||
|
ln -s /persist/secrets/dropbear /run
|
||||||
|
else
|
||||||
|
mkdir -p /run/dropbear
|
||||||
|
fi
|
||||||
. /etc/profile # sets PATH but do we need this? it's the same file as ashrc
|
. /etc/profile # sets PATH but do we need this? it's the same file as ashrc
|
||||||
exec env -i ENV=/etc/ashrc PATH=$PATH ${dropbear}/bin/dropbear ${concatStringsSep " " options}
|
exec env -i ENV=/etc/ashrc PATH=$PATH ${dropbear}/bin/dropbear ${concatStringsSep " " options}
|
||||||
'';
|
'';
|
||||||
|
@ -47,13 +47,9 @@ in {
|
|||||||
ENCRYPTED_KEYS = "y";
|
ENCRYPTED_KEYS = "y";
|
||||||
KEYS = "y";
|
KEYS = "y";
|
||||||
|
|
||||||
|
# see note in include/linux/netdevice.h re LL_MAX_HEADER
|
||||||
WLAN = "y";
|
WLAN = "y";
|
||||||
CFG80211 = "m";
|
|
||||||
MAC80211 = "m";
|
|
||||||
EXPERT = "y";
|
|
||||||
CFG80211_CERTIFICATION_ONUS = "y";
|
|
||||||
CFG80211_REQUIRE_SIGNED_REGDB = "n"; # depends on ONUS
|
|
||||||
CFG80211_CRDA_SUPPORT = "n";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
## Boot blessing via Zyxel
|
|
||||||
## =======================
|
|
||||||
## Boot blessing is the process to bless a particular boot configuration
|
|
||||||
## It is commonly encountered in devices with redundant partitions
|
|
||||||
## for automatic recovery of broken upgrades.
|
|
||||||
## This is also known as A/B schemas, where A represents the primary partition
|
|
||||||
## and B the secondary partition used for recovery.
|
|
||||||
## To use boot blessing on Liminix, you need to have the support of
|
|
||||||
## your bootloader to help you boot on the secondary partition in case of
|
|
||||||
## failure on the primary partition. The exact details are specifics to your device.
|
|
||||||
## See the Zyxel NWA50AX for an example.
|
|
||||||
## TODO: generalize this module.
|
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkOption types;
|
|
||||||
inherit (pkgs) liminix;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.boot.zyxel-dual-image = mkOption {
|
|
||||||
type = liminix.lib.types.serviceDefn;
|
|
||||||
};
|
|
||||||
|
|
||||||
config.boot.zyxel-dual-image = liminix.callService ./service.nix {
|
|
||||||
ensureActiveImage = mkOption {
|
|
||||||
type = types.enum [ "primary" "secondary" ];
|
|
||||||
default = "primary";
|
|
||||||
description = ''At boot, ensure that the active image is the one specified.
|
|
||||||
|
|
||||||
If you are already on a broken image, you need to manually boot
|
|
||||||
into the right image via `atgo <image index>` in U-Boot.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
kernelCommandLineSource = mkOption {
|
|
||||||
type = types.enum [ "/proc/cmdline" "/proc/device-tree/chosen/bootargs" ];
|
|
||||||
default = "/proc/device-tree/chosen/bootargs";
|
|
||||||
description = ''Kernel command line arguments source file.
|
|
||||||
On MIPS, Liminix embeds the kernel command line in /proc/device-tree/chosen/bootargs-override.
|
|
||||||
|
|
||||||
In this instance, it does not get concatenated with `/proc/cmdline`.
|
|
||||||
Therefore you may prefer to source it from another place, like `/proc/device-tree/chosen/bootargs`.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
primaryMtdPartition = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "Primary MTD partition device node, i.e. for image 0.";
|
|
||||||
};
|
|
||||||
|
|
||||||
secondaryMtdPartition = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "Secondary MTD partition device node, i.e. for image 1.";
|
|
||||||
};
|
|
||||||
|
|
||||||
bootConfigurationMtdPartition = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "Boot configuration MTD partition device node.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
liminix
|
|
||||||
, lib
|
|
||||||
, zyxel-bootconfig
|
|
||||||
}:
|
|
||||||
{ ensureActiveImage, primaryMtdPartition, secondaryMtdPartition, bootConfigurationMtdPartition, kernelCommandLineSource }:
|
|
||||||
let
|
|
||||||
inherit (liminix.services) oneshot;
|
|
||||||
activeImageIndex = if ensureActiveImage == "primary" then 0 else 1;
|
|
||||||
in oneshot {
|
|
||||||
name = "zyxel-boot-configure";
|
|
||||||
up = ''
|
|
||||||
set -- $(cat /proc/device-tree/chosen/bootargs)
|
|
||||||
for x in "$@"; do
|
|
||||||
case "$x" in
|
|
||||||
bootImage=*)
|
|
||||||
BOOT_IMAGE="''${x#bootImage=}"
|
|
||||||
echo "Current boot image is $BOOT_IMAGE."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if test -z "$BOOT_IMAGE"; then
|
|
||||||
echo "No valid image was provided in the kernel command line."
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
${lib.getExe zyxel-bootconfig} ${bootConfigurationMtdPartition} set-image-status "$BOOT_IMAGE" valid
|
|
||||||
${lib.getExe zyxel-bootconfig} ${bootConfigurationMtdPartition} set-active-image ${toString activeImageIndex}
|
|
||||||
|
|
||||||
echo "Active image is now ${ensureActiveImage}"
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
}
|
|
@ -104,7 +104,6 @@ extraPkgs // {
|
|||||||
"CONFIG_DRIVER_NL80211=y"
|
"CONFIG_DRIVER_NL80211=y"
|
||||||
"CONFIG_IAPP=y"
|
"CONFIG_IAPP=y"
|
||||||
"CONFIG_IEEE80211AC=y"
|
"CONFIG_IEEE80211AC=y"
|
||||||
"CONFIG_IEEE80211AX=y"
|
|
||||||
"CONFIG_IEEE80211N=y"
|
"CONFIG_IEEE80211N=y"
|
||||||
"CONFIG_IEEE80211W=y"
|
"CONFIG_IEEE80211W=y"
|
||||||
"CONFIG_INTERNAL_LIBTOMMATH=y"
|
"CONFIG_INTERNAL_LIBTOMMATH=y"
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
(fn assoc [tbl k v]
|
|
||||||
(tset tbl k v)
|
|
||||||
tbl)
|
|
||||||
|
|
||||||
(fn merge [table1 table2]
|
(fn merge [table1 table2]
|
||||||
(collect [k v (pairs table2) &into table1]
|
(collect [k v (pairs table2) &into table1]
|
||||||
k v))
|
k v))
|
||||||
@ -20,7 +16,7 @@
|
|||||||
|
|
||||||
(fn system [s]
|
(fn system [s]
|
||||||
(match (os.execute s)
|
(match (os.execute s)
|
||||||
res (do (print (.. "Executed \"" s "\", exit code " (tostring res))) res)
|
res res
|
||||||
(nil err) (error (.. "Error executing \"" s "\" (" err ")"))))
|
(nil err) (error (.. "Error executing \"" s "\" (" err ")"))))
|
||||||
|
|
||||||
(fn hash [str]
|
(fn hash [str]
|
||||||
@ -66,4 +62,4 @@
|
|||||||
(s:sub 1 (- (# s) pad))))
|
(s:sub 1 (- (# s) pad))))
|
||||||
|
|
||||||
|
|
||||||
{ : assoc : merge : split : file-exists? : system : hash : base64url : dup }
|
{ : merge : split : file-exists? : system : hash : base64url : dup }
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
(local netlink (require :netlink))
|
|
||||||
|
|
||||||
(local { : view } (require :fennel))
|
|
||||||
|
|
||||||
(fn events [groups]
|
|
||||||
(let [sock (netlink.socket)]
|
|
||||||
(coroutine.wrap
|
|
||||||
(fn []
|
|
||||||
(each [_ e (ipairs (sock:query groups))]
|
|
||||||
(coroutine.yield e))
|
|
||||||
(while (sock:poll)
|
|
||||||
(each [_ e (ipairs (sock:event))]
|
|
||||||
(coroutine.yield e)))))))
|
|
||||||
|
|
||||||
{ : events }
|
|
@ -1,7 +0,0 @@
|
|||||||
(local nl (require :anoia.nl))
|
|
||||||
(local { : view } (require :fennel))
|
|
||||||
|
|
||||||
(let [events (nl.events {:link true})]
|
|
||||||
(each [ev events]
|
|
||||||
(print "got one ")
|
|
||||||
(print (view ev))))
|
|
@ -66,7 +66,7 @@ in {
|
|||||||
ifwait = callPackage ./ifwait {};
|
ifwait = callPackage ./ifwait {};
|
||||||
initramfs-peek = callPackage ./initramfs-peek {};
|
initramfs-peek = callPackage ./initramfs-peek {};
|
||||||
kernel-backport = callPackage ./kernel-backport {};
|
kernel-backport = callPackage ./kernel-backport {};
|
||||||
kmodloader = callPackage ./kmodloader {};
|
kernel-modules = callPackage ./kernel-modules {};
|
||||||
levitate = callPackage ./levitate {};
|
levitate = callPackage ./levitate {};
|
||||||
libubootenv = callPackage ./libubootenv {};
|
libubootenv = callPackage ./libubootenv {};
|
||||||
linotify = callPackage ./linotify {};
|
linotify = callPackage ./linotify {};
|
||||||
@ -79,7 +79,6 @@ in {
|
|||||||
lzma = callPackage ./lzma {};
|
lzma = callPackage ./lzma {};
|
||||||
|
|
||||||
mac80211 = callPackage ./mac80211 {};
|
mac80211 = callPackage ./mac80211 {};
|
||||||
zyxel-bootconfig = callPackage ./zyxel-bootconfig {};
|
|
||||||
min-collect-garbage = callPackage ./min-collect-garbage {};
|
min-collect-garbage = callPackage ./min-collect-garbage {};
|
||||||
min-copy-closure = callPackage ./min-copy-closure {};
|
min-copy-closure = callPackage ./min-copy-closure {};
|
||||||
netlink-lua = callPackage ./netlink-lua {};
|
netlink-lua = callPackage ./netlink-lua {};
|
||||||
|
@ -8,14 +8,12 @@
|
|||||||
, writeScriptBin
|
, writeScriptBin
|
||||||
, linotify
|
, linotify
|
||||||
, anoia
|
, anoia
|
||||||
, netlink-lua
|
|
||||||
, fennel
|
, fennel
|
||||||
}:
|
}:
|
||||||
let packages = [
|
let packages = [
|
||||||
linotify
|
linotify
|
||||||
anoia
|
anoia
|
||||||
fennel
|
fennel
|
||||||
netlink-lua
|
|
||||||
lua.pkgs.luafilesystem
|
lua.pkgs.luafilesystem
|
||||||
];
|
];
|
||||||
join = ps: builtins.concatStringsSep ";" ps;
|
join = ps: builtins.concatStringsSep ";" ps;
|
||||||
|
@ -1,195 +0,0 @@
|
|||||||
{:event "newlink"
|
|
||||||
:hwaddr "00:00:00:00:00:00"
|
|
||||||
:index 1
|
|
||||||
:mtu 65536
|
|
||||||
:name "lo"
|
|
||||||
:running "yes"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "50:3e:aa:08:df:52"
|
|
||||||
:index 2
|
|
||||||
:mtu 1500
|
|
||||||
:name "enp1s0"
|
|
||||||
:running "no"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "1c:1b:0d:9c:39:2d"
|
|
||||||
:index 3
|
|
||||||
:mtu 1500
|
|
||||||
:name "enp0s31f6"
|
|
||||||
:running "yes"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "da:4d:53:c3:54:43"
|
|
||||||
:index 4
|
|
||||||
:mtu 1500
|
|
||||||
:name "vbridge0"
|
|
||||||
:running "yes"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "00:28:f8:69:fa:14"
|
|
||||||
:index 6
|
|
||||||
:mtu 1500
|
|
||||||
:name "wlp4s0"
|
|
||||||
:running "no"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "no"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "02:42:b1:e6:e5:bd"
|
|
||||||
:index 7
|
|
||||||
:mtu 1500
|
|
||||||
:name "br-7ddfef4820c5"
|
|
||||||
:running "no"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "02:42:8d:d4:36:34"
|
|
||||||
:index 8
|
|
||||||
:mtu 1500
|
|
||||||
:name "br-95da8b40a7cc"
|
|
||||||
:running "yes"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "02:42:bc:cf:a8:5e"
|
|
||||||
:index 9
|
|
||||||
:mtu 1500
|
|
||||||
:name "docker0"
|
|
||||||
:running "no"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "b6:66:50:69:33:a6"
|
|
||||||
:index 11
|
|
||||||
:mtu 1500
|
|
||||||
:name "veth2ff6ec3"
|
|
||||||
:running "yes"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "e6:94:c8:48:f3:97"
|
|
||||||
:index 13
|
|
||||||
:mtu 1500
|
|
||||||
:name "veth0913974"
|
|
||||||
:running "yes"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "9a:87:d8:f2:c6:96"
|
|
||||||
:index 15
|
|
||||||
:mtu 1500
|
|
||||||
:name "veth0e74156"
|
|
||||||
:running "yes"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "5e:d2:92:b9:5f:6d"
|
|
||||||
:index 17
|
|
||||||
:mtu 1500
|
|
||||||
:name "veth89a36b3"
|
|
||||||
:running "yes"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "ca:88:3f:09:bc:51"
|
|
||||||
:index 19
|
|
||||||
:mtu 1500
|
|
||||||
:name "veth73c1e0b"
|
|
||||||
:running "yes"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "b6:7d:5c:38:89:1d"
|
|
||||||
:index 21
|
|
||||||
:mtu 1500
|
|
||||||
:name "dummy0"
|
|
||||||
:running "no"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "no"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "52:f0:46:da:0c:0c"
|
|
||||||
:index 22
|
|
||||||
:mtu 1500
|
|
||||||
:name "dummy1"
|
|
||||||
:running "yes"
|
|
||||||
:stamp 857161382
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newneigh"
|
|
||||||
:hwaddr "00:22:61:3d:f7:54"
|
|
||||||
:index 4
|
|
||||||
:ip "192.168.8.140"
|
|
||||||
:probes 1
|
|
||||||
:stamp 857165355
|
|
||||||
:state "stale"}
|
|
||||||
{:event "delneigh"
|
|
||||||
:hwaddr "5c:60:ba:58:34:93"
|
|
||||||
:index 3
|
|
||||||
:stamp 857166891
|
|
||||||
:state "stale"}
|
|
||||||
{:event "newneigh"
|
|
||||||
:hwaddr "80:64:6f:9e:15:02"
|
|
||||||
:index 4
|
|
||||||
:ip "192.168.8.161"
|
|
||||||
:probes 1
|
|
||||||
:stamp 857172523
|
|
||||||
:state "stale"}
|
|
||||||
{:event "newneigh"
|
|
||||||
:hwaddr "e4:95:6e:42:c2:6c"
|
|
||||||
:index 3
|
|
||||||
:stamp 857174763
|
|
||||||
:state "reachable"}
|
|
||||||
{:event "newneigh"
|
|
||||||
:hwaddr "e4:b3:18:76:1b:23"
|
|
||||||
:index 4
|
|
||||||
:ip "2001:8b0:de3a:40de:4708:c700:4de2:9264"
|
|
||||||
:probes 1
|
|
||||||
:stamp 857175595
|
|
||||||
:state "stale"}
|
|
||||||
{:event "newneigh"
|
|
||||||
:hwaddr "80:64:6f:9e:10:c6"
|
|
||||||
:index 4
|
|
||||||
:ip "192.168.8.53"
|
|
||||||
:probes 1
|
|
||||||
:stamp 857176619
|
|
||||||
:state "stale"}
|
|
||||||
{:event "newneigh"
|
|
||||||
:hwaddr "80:64:6f:9e:15:02"
|
|
||||||
:index 4
|
|
||||||
:ip "192.168.8.161"
|
|
||||||
:probes 1
|
|
||||||
:stamp 857177643
|
|
||||||
:state "probe"}
|
|
||||||
{:event "newneigh"
|
|
||||||
:hwaddr "80:64:6f:9e:15:02"
|
|
||||||
:index 4
|
|
||||||
:ip "192.168.8.161"
|
|
||||||
:probes 1
|
|
||||||
:stamp 857177644
|
|
||||||
:state "reachable"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "b6:7d:5c:38:89:1d"
|
|
||||||
:index 21
|
|
||||||
:mtu 1500
|
|
||||||
:name "dummy0"
|
|
||||||
:running "yes"
|
|
||||||
:stamp 857178258
|
|
||||||
:up "yes"}
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "b6:7d:5c:38:89:1d"
|
|
||||||
:index 21
|
|
||||||
:mtu 1500
|
|
||||||
:name "dummy0"
|
|
||||||
:running "no"
|
|
||||||
:stamp 857181661
|
|
||||||
:up "no"}
|
|
||||||
{:event "newneigh"
|
|
||||||
:hwaddr "80:64:6f:9e:10:c6"
|
|
||||||
:index 4
|
|
||||||
:ip "192.168.8.53"
|
|
||||||
:probes 1
|
|
||||||
:stamp 857182251
|
|
||||||
:state "probe"}
|
|
@ -1,64 +1,52 @@
|
|||||||
(local nl (require :anoia.nl))
|
(local netlink (require :netlink))
|
||||||
(local { : assoc : system } (require :anoia))
|
(local sock (netlink.socket))
|
||||||
|
|
||||||
; (local { : view} (require :fennel))
|
; (local { : view} (require :fennel))
|
||||||
|
|
||||||
|
(fn assoc [tbl k v]
|
||||||
|
(tset tbl k v)
|
||||||
|
tbl)
|
||||||
|
|
||||||
(fn parse-args [args]
|
(fn parse-args [args]
|
||||||
(match args
|
(match args
|
||||||
["-v" & rest] (assoc (parse-args rest) :verbose true)
|
["-v" & rest] (assoc (parse-args rest) :verbose true)
|
||||||
["-t" timeout & rest] (assoc (parse-args rest) :timeout (tonumber timeout))
|
["-t" timeout & rest] (assoc (parse-args rest) :timeout (tonumber timeout))
|
||||||
["-s" service & rest] (assoc (parse-args rest) :service service)
|
|
||||||
[linkname "up"] {:link linkname :expecting "up"}
|
[linkname "up"] {:link linkname :expecting "up"}
|
||||||
[linkname "running"] {:link linkname :expecting "running"}
|
[linkname "running"] {:link linkname :expecting "running"}
|
||||||
[linkname "present"] {:link linkname :expecting "present"}
|
[linkname "present"] {:link linkname :expecting "present"}
|
||||||
[linkname nil] {:link linkname :expecting "present"}
|
[linkname nil] {:link linkname :expecting "present"}
|
||||||
_ nil))
|
_ nil))
|
||||||
|
|
||||||
(fn event-matches? [params v]
|
(local parameters
|
||||||
(let [got
|
(or
|
||||||
(match v
|
(parse-args arg)
|
||||||
;; - up: Reflects the administrative state of the interface (IFF_UP)
|
(assert false (.. "Usage: " (. arg 0) " [-v] ifname [present|up|running]"))))
|
||||||
;; - running: Reflects the operational state (IFF_RUNNING).
|
|
||||||
{:event "newlink" :name params.link :up :yes :running :yes}
|
|
||||||
{:present true :up true :running true}
|
|
||||||
|
|
||||||
{:event "newlink" :name params.link :up :yes}
|
(fn run-events [evs]
|
||||||
{:present :true :up true}
|
(each [_ v (ipairs evs)]
|
||||||
|
(let [got
|
||||||
|
(match v
|
||||||
|
;; - up: Reflects the administrative state of the interface (IFF_UP)
|
||||||
|
;; - running: Reflects the operational state (IFF_RUNNING).
|
||||||
|
{:event "newlink" :name parameters.link :up :yes :running :yes}
|
||||||
|
{:present true :up true :running true}
|
||||||
|
|
||||||
{:event "newlink" :name params.link}
|
{:event "newlink" :name parameters.link :up :yes}
|
||||||
{:present true }
|
{:present :true :up true}
|
||||||
|
|
||||||
_
|
{:event "newlink" :name parameters.link}
|
||||||
{})]
|
{:present true }
|
||||||
(not (not (. got params.expecting)))))
|
|
||||||
|
|
||||||
(var up :unknown)
|
_
|
||||||
(fn toggle-service [service wanted?]
|
{})]
|
||||||
(when (not (= up wanted?))
|
(when (. got parameters.expecting)
|
||||||
(set up
|
(os.exit 0)))))
|
||||||
(if wanted?
|
|
||||||
(pcall system (.. "s6-rc -u change " service))
|
|
||||||
(not (pcall system (.. "s6-rc -d change " service)))))
|
|
||||||
))
|
|
||||||
|
|
||||||
(fn run [args event-fn]
|
|
||||||
(set up :unknown)
|
|
||||||
(let [parameters
|
|
||||||
(assert (parse-args args)
|
|
||||||
(.. "Usage: ifwait [-v] ifname [present|up|running]"))]
|
|
||||||
(when parameters.verbose
|
|
||||||
(print (.. "ifwait: waiting for "
|
|
||||||
parameters.link " to be " parameters.expecting)))
|
|
||||||
|
|
||||||
(if parameters.service
|
(when parameters.verbose
|
||||||
(each [e (event-fn)]
|
(print (.. (. arg 0) ": waiting for "
|
||||||
(if (= e.name parameters.link)
|
parameters.link " to be " parameters.expecting)))
|
||||||
(toggle-service parameters.service (event-matches? parameters e))))
|
|
||||||
(each [e (event-fn)
|
|
||||||
&until (event-matches? parameters e)]
|
|
||||||
true))))
|
|
||||||
|
|
||||||
(when (not (= (. arg 0) "test"))
|
(run-events (sock:query {:link true}))
|
||||||
(run arg #(nl.events {:link true})))
|
|
||||||
|
|
||||||
{ : run }
|
(while (sock:poll) (run-events (sock:event)))
|
||||||
|
@ -1,119 +0,0 @@
|
|||||||
(local { : view &as fennel } (require :fennel))
|
|
||||||
(local anoia (require :anoia))
|
|
||||||
|
|
||||||
(var fake-system (fn [s] (print "executing " s)))
|
|
||||||
(tset anoia :system #(fake-system $1))
|
|
||||||
|
|
||||||
(macro expect= [actual expected]
|
|
||||||
`(let [ve# (view ,expected)
|
|
||||||
va# (view ,actual)]
|
|
||||||
(when (not (= ve# va#))
|
|
||||||
(assert false
|
|
||||||
(.. "\nexpected " ve# "\ngot " va#)
|
|
||||||
))))
|
|
||||||
|
|
||||||
(fn event-generator [events]
|
|
||||||
(coroutine.wrap
|
|
||||||
(fn []
|
|
||||||
(each [_ e (ipairs events)] (coroutine.yield e)))))
|
|
||||||
|
|
||||||
(fn file-events [path]
|
|
||||||
(let [data (with-open [e (io.open path "r")] (e:read "*a"))
|
|
||||||
parse (fennel.parser data)]
|
|
||||||
(icollect [_ ast parse]
|
|
||||||
ast)))
|
|
||||||
|
|
||||||
(set _G.arg (doto [] (tset 0 "test")))
|
|
||||||
(local ifwait (require :ifwait))
|
|
||||||
|
|
||||||
(let [gen (event-generator (file-events "events-fixture"))]
|
|
||||||
(ifwait.run ["dummy0" "up"] #gen)
|
|
||||||
(match (pcall gen)
|
|
||||||
(true _) true
|
|
||||||
(false msg) (error "didn't detect dummy0 up event")))
|
|
||||||
|
|
||||||
(var upsies [])
|
|
||||||
(set fake-system
|
|
||||||
(fn [s]
|
|
||||||
(if (s:match "-u change addmember")
|
|
||||||
(table.insert upsies :u)
|
|
||||||
(s:match "-d change addmember")
|
|
||||||
(table.insert upsies :d))))
|
|
||||||
|
|
||||||
(fn newlink [name up running]
|
|
||||||
{:event "newlink"
|
|
||||||
:hwaddr "b6:7d:5c:38:89:1d"
|
|
||||||
:index (string.unpack ">i2" name)
|
|
||||||
:mtu 1500
|
|
||||||
: name
|
|
||||||
: running
|
|
||||||
:stamp 857161382
|
|
||||||
: up })
|
|
||||||
|
|
||||||
"when it gets events that don't match the interface, nothing happens"
|
|
||||||
|
|
||||||
(let [gen (-> [(newlink "eth1" "no" "no")] event-generator)]
|
|
||||||
(set upsies [])
|
|
||||||
(ifwait.run [ "-s" "addmember" "dummy0" "up"] #gen)
|
|
||||||
(expect= upsies []))
|
|
||||||
|
|
||||||
"when it gets an event that should start the service, the service starts"
|
|
||||||
|
|
||||||
(let [gen (->
|
|
||||||
[(newlink "dummy0" "no" "no")
|
|
||||||
(newlink "dummy0" "yes" "no")
|
|
||||||
(newlink "eth1" "no" "no")]
|
|
||||||
event-generator)]
|
|
||||||
(set upsies [])
|
|
||||||
(ifwait.run ["-s" "addmember" "dummy0" "up"] #gen)
|
|
||||||
(expect= upsies [:d :u]))
|
|
||||||
|
|
||||||
"when it gets an event that should stop the service, the service stops"
|
|
||||||
|
|
||||||
(let [gen (->
|
|
||||||
[(newlink "dummy0" "no" "no")
|
|
||||||
(newlink "dummy0" "yes" "no")
|
|
||||||
(newlink "dummy0" "no" "no")
|
|
||||||
]
|
|
||||||
event-generator)]
|
|
||||||
(set upsies [])
|
|
||||||
(ifwait.run ["-s" "addmember" "dummy0" "up"] #gen)
|
|
||||||
(expect= upsies [:d :u :d]))
|
|
||||||
|
|
||||||
"it does not call s6-rc again if the service is already in required state"
|
|
||||||
|
|
||||||
(let [gen (->
|
|
||||||
[(newlink "dummy0" "no" "no")
|
|
||||||
(newlink "dummy0" "yes" "no")
|
|
||||||
(newlink "dummy0" "yes" "yes")
|
|
||||||
(newlink "dummy0" "yes" "yes")
|
|
||||||
(newlink "dummy0" "yes" "no")
|
|
||||||
(newlink "dummy0" "no" "no")
|
|
||||||
]
|
|
||||||
event-generator)]
|
|
||||||
(set upsies [])
|
|
||||||
(ifwait.run ["-s" "addmember" "dummy0" "up"] #gen)
|
|
||||||
(expect= upsies [:d :u :d]))
|
|
||||||
|
|
||||||
"it handles an error return from s6-rc"
|
|
||||||
|
|
||||||
(set fake-system
|
|
||||||
(fn [s]
|
|
||||||
(if (s:match "-u change addmember")
|
|
||||||
(table.insert upsies :u)
|
|
||||||
(s:match "-d change addmember")
|
|
||||||
(table.insert upsies :d))
|
|
||||||
(error "false")
|
|
||||||
))
|
|
||||||
|
|
||||||
(let [gen (->
|
|
||||||
[(newlink "dummy0" "yes" "no")
|
|
||||||
(newlink "dummy0" "yes" "yes")
|
|
||||||
(newlink "dummy0" "yes" "yes")
|
|
||||||
(newlink "dummy0" "yes" "no")
|
|
||||||
(newlink "dummy0" "no" "no")
|
|
||||||
]
|
|
||||||
event-generator)]
|
|
||||||
(set upsies [])
|
|
||||||
(ifwait.run ["-s" "addmember" "dummy0" "up"] #gen)
|
|
||||||
(expect= upsies [:u :u :u :u]))
|
|
3
pkgs/kernel-modules/Makefile
Normal file
3
pkgs/kernel-modules/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
# obj-m += net/ipv4/netfilter/nft_fib_ipv4.o
|
50
pkgs/kernel-modules/default.nix
Normal file
50
pkgs/kernel-modules/default.nix
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
stdenv
|
||||||
|
, buildPackages
|
||||||
|
, kernelSrc ? null
|
||||||
|
, modulesupport ? null
|
||||||
|
, targets ? []
|
||||||
|
, kconfig ? {}
|
||||||
|
, openssl
|
||||||
|
, writeText
|
||||||
|
, lib
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
writeConfig = import ../kernel/write-kconfig.nix { inherit lib writeText; };
|
||||||
|
arch = stdenv.hostPlatform.linuxArch;
|
||||||
|
in stdenv.mkDerivation {
|
||||||
|
name = "kernel-modules";
|
||||||
|
|
||||||
|
nativeBuildInputs = [buildPackages.stdenv.cc] ++
|
||||||
|
(with buildPackages.pkgs; [
|
||||||
|
bc bison flex
|
||||||
|
openssl
|
||||||
|
cpio
|
||||||
|
kmod
|
||||||
|
]);
|
||||||
|
CC = "${stdenv.cc.bintools.targetPrefix}gcc";
|
||||||
|
HOST_EXTRACFLAGS = with buildPackages.pkgs;
|
||||||
|
"-I${buildPackages.openssl.dev}/include -L${buildPackages.openssl.out}/lib";
|
||||||
|
CROSS_COMPILE = stdenv.cc.bintools.targetPrefix;
|
||||||
|
ARCH = arch;
|
||||||
|
KBUILD_BUILD_HOST = "liminix.builder";
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
cat ${writeConfig "kconfig" kconfig} > .more-config
|
||||||
|
cat .more-config >> .config
|
||||||
|
make olddefconfig
|
||||||
|
for v in $(cat .more-config) ; do grep $v .config || (echo Missing $v && exit 1);done
|
||||||
|
make modules
|
||||||
|
'';
|
||||||
|
src = modulesupport;
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/lib/modules/0.0
|
||||||
|
find . -name \*.ko | cpio --verbose --make-directories -p $out/lib/modules/0.0
|
||||||
|
depmod -b $out -v 0.0
|
||||||
|
touch $out/load.sh
|
||||||
|
for i in ${lib.concatStringsSep " " targets}; do
|
||||||
|
modprobe -S 0.0 -d $out --show-depends $i >> $out/load.sh
|
||||||
|
done
|
||||||
|
tac < $out/load.sh | sed 's/^insmod/rmmod/g' > $out/unload.sh
|
||||||
|
'';
|
||||||
|
}
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
, config
|
, config
|
||||||
, src
|
, src
|
||||||
, version ? "0"
|
, version ? "1"
|
||||||
, extraPatchPhase ? "echo"
|
, extraPatchPhase ? "echo"
|
||||||
, targets ? ["vmlinux"]
|
, targets ? ["vmlinux"]
|
||||||
} :
|
} :
|
||||||
@ -24,6 +24,7 @@ stdenv.mkDerivation rec {
|
|||||||
(with buildPackages.pkgs; [
|
(with buildPackages.pkgs; [
|
||||||
rsync bc bison flex pkg-config
|
rsync bc bison flex pkg-config
|
||||||
openssl ncurses.all perl
|
openssl ncurses.all perl
|
||||||
|
cpio
|
||||||
]);
|
]);
|
||||||
CC = "${stdenv.cc.bintools.targetPrefix}gcc";
|
CC = "${stdenv.cc.bintools.targetPrefix}gcc";
|
||||||
HOSTCC = with buildPackages.pkgs;
|
HOSTCC = with buildPackages.pkgs;
|
||||||
@ -53,7 +54,7 @@ stdenv.mkDerivation rec {
|
|||||||
patches = [
|
patches = [
|
||||||
./cmdline-cookie.patch
|
./cmdline-cookie.patch
|
||||||
./mips-malta-fdt-from-bootloader.patch
|
./mips-malta-fdt-from-bootloader.patch
|
||||||
] ++ lib.optional (lib.versionOlder version "5.18.0")
|
] ++ lib.optional (lib.versionOlder version "6.0")
|
||||||
./phram-allow-cached-mappings.patch;
|
./phram-allow-cached-mappings.patch;
|
||||||
|
|
||||||
# this is here to work around what I think is a bug in nixpkgs
|
# this is here to work around what I think is a bug in nixpkgs
|
||||||
@ -104,6 +105,7 @@ stdenv.mkDerivation rec {
|
|||||||
mkdir -p $headers
|
mkdir -p $headers
|
||||||
cp -a include .config $headers/
|
cp -a include .config $headers/
|
||||||
mkdir -p $modulesupport
|
mkdir -p $modulesupport
|
||||||
|
cp modules.* vmlinux.o $modulesupport
|
||||||
make modules
|
make modules
|
||||||
cp -a . $modulesupport
|
cp -a . $modulesupport
|
||||||
'';
|
'';
|
||||||
|
@ -15,12 +15,10 @@ let
|
|||||||
in {
|
in {
|
||||||
kernel
|
kernel
|
||||||
, commandLine
|
, commandLine
|
||||||
, commandLineDtbNode ? "bootargs"
|
|
||||||
, entryPoint
|
, entryPoint
|
||||||
, extraName ? "" # e.g. socFamily
|
, extraName ? "" # e.g. socFamily
|
||||||
, loadAddress
|
, loadAddress
|
||||||
, imageFormat
|
, imageFormat
|
||||||
, alignment ? null
|
|
||||||
, dtb ? null
|
, dtb ? null
|
||||||
} : stdenv.mkDerivation {
|
} : stdenv.mkDerivation {
|
||||||
name = "kernel.image";
|
name = "kernel.image";
|
||||||
@ -41,7 +39,7 @@ in {
|
|||||||
'';
|
'';
|
||||||
mungeDtbPhase = ''
|
mungeDtbPhase = ''
|
||||||
dtc -I dtb -O dts -o tmp.dts ${dtb}
|
dtc -I dtb -O dts -o tmp.dts ${dtb}
|
||||||
echo '/{ chosen { ${commandLineDtbNode} = ${builtins.toJSON commandLine}; }; };' >> tmp.dts
|
echo '/{ chosen { bootargs = ${builtins.toJSON commandLine}; }; };' >> tmp.dts
|
||||||
dtc -I dts -O dtb -o tmp.dtb tmp.dts
|
dtc -I dts -O dtb -o tmp.dtb tmp.dts
|
||||||
'';
|
'';
|
||||||
|
|
||||||
@ -71,7 +69,7 @@ in {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
_VARS
|
_VARS
|
||||||
mkimage -f mkimage.its ${lib.optionalString (alignment != null) "-B 0x${lib.toHexString alignment}"} kernel.uimage
|
mkimage -f mkimage.its kernel.uimage
|
||||||
mkimage -l kernel.uimage
|
mkimage -l kernel.uimage
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
{
|
|
||||||
liminix
|
|
||||||
, lib
|
|
||||||
, targets ? []
|
|
||||||
, kernel ? null
|
|
||||||
, runCommand
|
|
||||||
, pkgsBuildBuild
|
|
||||||
, dependencies ? []
|
|
||||||
} :
|
|
||||||
let
|
|
||||||
inherit (liminix.services) oneshot;
|
|
||||||
inherit (lib) concatStringsSep;
|
|
||||||
loader = runCommand "modules" {
|
|
||||||
nativeBuildInputs = with pkgsBuildBuild ;[
|
|
||||||
kmod cpio gawk
|
|
||||||
];
|
|
||||||
} ''
|
|
||||||
kernel=${kernel.modulesupport}
|
|
||||||
|
|
||||||
mkdir -p lib/modules/0.0
|
|
||||||
(cd $kernel && find . -name \*.ko | cpio --verbose --make-directories -p $NIX_BUILD_TOP/lib/modules/0.0)
|
|
||||||
cp $kernel/modules.* lib/modules/0.0
|
|
||||||
depmod -b . 0.0
|
|
||||||
|
|
||||||
(for i in ${lib.concatStringsSep " " targets}; do
|
|
||||||
modprobe -S 0.0 -d $NIX_BUILD_TOP --show-depends $i | sed "s,^insmod $NIX_BUILD_TOP/lib/modules/0.0/,,g"
|
|
||||||
done) | awk '!a[$0]++' > load-order
|
|
||||||
|
|
||||||
mkdir $out
|
|
||||||
for i in $(cat load-order); do
|
|
||||||
install -v $NIX_BUILD_TOP/lib/modules/0.0/$i -D $out/$i
|
|
||||||
done
|
|
||||||
echo "O=$out" > $out/load.sh
|
|
||||||
sed "s,^,insmod \$O/,g" < load-order >> $out/load.sh
|
|
||||||
echo "O=$out" > $out/unload.sh
|
|
||||||
tac load-order | sed "s,^,rmmod \$O/,g" > $out/unload.sh
|
|
||||||
'';
|
|
||||||
in oneshot {
|
|
||||||
name = "kmodloader-" + (concatStringsSep "-" targets);
|
|
||||||
up = "sh ${loader}/load.sh";
|
|
||||||
down = "sh ${loader}/unload.sh";
|
|
||||||
inherit dependencies;
|
|
||||||
}
|
|
@ -15,6 +15,6 @@ for i in run notification-fd up down consumer-for producer-for pipeline-name ; d
|
|||||||
test -n "$(printenv $i)" && (echo "$(printenv $i)" > $out/${name}/$i)
|
test -n "$(printenv $i)" && (echo "$(printenv $i)" > $out/${name}/$i)
|
||||||
done
|
done
|
||||||
|
|
||||||
( cd $out && ln -s /run/services/outputs/${name} ./.outputs )
|
( cd $out && ln -s /run/service-state/${name} ./.outputs )
|
||||||
for i in $out/${name}/{down,up,run} ; do test -f $i && chmod +x $i; done
|
for i in $out/${name}/{down,up,run} ; do test -f $i && chmod +x $i; done
|
||||||
true
|
true
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
inherit (builtins) concatStringsSep;
|
inherit (builtins) concatStringsSep;
|
||||||
prefix = "/run/services/outputs";
|
prefix = "/run/service-state";
|
||||||
output = service: name: "${prefix}/${service.name}/${name}";
|
output = service: name: "${prefix}/${service.name}/${name}";
|
||||||
serviceScript = commands : ''
|
serviceScript = commands : ''
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
@ -20,7 +20,7 @@ if toplevel=$(nix-build "$@" -A outputs.systemConfiguration --no-out-link); then
|
|||||||
echo systemConfiguration $toplevel
|
echo systemConfiguration $toplevel
|
||||||
min-copy-closure $target_host $toplevel
|
min-copy-closure $target_host $toplevel
|
||||||
$ssh_command $target_host $toplevel/bin/install
|
$ssh_command $target_host $toplevel/bin/install
|
||||||
$ssh_command $target_host "sync; source /etc/profile; reboot -f"
|
$ssh_command $target_host "sync; source /etc/profile; reboot"
|
||||||
else
|
else
|
||||||
echo Rebuild failed
|
echo Rebuild failed
|
||||||
fi
|
fi
|
||||||
|
@ -20,21 +20,23 @@
|
|||||||
out))
|
out))
|
||||||
(let [(address len preferred valid extra)
|
(let [(address len preferred valid extra)
|
||||||
(string.match str "(.-)/(%d+),(%d+),(%d+)(.*)$")]
|
(string.match str "(.-)/(%d+),(%d+),(%d+)(.*)$")]
|
||||||
(merge {: address : len
|
(merge {: address : len : preferred : valid} (parse-extra extra))))
|
||||||
:preferred (or preferred "forever")
|
|
||||||
:valid (or valid "forever")
|
|
||||||
}
|
|
||||||
(parse-extra extra))))
|
|
||||||
|
|
||||||
(fn write-addresses [prefix addresses]
|
(fn write-addresses [prefix addresses]
|
||||||
(each [_ a (ipairs (split " " addresses))]
|
(each [_ a (ipairs (split " " addresses))]
|
||||||
(let [address (parse-address a)
|
(let [address (parse-address a)
|
||||||
suffix (base64url (string.pack "n" (hash a)))
|
suffix (base64url (string.pack "n" (hash a)))
|
||||||
|
;; keydir should be a function of all the address
|
||||||
|
;; attributes: we want it to change whenever anything changes
|
||||||
|
;; so that clients can see which addresses are new without
|
||||||
|
;; deep table comparisons
|
||||||
keydir (..
|
keydir (..
|
||||||
prefix
|
prefix
|
||||||
(-> address.address
|
(-> address.address
|
||||||
(: :gsub "::$" "")
|
(: :gsub "::$" "")
|
||||||
(: :gsub ":" "-")))]
|
(: :gsub ":" "-"))
|
||||||
|
"_"
|
||||||
|
suffix)]
|
||||||
(mktree (.. state-directory "/" keydir))
|
(mktree (.. state-directory "/" keydir))
|
||||||
(each [k v (pairs address)]
|
(each [k v (pairs address)]
|
||||||
(write-value (.. keydir "/" k) v)))))
|
(write-value (.. keydir "/" k) v)))))
|
||||||
|
@ -14,7 +14,6 @@ let
|
|||||||
cp -av ${src}/target/linux/generic/files/* .
|
cp -av ${src}/target/linux/generic/files/* .
|
||||||
chmod -R u+w .
|
chmod -R u+w .
|
||||||
cp -av ${src}/target/linux/${family}/files/* .
|
cp -av ${src}/target/linux/${family}/files/* .
|
||||||
chmod -R u+w .
|
|
||||||
test -d ${src}/target/linux/${family}/files-5.15/ && cp -av ${src}/target/linux/${family}/files-5.15/* .
|
test -d ${src}/target/linux/${family}/files-5.15/ && cp -av ${src}/target/linux/${family}/files-5.15/* .
|
||||||
chmod -R u+w .
|
chmod -R u+w .
|
||||||
patches() {
|
patches() {
|
||||||
|
@ -2,15 +2,8 @@
|
|||||||
writeText "service-fns.sh" ''
|
writeText "service-fns.sh" ''
|
||||||
output() { cat $1/.outputs/$2; }
|
output() { cat $1/.outputs/$2; }
|
||||||
output_path() { echo $(realpath $1/.outputs)/$2; }
|
output_path() { echo $(realpath $1/.outputs)/$2; }
|
||||||
SERVICE_OUTPUTS=/run/services/outputs
|
|
||||||
SERVICE_STATE=/run/services/state
|
|
||||||
mkoutputs() {
|
mkoutputs() {
|
||||||
d=$SERVICE_OUTPUTS/$1
|
d=/run/service-state/$1
|
||||||
mkdir -m 2751 -p $d && chown root:system $d
|
|
||||||
echo $d
|
|
||||||
}
|
|
||||||
mkstate() {
|
|
||||||
d=$SERVICE_STATE/$1
|
|
||||||
mkdir -m 2751 -p $d && chown root:system $d
|
mkdir -m 2751 -p $d && chown root:system $d
|
||||||
echo $d
|
echo $d
|
||||||
}
|
}
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
stdenv
|
|
||||||
, openwrt
|
|
||||||
}:
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
name = "zyxel-bootconfig";
|
|
||||||
inherit (openwrt) src;
|
|
||||||
sourceRoot = "openwrt-source/package/utils/zyxel-bootconfig/src";
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out/bin
|
|
||||||
install -Dm544 zyxel-bootconfig $out/bin/zyxel-bootconfig
|
|
||||||
'';
|
|
||||||
meta = {
|
|
||||||
mainProgram = "zyxel-bootconfig";
|
|
||||||
};
|
|
||||||
}
|
|
@ -12,7 +12,7 @@ let derivation = (import liminix {
|
|||||||
img = derivation.outputs.tftpboot;
|
img = derivation.outputs.tftpboot;
|
||||||
uboot = derivation.outputs.u-boot;
|
uboot = derivation.outputs.u-boot;
|
||||||
pkgsBuild = derivation.pkgs.pkgsBuildBuild;
|
pkgsBuild = derivation.pkgs.pkgsBuildBuild;
|
||||||
in pkgsBuild.runCommand "check-${deviceName}" {
|
in pkgsBuild.runCommand "check" {
|
||||||
nativeBuildInputs = with pkgsBuild; [
|
nativeBuildInputs = with pkgsBuild; [
|
||||||
expect
|
expect
|
||||||
socat
|
socat
|
||||||
@ -44,11 +44,4 @@ in {
|
|||||||
mipsLz = check "qemu" {
|
mipsLz = check "qemu" {
|
||||||
boot.tftp.compressRoot = true;
|
boot.tftp.compressRoot = true;
|
||||||
};
|
};
|
||||||
# this works on real hardware but I haven't figured out how
|
|
||||||
# to make it work on qemu: it says
|
|
||||||
# "OF: fdt: No chosen node found, continuing without"
|
|
||||||
|
|
||||||
# mipsOldUboot = check "qemu" {
|
|
||||||
# boot.tftp.appendDTB = true;
|
|
||||||
# };
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user