Skip to content

Firmware Storage Formats

The SkyWalker-1 firmware exists in multiple container formats depending on context: the onboard EEPROM uses the Cypress C2 IIC boot format, the Linux kernel expects a custom binary hexline format, and analysis tools work with flat extracted binaries.

Cypress C2 IIC Second-Stage Boot Format Device Storage

Section titled “Cypress C2 IIC Second-Stage Boot Format ”

This is the native format stored in the SkyWalker-1’s onboard I2C EEPROM. The FX2’s internal boot ROM reads this format on power-up.

The 0xC2 marker byte in the header identifies this as “external memory, large code model” — it tells the boot ROM to load code from the EEPROM into internal RAM using the segment map that follows.

Offset Size Field Value (SkyWalker-1)
------ ---- ---------- -------------------
0x00 1 marker 0xC2 (external memory, large code model)
0x01 2 VID 0xC009 -> 0x09C0 (little-endian, Genpix)
0x03 2 PID 0x0302 -> 0x0203 (little-endian, SkyWalker-1)
0x05 2 DID 0x0000 (device ID, unused)
0x07 1 config 0x40 (400 kHz I2C bus speed)

The VID and PID in the C2 header determine the USB identifiers that the FX2 enumerates with after boot. This is how the kernel driver identifies the device model.

ValueI2C SpeedNotes
0x00100 kHzDefault if EEPROM missing
0x20200 kHz
0x40400 kHzUsed by SkyWalker-1

Following the 8-byte header, one or more code segments:

Offset Size Field
------ ---------- -----
0 2 seg_len (big-endian) -- number of data bytes
2 2 seg_addr (big-endian) -- target RAM address
4 seg_len data[] -- code/data bytes

Segments are packed contiguously. The 1023-byte maximum segment size is the limit of the FX2 boot ROM’s internal I2C read buffer.

Offset Size Field
------ ---- -----
0 2 0x8001 -- high bit set signals terminator (length with MSB set)
2 2 entry -- entry point address (big-endian) = 0xE600 (CPUCS)

Writing to CPUCS (0xE600) with value 0x00 releases the CPU from reset and begins execution at the reset vector (0x0000).

FileVIDPIDDIDI2C SpeedCode Size
skywalker1_eeprom.bin (v2.06)0x09C00x02030x0000400 kHz9,472 bytes
sw1_v213_fw_1_c2.bin (v2.13.1)0x09C00x02030x0000400 kHz9,322 bytes
sw1_v213_fw_2_c2.bin (v2.13.2)0x09C00x02030x0000400 kHz9,377 bytes
sw1_v213_fw_3_c2.bin (v2.13.3)0x09C00x02030x0000400 kHz9,369 bytes
rev2_v210_fw_1_c2.bin (Rev.2)0x09C00x02020x0000400 kHz8,843 bytes

All SkyWalker-1 C2 files use uniform 1023-byte segments (except the last):

SegmentAddressLengthNotes
10x00001023Reset vector, interrupt handlers
20x03FF1023
30x07FE1023
40x0BFD1023
50x0FFC1023
60x13FB1023
70x17FA1023
80x1BF91023
90x1FF81023
100x23F7varies115—265 bytes depending on version

The address of each segment is exactly previous_addr + 1023, creating a contiguous mapping from 0x0000 to the end of the firmware image.

Rev.2 has only 9 segments (one fewer than SkyWalker-1 variants) because its firmware is smaller:

SegmentAddressLength
10x00001023
20x03FF1023
30x07FE1023
40x0BFD1023
50x0FFC1023
60x13FB1023
70x17FA1023
80x1BF91023
90x1FF8659

This format is used exclusively by dvb-usb-gp8psk-01.fw for loading firmware into Rev.1 Cold devices (PID 0x0200). The SkyWalker-1 never uses this format at runtime.

Offset Size Field
------ ---- -----
0 1 len Number of data bytes in this record
1 1 addr_lo Target address, low byte
2 1 addr_hi Target address, high byte
3 1 type Record type
4 len data[] Payload bytes
4+len 1 chk Checksum byte
Total per record: len + 5 bytes
TypeNamePurpose
0x00DataWrite data bytes to FX2 RAM at address (addr_hi * 256 + addr_lo)
0x01EOFEnd of file, no more records
0x04Extended Linear Addressdata[0]:data[1] = upper 16 bits of target address

Files from other DVB-USB devices confirm the format:

FileSizeFirst Record
dvb-usb-dib0700-1.20.fw33,768len=2, addr=0x0000, type=0x04
dvb-usb-it9135-01.fw8,128len=3, addr=0x0000, type=0x03
dvb-usb-it9135-02.fw5,834len=3, addr=0x0000, type=0x03

The complete EEPROM can be dumped as a 65,536-byte raw image. The firmware occupies the first ~10 KB; the remainder contains:

Offset RangeContent
0x00000x0007C2 header (8 bytes)
0x00080x25xxCode segments (varies by version)
0x25xx0x26xxC2 terminator
0x27000x3FFFPadding / unused (typically 0xFF)
0x40000x7FFFMirror/unused (some EEPROMs wrap at 32K)

Extract raw code from a C2 file by stripping headers:

C2 to flat binary extraction
def c2_to_flat(c2_data):
"""Extract flat binary from C2 EEPROM format."""
pos = 8 # Skip 8-byte C2 header
flat = bytearray(0x10000) # 64K address space
while pos < len(c2_data):
seg_len = (c2_data[pos] << 8) | c2_data[pos + 1]
seg_addr = (c2_data[pos + 2] << 8) | c2_data[pos + 3]
pos += 4
if seg_len & 0x8000: # Terminator (high bit set)
break
flat[seg_addr:seg_addr + seg_len] = c2_data[pos:pos + seg_len]
pos += seg_len
return flat

Theoretical conversion for producing a dvb-usb-gp8psk-01.fw equivalent:

C2 to kernel hexline conversion
def c2_to_hexline(c2_data):
"""Convert C2 EEPROM format to kernel binary hexline."""
records = bytearray()
flat = c2_to_flat(c2_data)
code_end = find_code_end(flat)
for addr in range(0, code_end, 16):
chunk = flat[addr:addr + 16]
rec_len = len(chunk)
addr_lo = addr & 0xFF
addr_hi = (addr >> 8) & 0xFF
rec_type = 0x00 # Data record
chk = (rec_len + addr_lo + addr_hi + rec_type
+ sum(chunk)) & 0xFF
records.extend([rec_len, addr_lo, addr_hi, rec_type])
records.extend(chunk)
records.append((~chk + 1) & 0xFF)
# EOF record
records.extend([0x00, 0x00, 0x00, 0x01, 0xFF])
return records

For the v2.06 firmware (9,472 code bytes), this produces approximately 12,442 bytes in hexline format.

Quick format identification by examining the first byte:

First ByteFormatNotes
0xC2C2 EEPROMStandard SkyWalker-1 EEPROM dump
0xC0C0 EEPROMVID/PID-only header (no code segments)
0x02Flat binaryLikely starts with LJMP instruction (0x02 xx xx)
OtherHexline or unknownCheck record structure