https://bitbucket.org/daniel_fort/magic-lantern
Raw File
Tip revision: de7c83e4d7c4dbd899d30a1f06fe28142d89b441 authored by g3gg0 on 23 December 2012, 23:23:27 UTC
7D: release information
Tip revision: de7c83e
boot-hack.c
/** \file
 * Code to run on the camera once it has been relocated.
 *
 * !!!!!! FOR NEW PORTS, READ PROPERTY.C FIRST !!!!!!
 * OTHERWISE YOU CAN CAUSE PERMANENT CAMERA DAMAGE
 * 
 */
/*
 * Copyright (C) 2009 Trammell Hudson <hudson+ml@osresearch.net>
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#include "dryos.h"
#include "config.h"
#include "version.h"
#include "bmp.h"
#include "menu.h"
#include "version.h"
#include "property.h"
#include "consts.h"
#include "tskmon.h"
#if defined(HIJACK_CACHE_HACK) || defined(CONFIG_6D)
#include "cache_hacks.h"
#endif

/** These are called when new tasks are created */
void my_task_dispatch_hook( struct context ** );
int my_init_task(int a, int b, int c, int d);
void my_bzero( uint8_t * base, uint32_t size );

/** This just goes into the bss */
#define RELOCSIZE 0x3000 // look in HIJACK macros for the highest address, and subtract ROMBASEADDR
static uint8_t _reloc[ RELOCSIZE ];
#define RELOCADDR ((uintptr_t) _reloc)

/** Translate a firmware address into a relocated address */
#define INSTR( addr ) ( *(uint32_t*)( (addr) - ROMBASEADDR + RELOCADDR ) )

/** Fix a branch instruction in the relocated firmware image */
#define FIXUP_BRANCH( rom_addr, dest_addr ) \
    INSTR( rom_addr ) = BL_INSTR( &INSTR( rom_addr ), (dest_addr) )


/** Specified by the linker */
extern uint32_t _bss_start[], _bss_end[];

/** Zeroes out bss */
static inline void
zero_bss( void )
{
    uint32_t *bss = _bss_start;
    while( bss < _bss_end )
        *(bss++) = 0;
}

#if defined(CONFIG_6D)
void hijack_6d_guitask()
{
    void my_gui_main_task();
    task_create("GuiMainTask", 0x17, 0x2000, my_gui_main_task, 0);
}
#endif


