https://bitbucket.org/hudson/magic-lantern
Raw File
Tip revision: 507e319d9b6312d0fd9eed0dc7f509cc35451ffc authored by a1ex on 21 May 2014, 05:21:57 UTC
Close branch mlv_play
Tip revision: 507e319
qemu-helper.c
// Helper library to replace Canon stubs and allow ML emulation in QEMU

#include "dryos.h"
#include "bmp.h"
#include "cache_hacks.h"
#include "compiler.h"

/** Some small engio API **/
#define REG_PRINT_CHAR 0xCF123000
#define REG_SHUTDOWN 0xCF123004
#define REG_DUMP_VRAM 0xCF123008

// all DIGIC V cameras require a RAM offset, take it from stubs.S
#if defined(CONFIG_650D)
#define RAM_OFFSET (0xFFA4DF58-0x1900)
#elif defined(CONFIG_5D3)
#define RAM_OFFSET 0xFF9DEF48
#elif defined(CONFIG_6D)
#define RAM_OFFSET 0xFFCC34D4
#elif defined(CONFIG_EOSM)
#define RAM_OFFSET 0xFFA68D58
#else
#define RAM_OFFSET 0
#endif

#if defined(CONFIG_60D) || defined(CONFIG_600D)
#define AllocateMemory AllocateMemory_do
#endif

#ifdef CONFIG_5D3
#define FIO_FindFirstEx _FIO_FindFirstEx
#define FIO_GetFileSize _FIO_GetFileSize
#define FIO_CreateFile _FIO_CreateFile
extern thunk _FIO_FindFirstEx;
extern thunk _FIO_GetFileSize;
extern thunk _FIO_CreateFile;
#endif

#define BMP_VRAM_ADDR 0x003638100

int qprintf(const char * fmt, ...) // prints in the QEMU console
{
    va_list ap;
    char buf[256];
    va_start( ap, fmt );
    vsnprintf( buf, sizeof(buf)-1, fmt, ap );
    va_end( ap );
    
    for (char* c = buf; *c; c++)
        *(volatile uint32_t*)REG_PRINT_CHAR = *c;
    
    return 0;
}

int
streq( const char * a, const char * b )
{
    while( *a && *b )
        if( *a++ != *b++ )
            return 0;
    return *a == *b;
}

int
snprintf(
    char *          buf,
    size_t          max_len,
    const char *        fmt,
    ...
)
{
    va_list         ap;
    va_start( ap, fmt );
    int len = vsnprintf( buf, max_len - 1, fmt, ap );
    va_end( ap );
    return len;
}

#define NULL_STUB_BODY(name) int q_##name(void) { qprintf("*** " #name "\n"); return 0; }
#define NULL_STUB_BODY_STR(name) int q_##name(char* str) { qprintf("*** " #name "('%s')\n", str); return 0; }
#define NULL_STUB_BODY_HEX(name) int q_##name(int hex) { qprintf("*** " #name "(%x)\n", hex); return 0; }
#define NULL_STUB_BODY_INT(name) int q_##name(int num) { qprintf("*** " #name "(%d)\n", num); return 0; }
#define NULL_STUB_BODY_STR_INT(name) int q_##name(char* str, int num) { qprintf("*** " #name "('%s', %d)\n", str, num); return 0; }

NULL_STUB_BODY(init_task)
NULL_STUB_BODY_INT(cstart)
NULL_STUB_BODY_STR_INT(msg_queue_create)
NULL_STUB_BODY_HEX(CreateRecursiveLock)
NULL_STUB_BODY_HEX(prop_register_slave)
NULL_STUB_BODY_HEX(LoadCalendarFromRTC)
NULL_STUB_BODY_HEX(is_taskid_valid)
NULL_STUB_BODY_HEX(GUI_Control)
NULL_STUB_BODY_INT(CreateResLockEntry)

void launch(void (*func)(void*))
{
    func(0);
}

void q_task_create(char* name, uint32_t priority, uint32_t stack_size, void * entry, void * arg)
{
    qprintf("*** task_create('%s', %d, %x, %x, %x)\n", name, priority, stack_size, entry, arg);
    launch(entry);
}

void q_msleep(int ms)
{
    qprintf("*** msleep(%d)\n", ms);
}

void* q_create_named_semaphore(char* name, int val)
{
    qprintf("*** create_named_semaphore('%s', %d)\n", name, val);
    return 0;
}

int q_take_semaphore(void * sem)
{
    qprintf("*** take_semaphore(%x)\n", sem);
    return 0;
}

int q_give_semaphore(void * sem)
{
    qprintf("*** give_semaphore(%x)\n", sem);
    return 0;
}


void q_call(char* func)
{
    qprintf("*** call('%s')\n", func);
    
    if (streq(func, "dispcheck"))
    {
        *(volatile uint32_t*) REG_DUMP_VRAM = BMP_VRAM_ADDR;
        return;
    }

    if (streq(func, "shutdown"))
    {
        *(volatile uint32_t*) REG_SHUTDOWN = 1;
        return;
    }
}

