Esempio n. 1
0
//-----------------------------------------------
// return: 0 if error, otherwise ok
static int module_do_action( char* actionname, uint32_t offset, uint32_t count, uint32_t segment_size, _module_action_t func )
{
    if ( count > 0 ) 
    {
        if ( offset != lseek(module_fd, offset, SEEK_SET) )
        {
            moduleload_error("action %s",(int)actionname);
            return 0;
        }
        if ( segment_size != read(module_fd, buf_load, segment_size) )
        {
            moduleload_error("action %s", (int)actionname);
            return 0;
        }

        // make relocations
        if ( !func( flat_buf, (uint32_t*)buf_load, count ) )  
        {
            moduleload_error("bad import symbol",0);
            return 0;
        }
    }

    return 1;
}
Esempio n. 2
0
static int _module_load(module_handler_t* hMod)
{
    int idx;

    // Check if module loaded
    idx = module_find(hMod->name);
    if ( idx>=0 )
        return idx;

    // Find empty slot   
    for ( idx=0; idx<MAX_NUM_LOADED_MODULES && modules[idx].hdr; idx++ );

    if  ( idx == MAX_NUM_LOADED_MODULES )
    {
        moduleload_error("%d already loaded",MAX_NUM_LOADED_MODULES);
        return -1;
    }

    if (module_preload(hMod->name, hMod->version) != 0)
    {
        // Module is valid. Finalize binding
        modules[idx].hdr = flat_buf;

        // store runtime params
        flat_module_name_make(modules[idx].modulename, module_filename);
        modules[idx].hMod = hMod;

        int bind_err = bind_module( hMod, flat_buf->_module_info->lib );

        if ( flat_buf->_module_info->lib->loader )
        {
            uint32_t x = flat_buf->_module_info->lib->loader();
            bind_err = bind_err || x;
        }

        if ( bind_err )
        {
            module_unload(module_filename);
            moduleload_error("chdk mismatch",0);
            return -1;
        }

        return idx;
    }

    return -1;
}
Esempio n. 3
0
static int alloc_reloc_buf(uint32_t reloc_size, uint32_t import_size)
{
    // Get larger size
    int sz = (reloc_size > import_size) ? reloc_size : import_size;

    if (sz > BUFFER_FOR_READ_SIZE)  // If larger than already allocated
    {
        if (buf_load) ufree(buf_load);
        buf_load = umalloc(sz);
        if ( buf_load == 0 )
        {
            moduleload_error("malloc",0);   
            return 0;
        }
    }

    return 1;
}
Esempio n. 4
0
struct flat_hdr* module_preload(const char *name, _version_t ver)
{
    module_fd = -1;
    module_filename = name;
    flat_buf = 0;
    buf_load = 0;

    char path[60];
    struct flat_hdr flat;
    int size_flat;

    flat_module_path_make(path,module_filename);

    module_fd = open( path, O_RDONLY, 0777 );
    if ( module_fd <=0 )
    {
        moduleload_error("file not found",0);
        return 0;
    }

    // @tsv TODO - compare loaded with requested
    b_read( module_fd, (char*)&flat, sizeof(flat) );

    if ( flat.rev!=FLAT_VERSION || memcmp( flat.magic, FLAT_MAGIC_NUMBER, 4) )
    {
        moduleload_error("bad magicnum", 0);
        return 0;
    }

    size_flat = flat.reloc_start;

    flat_buf = (struct flat_hdr*)malloc( size_flat );
    if ( !flat_buf ) 
    {
        moduleload_error("malloc",0);
        return 0;
    }

    module_log_load(module_filename,flat_buf);

    if ( 0!= lseek(module_fd, 0, SEEK_SET) )
    {
        moduleload_error("read",0);
        return 0;
    }
    if ( size_flat != b_read(module_fd, (char*)flat_buf, size_flat) )
    {
        moduleload_error("read",0);
        return 0;
    }

    // Module info checks

    struct ModuleInfo *mod_info = flat_buf->_module_info = (struct ModuleInfo*)((unsigned int)flat_buf+flat_buf->_module_info_offset);

    if ( mod_info->magicnum != MODULEINFO_V1_MAGICNUM || mod_info->sizeof_struct != sizeof(struct ModuleInfo) )
    {
        moduleload_error("Malformed module info", 0 );
        return 0;
    }

    if ( mod_info->chdk_required_branch && mod_info->chdk_required_branch != CURRENT_CHDK_BRANCH )
    {
        moduleload_error("require different CHDK branch",0 );
        return 0;
    }

    if ( mod_info->chdk_required_ver > CHDK_BUILD_NUM) 
    {
        moduleload_error("require CHDK%05d", mod_info->chdk_required_ver);
        return 0;
    }

    if ( mod_info->chdk_required_platfid && mod_info->chdk_required_platfid != conf.platformid )
    {
        moduleload_error("require platfid %d", mod_info->chdk_required_platfid);
        return 0;
    }

	if ( !API_VERSION_MATCH_REQUIREMENT( mod_info->module_version, ver ) )
    {
        moduleload_error("incorrect module version", 0);
		return 0;
    }

	if ( !API_VERSION_MATCH_REQUIREMENT( conf.api_version, mod_info->conf_ver ) )
    {
        moduleload_error("incorrect CONF version", 0);
		return 0;
    }

	if ( !API_VERSION_MATCH_REQUIREMENT( camera_screen.api_version, mod_info->cam_screen_ver ) )
    {
        moduleload_error("incorrect CAM SCREEN version", 0);
		return 0;
    }

