Sunday, October 7, 2018

All ADFURead commands

Here I've listed all the different devices I've discovered so far, and their ADFURead commands.
As far as I can tell, there are 4 device types, 2 of them I have correct names for.
Each device type has a number of ADFU read commands. Some commands take an address, some don't. Some require a certificate.

I'm not sure what device type the Neo Geo Mini is, but none of these commands I am able to get to work. However I haven't thoroughly tested the ones requiring a certificate, still not entirely sure what it is.


Device Type A

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'............Length & 0xFFFF0x80...0x0C0x05
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0x80Address......0x00-0x06,0x08Length & 0xFFFF.....................

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'............Length0x80...0x0C0x08,0x09
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0x80Address...Length >> 9.....................

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'............Length0x80...0x0C0xCA
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0xF6...............Length.....................


Device Type B, "CDrm"

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'............Length & 0xFFFF0x80???0x100x15,0x17
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0x80Address......0x00-0x02,0x04-0x06,0x08Length & 0xFFFF.....................

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'0x000x000x000x00Length0x800x000x0C0xCA
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
..................Length.....................

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'............Length0x80???0x100xB0
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
..................LengthCertificate...............

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'............Length0x80???0x100xB0
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0x80...............LengthCertificate...............


Device Type C

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'.................................0x05
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
AddressLength0x80..................

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'.................................0x07-0x09
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
Address(Length + 0x1FF) >> 90x80..................


Device Type D, "CMipsDrm"

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'............Length0x800x000x100x05
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
AddressLength0x80..................

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'............Length0x800x000x100xCA
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0xF0,0xF1,0xF5,0xF6...............Length.....................

offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'............Length0x800x000x100xB0
offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
Address0x80 | Address[4]...Length >> 9Certificate...............

Thursday, September 27, 2018

Actions firmware appears to be bundled with a script which dictates how the firmware is to be transferred to the device. So the Actions firmware tool actually provides an interface in python on communicating with the hardware.

It's worth noting that the interface provides "DownloadImage" and "DownloadMem" indicating a host to device firmware and memory transfer, and "UploadMem" indicating a device to host memory transfer.
In fact, DownloadMem maps directly to ADFUWrite, and UploadMem maps directly to ADFURead.

Here's the full provided interface:
int __cdecl Py_CallEntry(U32 uId, U32 uAddress)
int __cdecl Py_CloseDevice(U32 uId)
int __cdecl Py_DetachDevice(U32 uId)
int __cdecl Py_DoUserComm(U32 uId, unsigned __int8 *USBC, unsigned __int8 *buffer)
int __cdecl Py_DownloadImage(U32 uId, U32 uType, U32 uSubType, U32 uPageSize, U32 uDiskCap, U32 uAddr, int nStartPer, int nEndPer)
int __cdecl Py_DownloadMem(U32 uId, int nType, U32 uAddress, unsigned __int8 *buffer, U32 uLength)
int __cdecl Py_EjectDevice(U32 uId)
const char *__cdecl Py_ExtractScript(const char *szFirmware)
int __cdecl Py_GetConfigFile(char *szType, int nSubType, unsigned __int8 *buffer, int nOffset, int nLength)
int __cdecl Py_GetFileInImage(const char *szImage, const char *szFile, unsigned __int8 *buffer)
U32 __cdecl Py_GetFirmwareBin(unsigned __int8 *fwBin, char *tmpImg)
const char *__cdecl Py_GetFirmwareCfg(const char *szFirmware, const char *szKey)
int __cdecl Py_GetImageSize(U32 uId, U32 uType, U32 uSubType, U32 uPageSize, U32 uDiskCap)
int __cdecl Py_GetProductionConfig(const char *szType, U32 nSubType, unsigned __int8 *szCfgValue)
int __cdecl Py_GetStatus(U32 uId, unsigned __int8 *buffer)
int __cdecl Py_OpenDevice(U32 uId)
int __cdecl Py_OpenFirmware(const char *szFirmwareFile, unsigned __int8 *fwBin, char *szImageFile)
int __cdecl Py_PollReady(U32 uId)
int __cdecl Py_PyThreadExit(U32 uId, int nExitCode)
int __cdecl Py_ReOpenDevice(U32 uId, int nType, int uTimeout)
int __cdecl Py_ReadFileInFW(const char *szImage, const char *szFileName, U32 uOffset, U32 uToRead, unsigned __int8 *buffer, U32 uAlign)
int __cdecl Py_Recv(U32 uId, unsigned __int8 *usbc, unsigned __int8 *buffer, U32 uLength)
int __cdecl Py_Send(U32 uId, unsigned __int8 *usbc, unsigned __int8 *buffer, U32 uLength)
int __cdecl Py_SetCommTimeout(U32 uId, U32 uMS)
void __cdecl Py_SetLibPath(const char *path)
int __cdecl Py_SetProductionConfig(const char *szType, U32 nSubType, unsigned __int8 *szCfgValue)
int __cdecl Py_ShowMessage(int nType, U32 nSubType, const unsigned __int8 *buffer, int nLength)
int __cdecl Py_SwitchFW(U32 uId, U32 uAddress)
int __cdecl Py_SwitchToAdfu(U32 uId, int uTimeout)
int __cdecl Py_UpdateCapacity(U32 uId, U32 uCapacity)
int __cdecl Py_UpdateProgress(U32 uId, int nPercent)
int __cdecl Py_UpdateStatus(U32 uId, const char *buffer)
int __cdecl Py_UploadMem(U32 uId, int nType, U32 uAddress, unsigned __int8 *buffer, U32 uLength)

