CedarX/Reverse Engineering

= Initial information = On June 15 2012 Iain Bullard started reverse engineering the proprietary libraries.

Unfortunately driver are proxy that maps HW Regs to Userspace using mmap all stuff constain in libvecore.so


 * open_cdxalloc as an free reimplementation of Allwinner's libcederxalloc.a.
 * CedarXWrapper as a LD_PRELOADed wrapper to help understanding the proprietary libraries.
 * CedarXPlayerTest as a basic player to use when testing.
 * ReCedro gitorious, has similar tools as those from IanB above, but with a different angle, works really well.

= Object file observations = While android and linux are different beasts from the userspace sense, It could be that the code was written in such way, that it could compile to both targets. Meaning that object files could be similar enough.

From android
The android-linux libvecore.a (md5sum 1c347a9ad3072ce3288bd6dba625b2a4) static lib contains the following files: android functions

From linux-armhf
The linux-armhf libvecore.so (md5sum a026d27307e5204db191878651cc6394) shared object contains the following functions: linux-armhf functions

Lilky both
To generate this list, libvecore.a was used, as it separates things quite nicely and appears to be identical to libvecore.so. That said, this obviously does not have to be true. There is one major difference, libvecore.so also has crtstuff.c functions combined from. While investigating nothing indicated that crtstuff.c from gcc was used directly, it is still likly some functions where used from there.

sunxi-bsp/cedarx-libs/libcedarv/android/libvecore $ arm-pc-linux-gnueabi-ar t libvecore.a | sort

The rest of the bits are all open source, see the linux-sunxi github. The exception is libcedarxalloc.a, but as mentioned above, we have open_cdxalloc.

Function references
So far the following references can easily be observed with readelf -W -s. This is just an indication of some functions, by far complete as it would take way to long and is not really needed.

FFmpeg huffman tree builder: ff_huff_build_tree http://ffmpeg.org/doxygen/trunk/huffman_8c.html

libjpeg: get_soi http://sourceforge.net/p/libjpeg-turbo/code/HEAD/tree/trunk/jdmarker.c

libvp62: VP62_InitCoeffScaleFactors http://en.verysource.com/code/5378534_1/libvp62.h.html

H264/AVC Reference encoder/decoder: remove_frame_from_dpb http://iphome.hhi.de/suehring/tml/doc/lenc/html/mbuffer_8c.html#901bd781eb9aef8b79e98b8e10fbc2aa

VC1 Reference decoder: vc1_eResult vc1DECPIC_UnpackInterlaceMVModeParams http://wiki.multimedia.cx/index.php?title=Understanding_VC-1#vc1DECPIC_UnpackInterlaceMVModeParams

MPEG2: There seems to have happened some function renaming etc, the one that google found though was: ParseQuantMatrixExtension http://sources.team-mediaportal.com/svn/public/tags/Release%201.0.2/DirectShowFilters/TsReader/source/MpegPesParser.cpp = Driver IOCTL guide = Blob mostly use MMIO Access but CedarX should be gate-on and support PLLs should be confugired before

INIT SEQUENCE
This required for make CedarX hardware regs in workable state

IOCTL_ENABLE_VE -> IOCTL_SET_VE_FREQ -> IOCTL_ENGINE_REQ -> IOCTL_RESET_VE

than cedar state should be checked by reading "VE Revision register" that constain chip version 0x1623 for a10, 0x1625 for a13

CORE IOCTL
IOCTL_GET_ENV_INFO = 0x101

return some configuration info, like reserved memory address for cedar

IOCTL_WAIT_VE = 0x102

IOCTL_RESET_VE = 0x103

do reset cedarx engine

IOCTL_ENABLE_VE = 0x104

start base clocks for cedarx

IOCTL_DISABLE_VE = 0x105

disable base clocks for cedarx

IOCTL_SET_VE_FREQ = 0x106

config cedarx plls

AVS2 IOCTL
IOCTL_CONFIG_AVS2 = 0x200

IOCTL_GETVALUE_AVS2 = 0x201

IOCTL_PAUSE_AVS2 = 0x202

IOCTL_START_AVS2 = 0x203

IOCTL_RESET_AVS2 = 0x204

IOCTL_ADJUST_AVS2 = 0x205

ENGINE IOCTL
IOCTL_ENGINE_REQ = 0x206

