Add support for Sercomm S3 on stock uboot

Thanks @inflabz . I have sent them to you.

1 Like

I hacked up a small tool a few days ago when I was facing the same problem. Mostly code stolen from other places. It might help: https://www.mork.no/~bjorn/crc32range.c

The UI was made for one-time usage by myself, so it obviously sucks. But the idea is to quickly be able to recalculate checksums over a selectable range of an image file, comparing then with an exiting value. For example for this image which as a 0x17c bytes long header with a checksum in offset 0x174:

 bjorn@canardo:/usr/local/src/openwrt$ /tmp/crc32range bin/r16596+3-6f77ce77248d/targets/ramips/mt7621/openwrt-snapshot-ramips-mt7621-zyxel_lte5398-initramfs-recovery.bin 0 0x17c 0x174
 old checksum at offset 372: f55bb8f4
 0aa4470b        0b47a40a        f55bb8f4        f4b85bf5

So you see that the 3rd value matches. Which means that this is a bit inverted crc32 sum.

This tool was very useful when I didn't even now which range the sum should be calculated over, since I easily could change the range without changing the tool or image

1 Like

Thanks for the tool @bmork . At the moment the main issue is why the router accepts the initramfs image from tftp but refuses to boot from flash. What I do is just flash the kernel, boot the image and I get a nice message like this "it gives me the checksum if it is incorrect and I just replace it.

FW header checksum should: 0xeb087576, crc32 result: 0xeb087576, Fw header CRC check OK!

I also use okteta from KDE. It is so usefull for people like me (very limited coding knowledge to not say none). I can just highlight the data or even select a range and just click on any checksum that is availble (quite a few there) and get instat result.

1 Like

@inflabz I just realised I am uisng your modified breed bootloader. Thanks for doing that.

I just compiled an image from snapshot and everything is working. I guess I will just use that instead of trying to make an image that boots from the stock bootloader.

1 Like

Can someone please point me to the right direction? I have been able to get the whole header sorted out (thanks to @Lucky1),

After days of trying to change the receipe to have a similar kernel as the stock one I overlooked for some reason the "Load address". In fact I did not overlook it I just decided it was the same for some reason.

I beleive the bootloader checks that address and it has to be 0x81001000. If I use the default one from openwrt "0x80001000" it loads the kernel and just hangs there. But the initramfs image in tftp does boot and work fine (I guess no checks are made there)

I tried to change that to the 0x81001000 in the "ramips/mage/Makefile" and although now it goes further till starting kernel "which it did not get to before" it does not work "not even the initramfs".

Can someone point me to the right direction please? I did a few search on the openwrt tree and I cannot seem to find a device that changes that. What is the correct way to change it?

"*************************************
Boot Flag : Sercomm0�
*************************************
Fw header Magic check OK!
FW header checksum should: 0x5bf8b2ce, crc32 result: 0x5bf8b2ce, Fw header CRC check OK!
kernel : real offset: 0x00400100, data length: 0x00264715,checksum :0x0a72d890
kernel result: 0x0a72d890, kernel check sum ok!
rootfs:  real offset: 0x01000000, data length: 0x003483fe, checksum :0x59f6e2aa
rootfs result: 0x59f6e2aa, rootfs check sum ok!
Kernel Addr : 0xbc400100
## Booting image at bc400100 ...
   Image Name:   Linux Kernel Image
   Image Type:   MIPS Linux Kernel Image (lzma compressed)
   Data Size:    2508501 Bytes =  2.4 MB
   Load Address: 81001000
   Entry Point:  81001000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
kernel addr :0xBC400100 
No initrd
## Transferring control to Linux (at address 81001000) ...
## Giving linux memsize in MB, 256

Starting kernel ...

1 Like

If it can help anyone this is the Sercomm header for both S3 and beeline turbo+
All values are written reverse

