Model & version check for simulator plugins.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8356 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/plugin.c b/apps/plugin.c
index 0997b0a..a2cb0de 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -369,15 +369,15 @@
 int plugin_load(const char* plugin, void* parameter)
 {
     enum plugin_status (*plugin_start)(struct plugin_api* api, void* param);
-    int rc;
+    int fd, rc;
 #ifndef SIMULATOR
     struct plugin_header header;
     ssize_t readsize;
+#else
+    struct plugin_header *hdr;
 #endif
-    int fd;
-
 #ifdef HAVE_LCD_BITMAP
-    int xm,ym;
+    int xm, ym;
 #endif
 
     if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */
@@ -397,18 +397,34 @@
     lcd_clear_display();
 #endif
 #ifdef SIMULATOR
-    plugin_start = sim_plugin_load((char *)plugin, &fd);
-    if(!plugin_start)
+    hdr = sim_plugin_load((char *)plugin, &fd);
+    if (!fd) {
+        gui_syncsplash(HZ*2, true, str(LANG_PLUGIN_CANT_OPEN), plugin);
         return -1;
+    }
+    if (hdr == NULL
+        || hdr->magic != PLUGIN_MAGIC
+        || hdr->target_id != TARGET_ID
+        || hdr->entry_point == NULL) {
+        sim_plugin_close(fd);
+        gui_syncsplash(HZ*2, true,  str(LANG_PLUGIN_WRONG_MODEL));
+        return -1;
+    }
+    if (hdr->api_version > PLUGIN_API_VERSION
+        || hdr->api_version < PLUGIN_MIN_API_VERSION) {
+        sim_plugin_close(fd);
+        gui_syncsplash(HZ*2, true,  str(LANG_PLUGIN_WRONG_VERSION));
+        return -1;
+    }
+    plugin_start = hdr->entry_point;
 #else
     fd = open(plugin, O_RDONLY);
     if (fd < 0) {
         gui_syncsplash(HZ*2, true, str(LANG_PLUGIN_CANT_OPEN), plugin);
         return fd;
     }
-
     readsize = read(fd, &header, sizeof(header));
-    close(fd); 
+    close(fd);
     /* Close for now. Less code than doing it in all error checks.
      * Would need to seek back anyway. */
 
@@ -428,7 +444,6 @@
         gui_syncsplash(HZ*2, true,  str(LANG_PLUGIN_WRONG_VERSION));
         return -1;
     }
-
     /* zero out plugin buffer to ensure a properly zeroed bss area */
     memset(pluginbuf, 0, header.end_addr - pluginbuf);
 
@@ -445,8 +460,8 @@
         gui_syncsplash(HZ*2, true, str(LANG_READ_FAILED), plugin);
         return -1;
     }
-    plugin_start = header.entry_point;
     plugin_size = header.end_addr - header.load_addr;
+    plugin_start = header.entry_point;
 #endif
 
     plugin_loaded = true;
@@ -463,11 +478,15 @@
 #else /* LCD_DEPTH == 1 */
     lcd_set_drawmode(DRMODE_SOLID);
 #endif /* LCD_DEPTH */
+    /* restore margins */
+    lcd_setmargins(xm,ym);
 #endif /* HAVE_LCD_BITMAP */
     
     if (pfn_tsr_exit == NULL)
         plugin_loaded = false;
 
+    sim_plugin_close(fd);
+
     switch (rc) {
         case PLUGIN_OK:
             break;
@@ -480,13 +499,6 @@
             break;
     }
 
-    sim_plugin_close(fd);
-
-#ifdef HAVE_LCD_BITMAP
-    /* restore margins */
-    lcd_setmargins(xm,ym);
-#endif
-
     return PLUGIN_OK;
 }
 
diff --git a/apps/plugin.h b/apps/plugin.h
index bf8f34a..69a2a79 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -427,7 +427,6 @@
 
 };
 
-#ifndef SIMULATOR
 /* plugin header */
 struct plugin_header {
     unsigned long magic;
@@ -438,6 +437,7 @@
     enum plugin_status(*entry_point)(struct plugin_api*, void*);
 };
 #ifdef PLUGIN
+#ifndef SIMULATOR
 extern unsigned char plugin_start_addr[];
 extern unsigned char plugin_end_addr[];
 #define PLUGIN_HEADER \
@@ -445,9 +445,12 @@
         __attribute__ ((section (".header")))= { \
         PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \
         plugin_start_addr, plugin_end_addr, plugin_start };
-#endif
 #else /* SIMULATOR */
-#define PLUGIN_HEADER
+#define PLUGIN_HEADER \
+        const struct plugin_header __header = { \
+        PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \
+        NULL, NULL, plugin_start };
+#endif
 #endif
 
 int plugin_load(const char* plugin, void* parameter);
@@ -456,7 +459,6 @@
 void plugin_tsr(void (*exit_callback)(void));
 
 /* defined by the plugin */
-enum plugin_status plugin_start(struct plugin_api* rockbox, void* parameter)
-    __attribute__ ((section (".entry")));
+enum plugin_status plugin_start(struct plugin_api* rockbox, void* parameter);
 
 #endif
diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c
index a5353af..1871b29 100644
--- a/uisimulator/common/io.c
+++ b/uisimulator/common/io.c
@@ -303,7 +303,7 @@
 #include <dlfcn.h>
 #endif
 
-void *sim_codec_load_ram(char* codecptr, int size, 
+void *sim_codec_load_ram(char* codecptr, int size,
         void* ptr2, int bufwrap, int *pd_fd)
 {
     void *pd;
@@ -372,22 +372,21 @@
 
 void sim_codec_close(int pd)
 {
-        dlclose((void *)pd);
+    dlclose((void *)pd);
 }
 
 void *sim_plugin_load(char *plugin, int *fd)
 {
-    void* pd;
+    void *pd, *hdr;
     char path[256];
-    int (*plugin_start)(void * api, void* param);
 #ifdef WIN32
     char buf[256];
 #endif
 
     snprintf(path, sizeof path, "archos%s", plugin);
-
-    *fd = -1;
     
+    *fd = 0;
+
     pd = dlopen(path, RTLD_NOW);
     if (!pd) {
         DEBUGF("failed to load %s\n", plugin);
@@ -402,16 +401,12 @@
         return NULL;
     }
 
-    plugin_start = dlsym(pd, "plugin_start");
-    if (!plugin_start) {
-        plugin_start = dlsym(pd, "_plugin_start");
-        if (!plugin_start) {
-            dlclose(pd);
-            return NULL;
-        }
-    }
+    hdr = dlsym(pd, "__header");
+    if (!hdr)
+        hdr = dlsym(pd, "___header");
+
     *fd = (int)pd; /* success */
-    return plugin_start;
+    return hdr;    /* maybe NULL if symbol not present */
 }
 
 void sim_plugin_close(int pd)
diff --git a/uisimulator/win32/plugin.def b/uisimulator/win32/plugin.def
index 403b2d1..e37ce20 100755
--- a/uisimulator/win32/plugin.def
+++ b/uisimulator/win32/plugin.def
@@ -1,3 +1,2 @@
 EXPORTS
-	plugin_start
-
+	__header