Planet Raumfahrtagentur

September 30, 2023

lynxis

Recover a Shelly Dimmer v1

A friend of mine tried out tasmota on a Shelly Dimmer, but he decided in the end to go back to the Shelly firmware because of the calibration and more precise configuration of the dimmer. The dimmer connected to a LED and you want to match the lowest possible energy to start at an offset because the LED won't turn on until you reach 50% duty cycle.

After trying flashing back from tasmota to Shelly, the dimmer broke down and couldn't be controlled by wlan anymore.

To recovery the Shelly Dimmer you need to have:

  • Debug connector 1x6 RM 1.27
  • USB UART for 3.3V
  • Shelly Recovery Firmware
  • esptool.py
Disconnect the 230 Volt connectors before connecting anything else to it!!!

The Shelly Dimmer comes with a debug connector which is accessable from outside and it consist of 1x6 RM 1.27. You may find different pinouts for the Dimmer. The correct pinout for the Shelly Dimmer v1 is:

     [x][x][x][x][x] 230V connector

[] U0TXD
[] U0RXD
[] GPIO2
[] GPIO0
[] 3V3
[] GND

* Button

Most USB UARTs will provide a good enough power supply for the shelly to boot up.

You need to connect a 3.3V UART to U0TXD, U0RXD, 3V3 and GND. Further you need to connect GPIO0 to GND to get the ESP8266 into boot mode.

Power cycle the ESP either by remove the 3.3V pin or by cycling the USB port.

There are multiple "recovery" firmwares around. I've used the following:

I'm strongly recommend you're doing a full backup before flashing the recovery firmware. There might be calibration data in the firmware.

# check if the connection works
esptool.py -p /dev/ttyUSB0 chip_id

# create a backup
esptool.py -p /dev/ttyUSB0 read_flash 0x0 0x200000 shelly_dimmer_v1_backup.bin

# flash the recovery firmware
esptool.py -p /dev/ttyUSB0 write_flash 0x0 dimmer.bin

Please disconnect now GPIO0 and U0TXD and U0RXD. U0RXD and U0TXD is used to communicate with an auxillary micro controller which controls the 230V. If you don't disconnect the U0RXD/U0TXD, a firmware update will be stuck because it can't talk with the micro controller.

Now connect to the Accesspoint of the Shelly, connect it into your wireless network and do a firmware update.

The Shelly Dimmer should be ready to build it into your home again.

November 16, 2022

lynxis

Boot a u-boot via u-boot

Simplified view of the boot process of the mt7622. Romloader to first u-boot to second u-boot to Linux/OpenWrt

Having full control of the boot process is always great. Either because you want to use features the original boot loader doesn't support. Most times a better compression, device-tree support or ubifs to improve resilance against bad blocks. Having the control also improves security because you know what you compiled and with reproducible builds there is also a relation between your source code and your binary. The reasons against replacing the bootloader are usually breaking the device if something bad happens (and you don't have the tools available to get it back into a working state). Or if you want to make it easier to get back to the original state of the device with the OEM firmware. Both doesn't count if you develop a new device or product before it gets released.

For my current project I don't have JTAG working neither is the flash chip on a socket. So testing a new bootloader is hard. In case of a failure I would have to desolder the chip, flash it and solder it again. Flashing it ISP (In-System-Programming) doesn't work often with wifi router or CPEs. If I'm desoldering a flash I always try to add a socket. I can recommend the qspimux from Felix Held. It comes with sockets and a qspimux to switch between the programmer and the board.

For testing the basic functions I would like to boot the u-boot from the current u-boot. At least I can test the higher functions. Does ethernet works to load a second bootloader? Can I boot from the second u-boot via tftp my u-boot?

OpenWrt also have a history of booting u-boot from u-boot in case the old bootloader is too buggy or have other shortcomings, some platforms just add a second u-boot (e.g. kirkwood platform).

To allow us to boot u-boot from u-boot, we should know what's the job of the the first u-boot? Must the hardware in a specific state? And what would be the difference between the first and second u-boot? To get started, everything depend on the architecture (arm, mips, arm64, ..) and the specific SoC what the first u-boot really does.

