Embedd System Kernel Recovery
2026-03-15 21:39:38

Agenda

This article discusses the restoration of corrupted embedd kernel using SDcard(Secure Digital card).

How I destroyed the kernel image

In my case, I attached an 8-pin SOIC clip directly to the NOR flash chip to read the firmware without performing a chip-off extraction, and then attempted to boot the device.
However, the kernel image was corrupted, causing the boot sequence to fail during the checksum verification stage.
Using 8-pin SOIC clip to restore kernel image is not impossible. But I was just scared to use it again, so I found another way, that uses SDcard, to restore kernel image.

1
2
3
4
5
6
7
8
9
## Booting kernel from Legacy Image at 00000000 ...
Image Name: Linux-4.19.91
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1568528 Bytes = 1.5 MiB
Load Address: 00008000
Entry Point: 00008000
Verifying Checksum ... Bad Data CRC
ERROR: can't get kernel image!
nvt@:

To restore the corrupted kernel image, I should extract the kernel image from the original firmware and flash it into the kernel partition of the NOR flash memory. I used the original firmware, that I extracted before.
By the way, In case you can only download a legacy firmware online, I believe flashing an entire legacy firmware in NOR flash chip and updating it to a stable firmware using apps, after reviving the device, is the one of the firmware restoring method.

1
2
3
4
5
6
7
8
9
10
11
12
13
% binwalk [firmware]
----------------------------------------------------------------------------------------------------------------------------------------------------
DECIMAL HEXADECIMAL DESCRIPTION
----------------------------------------------------------------------------------------------------------------------------------------------------
...(omitted)
431959 0x69757 uImage firmware image, header size: 64 bytes, data size: 1568528 bytes,
compression: none, CPU: ARM, OS: Linux, image type: OS Kernel Image, load
address: 0x8000, entry point: 0x8000, creation time: 2022-08-23,
image name: "Linux-4.19.91"
2000551 0x1E86A7 SquashFS file system, little endian, version: 4.0, compression: xz, inode
count: 917, block size: 262144, image size: 13376468 bytes, created:
2024-01-09
----------------------------------------------------------------------------------------------------------------------------------------------------

On the first attempt, I extracted the kernel image through binwalk from the original firmware and flashed it into the kernel partition of the NOR flash memory. However, the device still failed to boot it.
This is because binwalk extracts only 15685628 bytes, which is the data size, of kernel image from the kernel image offset.
During the boot sequence, the checksum verification of the kernel calculates CRC value using the entire kernel section.
Therefore, I had to extract 1568592(0x1e86a7-0x69757) bytes of the entire kernel section from the kernel image offset.

1
% dd if=[firmware] of=kernel.bin skip=431959 count=1568592 bs=1

This extracted kernel image includes the dummy section, which is located between the end of the kernel image and the start of the next section(SquashFS).
After extracting the kernel image, I had to flash it into the kernel partition.
By checking the mtdparts environment variable through the bootloader shell using printenv command, I could see that the linux partition, which contains the kernel image, starts at address 0x100000 and has a size of 0x1b0000.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
nvt@: printenv
...(omitted)
arch=arm
baudrate=115200
board=nvt-
board_name=nvt-
bootargs=earlyprintk console=ttyS0,115200 rootwait nprofile_irq_duration=on rootfstype=squashfs ro mtdparts=spi_nor.0 root=/dev/mtdblock6 bootts=154129,1029087 resume_addr=0x00200088 user_debug=0xff
bootcmd=nvt_boot
bootdelay=0
bootm_low=0x00000000
bootm_mapsize=0x04b00000
bootm_size=0x04b00000
cpu=armv7
filesize=17ef50
mtddevnum=0
mtdids=nor0=spi_nor.0
mtdparts=mtdparts=spi_nor.0:0x10000@0x10000(fdt),0x60000@0x60000(uboot),0x40000@0xc0000(uenv),0x1b0000@0x100000(linux),0xcd0000@0x2b0000(rootfs0)
netmask=255.255.255.0
partition=nor0,0
stderr=serial
stdin=serial
stdout=serial
ver=U-Boot 2019.04 (Nov 22 2023 - 16:28:23 +0800)