Neo Geo Mini UART dumps

I have dumped some UART output provided by the unit upon a normal boot. No UART information is provided in a recovery boot.

The login prompt is a little unresponsive at start, but no basic combinations of login appear to work. It's also ~1-2 seconds of delay for each wrong password, so bruteforce won't be very efficient.

Boot:
NAND ID: 2c 44 44 4b a9 0 0 0
[NAND] got lsb and readretry table!
startaddr 81055754, size 64, count 64, count_per_line 16
00000000: 2c 44 44 4b a9 ff ff ff 01 10 2e 28 00 01 50 08
00000010: ce 03 28 02 83 00 08 e0 00 00 00 00 00 00 00 00
00000020: 11 80 00 00 35 85 11 80 01 00 01 70 78 78 00 00
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 01 01 02
[SCAN] ScanSearchZoneTbls: (DieNo: 0) enter., 1st blk 8, count:1024
Zonetbl.is GOOD DieNo = 0.
lcd_probe: start
lcd_mfp_set: start
cvbs_probe: start
hdmi_probe: start
asocdss_probe: start
de_sclcoef_config:write DE_SCLCOEF1 fail, so rewrite
asoc_fb_probe: start
get_logo_addr_in_3rd_mbrc: trd_mbrc_start_addr=0x81000000, trd_stage_byte_size=0x7e000, logo_size=0x26000
get_logo_addr_in_3rd_mbrc: logo_addr=0x81058000
asocfb_unblank: pdisp_info->single_display_mode(2)
asocfb_unblank: pdisp_info->single_display_mode(2)
back_light_probe: start, CMU_DEVCLKEN1=0x50040011, PWM2_CTL=0x100
display_welcome: done
load vmlinux from disk0
BusyBox vdebug.14.3 (2018-07-17 07:10:16 PDT) multi-call binary
Usage: insmod FILE [symbol=value]...
Load the specified kernel modules into the kernel
/init: line 422: /Mount: not found
e2fsck 1.41.14 (22-Dec-2010)
/dev/actd: clean, 41/64000 files, 8480/256000 blocks
mknod: /dev/mmc: File exists
mknod: /dev/tty0: File exists
Load usb driver finished
waiting receive ...
(none) login: Property file  ok
sort load crc1 2102828029, crc2 2102828029

Launching Metal Slug 3:
--------- gameID: 32
-----Close font
w: 1280, h : 720
Property file  ok
launchDir = /usr/local/etc/dmenu/
cache_dir = /vendor/res/cache
game_dir = /vendor/res/roms
game_name = mslug3h
--cache_name = /vendor/res/cache/mslug3h_cache isForceCache = 1
CHECKING_BIOS neogeo_bios = -1
neogeo_bios = 12
ALL_NVRAM_FILES_ARE_REMOVED
CHECKING_ROM_INFO
MALLOC addr = 0x2cc7a008  size = 0x44fe4
FREE addr = 0x2cc7a008  size = 0x44fe4
+++ gamew = 304 gameh = 224 +++
CHECKING_ROM_INFO OK
ROMSET_mslug3h_PARENT_mslug3
MALLOC addr = 0x608e78  size = 0x1000
MALLOC addr = 0x609e80  size = 0x4000
MALLOC addr = 0x2cc6a008  size = 0x80000
MALLOC addr = 0x2ccfb008  size = 0x500000
LOADING 256-ph1.p1
LOADING 256-ph2.sp2
+++ neogeo_ngh = 0x256 +++
MALLOC addr = 0x60de88  size = 0x20000
LOADING_BIOS neo-po.bin (Japan AES)
MALLOC addr = 0x2d1fc008  size = 0x90000
LOADING 256-m1.m1
MALLOC addr = 0x62de90  size = 0x20000
LOADING sfix.sfix
MALLOC addr = 0x2d28d008  size = 0x80000
LOADING_DECRYPTED_GFX2_ROM
MALLOC addr = 0x64de98  size = 0x20000
LOADING 000-lo.lo
MALLOC addr = 0x66dea0  size = 0x10000
MALLOC addr = 0x2d30e008  size = 0x1000000
LOADING_DECRYPTED_SOUND1_ROM
LOADING_CACHE_INFORMATION_DATA
65536KB_GFX3_CACHE_FILE(ZYH)
-------open gameDSP
rate is 44100
--dsp fd: 13
reader 4
DONE2
Pressing Start + Select to launch the interrupt menu:
p1 key: 0x300
-------close gamedsp
w: 1280, h : 720
Mode: 0