I've a board with a Mediatek mt7622 SoC based on arm64 (to be precise 4x ARM Cortex A53 cores). We could take a look into the arm manuals how its booting. A summary can be found in the arm trusted firmware repository. The main question we have to find or just test, are there parts of the SoC or components which can't or must not be initialized twice? We should not re-initialize the memory controller if our second u-boot lies in memory.

The good point is the u-boot doesn't do memory initialisation and training it's done by the arm trusted firmware. Another thing we don't have to disable. Let's create a first u-boot image for us using OpenWrt. I expect you already added your board to the u-boot. Otherwise we could just use the already supported mt7622_bananapi_bpi-r64-snand.

# apt install quilt flex bison
cd openwrt
# I'm using OpenWrt, current master of revision c3322cf04a1b9ee826dcc56944750b6bbcb716ef
# Select your board, and config.
# Ensure Boot Loaders ->  u-boot-mt7622_bananapi_bpi-r64-snand is enabled
make menuconfig
make package/boot/arm-trusted-firmware-mediatek/clean package/boot/arm-trusted-firmware-mediatek/compile
make package/uboot-mediatek/clean package/uboot-mediatek/prepare QUILT=1
cd build_dir/target-aarch64_cortex-a53_musl/u-boot-mt7622_mt7622_bananapi_bpi-r64-snand/u-boot-2022.10/
quilt push -a
# now lets change the u-boot config
make mt7622_bananapi_bpi-r64-snand_defconfig
make menuconfig
# choose
* "Skip the call to lowlevel_init during early boot ONLY" (CONFIG_SKIP_LOWLEVEL_INIT_ONLY)
* "Boot options" -> "Boot Images" -> "Text Base" = 0x43e00000 (CONFIG_SYS_TEXT_BASE)
# now go back to the openwrt top dir (where you checkout OpenWrt)
cd openwrt/
make package/uboot-mediatek/compile V=s
cd build_dir/target-aarch64_cortex-a53_musl/u-boot-mt7622_mt7622_bananapi_bpi-r64-snand/u-boot-2022.10/
ls u-boot*
# u-boot:           ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, with debug_info, not stripped
# u-boot-dtb.bin:   u-boot binary with device-tree binary appeneded
# u-boot-nodtb.bin: u-boot binary without device-tree binary
# u-boot.bin:       same as u-boot-dtb.bin
# u-boot.cfg:       The build config as c defines
# u-boot.fip:       u-boot binary packed to be loaded by the arm trusted firmware
# u-boot.lds:       linker script (can be ignored)
# u-boot.map:       linker map file (can be ignored)

cp u-boot-dtb.bin /srv/tftp/

Now I tried to upload the whole binary to from the first u-boot via tftp

# u-boot shell
MT7622> tftpboot 0x43e00000 u-boot-dtb.bin
MT7622> go 0x43e00000
## Starting application at 0x43e00000 ...
data abort
pc : [<4007ff34>]          lr : [<5ef571e4>]
sp : 5cf4fe28  ip : 00000030     fp : 5cf5a818
r10: 00000002  r9 : 5cf4ff40     r8 : 5efa3784
r7 : 5cf5b2d8  r6 : 4007ff28     r5 : 00000002  r4 : 5cf5b2dc
r3 : 4007ff28  r2 : 5cf5b2dc     r1 : 5cf5b2dc  r0 : 00000001
Flags: nZCv  IRQs off  FIQs off  Mode SVC_32
Resetting CPU ...

And now it crashs. Let's take a look back into the u-boot

cd openwrt
cd build_dir/target-aarch64_cortex-a53_musl/u-boot-mt7622_mt7622_bananapi_bpi-r64-snand/u-boot-2022.10/
# first find instruction of the u-boot. It's usually the start.S. We're lazy and search for start.o. The compiled version.
find -iname 'start.o'
## ./arch/arm/cpu/armv8/start.o
# The start.S is in the same directory. Lets have a look into it with your favourite editor
vim ./arch/arm/cpu/armv8/start.S
// [..]
#include <asm/arch/boot0.h>
#else
        b       reset
