This commit is contained in:
Daniel Barlow 2023-11-10 21:17:20 +00:00
parent 22882dabee
commit 7cfb92e3ce
14 changed files with 102 additions and 58 deletions

1
ci.nix
View file

@ -42,6 +42,7 @@ let
installers = map (f: "system.outputs.${f}") [ installers = map (f: "system.outputs.${f}") [
"vmroot" "vmroot"
"flashimage" "flashimage"
"ubimage"
]; ];
inherit (pkgs.lib) concatStringsSep; inherit (pkgs.lib) concatStringsSep;
in pkgs.stdenv.mkDerivation { in pkgs.stdenv.mkDerivation {

View file

@ -1,4 +1,4 @@
{ rec {
description = '' description = ''
Belkin RT-3200 / Linksys E8450 Belkin RT-3200 / Linksys E8450
****************************** ******************************
@ -17,6 +17,7 @@
- b/g/n wireless using MediaTek MT7622BV (MT7615E driver) - b/g/n wireless using MediaTek MT7622BV (MT7615E driver)
- a/n/ac/ax wireless using MediaTek MT7915E - a/n/ac/ax wireless using MediaTek MT7915E
''; '';
installer = "ubimage";
system = { system = {
crossSystem = { crossSystem = {
@ -160,7 +161,7 @@
maxLEBcount = "1024"; # guessing maxLEBcount = "1024"; # guessing
}; };
defaultOutput = "ubimage"; defaultOutput = installer;
# the kernel expects this to be on a 2MB boundary. U-Boot # 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. # (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 # We put it at the 32MB mark so that tftpboot can put its rootfs

View file

@ -1,6 +1,6 @@
# GL.iNet GL-MT300A # GL.iNet GL-MT300A
{ rec {
system = { system = {
crossSystem = { crossSystem = {
config = "mipsel-unknown-linux-musl"; config = "mipsel-unknown-linux-musl";
@ -54,6 +54,7 @@
OpenWrt web page: https://openwrt.org/toh/gl.inet/gl-mt300a OpenWrt web page: https://openwrt.org/toh/gl.inet/gl-mt300a
''; '';
installer = "flashimage";
module = { pkgs, config, lib, ...}: module = { pkgs, config, lib, ...}:
let let
@ -66,7 +67,7 @@
in { in {
imports = [ ../../modules/arch/mipsel.nix ]; imports = [ ../../modules/arch/mipsel.nix ];
hardware = { hardware = {
defaultOutput = "flashimage"; defaultOutput = installer;
loadAddress = "0x80000000"; loadAddress = "0x80000000";
entryPoint = "0x80000000"; entryPoint = "0x80000000";

View file

@ -1,4 +1,4 @@
{ rec {
system = { system = {
crossSystem = { crossSystem = {
config = "mipsel-unknown-linux-musl"; config = "mipsel-unknown-linux-musl";
@ -23,6 +23,7 @@
OpenWrt web page: https://openwrt.org/toh/gl.inet/gl-mt300n_v2 OpenWrt web page: https://openwrt.org/toh/gl.inet/gl-mt300n_v2
''; '';
installer = "flashimage";
module = { pkgs, config, lib, ...}: module = { pkgs, config, lib, ...}:
let let
@ -49,7 +50,7 @@
}; };
}; };
hardware = { hardware = {
defaultOutput = "flashimage"; defaultOutput = installer;
loadAddress = "0x80000000"; loadAddress = "0x80000000";
entryPoint = "0x80000000"; entryPoint = "0x80000000";

View file

@ -2,16 +2,29 @@
# emulator. The default output is a directory containing separate # emulator. The default output is a directory containing separate
# kernel ("Image" format) and root filesystem (squashfs or jffs2) # kernel ("Image" format) and root filesystem (squashfs or jffs2)
# images # images
{ rec {
system = { system = {
crossSystem = { crossSystem = {
config = "aarch64-unknown-linux-musl"; config = "aarch64-unknown-linux-musl";
}; };
}; };
# this device is described by the "qemu" device description = ''
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` (MIPS) target for more information.
'';
# this device is described by the "qemu" device
installer = "vmroot";
module = {pkgs, config, ... }: { module = {pkgs, config, ... }: {
imports = [ ../../modules/arch/aarch64.nix ]; imports = [ ../../modules/arch/aarch64.nix ];
@ -51,7 +64,7 @@
klibBuild = config.system.outputs.kernel.modulesupport; klibBuild = config.system.outputs.kernel.modulesupport;
}; };
in { in {
defaultOutput = "vmroot"; defaultOutput = installer;
loadAddress = "0x0"; loadAddress = "0x0";
entryPoint = "0x0"; entryPoint = "0x0";
rootDevice = "/dev/mtdblock0"; rootDevice = "/dev/mtdblock0";

View file

@ -2,7 +2,7 @@
# emulator. The default output is a directory containing separate # emulator. The default output is a directory containing separate
# kernel ("Image" format) and root filesystem (squashfs or jffs2) # kernel ("Image" format) and root filesystem (squashfs or jffs2)
# images # images
{ rec {
system = { system = {
crossSystem = { crossSystem = {
config = "armv7l-unknown-linux-musleabihf"; config = "armv7l-unknown-linux-musleabihf";
@ -10,7 +10,19 @@
}; };
# this device is described by the "qemu" device # this device is described by the "qemu" device
description = ""; 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 = {pkgs, config, ... }: { module = {pkgs, config, ... }: {
imports = [ ../../modules/arch/arm.nix ]; imports = [ ../../modules/arch/arm.nix ];
@ -54,7 +66,7 @@
klibBuild = config.system.outputs.kernel.modulesupport; klibBuild = config.system.outputs.kernel.modulesupport;
}; };
in { in {
defaultOutput = "vmroot"; defaultOutput = installer;
loadAddress = "0x00010000"; loadAddress = "0x00010000";
entryPoint = "0x00010000"; entryPoint = "0x00010000";
rootDevice = "/dev/mtdblock0"; rootDevice = "/dev/mtdblock0";

View file

@ -1,7 +1,4 @@
# This "device" generates images that can be used with the QEMU rec {
# emulator. The default output is a directory containing separate
# kernel (uncompressed vmlinux) and initrd (squashfs) images
{
system = { system = {
crossSystem = { crossSystem = {
config = "mips-unknown-linux-musl"; config = "mips-unknown-linux-musl";
@ -13,24 +10,21 @@
}; };
description = '' description = ''
QEMU QEMU MIPS
**** *********
This is not a hardware device. This target produces an image for This target produces an image for
QEMU, the "generic and open source machine emulator and QEMU, the "generic and open source machine emulator and
virtualizer". 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 MIPS QEMU emulates a "Malta" board, which was an ATX form factor
evaluation board made by MIPS Technologies, but mostly in Liminix evaluation board made by MIPS Technologies, but mostly in Liminix
we use paravirtualized devices (Virtio) instead of emulating we use paravirtualized devices (Virtio) instead of emulating
hardware. For Aarch64 we use the QEMU "virt" board. hardware.
Building an image for QEMU results in a :file:`result/` directory Building an image for QEMU results in a :file:`result/` directory
containing ``run.sh`` ``vmlinux``, ``rootfs`` and possibly containing ``run.sh`` ``vmlinux``, and ``rootfs`` files. To invoke
(architecture-dependent) ``Image``. To invoke the emulator, the emulator, run ``run.sh``.
run ``run.sh``.
The configuration includes two emulated "hardware" ethernet The configuration includes two emulated "hardware" ethernet
devices and the kernel :code:`mac80211_hwsim` module to devices and the kernel :code:`mac80211_hwsim` module to
@ -39,6 +33,8 @@
in the Development manual. in the Development manual.
''; '';
installer = "vmroot";
module = {pkgs, config, ... }: { module = {pkgs, config, ... }: {
imports = [ ../../modules/arch/mipseb.nix ]; imports = [ ../../modules/arch/mipseb.nix ];
kernel = { kernel = {
@ -74,7 +70,7 @@
klibBuild = config.system.outputs.kernel.modulesupport; klibBuild = config.system.outputs.kernel.modulesupport;
}; };
in { in {
defaultOutput = "vmroot"; defaultOutput = installer;
rootDevice = "/dev/mtdblock0"; rootDevice = "/dev/mtdblock0";
flash.eraseBlockSize = "65536"; # c.f. pkgs/run-liminix-vm/run-liminix-vm.sh flash.eraseBlockSize = "65536"; # c.f. pkgs/run-liminix-vm/run-liminix-vm.sh
networkInterfaces = networkInterfaces =

View file

@ -56,6 +56,8 @@ Any VM started by a :command:`run.sh` script is connected to "lan" and
"access", and the emulated border network gateway (see below) runs "access", and the emulated border network gateway (see below) runs
PPPoE and is connected to "access" and "world". PPPoE and is connected to "access" and "world".
.. _border-network-gateway:
Border Network Gateway Border Network Gateway
---------------------- ----------------------

View file

@ -1,15 +1,15 @@
with import <nixpkgs> {} ; with import <nixpkgs> {} ;
let let
devices = devices = builtins.readDir ../devices;
builtins.readDir ../devices; inherit (builtins) stringLength;
texts = lib.mapAttrsToList (n: t: texts = lib.mapAttrsToList (n: t:
let d = import ../devices/${n}/default.nix; let d = import ../devices/${n}/default.nix;
d' = { d' = {
description = "no description for ${n}"; description = "${n}\n${substring 0 (stringLength n) "********************************"}\n";
} // d; } // d;
installer = installer =
if d ? installer if d ? description && d ? installer
then '' then ''
The default installation route for this device is The default installation route for this device is

View file

@ -11,7 +11,6 @@
./dnsmasq ./dnsmasq
./ext4fs.nix ./ext4fs.nix
./firewall ./firewall
./flashimage.nix
./hardware.nix ./hardware.nix
./hostapd ./hostapd
./hostname.nix ./hostname.nix
@ -24,6 +23,8 @@
./ntp ./ntp
./outputs.nix ./outputs.nix
./outputs/vmroot.nix ./outputs/vmroot.nix
./outputs/ubimage.nix
./outputs/flashimage.nix
./ppp ./ppp
./ramdisk.nix ./ramdisk.nix
./squashfs.nix ./squashfs.nix
@ -31,7 +32,6 @@
./standard.nix ./standard.nix
./tftpboot.nix ./tftpboot.nix
./ubifs.nix ./ubifs.nix
./ubimage.nix
./users.nix ./users.nix
./vlan ./vlan
./watchdog ./watchdog

View file

@ -12,6 +12,8 @@ in
imports = [ imports = [
./squashfs.nix ./squashfs.nix
./outputs/vmroot.nix ./outputs/vmroot.nix
./outputs/flashimage.nix
./outputs/ubimage.nix
]; ];
options = { options = {
system.outputs = { system.outputs = {

View file

@ -6,11 +6,19 @@
}: }:
let let
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep; inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep;
loadaddr = config.boot.tftp.loadAddress;
cfg = config.boot.tftp; cfg = config.boot.tftp;
instructions = pkgs.writeText "INSTALL.md" '' instructions = pkgs.writeText "env.scr" ''
setenv serverip ${cfg.serverip}
# First-time installation setenv ipaddr ${cfg.ipaddr}
setenv loadaddr ${cfg.loadAddress}
'';
in {
options.system.outputs = {
ubimage = mkOption {
type = types.package;
description = ''
ubimage
*******
First-time installation of a UBIFS Liminix system presently can only First-time installation of a UBIFS Liminix system presently can only
be done from the U-Boot command line (or from a ramdisk-based recovery be done from the U-Boot command line (or from a ramdisk-based recovery
@ -25,13 +33,17 @@ U-Boot
1) determine which MTD device is being used for UBI and the partition name: 1) determine which MTD device is being used for UBI and the partition name:
.. code-block:: console
uboot> ubi part uboot> ubi part
Device 0: ubi0, MTD partition ubi Device 0: ubi0, MTD partition ubi
In this case the important value is `ubi0` In this case the important value is ``ubi0``
2) list the available volumes and create a new one on which to install Liminix 2) list the available volumes and create a new one on which to install Liminix
.. code-block:: console
uboot> ubi info l uboot> ubi info l
[ copious output scrolls past ] [ copious output scrolls past ]
@ -40,32 +52,39 @@ important. Unless you know what you're doing, don't remove anything
whose name suggests it's related to uboot, or any kind of backup or whose name suggests it's related to uboot, or any kind of backup or
recovery partition. To see how much space is free: recovery partition. To see how much space is free:
.. code-block:: console
uboot> ubi info uboot> ubi info
[ ... ] [ ... ]
UBI: available PEBs: 823 UBI: available PEBs: 823
Now we can make our new root volume Now we can make our new root volume
.. code-block:: console
uboot> ubi create liminix - uboot> ubi create liminix -
3) transfer the root filesystem from the build system and write it 3) transfer the root filesystem from the build system and write it
to the new volume to the new volume. Paste the environment variable settings from
:file:`result/env.scr` into U-Boot, then run
uboot> setenv serverip ${cfg.serverip} .. code-block:: console
uboot> setenv ipaddr ${cfg.ipaddr}
uboot> tftpboot ${loadaddr} result/rootfs uboot> tftpboot ''${loadaddr} result/rootfs
uboot> ubi write ${loadaddr} liminix $filesize uboot> ubi write ''${loadaddr} liminix $filesize
Now we have the root filesystem installed on the device. You Now we have the root filesystem installed on the device. You
can even mount it and poke around using `ubifsmount ubi0:liminix; can even mount it and poke around using ``ubifsmount ubi0:liminix;
ubifsls /` ubifsls /``
4) optional: before you configure the device to boot into Liminix 4) optional: before you configure the device to boot into Liminix
automatically, you can try booting it by hand to see if it works: automatically, you can try booting it by hand to see if it works:
.. code-block:: console
uboot> ubifsmount ubi0:liminix uboot> ubifsmount ubi0:liminix
uboot> ubifsload ${loadaddr} boot/uimage uboot> ubifsload ''${loadaddr} boot/uimage
uboot> bootm ${loadaddr} uboot> bootm ''${loadaddr}
Once you've done this and you're happy with it, reset the device to Once you've done this and you're happy with it, reset the device to
U-Boot. You don't need to recreate the volume but you do need to U-Boot. You don't need to recreate the volume but you do need to
@ -76,7 +95,9 @@ device-dependent. On the Linksys E8450/Belkin RT3200, the environment
variable `boot_production` governs what happens on a normal boot, so variable `boot_production` governs what happens on a normal boot, so
you could do you could do
uboot> setenv boot_production 'led $bootled_pwr on ; ubifsmount ubi0:liminix; ubifsload ${loadaddr} boot/uimage; bootm ${loadaddr}' .. code-block:: console
uboot> setenv boot_production 'led $bootled_pwr on ; ubifsmount ubi0:liminix; ubifsload ''${loadaddr} boot/uimage; bootm ''${loadaddr}'
On other devices, some detective work may be needed. Try running On other devices, some detective work may be needed. Try running
`printenv` and look for likely commands, try looking at the existing `printenv` and look for likely commands, try looking at the existing
@ -84,15 +105,9 @@ boot process, maybe even try looking for documentation for that device.
6) Now you can reboot the device into Liminix 6) Now you can reboot the device into Liminix
uboot> reset .. code-block:: console
''; uboot> reset
in {
options.system.outputs = {
ubimage = mkOption {
type = types.package;
description = ''
UBIFS image and instructions to install it
''; '';
}; };
}; };
@ -105,7 +120,7 @@ in {
mkdir $out mkdir $out
cd $out cd $out
ln -s ${o.rootfs} rootfs ln -s ${o.rootfs} rootfs
ln -s ${instructions} INSTALL ln -s ${instructions} env.scr
''; '';
}; };
}; };

View file

@ -5,7 +5,7 @@
imports = [ imports = [
./tftpboot.nix ./tftpboot.nix
./kexecboot.nix ./kexecboot.nix
./flashimage.nix ./outputs/flashimage.nix
./jffs2.nix ./jffs2.nix
./ubifs.nix ./ubifs.nix
]; ];