mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
initial import of openbios--main--1.0--patch-26
git-svn-id: svn://coreboot.org/openbios/openbios-devel@1 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
209
arch/unix/plugins/loader.c
Normal file
209
arch/unix/plugins/loader.c
Normal file
@@ -0,0 +1,209 @@
|
||||
/* tag: openbios plugin loader
|
||||
*
|
||||
* Copyright (C) 2003 Stefan Reinauer
|
||||
*
|
||||
* See the file "COPYING" for further information about
|
||||
* the copyright and warranty status of this work.
|
||||
*/
|
||||
|
||||
/* This is a simple plugin loader. OpenBIOS duplicates some
|
||||
* of this code in kernel/arch/unix/plugins.c. This code is
|
||||
* here for reference and simple testing.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h> // sleep
|
||||
|
||||
#include "unix/plugins.h"
|
||||
|
||||
#define PLUGINDIR "/usr/share/OpenBIOS/plugins"
|
||||
#define PATHSIZE 256
|
||||
|
||||
#define DEBUG_PLUGINS
|
||||
|
||||
typedef struct iorange iorange_t;
|
||||
struct iorange {
|
||||
const char *name;
|
||||
unsigned int start;
|
||||
unsigned int end;
|
||||
io_ops_t *ops;
|
||||
iorange_t *next;
|
||||
};
|
||||
|
||||
iorange_t *ioranges = NULL;
|
||||
|
||||
typedef struct plugin plugin_t;
|
||||
struct plugin {
|
||||
const char *name;
|
||||
plugin_t *next;
|
||||
};
|
||||
|
||||
plugin_t *plugins = NULL;
|
||||
|
||||
int register_iorange(const char *name, io_ops_t * ops, unsigned int rstart,
|
||||
unsigned int rend)
|
||||
{
|
||||
iorange_t *newrange;
|
||||
|
||||
/* intersection check */
|
||||
newrange = ioranges;
|
||||
while (newrange) {
|
||||
int fail = 0;
|
||||
/* new section swallows old section */
|
||||
if (newrange->start >= rstart && newrange->end <= rend)
|
||||
fail = -1;
|
||||
/* new section start or end point are within range */
|
||||
if (newrange->start <= rstart && newrange->end >= rstart)
|
||||
fail = -1;
|
||||
if (newrange->start <= rend && newrange->end >= rend)
|
||||
fail = -1;
|
||||
if (fail) {
|
||||
printf("Error: overlapping IO regions: %s and %s\n",
|
||||
newrange->name, name);
|
||||
return -1;
|
||||
}
|
||||
newrange = newrange->next;
|
||||
}
|
||||
|
||||
newrange = malloc(sizeof(iorange_t));
|
||||
|
||||
newrange->name = name;
|
||||
newrange->ops = ops;
|
||||
newrange->start = rstart;
|
||||
newrange->end = rend;
|
||||
newrange->next = ioranges;
|
||||
|
||||
ioranges = newrange;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_loaded(const char *plugin_name)
|
||||
{
|
||||
plugin_t *p = plugins;
|
||||
while (p) {
|
||||
if (!strcmp(plugin_name, p->name))
|
||||
return -1;
|
||||
p = p->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_plugin(const char *plugin_name)
|
||||
{
|
||||
void *handle;
|
||||
char *error;
|
||||
char path[PATHSIZE];
|
||||
|
||||
int (*init_plugin) (void);
|
||||
char **deps;
|
||||
char **plugin_info;
|
||||
plugin_t *p;
|
||||
|
||||
if (is_loaded(plugin_name)) {
|
||||
printf("Plugin %s already loaded.\n", plugin_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strncpy(path, PLUGINDIR, PATHSIZE);
|
||||
strncat(path, "/plugin_", PATHSIZE);
|
||||
strncat(path, plugin_name, PATHSIZE);
|
||||
strncat(path, ".so", PATHSIZE);
|
||||
|
||||
#if DEBUG
|
||||
printf("Opening plugin %s\n", path);
|
||||
#endif
|
||||
|
||||
handle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
|
||||
if (!handle) {
|
||||
error = dlerror();
|
||||
printf("Error: Could not open plugin \"%s\": %s\n",
|
||||
plugin_name, error);
|
||||
exit(1);
|
||||
}
|
||||
#ifdef DEBUG_PLUGINS
|
||||
plugin_info = dlsym(handle, "plugin_author");
|
||||
if ((error = dlerror()) == NULL)
|
||||
printf("Plugin %s author: %s\n", plugin_name, *plugin_info);
|
||||
plugin_info = dlsym(handle, "plugin_license");
|
||||
if ((error = dlerror()) == NULL)
|
||||
printf("Plugin %s license: %s\n", plugin_name, *plugin_info);
|
||||
plugin_info = dlsym(handle, "plugin_description");
|
||||
if ((error = dlerror()) == NULL)
|
||||
printf("Plugin %s descr.: %s\n", plugin_name, *plugin_info);
|
||||
#endif
|
||||
p = malloc(sizeof(plugin_t));
|
||||
p->next = plugins;
|
||||
p->name = plugin_name;
|
||||
plugins = p;
|
||||
|
||||
deps = dlsym(handle, "plugin_deps");
|
||||
if ((error = dlerror()) != NULL)
|
||||
deps = NULL;
|
||||
|
||||
|
||||
strncpy(path, "plugin_", PATHSIZE);
|
||||
strncat(path, plugin_name, PATHSIZE);
|
||||
strncat(path, "_init", PATHSIZE);
|
||||
|
||||
init_plugin = dlsym(handle, path);
|
||||
if ((error = dlerror()) != NULL) {
|
||||
printf("error: %s\n", error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (deps) {
|
||||
int i = 0;
|
||||
char *walk = deps[0];
|
||||
#ifdef DEBUG_PLUGINS
|
||||
printf("\nPlugin %s dependencies:", plugin_name);
|
||||
#endif
|
||||
while (walk) {
|
||||
printf(" %s", walk);
|
||||
if (!is_loaded(walk)) {
|
||||
#ifdef DEBUG_PLUGINS
|
||||
printf("(loading)\n");
|
||||
#endif
|
||||
load_plugin(walk);
|
||||
}
|
||||
#ifdef DEBUG_PLUGINS
|
||||
else {
|
||||
printf("(loaded)");
|
||||
}
|
||||
#endif
|
||||
walk = deps[++i];
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
#if DEBUG
|
||||
printf("Initializing module:\n");
|
||||
#endif
|
||||
|
||||
return init_plugin();
|
||||
|
||||
// We don't dlclose the handle here since
|
||||
// we want to keep our symbols for later use.
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
iorange_t *r;
|
||||
|
||||
// load_plugin("kbd");
|
||||
// load_plugin("pci");
|
||||
load_plugin("qt");
|
||||
|
||||
printf("\nRegistered IO Ranges:\n");
|
||||
r = ioranges;
|
||||
while (r) {
|
||||
printf(" %s: %x-%x\n", r->name, r->start, r->end);
|
||||
r = r->next;
|
||||
}
|
||||
|
||||
sleep(10);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user