+------------------------------+-------------------------------------+------------------------------+---------------+
| Sercom HDR "53657200"        | Absoulte lenght for Sercomm footer  | HDR Checksum                 | 02 FF FF FF   |
| FFFFFFFF for hdr crc32 calc  | (normally kernel length + 0x400100) | FFFFFFFF for hdr crc32 calc  |               |
+------------------------------+-------------------------------------+------------------------------+---------------+
| kernel flash offset          | uImage kernel length                | uimage kernel crc32          | 00 00 00 00   |
| 00 01 40 00 (if bootlfag set |                                     |                              |               |
| to Sercomm0)                 |                                     |                              |               |
+------------------------------+-------------------------------------+------------------------------+---------------+
| FF FF FF FF                  | FF FF FF FF                         | rootfs flash offset          | rootfs length |
|                              |                                     | 00 00 00 01 (if bootflag set |               |
|                              |                                     | to Sercomm0)                 |               |
+------------------------------+-------------------------------------+------------------------------+---------------+
| Rootfs checksum              | 00 00 00 00                         | 00 00 00 00                  | 00 00 00 00   |
+------------------------------+-------------------------------------+------------------------------+---------------+````
1 Like

Just adding how I managed to get this to boot. maybe it will help someone else.

image/Makefile

define Build/loader-common-s3
	rm -rf $@.src
	$(MAKE) -C lzma-loader \
		PKG_BUILD_DIR="$@.src" \
		TARGET_DIR="$(dir $@)" LOADER_NAME="$(notdir $@)" \
		BOARD="$(BOARDNAME)" PLATFORM="$(LOADER_PLATFORM)" \
		LZMA_TEXT_START=0x82800000 LOADADDR=0x80001000 \
		$(1) compile loader.$(LOADER_TYPE)
	mv "$@.$(LOADER_TYPE)" "$@"
	rm -rf $@.src
endef
define Build/loader-kernel-s3
	$(call Build/loader-common-s3,LOADER_DATA="$@")
endef
define Device/uimage-lzma-loader-s3
  KERNEL_LOADADDR = 0x81001000
  LOADER_TYPE := bin
  KERNEL := kernel-bin | append-dtb | lzma | loader-kernel-s3 | lzma | uImage lzma
endef

And this in the mt7621.mk

define Device/sercomm_s3
$(Device/uimage-lzma-loader-s3)
  BLOCKSIZE := 128k
  PAGESIZE := 2048
  KERNEL_SIZE := 4096k
  UBINIZE_OPTS := -E 5
  IMAGES += kernel0.bin rootfs0.bin
  IMAGE/kernel0.bin := append-kernel
  IMAGE/rootfs0.bin := append-ubi
  DEVICE_VENDOR := Sercomm
  DEVICE_MODEL := S3
  DEVICE_PACKAGES := kmod-mt7603 kmod-mt7615e kmod-mt7615-firmware kmod-usb3 \
  kmod-usb-ledtrig-usbport
endef
TARGET_DEVICES += sercomm_s3

dts

// SPDX-License-Identifier: GPL-2.0-or-later OR MIT

#include "mt7621.dtsi"

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>

/ {
	compatible = "sercomm,s3", "mediatek,mt7621-soc";
	model = "Sercomm S3";

	aliases {
		led-boot = &led_status_blue;
		led-failsafe = &led_status_red;
		led-running = &led_status_green;
		led-upgrade = &led_status_red;
		label-mac-device = &gmac0;
	};

	chosen {
		bootargs = "console=ttyS0,57600n8";
	};

	leds {
		compatible = "gpio-leds";

		led_status_blue: status_blue {
			label = "blue:status";
			gpios = <&gpio 13 GPIO_ACTIVE_HIGH>;
		};

		led_status_green: status_green {
			label = "green:status";
			gpios = <&gpio 15 GPIO_ACTIVE_HIGH>;
		};

		led_status_red: status_red {
			label = "red:status";
			gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
		};
	};

	keys {
		compatible = "gpio-keys";

		wps {
			label = "wps";
			gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_WPS_BUTTON>;
		};

		reset {
			label = "reset";
			gpios = <&gpio 14 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_RESTART>;
		};
	};
};

