2
0

Compare commits

3 Commits

Author SHA1 Message Date
dan 4ae1edbce7 first boot on armv7 / Turris Omnia 2023-10-29 11:51:49 +00:00
dan 1a5efff3ae in uimage FIT, honour ${arch} 2023-10-29 11:50:23 +00:00
dan 8772e64b94 extract NETDEVICES kconfig to kernel.nix module 2023-10-29 11:49:03 +00:00
1803 changed files with 5491 additions and 25839 deletions
-1
View File
@@ -6,4 +6,3 @@ result-*
_build
*-secrets.nix
examples/static-leases.nix
/doc/hardware.rst
+57
View File
@@ -0,0 +1,57 @@
# Liminix community spaces Code of Conduct
As of Feb 2023, "RESPONSE TEAM" and "LEADERSHIP TEAM" in the text that follows
both refer to me, Daniel Barlow, as there are not yet any other project members.
Liminix is dedicated to providing a harassment-free experience for everyone. We do not tolerate harassment of participants in any form.
This code of conduct applies to all Liminix spaces, including the IRC channel, mailing lists, and Github forums, both online and off. Anyone who violates this code of conduct may be sanctioned or expelled from these spaces at the discretion of the RESPONSE TEAM.
Some Liminix spaces may have additional rules in place, which will be made clearly available to participants. Participants are responsible for knowing and abiding by these rules.
Harassment includes:
*Offensive comments related to gender, gender identity and expression, sexual orientation, disability, mental illness, neuro(a)typicality, physical appearance, body size, age, race, or religion.
*Unwelcome comments regarding a persons lifestyle choices and practices, including those related to food, health, parenting, drugs, and employment.
*Deliberate misgendering or use of dead or rejected names.
*Gratuitous or off-topic sexual images or behaviour in spaces where theyre not appropriate.
*Physical contact and simulated physical contact (eg, textual descriptions like “*hug*” or “*backrub*”) without consent or after a request to stop.
*Threats of violence.
*Incitement of violence towards any individual, including encouraging a person to commit suicide or to engage in self-harm.
*Deliberate intimidation.
*Stalking or following.
*Harassing photography or recording, including logging online activity for harassment purposes.
*Sustained disruption of discussion.
*Unwelcome sexual attention.
*Pattern of inappropriate social contact, such as requesting/assuming inappropriate levels of intimacy with others
*Continued one-on-one communication after requests to cease.
*Deliberate “outing” of any aspect of a persons identity without their consent except as necessary to protect vulnerable people from intentional abuse.
*Publication of non-harassing private communication.
Liminix prioritizes marginalized peoples safety over privileged peoples comfort. RESPONSE TEAM reserves the right not to act on complaints regarding:
*Reverse -isms, including reverse racism, reverse sexism, and cisphobia
*Reasonable communication of boundaries, such as “leave me alone,” “go away,” or “Im not discussing this with you.”
*Communicating in a tone you dont find congenial
*Criticizing racist, sexist, cissexist, or otherwise oppressive behavior or assumptions
## Reporting
If you are being harassed by a member of Liminix, notice that someone else is being harassed, or have any other concerns, please contact the RESPONSE TEAM at [email address or other contact point]. If the person who is harassing you is on the team, they will recuse themselves from handling your incident. We will respond as promptly as we can.
This code of conduct applies to Liminix spaces, but if you are being harassed by a member of Liminix outside our spaces, we still want to know about it. We will take all good-faith reports of harassment by Liminix members, especially LEADERSHIP TEAM, seriously. This includes harassment outside our spaces and harassment that took place at any point in time. The abuse team reserves the right to exclude people from Liminix based on their past behavior, including behavior outside Liminix spaces and behavior towards people who are not in Liminix.
In order to protect volunteers from abuse and burnout, we reserve the right to reject any report we believe to have been made in bad faith. Reports intended to silence legitimate criticism may be deleted without response.
We will respect confidentiality requests for the purpose of protecting victims of abuse. At our discretion, we may publicly name a person about whom weve received harassment complaints, or privately warn third parties about them, if we believe that doing so will increase the safety of Liminix members or the general public. We will not name harassment victims without their affirmative consent.
### Consequences
Participants asked to stop any harassing behavior are expected to comply immediately.
If a participant engages in harassing behavior, RESPONSE TEAM may take any action they deem appropriate, up to and including expulsion from all Liminix spaces and identification of the participant as a harasser to other Liminix members or the general public.
## License and attribution
The policy is based on the Geek Feminism
[Community anti-harassment/Policy](https://geekfeminism.fandom.com/wiki/Community_anti-harassment/Policy)
and is the work of Annalee Flower Horne with assistance from Valerie
Aurora, Alex Skud Bayley, Tim Chevalier, and Mary Gardiner.
-171
View File
@@ -1,171 +0,0 @@
A brief guide to backward-incompatible changes
that are likely to break configurations or workflows
2023-07-13
* a significant re-arrangement of modules and services, which will
probably break any configuration written before this time. For a
detailed explanation, see
https://www.liminix.org/doc/configuration.html#modules
2023-12-10
* configurations (usually) need no longer import modules from
modules/outputs because devices are expected to do this instead. This
change is because the outputs that make sense in any given context are
usually a property of the device being installed onto.
2023-12-11
* rename outputs.flashimage to outputs.mtdimage (and also diskimage to
mbrimage). This change is made in the expectation that "fooimage" is
the name of an outputs that gloms together other filesystem-like
outputs with some kind of partition table - so we might in future have
gptimage or lvmimage or ubimage.
2024-01-03
Liminix is now targeted to Nixpkgs 23.11 (not 23.05 as previously).
Upstream changes that have led to incompatible Liminix changes are:
* newer U-Boot version
* util-linux can now be built (previously depended on systemd)
2024-01-30
New port! Thanks to Arnout Engelen <arnout@bzzt.net>, Liminix
now runs on the TP-Link Archer AX23.
2024-02-12
* We now build wifi drivers (mac80211) from the same kernel source as
the running kernel, instead of using drivers from the linux-backports
project. This may be a regression on some devices that depend on
OpenWrt patches for wireless functionality: if you have a device that
used to work and now doesn't, refer to OpenWrt
package/kernel/mac80211/patches/ to see if there's something in there
that needs to be applied.
* in general, we build kernel modules (e.g. for nftables) at the same
time as the kernel itself instead of expecting to be able to build
them afterwards as though they were "out of tree". Refer to commit
b9c0d93670275e69df24902b05bf4aa4f0fcbe96 for a fuller explanation
of how this simplifies things.
2024-02-13
So that we can be more consistent about services that would like their
state to be preserved across boots (assuming a writable filesystem)
these changes have been made
* /run/service-state has been moved to /run/services/outputs
to better reflect what it's used for
* /run/services/state is either a symlink to /persist/services/state
(if there's a writeable fs on /persist) or a directory (if there
isn't)
The change will lose your ssh host key(s) unless you copy them from
the old location to the new one before rebooting into the new system
mkdir -m 02751 -p /run/services/state/dropbear
cp /persist/secrets/dropbear/* /run/services/state/dropbear
The `output`, `mkoutputs` functions defined by ${serviceFns}
have been updated for the new location.
2024-02-16
New (or at least, previously unreported) port! Liminix now runs on the
Turris Omnia and has been serving my family's internet needs for most
of this week. Thanks to NGI0 Entrust and the NLnet Foundation for
sponsoring this development (and funding the hardware)
2024-02-21
New port! Thanks to Raito Bezarius, Liminix now runs on the Zyxel NWA50AX,
an MT7621 (MIPS EL) dual radio WiFi AP.
2024-04-29
The setup for using `levitate` has changed: now it accepts an entire
config fragment, not just a list of services. Hopefully this makes it
a bit more useful :-)
defaultProfile.packages = with pkgs; [
...
(levitate.override {
config = {
services = {
inherit (config.services) dhcpc sshd watchdog;
};
defaultProfile.packages = [ mtdutils ];
users.root.openssh.authorizedKeys.keys = secrets.root.keys;
};
})
];
2024-07-16
* structured parameters are available for the pppoe service
* The "wan" configuration in modules/profiles/gateway.nix has changed:
instead of passing options that are used to create a pppoe interface,
callers should create a (pppoe or other) interface and pass that as
the value of profile.gateway.wan. For the pppoe case this is now only
very slightly more verbose, and it allows using the gateway profile
with other kinds of upstream.
2024-8-16
As part of implementing log shipping, the default directory for system
logs has beenchanged from /run/uncaught-logs to /run/log
2024-10-09
liminix-rebuild is being deprecated. From hereon in, the preferred way
to do an incremental update on an installed device with a writable
filesystem is to build the systemConfiguration output
nix-build -I liminix-config=hosts/myhost.nix --argstr deviceName turris-omnia -A outputs.systemConfiguration
and then run the generated `install.sh` script
result/install.sh root@192.168.8.1
2024-12-16
Config options changed: if you had set config.hardware.dts.includes
(maybe in an out-of-tree device port) to specify the search paths
in which dtc finds include files, you will need to change this to
hardware.dts.includePaths.
The "new" hardware.dts.includes option is now for dtsi files which
should be merged into the device tree.
2024-12-19
Incremental updates changed again (but not massively). From hereon in,
the preferred way to do an incremental update on an installed device
with a writable filesystem is to build the updater output
nix-build -I liminix-config=hosts/myhost.nix --argstr deviceName turris-omnia -A outputs.updater
and then run the generated `update.sh` script. See
https://www.liminix.org/doc/admin.html#updating-an-installed-system
2024-12-22
outputs.zimage is now outputs.kernel.zImage. This is unlikely to
affect many people at all but I mention it anyway.
2024-03-11
The fennel function (svc.open ...) now expects to be given the store
directory of a service derivation, not a direct path to the .outputs
directory. Thus
(svc.open "/nix/store/eeeeeeeeeeeeee-hellod")
not
(svc.open "/nix/store/eeeeeeeeeeeeee-hellod/.outputs")
This simplifies most extant uses of it
+15 -7
View File
@@ -18,14 +18,22 @@ outside word goes across it.
Liminix is pre-1.0. We are still finding new and better ways to do things,
and there is no attempt to maintain backward compatibility with the old
ways.
ways. This will change when it settles down.
The [NEWS](NEWS) file (available wherever you found this README) is
a high-level overview of breaking changes.
_In general:_ development mostly happens on the `main` branch, which is
therefore not guaranteed to build or to work on every commit. For the
latest functioning version, see [the CI system](https://build.liminix.org/jobset/liminix/build) and pick a revision with all jobs green.
Development mostly happens on the `main` branch, which is therefore
not guaranteed to build or to work on every commit. For the latest
functioning version, see [the CI system](https://build.liminix.org/jobset/liminix/build) and pick a revision with all jobs green.
_In particular:_ as of July 2023, a significant re-arrangement of
modules and services is ongoing:
* if you are using out-of-tree configurations created before commit
2e50368, especially if they reference things under pkgs.liminix,
they will need updating. Look at changes to examples/rotuer.nix
for guidance
* the same is intermittently true for examples/{extensino,arhcive}.nix
where I've updated rotuer and not updated them to match.
## Documentation
@@ -33,7 +41,7 @@ functioning version, see [the CI system](https://build.liminix.org/jobset/limini
Documentation is in the [doc](doc/) directory. You can build it
by running
nix-shell -p sphinx --run "make -C doc hardware.rst html"
nix-shell -p sphinx --run "make -C doc html"
Rendered documentation corresponding to the latest commit on `main`
is published to [https://www.liminix.org/doc/](https://www.liminix.org/doc/)
-4946
View File
File diff suppressed because it is too large Load Diff
-42
View File
@@ -1,42 +0,0 @@
# This is for use with minicom, but needs you to configure it to
# 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 "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"
puts stderr ";;; sending\r"
sendline $line
waitprompt
}
puts stderr "done\r\n"
close $f
+31 -111
View File
@@ -1,26 +1,9 @@
{
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;
default = [ ];
};
l2tp = {
host = mkOption {
description = mdDoc ''
@@ -68,17 +51,18 @@ in
<nixpkgs/nixos/modules/virtualisation/qemu-vm.nix>
];
config = {
boot.kernelParams = [ "loglevel=9" ];
boot.kernelParams = [
"loglevel=9"
];
systemd.services.pppoe =
let
conf = pkgs.writeText "kpppoed.toml" ''
interface_name = "eth1"
services = [ "myservice" ]
lns_ipaddr = "${cfg.l2tp.host}:${builtins.toString cfg.l2tp.port}"
ac_name = "kpppoed-1.0"
'';
in
{
let conf = pkgs.writeText "kpppoed.toml"
''
interface_name = "eth1"
services = [ "myservice" ]
lns_ipaddr = "${cfg.l2tp.host}:${builtins.toString cfg.l2tp.port}"
ac_name = "kpppoed-1.0"
'';
in {
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" ];
serviceConfig = {
@@ -92,114 +76,50 @@ in
};
};
services.openssh.enable = true;
services.dnsmasq = {
enable = true;
resolveLocalQueries = false;
settings = {
# domain-needed = true;
dhcp-range = [ "10.0.0.10,10.0.0.240" ];
interface = "eth1";
};
};
services.nginx = {
enable = true;
user = "liminix";
virtualHosts.${config.networking.hostName} = {
root = "/home/liminix";
default = true;
};
};
systemd.services.nginx.serviceConfig.ProtectHome = "read-only";
systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
virtualisation = {
forwardPorts = [
{
from = "host";
host.port = 7654;
# guest.address = "10.0.2.15";
guest.port = 7654;
}
{
host.port = 2222;
guest.address = "10.0.2.15";
guest.port = 22;
}
];
qemu = {
networkingOptions = [ ];
options =
[ ]
++ optional cfg.ethernet.pci.enable "-device vfio-pci,host=${cfg.ethernet.pci.id}"
++ optionals cfg.ethernet.usb.enable [
networkingOptions = [];
options = [] ++
optional cfg.ethernet.pci.enable
"-device vfio-pci,host=${cfg.ethernet.pci.id}" ++
optionals cfg.ethernet.usb.enable [
"-device usb-ehci,id=ehci"
"-device usb-host,bus=ehci.0,vendorid=${cfg.ethernet.usb.vendor},productid=${cfg.ethernet.usb.product}"
]
++ [
] ++ [
"-nographic"
"-serial mon:stdio"
];
};
sharedDirectories = {
liminix = {
securityModel = "none";
source = builtins.toString ./.;
target = "/home/liminix/liminix";
};
};
};
services.tang = {
enable = true;
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
];
environment.systemPackages = with pkgs; [
tcpdump
wireshark
socat
tufted
iptables
usbutils
];
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;
}
];
};
nat = {
enable = true;
internalInterfaces = [ "eth1" ];
externalInterface = "eth0";
ipv4.addresses = [ { address = "10.0.0.1"; prefixLength = 24;}];
};
};
users.users.liminix = {
isNormalUser = true;
uid = 1000;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = cfg.keys;
extraGroups = [ "wheel"];
};
services.getty.autologinUser = "liminix";
};
+2 -6
View File
@@ -1,12 +1,8 @@
{ ... }:
{...}:
{
bordervm = {
# ethernet.pci = { id = "01:00.0"; enable = true; };
ethernet.usb = {
vendor = "0x0bda";
product = "0x8153";
enable = true;
};
ethernet.usb = { vendor = "0x0bda"; product = "0x8153"; enable = true; };
l2tp = {
host = "l2tp.aa.net.uk";
};
+52 -38
View File
@@ -1,47 +1,61 @@
{
nixpkgs
, unstable
, liminix
, ... }:
let
pkgs = import <nixpkgs> { };
liminix = <liminix>;
borderVmConf = ./bordervm.conf-example.nix;
inherit (builtins) map;
pkgs = (import nixpkgs {});
borderVmConf = ./bordervm.conf-example.nix;
inherit (pkgs.lib.attrsets) genAttrs;
devices = [
"gl-ar750"
"gl-mt300a"
"gl-mt300n-v2"
"qemu"
"qemu-aarch64"
"qemu-armv7l"
"tp-archer-ax23"
"openwrt-one"
"zyxel-nwa50ax"
"turris-omnia"
"belkin-rt3200"
];
devices = {
virt = [ "qemu" "qemu-aarch64" ];
hw = [ "gl-ar750" "gl-mt300n-v2" "gl-mt300a" ];
};
vanilla = ./vanilla-configuration.nix;
for-device =
name:
for-device = cfg: name:
(import liminix {
inherit borderVmConf;
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/${name}");
liminix-config = vanilla;
liminix-config = cfg;
}).outputs.default;
tests = import ./tests/ci.nix;
jobs =
(genAttrs devices for-device)
// tests
// {
buildEnv =
(import liminix {
inherit borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = vanilla;
}).buildEnv;
doc = pkgs.callPackage ./doc.nix { inherit liminix borderVmConf; } ;
(genAttrs devices.hw (name: for-device ./vanilla-configuration-hw.nix name)) //
(genAttrs devices.virt (name: for-device vanilla name)) //
tests //
{
buildEnv = (import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = vanilla;
}).buildEnv;
doc = pkgs.stdenv.mkDerivation {
name = "liminix-doc";
nativeBuildInputs = with pkgs; [
gnumake sphinx
fennel luaPackages.lyaml
];
src = ./doc;
buildPhase = ''
cat ${(import ./doc/extract-options.nix).doc} > options.json
cat options.json | fennel --correlate parse-options.fnl > modules-generated.rst
cp ${(import ./doc/hardware.nix)} hardware.rst
make html
'';
installPhase = ''
mkdir -p $out/nix-support $out/share/doc/
cp modules.rst options.json $out
cp -a _build/html $out/share/doc/liminix
echo "file source-dist \"$out/share/doc/liminix\"" \
> $out/nix-support/hydra-build-products
'';
};
with-unstable = (import liminix {
nixpkgs = unstable;
inherit borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = vanilla;
}).outputs.default;
};
in
jobs
// {
all = pkgs.mkShell {
name = "all tests";
contents = pkgs.lib.collect pkgs.lib.isDerivation jobs;
};
}
in jobs
+25 -64
View File
@@ -1,85 +1,48 @@
{
deviceName ? null,
device ? (import ./devices/${deviceName}),
liminix-config ? <liminix-config>,
borderVmConf ? ./bordervm.conf.nix,
imageType ? "primary",
device
, liminix-config ? <liminix-config>
, nixpkgs ? <nixpkgs>
, borderVmConf ? ./bordervm.conf.nix
}:
let
overlay = import ./overlay.nix;
pkgs = import <nixpkgs> (
device.system
// {
overlays = [ overlay ];
config = {
allowUnsupportedSystem = true; # mipsel
permittedInsecurePackages = [
"python-2.7.18.6" # kernel backports needs python <3
"python-2.7.18.7"
];
};
}
);
eval = pkgs.lib.evalModules {
specialArgs = {
modulesPath = builtins.toString ./modules;
pkgs = import nixpkgs (device.system // {
overlays = [overlay];
config = {
allowUnsupportedSystem = true; # mipsel
permittedInsecurePackages = [
"python-2.7.18.6" # kernel backports needs python <3
];
};
});
config = (pkgs.lib.evalModules {
modules = [
{
_module.args = {
inherit pkgs;
inherit (pkgs) lim;
};
}
{ _module.args = { inherit pkgs; lib = pkgs.lib; }; }
./modules/hardware.nix
./modules/base.nix
./modules/busybox.nix
./modules/hostname.nix
./modules/kernel
./modules/logging.nix
./modules/klogd.nix
device.module
liminix-config
./modules/s6
./modules/users.nix
./modules/outputs.nix
{
boot.imageType = imageType;
}
];
};
config = eval.config;
}).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 = [ overlay ]; })
(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);
};
# this is just here as a convenience, so that we can get a
@@ -96,8 +59,6 @@ in
go-l2tp
min-copy-closure
fennelrepl
lzma
lua
];
};
}
+174 -301
View File
@@ -4,109 +4,18 @@
******************************
This device is based on a 64 bit Mediatek MT7622 ARM platform,
and is mostly feature-complete in Liminix but as of Dec 2024
has seen very little actual use.
and is "work in progress" in Liminix.
Hardware summary
================
The factory flash image contains ECC errors that make it incompatible
with Liminix: you need to use the `OpenWrt UBI Installer <https://github.com/dangowrt/owrt-ubi-installer>`_ to rewrite the partition layout before
you can flash Liminix onto it (or even use it with "tftpboot",
if you want the wireless to work).
- MediaTek MT7622BV (1350MHz)
- 128MB NAND flash
- 512MB RAM
- b/g/n wireless using MediaTek MT7622BV (MT7615E driver)
- a/n/ac/ax wireless using MediaTek MT7915E
Installation
============
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
-----------
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. 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
.. code-block:: console
MT7622> setenv ipaddr 10.0.0.6
MT7622> setenv serverip 10.0.0.1
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.
Building/installing Liminix
----------------
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 = {
@@ -115,218 +24,182 @@
};
};
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
];
config = {
kernel = {
extraPatchPhase = ''
${openwrt.applyPatches.mediatek}
module = {pkgs, config, lib, ... }:
let firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = ["installPhase"];
installPhase = ''
mkdir $out
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out
'';
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";
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";
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";
BLOCK = "y"; # move this to base option
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_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";
# 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";
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 "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;
};
};
};
in {
imports = [ ../../modules/arch/aarch64.nix ];
kernel = {
src = pkgs.pkgsBuildBuild.fetchurl {
name = "linux.tar.gz";
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.71.tar.gz";
hash = "sha256-yhO2cXIeIgUxkSZf/4aAsF11uxyh+UUZu6D1h92vCD8=";
};
extraPatchPhase = ''
${pkgs.openwrt.applyPatches.mediatek}
'';
config = {
PCI = "y";
ARCH_MEDIATEK = "y";
# ARM_MEDIATEK_CPUFREQ = "y";
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
};
# needed for "Cannot find regmap for /infracfg@10000000"
MFD_SYSCON = "y";
MTK_INFRACFG = "y";
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
];
};
MTK_PMIC_WRAP = "y";
MTK_EFUSE="y";
# MTK_HSDMA="y";
MTK_SCPSYS="y";
MTK_SCPSYS_PM_DOMAINS="y";
# MTK_THERMAL="y";
MTK_TIMER="y";
# - 0x000000000000-0x000008000000 : "spi-nand0"
# - 0x000000000000-0x000000080000 : "bl2"
# - 0x000000080000-0x0000001c0000 : "fip"
# - 0x0000001c0000-0x0000002c0000 : "factory"
# - 0x0000002c0000-0x000000300000 : "reserved"
# - 0x000000300000-0x000008000000 : "ubi"
COMMON_CLK_MT7622 = "y";
COMMON_CLK_MT7622_ETHSYS = "y";
COMMON_CLK_MT7622_HIFSYS = "y";
COMMON_CLK_MT7622_AUDSYS = "y";
PM_CLK="y";
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;
REGMAP_MMIO = "y";
CLKSRC_MMIO = "y";
REGMAP = "y";
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
};
};
MEDIATEK_GE_PHY = "y";
# MEDIATEK_MT6577_AUXADC = "y";
# MEDIATEK_WATCHDOG = "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
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";
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";
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";
};
};
boot = {
commandLine = [ "console=ttyS0,115200" ];
tftp.loadAddress = "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.mac80211.override {
drivers = [
"mt7615e"
"mt7915e"
];
klibBuild = config.system.outputs.kernel.modulesupport;
};
in {
ubi = {
minIOSize = "2048";
eraseBlockSize = "126976";
maxLEBcount = "1024"; # guessing
};
defaultOutput = "flashimage";
# 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 = "0x42000000";
entryPoint = "0x42000000";
rootDevice = "ubi0:liminix";
dts = {
src = "${openwrt.src}/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts";
includes = [
"${openwrt.src}/target/linux/mediatek/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm64/boot/dts/mediatek/"
];
};
flash.eraseBlockSize = "65536"; # this is probably wrong
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
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
@@ -1,8 +0,0 @@
/ {
reserved-memory {
/* make sure address matches upstream */
ramoops@42ff0000 {
pmsg-size = <0x10000>;
};
};
};
-60
View File
@@ -1,60 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
../../modules/outputs/jffs2.nix
];
config = {
kernel = {
config = {
MTD = "y";
MTD_BLOCK = "y";
MTD_CMDLINE_PARTS = "y";
MTD_PHRAM = "y";
VIRTIO_MENU = "y";
PCI = "y";
VIRTIO_PCI = "y";
BLOCK = "y";
VIRTIO_BLK = "y";
VIRTIO_NET = "y";
};
conditionalConfig = {
WLAN = {
MAC80211_HWSIM = "m";
};
};
};
hardware =
let
mac80211 = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel;
targets = [ "mac80211_hwsim" ];
};
in
{
defaultOutput = "vmroot";
rootDevice = "/dev/mtdblock0";
dts.src = pkgs.lib.mkDefault null;
flash.eraseBlockSize = 65536;
networkInterfaces =
let
inherit (config.system.service.network) link;
in
{
wan = link.build {
devpath = "/devices/pci0000:00/0000:00:12.0/virtio0";
ifname = "wan";
};
lan = link.build {
devpath = "/devices/pci0000:00/0000:00:13.0/virtio1";
ifname = "lan";
};
wlan_24 = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
};
};
};
}
+66 -106
View File
@@ -1,10 +1,18 @@
# I like GL.iNet devices because they're relatively accessible to
# DIY users: the serial port connections have headers preinstalled
# and don't need soldering
# Mainline linux 5.19 doesn't have device-tree support for this device
# or even for the SoC, so we use the extensive OpenWrt kernel patches
{
system = {
crossSystem = {
config = "mips-unknown-linux-musl";
gcc = {
abi = "32";
arch = "24kc"; # maybe mips_24kc-
arch = "24kc"; # maybe mips_24kc-
};
};
};
@@ -13,9 +21,6 @@
GL.iNet GL-AR750
****************
Hardware summary
================
The GL-AR750 "Creta" travel router features:
- QCA9531 @650Mhz SoC
@@ -25,44 +30,30 @@
- 16MB NOR Flash
- supported in OpenWrt by the "ath79" SoC family
As with many GL.iNet devices, the stock vendor firmware
is a fork of OpenWrt, meaning that the plain binary
``firmware.bin`` that Liminix builds can be flashed using the
vendor web UI and the U-Boot emergency "unbrick" routine
The GL-AR750 has two distinct sets of wifi hardware. The 2.4GHz
radio is part of the QCA9531 SoC, i.e. it's on the same silicon as
the CPU, the Ethernet, the USB etc. The device is connected to the
host via `AHB <https://en.wikipedia.org/wiki/Advanced_Microcontroller_Bus_Architecture>`_ and it is
supported in Linux using the ath9k driver. 5GHz wifi
is provided by a QCA9887 PCIe (PCI embedded) WLAN chip,
host via AHB, the "Advanced High-Performance Bus" and it is
supported in Linux using the ath9k driver. The 5GHz support, on the
other hand, is provided by a QCA9887 PCIe (PCI embedded) WLAN chip:
I haven't looked closely at the router innards to see if this is
actually physically a separate board that could be unplugged, but
as far as Linux is concerned it behaves as one. This is
supported by the ath10k driver.
Installation
============
As with many GL.iNet devices, the stock vendor firmware
is a fork of OpenWrt, meaning that the binary created by
:ref:`system-outputs-mtdimage` can be flashed using the
vendor web UI or the U-Boot emergency "unbrick" routine.
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/
OpenWrt web page: https://openwrt.org/toh/gl.inet/gl-ar750
'';
module =
{
pkgs,
config,
lim,
lib,
...
}:
module = {pkgs, config, ... }:
let
inherit (lib) mkIf;
openwrt = pkgs.openwrt;
firmwareBlobs = pkgs.pkgsBuildBuild.fetchFromGitHub {
owner = "kvalo";
@@ -72,7 +63,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
@@ -80,20 +71,15 @@
cp $blobdir/board.bin $out/ath10k/QCA9887/hw1.0/
'';
};
mac80211 = pkgs.kmodloader.override {
targets = [
"ath9k"
"ath10k_pci"
];
inherit (config.system.outputs) kernel;
dependencies = [ ath10k_cal_data ];
mac80211 = pkgs.mac80211.override {
drivers = ["ath9k" "ath10k_pci"];
klibBuild = config.system.outputs.kernel.modulesupport;
};
ath10k_cal_data =
let
offset = lim.parseInt "0x5000";
size = lim.parseInt "0x844";
in
pkgs.liminix.services.oneshot rec {
offset = 1024 * 20; # 0x5000
size = 2048 + 68; # 0x844
in pkgs.liminix.services.oneshot rec {
name = "ath10k_cal_data";
up = ''
part=$(basename $(dirname $(grep -l art /sys/class/mtd/*/name)))
@@ -102,65 +88,48 @@
(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
{
inherit (pkgs.liminix.networking) interface;
in {
imports = [
../../modules/network
../../modules/arch/mipseb.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/mtdimage.nix
../../modules/outputs/jffs2.nix
];
programs.busybox.options = {
FEATURE_DD_IBS_OBS = "y"; # ath10k_cal_data needs skip_bytes,fullblock
};
hardware = {
defaultOutput = "mtdimage";
loadAddress = lim.parseInt "0x80060000";
entryPoint = lim.parseInt "0x80060000";
defaultOutput = "flashimage";
loadAddress = "0x80060000";
entryPoint = "0x80060000";
flash = {
address = lim.parseInt "0x9F060000";
size = lim.parseInt "0xfa0000";
eraseBlockSize = 65536;
address = "0x9F060000";
size ="0xfa0000";
eraseBlockSize = "65536";
};
rootDevice = "/dev/mtdblock5";
dts = {
src = "${openwrt.src}/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts";
includePaths = [
includes = [
"${openwrt.src}/target/linux/ath79/dts"
];
includes = mkIf config.logging.persistent.enable [
./pstore-ramoops.dtsi
];
};
networkInterfaces =
let
inherit (config.system.service.network) link;
in
{
lan = link.build {
ifname = "lan";
devpath = "/devices/platform/ahb/1a000000.eth";
};
wan = link.build {
ifname = "wan";
devpath = "/devices/platform/ahb/19000000.eth";
};
let inherit (config.system.service.network) link;
in {
lan = link.build { ifname = "eth0"; };
wan = link.build { ifname = "eth1"; };
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [
ath10k_cal_data
mac80211
];
dependencies = [ mac80211 ath10k_cal_data ];
};
};
};
@@ -175,19 +144,17 @@
};
};
boot.tftp = {
loadAddress = lim.parseInt "0x00A00000";
appendDTB = true;
loadAddress = "0x00A00000";
};
kernel = {
# Mainline linux 5.19 doesn't have device-tree support for
# this device or even for the SoC, so we use the extensive
# OpenWrt kernel patches
src = pkgs.pkgsBuildBuild.fetchurl {
name = "linux.tar.gz";
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.71.tar.gz";
hash = "sha256-yhO2cXIeIgUxkSZf/4aAsF11uxyh+UUZu6D1h92vCD8=";
};
extraPatchPhase = ''
${openwrt.applyPatches.ath79}
sed -i.bak -e '\,include <linux/hw_random.h>,a #include <linux/gpio/driver.h>' drivers/net/wireless/ath/ath9k/ath9k.h # context reqd for next patch
patch -p1 < ${openwrt.src}/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch
'';
config = {
ATH79 = "y";
PCI = "y";
@@ -210,47 +177,40 @@
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
# this is all copied from nixwrt ath79 config. Clearly not all
# of it is device config, some of it is wifi config or
# installation method config or ...
EARLY_PRINTK = "y";
PRINTK_TIME = "y";
};
conditionalConfig = {
WLAN = {
WLAN_VENDOR_ATH = "y";
ATH_COMMON = "m";
ATH9K = "m";
ATH9K_AHB = "y";
ATH10K = "m";
ATH10K_PCI = "m";
ATH10K_DEBUG = "y";
};
};
};
};
}
-9
View File
@@ -1,9 +0,0 @@
/ {
reserved-memory {
ramoops@03f00000 {
compatible = "ramoops";
reg = <0x03f00000 0x10000>;
pmsg-size = <0x10000>;
};
};
};
+93 -87
View File
@@ -6,18 +6,41 @@
config = "mipsel-unknown-linux-musl";
gcc = {
abi = "32";
arch = "mips32"; # maybe mips_24kc-
arch = "mips32"; # maybe mips_24kc-
};
};
};
description = ''
GL.iNet GL-MT300A
*****************
********************
The GL-MT300A is based on a MT7620 chipset.
For flashing from U-Boot, the firmware partition is from
The GL.iNet pocket router range makes nice cheap hardware for
playing with Liminix or similar projects. The manufacturers seem
open to the DIY market, and the devices have a reasonable amount
of RAM and are much easier to get serial connections than many
COTS routers.
Wire up the serial connection: this probably involves opening
the box, locating the serial header pins (TX, RX and GND) and
connecting a USB TTL converter - e.g. a PL2303 based device - to
it. The defunct OpenWRT wiki has a guide with some pictures. (If
you don't have a USB TTL converter to hand, other options are
available. For example, use the GPIO pins on a Raspberry Pi.)
Run a terminal emulator such as Minicom on whatever is on the
other end of the link. I use 115200 8N1 and find it also helps
to set "Line tx delay" to 1ms, "backspace sends DEL" and
"lineWrap on".
When you turn the router on you should be greeted with some
messages from U-Boot and a little bit of ASCII art, followed by
the instruction to hit SPACE to stop autoboot. Do this and you
will get a gl-mt300a> prompt.
For flashing from uboot, the firmware partition is from
0xbc050000 to 0xbcfd0000.
WiFi on this device is provided by the rt2800soc module. It
@@ -25,18 +48,6 @@
- assuming we want to use the wireless - we need to build MTD
support into the kernel even if we're using TFTP root.
Installation
============
The stock vendor firmware is a fork of OpenWrt, meaning that the
binary created by :ref:`system-outputs-mtdimage` can be flashed
using the vendor web UI or the U-Boot emergency "unbrick" routine.
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/
@@ -44,32 +55,20 @@
'';
module =
{
pkgs,
config,
lib,
lim,
...
}:
module = { pkgs, config, lib, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs) openwrt;
mac80211 = pkgs.kmodloader.override {
targets = [ "rt2800soc" ];
inherit (config.system.outputs) kernel;
mac80211 = pkgs.mac80211.override {
drivers = ["rt2800soc"];
klibBuild = config.system.outputs.kernel.modulesupport;
};
in
{
imports = [
../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/mtdimage.nix
../../modules/outputs/jffs2.nix
];
in {
imports = [ ../../modules/arch/mipsel.nix ];
hardware = {
defaultOutput = "mtdimage";
loadAddress = lim.parseInt "0x80000000";
entryPoint = lim.parseInt "0x80000000";
defaultOutput = "flashimage";
loadAddress = "0x80000000";
entryPoint = "0x80000000";
# Creating 5 MTD partitions on "spi0.0":
# 0x000000000000-0x000000030000 : "u-boot"
@@ -82,15 +81,15 @@
# 0x000000260000-0x000000f80000 : "rootfs"
flash = {
address = lim.parseInt "0xbc050000";
size = lim.parseInt "0xf80000";
eraseBlockSize = 65536;
address = "0xbc050000";
size ="0xf80000";
eraseBlockSize = "65536";
};
rootDevice = "/dev/mtdblock5";
dts = {
src = "${openwrt.src}/target/linux/ramips/dts/mt7620a_glinet_gl-mt300a.dts";
includePaths = [
includes = [
"${openwrt.src}/target/linux/ramips/dts"
];
};
@@ -98,19 +97,33 @@
let
inherit (config.system.service.network) link;
inherit (config.system.service) vlan;
in
rec {
inherit (pkgs.liminix.services) oneshot;
swconfig = oneshot {
name = "swconfig";
up = ''
PATH=${pkgs.swconfig}/bin:$PATH
swconfig dev switch0 set reset
swconfig dev switch0 set enable_vlan 1
swconfig dev switch0 vlan 1 set ports '1 2 3 4 6t'
swconfig dev switch0 vlan 2 set ports '0 6t'
swconfig dev switch0 set apply
'';
down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset";
};
in rec {
eth = link.build { ifname = "eth0"; };
# lan and wan ports are both behind a switch on eth0
lan = vlan.build {
ifname = "eth0.1";
primary = eth;
vid = "1";
dependencies = [swconfig eth];
};
wan = vlan.build {
ifname = "eth0.2";
primary = eth;
vid = "2";
dependencies = [swconfig eth];
};
wlan = link.build {
ifname = "wlan0";
@@ -119,66 +132,59 @@
};
};
boot.tftp = {
loadAddress = lim.parseInt "0x00A00000";
appendDTB = true;
loadAddress = "0x00A00000";
};
kernel = {
src = pkgs.fetchurl {
name = "linux.tar.gz";
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.71.tar.gz";
hash = "sha256-yhO2cXIeIgUxkSZf/4aAsF11uxyh+UUZu6D1h92vCD8=";
};
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";
};
conditionalConfig = {
WLAN = {
WLAN_VENDOR_RALINK = "y";
RT2800SOC = "m";
RT2X00 = "m";
};
PRINTK_TIME = "y";
} // lib.optionalAttrs (config.system.service ? vlan) {
SWCONFIG = "y";
};
};
};
}
+67 -104
View File
@@ -4,7 +4,7 @@
config = "mipsel-unknown-linux-musl";
gcc = {
abi = "32";
arch = "mips32"; # maybe mips_24kc-
arch = "mips32"; # maybe mips_24kc-
};
};
};
@@ -13,23 +13,10 @@
GL.iNet GL-MT300N-v2
********************
The GL-MT300N-v2 "Mango" is is very similar to the :ref:`gl-mt300a`, but is
based on the MT7628 chipset instead of MT7620. It's also marginally cheaper
and comes in a yellow case not a blue one. Be sure your device is
v2 not v1, which is a different animal and has only half as much RAM.
Installation
============
The stock vendor firmware is a fork of OpenWrt, meaning that the
binary created by :ref:`system-outputs-mtdimage` can be flashed
using the vendor web UI or the U-Boot emergency "unbrick" routine.
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.
The GL-MT300N-v2 "Mango" is is very similar to the MT300A, but is
based on MT7628 instead of MT7620. It's also marginally cheaper
and comes in a yellow case not a blue one. It's different again
to the v1, which has only half the RAM.
Vendor web page: https://www.gl-inet.com/products/gl-mt300n-v2/
@@ -37,35 +24,23 @@
'';
module =
{
pkgs,
config,
lib,
lim,
...
}:
module = { pkgs, config, lib, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;
mac80211 = pkgs.kmodloader.override {
targets = [ "mt7603e" ];
inherit (config.system.outputs) kernel;
mac80211 = pkgs.mac80211.override {
drivers = ["mt7603e"];
klibBuild = config.system.outputs.kernel.modulesupport;
};
wlan_firmware = pkgs.fetchurl {
url = "https://github.com/openwrt/mt76/raw/f24b56f935392ca1d35fae5fd6e56ef9deda4aad/firmware/mt7628_e2.bin";
hash = "sha256:1dkhfznmdz6s50kwc841x3wj0h6zg6icg5g2bim9pvg66as2vmh9";
};
in
{
imports = [
../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/mtdimage.nix
../../modules/outputs/jffs2.nix
];
in {
imports = [ ../../modules/arch/mipsel.nix ];
filesystem = dir {
lib = dir {
firmware = dir {
@@ -74,20 +49,20 @@
};
};
hardware = {
defaultOutput = "mtdimage";
loadAddress = lim.parseInt "0x80000000";
entryPoint = lim.parseInt "0x80000000";
defaultOutput = "flashimage";
loadAddress = "0x80000000";
entryPoint = "0x80000000";
flash = {
address = lim.parseInt "0xbc050000";
size = lim.parseInt "0xfb0000";
eraseBlockSize = 65536;
address = "0xbc050000";
size = "0xfb0000";
eraseBlockSize = "65536";
};
rootDevice = "/dev/mtdblock5";
dts = {
src = "${openwrt.src}/target/linux/ramips/dts/mt7628an_glinet_gl-mt300n-v2.dts";
includePaths = [
includes = [
"${openwrt.src}/target/linux/ramips/dts"
];
};
@@ -105,14 +80,10 @@
swconfig dev switch0 vlan 2 set ports '0 6t'
swconfig dev switch0 set apply
'';
down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset";
};
in
rec {
eth = link.build {
ifname = "eth0";
dependencies = [ swconfig ];
down = "swconfig dev switch0 set reset";
};
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";
@@ -133,78 +104,70 @@
boot.tftp = {
# 20MB seems to give enough room to uncompress the kernel
# without anything getting trodden on. 10MB was too small
loadAddress = lim.parseInt "0x1400000";
appendDTB = true;
loadAddress = "0x1400000";
};
kernel = {
src = pkgs.fetchurl {
name = "linux.tar.gz";
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.71.tar.gz";
hash = "sha256-yhO2cXIeIgUxkSZf/4aAsF11uxyh+UUZu6D1h92vCD8=";
};
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
};
conditionalConfig = {
WLAN = {
WLAN_VENDOR_RALINK = "y";
WLAN_VENDOR_MEDIATEK = "y";
MT7603E = "m";
};
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
};
};
};
}
-751
View File
@@ -1,751 +0,0 @@
{
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 ];
};
};
};
};
};
}
+57 -40
View File
@@ -9,49 +9,66 @@
};
};
description = ''
QEMU Aarch64
************
This target produces an image for
the `QEMU "virt" platform <https://www.qemu.org/docs/master/system/arm/virt.html>`_ using a 64 bit CPU type.
ARM targets differ from MIPS in that the kernel format expected
by QEMU is an "Image" (raw binary file) rather than an ELF
file, but this is taken care of by :command:`run.sh`. Check the
documentation for the :ref:`qemu` target for more information.
'';
# this device is described by the "qemu" device
installer = "vmroot";
description = "";
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";
};
module = {pkgs, config, ... }: {
imports = [ ../../modules/arch/aarch64.nix ];
kernel = {
src = pkgs.pkgsBuildBuild.fetchurl {
name = "linux.tar.gz";
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.71.tar.gz";
hash = "sha256-yhO2cXIeIgUxkSZf/4aAsF11uxyh+UUZu6D1h92vCD8=";
};
config = {
VIRTUALIZATION = "y";
PCI_HOST_GENERIC="y";
MTD = "y";
MTD_BLOCK2MTD = "y";
MTD_BLOCK = "y";
VIRTIO_MENU = "y";
PCI = "y";
VIRTIO_PCI = "y";
BLOCK = "y";
VIRTIO_BLK = "y";
VIRTIO_NET = "y";
SERIAL_EARLYCON_ARM_SEMIHOST = "y"; # earlycon=smh
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
mac80211 = pkgs.mac80211.override {
drivers = ["mac80211_hwsim"];
klibBuild = config.system.outputs.kernel.modulesupport;
};
in {
defaultOutput = "vmroot";
loadAddress = "0x0";
entryPoint = "0x0";
rootDevice = "/dev/mtdblock0";
flash.eraseBlockSize = "65536"; # c.f. pkgs/mips-vm/mips-vm.sh
networkInterfaces =
let inherit (config.system.service.network) link;
in {
wan = link.build { ifname = "eth0"; };
lan = link.build { ifname = "eth1"; };
wlan_24 = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
};
};
};
}
-59
View File
@@ -1,59 +0,0 @@
# This "device" generates images that can be used with the QEMU
# emulator. The default output is a directory containing separate
# kernel ("Image" format) and root filesystem (squashfs or jffs2)
# images
{
system = {
crossSystem = {
config = "armv7l-unknown-linux-musleabihf";
};
};
# this device is described by the "qemu" device
description = ''
QEMU ARM v7
***********
This target produces an image for
the `QEMU "virt" platform <https://www.qemu.org/docs/master/system/arm/virt.html>`_ using a 32 bit CPU type.
ARM targets differ from MIPS in that the kernel format expected
by QEMU is an "Image" (raw binary file) rather than an ELF
file, but this is taken care of by :command:`run.sh`. Check the
documentation for the :ref:`QEMU` (MIPS) target for more information.
'';
installer = "vmroot";
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";
SERIAL_AMBA_PL011 = "y";
SERIAL_AMBA_PL011_CONSOLE = "y";
};
};
boot.commandLine = [
"console=ttyAMA0"
];
hardware =
let
addr = lim.parseInt "0x40008000";
in
{
loadAddress = addr;
entryPoint = addr;
};
};
}
+57 -49
View File
@@ -7,27 +7,30 @@
config = "mips-unknown-linux-musl";
gcc = {
abi = "32";
arch = "mips32"; # maybe mips_24kc-
arch = "mips32"; # maybe mips_24kc-
};
};
};
description = ''
QEMU MIPS
*********
QEMU
****
This target produces an image for
This is not a hardware device. This target produces an image for
QEMU, the "generic and open source machine emulator and
virtualizer".
Liminix can build QEMU for both MIPS (:code:`qemu` device) and Aarch64 (:code:`qemu-aarch64` device)
MIPS QEMU emulates a "Malta" board, which was an ATX form factor
evaluation board made by MIPS Technologies, but mostly in Liminix
we use paravirtualized devices (Virtio) instead of emulating
hardware.
hardware. For Aarch64 we use the QEMU "virt" board.
Building an image for QEMU results in a :file:`result/` directory
containing ``run.sh`` ``vmlinux``, and ``rootfs`` files. To invoke
the emulator, run ``run.sh``.
containing ``run.sh`` ``vmlinux``, ``rootfs`` and possibly
(architecture-dependent) ``Image``. To invoke the emulator,
run ``run.sh``.
The configuration includes two emulated "hardware" ethernet
devices and the kernel :code:`mac80211_hwsim` module to
@@ -36,50 +39,55 @@
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";
POWER_RESET = "y";
POWER_RESET_SYSCON = "y";
SERIAL_8250 = "y";
SERIAL_8250_CONSOLE = "y";
};
module = {pkgs, config, ... }: {
imports = [ ../../modules/arch/mipseb.nix ];
kernel = {
src = pkgs.pkgsBuildBuild.fetchurl {
name = "linux.tar.gz";
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.71.tar.gz";
hash = "sha256-yhO2cXIeIgUxkSZf/4aAsF11uxyh+UUZu6D1h92vCD8=";
};
hardware =
# from arch/mips/mti-malta/Platform:load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000
let
addr = lim.parseInt "0x80100000";
in
{
loadAddress = addr;
entryPoint = addr;
config = {
MIPS_MALTA= "y";
CPU_MIPS32_R2= "y";
# 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/"
];
};
MTD = "y";
MTD_BLOCK2MTD = "y";
MTD_BLOCK = "y";
};
VIRTIO_MENU = "y";
PCI = "y";
VIRTIO_PCI = "y";
BLOCK = "y";
VIRTIO_BLK = "y";
VIRTIO_NET = "y";
SERIAL_8250= "y";
SERIAL_8250_CONSOLE= "y";
};
};
hardware =
let
mac80211 = pkgs.mac80211.override {
drivers = ["mac80211_hwsim"];
klibBuild = config.system.outputs.kernel.modulesupport;
};
in {
defaultOutput = "vmroot";
rootDevice = "/dev/mtdblock0";
flash.eraseBlockSize = "65536"; # c.f. pkgs/run-liminix-vm/run-liminix-vm.sh
networkInterfaces =
let inherit (config.system.service.network) link;
in {
wan = link.build { ifname = "eth0"; };
lan = link.build { ifname = "eth1"; };
wlan_24 = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
};
};
};
}
-450
View File
@@ -1,450 +0,0 @@
{
description = ''
TP-Link Archer AX23 / AX1800 Dual Band Wi-Fi 6 Router
*****************************************************
Hardware summary
================
- MediaTek MT7621 (880MHz)
- 16MB Flash
- 128MB RAM
- WLan hardware: Mediatek MT7905, MT7975
Limitations
===========
Status LEDs do not work yet.
Uploading an image via tftp doesn't work yet, because the Archer uboot
version is so old it doesn't support overriding the DTB from the mboot
command. The tftpboot module doesn't support this yet, see
https://gti.telent.net/dan/liminix/pulls/5 for the WiP.
'';
system = {
crossSystem = {
config = "mipsel-unknown-linux-musl";
gcc = {
abi = "32";
# https://openwrt.org/docs/techref/instructionset/mipsel_24kc
arch = "24kc";
};
};
};
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
../../modules/outputs/tplink-safeloader.nix
];
config = {
kernel = {
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
};
conditionalConfig = {
WLAN = {
MT7915E = "m";
};
};
};
tplink-safeloader.board = "ARCHER-AX23-V1";
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 0x80001000, which suggests the
# RAM would start at 0x8000000 and (being 128MB) go to
# to 0x8800000. Let's put it at the 100MB mark at
# 0x8000000+0x0640000=0x86400000
loadAddress = lim.parseInt "0x86400000";
};
};
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 ];
};
};
};
};
};
}
+87 -399
View File
@@ -2,149 +2,6 @@
description = ''
Turris Omnia
************
This is a 32 bit ARMv7 MVEBU device, which is usually shipped with
TurrisOS, an OpenWrt-based system. Rather than reformatting the
builtin storage, we install Liminix on to the existing btrfs
filesystem so that the vendor snapshot/recovery system continues
to work (and provides you an easy rollback if you decide you don't
like Liminix after all).
The install process has two stages, and is intended that you
should not need to open the device and add a serial console
(although it may be handy for visibility, and in case anything
goes wrong). First we build a minimal installation/recovery
system, then we reboot into that recovery image to prepare the
device for the full target install.
Installation using a USB stick
==============================
First, build the image for the USB stick. Review
:file:`examples/recovery.nix` in order to change the default
root password (which is ``secret``) and/or the SSH keys, then
build it with
.. code-block:: console
$ nix-build -I liminix-config=./examples/recovery.nix \
--arg device "import ./devices/turris-omnia" \
-A outputs.mbrimage -o mbrimage
$ file -L mbrimage
mbrimage: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,0,5), end-CHS (0x6,130,26), startsector 4, 104602 sectors
Next, copy the image from your build machine to a USB storage
medium using :command:`dd` or your other most favoured file copying
tool, which might be a comand something like this:
.. code-block:: console
$ dd if=mbrimage of=/dev/path/to/the/usb/stick \
bs=1M conv=fdatasync status=progress
The Omnia's default boot order only checks USB after it has failed
to boot from eMMC, which is not ideal for our purpose. Unless you
have a serial cable, the easiest way to change this is by booting
to TurrisOS and logging in with ssh:
.. code-block:: console
root@turris:/# fw_printenv boot_targets
boot_targets=mmc0 nvme0 scsi0 usb0 pxe dhcp
root@turris:/# fw_setenv boot_targets usb0 mmc0
root@turris:/# fw_printenv boot_targets
boot_targets=usb0 mmc0
root@turris:/# reboot -f
It should now boot into the recovery image. It expects a network
cable to be plugged into LAN2 with something on the other end of
it that serves DHCP requests. Check your DHCP server logs for a
request from a ``liminix-recovery`` host and figure out what IP
address was assigned.
.. code-block:: console
$ ssh liminix-recovery.lan
You should get a "Busybox" banner and a root prompt. Now you can
start preparing the device to install Liminix on it. First we'll
mount the root filesystem and take a snapshot:
.. code-block:: console
# mkdir /dest && mount /dev/mmcblk0p1 /dest
# schnapps -d /dest create "pre liminix"
# schnapps -d /dest list
ERROR: not a valid btrfs filesystem: /
# | Type | Size | Date | Description
------+-----------+-------------+---------------------------+------------------------------------
1 | single | 16.00KiB | 1970-01-01 00:11:49 +0000 | pre liminix
(``not a valid btrfs filesystem: /`` is not a real error)
then we can remove all the files
.. code-block:: console
# rm -r /dest/@/*
and then it's ready to install the real Liminix system onto. On
your build system, create the Liminix configuration you wish to
install: here we'll use the ``rotuer`` example.
.. code-block:: console
build$ nix-build -I liminix-config=./examples/rotuer.nix \
--arg device "import ./devices/turris-omnia" \
-A outputs.systemConfiguration
and then use :command:`min-copy-closure` to copy it to the device.
.. code-block:: console
build$ nix-shell --run \
"min-copy-closure -r /dest/@ root@liminix-recovery.lan result"
and activate it
.. code-block:: console
build$ ssh root@liminix-recovery.lan \
"/dest/@/$(readlink result)/bin/install /dest/@"
The final steps are performed directly on the device again: add
a symlink so U-Boot can find :file:`/boot`, then restore the
default boot order and reboot into the new configuration.
.. code-block:: console
# cd /dest && ln -s @/boot .
# fw_setenv boot_targets "mmc0 nvme0 scsi0 usb0 pxe dhcp"
# cd / ; umount /dest
# reboot
Installation using a TFTP server and serial console
===================================================
If you have a :ref:`serial` console connection and a TFTP server,
and would rather use them than fiddling with USB sticks, the
:file:`examples/recovery.nix` configuration also works
using the ``tftpboot`` output. So you can do
.. code-block:: console
build$ nix-build -I liminix-config=./examples/recovery.nix \
--arg device "import ./devices/turris-omnia" \
-A outputs.tftpboot
and then paste the generated :file:`result/boot.scr` into
U-Boot, and you will end up with the same system as you would
have had after booting from USB. If you don't have a serial
console connection you could probably even get clever with
elaborate use of :command:`fw_setenv`, but that is left as
an exercise for the reader.
'';
system = {
@@ -153,271 +10,102 @@
};
};
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
mtd_by_name_links = pkgs.liminix.services.oneshot rec {
name = "mtd_by_name_links";
up = ''
mkdir -p /dev/mtd/by-name
cd /dev/mtd/by-name
for i in /sys/class/mtd/mtd*[0-9]; do
ln -s ../../$(basename $i) $(cat $i/name)
done
'';
module = {pkgs, config, lib, ... }:
let openwrt = pkgs.openwrt; in {
imports = [ ../../modules/arch/arm.nix ];
kernel = {
src = pkgs.pkgsBuildBuild.fetchurl {
name = "linux.tar.gz";
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.71.tar.gz";
hash = "sha256-yhO2cXIeIgUxkSZf/4aAsF11uxyh+UUZu6D1h92vCD8=";
};
in
{
imports = [
../../modules/arch/arm.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/mbrimage.nix
];
extraPatchPhase = ''
${pkgs.openwrt.applyPatches.mvebu}
'';
config = {
rootfsType = lib.mkDefault "btrfs"; # override this if you are building tftpboot
rootOptions = lib.mkDefault "subvol=@";
PCI = "y";
OF = "y";
MEMORY = "y"; # for MVEBU_DEVBUS
DMADEVICES = "y"; # for MV_XOR
CPU_V7 = "y";
ARCH_MULTIPLATFORM = "y";
ARCH_MVEBU = "y";
ARCH_MULTI_V7= "y";
PCI_MVEBU = "y";
AHCI_MVEBU = "y";
MACH_ARMADA_38X = "y";
SMP = "y";
NR_CPUS = "4";
VFP = "y";
NEON= "y";
services.mtd-name-links = mtd_by_name_links;
kernel = {
src = pkgs.pkgsBuildBuild.fetchurl {
name = "linux.tar.gz";
url = "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.7.4.tar.gz";
hash = "sha256-wIrmL0BS63nRwWfm4nw+dRNVPUzGh9M4X7LaHzAn5tU=";
};
version = "6.7.4";
config = {
PCI = "y";
OF = "y";
MEMORY = "y"; # for MVEBU_DEVBUS
DMADEVICES = "y"; # for MV_XOR
CPU_V7 = "y";
ARCH_MULTIPLATFORM = "y";
ARCH_MVEBU = "y";
ARCH_MULTI_V7 = "y";
PCI_MVEBU = "y";
AHCI_MVEBU = "y";
# WARNING: unmet direct dependencies detected for ARCH_WANT_LIBATA_LEDS
ATA = "y";
RTC_CLASS = "y";
RTC_DRV_ARMADA38X = "y"; # this may be useful anyway?
# switch is DSA
# CONFIG_NET_DSA_MV88E6060=y
# CONFIG_NET_DSA_MV88E6XXX=y
# CONFIG_NET_DSA_MV88E6XXX_GLOBAL2=y
EXPERT = "y";
ALLOW_DEV_COREDUMP = "n";
# CONFIG_REGMAP=y
# CONFIG_REGMAP_I2C=y
# CONFIG_REGMAP_SPI=y
# CONFIG_REGMAP_MMIO=y
# dts has a compatible for this but dmesg is not
# showing it
EEPROM_AT24 = "y"; # atmel,24c64
PSTORE = "y";
PSTORE_RAM = "y";
PSTORE_CONSOLE = "y";
PSTORE_DEFLATE_COMPRESS = "n";
I2C = "y";
I2C_MUX = "y";
I2C_MUX_PCA954x = "y";
SERIAL_8250 = "y";
SERIAL_8250_CONSOLE = "y";
SERIAL_OF_PLATFORM="y";
SERIAL_MVEBU_UART = "y";
SERIAL_MVEBU_CONSOLE = "y";
MACH_ARMADA_38X = "y";
SMP = "y";
# 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";
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";
# 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_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_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";
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";
MVNETA = "y";
MVNETA_BM = "y";
MVNETA_BM_ENABLE = "y";
SRAM = "y"; # mmio-sram is "compatible" for bm_bppi reqd by BM
PHY_MVEBU_A38X_COMPHY = "y"; # for eth2
MARVELL_PHY = "y";
MVPP2 = "y";
MV_XOR = "y";
# there is NOR flash on this device, which is used for U-Boot
# and the rescue system (which we don't interfere with) but
# also for the U-Boot environment variables (which we might
# need to meddle with)
MTD_SPI_NOR = "y";
SPI = "y";
SPI_MASTER = "y";
SPI_ORION = "y";
NET_DSA = "y";
NET_DSA_MV88E6XXX = "y"; # depends on PTP_1588_CLOCK_OPTIONAL
};
conditionalConfig = {
USB = {
USB_XHCI_MVEBU = "y";
USB_XHCI_HCD = "y";
};
WLAN = {
WLAN_VENDOR_ATH = "y";
ATH_COMMON = "m";
ATH9K = "m";
ATH9K_PCI = "y";
ATH10K = "m";
ATH10K_PCI = "m";
ATH10K_DEBUG = "y";
};
};
};
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
];
};
filesystem =
let
inherit (pkgs.pseudofile) dir symlink;
firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = [ "installPhase" ];
installPhase = ''
mkdir $out
cp -r ${pkgs.linux-firmware}/lib/firmware/ath10k/QCA988X $out
'';
};
in
dir {
lib = dir {
firmware = dir {
ath10k = symlink firmware;
};
};
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;
};
};
boot.tftp = {
loadAddress = lim.parseInt "0x1700000";
kernelFormat = "zimage";
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 ];
};
};
};
MVEBU_DEVBUS= "y"; # "Device Bus controller ... flash devices such as NOR, NAND, SRAM, and FPGA"
MVMDIO= "y";
MVNETA= "y";
MVNETA_BM= "y";
MVNETA_BM_ENABLE= "y";
MVPP2= "y";
MV_XOR= "y";
};
};
boot = {
commandLine = [ "console=ttyS0,115200" ];
imageFormat = "fit";
};
hardware = {
defaultOutput = "flashimage";
loadAddress = "0x00008000";
entryPoint = "0x00008000";
rootDevice = "/dev/mtdblock0";
dts = {
src = "${config.system.outputs.kernel.modulesupport}/arch/arm/boot/dts/armada-385-turris-omnia.dts";
includes = [
# "${openwrt.src}/target/linux/mediatek/dts"
"${config.system.outputs.kernel.modulesupport}/arch/arm/boot/dts/"
];
};
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
in rec {
lan = link.build { ifname = "eth0"; };
};
};
};
}
@@ -1,155 +0,0 @@
#include "mt7621.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
/ {
aliases {
label-mac-device = &gmac0;
};
};
&nand {
status = "okay";
mediatek,nmbm;
mediatek,bmt-max-ratio = <15>;
mediatek,bmt-max-reserved-blocks = <64>;
mediatek,bmt-remap-range =
<0x0 0x980000>,
<0x2980000 0x7800000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "u-boot";
reg = <0x0 0x80000>;
read-only;
};
partition@80000 {
label = "u-boot-env";
reg = <0x80000 0x80000>;
read-only;
};
factory: partition@100000 {
label = "factory";
reg = <0x100000 0x80000>;
read-only;
};
partition@180000 {
label = "firmware_a";
reg = <0x180000 0x2800000>;
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "kernel_a";
reg = <0x0 0x800000>;
};
partition@400000 {
label = "ubi";
reg = <0x800000 0x2000000>;
};
};
partition@2980000 {
label = "firmware_b";
reg = <0x2980000 0x2800000>;
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "kernel_b";
reg = <0x0 0x800000>;
};
partition@400000 {
label = "ubi_b";
reg = <0x800000 0x2000000>;
};
};
partition@5180000 {
label = "rootfs_data";
reg = <0x5180000 0x1400000>;
};
partition@6580000 {
label = "logs";
reg = <0x6580000 0xd00000>;
};
partition@7280000 {
label = "vendor-myzyxel";
reg = <0x7280000 0x480000>;
read-only;
};
partition@7700000 {
label = "bootconfig";
reg = <0x7700000 0x80000>;
};
mrd: partition@7780000 {
label = "mrd";
reg = <0x7780000 0x80000>;
read-only;
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
macaddr_mrd_1fff8: macaddr@1fff8 {
reg = <0x1fff8 0x6>;
};
};
};
};
};
&pcie {
status = "okay";
};
&pcie1 {
wlan_5g: wifi@0,0 {
reg = <0x0 0 0 0 0>;
compatible = "mediatek,mt76";
mediatek,mtd-eeprom = <&factory 0x0>;
/* MAC-Address set in userspace */
};
};
&gmac0 {
nvmem-cells = <&macaddr_mrd_1fff8>;
nvmem-cell-names = "mac-address";
};
&switch0 {
ports {
port@4 {
status = "okay";
label = "lan";
};
};
};
&state_default {
gpio {
groups = "uart3";
function = "gpio";
};
};
@@ -1,155 +0,0 @@
#include "mt7621.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
/ {
aliases {
label-mac-device = &gmac0;
};
};
&nand {
status = "okay";
mediatek,nmbm;
mediatek,bmt-max-ratio = <15>;
mediatek,bmt-max-reserved-blocks = <64>;
mediatek,bmt-remap-range =
<0x0 0x980000>,
<0x2980000 0x7800000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "u-boot";
reg = <0x0 0x80000>;
read-only;
};
partition@80000 {
label = "u-boot-env";
reg = <0x80000 0x80000>;
read-only;
};
factory: partition@100000 {
label = "factory";
reg = <0x100000 0x80000>;
read-only;
};
partition@2980000 {
label = "firmware_b";
reg = <0x2980000 0x2800000>;
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "kernel_b";
reg = <0x0 0x800000>;
};
partition@400000 {
label = "ubi";
reg = <0x800000 0x2000000>;
};
};
partition@180000 {
label = "firmware_a";
reg = <0x180000 0x2800000>;
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "kernel_a";
reg = <0x0 0x800000>;
};
partition@400000 {
label = "ubi_a";
reg = <0x800000 0x2000000>;
};
};
partition@5180000 {
label = "rootfs_data";
reg = <0x5180000 0x1400000>;
};
partition@6580000 {
label = "logs";
reg = <0x6580000 0xd00000>;
};
partition@7280000 {
label = "vendor-myzyxel";
reg = <0x7280000 0x480000>;
read-only;
};
partition@7700000 {
label = "bootconfig";
reg = <0x7700000 0x80000>;
};
mrd: partition@7780000 {
label = "mrd";
reg = <0x7780000 0x80000>;
read-only;
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
macaddr_mrd_1fff8: macaddr@1fff8 {
reg = <0x1fff8 0x6>;
};
};
};
};
};
&pcie {
status = "okay";
};
&pcie1 {
wlan_5g: wifi@0,0 {
reg = <0x0 0 0 0 0>;
compatible = "mediatek,mt76";
mediatek,mtd-eeprom = <&factory 0x0>;
/* MAC-Address set in userspace */
};
};
&gmac0 {
nvmem-cells = <&macaddr_mrd_1fff8>;
nvmem-cell-names = "mac-address";
};
&switch0 {
ports {
port@4 {
status = "okay";
label = "lan";
};
};
};
&state_default {
gpio {
groups = "uart3";
function = "gpio";
};
};
-371
View File
@@ -1,371 +0,0 @@
{
system = {
crossSystem = {
config = "mipsel-unknown-linux-musl";
gcc = {
abi = "32";
arch = "mips32"; # mips32r2?
};
};
};
description = ''
Zyxel NWA50AX
********************
Zyxel NWA50AX is quite close to the GL-MT300N-v2 "Mango" device, but it is based on the MT7621
chipset instead of the MT7628.
Installation
============
This device is pretty, but, due to its A/B capabilities, can be a bit hard
to use completely.
The stock vendor firmware is a downstream fork of U-Boot: <https://github.com/RaitoBezarius/uboot-nwa50ax>
with restricted boot commands. Fortunately, OpenWrt folks figured out trivial command injections,
so you can use most of the OpenWrt commands without trouble by just command injecting
atns, atna or atnf, e.g. atns "; $real_command".
From factory web UI, you can upload the result of the zyxel-nwa-fit output.
From another operating system, you need to `dumpimage -T flat_dt -p 0 $zyxel-nwa-fit -o firmware.bin`,
`flash_erase $(mtd partition of the target partition firmware or zy_firmware) 0 0`, then you complete by
`nandwrite -p $(mtd partition of the target partition firmware or zy_firmware) firmware.bin`.
How to put the firmware.bin on the machine is left to you as an exercise, e.g. SSH, TFTP, whatever.
From serial, you have two choices:
- Flash this system via U-Boot:
same reasoning as from an existing Linux system, two choices:
- ymodem the binary, perform the write manually, you can inspire yourself
from the `script` contained in the vendor firmware, those are just a FIT containing a script.
- prepare a FIT containing a script executing your commands, tftpboot this.
- boot from an existing Liminix system, e.g. TFTPBOOT image.
- boot from an OpenWrt system, i.e. follow OpenWrt steps.
Once you are in a Linux system, understand that this device has A/B boot.
OpenWrt provides you with `zyxel-bootconfig` to set/unset the image status and choice.
The kernel is booted with `bootImage=<number>` which tells you which slot are you on.
You should find yourself with 10ish MTD partitions, the most interesting ones are two:
- firmware: 40MB
- firmware_1: 40MB
In the current setup, they are split further into kernel (8MB) and ubi (32MB).
Once you are done with first installation, note that if you want to use the A/B feature,
you need to write a _secondary_ image on the slot B. There is no proper flashing code
that will set the being-updated slot to `new` and boot on it to verify if it's working.
This is a WIP.
Upgrading your system can be achieved via:
- `liminix-rebuild` for the userspace.
- `flash_erase` + `nandwrite` for the kernelspace to the other slot than the one you are booted on,
note that you can just nandwrite the mtd partition corresponding to the *kernel* and not the whole firmware.
If you soft-bricked your AP, i.e. you cannot boot anything in U-Boot, no worries, just plug the serial console,
prepare a TFTP server (via `tufted` for example), download vendor firmware, set up `atns`, `atnf`, etc. and run `atnz`.
This will reflash everything back to normal via TFTP.
If you hard-bricked your AP, i.e. U-Boot is telling you to transfer a valid bootloader via ymodem, just extract
a U-Boot from the vendor OS, send it via ymodem and use the previous operations to perform a full flash this time
of all partitions.
Note that if you erased your MRD partition, you lost your serial and MAC address. There's no way to recover the original one
except by reading the physical label on your device!
If you super-hard-bricked your AP, i.e. no output on serial console, congratulations, you reached one of the rare state
of this device. You need an external NAND flasher to repair it and write the first stage from Mediatek to continue the previous
recovery operations.
Development TODO list:
- Better support for upgrade automation w.r.t. to A/B, e.g. automagic scripts.
- Mount the logs partition, mount / as overlayfs of firmware ? rootfs and rootfs_data for extended data.
- Jitter-based entropy injection? Device can be slow to initialize its CRNG and hostapd will reject few clients at the start because of that.
- Defaults for hostapd based on MT7915 capabilities? See the example for one possible list.
- Remove primary/secondary hack and put it in preinit.
- Offer ways to reflash the *bootloader* itself to support direct boot via UBI and kernel upgrades via filesystem rewrite.
Vendor web page: https://www.zyxel.com/fr/fr/products/wireless/ax1800-wifi-6-dual-radio-nebulaflex-access-point-nwa50ax
OpenWrt web page: https://openwrt.org/inbox/toh/zyxel/nwa50ax
OpenWrt tech data: https://openwrt.org/toh/hwdata/zyxel/zyxel_nwa50ax
'';
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;
mac80211 = pkgs.mac80211.override {
drivers = [ "mt7915e" ];
klibBuild = config.system.outputs.kernel.modulesupport;
};
# v204520220929
wlan_firmware = pkgs.fetchurl {
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_wa.bin";
hash = "sha256-wooyefzb0i8640+lwq3vNhcBXRFCtGuo+jiL7afZaKA=";
};
wlan_firmware' = pkgs.fetchurl {
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_wm.bin";
hash = "sha256-k62nQewRuKjBLd5R3RxU4F74YKnQx5zr6gqMMImqVQw=";
};
wlan_firmware'' = pkgs.fetchurl {
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_rom_patch.bin";
hash = "sha256-ifriAjWzFACrxVWCANZpUaEZgB/0pdbhnTVQytx6ddg=";
};
in
{
imports = [
# We include it to ensure the bridge functionality
# is available on the target kernel.
../../modules/bridge
../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/zyxel-nwa-fit.nix
../../modules/zyxel-dual-image
];
filesystem = dir {
lib = dir {
firmware = dir {
mediatek = dir {
"mt7915_wa.bin" = symlink wlan_firmware;
"mt7915_wm.bin" = symlink wlan_firmware';
"mt7915_rom_patch.bin" = symlink wlan_firmware'';
};
};
};
};
rootfsType = "ubifs";
hardware = {
# Taken from OpenWRT
# root@OpenWrt:/# ubinfo /dev/ubi0
# ubi0
# Volumes count: 2
# Logical eraseblock size: 126976 bytes, 124.0 KiB
# Total amount of logical eraseblocks: 256 (32505856 bytes, 31.0 MiB)
# Amount of available logical eraseblocks: 0 (0 bytes)
# Maximum count of volumes 128
# Count of bad physical eraseblocks: 0
# Count of reserved physical eraseblocks: 19
# Current maximum erase counter value: 2
# Minimum input/output unit size: 2048 bytes
# Character device major/minor: 250:0
# Present volumes: 0, 1
ubi = {
minIOSize = "2048";
logicalEraseBlockSize = "126976";
physicalEraseBlockSize = "128KiB";
maxLEBcount = "256";
};
# This is a FIT containing a kernel padded and
# a UBI volume rootfs.
defaultOutput = "zyxel-nwa-fit";
loadAddress = lim.parseInt "0x80001000";
entryPoint = lim.parseInt "0x80001000";
# Aligned on 2kb.
alignment = 2048;
rootDevice = "ubi:rootfs";
dts = {
# Actually, this is not what we want.
# This DTS is insufficient.
src = ./mt7621_zyxel_nwa50ax.dtsi;
includePaths = [
# Here's one weird trick to make `ubi` detection
# out of the box.
# We will write ubi on /dev/firmware_a:rootfs location
# and same for /dev/firmware_b:rootfs.
# How do we distinguish both?
# We can just use the DTS to point ubi at A or B.
# This, unfortunately, means that we have "two images".
# But they are really just 1 image with 2 different DTS.
# TODO: improve this hack in preinit?
(if config.boot.imageType == "primary" then "${./a_image}" else "${./b_image}")
"${openwrt.src}/target/linux/ramips/dts"
];
};
networkInterfaces =
let
inherit (config.system.service.network) link;
in
{
eth = link.build { ifname = "eth0"; };
lan = link.build { ifname = "lan"; };
wlan0 = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan1 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
};
};
boot = {
# Critical because NWA50AX will extend your cmdline with the image number booted.
# and some bootloader version.
# You don't want to find yourself being overridden.
commandLineDtbNode = "bootargs-override";
imageFormat = "fit";
tftp = {
# 5MB is nice.
freeSpaceBytes = 5 * 1024 * 1024;
loadAddress = lim.parseInt "0x2000000";
};
};
# Dual image management service in userspace.
services.zyxel-dual-image = config.boot.zyxel-dual-image.build {
ensureActiveImage = "primary";
# TODO: use mtd names rather…
# primary and secondary are always /dev/mtd3 by virtue of the
# dtb being not too wrong…
# TODO: remove this hack.
primaryMtdPartition = "/dev/mtd3";
secondaryMtdPartition = "/dev/mtd3";
bootConfigurationMtdPartition = "/dev/mtd12";
};
# DEVICE_VENDOR := ZyXEL
# KERNEL_SIZE := 8192k
# DEVICE_PACKAGES := kmod-mt7915-firmware zyxel-bootconfig
# KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb
# IMAGES += factory.bin ramboot-factory.bin
# IMAGE/factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | zyxel-nwa-fit
# IMAGE/ramboot-factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi
kernel = {
extraPatchPhase = ''
${openwrt.applyPatches.ramips}
'';
config =
{
RALINK = "y";
PCI = "y";
PHY_MT7621_PCI = "y";
PCIE_MT7621 = "y";
SOC_MT7621 = "y";
CLK_MT7621 = "y";
CLOCKSOURCE_WATCHDOG = "y";
SERIAL_8250_CONSOLE = "y";
SERIAL_8250 = "y";
SERIAL_CORE_CONSOLE = "y";
SERIAL_OF_PLATFORM = "y";
SERIAL_8250_NR_UARTS = "3";
SERIAL_8250_RUNTIME_UARTS = "3";
SERIAL_MCTRL_GPIO = "y";
CONSOLE_LOGLEVEL_DEFAULT = "8";
CONSOLE_LOGLEVEL_QUIET = "4";
# MTD_UBI_BEB_LIMIT = "20";
# MTD_UBI_WL_THRESHOLD = "4096";
MTD = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev
MTD_RAW_NAND = "y";
MTD_NAND_MT7621 = "y";
MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table
MTD_NAND_ECC_SW_HAMMING = "y";
MTD_SPI_NAND = "y";
MTD_OF_PARTS = "y";
MTD_NAND_CORE = "y";
MTD_SPLIT_FIRMWARE = "y";
MTD_SPLIT_FIT_FW = "y";
PINCTRL = "y";
PINCTRL_MT7621 = "y";
I2C = "y";
I2C_MT7621 = "y";
SPI = "y";
MTD_SPI_NOR = "y";
SPI_MT7621 = "y";
SPI_MASTER = "y";
SPI_MEM = "y";
REGULATOR = "y";
REGULATOR_FIXED_VOLTAGE = "y";
RESET_CONTROLLER = "y";
POWER_RESET = "y";
POWER_RESET_GPIO = "y";
POWER_SUPPLY = "y";
LED_TRIGGER_PHY = "y";
PCI_DISABLE_COMMON_QUIRKS = "y";
PCI_DOMAINS = "y";
PCI_DOMAINS_GENERIC = "y";
PCI_DRIVERS_GENERIC = "y";
PCS_MTK_LYNXI = "y";
SOC_BUS = "y";
NET = "y";
ETHERNET = "y";
WLAN = "y";
PHYLIB = "y";
AT803X_PHY = "y";
FIXED_PHY = "y";
GENERIC_PHY = "y";
NET_DSA = "y";
NET_DSA_MT7530 = "y";
NET_DSA_MT7530_MDIO = "y";
NET_DSA_TAG_MTK = "y";
NET_MEDIATEK_SOC = "y";
NET_SWITCHDEV = "y";
NET_VENDOR_MEDIATEK = "y";
SWPHY = "y";
GPIOLIB = "y";
GPIO_MT7621 = "y";
OF_GPIO = "y";
EARLY_PRINTK = "y";
NEW_LEDS = "y";
LEDS_TRIGGERS = "y";
LEDS_CLASS = "y"; # required by rt2x00lib
LEDS_CLASS_MULTICOLOR = "y";
LEDS_BRIGHTNESS_HW_CHANGED = "y";
PRINTK_TIME = "y";
}
// lib.optionalAttrs (config.system.service ? vlan) {
SWCONFIG = "y";
}
// lib.optionalAttrs (config.system.service ? watchdog) {
RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};
};
};
}
@@ -1,56 +0,0 @@
#include "mt7621_zyxel_nwa-ax-for-ab.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
/ {
compatible = "zyxel,nwa50ax", "mediatek,mt7621-soc";
model = "ZyXEL NWA50AX";
aliases {
led-boot = &led_system_green;
led-failsafe = &led_system_red;
led-running = &led_system_green;
led-upgrade = &led_system_red;
};
leds {
compatible = "gpio-leds";
led_system_red: system_red {
label = "red:system";
gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
};
led_system_green: system_green {
label = "green:system";
gpios = <&gpio 7 GPIO_ACTIVE_HIGH>;
};
system_blue {
label = "blue:system";
gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
};
};
keys {
compatible = "gpio-keys";
reset {
label = "reset";
gpios = <&gpio 30 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
};
};
&ethernet {
pinctrl-0 = <&mdio_pins>, <&rgmii1_pins>;
};
&state_default {
gpio {
groups = "uart3", "rgmii2";
function = "gpio";
};
};
-55
View File
@@ -1,55 +0,0 @@
{ stdenv,
lib,
liminix,
gnumake,
fennel,
pandoc,
luaPackages,
asciidoctor,
borderVmConf
}:
let
json =
(import liminix {
inherit borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config =
{ ... }:
{
imports = [ ./modules/all-modules.nix ];
};
}).outputs.optionsJson;
in
stdenv.mkDerivation {
name = "liminix-doc";
nativeBuildInputs = [
gnumake
fennel
pandoc
asciidoctor
luaPackages.lyaml
];
src = lib.sources.sourceFilesBySuffices
(lib.cleanSource ./. ) [
".adoc"
".nix" ".rst" "Makefile" ".svg"
".fnl" ".py" ".css" ".html"
".md" ".html.in"
];
buildPhase = ''
cat ${json} | fennel --correlate doc/parse-options.fnl > doc/module-options-generated.inc.rst
cat ${json} | fennel --correlate doc/parse-options-outputs.fnl > doc/outputs-generated.inc.rst
cp ${(import ./doc/hardware.nix)} doc/hardware.rst
make -C doc html
'';
installPhase = ''
mkdir -p $out/nix-support
cd doc
make install prefix=$out
ln -s ${json} $out/options.json
echo "file source-dist \"$out/share/doc/liminix\"" \
> $out/nix-support/hydra-build-products
'';
}
+16 -19
View File
@@ -1,23 +1,20 @@
DOCS=\
admin \
configuration \
development \
index \
installation \
intro \
hardware \
module-options-generated.inc \
outputs-generated.inc \
tutorial
# Minimal makefile for Sphinx documentation
#
%.adoc: %.rst
pandoc -f rst -t asciidoc $< | sed -E -e 's/^(=*) /=\1 /g' > $@
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
hardware.adoc: hardware.nix
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
html: Makefile $(patsubst %,%.adoc,$(DOCS))
asciidoctor -D _build -d book index.adoc
.PHONY: help Makefile
install:
mkdir -p $(prefix)/share/doc/liminix
cp -a _build/* $(prefix)/share/doc/liminix
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-352
View File
@@ -1,352 +0,0 @@
== System Administration
=== Services on a running system
Liminix services are built on s6-rc, which is itself layered on s6.
Services are defined at build time in your configuration (see
<<_services>> for information) and can't be added
to/changed at runtime, but to monitor events or diagnose problems you
may need to inspect them on the running system. Here are some of the
most commonly used s6,-rc commands:
.Service management quick reference
[width="100%",cols="55%,45%",options="header",]
|===
|What |How
|List all running services |`+s6-rc -a list+`
|List all services that are *not* running |`+s6-rc -da list+`
|List services that `+wombat+` depends on
|`+s6-rc-db dependencies wombat+`
|... transitively |`+s6-rc-db all-dependencies wombat+`
|List services that depend on service `+wombat+`
|`+s6-rc-db -d dependencies wombat+`
|... transitively |`+s6-rc-db -d all-dependencies wombat+`
|Stop service `+wombat+` and everything depending on it
|`+s6-rc -d change wombat+`
|Start service `+wombat+` (but not any services depending on it)
|`+s6-rc -u change wombat+`
|Start service `+wombat+` and all* services depending on it
|`+s6-rc-up-tree wombat+`
|===
`+s6-rc-up-tree+` brings up a service and all services that depend on
it, except for any services that depend on a "controlled" service that
is not currently running. Controlled services are not started at boot
time but in response to external events (e.g. plugging in a particular
piece of hardware) so you probably don't want to be starting them by
hand if the conditions aren't there.
A service may be *up* or *down* (there are no intermediate states like
"started" or "stopping" or "dying" or "cogitating"). Some (but not all)
services have "readiness" notifications: the dependents of a service
with a readiness notification won't be started until the service signals
(by writing to a nominated file descriptor) that it's prepared to start
work. Most services defined by Liminix also have a `+timeout-up+`
parameter, which means that if a service has readiness notifications and
doesn't become ready in the allotted time (defaults 20 seconds) it will
be terminated and its state set to *down*.
If the process providing a service dies, it will be restarted
automatically. Liminix does not automatically set it to *down*.
(If the process providing a service dies without ever notifying
readiness, Liminix will restart it as many times as it has to until the
timeout period elapses, and then stop it and mark it down.)
==== Controlled services
*Controlled* services are those which are started/stopped on demand by a
*controller* (another service) instead of being started at boot time.
For example:
* `+svc.uevent-rule.build+` creates a controlled service which is active
when a particular hardware device (identified by uevent/sysfs directory)
is present.
* `+svc.round-robin.build+` creates a service controller that invokes
two or more services in turn, running the next one when the process
providing the previous one exits. We use this for failover from one
network connection to a backup connection, for example.
* `+svc.health-check.build+` creates a service controller that runs a
controlled service and periodically tests whether it is healthy by
running an external health check command or script. If the check command
repeatedly fails, the controlled service is restarted.
+
The Configuration section of the manual describes controlled services in
more detail. Some operational considerations
* `+round-robin+` detects a service status by looking at its `+outputs+`
directory, so it won't work unless the service creates some outputs.
This is considered a bug and will be fixed in a future release
* `+health-check+` works for longruns but not for oneshots, as it
internally relies on `+s6-svc+` to restart the process
==== Logs
Logs for all services are collated into `+/run/log/current+`. The log
file is rotated when it reaches a threshold size, into another file in
the same directory whose name contains a TAI64 timestamp.
Each log line is prefixed with a TAI64 timestamp and the name of the
service, if it is a longrun. If it is a oneshot, a timestamp and the
name of some other service. To convert the timestamp into a
human-readable format, use `+s6-tai64nlocal+`.
[source,console]
----
# ls -l /run/log/
-rw-r--r-- 1 0 lock