#endif

        .align 3

.globl  _TEXT_BASE
_TEXT_BASE:
        .quad   CONFIG_SYS_TEXT_BASE

/*
 * These are defined in the linker script.
 */
.globl  _end_ofs
_end_ofs:
        .quad   _end - _start

.globl  _bss_start_ofs
_bss_start_ofs:
        .quad   __bss_start - _start

.globl  _bss_end_ofs
_bss_end_ofs:
        .quad   __bss_end - _start

reset:
        /* Allow the board to save important registers */
        b       save_boot_params
.globl  save_boot_params_ret
save_boot_params_ret:
// [..]

Ok The first instruction should be a branch (or jump) to the marker reset. Let's have a short look into the u-boot-dtb.bin.

cd openwrt/
export PATH=$PATH:$(pwd)/staging_dir/toolchain-aarch64_cortex-a53_gcc-11.3.0_musl/bin
cd build_dir/target-aarch64_cortex-a53_musl/u-boot-mt7622_mt7622_bananapi_bpi-r64-snand/u-boot-2022.10/
# the u-boot file is a elf binary
aarch64-openwrt-linux-objdump -D ./u-boot
0000000041e00000 <__image_copy_start>:
    41e00000:   1400000a        b       41e00028 <reset>
    41e00004:   d503201f        nop

0000000041e00008 <_TEXT_BASE>:
    41e00008:   41e00000        .inst   0x41e00000 ; undefined
    41e0000c:   00000000        udf     #0

0000000041e00010 <_end_ofs>:
    41e00010:   000f21f8        .inst   0x000f21f8 ; undefined
    41e00014:   00000000        udf     #0

0000000041e00018 <_bss_start_ofs>:
    41e00018:   000f21f8        .inst   0x000f21f8 ; undefined
    41e0001c:   00000000        udf     #0

0000000041e00020 <_bss_end_ofs>:
    41e00020:   000fe8c8        .inst   0x000fe8c8 ; undefined
    41e00024:   00000000        udf     #0

0000000041e00028 <reset>:
    41e00028:   14000053        b       41e00174 <save_boot_params>

0000000041e0002c <save_boot_params_ret>:
    41e0002c:   10fffea0        adr     x0, 41e00000 <__image_copy_start>
    41e00030:   f2402c00        ands    x0, x0, #0xfff
    41e00034:   54000060        b.eq    41e00040 <pie_fixup>  // b.none
    41e00038:   d503207f        wfi
    41e0003c:   17ffffff        b       41e00038 <save_boot_params_ret+0xc>
[..]

Ok. This looks good. Maybe the u-boot go command is missing some handover or doesn't initialize the some cpu register or other state? My first u-boot doesn't support elf binary. But it supports the uimage file format.

cd openwrt/
cd build_dir/target-aarch64_cortex-a53_musl/u-boot-mt7622_mt7622_bananapi_bpi-r64-snand/u-boot-2022.10/
mkimage -A arm -O linux  -T standalone -C none -a 0x43e00000 -e 0x43e00000 -d ./u-boot-dtb.bin /srv/tftp/u-boot.image
# u-boot shell
MT7622> tftpboot 0x41000000 u-boot.image
MT7622> bootm 0x41000000

U-Boot 2022.10-OpenWrt-r21176-c32b761842a8 (Nov 15 2022 - 19:27:37 +0000)

CPU:   MediaTek MT7622
...

Finally we managed to boot it. Now we can test the u-boot-env, booting via tftpboot and so on.

EDIT: Fixed 3x typos in the how to build receipt. The u-boot mediatek package in OpenWrt is called uboot-mediatek and not u-boot-mediatek

November 13, 2022

lynxis

