{"id":868,"date":"2012-06-17T23:55:02","date_gmt":"2012-06-17T15:55:02","guid":{"rendered":"http:\/\/www.computersolutions.cn\/blog\/?p=868"},"modified":"2012-06-17T23:55:02","modified_gmt":"2012-06-17T15:55:02","slug":"138-in-1-jamma-pcb-with-sd-card-xinye-arm-jamma-board-quick-file-system-firmware-reversing-engineering-notes","status":"publish","type":"post","link":"https:\/\/www.computersolutions.cn\/blog\/2012\/06\/138-in-1-jamma-pcb-with-sd-card-xinye-arm-jamma-board-quick-file-system-firmware-reversing-engineering-notes\/","title":{"rendered":"138 in 1 Jamma PCB with SD Card (XinYe Arm Jamma Board) &#8211; Quick file system firmware reversing engineering notes"},"content":{"rendered":"<p>Someone from the JammaForums.co.uk emailed me a copy of the firmware in their SD card from a XinYe 138 in 1.<\/p>\n<p>Card looks something like this:<\/p>\n<p><a href=\"http:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/Unknown.jpeg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/Unknown-300x300.jpg\" alt=\"\" title=\"Unknown\" width=\"300\" height=\"300\" class=\"aligncenter size-medium wp-image-869\" srcset=\"https:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/Unknown-300x300.jpg 300w, https:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/Unknown-150x150.jpg 150w, https:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/Unknown.jpeg 600w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>I don&#8217;t have one, but I took a quick look at the data provided, and it looks fairly straightforward to &#8220;hack&#8221;.<\/p>\n<p>It actually took me less than 30 minutes to have most of the good bits extracted from receiving the file!<\/p>\n<p>There are 2 files on the SD card.<\/p>\n<p>One is a 64 byte file called sn.bin which contains this data:<\/p>\n<p><a href=\"http:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/Screen-shot-2012-06-17-at-11.30.15-PM.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/Screen-shot-2012-06-17-at-11.30.15-PM.png\" alt=\"\" title=\"Screen shot 2012-06-17 at 11.30.15 PM\" width=\"579\" height=\"61\" class=\"aligncenter size-full wp-image-870\" srcset=\"https:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/Screen-shot-2012-06-17-at-11.30.15-PM.png 579w, https:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/Screen-shot-2012-06-17-at-11.30.15-PM-300x31.png 300w\" sizes=\"auto, (max-width: 579px) 100vw, 579px\" \/><\/a><\/p>\n<p>This looks suspiciously like a header, but I haven&#8217;t taken a clear look.<\/p>\n<p>The second file is called x3rodl.bin, and contains a Linux firmware in ARM format.<\/p>\n<p>The first few hundred bytes look like this:<\/p>\n<p><a href=\"http:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/x3rodl-first-bytes.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/x3rodl-first-bytes.gif\" alt=\"\" title=\"x3rodl-first-bytes\" width=\"640\" height=\"126\" class=\"aligncenter size-full wp-image-871\" srcset=\"https:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/x3rodl-first-bytes.gif 640w, https:\/\/www.computersolutions.cn\/blog\/wp-content\/uploads\/2012\/06\/x3rodl-first-bytes-300x59.gif 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>Its obviously in ARM format, as the first set of bytes are ARM no-op codes.<\/p>\n<p>00 00 A0 E1, which repeats 8 times.<br \/>\n02 00 00 EA, then&#8230;<br \/>\n18 28 6F 01 &#8211; Which is a magic word indicating that this contains a zImage (compressed Linux kernel)<\/p>\n<p>18 28 6F 01 =  0x016f2818<\/p>\n<p>Linux code looks something like this for identifying if its a kernel:<\/p>\n<p><code>if (*(ulong *)(to + 9*4) != LINUX_ZIMAGE_MAGIC) {<br \/>\n        printk(\"Warning: this binary is not compressed linux kernel image\/n\");<br \/>\n        printk(\"zImage magic = 0x%08lx\/n\", *(ulong *)(to + 9*4));<br \/>\n    } else {<br \/>\n        printk(\"zImage magic = 0x%08lx\/n\", *(ulong *)(to + 9*4));<br \/>\n    }<br \/>\n<\/code><\/p>\n<p>9 * 4 = 36, which is our location, and this happens to have our magic number.<br \/>\nSo, we know its a kernel.  Its also probably the VIVI bootloader from Samsung, as that uses that style MAGIC.<\/p>\n<p>The following bits of data, contain the setup for the kernel, and the boot code.<\/p>\n<p>This continues on until the compressed kernel+ramdisk.  That starts with 1F 8B 08 (gzip header bytes) over at 0x3EF2, until roughly the end of the file.<\/p>\n<p>I extracted that part and had a quick look.<br \/>\nIts about 7.7M size unpacked.<\/p>\n<p>Linux version is:  2.6.36-FriendlyARM<\/p>\n<p>Boot params are:<br \/>\nconsole=ttySAC0,115200 root=\/dev\/ram init=\/linuxrc initrd=0x51000000,6M ramdisk_size=6144<\/p>\n<p>RAMDISK File System starts at 0x20000, and looks like this:<\/p>\n<p><code>lawrence$ ls -al<br \/>\ntotal 24<br \/>\ndrwxr-xr-x  13 lawrence  staff   442 Jun 17 23:09 .<br \/>\ndrwxr-xr-x   4 lawrence  staff   136 Jun 17 23:08 ..<br \/>\ndrwxr-xr-x  51 lawrence  staff  1734 Jun 17 23:09 bin<br \/>\ndrwxr-xr-x   2 lawrence  staff    68 Jun 17 23:09 dev<br \/>\ndrwxr-xr-x  11 lawrence  staff   374 Jun 17 23:09 etc<br \/>\n-rwxr-xr-x   1 lawrence  staff  3821 Jun 17 23:09 init<br \/>\n-rw-r--r--   1 lawrence  staff  3821 Jun 17 23:09 init~<br \/>\nlrwxrwxrwx   1 lawrence  staff    11 Jun 17 23:09 linuxrc -> bin\/busybox<br \/>\ndrwxr-xr-x   2 lawrence  staff    68 Jun 17 23:09 proc<br \/>\ndrwxr-xr-x   2 lawrence  staff    68 Jun 17 23:09 r<br \/>\ndrwxr-xr-x  19 lawrence  staff   646 Jun 17 23:09 sbin<br \/>\ndrwxr-xr-x   2 lawrence  staff    68 Jun 17 23:09 sdcard<br \/>\ndrwxr-xr-x   4 lawrence  staff   136 Jun 17 23:09 usr<br \/>\n<\/code><\/p>\n<p>The bootup script for this looks like this:<\/p>\n<p><code><br \/>\n#! \/bin\/sh<\/p>\n<p>PATH=\/sbin:\/bin:\/usr\/sbin:\/usr\/bin<br \/>\nrunlevel=S<br \/>\nprevlevel=N<br \/>\numask 022<br \/>\nexport PATH runlevel prevlevel<\/p>\n<p>echo st.<\/p>\n<p>#<br \/>\n#\tTrap CTRL-C &c only in this shell so we can interrupt subprocesses.<br \/>\n#<br \/>\ntrap \":\" INT QUIT TSTP<br \/>\n\/bin\/hostname FriendlyARM<br \/>\n\/bin\/mount -n -t proc proc \/proc<\/p>\n<p>cmdline=`cat \/proc\/cmdline`<\/p>\n<p>ROOT=none<br \/>\nROOTFLAGS=<br \/>\nROOTFSTYPE=<br \/>\nNFSROOT=<br \/>\nIP=<br \/>\nINIT=\/sbin\/init<br \/>\n#run_fs_image=\/images\/linux\/rootfs_xin1arm_sdhotplug.ext3<\/p>\n<p>for x in $cmdline ; do<br \/>\n\tcase $x in<br \/>\n\troot=*)<br \/>\n\t\tROOT=${x#root=}<br \/>\n\t\t;;<br \/>\n\trootfstype=*)<br \/>\n\t\tROOTFSTYPE=\"-t ${x#rootfstype=}\"<br \/>\n\t\t;;<br \/>\n\trootflags=*)<br \/>\n\t\tROOTFLAGS=\"-o ${x#rootflags=}\"<br \/>\n\t\t;;<br \/>\n\tinit=*)<br \/>\n\t\tINIT=${x#init=}<br \/>\n\t\t;;<br \/>\n\tnfsroot=*)<br \/>\n\t\tNFSROOT=${x#nfsroot=}<br \/>\n\t\t;;<br \/>\n\tip=*)<br \/>\n\t\tIP=${x#ip=}<br \/>\n\t\t;;<\/p>\n<p>\tesac<br \/>\ndone<\/p>\n<p>if [ ! -z $NFSROOT ] ; then<br \/>\n\techo $NFSROOT | sed s\/:\/\\ \/g  > \/dev\/x ;  read sip dir < \/dev\/x\n\techo $IP | sed s\/:\/\\ \/g > \/dev\/x;  read cip sip2 gip netmask hostname device autoconf < \/dev\/x\n\trm \/dev\/x\n\t#echo $sip $dir $cip $sip2 $gip $netmask $hostname $device $autoconf\n\tmount -t nfs $NFSROOT \/r -o nolock,proto=tcp\n\t#[ -e \/r\/dev\/console ] || exec \/bin\/sh\n\nelif [ ! -z $run_fs_image ] ; then\n\t#lilxc\n\t#echo $run_fs_image\n\techo sdroot.\n\n\tif [ ! -e \/dev\/mmcblk0p2 ] ; then\n\t\techo \"p2 not found.\"\n\t\treboot\n\t\tsleep 5\n\tfi\n\n\tROOTFSTYPE=\"-t ext3\"\n\tfor i in 1 2 3 4 5 ; do\n\t#\/bin\/mount -n -o sync -o noatime -o nodiratime -o ro -t vfat \/dev\/mmcblk0p1 \/sdcard &#038;&#038; break\n\t\/bin\/mount -n -o sync -o noatime -o nodiratime -o ro -t ext3 \/dev\/mmcblk0p2 \/sdcard &#038;&#038; break\n\techo Waiting for SD Card...\n\n\tif [ $i = 4 ] ; then\n\t\techo  \" p2 failed. \"\n\t\treboot\n\t\tsleep 5\n\t\tbreak;\n\tfi\t\n\n\tsleep 1\n\tdone\n\n\t#echo ------begin----------------------------------------\n\t#sleep 1\n\t#lilxc\n\t#ls -l \/dev\n\t#sleep 1\n\t#echo -----------------------------------------------\n\t#ls -l \/sdcard\n\t#sleep 1\n\t#echo ------end------------------------------------------\n\n\t#\/sbin\/losetup \/dev\/loop0 \/sdcard\/$run_fs_image\n\t#\/bin\/mount $ROOTFSTYPE \/dev\/loop0 \/r\n\t#\/bin\/mount $ROOTFSTYPE -o noatime -o nodiratime -o ro \/dev\/mmcblk0p2 \/r  > \/dev\/null 2>&1<br \/>\n\t\/bin\/mount $ROOTFSTYPE -n -o noatime -o nodiratime -o ro \/dev\/mmcblk0p3 \/r  > \/dev\/null 2>&1<br \/>\n\tmount -o move \/sdcard \/r\/sdcard<br \/>\n\t#\/sbin\/losetup \/dev\/loop1 \/r\/sdcard\/swap<br \/>\n\t#\/sbin\/swapon \/dev\/loop1<\/p>\n<p>else<br \/>\n#\t\/bin\/mount -n $ROOTFLAGS $ROOTFSTYPE $ROOT \/r<br \/>\n#\techo \"Readonly mount...(lilxc)\"<br \/>\n#\tmount -n -t yaffs2  -o noatime -o nodiratime -o ro \/dev\/mtdblock2 \/r<br \/>\n#\tmount -n -t yaffs2  -o noatime -o nodiratime \/dev\/mtdblock2 \/r<\/p>\n<p>\tmount -n -t yaffs2  -o noatime -o nodiratime -o ro \/dev\/mtdblock2 \/r<\/p>\n<p>\tif [ -e \/r\/home\/plg\/reboot ]; then<br \/>\n\t\tumount \/r<br \/>\n\t\tmount -n -t yaffs2  -o noatime -o nodiratime \/dev\/mtdblock2 \/r<br \/>\n\tfi<\/p>\n<p>fi<\/p>\n<p>ONE_WIRE_PROC=\/proc\/driver\/one-wire-info<br \/>\nETC_BASE=\/r\/etc<br \/>\n[ -d \/r\/system\/etc ] && ETC_BASE=\/r\/system\/etc<br \/>\n[ -e $ETC_BASE\/ts.detected ] && . $ETC_BASE\/ts.detected<br \/>\n[ -z $CHECK_1WIRE ] && CHECK_1WIRE=Y<br \/>\nif [ $CHECK_1WIRE = \"Y\" -a -e $ONE_WIRE_PROC ] ; then<br \/>\n\tif read lcd_type fw_ver tail < $ONE_WIRE_PROC ; then\n\t\tif [ x$lcd_type = \"x0\" -a x$fw_ver = \"x0\" ] ; then\n\t\t\tTS_DEV=\/dev\/touchscreen\n\t\telse\n\t\t\tTS_DEV=\/dev\/touchscreen-1wire\n\t\t\techo \"1Wire touchscreen OK\"\n\t\tfi\n\t\tif [ -e $ETC_BASE\/friendlyarm-ts-input.conf ]; then\n\t\t\tsed \"s:^\\(TSLIB_TSDEVICE=\\).*:\\1$TS_DEV:g\" $ETC_BASE\/friendlyarm-ts-input.conf > $ETC_BASE\/ts-autodetect.conf<br \/>\n\t\t\tmv $ETC_BASE\/ts-autodetect.conf $ETC_BASE\/friendlyarm-ts-input.conf -f<br \/>\n\t\t\techo \"CHECK_1WIRE=N\" > $ETC_BASE\/ts.detected<br \/>\n\t\tfi<br \/>\n\tfi<br \/>\nfi<\/p>\n<p>[ -e \/r\/etc\/friendlyarm-ts-input.conf ] && . \/r\/etc\/friendlyarm-ts-input.conf<br \/>\n[ -e \/r\/system\/etc\/friendlyarm-ts-input.conf ] && . \/r\/system\/etc\/friendlyarm-ts-input.conf<br \/>\nexport TSLIB_TSDEVICE<\/p>\n<p>#lilxc  debug here<br \/>\n#\/bin\/mount -n -o sync -o noatime -o nodiratime -t vfat \/dev\/mmcblk0p1 \/sdcard<br \/>\n#cp \/sdcard\/lktcmd \/r\/tmp<br \/>\n#exec \/bin\/sh<\/p>\n<p># for running game<br \/>\numount \/proc<br \/>\nexec switch_root \/r $INIT <\/r\/dev\/console >\/r\/dev\/console 2>&1<br \/>\n<\/code><\/p>\n<p>The secondary loader in init looks like this:<\/p>\n<p><code><\/p>\n<p>#! \/bin\/sh<\/p>\n<p>PATH=\/sbin:\/bin:\/usr\/sbin:\/usr\/bin:\/usr\/local\/bin:<br \/>\nrunlevel=S<br \/>\nprevlevel=N<br \/>\numask 022<br \/>\nexport PATH runlevel prevlevel<\/p>\n<p>#<br \/>\n#\tTrap CTRL-C &c only in this shell so we can interrupt subprocesses.<br \/>\n#<br \/>\ntrap \":\" INT QUIT TSTP<br \/>\n\/bin\/hostname FriendlyARM<\/p>\n<p>[ -e \/proc\/1 ]    || \/bin\/mount -n -t proc  none \/proc<br \/>\n[ -e \/sys\/class ] || \/bin\/mount -n -t sysfs none \/sys<br \/>\n[ -e \/dev\/tty ]   || \/bin\/mount    -t ramfs none \/dev<br \/>\n\/bin\/mount -n -t usbfs none \/proc\/bus\/usb<\/p>\n<p>echo \/sbin\/mdev > \/proc\/sys\/kernel\/hotplug<br \/>\n\/sbin\/mdev -s<br \/>\n\/bin\/hotplug<br \/>\n# mounting file system specified in \/etc\/fstab<br \/>\nmkdir -p \/dev\/pts<br \/>\nmkdir -p \/dev\/shm<br \/>\n\/bin\/mount -n -t devpts none \/dev\/pts -o mode=0622<br \/>\n\/bin\/mount -n -t tmpfs tmpfs \/dev\/shm<br \/>\n\/bin\/mount -n -t ramfs none \/tmp<br \/>\n\/bin\/mount -n -t ramfs none \/var<br \/>\nmkdir -p \/var\/empty<br \/>\nmkdir -p \/var\/log<br \/>\nmkdir -p \/var\/lock<br \/>\nmkdir -p \/var\/run<br \/>\nmkdir -p \/var\/tmp<\/p>\n<p>\/sbin\/hwclock -s<\/p>\n<p>echo \"                         \" > \/dev\/tty1<br \/>\necho \"System starting...       \" > \/dev\/tty1<br \/>\nsyslogd<\/p>\n<p>#\/etc\/rc.d\/init.d\/netd start<br \/>\n#echo \"                        \" > \/dev\/tty1<br \/>\n#echo \"Starting networking...\" > \/dev\/tty1<br \/>\n#sleep 1<br \/>\n#\/etc\/rc.d\/init.d\/httpd start<br \/>\n#echo \"                        \" > \/dev\/tty1<br \/>\n#echo \"Starting web server...\" > \/dev\/tty1<br \/>\n#sleep 1<br \/>\n#\/etc\/rc.d\/init.d\/leds start<br \/>\n#echo \"                        \" > \/dev\/tty1<br \/>\n#echo \"Starting leds service...\" > \/dev\/tty1<br \/>\n#echo \"                        \"<br \/>\n#sleep 1<\/p>\n<p>\/etc\/rc.d\/init.d\/mkjoy<br \/>\n#echo \"                        \" > \/dev\/tty1<br \/>\n#echo \"System Starting...      \" > \/dev\/tty1<br \/>\n#echo \"                        \" > \/dev\/tty1 <\/p>\n<p>#echo \"                        \" > \/dev\/tty1<br \/>\n\/etc\/rc.d\/init.d\/alsaconf start<br \/>\n#echo \"Loading sound card config...\" > \/dev\/tty1<br \/>\n#echo \"                        \"<\/p>\n<p>#\/sbin\/ifconfig lo 127.0.0.1<br \/>\n#\/etc\/init.d\/ifconfig-eth0<\/p>\n<p>#\/bin\/qtopia &<br \/>\n#echo \"                                  \" > \/dev\/tty1<br \/>\n#echo \"Starting Qtopia, please waiting...\" > \/dev\/tty1<\/p>\n<p>cd  \/sdcard<br \/>\n.\/run.sh<br \/>\nreboot<\/p>\n<p><\/code><\/p>\n<p>Fairly easy to reverse!<\/p>\n<p>Refs:<br \/>\n<a href=\"http:\/\/www.jammaplus.co.uk\/\">http:\/\/www.jammaplus.co.uk\/<a\/><br \/>\n<a href=\"http:\/\/blog.csdn.net\/liangkaiming\/article\/details\/6259189\">http:\/\/blog.csdn.net\/liangkaiming\/article\/details\/6259189<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Someone from the JammaForums.co.uk emailed me a copy of the firmware in their SD card from a XinYe 138 in 1. Card looks something like this: I don&#8217;t have one, but I took a quick look at the data provided, and it looks fairly straightforward to &#8220;hack&#8221;. It actually took me less than 30 minutes [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[390,282,25],"tags":[392,197,391,393],"class_list":["post-868","post","type-post","status-publish","format-standard","hentry","category-arcade-machines","category-firmware-2","category-technical-mumbo-jumbo","tag-arm","tag-firmware","tag-jamma","tag-reverse-engineering"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts\/868","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/comments?post=868"}],"version-history":[{"count":1,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts\/868\/revisions"}],"predecessor-version":[{"id":872,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts\/868\/revisions\/872"}],"wp:attachment":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/media?parent=868"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/categories?post=868"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/tags?post=868"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}