count references to cedar hardware and more important start some clocks that required for cedar init

IOCTL_ENGINE_REL = 0x207

decrement reference count

IOCTL_ENGINE_CHECK_DELAY = 0x208

IOCTL_GET_IC_VER = 0x209

IOCTL_ADJUST_AVS2_ABS = 0x20a

IOCTL_FLUSH_CACHE = 0x20b do invalidate CPU cache for internal cedar dma

= HW Registers guide = REGS_BASE = 0x01C00000 A10  IO register base addr

MACC_REGS_BASE = (REGS_BASE + 0x0E000) media accelerate VE IO space(4 kb)

Reset/Clock register
MACC_REGS_BASE + 0x00

On some cases reset logic not same with Cedar revisions

VE Ready register
MACC_REGS_BASE + 0x1c

when ready == 0

when not ready == 0x3f00

VE Revision register
MACC_REGS_BASE + 0xF2

Can be used after IOCTL sequence

Constain SoC ID - as VE version

Possible cases:

0x1625 - a13

0x1623 - a10

0x1620 - ???

0x1619 - ???

MPEG Engine
Base address

MPEG_REGS_BASE = (MACC_REGS_BASE + 0x100)

Interupt enable reg = MPEG_REGS_BASE + 0x14

CedarX have internal DMA engine that can use preallocated buffs directly. According traces (mpeg4 test file) CedarX MPEG-Engine use regs as pointers to some mem

MPEG_RESG_BASE+ 0x44 = 0x04009000

MPEG_RESG_BASE+ 0x38 = 0x04000000

MPEG_RESG_BASE+ 0x3c = 0x04008000

MPEG_RESG_BASE+ 0xcc = 0x0480a000

MPEG_RESG_BASE+ 0x1d = 0x0481e000

MPEG_RESG_BASE+ 0x18 = 0x04000000

MPEG_RESG_BASE+ 0x48 = 0x0480a000

MPEG_RESG_BASE+ 0x34 = 0x04809fff

MPEG_RESG_BASE+ 0x4c = 0x0481e000(changes macrocell?)

possible usage: 1) steam info buff 2) src buff 3)dst buff

H264 Engine
Base address

H264_REGS_BASE = (MACC_REGS_BASE + 0x200)

Interupt enable reg = H264_REGS_BASE + 0x20

bitmask 0x0111 enable/disable IRQs from H264 decoder

VC1 Engine
Base address

VC1_REGS_BASE = (MACC_REGS_BASE + 0x300)

Interupt enable reg = VC1_REGS_BASE + 0x24

RMVB Engine
Base address

RMVB_REGS_BASE = (MACC_REGS_BASE + 0x400)

Interupt enable reg = RMVB_REGS_BASE + 0x14

ISP ??
Base address

ISP_REGS_BASE = (MACC_REGS_BASE + 0xa00)

Interupt enable reg = ISP_REGS_BASE + 0x8

AVC Encoder engine
Base address

ISP_REGS_BASE = (MACC_REGS_BASE + 0xb00 )

Interupt enable reg = ISP_REGS_BASE + 0x8

Blob exported funtions description
libv_open do clock setup and initial configuration and init selected engine doing selected *_open

MJPEG Engine API
mjpeg_setup_anaglagh_transform

mjpeg_set_vbv -Video buffering verifier config (CBR/VBR select) call calbacks vbv_get_base_addr and vbv_get_size that we have in source and save infor to internal structure.

mjpeg_set_parent - save pointer to internal structure

mjpeg_set_minor_vbv - STUD

mjpeg_reset - do reset using ve_reset_hardware and internal reset function that touches clock/reset register

mjpeg_release - call callback fbm_release and ve_reset_hardware that we have in sources

mjpeg_open - init mjpeg decoder called by libve_open

mjpeg_io_control -

mjpeg_get_stream_info - use callback for memcopy

mjpeg_get_minor_fbm STUD

mjpeg_get_fbm_num return 1;

mjpeg_get_fbm - return int valure

mjpeg_flush - STUD

mjpeg_decode - general big decoding function

mjpeg_close_anaglagh_transform

mjpeg_close - do callbacks ve_reset_hardware and fbm_release that we have in source

Other findings

 * Old and new kernel drivers both offer a way to directly access registers. It looks like for quite some functions, this approach was chosen. Probably to hide the gory details in the library.