liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 7cfb92e3ced96ca6d71768e616ca437fba421bcc
parent 22882dabee5e6ae75cf6b6b500e694a8185d9fd3
Author: Daniel Barlow <dan@telent.net>
Date:   Fri, 10 Nov 2023 21:17:20 +0000

more doc

Diffstat:
Mci.nix | 1+
Mdevices/belkin-rt3200/default.nix | 5+++--
Mdevices/gl-mt300a/default.nix | 5+++--
Mdevices/gl-mt300n-v2/default.nix | 5+++--
Mdevices/qemu-aarch64/default.nix | 21+++++++++++++++++----
Mdevices/qemu-armv7l/default.nix | 18+++++++++++++++---
Mdevices/qemu/default.nix | 24++++++++++--------------
Mdoc/development.rst | 2++
Mdoc/hardware.nix | 8++++----
Mmodules/all-modules.nix | 4++--
Mmodules/outputs.nix | 2++
Rmodules/flashimage.nix -> modules/outputs/flashimage.nix | 0
Amodules/outputs/ubimage.nix | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmodules/standard.nix | 2+-
Dmodules/ubimage.nix | 112-------------------------------------------------------------------------------
15 files changed, 190 insertions(+), 146 deletions(-)

diff --git a/ci.nix b/ci.nix @@ -42,6 +42,7 @@ let installers = map (f: "system.outputs.${f}") [ "vmroot" "flashimage" + "ubimage" ]; inherit (pkgs.lib) concatStringsSep; in pkgs.stdenv.mkDerivation { diff --git a/devices/belkin-rt3200/default.nix b/devices/belkin-rt3200/default.nix @@ -1,4 +1,4 @@ -{ +rec { description = '' Belkin RT-3200 / Linksys E8450 ****************************** @@ -17,6 +17,7 @@ - b/g/n wireless using MediaTek MT7622BV (MT7615E driver) - a/n/ac/ax wireless using MediaTek MT7915E ''; + installer = "ubimage"; system = { crossSystem = { @@ -160,7 +161,7 @@ maxLEBcount = "1024"; # guessing }; - defaultOutput = "ubimage"; + defaultOutput = installer; # 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 diff --git a/devices/gl-mt300a/default.nix b/devices/gl-mt300a/default.nix @@ -1,6 +1,6 @@ # GL.iNet GL-MT300A -{ +rec { system = { crossSystem = { config = "mipsel-unknown-linux-musl"; @@ -54,6 +54,7 @@ OpenWrt web page: https://openwrt.org/toh/gl.inet/gl-mt300a ''; + installer = "flashimage"; module = { pkgs, config, lib, ...}: let @@ -66,7 +67,7 @@ in { imports = [ ../../modules/arch/mipsel.nix ]; hardware = { - defaultOutput = "flashimage"; + defaultOutput = installer; loadAddress = "0x80000000"; entryPoint = "0x80000000"; diff --git a/devices/gl-mt300n-v2/default.nix b/devices/gl-mt300n-v2/default.nix @@ -1,4 +1,4 @@ -{ +rec { system = { crossSystem = { config = "mipsel-unknown-linux-musl"; @@ -23,6 +23,7 @@ OpenWrt web page: https://openwrt.org/toh/gl.inet/gl-mt300n_v2 ''; + installer = "flashimage"; module = { pkgs, config, lib, ...}: let @@ -49,7 +50,7 @@ }; }; hardware = { - defaultOutput = "flashimage"; + defaultOutput = installer; loadAddress = "0x80000000"; entryPoint = "0x80000000"; diff --git a/devices/qemu-aarch64/default.nix b/devices/qemu-aarch64/default.nix @@ -2,16 +2,29 @@ # emulator. The default output is a directory containing separate # kernel ("Image" format) and root filesystem (squashfs or jffs2) # images -{ +rec { system = { crossSystem = { 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, ... }: { imports = [ ../../modules/arch/aarch64.nix ]; @@ -51,7 +64,7 @@ klibBuild = config.system.outputs.kernel.modulesupport; }; in { - defaultOutput = "vmroot"; + defaultOutput = installer; loadAddress = "0x0"; entryPoint = "0x0"; rootDevice = "/dev/mtdblock0"; diff --git a/devices/qemu-armv7l/default.nix b/devices/qemu-armv7l/default.nix @@ -2,7 +2,7 @@ # emulator. The default output is a directory containing separate # kernel ("Image" format) and root filesystem (squashfs or jffs2) # images -{ +rec { system = { crossSystem = { config = "armv7l-unknown-linux-musleabihf"; @@ -10,7 +10,19 @@ }; # 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, ... }: { imports = [ ../../modules/arch/arm.nix ]; @@ -54,7 +66,7 @@ klibBuild = config.system.outputs.kernel.modulesupport; }; in { - defaultOutput = "vmroot"; + defaultOutput = installer; loadAddress = "0x00010000"; entryPoint = "0x00010000"; rootDevice = "/dev/mtdblock0"; diff --git a/devices/qemu/default.nix b/devices/qemu/default.nix @@ -1,7 +1,4 @@ -# This "device" generates images that can be used with the QEMU -# emulator. The default output is a directory containing separate -# kernel (uncompressed vmlinux) and initrd (squashfs) images -{ +rec { system = { crossSystem = { config = "mips-unknown-linux-musl"; @@ -13,24 +10,21 @@ }; 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 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. For Aarch64 we use the QEMU "virt" board. + hardware. Building an image for QEMU results in a :file:`result/` directory - containing ``run.sh`` ``vmlinux``, ``rootfs`` and possibly - (architecture-dependent) ``Image``. To invoke the emulator, - run ``run.sh``. + containing ``run.sh`` ``vmlinux``, and ``rootfs`` files. To invoke + the emulator, run ``run.sh``. The configuration includes two emulated "hardware" ethernet devices and the kernel :code:`mac80211_hwsim` module to @@ -39,6 +33,8 @@ in the Development manual. ''; + installer = "vmroot"; + module = {pkgs, config, ... }: { imports = [ ../../modules/arch/mipseb.nix ]; kernel = { @@ -74,7 +70,7 @@ klibBuild = config.system.outputs.kernel.modulesupport; }; in { - defaultOutput = "vmroot"; + defaultOutput = installer; rootDevice = "/dev/mtdblock0"; flash.eraseBlockSize = "65536"; # c.f. pkgs/run-liminix-vm/run-liminix-vm.sh networkInterfaces = diff --git a/doc/development.rst b/doc/development.rst @@ -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 PPPoE and is connected to "access" and "world". +.. _border-network-gateway: + Border Network Gateway ---------------------- diff --git a/doc/hardware.nix b/doc/hardware.nix @@ -1,15 +1,15 @@ with import <nixpkgs> {} ; let - devices = - builtins.readDir ../devices; + devices = builtins.readDir ../devices; + inherit (builtins) stringLength; texts = lib.mapAttrsToList (n: t: let d = import ../devices/${n}/default.nix; d' = { - description = "no description for ${n}"; + description = "${n}\n${substring 0 (stringLength n) "********************************"}\n"; } // d; installer = - if d ? installer + if d ? description && d ? installer then '' The default installation route for this device is diff --git a/modules/all-modules.nix b/modules/all-modules.nix @@ -11,7 +11,6 @@ ./dnsmasq ./ext4fs.nix ./firewall - ./flashimage.nix ./hardware.nix ./hostapd ./hostname.nix @@ -24,6 +23,8 @@ ./ntp ./outputs.nix ./outputs/vmroot.nix + ./outputs/ubimage.nix + ./outputs/flashimage.nix ./ppp ./ramdisk.nix ./squashfs.nix @@ -31,7 +32,6 @@ ./standard.nix ./tftpboot.nix ./ubifs.nix - ./ubimage.nix ./users.nix ./vlan ./watchdog diff --git a/modules/outputs.nix b/modules/outputs.nix @@ -12,6 +12,8 @@ in imports = [ ./squashfs.nix ./outputs/vmroot.nix + ./outputs/flashimage.nix + ./outputs/ubimage.nix ]; options = { system.outputs = { diff --git a/modules/flashimage.nix b/modules/outputs/flashimage.nix diff --git a/modules/outputs/ubimage.nix b/modules/outputs/ubimage.nix @@ -0,0 +1,127 @@ +{ + config +, pkgs +, lib +, ... +}: +let + inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep; + cfg = config.boot.tftp; + instructions = pkgs.writeText "env.scr" '' + setenv serverip ${cfg.serverip} + 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 +be done from the U-Boot command line (or from a ramdisk-based recovery +system: see "kexecboot" but we don't have detailed instructions for +this process yet). + +These steps were tested on a Belkin RT3200 (also known as Linksys +E8450). Other devices may be set up differently, so use them as +inspiration and don't just paste them blindly. Consult the Liminix +manual for how to connect a serial cable to your device and get into +U-Boot + +1) determine which MTD device is being used for UBI and the partition name: + +.. code-block:: console + + uboot> ubi part + Device 0: ubi0, MTD partition ubi + +In this case the important value is ``ubi0`` + +2) list the available volumes and create a new one on which to install Liminix + +.. code-block:: console + + uboot> ubi info l + [ copious output scrolls past ] + +Expect there to be existing volumes and for some or all of them to be +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 +recovery partition. To see how much space is free: + +.. code-block:: console + + uboot> ubi info + [ ... ] + UBI: available PEBs: 823 + +Now we can make our new root volume + +.. code-block:: console + + uboot> ubi create liminix - + +3) transfer the root filesystem from the build system and write it +to the new volume. Paste the environment variable settings from +:file:`result/env.scr` into U-Boot, then run + +.. code-block:: console + + uboot> tftpboot ''${loadaddr} result/rootfs + uboot> ubi write ''${loadaddr} liminix $filesize + +Now we have the root filesystem installed on the device. You +can even mount it and poke around using ``ubifsmount ubi0:liminix; +ubifsls /`` + +4) optional: before you configure the device to boot into Liminix +automatically, you can try booting it by hand to see if it works: + +.. code-block:: console + + uboot> ubifsmount ubi0:liminix + uboot> ubifsload ''${loadaddr} boot/uimage + uboot> bootm ''${loadaddr} + +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 +repeat step 3. + +5) Instructions for configuring autoboot are likely to be very +device-dependent. On the Linksys E8450/Belkin RT3200, the environment +variable `boot_production` governs what happens on a normal boot, so +you could do + +.. code-block:: console + + uboot> setenv 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 +`printenv` and look for likely commands, try looking at the existing +boot process, maybe even try looking for documentation for that device. + +6) Now you can reboot the device into Liminix + +.. code-block:: console + + uboot> reset + ''; + }; + }; + + config = mkIf (config.rootfsType == "ubifs") { + system.outputs = { + ubimage = + let o = config.system.outputs; in + pkgs.runCommand "ubimage" {} '' + mkdir $out + cd $out + ln -s ${o.rootfs} rootfs + ln -s ${instructions} env.scr + ''; + }; + }; +} diff --git a/modules/standard.nix b/modules/standard.nix @@ -5,7 +5,7 @@ imports = [ ./tftpboot.nix ./kexecboot.nix - ./flashimage.nix + ./outputs/flashimage.nix ./jffs2.nix ./ubifs.nix ]; diff --git a/modules/ubimage.nix b/modules/ubimage.nix @@ -1,112 +0,0 @@ -{ - config -, pkgs -, lib -, ... -}: -let - inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep; - loadaddr = config.boot.tftp.loadAddress; - cfg = config.boot.tftp; - instructions = pkgs.writeText "INSTALL.md" '' - -# First-time installation - -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 -system: see "kexecboot" but we don't have detailed instructions for -this process yet). - -These steps were tested on a Belkin RT3200 (also known as Linksys -E8450). Other devices may be set up differently, so use them as -inspiration and don't just paste them blindly. Consult the Liminix -manual for how to connect a serial cable to your device and get into -U-Boot - -1) determine which MTD device is being used for UBI and the partition name: - - uboot> ubi part - Device 0: ubi0, MTD partition ubi - -In this case the important value is `ubi0` - -2) list the available volumes and create a new one on which to install Liminix - - uboot> ubi info l - [ copious output scrolls past ] - -Expect there to be existing volumes and for some or all of them to be -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 -recovery partition. To see how much space is free: - - uboot> ubi info - [ ... ] - UBI: available PEBs: 823 - -Now we can make our new root volume - - uboot> ubi create liminix - - -3) transfer the root filesystem from the build system and write it -to the new volume - - uboot> setenv serverip ${cfg.serverip} - uboot> setenv ipaddr ${cfg.ipaddr} - uboot> tftpboot ${loadaddr} result/rootfs - uboot> ubi write ${loadaddr} liminix $filesize - -Now we have the root filesystem installed on the device. You -can even mount it and poke around using `ubifsmount ubi0:liminix; -ubifsls /` - -4) optional: before you configure the device to boot into Liminix -automatically, you can try booting it by hand to see if it works: - - uboot> ubifsmount ubi0:liminix - uboot> ubifsload ${loadaddr} boot/uimage - uboot> bootm ${loadaddr} - -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 -repeat step 3. - -5) Instructions for configuring autoboot are likely to be very -device-dependent. On the Linksys E8450/Belkin RT3200, the environment -variable `boot_production` governs what happens on a normal boot, so -you could do - - 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 -`printenv` and look for likely commands, try looking at the existing -boot process, maybe even try looking for documentation for that device. - -6) Now you can reboot the device into Liminix - - uboot> reset - -''; -in { - options.system.outputs = { - ubimage = mkOption { - type = types.package; - description = '' - UBIFS image and instructions to install it - ''; - }; - }; - - config = mkIf (config.rootfsType == "ubifs") { - system.outputs = { - ubimage = - let o = config.system.outputs; in - pkgs.runCommand "ubimage" {} '' - mkdir $out - cd $out - ln -s ${o.rootfs} rootfs - ln -s ${instructions} INSTALL - ''; - }; - }; -}