root/modules/module_load.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hash_module_name
  2. get_module_path
  3. get_buffer
  4. b_open
  5. b_read
  6. b_close
  7. namecmp
  8. module_find
  9. moduleload_error
  10. module_do_relocations
  11. module_find_symbol_address
  12. module_do_imports
  13. module_do_action
  14. module_writeline
  15. module_log_hdr
  16. module_log_clear
  17. module_log_load
  18. module_log_unload
  19. bind_module
  20. module_unload_idx
  21. module_unload
  22. validate
  23. load_module_file
  24. link_module
  25. module_preload
  26. _module_load
  27. module_load
  28. module_run_error
  29. default_run
  30. default_run0
  31. default_run1
  32. default_run2
  33. default_run3
  34. module_run
  35. module_exit_alt
  36. module_tick_unloader
  37. module_get_adr
  38. get_module_info

   1 /*
   2 *   CHDK-FLAT Module System.  
   3 *
   4 *   (c)2011 Sergey Taranenko aka tsvstar
   5 *
   6 *   This is main file of module processing system. Module load/unload/service functions
   7 */
   8 
   9 #include "camera_info.h"
  10 #include "stdlib.h"
  11 #include "conf.h"
  12 #include "console.h"
  13 #include "clock.h"
  14 #include "cache.h"
  15 #include "lang.h"
  16 #include "gui_mbox.h"
  17 #include "gui_lang.h"
  18 
  19 #include "simple_module.h"
  20 #include "module_load.h"
  21 #include "module_exportlist.h"
  22 #include "module_hash.h"
  23 
  24 //-----------------------------------------------
  25 
  26 // Symbol hash table for resolving exported symbol references
  27 // see autogenerated file modules/module_hashlist.c
  28 extern sym_hash symbol_hash_table[];
  29 
  30 //-----------------------------------------------
  31 
  32 // array of loaded modules (hdr == NULL -> slot is empty)
  33 static module_entry modules[MAX_NUM_LOADED_MODULES];
  34 
  35 //-----------------------------------------------
  36 
  37 #define BUFFER_FOR_READ_SIZE    4096
  38 #define MODULES_PATH            "A/CHDK/MODULES/"       // Module folder, module files are only loaded from here
  39 
  40 // Generate a unique hash of the full module path
  41 // Can't use lang_strhash31 as we want case-insensitive hashes here
  42 // (File browser passes upper case names, modules names in modules.c are lower case
  43 static unsigned int hash_module_name(char *str)
  44 {
  45     unsigned int hash = 5381;
  46     int c;
  47 
  48     // djb2 hash algorithm (Dan Bernstein - http://cr.yp.to/djb.html)
  49     while ((c = *str++) != 0)
  50         hash = ((hash << 5) + hash) ^ toupper(c); /* hash * 33 xor c */
  51 
  52     return hash;
  53 }
  54 
  55 // Get full path of module file and hash of path
  56 // If path specified in name, just copy it, otherwise prepend MODULES_PATH
  57 // No validation on size of path variable - make sure you pass a buffer with enough space
  58 // Returns hash value of path for comparison to loaded modules
  59 static unsigned int get_module_path(char *path, const char *name)
  60 {
  61     // Check if full path supplied?
  62     if ((tolower(name[0]) != 'a') || (name[1] != '/'))
  63         strcpy(path, MODULES_PATH);
  64     else
  65         path[0] = 0;
  66     // Add supplied name to path
  67     strcat(path, name);
  68 
  69     return hash_module_name(path);
  70 }
  71 
  72 //********************************************************/
  73 //**  Small library for safe io to cacheable memory     **
  74 //**  use smaller buffer then fopen so bigger could     **
  75 //**  be loaded                                         **
  76 //********************************************************/
  77 
  78 static char* buf_load = 0;  // Also used for relocation & imports
  79 static int   buf_size = 0;  // Current size, only re-allocate if larger buffer needed
  80 
  81 // Allocate uncached memory buffer of given size
  82 // Only allocate buffer if no buffer exists or new size is larger than existing buffer
  83 // Returns 0 on error, or allocated size if no error
  84 static int get_buffer(int size)
  85 {
  86     size = (size + 3) & 0xFFFFFFFC; // round up to 4 byte boundary
  87     if (size > buf_size)
  88     {
  89         if (buf_load)
  90         {
  91             ufree(buf_load);
  92             buf_load = 0;
  93             buf_size = 0;
  94         }
  95         buf_load = umalloc(size);
  96         if (buf_load)
  97             buf_size = size;
  98     }
  99 
 100     return buf_size;
 101 }
 102 
 103 // Allocate default buffer (if required)
 104 // Open named module file, return file handle (or -1 if error)
 105 static int b_open(const char* name)
 106 {
 107     if (!get_buffer(BUFFER_FOR_READ_SIZE))
 108     {
 109         return -1;
 110     }
 111 
 112     return open(name, O_RDONLY, 0777);
 113 }
 114 
 115 // Read 'len' bytes from file - uses uncached memory buffer
 116 // Copy file contents to destination 'buf'
 117 // Returns number of bytes read from file
 118 int b_read(int fd, char* buf, int len)
 119 {
 120     int loaded = 0, now = 1;
 121 
 122     while (now && loaded<len)
 123     {
 124         now = len - loaded;
 125         if (now > buf_size)
 126             now = buf_size;
 127 
 128         now = read(fd, buf_load, now);
 129         memcpy(buf+loaded, buf_load, now);
 130         loaded += now;
 131     }
 132 
 133     return loaded;
 134 }
 135 
 136 // Close module file if still open
 137 void b_close(int fd)
 138 {
 139     if (fd >= 0)
 140         close(fd);
 141 }
 142 
 143 //********************************************************/
 144 //**       Auxilary module system functions             **
 145 //********************************************************/
 146 
 147 // Case insensitive comparison
 148 // Returns 1 if strings are equal, 0 otherwise
 149 static int namecmp(const char* s1, const char* s2)
 150 {
 151     if ((s1 == 0) && (s2 == 0)) return 1;   // Both null --> equal
 152     if ((s1 == 0) || (s2 == 0)) return 0;   // One null (but not both) --> not equal
 153     while (*s1 && *s2)
 154     {
 155         if (tolower(*s1) != tolower(*s2)) return 0;
 156         s1++;
 157         s2++;
 158     }
 159     return ((*s1 == 0) && (*s2 == 0));
 160 }
 161 
 162 //-----------------------------------------------
 163 // PURPOSE: Find loaded module by name hash
 164 // RETURN: -1 if module not loaded yet, otherwise idx in modules[]
 165 //-----------------------------------------------
 166 static int module_find(unsigned int hash)
 167 {
 168     int i;
 169 
 170     for (i=0; i<MAX_NUM_LOADED_MODULES; i++)
 171     {
 172         if (modules[i].hdr && (modules[i].hName == hash))
 173         {
 174             return i;
 175         }
 176     }
 177     return -1;
 178 }
 179 
 180 //-----------------------------------------------
 181 // Display module load/unload error message on console
 182 static void moduleload_error(const char* name, const char* text)
 183 {
 184     extern volatile int chdk_started_flag;
 185     if (chdk_started_flag)
 186     {
 187         char buf[100];
 188         sprintf(buf, "Fail to load %s: %s", name, text);
 189 
 190         console_clear();
 191         console_add_line(buf);
 192         msleep(1000);
 193     }
 194 }
 195 
 196 //-----------------------------------------------
 197 // Module relocation and linking to CHDK core
 198 
 199 // Relocation of loaded module
 200 // Relocation table is a list of int (4 byte) values, each value specifies the offset in the
 201 // module of a pointer (4 bytes) to relocate. The offset is relative to the start of the module file.
 202 // The initial values stored at each pointer are correct assuming the module was loaded at address 0.
 203 // To relocate simply update the pointer with initial value + the actual load address of the module.
 204 static int module_do_relocations(flat_hdr* flat, void* relocbuf, uint32_t reloc_count)
 205 {
 206     int i;
 207     unsigned char* buf = (unsigned char*)flat;      // base address of module in memory
 208     uint32_t* rbuf = (uint32_t*)relocbuf;           // relocation array
 209 
 210     for (i=0; i < reloc_count; i++)
 211     {
 212         // Add initial value at relocated address to the base module address
 213         *(uint32_t*)(buf+rbuf[i]) += (uint32_t)buf;
 214     }
 215 
 216     return 1;
 217 }
 218 
 219 // Find function or variable address in array from hash id.
 220 // Performs a binary search of the symbol_hash_table array looking for the 'importid' value
 221 // Returns the function or variable address if found, 0 if not found
 222 static const void* module_find_symbol_address(uint32_t importid)
 223 {
 224     int min = 0, max = EXPORTLIST_COUNT-1;
 225     do
 226     {
 227         int mid = (min + max) >> 1;
 228         if (importid == symbol_hash_table[mid].hash)
 229             return symbol_hash_table[mid].address;
 230         else if (importid > symbol_hash_table[mid].hash)
 231             min = mid + 1;
 232         else
 233             max = mid - 1;
 234     } while (min <= max);
 235     return 0;
 236 }
 237 
 238 // Link module to CHDK core code.
 239 // Functions and variables to link to are mapped via the symbol_hash_table array.
 240 // The link information in the module comprises 'import_count' int values (4 bytes each)
 241 // grouped into blocks. Each block is defined as:
 242 //      - function / variable symbol hash
 243 //      - N x int values, each value specifies the offset in the module to link
 244 // The value of N is stored in the top 8 bits of the first value in list.
 245 // Each location to link is assumed to be a pointer (4 bytes) into the CHDK core memory.
 246 // To update each link location add the initial value stored to the link address found in the symbol table.
 247 static int module_do_imports(flat_hdr* flat, void* relocbuf, uint32_t import_count)
 248 {
 249     int i;
 250     unsigned char* buf = (unsigned char*)flat;  // base address of module in memory
 251     uint32_t* rbuf = (uint32_t*)relocbuf;       // link array
 252 
 253     for (i=0; i < import_count;)
 254     {
 255         // Find CHDK address of symbol via hash value, if not found return error
 256         int importaddress = (int)module_find_symbol_address(rbuf[i++]);
 257         if (importaddress == 0) return 0;
 258 
 259         // Get number of locations in module to link
 260         int cnt = rbuf[i] >> 24;
 261 
 262         for (; cnt>0; cnt--)
 263         {
 264             // Get offset into module (exclude count value)
 265             uint32_t offs = rbuf[i++] & 0x00FFFFFF;
 266             // Add initial value at location to symbol address
 267             *(uint32_t*)(buf+offs) += importaddress;
 268         }
 269     }  
 270     return 1;
 271 }
 272 
 273 //-----------------------------------------------
 274 // Load relocation or link data from module file, call appropriate function to process data
 275 // return: 0 if error, otherwise ok
 276 static int module_do_action(int fd, flat_hdr* mod, uint32_t offset, uint32_t segment_size, int (*func)(flat_hdr*, void*, uint32_t))
 277 {
 278     if (segment_size > 0)
 279     {
 280         if (lseek(fd, offset, SEEK_SET) == offset)
 281         {
 282             if (read(fd, buf_load, segment_size) == segment_size)
 283             {
 284                 // relocate or link module
 285                 return func(mod, (uint32_t*)buf_load, segment_size >> 2);
 286             }
 287         }
 288         return 0;
 289     }
 290     return 1;
 291 }
 292 
 293 //********************************************************/
 294 //**           Main module system functions             **
 295 //********************************************************/
 296 
 297 //-----------------------------------------------
 298 // Logging
 299 
 300 // Append a line to the module log file if logging enabled
 301 static void module_writeline(char *buf)
 302 {
 303     if (conf.module_logging)
 304     {
 305         int fd = open("A/MODULES.LOG", O_WRONLY|O_CREAT|O_APPEND, 0777);
 306         if (fd >= 0)
 307         {
 308             lseek(fd, 0, SEEK_END);
 309             write(fd, buf, strlen(buf));
 310             close(fd);
 311         }
 312     }
 313 }
 314 
 315 // Write header line to the module file if logging enabled
 316 // Once header written, it will not be written again until CHDK restarted.
 317 static void module_log_hdr()
 318 {
 319     static int hdr_logged = 0;
 320 
 321     if (conf.module_logging)
 322     {
 323         if (hdr_logged == 0)
 324         {
 325             hdr_logged = 1;
 326 
 327             time_t datetime;
 328             struct tm *ttm;
 329             char buf[100];
 330 
 331             datetime = time(NULL);
 332             ttm = localtime(&datetime);
 333 
 334             sprintf(buf, "Tick    ,Op,Address ,Name (%04d:%02d:%02d %02d:%02d:%02d)\n", ttm->tm_year+1900, ttm->tm_mon+1, ttm->tm_mday, ttm->tm_hour, ttm->tm_min, ttm->tm_sec);
 335 
 336             module_writeline(buf);
 337         }
 338     }
 339 }
 340 
 341 // Delete log file
 342 void module_log_clear()
 343 {
 344     remove("A/MODULES.LOG");
 345 }
 346 
 347 // Log message about a module being loaded
 348 static void module_log_load(const char *name, void* adr)
 349 {
 350     if (conf.module_logging)
 351     {
 352         char buf[100];
 353         sprintf(buf,"%8d,LD,%08x,%s\n",get_tick_count(),adr,name);
 354 
 355         module_log_hdr();
 356         module_writeline(buf);
 357     }
 358 }
 359 
 360 // Log message about a module being unloaded
 361 static void module_log_unload(char *name)
 362 {
 363     if (conf.module_logging)
 364     {
 365         char buf[100];
 366         sprintf(buf,"%8d,UN,        ,%s\n",get_tick_count(),name);
 367 
 368         module_log_hdr();
 369         module_writeline(buf);
 370     }
 371 }
 372 
 373 //-----------------------------------------------
 374 // Bind/unbind loaded module to library pointer
 375 static int bind_module(module_handler_t* hMod, void* module_lib)
 376 {
 377     // If unloading module, reset library to unloaded default
 378     if (module_lib == 0)
 379         *hMod->lib = hMod->default_lib;
 380     else
 381         *hMod->lib = module_lib;
 382 
 383     return 0;
 384 }
 385 
 386 //-----------------------------------------------
 387 // Unload module at given index in modules array
 388 static void module_unload_idx(int idx)
 389 {
 390     if ((idx >= 0) && (modules[idx].hdr != 0))
 391     {
 392         // Log unload
 393         module_log_unload(modules[idx].hMod->name);
 394 
 395         // Call module unload function
 396         if (modules[idx].hdr->_module_info->lib->unloader)
 397             modules[idx].hdr->_module_info->lib->unloader();
 398 
 399         // Unbind pointers to module (chdk core callback)
 400         bind_module(modules[idx].hMod, 0);
 401 
 402         // Free module memory, and mark module as inactive
 403         free(modules[idx].hdr);
 404         modules[idx].hdr = 0;
 405     }
 406 }
 407 
 408 // Unload module by name
 409 void module_unload(const char* name)
 410 {
 411     // Get full path to module file, and hash of path
 412     char path[60];
 413     unsigned int hash = get_module_path(path, name);
 414 
 415     // Find loaded module, and unload it
 416     module_unload_idx(module_find(hash));
 417 }
 418 
 419 //-----------------------------------------------
 420 // Validate loaded module header and versions
 421 // Returns 0 if all ok, otherwise returns error message
 422 static char* validate(ModuleInfo *mod_info, _version_t ver)
 423 {
 424     static char msg[50];
 425 
 426     if ((mod_info->magicnum != MODULEINFO_V1_MAGICNUM) || (mod_info->sizeof_struct != sizeof(ModuleInfo)))
 427         return "Malformed module info";
 428 
 429     if (mod_info->chdk_required_branch && (mod_info->chdk_required_branch != CURRENT_CHDK_BRANCH))
 430         return "require different CHDK branch";
 431 
 432     if (mod_info->chdk_required_architecture != OPT_ARCHITECTURE)
 433         return "wrong CHDK architecture";
 434 
 435     if (mod_info->chdk_required_ver > CHDK_BUILD_NUM)
 436     {
 437         sprintf(msg, "require CHDK%05d", mod_info->chdk_required_ver);
 438         return msg;
 439     }
 440 
 441     if (mod_info->chdk_required_platfid && (mod_info->chdk_required_platfid != conf.platformid))
 442     {
 443         sprintf(msg, "require platfid %d", mod_info->chdk_required_platfid);
 444         return msg;
 445     }
 446 
 447     if (!chk_api_version(mod_info->module_version, ver))
 448         return "incorrect module version";
 449 
 450     if (!chk_api_version((_version_t)CONF_VERSION, mod_info->conf_ver))
 451         return "incorrect CONF version";
 452 
 453     if (!chk_api_version((_version_t)CAM_SCREEN_VERSION, mod_info->cam_screen_ver))
 454         return "incorrect CAM SCREEN version";
 455 
 456     if (!chk_api_version((_version_t)CAM_SENSOR_VERSION, mod_info->cam_sensor_ver))
 457         return "incorrect CAM SENSOR version";
 458 
 459     if (!chk_api_version((_version_t)CAM_INFO_VERSION, mod_info->cam_info_ver))
 460         return "incorrect CAM INFO version";
 461 
 462     return 0;
 463 }
 464 
 465 // Allocate module memory and load file
 466 // Returns 0 if all ok, otherwise returns error message
 467 static char* load_module_file(int fd, const char* name, int size, int bss_size, flat_hdr** flat_buf)
 468 {
 469     *flat_buf = (flat_hdr*)malloc(size+bss_size);
 470     if (!*flat_buf)
 471         return "malloc";
 472 
 473     module_log_load(name, *flat_buf);
 474 
 475     if (lseek(fd, 0, SEEK_SET) == 0)
 476     {
 477         if (b_read(fd, (char*)*flat_buf, size) == size)
 478         {
 479             memset((unsigned char*)(*flat_buf)+size, 0, bss_size);
 480             return 0;
 481         }
 482     }
 483 
 484     // Load failed, free memory
 485     free(*flat_buf);
 486     *flat_buf = 0;
 487 
 488     return "read";
 489 }
 490 
 491 // Relocate and link module
 492 // Returns 0 if all ok, otherwise returns error message
 493 static char* link_module(int fd, flat_hdr* flat_buf)
 494 {
 495     // Make relocations
 496     int reloc_size = flat_buf->import_start - flat_buf->reloc_start;
 497     int import_size = flat_buf->import_size;
 498 
 499     // Get larger buffer size if needed
 500     int sz = (reloc_size > import_size) ? reloc_size : import_size;
 501 
 502     if (!get_buffer(sz))  // Re-allocate if needed
 503         return "malloc";
 504 
 505     if (!module_do_action(fd, flat_buf, flat_buf->reloc_start, reloc_size, module_do_relocations))
 506         return "reloc error";
 507 
 508     if (!module_do_action(fd, flat_buf, flat_buf->import_start, import_size, module_do_imports))
 509         return "link error";
 510 
 511     return 0;
 512 }
 513 
 514 // Attempt to load a module file.
 515 // If file found and is a valid module, then load into memory, relocate and link to CHDK core
 516 // Returns memory address of module if successful, 0 if failure.
 517 flat_hdr* module_preload(const char *path, const char *name, _version_t ver)
 518 {
 519     // Allocate buffer and open file
 520     int module_fd = b_open(path);
 521     if (module_fd <= 0)
 522     {
 523         moduleload_error(name, "open error");
 524         return 0;
 525     }
 526 
 527     // Read module header only to get size info
 528     flat_hdr flat;
 529     b_read(module_fd, (char*)&flat, sizeof(flat));  // TODO - compare loaded with requested size
 530 
 531     // Error message
 532     char *msg = 0;
 533 
 534     // Pointer to memory allocated to load module
 535     flat_hdr* flat_buf = 0;
 536 
 537     // Check version and magic number - make sure it is a CHDK module file
 538     if ((flat.rev == FLAT_VERSION) && (flat.magic == FLAT_MAGIC_NUMBER))
 539     {
 540         // Allocate module memory, and load module code
 541         msg = load_module_file(module_fd, name, flat.reloc_start, flat.bss_size, &flat_buf);
 542         if (msg == 0)
 543         {
 544             // Module info checks
 545             ModuleInfo *mod_info = flat_buf->_module_info = (ModuleInfo*)((unsigned int)flat_buf+flat_buf->_module_info_offset);
 546 
 547             // Validate version requirements
 548             msg = validate(mod_info, ver);
 549             if (msg == 0)
 550             {
 551                 // Make relocations
 552                 msg = link_module(module_fd, flat_buf);
 553             }
 554         }
 555     }
 556     else
 557         msg = "bad magicnum";
 558 
 559     // Close file
 560     b_close(module_fd);
 561 
 562     // If any error found, free module memory and display error
 563     if (msg)
 564     {
 565         if (flat_buf)
 566             free(flat_buf);
 567         moduleload_error(name, msg);
 568         return 0;
 569     }
 570 
 571     // TODO these could be changed to operate on affected address ranges only
 572     // after relocating but before attempting to execute loaded code
 573     // clean data cache to ensure code is in main memory
 574     dcache_clean_all();
 575     // then flush instruction cache to ensure no addresses containing new code are cached
 576     icache_flush_all();
 577 
 578     // Return module memory address
 579     return flat_buf;
 580 }
 581 
 582 // Load a module referenced by a 'module_handler_t' structure
 583 // Returns index into modules array if successful (or module already loaded)
 584 // otherwise returns -1
 585 static int _module_load(module_handler_t* hMod)
 586 {
 587     int idx;
 588 
 589     // Get full path to module file, and hash of path
 590     char path[60];
 591     unsigned int hash = get_module_path(path, hMod->name);
 592 
 593     // Check if module already loaded
 594     idx = module_find(hash);
 595     if (idx >= 0)
 596         return idx;
 597 
 598     // Reset lib (should not be needed, loader should only be called from 'default' lib)
 599     *hMod->lib = hMod->default_lib;
 600 
 601     // Simple lock to prevent multiple attempts to load modules simultaneously (in different tasks)
 602     // Not perfect; but should be sufficient
 603     static int isLoading = 0;
 604     while (isLoading != 0) msleep(10);
 605     isLoading = 1;
 606 
 607     // Find empty slot   
 608     for (idx=0; idx<MAX_NUM_LOADED_MODULES && modules[idx].hdr; idx++) ;
 609 
 610     // If no slot found return error
 611     if  (idx == MAX_NUM_LOADED_MODULES)
 612     {
 613         moduleload_error(hMod->name, "too many modules loaded");
 614         idx = -1;
 615     }
 616     else
 617     {
 618         // Load and relocate module (returns 0 if error)
 619         flat_hdr* mod = module_preload(path, hMod->name, hMod->version);
 620 
 621         if (mod != 0)
 622         {
 623             // Module is valid. Finalize binding
 624             modules[idx].hdr = mod;
 625             modules[idx].hName = hash;
 626             modules[idx].hMod = hMod;
 627 
 628             int bind_err = bind_module(hMod, mod->_module_info->lib);
 629 
 630             // Call module loader if required
 631             if (!bind_err && mod->_module_info->lib->loader)
 632             {
 633                 bind_err = mod->_module_info->lib->loader();
 634             }
 635 
 636             // If any errors, unload module and display error message
 637             if (bind_err)
 638             {
 639                 module_unload_idx(idx);
 640                 moduleload_error(hMod->name, "loader error");
 641                 idx = -1;
 642             }
 643         }
 644         else
 645         {
 646             // module did not load, return invalid index
 647             idx = -1;
 648         }
 649     }
 650 
 651     // Release lock
 652     isLoading = 0;
 653 
 654     return idx;
 655 }
 656 
 657 // Load a module referenced by a 'module_handler_t' structure
 658 // Return: 0-fail, 1-ok
 659 int module_load(module_handler_t* hMod)
 660 {
 661     // Attempt to load module
 662     _module_load(hMod);
 663 
 664     // If load succeeded return success
 665     if (*hMod->lib && (*hMod->lib != hMod->default_lib))
 666     {
 667         return 1;
 668     }
 669 
 670     // If load failed reset library to unloaded default (should not be needed!)
 671     if (*hMod->lib == 0)
 672         *hMod->lib = hMod->default_lib;
 673 
 674     // Failure
 675     return 0;
 676 }
 677 
 678 //-----------------------------------------------
 679 // Simple module support - allow module to be loaded and run by name.
 680 // Module must implement the 'run' method
 681 //-----------------------------------------------
 682 // Number of simple modules that can be loaded at any one time
 683 #define MAX_SIMPLE_MODULE   4
 684 
 685 // Forward reference for default run methods - one for each simple module
 686 static int default_run0();
 687 static int default_run1();
 688 static int default_run2();
 689 static int default_run3();
 690 
 691 // Default library handlers - one per simple module
 692 static libsimple_sym default_librun[MAX_SIMPLE_MODULE] =
 693 {
 694     { { 0, 0, 0, 0, default_run0 } },
 695     { { 0, 0, 0, 0, default_run1 } },
 696     { { 0, 0, 0, 0, default_run2 } },
 697     { { 0, 0, 0, 0, default_run3 } }
 698 };
 699 static libsimple_sym* librun[MAX_SIMPLE_MODULE] = { &default_librun[0], &default_librun[1], &default_librun[2], &default_librun[3] };
 700 
 701 // Name of loaded module in each slot
 702 // Each buffer needs to be long enough to hold full path to module (when called from file browser)
 703 static char h_name[MAX_SIMPLE_MODULE][64];
 704 
 705 // Handlers for simple modules - link to above implementation
 706 static module_handler_t h_run[MAX_SIMPLE_MODULE] =
 707 {
 708     { (base_interface_t**)&librun[0], &default_librun[0].base, ANY_VERSION, h_name[0] },
 709     { (base_interface_t**)&librun[1], &default_librun[1].base, ANY_VERSION, h_name[1] },
 710     { (base_interface_t**)&librun[2], &default_librun[2].base, ANY_VERSION, h_name[2] },
 711     { (base_interface_t**)&librun[3], &default_librun[3].base, ANY_VERSION, h_name[3] }
 712 };
 713 
 714 // Display error message if attempting to run a module with no 'run' method, or no space left for module
 715 static void module_run_error(int err, char *name)
 716 {
 717     char buf[100];
 718     sprintf(buf, lang_str(err), name);
 719     gui_mbox_init(LANG_ERROR, (int)buf, MBOX_BTN_OK|MBOX_TEXT_CENTER, NULL);
 720 }
 721 
 722 // Default run method
 723 // If module loaded in selected slot call the 'run' method.
 724 // If not 'run' method defined then display error
 725 static int default_run(int n)
 726 {
 727     if (module_load(&h_run[n]))
 728     {
 729         if ((*h_run[n].lib)->run)
 730         {
 731             return (*h_run[n].lib)->run();
 732         }
 733         else
 734         {
 735             // Error - module does not support 'simple' mode
 736             module_run_error(LANG_MODULE_NOT_SIMPLE, h_run[n].name);
 737             // Assumption - module will unload automatically via module_tick_unloader()
 738         }
 739     }
 740 
 741     return -1;
 742 }
 743 
 744 // Default run methods - one for each simple module
 745 static int default_run0() { return default_run(0); }
 746 static int default_run1() { return default_run(1); }
 747 static int default_run2() { return default_run(2); }
 748 static int default_run3() { return default_run(3); }
 749 
 750 //-----------------------------------------------
 751 // PURPOSE:      run simple module "name"
 752 // RETURN VALUE: passed from module. -1 if something was failed
 753 //-----------------------------------------------
 754 int module_run(char* name)
 755 {
 756     int i;
 757     for (i=0; i<MAX_SIMPLE_MODULE; i++)
 758     {
 759         // Check if module loaded (otherwise name not valid)
 760         if (*h_run[i].lib != h_run[i].default_lib)
 761         {
 762             if (namecmp(name, h_run[i].name))
 763             {
 764                 // Already loaded
 765                 return (*h_run[i].lib)->run();
 766             }
 767         }
 768     }
 769     for (i=0; i<MAX_SIMPLE_MODULE; i++)
 770     {
 771         // Look for empty slot
 772         if (*h_run[i].lib == h_run[i].default_lib)
 773         {
 774             // Found space - run module
 775             strcpy(h_run[i].name, name);
 776             return (*h_run[i].lib)->run();
 777         }
 778     }
 779 
 780     // Error - no space
 781     module_run_error(LANG_MODULE_NO_SPACE, name);
 782 
 783     return -1;
 784 }
 785 
 786 //-----------------------------------------------
 787 // Warn modules when leaving <ALT>
 788 //   1. Called when goto GUI_MODE_NONE
 789 //   2. Tell all modules that we are leaving <ALT> mode
 790 //-----------------------------------------------
 791 void module_exit_alt()
 792 {
 793     int idx;
 794 
 795     for (idx=MAX_NUM_LOADED_MODULES-1; idx>=0; idx--)
 796     {
 797         if (modules[idx].hdr && modules[idx].hdr->_module_info->lib->exit_alt)
 798         {
 799             // Tell module we are leaving <ALT>
 800             modules[idx].hdr->_module_info->lib->exit_alt();
 801         }
 802     }
 803 }
 804 
 805 //-----------------------------------------------
 806 // Called on each tick to safe asynchronous unload module by its requests 
 807 //-----------------------------------------------
 808 void module_tick_unloader()
 809 {
 810     int idx;
 811 
 812     for (idx=MAX_NUM_LOADED_MODULES-1; idx>=0; idx--)
 813     {
 814         if (modules[idx].hdr && modules[idx].hdr->_module_info->lib->can_unload)
 815         {
 816             // Ask module if it is safe to unload
 817             if (modules[idx].hdr->_module_info->lib->can_unload())
 818                 module_unload_idx(idx);
 819         }
 820     }
 821 }
 822 
 823 //-----------------------------------------------
 824 // Return address of module entry in modules array for given index
 825 // return 0 if no valid module at given index
 826 //-----------------------------------------------
 827 module_entry* module_get_adr(unsigned int idx)
 828 {
 829     if ((idx >= 0) && (idx < MAX_NUM_LOADED_MODULES))
 830         if (modules[idx].hdr)
 831             return &modules[idx];
 832     return 0;
 833 }
 834 
 835 //-----------------------------------------------
 836 // Load module file and return ModuleInfo data
 837 void get_module_info(const char *name, ModuleInfo *mi, char *modName, int modNameLen)
 838 {
 839     memset(mi, 0, sizeof(ModuleInfo));
 840     if (modName)
 841         modName[0] = 0;     // Only used if module name stored in file (not a LANG string)
 842 
 843     // Get full path to module file, and hash of path
 844     char path[60];
 845     get_module_path(path, name);
 846 
 847     // open file
 848     int fd = open(path, O_RDONLY, 0777);
 849     if (fd < 0)
 850         return;
 851 
 852     // Read module header only to get size info
 853     flat_hdr flat;
 854     read(fd, (char*)&flat, sizeof(flat_hdr));
 855 
 856     // Check version and magic number - make sure it is a CHDK module file
 857     if ((flat.rev == FLAT_VERSION) && (flat.magic == FLAT_MAGIC_NUMBER))
 858     {
 859         lseek(fd, flat._module_info_offset, SEEK_SET);
 860         read(fd, mi, sizeof(ModuleInfo));
 861 
 862         if ((mi->moduleName >= 0) && modName)
 863         {
 864             // Load module name string
 865             lseek(fd, mi->moduleName, SEEK_SET);
 866             read(fd, modName, modNameLen-1);
 867             modName[modNameLen-1] = 0;
 868         }
 869     }
 870 
 871     close(fd);
 872 }
 873 
 874 //-----------------------------------------------

/* [<][>][^][v][top][bottom][index][help] */