/** Copy firmware to RAM, patch it and restart it */
void
copy_and_restart( )
{
    // Clear bss
    zero_bss();

#ifdef HIJACK_CACHE_HACK
    /* make sure we have the first segment locked in d/i cache for patching */    
    cache_lock();

    /* patch init code to start our init task instead of canons default */
    cache_fake(HIJACK_CACHE_HACK_INITTASK_ADDR, (uint32_t) my_init_task, TYPE_DCACHE);

    /* now start main firmware */
    void (*reset)(void) = (void*) ROMBASEADDR;
    reset();
#else
    // Copy the firmware to somewhere safe in memory
    const uint8_t * const firmware_start = (void*) ROMBASEADDR;
    const uint32_t firmware_len = RELOCSIZE;
    uint32_t * const new_image = (void*) RELOCADDR;

    blob_memcpy( new_image, firmware_start, firmware_start + firmware_len );

    /*
     * in entry2() (0xff010134) make this change to
     * return to our code before calling cstart().
     * This should be a "BL cstart" instruction.
     */
    INSTR( HIJACK_INSTR_BL_CSTART ) = RET_INSTR;

    /*
     * in cstart() (0xff010ff4) make these changes:
     * calls bzero(), then loads bs_end and calls
     * create_init_task
     */
    // Reserve memory after the BSS for our application
    #if !defined(CONFIG_550D) && !defined(CONFIG_600D) && !defined(CONFIG_1100D) // 550D/600D/1100D load ML in the AllocateMemory pool
    INSTR( HIJACK_INSTR_BSS_END ) = (uintptr_t) _bss_end;
    #endif

    // Fix the calls to bzero32() and create_init_task()
    FIXUP_BRANCH( HIJACK_FIXBR_BZERO32, bzero32 );
    FIXUP_BRANCH( HIJACK_FIXBR_CREATE_ITASK, create_init_task );

    // Set our init task to run instead of the firmware one
    INSTR( HIJACK_INSTR_MY_ITASK ) = (uint32_t) my_init_task;
    
    // Make sure that our self-modifying code clears the cache
    clean_d_cache();
    flush_caches();
    
    //~ temporary, this is the only way I could manage to hijack the GUI task. just hacking data cache
    //~ didn't work..
#ifdef CONFIG_6D
    cache_lock();
    cache_fake(0xFF0DF6DC, BL_INSTR(0xFF0DF6DC, (uint32_t)hijack_6d_guitask), TYPE_ICACHE);
#endif

    // We enter after the signature, avoiding the
    // relocation jump that is at the head of the data
    thunk reloc_entry = (thunk)( RELOCADDR + 0xC );
    reloc_entry();

    /*
    * We're back!
    * The RAM copy of the firmware startup has:
    * 1. Poked the DMA engine with what ever it does
    * 2. Copied the rw_data segment to 0x1900 through 0x20740
    * 3. Zeroed the BSS from 0x20740 through 0x47550
    * 4. Copied the interrupt handlers to 0x0
    * 5. Copied irq 4 to 0x480.
    * 6. Installed the stack pointers for CPSR mode D2 and D3
    * (we are still in D3, with a %sp of 0x1000)
    * 7. Returned to us.
    *
    * Now is our chance to fix any data segment things, or
    * install our own handlers.
    */

    //~ Canon changed their task starting method in the 6D so our old hook method doesn't work.
#ifndef CONFIG_6D
#if !defined(CONFIG_EARLY_PORT) && !defined(CONFIG_HELLO_WORLD)
    // Install our task creation hooks
    task_dispatch_hook = my_task_dispatch_hook;
    tskmon_init();
#endif
#endif

    // This will jump into the RAM version of the firmware,
    // but the last branch instruction at the end of this
    // has been modified to jump into the ROM version
    // instead.
    void (*ram_cstart)(void) = (void*) &INSTR( cstart );
    ram_cstart();
#endif

    // Unreachable
    while(1)
        ;
}


#ifndef CONFIG_EARLY_PORT

/** This task does nothing */
void
null_task( void )
{
    DebugMsg( DM_SYS, 3, "%s created (and exiting)", __func__ );
    return;
}

/**
 * Called by DryOS when it is dispatching (or creating?)
 * a new task.
 */
void
my_task_dispatch_hook(
    struct context **   context
)
{
    if( !context )
        return;
    
    tskmon_task_dispatch();

    // Do nothing unless a new task is starting via the trampoile
    if( (*context)->pc != (uint32_t) task_trampoline )
        return;
    
    // Determine the task address
    struct task * const task = *(struct task**) HIJACK_TASK_ADDR;

    thunk entry = (thunk) task->entry;

    // Search the task_mappings array for a matching entry point
    extern struct task_mapping _task_overrides_start[];
    extern struct task_mapping _task_overrides_end[];
    const struct task_mapping * mapping = _task_overrides_start;

    for( ; mapping < _task_overrides_end ; mapping++ )
    {
        thunk original_entry = mapping->orig;
        if( original_entry != entry )
            continue;

/* -- can't call debugmsg from this context */
#if 0
        DebugMsg( DM_SYS, 3, "***** Replacing task %x with %x",
            original_entry,
            mapping->replacement
        );
#endif

        task->entry = mapping->replacement;
        break;
    }
}


/** 
 * First task after a fresh rebuild.
 *
 * Try to dump the debug log after ten seconds.
 * This requires the create_task(), dmstart(), msleep() and dumpf()
 * routines to have been found.
 */
void
my_dump_task( void )
{
    call("dmstart");

    msleep( 10000 );
    call("dispcheck");

    call("dumpf");
    call("dmstop");
}


struct config * global_config;

static volatile int init_funcs_done;


/** Call all of the init functions  */
static void
call_init_funcs( void * priv )
{
    extern struct task_create _init_funcs_start[];
    extern struct task_create _init_funcs_end[];
    struct task_create * init_func = _init_funcs_start;

    for( ; init_func < _init_funcs_end ; init_func++ )
    {
        DebugMsg( DM_MAGIC, 3,
            "Calling init_func %s (%x)",
            init_func->name,
            (unsigned) init_func->entry
        );
        thunk entry = (thunk) init_func->entry;
        entry();
    }

}


