2
0

84 Commits

Author SHA1 Message Date
dan 9ab77a7d7e remove unused function 2025-03-09 20:44:35 +00:00
dan c6918fec00 firewall: use extraText for zone set contents
* the lua necessary is quite wordy, but it's less of a hack than
post-processing the rules file with pseudo-sed to get rid of `elements
= { }` lines

* also switch from stop/starting the firewall service to using a
signal, so that we don't go briefly offline every time a new interface
appears
2025-03-09 20:42:02 +00:00
dan d4e46dbe28 secrets/subscriber don't depend on the services we're watching
this means a watched service can stop and start without killing
the subscriber, and that we can watch for services that don't
yet exist
2025-03-09 20:35:40 +00:00
dan d1f87a56e0 secrets/subscriber: use correct numbers for signals to s6-svc 2025-03-09 20:34:29 +00:00
dan 8c39b47cae output-template: allow splicing statements instead of expression
if the text inside the delimiters begins with ; (a semicolon) then
the rest of it is expected to be one or more Lua statements. It needs
to say `return "foo"` to interpolate anything, as there is no
implicit return of the value of the last statement
2025-03-05 22:38:48 +00:00
dan 2c7a16d792 firewallgen: add extraText param to set
anything in here is added verbatim to the set definition
2025-03-05 22:36:35 +00:00
dan d6b06abb63 delet second copy of output-template 2025-03-02 21:34:02 +00:00
dan 6b32aa569e think 2025-03-02 21:21:45 +00:00
dan 234d1bd87e basic unit tests for output-template 2025-03-02 21:14:46 +00:00
dan c38f180fb7 output-template expose table module 2025-03-02 21:14:16 +00:00
dan 9a8b22997c output-template: pass the tests 2025-03-02 21:09:32 +00:00
dan c32d09bd83 output-template: run the tests 2025-03-02 21:09:11 +00:00
dan 6649ebeccd firewall: use watch-outputs to track changes in zone->interface map
includes a horrible hack to work around (claimed (by me)) deficiencies
in the nftables parser
2025-02-28 00:43:20 +00:00
dan 929226ed9e delete commented code 2025-02-27 20:55:30 +00:00
dan a98f026210 think 2025-02-27 20:54:44 +00:00
dan f4dc001b71 check firewall zones in pppoe test 2025-02-25 23:32:05 +00:00
dan 024c018262 run the output-template test 2025-02-22 00:10:19 +00:00
dan e1293e3778 think 2025-02-21 23:22:39 +00:00
dan 0c406058e9 remove acceotance of udp sport 5 on wan
this was added for replies to dns queries but isn't needed for
that purpose as connection tracking does that anyway
2025-02-12 21:54:01 +00:00
dan 19d441333c remove duplicate rule 2025-02-10 23:50:07 +00:00
dan a726c09ae4 improve explanaton of reverse path filtering rule
thanks RoS for the references :-)
2025-02-10 23:48:29 +00:00
dan 7e2b0068e6 nixfmt-rfc-style
There is nothing in this commit except for the changes made by
nix-shell -p nixfmt-rfc-style --run "nixfmt ."

If this has mucked up your open branches then sorry about that. You
can probably nixfmt them to match before merging
2025-02-10 21:55:08 +00:00
dan 13cc5a8992 Merge pull request 'support firewall zones: don't hardcode interface names in rules' (#16) from firescape into main
Reviewed-on: #16
2025-02-10 21:23:15 +00:00
dan 3f889c7119 default firewall zones in gateway profile 2025-02-10 21:21:08 +00:00
dan 7f17125039 firewall: update zones with interface names as they appear 2025-02-10 21:21:08 +00:00
dan 4bb081ffcf export anoia.svc:fileno so it can be used with event loops 2025-02-10 21:21:08 +00:00
dan 6587813577 WIP add zones to firewall module
- zones are an attrset of name -> [interface-service]

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

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

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

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

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

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