Mikrotik wAP R AC / wAP ac LTE / wAP ac LTE6

  • CPU: QCOM IPQ4018 / 4x ARM Cortex A7
  • RAM: 128MB DDR3L NT5CC64M16GP-DI NANYA 1909
  • flash: 16MB SPI-NOR Winbond 25Q128JVSM
  • wifi: 2x 802.11ac, 1x 2.4Ghz, 1x 5Ghz ipq4018 with external lna/pa
  • 2x 1GBit ethernet ports, 1 PoE in, 1 normal ethernet
    • QCA8072 dual port ethernet phy
  • miniPCIe slot: usb2 & simcard but no pcie.
  • ZT2046Q: for voltage and temp sensing. A cheap touchscreen controller compatible to ads7846.
  • high_res_front high_res_back
PCBA of a Mikrotik wAP R AC frontside PCBA of a Mikrotik wAP R AC backside

December 13, 2020

lynxis

d-link dir x-1860 - a mediatek ax board

  • CPU mediatek 7621AT - a ramips based cpu with 2 cores
  • RAM: winbond w632... (too small to read ;)
  • flash: 128 MByte NAND winbond w29n01hvsinf
  • wifi: ax with a mt7915dan (2T2R 2.4 Ghz, 2T2R 5Ghz) + mt7975dn
PCB of a d-link dir x 1860

d-link dir x-1860 - a mediatek ax board

  • CPU mediatek 7621AT - a ramips based cpu with 2 cores
  • RAM: winbond w632... (too small to read ;)
  • flash: 128 MByte NAND winbond w29n01hvsinf
  • wifi: ax with a mt7915dan (2T2R 2.4 Ghz, 2T2R 5Ghz) + mt7975dn
PCB of a d-link dir x 1860

April 26, 2020

lynxis

How to recover a supermicro board with a broken bios firmware

I was asked to take a look on a supermicro server which has been damaged by an firmware update. It was an Supermicro X10DRW-IT. The firmware update was tried by USB storage, but somehow failed.

After powering the system, it went like this:

  • On with all fans for 5 sec
  • Off for 5 sec
  • On with all fans for 5 sec
  • [..]

However it seems the IPMI is still booting through and won't be disconnected from the power as the remaining mainboard does, but the IPMI doesn't accept any bios update anymore.

As preparation I read up on the coreboot support for the Supermicro X10SLM+-F [0]

The bios chip is hidden under the raid controller if you've one.

Supermicro mainboard. Source: Supermicro X10DRW-i/X10DRW-iT USER’S MANUAL Revision 1.2b

First I've taken a look on the BIOS flash. To read the bios flash out, I've used a raspberry pi 3 with a SOIC-8 clip using the SPI bus.

Required tools:

  • raspberry pi with raspian (apt-get install flashrom)
  • some wire cables to the SOIC8 test clip
  • a SOIC-8 test clip (either the cheap ones from aliexpress or the expensive, high quality pomona 5250 [1]).

How you have to connect the SPI SOIC chip is described in [2]. Pin 1 of the SPI chip is where the small hole is on the.

Ensure you Disconnect both power supplies from the mainboard.

sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -r bios
sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -r bios2

sha256sum bios bios2
# ensure the checksum is equal, to ensure you read real things.

strings -n 16 bios
# try to get some strings out of it, ensure you not only read 0xffff or 0x0000.

Next I downloaded the supermicro bios update. Here you can find:

tree .

.
├── DOS
│   ├── AFUDOSU.SMC
│   ├── CHOICE.SMC
│   ├── FDT.smc
│   ├── FLASH.BAT
│   ├── Readme for X10 AMI BIOS-DOS+UEFI.txt
│   └── X10DRW9.B22
└── UEFI
    ├── Readme for X10 AMI BIOS-DOS+UEFI.txt
    ├── X10DRW9.B22
    ├── afuefi.smc
    ├── fdt.smc
    └── flash.nsh

ls -al X10DRW9.B22
-rw------- 1 lynxis users 16777216 Nov 22 16:07  X10DRW9.B22

Sound good, it's size is exact 16 MB, the same size as the bios flash. file also tell me what it is.

file X10DRW9.B22

X10DRW9.B22: Intel serial flash for PCH ROM