&nand {
	status = "okay";

	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		partition@0 {
			label = "bootloader";
			reg = <0x0 0x100000>;
		};

		partition@100000{
			label = "part_map ";
			reg = <0x100000 0x100000 >;
		};

		factory:partition@200000 {
			label = "factory-data";
			reg = <0x200000 0x100000>;
		};

		partition@300000 {
			label = "bootflag";
			reg = <0x300000 0x100000>;
		};

		partition@400000 {
			label = "kernel0";
			reg = <0x400000 0x600000>;
		};

		partition@a00000 {
			label = "kernel1";
			reg = <0xa00000 0x600000>;
		};

		partition@1000000 {
			label = "ubi";
			reg = <0x1000000 0x2000000>;
		};

		partition@3000000 {
			label = "rootfs1";
			reg = <0x3000000 0x2000000>;
		};

		partition@5000000{
			label = "config-log";
			reg = <0x5000000 0x1400000>;
		};

		partition@6400000 {
			label = "reserved";
			reg = <0x6400000 0x1b80000>;
		};
	};
};

&pcie {
	status = "okay";
};

&pcie0 {
	wifi@0,0 {
		compatible = "pci14c3,7615";
		reg = <0x0000 0 0 0 0>;
		mediatek,mtd-eeprom = <&factory 0x8000>;
		ieee80211-freq-limit = <5000000 6000000>;
		mtd-mac-address = <&factory 0x21000>;
		mtd-mac-address-increment = <2>;
	};
};

&pcie1 {
	wifi@0,0 {
		compatible = "pci14c3,7603";
		reg = <0x0000 0 0 0 0>;
		mediatek,mtd-eeprom = <&factory 0x0000>;
		ieee80211-freq-limit = <2400000 2500000>;
		mtd-mac-address = <&factory 0x21000>;
		mtd-mac-address-increment = <3>;
	};
};

&gmac0 {
	mtd-mac-address = <&factory 0x21000>;
};

&switch0 {
	ports {
		port@0 {
			status = "okay";
			label = "wan";
			mtd-mac-address = <&factory 0x21000>;
			mtd-mac-address-increment = <1>;
		};

		port@1 {
			status = "okay";
			label = "lan1";
		};

		port@2 {
			status = "okay";
			label = "lan2";
		};

		port@3 {
			status = "okay";
			label = "lan3";
		};

		port@4 {
			status = "okay";
			label = "lan4";
		};
	};
};

&state_default {
	gpio {
		groups = "uart2", "jtag";
		function = "gpio";
	};
};
2 Likes

And this Sercomm header will pass all the checks. The reason behind it is that I just used 4 bytes for kernel and rootfs checksum therfore they are always the same results

00000000  53 65 72 00 2b 57 66 00  f8 17 de af 02 ff ff ff  |Ser.+Wf.........|
00000010  00 01 40 00 04 00 00 00  a9 d7 62 03 00 00 00 00  |..@.......b.....|
00000020  ff ff ff ff ff ff ff ff  00 00 00 01 04 00 00 00  |................|
00000030  1c fc 55 2d 00 00 00 00  ff ff ff ff ff ff ff ff  |..U-............|
00000040  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
00000100

and again in a hex

536572002b576600f817deaf02ffffff0001400004000000a9d7620300000000ffffffffffffffff00000001040000001cfc552d00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
*************************************
Boot Flag : Sercomm0�
*************************************
Fw header Magic check OK!
FW header checksum should: 0xafde17f8, crc32 result: 0xafde17f8, Fw header CRC check OK!
kernel : real offset: 0x00400100, data length: 0x00000004,checksum :0x0362d7a9
kernel result: 0x0362d7a9, kernel check sum ok!
rootfs:  real offset: 0x01000000, data length: 0x00000004, checksum :0x2d55fc1c
rootfs result: 0x2d55fc1c, rootfs check sum ok!
Kernel Addr : 0xbc400100
## Booting image at bc400100 ...
   Image Name:   MIPS OpenWrt Linux-5.4.111
   Image Type:   MIPS Linux Kernel Image (lzma compressed)
   Data Size:    2382013 Bytes =  2.3 MB
   Load Address: 81001000
   Entry Point:  81001000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
