Repository navigation
HOST BSP and Vehicle Coding
This page covers what's actually running on the RNS510's separate
HOST processor, and the real diagnostic protocol the factory uses to
configure a unit for a specific vehicle. See
SWL Disc: Boot Chain and Build System
for how these files get onto the unit in the first place, and
Firmware Reversing for FHDD6.FLI's own
disassembly. Reader/analysis code: research/swl_5238_reader.py.
Every H_*.FRG file (one per vehicle project variant — see the disc
structure on the build-system page) hides a real zlib (RFC 1950)
stream at a fixed file offset, 16051. zlib.decompress() on it
succeeds immediately — no scanning needed once the offset is known.
Consumes exactly 497,964 compressed bytes -> 1,573,904 bytes
decompressed, byte-identical (same SHA256) across every variant tested
(H_PQEE.FRG, H_SB_HDD.FRG, H_SE_DAB.FRG, H_AK.FRG) — one shared
image, not a per-variant build. The decompressed bytes open with the
same function-prologue signature FHDD6.FLI's own disassembly uses
(stwu+mflr); find_prologues() finds 3,079 real prologues in
it — genuine, substantial compiled code.
This is the real VxWorks bootrom/BSP (Board Support Package) source
for the RNS510 hardware, self-named directly in its own strings:
SSW_VW-RNS and (c) 2005 Siemens VDO Automotive AG — the first
direct internal evidence tracing this codebase specifically to Siemens
VDO Automotive (Continental's predecessor here, acquired 2007;
everywhere else this project only ever found "Continental"). Real,
dated internal revision-control stamps span 2004-2011, well before this
disc's own Sep 2012 build stamp — a long-lived, actively maintained
codebase.
Real embedded C source file names: usrStartup.c, usrConfig.c,
usrCache.c, usrBreakpoint.c, usbPciStub.c, sysTffs.c (True FFS
flash filesystem — the real driver behind the /tffs0/ paths below),
sysSerial.c, sysPciManualConfig.c, sysLib.c, sysGpTimer.c,
sysGpioDemux.c, sysAta.c (ATA/IDE disk driver — almost certainly
what the HDD-equipped variants need this for), ssw_memorymap.c,
pca9554LedI2CSlave.c, nvRamToImageIO.c, nvRamToFlash.c,
minicoreStubs.c, flashMem.c, bootInit.c, bootConfig.c.
Functionally, this BSP owns: MMU setup and machine-check/exception
handling; a full PCI bus scanner/enumerator (M5200 PCI Configuration
— the real Freescale MPC5200 chip already identified elsewhere in this
project — vendor/device ID and BAR-register dumps, Mediator/CoralP
graphics-controller config-space access); video-input source
switching — cpdrVideoInSetSource JN/DVD/TV/RVC confirms rear-view-
camera/DVD/TV-tuner video-in muxing lives at this layer, driven through
real Analog Devices video-decoder chips (ad9883/adv7400) over I2C;
flash/NAND image management with real A/B-style rollback versioning
(BuildFlashTable, RF_ProcessImage) against a real Samsung NAND part
number, K9F12088U0; and a detailed physical memory map (SDRAM/NOR/
NAND/PCI0-2/FPGA/PCMCIA regions, named image slots including
InfoLog 1/2, SplashScr, BootLoader 1/2, host img, Bestcomm
[Freescale's real MPC5200 DMA engine]). A live interactive VxWorks
debug shell is present too (sp adr,args... Spawn a task — real
WindShell command help text, matching the sp command literally used
in the .WSH scripts below).
Settles HOST vs APPS directly: HOST is the base hardware
platform layer — boot, low-level drivers, PCI/flash/video-mux/graphics-
chip bring-up, the persistent fault-log store — completely separate
from the navicore/dbal map codebase (zero db_*/navicore/
MDCache-family strings appear anywhere in it). APPS (FHDD6.FLI)
is the actual navigation/media application logic.
Per-variant differences: the outer .FRG file sizes differ
(994,140 / 1,286,592 / 1,855,592 bytes across the 3 tested) purely
because of what comes AFTER the shared 497,964-byte compressed BSP
stream — a separate, non-zlib, tightly-repetitive-pattern binary region
containing exactly one real readable string each: a genuine VW part
number (matching the #VwSwPartNumber format already known from
VERSION.TXT) plus the literal product-family label "RNS-MID" —
almost certainly a per-variant boot splash-screen bitmap, not decoded
further.
Every cleanup script uses the real WindShell sp xdelete, "<path>"
(spawn a task) / rmdir syntax — confirmed against the BSP's own shell
help text above. CYCFLAG0.TXT/CYCFLAG1.TXT are each one line,
dlpSetCyclicFlag 0/dlpSetCyclicFlag 1.
DEL_LANG.WSH deletes /tffs0/data/speech/{uvo,synth,recog} —
matches INOUT.TXT's own UVO_*.ZIP/LANG_*.FRG(synth)/REC_*.FRG
(recog) naming exactly.
DEL_FOLD.WSH deletes /tffs0/FLASH, with a real German comment
("30.04.2008 MaRu # Flash-Ordner wird gelöscht") matching
CDSTRUCTTMP.CFG's own changelog entry for this exact file, word for
word.
DEL_OUT.WSH (dated 06.07.2010, author RoNe — the same initials as
USER.CFG's own <AUTHOR> tag, a real engineer active across at least
2010-2012) references a real internal change-request ID, CR 54634 (a
different tracker from the TlaWtz# bug IDs), and deletes ~20 real
compiled-module paths — the first direct evidence of the live /tffs0/ lib/ filesystem layout (previously only file-internal debug strings
were known, never a real deployed directory tree):
| Path | What it is |
|---|---|
/tffs0/lib/mm/mostgen.out, WMADEC.out, dab.out, servicebroker.out, mpeg4_celp_lib.out, MpegAtaSwitcher.out, ... |
multimedia modules. servicebroker.out matches the vdo::svc::dispatcher::Dispatcher command/event-dispatch pattern found in FHDD6.FLI's own disassembly (see Firmware Reversing) |
/tffs0/lib/pos/pos.out |
the real positioning/GPS library |
/tffs0/lib/arriba/navcore.out |
first direct confirmation that "Arriba" (previously only ever a bare string count in FHDD6.FLI) is a real product/codebase name — its actual compiled navigation-core module |
/tffs0/lib/kernel/libDelayImage.out, fileMgr.out
|
kernel-level modules |
FIXCOD.WSH independently confirms and extends this:
sp xdelete, "/tffs0/lib/Arriba/dbal.out" — dbal.out (this whole
project's single most-studied subsystem) sits in the SAME Arriba/
directory as navcore.out — direct, concrete proof dbal and
navcore are sibling compiled modules of the same product line.
References /tffs0/data/fwdir/bundles/4 and calls IL_Flush (InfoLog
flush — ties to the InfoLog 1/2 flash regions in the BSP above).
5 region scripts (EURPQTO.WSH, EURPQTOD.WSH, EURSEDAB.WSH,
ESKHDDL.WSH, ESKHDDDL.WSH — dated March 2013, 5 months after
the rest of this disc, a later patch) each call
SetCoding(0x400, value, offset, width) and SetRegData/
SetRegDataHex(reg, value, ?, width, extra). Comparing all 5 files
against each other resolves the real byte layout directly:
| Coding-array offset | Meaning | Values seen |
|---|---|---|
| 1 | manufacturer |
0x02=VW, 0x05=Skoda |
| 2 | HDD active | 0/1 |
| 5 | Tuner "RUDI" active | real internal tuner codename |
| 6 | DAB active | 0 (EURPQTO/EURPQTOD) / 1 (EURSEDAB/ESKHDDL/ESKHDDDL) |
| 7 | SDARS active | 0 for EUR everywhere — SDARS is Sirius XM's own formal name, ties to SIRIUS.DB3 (NAR-only) |
| 8 | MPEG active | 0/1 |
Plus real register-level commands, identical across all 5 files:
SetRegData(0xa91,0,0,2,0x8a) ("Delete Presets"), SetRegDataHex(0x21, "01",0x0,0x1,0x1) ("Testmode: Active"), SetRegDataHex(0x0B3A,"012C", 0x0,0x2,0x89) ("Speed limit DVD/TV: 300km/h" — 0x012C=300 decimal, a
real factory-override of the "no video while driving" safety lockout).
ESKHDDDL.WSH (Skoda) adds SetRegDataHex(0x0a0a,"01",0x0,0x1,0x1)
("Big VW Splashscreen in NAND: Not Active") — a real per-brand
splash-screen selector register.
CTEST.OUT (89,576 bytes) is a real, complete, standalone PowerPC ELF
relocatable object (ET_REL, EM_PPC) with a full symbol table —
already known to this project as a factory ECU coding/diagnostics test
utility (source files CodingTest.c, RegTest.c,
ConfigFblockTest.c, ctdt.c). Its symbol table names the exact
functions the .WSH scripts above call: SetCoding (.text+2336,
620 bytes), SetRegData (.text+6796, 872 bytes), SetRegDataHex
(.text+7668, 1152 bytes), SetRegDataStr (.text+8820, 668 bytes),
ReadRegData (.text+5816, 448 bytes), DeleteRegData (.text+6544,
252 bytes), SaveRegData (.text+6264, 280 bytes) — all 7
disassembled with capstone, relocations resolved via .rela.text
(real external call targets, not guesses; R_PPC_ADDR16_HI/_LO
relocations target the instruction's own 2-byte immediate field, i.e.
offset+2 from the instruction start, not the instruction's own address
— easy to get wrong on a first pass).
SetCoding(reg, value, offset, width) — real UDS-style "long coding"
(Kodierung) byte-array read/patch/write:
- The logical register id (
0x400) is transformed into the real ECU diagnostic identifier by adding0x3000->0x3400. -
ReadEcuData(status, 1, 0x3400, &buffer, 0xff, 0)reads the current coding byte array. -
value(shifted into the correct byte position bywidth) is copied intobuffer[offset]viamemcpy— patching exactlywidthbytes at byte-offsetoffset, not a bit index. -
WriteEcuData(status, 1, 0x3400, &buffer, length, 0)writes the patched array back.
SetRegData/SetRegDataHex/SetRegDataStr/ReadRegData/
DeleteRegData/SaveRegData — a separate register channel through a
real 4-slot function-pointer table, pReg: a global object,
registered once via svcb_addServiceListener(sServiceReg) on first
use, requiring a cached 2-byte global accKey (see the correction
below) fetched once through pReg[0x10]. Tracing all 6 of these
functions against each other maps pReg out completely — it's a real
service vtable, not just a read/write pair:
pReg offset |
Role | Confirmed by |
|---|---|---|
0x00 |
read |
ReadRegData, SetRegData, SetRegDataHex, SetRegDataStr
|
0x04 |
write |
SetRegData, SetRegDataHex, SetRegDataStr
|
0x14 |
delete | DeleteRegData |
0x1c |
save | SaveRegData |
SetRegData/SetRegDataHex share SetCoding's exact read -> shift-
into-byte-position -> memcpy -> write-back shape, just via
pReg[0x00]/pReg[0x04] instead of ReadEcuData/WriteEcuData
directly. SetRegDataStr is a genuinely different, 2nd write style:
instead of a fixed-width integer, it strlen()s the input string,
bounds-checks against 0xfe, and memcpys the STRING content
directly into the buffer — a variable-length write, not an integer
patch. ReadRegData is the pure read half, no patch/write-back.
A real access-control asymmetry, confirmed structurally: Read/
Set* silently call pReg[0x10] to acquire accKey if it's still 0;
DeleteRegData/SaveRegData do NOT — if accKey is 0 when either is
called, they immediately printf an error and return early, requiring
the caller to have already authenticated via a prior Read/Set*
call. SaveRegData additionally has the most complex signature in the
family: a real 9-argument call to pReg[0x1c] (param1, 2, 0,0,0,0,0, accKey, param2 — the literal 2 is plausibly a record-type/save-mode
constant; param2 spills to the stack past the 8 GPR argument
registers) — and no .WSH script on this disc actually calls it.
Correction — accKey is NOT a UDS SecurityAccess key. That label
was used when first describing this to the user and is wrong, caught 2
ways: accKey is a plain 2-byte .data global — too small for a real
seed-key, and unable to hold every possible 5-digit VCDS-style code
(65536-99999 doesn't fit a uint16). Decisively, FHDD6.FLI itself
has 2 real debug strings using the exact same name in a completely
unrelated context — "registry srv %s avail., accessKey: 0x%x" and
"...suppData.accesskey %x MASK_EVT %x" — both about a service
registering ITSELF with this codebase's own internal message-broker
framework, printed as a raw hex handle. A 2nd candidate,
checkSecurityAccess, is also unrelated — its surrounding bytes show
it's Java's own standard SecurityManager.checkSecurityAccess()
(sitting inside java/util/Vector's method list), not anything
automotive. accKey is CTEST.OUT's own internal service-registry
handle, unrelated to the vehicle's real security code.
The real VCDS-style vehicle Login/SecurityAccess PIN validation was
searched for directly and not found in FHDD6.FLI's own
load-base-recovered, disassemblable 0-9MB region — resolved
since: TpPvVerifyPin (the real PIN-check entry point) DOES exist
in FHDD6.FLI, verbatim, at file offset ~82.6MB — inside the
already-known 76-85.6MB VxWorks/BSP region (a different linking unit
this project's PowerPC load base doesn't cover), and is furthermore
confirmed LIVE and callable over a real serial console. This spans a
large, separate real investigation (a custom ST10/C166 disassembler
for the CAN gateway chip, a byte-level-confirmed EEPROM state machine,
the real vehicle-ClusterID pairing design, and the serial-console
confirmation) — see
Theft Protection, the CAN Gateway, and TpPvVerifyPin
for the complete writeup, including a real 26-pin-connector wiring
diagram and the commercial SetConfig tool's own "Theft
protection"/"PIN verification" coding toggles.
Net result: two genuinely distinct, real UDS (ISO 14229) diagnostic
write paths (direct ReadEcuData/WriteEcuData, and the pReg
service vtable), both confirmed at the disassembly level with real
function names, real argument roles, and the real identifier-namespace
offset (+0x3000) — not inferred from the .WSH comments alone.
BASE/Other/Setconfig-for-rns510.pdf is a real manual for "SetConfig
for RNS510", a commercial third-party coding/diagnostic tool (sold
with an FTDI cable). Its "Theft protection"/"PIN verification" coding
toggles and PIN read/write field are covered on the
Theft Protection page; the
rest of what it independently corroborates, from a working tool's own
UI against real hardware:
- Its Coding tab's "Display protocol: BAP" dropdown value confirms BAP is a real, user-facing, independently togglable protocol choice, not only an internal implementation detail (see the BAP protocol section below).
- Its Logo tab requires a custom boot screen as an 800×480
BMP — a 3rd independent confirmation of the real screen resolution
(already found 2 other ways via
FHDD6.FLI's own widget-bounds strings; see Firmware Reversing). - Its Monitor tab shows a real captured debug log from a running
unit, including
GW_printandRTDD_PS_VuC_HB— real strings tying directly to the CAN gateway ("VuC") diagnostic protocol. - A real, literal
# by SetConfig 000015B4comment was found LEFT BEHIND by this exact tool in one SWL disc's ownHDD_20GB/ RNSMIDEC/CONFIG/DLSCRIPT.TXT(build3810a,BASE/Firmware/) — direct, concrete proof the tool really performs the sameSetRegDataHex(0x21,...)/SetRegDataHex(0x0B3A,...)edit documented in the testmode-unlock pattern on SWL Disc: Boot Chain and Build System, caught in the wild rather than only inferred from the manual.
BASE/Other/rns510-online-dest-master and rns510-tv-input-master are
real C source (SocketCAN, Raspberry Pi target — one ships a prebuilt
ARM ELF binary, confirming it's genuinely used) implementing BAP from
the PC side: each emulates a MOST-over-CAN "function block" device and
talks BAP to a real RNS510 over its CAN bus. The first byte-exact BAP
transport this project has examined directly, rather than only
inferring the protocol's existence.
Real frame framing: long frames (data_len > 6, ISO-TP-style
segmented, but with BAP's own header baked into the start frame rather
than ISO-TP's PCI byte) — start frame: byte0 = 0x80 | (len>>8),
byte1 = len&0xFF, byte2 = (opcode<<4)|(lsg_id>>2), byte3 =
(lsg_id<<6)|fct_id, bytes4-7 = first 4 data bytes; continuation
frames: byte0 = 0xC0|(seqno&0x0F), up to 7 more data bytes. Short
frames (data_len<=6): byte0 = (opcode<<4)|(lsg_id>>2), byte1 =
(lsg_id<<6)|fct_id, remaining bytes = data. opcode(3 bits)/
lsg_id("Logical Service Group", 6 bits)/fct_id(6 bits) — a real
3-level MOST/BAP function-addressing scheme.
Real, distinct CAN IDs per emulated virtual MOST device: the
Online Connectivity Unit (lsg_id=0x37, online-destination injection)
sends on 0x6FD, listens on 0x6B7; the hybrid-TV-tuner emulator
sends on 0x6D3, listens on 0x6C7, and sends its own presence
heartbeat on 0x602; both also watch 0x575 (ignition) and 0x661
(radio on/off).
Real function-ID catalogs: OCU (lsg_id=0x37) — GET_ALL=0x01,
MOST_CATALOG_VERSION=0x02, FUNCTION_LIST=0x03,
FBLOCK_AVAILABILITY=0x04, FSG_CONTROL=0x0D, FSG_SETUP=0x0E,
FSG_OPERATION_STATE=0x0F, DESTINATION_LIST=0x10,
ASG_CAPACITY=0x11. Hybrid-TV (25 IDs, same FSG_* triad shared —
plausibly a real MOST/BAP base-class convention): MOST_CATALOG_ VERSION=0x01 ... TVDISPLAY_NOTIFICATION=0x28 (full list in
research/swl_5238_reader.py).
A worked DESTINATION_LIST payload — the field layout is real, the
coordinates are NOT: the active example encodes a named destination
("Pacanow", a real Polish town) as length-prefixed name/street/house-
number/city/country/postal-code strings plus a 2-byte icon/flag field
— a real, concrete template for the on-wire address format. The
apparent lat/lon sub-field is proven fake: a 2nd, commented-out
example in the same source ("Miekinia", a real, different, far-away
Polish town) uses the byte-for-byte IDENTICAL coordinate bytes — two
different real places cannot share one real coordinate pair, so these
are placeholder/test bytes the tool's author reused, not real geocoded
values for either place. Do not spend time trying to fit a fixed-point
scale to these specific bytes.
rns510-online-dest-master's own README notes this only works for NAR
(North American Region) because VW CarNet was only available there.
A 3rd, standalone Qt/gstreamer DVB-T tuner application
(BASE/Other/rns510_dtv-master) was initially assumed to build on
this same BAP/MOST mechanism — corrected: its real QMostInterface
class does NOT speak BAP at all, despite the name. It instead talks
over a plain RS232 UART with its own separate, much simpler custom
protocol — out of scope for this wiki (which documents the RNS510
head unit itself, not 3rd-party retrofit hardware's own protocols).
UPDATE, a later session: the real on-unit consumer of BAP phone
events (BapPhoneListener), Bluetooth pairing/HFP state, and climate-
control/park-distance-control integration was found — all implemented
in a substantial embedded Java application layer inside FHDD6.FLI
itself (2,806+ real class paths found, e.g. Lvdo/dvc/pdc/impl/parrot/ CT... naming Parrot as the real Bluetooth hands-free module
vendor), not in APPS's native PowerPC C++ code or here in HOST's
BSP. See
The Embedded Java Application Layer
for the full writeup.
These are the real per-platform CAN-gateway routing tables named
GWTABLE.FLI internally (see
INFO/INOUT.TXT's own manifest),
flashed straight to the gateway ECU via LOAD_ECU_BLOCK (see the
boot-chain page for that
command). A plain hex dump of the first 128 bytes (any build, either
table) shows real, readable embedded text: K2L GmbHVer.1.43<hex>. <hex>.<hex>.<hex> 01.43... — K2L GmbH is a real, named
third-party automotive CAN/LIN/MOST bus tooling vendor, evidently the
real source of the tool that generates these tables. Same AA55 AA55
magic already known from FHDD.FLI's own header (see the
boot-chain page) — a real,
shared container-format signature across multiple file types on this
platform.
The version field is fully decoded: the 4 hex-pair groups in that
embedded string (e.g. A5.2A.04.00) are literally the raw header
bytes at offset 0x18-0x1B, rendered as dotted hex for a human
reading a raw dump — verified byte-for-byte across every build
checked. Using this, both tables' real version histories are now
known exactly (900=2008-05-29 through 6276_original_update
=2014-03-20):
SKTABLE.FLI: A5.2A.02.00 (900) -> A5.2A.03.00 (1300, 2680) -> A5.2A.04.00 (3810 onward, stable)
PQTABLE.FLI: 44.2A.03.00 (900) -> 44.2A.05.00 (1300) -> 44.2A.09.00 (3810 onward, stable)
PQTABLE.FLI (the main/EU table, first header byte 44) revised more
times than SKTABLE.FLI (Skoda-specific, first header byte A5 —
plausibly a per-table-type id, not decoded further) over the same
period — consistent with it being the more heavily used variant. A
direct byte diff between the oldest and newest SKTABLE.FLI versions
found 2,764 of 8,192 bytes differ (33.7%) — a real, substantial
content revision, not a trivial stamp change. Neither table's real
per-entry routing content is decoded at the field level — this closes
the header/versioning question, not the full routing-table format.
import struct, capstone
with open("H_PQEE.FRG", "rb") as f:
data = f.read()
payload = zlib.decompress(data[16051:]) # the real BSP image, 1,573,904 bytes
with open("CTEST.OUT", "rb") as f:
data = f.read()
# Elf32_Ehdr fields after e_ident (16 bytes): '>HHIIIIIHHHHHH'
# .symtab/.strtab/.rela.text section offsets from the section header table
# give SetCoding/SetRegData/SetRegDataHex's real .text offsets directly.Full narrative and every validation number: research/ swl_5238_reader.py's own module docstring — search for "DECOMPRESSED",
"real VxWorks bootrom/BSP", "CRACKED (a still-later session, user-asked \"check the files here\")", "Setconfig-for-rns510.pdf",
"rns510-online-dest-master", and "SOLVED: PQTABLE.FLI/SKTABLE.FLI's header format". For TpPvVerifyPin, the CAN gateway, and the theft-
protection state machine specifically, see
Theft Protection, the CAN Gateway, and TpPvVerifyPin
and its own "Reproducing this work" section.
Road network
- eeu.rd
- eeu.il
- eeu.iof
- eeu.typ
- rt / rl / prl
- eeu.si (segment classification)
- eeu.tmc (TMC traffic data)
Places
- eeu.ctr
- cty / cl / ct
- eeu.cny (counties)
- eeu.stt (states/regions)
- eeu.ti (time-info/DST)
- pmc / pmm (postal-code merge)
- pol / pot / pmp (postal-code, empty)
Language / TTS support
- eeu.abc (alphabet)
- eeu.aff (affix)
- eeu.cal (country names)
- eeu.cat (country bboxes)
- prd (road phonetics)
- pct (city phonetics)
- pcl (phoneme cluster list)
- pca (country phonemes)
Map tiles
Container formats
Cross-cutting
- eeu.mod (schema dictionary)
- Road naming join
- Header trailer fields
- Map viewer tool
- Road editor tool
- Unexamined files
- Disc-root build script & subsystems
Firmware reversing