skywalker-1/kernel-fw01-analysis.md
Ryan Malloy bbdcb243dc Normalize line endings to LF across entire repository
Apply .gitattributes normalization to convert all CRLF line
endings inherited from Windows-origin source files to Unix LF.
175 files, zero content changes.
2026-02-20 10:55:50 -07:00

426 lines
18 KiB
Markdown

# Genpix GP8PSK Kernel Firmware File Analysis
## 1. Firmware File Search Results
### Standard Locations Checked
| Path | Result |
|------|--------|
| `/lib/firmware/dvb-usb-gp8psk-01.fw` | **Not found** |
| `/lib/firmware/dvb-usb-gp8psk-02.fw` | **Not found** |
| `/usr/lib/firmware/dvb-usb-gp8psk-01.fw` | **Not found** |
| `/usr/lib/firmware/dvb-usb-gp8psk-02.fw` | **Not found** |
| `/usr/share/firmware/` | Directory does not exist |
### Package Search
- `linux-firmware` (v20260110-1) is installed but contains **no gp8psk files**
- The `/usr/lib/firmware/WHENCE` manifest has **no gp8psk entry**
- `pacman -F dvb-usb-gp8psk-01.fw` returns no results -- no Arch package provides it
- `pacman -Ss gp8psk` finds nothing
### linux-firmware Git Repository
The upstream linux-firmware repository at `git.kernel.org` was checked. The gp8psk firmware files have **never been included** in the linux-firmware collection. Other DVB-USB firmware files exist (dib0700, it9135, terratec-h5-drxk), but gp8psk is absent.
### Kernel get_dvb_firmware Script
The kernel's `scripts/get_dvb_firmware` helper (which downloads firmware from various vendor sites) has **no entry for gp8psk**. The original firmware was presumably distributed by Genpix Electronics directly, likely packaged with their Windows BDA driver installer.
### Filesystem-Wide Search
A full filesystem search (`find / -name 'dvb-usb-gp8psk*'`) found only the compiled kernel module (`.ko.zst`), no `.fw` firmware files anywhere on the system.
### Conclusion
**Neither `dvb-usb-gp8psk-01.fw` nor `dvb-usb-gp8psk-02.fw` exist on this system or in any standard distribution channel.** The gp8psk firmware was never open-sourced or contributed to linux-firmware.
---
## 2. Why SkyWalker-1 Works Without FW01/FW02
### The Driver Device Table Tells the Story
From `gp8psk.c` (kernel source):
```c
static struct dvb_usb_device_properties gp8psk_properties = {
.usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-gp8psk-01.fw",
// ...
.devices = {
{ .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
.cold_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_COLD], NULL }, // <-- HAS cold_ids
.warm_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_WARM], NULL },
},
{ .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver",
.cold_ids = { NULL }, // <-- NO cold_ids
.warm_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_2], NULL },
},
{ .name = "Genpix SkyWalker-1 DVB-S receiver",
.cold_ids = { NULL }, // <-- NO cold_ids
.warm_ids = { &gp8psk_usb_table[GENPIX_SKYWALKER_1], NULL },
},
// ...
}
};
```
**Only Rev.1 Cold (PID 0x0200) triggers firmware download.** When `cold_ids` is NULL, the DVB-USB framework skips the firmware loading step entirely. The device is assumed to already be in "warm" state.
### FW01 Loading Path
```
USB device enumeration
|
+-- DVB-USB framework matches USB IDs
+-- Checks cold_ids vs warm_ids
| |
| +-- cold_ids match? -> dvb_usb_download_firmware()
| | | -> request_firmware("dvb-usb-gp8psk-01.fw")
| | | -> usb_cypress_load_firmware() [hexline parser]
| | | -> Device re-enumerates with warm PID
| | |
| +-- warm_ids match? -> Skip firmware, proceed to frontend attach
|
+-- SkyWalker-1 (PID 0x0203) -> warm_ids only -> NO FW01 NEEDED
```
### FW02 Loading Path
From `gp8psk_power_ctrl()`:
```c
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) // Only for Rev.1!
if (!(status & bm8pskFW_Loaded))
if (gp8psk_load_bcm4500fw(d))
return -EINVAL;
```
BCM4500 firmware loading (`dvb-usb-gp8psk-02.fw`) is **only attempted for Rev.1 Warm devices** (PID 0x0201). Rev.2 and SkyWalker devices have the BCM4500 firmware burned into ROM, so `bm8pskFW_Loaded` (bit 1 of `GET_8PSK_CONFIG`) is already set at boot.
### Summary
| Device | PID | Needs FW01? | Needs FW02? | Boot Source |
|--------|-----|-------------|-------------|-------------|
| Rev.1 Cold | 0x0200 | **YES** | -- | RAM (empty) |
| Rev.1 Warm | 0x0201 | No | **YES** | RAM (FW01 loaded) |
| Rev.2 | 0x0202 | No | No | EEPROM |
| SkyWalker-1 | 0x0203 | No | No | EEPROM |
| SkyWalker-2 | 0x0205 | No | No | EEPROM |
| SkyWalker CW3K | 0x0206 | No | No | EEPROM |
**The SkyWalker-1 boots entirely from its onboard EEPROM. It never requests either firmware file from the host.**
---
## 3. FW01 Expected Format: DVB-USB Binary Hexline
### Format Specification
The DVB-USB framework's `dvb_usb_get_hexline()` parser reads a **compact binary representation** of Intel HEX records. This is NOT standard Intel HEX text (`:10000000...`), nor the kernel's `ihex_binrec` format from `<linux/ihex.h>`.
**Record structure:**
```
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 (0x00=data, 0x01=EOF, 0x04=extended addr)
4 len data[] - Payload bytes
4+len 1 chk - Checksum byte
```
Total bytes per record: `len + 5`
The parser advances position by `len + 5` each iteration. Type 0x04 records carry extended linear address bits in `data[0]` and `data[1]`, allowing 32-bit addressing.
### Loading Mechanism
`usb_cypress_load_firmware()` performs:
1. Halt FX2 CPU: write `0x01` to CPUCS register (0xE600)
2. For each hexline record: write `data[0..len-1]` to FX2 RAM at `addr` via 0xA0 vendor request
3. Restart FX2 CPU: write `0x00` to CPUCS register (0xE600)
The 0xA0 vendor request is handled by the FX2's built-in boot ROM, which writes directly to program/data RAM regardless of whether user firmware is running.
### Comparison with Other DVB-USB Firmware Files
Other firmware files installed on this system confirm the format:
| File | Size | First Record |
|------|------|-------------|
| `dvb-usb-dib0700-1.20.fw` | 33,768 bytes | len=2, addr=0x0000, type=0x04 (ext addr) |
| `dvb-usb-it9135-01.fw` | 8,128 bytes | len=3, addr=0x0000, type=0x03 |
| `dvb-usb-it9135-02.fw` | 5,834 bytes | len=3, addr=0x0000, type=0x03 |
---
## 4. Our Extracted Firmware Format: Cypress C2 EEPROM Boot
### C2 Header Structure
All extracted firmware dumps are in **Cypress C2 IIC second-stage boot format**, as stored in the device's EEPROM. This format is read by the FX2's internal boot ROM on power-up.
**C2 header (8 bytes):**
```
Offset Size Field
------ ---- -----
0 1 marker - Always 0xC2 (indicates external memory, large code model)
1 2 VID - USB Vendor ID (little-endian) -> 0x09C0 (Genpix)
3 2 PID - USB Product ID (little-endian)
5 2 DID - Device ID (little-endian) -> 0x0000
7 1 config - 0x40 (400kHz I2C bus speed)
```
**Followed by code segments:**
```
Offset Size Field
------ ---------- -----
0 2 seg_len - Segment length (big-endian)
2 2 seg_addr - Target RAM address (big-endian)
4 seg_len data[] - Code/data bytes
```
**Terminated by:**
```
0 2 0x8001 - High bit set signals terminator
2 2 entry - Entry point address (big-endian) -> 0xE600 (CPUCS)
```
### Decoded C2 Headers
| File | VID | PID | Segments | Code Size | Entry |
|------|-----|-----|----------|-----------|-------|
| `skywalker1_eeprom.bin` (v2.06) | 0x09C0 | **0x0203** | 10 | 9,472 bytes | 0xE600 |
| `sw1_v213_fw_1_c2.bin` (v2.13.1) | 0x09C0 | **0x0203** | 10 | 9,322 bytes | 0xE600 |
| `sw1_v213_fw_2_c2.bin` (v2.13.2) | 0x09C0 | **0x0203** | 10 | 9,377 bytes | 0xE600 |
| `sw1_v213_fw_3_c2.bin` (v2.13.3) | 0x09C0 | **0x0203** | 10 | 9,369 bytes | 0xE600 |
| `rev2_v210_fw_1_c2.bin` (Rev2 v2.10) | 0x09C0 | **0x0202** | 9 | 8,843 bytes | 0xE600 |
Note: The PID in the C2 header determines the USB Product ID that the FX2 enumerates with after booting. SkyWalker-1 variants all use PID 0x0203, while Rev.2 uses 0x0202.
### C2 Segment Layout (All SkyWalker-1 Variants)
All SkyWalker-1 C2 files use uniform 1023-byte segments (except the last):
```
Segment Address Length Notes
------- ------- ------ -----
1 0x0000 1023 Contains reset vector, interrupt handlers
2 0x03FF 1023
3 0x07FE 1023
4 0x0BFD 1023
5 0x0FFC 1023
6 0x13FB 1023
7 0x17FA 1023
8 0x1BF9 1023
9 0x1FF8 1023
10 0x23F7 varies (115-265 bytes depending on version)
```
The 1023-byte segment size is the maximum the FX2 I2C EEPROM boot ROM reads per transaction (limited by internal buffer).
---
## 5. Format Incompatibility: C2 vs Kernel Hexline
The firmware as stored in EEPROM (C2 format) is **structurally different** from what the kernel expects (binary hexline format). They cannot be used interchangeably.
| Property | C2 (EEPROM) | Hexline (Kernel FW01) |
|----------|-------------|-----------------------|
| Header | 8-byte C2 with VID/PID/DID | None |
| Address encoding | Big-endian 16-bit per segment | Little-endian split (addr_lo, addr_hi) per record |
| Data chunking | 1023-byte segments | Typically 16-byte records |
| Record overhead | 4 bytes per segment | 5 bytes per record |
| Terminator | 0x80xx + entry point | Type 0x01 EOF record |
| Entry point | Explicit in terminator | Implicit (CPUCS at 0xE600) |
However, the **payload data is identical**. The "flat" extracted firmware (C2 segments concatenated, headers stripped) contains the same 8051 machine code that a hexline-format FW01 would carry. The difference is purely container format.
### Theoretical Conversion: C2 -> Hexline
A C2 file can be converted to the kernel's hexline format by:
1. Strip the 8-byte C2 header
2. For each segment: emit 16-byte hexline records with type=0x00, splitting the segment data
3. Append an EOF record (len=0, type=0x01)
The resulting file would be the equivalent of `dvb-usb-gp8psk-01.fw` for that firmware version. For the v2.06 EEPROM (9,472 code bytes), this produces approximately 12,442 bytes in hexline format.
---
## 6. FW02 (BCM4500 Demodulator Firmware) Analysis
### Loading Protocol
From the kernel source (`gp8psk_load_bcm4500fw()`), FW02 uses a **custom chunk protocol** sent via USB bulk endpoint:
```
Chunk format:
Byte 0: payload_length (N)
Bytes 1-3: header/address bytes (3 bytes)
Bytes 4..N+3: payload data
Total chunk size = ptr[0] + 4 = payload_length + 4
Maximum chunk size: 64 bytes (USB control transfer limit)
Terminator: single byte 0xFF
```
The loading sequence:
1. Send `LOAD_BCM4500` command (0x88, wValue=1) to initiate transfer mode
2. Iterate through chunks until 0xFF terminator
3. Each chunk is sent via `dvb_usb_generic_write()` (bulk endpoint 0x01)
### Relevance to SkyWalker-1
**FW02 is irrelevant for SkyWalker-1.** The BCM4500 demodulator firmware is burned into ROM on all Rev.2 and later hardware. The kernel driver explicitly checks:
```c
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) // 0x0201 only
```
On the SkyWalker-1 (PID 0x0203), command 0x88 (`LOAD_BCM4500`) routes to the STALL handler in the FX2 firmware -- confirmed by Ghidra disassembly of all extracted firmware versions.
---
## 7. Firmware Version Identification
### Kernel dmesg Output
```
gp8psk: FW Version = 2.06.4 (0x20604) Build 2007/07/13
gp8psk: usb in 149 operation failed.
gp8psk: failed to get FPGA version
gp8psk_fe: Frontend attached
gp8psk: found Genpix USB device pID = 203 (hex)
```
The version is read via USB command `GET_FW_VERS` (0x92), which returns 6 bytes: `[minor, build, major, day, month, year-2000]`. The FX2 firmware computes and returns this at runtime from internal constants -- the version bytes are not stored as a simple searchable pattern in the binary.
### Kernel Firmware Revision Constants
From `gp8psk-fe.h`:
```c
#define GP8PSK_FW_REV1 0x020604 // v2.06.4
#define GP8PSK_FW_REV2 0x020704 // v2.07.4
```
The kernel only knows about two firmware revisions. Our v2.10 and v2.13 firmwares are significantly newer and unknown to the kernel.
### FPGA Version Failure
```
gp8psk: usb in 149 operation failed.
gp8psk: failed to get FPGA version
```
Command 0x95 (`GET_FPGA_VERS`, decimal 149) fails on the SkyWalker-1. This command likely targets a separate FPGA that exists only on certain hardware revisions, or the SkyWalker-1 firmware does not implement this vendor command. The driver logs the failure but continues normally.
### Version Strings in Firmware
No human-readable version strings were found in the v2.06 or Rev2 v2.10 firmware binaries. The v2.13.x variants contain a single notable string:
```
Offset 0x1880 (all three v2.13 sub-variants):
"Tampering is detected. Attempt is logged. Warranty is voided ! \n"
```
Followed by bytes `01 10 aa 82 02 41 41 83` -- likely I2C register write commands related to the tampering detection/logging mechanism. This string is absent from v2.06 and v2.10 firmware, indicating Genpix added anti-tampering measures in the v2.13 firmware generation.
---
## 8. Binary Comparison: Extracted Firmware Dumps
### File Sizes
| File | Size | Format |
|------|------|--------|
| `skywalker1_eeprom_flat.bin` (v2.06.4) | 9,472 bytes | Flat binary |
| `sw1_v213_fw_1_flat.bin` (v2.13.1) | 9,322 bytes | Flat binary |
| `sw1_v213_fw_2_flat.bin` (v2.13.2) | 9,377 bytes | Flat binary |
| `sw1_v213_fw_3_flat.bin` (v2.13.3) | 9,369 bytes | Flat binary |
| `rev2_v210_fw_1_flat.bin` (Rev2 v2.10.4) | 8,843 bytes | Flat binary |
### Byte-Level Similarity Matrix
Percentage of matching bytes within the shared length of each pair:
| | v2.06 | v2.13.1 | v2.13.2 | v2.13.3 | Rev2 v2.10 |
|---|---|---|---|---|---|
| **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% |
| **Rev2 v2.10** | | | | | -- |
### Differing Byte Counts
| Pair | Different Bytes | Shared Length | Mismatch Rate |
|------|----------------|---------------|---------------|
| v2.06 vs v2.13.1 | 8,878 | 9,322 | 95.2% |
| v2.06 vs Rev2 v2.10 | 8,312 | 8,843 | 94.0% |
| v2.13.1 vs Rev2 v2.10 | 8,133 | 8,843 | 92.0% |
| v2.13.1 vs v2.13.2 | 3,994 | 9,322 | 42.8% |
| v2.13.2 vs v2.13.3 | 1,549 | 9,369 | 16.5% |
### Longest Identical Run
| Pair | Longest Match | Starting Offset |
|------|--------------|-----------------|
| v2.06 vs v2.13.1 | 22 bytes | 0x0055 |
| v2.06 vs Rev2 v2.10 | 36 bytes | 0x080C |
### Interpretation
The very low byte-level similarity between different major versions (v2.06 vs v2.10 vs v2.13) indicates **complete recompilation** with different toolchains or linker configurations. Functions are relocated to different addresses even when their logic is identical. The first byte of every flat dump already differs (the second byte of the reset vector LJMP target), confirming different code layout starting from the entry point.
Within the v2.13 family, FW2 and FW3 share 83.5% of bytes, reflecting minor hardware-specific changes (parallel bus timing, GPIO defaults, IRAM layout). FW1 differs more substantially (57-59% match) because it targets fundamentally different hardware (I2C vs parallel bus demodulator interface).
---
## 9. Other Extracted Files
### FX2 Internal ROM (`skywalker1_fx2_internal.bin`, 8,192 bytes)
The FX2 internal ROM dump does **not** contain program code in a recognizable 8051 format. It appears to be the FX2's built-in boot ROM (mask ROM), which handles:
- USB enumeration in "unconfigured" state
- I2C EEPROM boot loading (reading C2 format images)
- 0xA0 vendor request handling (RAM write for host firmware upload)
This ROM is identical across all Cypress CY7C68013A chips and is not Genpix-specific.
### FX2 External Memory (`skywalker1_fx2_external.bin`, 65,536 bytes)
A 64KB dump of the FX2's full external address space. The first ~9.5KB contains the same code as `skywalker1_eeprom_flat.bin`; the remainder is the full 64KB memory space including RAM, SFR shadows, and unused regions.
---
## 10. Summary of Findings
1. **Firmware files `dvb-usb-gp8psk-01.fw` and `dvb-usb-gp8psk-02.fw` do not exist** on this system, in linux-firmware, or in any standard distribution. They were never open-sourced.
2. **SkyWalker-1 does not need either file.** The kernel driver only requests FW01 for Rev.1 Cold devices (PID 0x0200) and FW02 for Rev.1 Warm devices (PID 0x0201). The SkyWalker-1 boots from its onboard EEPROM and appears directly as a "warm" device (PID 0x0203).
3. **FW01 format** would be DVB-USB binary hexline records (a compact binary encoding of Intel HEX), loaded via Cypress FX2 0xA0 vendor requests to CPUCS. Our extracted dumps are in Cypress C2 EEPROM boot format -- different container, identical payload.
4. **FW02 format** is a custom Genpix chunk protocol (length byte + 3 header bytes + data, terminated by 0xFF), loaded via USB bulk transfers after a LOAD_BCM4500 command (0x88). This is only relevant for Rev.1 hardware.
5. **The currently running firmware** is v2.06.4 (build 2007/07/13), matching the kernel's `GP8PSK_FW_REV1` constant (0x020604). This is the original factory firmware burned into the SkyWalker-1 EEPROM.
6. **The v2.13 firmware** (extracted from the Windows updater) adds anti-tampering detection and supports three different hardware sub-variants. The v2.10 Rev.2 firmware is for a different product (PID 0x0202).
---
## Sources
- Linux kernel 6.16.5 source: `drivers/media/usb/dvb-usb/gp8psk.c`, `gp8psk.h`
- Linux kernel 6.16.5 source: `drivers/media/dvb-frontends/gp8psk-fe.h`
- Linux kernel 6.16.5 source: `drivers/media/usb/dvb-usb/dvb-usb-firmware.c`
- Linux kernel 6.16.5 source: `include/linux/ihex.h`
- Firmware dumps: `/home/rpm/claude/ham/satellite/genpix/skywalker-1/firmware-dump/`
- `dmesg` output from running SkyWalker-1 hardware
- linux-firmware git repository (https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git)