forked from dan/liminix
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ae1edbce7 | |||
| 1a5efff3ae | |||
| 8772e64b94 | |||
| e6ef4f78bb | |||
| d2f517a4e9 | |||
| 0f38ee0e9c | |||
| 61dc5beca8 | |||
| f3225c2bd5 | |||
| 8798ee9830 | |||
| 629914f65e | |||
| 0693cf23d8 | |||
| c341eb46b6 | |||
| 1a369ff3bf | |||
| 364c5faf9e | |||
| 80a09a9a9b | |||
| 3518e2ecca | |||
| fc2eb6ee4d | |||
| bd20f3e419 | |||
| f62ad0e1d7 | |||
| ed792e0dc0 | |||
| d025c33d30 | |||
| a755c9c3c5 | |||
| fdf74fa06b | |||
| b8dea2ed34 | |||
| c18f07f02f | |||
| 1c4412a1f4 | |||
| dbc16edf96 | |||
| 528d619d76 |
+255
@@ -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.
|
||||
|
||||
@@ -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 ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
@@ -175,7 +175,6 @@
|
||||
CONSOLE_LOGLEVEL_QUIET = "4";
|
||||
|
||||
NET = "y";
|
||||
NETDEVICES = "y";
|
||||
ETHERNET = "y";
|
||||
NET_VENDOR_ATHEROS = "y";
|
||||
AG71XX = "y"; # ethernet (qca,qca9530-eth)
|
||||
|
||||
@@ -159,7 +159,6 @@
|
||||
CONSOLE_LOGLEVEL_QUIET = "4";
|
||||
|
||||
NET = "y";
|
||||
NETDEVICES = "y";
|
||||
ETHERNET = "y";
|
||||
NET_VENDOR_RALINK = "y";
|
||||
NET_RALINK_MDIO = "y";
|
||||
|
||||
@@ -143,7 +143,6 @@
|
||||
REGULATOR_FIXED_VOLTAGE = "y";
|
||||
|
||||
NET = "y";
|
||||
NETDEVICES = "y";
|
||||
ETHERNET = "y";
|
||||
|
||||
PHYLIB = "y";
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -60,7 +60,6 @@
|
||||
VIRTIO_PCI = "y";
|
||||
BLOCK = "y";
|
||||
VIRTIO_BLK = "y";
|
||||
NETDEVICES = "y";
|
||||
VIRTIO_NET = "y";
|
||||
|
||||
SERIAL_8250= "y";
|
||||
|
||||
@@ -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"; };
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -7,5 +7,6 @@
|
||||
./kexecboot.nix
|
||||
./flashimage.nix
|
||||
./jffs2.nix
|
||||
./ubifs.nix
|
||||
];
|
||||
}
|
||||
|
||||
+20
-8
@@ -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
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -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
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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 = ''
|
||||
|
||||
@@ -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
@@ -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
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -34,4 +34,5 @@ in {
|
||||
applyPatches.ath79 = doPatch "ath79";
|
||||
applyPatches.ramips = doPatch "ramips";
|
||||
applyPatches.mediatek = doPatch "mediatek"; # aarch64
|
||||
applyPatches.mvebu = doPatch "mvebu"; # arm
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
CFLAGS+=-Os -fno-stack-protector -fpic -fPIC
|
||||
LDFLAGS=-static
|
||||
|
||||
preinit: preinit.o parseopts.o
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
with import <nixpkgs> {};
|
||||
mkShell {
|
||||
name = "preinit-env";
|
||||
src = ./.;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ in attrset:
|
||||
src = ./.;
|
||||
|
||||
CFLAGS = "-Os";
|
||||
LDFLAGS = "-static";
|
||||
LDFLAGS = "-static -Xlinker -static";
|
||||
|
||||
postConfigure = ''
|
||||
cp ${makedevs} makedevs.c
|
||||
|
||||
+22
-11
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user