Great we found a firmware image with ifd (intel firmware descriptor). Now I've looked on the BIOS backup we read with the raspberry pi.

I used hexdump -C bios to see if the end contains a lot of 1s (or 0xffff in hex). Why? Because if you want to write a SPI flash, you can not just write to it like a hard drive. SPI flash chips are organised in blocks. A block is usally 64 kbyte. A single bit on a flash chip can only be written to a 0. If you want to write a single bit with a 1 where a 0 was before (0 -> 1), you've to erase the whole block, not only the address. An erase blocked is full of 1. To find out, if we have a half written flash, we can try to look on the end of the flash if there are a lot of 1s (or 0xffffffff).

hexdump -C is showing it quite nice

00c2ee20  4d 50 44 54 00 01 00 00  10 00 00 00 00 00 10 00  |MPDT............|
00c2ee30  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
01000000

This means, it only written up to 0x00c2ee30 (12.2 MB). Now we can look into the downloaded image, if it looks similiar. Maybe here starts configuration data. But no, it's missing some data here.

Next task is to flash the bios section. Bios section? The intel firmware description contains section. Similiar to a partition layout on a hard drive. On this platform there are 3 different sections

00000000:00000fff fd
00400000:00ffffff bios
00011000:003fffff me
  • fd stands for firmware descriptor
  • bios stands for the x86 firmware or UEFI
  • me for the management engine (also called on servers "Server Platform Services")

To flash only the partition you either have to use a recent flashrom version (at least 1.0) or you've to extract the layout file using the ifdtool (from coreboot). You can also use the last code snipped as layout.

flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -l layout -i bios -w X10DRW9.B22

It verifies it after writing to it. But still it doesn't work. My next thought was maybe the IPMI flash got damaged as well. The SPI flash of the IPMI is close by. So let's have a look. I was lucky to also have a SOIC-16 test clip available. I did the same procedure on the IPMI flash. However the flashrom in raspian was too old. The flash chip wasn't known to this version flashrom. I had to compile it myself.

sudo apt install git build-essential
git clone https://review.coreboot.org/flashrom.git
cd flashrom
make CONFIG_ENABLE_LIBPCI_PROGRAMMERS=no CONFIG_ENABLE_LIBUSB1_PROGRAMMERS=no
./flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -r ipmi

But it looks good so far. Running binwalk on it shows us

binwalk ipmi

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
103328        0x193A0         CRC32 polynomial table, little endian
1048576       0x100000        JFFS2 filesystem, little endian
4194304       0x400000        CramFS filesystem, little endian, size: 15216640, version 2, sorted_dirs, CRC 0xB1031FF3, edition 0, 8613 blocks, 1099 files
20971520      0x1400000       uImage header, header size: 64 bytes, header CRC: 0x3F1E0DA5, created: 2019-11-15 08:36:11, image size: 1537512 bytes, Data Address: 0x40008000, Entry Point: 0x40008000, data CRC: 0x310498CA, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: gzip, image name: "21400000"
20971584      0x1400040       gzip compressed data, maximum compression, has original file name: "linux.bin", from Unix, last modified: 2019-11-15 07:25:15
24117248      0x1700000       CramFS filesystem, little endian, size: 7458816, version 2, sorted_dirs, CRC 0xF5B9463B, edition 0, 3108 blocks, 466 files

Looks also good, however I want to be sure, it's the fine. I did first a backup, second overwritten with a file from the IPMI firmware update.

Still no change.

So what's wrong here? Is the power management controller damaged? The power supply are controller digital via I2C. Maybe it's somehow telling me something is wrong?

I was lucky, I didn't had a i2c sniffer around, otherwise I would have digged into it. I nearly gave it up, before I found out, that the backup file didn't worked with ifdtool. I exported the layout using the firmware update file, and not with the backup file. Usually firmware updates do not touch the ifd. It seems server boards are different. So the backup didn't contained an ifd. It wasn't only damaged in the end, also in the beginning. Not sure if this is a safety feature of the update. It might ensure at the beginning of an update the partial flash wouldn't be recognized as a working image. It's not a good thing booting a half working image.