void* q_AllocateMemory(size_t size)
{
    // dumb alloc, no free
    qprintf("*** AllocateMemory(%x)", size);
    
    static uint32_t alloc_ptr = 0x10000000;
    void* ans = (void*)ALIGN32(alloc_ptr + 64);
    alloc_ptr = ALIGN32(alloc_ptr + size + 128);
    qprintf(" => %x\n", ans);
    return ans;
}

void* q_AllocateMemory_do(void* pool, size_t size) { return q_AllocateMemory(size); }
void* q_malloc(size_t size) { return q_AllocateMemory(size); }
void* q_alloc_dma_memory(size_t size) { return q_AllocateMemory(size); }
NULL_STUB_BODY_HEX(free);
NULL_STUB_BODY_HEX(FreeMemory);
NULL_STUB_BODY_HEX(free_dma_memory);

void q_DryosDebugMsg(int class, int level, char* fmt, ...)
{
    va_list ap;
    char buf[128];
    va_start( ap, fmt );
    vsnprintf( buf, sizeof(buf)-1, fmt, ap );
    va_end( ap );

    qprintf("[DebugMsg] (%d,%d) %s\n", class, level, buf);
}

void * q_FIO_FindFirstEx(const char * dirname, struct fio_file * file)
{
    qprintf("*** FIO_FindFirstEx('%s', %x)\n", dirname, file);
    return (void*)1;
}

int q_FIO_GetFileSize(const char * filename, int* size)
{
    qprintf("*** FIO_GetFileSize('%s')\n", filename);
    *size = 0;
    return 0;
}

int q_FIO_CreateFile(const char * filename)
{
    static int fd = 1;
    qprintf("*** FIO_CreateFile('%s') => %d\n", filename, fd);
    return fd++;
}

int q_FIO_CloseFile(int fd)
{
    qprintf("*** FIO_CloseFile(%x)\n", fd);
    return -1;
}

int q_FIO_WriteFile(int fd, char* buf, int size)
{
    qprintf("*** FIO_WriteFile(%x, %d)\n{{{\n", fd, size);
    for (int i = 0; i < MIN(size, 128); i++)
        *(volatile uint32_t*)REG_PRINT_CHAR = buf[i];
    qprintf("\n}}}\n");
    return size;
}

#define STUB_MAP(name) &name, &q_##name,

void cam_init()
{
    // set BMP VRAM
    bmp_vram_info[1].vram2 = (void*) BMP_VRAM_ADDR;

    // fake display on
    #ifdef DISPLAY_STATEOBJ
    DISPLAY_STATEOBJ->current_state = 1;
    #else
    DISPLAY_IS_ON = 1;
    #endif
}

void q_create_init_task(int unused, void (*init_task)(void*))
{
    qprintf("create_init_task(%x)\n", init_task);
    cam_init();
    launch(init_task);
}

extern thunk AllocateMemory_do;
extern thunk msg_queue_create;
extern thunk prop_register_slave;
extern thunk is_taskid_valid;
extern thunk GUI_Control;
extern thunk CreateResLockEntry;

#define MAGIC (void*)0x12345678
void*  stub_mappings[] = {
    MAGIC, MAGIC, RAM_OFFSET,
    STUB_MAP(create_init_task)
    STUB_MAP(init_task)
    STUB_MAP(task_create)
    STUB_MAP(msleep)
    STUB_MAP(malloc)
    STUB_MAP(free)
    STUB_MAP(alloc_dma_memory)
    STUB_MAP(free_dma_memory)
    STUB_MAP(AllocateMemory)
    STUB_MAP(FreeMemory)
    STUB_MAP(DryosDebugMsg)
    STUB_MAP(call)
    STUB_MAP(create_named_semaphore)
    STUB_MAP(take_semaphore)
    STUB_MAP(give_semaphore)
    STUB_MAP(msg_queue_create)
    STUB_MAP(CreateRecursiveLock)
    STUB_MAP(FIO_FindFirstEx)
    STUB_MAP(FIO_GetFileSize)
    STUB_MAP(FIO_CreateFile)
    STUB_MAP(FIO_WriteFile)
    STUB_MAP(FIO_CloseFile)
    
    STUB_MAP(prop_register_slave)
    STUB_MAP(LoadCalendarFromRTC)
    STUB_MAP(is_taskid_valid)
    STUB_MAP(GUI_Control)
    #ifdef CONFIG_ENGINE_RESLOCK
    STUB_MAP(CreateResLockEntry)
    #endif
    
    MAGIC, MAGIC,
};

void exit(int arg)
{
    *(volatile uint32_t*) REG_SHUTDOWN = 1;
    while(1);
}
back to top