#endif // !CONFIG_EARLY_PORT

static void nop( void ) { }
void menu_init( void ) __attribute__((weak,alias("nop")));
void debug_init( void ) __attribute__((weak,alias("nop")));

int magic_off = 0; // Set to 1 to disable ML
int magic_off_request = 0;
int magic_is_off() 
{
    return magic_off; 
}


#if defined(CONFIG_AUTOBACKUP_ROM)

#define BACKUP_BLOCKSIZE 0x00100000

void backup_region(char *file, uint32_t base, uint32_t length)
{
    FILE *handle = NULL;
    unsigned int size = 0;
    uint32_t pos = 0;
    
    /* already backed up that region? */
    if((FIO_GetFileSize( file, &size ) == 0) && (size == length) )
    {
        return;
    }
    
    /* no, create file and store data */
    handle = FIO_CreateFileEx(file);
    while(pos < length)
    {
        uint32_t blocksize = BACKUP_BLOCKSIZE;
        
        if(length - pos < blocksize)
        {
            blocksize = length - pos;
        }
        
        FIO_WriteFile(handle, &((uint8_t*)base)[pos], blocksize);
        pos += blocksize;
        
        /* to make sure lower prio tasks can also run */
        msleep(20);
    }
    FIO_CloseFile(handle);
}

void backup_task()
{
    backup_region(CARD_DRIVE "ML/LOGS/ROM1.BIN", 0xF8000000, 0x01000000);
    backup_region(CARD_DRIVE "ML/LOGS/ROM0.BIN", 0xF0000000, 0x01000000);
}
#endif

int _hold_your_horses = 1; // 0 after config is read
int ml_started = 0; // 1 after ML is fully loaded
int ml_gui_initialized = 0; // 1 after gui_main_task is started 

static int compute_signature(int* start, int num)
{
        int c = 0;
        int* p;
        for (p = start; p < start + num; p++)
        {
                c += *p;
        }
        return c;
}


