Help needed for porting Buffalo LS421DE img to LS220DE

Your ethernet phy is a Marvel 88E1518 right?, then it isn't configured with the correct voltage. It might cause issues. It should return 0x00000A8A

It seems there aren't firmwares below 1.60 version available for this unit. So UBIFS in kernel partition is the only one way to go.

Still not sure how to make a good approach, It's even possible to just copy the openwrt kernel into the stock partition overwritting the oem kernel file.

1 Like

Seems a 1318 one:
[ 3.256865] mvneta d0074000.ethernet eth0: PHY [d0072004.mdio-mii:00] driver [Marvell 88E1318S] (irq=POLL)

Connection stills working flawlessly.

I booted again with the initram, finally I got one compiled and I'm using now for testing.
Seems that for result I desire (and ignoring eventual cfg-lose at each reboot), it will make happen, but I need to "pump it muscles", it cames only with the core.

Analysing the files, I got:
openwrt-22.03.3-mvebu-cortexa9-buffalo_ls220d-initramfs-kernel.bin: u-boot legacy uImage, ARM OpenWrt Linux-5.10.161, Linux/ARM, OS Kernel Image (Not compressed), 6543386 bytes, Tue Jan 3 00:24:21 2023, Load Address: 0x00008000, Entry Point: 0x00008000, Header CRC: 0x0B226765, Data CRC: 0xCC25DC28
openwrt-22.03.3-mvebu-cortexa9-buffalo_ls220d-squashfs-sysupgrade.bin: POSIX tar archive (GNU)
Untaring squashfs, I got:

-rw-r--r-- 1 w w       32 Jan  2 21:24 CONTROL
-rw-r--r-- 1 w w 33554432 Jan  2 21:24 kernel
-rw-r--r-- 1 w w  3567616 Jan  2 21:24 root

Kernel file looks to be a reunion of a "fake initrd", followed by "uImage" with a A LOT of space at the end (FF) -- saw in Hex Workshop.

root: Squashfs filesystem, little endian, version 4.0, xz compressed, 3567198 bytes, 1106 inodes, blocksize: 262144 bytes, created: Tue Jan  3 00:24:21 2023
kernel: Linux jffs2 filesystem data little endian

"fake initrd" (is he what is saying, the beginning of filefrom Hex Workshop), almost 80/90% of the "file" (first part of kernel file) empty too:
....6.....U.....................R..g.6.initrd.buffalo......D...mX..................................................&y/..N-.'..V...Tc.u.............o..r....fake initrd......... [...]

Mounting root:

drwxr-xr-x  2 root root 778 Jan  2 21:24 bin
drwxr-xr-x  2 root root  30 Jan  2 21:24 dev
drwxr-xr-x 23 root root 985 Jan  2 21:24 etc
-rwxr-xr-x  1 root root 276 Jan  2 21:24 init
drwxr-xr-x 11 root root 538 Jan  2 21:24 lib
drwxr-xr-x  2 root root   3 Jan  2 21:24 mnt
drwxr-xr-x  2 root root   3 Jan  2 21:24 overlay
drwxr-xr-x  2 root root   3 Jan  2 21:24 proc
drwxr-xr-x  2 root root  27 Jan  2 21:24 rom
drwxr-xr-x  2 root root   3 Jan  2 21:24 root
drwxr-xr-x  2 root root 891 Jan  2 21:24 sbin
drwxr-xr-x  2 root root   3 Jan  2 21:24 sys
drwxrwxrwt  2 root root   3 Jan  2 21:24 tmp
drwxr-xr-x  7 root root  89 Jan  2 21:24 usr
lrwxrwxrwx  1 root root   3 Jan  2 21:24 var -> tmp
drwxr-xr-x  2 root root   3 Jan  2 21:24 www

I'm unable to mount kernel because the lack of jffs2 support on WSL.

Interestingly, the kernel (removing the FF's at the end) and root files together have a little more size than the initram. SEVERAL BIG blocks of kernel corresponds to initram blocks -- but no block from root corresponds to nothing on initram. The "end" (before the FF's) of the kernel is the same of the initram (opened on Hex Workshop):

[...]
gpio.default-state.linux,code.gpio-fan,speed-map.alarm-gpios

So I'm guessing the initram has the bootloader, some binaries, and the kernel after it.

Right now I'm recompiling, with the other 4 feeds (luci, packages, routing, telephony) marked down in menuconfig to builtin in kernel. Unmarked unwanted bin generations to speed up (squashfs, toolchain, etc).

Seems that I'll need to manually opkg what I want to incorporate the packages or something (there's no luci pkg on [https://downloads.openwrt.org/snapshots/targets/mvebu/cortexa9/packages/] i.e.). Any hint?

I think the next objectives are:

  1. Incorporate the "rest" of luci, like webui and all the rest -- could be inside or outside initram (Buffalo hdrootfs style), but I have no idea in how to achieve that;
  2. Make postinstalled pkgs, kmods, and configs persistent, updateable -- again inside or outside initram.

I think i'll try split kernel file from squashfs into initrd and uImage, letting root file together in / NAS dir, just to see what happens. :grimacing: :grimacing: :grimacing:

And if we be able to tell to sysupgrade cmd to make the job on /boot (/dev/sd[ab]1) or smth, instead /mtd2 (NAND)?

Grossly talking, sounds like a "compiling profile" (initram ads bootloader and vram mounting, squashfs is persistent, etc), but my ignorance preventes me from understanding well.

The problem was trying to write squashfs to NAND -- SPI bootloader protecting, maybe? --, bricked it. Redirecting to /boot default Buffalo partition may work.
Can you help me on that?

About initram being mounted as "ro ram", I found some topics, but already burned all my free time, won't be able to follow up all quickly.
[Modify final initramfs image? - #8 by pwned]
[Settings are not saved after reboot]

You only need to work on the kernel partition. Once you copied the kernel into its ubifs then you're done. The bootloader will execute the Openwrt kernel and then it will mount our rootfs. Then you need to create an ubi partition with both the kernel and a fake initrd ramdisk (the buffalo one also works).

To achieve this we may need to modify the sysupgrade script, example: ipq40xx: add support for MikroTik hAP ac3

Are you able mount the kernel OEM partition?

block info
mount -t ubifs /dev/ubi0_X /mnt

If you already used sysupgrade you won't be able to do it. But then you could format this partition in ubifs manually from Openwrt using nand utils (with the kernel-initramfs openwrt firmware), and then copy our kernel there after mounting the partition.

1 Like

Mocking the start of kernel file inside squashfs binary as initrd, and the rest as uImage didn't worked. Using only the rest (except the FF's) as uImage, didn't worked too.
That portion of kernel file has less than 4mb, size what you seemed to expect on initram binary. Looks very similar as the initram, same start and ending, but smaller.

So, only initram is able to "mock" or whatever the SPI bootloader and the stock initrd (when present).

Sysupg bricks my LS220, can do tests only on openwrt-initram or buffalo stock shell.

On initram or Buffalo stock shell:

root@OpenWrt:~# block info
-ash: block: not found

The kernel of initram isn't sufficient to be mounted? It's bigger than the kernel de facto of squashfs binary.

I'm not visualizing completely your solution yet, need to read more.

But the good thing is that initram is completely functional, just has a lot of missing packages, and doesn't save changes. Firmwares had been built with less, LMAO.

LK

I compiled a firmware with the kernel partition ubinized. Not sure if the linkstation uboot will recognize it: openwrt-ls220de-test.zip
Can you test it?

I used the previous mikrotik example to flash this partition at the sysupgrade script.

Current patch:

diff --git a/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network b/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network
index c613a3cd60..d2229fe6bf 100644
--- a/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network
+++ b/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network
@@ -61,6 +61,7 @@ mvebu_setup_macs()
 	local label_mac=""
 
 	case "$board" in
+	buffalo,ls220de|\
 	buffalo,ls421de)
 		lan_mac=$(mtd_get_mac_ascii u-boot-env eth1addr)
 		;;
