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

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