Therefore, I had to flash the linux partition to the kernel image extracted earlier. In my case, I used fatload command to load the kernel image on the device RAM, so I had to format the SDcard FAT in advance.

Formatting SDcard

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
% diskutil list
/dev/disk0 (internal, physical):
#: TYPE NAME SIZE IDENTIFIER
0: GUID_partition_scheme *500.3 GB disk0
1: Apple_APFS_ISC Container disk1 524.3 MB disk0s1
2: Apple_APFS Container disk3 494.4 GB disk0s2
3: Apple_APFS_Recovery Container disk2 5.4 GB disk0s3

/dev/disk3 (synthesized):
#: TYPE NAME SIZE IDENTIFIER
0: APFS Container Scheme - +494.4 GB disk3
Physical Store disk0s2
1: APFS Volume Macintosh HD 15.8 GB disk3s1
2: APFS Snapshot com.apple.os.update-... 15.8 GB disk3s1s1
3: APFS Volume Preboot 13.8 GB disk3s2
4: APFS Volume Recovery 2.1 GB disk3s3
5: APFS Volume Data 107.1 GB disk3s5
6: APFS Volume VM 20.5 KB disk3s6

/dev/disk4 (internal, physical):
#: TYPE NAME SIZE IDENTIFIER
0: FDisk_partition_scheme *134.2 GB disk4
1: DOS_FAT_32 SDCARD 134.2 GB disk4s1

Since I was using MacOS, I used diskutil command to format the SDcard. In my case, the SDcard was /dev/disk4.

1
2
3
4
5
6
7
8
9
10
11
% diskutil eraseDisk FAT32 SDCARD MBRFormat /dev/disk4
Started erase on disk4
Unmounting disk
Creating the partition map
Waiting for partitions to activate
Formatting disk4s1 as MS-DOS (FAT32) with name SDCARD
512 bytes per physical sector
/dev/rdisk4s1: 262049216 sectors in 4094519 FAT32 clusters (32768 bytes/cluster)
bps=512 spc=64 res=32 nft=2 mid=0xf8 spt=32 hds=255 hid=32768 drv=0x80 bsec=262113280 bspf=31989 rdcl=2 infs=1 bkbs=6
Mounting disk
Finished erase on disk4

After formatting the SDcard, I copied kernel image, which I extracted earlier to file system of the SDcard.

1
% cp ./kernel.bin /Volumes/SDCARD/

Restoring the kernel image

Back to the bootloader shell, first I attached the SDcard to the device, and then I checked if the device could recognize the SDcard and set the current mmc(MultiMediaCard) device through mmc command. In my case, mmc index of the SDcard was 0.

1
2
nvt@: mmc dev 0
mmc0 is current device

After setting the current mmc device, I loaded the kernel image, which I stored into the SDcard, on 0x00000000 address of the device RAM through fatload command.

1
2
nvt@: fatload mmc 0:1 0x00000000 kernel.bin
1568592 bytes read in 77 ms (19.4 MiB/s)

On the second attempt, I tried to boot the device from 0x00000000 address of RAM through bootm command to see the result of the checksum verification. The checksum verification of kernel image was succeed. However, as expected, the boot sequence still failed.

1
2
3
4
5
6
7
8
9
10
nvt@: bootm 0x00000000
## Booting kernel from Legacy Image at 00000000 ...
Image Name: Linux-4.19.91
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1568528 Bytes = 1.5 MiB
Load Address: 00008000
Entry Point: 00008000
Verifying Checksum ... OK
ERROR: can't get kernel image!
nvt@:

Because during the boot sequence, NVT bootloader will find the kernel image in the kernel partition of NOR flash memory, but I had not yet properly flash the kernel image into the NOR flash memory. So the corrupted kernel image is still at the kernel partition of the NOR flash memory.
To flash the NOR flash memory, I used sf command. And I set the current SPI(NOR) flash chip to use it. In my case, the index of the NOR flash chip was 0.