diff --git a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh
index 18b978d437..40ef65f169 100755
--- a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh
+++ b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh
@@ -23,8 +23,28 @@ platform_check_image() {
 	esac
 }
 
+platform_do_upgrade_buffalo_nand() {
+	CI_KERNPART=none
+
+	local fw_mtd=$(find_mtd_part kernel)
+	fw_mtd="${fw_mtd/block/}"
+	[ -n "$fw_mtd" ] || return
+
+	local board_dir=$(tar tf "$1" | grep -m 1 '^sysupgrade-.*/$')
+	board_dir=${board_dir%/}
+	[ -n "$board_dir" ] || return
+
+	mtd erase kernel
+	tar xf "$1" ${board_dir}/kernel -O | nandwrite -o "$fw_mtd" -
+
+	nand_do_upgrade "$1"
+}
+
 platform_do_upgrade() {
 	case "$(board_name)" in
+	buffalo,ls220de)
+		platform_do_upgrade_buffalo_nand "$1"
+		;;
 	buffalo,ls421de)
 		nand_do_upgrade "$1"
 		;;
diff --git a/target/linux/mvebu/files/arch/arm/boot/dts/armada-370-buffalo-ls220de.dts b/target/linux/mvebu/files/arch/arm/boot/dts/armada-370-buffalo-ls220de.dts
new file mode 100644
index 0000000000..fe656f388d
--- /dev/null
+++ b/target/linux/mvebu/files/arch/arm/boot/dts/armada-370-buffalo-ls220de.dts
@@ -0,0 +1,390 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Device Tree file for Buffalo LinkStation LS220DE
+ *
+ * Copyright (C) 2020 Daniel González Cabanelas <dgcbueu@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "armada-370.dtsi"
+#include "mvebu-linkstation-fan.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/thermal/thermal.h>
+
+/ {
+	model = "Buffalo LinkStation LS220DE";
+	compatible = "buffalo,ls220de", "marvell,armada370", "marvell,armada-370-xp";
+
+	aliases {
+		led-boot = &led_boot;
+		led-failsafe = &led_failsafe;
+		led-running = &led_power;
+		led-upgrade = &led_upgrade;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+		append-rootblock = "nullparameter="; /* override the bootloader args */
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>; /* 256 MB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xd0000000 0x100000
+			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000
+			  MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>;
+	};
+
+	system_fan: gpio_fan {
+		gpios = <&gpio0 13 GPIO_ACTIVE_HIGH
+			 &gpio0 14 GPIO_ACTIVE_HIGH>;
+		alarm-gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
+
+		#cooling-cells = <2>;
+	};
+
+	thermal-zones {
+		hdd-thermal {
+			polling-delay = <20000>;
+			polling-delay-passive = <2000>;
+
+			thermal-sensors = <&hdd0_temp>; /* only one drivetemp sensor is supported */
+
+			trips {
+				hdd_alert1: trip1 {
+					temperature = <36000>;
+					hysteresis = <2000>;
+					type = "active";
+				};
+				hdd_alert2: trip2 {
+					temperature = <44000>;
+					hysteresis = <2000>;
+					type = "active";
+				};
+				hdd_alert3: trip3 {
+					temperature = <52000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				hdd_crit: trip4 {
+					temperature = <60000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map1 {
+					trip = <&hdd_alert1>;
+					cooling-device = <&system_fan THERMAL_NO_LIMIT 1>;
+				};
+				map2 {
+					trip = <&hdd_alert2>;
+					cooling-device = <&system_fan 2 2>;
+				};
+				map3 {
+					trip = <&hdd_alert3>;
+					cooling-device = <&system_fan 3 THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		ethphy-thermal {
+			polling-delay = <20000>;
+			polling-delay-passive = <2000>;
+
+			thermal-sensors = <&ethphy0>;
+
+			trips {
+				ethphy_alert1: trip1 {
+					temperature = <65000>;
+					hysteresis = <4000>;
+					type = "passive";
+				};
+
+				ethphy_crit: trip2 {
+					temperature = <100000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map1 {
+					trip = <&ethphy_alert1>;
+					cooling-device = <&system_fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-0 = <&pmx_buttons>;
+		pinctrl-names = "default";
+
+		power {
+			label = "Power Switch";
+			linux,code = <KEY_POWER>;
+			linux,input-type = <EV_SW>;
+			gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
+		};
+
+		function {
+			label = "Function Button";
+			linux,code = <KEY_CONFIG>;
+			gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio_leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmx_leds1 &pmx_leds2>;
+
+		system_red {
+			label = "ls421de:red:system";
+			gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+		};
+
+		led_power: power_white {
+			label = "ls421de:white:power";
+			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+
+		led_failsafe: power_red {
+			label = "ls421de:red:power";
+			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+		};
+
+		led_upgrade: power_orange {
+			label = "ls421de:orange:power";
+			gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>;
+		};
+
+		led_boot: system_white {
+			label = "ls421de:white:system";
+			gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+		};
+
+		hdd1_red {
+			label = "ls421de:red:hdd1";
+			gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "ata1";
+		};
+
+		hdd2_red {
+			label = "ls421de:red:hdd2";
+			gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "ata2";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_power_hdd1 &pmx_power_hdd2>;
+		pinctrl-names = "default";
+
+		sata1_power: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "HDD1";
+			regulator-min-microvolt = <12000000>;
+			regulator-max-microvolt = <12000000>;
+			startup-delay-us = <2000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio0 8 GPIO_ACTIVE_HIGH>;
+		};
+
+		sata2_power: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "HDD2";
+			regulator-min-microvolt = <12000000>;
+			regulator-max-microvolt = <12000000>;
+			startup-delay-us = <4000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio0 2 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&coherencyfab {
+	broken-idle;
+};
+
+&eth1 {
+	pinctrl-0 = <&ge1_rgmii_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+	phy-handle = <&ethphy0>;
+	phy-connection-type = "rgmii-id";
+};
+
+&mdio {
+	pinctrl-0 = <&mdio_pins>;
+	pinctrl-names = "default";
+
+	ethphy0: ethernet-phy@0 { /* Marvell 88E1518 */
+		reg = <0>;
+		marvell,reg-init = <0x2 0x10 0xffff 0x0006>, /* disable CLK125 */
+				   <0x3 0x10 0x0000 0x1991>, /* LED function */
+				   <0x3 0x11 0x0000 0x4401>, /* LED polarity */
+				   <0x3 0x12 0x0000 0x4905>; /* LED timer */
+		#thermal-sensor-cells = <0>;
+	};
+};
+
+&pmsu {
+	pinctrl-0 = <&pmx_power_cpu>;
+	pinctrl-names = "default";
+};
+
+&sata {
+	nr-ports = <2>;
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	hdd0_temp: sata-port@0 {
+		reg = <0>;
+		#thermal-sensor-cells = <0>;
+	};
+
+	hdd1_temp: sata-port@1 {
+		reg = <1>;
+		#thermal-sensor-cells = <0>;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&nand_controller {
+	status = "okay";
+
+	nand@0 {
+		reg = <0>;
+		label = "pxa3xx_nand-0";
+		nand-rb = <0>;
+		marvell,nand-keep-config;
+		nand-on-flash-bbt;
+		nand-ecc-strength = <4>;
+		nand-ecc-step-size = <512>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "kernel";
+				reg = <0x00000000 0x02000000>;  /* 32 MiB */
+			};
+
+			partition@2000000 {
+				label = "ubi";
+				reg = <0x02000000 0x1e000000>;  /* 480 MiB */
+			};
+		};
+	};
+};
+
+&spi0 {
+	status = "okay";
+	pinctrl-0 = <&spi0_pins2>;
+	pinctrl-names = "default";
+
+	spi-flash@0 {
+		compatible = "mxicy,mx25l8005", "jedec,spi-nor";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <50000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				reg = <0x00000 0xf0000>; /* 960 KiB*/
+				label = "u-boot";
+				read-only;
+			};
+			partition@f0000 {
+				reg = <0xf0000 0x10000>; /* 64 KiB */
+				label = "u-boot-env";
+			};
+		};
+	};
+};
+
+&pinctrl {
+	pmx_power_cpu: pmx-power-cpu {
+		marvell,pins = "mpp4";
+		marvell,function = "vdd";
+	};
+
+	pmx_power_hdd1: pmx-power-hdd1 {
+		marvell,pins = "mpp8";
+		marvell,function = "gpio";
+	};
+
+	pmx_power_hdd2: pmx-power-hdd2 {
+		marvell,pins = "mpp2";
+		marvell,function = "gpo";
+	};
+
+	pmx_fan_lock: pmx-fan-lock {
+		marvell,pins = "mpp10";
+		marvell,function = "gpio";
+	};
+
+	pmx_hdd_present: pmx-hdd-present {
+		marvell,pins = "mpp11", "mpp12";
+		marvell,function = "gpio";
+	};
+
+	pmx_fan_high: pmx-fan-high {
+		marvell,pins = "mpp13";
+		marvell,function = "gpio";
+	};
+
+	pmx_fan_low: pmx-fan-low {
+		marvell,pins = "mpp14";
+		marvell,function = "gpio";
+	};
+
+	pmx_buttons: pmx-buttons {
+		marvell,pins = "mpp15", "mpp16";
+		marvell,function = "gpio";
+	};
+
+	pmx_leds1: pmx-leds {
+		marvell,pins = "mpp7", "mpp54", "mpp59", "mpp61";
+		marvell,function = "gpo";
+	};
+
+	pmx_leds2: pmx-leds {
+		marvell,pins = "mpp55", "mpp57", "mpp62";
+		marvell,function = "gpio";
+	};
+};
diff --git a/target/linux/mvebu/image/Makefile b/target/linux/mvebu/image/Makefile
index 44e66a5f87..fdac4d218c 100644
--- a/target/linux/mvebu/image/Makefile
+++ b/target/linux/mvebu/image/Makefile
@@ -51,6 +51,19 @@ define Build/buffalo-kernel-jffs2
 	rm -rf $(KDIR)/kernel_jffs2 $@.fakerd
 endef
 
+define Build/buffalo-kernel-ubifs
+	rm -rf $(KDIR)/kernel_ubifs $@.fakerd
+	mkdir -p $(KDIR)/kernel_ubifs
+	dd if=/dev/zero of=$@.fakerd bs=131008 count=1 conv=sync
+	$(STAGING_DIR_HOST)/bin/mkimage \
+		-T ramdisk -A $(LINUX_KARCH) -O linux -C gzip -n 'fake initrd' \
+		-d $@.fakerd $(KDIR)/kernel_ubifs/initrd.buffalo
+	cp $@ $(KDIR)/kernel_ubifs/uImage.buffalo
+	$(STAGING_DIR_HOST)/bin/mkfs.ubifs \
+		$(KERNEL_UBIFS_OPTS) \
+		-r $(KDIR)/kernel_ubifs $@
+	rm -rf $(KDIR)/kernel_ubifs $@.fakerd
+endef
 # Some info about Ctera firmware:
 # 1. It's simple tar file (GNU standard), but it must have ".firm" suffix.
 # 2. It contains two images: kernel and romdisk. Both are required.
diff --git a/target/linux/mvebu/image/cortexa9.mk b/target/linux/mvebu/image/cortexa9.mk
index 6715a41c9e..d3378e0f8f 100644
--- a/target/linux/mvebu/image/cortexa9.mk
+++ b/target/linux/mvebu/image/cortexa9.mk
@@ -14,6 +14,24 @@ define Device/kernel-size-migration
 	Upgrade via sysupgrade mechanism is not possible, so new installation via factory style image is required.
 endef
 
+define Device/buffalo_ls220de
+  $(Device/NAND-128K)
+  DEVICE_VENDOR := Buffalo
+  DEVICE_MODEL := LinkStation LS220DE
+  SUBPAGESIZE :=
+  KERNEL_UBIFS_OPTS = -m $$(PAGESIZE) -e 124KiB -c $$(PAGESIZE) -x none
+  KERNEL_SIZE := 33554432
+  FILESYSTEMS := squashfs ubifs
+  KERNEL := kernel-bin | append-dtb | uImage none | buffalo-kernel-ubifs | ubinize-kernel
+  KERNEL_INITRAMFS := kernel-bin | append-dtb | uImage none
+  DEVICE_DTS := armada-370-buffalo-ls220de
+  DEVICE_PACKAGES :=  \
+    kmod-hwmon-gpiofan kmod-hwmon-drivetemp kmod-linkstation-poweroff \
+    kmod-md-raid0 kmod-md-raid1 kmod-md-mod \
+    kmod-fs-xfs mkf2fs e2fsprogs partx-utils
+endef
+TARGET_DEVICES += buffalo_ls220de
+
 define Device/buffalo_ls421de
   $(Device/NAND-128K)
   DEVICE_VENDOR := Buffalo

I prefer to use the ls220de name because it seems only units selled as "enclosure only" have a NAND chip.

1 Like

Initram working as usual, sysupg does something, but after reboot returns to initram -- I'm not moving anymore the stock bkp to uImage.buffalo.

Indeed, sounds you couldn't be more right.

Correcting myself, I didn't read the commit at that time, so was in my mind that would be a hdd sysupg. But looking your commit, it's a NAND one, right?
Indeed, NAND got corrupted again, same error 7. I'm restoring stock NAND now to serve as a reference if you want to attempt another NAND try.

I restarted compiling from scratch, and now I'm selecting all needed for "full run" (without latter opkg installs) in make menuconfig. If works as intended, I'll study the "img config -> init config opts" on menuconfig, maybe there I could point to initram load configs from a partition, and save them every 5min in this loaded savefile, i.e.
Well, it's the only approach I can visualize with my knowledge, lol. And openwrt cfg-saves works pretty well.

LK

"Pimped" initram got almost 60 MB, lol.
Didn't booted, seems that initrd skipped it and used stock bkp uImage from flash.

I will do further reading about size limitations of Buffalo boot, splitting or smth...

Btw, another approach idea:
What about "Compile kernel with rootfs on NFS" on Global build settings -> Kernel build options in make menuconfig?
Viable to an initram have ability to start nfsd, mount raid1, and them boot a full kernel, apps, in a persistent partition?

I compiled again the firmware. The ubinized kernel should be ok this time. Also it turned out that nand-utils were missing from the default configuration.

openwrt-ls220de-test.zip

Use the kernel initram for booting Openwrt and then perform a sysupgrade. Don't forget to remove the hard drive after the installation. I still didn't include Luci web interface.

1 Like

Did a quick test, and booting from NAND is working, sir! :partying_face: :partying_face: :partying_face:
[KNOW BUG: after a soft power-off (button in the back panel), switching it again to the "on" position results on nothing -- DC needs to be removed and replugged.]

But the doubt remains: powering off, and connecting the hd, I'm booting NAND or hdd initram? How to know?
Sounds hdd, not so fast, and spinning.
It'll be able to boot as itself, without removing hdd's, after a power loss?

Compiling, did you had to remove kmod-hwmon-gpiofan to work? Also, I had to use localhost llvm, dunno if it's a bug only here on Debian WSL -- tell me.

Please send me your .config :crazy_face:

Don't forget your towel! -- Towelie
Indeed, on first ubinezed, I didn't did that -- worth the try (nand-utils missing), or not?
I realized that the NAND write this time took the double of seconds to write, like 10.

LK

You should use a blank, formatted hard drive once Openwrt is installed on the Linkstation. Keep apart the hard drive you used for the installation for recovering purposes.

The formatted hard drive used with the fresh Openwrt installed at the nand should meet some requeriments, see:

Didn't the FAN work ok?, it's inlcuded in my build.
I'm still making some cleanup, then I'll post patches. About the .config, I used the default, I just included nand-utils.

Mi intention is to send patches to Openwrt dev for adding official support for this unit.

1 Like

Spins, but very quietly -- stock boot puts the boy to shout out. Case got a bit hot, but I didn't letted too much to see if it would throttle to cold the casing.

Completely forgot that install step of hdd. I do those hobby things on free time, so, drunk, and is in "post installation" section (it's mid installation for an autist).

To be honest, I don't see why it can't have retrocompatibility.
See:

  1. Existing Buffalo users just wanna to change firmware, keeping the retrocompat, in a quick and easy way;
  2. We can adapt too where the NAND image will install on hdd's/array (like NAND installscript you changed), don't? Maybe adding partitions section on hdd0 and hdd1 labels of .dts, also?
  3. The default partition table I already posted (quoted below), it's the reference;
  4. /dev/sd[ab]6 seems perfect for the job, but eventually could have conflicts with existing folders (installer should not expect a blank drive) -- /dev/sd[ab]6/openwrt would be even better as /, and /dev/sd[ab]6 could be mounted as /shares folder -- dunno if is possible that cross-reference, saw some /overlay mounts of stock Buffalo fw that raised my attention, incoherent like that;
  5. If is possible to do that cross-references, would be even better install on /dev/sd[ab]1/openwrt;
  6. A change on the behavior of the "reset" button in back panel would be needed too, like "normal boot -> /dev/sd[ab]6", "stock boot (holding reset for 2seg when power up) -> /dev/sd[ab]1 (/boot, if uImage.buffalo is the initram, will boot it), and "reset (holding reset for 10+seg anytime) -> resetting openwrt cfgs to default" -- probably more than a .dts editing;
  7. I'm thinking about raid1 arrays, not single hdd's, to make even friendly to the end user -- install and run, openwrt way, without much manual script duties... I.e., at boot, NAND ?squashfs? looks for default partitioning pattern (below) of ls220, if found will mount the arrays, install on md10 (or in a new md, if subfolder scheme is a good idea), and point boot to there.

The only variable size partition is the last.

Said that, if is a good way to proceed, I propose:

  1. Make ?squashfs? NAND looks for /dev/sda6, install openwrt on it, and boot there when powered up;
  2. Working the previous, try to make now work on the raid1 scheme: if sdb is also detected, make the mounts/associations (md0, md1, md2, md10, mdxx), installing on mdXX and pointing boot there -- with the failsafe to boot to sda6 on sdb absence;
  3. Working the above, we can try to mess with reset button behavior.

Good idea, bad idea? What path we'll proceed?

Btw, I guess NAND ?squashfs? just ignored the raid array... data untouched, no install attempted from openwrt.

So, I restored stock uImage.buffalo to see if I was booting on initram or squashfs, and returned to stock OS. I'm rewriting stock NAND, to it's stock fw serve again as a reference of what's going on.

LK

It would be nice to just install OpenWrt, and previous HDDs partitioning were recognized. Probably this should be done with an specific script for these devices. Since I'm not sure how Buffallo's OS mounts this md stuff, I prefer to not deal with it.

However you can still use your HDDs with the data from the buffalo OS:

  1. To avoid loading the OS from HDDs you need to delete or rename the files uImage.buffalo and initrd.buffalo. This way it will load Openwrt from NAND
  2. Now you need to deal manually with md to replicate what the Buffalo OS had configured with the arrays. Add partitions to fstab, etc.

As I said previously if a NAND is present it should be used for installing OpenWrt. It has its advantages like running the device without Sata HDDs. Or spinning down the HDD, since the OS won't be stored on it, and therefore extending its life.

BTW another version of images of OpenWrt for NANDless units would also be nice. For now I let others to make this job.

1 Like

I'm up to do that. The Buffalo scripts are all on its images, and in hdd also, I can analyze it.
But where to change in OpenWrt install is my weak point. No idea where to start. Will search some docs about how to customize OpenWrt install. If you already know some link, I'll appreciate. I'm posting some below, very clarifying.

I got confused with your statement:

I confirmed that NAND has the "fullsys" as expected:

/dev/ubi0_1 on /overlay type ubifs (rw,noatime,assert=read-only,ubi=0,vol=1)
overlayfs:/overlay on / type overlay (rw,noatime,lowerdir=/,upperdir=/overlay/upper,workdir=/overlay/work)

My doubt is, why are we worried about hdd install?
There's no trace of Buffalo stuff on nand, but spi remains untouched. Is it forcing hdd to boot if present?
If yes, better don't touch that spi. Then, renaming initrd and uImage would be the best workaround, as you suggested -- is fully working.

I didn't found nothing in any of links below about the installed system in nand try to copy itself to hdd or something. This really occurs on LS421DE? It's a init script? I didn't found nothing in target\linux\mvebu\cortexa9\base-files\etc\hotplug.d or init.d .
Assuming that, it's a normal behavior not trying to install something on hdd. No "mixed mode" install/boot or duplicated files (both in nand and hdd).

I see two good pathways here:

  1. You already achieve that, making OpenWrt works completely from NAND. For retrocompatibility, user just needs to rename initrd.buffalo and uImage.buffalo (and rename again in openwrt shell if wanna take a walk on stock fw);
  2. The "sdcard" approach, for all devices, including NANDless ones. Like you, I'm not headlining that, but I'll study about it. In this concept, NAND (for who haves) remains with recovery Buffalo stuff, and OpenWrt is installed on hdd (somehow¹) like as in a sdcard install.
  3. For hardcore users what desires to mess with the SPI (note that I'm assuming the SPI is who redirect the boot to hdd), and want to make a "roots" sdcard true install, the usb2 port of LS's devices could be used for this. I guess that would be a good suggestion of path to follow for who headline this, and will work flawlessly. Also, I guess I already saw another NAS'es (LS-WXL or smth) in this scheme, running Openwrt.
  4. In both cases 2 and 3, the only point is the "superblock" mentioned in docs, what OpenWrt searches for boot. If it could be the same superblock of stock boot (/dev/sd[ab]1), retrocompatibility would be l33t.

¹Seems that "mount --bind" and friends would do that "cross-reference" I was talking about. Mount /dev/sd[ab]1 on /boot, like normal Buffalo behavior, and /boot/openwrt on /, binding. Since OpenWrt doesn't have "/boot" in root tree, no conflicts.
[https://www.baeldung.com/linux/bind-mounts]

#random interesting server found
https://sysupgrade.openwrt.org/

@danitool, it's too much ask you a last compile, with luci webgui? Then I mark it as the solution, to ppl use until the device gets official support.

Also, based on this [https://github.com/openwrt/openwrt/commit/4f8da19572cf1adc480dca42251a4cded0cb3c7c], maybe you want to make a LS220DE commit too.

And fan is spinning a bit louder now (stressed the hd to heat and test), cooling adequately the case.
Also, after renaming initrd.buffalo and uImage.buffalo, I got a clean NAND boot with both hdd's in trays -- and fully working, saving and maintaining the configs! :smiley:

Tnx again.

LK

###links to study about
Boot:

System bootup is as follows: →[process.boot](https://openwrt.org/docs/techref/process.boot)
1. kernel boots from a known raw partition (without a FS), scans mtd partition *rootfs* for a valid superblock and mounts the SquashFS partition (containing `/etc`) then runs `/etc/preinit`. (More info at [technical.details](https://openwrt.org/docs/techref/filesystems#technicaldetails))
2. `/etc/preinit` runs `/sbin/mount_root`
3. `mount_root` mounts the JFFS2 partition (`/overlay`) and **combines** it with the SquashFS partition (`/rom`) to create a new *virtual root filesystem* (`/`)
4. bootup continues with `/sbin/init`
`/overlay` was previously named `/jffs2`

Same link, #technical_details:
Either way, if there is a partition named 'rootfs' and 'MTD_ROOTFS_ROOT_DEV' kernel config option is set to 'yes' , this partition is automatically used for the root filesystem.

Preinit mount and customization:

Boot parameters:

Configs intended to edit "on hand":

Sysupg steps:

Beautiful, isn't?
I opkg'ed "luci".
Collected some errors:

Collected errors:
 * pkg_hash_check_unresolved: cannot find dependency kernel (= 5.10.165-1-46436c764fec233a76595c80b0d7d5ab) for kmod-nf-ipt
 * pkg_hash_fetch_best_installation_candidate: Packages for kmod-nf-ipt found, but incompatible with the architectures configured
 * pkg_hash_check_unresolved: cannot find dependency kernel (= 5.10.165-1-46436c764fec233a76595c80b0d7d5ab) for kmod-ipt-core
 * pkg_hash_fetch_best_installation_candidate: Packages for kmod-ipt-core found, but incompatible with the architectures configured
 * pkg_hash_check_unresolved: cannot find dependency kernel (= 5.10.165-1-46436c764fec233a76595c80b0d7d5ab) for kmod-ipt-conntrack
 * pkg_hash_fetch_best_installation_candidate: Packages for kmod-ipt-conntrack found, but incompatible with the architectures configured
 * pkg_hash_check_unresolved: cannot find dependency kernel (= 5.10.165-1-46436c764fec233a76595c80b0d7d5ab) for kmod-ipt-nat
 * pkg_hash_fetch_best_installation_candidate: Packages for kmod-ipt-nat found, but incompatible with the architectures configured

Will search l8r where to submit a bug report. On Git website, I guess. Those pkgs was server-autogenerated, right?

Anyway, if possible to generate the initram and sysupg with luci already incorporated, I thank, to mark it solved.

LK

Collected errors:
 * pkg_hash_check_unresolved: cannot find dependency kernel (= 5.10.165-1-46436c764fec233a76595c80b0d7d5ab) for kmod-md-raid10
 * pkg_hash_fetch_best_installation_candidate: Packages for kmod-md-raid10 found, but incompatible with the architectures configured
 * satisfy_dependencies_for: Cannot satisfy the following dependencies for mdadm:
 * 	kernel (= 5.10.165-1-46436c764fec233a76595c80b0d7d5ab)
 * opkg_install_cmd: Cannot install package mdadm.

:confounded: :confounded: :confounded:
Critical.

[Updated: KNOW ISSUE: fan subsystem seems to only fetch thermal data at boot.]

My NAS reached like 50ºC, and checking the fan, was static. Rebooted, got full throttle, and maintained it all-time even after case got cooled.

Looks like a missing timer, what eventually can be added "on hand" in init.d with cron or smth. I didn't found any hw tools, like sensors, hddtemp -- I was only able to cat and hexdump some thermal device files.

The SPI flash chip is never touched by Openwrt. Furthermore the u-boot environment configuration is mostly embedded in the bootloader itself, it cannot be modified. Only a couple of parameters can be changed, like the MAC address. Therefore the behavior will allways be the same, with or without Openwrt installed

  1. Once UBoot is loaded it tries to load the kernel and initram uimages from HDD
  2. If none was found, then it tries to load them from the NAND flash
  3. If the NAND kernel partition got corrupted, or no kernel and initram found, then it stops.

The FAN is fully controlled by the kernel. No scripts here. It uses "thermal zones", you can see them at the dts file. If it didn't work then the gpio pinmux might be incorrect defined. One problem with thermal zones is than only one temperature sensor can be read from hardrives (the first it found). Or maybe the ethernet sensor temperature is interfering and takes priority over HDD sensors, slowing down arbitrary the FAN.

I'll compile again the firmware, this time with Luci, with the poweroff driver fixed, and without the ethernet thermal zone.

1 Like

If you don't mind, mdadm for a NAS device would be l33t, too. Eventually samba4 and samba4-luci.

I can try to debug the kernel run/running, if told how to.

I compiled again the firmware: openwrt-ls220de-test.zip

Parts to check:

  • FAN cooler
  • poweroff and restart.
  • ethernet LED: should blink on activity, and should be on when the ethernet cable is connected

I also included devmem. Since your ethernet phy is only 1.8V capable, you should adjust the voltage with the command:

devmem 0xd00184e0 32 0xa8a

devmem can't be installed with the default Openwrt fimware, therefore for a permanent solution an Uboot modification should be done. Before using this command Double check your ethernet phy is indeed a Marvell 88E1318

I'm still looking for a way to simplify a bit more the sysupgrade process without nand-utils. I'll check if nandwrite can be replaced with mtd write. Even with mtd erase looks like the NAND isn't erased as it should.

The current patch:

diff --git a/package/boot/uboot-envtools/files/mvebu b/package/boot/uboot-envtools/files/mvebu
index cffd396ae1..e07e797858 100644
--- a/package/boot/uboot-envtools/files/mvebu
+++ b/package/boot/uboot-envtools/files/mvebu
@@ -13,6 +13,7 @@ touch /etc/config/ubootenv
 board=$(board_name)
 
 case "$board" in
+buffalo,ls220de|\
 buffalo,ls421de)
 	ubootenv_add_uci_config "/dev/mtd3" "0x0" "0x10000"
 	;;
diff --git a/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network b/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network
index c613a3cd60..d2229fe6bf 100644
--- a/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network
+++ b/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network
@@ -61,6 +61,7 @@ mvebu_setup_macs()
 	local label_mac=""
 
 	case "$board" in
+	buffalo,ls220de|\
 	buffalo,ls421de)
 		lan_mac=$(mtd_get_mac_ascii u-boot-env eth1addr)
 		;;
diff --git a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh
index 18b978d437..b879296e3b 100755
--- a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh
+++ b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh
@@ -23,8 +23,29 @@ platform_check_image() {
 	esac
 }
 
+platform_do_upgrade_buffalo_nand() {
+	CI_KERNPART=none
+
+	local fw_mtd=$(find_mtd_part kernel)
+	fw_mtd="${fw_mtd/block/}"
+	[ -n "$fw_mtd" ] || return
+
+	local board_dir=$(tar tf "$1" | grep -m 1 '^sysupgrade-.*/$')
+	board_dir=${board_dir%/}
+	[ -n "$board_dir" ] || return
+
+	mtd erase kernel
+	tar xf "$1" ${board_dir}/kernel
+	nandwrite "$fw_mtd" ${board_dir}/kernel
+
+	nand_do_upgrade "$1"
+}
+
 platform_do_upgrade() {
 	case "$(board_name)" in
+	buffalo,ls220de)
+		platform_do_upgrade_buffalo_nand "$1"
+		;;
 	buffalo,ls421de)
 		nand_do_upgrade "$1"
 		;;
diff --git a/target/linux/mvebu/files/arch/arm/boot/dts/armada-370-buffalo-ls220de.dts b/target/linux/mvebu/files/arch/arm/boot/dts/armada-370-buffalo-ls220de.dts
new file mode 100644
index 0000000000..d82a3f23bb
--- /dev/null
+++ b/target/linux/mvebu/files/arch/arm/boot/dts/armada-370-buffalo-ls220de.dts
@@ -0,0 +1,361 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Device Tree file for Buffalo LinkStation LS220DE
+ *
+ * Copyright (C) 2020 Daniel González Cabanelas <dgcbueu@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "armada-370.dtsi"
+#include "mvebu-linkstation-fan.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/thermal/thermal.h>
+
+/ {
+	model = "Buffalo LinkStation LS220DE";
+	compatible = "buffalo,ls220de", "marvell,armada370", "marvell,armada-370-xp";
+
+	aliases {
+		led-boot = &led_boot;
+		led-failsafe = &led_failsafe;
+		led-running = &led_power;
+		led-upgrade = &led_upgrade;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+		append-rootblock = "nullparameter="; /* override the bootloader args */
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>; /* 256 MB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xd0000000 0x100000
+			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000
+			  MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>;
+	};
+
+	system_fan: gpio_fan {
+		gpios = <&gpio0 13 GPIO_ACTIVE_HIGH
+			 &gpio0 14 GPIO_ACTIVE_HIGH>;
+		alarm-gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
+
+		#cooling-cells = <2>;
+	};
+
+	thermal-zones {
+		hdd-thermal {
+			polling-delay = <20000>;
+			polling-delay-passive = <2000>;
+
+			thermal-sensors = <&hdd0_temp>; /* only one drivetemp sensor is supported */
+
+			trips {
+				hdd_alert1: trip1 {
+					temperature = <36000>;
+					hysteresis = <2000>;
+					type = "active";
+				};
+				hdd_alert2: trip2 {
+					temperature = <44000>;
+					hysteresis = <2000>;
+					type = "active";
+				};
+				hdd_alert3: trip3 {
+					temperature = <52000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				hdd_crit: trip4 {
+					temperature = <60000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map1 {
+					trip = <&hdd_alert1>;
+					cooling-device = <&system_fan THERMAL_NO_LIMIT 1>;
+				};
+				map2 {
+					trip = <&hdd_alert2>;
+					cooling-device = <&system_fan 2 2>;
+				};
+				map3 {
+					trip = <&hdd_alert3>;
+					cooling-device = <&system_fan 3 THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-0 = <&pmx_buttons>;
+		pinctrl-names = "default";
+
+		power {
+			label = "Power Switch";
+			linux,code = <KEY_POWER>;
+			linux,input-type = <EV_SW>;
+			gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
+		};
+
+		function {
+			label = "Function Button";
+			linux,code = <KEY_CONFIG>;
+			gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio_leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmx_leds1 &pmx_leds2>;
+
+		system_red {
+			label = "ls421de:red:system";
+			gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+		};
+
+		led_power: power_white {
+			label = "ls421de:white:power";
+			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+
+		led_failsafe: power_red {
+			label = "ls421de:red:power";
+			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+		};
+
+		led_upgrade: power_orange {
+			label = "ls421de:orange:power";
+			gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>;
+		};
+
+		led_boot: system_white {
+			label = "ls421de:white:system";
+			gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+		};
+
+		hdd1_red {
+			label = "ls421de:red:hdd1";
+			gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "ata1";
+		};
+
+		hdd2_red {
+			label = "ls421de:red:hdd2";
+			gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "ata2";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_power_hdd1 &pmx_power_hdd2>;
+		pinctrl-names = "default";
+
+		sata1_power: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "HDD1";
+			regulator-min-microvolt = <12000000>;
+			regulator-max-microvolt = <12000000>;
+			startup-delay-us = <2000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio0 8 GPIO_ACTIVE_HIGH>;
+		};
+
+		sata2_power: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "HDD2";
+			regulator-min-microvolt = <12000000>;
+			regulator-max-microvolt = <12000000>;
+			startup-delay-us = <4000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio0 2 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&coherencyfab {
+	broken-idle;
+};
+
+&eth1 {
+	pinctrl-0 = <&ge1_rgmii_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+	phy-handle = <&ethphy0>;
+	phy-connection-type = "rgmii-id";
+};
+
+&mdio {
+	pinctrl-0 = <&mdio_pins>;
+	pinctrl-names = "default";
+
+	ethphy0: ethernet-phy@0 { /* Marvell 88E1318 */
+		reg = <0>;
+		marvell,reg-init = <0x2 0x10 0xffff 0x0006>, /* disable CLK125 */
+				   <0x3 0x10 0xf000 0x0918>, /* LED function */
+				   <0x3 0x11 0x0000 0x4401>, /* LED polarity */
+				   <0x3 0x12 0x0000 0x4905>; /* LED timer */
+		#thermal-sensor-cells = <0>;
+	};
+};
+
+&pmsu {
+	pinctrl-0 = <&pmx_power_cpu>;
+	pinctrl-names = "default";
+};
+
+&sata {
+	nr-ports = <2>;
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	hdd0_temp: sata-port@0 {
+		reg = <0>;
+		#thermal-sensor-cells = <0>;
+	};
+
+	hdd1_temp: sata-port@1 {
+		reg = <1>;
+		#thermal-sensor-cells = <0>;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&nand_controller {
+	status = "okay";
+
+	nand@0 {
+		reg = <0>;
+		label = "pxa3xx_nand-0";
+		nand-rb = <0>;
+		marvell,nand-keep-config;
+		nand-on-flash-bbt;
+		nand-ecc-strength = <4>;
+		nand-ecc-step-size = <512>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "kernel";
+				reg = <0x00000000 0x02000000>;  /* 32 MiB */
+			};
+
+			partition@2000000 {
+				label = "ubi";
+				reg = <0x02000000 0x1e000000>;  /* 480 MiB */
+			};
+		};
+	};
+};
+
+&spi0 {
+	status = "okay";
+	pinctrl-0 = <&spi0_pins2>;
+	pinctrl-names = "default";
+
+	spi-flash@0 {
+		compatible = "mxicy,mx25l8005", "jedec,spi-nor";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <50000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				reg = <0x00000 0xf0000>; /* 960 KiB*/
+				label = "u-boot";
+				read-only;
+			};
+			partition@f0000 {
+				reg = <0xf0000 0x10000>; /* 64 KiB */
+				label = "u-boot-env";
+			};
+		};
+	};
+};
+
+&pinctrl {
+	pmx_power_cpu: pmx-power-cpu {
+		marvell,pins = "mpp4";
+		marvell,function = "vdd";
+	};
+
+	pmx_power_hdd1: pmx-power-hdd1 {
+		marvell,pins = "mpp8";
+		marvell,function = "gpio";
+	};
+
+	pmx_power_hdd2: pmx-power-hdd2 {
+		marvell,pins = "mpp2";
+		marvell,function = "gpo";
+	};
+
+	pmx_fan_lock: pmx-fan-lock {
+		marvell,pins = "mpp10";
+		marvell,function = "gpio";
+	};
+
+	pmx_hdd_present: pmx-hdd-present {
+		marvell,pins = "mpp11", "mpp12";
+		marvell,function = "gpio";
+	};
+
+	pmx_fan_high: pmx-fan-high {
+		marvell,pins = "mpp13";
+		marvell,function = "gpio";
+	};
+
+	pmx_fan_low: pmx-fan-low {
+		marvell,pins = "mpp14";
+		marvell,function = "gpio";
+	};
+
+	pmx_buttons: pmx-buttons {
+		marvell,pins = "mpp15", "mpp16";
+		marvell,function = "gpio";
+	};
+
+	pmx_leds1: pmx-leds {
+		marvell,pins = "mpp7", "mpp54", "mpp59", "mpp61";
+		marvell,function = "gpo";
+	};
+
+	pmx_leds2: pmx-leds {
+		marvell,pins = "mpp55", "mpp57", "mpp62";
+		marvell,function = "gpio";
+	};
+};
diff --git a/target/linux/mvebu/image/Makefile b/target/linux/mvebu/image/Makefile
index 44e66a5f87..a13b61c1eb 100644
--- a/target/linux/mvebu/image/Makefile
+++ b/target/linux/mvebu/image/Makefile
@@ -51,6 +51,20 @@ define Build/buffalo-kernel-jffs2
 	rm -rf $(KDIR)/kernel_jffs2 $@.fakerd
 endef
 
+define Build/buffalo-kernel-ubifs
+	rm -rf $@-ubidir $@.ubi
+	mkdir -p $@-ubidir
+	mv $@ $@-ubidir/uImage.buffalo
+	touch $@
+	$(call Build/append-uImage-fakehdr, ramdisk)
+	mv $@ $@-ubidir/initrd.buffalo
+	$(STAGING_DIR_HOST)/bin/mkfs.ubifs \
+		$(KERNEL_UBIFS_OPTS) -r $@-ubidir $@.ubi
+	sh $(TOPDIR)/scripts/ubinize-image.sh \
+		--part boot=$@.ubi=20 $@ -p $(BLOCKSIZE:%k=%KiB) -m $(PAGESIZE) \
+		-s $(SUBPAGESIZE) -O $(VID_HDR_OFFSET) $(UBINIZE_OPTS)
+endef
+
 # Some info about Ctera firmware:
 # 1. It's simple tar file (GNU standard), but it must have ".firm" suffix.
 # 2. It contains two images: kernel and romdisk. Both are required.
diff --git a/target/linux/mvebu/image/cortexa9.mk b/target/linux/mvebu/image/cortexa9.mk
index 6715a41c9e..1c96ae47d6 100644
--- a/target/linux/mvebu/image/cortexa9.mk
+++ b/target/linux/mvebu/image/cortexa9.mk
@@ -14,14 +14,30 @@ define Device/kernel-size-migration
 	Upgrade via sysupgrade mechanism is not possible, so new installation via factory style image is required.
 endef
 
+define Device/buffalo_ls220de
+  $(Device/NAND-128K)
+  DEVICE_VENDOR := Buffalo
+  DEVICE_MODEL := LinkStation LS220DE
+  KERNEL_UBIFS_OPTS = -m $$(PAGESIZE) -e 124KiB -c $$(PAGESIZE) -x none
+  KERNEL_SIZE := 33554432
+  FILESYSTEMS := squashfs ubifs
+  KERNEL := kernel-bin | append-dtb | uImage none | buffalo-kernel-ubifs
+  KERNEL_INITRAMFS := kernel-bin | append-dtb | uImage none
+  DEVICE_DTS := armada-370-buffalo-ls220de
+  DEVICE_PACKAGES :=  \
+    kmod-hwmon-gpiofan kmod-hwmon-drivetemp kmod-linkstation-poweroff \
+    kmod-md-raid0 kmod-md-raid1 kmod-md-mod \
+    kmod-fs-xfs mkf2fs e2fsprogs partx-utils
+endef
+TARGET_DEVICES += buffalo_ls220de
 define Device/buffalo_ls421de
   $(Device/NAND-128K)
   DEVICE_VENDOR := Buffalo
   DEVICE_MODEL := LinkStation LS421DE
-  SUBPAGESIZE :=
+  KERNEL_UBIFS_OPTS = -m $$(PAGESIZE) -e 124KiB -c $$(PAGESIZE) -x none
   KERNEL_SIZE := 33554432
   FILESYSTEMS := squashfs ubifs
-  KERNEL := kernel-bin | append-dtb | uImage none | buffalo-kernel-jffs2
+  KERNEL := kernel-bin | append-dtb | uImage none | buffalo-kernel-ubifs
   KERNEL_INITRAMFS := kernel-bin | append-dtb | uImage none
   DEVICE_DTS := armada-370-buffalo-ls421de
   DEVICE_PACKAGES :=  \
diff --git a/target/linux/mvebu/patches-5.10/linkstation-poweroff.patch b/target/linux/mvebu/patches-5.10/linkstation-poweroff.patch
new file mode 100644
index 0000000000..e23ba81812
--- /dev/null
+++ b/target/linux/mvebu/patches-5.10/linkstation-poweroff.patch
@@ -0,0 +1,15 @@
+--- a/drivers/power/reset/linkstation-poweroff.c
++++ b/drivers/power/reset/linkstation-poweroff.c
+@@ -86,10 +86,12 @@
+ 
+ 	kernel_restart("Power off");
+ }
+ 
+ static const struct of_device_id ls_poweroff_of_match[] = {
++	{ .compatible = "buffalo,ls220d" },
++	{ .compatible = "buffalo,ls220de" },
+ 	{ .compatible = "buffalo,ls421d" },
+ 	{ .compatible = "buffalo,ls421de" },
+ 	{ },
+ };
+ 

1 Like