ADFU ops

So the USB device provided by the unit when booting in recovery mode is an Actions device, vid: 0x10d6, pid: 0x10d6.
It appears to mimic the USB Mass Storage protocol, but a little loosely.
It doesn't follow any of the SCSI commands, instead it appears to have its own command interface.

Commands 0x05, 0x10, and 0xCC were as far as I know found by https://twitter.com/hissorii_com , so props to him. He's attempted to do a little disassembling, but didn't look to go too far before getting bored and giving up. I'll delve in to 0xCC in a different post.

The following have all been disassembled from the x86 linux firmware writing program provided by Actions, from the CMipsDrm class (they left symbols in, awesome!). The x64 version, and the windows versions differ slightly, some fill out the 0x08-0x0B bytes a bit more, some write more zeroes in to bytes, but they're mostly the same. There's also a CDrm class, I may disassemble those too in the future.

Any byte filled with a period hasn't been written to explicitly by one of the routines, but are zeroed out initially. Any byte filled with 0x00 has been explicitly zeroed by a routine, on top of the initial zeroing.

Note regarding the "certificates", I have no idea what these are, they are quite confusing. Each command appears to fetch a different 16bit integer and call it a "certificate".

ADFU Write Type=0x05
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'....length0x00.0x100x05
Offset:0x100x110x120x130x140x150x160x170x18*0x190x1A0x1B0x1C0x1D0x1E
addresslength. & 0x7F......
0x18* : the code AND's 0x7F at offset 0x18 on top of zeroed memory

ADFU Write Type=0x08
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'....length0x00.0x100x08
Offset:0x100x110x120x130x140x150x160x170x18*0x190x1A0x1B0x1C0x1D0x1E
addressaddress4.length >> 9. & 0x7F......
0x18* : the code AND's 0x7F at offset 0x18 on top of zeroed memory

ADFU Write Type=0xB0
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'....length0x00.0x100xB0
Offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
address0x7F & address4.length >> 9certificate.....

ADFU Write Type=0xB0,0x7F
Offset:0x000x010x020x030x040x050x060x070x080x090x0A*0x0B*0x0C0x0D0x0E0x0F
'U''S''B''C'....length0x00.0x100xB0
Offset:0x10*0x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
. & 0x7F.....length >> 9certificate.....
0x0A,0x0B* : bytes at offset 0x0A and 0x0B had 0x00 written to it before the length
0x10* : for some reason the code AND's 0x7F at offset 0x10 on top of the zeroed memory

ADFU Write Type=0xC9,0xF0
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'....length0x00.0x100xC9
Offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0xF0.....length.......

ADFU Write Type=0xC9,0xF2
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'....length0x00.0x100xC9
Offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0xF2.....length.......

ADFU Write Type=0xC9,0xF3
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'....length0x00.0x100xC9
Offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0xF3.....length.......

ADFU Write Type=0xC9,0xF4
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'....length0x00.0x100xC9
Offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0xF4.....length.......

ADFU Read Type=0x05
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'........0x800x000x0C0x05
Offset:0x100x110x120x130x140x150x160x170x18*0x190x1A0x1B0x1C0x1D0x1E
addresslength. | 0x80......
0x18* : 0x80 is OR'd on top of the zeroed memory

ADFU Read Type=0xB0
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'........0x800x000x0C0xB0
Offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
address0x80 | address4.length >> 9certificate.....

ADFU Read Type=0xCA,0xF0
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'........0x800x000x0C0xCA
Offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0xF0.....length.......

ADFU Read Type=0xCA,0xF1
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'....length0x000x000x800x000x0C0xCA
Offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0xF1.....length.......

ADFU Read Type=0xCA,0xF5
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'........0x800x000x0C0xCA
Offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0xF5.....length.......

ADFU Read Type=0xCA,0xF6
Offset:0x000x010x020x030x040x050x060x070x080x090x0A0x0B0x0C0x0D0x0E0x0F
'U''S''B''C'........0x800x000x0C0xCA
Offset:0x100x110x120x130x140x150x160x170x180x190x1A0x1B0x1C0x1D0x1E
0xF6.....length.......
Here I will log all the information I come across as I attempt to explore the inner workings of the very awesome Neo Geo Mini.

All ADFURead commands