1
0
forked from dan/liminix

Compare commits

...

28 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
dan e6ef4f78bb "ubimage" module contains ubifs image + instructions
Presently either you run this from U-Boot or you figure out for
yourself how to kexecboot into a recovery system :-)
2023-10-21 23:20:53 +01:00
dan d2f517a4e9 preinit.c: reindent 2023-10-19 21:02:18 +01:00
dan 0f38ee0e9c remove PREINIT_USE_LIBC option as it is now the only option 2023-10-19 18:59:02 +01:00
dan 61dc5beca8 preinit: parse rootfstype from kernel command line 2023-10-19 18:56:09 +01:00
dan f3225c2bd5 delete dup outputs.systemConfiguration
perhaps this should go into initramfs.nix not jffs2.nix
2023-10-19 10:09:08 +01:00
dan 8798ee9830 partial fix for timeout handling
1) "Unknown transfer id" message was because the local variable "tid"
is not a transfer id, it is a sequence number  - so the check was
actually comparing expected vs actual acknowledged sequence number,
not TID.  It's still a problem if we get the wrong one, but it
indicates a lost packet (so we should resend) not a packet that was
sent from somewhere else.

2) if the ACK packet has not been received, our retry should involve
_resending_ it, not just trying to wait for it again.

3) I have removed the timeout condition for terminating the resend
loop, because in practice (assuming both ends have the same timeout
setting) all it did was ensure that the loop only ran once. The
timeout is supposed to regulate how long we wait for before retrying
(it doesn't do this, we wait indefinitely), not how long we wait for
before giving up.
2023-10-18 23:35:23 +01:00
dan 629914f65e initial support for ubifs 2023-10-16 19:55:17 +01:00
dan 0693cf23d8 preinit: improve error logging for fork_exec 2023-10-12 19:00:57 +01:00
dan c341eb46b6 use hostPlatform.linuxArch in kernel derivation 2023-10-12 18:59:45 +01:00
dan 1a369ff3bf preinit: remove no-longer-used mips assembly 2023-10-12 18:57:54 +01:00
dan 364c5faf9e tftpboot: fix errors in phram partition size calc 2023-10-10 20:26:27 +01:00
dan 80a09a9a9b rt3200: move the entryPoint 2023-10-10 20:25:42 +01:00
dan 3518e2ecca Merge branch 'hark-how-all-the-belkin-rings' 2023-10-09 19:56:48 +01:00
dan fc2eb6ee4d rt3200 mumble 2023-10-09 19:56:22 +01:00
dan bd20f3e419 uimage: make fit optional 2023-10-09 19:47:57 +01:00
dan f62ad0e1d7 use "tftpboot" instead of "tftp" in u-boot commands
openwrt's u-boot installation doesn't accept the short form
2023-10-09 19:47:57 +01:00
dan ed792e0dc0 rt3200: swap wireless driver load order
mt7515e loads first, so that wlan0 is 2.4GHz
mt7515e loads after, so that 5GHz gets wlan1
2023-10-09 19:47:57 +01:00
dan d025c33d30 rt3200: enable flash/mtd 2023-10-09 19:47:57 +01:00
dan a755c9c3c5 delete some inapplicable kconfig 2023-10-09 19:47:57 +01:00
dan fdf74fa06b add mt7915, 7615 wifi modules
7915 won't work until we have working MTD, because it needs to
read calibration data from flash
2023-10-09 19:47:57 +01:00
dan b8dea2ed34 rt3200: add DSA
this creates a bunch of network interfaces {lan[1234],wan}@eth0
2023-10-09 19:47:57 +01:00
dan c18f07f02f aarch64: make tftpboot work
- patch dtb to add reserved-memory stanza for the phram device to use
  (aarch64 does not accept memmap= command line option)

- patch phram driver to use memremap() instead of ioremap() as
  ioremap can't be used for system ram on arm devices
2023-10-09 19:47:57 +01:00
dan 1c4412a1f4 rt3200: enable serial console 2023-10-09 19:47:57 +01:00
dan dbc16edf96 don't use ttyAMA0 console on all aarch64, just qemu 2023-10-09 19:47:57 +01:00
dan 528d619d76 WIP kernel config for belkin rt3200 2023-10-09 19:47:57 +01:00
28 changed files with 1043 additions and 129 deletions
+255
View File
@@ -2436,3 +2436,258 @@ Sun Sep 17 16:44:31 BST 2023
Can we figure out which bits of the old doc are missing from the new
one and just transplant those? Then we can merge it sooner
instead of blocking on writig all the new stuff
Mon Sep 25 16:58:51 BST 2023
jffs2 on mt300a isn't finding root partition in initramfs, and it
seems to be because MTD_SPLIT_UIMAGE_FW isn't working
[ 0.426792] spi spi0.0: force spi mode3
[ 0.431305] spi-nor spi0.0: w25q128 (16384 Kbytes)
[ 0.436322] 5 fixed-partitions partitions found on MTD device spi0.0
[ 0.442875] OF: Bad cell count for /palmbus@10000000/spi@b00/flash@0/partitions
[ 0.450400] OF: Bad cell count for /palmbus@10000000/spi@b00/flash@0/partitions
[ 0.458208] OF: Bad cell count for /palmbus@10000000/spi@b00/flash@0/partitions
[ 0.465751] OF: Bad cell count for /palmbus@10000000/spi@b00/flash@0/partitions
[ 0.473522] Creating 5 MTD partitions on "spi0.0":
[ 0.478466] 0x000000000000-0x000000030000 : "u-boot"
[ 0.484447] 0x000000030000-0x000000040000 : "u-boot-env"
[ 0.490888] 0x000000040000-0x000000050000 : "factory"
[ 0.497110] 0x000000050000-0x000000fd0000 : "firmware"
[ 0.596423] 0x000000ff0000-0x000001000000 : "art"
[ 0.611508] gsw: setting port4 to ephy mode
with squashfs root it's the same but for the extra split partitions:
[ 0.468715] Creating 5 MTD partitions on "spi0.0":
[ 0.473653] 0x000000000000-0x000000030000 : "u-boot"
[ 0.479652] 0x000000030000-0x000000040000 : "u-boot-env"
[ 0.486085] 0x000000040000-0x000000050000 : "factory"
[ 0.492318] 0x000000050000-0x000000fd0000 : "firmware"
[ 0.499304] 2 uimage-fw partitions found on MTD device firmware
[ 0.505457] Creating 2 MTD partitions on "firmware":
[ 0.510543] 0x000000000000-0x000000260000 : "kernel"
[ 0.516616] 0x000000260000-0x000000f80000 : "rootfs"
[ 0.522570] mtd: device 5 (rootfs) set to be root filesystem
[ 0.528565] 0x000000ff0000-0x000001000000 : "art"
turns out this is because the device thinks it has 4k erase block size
because MTD_SPI_NOR_USE_4K_SECTORS was set, and that was causing
mtdsplit to look in the wrong place for a root filesystem
Mon Sep 25 18:50:05 BST 2023
No, that wasn't it. Turned out to be an endianness-dependent check for
JFFS2 magic in mtdsplit.
setenv serverip 10.0.0.1
setenv ipaddr 10.0.0.8
tftp 0xa00000 result/uimage
bootm 0xa00000
Fri Sep 29 20:50:39 BST 2023
setenv bootargs 'liminix mtdparts=phram0:M(rootfs) phram.phram=phram0,0x40411f28,4194304,65536 memmap=4194304$0x40411f28 root=/dev/mtdblock0 console=ttyAMA0,115200 earlycon'
setenv serverip 10.0.0.1
setenv ipaddr 10.0.0.5
setenv bootargs 'liminix console=ttyS0,115200 panic=10 oops=panic earlycon=uart8250,mmio32,0x11002000 root=/dev/mtdblock0'
tftp 0x4007ff28 result/uimage ; tftp 0x40432f28 result/rootfs
bootm 0x4007ff28
setenv bootargs 'liminix console=ttyS0,115200 panic=1 oops=panic earlycon root=/dev/mtdblock0'
md 0x42ff0000
Cannot find regmap for /infracfg@10000000: -524.
# "console=ttyAMA0,38400 panic=10 oops=panic init=/bin/init loglevel=8 root=/dev/mtdblock0 rootfstype=squashfs fw_devlink=off"
40812468: 69726553 203a6c61 41424d41 304c5020 Serial: AMBA PL0
40812478: 55203131 20545241 76697264 3c0a7265 11 UART driver.<
40812488: 61723e33 706f6f6d 61203a73 6165726c 3>ramoops: alrea
40812498: 69207964 6974696e 7a696c61 3c0a6465 dy initialized.<
408124a8: 61723e34 706f6f6d 70203a73 65626f72 4>ramoops: probe
408124b8: 20666f20 66663234 30303030 6d61722e of 42ff0000.ram
408124c8: 73706f6f 69616620 2064656c 68746977 oops failed with
408124d8: 72726520 2d20726f 3c0a3232 61433e33 error -22.<3>Ca
408124e8: 746f6e6e 6e696620 65722064 70616d67 nnot find regmap
408124f8: 726f6620 6e692f20 63617266 31406766 for /infracfg@1
40812508: 30303030 3a303030 32352d20 333c0a34 0000000: -524.<3
40812518: 6e61433e 20746f6e 646e6966 67657220 >Cannot find reg
MT7622>
40812528: 2070616d 20726f66 666e692f 66636172 map for /infracf
40812538: 30314067 30303030 203a3030 3432352d g@10000000: -524
40812548: 3e333c0a 6e6e6143 6620746f 20646e69 .<3>Cannot find
40812558: 6d676572 66207061 2f20726f 72666e69 regmap for /infr
40812568: 67666361 30303140 30303030 2d203a30 acfg@10000000: -
40812578: 0a343235 433e333c 6f6e6e61 69662074 524.<3>Cannot fi
40812588: 7220646e 616d6765 6f662070 702f2072 nd regmap for /p
40812598: 63697265 31406766 32303030 3a303030 ericfg@10002000:
408125a8: 32352d20 313c0a34 616e553e 20656c62 -524.<1>Unable
408125b8: 68206f74 6c646e61 656b2065 6c656e72 to handle kernel
408125c8: 67617020 20676e69 75716572 20747365 paging request
408125d8: 76207461 75747269 61206c61 65726464 at virtual addre
408125e8: 66207373 66666666 66666666 66666666 ss fffffffffffff
408125f8: 0a656666 4d3e313c 61206d65 74726f62 ffe.<1>Mem abort
CONFIG_SERIAL_8250_FSL=y
CONFIG_SERIAL_8250_MT6577=y
CONFIG_SERIAL_8250_NR_UARTS=3
CONFIG_SERIAL_8250_RUNTIME_UARTS=3
CONFIG_SERIAL_DEV_BUS=y
CONFIG_SERIAL_DEV_CTRL_TTYPORT=y
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_OF_PLATFORM=y
Mon Oct 2 10:17:04 BST 2023
We have a bootable aarch64 kernel for the Belkin, but it does not
understand the memmap= parameter we're using to protect the
phram image from being used as general memory.
One option is to add a reserved-memory stanza in the device tree,
using u-boot "fdt" command, but we don't know the fdt address in u-boot
because it doesn't have any commands to parse the image and set
variables pointing at the sub-components. (There's iminfo, but it's
onyl human-readable)
Second option is to amend the dtb in the tftpboot module: this
would mean regenerating the uimage
Third option: for tftpboot do we _have_ to use FIT? maybe we could
grab the fdt as a separate tftp transaction
we need to apply kernel patch 9401911f2d9f89035f7acebab16e72d43d1282fb
to avoid using ioremap on sysem ram which is not allowed on arm
Tue Oct 3 14:15:38 BST 2023
Progress on Liminix ARM support. The device I'm starting with is
the Belkin RT3200 (also known as [Linksys E8450](https://openwrt.org/toh/linksys/e8450)) which seems to be a featureful piece of kit, and whioch I snagged for a
very good price on the Bay of E
# Where are we right now?
* we can TFTP boot it to userland
* ethernet works
## What else needs doing?
* it has dual band wifi with many interesting features. I've built the
* we're only running in RAM, probably need to add some kernel config
to support the flash
* initramfs support is not yet implemented
* the flash is NAND flash and it's quite large compared with the
existing Liminix devices, so we're going to add UBIFS which will
use it better than JFFS2 does
* all this work is on a branch and needs to be cleaned up a lot before
I'm letting it into main
## What have we found?
There are some significant differences between this and the MIPS
devices (yes, other than an entirely different architecture), mostly
to do with "legacy boot" support or the lack thereof. For example:
* there aren't any options like `MIPS_RAW_APPENDED_DTB` to glom
together a kernel and device tree (FDT), because the bootloader is
expected to be able to provide a FDT following "standards".
U-Boot will do this, provided that we use the newer "FIT" Uimage
format which allows a kernel and DTB and initrd to be combined in
the same container. (Sadly we can't use FIT everywhere because a
lot of MIPS devices use really old forks of U-Boot that don't
understand it)
* for tftpboot, on MIPS we use the `memmap` kernel command line option
to reserve some RAM for the root filesystem. On Arm there's no such
option, so we have to add a
[reserved-memory](https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/reserved-memory/reserved-memory.yaml)
node in the device tree instead. Which means, given that we _only_
want to do this when tftp booting (the memory is wasted
otherwise), we have to rewrite the device tree in that
scenario.
* then it turns out that phram doesn't (didn't) work anyway, because
it calls ioremap() and [you can't use ioremap on system memory on ARM](https://lwn.net/Articles/409689/). In newer kernels this is
fixed: there is a [conditional](https://github.com/torvalds/linux/blob/master/drivers/mtd/devices/phram.c#L127) here to use whichever of ioremap or
memremap is appropriate for the memory passed to phram, but it looks
non-trivial to backport so I've gone for a [much less sophisticated approach](https://gti.telent.net/dan/liminix/commit/f7cd9c2b6e6c99a228e066b09e3febcf71c63fa1#diff-d8e355f1b2dcde7378ebb40c92cdd2ce3125753c)
* we're using [DSA](https://www.kernel.org/doc/Documentation/networking/dsa/dsa.txt) instead of the OpenWrt [swconfig](https://openwrt.org/docs/techref/swconfig) program. There was actually surprisingly little work needed to adjust to this.
Other than that, it was mostly the usual process of "did the kernel
crash silently, or has it just been unable to open a console device?".
In this regard, *one neat trick*: even though U-Boot on this device
doesn't support pstore, we can use it anyway if we don't do compression.
Enable
```
PSTORE = "y";
PSTORE_RAM = "y";
PSTORE_CONSOLE = "y";
PSTORE_DEFLATE_COMPRESS = "n";
```
then boot with `panic=3 oops=panic`, then when it resets use the
U_Boot `md` command to see what happened:
```
MT7622> md 0x42ff0000
42ff0000: 43474244 00000000 00000ff4 3d3d3d3d DBGC........====
42ff0010: 39342e31 36373031 500a442d 63696e61 1.491076-D.Panic
42ff0020: 50203123 31747261 3e363c0a 20505050 #1 Part1.<6>PPP
42ff0030: 20445342 706d6f43 73736572 206e6f69 BSD Compression
[....]
42ff0ca0: 20676e69 73756e75 6b206465 656e7265 ing unused kerne
42ff0cb0: 656d206c 79726f6d 3731203a 0a4b3832 l memory: 1728K.
42ff0cc0: 523e363c 2f206e75 74696e69 20736120 <6>Run /init as
42ff0cd0: 74696e69 6f727020 73736563 3e373c0a init process.<7>
```
Wed Oct 4 21:08:44 BST 2023
By randomly including chinks of the openwrt config we have made it
find the mt7915e on the pcie bus. I just don't yet know which bit of
the openwrt config it was.
It doesn't actually work yet though. 5GHz wifi gets calibration data
from the flash, so it is not going to work unless (1) we reflash the
firmware partition, or (2) we find another way to provide it
calibration data.
https://forum.openwrt.org/t/belkin-rt3200-linksys-e8450-wifi-ax-discussion/94302/401
Sat Oct 7 22:56:40 BST 2023
We're almost ready to merge the rt3200 support (it's not finished
but it mostly won't break mips) except for the uimage module
which needs all that FIT stuff, and the tftpboot contortions
to amend the dtb for memmap
For legacy uimage
1) add commandline params to dtb
2) objcopy fdt into vmlinux.elf
3) strip to raw image and compress
4) mkimage
For FIT uimage
1) add commandline params to dtb
2) strip to raw image and compress
3) create its file
4) mkimage
Do we still want to handle the no-dtb case? what about
standards-compliant boot, where u-boot is providing the dtb? No option
to provide a commandline in that case, but maybe also no need to.
For tftpboot, am undecided. We could use the dtb rewriting thing
everywhere, in the interest of consistency.
+205
View File
@@ -0,0 +1,205 @@
{
description = ''
Belkin RT-3200 / Linksys E8450
******************************
This device is based on a 64 bit Mediatek MT7622 ARM platform,
and is "work in progress" in Liminix.
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
'';
system = {
crossSystem = {
config = "aarch64-unknown-linux-musl";
};
};
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
'';
};
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";
# needed for "Cannot find regmap for /infracfg@10000000"
MFD_SYSCON = "y";
MTK_INFRACFG = "y";
MTK_PMIC_WRAP = "y";
MTK_EFUSE="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";
# 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 ];
};
};
};
};
}
-1
View File
@@ -175,7 +175,6 @@
CONSOLE_LOGLEVEL_QUIET = "4";
NET = "y";
NETDEVICES = "y";
ETHERNET = "y";
NET_VENDOR_ATHEROS = "y";
AG71XX = "y"; # ethernet (qca,qca9530-eth)
-1
View File
@@ -159,7 +159,6 @@
CONSOLE_LOGLEVEL_QUIET = "4";
NET = "y";
NETDEVICES = "y";
ETHERNET = "y";
NET_VENDOR_RALINK = "y";
NET_RALINK_MDIO = "y";
-1
View File
@@ -143,7 +143,6 @@
REGULATOR_FIXED_VOLTAGE = "y";
NET = "y";
NETDEVICES = "y";
ETHERNET = "y";
PHYLIB = "y";
+3 -1
View File
@@ -34,7 +34,6 @@
VIRTIO_PCI = "y";
BLOCK = "y";
VIRTIO_BLK = "y";
NETDEVICES = "y";
VIRTIO_NET = "y";
SERIAL_EARLYCON_ARM_SEMIHOST = "y"; # earlycon=smh
@@ -42,6 +41,9 @@
SERIAL_AMBA_PL011_CONSOLE = "y";
};
};
boot.commandLine = [
"console=ttyAMA0,38400"
];
hardware =
let
mac80211 = pkgs.mac80211.override {
-1
View File
@@ -60,7 +60,6 @@
VIRTIO_PCI = "y";
BLOCK = "y";
VIRTIO_BLK = "y";
NETDEVICES = "y";
VIRTIO_NET = "y";
SERIAL_8250= "y";
+111
View File
@@ -0,0 +1,111 @@
{
description = ''
Turris Omnia
************
'';
system = {
crossSystem = {
config = "armv7l-unknown-linux-musleabihf";
};
};
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=";
};
extraPatchPhase = ''
${pkgs.openwrt.applyPatches.mvebu}
'';
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";
MACH_ARMADA_38X = "y";
SMP = "y";
NR_CPUS = "4";
VFP = "y";
NEON= "y";
# WARNING: unmet direct dependencies detected for ARCH_WANT_LIBATA_LEDS
ATA = "y";
# switch is DSA
# CONFIG_NET_DSA_MV88E6060=y
# CONFIG_NET_DSA_MV88E6XXX=y
# CONFIG_NET_DSA_MV88E6XXX_GLOBAL2=y
# CONFIG_REGMAP=y
# CONFIG_REGMAP_I2C=y
# CONFIG_REGMAP_SPI=y
# CONFIG_REGMAP_MMIO=y
PSTORE = "y";
PSTORE_RAM = "y";
PSTORE_CONSOLE = "y";
PSTORE_DEFLATE_COMPRESS = "n";
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";
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 -4
View File
@@ -6,14 +6,11 @@
CPU_BIG_ENDIAN= "n";
# CMDLINE_FROM_BOOTLOADER availability is conditional
# on CMDLINE being set to something non-empty
CMDLINE="\"console=ttyAMA0\"";
CMDLINE="\"empty=false\"";
CMDLINE_FROM_BOOTLOADER = "y";
OF = "y";
# USE_OF = "y";
};
boot.commandLine = [
"console=ttyAMA0,38400"
];
};
}
+5 -1
View File
@@ -39,7 +39,7 @@ in {
};
rootfsType = mkOption {
default = "squashfs";
type = types.enum ["squashfs" "jffs2"];
type = types.enum ["squashfs" "jffs2" "ubifs"];
};
boot = {
commandLine = mkOption {
@@ -47,6 +47,10 @@ in {
default = [];
description = "Kernel command line";
};
imageFormat = mkOption {
type = types.enum ["fit" "uimage"];
default = "uimage";
};
tftp = {
loadAddress = mkOption {
type = types.str;
+2
View File
@@ -64,6 +64,8 @@ in {
PACKET = "y"; # for ppp, tcpdump ...
SYSVIPC= "y";
NETDEVICES = "y"; # even PPP needs this
# disabling this option causes the kernel to use an "empty"
# initramfs instead: it has a /dev/console node and not much
# else. Note that pid 1 is started *before* the root
+1
View File
@@ -78,6 +78,7 @@ in
uimage = liminix.builders.uimage {
commandLine = concatStringsSep " " config.boot.commandLine;
inherit (config.hardware) loadAddress entryPoint;
inherit (config.boot) imageFormat;
inherit kernel;
inherit dtb;
};
+1
View File
@@ -7,5 +7,6 @@
./kexecboot.nix
./flashimage.nix
./jffs2.nix
./ubifs.nix
];
}
+20 -8
View File
@@ -42,27 +42,39 @@ in {
ln -s ${o.manifest} manifest
ln -s ${o.kernel.headers} build
ln -s ${o.uimage} uimage
ln -s ${o.boot-scr} boot.scr
ln -s ${o.boot-scr}/dtb dtb
ln -s ${o.boot-scr}/script boot.scr
'';
boot-scr =
let
inherit (pkgs.lib.trivial) toHexString;
o = config.system.outputs;
cmdline = concatStringsSep " " config.boot.commandLine;
in
pkgs.buildPackages.runCommand "boot-scr" {} ''
pkgs.buildPackages.runCommand "boot-scr" { nativeBuildInputs = [ pkgs.pkgsBuildBuild.dtc ]; } ''
uimageSize=$(($(stat -L -c %s ${o.uimage}) + 0x1000 &(~0xfff)))
rootfsStart=0x$(printf %x $((${cfg.loadAddress} + 0x100000 + $uimageSize)))
rootfsStart=0x$(printf %x $((${cfg.loadAddress} + 0x100000 + $uimageSize &(~0xfffff) )))
rootfsBytes=$(($(stat -L -c %s ${o.rootfs}) + 0x100000 &(~0xfffff)))
rootfsBytes=$(($rootfsBytes + ${toString cfg.freeSpaceBytes} ))
cmd="mtdparts=phram0:''${rootfsMb}M(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsBytes},${config.hardware.flash.eraseBlockSize} memmap=''${rootfsBytes}\$''${rootfsStart} root=/dev/mtdblock0";
rootfsMb=$(($rootfsBytes >> 20))
cmd="mtdparts=phram0:''${rootfsMb}M(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsBytes},${config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0";
cat > $out << EOF
dtbStart=$(printf %x $((${cfg.loadAddress} + $rootfsBytes + 0x100000 + $uimageSize )))
mkdir $out
cat ${o.dtb} > $out/dtb
fdtput -p -t s $out/dtb /reserved-memory/phram-rootfs compatible phram
fdtput -p -t lx $out/dtb /reserved-memory/phram-rootfs reg 0 $rootfsStart 0 $(printf %x $rootfsBytes)
dtbBytes=$(($(stat -L -c %s $out/dtb) + 0x1000 &(~0xfff)))
cat > $out/script << EOF
setenv serverip ${cfg.serverip}
setenv ipaddr ${cfg.ipaddr}
setenv bootargs 'liminix $cmd'
tftp 0x$(printf %x ${cfg.loadAddress}) result/uimage ; tftp 0x$(printf %x $rootfsStart) result/rootfs
bootm 0x$(printf %x ${cfg.loadAddress})
setenv bootargs 'liminix ${cmdline} $cmd'
tftpboot 0x$(printf %x ${cfg.loadAddress}) result/uimage ; tftpboot 0x$(printf %x $rootfsStart) result/rootfs ; tftpboot 0x$dtbStart result/dtb
bootm 0x$(printf %x ${cfg.loadAddress}) - 0x$dtbStart
EOF
'';
};
+50
View File
@@ -0,0 +1,50 @@
{
config
, pkgs
, lib
, ...
}:
let
inherit (lib) mkIf mkOption types;
in
{
imports = [
./initramfs.nix
];
options.hardware.ubi = {
minIOSize = mkOption { type = types.str; };
eraseBlockSize = mkOption { type = types.str; }; # LEB
maxLEBcount = mkOption { type = types.str; }; # LEB
};
config = mkIf (config.rootfsType == "ubifs") {
kernel.config = {
MTD_UBI="y";
UBIFS_FS = "y";
UBIFS_FS_SECURITY = "n";
};
boot.initramfs.enable = true;
system.outputs = rec {
systemConfiguration =
pkgs.systemconfig config.filesystem.contents;
rootfs =
let
inherit (pkgs.pkgsBuildBuild) runCommand mtdutils;
cfg = config.hardware.ubi;
in runCommand "mkfs.ubifs" {
depsBuildBuild = [ mtdutils ];
} ''
mkdir -p $TMPDIR/empty/nix/store/ $TMPDIR/empty/secrets $TMPDIR/empty/boot
cp ${systemConfiguration}/bin/activate $TMPDIR/empty/activate
ln -s ${pkgs.s6-init-bin}/bin/init $TMPDIR/empty/init
cp ${config.system.outputs.uimage} $TMPDIR/empty/boot/uimage
mkdir -p $TMPDIR/empty/nix/store
for path in $(cat ${systemConfiguration}/etc/nix-store-paths) ; do
(cd $TMPDIR/empty && cp -a $path .$path)
done
mkfs.ubifs -x favor_lzo -c ${cfg.maxLEBcount} -m ${cfg.minIOSize} -e ${cfg.eraseBlockSize} -y -r $TMPDIR/empty --output $out --squash-uids -o $out
'';
};
};
}
+112
View File
@@ -0,0 +1,112 @@
{
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
'';
};
};
}
+3 -7
View File
@@ -11,12 +11,7 @@
let
writeConfig = import ./write-kconfig.nix { inherit lib writeText; };
kconfigFile = writeConfig "kconfig" config;
arch = if stdenv.isMips
then "mips"
else if stdenv.isAarch64
then "arm64"
else throw "unknown arch";
arch = stdenv.hostPlatform.linuxArch;
inherit lib; in
stdenv.mkDerivation rec {
name = "kernel";
@@ -54,6 +49,7 @@ stdenv.mkDerivation rec {
patches = [
./cmdline-cookie.patch
./phram-allow-cached-mappings.patch
];
# this is here to work around what I think is a bug in nixpkgs
@@ -81,7 +77,7 @@ stdenv.mkDerivation rec {
export KBUILD_OUTPUT=`pwd`
cp ${kconfigFile} .config
cp ${kconfigFile} .config.orig
make V=1 olddefconfig
make olddefconfig
'';
checkConfigurationPhase = ''
+3 -3
View File
@@ -1,6 +1,6 @@
/dts-v1/;
// used on aarch64 to provide a U-bootable image that combines
// used on arm/aarch64 to provide a U-bootable image that combines
// kernel and fdt
/ {
@@ -12,7 +12,7 @@
description = "Vanilla Linux kernel";
// data = /incbin/("./vmlinux.bin.gz");
type = "kernel";
arch = "arm64";
// arch = "arm64";
os = "linux";
// compression = "gzip";
// load = <00000000>;
@@ -28,7 +28,7 @@
description = "Flattened Device Tree blob";
// data = /incbin/("./target.dtb");
type = "flat_dt";
arch = "arm64";
// arch = "arm64";
compression = "none";
hash-1 {
algo = "crc32";
@@ -0,0 +1,47 @@
From bb7e7aeb3d832059e33b1e76eb85d4680f77abf2 Mon Sep 17 00:00:00 2001
From: Ben Hutchings <ben@decadent.org.uk>
Date: Fri, 3 Jun 2016 01:08:36 +0100
Subject: [PATCH] phram: Use memremap() to allow mapping of system RAM
Using memremap() instead of ioremap() allows mapping a disk image in
system RAM that has somehow been reserved. It should fall back
to ioremap() where necessary.
Entirely untested, and I'm not convinced this is a good idea at all.
---
drivers/mtd/devices/phram.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 8b66e52ca3cc..0ea254e2ba51 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -88,7 +88,7 @@ static void unregister_devices(void)
list_for_each_entry_safe(this, safe, &phram_list, list) {
mtd_device_unregister(&this->mtd);
- iounmap(this->mtd.priv);
+ memunmap(this->mtd.priv);
kfree(this->mtd.name);
kfree(this);
}
@@ -104,7 +104,8 @@ static int register_device(char *name, phys_addr_t start, size_t len)
goto out0;
ret = -EIO;
- new->mtd.priv = ioremap(start, len);
+ new->mtd.priv = memremap(start, len,
+ MEMREMAP_WB | MEMREMAP_WT | MEMREMAP_WC);
if (!new->mtd.priv) {
pr_err("ioremap failed\n");
goto out1;
@@ -134,7 +135,7 @@ static int register_device(char *name, phys_addr_t start, size_t len)
return 0;
out2:
- iounmap(new->mtd.priv);
+ memunmap(new->mtd.priv);
out1:
kfree(new);
out0:
+43 -29
View File
@@ -7,21 +7,27 @@
} :
let
objcopy = "${stdenv.cc.bintools.targetPrefix}objcopy";
arch = stdenv.hostPlatform.linuxArch;
stripAndZip = ''
${objcopy} -O binary -R .reginfo -R .notes -R .note -R .comment -R .mdebug -R .note.gnu.build-id -S vmlinux.elf vmlinux.bin
rm -f vmlinux.bin.lzma ; lzma -k -z vmlinux.bin
'';
in {
kernel
, commandLine
, entryPoint
, extraName ? "" # e.g. socFamily
, loadAddress
, imageFormat
, dtb ? null
} :
stdenv.mkDerivation {
} : stdenv.mkDerivation {
name = "kernel.image";
phases = [
"preparePhase"
(if dtb != null then "dtbPhase" else ":")
"buildPhase"
"installPhase" ];
(if commandLine != null then assert dtb != null; "mungeDtbPhase" else ":")
(if imageFormat == "fit" then "buildPhaseFIT" else "buildPhaseUImage")
"installPhase"
];
nativeBuildInputs = [
lzma
dtc
@@ -31,35 +37,43 @@ stdenv.mkDerivation {
preparePhase = ''
cp ${kernel} vmlinux.elf; chmod +w vmlinux.elf
'';
dtbPhase = ''
mungeDtbPhase = ''
dtc -I dtb -O dts -o tmp.dts ${dtb}
echo '/{ chosen { bootargs = ${builtins.toJSON commandLine}; }; };' >> tmp.dts
dtc -I dts -O dtb -o tmp.dtb tmp.dts
'';
buildPhase =
let arch =
# per output of "mkimage -A list". I *think* these
# are the same as the kernel arch convention, but
# maybe that's coincidence
if stdenv.isMips
then "mips"
else if stdenv.isAarch64
then "arm64"
else throw "unknown arch";
in ''
${objcopy} -O binary -R .reginfo -R .notes -R .note -R .comment -R .mdebug -R .note.gnu.build-id -S vmlinux.elf vmlinux.bin
rm -f vmlinux.bin.lzma ; lzma -k -z vmlinux.bin
cat ${./kernel_fdt.its} > mkimage.its
echo '/ { images { kernel { data = /incbin/("./vmlinux.bin.lzma"); }; }; };' >> mkimage.its
echo '/ { images { kernel { load = <${loadAddress}>; }; }; };' >> mkimage.its
echo '/ { images { kernel { entry = <${entryPoint}>; }; }; };' >> mkimage.its
echo '/ { images { kernel { compression = "lzma"; }; }; };' >> mkimage.its
echo '/ { images { fdt-1 { data = /incbin/("./tmp.dtb"); }; }; }; ' >> mkimage.its
mkimage -f mkimage.its mkimage.itb
mkimage -l mkimage.itb
'';
buildPhaseUImage = ''
test -f tmp.dtb && ${objcopy} --update-section .appended_dtb=tmp.dtb vmlinux.elf || ${objcopy} --add-section .appended_dtb=tmp.dtb vmlinux.elf
${stripAndZip}
mkimage -A ${arch} -O linux -T kernel -C lzma -a ${loadAddress} -e ${entryPoint} -n '${lib.toUpper arch} Liminix Linux ${extraName}' -d vmlinux.bin.lzma kernel.uimage
'';
buildPhaseFIT = ''
${stripAndZip}
cat ${./kernel_fdt.its} > mkimage.its
cat << _VARS >> mkimage.its
/ {
images {
kernel {
data = /incbin/("./vmlinux.bin.lzma");
load = <${loadAddress}>;
entry = <${entryPoint}>;
arch = "${arch}";
compression = "lzma";
};
fdt-1 {
data = /incbin/("./tmp.dtb");
arch = "${arch}";
};
};
};
_VARS
mkimage -f mkimage.its kernel.uimage
mkimage -l kernel.uimage
'';
installPhase = ''
cp mkimage.itb $out
cp kernel.uimage $out
'';
}
+1
View File
@@ -34,4 +34,5 @@ in {
applyPatches.ath79 = doPatch "ath79";
applyPatches.ramips = doPatch "ramips";
applyPatches.mediatek = doPatch "mediatek"; # aarch64
applyPatches.mvebu = doPatch "mvebu"; # arm
}
+4
View File
@@ -0,0 +1,4 @@
CFLAGS+=-Os -fno-stack-protector -fpic -fPIC
LDFLAGS=-static
preinit: preinit.o parseopts.o
-1
View File
@@ -15,7 +15,6 @@ stdenv.mkDerivation {
# NIX_DEBUG=2;
hardeningDisable = [ "all" ];
CFLAGS = "-Os -static -DPREINIT_USE_LIBC -fno-stack-protector -fpic -fPIC -I ./ -I ${kernel}/tools/include/nolibc";
postBuild = ''
$STRIP --remove-section=.note --remove-section=.comment preinit
+97
View File
@@ -0,0 +1,97 @@
#include <string.h>
#include <unistd.h>
static int begins_with(char * str, char * prefix)
{
while(*prefix) {
if(*str == '\0') return 0;
if(*str != *prefix) return 0;
str++;
prefix++;
}
return 1;
}
void parseopts(char * cmdline, char **root, char **rootfstype) {
*root = 0;
*rootfstype = 0;
for(char *p = cmdline; *p; p++) {
if(begins_with(p, "root=")) {
*root = p + strlen("root=");
while(*p && (*p != ' ')) p++;
if(*p) {
*p = '\0';
p++;
};
};
if(begins_with(p, "rootfstype=")) {
*rootfstype = p + strlen("rootfstype=");
while(*p && (*p != ' ')) p++;
if(*p) {
*p = '\0';
p++;
};
};
};
}
#ifdef TESTS
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define die(fmt, ...) do { printf(fmt, __VA_ARGS__); exit(1); } while(0)
#define S(x) #x
#define expect_equal(actual, expected) \
if(!actual || strcmp(actual, expected)) die("%d: expected \"%s\", got \"%s\"", __LINE__, expected, actual);
int main()
{
char * root = "/dev/hda1";
char * rootfstype = "xiafs";
char *buf;
// finds root= and rootfstype= options
buf = strdup("liminix console=ttyS0,115200 panic=10 oops=panic init=/bin/init loglevel=8 root=/dev/ubi0_4 rootfstype=ubifs fw_devlink=off mtdparts=phram0:18M(rootfs) phram.phram=phram0,0x40400000,18874368,65536 root=/dev/mtdblock0 foo");
parseopts(buf, &root, &rootfstype);
expect_equal(root, "/dev/mtdblock0");
expect_equal(rootfstype, "ubifs");
// in case of duplicates, chooses the latter
// also: works if the option is end of string
buf = strdup("liminix console=ttyS0,115200 panic=10 oops=panic init=/bin/init loglevel=8 root=/dev/ubi0_4 rootfstype=ubifs fw_devlink=off mtdparts=phram0:18M(rootfs) phram.phram=phram0,0x40400000,18874368,65536 root=/dev/mtdblock0");
parseopts(buf, &root, &rootfstype);
expect_equal(root, "/dev/mtdblock0");
expect_equal(rootfstype, "ubifs");
// options may appear in either order
buf = strdup("liminix fw_devlink=off root=/dev/hda1 rootfstype=ubifs foo");
parseopts(buf, &root, &rootfstype);
expect_equal(root, "/dev/hda1");
expect_equal(rootfstype, "ubifs");
buf = strdup("liminix rootfstype=ubifs fw_devlink=off root=/dev/hda1 foo");
parseopts(buf, &root, &rootfstype);
expect_equal(rootfstype, "ubifs");
expect_equal(root, "/dev/hda1");
// provides NULL for missing options
buf = strdup("liminix rufustype=ubifs fw_devlink=off foot=/dev/hda1");
parseopts(buf, &root, &rootfstype);
if(rootfstype) die("expected null rootfstype, got \"%s\"", rootfstype);
if(root) die("expected null root, got \"%s\"", root);
// provides empty strings for empty options
buf = strdup("liminix rootfstype= fw_devlink=off root= /dev/hda1");
parseopts(buf, &root, &rootfstype);
if(strlen(rootfstype)) die("expected empty rootfstype, got \"%s\"", rootfstype);
if(strlen(root)) die("expected null root, got \"%s\"", root);
}
#endif
+51 -59
View File
@@ -1,37 +1,36 @@
#ifdef PREINIT_USE_LIBC
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <string.h>
#else
#include <nolibc.h>
#endif
#include <asm/setup.h>
#include <asm/setup.h> /* for COMMAND_LINE_SIZE */
void parseopts(char * cmdline, char **root, char **rootfstype);
#define ERR(x) write(2, x, strlen(x))
#define AVER(c) do { if(c < 0) ERR("failed: " #c); } while(0)
static int begins_with(char * str, char * prefix)
{
while(*prefix) {
if(*str == '\0') return 0;
if(*str != *prefix) return 0;
str++;
prefix++;
}
return 1;
while(*prefix) {
if(*str == '\0') return 0;
if(*str != *prefix) return 0;
str++;
prefix++;
}
return 1;
}
static void fork_exec(char * command, char *args[])
static int fork_exec(char * command, char *args[])
{
int fork_pid = fork();
AVER(fork_pid);
if(fork_pid > 0)
wait(NULL);
else
AVER(execve(command, args, NULL));
int fork_pid = fork();
AVER(fork_pid);
if(fork_pid > 0)
wait(NULL);
else
return execve(command, args, NULL);
}
char banner[] = "Running pre-init...\n";
@@ -39,52 +38,45 @@ char buf[COMMAND_LINE_SIZE];
int main(int argc, char *argv[], char *envp[])
{
#ifndef PREINIT_USE_LIBC
asm("la $gp, _gp\nsw $gp,16($sp)");
#endif
char *rootdevice = 0;
char *p = buf;
write(1, banner, strlen(banner));
char *rootdevice = 0;
char *rootfstype = 0;
char *p = buf;
write(1, banner, strlen(banner));
mount("none", "/proc", "proc", 0, NULL);
mount("none", "/proc", "proc", 0, NULL);
int cmdline = open("/proc/cmdline", O_RDONLY, 0);
int cmdline = open("/proc/cmdline", O_RDONLY, 0);
if(cmdline>=0) {
int len = read(cmdline, buf, sizeof buf - 1);
buf[len]='\0';
write(1, "cmdline ", 8);
write(1, buf, len);
};
if(cmdline>=0) {
int len = read(cmdline, buf, sizeof buf - 1);
buf[len]='\0';
write(1, "cmdline ", 8);
write(1, buf, len);
};
while(*p) {
if(begins_with(p, "root=")) {
rootdevice = p + 5;
while(*p && (*p != ' ')) p++;
*p= '\0';
}
while(*p && (*p != ' ')) p++;
p++;
}
parseopts(buf, &rootdevice, &rootfstype);
if(rootdevice) {
if(!rootfstype) rootfstype = "jffs2"; /* backward compatibility */
write(1, "rootdevice ", 11);
write(1, rootdevice, strlen(rootdevice));
write(1, " (", 2);
write(1, rootfstype, strlen(rootfstype));
write(1, ")\n", 1);
if(rootdevice) {
write(1, "rootdevice ", 11);
write(1, rootdevice, strlen(rootdevice));
write(1, "\n", 1);
AVER(mount(rootdevice, "/target/persist", rootfstype, 0, NULL));
AVER(mount("/target/persist/nix", "/target/nix",
"bind", MS_BIND, NULL));
AVER(mount(rootdevice, "/target/persist", "jffs2", 0, NULL));
AVER(mount("/target/persist/nix", "/target/nix",
"bind", MS_BIND, NULL));
char *exec_args[] = { "activate", "/target", NULL };
AVER(fork_exec("/target/persist/activate", exec_args));
AVER(chdir("/target"));
char *exec_args[] = { "activate", "/target", NULL };
fork_exec("/target/persist/activate", exec_args);
AVER(chdir("/target"));
AVER(mount("/target", "/", "bind", MS_BIND | MS_REC, NULL));
AVER(chroot("."));
AVER(mount("/target", "/", "bind", MS_BIND | MS_REC, NULL));
AVER(chroot("."));
argv[0] = "init";
argv[1] = NULL;
AVER(execve("/persist/init", argv, envp));
}
argv[0] = "init";
argv[1] = NULL;
AVER(execve("/persist/init", argv, envp));
}
}
+5
View File
@@ -0,0 +1,5 @@
with import <nixpkgs> {};
mkShell {
name = "preinit-env";
src = ./.;
}
+1 -1
View File
@@ -68,7 +68,7 @@ in attrset:
src = ./.;
CFLAGS = "-Os";
LDFLAGS = "-static";
LDFLAGS = "-static -Xlinker -static";
postConfigure = ''
cp ${makedevs} makedevs.c
+22 -11
View File
@@ -195,19 +195,22 @@ function tftp:handle_RRQ(socket, host, port, source, options)
]]
yield(false, true)
end
socket:sendto(self.DATA(data, tid), host, port)
--[[ Now check for an ACK.
RFC1350 requires that for every packet sent, an ACK is received
before the next packet can be sent.
]]
local acked
local retried = 0
local timeout = time() + timeout_secs
local timedout = false
repeat
socket:sendto(self.DATA(data, tid), host, port)
--[[ Now check for an ACK.
RFC1350 requires that for every packet sent, an ACK is received
before the next packet can be sent.
]]
yield(true, false) -- we need to wait until the socket is readable again
local ack, ackhost, ackport = socket:recvfrom(ACKSIZE)
if ackhost ~= host or ackport ~= port or self.parse_ACK(ack) ~= tid then
local ack_sequence = self.parse_ACK(ack)
if ackhost ~= host or ackport ~= port then
--[[https://tools.ietf.org/html/rfc1350#page-5
"If a source TID does not match, the packet should be
discarded as erroneously sent from somewhere else.
@@ -216,13 +219,21 @@ function tftp:handle_RRQ(socket, host, port, source, options)
]]
socket:sendto(err(ERR_UNKNOWN_ID), ackhost, ackport)
yield(true, false)
else
acked = true
end
elseif ack_sequence ~= tid then
-- this looks confusing, but the local variable
-- "tid" here is actually block number (aka
-- sequence number), not tid at all.
log(("ack received for old block %d (expecting %d)"):format(ack_sequence, tid))
acked = false
else
acked = true
end
if not acked then log("resending") end
retried = retried + 1
timedout = time() > timeout
until acked or retried > ACK_RETRIES or timedout
if timedout or retried > ACK_RETRIES then
until acked or retried > ACK_RETRIES
if retried > ACK_RETRIES then
--There doesn't seem to be a standard error for timeout.
socket:sendto(err("Ack timeout"), host, port)
error("Timeout waiting for ACK")