Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / unix / plugins.c
1 /* tag: plugin interface for openbios forth kernel
2  *
3  * Copyright (C) 2003, 2004 Stefan Reinauer
4  *
5  * See the file "COPYING" for further information about
6  * the copyright and warranty status of this work.
7  */
8
9 #include "sysinclude.h"
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <dlfcn.h>
14
15 #include "unix/plugins.h"
16
17 unsigned char *plugindir = "/usr/share/OpenBIOS/plugins";
18 #define PLUGINDIR  plugindir
19 #define PATHSIZE   256
20
21 #define CONFIG_DEBUG_PLUGINS
22
23 typedef struct iorange iorange_t;
24 struct iorange {
25         const char *name;
26         unsigned int start;
27         unsigned int end;
28         io_ops_t *ops;
29         iorange_t *next;
30 };
31
32 static iorange_t *ioranges = NULL;
33
34 typedef struct plugin plugin_t;
35 struct plugin {
36         const char *name;
37         plugin_t *next;
38 };
39
40 static plugin_t *plugins = NULL;
41
42 io_ops_t *find_iorange(u32 reg)
43 {
44         iorange_t *range = ioranges;
45         while (range) {
46                 if (range->start <= reg && range->end >= reg)
47                         return range->ops;
48                 range = range->next;
49         }
50         return NULL;
51 }
52
53 int register_iorange(const char *name, io_ops_t * ops, unsigned int rstart,
54                      unsigned int rend)
55 {
56         iorange_t *newrange;
57
58         /* intersection check */
59         newrange = ioranges;
60         while (newrange) {
61                 int fail = 0;
62                 /* new section swallows old section */
63                 if (newrange->start >= rstart && newrange->end <= rend)
64                         fail = -1;
65                 /* new section start or end point are within range */
66                 if (newrange->start <= rstart && newrange->end >= rstart)
67                         fail = -1;
68                 if (newrange->start <= rend && newrange->end >= rend)
69                         fail = -1;
70                 if (fail) {
71                         printf("Error: overlapping IO regions: %s and %s\n",
72                                 newrange->name, name);
73                         return -1;
74                 }
75                 newrange = newrange->next;
76         }
77
78         newrange = malloc(sizeof(iorange_t));
79
80         newrange->name = name;
81         newrange->ops = ops;
82         newrange->start = rstart;
83         newrange->end = rend;
84         newrange->next = ioranges;
85
86         ioranges = newrange;
87
88         return 0;
89 }
90
91 int is_loaded(const char *plugin_name)
92 {
93         plugin_t *p = plugins;
94         while (p) {
95                 if (!strcmp(plugin_name, p->name))
96                         return -1;
97                 p = p->next;
98         }
99         return 0;
100 }
101
102 int load_plugin(const char *plugin_name)
103 {
104         void *handle;
105         char *error;
106         char path[PATHSIZE];
107
108         int (*init_plugin) (void);
109         char **deps;
110         char **plugin_info;
111         plugin_t *p;
112
113         if (is_loaded(plugin_name)) {
114                 printf("Plugin %s already loaded.\n", plugin_name);
115                 return 0;
116         }
117
118         strncpy(path, PLUGINDIR, PATHSIZE);
119         strncat(path, "/plugin_", PATHSIZE);
120         strncat(path, plugin_name, PATHSIZE);
121         strncat(path, ".so", PATHSIZE);
122
123 #if DEBUG
124         printf("Opening plugin %s\n", path);
125 #endif
126
127         handle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
128         if (!handle) {
129                 error = dlerror();
130                 printf("Error: Could not open plugin \"%s\": %s\n",
131                        plugin_name, error);
132                 exit(1);
133         }
134 #ifdef CONFIG_DEBUG_PLUGINS
135         plugin_info = dlsym(handle, "plugin_author");
136         if ((error = dlerror()) == NULL)
137                 printf("Plugin %s author:  %s\n", plugin_name, *plugin_info);
138         plugin_info = dlsym(handle, "plugin_license");
139         if ((error = dlerror()) == NULL)
140                 printf("Plugin %s license: %s\n", plugin_name, *plugin_info);
141         plugin_info = dlsym(handle, "plugin_description");
142         if ((error = dlerror()) == NULL)
143                 printf("Plugin %s descr.: %s\n", plugin_name, *plugin_info);
144 #endif
145         p = malloc(sizeof(plugin_t));
146         p->next = plugins;
147         p->name = plugin_name;
148         plugins = p;
149
150         deps = dlsym(handle, "plugin_deps");
151         if ((error = dlerror()) != NULL)
152                 deps = NULL;
153
154
155         strncpy(path, "plugin_", PATHSIZE);
156         strncat(path, plugin_name, PATHSIZE);
157         strncat(path, "_init", PATHSIZE);
158
159         init_plugin = dlsym(handle, path);
160         if ((error = dlerror()) != NULL) {
161                 printf("error: %s\n", error);
162                 exit(1);
163         }
164
165         if (deps) {
166                 int i = 0;
167                 char *walk = deps[0];
168 #ifdef CONFIG_DEBUG_PLUGINS
169                 printf("\nPlugin %s dependencies:", plugin_name);
170 #endif
171                 while (walk) {
172                         printf(" %s", walk);
173                         if (!is_loaded(walk)) {
174 #ifdef CONFIG_DEBUG_PLUGINS
175                                 printf("(loading)\n");
176 #endif
177                                 load_plugin(walk);
178                         }
179 #ifdef CONFIG_DEBUG_PLUGINS
180                         else {
181                                 printf("(loaded)");
182                         }
183 #endif
184                         walk = deps[++i];
185                 }
186         }
187
188         printf("\n");
189 #if DEBUG
190         printf("Initializing module:\n");
191 #endif
192
193         return init_plugin();
194
195         // We don't dlclose the handle here since
196         // we want to keep our symbols for later use.
197 }