EEPROM Utilities
Three tools manage the SkyWalker-1’s I2C EEPROM (24Cxx-family at address 0x51): eeprom_write.py for flashing firmware images, eeprom_dump.py for reading EEPROM contents, and eeprom_probe.py for testing I2C addressing methods.
The EEPROM stores the Cypress FX2 boot firmware in C2 IIC format. The FX2 loads this firmware automatically on every power-up. Writing incorrect data to the EEPROM will prevent the device from enumerating on USB.
pip install pyusbEEPROM Flash Tool
Section titled “EEPROM Flash Tool”eeprom_write.py is the full-featured EEPROM management tool with four subcommands.
Subcommands
Section titled “Subcommands”| Subcommand | Purpose |
|---|---|
info | Parse and display C2 header from a .bin file (offline, no device needed) |
backup | Dump current EEPROM contents to a file |
verify | Compare a .bin file against current EEPROM contents |
flash | Write a C2 firmware image to the EEPROM |
info — Inspect a C2 Image File
Section titled “info — Inspect a C2 Image File”Parse and display the C2 header and load records from a firmware binary without connecting to the device.
python3 tools/eeprom_write.py info firmware.binC2 Image: firmware.binFile size: 9512 bytes========================================
Header: Format: C2 (Large EEPROM, code loads to internal RAM) VID: 0x09C0 (Genpix) PID: 0x0203 (SkyWalker-1) DID: 0x0000 Config: 0x40 (400kHz I2C)
Load Records: [0] 1023 bytes -> 0x0000-0x03FE [02 18 8d 78 7f e4 f6 d8...] [1] 1023 bytes -> 0x03FF-0x07FD [...] ... [9] 115 bytes -> 0x23F7-0x2469 [...] [10] END MARKER -> entry point: 0xE600
Total firmware: 9472 bytes in 10 segments Entry point: 0xE600 (LJMP target after boot)
EEPROM footprint: 9512 bytes (0x2528)backup — Read EEPROM to File
Section titled “backup — Read EEPROM to File”sudo python3 tools/eeprom_write.py backup -o my_backup.binsudo python3 tools/eeprom_write.py backup -o my_backup.bin --max-size 16384| Flag | Description |
|---|---|
-o, --output FILE | Output file (default: skywalker1_eeprom.bin) |
--max-size BYTES | Maximum bytes to read (default: 16384) |
verify — Compare Image Against EEPROM
Section titled “verify — Compare Image Against EEPROM”Read the EEPROM and compare byte-by-byte against a local .bin file. Reports any mismatches with offset and expected vs. actual values.
sudo python3 tools/eeprom_write.py verify firmware.binExit code 0 = match, 1 = mismatch.
flash — Write Image to EEPROM
Section titled “flash — Write Image to EEPROM”The flash workflow includes built-in safety measures: image validation, VID/PID check, automatic backup, countdown timer, write verification.
- Validate the C2 image file (header format, VID/PID match, record integrity)
- Connect to the SkyWalker-1 and check device VID/PID against the image
- Backup the current EEPROM contents to a timestamped file
- Wait 3 seconds with a countdown (Ctrl-C to abort)
- Write the image in 16-byte page-aligned chunks with 10 ms write cycle delays
- Verify by reading back and comparing every byte
sudo python3 tools/eeprom_write.py flash firmware.binsudo python3 tools/eeprom_write.py flash firmware.bin --dry-runsudo python3 tools/eeprom_write.py flash firmware.bin --no-backupsudo python3 tools/eeprom_write.py flash firmware.bin --force| Flag | Description |
|---|---|
FILE | C2 firmware image (positional, required) |
--dry-run | Validate and show plan without writing |
--no-backup | Skip pre-flash EEPROM backup |
--force | Override VID/PID mismatch check |
EEPROM Write Parameters
Section titled “EEPROM Write Parameters”| Parameter | Value |
|---|---|
| I2C slave address | 0x51 (7-bit) |
| Vendor command (write) | I2C_WRITE (0x83) |
| Vendor command (read) | I2C_READ (0x84) |
| Page size | 16 bytes (conservative for 24Cxx) |
| Write cycle time | 10 ms per page |
| Maximum image size | 16,384 bytes (16 KB) |
EEPROM Dump Tool
Section titled “EEPROM Dump Tool”eeprom_dump.py is a simpler read-only tool focused on extracting and analyzing EEPROM contents.
sudo python3 tools/eeprom_dump.py -o eeprom.binsudo python3 tools/eeprom_dump.py -o eeprom.bin --extractOptions
Section titled “Options”| Flag | Description |
|---|---|
-o, --output FILE | Output file (default: skywalker1_eeprom.bin) |
--extract | Extract firmware as flat binary + full 64K image |
--max-size BYTES | Maximum EEPROM size to read (default: 16384) |
Auto-Detect End of Data
Section titled “Auto-Detect End of Data”The tool detects the end of valid data by watching for consecutive 0xFF chunks (4 or more = end of programmed region). This avoids reading the entire EEPROM when only the first few KB contain firmware.
Extract Mode (—extract)
Section titled “Extract Mode (—extract)”When --extract is specified, the tool additionally produces:
*_flat.bin— firmware code extracted from C2 records, stored as a flat binary covering only the used address range*_full64k.bin— full 64 KB memory image (unused regions filled with0xFF), suitable for loading in Ghidra at base address0x0000
Output
Section titled “Output”Genpix SkyWalker-1 EEPROM Dump========================================Found device: Bus 1 Addr 12
Reading EEPROM (max 16384 bytes)... End of data at 0x2600 (0xFF padding) Read 9728 bytes total Saved raw EEPROM to: eeprom.bin
========================================EEPROM Header: Format: C2 (Large EEPROM, code loads to internal RAM) VID: 0x09C0 (Genpix) PID: 0x0203 (SkyWalker-1) DID: 0x0000 Config: 0x40 (400kHz I2C)
Load Records: [0] 1023 bytes -> 0x0000-0x03FE [02 18 8d 78 7f e4 f6 d8...] ... [10] END MARKER -> entry point: 0xE600
Total firmware: 9472 bytes in 10 records Entry point: 0xE600 (LJMP target after boot)EEPROM Address Probe
Section titled “EEPROM Address Probe”eeprom_probe.py is a diagnostic script that tests different I2C addressing methods to determine how the Genpix firmware’s I2C_READ/I2C_WRITE commands interpret wValue and wIndex parameters for EEPROM access.
This is a developer tool used during reverse engineering. It runs 7 different addressing approaches and checks each result against known reference bytes from the EEPROM header.
sudo python3 tools/eeprom_probe.pyTest Approaches
Section titled “Test Approaches”| Approach | Method | Description |
|---|---|---|
| 1 | I2C_WRITE data=[addr_h, addr_l] then I2C_READ | Set EEPROM offset via write data |
| 2 | wValue=addr, wIndex=slave | Reversed parameter mapping |
| 3 | wValue=slave, wIndex=addr | Standard Genpix mapping |
| 4 | I2C_READ wIndex=offset | Offset in wIndex field |
| 5 | wValue=(slave<<8|offset) | Packed slave + offset |
| 6 | wValue=offset (no slave) | Offset only, no slave address |
| 7 | Larger reads (64 bytes) | Verify sequential data across page boundaries |
Known Reference Bytes
Section titled “Known Reference Bytes”The script compares against two known patterns:
- Offset 0x0000:
C2 C0 09 03 02 00 00 40(C2 header: marker, VID, PID, DID, config) - Offset 0x0008:
03 FF 00 00 02 18 8D 30(first load record)
Cypress C2 Boot Format
Section titled “Cypress C2 Boot Format”The EEPROM stores firmware in the Cypress C2 IIC second-stage boot format:
| Field | Offset | Size | Description |
|---|---|---|---|
| Marker | 0 | 1 | 0xC2 (large EEPROM, external memory) |
| VID | 1 | 2 | USB Vendor ID, little-endian (0x09C0) |
| PID | 3 | 2 | USB Product ID, little-endian (0x0203) |
| DID | 5 | 2 | Device ID, little-endian |
| Config | 7 | 1 | Boot config (0x40 = 400 kHz I2C) |
| Records | 8+ | var | Code segments: [len_hi][len_lo][addr_hi][addr_lo][data...] |
| End | last | 4 | [0x80][0x01][entry_hi][entry_lo] (entry point = 0xE600) |
For a full description of the storage format, see Firmware Storage Formats.
See Also
Section titled “See Also”- Firmware Loader — RAM-based firmware loading (non-destructive)
- Storage Formats — C2 format, hexline, and FW02 chunk details
- Version Comparison — differences across firmware versions
- I2C Bus Architecture — I2C protocol details