Skip to content

Kernel FW01 Analysis

The Linux kernel dvb_usb_gp8psk driver references two firmware files: dvb-usb-gp8psk-01.fw (FX2 microcontroller code) and dvb-usb-gp8psk-02.fw (BCM4500 demodulator code). Neither file was ever open-sourced or included in the linux-firmware repository. The SkyWalker-1 does not need them.

FilePurposeAvailable?Needed by SkyWalker-1?
dvb-usb-gp8psk-01.fwFX2 RAM codeNot in linux-firmwareNo
dvb-usb-gp8psk-02.fwBCM4500 demod codeNot in linux-firmwareNo

Standard locations checked:

PathResult
/lib/firmware/dvb-usb-gp8psk-01.fwNot found
/lib/firmware/dvb-usb-gp8psk-02.fwNot found
linux-firmware WHENCE manifestNo gp8psk entry
Kernel scripts/get_dvb_firmwareNo gp8psk handler
pacman -F dvb-usb-gp8psk-01.fwNo package provides it

Why SkyWalker-1 Works Without Firmware Files

Section titled “Why SkyWalker-1 Works Without Firmware Files”

The answer is in the kernel driver’s device table. Only Rev.1 Cold devices (PID 0x0200) have a cold_ids entry, which triggers firmware download:

Kernel device properties (from gp8psk.c)
.devices = {
{ .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
.cold_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_COLD], NULL },
.warm_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_WARM], NULL },
},
{ .name = "Genpix SkyWalker-1 DVB-S receiver",
.cold_ids = { NULL }, // <-- NO cold_ids: skip firmware
.warm_ids = { &gp8psk_usb_table[GENPIX_SKYWALKER_1], NULL },
},
// ...
}

When cold_ids is NULL, the DVB-USB framework skips firmware download entirely. The SkyWalker-1 boots from its onboard EEPROM and enumerates directly as a “warm” device.

DevicePIDNeeds FW01?Needs FW02?Boot Source
Rev.1 Cold0x0200YesRAM (empty)
Rev.1 Warm0x0201NoYesRAM (FW01 loaded)
Rev.20x0202NoNoEEPROM
SkyWalker-10x0203NoNoEEPROM
SkyWalker CW3K0x0206NoNoEEPROM

For Rev.1 Cold devices, the firmware loading follows this sequence:

  1. DVB-USB framework matches the USB VID:PID against cold_ids and calls dvb_usb_download_firmware()

  2. Kernel requests firmware via request_firmware("dvb-usb-gp8psk-01.fw", ...) from the userspace firmware loader

  3. Cypress FX2 loader (usb_cypress_load_firmware()) halts the FX2 CPU by writing 0x01 to CPUCS register (0xE600) via the 0xA0 vendor request

  4. Hexline records are parsed and written to FX2 RAM via USB control transfers (0xA0 vendor request)

  5. FX2 CPU restarted by writing 0x00 to CPUCS. The device re-enumerates with a new PID (0x0201, “warm”)

  6. DVB-USB framework re-matches the new PID against warm_ids and proceeds to frontend attach

The 0xA0 vendor request is handled by the FX2’s built-in silicon boot ROM, which provides RAM read/write access regardless of whether user firmware is running. This is the same mechanism used by the custom firmware’s fw_load.py tool.

The kernel’s dvb_usb_get_hexline() parser expects 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>.

Offset Size Field
------ ---- -----
0 1 len - Number of data bytes
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
0x00DataCode/data bytes for FX2 RAM
0x01EOFEnd of file
0x04Extended AddressSets upper 16 bits of target address

FW02 is only relevant for Rev.1 Warm devices (PID 0x0201). It uses a custom chunk protocol:

Chunk format:
Byte 0: payload_length (N)
Bytes 1-3: header/address bytes
Bytes 4..N+3: payload data
Terminator: single byte 0xFF
Maximum chunk size: 64 bytes (USB control transfer limit)

The loading sequence:

  1. Initiate transfer: Send LOAD_BCM4500 command (0x88, wValue=1)

  2. Download chunks: Iterate through firmware data, sending each chunk via dvb_usb_generic_write() on bulk endpoint 0x01

  3. Detect end: Stop when a byte with value 0xFF is encountered

BCM4500 firmware loading (from gp8psk.c)
ptr = fw_data;
while (ptr[0] != 0xFF) {
chunk_size = ptr[0] + 4;
if (chunk_size > 64) {
// Error: chunk too large
}
usb_control_msg(device, USB_SNDCTRLPIPE, 0, ...,
buf, chunk_size, 2000);
ptr += chunk_size;
}

The firmware as stored in the SkyWalker-1’s EEPROM uses Cypress C2 format, which is structurally different from the kernel’s binary hexline format. They carry identical payload data but are different containers.

PropertyC2 (EEPROM)Hexline (Kernel FW01)
Header8-byte C2 with VID/PID/DIDNone
Address encodingBig-endian 16-bit per segmentLittle-endian split (lo, hi) per record
Data chunking1023-byte segmentsTypically 16-byte records
Record overhead4 bytes per segment5 bytes per record
Terminator0x80xx + entry pointType 0x01 EOF record
Entry pointExplicit in terminatorImplicit (CPUCS at 0xE600)

A C2 file can theoretically be converted to hexline format by:

  1. Stripping the 8-byte C2 header
  2. Splitting each segment into 16-byte records with type 0x00
  3. Appending an EOF record (len=0, type=0x01)

For the v2.06 EEPROM (9,472 code bytes), this would produce approximately 12,442 bytes in hexline format.

See the Storage Formats page for detailed C2 format documentation.

When the SkyWalker-1 is connected, the kernel logs:

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 “failed to get FPGA version” error is command 0x95 (GET_FPGA_VERS, decimal 149) returning an error on some units. Despite the name, there is no FPGA on the SkyWalker-1 — this command reads a hardware platform ID from the EEPROM. The driver logs the failure but continues normally.