// Only after this task finished, the others are started
// From here we can do file I/O and maybe other complex stuff
void my_big_init_task()
{
    load_fonts();
    
#if defined(CONFIG_HELLO_WORLD) || defined(CONFIG_DUMPER_BOOTFLAG)
  uint32_t len;
#endif

#ifdef CONFIG_HELLO_WORLD
    len = compute_signature(ROMBASEADDR, 0x10000);
    while(1)
    {
        bmp_printf(FONT_LARGE, 50, 50, "Hello, World!");
        bfnt_puts("Hello, World", 50, 100, COLOR_BLACK, COLOR_WHITE);
        bmp_printf(FONT_LARGE, 50, 400, "firmware signature = 0x%x", len);
        info_led_blink(1, 500, 500);
    }
#endif
#ifdef CONFIG_DUMPER_BOOTFLAG
    msleep(500);
    call("EnableBootDisk");
    bmp_printf(FONT_LARGE, 50, 200, "EnableBootDisk");
    msleep(500);
    FILE* f = FIO_CreateFile(CARD_DRIVE "k301_101.dat");
    if (f) {
        len=FIO_WriteFile(f, (void*) 0xFF000000, 0x01000000);
        FIO_CloseFile(f);
        bmp_printf(FONT_LARGE, 50, 250, "Oops!");    
    }
    info_led_blink(1, 500, 500);
#endif
    
    call("DisablePowerSave");
    menu_init();
    debug_init();
    call_init_funcs( 0 );
    msleep(200); // leave some time for property handlers to run

    #ifdef CONFIG_BATTERY_TEST
    while(1)
    {
        RefreshBatteryLevel_1Hz();
        wait_till_next_second();
        batt_display(0, 0, 0, 0);
    }
    return;
    #endif

    #if defined(CONFIG_AUTOBACKUP_ROM)
    /* backup ROM first time to be prepared if anything goes wrong. choose low prio */
    /* On 5D3, this needs to run after init functions (after card tests) */
    task_create("ml_backup", 0x1f, 0x4000, backup_task, 0 );
    #endif

    #ifdef CONFIG_CONFIG_FILE
    // Read ML config
    config_parse_file( CARD_DRIVE "ML/SETTINGS/magic.cfg" );
    #endif
    
    debug_init_stuff();

    _hold_your_horses = 0; // config read, other overriden tasks may start doing their job

    // Create all of our auto-create tasks
    extern struct task_create _tasks_start[];
    extern struct task_create _tasks_end[];
    struct task_create * task = _tasks_start;

    int ml_tasks = 0;
    for( ; task < _tasks_end ; task++ )
    {
        //~ DebugMsg( DM_MAGIC, 3,
            //~ "Creating task %s(%d) pri=%02x flags=%08x",
            //~ task->name,
            //~ task->arg,
            //~ task->priority,
            //~ task->flags
        //~ );
        
        // for debugging: uncomment this to start only some specific tasks
        // tip: use something like grep -nr TASK_CREATE ./ to find all task names
        #if 0
        if (
                //~ streq(task->name, "audio_meter_task") ||
                //~ streq(task->name, "audio_level_task") ||
                //~ streq(task->name, "bitrate_task") ||
                //~ streq(task->name, "cartridge_task") ||
                //~ streq(task->name, "cls_task") ||
                //~ streq(task->name, "console_task") ||
                streq(task->name, "debug_task") ||
                //~ streq(task->name, "dmspy_task") ||
                //~ streq(task->name, "focus_task") ||
                //~ streq(task->name, "focus_misc_task") ||
                //~ streq(task->name, "fps_task") ||
                //~ streq(task->name, "iso_adj_task") ||
                //~ streq(task->name, "joypress_task") ||
                //~ streq(task->name, "light_sensor_task") ||
                //~ streq(task->name, "livev_hiprio_task") ||
                //~ streq(task->name, "livev_loprio_task") ||
                streq(task->name, "menu_task") ||
                streq(task->name, "menu_redraw_task") ||
                //~ streq(task->name, "morse_task") ||
                //~ streq(task->name, "movtweak_task") ||
                //~ streq(task->name, "ms100_clock_task") ||
                //~ streq(task->name, "notifybox_task") ||
                //~ streq(task->name, "plugins_task") ||
                //~ streq(task->name, "seconds_clock_task") ||
                //~ streq(task->name, "shoot_task") ||
                //~ streq(task->name, "tweak_task") ||
                //~ streq(task->name, "beep_task") ||
                //~ streq(task->name, "crash_log_task") ||
            0 )
        #endif
        {
            task_create(
                task->name,
                task->priority,
                task->stack_size,
                task->entry,
                task->arg
            );
            ml_tasks++;
        }
        //~ else
        //~ {
            //~ bmp_printf(FONT_LARGE, 50, 50, "skip %s  ", task->name);
            //~ msleep(1000);
        //~ }
    }
    //~ bmp_printf( FONT_MED, 0, 85,
        //~ "Magic Lantern is up and running... %d tasks started.",
        //~ ml_tasks
    //~ );
    
    msleep(500);
    ml_started = 1;

    //~ stress_test_menu_dlg_api_task(0);
}

/*void logo_task(void* unused)
{
    show_logo();
    while (!ml_started) msleep(100);
    stop_killing_flicker();
}*/

/** Blocks execution until config is read */
void hold_your_horses(int showlogo)
{
    while (_hold_your_horses)
    {
        msleep( 100 );
    }
}

/**
 * Custom assert handler - intercept ERR70 and try to save a crash log.
 * Crash log should contain Canon error message.
 */
static char assert_msg[1000] = "";
int (*old_assert_handler)(char*,char*,int,int) = 0;
const char* get_assert_msg() { return assert_msg; }

int my_assert_handler(char* msg, char* file, int line, int arg4)
{
    snprintf(assert_msg, sizeof(assert_msg), 
        "ASSERT: %s\n"
        "at %s:%d, task %s\n"
        "lv:%d mode:%d\n", 
        msg, 
        file, line, get_task_name_from_id(get_current_task()), 
        lv, shooting_mode
    );
    request_crash_log(1);
    return old_assert_handler(msg, file, line, arg4);
}

