Firmware Version Comparison
Five firmware versions have been analyzed through Ghidra reverse engineering and source code review. This page compares their architecture, features, and binary characteristics.
Version Summary
Section titled “Version Summary”| Firmware | Version ID | Build Date | Target PID | Functions | Binary Size | Stack Pointer |
|---|---|---|---|---|---|---|
| v2.06.04 | 0x020604 | 2007-07-13 | 0x0203 | 61 | 9,472 bytes | 0x72 |
| Rev.2 v2.10.04 | 0x020A04 | 2010-03-12 | 0x0202 | 107 | 8,843 bytes | 0x4F |
| v2.13.01 (FW1) | 0x020D01 | 2010-03-12 | 0x0203 | 82-88 | 9,322 bytes | 0x50 |
| v2.13.02 (FW2) | 0x020D01 | 2010-03-12 | 0x0203 | 83 | 9,377 bytes | 0x50 |
| v2.13.03 (FW3) | 0x020D01 | 2010-03-12 | 0x0203 | 83 | 9,369 bytes | 0x52 |
| Custom v3.01.0 | 0x030100 | 2026-02-12 | 0x0203 | N/A | ~3 KB (RAM) | N/A |
Version-by-Version Details
Section titled “Version-by-Version Details”v2.06.04 Stock
Section titled “v2.06.04 ”The original SkyWalker-1 firmware extracted from the device’s onboard EEPROM.
| Property | Value |
|---|---|
| Version ID | 0x020604 |
| Build date | 2007-07-13 |
| Functions | 61 |
| Binary size | 9,472 bytes |
| Stack pointer | 0x72 |
| Config byte IRAM | 0x6D |
| Descriptor base | 0x1200 |
| Init table address | CODE:0B46 |
| Vendor commands | 30 (0x80—0x9D) |
| DiSEqC data pin | P0.7 |
Characteristics:
- Simplest firmware with the fewest functions
- INT0 handler performs USB re-enumeration (CPUCS pulse)
- No demodulator probe at boot
- No retry loops or integrity verification
- BCM4500 status polling reads 3 registers (0xA2, 0xA8, 0xA4) up to 6 times
- Commands 0x99, 0x9A, 0x9C route to STALL
- Command 0x9D reads descriptor byte and sets mode flag based on hardware revision (4, 5, or 6)
Rev.2 v2.10.04 Transitional
Section titled “Rev.2 v2.10.04 ”Firmware for the Rev.2 hardware variant (PID 0x0202). Architecturally sits between v2.06 and v2.13.
| Property | Value |
|---|---|
| Version ID | 0x020A04 |
| Build date | 2010-03-12 |
| Functions | 107 (most of any version) |
| Binary size | 8,843 bytes (smallest) |
| Stack pointer | 0x4F |
| Config byte IRAM | 0x4E |
| Descriptor base | 0x0E00 |
| Init table address | CODE:0B48 |
| Vendor commands | 27 (0x80—0x9A) |
| DiSEqC data pin | P0.4 |
Characteristics:
- Highest function count due to granular decomposition (10-30 byte helper functions)
- Smallest binary despite having the most functions
- Retained v2.06’s INT0 USB re-enumeration behavior
- Already adopted v2.13’s descriptor base (
0x0E00) and similar stack pointer - Contains
FUN_CODE_0800: a massive 874-byte configuration dispatcher with embedded main loop - Lacks v2.13’s demodulator polling, retry loops, and additional vendor commands (0x9B—0x9D out of range)
- 0x99/0x9A present as prototype implementations
See the Rev.2 Analysis page for the complete 107-function inventory.
v2.13.01 (FW1) Stock
Section titled “v2.13.01 (FW1) ”The most feature-complete stock firmware, targeting the original I2C-connected SkyWalker-1 hardware.
| Property | Value |
|---|---|
| Version ID | 0x020D01 |
| Build date | 2010-03-12 |
| Functions | 82-88 |
| Binary size | 9,322 bytes |
| Stack pointer | 0x50 |
| Config byte IRAM | 0x4F |
| Descriptor base | 0x0E00 |
| Init table address | CODE:0B88 |
| Vendor commands | 30 (0x80—0x9D) |
| DiSEqC data pin | P0.0 |
New features over v2.06:
- Three new vendor commands:
0x99(GET_DEMOD_STATUS),0x9A(INIT_DEMOD),0x9C(DELAY_COMMAND) - INT0 repurposed for demodulator availability polling (40 attempts at addresses 0x7F and 0x3F)
- USB re-enumeration moved to
FUN_CODE_2031(called as normal function before main loop) - Demodulator signature verification (
FUN_CODE_1799) with 20 retry attempts - Descriptor checksum verification (
FUN_CODE_1ca0) with 20 retry attempts - Hardware revision detection via descriptor byte (flag
_1_3) - Consolidated BCM4500 status polling (1 register instead of 3)
- Anti-tampering string at firmware offset 0x1880
See the FW2.13 Variants page for sub-variant comparison.
Custom v3.01.0 Custom
Section titled “Custom v3.01.0 ”Open-source replacement firmware built with SDCC + fx2lib. RAM-loaded for testing.
| Property | Value |
|---|---|
| Version ID | 0x030100 |
| Build date | 2026-02-12 |
| Toolchain | SDCC + fx2lib |
| Source | firmware/skywalker1.c (1351 lines) |
| Binary size | ~3 KB |
| Load method | RAM upload via tools/fw_load.py |
| DiSEqC data pin | P0.7 (v2.06 assignment) |
Additions over stock:
- Seven new diagnostic commands (
0xB0—0xB6) - Incremental debug boot modes (wValue
0x80—0x85for BOOT_8PSK) - I2C timeout protection (6000-iteration countdown vs. infinite spin)
- I2C bus scan for device discovery
- Spectrum sweep and blind scan capabilities
- Raw BCM4500 register access
See the Custom v3.01 page for full details.
Architectural Differences
Section titled “Architectural Differences”| Feature | v2.06 | Rev.2 v2.10 | v2.13 | Custom v3.01 |
|---|---|---|---|---|
| Vendor commands | 30 | 27 | 30 | 30 stock + 7 custom |
| INT0 handler | USB re-enum | USB re-enum | Demod polling | N/A (fx2lib ISR) |
| Demod probe at boot | No | No | Yes (40 attempts) | Yes (with timeout) |
| Retry loops | No | No | Yes (20-attempt) | Yes (with timeout) |
| HW revision detect | No | Yes (descriptor walker) | Yes (flag _1_3) | No |
| DiSEqC data pin | P0.7 | P0.4 | P0.0 | P0.7 |
| Config byte IRAM addr | 0x6D | 0x4E | 0x4F | C variable |
| BCM4500 status poll | 3 registers | 3 registers | 1 register | 1 register |
| I2C timeout | None | None | None | 6000-count |
| Anti-tampering | No | No | Yes | No |
| New commands | — | 0x99/0x9A proto | 0x99, 0x9A, 0x9C | 0xB0—0xB6 |
| 0x9D behavior | HW revision mode | N/A (out of range) | Conditional demod reset | N/A |
Kernel Version Constants
Section titled “Kernel Version Constants”The Linux kernel driver defines two firmware version thresholds in gp8psk-fe.h:
GP8PSK_FW_REV1 = 0x020604 // v2.06.4GP8PSK_FW_REV2 = 0x020704 // v2.07.4If the firmware version reported by GET_FW_VERS (command 0x92) is >= GP8PSK_FW_REV2, the kernel enables Rev.2-specific code paths. All v2.10 and v2.13 firmwares are newer than either constant.
Binary Similarity Matrix
Section titled “Binary Similarity Matrix”Byte-level comparison across the shared code length (percentage of identical bytes):
| v2.06 | v2.13.1 | v2.13.2 | v2.13.3 | Rev.2 | |
|---|---|---|---|---|---|
| v2.06 | — | 4.8% | 4.3% | 4.3% | 6.0% |
| v2.13.1 | — | 57.2% | 59.4% | 8.0% | |
| v2.13.2 | — | 83.5% | 5.8% | ||
| v2.13.3 | — | 5.8% | |||
| Rev.2 | — |
Key Function Correspondence
Section titled “Key Function Correspondence”Functions that serve the same role but reside at different addresses:
| Role | v2.06 | Rev.2 | v2.13 |
|---|---|---|---|
| RESET vector / main | 0x188D | 0x155F | 0x170D |
| Main init + loop | 0x09A7 | 0x09A9 | 0x0800 |
| USB descriptor setup | 0x13C3 | 0x10D9 | 0x11AB |
| Standard USB handler | 0x032A | 0x0319 | 0x034E |
| Vendor cmd dispatch | 0x0056 | 0x0056 | 0x0056 |
| Main loop poll | 0x2297 | — | 0x21EC |
| GPIF/FIFO management | 0x1919 | 0x0D7C | 0x1800 |
| BCM4500 firmware loader | 0x0DDD | 0x0C64 | 0x0CA4 |
| BCM4500 status polling | 0x2000 | — | 0x208D |
| Delay loop | 0x1DFB | 0x1BDA | 0x14B9 |
INT0 Handler Evolution
Section titled “INT0 Handler Evolution”The INT0 interrupt vector (CODE:0003) was repurposed between firmware generations:
USB Re-enumeration — pulses CPUCS bit 3 to trigger controlled USB disconnect/reconnect:
void INT0_vec(void) { if (flag == 0) CPUCS |= 0x08; // CPUCS bit 3 else CPUCS |= 0x0A; // CPUCS bits 3+1 delay(5, 0xDC); // ~1500 cycles EPIRQ = 0xFF; // Clear endpoint IRQs USBIRQ = 0xFF; // Clear USB IRQs EXIF &= 0xEF; // Clear external interrupt flag CPUCS &= 0xF7; // Clear CPUCS bit 3}Demodulator Availability Polling — probes two I2C addresses up to 40 times:
void INT0_vector(void) { for (counter = 0x28; counter != 0; counter--) { byte result = I2C_read(0x7F); if (result != 0x01) { result = I2C_read(0x3F); if (result != 0x01) break; } } no_demod_flag = (counter == 0);}The USB re-enumeration logic was moved to FUN_CODE_2031 and called as a normal function before the main loop.
XRAM Initialization Table
Section titled “XRAM Initialization Table”All versions initialize FX2 peripheral registers from a CODE-space table at startup. The table format is identical: [addr_hi] [addr_lo] [data_byte] triplets terminated by 0x0000.
| Firmware | Table Address | Key Registers Set |
|---|---|---|
| v2.06 | CODE:0B46 | IFCONFIG, EP2CFG, EP2FIFOCFG, REVCTL, I2CTL |
| Rev.2 | CODE:0B48 | Same set, 2 bytes later |
| v2.13 | CODE:0B88 | Same set, different offsets |
All versions set the same final values: IFCONFIG=0xEE, EP2CFG=0xE2, EP2FIFOCFG=0x0C, REVCTL=0x03, I2CTL=0x01.
Anti-Tampering (v2.13 Only)
Section titled “Anti-Tampering (v2.13 Only)”All v2.13 sub-variants contain this string at firmware offset 0x1880:
"Tampering is detected. Attempt is logged. Warranty is voided ! \n"This is followed by I2C register write commands (01 10 aa 82 02 41 41 83). The mechanism is absent from v2.06, Rev.2, and the custom firmware.
Version Identification
Section titled “Version Identification”The GET_FW_VERS command (0x92) returns 6 bytes of hardcoded constants:
Byte 0: version minor_minor (e.g., 0x04)Byte 1: version minor (e.g., 0x06)Byte 2: version major (e.g., 0x02)Byte 3: build day (e.g., 0x0D = 13)Byte 4: build month (e.g., 0x07 = July)Byte 5: build year - 2000 (e.g., 0x07 = 2007)Full version = byte[2] << 16 | byte[1] << 8 | byte[0]. Build date = (2000 + byte[5]) / byte[4] / byte[3].