Reverse Engineering the firmware on a Kenwood DDX9903S

UPDATE 14 MAR 2020: For discussion, see the Google group. Comments from the old WordPress site have been migrated there.


I bought and really like my Kenwood Excelon DDX9903S headunit. I had it in my WRX, and moved it to my LS430. It supports Android Auto and CarPlay, which I find really useful when driving.

However, it has a nag screen every time it boots up. This got me curious as to how it worked, and see if it could be patched to skip this disclaimer. I figured it probably ran Linux on a SoC, as pretty much everything does nowadays. So I grabbed the latest firmware for it (mine was already updated to it), and started probing.

S_V2_7_0008_0600_AT1.zip

Extract that and you get 3 folders under S_V2_7_0008_0600/:

BOOT_V2_7_0008_0600_release/
MAIN_V1_0_2758_0400/
SOC_V2_7_0008_0600/

In each there’s a .nfu file, which I’ve never encountered before. I ran binwalk on each:

[BOOT_V2_7_0008_0600_release]$ binwalk Boot_2.7.0008.0600.nfu
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
248776 0x3CBC8 Android bootimg, kernel size: 0 bytes, kernel addr: 0x4F525245, ramdisk size: 1226848850 bytes, ramdisk addr: 0x6C61766E, product name: "ERROR: Cannot read kernel image"
1571592 0x17FB08 ELF, 64-bit LSB shared object, AMD x86-64, version 1 (SYSV)
2358024 0x23FB08 ELF, 64-bit LSB shared object, AMD x86-64, version 1 (SYSV)
3209992 0x30FB08 ELF, 64-bit LSB shared object, AMD x86-64, version 1 (SYSV)

Surprise, surprise, it runs Android. But, I’m thinking this image is possibly just the firmware updater, and not what I am looking for.

[SOC_V2_7_0008_0600]$ binwalk Soc_V2_7_0008_0600.nfu
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
5767936 0x580300 Android bootimg, kernel size: 16823168 bytes, kernel addr: 0x80008000, ramdisk size: 0 bytes, ramdisk addr: 0x81000000, product name: ""
5784320 0x584300 Linux kernel ARM boot executable zImage (little-endian)
5800283 0x58815B gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)
41943040 0x2800000 Zip archive data, at least v2.0 to extract, compressed size: 14612206, uncompressed size: 14696448, name: 16dnx_2.5s_fbios_bootimg.img
56555332 0x35EF744 Zip archive data, at least v2.0 to extract, compressed size: 16765150, uncompressed size: 16842752, name: TCC893X_recovery.img
73320560 0x45EC870 Zip archive data, at least v2.0 to extract, compressed size: 210950775, uncompressed size: 1825360896, name: automotive-linux-16DDX-image.ext4
284271426 0x10F1A342 Zip archive data, at least v2.0 to extract, compressed size: 87690, uncompressed size: 524288, name: fbios_dual.bin
284359188 0x10F2FA14 Zip archive data, at least v2.0 to extract, compressed size: 168, uncompressed size: 223, name: filelist.txt
284359426 0x10F2FB02 Zip archive data, at least v2.0 to extract, compressed size: 29903609, uncompressed size: 39549952, name: qboot_ddx.bin
314263106 0x12BB4642 Zip archive data, at least v2.0 to extract, compressed size: 33193, uncompressed size: 5242880, name: sbios_dual.bin
314296995 0x12BBCAA3 End of Zip archive, footer length: 22

Here we go. A kernel with a sane size and name string, some recovery images, and what looks like a filesystem image! qboot_ddx.bin must be part of Ubiquitous' QuickBoot software. It does boot awfully fast, so that explains that. Would be interesting to see full kernel and init output on a stereo headunit. Well, once anyway.

Running binwalk on MAIN_V1_0_2758_0400/MainFw_1.0.2758.0400.mfu didn’t output anything. Not sure what that is.

I tried unzip to extract Soc_V2_7_0008_0600.nfu. Seemed to work, though it complained about a 41MB extra bytes at the beginning. I was really just interested in the filesystem image for the moment:

[SOC_V2_7_0008_0600]$ unzip Soc_V2_7_0008_0600.nfu
Archive: Soc_V2_7_0008_0600.nfu
warning [Soc_V2_7_0008_0600.nfu]: 41943040 extra bytes at beginning or within zipfile
(attempting to process anyway)
inflating: 16dnx_2.5s_fbios_bootimg.img
inflating: TCC893X_recovery.img
inflating: automotive-linux-16DDX-image.ext4
inflating: fbios_dual.bin
inflating: filelist.txt
inflating: qboot_ddx.bin
inflating: sbios_dual.bin

Running binwalk on the .ext4 verifies it is an ext4 filesystem image. I ran binwalk on the others and nothing was notable except the presumed QuickBoot file, qboot_ddx.bin which had images, and what looks like Qt library .qml files for some type of GUI. Also a Pandora image and other images. Hmm…

I decided to mount the ext4 image to take a look.

[SOC_V2_7_0008_0600]$ sudo mount -o loop automotive-linux-16DDX-image.ext4 /mnt/temp
[SOC_V2_7_0008_0600]$ cd /mnt/temp/
[temp]$ ls
bin dev home lost+found Music proc sbin sys temp usr
boot etc IMG_DEC_WORK media nand1 RAMDISK sdcard Syslog Temp var
DB filesave lib mnt opt run share system tmp

Interesting things appear to be in: /opt/jkpf:

bin dbg_daemon_starter.sh etc kill_applications.sh lib rsc script system_init.sh

That appears to be where lots of magic happens. Whenever I’m done disassembling the rest of the car for a particularly annoying remote start installation, I’ll come back to it.