void ml_assert_handler(char* msg, char* file, int line, const char* func)
{
    snprintf(assert_msg, sizeof(assert_msg), 
        "ML ASSERT:\n%s\n"
        "at %s:%d (%s), task %s\n"
        "lv:%d mode:%d\n", 
        msg, 
        file, line, func, get_task_name_from_id(get_current_task()), 
        lv, shooting_mode
    );
    request_crash_log(2);
}


#ifdef CONFIG_550D
int init_task_patched_for_550D(int a, int b, int c, int d)
{
    // We shrink the AllocateMemory (system memory) pool in order to make space for ML binary
    // ff018d1c: init_task:
    // ff018d90: b CreateTaskMain
    //
    // ff011c94 CreateTaskMain:
    // ff011cb4: mov r1, #13631488  ; 0xd00000  <-- end address
    // ff011cb8: mov r0, #3997696   ; 0x3d0000  <-- start address
    // ff011cbc: bl  allocatememory_init_pool

    // So... we need to patch CreateTaskMain, which is called by init_task.
    //
    // First we use Trammell's reloc.c code to relocate init_task and CreateTaskMain...

    #define init_task_start 0xff018d1c
    #define init_task_end   0xff018ef4
    #define init_task_len   (init_task_end - init_task_start)

    #define CreateTaskMain_start 0xff011c94
    #define CreateTaskMain_end   0xff011f50
    #define CreateTaskMain_len   (CreateTaskMain_end - CreateTaskMain_start)
    
    static char init_task_reloc_buf[init_task_len+64];
    static char CreateTaskMain_reloc_buf[CreateTaskMain_len+64];
    
    int (*new_init_task)(int,int,int,int) = (void*)reloc(
        0,      // we have physical memory
        0,      // with no virtual offset
        init_task_start,
        init_task_end,
        init_task_reloc_buf
    );

    int (*new_CreateTaskMain)(void) = (void*)reloc(
        0,      // we have physical memory
        0,      // with no virtual offset
        CreateTaskMain_start,
        CreateTaskMain_end,
        CreateTaskMain_reloc_buf
    );
    
    const uintptr_t init_task_offset = (intptr_t)new_init_task - (intptr_t)init_task_reloc_buf - (intptr_t)init_task_start;
    const uintptr_t CreateTaskMain_offset = (intptr_t)new_CreateTaskMain - (intptr_t)CreateTaskMain_reloc_buf - (intptr_t)CreateTaskMain_start;

    // Done relocating, now we can patch things.

    //~ uint32_t* addr_AllocMem_start   = (void*)(CreateTaskMain_reloc_buf + 0xff011cb8 + CreateTaskMain_offset);
    uint32_t* addr_AllocMem_end     = (void*)(CreateTaskMain_reloc_buf + 0xff011cb4 + CreateTaskMain_offset);
    uint32_t* addr_BL_AllocMem_init = (void*)(CreateTaskMain_reloc_buf + 0xff011cbc + CreateTaskMain_offset);

    // change end limit to 0xc800000 => reserve 500K for ML
    // thanks to ARMada by g3gg0 for the black magic :)
    *addr_AllocMem_end = 0xE3A01732;

    // relocating CreateTaskMain does some nasty things, so, right after patching,
    // we jump back to ROM version; at least, what's before patching seems to be relocated properly
    *addr_BL_AllocMem_init = B_INSTR(addr_BL_AllocMem_init, 0xff011cbc);
    
    uint32_t* addr_B_CreateTaskMain = (void*)init_task_reloc_buf + 0xff018d90 + init_task_offset;
    *addr_B_CreateTaskMain = B_INSTR(addr_B_CreateTaskMain, new_CreateTaskMain);
    
    
    /* FIO_RemoveFile("B:/dump.hex");
    FILE* f = FIO_CreateFile("B:/dump.hex");
    FIO_WriteFile(f, UNCACHEABLE(new_CreateTaskMain), CreateTaskMain_len);
    FIO_CloseFile(f);
    
    NotifyBox(10000, "%x ", new_CreateTaskMain); */
    
    // Well... let's cross the fingers and call the relocated stuff
    return new_init_task(a,b,c,d);

}
#endif