I flashed the bios firmware update image and the board is back. To be sure, I flashed the ipmi backup on the SPI chip.

TLDR; So the fast way to recover a partial bios, do a backup first! Then flash the full image. At least for this generation it works.

Note: Depending on your specific hardware setup (cable length, test clip) you can increase or decrease the spispeed. spispeed=10000 => 10 MHz should be still ok. You'll notice the wrong spispeed if the reading or flashing fails.

[0] https://doc.coreboot.org/mainboard/supermicro/x10slm-f.html

[1] https://www.pomonaelectronics.com/products/test-clips/soic-clip-8-pin

[2] https://github.com/bibanon/Coreboot-ThinkPads/wiki/Hardware-Flashing-with-Raspberry-Pi

How to recover a supermicro board with a broken bios firmware

I was asked to take a look on a supermicro server which has been damaged by an firmware update. It was an Supermicro X10DRW-IT. The firmware update was tried by USB storage, but somehow failed.

After powering the system, it went like this:

  • On with all fans for 5 sec
  • Off for 5 sec
  • On with all fans for 5 sec
  • [..]

However it seems the IPMI is still booting through and won't be disconnected from the power as the remaining mainboard does, but the IPMI doesn't accept any bios update anymore.

As preparation I read up on the coreboot support for the Supermicro X10SLM+-F [0]

The bios chip is hidden under the raid controller if you've one.

Supermicro mainboard. Source: Supermicro X10DRW-i/X10DRW-iT USER’S MANUAL Revision 1.2b

First I've taken a look on the BIOS flash. To read the bios flash out, I've used a raspberry pi 3 with a SOIC-8 clip using the SPI bus.

Required tools:

  • raspberry pi with raspian (apt-get install flashrom)
  • some wire cables to the SOIC8 test clip
  • a SOIC-8 test clip (either the cheap ones from aliexpress or the expensive, high quality pomona 5250 [1]).

How you have to connect the SPI SOIC chip is described in [2]. Pin 1 of the SPI chip is where the small hole is on the.

Ensure you Disconnect both power supplies from the mainboard.

sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -r bios
sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -r bios2

sha256sum bios bios2
# ensure the checksum is equal, to ensure you read real things.

strings -n 16 bios
# try to get some strings out of it, ensure you not only read 0xffff or 0x0000.

Next I downloaded the supermicro bios update. Here you can find:

tree .

.
├── DOS
   ├── AFUDOSU.SMC
   ├── CHOICE.SMC
   ├── FDT.smc
   ├── FLASH.BAT
   ├── Readme for X10 AMI BIOS-DOS+UEFI.txt
   └── X10DRW9.B22
└── UEFI
    ├── Readme for X10 AMI BIOS-DOS+UEFI.txt
    ├── X10DRW9.B22
    ├── afuefi.smc
    ├── fdt.smc
    └── flash.nsh

ls -al X10DRW9.B22
-rw------- 1 lynxis users 16777216 Nov 22 16:07  X10DRW9.B22

Sound good, it's size is exact 16 MB, the same size as the bios flash. file also tell me what it is.

file X10DRW9.B22

X10DRW9.B22: Intel serial flash for PCH ROM

Great we found a firmware image with ifd (intel firmware descriptor). Now I've looked on the BIOS backup we read with the raspberry pi.

I used hexdump -C bios to see if the end contains a lot of 1s (or 0xffff in hex). Why? Because if you want to write a SPI flash, you can not just write to it like a hard drive. SPI flash chips are organised in blocks. A block is usally 64 kbyte. A single bit on a flash chip can only be written to a 0. If you want to write a single bit with a 1 where a 0 was before (0 -> 1), you've to erase the whole block, not only the address. An erase blocked is full of 1. To find out, if we have a half written flash, we can try to look on the end of the flash if there are a lot of 1s (or 0xffffffff).

hexdump -C is showing it quite nice

00c2ee20  4d 50 44 54 00 01 00 00  10 00 00 00 00 00 10 00  |MPDT............|
00c2ee30  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
01000000