1
2
nvt@: sf probe 0
SF: Detected GigaDevice 25Q128E ...(omitted)

After setting the current NOR flash chip, I flashed kernel image, which is loaded on 0x00000000 address of the device RAM, into 0x100000 address of NOR flash memory, which is kernel partition, 0x1b0000 bytes.

1
2
3
4
5
6
7
8
nvt@: sf update 0x00000000 0x100000 0x1b0000
device 0 offset 0x100000, size 0x1b0000
nor0 0x10000 0x100
Updating, 26% 1565873 B/snor0 0x10000 0x100
Updating, 89% 2403899 B/snor0 0x10000 0x100
Updating, 93% 1906501 B/snor0 0x10000 0x100
Updating, 97% 1584768 B/snor0 0x10000 0x100
327680 bytes written, 1441792 bytes skipped in 1.318s, speed 1371642 B/s

After flashing kernel partition, finally I could boot the device through nvt_boot command. I could see the bootcmd environment variable through printenv command.
Additionally, you can also flash the entire firmware into the NOR flash memory through the same method. And if the bootloader is also corrupted and cannot load anything, just perform a chip-off extraction(optional) and use an 8-pin SOIC clip to flash the entire firmware into the NOR flash chip.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
nvt@: nvt_boot
do_nvt_boot_cmd: boot time: 114060935(us)
NVT firmware boot.....
nvt_detect_fw_tbin: Boot from flash or emmc
device 0 offset 0x100000, size 0x40
SF: 64 bytes @ 0x100000 Read: OK
device 0 offset 0x100000, size 0x17ef80
SF: 1568640 bytes @ 0x100000 Read: OK
nvt_ker_img_ungzip_linux: not gzip linux
nvt_boot_linux_bin_auto: linux_addr:0x05800000
nvt_boot_linux_bin_auto: linux_size:0x0017ef50
do_nvt_boot_cmd: boot time: 114238348(us)
do_nvt_boot_cmd: bootargs:earlyprintk console=ttyS0,115200 rootwait nprofile_irq_duration=on rootfstype=squashfs ro mtdparts=spi_nor.0 root=/dev/mtdblock6 bootts=154129,1029087 resume_addr=0x00200088 user_debug=0xff bootts=154129,114242941 resume_addr=0x00200088 user_debug=0xff
Image Name: Linux-4.19.91
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1568528 Bytes = 1.5 MiB
Load Address: 00008000
Entry Point: 00008000
Linux Image is at 5800000, uboot fdt image is at 7c403c8, loader tmp fdt address is at 100000
bootm 5800000 - 7c403c8
do_nvt_boot_cmd: boot time: 114295115(us)
do_nvt_boot_cmd: Uboot boot time:
start: 154129 us
ending: 114242941 us
## Booting kernel from Legacy Image at 05800000 ...
Image Name: Linux-4.19.91
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1568528 Bytes = 1.5 MiB
Load Address: 00008000
Entry Point: 00008000
Verifying Checksum ... OK
## Flattened Device Tree blob at 07c403c8
Booting using the fdt blob at 0x7c403c8
Loading Kernel Image
Loading Device Tree to 04af8000, end 04aff196 ... OK

Starting kernel ...

ACTLR: 0x00000004
ACTLR: 0x00000044
Disable MMU
Clear MMU
Uboot L2 cache aux val: 0x72420000
Uboot L2 cache prefetch ctrl val: 0x70800000
Uboot L2 cache ctrl val: 0x00000000
Done
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 4.19.91 (mdq@ubuntu) (gcc version 8.4.0 (Buildroot 2020.02.9-3-g58c1c2e-dirty)) #2 PREEMPT Tue Aug 23 18:36:45 CST 2022
CPU: ARMv7 Processor [414fc091] revision 1 (ARMv7), cr=10c5387d
...

Device revived! :D

2026-03-15 21:39:38