kernel addr :0xBC400100 
No initrd
## Transferring control to Linux (at address 81001000) ...
## Giving linux memsize in MB, 256

Starting kernel ...



OpenWrt kernel loader for MIPS based SoC
Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
Decompressing kernel... done!
Starting kernel at 80001000...

[    0.000000] Linux version 5.4.111 (builder@buildhost) (gcc version 8.4.0 (OpenWrt GCC 8.4.0 r16046-59980f7aaf)) #0 SMP Sun Apr 18 10:06:57 2021
[    0.000000] SoC Type: MediaTek MT7621 ver:1 eco:3
[    0.000000] printk: bootconsole [early0] enabled
[    0.000000] CPU0 revision is: 0001992f (MIPS 1004Kc)

3 Likes

Hello @kar200 and thanks for continuing to work on the device. If you need to test something or information about Turbo+, then let me know. Can you post information and photo about S3 on the WikiDevi (https://wikidevi.wi-cat.ru/ or https://deviwiki.com/)? To compare better. I understand your device gives ISP Etisalat in the UAE?[1][2] Do our devices need to be combined under one vendor name? Or leave it as it is?

Hi @MaxS0niX,

If you are interested (and have console access) I can send you the openwrt 21.02.RC I have created. It actually works well.

At the moment I am trying to understand the structure of the update file.
For the Sercomm S3 there is a header with a string with the 1st line that represent probably the model number followed by a 16 byte sha256 that is just the calculation of the firmware in gzip format.

The Turbo+ looks similar exept that sha256sum (or what I think it is) does not match anything I tried. I am still trying to find out what it represent. This way we could have a firmware that can be updated through the web interface.

These are the files to be written to mtd4 and mtd6. !!!!!PLEASE USE THEM ONLY IF YOU HAVE ACCESS TO THE CONSOLE!!!! as since the header is done in a way to always work you won't get the uboot protection that swtiches to the second boot kernel anymore.

1 Like

Perhaps your guesses are correct.

Sorry, my English is bad :sweat_smile:. UART is connected. Bin files mtd4 and mtd6 are OpenWRT kernel and rootfs for the stock Uboot "Kernel 1" 0x000000400000-0x000000a00000 and "File System 1" 0x000001000000-0x000003000000?

Yes that is correct.

@inflabz is working on a better version at the moment. We realized that the bootloader is different as for the turbo+ there is a boot counter that needs to be reset in firmware which this does not have.

If the counter gets to 3 it automatically switch to the second kernel for boot.

You can still try with UART as it won't do anything bad beyond recovery.

1 Like

Hi. Thanks your work! If I understand correctly rootfs checksum must be recalculated after any write operation. How do you handle this?

1 Like

Hi @csharper2005,

Yes you are correct. But some of the firmware for the Turbo+ already use UBI for the rootfs and they still pass the checksum. I did not look into it but I guess there are no write operations on them.

With openwrt it is tricky. The "append-ubi" seem to create a ubi volume for rootfs that gets formated at the first boot so it changes the header already and the following boot it fails the checksum. I beleive this is done on purpose for openwrt to have a normal size rootfs but to then use the whole partition when it formats it the first time it boots (this is a very uneducated guess).

The easiest way to get around it is to actually set the rootfs size to 4 bytes only rather than the whole rootfs. This can also be done for the kernel. Since the first 4 bytes of the kernel and ubi are always the same in any image it will always pass the check (just a nice way to disabled the check in some way).

2 Likes

Just in case someone needs it
This hdr will pass the checksum calculation with any kernel and rootfs (for Sercomm0 bootflag)

Note: Rootfs needs to be UBI and not JFFS

❯ hexdump -C hdr.bin
00000000  53 65 72 00 2b 57 66 00  f8 17 de af 02 ff ff ff  |Ser.+Wf.........|
00000010  00 01 40 00 04 00 00 00  a9 d7 62 03 00 00 00 00  |..@.......b.....|
00000020  ff ff ff ff ff ff ff ff  00 00 00 01 04 00 00 00  |................|
00000030  1c fc 55 2d 00 00 00 00  ff ff ff ff ff ff ff ff  |..U-............|
00000040  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
00000100
2 Likes

Oh, magic hdr, thanks. I'm trying to adapt your method to Smartbox Giga / second slot (Sercomm1, kernel@0xa00000). I think the header for this case should look like this:

0000000000: 53 65 72 00 2B 57 66 00 │ F8 17 DE AF 02 FF FF FF  Ser +Wf ø↨Þ¯☻ÿÿÿ
0000000010: 00 01 A0 00 04 00 00 00 │ A9 D7 62 03 00 00 00 00   ☺  ♦   ©×b♥                        
0000000020: FF FF FF FF FF FF FF 00 │ 00 80 02 04 00 00 00 00  ÿÿÿÿÿÿÿ  €☻♦                         
0000000030: 1C FC 55 2D 00 00 00 00 │ FF FF FF FF FF FF FF FF  ∟üU-    ÿÿÿÿÿÿÿÿ                     
0000000040: FF FF FF FF FF FF FF FF │ FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
1 Like

I don't think that one is corect. The only thing that should change between the 2 is the location of the kernel and rootfs "400100 to A00100 for kernel" and " 1000000 to 3000000 for rootfs" and obviously the header checksum.

So:
Sercomm0 bootflag

0000:0000 | 53 65 72 00  2B 57 66 00  F8 17 DE AF  02 FF FF FF | Ser.+Wf.ø.Þ¯.ÿÿÿ
0000:0010 | 00 01 40 00  04 00 00 00  A9 D7 62 03  00 00 00 00 | ..@.....©×b.....
0000:0020 | FF FF FF FF  FF FF FF FF  00 00 00 01  04 00 00 00 | ÿÿÿÿÿÿÿÿ........
0000:0030 | 1C FC 55 2D  00 00 00 00  FF FF FF FF  FF FF FF FF | .üU-....ÿÿÿÿÿÿÿÿ
0000:0040 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:0050 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:0060 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:0070 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:0080 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:0090 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00A0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00B0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00C0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00D0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00E0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00F0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

Sercomm1 bootflag

0000:0000 | 53 65 72 00  2B 57 66 00  80 8C BC 85  02 FF FF FF | Ser.+Wf...¼..ÿÿÿ
0000:0010 | 00 01 A0 00  04 00 00 00  A9 D7 62 03  00 00 00 00 | .. .....©×b.....
0000:0020 | FF FF FF FF  FF FF FF FF  00 00 00 03  04 00 00 00 | ÿÿÿÿÿÿÿÿ........
0000:0030 | 1C FC 55 2D  00 00 00 00  FF FF FF FF  FF FF FF FF | .üU-....ÿÿÿÿÿÿÿÿ
0000:0040 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:0050 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:0060 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:0070 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:0080 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:0090 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00A0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00B0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00C0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00D0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00E0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0000:00F0 | FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF | ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
````
2 Likes

What utility do you use to generate the header? I've checked openwrt firmware-utils collection. There are many similar utils but none of them can be used unchanged for our case.

1 Like

At the moment just a hex editor so no utility.
I then use "cat" to add the header to the kernel.

This is still a work in progress. Actually more like a work without progress since I cannot even get an image that flashes from the web interface. The only image I have is one that was sent to the router by the ISP using TR69 which I copied to the usb while the automatic process was flashing the file. That imge does not work with the web interface.

1 Like