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
find_iorange(u32 reg)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
register_iorange(const char * name,io_ops_t * ops,unsigned int rstart,unsigned int rend)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
is_loaded(const char * plugin_name)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
load_plugin(const char * plugin_name)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 }
198