#ifdef CONFIG_600D
int init_task_patched_for_600D(int a, int b, int c, int d)
{
    // We shrink the AllocateMemory (system memory) pool in order to make space for ML binary
    // ff0197fc: init_task:
    // ff019870: b CreateTaskMain
    //
    // ff0123c4 CreateTaskMain:
    // ff0123e4: mov r1, #13631488  ; 0xd00000  <-- end address
    // ff0123e8: mov r0, #3997696   ; 0x3d0000  <-- start address
    // ff0123ec: bl  allocatememory_init_pool

    // So... we need to patch CreateTaskMain, which is called by init_task.
    //
    // First we use Trammell's reloc.c code to relocate init_task and CreateTaskMain...

    #define init_task_start 0xff0197fc
    #define init_task_end   0xFF0199D4
    #define init_task_len   (init_task_end - init_task_start)

    #define CreateTaskMain_start 0xFF0123C4
    #define CreateTaskMain_end   0xFF0126B8
    #define CreateTaskMain_len   (CreateTaskMain_end - CreateTaskMain_start)
    
    static char init_task_reloc_buf[init_task_len+64];
    static char CreateTaskMain_reloc_buf[CreateTaskMain_len+64];
    
    int (*new_init_task)(int,int,int,int) = (void*)reloc(
        0,      // we have physical memory
        0,      // with no virtual offset
        init_task_start,
        init_task_end,
        init_task_reloc_buf
    );

    int (*new_CreateTaskMain)(void) = (void*)reloc(
        0,      // we have physical memory
        0,      // with no virtual offset
        CreateTaskMain_start,
        CreateTaskMain_end,
        CreateTaskMain_reloc_buf
    );
    
    const uintptr_t init_task_offset = (intptr_t)new_init_task - (intptr_t)init_task_reloc_buf - (intptr_t)init_task_start;
    const uintptr_t CreateTaskMain_offset = (intptr_t)new_CreateTaskMain - (intptr_t)CreateTaskMain_reloc_buf - (intptr_t)CreateTaskMain_start;

    // Done relocating, now we can patch things.

    uint32_t* addr_AllocMem_end     = (void*)(CreateTaskMain_reloc_buf + 0xff0123e4 + CreateTaskMain_offset);
    uint32_t* addr_BL_AllocMem_init = (void*)(CreateTaskMain_reloc_buf + 0xff0123ec + CreateTaskMain_offset);

    // change end limit to 0xc800000 => reserve 500K for ML
    // thanks to ARMada by g3gg0 for the black magic :)
    *addr_AllocMem_end = 0xE3A01732;

    // relocating CreateTaskMain does some nasty things, so, right after patching,
    // we jump back to ROM version; at least, what's before patching seems to be relocated properly
    *addr_BL_AllocMem_init = B_INSTR(addr_BL_AllocMem_init, 0xff0123ec);
    
    uint32_t* addr_B_CreateTaskMain = (void*)init_task_reloc_buf + 0xff019870 + init_task_offset;
    *addr_B_CreateTaskMain = B_INSTR(addr_B_CreateTaskMain, new_CreateTaskMain);
    
    
    /* FIO_RemoveFile("B:/dump.hex");
    FILE* f = FIO_CreateFile("B:/dump.hex");
    FIO_WriteFile(f, UNCACHEABLE(new_CreateTaskMain), CreateTaskMain_len);
    FIO_CloseFile(f);
    
    NotifyBox(10000, "%x ", new_CreateTaskMain); */
    
    // Well... let's cross the fingers and call the relocated stuff
    return new_init_task(a,b,c,d);

}
#endif