	if ( !API_VERSION_MATCH_REQUIREMENT( camera_sensor.api_version, mod_info->cam_sensor_ver ) )
    {
        moduleload_error("incorrect CAM SENSOR version", 0);
		return 0;
    }

	if ( !API_VERSION_MATCH_REQUIREMENT( camera_info.api_version, mod_info->cam_info_ver ) )
    {
        moduleload_error("incorrect CAM INFO version", 0);
		return 0;
    }

    // Make relocations

    int reloc_size = flat.import_start - flat.reloc_start;
    int reloc_count = reloc_size/sizeof(uint32_t);
    int import_size = flat.file_size - flat.import_start;
    int import_count = import_size/sizeof(uint32_t);

    if (!alloc_reloc_buf(reloc_size, import_size))
        return 0;
    if ( !module_do_action( "reloc", flat.reloc_start, reloc_count, reloc_size, module_do_relocations ) )
        return 0;
    if ( !module_do_action( "export", flat.import_start, import_count, import_size, module_do_imports ) )
        return 0;

    b_close( module_fd );
    module_fd = -1;

    // TODO these could be changed to operate on affected address ranges only
    // after relocating but before attempting to execute loaded code
    // clean data cache to ensure code is in main memory
    dcache_clean_all();
    // then flush instruction cache to ensure no addresses containing new code are cached
    icache_flush_all();

    return flat_buf;
}
Esempio n. 5
0
// Load a module referenced by a 'module_handler_t' structure
// Returns index into modules array if successful (or module already loaded)
// otherwise returns -1
static int _module_load(module_handler_t* hMod)
{
    int idx;

    // Get full path to module file, and hash of path
    char path[60];
    unsigned int hash = get_module_path(path, hMod->name);

    // Check if module already loaded
    idx = module_find(hash);
    if (idx >= 0)
        return idx;

    // Reset lib (should not be needed, loader should only be called from 'default' lib)
    *hMod->lib = hMod->default_lib;

    // Simple lock to prevent multiple attempts to load modules simultaneously (in different tasks)
    // Not perfect; but should be sufficient
    static int isLoading = 0;
    while (isLoading != 0) msleep(10);
    isLoading = 1;

    // Find empty slot   
    for (idx=0; idx<MAX_NUM_LOADED_MODULES && modules[idx].hdr; idx++) ;

    // If no slot found return error
    if  (idx == MAX_NUM_LOADED_MODULES)
    {
        moduleload_error(hMod->name, "too many modules loaded");
        idx = -1;
    }
    else
    {
        // Load and relocate module (returns 0 if error)
        flat_hdr* mod = module_preload(path, hMod->name, hMod->version);

        if (mod != 0)
        {
            // Module is valid. Finalize binding
            modules[idx].hdr = mod;
            modules[idx].hName = hash;
            modules[idx].hMod = hMod;

            int bind_err = bind_module(hMod, mod->_module_info->lib);

            // Call module loader if required
            if (!bind_err && mod->_module_info->lib->loader)
            {
                bind_err = mod->_module_info->lib->loader();
            }

            // If any errors, unload module and display error message
            if (bind_err)
            {
                module_unload_idx(idx);
                moduleload_error(hMod->name, "loader error");
                idx = -1;
            }
        }
        else
        {
            // module did not load, return invalid index
            idx = -1;
        }
    }

    // Release lock
    isLoading = 0;

    return idx;
}
Esempio n. 6
0
// Attempt to load a module file.
// If file found and is a valid module, then load into memory, relocate and link to CHDK core
// Returns memory address of module if successful, 0 if failure.
flat_hdr* module_preload(const char *path, const char *name, _version_t ver)
{
    // Allocate buffer and open file
    int module_fd = b_open(path);
    if (module_fd <= 0)
    {
        moduleload_error(name, "open error");
        return 0;
    }

    // Read module header only to get size info
    flat_hdr flat;
    b_read(module_fd, (char*)&flat, sizeof(flat));  // TODO - compare loaded with requested size

    // Error message
    char *msg = 0;

    // Pointer to memory allocated to load module
    flat_hdr* flat_buf = 0;

    // Check version and magic number - make sure it is a CHDK module file
    if ((flat.rev == FLAT_VERSION) && (flat.magic == FLAT_MAGIC_NUMBER))
    {
        // Allocate module memory, and load module code
        msg = load_module_file(module_fd, name, flat.reloc_start, flat.bss_size, &flat_buf);
        if (msg == 0)
        {
            // Module info checks
            ModuleInfo *mod_info = flat_buf->_module_info = (ModuleInfo*)((unsigned int)flat_buf+flat_buf->_module_info_offset);

            // Validate version requirements
            msg = validate(mod_info, ver);
            if (msg == 0)
            {
                // Make relocations
                msg = link_module(module_fd, flat_buf);
            }
        }
    }
    else
        msg = "bad magicnum";

    // Close file
    b_close(module_fd);

    // If any error found, free module memory and display error
    if (msg)
    {
        if (flat_buf)
            free(flat_buf);
        moduleload_error(name, msg);
        return 0;
    }

    // TODO these could be changed to operate on affected address ranges only
    // after relocating but before attempting to execute loaded code
    // clean data cache to ensure code is in main memory
    dcache_clean_all();
    // then flush instruction cache to ensure no addresses containing new code are cached
    icache_flush_all();

    // Return module memory address
    return flat_buf;
}