This means, it only written up to 0x00c2ee30 (12.2 MB). Now we can look into the downloaded image, if it looks similiar. Maybe here starts configuration data. But no, it's missing some data here.

Next task is to flash the bios section. Bios section? The intel firmware description contains section. Similiar to a partition layout on a hard drive. On this platform there are 3 different sections

00000000:00000fff fd
00400000:00ffffff bios
00011000:003fffff me
  • fd stands for firmware descriptor
  • bios stands for the x86 firmware or UEFI
  • me for the management engine (also called on servers "Server Platform Services")

To flash only the partition you either have to use a recent flashrom version (at least 1.0) or you've to extract the layout file using the ifdtool (from coreboot). You can also use the last code snipped as layout.

flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -l layout -i bios -w X10DRW9.B22

It verifies it after writing to it. But still it doesn't work. My next thought was maybe the IPMI flash got damaged as well. The SPI flash of the IPMI is close by. So let's have a look. I was lucky to also have a SOIC-16 test clip available. I did the same procedure on the IPMI flash. However the flashrom in raspian was too old. The flash chip wasn't known to this version flashrom. I had to compile it myself.

sudo apt install git build-essential
git clone https://review.coreboot.org/flashrom.git
cd flashrom
make CONFIG_ENABLE_LIBPCI_PROGRAMMERS=no CONFIG_ENABLE_LIBUSB1_PROGRAMMERS=no
./flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -r ipmi

But it looks good so far. Running binwalk on it shows us

binwalk ipmi

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
103328        0x193A0         CRC32 polynomial table, little endian
1048576       0x100000        JFFS2 filesystem, little endian
4194304       0x400000        CramFS filesystem, little endian, size: 15216640, version 2, sorted_dirs, CRC 0xB1031FF3, edition 0, 8613 blocks, 1099 files
20971520      0x1400000       uImage header, header size: 64 bytes, header CRC: 0x3F1E0DA5, created: 2019-11-15 08:36:11, image size: 1537512 bytes, Data Address: 0x40008000, Entry Point: 0x40008000, data CRC: 0x310498CA, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: gzip, image name: "21400000"
20971584      0x1400040       gzip compressed data, maximum compression, has original file name: "linux.bin", from Unix, last modified: 2019-11-15 07:25:15
24117248      0x1700000       CramFS filesystem, little endian, size: 7458816, version 2, sorted_dirs, CRC 0xF5B9463B, edition 0, 3108 blocks, 466 files

Looks also good, however I want to be sure, it's the fine. I did first a backup, second overwritten with a file from the IPMI firmware update.

Still no change.

So what's wrong here? Is the power management controller damaged? The power supply are controller digital via I2C. Maybe it's somehow telling me something is wrong?

I was lucky, I didn't had a i2c sniffer around, otherwise I would have digged into it. I nearly gave it up, before I found out, that the backup file didn't worked with ifdtool. I exported the layout using the firmware update file, and not with the backup file. Usually firmware updates do not touch the ifd. It seems server boards are different. So the backup didn't contained an ifd. It wasn't only damaged in the end, also in the beginning. Not sure if this is a safety feature of the update. It might ensure at the beginning of an update the partial flash wouldn't be recognized as a working image. It's not a good thing booting a half working image.

I flashed the bios firmware update image and the board is back. To be sure, I flashed the ipmi backup on the SPI chip.

TLDR; So the fast way to recover a partial bios, do a backup first! Then flash the full image. At least for this generation it works.

Note: Depending on your specific hardware setup (cable length, test clip) you can increase or decrease the spispeed. spispeed=10000 => 10 MHz should be still ok. You'll notice the wrong spispeed if the reading or flashing fails.

[0] https://doc.coreboot.org/mainboard/supermicro/x10slm-f.html

[1] https://www.pomonaelectronics.com/products/test-clips/soic-clip-8-pin

[2] https://github.com/bibanon/Coreboot-ThinkPads/wiki/Hardware-Flashing-with-Raspberry-Pi