#ifdef CONFIG_1100D
int init_task_patched_for_1100D(int a, int b, int c, int d)
{
    // We shrink the AllocateMemory (system memory) pool in order to make space for ML binary
    // ff0197d8: init_task:
    // ff01984c: b CreateTaskMain
    //
    // ff0123c4 CreateTaskMain:
    // ff0123e4: mov r1, #13631488  ; 0xd00000  <-- end address
    // ff0123e8: mov r0, #3997696   ; 0x3d0000  <-- start address
    // ff0123ec: bl  allocatememory_init_pool

    // So... we need to patch CreateTaskMain, which is called by init_task.
    //
    // First we use Trammell's reloc.c code to relocate init_task and CreateTaskMain...

    #define init_task_start 0xff0197d8
    #define init_task_end   0xff0199b0
    #define init_task_len   (init_task_end - init_task_start)

    #define CreateTaskMain_start 0xFF0123C4
    #define CreateTaskMain_end   0xFF0126B4
    #define CreateTaskMain_len   (CreateTaskMain_end - CreateTaskMain_start)
    
    static char init_task_reloc_buf[init_task_len+64];
    static char CreateTaskMain_reloc_buf[CreateTaskMain_len+64];
    
    int (*new_init_task)(int,int,int,int) = (void*)reloc(
        0,      // we have physical memory
        0,      // with no virtual offset
        init_task_start,
        init_task_end,
        init_task_reloc_buf
    );

    int (*new_CreateTaskMain)(void) = (void*)reloc(
        0,      // we have physical memory
        0,      // with no virtual offset
        CreateTaskMain_start,
        CreateTaskMain_end,
        CreateTaskMain_reloc_buf
    );
    
    const uintptr_t init_task_offset = (intptr_t)new_init_task - (intptr_t)init_task_reloc_buf - (intptr_t)init_task_start;
    const uintptr_t CreateTaskMain_offset = (intptr_t)new_CreateTaskMain - (intptr_t)CreateTaskMain_reloc_buf - (intptr_t)CreateTaskMain_start;

    // Done relocating, now we can patch things.

    uint32_t* addr_AllocMem_end     = (void*)(CreateTaskMain_reloc_buf + 0xff0123e4 + CreateTaskMain_offset);
    uint32_t* addr_BL_AllocMem_init = (void*)(CreateTaskMain_reloc_buf + 0xff0123ec + CreateTaskMain_offset);

    // change end limit to 0xc800000 => reserve 500K for ML
    // thanks to ARMada by g3gg0 for the black magic :)
    *addr_AllocMem_end = 0xE3A01732;

    // relocating CreateTaskMain does some nasty things, so, right after patching,
    // we jump back to ROM version; at least, what's before patching seems to be relocated properly
    *addr_BL_AllocMem_init = B_INSTR(addr_BL_AllocMem_init, 0xff0123ec);
    
    uint32_t* addr_B_CreateTaskMain = (void*)init_task_reloc_buf + 0xff01984c + init_task_offset;
    *addr_B_CreateTaskMain = B_INSTR(addr_B_CreateTaskMain, new_CreateTaskMain);
    
    
    /* FIO_RemoveFile("B:/dump.hex");
    FILE* f = FIO_CreateFile("B:/dump.hex");
    FIO_WriteFile(f, UNCACHEABLE(new_CreateTaskMain), CreateTaskMain_len);
    FIO_CloseFile(f);
    
    NotifyBox(10000, "%x ", new_CreateTaskMain); */
    
    // Well... let's cross the fingers and call the relocated stuff
    return new_init_task(a,b,c,d);

}
#endif

// flag set to 1 when gui_main_task started to process messages from queue
int gui_init_done = 0;



/** Initial task setup.
 *
 * This is called instead of the task at 0xFF811DBC.
 * It does all of the stuff to bring up the debug manager,
 * the terminal drivers, stdio, stdlib and armlib.
 */
