The open source ESP8266 esptool that’s part of the esp-open-sdk is used as a tool to create a firmware image from elf image/binary. It is also used to flash/program an ESP8266 with this firmware image. In addition you can do the opposite, download a firmware image.


Browsing through the source code I found an interesting piece of binary blob I just had to take a closer look at.

# Sflash stub: an assembly routine to read from spi flash and send to host
SFLASH_STUB = "\x80\x3c\x00\x40\x1c\x4b\x00\x40\x21\x11\x00\x40\x00\x80\xfe" \
              "\x3f\xc1\xfb\xff\xd1\xf8\xff\x2d\x0d\x31\xfd\xff\x41\xf7\xff" \
              "\x4a\xdd\x51\xf9\xff\xc0\x05\x00\x21\xf9\xff\x31\xf3\xff\x41" \

It is used in the following python function.

""" Read SPI flash """
def flash_read(self, offset, size, count=1):
    # Create a custom stub
    stub = struct.pack('<III', offset, size, count) + self.SFLASH_STUB

    # Trick ROM to initialize SFlash
    self.flash_begin(0, 0)

    # Download stub
    self.mem_begin(len(stub), 1, len(stub), 0x40100000)
    self.mem_block(stub, 0)

This means the stub is prefixed with 3x 32bit integers, respectively offset, size and count. The stub plus prefix is flashed into memory @ 0x40100000 and then execution starts @ 0x4010001c meaning that first 4x 32bit integers of the stub is probably data.


I figured, this was a perfect use case of showing how to use radare. Here it is: asciinema

There you have it! esptool uploads the sflash stub and executes it. The stub itself contains a small function which calls two functions in a loop. First SPIRead is called to fetch a block from flash into RAM. Then send_pakcet is called to send this block back over UART. Both SPIRead and send_packet resides in ROM and are so called ROM functionality.