I managed to package an OpenWrt image in such a way OEM firmware accepts. No serial port needed.
I described the D-link OEM firmware format in https://openwrt.org/toh/d-link/dgs-1210-16_g1#vendor_firmware_rebuild . However, the OEM software barely validates it. The OEM firmware packs a kernel and a rootfs and write them to the corresponding partition. For image1, both partitions are continuous. So, the trick is simply to cut the OpenWrt firmware exactly the size of the kernel partition and offer it as "the kernel", and use the remaining kernel code and the squashfs as "the rootfs", padded to 16 bytes. Pack them with the imghdr tool (from D-Link GPL pack) and ship it.
The only problem is that you do need to write it to image1. Image2 has a sysinfo partition between kernel2 and rootfs2 and it will cut the kernel in the middle with funny results.
At least for 6.30.016, web interface simply reboots the switch whatever firmware I send. I wrote the firmware using the telnet interface.
Does anyone knows if there is a OSS imghdr-like tool? Or, at least, does anyone know the meaning of those 0x40 bytes?
BTW, D-link does have an emergency mode to recover a firmware from bootloader. However, I only managed to trigger it by breaking both firmwares, pressing ESC in the serial console, or holding reset for more than 11s from a running OEM image. I couldn't do it from a cold reboot. Am I missing something?
I reverse engineered the headed format and created a python tool. I still don't understand 2 bytes in the 64b headed, but they are always static. I might submit a PR today or at least this week.
Nice. So U-Boot loads a kernel larger than the OEM kernel partitions, without any modifications?
Ughh, when I tried using a larger kernel it would fail as its looking for the checksum only in the kernel partition space.
I presume its working like the current OpenWrt images where checksum checks for kernel 1 and rootfs 1 fail, but will succeed for the second kernel and rootfs as these are left untouched.
Check is implemented stupidly and does not care if you want to boot kernel 1 and that fails as only the function return code is checked.
Yes, it does fail on the first kernel checksum but does not care to switch the load address. It only use that check to trigger the firmware recovery when both are bad. That's how the image installed from serial works and I just figure out how to place the same bits in the same place using the OEM firmware.
Many things are badly implemented. Firmware recovery can only be trigged from a working OEM firmware (!!), IPv6 stops workings after some time (probably after the first RA received expires), the system daemon crashes on any web upload (ssh keys, firmwares) and it also freezes when I reboot the router (an OpenWrt). Except for the firmware recovery, all problems actually help or incentive OpenWrt. I would never recommend this switch until it booted OpenWrt.
A clean solution would be to have an OpenWrt U-Boot with all features and fixes we need. I tried to play with it but it is too much work to do by myself. Dlink might try to fix their issues and unintentionally break OpenWrt support.
I modified an OEM firmware to provide me with a root access if someone needs. That was my first plan: an OEM firmware that bundles the OpenWrt firmware and only installs it once booted but I abandoned it once I figure out OEM does not really validates the firmware. And the limited "Compact CLI" command offer is just a soft lock: if you manage to connect to telnet before admin autenticates, you'll have access to a real CLI, with even some extra debug commands like GPIO info.
I am interested in root shell, to get some more details about the SFP and fan controller.
I got tired of D-link forcing dual FW, and modified the bootloader a while back to just skip the checksum check completely.
If dlink one day fixes the checksum in such a way it breaks OpenWrt, we could ship that U-Boot with the factory image. The issue is that we should manage to build it from sources inside the OpenWrt to be able to merge it.
I'll send you a link with an OEM image in a couple of hours. I'm out of office.
Not necessarily, it can be kept outside of OpenWrt as binary, there are devices already requiring U-boot change to flash OpenWrt.
Thanks in advance
Oh, another issue with the OEM firmware. The SSH host key is the same for every device. I don't know if that allows a malicious actor to break the SSH encryption but it does allow a MITM attack.
For those that already have an OpenWrt installed and want to play with the original firmware, just mount mtd10 and replicate the root line with another user name, a password hash (you can copy from admin) and /bin/sh shell. Enable ssh once you boot the original firmware and log with your new user.
The PR is mostly ready: https://github.com/openwrt/openwrt/pull/10113
If someone have access to other models, please test this solution. I don't know which parameters are shared or specific for each device (but my guess is that all of them uses the same ones).
I'm working on dgs-1210-52 and the firmware installation works as well, even it being a different SoC. The port is as good as other devices and it shares the same GPIO pins. I also opted to keep u-boot-env writable to be able to easily dual boot. Only the combo ports that are not working nicely. It looks like they start in "sfp mode" by default except if I load initramfs using one of those ports.
@robimarko , you said you were working on the dgs-1210-28 sfp ports. I believe that once it gets fixed there, the same solution would work for the 52-port variant (its the same module). Do you need a hand? It's the only thing remaining to compete the device support as my device does not have fans.