int
my_init_task(int a, int b, int c, int d)
{
#ifdef ARMLIB_OVERFLOWING_BUFFER
    // An overflow in Canon code may write a zero right in the middle of ML code
    unsigned int *backup_address = 0;
    unsigned int backup_data = 0;
    unsigned int task_id = (unsigned int)get_current_task();

    if(task_id > 0x68 && task_id < 0xFFFFFFFF)
    {
        unsigned int *some_table = (unsigned int *)ARMLIB_OVERFLOWING_BUFFER;
        backup_address = &some_table[task_id-1];
        backup_data = *backup_address;
    }
#endif

#ifdef HIJACK_CACHE_HACK
    /* as we do not return in the middle of te init task as in the hijack-through-copy method, we have to install the hook here */
    task_dispatch_hook = my_task_dispatch_hook;
    tskmon_init();
    
    /* now patch init task and continue execution */
    cache_fake(HIJACK_CACHE_HACK_BSS_END_ADDR, HIJACK_CACHE_HACK_BSS_END_INSTR, TYPE_ICACHE);
    
    int ans = init_task(a,b,c,d);
    
    /* no functions/caches need to get patched anymore, we can disable cache hacking again */    
    /* use all cache pages again, so we run at "full speed" although barely noticeable (<1% speedup/slowdown) */
    //cache_unlock();
#else
    // Call their init task
    #ifdef CONFIG_550D
    int ans = init_task_patched_for_550D(a,b,c,d);
    #elif defined(CONFIG_600D)
    int ans = init_task_patched_for_600D(a,b,c,d);
    #elif defined(CONFIG_1100D)
    int ans = init_task_patched_for_1100D(a,b,c,d);
    #else
    int ans = init_task(a,b,c,d);
    #endif
#endif

#ifdef ARMLIB_OVERFLOWING_BUFFER
    // Restore the overwritten value, if any
    if(backup_address != 0)
    {
        *backup_address = backup_data;
    }
#endif

#ifdef CONFIG_CRASH_LOG
#ifdef DRYOS_ASSERT_HANDLER
    // decompile TH_assert to find out the location
    old_assert_handler = (void*)MEM(DRYOS_ASSERT_HANDLER);
    *(void**)(DRYOS_ASSERT_HANDLER) = (void*)my_assert_handler;
#endif
#endif
    
#ifndef CONFIG_EARLY_PORT
    // Overwrite the PTPCOM message
    dm_names[ DM_MAGIC ] = "[MAGIC] ";
    //~ dmstart(); // already called by firmware?

    DebugMsg( DM_MAGIC, 3, "Magic Lantern %s (%s)",
        build_version,
        build_id
    );

    DebugMsg( DM_MAGIC, 3, "Built on %s by %s",
        build_date,
        build_user
    );
#endif

#if !defined(CONFIG_NO_ADDITIONAL_VERSION)
    // Re-write the version string.
    // Don't use strcpy() so that this can be done
    // before strcpy() or memcpy() are located.
    extern char additional_version[];
    additional_version[0] = '-';
    additional_version[1] = 'm';
    additional_version[2] = 'l';
    additional_version[3] = '-';
    additional_version[4] = build_version[0];
    additional_version[5] = build_version[1];
    additional_version[6] = build_version[2];
    additional_version[7] = build_version[3];
    additional_version[8] = build_version[4];
    additional_version[9] = build_version[5];
    additional_version[10] = build_version[6];
    additional_version[11] = build_version[7];
    additional_version[12] = build_version[8];
    additional_version[13] = '\0';
#endif

#ifndef CONFIG_EARLY_PORT

    // wait for firmware to initialize
    while (!bmp_vram_raw()) msleep(100);
    
    // wait for overriden gui_main_task (but use a timeout so it doesn't break if you disable that for debugging)
    for (int i = 0; i < 30; i++)
    {
        if (ml_gui_initialized) break;
        msleep(100);
    }
    msleep(200);

    // at this point, gui_main_start should be started and should be able to tell whether SET was pressed at startup
    if (magic_off_request)
    {
        magic_off = 1;  // magic off request might be sent later (until ml is fully started), but will be ignored
        for (int i = 0; i < 10; i++)
        {
            if (DISPLAY_IS_ON) break;
            msleep(100);
        }
        bfnt_puts("Magic OFF", 0, 0, COLOR_WHITE, COLOR_BLACK);
    #if !defined(CONFIG_NO_ADDITIONAL_VERSION)
        extern char additional_version[];
        additional_version[0] = '-';
        additional_version[1] = 'm';
        additional_version[2] = 'l';
        additional_version[3] = '-';
        additional_version[4] = 'o';
        additional_version[5] = 'f';
        additional_version[6] = 'f';
        additional_version[7] = '\0';
    #endif
        return ans;
    }

    task_create("ml_init", 0x1e, 0x4000, my_big_init_task, 0 );

    return ans;
#endif // !CONFIG_EARLY_PORT
}

#ifdef CONFIG_5D3
// dummy stubs
int lcd_release_running = 0;
void lcd_release_step() {};
int get_lcd_sensor_shortcuts() { return 0; }
void display_lcd_remote_icon(int x0, int y0) {}
int new_LiveViewApp_handler = 0xff123456;
void bootflag_write_bootblock(){};
int handle_af_patterns(struct event * event) { return 1; }

#endif
back to top