This will allow more flexibility in using PHY drivers as kmods.
Signed-off-by: Mantas Pucka <mantas@8devices.com>
Link: https://github.com/openwrt/openwrt/pull/18435
Signed-off-by: Robert Marko <robimarko@gmail.com>
Add support for Maxlinear GPHY module. Also add support for
kmod-polynomial, which is a dependency for this module.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/18435
Signed-off-by: Robert Marko <robimarko@gmail.com>
The IgniteNet SunSpot AC Wave2 uses the standard smem-assigned partition
for its bootloader environment.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
The qcomsmem MTD partition parser converts all partition names to
lower case while the vendor solution uses upper case names, which
often made their way into OpenWrt as labels in 'fixed-partitions'
(probably due to contributors and reviewers being unaware of the
qcomsmem parsers).
Use case-insensitive matching of the 'APPSBLENV' name to make
ubootenv_mtdinfo() work in both cases.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
The IgniteNet SunSpot AC Wave2 comes with 2x QCA9994 ath10k chips
connected to the IPQ8068 SoC via PCIe.
Add board-2.bin for both radios on this board.
3ac4a64 qca9984: add BDFs for IgniteNet SS-W2-AC2600
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Override via RSNE is a relatively new feature, which can be used to enable
WPA3 features in a way that is invisible to older clients.
Use it by default to mask the GCMP-256 cipher from older clients, since
there are compatibility issues with existing devices.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Fixes status information and scanning on extra BSS interfaces when operating
on multi-radio devices.
Reported-by: Chad Monroe <chad.monroe@adtran.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
glibc 2.39 has removed libcrypt completely.
solution: build libxcrypt with glibc compatibility.
Signed-off-by: Konstantin Demin <rockdrilla@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/19160
Signed-off-by: Robert Marko <robimarko@gmail.com>
On commit 3010ab8 ("base-files: add update_alternatives function") was
implemented the function to handle ALTERNATIVES when using APK (OPKG
handle it internally) but in commit bcc6415 ("base-files: add
compatibility for APK and OPKG") was only called when adding a package,
so call it also when removing packages.
While we are here, check for a more specific *.alternatives files instead
of *.list, and remove redundant "filelist" variable definition.
Fixes: bcc6415 ("base-files: add compatibility for APK and OPKG")
Fixes: https://github.com/openwrt/openwrt/issues/19090
Fixes: https://github.com/openwrt/openwrt/issues/16991
Reported-and-tested-by: Eric Fahlgren <ericfahlgren@gmail.com>
Signed-off-by: Mario Andrés Pérez <mapb_@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/19093
Signed-off-by: Robert Marko <robimarko@gmail.com>
9389775ceb47 rpc-sys: update packagelist call to handle apk abiversion tag
ed0d01e4360b file: linkstat to get link stat info
Signed-off-by: Eric Fahlgren <ericfahlgren@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/19211
Signed-off-by: Robert Marko <robimarko@gmail.com>
Add support for Check Point V-81 to add/edit bootcmd variables for
booting OpenWrt.
Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/16904
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Add support for Check Point V-80 to add/edit bootcmd variables for
booting OpenWrt.
Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/16904
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Add support for the tar archive compressed by gzip to emmc_upgrade_tar()
function.
Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/16904
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
1. No need to explicitly call the defaults
2. There is efficient way how to set PKG_BUILD_DIR,
which allows to drop PKG_SOURCE_DIR.
Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/19105
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
In the development history of Intel's drivers, the i40evf driver was later
renamed the iavf driver. For example, some documents mention that
Intel® Network Connections Software Version 24.0 renamed the i40evf
and ixlv drivers to iavf. In subsequent versions, the i40evf driver was
gradually removed, and its functions were taken over by the iavf driver.
In the Linux system, relevant configuration instructions also exist. For
instance, the User Guide for X722 Onboard Network Card states that the
i40evf driver module should be disabled, and the iavf driver should be
installed and used.
blamed commit: 5d81b28a82
Signed-off-by: xiao bo <peterwillcn@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/19197
Signed-off-by: Robert Marko <robimarko@gmail.com>
The stm32-dfsdm-adc module depends on it (kernel 6.12).
Signed-off-by: Thomas Richard <thomas.richard@bootlin.com>
Link: https://github.com/openwrt/openwrt/pull/18740
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
The memory mapped TPM interface (TIS) can be used for
emulated or virtualized TPM instances with QEMU and
a simulation package like swtpm.
On QEMU the device will appear in the device tree
with a "tcg,tpm-tis-mmio" compatible.
For example:
qemu-system-aarch64 -machine virt -cpu max \
-bios u-boot.bin \
-nographic \
.... \
-hda openwrt-armsr-armv8-combined-efi.img \
-chardev socket,id=chrtpm,path=/tmp/mytpm/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis-device,tpmdev=tpm0
Signed-off-by: Mathew McBride <matt@traverse.com.au>
Link: https://github.com/openwrt/openwrt/pull/19188
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This file is a leftover of cns3xxx target which has been dropped
in commit a9790dff53 ("cns3xxx: drop target").
Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/19191
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Ensure that hapd->own_addr is set properly, since hostapd_setup_bss
only handles it for secondary BSS interfaces
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Change deprecated function strlcpy to strscpy
for compatibility with kernel 6.12.
strlcpy() reads the entire source buffer first.
This read may exceed the destination size limit.
This is both inefficient and can lead to linear read
overflows if a source string is not NUL-terminated [1].
In an effort to remove strlcpy() completely [2], replace
strlcpy() here with strscpy().
Direct replacement is safe here since DEV_ASSIGN is only used by
TRACE macros and the return values are ignored.
[1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy
[2] https://github.com/KSPP/linux/issues/89
Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
Link: https://github.com/openwrt/openwrt/pull/18927
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Backport accepted BCM5325 patches from net-next.
These patches will be merged in the v6.17 kernel window.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Glibc since 2.41 tries to include linux/sched/types.h from sched.h, and
pointing KERNEL_INCLUDE to the kernel headers makes it use
linux/sched/types.h from the kernel headers instead of the installed
one.
This then breaks the configure (test) compile for setns() and the test:
mips-openwrt-linux-gnu-gcc -I/fork.openwrt/build_dir/target-mips_24kc_glibc/linux-ath79_generic/linux-6.6.93/include/uapi -o config.HaAJYe/setnstest config.HaAJYe/setnstest.c
In file included from /fork.openwrt/build_dir/target-mips_24kc_glibc/linux-ath79_generic/linux-6.6.93/include/uapi/linux/sched/types.h:5,
from /fork.openwrt/staging_dir/toolchain-mips_24kc_gcc-14.3.0_glibc/include/bits/sched.h:63,
from /fork.openwrt/staging_dir/toolchain-mips_24kc_gcc-14.3.0_glibc/include/sched.h:43,
from config.HaAJYe/setnstest.c:2:
/fork.openwrt/build_dir/target-mips_24kc_glibc/linux-ath79_generic/linux-6.6.93/include/uapi/linux/types.h:10:2: warning: #warning "Attempt to use kernel headers from user space, see https://kernelnewbies.org/KernelHeaders" [-Wcpp]
10 | #warning "Attempt to use kernel headers from user space, see https://kernelnewbies.org/KernelHeaders"
| ^~~~~~~
In file included from /fork.openwrt/build_dir/target-mips_24kc_glibc/linux-ath79_generic/linux-6.6.93/include/uapi/linux/posix_types.h:5,
from /fork.openwrt/build_dir/target-mips_24kc_glibc/linux-ath79_generic/linux-6.6.93/include/uapi/linux/types.h:14:
/fork.openwrt/build_dir/target-mips_24kc_glibc/linux-ath79_generic/linux-6.6.93/include/uapi/linux/stddef.h:5:10: fatal error: linux/compiler_types.h: No such file or directory
5 | #include <linux/compiler_types.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
Fix this by pointing KERNEL_INCLUDE to the toolchain headers, which
include the installed kernel headers.
Tested with musl, glibc, and SDK.
Fixes: 60738feded ("iproute2: Fix KERNEL_INCLUDE in SDK")
Reported-by: Signed-off-by: Konstantin Demin <rockdrilla@gmail.com>
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
libs/slang2 is getting picked up from the packages feed, if the slang2
is compiled first and then if you try to compile perf, it fails
due to unmet dependency.
Fixes:
Package perf is missing dependencies for the following libraries:
libslang.so.2
Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/19123
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Add support for Xiaomi AX6000.
Speficiations:
* SoC: Qualcomm IPQ5018 (64-bit dual-core ARM Cortex-A53 @ 1.0Ghz)
* Memory: Etrontech EM6HE16EWAKG 512 MiB DDR3L-933
* Serial Port: 1v8 TTL 115200n8
* Wi-Fi: IPQ5018 (2x2 2.4 Ghz 802.11b/g/n/ax - up to 574 Mbps)
QCN9024 (4x4 5 Ghz 802.11an/ac/ax - up to 4804 Mbps)
QCA9887 (1x1 5 Ghz 802.11ac/n - up to 433 Mbps)
* Ethernet: IPQ5018 integrated virtual switch connected to:
- external QCA8337 switch (3 LAN Ports 10/100/1000)
- QCA8081 Phy WAN port (10/100/1000/2500)
* Flash: Either of:
- Gigadevice GD5F1GQ4RE9IGD (128 MiB)
- ESMT F50D1G41LB (128 MiB)
* LEDs: 1x WLAN Link (GPIO 23 Active High)
1x System Blue (GPIO 24 Active High)
1x System Yellow (GPIO 25 Active High)
1x WAN Link Blue (GPIO 26 Active High)
1x WAN Link Yellow (GPIO 27 Active High)
1x Green - Unused(GPIO 28 Active High)
3x LAN Phy Green
1x WAN Phy Green
* Buttons: 1x Reset (GPIO 38 Active Low)
Known issue:
- QCA9887 doesn't come up (possibly due to 1-lane PCIe phy not coming up or missing method to drive power),
hence the host PCIe controller is disabled in the DTS.
Flash instructions:
Download XMIR Patcher: https://github.com/openwrt-xiaomi/xmir-patcher
First flash a ubinized OpenWrt initramfs that will serve as the intermediate step, since
OpenWrt uses unified rootfs in order to fully utilize NAND and provide enough space for
packages, through either of the below two methods:
Installation via XMIR Patcher:
1. Load the initramfs image: openwrt-qualcommax-ipq50xx-xiaomi_ax6000-initramfs-factory.ubi
Installation via ubiformat method, through SSH:
1. If needed, enable SSH using XMIR Patcher.
2. Copy the file openwrt-qualcommax-ipq50xx-xiaomi_ax6000-initramfs-factory.ubi to the /tmp directory
3. Open an SSH shell to the router
4. Check which rootfs partition is your router booted in (0 = rootfs | 1 = rootfs_1):
nvram get flag_boot_rootfs
5. Find the rootfs and rootfs_1 mtd indexes respectively:
cat /proc/mtd
Please confirm if mtd18 and mtd19 are the correct indexes from above!
6. Use the command ubiformat to flash the opposite mtd with UBI image:
If nvram get flag_boot_rootfs returned 0:
ubiformat /dev/mtd19 -y -f /tmp/openwrt-qualcommax-ipq50xx-xiaomi_ax6000-initramfs-factory.ubi && nvram set flag_boot_rootfs=1 && nvram set flag_last_success=1 && nvram commit
otherwise:
ubiformat /dev/mtd18 -y -f /tmp/openwrt-qualcommax-ipq50xx-xiaomi_ax6000-initramfs-factory.ubi && nvram set flag_boot_rootfs=0 && nvram set flag_last_success=0 && nvram commit
7. Reboot the device by:
reboot
Continue in order to pernamently flash OpenWrt:
1. Upload the sysupgrade image to /tmp/ using SCP:
scp -O <path to image> root@192.168.1.1:/tmp/
2. Open an SSH shell to 192.168.1.1 from a PC within the same subnet
3. Use sysupgrade to flash the sysupgrade image:
sysupgrade -n -v /tmp/openwrt-qualcommax-ipq50xx-xiaomi_ax6000-squashfs-sysupgrade.bin
Device will reboot with OpenWrt, and then sysupgrade can be used to upgrade the device when desired.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/19004
Signed-off-by: Robert Marko <robimarko@gmail.com>
5be4c60a9084 ipq5018: add BDF for Xiaomi AX6000
22588512b844 qcn9074: add BDF for Xiaomi AX6000
4810aacf3b1c qca9889: add BDF for Xiaomi AX6000
Signed-off-by: Robert Marko <robimarko@gmail.com>
QCN6122 wifi in fw-memory-mode 1 has a slightly larger caldb size than
currently defined in the ath11k driver. When coldboot calibration was
disabled, the fw mem mode was changed from 2 (256MB mem profile) to 1
(512MB mem profile), which is the correct setting for devices in scope.
However, in fw mem mode, the caldb size is 0x500000 instead of the max
0x480000 defined in the driver, causing QCN6122 wifi failing to boot:
ath11k b00a040.wifi1: qmi mem size is low to load caldata
ath11k b00a040.wifi1: failed to assign qmi target memory: -22
As such, change the max caldb memory size accordingly.
This macro is used by the driver only as a max size limit to validate
the requested caldb size returned by QMI. Different ath11k wifi chips
have different caldb sizes (for ex. the size for IPQ5018 is 0x200000).
Fixes: cf715a2305 ("wifi: ath11k: disable coldboot calibration for ipq5018")
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/19118
Signed-off-by: Robert Marko <robimarko@gmail.com>
54b00e3b1fa9 ubus: fix double registry clear on disconnect
69521b55855c ubus: fix use-after-free on deferred request reply() method
22e8c16d9deb debug: fix crash when passing tagged string to getinfo()
2c9eea5174d6 ubus: use ucv_resource_create_ex for connections/channels
0a4cf4b7e71a ubus: use ucv_resource_create_ex for for ubus.request resources
99ee75a69cd3 ubus: use ucv_resource_create_ex for ubus.deferred resources
f085a42b977f ubus: use ucv_resource_create_ex for objects
94ad17d13a0d ubus: use ucv_resource_create_ex for ubus.notify resources
a3fa47fdda3e ubus: use ucv_resource_create_ex for ubus.listener resources
9ab5fa869dec ubus: use ucv_resource_create_ex for ubus.subscriber resources
be92ebd70633 CI: debian: install cmake package
fd202fd40bd1 socket: respect port argument in sockinst.connect()
767c209b917b socket: properly handle async `connect(2)` errors in socket.connect()
37ac8f112af6 socket: improve port argument validation in sockinst.connect()
Fixes: https://github.com/jow-/ucode/issues/302
Fixes: https://github.com/jow-/ucode/issues/303
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Remove upstream backport patch.
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Link: https://github.com/openwrt/openwrt/pull/19100
Signed-off-by: Robert Marko <robimarko@gmail.com>
I-O DATA WN-DAX3000GR is a 2.4/5 GHz band 11ax (Wi-Fi 6) router, based
on IPQ5018.
Specification:
- SoC : Qualcomm IPQ5018
- RAM : DDR3 512 MiB
- Flash : SPI-NAND 128 MiB (Macronix MX35UF1G24AD-Z4I)
- WLAN : 2.4/5 GHz 2T2R
- 2.4 GHz : Qualcomm IPQ5018 (SoC)
- 5 GHz : Qualcomm Atheros QCN6102
- Ethernet : 5x 10/100/1000 Mbps
- wan (phy) : Qualcomm IPQ5018 (SoC)
- lan (switch) : Qualcomm Atheros QCA8337
- LEDs/Keys (GPIO): 7x/5x
- UART : through-hole on PCB (J3)
- assignment : 3.3V, TX, RX, NC, GND from tri-angle marking
- settings : 115200n8
- USB : USB 2.0 Type-A (through-hole on PCB, "J6")
- Power : 12 VDC, 1A (Typ. 930 mA)
Flash instruction using factory.bin image:
1. Boot WN-DAX3000GR with router mode
2. Access to the WebUI ("http://192.168.0.1/") on the device and open
the firmware update page ("ファームウェア")
3. Select the OpenWrt factory.bin image and click update ("更新") button
4. Wait ~120 seconds to complete flashing
Switching to the stock firmware:
1. Load the elecom.sh script
. /lib/upgrade/elecom.sh
2. Check the current index of rootfs
bootconfig_rw_index 0:bootconfig rootfs
3. Set the index to inverted value
bootconfig_rw_index 0:bootconfig rootfs <value>
bootconfig_rw_index 0:bootconfig1 rootfs <value>
example:
- step2 returned "0":
bootconfig_rw_index 0:bootconfig rootfs 1
bootconfig_rw_index 0:bootconfig1 rootfs 1
- step2 returned "1":
bootconfig_rw_index 0:bootconfig rootfs 0
bootconfig_rw_index 0:bootconfig1 rootfs 0
4. Reboot
Partition Layout (Stock FW, bootconfig(rootfs)=1):
0x000000000000-0x000000080000 : "0:SBL1"
0x000000080000-0x000000100000 : "0:MIBIB"
0x000000100000-0x000000140000 : "0:BOOTCONFIG"
0x000000140000-0x000000180000 : "0:BOOTCONFIG1"
0x000000180000-0x000000280000 : "0:QSEE"
0x000000280000-0x000000380000 : "0:QSEE_1"
0x000000380000-0x0000003c0000 : "0:DEVCFG"
0x0000003c0000-0x000000400000 : "0:DEVCFG_1"
0x000000400000-0x000000440000 : "0:CDT"
0x000000440000-0x000000480000 : "0:CDT_1"
0x000000480000-0x000000500000 : "0:APPSBLENV"
0x000000500000-0x000000640000 : "0:APPSBL"
0x000000640000-0x000000780000 : "0:APPSBL_1"
0x000000780000-0x000000880000 : "0:ART"
0x000000880000-0x000000900000 : "0:TRAINING"
0x000000900000-0x000003c40000 : "rootfs_1"
0x000003c40000-0x000003fc0000 : "Config"
0x000003fc0000-0x000007300000 : "rootfs"
0x000007300000-0x000007680000 : "Config_2"
0x000007680000-0x000007700000 : "idmkey"
0x000007700000-0x000007c00000 : "Reserved"
0x000007c00000-0x000007c80000 : "FWHEADER"
0x000007c80000-0x000007d00000 : "Factory"
Known Issues:
- This device has a Macronix MX35UF1G24AD SPI-NAND chip registered as
oobsize=128 in Linux Kernel. But using BCH8 breaks I/O on the chip
with the following errors, so this support uses BCH4 instead.
[ 1.542261] 0x000000480000-0x000000500000 : "0:appsblenv"
[ 1.547959] 1 fixed-partitions partitions found on MTD device 0:appsblenv
[ 1.551265] Creating 1 MTD partitions on "0:appsblenv":
[ 1.558096] 0x000000000000-0x000000040000 : "env-data"
[ 1.627282] u-boot-env-layout 79b0000.qpic-nand:flash@0:partitions:partition-0-appsblenv:partition@0:nvmem-layout: probe with driver u-boot-env-layout failed with error -74
root@OpenWrt:~# strings /dev/mtdblock10
[ 77.806720] mtdblock: MTD device '0:appsblenv' is NAND, please consider using UBI block devices instead.
[ 77.807554] I/O error, dev mtdblock10, sector 0 op 0x0:(READ) flags 0x80700 phys_seg 4 prio class 0
[ 77.815977] I/O error, dev mtdblock10, sector 8 op 0x0:(READ) flags 0x80700 phys_seg 3 prio class 0
[ 77.824721] I/O error, dev mtdblock10, sector 16 op 0x0:(READ) flags 0x80700 phys_seg 2 prio class 0
[ 77.834095] I/O error, dev mtdblock10, sector 24 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 0
[ 77.843278] I/O error, dev mtdblock10, sector 0 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0
[ 77.851577] Buffer I/O error on dev mtdblock10, logical block 0, async page read
Notes:
- This device has dual-boot feature and it's managed by the index in the
0:bootconfig and 0:bootconfig1 partitions.
- There are through-holes on PCB for USB 2.0, but it cannot be accessed
without disassembly of the housing. So it's not enabled in this
support.
- WN-DAX3000GR has the "bt_fw" volume in the firmware UBI in addition to
the volumes that will be removed in the section of ELECOM WRC-X3000GS2
in /lib/upgrade/platform.sh.
That volume is unnecessary for OpenWrt and add
`remove_oem_ubi_volume bt_fw` to remove that volume when sysupgrade.
(that function doesn't anything without errors if no specified volume)
MAC Addresses:
LAN : 50:41:B9:xx:xx:64 (0:APPSBLENV, "ethaddr"/"eth1addr" (text))
WAN : 50:41:B9:xx:xx:66 (0:APPSBLENV, "eth0addr" (text))
2.4 GHz: 50:41:B9:xx:xx:64 (0:APPSBLENV, "wifi0" (text))
5 GHz : 50:41:B9:xx:xx:65 (0:APPSBLENV, "wifi1" (text))
Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/19053
Signed-off-by: Robert Marko <robimarko@gmail.com>
Add support for I-O DATA WN-DAX3000GR to update bootdelay variable while
sysupgrade.
Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/19053
Signed-off-by: Robert Marko <robimarko@gmail.com>
Coldboot calibration does not work causes the firmware to crash during
wifi startup. So let's disable coldboot calibration until a solution is
found.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/19083
Signed-off-by: Robert Marko <robimarko@gmail.com>