this is very copy-pastey, will tidy it up after it
stops being a moving target
2025-01-03 23:52:08 +00:00
dan 13cb8d3692 sort imports 2025-01-03 15:41:22 +00:00
dan 62b7aea8ab add btrfs.nix to outputs imports 2025-01-03 15:40:33 +00:00
dan 76e3fd9a55 add rt3200 to CI 2025-01-03 15:39:08 +00:00
dan 92284fa9ba mtdimage can't be a default import
it adds kernel config that depend on openwrt patches,
which aren't used/needed on all devices
2025-01-03 00:19:17 +00:00
dan a2bb55e885 oops fix syntax error 2025-01-03 00:07:00 +00:00
dan 74027b44d7 extract log persistence config from s6 to new module
because it frobs kernel config, it breaks levitate
as levitate evalModules doesn't include the kernel
2025-01-02 23:56:49 +00:00
dan ea5370b3f4 import mtdimage in outputs 2025-01-02 23:37:07 +00:00
dan 55ed365920 turris omnia: default rootfs and bootloader settings 2025-01-02 23:36:15 +00:00
dan aa2160dd05 logtap: fix indentation
spaces not tabs
2025-01-02 22:45:00 +00:00
dan df414b796f drivel 2025-01-02 22:19:49 +00:00
dan 7377f7ceb2 implement mechanism for reverting from update.sh 2025-01-02 22:19:49 +00:00
dan 49432aeda5 Merge pull request 'Fix typo: Buildiing -> Building' (#15) from raboof/liminix:typo into main
Reviewed-on: #15
Reviewed-by: dan <dan@telent.net>
2025-01-02 14:46:36 +00:00
Arnout Engelen 3caf8a75bb Fix typo: Buildiing -> Building 2025-01-02 10:53:38 +01:00
dan cc94ef57fa in rc.init copy log from previous boot to place of safety 2025-01-01 18:22:45 +00:00
dan fd28f0ce04 rt3200 needs pmsg-size set in its dts for persistent logging 2025-01-01 14:11:22 +00:00
dan 497307588f automate ubimage instructions a little 2025-01-01 12:38:08 +00:00
dan 788169586f /boot is a directory, copy files instead of replacing it with symlink
for the record, u-boot doesn't like having /boot/fit -> ../nix/store/..../fit
symlinks so we don't use symlinks inside /boot either
2025-01-01 12:29:25 +00:00
dan 3af9e86624 rt3200: replace bootcmd variable
the default is to boot to recovery if there's anything in pstore, but
this doesn't interact well with persstent logging
2025-01-01 11:56:54 +00:00
dan 28d39cd66d provide etc/kconfig in updater output
this is for debugging/documentation purposes and isn't copied to the
device
2025-01-01 11:55:33 +00:00
dan 9dd169d500 add "config" output to kernel derivation 2025-01-01 11:54:46 +00:00
dan 2e513eb4a7 example sni proxy using nginx 2024-12-29 23:34:15 +00:00
dan f2e4e77d73 firewall: don't use oifname in input rules
because it's empty, these are input rules for the local machine
2024-12-29 23:17:31 +00:00
dan 48dfbe0c01 add nginx-small : nginx with finegrained configure options 2024-12-29 20:47:03 +00:00
dan 6f697db57c remove PSTORE from rt3200 default kconfig
we have config.logging.persistent.enable at home
2024-12-29 13:33:55 +00:00
dan fe1ee12e3d swap strchr for strchrnul in dropbear authkeyfile patch
The strchrnul version was giving weird crashes on aarch64
belkin-rt3200. I haven't figured out why but this one doesn't
2024-12-29 13:30:21 +00:00
dan 4d273a9469 dropbear would like /etc/shells to exist 2024-12-29 13:27:49 +00:00
dan 40db175b41 complain if user attempting to tftpboot a ubifs 2024-12-29 13:26:45 +00:00
dan ab07212a7e include jffs2 module per default
it has no effect unless enabled
2024-12-29 13:26:06 +00:00
dan f5e08ac9d9 rt3200 default to loader.fit 2024-12-29 13:25:26 +00:00
dan 0cb18eabcd boot.expect: improve reliability
don't depend on seeing u-boot prompt, it's just too easy to get
out of sync
2024-12-27 18:08:01 +00:00
dan 24151425b8 and fix quoting 2024-12-24 14:29:01 +00:00
dan e06295ed83 rt3200: add fw_setenv commands to update boot_production 2024-12-24 14:19:29 +00:00
dan 608d3e3abf proofread 2024-12-24 14:01:30 +00:00
dan 3e19f1b927 Merge branch 'runciter' 2024-12-24 13:47:27 +00:00
dan 3f6e9b6384 rt3200 defaults to ubifs 2024-12-24 13:46:36 +00:00
dan 294492a176 jiggle imports 2024-12-24 13:46:19 +00:00
dan 67a1cd3718 improve install instructions for belkin rt3200 2024-12-24 13:45:11 +00:00
dan 452aaa2f60 Merge pull request 'use Linux kernel sources associated with openwrt by default' (#12) from raboof/liminix:linux-version-with-openwrt into main
Reviewed-on: #12
2024-12-24 12:24:31 +00:00
dan 52967f746b Merge branch 'main' into linux-version-with-openwrt 2024-12-24 12:24:13 +00:00
Arnout Engelen a89f866bf0 use Linux kernel sources associated with openwrt by default 2024-12-24 12:21:28 +00:00
dan f3fadd5cd7 think 2024-12-24 12:20:48 +00:00
Arnout Engelen 1ff779c1a9 use Linux kernel sources associated with openwrt by default 2024-12-17 20:24:14 +01:00
242 changed files with 7595 additions and 4010 deletions
+526
View File
@@ -6670,3 +6670,529 @@ Mon Dec 23 18:28:50 GMT 2024
it might be worth moving ubi option decls into the hardware module, if
they're hardware-dependent
Tue Dec 24 16:14:50 GMT 2024
Where next?
a config for haproxy would be good
> a connection or request arrives on a frontend, then the
information carried with this request or connection are processed, and
at this point it is possible to write ACLs-based conditions making use
of these information to decide what backend will process the request.
http://docs.haproxy.org/3.1/intro.html#3.4.4
listen foo
bind :443
frontend foo
mode tcp
Thu Dec 26 14:27:26 GMT 2024
What's the plan?
1) build the updater target for rotuer
2) ssh forward through bordervm to install it
3) carve the ngix sni proxy into examples/module-sniproxy
with a fat warning comment
3.5) should we add the examples to ci?
4) see if it builds
5) using curl on bordervm, see if it forwards
5000) swap the real rotuer hardware
Sun Dec 29 18:22:42 GMT 2024
To make sniproxy work it needs dns, which means it needs an upstream.
But if we move the bordervm cable from lan to wan, we won't be able to
rebuild over ssh unless it's sufficiently unbroken for pppoe to be working
... unless we add a "management" address to the wan interface along with pppoe
to permit wan stuff through the firewall, now that we've fixed the
firewall :embarrassed:, do
/nix/store/*nftables*/bin/nft insert rule table-ip input-ip4 position 19 iifname "wan" jump incoming-allowed-ip4
What else do we need to try rt3200 as prod rotuer?
- pstore logging
- log shipping (maybe via wan to bordervm for now)
- enable sniproxy module
zcat /proc/config.gz | grep PSTORE
Tue Dec 31 22:45:33 GMT 2024
/nix/store/i1khbsqpyx020xrhvfbdazc1bnmirc72-kernel-aarch64-unknown-linux-musl-modulesupport/vmlinux
these 3 derivations will be built:
/nix/store/fvxrvyx64cm86cc4na0584qj9xw6s406-kernel-aarch64-unknown-linux-musl.drv
/nix/store/ksg93bd8x2z1xpfmj24ixm2srg547mjx-dtb-aarch64-unknown-linux-musl.drv
/nix/store/n33ij1npzwjmlsw23sz6yhyrh9hgxwaw-kernel.image-aarch64-unknown-linux-musl.drv
building '/nix/store/fvxrvyx64cm86cc4na0584qj9xw6s406-kernel-aarch64-unknown-linux-musl.drv'...
zcat /proc/config.gz | grep PSTORE
we think tftpboot works (check!)
build the FIT from the updater target with squashfs added in rotuer.nix
boot it with tftp by copy-pasting the boot.scr and changing it
setenv serverip 10.0.0.1
setenv ipaddr 10.0.0.8
tftpboot 0x4007ff28 r2/rootfs; tftpboot 0x41086f28 r2/image; tftpboot 0x4107ff28 r2/dtb
bootm 0x41086f28 - 0x4107ff28
tftpboot works
tftpboot with outputs.uimage works
1458ed2cdeaa6bf4c02c6511a6d7369d /nix/store/4n3jc4n7lsp73yc2ccnmgibc7079rxms-kernel.image-aarch64-unknown-linux-musl
$ grep fit /nix/store/ihi7vski37b9ph4xcyqpabymc5nsngjd-system-configuration-aarch64-unknown-linux-musl/etc/nix-store-paths
/nix/store/5jphs9mnb8hzhvwfi2z8h6cnaz6qx4y6-boot-fit
$ md5sum /nix/store/5jphs9mnb8hzhvwfi2z8h6cnaz6qx4y6-boot-fit/fit
1458ed2cdeaa6bf4c02c6511a6d7369d /nix/store/5jphs9mnb8hzhvwfi2z8h6cnaz6qx4y6-boot-fit/fit
something is changing /persist/boot from a symlink to a directory and I don't know what
... plot twist: or is it? maybe it's ubimage that makes it a directory
rt3200 has no pmsg-size according to dtc -I fs /proc/device-tree/ -O dts
should be more like
reserved-memory {
ramoops@03f00000 {
compatible = "ramoops";
reg = <0x03f00000 0x10000>;
pmsg-size = <0x10000>;
};
};
};
Wed Jan 1 14:57:35 GMT 2025
At last I have working persistent logging.
I think we need to do something at boot time to move the persistent logs into
the regular s6 log thing
foreground {
redirfd -w 1 /run/prior-boot2
elglob file /sys/fs/pstore/* cat $file
}
Thu Jan 2 14:31:11 GMT 2025
to change to a previous "generation" we could run any of
"/nix/store/*system-configuration*/bin/install /mnt" from a rescue
system. It would populate /boot and bin/activate
supposing we are in such a rescue system, how do we find *which*
system-configuration is the one we want to revert to? The derivation
should be pure, so if we're going to timestamp anything we have to do
that in the imperative step i.e. update.sh
perhaps a symlink from /persist/configuration/yyyymmddtmmhhss -> /nix/store/eeee-blah
Thu Jan 2 23:38:59 GMT 2025
Stuff we should tidy up:
1) all devices to set credible default output, rootfs, etc
2) expunge remaining references to kexecboot
3) dynamic uid assigment for users
4) lessen logging noise from firewall
5) update.sh --fast sends wlan services for a spin
Fri Jan 3 16:05:10 GMT 2025
* build actual rotuer config and install on rt3200
* find usb ethernet dongle for laptop
* plug it in?
Sat Jan 4 15:32:03 GMT 2025
didn't work so well, because the installer version is coupled with the
dtb and the dtb can't be upgraded without upgrading the kenrel
kernel 6.6.67 builds and boots but seems to have no wired ethernet.
looking through the openwrt config changes ...
+CONFIG_MTD_UBI_NVMEM=y
+CONFIG_NVMEM_BLOCK=y
+CONFIG_NVMEM_LAYOUT_ADTRAN=y
+CONFIG_PHYLIB_LEDS=y
+CONFIG_MTK_REGULATOR_COUPLER=y
+CONFIG_FW_LOADER_SYSFS=y
Sun Jan 5 12:58:52 GMT 2025
We are running with rt3200 and everything appears to work :-)
Sun Jan 5 20:34:18 GMT 2025
what customization do we want from the firewall?
- what's allowed wan->lan
- what's allowed lan->wan
- which dropped packets get logged or don't
plus fix whatever it was RoS found
plus stop hardcoding the interface names
Q: if pppd _makes_ an interface, how do we know what the name of it
is going to be before it's up and passing packets so that we can
have the firewall active before it starts
or could we have ppp service install a "drop everything" firewall
before it starts? what if there's more than one upstream interface,
they shouldn't wipe each other out
so can we have a "default deny" firewall in which every allowed flow
is qualified by the interface name, and any service that brings up an
interface is required to add firewall rules for it according to its
role
or maybe the firewall service could watch for interfaces being added
(and removed) and update the ruleset as appropriate for the interface
role (lan, wan, dmz, management, guest, ???). but how does it know
the role based on the interface name?
Tue Jan 14 19:33:28 GMT 2025
each interface can add its own chain when it comes up, and then we can
figure out some way to jump to the correct chain (vmaps) based on
interface name
% nft add map filter mydict { type ipv4_addr : verdict\; }
% nft add element filter mydict { 192.168.0.10 : drop, 192.168.0.11 : accept }
% nft add rule filter input ip saddr vmap @mydict
_but_ we might be better off declaring static "zones" (lan, world,
dmz, guest, etc etc) with a map for each, and then replace the hardcoded
interface names with a map lookup
% nft add map filter ifzone { type ifname : string ; }
zones { type ifname: ipv4_addr\; }
... and presumably we also need identical maps for nat and
... any other chain type where we need to distinguish
... inside from outside
% nft add element nat porttoip { 80 : 192.168.1.100, 8888 : 192.168.1.101 }
% nft add rule ip nat postrouting snat to tcp dport map @porttoip
Mon Jan 20 20:32:58 GMT 2025
1) maybe we can add a type="chain" or type="set" attribute to the
firewallgen input, then we cna have sets in the default firewall rules
2) then we convert the default firewall rules to use sets instead of
hardcoding ifname
3) then find a nice place to hook "new interface is available" and
add it to the appropriate zone (separately for ip4 and ip6, gah)
4) and how do we find
# nft add element ip table-ip lan { int }
# nft add element ip table-ip wan { ppp0 }
# nft add element ip6 table-ip6 lan { int }
# nft add element ip6 table-ip6 wan { ppp0 }
Tue Jan 28 21:51:46 GMT 2025
Going back and forth on the firewall stuff, in respect of where to aim
for with "general" vs "useful". Specifically, if we have hooks
every time interfaces are added/removed that
expect some specific sets to (a) exist and (b) have particular
semantics, there is necessary coupling between those hooks and the
firewall definition. So, practically speaking, the "a new interface
appears" rules need to be bundled with the firewall ruleset
Which also means that the firewall needs to know which zone the
interface is assigned to, which is a problem if it can't tell from the
name (for example wg0 wg1 wg2 ... could be wan or lan or dmz or
anything)
So the service that owns the interface needs to communicate "another
one for the lan zone" to the firewall and it can't do that by adding
to sets directly unless it knows what the sets are called. Implying we
need an interface between the interface service that knows "new
interface ppp7 added in wan zone" and the firewall service that knows
how to accommodate this. For extra credit this actually should be more
like pubsub: the interface shouldn't really have to know the firewall
exists.
outputs?
- what if each interface wrote a "zone" output and the firewall
subscribed to them? would need the firewall to know which of all the
available services were interfaces
- a zone service that every interface in the zone depends on. it
doesn't do much in itself but it means the interface updown scripts
know a service directory where they can touch lan-zone/eth0 or
whatever. This could work. The firewall service definition specifies
the zone services and uses inotify watcher thingies to update
interface sets when contents change.
Wed Jan 29 17:19:24 GMT 2025
1) make a zone service defn that can be instantiated for each zone.
it should create $output/interfaces
2) add a `zone` attribute to interface definitions, causing
- the zone service to be added to the dependencies
- the interface "up" script to include writing to the zone/interfaces output
2b) any other service that creates an interface (e.g. ppp) needs to also
have `zone` and do the same
3) firewallgen to be able to make sets
4) firewall service to watch the zone outputs
Fri Jan 31 17:11:16 GMT 2025
Do we need zone services? I think we could put zones in the outputs of
the firewall service?
Sun Feb 2 20:59:56 GMT 2025
What's the smallest first step?
- [done] how can we make firewallgen output sets (or could we
make the firewall service tack them on afterwards)
- make a longrun that watches its own zones output and updates the
appropriate sets
The sticking point is that if you give the firewall `rules` instead of
`extraRules` then the longrun may or may not work depending on (1)
whether you made the zone sets; (2) whether your rules use
them. Conclusion: if you supply `rules` then you also have to say
whether you want the longrun or not. So add a param
watchForInterfaceUpdates which defaults true
Mon Feb 3 21:12:55 GMT 2025
the thing that updates sets has to know they exist, so the interface watcher
service must live in the firewall module
the firewall service defn should return the firewall service after
adding the interface watcher as a dependency of it. Or: the watcher
should make the sets and then the firewall service could depend on _it_.
That would mean that the firewall service would fail if it used sets
that the watcher didn't make, is that good or bad or indifferent?
the interface services have to know about the watcher as well in order
to write into its outputs, so it can't be hidden inside the module
maybe the watcher service should _be_ the firewall service.
we could add a "notify" param to an interface which would be an output
reference to (the firewall service / zones / lan ) that the interface would
write its ifname into when the service is up
Wed Feb 5 00:14:29 GMT 2025
another thought: the firewall service could have params to say
which interface services are in which zones
we'd have to ensure that the interface services did not end up as
dependencies of the firewall
then the firewall could
- create the sets
- watch each interface service for the ifname output and add it to the right zone
Sun Feb 9 21:33:57 GMT 2025
nft update set @lan
echo 'flush set table-ip lan; add element table-ip lan { eth0,lo }' | nft -f -
Tue Feb 11 18:30:09 GMT 2025
outstanding for 1.0:
1) security audit fedback
a) ask ROS if I can ship their report, with a response doc
showing the commits that address each finding/non-finding
b) firewall rules: icmp rate limit, DNS, doc for icmpv6 packet dropping
c) look over env var inputs and parse them properly instead of
string glommeration
2) docs:
- for each device, add "finishedness" status and link to build status
- generally read them over and spruce up
- porting guide
3) some kconfig magic to generate minimal kconfig files so that
device modules don't end up as copy-pastes of the openwrt defconfig
---
apparently 5% of available bandwidth is a reasonable rate limit for
icmp
% nft add rule filter input limit rate over 10 mbytes/second drop
but nftables has no way to get interface bandwidth and indeed nor does
the device generally: the 1000Mb/s ethernet interface might be
connected to a 70Mb/s pppoe upstream and how would it know? So the
site operator needs to say somewhere what the upstream bandwidth is.
Sun Feb 16 22:16:29 GMT 2025
we probably didn't need to write that service, we could have used the
thing that makes templated config files _and_ if we somehow contrive
to write the interface bandwidth as an interface output we could get
that the same way
if only I could remember how it worked :-)
----
* watch-output watches only _one_ service and is called with a list of
outputs inside that service, so not exactly what we need. we can
extend it easily enough to watch multiple services using poll() if we
can figure out the syntax we want. Luckily all the places that call it
go through modules/secrets/subscriber.nix so it's easy enough to change
existing uses
we could do
watch-outputs -r foo /nix/store/blah/.outputs/ifname /nix/store/eee/.outputs/ifname ...
or
watch-outputs -r foo /nix/store/blah:ifname /nix/store/eee:ifname /nix/store/eee:bandwidth
or
watch-outputs -r foo /nix/store/blah:ifname /nix/store/eee:ifname:bandwidth
which I quite like insofar as it's shorter but has no other real merit
then we need to decide how to represent an output reference in a firewall rule.
Since each rule is basically text already, might just put the handlebars straight in
let qq = builtins.toJSON ;
in "icmp6 limit rate over {{ tonumber(output(${qq (intf "service")}, ${qq (intf "bandwidth")})) / 20 }} bytes/second drop"
probably we should do a separate rule for each interface in the wan zone
Sun Feb 23 00:34:34 GMT 2025
looks like we have no tests for anything involving watched services or subscribers,
or if we do I can't see what
Thu Feb 27 20:47:03 GMT 2025
- use output-template to write firewall rule file
- wrap firewall in svc.secrets.subscriber.build (c.f. e745991) with zones as
watched services
- put the handlebars in the firewall config
we have uncommitted changes to watch-outputs that I'm relunctant to
commit until I have some way to see if they're working. the pppoe test
will check both firewall zones so _should_ start to fail with the
current watch-outputs (because only one service) and then pass when we
put the new one in
Fri Feb 28 01:00:03 GMT 2025
Well, it works at least well enough to pass the test. There is an awful hack
though, because nftables doesn't accept "elements = { }" as valid syntax
for a set with no elements, so we post-process the file to wipe those lines
I wonder if we could instead create the set empty and then use the "other"
nftables format to generate commands that add the elements. If it's
all in the same file (or included files) it will continue to be atomic
Other options
- is the nftables json format any better? we will have to rebuild it
with json support, may be bugger
- write lua bindings to libnftables
Fri Feb 28 23:31:06 GMT 2025
adding json would add 76 + 88k to the image, but I think it would also
mean we have to rewrite all the default rules in json format
with json
[dan@loaclhost:~/src/liminix]$ du result/
20 result/share/doc/nftables/examples
24 result/share/doc/nftables
28 result/share/doc
12 result/share/man/man3
16 result/share/man/man5
44 result/share/man/man8
76 result/share/man
60 result/share/nftables
168 result/share
36 result/etc/nftables/osf
40 result/etc/nftables
44 result/etc
76 result/bin
8 result/include/nftables
12 result/include
8 result/lib/pkgconfig
1172 result/lib
1476 result/
[dan@loaclhost:~/src/liminix]$ du /nix/store/l0zsvldsskiv52b4c9b21ziq5z1qr7vn-jansson-mips-unknown-linux-musl-2.14/
84 /nix/store/l0zsvldsskiv52b4c9b21ziq5z1qr7vn-jansson-mips-unknown-linux-musl-2.14/lib
88 /nix/store/l0zsvldsskiv52b4c9b21ziq5z1qr7vn-jansson-mips-unknown-linux-musl-2.14/
without:
[dan@loaclhost:~/src/liminix]$ du result/
20 result/share/doc/nftables/examples
24 result/share/doc/nftables
28 result/share/doc
12 result/share/man/man3
16 result/share/man/man5
44 result/share/man/man8
76 result/share/man
60 result/share/nftables
168 result/share
36 result/etc/nftables/osf
40 result/etc/nftables
44 result/etc
76 result/bin
8 result/include/nftables
12 result/include
8 result/lib/pkgconfig
1096 result/lib
1400 result/
Sat Mar 1 23:43:17 GMT 2025
I don't think json is going to help because either we'd have to do
elements = map (f: "{{ lookup(f, \"ifname\") }}") zones.${zone}
and there would be null elements in the places for the interfaces that don't exist
yet, or we'd have to write actual json syntax at runtime, at which point why don't
we write the trad nftables syntax instead?
let's write a firewall .nftables file consisting of the zone set
elements plus an "include" directive for the rest of the firewall. NOTE THAT
we may still need to template the rest of the firewall if we want to have
other variables (rate limits) in it, because the rules for that need to be
inserted ahead of the rules for accepting icmp, and there's no way to
do that without
+31 -9
View File
@@ -2,19 +2,41 @@
# use expect as its "Script program" instead of runscript. Try
# Ctrl+A O -> Filenames and paths -> D
fconfigure stderr -buffering none
fconfigure stdout -buffering none
proc waitprompt { } {
expect {
"BusyBox" { puts stderr "DONE\r"; exit 0 }
"READY" { puts stderr ";;; READY\r"; }
timeout { puts stderr ";;; timed out waiting after $line\r" }
}
}
proc sendline { line } {
send "$line; echo \$ready \r"
sleep 0.1
}
log_user 0
log_file -a -open stderr
set f [open "result/boot.scr"]
send "version\r"
set timeout 60
send "setenv ready REA\r"
sleep 0.1
send "setenv ready \${ready}DY\r"
sleep 0.1
set timeout 300
expect_before timeout abort
while {[gets $f line] >= 0} {
puts stderr "next line $line\r"
puts stderr "waiting for prompt\r"
expect {
"ath>" {}
"BusyBox" { puts stderr "DONE"; exit 0 }
}
send "$line\r\n"
puts stderr ";;; next line $line\r"
puts stderr ";;; waiting for prompt\r"
puts stderr ";;; sending\r"
sendline $line
waitprompt
}
puts stderr "done\r\n"
close $f
+46 -19
View File
@@ -1,8 +1,21 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.bordervm;
inherit (lib) mkOption mkEnableOption mdDoc types optional optionals;
in {
inherit (lib)
mkOption
mkEnableOption
mdDoc
types
optional
optionals
;
in
{
options.bordervm = {
keys = mkOption {
type = types.listOf types.str;
@@ -107,13 +120,14 @@ in {
from = "host";
host.port = 7654;
# guest.address = "10.0.2.15";
guest.port =7654;
guest.port = 7654;
}
{
host.port = 2222;
guest.address = "10.0.2.15";
guest.port = 22;
}];
}
];
qemu = {
networkingOptions = [ ];
options =
@@ -139,28 +153,41 @@ in {
services.tang = {
enable = true;
ipAddressAllow = [ "10.0.0.0/24" "0.0.0.0/0" ];
ipAddressAllow = [
"10.0.0.0/24"
"0.0.0.0/0"
];
};
environment.systemPackages =
let wireshark-nogui = pkgs.wireshark.override { withQt = false ; };
in with pkgs; [
tcpdump
wireshark-nogui
socat
tufted
iptables
usbutils
busybox
clevis
];
let
wireshark-nogui = pkgs.wireshark.override { withQt = false; };
in
with pkgs;
[
tcpdump
wireshark-nogui
socat
tufted
iptables
usbutils
busybox
clevis
];
security.sudo.wheelNeedsPassword = false;
networking = {
hostName = "border";
firewall = { enable = false; };
firewall = {
enable = false;
};
interfaces.eth1 = {
useDHCP = false;
ipv4.addresses = [ { address = "10.0.0.1"; prefixLength = 24;}];
ipv4.addresses = [
{
address = "10.0.0.1";
prefixLength = 24;
}
];
};
nat = {
enable = true;
+13 -9
View File
@@ -11,11 +11,14 @@ let
"qemu-aarch64"
"qemu-armv7l"
"tp-archer-ax23"
"openwrt-one"
"zyxel-nwa50ax"
"turris-omnia"
"belkin-rt3200"
];
vanilla = ./vanilla-configuration.nix;
for-device = name:
for-device =
name:
(import liminix {
inherit borderVmConf;
device = import (liminix + "/devices/${name}");
@@ -69,12 +72,13 @@ let
echo "file source-dist \"$out/share/doc/liminix\"" \
> $out/nix-support/hydra-build-products
'';
};
};
};
in jobs //
{
all = pkgs.mkShell {
name = "all tests";
contents = pkgs.lib.collect pkgs.lib.isDerivation jobs;
};
}
in
jobs
// {
all = pkgs.mkShell {
name = "all tests";
contents = pkgs.lib.collect pkgs.lib.isDerivation jobs;
};
}
+32 -22
View File
@@ -27,12 +27,18 @@ let
modulesPath = builtins.toString ./modules;
};
modules = [
{ _module.args = { inherit pkgs; inherit (pkgs) lim; }; }
{
_module.args = {
inherit pkgs;
inherit (pkgs) lim;
};
}
./modules/hardware.nix
./modules/base.nix
./modules/busybox.nix
./modules/hostname.nix
./modules/kernel
./modules/logging.nix
./modules/klogd.nix
device.module
liminix-config
@@ -46,30 +52,34 @@ let
};
config = eval.config;
borderVm = ((import <nixpkgs/nixos/lib/eval-config.nix>) {
system = builtins.currentSystem;
modules = [
{
nixpkgs.overlays = [
(final: prev: {
go-l2tp = final.callPackage ./pkgs/go-l2tp {};
tufted = final.callPackage ./pkgs/tufted {};
})
];
}
(import ./bordervm-configuration.nix)
borderVmConf
];
}).config.system;
in {
borderVm =
((import <nixpkgs/nixos/lib/eval-config.nix>) {
system = builtins.currentSystem;
modules = [
{
nixpkgs.overlays = [
(final: prev: {
go-l2tp = final.callPackage ./pkgs/go-l2tp { };
tufted = final.callPackage ./pkgs/tufted { };
})
];
}
(import ./bordervm-configuration.nix)
borderVmConf
];
}).config.system;
in
{
outputs = config.system.outputs // {
default = config.system.outputs.${config.hardware.defaultOutput};
optionsJson =
let o = import ./doc/extract-options.nix {
inherit pkgs eval;
lib = pkgs.lib;
};
in pkgs.writeText "options.json" (builtins.toJSON o);
let
o = import ./doc/extract-options.nix {
inherit pkgs eval;
lib = pkgs.lib;
};
in
pkgs.writeText "options.json" (builtins.toJSON o);
};
# this is just here as a convenience, so that we can get a
+263 -187
View File
@@ -4,13 +4,8 @@
******************************
This device is based on a 64 bit Mediatek MT7622 ARM platform,
and is "work in progress" in Liminix.
.. note:: The factory flash image contains ECC errors that make it
incompatible with Liminix: use the `OpenWrt
UBI Installer <https://github.com/dangowrt/owrt-ubi-installer>`_ to
rewrite the partition layout before you can use
Liminix with it
and is mostly feature-complete in Liminix but as of Dec 2024
has seen very little actual use.
Hardware summary
================
@@ -25,7 +20,11 @@
Installation
============
Installation is currently a manual process.
Liminix on this device uses the UBI volume management system to
perform wear leveling on the flash. This is not set up from the
factory, so a one-time step is needed to prepare it before Liminix
can be installed.
Preparation
-----------
@@ -33,9 +32,16 @@
To prepare the device for Liminix you first need to use the
`OpenWrt UBI Installer
<https://github.com/dangowrt/owrt-ubi-installer>`_ image to
rewrite the flash layout. You can do this in onw of two ways:
rewrite the flash layout. As of Jan 2025 there are two versions
of the installer available: the release version 1.0.2 and the
pre-release 1.1.3 and for Liminix you nee the pre-relese.
The release version of the installer creates UBI volumes
according to an older layout that is not compatible with
the Linux 6.6.67 kernel used in Liminix.
You can run the installer in one of two ways:
either follow the instructions to do it through the vendor web
interface, or you can drop to U-boot and use TFTP
interface, or you can drop to U-Boot and use TFTP
.. code-block:: console
@@ -44,16 +50,64 @@
MT7622> tftpboot 0x42000000 openwrt-mediatek-mt7622-linksys_e8450-ubi-initramfs-recovery-installer.itb
MT7622> bootm 0x42000000
This will write the new flash layout and then boot into a
"recovery" OpenWrt installation. Once it's finished booting into
Linux you can safely reboot
This will write the new flash layout and then boot into a
"recovery" OpenWrt installation.
Installing Liminix
------------------
Building/installing Liminix
----------------
This is a manual process: you need a :ref:`serial <serial>` conection and TFTP : follow the instructions at :ref:`system-outputs-ubimage`
The default target for this device is ``outputs.ubimage`` which
makes a ubifs image suitable for use with :command:`ubiupdatevol`.
To write this to the device we use the OpenWrt recovery system
installed in the previous step. In this configuration the
device assigns itself the IP address 192.168.1.1/24 on its LAN
ports and expects the connected computer to have 192.168.1.254
'';
.. warning:: The `ubi0_7` device in these instructions is correct
as of Dec 2024 (dangowrt/owrt-ubi-installer commit
d79e7928). If you are installing some time later, it
is important to check the output from
:command:`ubinfo -a` and make sure you are updating
the "liminix" volume and not some other one which had
been introduced since I wrote this.
.. code-block:: console
$ nix-build -I liminix-config=./my-configuration.nix --arg device "import ./devices/belkin-rt3200" -A outputs.default
$ cat result/rootfs | ssh root@192.168.1.1 "cat > /tmp/rootfs"
$ ssh root@192.168.1.1
root@OpenWrt:~# ubimkvol /dev/ubi0 --name=liminix --maxavsize
root@OpenWrt:~# ubinfo -a
[...]
Volume ID: 7 (on ubi0)
Type: dynamic
Alignment: 1
Size: 851 LEBs (108056576 bytes, 103.0 MiB)
State: OK
Name: liminix
Character device major/minor: 250:8
root@OpenWrt:~# ubiupdatevol /dev/ubi0_7 /tmp/rootfs
To make the new system bootable we also need to change some U-Boot variables.
``boot_production`` needs to mount the filesystem and boot the FIT image
found there, and :code:`bootcmd` needs to be told _not_ to boot the rescue
image if there are records in pstore, because that interferes with
``config.log.persistent``
.. code-block:: console
root@OpenWrt:~# fw_setenv orig_boot_production $(fw_printenv -n boot_production)
root@OpenWrt:~# fw_setenv orig_bootcmd $(fw_printenv -n bootcmd)
root@OpenWrt:~# fw_setenv boot_production 'led $bootled_pwr on ; ubifsmount ubi0:liminix && ubifsload ''${loadaddr} boot/fit && bootm ''${loadaddr}'
root@OpenWrt:~# fw_setenv bootcmd 'run boot_ubi'
For subsequent Liminix reinstalls, just run the
:command:`ubiupdatevol` command again. You don't need to repeat
the "Preparation" step and in fact should seek to avoid it if
possible, as it will reset the erase counters used for write
levelling. Using UBI-aware tools is therefore preferred over any
kind of "factory" wipe which will reset them.
'';
system = {
crossSystem = {
@@ -61,196 +115,218 @@
};
};
module = {pkgs, config, lib, lim, ... }:
let firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = ["installPhase"];
installPhase = ''
mkdir $out
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out
'';
};
in {
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (lib) mkIf;
firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = [ "installPhase" ];
installPhase = ''
mkdir $out
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out
'';
};
openwrt = pkgs.openwrt_24_10;
in
{
imports = [
../../modules/arch/aarch64.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/ubifs.nix
../../modules/outputs/ubimage.nix
];
config = {
kernel = {
extraPatchPhase = ''
${pkgs.openwrt.applyPatches.mediatek}
'';
config = {
PCI = "y";
ARCH_MEDIATEK = "y";
# ARM_MEDIATEK_CPUFREQ = "y";
kernel = {
extraPatchPhase = ''
${openwrt.applyPatches.mediatek}
'';
src = openwrt.kernelSrc;
version = openwrt.kernelVersion;
config = {
PCI = "y";
ARCH_MEDIATEK = "y";
# ARM_MEDIATEK_CPUFREQ = "y";
# needed for "Cannot find regmap for /infracfg@10000000"
MFD_SYSCON = "y";
MTK_INFRACFG = "y";
# needed for "Cannot find regmap for /infracfg@10000000"
MFD_SYSCON = "y";
MTK_INFRACFG = "y";
MTK_PMIC_WRAP = "y";
NVMEM_MTK_EFUSE="y";
# MTK_HSDMA="y";
MTK_SCPSYS="y";
MTK_SCPSYS_PM_DOMAINS="y";
# MTK_THERMAL="y";
MTK_TIMER="y";
MTK_PMIC_WRAP = "y";
DMADEVICES = "y";
MTK_HSDMA = "y";
MTK_SCPSYS = "y";
MTK_SCPSYS_PM_DOMAINS = "y";
# MTK_THERMAL="y";
MTK_TIMER = "y";
COMMON_CLK_MT7622 = "y";
COMMON_CLK_MT7622_ETHSYS = "y";
COMMON_CLK_MT7622_HIFSYS = "y";
COMMON_CLK_MT7622_AUDSYS = "y";
PM_CLK="y";
COMMON_CLK_MT7622 = "y";
COMMON_CLK_MT7622_ETHSYS = "y";
COMMON_CLK_MT7622_HIFSYS = "y";
COMMON_CLK_MT7622_AUDSYS = "y";
PM_CLK = "y";
REGMAP_MMIO = "y";
CLKSRC_MMIO = "y";
REGMAP = "y";
REGMAP_MMIO = "y";
CLKSRC_MMIO = "y";
REGMAP = "y";
MEDIATEK_GE_PHY = "y";
# MEDIATEK_MT6577_AUXADC = "y";
NET_MEDIATEK_SOC = "y";
NET_MEDIATEK_SOC_WED = "y";
NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO
NET_VENDOR_MEDIATEK = "y";
PCIE_MEDIATEK = "y";
MEDIATEK_GE_PHY = "y";
# MEDIATEK_MT6577_AUXADC = "y";
NET_MEDIATEK_SOC = "y";
NET_MEDIATEK_SOC_WED = "y";
NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO
NET_VENDOR_MEDIATEK = "y";
PCIE_MEDIATEK = "y";
BLOCK = "y"; # move this to base option
BLOCK = "y"; # move this to base option
SPI_MASTER = "y";
SPI = "y";
SPI_MEM="y";
SPI_MTK_NOR="y";
SPI_MTK_SNFI = "y";
SPI_MASTER = "y";
SPI = "y";
SPI_MEM = "y";
SPI_MTK_NOR = "y";
SPI_MTK_SNFI = "y";
MTD = "y";
MTD_BLOCK = "y";
MTD_RAW_NAND = "y";
MTD_NAND_MTK = "y";
MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table
MTD_NAND_ECC_MEDIATEK= "y";
MTD_NAND_ECC_SW_HAMMING= "y";
MTD_SPI_NAND= "y";
MTD_OF_PARTS = "y";
MTD_NAND_CORE= "y";
MTD_SPI_NOR= "y";
MTD_SPLIT_FIRMWARE= "y";
MTD_SPLIT_FIT_FW= "y";
MTD = "y";
MTD_BLOCK = "y";
MTD_RAW_NAND = "y";
MTD_NAND_MTK = "y";
MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table
MTD_NAND_ECC_MEDIATEK = "y";
MTD_NAND_ECC_SW_HAMMING = "y";
MTD_SPI_NAND = "y";
MTD_OF_PARTS = "y";
MTD_NAND_CORE = "y";
MTD_SPI_NOR = "y";
MTD_SPLIT_FIRMWARE = "y";
MTD_SPLIT_FIT_FW = "y";
MTD_UBI_NVMEM = "y";
NVMEM_MTK_EFUSE = "y";
NVMEM_BLOCK = "y";
NVMEM_LAYOUT_ADTRAN = "y";
MMC = "y";
MMC_BLOCK = "y";
MMC_CQHCI = "y";
MMC_MTK = "y";
MMC = "y";
MMC_BLOCK = "y";
MMC_CQHCI = "y";
MMC_MTK = "y";
# Distributed Switch Architecture is needed
# to make the ethernet ports visible
NET_DSA="y";
NET_DSA_MT7530="y";
NET_DSA_TAG_MTK="y";
# Distributed Switch Architecture is needed
# to make the ethernet ports visible
NET_DSA = "y";
NET_DSA_MT7530 = "y";
NET_DSA_TAG_MTK = "y";
NET_DSA_MT7530_MDIO = "y";
PSTORE = "y";
PSTORE_RAM = "y";
PSTORE_CONSOLE = "y";
PSTORE_DEFLATE_COMPRESS = "n";
SERIAL_8250 = "y";
SERIAL_8250_CONSOLE = "y";
SERIAL_8250_MT6577 = "y";
# SERIAL_8250_NR_UARTS="3";
# SERIAL_8250_RUNTIME_UARTS="3";
SERIAL_OF_PLATFORM = "y";
SERIAL_8250 = "y";
SERIAL_8250_CONSOLE = "y";
SERIAL_8250_MT6577="y";
# SERIAL_8250_NR_UARTS="3";
# SERIAL_8250_RUNTIME_UARTS="3";
SERIAL_OF_PLATFORM="y";
# Must enble hardware watchdog drivers. Else the device reboots after several seconds
WATCHDOG = "y";
MEDIATEK_WATCHDOG = "y";
};
conditionalConfig = {
WLAN= {
MT7615E = "m";
MT7622_WMAC = "y";
MT7915E = "m";
};
};
};
boot = {
commandLine = [ "console=ttyS0,115200" ];
tftp.loadAddress = lim.parseInt "0x4007ff28";
imageFormat = "fit";
};
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in
dir {
lib = dir {
firmware = dir {
mediatek = symlink firmware;
};
};
};
hardware =
let
openwrt = pkgs.openwrt;
mac80211 = pkgs.kmodloader.override {
targets = ["mt7615e" "mt7915e"];
inherit (config.system.outputs) kernel;
};
in {
ubi = {
minIOSize = "2048";
logicalEraseBlockSize = "126976";
physicalEraseBlockSize = "131072";
maxLEBcount = "1024"; # guessing
};
defaultOutput = "ubimage";
# the kernel expects this to be on a 2MB boundary. U-Boot
# (I don't know why) has a default of 0x41080000, which isn't.
# We put it at the 32MB mark so that tftpboot can put its rootfs
# image and DTB underneath, but maybe this is a terrible waste of
# RAM unless the kernel is able to reuse it later. Oh well
loadAddress = lim.parseInt "0x42000000";
entryPoint = lim.parseInt "0x42000000";
rootDevice = "ubi0:liminix";
dts = {
src = "${openwrt.src}/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts";
includePaths = [
"${openwrt.src}/target/linux/mediatek/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
};
# - 0x000000000000-0x000008000000 : "spi-nand0"
# - 0x000000000000-0x000000080000 : "bl2"
# - 0x000000080000-0x0000001c0000 : "fip"
# - 0x0000001c0000-0x0000002c0000 : "factory"
# - 0x0000002c0000-0x000000300000 : "reserved"
# - 0x000000300000-0x000008000000 : "ubi"
networkInterfaces =
let
inherit (config.system.service.network) link;
in rec {
wan = link.build { ifname = "wan"; };
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
lan = lan3;
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
# Must enble hardware watchdog drivers. Else the device reboots after several seconds
WATCHDOG = "y";
MEDIATEK_WATCHDOG = "y";
};
conditionalConfig = {
WLAN = {
MT7615E = "m";
MT7622_WMAC = "y";
MT7915E = "m";
};
};
};
boot = {
commandLine = [ "console=ttyS0,115200" ];
tftp.loadAddress = lim.parseInt "0x48000000";
imageFormat = "fit";
loader.fit.enable = lib.mkDefault true; # override this if you are building tftpboot
};
rootfsType = lib.mkDefault "ubifs"; # override this if you are building tftpboot
filesystem =
let
inherit (pkgs.pseudofile) dir symlink;
in
dir {
lib = dir {
firmware = dir {
mediatek = symlink firmware;
};
};
};
hardware =
let
mac80211 = pkgs.kmodloader.override {
targets = [
"mt7615e"
"mt7915e"
];
inherit (config.system.outputs) kernel;
};
in
{
ubi = {
minIOSize = "2048";
logicalEraseBlockSize = "126976";
physicalEraseBlockSize = "131072";
maxLEBcount = "1024"; # guessing
};
defaultOutput = "ubimage";
# the kernel expects this to be on a 2MB boundary. U-Boot
# (I don't know why) has a default of 0x41080000, which isn't.
# We put it at the 32MB mark so that tftpboot can put its rootfs
# image and DTB underneath, but maybe this is a terrible waste of
# RAM unless the kernel is able to reuse it later. Oh well
loadAddress = lim.parseInt "0x42000000";
entryPoint = lim.parseInt "0x42000000";
rootDevice = "ubi0:liminix";
dts = {
src = "${openwrt.src}/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts";
includePaths = [
"${openwrt.src}/target/linux/mediatek/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
includes = mkIf config.logging.persistent.enable [
./pstore-pmsg.dtsi
];
};
# - 0x000000000000-0x000008000000 : "spi-nand0"
# - 0x000000000000-0x000000080000 : "bl2"
# - 0x000000080000-0x0000001c0000 : "fip"
# - 0x0000001c0000-0x0000002c0000 : "factory"
# - 0x0000002c0000-0x000000300000 : "reserved"
# - 0x000000300000-0x000008000000 : "ubi"
networkInterfaces =
let
inherit (config.system.service.network) link;
in
rec {
wan = link.build { ifname = "wan"; };
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
lan = lan3;
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
};
};
};
};
};
};
}
+8
View File
@@ -0,0 +1,8 @@
/ {
reserved-memory {
/* make sure address matches upstream */
ramoops@42ff0000 {
pmsg-size = <0x10000>;
};
};
};
+9 -6
View File
@@ -19,25 +19,28 @@
VIRTIO_NET = "y";
};
conditionalConfig = {
WLAN= {
WLAN = {
MAC80211_HWSIM = "m";
};
};
};
hardware =
let
mac80211 = pkgs.kmodloader.override {
mac80211 = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel;
targets = ["mac80211_hwsim"];
targets = [ "mac80211_hwsim" ];
};
in {
in
{
defaultOutput = "vmroot";
rootDevice = "/dev/mtdblock0";
dts.src = pkgs.lib.mkDefault null;
flash.eraseBlockSize = 65536;
networkInterfaces =
let inherit (config.system.service.network) link;
in {
let
inherit (config.system.service.network) link;
in
{
wan = link.build {
devpath = "/devices/pci0000:00/0000:00:13.0/virtio0";
ifname = "wan";
+46 -28
View File
@@ -4,7 +4,7 @@
config = "mips-unknown-linux-musl";
gcc = {
abi = "32";
arch = "24kc"; # maybe mips_24kc-
arch = "24kc"; # maybe mips_24kc-
};
};
};
@@ -41,10 +41,11 @@
:ref:`system-outputs-mtdimage` can be flashed using the
vendor web UI or the U-Boot emergency "unbrick" routine.
For flashing from an existing Liminix system (we believe that) it
is necessary to first boot into a :ref:`system-outputs-kexecboot`
system, otherwise you'll be overwriting flash partitions while
they're in use - and that might not end well.
Flashing over an existing Liminix system is not possible while
that system is running, otherwise you'll be overwriting flash
partitions while they're in use - and that might not end well.
Configure the system with :ref:`levitate` if you need to
make it upgradable.
Vendor web page: https://www.gl-inet.com/products/gl-ar750/
@@ -52,7 +53,14 @@
'';
module = {pkgs, config, lim, lib, ... }:
module =
{
pkgs,
config,
lim,
lib,
...
}:
let
inherit (lib) mkIf;
openwrt = pkgs.openwrt;
@@ -64,7 +72,7 @@
};
firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = ["installPhase"];
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/ath10k/QCA9887/hw1.0/
blobdir=${firmwareBlobs}/QCA9887/hw1.0
@@ -73,7 +81,10 @@
'';
};
mac80211 = pkgs.kmodloader.override {
targets = ["ath9k" "ath10k_pci"];
targets = [
"ath9k"
"ath10k_pci"
];
inherit (config.system.outputs) kernel;
dependencies = [ ath10k_cal_data ];
};
@@ -81,7 +92,8 @@
let
offset = lim.parseInt "0x5000";
size = lim.parseInt "0x844";
in pkgs.liminix.services.oneshot rec {
in
pkgs.liminix.services.oneshot rec {
name = "ath10k_cal_data";
up = ''
part=$(basename $(dirname $(grep -l art /sys/class/mtd/*/name)))
@@ -90,10 +102,11 @@
(in_outputs ${name}
dd if=/dev/$part of=data iflag=skip_bytes,fullblock bs=${toString size} skip=${toString offset} count=1
)
'';
};
'';
};
inherit (pkgs.pseudofile) dir symlink;
in {
in
{
imports = [
../../modules/network
../../modules/arch/mipseb.nix
@@ -117,7 +130,7 @@
rootDevice = "/dev/mtdblock5";
dts = {
src = "${openwrt.src}/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts";
includePaths = [
includePaths = [
"${openwrt.src}/target/linux/ath79/dts"
];
includes = mkIf config.logging.persistent.enable [
@@ -126,8 +139,10 @@
};
networkInterfaces =
let inherit (config.system.service.network) link;
in {
let
inherit (config.system.service.network) link;
in
{
lan = link.build {
ifname = "lan";
devpath = "/devices/platform/ahb/1a000000.eth";
@@ -142,7 +157,10 @@
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ ath10k_cal_data mac80211 ];
dependencies = [
ath10k_cal_data
mac80211
];
};
};
};
@@ -192,31 +210,31 @@
NET = "y";
ETHERNET = "y";
NET_VENDOR_ATHEROS = "y";
AG71XX = "y"; # ethernet (qca,qca9530-eth)
MFD_SYSCON = "y"; # ethernet (compatible "syscon")
AR8216_PHY = "y"; # eth1 is behind a switch
AG71XX = "y"; # ethernet (qca,qca9530-eth)
MFD_SYSCON = "y"; # ethernet (compatible "syscon")
AR8216_PHY = "y"; # eth1 is behind a switch
MTD_SPI_NOR = "y";
SPI_ATH79 = "y"; # these are copied from OpenWrt.
SPI_MASTER= "y"; # At least one of them is necessary
SPI_MEM= "y";
SPI_AR934X= "y";
SPI_BITBANG= "y";
SPI_GPIO= "y";
SPI_ATH79 = "y"; # these are copied from OpenWrt.
SPI_MASTER = "y"; # At least one of them is necessary
SPI_MEM = "y";
SPI_AR934X = "y";
SPI_BITBANG = "y";
SPI_GPIO = "y";
GPIO_ATH79 = "y";
GPIOLIB = "y";
EXPERT="y";
EXPERT = "y";
GPIO_SYSFS = "y"; # required by patches-5.15/0004-phy-add-ath79-usb-phys.patch
OF_GPIO = "y";
SYSFS = "y";
SPI = "y";
MTD = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs
WATCHDOG = "y";
ATH79_WDT = "y"; # watchdog timer
ATH79_WDT = "y"; # watchdog timer
EARLY_PRINTK = "y";
+54 -42
View File
@@ -6,7 +6,7 @@
config = "mipsel-unknown-linux-musl";
gcc = {
abi = "32";
arch = "mips32"; # maybe mips_24kc-
arch = "mips32"; # maybe mips_24kc-
};
};
};
@@ -32,10 +32,11 @@
binary created by :ref:`system-outputs-mtdimage` can be flashed
using the vendor web UI or the U-Boot emergency "unbrick" routine.
For flashing from an existing Liminix system (we think) it
is necessary to first boot into a :ref:`system-outputs-kexecboot`
system, otherwise you'll be overwriting flash partitions while
they're in use - and that might not end well.
Flashing over an existing Liminix system is not possible while
that system is running, otherwise you'll be overwriting flash
partitions while they're in use - and that might not end well.
Configure the system with :ref:`levitate` if you need to
make it upgradable.
Vendor web page: https://www.gl-inet.com/products/gl-mt300a/
@@ -43,14 +44,22 @@
'';
module = { pkgs, config, lib, lim, ...}:
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (pkgs) openwrt;
mac80211 = pkgs.kmodloader.override {
targets = ["rt2800soc"];
targets = [ "rt2800soc" ];
inherit (config.system.outputs) kernel;
};
in {
in
{
imports = [
../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix
@@ -89,7 +98,8 @@
let
inherit (config.system.service.network) link;
inherit (config.system.service) vlan;
in rec {
in
rec {
eth = link.build { ifname = "eth0"; };
# lan and wan ports are both behind a switch on eth0
lan = vlan.build {
@@ -111,54 +121,56 @@
boot.tftp = {
loadAddress = lim.parseInt "0x00A00000";
appendDTB = true;
};
};
kernel = {
extraPatchPhase = ''
${openwrt.applyPatches.ramips}
${openwrt.applyPatches.rt2x00}
'';
config = {
config =
{
RALINK = "y";
PCI = "y";
SOC_MT7620 = "y";
RALINK = "y";
PCI = "y";
SOC_MT7620 = "y";
SERIAL_8250_CONSOLE = "y";
SERIAL_8250 = "y";
SERIAL_CORE_CONSOLE = "y";
SERIAL_OF_PLATFORM = "y";
SERIAL_8250_CONSOLE = "y";
SERIAL_8250 = "y";
SERIAL_CORE_CONSOLE = "y";
SERIAL_OF_PLATFORM = "y";
CONSOLE_LOGLEVEL_DEFAULT = "8";
CONSOLE_LOGLEVEL_QUIET = "4";
CONSOLE_LOGLEVEL_DEFAULT = "8";
CONSOLE_LOGLEVEL_QUIET = "4";
NET = "y";
ETHERNET = "y";
NET_VENDOR_RALINK = "y";
NET_RALINK_MDIO = "y";
NET_RALINK_MDIO_MT7620 = "y";
NET_RALINK_MT7620 = "y";
SWPHY = "y";
NET = "y";
ETHERNET = "y";
NET_VENDOR_RALINK = "y";
NET_RALINK_MDIO = "y";
NET_RALINK_MDIO_MT7620 = "y";
NET_RALINK_MT7620 = "y";
SWPHY = "y";
SPI = "y";
MTD_SPI_NOR = "y";
SPI_MT7621 = "y"; # } probably don't need both of these
SPI_RT2880 = "y"; # }
SPI_MASTER= "y";
SPI_MEM= "y";
SPI = "y";
MTD_SPI_NOR = "y";
SPI_MT7621 = "y"; # } probably don't need both of these
SPI_RT2880 = "y"; # }
SPI_MASTER = "y";
SPI_MEM = "y";
MTD = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs
MTD = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs
EARLY_PRINTK = "y";
EARLY_PRINTK = "y";
NEW_LEDS = "y";
LEDS_CLASS = "y"; # required by rt2x00lib
NEW_LEDS = "y";
LEDS_CLASS = "y"; # required by rt2x00lib
PRINTK_TIME = "y";
} // lib.optionalAttrs (config.system.service ? vlan) {
SWCONFIG = "y";
};
PRINTK_TIME = "y";
}
// lib.optionalAttrs (config.system.service ? vlan) {
SWCONFIG = "y";
};
conditionalConfig = {
WLAN = {
WLAN_VENDOR_RALINK = "y";
+66 -50
View File
@@ -4,7 +4,7 @@
config = "mipsel-unknown-linux-musl";
gcc = {
abi = "32";
arch = "mips32"; # maybe mips_24kc-
arch = "mips32"; # maybe mips_24kc-
};
};
};
@@ -25,10 +25,11 @@
binary created by :ref:`system-outputs-mtdimage` can be flashed
using the vendor web UI or the U-Boot emergency "unbrick" routine.
For flashing from an existing Liminix system (we think) it
is necessary to first boot into a :ref:`system-outputs-kexecboot`
system, otherwise you'll be overwriting flash partitions while
they're in use - and that might not end well.
Flashing over an existing Liminix system is not possible while
that system is running, otherwise you'll be overwriting flash
partitions while they're in use - and that might not end well.
Configure the system with :ref:`levitate` if you need to
make it upgradable.
Vendor web page: https://www.gl-inet.com/products/gl-mt300n-v2/
@@ -36,21 +37,29 @@
'';
module = { pkgs, config, lib, lim, ...}:
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;
mac80211 = pkgs.kmodloader.override {
targets = ["mt7603e"];
targets = [ "mt7603e" ];
inherit (config.system.outputs) kernel;
};
wlan_firmware = pkgs.fetchurl {
url = "https://github.com/openwrt/mt76/raw/f24b56f935392ca1d35fae5fd6e56ef9deda4aad/firmware/mt7628_e2.bin";
hash = "sha256:1dkhfznmdz6s50kwc841x3wj0h6zg6icg5g2bim9pvg66as2vmh9";
};
in {
in
{
imports = [
../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix
@@ -98,8 +107,12 @@
'';
down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset";
};
in rec {
eth = link.build { ifname = "eth0"; dependencies = [swconfig]; };
in
rec {
eth = link.build {
ifname = "eth0";
dependencies = [ swconfig ];
};
# lan and wan ports are both behind a switch on eth0
lan = vlan.build {
ifname = "eth0.1";
@@ -128,58 +141,61 @@
extraPatchPhase = ''
${openwrt.applyPatches.ramips}
'';
config = {
config =
{
RALINK = "y";
PCI = "y";
SOC_MT7620 = "y";
RALINK = "y";
PCI = "y";
SOC_MT7620 = "y";
SERIAL_8250_CONSOLE = "y";
SERIAL_8250 = "y";
SERIAL_CORE_CONSOLE = "y";
SERIAL_OF_PLATFORM = "y";
SERIAL_8250_CONSOLE = "y";
SERIAL_8250 = "y";
SERIAL_CORE_CONSOLE = "y";
SERIAL_OF_PLATFORM = "y";
CONSOLE_LOGLEVEL_DEFAULT = "8";
CONSOLE_LOGLEVEL_QUIET = "4";
CONSOLE_LOGLEVEL_DEFAULT = "8";
CONSOLE_LOGLEVEL_QUIET = "4";
MTD = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev
MTD = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev
SPI = "y";
MTD_SPI_NOR = "y";
SPI_MT7621 = "y";
SPI_MASTER= "y";
SPI_MEM= "y";
SPI = "y";
MTD_SPI_NOR = "y";
SPI_MT7621 = "y";
SPI_MASTER = "y";
SPI_MEM = "y";
REGULATOR = "y";
REGULATOR_FIXED_VOLTAGE = "y";
REGULATOR = "y";
REGULATOR_FIXED_VOLTAGE = "y";
NET = "y";
ETHERNET = "y";
NET = "y";
ETHERNET = "y";
PHYLIB = "y";
AT803X_PHY="y";
FIXED_PHY="y";
GENERIC_PHY="y";
NET_VENDOR_RALINK = "y";
NET_RALINK_RT3050 = "y";
NET_RALINK_SOC="y";
SWPHY = "y";
PHYLIB = "y";
AT803X_PHY = "y";
FIXED_PHY = "y";
GENERIC_PHY = "y";
NET_VENDOR_RALINK = "y";
NET_RALINK_RT3050 = "y";
NET_RALINK_SOC = "y";
SWPHY = "y";
GPIOLIB="y";
GPIO_MT7621 = "y";
GPIOLIB = "y";
GPIO_MT7621 = "y";
PHY_RALINK_USB = "y";
PHY_RALINK_USB = "y";
EARLY_PRINTK = "y";
EARLY_PRINTK = "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
};
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
};
conditionalConfig = {
WLAN = {
WLAN_VENDOR_RALINK = "y";
+751
View File
@@ -0,0 +1,751 @@
{
description = ''
OpenWrt One
***********
Hardware summary
================
- MediaTek MT7981B (1300MHz)
- 256MB NAND Flash
- 1024MB RAM
- WLan hardware: Mediatek MT7976C
Status
======
- Only tested over TFTP so far.
- WiFi (2.4G and 5G) works.
- 2.5G ethernet port works.
Limitations
===========
- adding `he_bss_color="128"` causes `Invalid argument` for hostap
- nvme support untested
- I don't think the front LEDs work yet
Installation
============
TODO: add instructions on how to boot directly from TFTP to memory
and how to install from TFTP to flash without going through OpenWrt.
The instructions below assume you can boot and SSH into OpenWrt:
Boot into OpenWrt and create a 'liminix' UBI partition:
root@OpenWrt:~# ubimkvol /dev/ubi0 --name=liminix --maxavsize
Remember the 'Volume ID' that was created for this new partition
Build the UBI image and write it to this new partition:
$ nix-build -I liminix-config=./my-configuration.nix --arg device "import ./devices/openwrt-one" -A outputs.default
$ cat result/rootfs | ssh root@192.168.1.1 "cat > /tmp/rootfs"
$ ssh root@192.168.1.1
root@OpenWrt:~# ubiupdatevol /dev/ubi0_X /tmp/rootfs # replace X with the volume id, if needed check with `ubinfo`
Reboot into the U-Boot prompt and boot with:
OpenWrt One> ubifsmount ubi0:liminix && ubifsload ''${loadaddr} boot/fit && bootm ''${loadaddr}'
If this works, reboot into OpenWrt and configure U-Boot to boot ubifs by default:
root@OpenWrt:~# fw_setenv orig_boot_production $(fw_printenv -n boot_production)
root@OpenWrt:~# fw_setenv boot_production 'led white on ; ubifsmount ubi0:liminix && ubifsload ''${loadaddr} boot/fit && bootm ''${loadaddr}'
Troubleshooting
===============
The instructions above assume you can boot and SSH into the (recovery)
OpenWrt installation. If you have broken your device to the point where that
is no longer possible, you could re-install OpenWrt, but probably you could
also install directly from U-Boot:
https://github.com/u-boot/u-boot/blob/master/doc/README.ubi
'';
system = {
crossSystem = {
config = "aarch64-unknown-linux-musl";
gcc = {
# https://openwrt.org/docs/techref/instructionset/aarch64_cortex-a53
# openwrt ./target/linux/mediatek/filogic/target.mk
# https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html
# https://en.wikipedia.org/wiki/Comparison_of_ARM_processors
arch = "armv8-a";
};
};
};
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
openwrt = pkgs.openwrt_24_10;
mediatek-firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = [ "installPhase" ];
installPhase = ''
mkdir $out
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7986_eeprom_mt7976,mt7981}* $out
'';
};
airoha-firmware = pkgs.stdenv.mkDerivation {
name = "airoha-firmware";
phases = [ "installPhase" ];
installPhase = ''
mkdir $out
cp ${pkgs.linux-firmware}/lib/firmware/airoha/* $out
'';
};
in
{
imports = [
../../modules/arch/aarch64.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/ubifs.nix
];
config = {
kernel = {
src = openwrt.kernelSrc;
version = openwrt.kernelVersion;
extraPatchPhase = ''
${openwrt.applyPatches.mediatek}
'';
config =
{
NET = "y"; # unlock NET_XGRESS
SERIAL_8250 = "y"; # unlock SERIAL_8250_FSL
SERIAL_8250_CONSOLE = "y"; # to get the serial console
WATCHDOG = "y"; # unlock WATCHDOG_CORE
NEW_LEDS = "y"; # unlock LEDS_PWM
LEDS_CLASS = "y"; # unlock LEDS_PWM
LEDS_TRIGGERS = "y"; # unlock LEDS_TRIGGER_PATTERN
DEFERRED_STRUCT_PAGE_INIT = "y"; # trigger PADATA
# Taken from openwrt's ./target/linux/mediatek/filogic/config-6.6
"64BIT" = "y";
AIROHA_EN8801SC_PHY = "y";
ARCH_BINFMT_ELF_EXTRA_PHDRS = "y";
ARCH_CORRECT_STACKTRACE_ON_KRETPROBE = "y";
ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG = "y";
ARCH_DMA_ADDR_T_64BIT = "y";
ARCH_FORCE_MAX_ORDER = "10";
ARCH_KEEP_MEMBLOCK = "y";
ARCH_MEDIATEK = "y";
ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE = "y";
ARCH_MMAP_RND_BITS = "18";
ARCH_MMAP_RND_BITS_MAX = "24";
ARCH_MMAP_RND_BITS_MIN = "18";
ARCH_MMAP_RND_COMPAT_BITS_MIN = "11";
ARCH_PROC_KCORE_TEXT = "y";
ARCH_SPARSEMEM_ENABLE = "y";
ARCH_STACKWALK = "y";
ARCH_SUSPEND_POSSIBLE = "y";
ARCH_WANTS_NO_INSTR = "y";
ARCH_WANTS_THP_SWAP = "y";
ARM64 = "y";
ARM64_4K_PAGES = "y";
ARM64_ERRATUM_843419 = "y";
ARM64_LD_HAS_FIX_ERRATUM_843419 = "y";
ARM64_PAGE_SHIFT = "12";
ARM64_PA_BITS = "48";
ARM64_PA_BITS_48 = "y";
ARM64_TAGGED_ADDR_ABI = "y";
ARM64_VA_BITS = "39";
ARM64_VA_BITS_39 = "y";
ARM_AMBA = "y";
ARM_ARCH_TIMER = "y";
ARM_ARCH_TIMER_EVTSTREAM = "y";
ARM_GIC = "y";
ARM_GIC_V2M = "y";
ARM_GIC_V3 = "y";
ARM_GIC_V3_ITS = "y";
ARM_GIC_V3_ITS_PCI = "y";
ARM_MEDIATEK_CPUFREQ = "y";
ARM_PMU = "y";
ARM_PMUV3 = "y";
ARM_PSCI_FW = "y";
ATA = "y";
AUDIT_ARCH_COMPAT_GENERIC = "y";
BLK_DEV_LOOP = "y";
BLK_DEV_SD = "y";
BLK_MQ_PCI = "y";
BLK_PM = "y";
BLOCK_NOTIFIERS = "y";
BSD_PROCESS_ACCT = "y";
BSD_PROCESS_ACCT_V3 = "y";
BUFFER_HEAD = "y";
BUILTIN_RETURN_ADDRESS_STRIPS_PAC = "y";
CC_HAVE_SHADOW_CALL_STACK = "y";
CC_HAVE_STACKPROTECTOR_SYSREG = "y";
#CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5";
CC_NO_ARRAY_BOUNDS = "y";
CLKSRC_MMIO = "y";
CLONE_BACKWARDS = "y";
CMDLINE_OVERRIDE = "y";
COMMON_CLK = "y";
COMMON_CLK_MEDIATEK = "y";
COMMON_CLK_MT7981 = "y";
COMMON_CLK_MT7981_ETHSYS = "y";
COMMON_CLK_MT7986 = "y";
COMMON_CLK_MT7986_ETHSYS = "y";
COMMON_CLK_MT7988 = "y";
COMPACT_UNEVICTABLE_DEFAULT = "1";
CONFIGFS_FS = "y";
CONSOLE_LOGLEVEL_DEFAULT = "15";
CONTEXT_TRACKING = "y";
CONTEXT_TRACKING_IDLE = "y";
CPU_FREQ = "y";
CPU_FREQ_DEFAULT_GOV_USERSPACE = "y";
CPU_FREQ_GOV_ATTR_SET = "y";
CPU_FREQ_GOV_COMMON = "y";
CPU_FREQ_GOV_CONSERVATIVE = "y";
CPU_FREQ_GOV_ONDEMAND = "y";
CPU_FREQ_GOV_PERFORMANCE = "y";
CPU_FREQ_GOV_POWERSAVE = "y";
CPU_FREQ_GOV_SCHEDUTIL = "y";
CPU_FREQ_GOV_USERSPACE = "y";
CPU_FREQ_STAT = "y";
CPU_LITTLE_ENDIAN = "y";
CPU_RMAP = "y";
CPU_THERMAL = "y";
CRC16 = "y";
CRC_CCITT = "y";
CRYPTO_AES_ARM64 = "y";
CRYPTO_AES_ARM64_CE = "y";
CRYPTO_AES_ARM64_CE_BLK = "y";
CRYPTO_AES_ARM64_CE_CCM = "y";
CRYPTO_CMAC = "y";
CRYPTO_CRC32 = "y";
CRYPTO_CRC32C = "y";
CRYPTO_CRYPTD = "y";
CRYPTO_DEFLATE = "y";
CRYPTO_DRBG = "y";
CRYPTO_DRBG_HMAC = "y";
CRYPTO_DRBG_MENU = "y";
CRYPTO_ECB = "y";
CRYPTO_ECC = "y";
CRYPTO_ECDH = "y";
CRYPTO_GHASH_ARM64_CE = "y";
CRYPTO_HASH_INFO = "y";
CRYPTO_HMAC = "y";
CRYPTO_JITTERENTROPY = "y";
CRYPTO_LIB_BLAKE2S_GENERIC = "y";
CRYPTO_LIB_GF128MUL = "y";
CRYPTO_LIB_SHA1 = "y";
CRYPTO_LIB_SHA256 = "y";
CRYPTO_LIB_UTILS = "y";
CRYPTO_LZO = "y";
CRYPTO_RNG = "y";
CRYPTO_RNG2 = "y";
CRYPTO_RNG_DEFAULT = "y";
CRYPTO_SHA256 = "y";
CRYPTO_SHA256_ARM64 = "y";
CRYPTO_SHA2_ARM64_CE = "y";
CRYPTO_SHA3 = "y";
CRYPTO_SHA512 = "y";
CRYPTO_SM4 = "y";
CRYPTO_SM4_ARM64_CE_BLK = "y";
CRYPTO_SM4_ARM64_CE_CCM = "y";
CRYPTO_SM4_ARM64_CE_GCM = "y";
CRYPTO_ZSTD = "y";
DCACHE_WORD_ACCESS = "y";
#DEBUG_INFO="y";
DEBUG_MISC = "y";
DIMLIB = "y";
DMADEVICES = "y";
DMATEST = "y";
DMA_BOUNCE_UNALIGNED_KMALLOC = "y";
DMA_DIRECT_REMAP = "y";
DMA_ENGINE = "y";
DMA_ENGINE_RAID = "y";
DMA_OF = "y";
DMA_VIRTUAL_CHANNELS = "y";
DTC = "y";
EDAC_SUPPORT = "y";
EINT_MTK = "y";
EXCLUSIVE_SYSTEM_RAM = "y";
EXT4_FS = "y";
F2FS_FS = "y";
FIXED_PHY = "y";
FIX_EARLYCON_MEM = "y";
FRAME_POINTER = "y";
FS_IOMAP = "y";
FS_MBCACHE = "y";
FUNCTION_ALIGNMENT = "4";
FUNCTION_ALIGNMENT_4B = "y";
FWNODE_MDIO = "y";
FW_LOADER_PAGED_BUF = "y";
#FW_LOADER_SYSFS="y";
#GCC11_NO_ARRAY_BOUNDS="y";
#GCC_ASM_GOTO_OUTPUT_WORKAROUND="y";
GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS = "y";
GENERIC_ALLOCATOR = "y";
GENERIC_ARCH_TOPOLOGY = "y";
GENERIC_BUG = "y";
GENERIC_BUG_RELATIVE_POINTERS = "y";
GENERIC_CLOCKEVENTS = "y";
GENERIC_CLOCKEVENTS_BROADCAST = "y";
GENERIC_CPU_AUTOPROBE = "y";
GENERIC_CPU_VULNERABILITIES = "y";
GENERIC_CSUM = "y";
GENERIC_EARLY_IOREMAP = "y";
GENERIC_GETTIMEOFDAY = "y";
GENERIC_IDLE_POLL_SETUP = "y";
GENERIC_IOREMAP = "y";
GENERIC_IRQ_EFFECTIVE_AFF_MASK = "y";
GENERIC_IRQ_SHOW = "y";
GENERIC_IRQ_SHOW_LEVEL = "y";
GENERIC_LIB_DEVMEM_IS_ALLOWED = "y";
GENERIC_MSI_IRQ = "y";
GENERIC_PCI_IOMAP = "y";
GENERIC_PHY = "y";
GENERIC_PINCONF = "y";
GENERIC_PINCTRL_GROUPS = "y";
GENERIC_PINMUX_FUNCTIONS = "y";
GENERIC_SCHED_CLOCK = "y";
GENERIC_SMP_IDLE_THREAD = "y";
GENERIC_STRNCPY_FROM_USER = "y";
GENERIC_STRNLEN_USER = "y";
GENERIC_TIME_VSYSCALL = "y";
GLOB = "y";
GPIO_CDEV = "y";
GPIO_WATCHDOG = "y";
GPIO_WATCHDOG_ARCH_INITCALL = "y";
GRO_CELLS = "y";
HARDIRQS_SW_RESEND = "y";
HAS_DMA = "y";
HAS_IOMEM = "y";
HAS_IOPORT = "y";
HAS_IOPORT_MAP = "y";
HWMON = "y";
HW_RANDOM = "y";
HW_RANDOM_MTK = "y";
I2C = "y";
I2C_BOARDINFO = "y";
I2C_CHARDEV = "y";
I2C_MT65XX = "y";
ICPLUS_PHY = "y";
ILLEGAL_POINTER_VALUE = "0xdead000000000000";
#INITRAMFS_SOURCE="""";
IRQCHIP = "y";
IRQ_DOMAIN = "y";
IRQ_DOMAIN_HIERARCHY = "y";
IRQ_FORCED_THREADING = "y";
IRQ_TIME_ACCOUNTING = "y";
IRQ_WORK = "y";
JBD2 = "y";
JUMP_LABEL = "y";
LEDS_PWM = "y";
LEDS_SMARTRG_LED = "y";
LIBFDT = "y";
LOCK_DEBUGGING_SUPPORT = "y";
LOCK_SPIN_ON_OWNER = "y";
LZO_COMPRESS = "y";
LZO_DECOMPRESS = "y";
MAGIC_SYSRQ = "y";
MAXLINEAR_GPHY = "y";
MDIO_BUS = "y";
MDIO_DEVICE = "y";
MDIO_DEVRES = "y";
MEDIATEK_2P5GE_PHY = "y";
MEDIATEK_GE_PHY = "y";
MEDIATEK_GE_SOC_PHY = "y";
MEDIATEK_WATCHDOG = "y";
MESSAGE_LOGLEVEL_DEFAULT = "7";
MFD_SYSCON = "y";
MIGRATION = "y";
MMC = "y";
MMC_BLOCK = "y";
MMC_CQHCI = "y";
MMC_MTK = "y";
MMU_LAZY_TLB_REFCOUNT = "y";
MODULES_TREE_LOOKUP = "y";
MODULES_USE_ELF_RELA = "y";
MTD_NAND_CORE = "y";
MTD_NAND_ECC = "y";
MTD_NAND_ECC_MEDIATEK = "y";
MTD_NAND_ECC_SW_HAMMING = "y";
MTD_NAND_MTK = "y";
MTD_NAND_MTK_BMT = "y";
MTD_PARSER_TRX = "y";
MTD_RAW_NAND = "y";
MTD_SPI_NAND = "y";
MTD_SPI_NOR = "y";
MTD_SPLIT_FIRMWARE = "y";
MTD_SPLIT_FIT_FW = "y";
MTD_UBI = "y";
MTD_UBI_BEB_LIMIT = "20";
MTD_UBI_BLOCK = "y";
MTD_UBI_FASTMAP = "y";
MTD_UBI_NVMEM = "y";
MTD_UBI_WL_THRESHOLD = "4096";
MTK_CPUX_TIMER = "y";
MTK_HSDMA = "y";
MTK_INFRACFG = "y";
MTK_LVTS_THERMAL = "y";
MTK_LVTS_THERMAL_DEBUGFS = "y";
MTK_PMIC_WRAP = "y";
MTK_REGULATOR_COUPLER = "y";
MTK_SCPSYS = "y";
MTK_SCPSYS_PM_DOMAINS = "y";
MTK_SOC_THERMAL = "y";
MTK_THERMAL = "y";
MTK_TIMER = "y";
MUTEX_SPIN_ON_OWNER = "y";
NEED_DMA_MAP_STATE = "y";
NEED_SG_DMA_LENGTH = "y";
NET_DEVLINK = "y";
NET_DSA = "y";
NET_DSA_MT7530 = "y";
NET_DSA_MT7530_MDIO = "y";
NET_DSA_MT7530_MMIO = "y";
NET_DSA_TAG_MTK = "y";
#NET_EGRESS="y";
NET_FLOW_LIMIT = "y";
#NET_INGRESS="y";
NET_MEDIATEK_SOC = "y";
NET_MEDIATEK_SOC_WED = "y";
NET_SELFTESTS = "y";
NET_SWITCHDEV = "y";
NET_VENDOR_MEDIATEK = "y";
#NET_XGRESS="y";
NLS = "y";
NO_HZ_COMMON = "y";
NO_HZ_IDLE = "y";
NR_CPUS = "4";
NVMEM = "y";
NVMEM_BLOCK = "y";
NVMEM_LAYOUTS = "y";
NVMEM_LAYOUT_ADTRAN = "y";
NVMEM_MTK_EFUSE = "y";
NVMEM_SYSFS = "y";
OF = "y";
OF_ADDRESS = "y";
OF_DYNAMIC = "y";
OF_EARLY_FLATTREE = "y";
OF_FLATTREE = "y";
OF_GPIO = "y";
OF_IRQ = "y";
OF_KOBJ = "y";
OF_MDIO = "y";
OF_OVERLAY = "y";
OF_RESOLVE = "y";
PADATA = "y";
PAGE_POOL = "y";
PAGE_POOL_STATS = "y";
PAGE_SIZE_LESS_THAN_256KB = "y";
PAGE_SIZE_LESS_THAN_64KB = "y";
#PAHOLE_HAS_LANG_EXCLUDE="y";
PARTITION_PERCPU = "y";
PCI = "y";
PCIEAER = "y";
PCIEASPM = "y";
PCIEASPM_PERFORMANCE = "y";
PCIEPORTBUS = "y";
PCIE_MEDIATEK_GEN3 = "y";
PCIE_PME = "y";
PCI_DEBUG = "y";
PCI_DOMAINS = "y";
PCI_DOMAINS_GENERIC = "y";
PCI_MSI = "y";
PCS_MTK_LYNXI = "y";
PCS_MTK_USXGMII = "y";
PERF_EVENTS = "y";
PER_VMA_LOCK = "y";
PGTABLE_LEVELS = "3";
PHYLIB = "y";
PHYLIB_LEDS = "y";
PHYLINK = "y";
PHYS_ADDR_T_64BIT = "y";
PHY_MTK_TPHY = "y";
PHY_MTK_XFI_TPHY = "y";
PHY_MTK_XSPHY = "y";
PINCTRL = "y";
PINCTRL_MT7981 = "y";
PINCTRL_MT7986 = "y";
PINCTRL_MT7988 = "y";
PINCTRL_MTK_MOORE = "y";
PINCTRL_MTK_V2 = "y";
PM = "y";
PM_CLK = "y";
PM_GENERIC_DOMAINS = "y";
PM_GENERIC_DOMAINS_OF = "y";
PM_OPP = "y";
POLYNOMIAL = "y";
POSIX_CPU_TIMERS_TASK_WORK = "y";
POWER_RESET = "y";
POWER_RESET_SYSCON = "y";
POWER_SUPPLY = "y";
PREEMPT_NONE_BUILD = "y";
PRINTK_TIME = "y";
PSTORE = "y";
PSTORE_COMPRESS = "y";
PSTORE_CONSOLE = "y";
PSTORE_PMSG = "y";
PSTORE_RAM = "y";
PTP_1588_CLOCK_OPTIONAL = "y";
PWM = "y";
PWM_MEDIATEK = "y";
PWM_SYSFS = "y";
QUEUED_RWLOCKS = "y";
QUEUED_SPINLOCKS = "y";
RANDSTRUCT_NONE = "y";
RAS = "y";
RATIONAL = "y";
REALTEK_PHY = "y";
REED_SOLOMON = "y";
REED_SOLOMON_DEC8 = "y";
REED_SOLOMON_ENC8 = "y";
REGMAP = "y";
REGMAP_I2C = "y";
REGMAP_MMIO = "y";
REGULATOR = "y";
REGULATOR_FIXED_VOLTAGE = "y";
REGULATOR_MT6380 = "y";
REGULATOR_RT5190A = "y";
RESET_CONTROLLER = "y";
RESET_TI_SYSCON = "y";
RFS_ACCEL = "y";
RODATA_FULL_DEFAULT_ENABLED = "y";
RPS = "y";
RTC_CLASS = "y";
RTC_DRV_MT7622 = "y";
RTC_I2C_AND_SPI = "y";
RWSEM_SPIN_ON_OWNER = "y";
SCHED_MC = "y";
SCSI = "y";
SCSI_COMMON = "y";
SERIAL_8250_FSL = "y";
SERIAL_8250_MT6577 = "y";
SERIAL_8250_NR_UARTS = "3";
SERIAL_8250_RUNTIME_UARTS = "3";
SERIAL_DEV_BUS = "y";
SERIAL_DEV_CTRL_TTYPORT = "y";
SERIAL_MCTRL_GPIO = "y";
SERIAL_OF_PLATFORM = "y";
SGL_ALLOC = "y";
SG_POOL = "y";
SMP = "y";
SOCK_RX_QUEUE_MAPPING = "y";
SOFTIRQ_ON_OWN_STACK = "y";
SPARSEMEM = "y";
SPARSEMEM_EXTREME = "y";
SPARSEMEM_VMEMMAP = "y";
SPARSEMEM_VMEMMAP_ENABLE = "y";
SPARSE_IRQ = "y";
SPI = "y";
SPI_DYNAMIC = "y";
SPI_MASTER = "y";
SPI_MEM = "y";
SPI_MT65XX = "y";
SPI_MTK_SNFI = "y";
#SQUASHFS_DECOMP_MULTI_PERCPU="y";
SWIOTLB = "y";
SWPHY = "y";
SYSCTL_EXCEPTION_TRACE = "y";
THERMAL = "y";
THERMAL_DEFAULT_GOV_STEP_WISE = "y";
THERMAL_EMERGENCY_POWEROFF_DELAY_MS = "0";
THERMAL_GOV_BANG_BANG = "y";
THERMAL_GOV_FAIR_SHARE = "y";
THERMAL_GOV_STEP_WISE = "y";
THERMAL_GOV_USER_SPACE = "y";
THERMAL_HWMON = "y";
THERMAL_OF = "y";
THERMAL_WRITABLE_TRIPS = "y";
THREAD_INFO_IN_TASK = "y";
TICK_CPU_ACCOUNTING = "y";
TIMER_OF = "y";
TIMER_PROBE = "y";
TRACE_IRQFLAGS_NMI_SUPPORT = "y";
TREE_RCU = "y";
TREE_SRCU = "y";
UBIFS_FS = "y";
UIMAGE_FIT_BLK = "y";
USB_SUPPORT = "y";
VMAP_STACK = "y";
WATCHDOG_CORE = "y";
WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC = "y";
WATCHDOG_PRETIMEOUT_GOV = "y";
WATCHDOG_PRETIMEOUT_GOV_PANIC = "y";
WATCHDOG_PRETIMEOUT_GOV_SEL = "m";
WATCHDOG_SYSFS = "y";
XPS = "y";
XXHASH = "y";
ZLIB_DEFLATE = "y";
ZLIB_INFLATE = "y";
ZONE_DMA32 = "y";
ZSTD_COMMON = "y";
ZSTD_COMPRESS = "y";
ZSTD_DECOMPRESS = "y";
# from DEVICE_PACKAGES in the openwrt_one section of
# openwrt's ./target/linux/mediatek/image/filogic.mk:
# chop off the 'kmod-' prefix and search for 'KernelPackage/...'
# in ./package/kernel/linux/modules/*.mk, and remember to add
# modules to kmodloader targets below
AIR_EN8811H_PHY = "m";
RTC_DRV_PCF8563 = "m";
NVME_CORE = "m";
BLK_DEV_NVME = "m";
NVME_MULTIPATH = "n";
NVME_HWMON = "y";
# ???
AQUANTIA_PHY = "m";
MT798X_WMAC = "y";
}
// lib.optionalAttrs (config.system.service ? watchdog) {
RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};
conditionalConfig = {
WLAN = {
MT7915E = "m";
};
};
};
boot = {
commandLine = [ "console=ttyS0,115200" ];
tftp = {
# Should be a segment of free RAM, where the tftp artifact
# can be stored before unpacking it to the 'hardware.loadAddress'
# The 'hardware.loadAddress' is 0x44000000, and the bootlog
# suggests it loads the fit to 0x46000000
loadAddress = lim.parseInt "0x46000000";
};
imageFormat = "fit";
loader.fit.enable = lib.mkDefault true; # override this if you are building tftpboot
};
rootfsType = lib.mkDefault "ubifs"; # override this if you are building tftpboot
filesystem =
let
inherit (pkgs.pseudofile) dir symlink;
in
dir {
lib = dir {
firmware = dir {
mediatek = symlink mediatek-firmware;
airoha = symlink airoha-firmware;
};
};
};
hardware =
let
phy = pkgs.kmodloader.override {
targets = [
"air_en8811h"
];
inherit (config.system.outputs) kernel;
};
mac80211 = pkgs.kmodloader.override {
targets = [
"mt7915e"
"rtc-pcf8563"
"nvme_core"
"nvme"
#"mt7996e"
"aquantia"
];
inherit (config.system.outputs) kernel;
};
in
{
# from OEM bootlog
# Creating 4 MTD partitions on "spi0.0":
# 0x000000000000-0x000000040000 : "bl2-nor"
# 0x000000040000-0x000000100000 : "factory"
# 0x000000100000-0x000000180000 : "fip-nor"
# 0x000000180000-0x000000e00000 : "recovery"
# spi-nand spi1.1: calibration result: 0x3
# spi-nand spi1.1: Winbond SPI NAND was found.
# spi-nand spi1.1: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
# 2 fixed-partitions partitions found on MTD device spi1.1
# Creating 2 MTD partitions on "spi1.1":
# 0x000000000000-0x000000100000 : "bl2"
# 0x000000100000-0x000010000000 : "ubi"
flash = {
# from the OEM bootlog:
# ## Checking Image at 46000000 ...
# FIT image found
# FIT description: ARM64 OpenWrt FIT (Flattened Image Tree)
# Image 0 (kernel-1)
# Description: ARM64 OpenWrt Linux-6.6.57
# Type: Kernel Image
# Compression: gzip compressed
# Data Start: 0x46001000
# Data Size: 5751840 Bytes = 5.5 MiB
# Architecture: AArch64
# OS: Linux
# Load Address: 0x44000000
# Entry Point: 0x44000000
address = lim.parseInt "0x44000000";
size = lim.parseInt "0xf60000";
# /proc/mtd on a running system:
# dev: size erasesize name
# mtd0: 00040000 00010000 "bl2-nor"
# mtd1: 000c0000 00010000 "factory"
# mtd2: 00080000 00010000 "fip-nor"
# mtd3: 00c80000 00010000 "recovery"
# mtd4: 00100000 00020000 "bl2"
# mtd5: 0ff00000 00020000 "ubi"
eraseBlockSize = 65536;
};
ubi = {
# TODO taken from belkin-rt3200, to review
minIOSize = "2048";
logicalEraseBlockSize = "126976";
physicalEraseBlockSize = "131072";
maxLEBcount = "1024"; # guessing
};
defaultOutput = "ubimage";
loadAddress = lim.parseInt "0x44000000";
entryPoint = lim.parseInt "0x44000000";
# TODO AFAICT this should be 2048, but I got 'FIT: image rootfs-1 start not aligned to page boundaries' with that...
#alignment = 2048;
alignment = 4096;
rootDevice = "ubi0:liminix";
dts = {
src = "${openwrt.src}/target/linux/mediatek/dts/mt7981b-openwrt-one.dts";
includePaths = [
"${openwrt.src}/target/linux/mediatek/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
};
networkInterfaces =
let
inherit (config.system.service.network) link;
in
rec {
eth0 = link.build {
ifname = "eth0";
dependencies = [ phy ];
};
eth1 = link.build { ifname = "eth1"; };
wlan0 = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan1 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
};
};
};
};
}
+25 -19
View File
@@ -26,26 +26,32 @@
# this device is described by the "qemu" device
installer = "vmroot";
module = { config, lim, ... }: {
imports = [
../../modules/arch/aarch64.nix
../families/qemu.nix
];
kernel = {
config = {
VIRTUALIZATION = "y";
PCI_HOST_GENERIC="y";
module =
{ config, lim, ... }:
{
imports = [
../../modules/arch/aarch64.nix
../families/qemu.nix
];
kernel = {
config = {
VIRTUALIZATION = "y";
PCI_HOST_GENERIC = "y";
SERIAL_AMBA_PL011 = "y";
SERIAL_AMBA_PL011_CONSOLE = "y";
SERIAL_AMBA_PL011 = "y";
SERIAL_AMBA_PL011_CONSOLE = "y";
};
};
boot.commandLine = [
"console=ttyAMA0,38400"
];
hardware =
let
addr = lim.parseInt "0x40010000";
in
{
loadAddress = addr;
entryPoint = addr;
};
};
boot.commandLine = [
"console=ttyAMA0,38400"
];
hardware = let addr = lim.parseInt "0x40010000"; in {
loadAddress = addr;
entryPoint = addr;
};
};
}
+29 -23
View File
@@ -5,7 +5,7 @@
{
system = {
crossSystem = {
config = "armv7l-unknown-linux-musleabihf";
config = "armv7l-unknown-linux-musleabihf";
};
};
@@ -24,30 +24,36 @@
'';
installer = "vmroot";
module = { config, lim, ... }: {
imports = [
../../modules/arch/arm.nix
../families/qemu.nix
];
kernel = {
config = {
PCI_HOST_GENERIC = "y";
ARCH_VIRT = "y";
module =
{ config, lim, ... }:
{
imports = [
../../modules/arch/arm.nix
../families/qemu.nix
];
kernel = {
config = {
PCI_HOST_GENERIC = "y";
ARCH_VIRT = "y";
VFP = "y";
NEON = "y";
AEABI = "y";
VFP = "y";
NEON = "y";
AEABI = "y";
SERIAL_AMBA_PL011 = "y";
SERIAL_AMBA_PL011_CONSOLE = "y";
SERIAL_AMBA_PL011 = "y";
SERIAL_AMBA_PL011_CONSOLE = "y";
};
};
boot.commandLine = [
"console=ttyAMA0"
];
hardware =
let
addr = lim.parseInt "0x40008000";
in
{
loadAddress = addr;
entryPoint = addr;
};
};
boot.commandLine = [
"console=ttyAMA0"
];
hardware = let addr = lim.parseInt "0x40008000"; in {
loadAddress = addr;
entryPoint = addr;
};
};
}
+43 -34
View File
@@ -7,7 +7,7 @@
config = "mips-unknown-linux-musl";
gcc = {
abi = "32";
arch = "mips32"; # maybe mips_24kc-
arch = "mips32"; # maybe mips_24kc-
};
};
};
@@ -36,41 +36,50 @@
in the Development manual.
'';
module = { config, lib, lim, ... }: {
imports = [
../../modules/arch/mipseb.nix
../families/qemu.nix
];
kernel = {
config = {
MIPS_MALTA= "y";
CPU_MIPS32_R2= "y";
module =
{
config,
lib,
lim,
...
}:
{
imports = [
../../modules/arch/mipseb.nix
../families/qemu.nix
];
kernel = {
config = {
MIPS_MALTA = "y";
CPU_MIPS32_R2 = "y";
POWER_RESET = "y";
POWER_RESET_SYSCON = "y";
POWER_RESET = "y";
POWER_RESET_SYSCON = "y";
SERIAL_8250= "y";
SERIAL_8250_CONSOLE= "y";
};
};
hardware =
# from arch/mips/mti-malta/Platform:load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000
let addr = lim.parseInt "0x80100000";
in {
loadAddress = addr;
entryPoint = addr;
# Unlike the arm qemu targets, we need a static dts when
# running u-boot-using tests, qemu dumpdtb command doesn't
# work for this board. I am not at all sure this dts is
# *correct* but it does at least boot
dts = lib.mkForce {
src = "${config.system.outputs.kernel.modulesupport}/arch/mips/boot/dts/mti/malta.dts";
includePaths = [
"${config.system.outputs.kernel.modulesupport}/arch/mips/boot/dts/"
];
SERIAL_8250 = "y";
SERIAL_8250_CONSOLE = "y";
};
};
};
hardware =
# from arch/mips/mti-malta/Platform:load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000
let
addr = lim.parseInt "0x80100000";
in
{
loadAddress = addr;
entryPoint = addr;
# Unlike the arm qemu targets, we need a static dts when
# running u-boot-using tests, qemu dumpdtb command doesn't
# work for this board. I am not at all sure this dts is
# *correct* but it does at least boot
dts = lib.mkForce {
src = "${config.system.outputs.kernel.modulesupport}/arch/mips/boot/dts/mti/malta.dts";
includePaths = [
"${config.system.outputs.kernel.modulesupport}/arch/mips/boot/dts/"
];
};
};
};
}
+381 -367
View File
@@ -33,16 +33,25 @@
};
};
module = {pkgs, config, lib, lim, ... }:
let firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = ["installPhase"];
installPhase = ''
mkdir $out
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out
'';
};
in {
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = [ "installPhase" ];
installPhase = ''
mkdir $out
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out
'';
};
in
{
imports = [
../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix
@@ -53,273 +62,275 @@
extraPatchPhase = ''
${pkgs.openwrt.applyPatches.ramips}
'';
config = {
# Initially taken from openwrt's ./target/linux/ramips/mt7621/config-5.15,
# then tweaked here and there
ARCH_32BIT_OFF_T="y";
ARCH_HIBERNATION_POSSIBLE="y";
ARCH_KEEP_MEMBLOCK="y";
ARCH_MMAP_RND_BITS_MAX="15";
ARCH_MMAP_RND_COMPAT_BITS_MAX="15";
ARCH_SUSPEND_POSSIBLE="y";
AT803X_PHY="y";
BLK_MQ_PCI="y";
BOARD_SCACHE="y";
CEVT_R4K="y";
CLKSRC_MIPS_GIC="y";
CLK_MT7621="y";
CLOCKSOURCE_WATCHDOG="y";
CLONE_BACKWARDS="y";
CMDLINE_BOOL="y";
COMMON_CLK="y";
COMPAT_32BIT_TIME="y";
CPU_GENERIC_DUMP_TLB="y";
CPU_HAS_DIEI="y";
CPU_HAS_PREFETCH="y";
CPU_HAS_RIXI="y";
CPU_HAS_SYNC="y";
CPU_LITTLE_ENDIAN="y";
CPU_MIPS32="y";
CPU_MIPS32_R2="y";
CPU_MIPSR2="y";
CPU_MIPSR2_IRQ_EI="y";
CPU_MIPSR2_IRQ_VI="y";
CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS="y";
CPU_R4K_CACHE_TLB="y";
CPU_RMAP="y";
CPU_SUPPORTS_32BIT_KERNEL="y";
CPU_SUPPORTS_HIGHMEM="y";
CPU_SUPPORTS_MSA="y";
CRC16="y";
CRYPTO_DEFLATE="y";
CRYPTO_HASH_INFO="y";
CRYPTO_LIB_BLAKE2S_GENERIC="y";
CRYPTO_LIB_POLY1305_RSIZE="2";
CRYPTO_LZO="y";
CRYPTO_ZSTD="y";
CSRC_R4K="y";
DIMLIB="y";
DMA_NONCOHERENT="y";
DTB_RT_NONE="y";
DTC="y";
EARLY_PRINTK="y";
FIXED_PHY="y";
FWNODE_MDIO="y";
FW_LOADER_PAGED_BUF="y";
GENERIC_ATOMIC64="y";
GENERIC_CLOCKEVENTS="y";
GENERIC_CMOS_UPDATE="y";
GENERIC_CPU_AUTOPROBE="y";
GENERIC_FIND_FIRST_BIT="y";
GENERIC_GETTIMEOFDAY="y";
GENERIC_IOMAP="y";
GENERIC_IRQ_CHIP="y";
GENERIC_IRQ_EFFECTIVE_AFF_MASK="y";
GENERIC_IRQ_SHOW="y";
GENERIC_LIB_ASHLDI3="y";
GENERIC_LIB_ASHRDI3="y";
GENERIC_LIB_CMPDI2="y";
GENERIC_LIB_LSHRDI3="y";
GENERIC_LIB_UCMPDI2="y";
GENERIC_PCI_IOMAP="y";
GENERIC_PHY="y";
GENERIC_PINCONF="y";
GENERIC_SCHED_CLOCK="y";
GENERIC_SMP_IDLE_THREAD="y";
GENERIC_TIME_VSYSCALL="y";
GLOB="y";
GPIOLIB_IRQCHIP="y";
GPIO_CDEV="y";
GPIO_GENERIC="y";
GPIO_MT7621="y";
GRO_CELLS="y";
HANDLE_DOMAIN_IRQ="y";
HARDWARE_WATCHPOINTS="y";
HAS_DMA="y";
HAS_IOMEM="y";
HAS_IOPORT_MAP="y";
I2C="y";
I2C_ALGOBIT="y";
I2C_BOARDINFO="y";
I2C_CHARDEV="y";
I2C_GPIO="y";
I2C_MT7621="y";
ICPLUS_PHY="y";
IRQCHIP="y";
IRQ_DOMAIN="y";
IRQ_DOMAIN_HIERARCHY="y";
IRQ_FORCED_THREADING="y";
IRQ_MIPS_CPU="y";
IRQ_WORK="y";
LIBFDT="y";
LOCK_DEBUGGING_SUPPORT="y";
LZO_COMPRESS="y";
LZO_DECOMPRESS="y";
MDIO_BUS="y";
MDIO_DEVICE="y";
MDIO_DEVRES="y";
MEDIATEK_GE_PHY="y";
MEMFD_CREATE="y";
MFD_SYSCON="y";
MIGRATION="y";
MIKROTIK="y";
MIKROTIK_RB_SYSFS="y";
MIPS="y";
MIPS_ASID_BITS="8";
MIPS_ASID_SHIFT="0";
MIPS_CLOCK_VSYSCALL="y";
MIPS_CM="y";
MIPS_CPC="y";
MIPS_CPS="y";
MIPS_CPU_SCACHE="y";
MIPS_GIC="y";
MIPS_L1_CACHE_SHIFT="5";
MIPS_LD_CAN_LINK_VDSO="y";
MIPS_MT="y";
MIPS_MT_FPAFF="y";
MIPS_MT_SMP="y";
MIPS_NR_CPU_NR_MAP="4";
MIPS_PERF_SHARED_TC_COUNTERS="y";
MIPS_SPRAM="y";
MODULES_USE_ELF_REL="y";
MTD_CMDLINE_PARTS="y";
MTD_NAND_CORE="y";
MTD_NAND_ECC="y";
MTD_NAND_ECC_SW_HAMMING="y";
MTD_NAND_MT7621="y";
MTD_NAND_MTK_BMT="y";
MTD_RAW_NAND="y";
MTD_ROUTERBOOT_PARTS="y";
MTD_SERCOMM_PARTS="y";
MTD_SPI_NOR="y";
MTD_SPLIT_FIT_FW="y";
MTD_SPLIT_MINOR_FW="y";
MTD_SPLIT_SEAMA_FW="y";
MTD_SPLIT_TPLINK_FW="y";
MTD_SPLIT_TRX_FW="y";
MTD_SPLIT_UIMAGE_FW="y";
MTD_UBI="y";
MTD_UBI_BEB_LIMIT="20";
MTD_UBI_BLOCK="y";
MTD_UBI_WL_THRESHOLD="4096";
MTD_VIRT_CONCAT="y";
NEED_DMA_MAP_STATE="y";
NET_DEVLINK="y";
NET_DSA="y";
NET_DSA_MT7530="y";
NET_DSA_MT7530_MDIO="y";
NET_DSA_TAG_MTK="y";
NET_FLOW_LIMIT="y";
NET_MEDIATEK_SOC="y";
NET_SELFTESTS="y";
NET_SWITCHDEV="y";
NET_VENDOR_MEDIATEK="y";
NO_HZ_COMMON="y";
NO_HZ_IDLE="y";
NR_CPUS="4";
NVMEM="y";
OF="y";
OF_ADDRESS="y";
OF_EARLY_FLATTREE="y";
OF_FLATTREE="y";
OF_GPIO="y";
OF_IRQ="y";
OF_KOBJ="y";
OF_MDIO="y";
PAGE_POOL="y";
PAGE_POOL_STATS="y";
PCI="y";
PCIE_MT7621="y";
PCI_DISABLE_COMMON_QUIRKS="y";
PCI_DOMAINS="y";
PCI_DOMAINS_GENERIC="y";
PCI_DRIVERS_GENERIC="y";
PCS_MTK_LYNXI="y";
PERF_USE_VMALLOC="y";
PGTABLE_LEVELS="2";
PHYLIB="y";
PHYLINK="y";
PHY_MT7621_PCI="y";
PINCTRL="y";
PINCTRL_AW9523="y";
PINCTRL_MT7621="y";
PINCTRL_RALINK="y";
PINCTRL_SX150X="y";
POWER_RESET="y";
POWER_RESET_GPIO="y";
POWER_SUPPLY="y";
PTP_1588_CLOCK_OPTIONAL="y";
QUEUED_RWLOCKS="y";
QUEUED_SPINLOCKS="y";
RALINK="y";
RATIONAL="y";
REGMAP="y";
REGMAP_I2C="y";
REGMAP_MMIO="y";
REGULATOR="y";
REGULATOR_FIXED_VOLTAGE="y";
RESET_CONTROLLER="y";
RFS_ACCEL="y";
RPS="y";
RTC_CLASS="y";
RTC_DRV_BQ32K="y";
RTC_DRV_PCF8563="y";
RTC_I2C_AND_SPI="y";
SCHED_SMT="y";
SERIAL_8250="y";
SERIAL_8250_CONSOLE="y";
SERIAL_8250_NR_UARTS="3";
SERIAL_8250_RUNTIME_UARTS="3";
SERIAL_MCTRL_GPIO="y";
SERIAL_OF_PLATFORM="y";
SGL_ALLOC="y";
SMP="y";
SMP_UP="y";
SOCK_RX_QUEUE_MAPPING="y";
SOC_BUS="y";
SOC_MT7621="y";
SPI="y";
SPI_MASTER="y";
SPI_MEM="y";
SPI_MT7621="y";
SRCU="y";
SWPHY="y";
SYNC_R4K="y";
SYSCTL_EXCEPTION_TRACE="y";
SYS_HAS_CPU_MIPS32_R1="y";
SYS_HAS_CPU_MIPS32_R2="y";
SYS_HAS_EARLY_PRINTK="y";
SYS_SUPPORTS_32BIT_KERNEL="y";
SYS_SUPPORTS_ARBIT_HZ="y";
SYS_SUPPORTS_HIGHMEM="y";
SYS_SUPPORTS_HOTPLUG_CPU="y";
SYS_SUPPORTS_LITTLE_ENDIAN="y";
SYS_SUPPORTS_MIPS16="y";
SYS_SUPPORTS_MIPS_CPS="y";
SYS_SUPPORTS_MULTITHREADING="y";
SYS_SUPPORTS_SCHED_SMT="y";
SYS_SUPPORTS_SMP="y";
SYS_SUPPORTS_ZBOOT="y";
TARGET_ISA_REV="2";
TICK_CPU_ACCOUNTING="y";
TIMER_OF="y";
TIMER_PROBE="y";
TREE_RCU="y";
TREE_SRCU="y";
UBIFS_FS="y";
USB_SUPPORT="y";
USE_OF="y";
WEAK_ORDERING="y";
XPS="y";
XXHASH="y";
ZLIB_DEFLATE="y";
ZLIB_INFLATE="y";
ZSTD_COMPRESS="y";
ZSTD_DECOMPRESS="y";
} // lib.optionalAttrs (config.system.service ? watchdog) {
RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};
config =
{
# Initially taken from openwrt's ./target/linux/ramips/mt7621/config-5.15,
# then tweaked here and there
ARCH_32BIT_OFF_T = "y";
ARCH_HIBERNATION_POSSIBLE = "y";
ARCH_KEEP_MEMBLOCK = "y";
ARCH_MMAP_RND_BITS_MAX = "15";
ARCH_MMAP_RND_COMPAT_BITS_MAX = "15";
ARCH_SUSPEND_POSSIBLE = "y";
AT803X_PHY = "y";
BLK_MQ_PCI = "y";
BOARD_SCACHE = "y";
CEVT_R4K = "y";
CLKSRC_MIPS_GIC = "y";
CLK_MT7621 = "y";
CLOCKSOURCE_WATCHDOG = "y";
CLONE_BACKWARDS = "y";
CMDLINE_BOOL = "y";
COMMON_CLK = "y";
COMPAT_32BIT_TIME = "y";
CPU_GENERIC_DUMP_TLB = "y";
CPU_HAS_DIEI = "y";
CPU_HAS_PREFETCH = "y";
CPU_HAS_RIXI = "y";
CPU_HAS_SYNC = "y";
CPU_LITTLE_ENDIAN = "y";
CPU_MIPS32 = "y";
CPU_MIPS32_R2 = "y";
CPU_MIPSR2 = "y";
CPU_MIPSR2_IRQ_EI = "y";
CPU_MIPSR2_IRQ_VI = "y";
CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS = "y";
CPU_R4K_CACHE_TLB = "y";
CPU_RMAP = "y";
CPU_SUPPORTS_32BIT_KERNEL = "y";
CPU_SUPPORTS_HIGHMEM = "y";
CPU_SUPPORTS_MSA = "y";
CRC16 = "y";
CRYPTO_DEFLATE = "y";
CRYPTO_HASH_INFO = "y";
CRYPTO_LIB_BLAKE2S_GENERIC = "y";
CRYPTO_LIB_POLY1305_RSIZE = "2";
CRYPTO_LZO = "y";
CRYPTO_ZSTD = "y";
CSRC_R4K = "y";
DIMLIB = "y";
DMA_NONCOHERENT = "y";
DTB_RT_NONE = "y";
DTC = "y";
EARLY_PRINTK = "y";
FIXED_PHY = "y";
FWNODE_MDIO = "y";
FW_LOADER_PAGED_BUF = "y";
GENERIC_ATOMIC64 = "y";
GENERIC_CLOCKEVENTS = "y";
GENERIC_CMOS_UPDATE = "y";
GENERIC_CPU_AUTOPROBE = "y";
GENERIC_FIND_FIRST_BIT = "y";
GENERIC_GETTIMEOFDAY = "y";
GENERIC_IOMAP = "y";
GENERIC_IRQ_CHIP = "y";
GENERIC_IRQ_EFFECTIVE_AFF_MASK = "y";
GENERIC_IRQ_SHOW = "y";
GENERIC_LIB_ASHLDI3 = "y";
GENERIC_LIB_ASHRDI3 = "y";
GENERIC_LIB_CMPDI2 = "y";
GENERIC_LIB_LSHRDI3 = "y";
GENERIC_LIB_UCMPDI2 = "y";
GENERIC_PCI_IOMAP = "y";
GENERIC_PHY = "y";
GENERIC_PINCONF = "y";
GENERIC_SCHED_CLOCK = "y";
GENERIC_SMP_IDLE_THREAD = "y";
GENERIC_TIME_VSYSCALL = "y";
GLOB = "y";
GPIOLIB_IRQCHIP = "y";
GPIO_CDEV = "y";
GPIO_GENERIC = "y";
GPIO_MT7621 = "y";
GRO_CELLS = "y";
HANDLE_DOMAIN_IRQ = "y";
HARDWARE_WATCHPOINTS = "y";
HAS_DMA = "y";
HAS_IOMEM = "y";
HAS_IOPORT_MAP = "y";
I2C = "y";
I2C_ALGOBIT = "y";
I2C_BOARDINFO = "y";
I2C_CHARDEV = "y";
I2C_GPIO = "y";
I2C_MT7621 = "y";
ICPLUS_PHY = "y";
IRQCHIP = "y";
IRQ_DOMAIN = "y";
IRQ_DOMAIN_HIERARCHY = "y";
IRQ_FORCED_THREADING = "y";
IRQ_MIPS_CPU = "y";
IRQ_WORK = "y";
LIBFDT = "y";
LOCK_DEBUGGING_SUPPORT = "y";
LZO_COMPRESS = "y";
LZO_DECOMPRESS = "y";
MDIO_BUS = "y";
MDIO_DEVICE = "y";
MDIO_DEVRES = "y";
MEDIATEK_GE_PHY = "y";
MEMFD_CREATE = "y";
MFD_SYSCON = "y";
MIGRATION = "y";
MIKROTIK = "y";
MIKROTIK_RB_SYSFS = "y";
MIPS = "y";
MIPS_ASID_BITS = "8";
MIPS_ASID_SHIFT = "0";
MIPS_CLOCK_VSYSCALL = "y";
MIPS_CM = "y";
MIPS_CPC = "y";
MIPS_CPS = "y";
MIPS_CPU_SCACHE = "y";
MIPS_GIC = "y";
MIPS_L1_CACHE_SHIFT = "5";
MIPS_LD_CAN_LINK_VDSO = "y";
MIPS_MT = "y";
MIPS_MT_FPAFF = "y";
MIPS_MT_SMP = "y";
MIPS_NR_CPU_NR_MAP = "4";
MIPS_PERF_SHARED_TC_COUNTERS = "y";
MIPS_SPRAM = "y";
MODULES_USE_ELF_REL = "y";
MTD_CMDLINE_PARTS = "y";
MTD_NAND_CORE = "y";
MTD_NAND_ECC = "y";
MTD_NAND_ECC_SW_HAMMING = "y";
MTD_NAND_MT7621 = "y";
MTD_NAND_MTK_BMT = "y";
MTD_RAW_NAND = "y";
MTD_ROUTERBOOT_PARTS = "y";
MTD_SERCOMM_PARTS = "y";
MTD_SPI_NOR = "y";
MTD_SPLIT_FIT_FW = "y";
MTD_SPLIT_MINOR_FW = "y";
MTD_SPLIT_SEAMA_FW = "y";
MTD_SPLIT_TPLINK_FW = "y";
MTD_SPLIT_TRX_FW = "y";
MTD_SPLIT_UIMAGE_FW = "y";
MTD_UBI = "y";
MTD_UBI_BEB_LIMIT = "20";
MTD_UBI_BLOCK = "y";
MTD_UBI_WL_THRESHOLD = "4096";
MTD_VIRT_CONCAT = "y";
NEED_DMA_MAP_STATE = "y";
NET_DEVLINK = "y";
NET_DSA = "y";
NET_DSA_MT7530 = "y";
NET_DSA_MT7530_MDIO = "y";
NET_DSA_TAG_MTK = "y";
NET_FLOW_LIMIT = "y";
NET_MEDIATEK_SOC = "y";
NET_SELFTESTS = "y";
NET_SWITCHDEV = "y";
NET_VENDOR_MEDIATEK = "y";
NO_HZ_COMMON = "y";
NO_HZ_IDLE = "y";
NR_CPUS = "4";
NVMEM = "y";
OF = "y";
OF_ADDRESS = "y";
OF_EARLY_FLATTREE = "y";
OF_FLATTREE = "y";
OF_GPIO = "y";
OF_IRQ = "y";
OF_KOBJ = "y";
OF_MDIO = "y";
PAGE_POOL = "y";
PAGE_POOL_STATS = "y";
PCI = "y";
PCIE_MT7621 = "y";
PCI_DISABLE_COMMON_QUIRKS = "y";
PCI_DOMAINS = "y";
PCI_DOMAINS_GENERIC = "y";
PCI_DRIVERS_GENERIC = "y";
PCS_MTK_LYNXI = "y";
PERF_USE_VMALLOC = "y";
PGTABLE_LEVELS = "2";
PHYLIB = "y";
PHYLINK = "y";
PHY_MT7621_PCI = "y";
PINCTRL = "y";
PINCTRL_AW9523 = "y";
PINCTRL_MT7621 = "y";
PINCTRL_RALINK = "y";
PINCTRL_SX150X = "y";
POWER_RESET = "y";
POWER_RESET_GPIO = "y";
POWER_SUPPLY = "y";
PTP_1588_CLOCK_OPTIONAL = "y";
QUEUED_RWLOCKS = "y";
QUEUED_SPINLOCKS = "y";
RALINK = "y";
RATIONAL = "y";
REGMAP = "y";
REGMAP_I2C = "y";
REGMAP_MMIO = "y";
REGULATOR = "y";
REGULATOR_FIXED_VOLTAGE = "y";
RESET_CONTROLLER = "y";
RFS_ACCEL = "y";
RPS = "y";
RTC_CLASS = "y";
RTC_DRV_BQ32K = "y";
RTC_DRV_PCF8563 = "y";
RTC_I2C_AND_SPI = "y";
SCHED_SMT = "y";
SERIAL_8250 = "y";
SERIAL_8250_CONSOLE = "y";
SERIAL_8250_NR_UARTS = "3";
SERIAL_8250_RUNTIME_UARTS = "3";
SERIAL_MCTRL_GPIO = "y";
SERIAL_OF_PLATFORM = "y";
SGL_ALLOC = "y";
SMP = "y";
SMP_UP = "y";
SOCK_RX_QUEUE_MAPPING = "y";
SOC_BUS = "y";
SOC_MT7621 = "y";
SPI = "y";
SPI_MASTER = "y";
SPI_MEM = "y";
SPI_MT7621 = "y";
SRCU = "y";
SWPHY = "y";
SYNC_R4K = "y";
SYSCTL_EXCEPTION_TRACE = "y";
SYS_HAS_CPU_MIPS32_R1 = "y";
SYS_HAS_CPU_MIPS32_R2 = "y";
SYS_HAS_EARLY_PRINTK = "y";
SYS_SUPPORTS_32BIT_KERNEL = "y";
SYS_SUPPORTS_ARBIT_HZ = "y";
SYS_SUPPORTS_HIGHMEM = "y";
SYS_SUPPORTS_HOTPLUG_CPU = "y";
SYS_SUPPORTS_LITTLE_ENDIAN = "y";
SYS_SUPPORTS_MIPS16 = "y";
SYS_SUPPORTS_MIPS_CPS = "y";
SYS_SUPPORTS_MULTITHREADING = "y";
SYS_SUPPORTS_SCHED_SMT = "y";
SYS_SUPPORTS_SMP = "y";
SYS_SUPPORTS_ZBOOT = "y";
TARGET_ISA_REV = "2";
TICK_CPU_ACCOUNTING = "y";
TIMER_OF = "y";
TIMER_PROBE = "y";
TREE_RCU = "y";
TREE_SRCU = "y";
UBIFS_FS = "y";
USB_SUPPORT = "y";
USE_OF = "y";
WEAK_ORDERING = "y";
XPS = "y";
XXHASH = "y";
ZLIB_DEFLATE = "y";
ZLIB_INFLATE = "y";
ZSTD_COMPRESS = "y";
ZSTD_DECOMPRESS = "y";
}
// lib.optionalAttrs (config.system.service ? watchdog) {
RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};
conditionalConfig = {
WLAN = {
MT7915E = "m";
@@ -340,97 +351,100 @@
};
};
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in
dir {
lib = dir {
firmware = dir {
mediatek = symlink firmware;
};
};
};
hardware =
let
openwrt = pkgs.openwrt;
mac80211 = pkgs.kmodloader.override {
targets = [
"mt7915e"
];
inherit (config.system.outputs) kernel;
};
in {
# from OEM bootlog (openwrt wiki):
# 4 cmdlinepart partitions found on MTD device raspi
# Creating 4 MTD partitions on "raspi":
# 0x000000000000-0x000000040000 : "uboot"
# 0x000000040000-0x000000440000 : "uImage"
# 0x000000440000-0x000000ff0000 : "rootfs"
# 0x000000ff0000-0x000001000000 : "ART"
# from openwrt bootlog (openwrt wiki):
# 5 fixed-partitions partitions found on MTD device spi0.0
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# Creating 5 MTD partitions on "spi0.0":
# 0x000000000000-0x000000040000 : "u-boot"
# 0x000000040000-0x000000fa0000 : "firmware"
# 2 uimage-fw partitions found on MTD device firmware
# Creating 2 MTD partitions on "firmware":
# 0x000000000000-0x0000002c0000 : "kernel"
# 0x0000002c0000-0x000000f60000 : "rootfs"
# mtd: setting mtd3 (rootfs) as root device
# 1 squashfs-split partitions found on MTD device rootfs
# 0x000000640000-0x000000f60000 : "rootfs_data"
# 0x000000fa0000-0x000000fb0000 : "config"
# 0x000000fb0000-0x000000ff0000 : "tplink"
# 0x000000ff0000-0x000001000000 : "radio"
flash = {
# from the OEM bootlog 'Booting image at bc040000'
# (0x40000 from 0xbc000000)
address = lim.parseInt "0xbc040000";
# 0x000000040000-0x000000fa0000
size = lim.parseInt "0xf60000";
# TODO: find in /proc/mtd on a running system
eraseBlockSize = 65536;
};
# since this is mentioned in the partition table as well?
defaultOutput = "tplink-safeloader";
# taken from openwrt sysupgrade image:
# openwrt-23.05.2-ramips-mt7621-tplink_archer-ax23-v1-squashfs-sysupgrade.bin: u-boot legacy uImage, MIPS OpenWrt Linux-5.15.137, Linux/MIPS, OS Kernel Image (lzma), 2797386 bytes, Tue Nov 14 13:38:11 2023, Load Address: 0X80001000, Entry Point: 0X80001000, Header CRC: 0X19F74C5B, Data CRC: 0XF685563C
loadAddress = lim.parseInt "0x80001000";
entryPoint = lim.parseInt "0x80001000";
rootDevice = "/dev/mtdblock3";
dts = {
src = "${openwrt.src}/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts";
includePaths = [
"${openwrt.src}/target/linux/ramips/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
};
networkInterfaces =
let
inherit (config.system.service.network) link;
in rec {
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
wan = link.build { ifname = "wan"; };
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
let
inherit (pkgs.pseudofile) dir symlink;
in
dir {
lib = dir {
firmware = dir {
mediatek = symlink firmware;
};
};
};
};
};
hardware =
let
openwrt = pkgs.openwrt;
mac80211 = pkgs.kmodloader.override {
targets = [
"mt7915e"
];
inherit (config.system.outputs) kernel;
};
in
{
# from OEM bootlog (openwrt wiki):
# 4 cmdlinepart partitions found on MTD device raspi
# Creating 4 MTD partitions on "raspi":
# 0x000000000000-0x000000040000 : "uboot"
# 0x000000040000-0x000000440000 : "uImage"
# 0x000000440000-0x000000ff0000 : "rootfs"
# 0x000000ff0000-0x000001000000 : "ART"
# from openwrt bootlog (openwrt wiki):
# 5 fixed-partitions partitions found on MTD device spi0.0
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# OF: Bad cell count for /palmbus@1e000000/spi@b00/flash@0/partitions
# Creating 5 MTD partitions on "spi0.0":
# 0x000000000000-0x000000040000 : "u-boot"
# 0x000000040000-0x000000fa0000 : "firmware"
# 2 uimage-fw partitions found on MTD device firmware
# Creating 2 MTD partitions on "firmware":
# 0x000000000000-0x0000002c0000 : "kernel"
# 0x0000002c0000-0x000000f60000 : "rootfs"
# mtd: setting mtd3 (rootfs) as root device
# 1 squashfs-split partitions found on MTD device rootfs
# 0x000000640000-0x000000f60000 : "rootfs_data"
# 0x000000fa0000-0x000000fb0000 : "config"
# 0x000000fb0000-0x000000ff0000 : "tplink"
# 0x000000ff0000-0x000001000000 : "radio"
flash = {
# from the OEM bootlog 'Booting image at bc040000'
# (0x40000 from 0xbc000000)
address = lim.parseInt "0xbc040000";
# 0x000000040000-0x000000fa0000
size = lim.parseInt "0xf60000";
# TODO: find in /proc/mtd on a running system
eraseBlockSize = 65536;
};
# since this is mentioned in the partition table as well?
defaultOutput = "tplink-safeloader";
# taken from openwrt sysupgrade image:
# openwrt-23.05.2-ramips-mt7621-tplink_archer-ax23-v1-squashfs-sysupgrade.bin: u-boot legacy uImage, MIPS OpenWrt Linux-5.15.137, Linux/MIPS, OS Kernel Image (lzma), 2797386 bytes, Tue Nov 14 13:38:11 2023, Load Address: 0X80001000, Entry Point: 0X80001000, Header CRC: 0X19F74C5B, Data CRC: 0XF685563C
loadAddress = lim.parseInt "0x80001000";
entryPoint = lim.parseInt "0x80001000";
rootDevice = "/dev/mtdblock3";
dts = {
src = "${openwrt.src}/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts";
includePaths = [
"${openwrt.src}/target/linux/ramips/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
};
networkInterfaces =
let
inherit (config.system.service.network) link;
in
rec {
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
wan = link.build { ifname = "wan"; };
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
};
};
};
};
}
+119 -99
View File
@@ -153,11 +153,18 @@
};
};
module = {pkgs, config, lib, lim, ... }:
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
mtd_by_name_links = pkgs.liminix.services.oneshot rec {
mtd_by_name_links = pkgs.liminix.services.oneshot rec {
name = "mtd_by_name_links";
up = ''
mkdir -p /dev/mtd/by-name
@@ -167,7 +174,8 @@
done
'';
};
in {
in
{
imports = [
../../modules/arch/arm.nix
../../modules/outputs/tftpboot.nix
@@ -175,6 +183,9 @@
];
config = {
rootfsType = lib.mkDefault "btrfs"; # override this if you are building tftpboot
rootOptions = lib.mkDefault "subvol=@";
services.mtd-name-links = mtd_by_name_links;
kernel = {
src = pkgs.pkgsBuildBuild.fetchurl {
@@ -191,7 +202,7 @@
CPU_V7 = "y";
ARCH_MULTIPLATFORM = "y";
ARCH_MVEBU = "y";
ARCH_MULTI_V7= "y";
ARCH_MULTI_V7 = "y";
PCI_MVEBU = "y";
AHCI_MVEBU = "y";
@@ -201,7 +212,6 @@
EXPERT = "y";
ALLOW_DEV_COREDUMP = "n";
# dts has a compatible for this but dmesg is not
# showing it
EEPROM_AT24 = "y"; # atmel,24c64
@@ -212,44 +222,44 @@
MACH_ARMADA_38X = "y";
SMP = "y";
# this is disabled for the moment because it relies on a
# this is disabled for the moment because it relies on a
# GCC plugin that requires gmp.h to build, and I can't see
# right now how to confgure it to find gmp
STACKPROTECTOR_PER_TASK = "n";
NR_CPUS = "4";
VFP = "y";
NEON= "y";
NEON = "y";
# WARNING: unmet direct dependencies detected for ARCH_WANT_LIBATA_LEDS
ATA = "y";
BLOCK = "y";
MMC="y";
PWRSEQ_EMMC="y"; # ???
PWRSEQ_SIMPLE="y"; # ???
MMC_BLOCK="y";
MMC = "y";
PWRSEQ_EMMC = "y"; # ???
PWRSEQ_SIMPLE = "y"; # ???
MMC_BLOCK = "y";
MMC_SDHCI= "y";
MMC_SDHCI_PLTFM= "y";
MMC_SDHCI_PXAV3= "y";
MMC_MVSDIO= "y";
MMC_SDHCI = "y";
MMC_SDHCI_PLTFM = "y";
MMC_SDHCI_PXAV3 = "y";
MMC_MVSDIO = "y";
SERIAL_8250 = "y";
SERIAL_8250_CONSOLE = "y";
SERIAL_OF_PLATFORM="y";
SERIAL_OF_PLATFORM = "y";
SERIAL_MVEBU_UART = "y";
SERIAL_MVEBU_CONSOLE = "y";
SERIAL_8250_DMA= "y";
SERIAL_8250_DW= "y";
SERIAL_8250_EXTENDED= "y";
SERIAL_8250_MANY_PORTS= "y";
SERIAL_8250_SHARE_IRQ= "y";
OF_ADDRESS= "y";
OF_MDIO= "y";
SERIAL_8250_DMA = "y";
SERIAL_8250_DW = "y";
SERIAL_8250_EXTENDED = "y";
SERIAL_8250_MANY_PORTS = "y";
SERIAL_8250_SHARE_IRQ = "y";
OF_ADDRESS = "y";
OF_MDIO = "y";
WATCHDOG = "y"; # watchdog is enabled by u-boot
ORION_WATCHDOG = "y"; # so is non-optional to keep feeding
WATCHDOG = "y"; # watchdog is enabled by u-boot
ORION_WATCHDOG = "y"; # so is non-optional to keep feeding
MVEBU_DEVBUS = "y"; # "Device Bus controller ... flash devices such as NOR, NAND, SRAM, and FPGA"
MVMDIO = "y";
@@ -292,6 +302,7 @@
};
};
boot = {
loader.extlinux.enable = lib.mkDefault true; # override this if you are building tftpboot
commandLine = [
"console=ttyS0,115200"
"pcie_aspm=off" # ath9k pci incompatible with PCIe ASPM
@@ -302,13 +313,14 @@
inherit (pkgs.pseudofile) dir symlink;
firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = ["installPhase"];
phases = [ "installPhase" ];
installPhase = ''
mkdir $out
cp -r ${pkgs.linux-firmware}/lib/firmware/ath10k/QCA988X $out
'';
};
in dir {
in
dir {
lib = dir {
firmware = dir {
ath10k = symlink firmware;
@@ -316,10 +328,12 @@
};
etc = dir {
"fw_env.config" =
let f = pkgs.writeText "fw_env.config" ''
/dev/mtd/by-name/u-boot-env 0x0 0x10000 0x10000
'';
in symlink f;
let
f = pkgs.writeText "fw_env.config" ''
/dev/mtd/by-name/u-boot-env 0x0 0x10000 0x10000
'';
in
symlink f;
};
};
@@ -329,75 +343,81 @@
compressRoot = true;
};
hardware = let
mac80211 = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel;
targets = ["ath9k" "ath10k_pci"];
};
in {
defaultOutput = "updater";
loadAddress = lim.parseInt "0x00800000"; # "0x00008000";
entryPoint = lim.parseInt "0x00800000"; # "0x00008000";
rootDevice = "/dev/mmcblk0p1";
dts = {
src = "${config.system.outputs.kernel.modulesupport}/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts";
includePaths = [
"${config.system.outputs.kernel.modulesupport}/arch/arm/boot/dts/marvell/"
];
};
flash.eraseBlockSize = 65536; # only used for tftpboot
networkInterfaces =
let
inherit (config.system.service.network) link;
in rec {
en70000 = link.build {
# in armada-38x.dtsi this is eth0.
# It's connected to port 5 of the 88E6176 switch
devpath = "/devices/platform/soc/soc:internal-regs/f1070000.ethernet";
# name is unambiguous but not very semantic
ifname = "en70000";
};
en30000 = link.build {
# in armada-38x.dtsi this is eth1
# It's connected to port 6 of the 88E6176 switch
devpath = "/devices/platform/soc/soc:internal-regs/f1030000.ethernet";
# name is unambiguous but not very semantic
ifname = "en30000";
};
# the default (from the dts? I'm guessing) behavour for
# lan ports on the switch is to attach them to
# en30000. It should be possible to do something better,
# per
# https://www.kernel.org/doc/html/latest/networking/dsa/configuration.html#affinity-of-user-ports-to-cpu-ports
# but apparently OpenWrt doesn't either so maybe it's more
# complicated than it looks.
wan = link.build {
# in armada-38x.dtsi this is eth2. It may be connected to
# an ethernet phy or to the SFP cage, depending on a gpio
devpath = "/devices/platform/soc/soc:internal-regs/f1034000.ethernet";
ifname = "wan";
};
lan0 = link.build { ifname = "lan0"; };
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
lan5 = link.build { ifname = "lan5"; };
lan = lan0; # maybe we should build a bridge?
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
hardware =
let
mac80211 = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel;
targets = [
"ath9k"
"ath10k_pci"
];
};
};
in
{
defaultOutput = "updater";
loadAddress = lim.parseInt "0x00800000"; # "0x00008000";
entryPoint = lim.parseInt "0x00800000"; # "0x00008000";
rootDevice = "/dev/mmcblk0p1";
dts = {
src = "${config.system.outputs.kernel.modulesupport}/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts";
includePaths = [
"${config.system.outputs.kernel.modulesupport}/arch/arm/boot/dts/marvell/"
];
};
flash.eraseBlockSize = 65536; # only used for tftpboot
networkInterfaces =
let
inherit (config.system.service.network) link;
in
rec {
en70000 = link.build {
# in armada-38x.dtsi this is eth0.
# It's connected to port 5 of the 88E6176 switch
devpath = "/devices/platform/soc/soc:internal-regs/f1070000.ethernet";
# name is unambiguous but not very semantic
ifname = "en70000";
};
en30000 = link.build {
# in armada-38x.dtsi this is eth1
# It's connected to port 6 of the 88E6176 switch
devpath = "/devices/platform/soc/soc:internal-regs/f1030000.ethernet";
# name is unambiguous but not very semantic
ifname = "en30000";
};
# the default (from the dts? I'm guessing) behavour for
# lan ports on the switch is to attach them to
# en30000. It should be possible to do something better,
# per
# https://www.kernel.org/doc/html/latest/networking/dsa/configuration.html#affinity-of-user-ports-to-cpu-ports
# but apparently OpenWrt doesn't either so maybe it's more
# complicated than it looks.
wan = link.build {
# in armada-38x.dtsi this is eth2. It may be connected to
# an ethernet phy or to the SFP cage, depending on a gpio
devpath = "/devices/platform/soc/soc:internal-regs/f1034000.ethernet";
ifname = "wan";
};
lan0 = link.build { ifname = "lan0"; };
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
lan5 = link.build { ifname = "lan5"; };
lan = lan0; # maybe we should build a bridge?
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
};
};
};
};
}
+99 -87
View File
@@ -4,7 +4,7 @@
config = "mipsel-unknown-linux-musl";
gcc = {
abi = "32";
arch = "mips32"; # mips32r2?
arch = "mips32"; # mips32r2?
};
};
};
@@ -101,7 +101,14 @@
'';
module = { pkgs, config, lib, lim, ...}:
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;
@@ -123,7 +130,8 @@
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_rom_patch.bin";
hash = "sha256-ifriAjWzFACrxVWCANZpUaEZgB/0pdbhnTVQytx6ddg=";
};
in {
in
{
imports = [
# We include it to ensure the bridge functionality
# is available on the target kernel.
@@ -201,7 +209,8 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
in {
in
{
eth = link.build { ifname = "eth0"; };
lan = link.build { ifname = "lan"; };
wlan0 = link.build {
@@ -253,107 +262,110 @@
extraPatchPhase = ''
${openwrt.applyPatches.ramips}
'';
config = {
config =
{
RALINK = "y";
PCI = "y";
PHY_MT7621_PCI = "y";
PCIE_MT7621 = "y";
SOC_MT7621 = "y";
CLK_MT7621 = "y";
CLOCKSOURCE_WATCHDOG = "y";
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";
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";
CONSOLE_LOGLEVEL_DEFAULT = "8";
CONSOLE_LOGLEVEL_QUIET = "4";
# MTD_UBI_BEB_LIMIT = "20";
# MTD_UBI_WL_THRESHOLD = "4096";
# 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";
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";
PINCTRL = "y";
PINCTRL_MT7621 = "y";
I2C = "y";
I2C_MT7621 = "y";
I2C = "y";
I2C_MT7621 = "y";
SPI = "y";
MTD_SPI_NOR = "y";
SPI_MT7621 = "y";
SPI_MASTER = "y";
SPI_MEM = "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";
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";
PCI_DISABLE_COMMON_QUIRKS = "y";
PCI_DOMAINS = "y";
PCI_DOMAINS_GENERIC = "y";
PCI_DRIVERS_GENERIC = "y";
PCS_MTK_LYNXI = "y";
SOC_BUS = "y";
SOC_BUS = "y";
NET = "y";
ETHERNET = "y";
WLAN = "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";
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";
SWPHY = "y";
GPIOLIB = "y";
GPIO_MT7621 = "y";
OF_GPIO = "y";
GPIOLIB = "y";
GPIO_MT7621 = "y";
OF_GPIO = "y";
EARLY_PRINTK = "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";
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
};
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
};
};
};
}
+45 -16
View File
@@ -145,17 +145,8 @@ to :file:`/dev/pmsg0` as well as to the regular log. This is a
circular buffer, so when it fills up newer messages will overwrite the
oldest messages.
To check the previous messages after a (planned or forced) reboot,
you need to mooun the pstore filesystem.
.. code-block:: console
# mount -t pstore pstore /sys/fs/pstore/
# ls -l /sys/fs/pstore/
-r--r--r-- 1 43071 pmsg-ramoops-0
# cat /sys/fs/pstore/pmsg-ramoops-0
@40000000000000282c997d29 mydevice klogd <6>[ 30.793756] int: port 2(wlan0) entered blocking state
[log messages from before the reboot follow]
Logs found in pstore after a reboot will be moved at startup to
:file:`/run/log/previous-boot`
@@ -197,16 +188,54 @@ the current system closure. Note that Liminix does not have the NixOS
concept of environments or generations, and there is no way back from
this except for building the previous configuration again.
Caveats
-------
* it needs there to be enough free space on the device for all the new
packages in addition to all the packages already on it - which may be
a problem if a lot of things have changed (e.g. a new version of
nixpkgs).
packages in addition to all the packages already on it - which may
be a problem if there is little flash storage or if a lot of things
have changed (e.g. a new version of nixpkgs).
* it may not be able to upgrade the kernel: this is device-dependent.
If your device boots from a kernel image on a raw MTD partition or
or UBI volume, update.sh is unable to alter the kernel partition.
If your device boots from a kernel inside the filesystem (e.g. using
bootloader.extlinux or bootloder.fit) then the kernel will be
upgraded along with the userland
Recovery/downgrades
-------------------
The :command:`update.sh` script also creates a timestamped symlink on
the device which points to the system configuration it installs. If
you install a configuration that doesn't work, you can revert to any
other installed configuration by
1) booting to some kind of rescue or recovery system (which may be
some vendor-provided rescue option, or your own recovery system
perhaps based on :file:`examples/recovery.nix`) and mounting
your Liminix filesystem on /mnt
2) picking another previously-installed configuration that _did_ work,
and switching back to it:
.. code-block:: console
# ls -ld /mnt/*configuration
lrwxrwxrwx 1 90 /mnt/20252102T182104.configuration -> nix/store/v1w0h4zw65ah4c2r0k7nyy125qrxhq78-system-configuration-aarch64-unknown-linux-musl
lrwxrwxrwx 1 90 /mnt/20251802T181822.configuration -> nix/store/wqjl9s9xljl2wg8257292zghws9ssidk-system-configuration-aarch64-unknown-linux-musl
# : 20251802T181822 is the working system, so reinstall it
# /mnt/20251802T181822.configuration/bin/install /mnt
# umount /mnt
# reboot
This will install the previous configuration's activation binary into
/bin, and copy its kernel and initramfs into /boot. Note that it
depends on the previous system not having been garbage-collected.
* it cannot upgrade the kernel, only userland
.. _levitate:
+19 -12
View File
@@ -1,4 +1,8 @@
{ eval, lib, pkgs }:
{
eval,
lib,
pkgs,
}:
let
conf = eval.config;
rootDir = builtins.toPath ./..;
@@ -7,21 +11,24 @@ let
inherit name;
description = opt.description or null;
default = opt.default or null;
visible =
if (opt ? visible && opt.visible == "shallow")
then true
else opt.visible or true;
visible = if (opt ? visible && opt.visible == "shallow") then true else opt.visible or true;
readOnly = opt.readOnly or false;
type = opt.type.description or "unspecified";
};
spliceServiceDefn = item :
if item.type == "parametrisable s6-rc service definition"
then
let sd = lib.attrByPath item.loc ["not found"] conf;
in item // {
declarations = map stripAnyPrefixes item.declarations;
spliceServiceDefn =
item:
if item.type == "parametrisable s6-rc service definition" then
let
sd = lib.attrByPath item.loc [ "not found" ] conf;
in
item
// {
declarations = map stripAnyPrefixes item.declarations;
parameters =
let x = lib.mapAttrsToList optToDoc sd.parameters; in x;
let
x = lib.mapAttrsToList optToDoc sd.parameters;
in
x;
}
else
item // { declarations = map stripAnyPrefixes item.declarations; };
+2 -2
View File
@@ -7,7 +7,7 @@ let
n:
let
d = import ../devices/${n}/default.nix;
tag = ".. _${lib.strings.replaceStrings [" "] ["-"] n}:";
tag = ".. _${lib.strings.replaceStrings [ " " ] [ "-" ] n}:";
d' = {
description = ''
${n}
@@ -15,7 +15,7 @@ let
'';
} // d;
in
"${tag}\n\n${d'.description}"
"${tag}\n\n${d'.description}"
) devices;
in
writeText "hwdoc" ''
+2 -2
View File
@@ -116,8 +116,8 @@ TFTP server you're using and so is out of scope for this document.
Buildiing and installing the image
==================================
Building and installing the image
=================================
Follow the device-specific instructions for "TFTP install": usually,
the steps are
+21 -11
View File
@@ -9,13 +9,15 @@
pkgs,
lib,
...
}: let
}:
let
secrets = import ./extneder-secrets.nix;
inherit (pkgs.liminix.services) oneshot longrun target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) writeText serviceFns;
svc = config.system.service;
in rec {
in
rec {
boot = {
tftp = {
serverip = "10.0.0.1";
@@ -34,10 +36,11 @@ in rec {
];
hostname = "arhcive";
services.dhcpc =
let iface = config.hardware.networkInterfaces.lan;
in svc.network.dhcp.client.build {
let
iface = config.hardware.networkInterfaces.lan;
in
svc.network.dhcp.client.build {
interface = iface;
dependencies = [ config.services.hostname ];
};
@@ -45,7 +48,10 @@ in rec {
services.sshd = svc.ssh.build { };
services.watchdog = svc.watchdog.build {
watched = with config.services ; [ sshd dhcpc ];
watched = with config.services; [
sshd
dhcpc
];
};
services.resolvconf = oneshot rec {
@@ -63,17 +69,20 @@ in rec {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
srv = dir {};
srv = dir { };
};
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.dhcpc} router)";
target = "default";
dependencies = [services.dhcpc];
dependencies = [ services.dhcpc ];
};
programs.busybox = {
applets = ["lsusb" "tar"];
programs.busybox = {
applets = [
"lsusb"
"tar"
];
options = {
FEATURE_LS_TIMESTAMPS = "y";
FEATURE_LS_SORTFILES = "y";
@@ -108,7 +117,8 @@ in rec {
gid = backup
secrets file = ${secrets_file}/.outputs/secrets
'';
in longrun {
in
longrun {
name = "rsync";
run = ''
${pkgs.rsyncSmall}/bin/rsync --no-detach --daemon --config=${configFile}
+23 -12
View File
@@ -14,7 +14,8 @@ let
ipv4LocalNet = "10.8.0";
svc = config.system.service;
in rec {
in
rec {
boot = {
tftp = {
freeSpaceBytes = 3 * 1024 * 1024;
@@ -99,8 +100,10 @@ in rec {
};
services.dns =
let interface = services.int;
in svc.dnsmasq.build {
let
interface = services.int;
in
svc.dnsmasq.build {
resolvconf = services.resolvconf;
inherit interface;
ranges = [
@@ -124,12 +127,16 @@ in rec {
services.wan = svc.pppoe.build {
interface = config.hardware.networkInterfaces.wan;
ppp-options = [
"debug" "+ipv6" "noauth"
"debug"
"+ipv6"
"noauth"
# EDIT: change the strings "chap-username"
# and "chap-secret" to match the username/password
# provided by your ISP for PPP logins
"name" "chap-username"
"password" "chap-secret"
"name"
"chap-username"
"password"
"chap-secret"
];
};
@@ -146,8 +153,10 @@ in rec {
};
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in dir {
let
inherit (pkgs.pseudofile) dir symlink;
in
dir {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
@@ -176,10 +185,12 @@ in rec {
# LAN interfaces respectively.
services.dhcp6c =
let client = svc.dhcp6c.client.build {
interface = services.wan;
};
in bundle {
let
client = svc.dhcp6c.client.build {
interface = services.wan;
};
in
bundle {
name = "dhcp6c";
contents = [
(svc.dhcp6c.prefix.build {
+12 -5
View File
@@ -10,10 +10,12 @@
lib,
modulesPath,
...
}: let
}:
let
secrets = import ./extneder-secrets.nix;
svc = config.system.service;
in rec {
in
rec {
boot = {
tftp = {
serverip = "192.168.8.148";
@@ -30,7 +32,7 @@ in rec {
hostname = "extneder";
profile.wap = {
interfaces = with config.hardware.networkInterfaces; [
interfaces = with config.hardware.networkInterfaces; [
lan
wlan
];
@@ -47,7 +49,12 @@ in rec {
};
};
services.sshd = svc.ssh.build {};
services.sshd = svc.ssh.build { };
users.root.passwd = lib.mkForce secrets.root.passwd;
defaultProfile.packages = with pkgs; [nftables strace tcpdump swconfig];
defaultProfile.packages = with pkgs; [
nftables
strace
tcpdump
swconfig
];
}
+3 -2
View File
@@ -1,8 +1,9 @@
{ config, pkgs, ... } :
{ config, pkgs, ... }:
let
svc = config.system.service;
in rec {
in
rec {
imports = [
../modules/network
../modules/ssh
+10 -5
View File
@@ -1,8 +1,9 @@
{ config, pkgs, ... } :
{ config, pkgs, ... }:
let
svc = config.system.service;
in rec {
in
rec {
imports = [
../modules/network
../modules/dnsmasq
@@ -14,7 +15,9 @@ in rec {
# configure the internal network (LAN) with an address
services.int = svc.network.address.build {
interface = config.hardware.networkInterfaces.lan;
family = "inet"; address ="10.3.0.1"; prefixLength = 16;
family = "inet";
address = "10.3.0.1";
prefixLength = 16;
};
services.sshd = svc.ssh.build { };
@@ -26,8 +29,10 @@ in rec {
};
services.dns =
let interface = services.int;
in svc.dnsmasq.build {
let
interface = services.int;
in
svc.dnsmasq.build {
inherit interface;
ranges = [
"10.3.0.10,10.3.0.240"
+86
View File
@@ -0,0 +1,86 @@
# This is "contrib"-level code. This module solves a particular
# problem for my particular setup and is provided as is, as an example
# of how you might write something similar if you had a similar
# problem. Don't expect it to work unmolested in your setup (you will
# at the absolute minimum have to change the domain name), nor even to
# continue to exist without possibly being changed beyond recognition.
# The computers on my LAN have globally unique routable IPv6
# addresses, but I have only one public IPv4 address. I want to expose
# HTTPS services to the Internet _whatever_ machine is hosting them,
# so I publish an AAAA record to the machine itself, and an A record
# to the public v4 address of the router which is running this nginx.
# This nginx checks the SNI in the incoming connection and forwards
# the connection to the (IPv6 address of the) same hostname
# See https://ww.telent.net/2020/12/2/six_into_4_won_t_go for
# the original solution to this problem, which used sniproxy (now
# unmaintained) instead of nginx
{ config, pkgs, ... }:
let
inherit (pkgs.liminix.services) longrun;
inherit (pkgs) writeText;
nginx_uid = 62;
in
{
config = {
users.nginx = {
uid = nginx_uid;
gid = nginx_uid;
dir = "/run/";
shell = "/bin/false";
};
groups.nginx = {
gid = nginx_uid;
usernames = [ "nginx" ];
};
services.sniproxy =
let
nginx = pkgs.nginx-small.override {
pcre = null;
zlib = null;
options = [
"stream"
"stream_ssl_module"
"stream_ssl_preread_module"
"stream_map_module"
];
};
conf = writeText "nginx.conf" ''
worker_processes auto;
error_log /proc/self/fd/1 info;
pid /dev/null;
user nginx;
daemon off;
events {
worker_connections 1024;
}
stream {
log_format proxy '$remote_addr -> $ssl_target';
access_log /proc/self/fd/1 proxy;
map $ssl_preread_server_name $ssl_target {
hostnames;
.telent.net $ssl_preread_server_name:443;
}
server {
listen 443;
resolver 127.0.0.1 ipv6=on ipv4=off;
resolver_timeout 1s;
proxy_pass $ssl_target;
ssl_preread on;
}
}
'';
in
longrun {
name = "sniproxy";
run = ''
${nginx}/bin/nginx -c ${conf}
'';
};
};
}
+24 -10
View File
@@ -1,4 +1,4 @@
{ config, pkgs, ... } :
{ config, pkgs, ... }:
let
inherit (pkgs.liminix.services) target;
svc = config.system.service;
@@ -43,13 +43,16 @@ let
he_oper_centr_freq_seg0_idx = 42;
require_vht = 1;
};
mkWifiSta = params: interface: secrets: svc.hostapd.build {
inherit interface;
mkWifiSta =
params: interface: secrets:
svc.hostapd.build {
inherit interface;
params = params // {
inherit (secrets) ssid wpa_passphrase;
};
};
in rec {
};
in
rec {
imports = [
../modules/wlan.nix
../modules/network
@@ -87,8 +90,10 @@ in rec {
};
services.dhcpv4 =
let iface = services.int;
in svc.network.dhcp.client.build { interface = iface; };
let
iface = services.int;
in
svc.network.dhcp.client.build { interface = iface; };
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.dhcpv4} address)";
@@ -102,7 +107,9 @@ in rec {
};
services.ntp = config.system.service.ntp.build {
pools = { "pool.ntp.org" = ["iburst"] ; };
pools = {
"pool.ntp.org" = [ "iburst" ];
};
};
boot.tftp = {
@@ -113,7 +120,14 @@ in rec {
# 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;
services.hostap-2 = mkWifiSta (
baseParams // modernParams
) config.hardware.networkInterfaces.wlan1 secrets-2;
defaultProfile.packages = with pkgs; [ zyxel-bootconfig iw min-collect-garbage mtdutils ];
defaultProfile.packages = with pkgs; [
zyxel-bootconfig
iw
min-collect-garbage
mtdutils
];
}
+27 -17
View File
@@ -1,4 +1,9 @@
{ config, pkgs, lib, ... } :
{
config,
pkgs,
lib,
...
}:
let
inherit (pkgs) serviceFns;
svc = config.system.service;
@@ -9,7 +14,8 @@ let
cd ${pkgs.util-linux-small}/bin
cp fdisk sfdisk mkswap $out/bin
'';
in rec {
in
rec {
imports = [
../modules/network
../modules/ssh
@@ -67,19 +73,23 @@ in rec {
'';
};
services.growfs = let name = "growfs"; in oneshot {
inherit name;
up = ''
device=$(grep /persist /proc/1/mountinfo | cut -f9 -d' ')
${pkgs.e2fsprogs}/bin/resize2fs $device
'';
};
services.growfs =
let
name = "growfs";
in
oneshot {
inherit name;
up = ''
device=$(grep /persist /proc/1/mountinfo | cut -f9 -d' ')
${pkgs.e2fsprogs}/bin/resize2fs $device
'';
};
filesystem = dir {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
mnt = dir {};
mnt = dir { };
};
rootfsType = "ext4";
@@ -92,20 +102,20 @@ in rec {
# create this hashed password string
passwd = "$6$y7WZ5hM6l5nriLmo$5AJlmzQZ6WA.7uBC7S8L4o19ESR28Dg25v64/vDvvCN01Ms9QoHeGByj8lGlJ4/b.dbwR9Hq2KXurSnLigt1W1";
openssh.authorizedKeys.keys =
let fromBuild =
(builtins.readFile
((builtins.toPath (builtins.getEnv "HOME")) + "/.ssh/authorized_keys")
);
in lib.splitString "\n" fromBuild;
let
fromBuild = (
builtins.readFile ((builtins.toPath (builtins.getEnv "HOME")) + "/.ssh/authorized_keys")
);
in
lib.splitString "\n" fromBuild;
};
defaultProfile.packages = with pkgs; [
e2fsprogs # ext4
btrfs-progs
mtdutils # mtd, jffs2, ubifs
dtc # you never know when you might need device tree stuff
dtc # you never know when you might need device tree stuff
some-util-linux
libubootenv # fw_{set,print}env
pciutils
+32 -15
View File
@@ -4,7 +4,13 @@
# devices: mostly you will need to attend to the number of wlan and lan
# interfaces
{ config, pkgs, lib, modulesPath, ... } :
{
config,
pkgs,
lib,
modulesPath,
...
}:
let
secrets = {
domainName = "fake.liminix.org";
@@ -17,7 +23,8 @@ let
wmm_enabled = 1;
};
in rec {
in
rec {
boot = {
tftp = {
freeSpaceBytes = 3 * 1024 * 1024;
@@ -33,22 +40,26 @@ in rec {
profile.gateway = {
lan = {
interfaces = with config.hardware.networkInterfaces;
[
# EDIT: these are the interfaces exposed by the gl.inet gl-ar750:
# if your device has more or differently named lan interfaces,
# specify them here
wlan wlan5
lan
];
interfaces = with config.hardware.networkInterfaces; [
# EDIT: these are the interfaces exposed by the gl.inet gl-ar750:
# if your device has more or differently named lan interfaces,
# specify them here
wlan
wlan5
lan
];
inherit (secrets.lan) prefix;
address = {
family = "inet"; address ="${secrets.lan.prefix}.1"; prefixLength = 24;
family = "inet";
address = "${secrets.lan.prefix}.1";
prefixLength = 24;
};
dhcp = {
start = 10;
end = 240;
hosts = { } // lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
hosts =
{ }
// lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
localDomain = "lan";
};
};
@@ -95,8 +106,13 @@ in rec {
};
services.ntp = svc.ntp.build {
pools = { "pool.ntp.org" = ["iburst"]; };
makestep = { threshold = 1.0; limit = 3; };
pools = {
"pool.ntp.org" = [ "iburst" ];
};
makestep = {
threshold = 1.0;
limit = 3;
};
};
services.sshd = svc.ssh.build { };
@@ -113,7 +129,8 @@ in rec {
programs.busybox = {
applets = [
"fdisk" "sfdisk"
"fdisk"
"sfdisk"
];
options = {
FEATURE_FANCY_TAIL = "y";
+92 -61
View File
@@ -6,7 +6,8 @@
pkgs,
lib,
...
}: let
}:
let
secrets = import ./extneder-secrets.nix;
rsecrets = import ./rotuer-secrets.nix;
@@ -27,7 +28,10 @@
# to start l2tp unless the expected lns address is one of the
# addresses returned. I think this satisfies "do check the DNS"
lns = { hostname = "l2tp.aaisp.net.uk"; address = "194.4.172.12"; };
lns = {
hostname = "l2tp.aaisp.net.uk";
address = "194.4.172.12";
};
inherit (pkgs.liminix.services) oneshot longrun target;
inherit (pkgs.liminix) outputRef;
@@ -39,7 +43,8 @@
inherit (rsecrets) wpa_passphrase;
wmm_enabled = 1;
};
in rec {
in
rec {
boot = {
tftp = {
serverip = "10.0.0.1";
@@ -62,7 +67,9 @@ in rec {
services.wan-address-for-secrets = svc.network.address.build {
interface = config.hardware.networkInterfaces.wan;
family = "inet"; address ="10.0.0.10"; prefixLength = 24;
family = "inet";
address = "10.0.0.10";
prefixLength = 24;
};
services.secrets = svc.secrets.outboard.build {
@@ -83,22 +90,26 @@ in rec {
profile.gateway = {
lan = {
interfaces = with config.hardware.networkInterfaces;
[
# EDIT: these are the interfaces exposed by the gl.inet gl-ar750:
# if your device has more or differently named lan interfaces,
# specify them here
wlan wlan5
lan
];
interfaces = with config.hardware.networkInterfaces; [
# EDIT: these are the interfaces exposed by the gl.inet gl-ar750:
# if your device has more or differently named lan interfaces,
# specify them here
wlan
wlan5
lan
];
inherit (rsecrets.lan) prefix;
address = {
family = "inet"; address ="${rsecrets.lan.prefix}.1"; prefixLength = 24;
family = "inet";
address = "${rsecrets.lan.prefix}.1";
prefixLength = 24;
};
dhcp = {
start = 10;
end = 240;
hosts = { } // lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
hosts =
{ }
// lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
localDomain = "lan";
};
};
@@ -107,7 +118,8 @@ in rec {
secret = outputRef config.services.secrets;
username = secret "ppp/username";
password = secret "ppp/password";
in {
in
{
interface =
let
pppoe = svc.pppoe.build {
@@ -126,21 +138,29 @@ in rec {
route = svc.network.route.build {
via = "$(output ${services.bootstrap-dhcpc} router)";
target = lns.address;
dependencies = [services.bootstrap-dhcpc check-address];
dependencies = [
services.bootstrap-dhcpc
check-address
];
};
l2tpd= svc.l2tp.build {
l2tpd = svc.l2tp.build {
lns = lns.address;
inherit username password;
dependencies = [config.services.lns-address route check-address];
dependencies = [
config.services.lns-address
route
check-address
];
};
in
svc.health-check.build {
service = l2tpd;
threshold = 3;
interval = 2;
healthCheck = pkgs.writeAshScript "ping-check" {} "ping 1.1.1.1";
};
in svc.round-robin.build {
svc.health-check.build {
service = l2tpd;
threshold = 3;
interval = 2;
healthCheck = pkgs.writeAshScript "ping-check" { } "ping 1.1.1.1";
};
in
svc.round-robin.build {
name = "wan";
services = [
pppoe
@@ -151,27 +171,33 @@ in rec {
};
wireless.networks = {
"${rsecrets.ssid}" = {
interface = config.hardware.networkInterfaces.wlan;
hw_mode = "g";
channel = "6";
ieee80211n = 1;
} // wirelessConfig // {
wpa_passphrase = outputRef config.services.secrets "wpa_passphrase";
};
"${rsecrets.ssid}" =
{
interface = config.hardware.networkInterfaces.wlan;
hw_mode = "g";
channel = "6";
ieee80211n = 1;
}
// wirelessConfig
// {
wpa_passphrase = outputRef config.services.secrets "wpa_passphrase";
};
"${rsecrets.ssid}5" = rec {
interface = config.hardware.networkInterfaces.wlan5;
hw_mode = "a";
channel = 36;
ht_capab = "[HT40+]";
vht_oper_chwidth = 1;
vht_oper_centr_freq_seg0_idx = channel + 6;
ieee80211n = 1;
ieee80211ac = 1;
} // wirelessConfig // {
wpa_passphrase = outputRef config.services.secrets "wpa_passphrase";
};
"${rsecrets.ssid}5" =
rec {
interface = config.hardware.networkInterfaces.wlan5;
hw_mode = "a";
channel = 36;
ht_capab = "[HT40+]";
vht_oper_chwidth = 1;
vht_oper_centr_freq_seg0_idx = channel + 6;
ieee80211n = 1;
ieee80211ac = 1;
}
// wirelessConfig
// {
wpa_passphrase = outputRef config.services.secrets "wpa_passphrase";
};
};
};
@@ -184,23 +210,28 @@ in rec {
authorizedKeys = outputRef config.services.secrets "ssh/authorizedKeys";
};
services.lns-address = let
ns = "$(output_word ${services.bootstrap-dhcpc} dns 1)";
route-to-bootstrap-nameserver = svc.network.route.build {
via = "$(output ${services.bootstrap-dhcpc} router)";
target = ns;
dependencies = [services.bootstrap-dhcpc];
services.lns-address =
let
ns = "$(output_word ${services.bootstrap-dhcpc} dns 1)";
route-to-bootstrap-nameserver = svc.network.route.build {
via = "$(output ${services.bootstrap-dhcpc} router)";
target = ns;
dependencies = [ services.bootstrap-dhcpc ];
};
in
oneshot rec {
name = "resolve-l2tp-server";
dependencies = [
services.bootstrap-dhcpc
route-to-bootstrap-nameserver
];
up = ''
(in_outputs ${name}
DNSCACHEIP="${ns}" ${pkgs.s6-dns}/bin/s6-dnsip4 ${lns.hostname} \
> addresses
)
'';
};
in oneshot rec {
name = "resolve-l2tp-server";
dependencies = [ services.bootstrap-dhcpc route-to-bootstrap-nameserver ];
up = ''
(in_outputs ${name}
DNSCACHEIP="${ns}" ${pkgs.s6-dns}/bin/s6-dnsip4 ${lns.hostname} \
> addresses
)
'';
};
users.root = rsecrets.root;
+26 -15
View File
@@ -1,8 +1,14 @@
{ config, pkgs, lim, ... } :
{
config,
pkgs,
lim,
...
}:
let
svc = config.system.service;
in rec {
in
rec {
imports = [
../modules/network
../modules/ssh
@@ -29,12 +35,14 @@ in rec {
hostname = "omnia";
services.hostap =
let secrets = {
ssid = "not-the-internet";
channel = 4;
wpa_passphrase = "diamond dogs";
};
in svc.hostapd.build {
let
secrets = {
ssid = "not-the-internet";
channel = 4;
wpa_passphrase = "diamond dogs";
};
in
svc.hostapd.build {
interface = config.hardware.networkInterfaces.wlan;
params = {
country_code = "GB";
@@ -51,12 +59,14 @@ in rec {
};
services.hostap5 =
let secrets = {
ssid = "not-the-internet";
channel = 36;
wpa_passphrase = "diamond dogs";
};
in svc.hostapd.build {
let
secrets = {
ssid = "not-the-internet";
channel = 36;
wpa_passphrase = "diamond dogs";
};
in
svc.hostapd.build {
interface = config.hardware.networkInterfaces.wlan5;
params = {
country_code = "GB";
@@ -103,6 +113,7 @@ in rec {
};
defaultProfile.packages = with pkgs; [
figlet pciutils
figlet
pciutils
];
}
+31 -32
View File
@@ -4,36 +4,35 @@
{
imports = [
./base.nix
./bridge
./busybox.nix
./dhcp6c
./dnsmasq
./firewall
./hardware.nix
./hostapd
./hostname.nix
./kernel
./mdevd.nix
./mount
./network
./ntp
./outputs.nix
./outputs/ext4fs.nix
./outputs/initramfs.nix
./outputs/jffs2.nix
./outputs/kexecboot.nix
./outputs/mtdimage.nix
./outputs/tftpboot.nix
./outputs/ubifs.nix
./outputs/ubimage.nix
./outputs/vmroot.nix
./ppp
./ramdisk.nix
./ssh
./users.nix
./vlan
./watchdog
./wlan.nix
];
./base.nix
./bridge
./busybox.nix
./dhcp6c
./dnsmasq
./firewall
./hardware.nix
./hostapd
./hostname.nix
./kernel
./mdevd.nix
./mount
./network
./ntp
./outputs.nix
./outputs/ext4fs.nix
./outputs/initramfs.nix
./outputs/jffs2.nix
./outputs/mtdimage.nix
./outputs/tftpboot.nix
./outputs/ubifs.nix
./outputs/ubimage.nix
./outputs/vmroot.nix
./ppp
./ramdisk.nix
./ssh
./users.nix
./vlan
./watchdog
./wlan.nix
];
}
+9 -4
View File
@@ -1,12 +1,17 @@
{ lim, pkgs, config, ...}:
{
lim,
pkgs,
config,
...
}:
{
config = {
kernel.config = {
CPU_LITTLE_ENDIAN= "y";
CPU_BIG_ENDIAN= "n";
CPU_LITTLE_ENDIAN = "y";
CPU_BIG_ENDIAN = "n";
# CMDLINE_FROM_BOOTLOADER availability is conditional
# on CMDLINE being set to something non-empty
CMDLINE="\"empty=false\"";
CMDLINE = "\"empty=false\"";
CMDLINE_FROM_BOOTLOADER = "y";
OF = "y";
+7 -2
View File
@@ -1,10 +1,15 @@
{ lim, pkgs, config, ...}:
{
lim,
pkgs,
config,
...
}:
{
config = {
kernel.config = {
OF = "y";
};
kernel.makeTargets = ["arch/arm/boot/zImage"];
kernel.makeTargets = [ "arch/arm/boot/zImage" ];
hardware.ram.startAddress = lim.parseInt "0x40000000";
system.outputs.u-boot = pkgs.ubootQemuArm;
};
+1 -1
View File
@@ -1,4 +1,4 @@
{ config, lim, ...}:
{ config, lim, ... }:
{
config = {
kernel.config = {
+1 -1
View File
@@ -1,4 +1,4 @@
{ pkgs, config, ...}:
{ pkgs, config, ... }:
{
imports = [ ./mips.nix ];
config = {
+1 -1
View File
@@ -1,4 +1,4 @@
{ config, ...}:
{ config, ... }:
{
imports = [ ./mips.nix ];
config = {
+79 -40
View File
@@ -1,15 +1,20 @@
## Base options
## ============
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs.pseudofile) dir symlink;
type_service = pkgs.liminix.lib.types.service;
in {
in
{
options = {
defaultProfile = {
packages = mkOption {
@@ -109,8 +114,13 @@ in {
};
};
config = {
defaultProfile.packages = with pkgs;
[ s6 s6-init-bin execline s6-linux-init s6-rc ];
defaultProfile.packages = with pkgs; [
s6
s6-init-bin
execline
s6-linux-init
s6-rc
];
boot.commandLine = [
"panic=10 oops=panic init=/bin/init loglevel=8"
@@ -119,69 +129,98 @@ in {
"fw_devlink=off"
] ++ lib.optional (config.rootOptions != null) "rootflags=${config.rootOptions}";
system.callService = path : parameters :
system.callService =
path: parameters:
let
typeChecked = caller: type: value:
typeChecked =
caller: type: value:
let
inherit (lib) types mergeDefinitions;
defs = [{ file = caller; inherit value; }];
defs = [
{
file = caller;
inherit value;
}
];
type' = types.submodule { options = type; };
in (mergeDefinitions [] type' defs).mergedValue;
cp = lib.callPackageWith(pkgs // { svc = config.system.service; });
pkg = cp path {};
checkTypes = t : p : typeChecked (builtins.toString path) t p;
in {
in
(mergeDefinitions [ ] type' defs).mergedValue;
cp = lib.callPackageWith (pkgs // { svc = config.system.service; });
pkg = cp path { };
checkTypes = t: p: typeChecked (builtins.toString path) t p;
in
{
inherit parameters;
build = { dependencies ? [], ... } @ args :
build =
{
dependencies ? [ ],
...
}@args:
let
s = pkg (checkTypes parameters
(builtins.removeAttrs args ["dependencies"]));
in s.overrideAttrs (o: {
s = pkg (checkTypes parameters (builtins.removeAttrs args [ "dependencies" ]));
in
s.overrideAttrs (o: {
dependencies = dependencies ++ o.dependencies;
buildInputs = dependencies ++ o.buildInputs;
});
};
users.root = {
uid = 0; gid= 0; gecos = "Root of all evaluation";
uid = 0;
gid = 0;
gecos = "Root of all evaluation";
dir = "/home/root/";
passwd = lib.mkDefault "";
shell = "/bin/sh";
};
groups = {
root = {
gid = 0; usernames = ["root"];
gid = 0;
usernames = [ "root" ];
};
system = {
gid = 1; usernames = ["root"];
gid = 1;
usernames = [ "root" ];
};
};
filesystem = dir {
dev =
let node = type: major: minor: mode : { inherit type major minor mode; };
in dir {
null = node "c" "1" "3" "0666";
zero = node "c" "1" "5" "0666";
tty = node "c" "5" "0" "0666";
let
node = type: major: minor: mode: {
inherit
type
major
minor
mode
;
};
in
dir {
null = node "c" "1" "3" "0666";
zero = node "c" "1" "5" "0666";
tty = node "c" "5" "0" "0666";
console = node "c" "5" "1" "0600";
pts = dir {};
pts = dir { };
};
etc =
let
profile = symlink (
pkgs.writeScript ".profile" ''
PATH=${lib.makeBinPath config.defaultProfile.packages}:/bin
export PATH
''
);
in
dir {
inherit profile;
ashrc = profile;
};
etc = let
profile = symlink
(pkgs.writeScript ".profile" ''
PATH=${lib.makeBinPath config.defaultProfile.packages}:/bin
export PATH
'');
in dir {
inherit profile;
ashrc = profile;
};
proc = dir {};
run = dir {};
sys = dir {};
tmp = dir {};
proc = dir { };
run = dir { };
sys = dir { };
tmp = dir { };
};
};
}
+17 -11
View File
@@ -6,8 +6,12 @@
## with one or more WLANs so that several local devices appear to be
## on the same network.
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
@@ -40,13 +44,15 @@ in
};
};
};
config.kernel.config = {
BRIDGE = "y";
BRIDGE_IGMP_SNOOPING = "y";
} // lib.optionalAttrs (config.system.service ? vlan) {
# depends on bridge _and_ vlan. I would like there to be
# a better way to test for the existence of vlan config:
# maybe the module should set an `enabled` attribute?
BRIDGE_VLAN_FILTERING = "y";
};
config.kernel.config =
{
BRIDGE = "y";
BRIDGE_IGMP_SNOOPING = "y";
}
// lib.optionalAttrs (config.system.service ? vlan) {
# depends on bridge _and_ vlan. I would like there to be
# a better way to test for the existence of vlan config:
# maybe the module should set an `enabled` attribute?
BRIDGE_VLAN_FILTERING = "y";
};
}
+12 -7
View File
@@ -1,21 +1,25 @@
{
liminix
, ifwait
, svc
liminix,
ifwait,
svc,
}:
{ members, primary } :
{ members, primary }:
let
inherit (liminix.networking) interface;
inherit (liminix.services) bundle oneshot;
addif = member :
addif =
member:
# how do we get sight of services from here? maybe we need to
# implement ifwait as a regualr derivation instead of a
# servicedefinition
svc.ifwait.build {
state = "running";
interface = member;
dependencies = [ primary member ];
dependencies = [
primary
member
];
service = oneshot {
name = "${primary.name}.member.${member.name}";
up = ''
@@ -24,7 +28,8 @@ let
down = "ip link set dev $(output ${member} ifname) nomaster";
};
};
in bundle {
in
bundle {
name = "${primary.name}.members";
contents = map addif members;
}
+5 -4
View File
@@ -1,11 +1,12 @@
{
liminix
, lib
liminix,
lib,
}:
{ ifname } :
{ ifname }:
let
inherit (liminix.services) oneshot;
in oneshot rec {
in
oneshot rec {
name = "${ifname}.link";
up = ''
ip link add name ${ifname} type bridge
+166 -32
View File
@@ -6,19 +6,26 @@
## the commands (termed "applets") required by the user or
## by other included modules.
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types mapAttrsToList;
inherit (pkgs.pseudofile) dir symlink;
inherit (lib.strings) toUpper;
attrs = { options, applets } :
attrs =
{ options, applets }:
let
extraOptions = builtins.concatStringsSep "\n"
(mapAttrsToList (n: v: "CONFIG_${toUpper n} ${toString v}") options);
appletOptions = builtins.concatStringsSep "\n"
(map (n: "CONFIG_${toUpper n} y") applets);
in {
extraOptions = builtins.concatStringsSep "\n" (
mapAttrsToList (n: v: "CONFIG_${toUpper n} ${toString v}") options
);
appletOptions = builtins.concatStringsSep "\n" (map (n: "CONFIG_${toUpper n} y") applets);
in
{
enableMinimal = true;
extraConfig = ''
${extraOptions}
@@ -26,44 +33,171 @@ let
'';
};
cfg = config.programs.busybox;
busybox = pkgs.busybox.override (attrs { inherit (cfg) applets options; });
makeLinks = lib.attrsets.genAttrs
cfg.applets
(a: symlink "${busybox}/bin/busybox");
busybox = pkgs.busybox.override (attrs {
inherit (cfg) applets options;
});
makeLinks = lib.attrsets.genAttrs cfg.applets (a: symlink "${busybox}/bin/busybox");
minimalApplets = [
# this is probably less minimal than it could be
"arch" "ash" "base64" "basename" "bc" "brctl" "bunzip2" "bzcat" "bzip2"
"cal" "cat" "chattr" "chgrp" "chmod" "chown" "chpst" "chroot" "clear" "cmp"
"comm" "cp" "cpio" "cut" "date" "dhcprelay" "dd" "df" "dirname" "dmesg"
"du" "echo" "egrep" "env" "expand" "expr" "false" "fdisk" "fgrep" "find"
"free" "fuser" "grep" "gunzip" "gzip" "head" "hexdump" "hostname" "hwclock"
"ifconfig" "ip" "ipaddr" "iplink" "ipneigh" "iproute" "iprule" "kill"
"killall" "killall5" "less" "ln" "ls" "lsattr" "lsof" "md5sum" "mkdir"
"mknod" "mktemp" "mount" "mv" "nc" "netstat" "nohup" "od" "pgrep" "pidof"
"ping" "ping6" "pkill" "pmap" "printenv" "printf" "ps" "pwd" "readlink"
"realpath" "reset" "rm" "rmdir" "route" "sed" "seq" "setsid" "sha1sum"
"sha256sum" "sha512sum" "sleep" "sort" "stat" "strings" "stty" "su" "sum"
"swapoff" "swapon" "sync" "tail" "tee" "test" "time" "touch" "tr"
"traceroute" "traceroute6" "true" "truncate" "tty" "udhcpc" "umount"
"uname" "unexpand" "uniq" "unlink" "unlzma" "unxz" "unzip" "uptime" "watch"
"wc" "whoami" "xargs" "xxd" "xz" "xzcat" "yes" "zcat"
"arch"
"ash"
"base64"
"basename"
"bc"
"brctl"
"bunzip2"
"bzcat"
"bzip2"
"cal"
"cat"
"chattr"
"chgrp"
"chmod"
"chown"
"chpst"
"chroot"
"clear"
"cmp"
"comm"
"cp"
"cpio"
"cut"
"date"
"dhcprelay"
"dd"
"df"
"dirname"
"dmesg"
"du"
"echo"
"egrep"
"env"
"expand"
"expr"
"false"
"fdisk"
"fgrep"
"find"
"free"
"fuser"
"grep"
"gunzip"
"gzip"
"head"
"hexdump"
"hostname"
"hwclock"
"ifconfig"
"ip"
"ipaddr"
"iplink"
"ipneigh"
"iproute"
"iprule"
"kill"
"killall"
"killall5"
"less"
"ln"
"ls"
"lsattr"
"lsof"
"md5sum"
"mkdir"
"mknod"
"mktemp"
"mount"
"mv"
"nc"
"netstat"
"nohup"
"od"
"pgrep"
"pidof"
"ping"
"ping6"
"pkill"
"pmap"
"printenv"
"printf"
"ps"
"pwd"
"readlink"
"realpath"
"reset"
"rm"
"rmdir"
"route"
"sed"
"seq"
"setsid"
"sha1sum"
"sha256sum"
"sha512sum"
"sleep"
"sort"
"stat"
"strings"
"stty"
"su"
"sum"
"swapoff"
"swapon"
"sync"
"tail"
"tee"
"test"
"time"
"touch"
"tr"
"traceroute"
"traceroute6"
"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 = {
programs.busybox = {
applets = mkOption {
applets = mkOption {
type = types.listOf types.str;
description = "Applets required";
default = [];
example = ["sh" "getty" "login"];
default = [ ];
example = [
"sh"
"getty"
"login"
];
};
options = mkOption {
# mostly the values are y n or m, but sometimes
# other strings are also used
description = "Other busybox config flags that do not map directly to applet names (often prefixed FEATURE_)";
type = types.attrsOf types.nonEmptyStr;
default = { };
example = { FEATURE_DD_IBS_OBS = "y"; };
default = { };
example = {
FEATURE_DD_IBS_OBS = "y";
};
};
};
};
+9 -5
View File
@@ -1,10 +1,14 @@
{
writeFennel
, linotify
, anoia
, lualinux
writeFennel,
linotify,
anoia,
lualinux,
}:
writeFennel "acquire-delegated-prefix" {
packages = [ linotify anoia lualinux ];
packages = [
linotify
anoia
lualinux
];
mainFunction = "run";
} ./acquire-delegated-prefix.fnl
+9 -5
View File
@@ -1,10 +1,14 @@
{
writeFennel
, linotify
, anoia
, lualinux
writeFennel,
linotify,
anoia,
lualinux,
}:
writeFennel "acquire-wan-address" {
packages = [ linotify anoia lualinux ];
packages = [
linotify
anoia
lualinux
];
mainFunction = "run";
} ./acquire-wan-address.fnl
+10 -6
View File
@@ -1,14 +1,18 @@
{
liminix
, callPackage
liminix,
callPackage,
}:
{ client, interface } :
{ client, interface }:
let
inherit (liminix.services) longrun;
name = "dhcp6c.addr.${client.name}.${interface.name}";
script = callPackage ./acquire-wan-address.nix { };
in longrun {
script = callPackage ./acquire-wan-address.nix { };
in
longrun {
inherit name;
run = "${script} $SERVICE_OUTPUTS/${client.name} $(output ${interface} ifname)";
dependencies = [ client interface ];
dependencies = [
client
interface
];
}
+6 -5
View File
@@ -1,13 +1,14 @@
{
liminix
, odhcp6c
, odhcp-script
liminix,
odhcp6c,
odhcp-script,
}:
{ interface } :
{ interface }:
let
inherit (liminix.services) longrun;
name = "dhcp6c.${interface.name}";
in longrun {
in
longrun {
inherit name;
notification-fd = 10;
run = ''
+6 -1
View File
@@ -9,7 +9,12 @@
## addresses of network interfaces that you want to assign those
## prefixes to
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
+10 -6
View File
@@ -1,14 +1,18 @@
{
liminix
, callPackage
liminix,
callPackage,
}:
{ client, interface } :
{ client, interface }:
let
inherit (liminix.services) longrun;
name = "dhcp6c.prefix.${client.name}.${interface.name}";
script = callPackage ./acquire-delegated-prefix.nix { };
in longrun {
script = callPackage ./acquire-delegated-prefix.nix { };
in
longrun {
inherit name;
run = "${script} $SERVICE_OUTPUTS/${client.name} $(output ${interface} ifname)";
dependencies = [ client interface ];
dependencies = [
client
interface
];
}
+51 -38
View File
@@ -4,12 +4,17 @@
## This module includes a service to provide DNS, DHCP, and IPv6
## router advertisement for the local network.
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
in {
in
{
options = {
system.service.dnsmasq = mkOption {
type = liminix.lib.types.serviceDefn;
@@ -20,12 +25,12 @@ in {
user = mkOption {
type = types.str;
default = "dnsmasq";
description = "Specifies the unix user which dnsmasq will run as" ;
description = "Specifies the unix user which dnsmasq will run as";
};
group = mkOption {
type = types.str;
default = "dnsmasq";
description = "Specifies the unix group which dnsmasq will run as" ;
description = "Specifies the unix group which dnsmasq will run as";
};
resolvconf = mkOption {
type = types.nullOr liminix.lib.types.service;
@@ -37,42 +42,47 @@ in {
};
upstreams = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
};
ranges = mkOption {
type = types.listOf types.str;
};
hosts = mkOption {
default = {};
type = types.attrsOf (types.submodule {
options = {
mac = mkOption {
description = ''
MAC or other hardware address to match on. For Ethernet