- compare disk size with the size calculated from geometry to avoid image
[bochs-mirror.git] / plugin.cc
blobbf93a6e79d32e06612871c2e7d5fafa19a5b1247
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: plugin.cc,v 1.21 2006/09/16 14:47:40 vruppert Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // This file defines the plugin and plugin-device registration functions and
6 // the device registration functions. It handles dynamic loading of modules,
7 // using the LTDL library for cross-platform support.
8 //
9 // This file is based on the plugin.c file from plex86, but with significant
10 // changes to make it work in Bochs.
11 // Plex86 is Copyright (C) 1999-2000 The plex86 developers team
13 /////////////////////////////////////////////////////////////////////////
15 #include "bochs.h"
16 #include "iodev/iodev.h"
17 #include "plugin.h"
19 #define LOG_THIS genlog->
21 #define PLUGIN_INIT_FMT_STRING "lib%s_LTX_plugin_init"
22 #define PLUGIN_FINI_FMT_STRING "lib%s_LTX_plugin_fini"
23 #define PLUGIN_PATH ""
25 #ifndef WIN32
26 #define PLUGIN_FILENAME_FORMAT "libbx_%s.la"
27 #else
28 #define PLUGIN_FILENAME_FORMAT "bx_%s.dll"
29 #endif
31 extern "C" {
33 void (*pluginRegisterIRQ)(unsigned irq, const char* name) = 0;
34 void (*pluginUnregisterIRQ)(unsigned irq, const char* name) = 0;
36 void (*pluginSetHRQ)(unsigned val) = 0;
37 void (*pluginSetHRQHackCallback)( void (*callback)(void) ) = 0;
39 int (*pluginRegisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
40 unsigned base, const char *name, Bit8u mask) = 0;
41 int (*pluginRegisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
42 unsigned base, const char *name, Bit8u mask) = 0;
43 int (*pluginUnregisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
44 unsigned base, Bit8u mask) = 0;
45 int (*pluginUnregisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
46 unsigned base, Bit8u mask) = 0;
47 int (*pluginRegisterIOReadHandlerRange)(void *thisPtr, ioReadHandler_t callback,
48 unsigned base, unsigned end, const char *name, Bit8u mask) = 0;
49 int (*pluginRegisterIOWriteHandlerRange)(void *thisPtr, ioWriteHandler_t callback,
50 unsigned base, unsigned end, const char *name, Bit8u mask) = 0;
51 int (*pluginUnregisterIOReadHandlerRange)(void *thisPtr, ioReadHandler_t callback,
52 unsigned begin, unsigned end, Bit8u mask) = 0;
53 int (*pluginUnregisterIOWriteHandlerRange)(void *thisPtr, ioWriteHandler_t callback,
54 unsigned begin, unsigned end, Bit8u mask) = 0;
55 int (*pluginRegisterDefaultIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
56 const char *name, Bit8u mask) = 0;
57 int (*pluginRegisterDefaultIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
58 const char *name, Bit8u mask) = 0;
59 int (*pluginRegisterTimer)(void *this_ptr, void (*funct)(void *),
60 Bit32u useconds, bx_bool continuous,
61 bx_bool active, const char* name) = 0;
62 void (*pluginActivateTimer)(unsigned id, Bit32u usec, bx_bool continuous) = 0;
64 void (*pluginHRQHackCallback)(void);
65 unsigned pluginHRQ = 0;
67 plugin_t *plugins = NULL; /* Head of the linked list of plugins */
68 #if BX_PLUGINS
69 static void plugin_init_one(plugin_t *plugin);
70 #endif
72 device_t *devices = NULL; /* Head of the linked list of registered devices */
74 plugin_t *current_plugin_context = NULL;
76 /************************************************************************/
77 /* Builtins declarations */
78 /************************************************************************/
80 static void
81 builtinRegisterIRQ(unsigned irq, const char* name)
83 #if 0
84 pluginlog->panic("builtinRegisterIRQ called, no pic plugin loaded?");
85 #else
86 bx_devices.register_irq(irq, name);
87 #endif
90 static void
91 builtinUnregisterIRQ(unsigned irq, const char* name)
93 #if 0
94 pluginlog->panic("builtinUnregisterIRQ called, no pic plugin loaded?");
95 #else
96 bx_devices.unregister_irq(irq, name);
97 #endif
100 static void
101 builtinSetHRQ(unsigned val)
103 #if 0
104 pluginlog->panic("builtinSetHRQ called, no plugin loaded?");
105 #else
106 pluginHRQ = val;
107 #endif
110 static void
111 builtinSetHRQHackCallback( void (*callback)(void) )
113 #if 0
114 pluginlog->panic("builtinSetHRQHackCallback called, no plugin loaded?");
115 #else
116 pluginHRQHackCallback = callback;
117 #endif
120 static int
121 builtinRegisterIOReadHandler(void *thisPtr, ioReadHandler_t callback,
122 unsigned base, const char *name, Bit8u mask)
124 int ret;
125 BX_ASSERT (mask<8);
126 ret = bx_devices.register_io_read_handler (thisPtr, callback, base, name, mask);
127 pluginlog->ldebug("plugin %s registered I/O read address at %04x", name, base);
128 return ret;
131 static int
132 builtinRegisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
133 unsigned base, const char *name, Bit8u mask)
135 int ret;
136 BX_ASSERT (mask<8);
137 ret = bx_devices.register_io_write_handler (thisPtr, callback, base, name, mask);
138 pluginlog->ldebug("plugin %s registered I/O write address at %04x", name, base);
139 return ret;
142 static int
143 builtinUnregisterIOReadHandler(void *thisPtr, ioReadHandler_t callback,
144 unsigned base, Bit8u mask)
146 int ret;
147 BX_ASSERT (mask<8);
148 ret = bx_devices.unregister_io_read_handler (thisPtr, callback, base, mask);
149 pluginlog->ldebug("plugin unregistered I/O read address at %04x", base);
150 return ret;
153 static int
154 builtinUnregisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
155 unsigned base, Bit8u mask)
157 int ret;
158 BX_ASSERT (mask<8);
159 ret = bx_devices.unregister_io_write_handler (thisPtr, callback, base, mask);
160 pluginlog->ldebug("plugin unregistered I/O write address at %04x", base);
161 return ret;
164 static int
165 builtinRegisterIOReadHandlerRange(void *thisPtr, ioReadHandler_t callback,
166 unsigned base, unsigned end, const char *name, Bit8u mask)
168 int ret;
169 BX_ASSERT (mask<8);
170 ret = bx_devices.register_io_read_handler_range (thisPtr, callback, base, end, name, mask);
171 pluginlog->ldebug("plugin %s registered I/O read addresses %04x to %04x", name, base, end);
172 return ret;
175 static int
176 builtinRegisterIOWriteHandlerRange(void *thisPtr, ioWriteHandler_t callback,
177 unsigned base, unsigned end, const char *name, Bit8u mask)
179 int ret;
180 BX_ASSERT (mask<8);
181 ret = bx_devices.register_io_write_handler_range (thisPtr, callback, base, end, name, mask);
182 pluginlog->ldebug("plugin %s registered I/O write addresses %04x to %04x", name, base, end);
183 return ret;
186 static int
187 builtinUnregisterIOReadHandlerRange(void *thisPtr, ioReadHandler_t callback,
188 unsigned begin, unsigned end, Bit8u mask)
190 int ret;
191 BX_ASSERT (mask<8);
192 ret = bx_devices.unregister_io_read_handler_range (thisPtr, callback, begin, end, mask);
193 pluginlog->ldebug("plugin unregistered I/O read addresses %04x to %04x", begin, end);
194 return ret;
197 static int
198 builtinUnregisterIOWriteHandlerRange(void *thisPtr, ioWriteHandler_t callback,
199 unsigned begin, unsigned end, Bit8u mask)
201 int ret;
202 BX_ASSERT (mask<8);
203 ret = bx_devices.unregister_io_write_handler_range (thisPtr, callback, begin, end, mask);
204 pluginlog->ldebug("plugin unregistered I/O write addresses %04x to %04x", begin, end);
205 return ret;
208 static int
209 builtinRegisterDefaultIOReadHandler(void *thisPtr, ioReadHandler_t callback,
210 const char *name, Bit8u mask)
212 BX_ASSERT (mask<8);
213 bx_devices.register_default_io_read_handler (thisPtr, callback, name, mask);
214 pluginlog->ldebug("plugin %s registered default I/O read ", name);
215 return 0;
218 static int
219 builtinRegisterDefaultIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
220 const char *name, Bit8u mask)
222 BX_ASSERT (mask<8);
223 bx_devices.register_default_io_write_handler (thisPtr, callback, name, mask);
224 pluginlog->ldebug("plugin %s registered default I/O write ", name);
225 return 0;
228 static int
229 builtinRegisterTimer(void *this_ptr, void (*funct)(void *),
230 Bit32u useconds, bx_bool continuous,
231 bx_bool active, const char* name)
233 int id = bx_pc_system.register_timer (this_ptr, funct, useconds, continuous, active, name);
234 pluginlog->ldebug("plugin %s registered timer %d", name, id);
235 return id;
238 static void
239 builtinActivateTimer(unsigned id, Bit32u usec, bx_bool continuous)
241 bx_pc_system.activate_timer (id, usec, continuous);
242 pluginlog->ldebug("plugin activated timer %d", id);
245 #if BX_PLUGINS
246 /************************************************************************/
247 /* Plugin initialization / deinitialization */
248 /************************************************************************/
250 void
251 plugin_init_all (void)
253 plugin_t *plugin;
255 pluginlog->info("Initializing plugins");
257 for (plugin = plugins; plugin; plugin = plugin->next)
259 char *arg_ptr = plugin->args;
261 /* process the command line */
262 plugin->argc = 0;
263 while (plugin->argc < MAX_ARGC)
265 while (*arg_ptr && isspace (*arg_ptr))
266 arg_ptr++;
268 if (!*arg_ptr)
269 break;
270 plugin->argv[plugin->argc++] = arg_ptr;
272 while (*arg_ptr && !isspace (*arg_ptr))
273 arg_ptr++;
275 if (!*arg_ptr)
276 break;
277 *arg_ptr++ = '\0';
280 /* initialize the plugin */
281 if (plugin->plugin_init (plugin, plugin->type, plugin->argc, plugin->argv))
283 pluginlog->panic("Plugin initialization failed for %s", plugin->name);
284 plugin_abort();
287 plugin->initialized = 1;
290 return;
293 void
294 plugin_init_one(plugin_t *plugin)
296 char *arg_ptr = plugin->args;
298 /* process the command line */
299 plugin->argc = 0;
300 while (plugin->argc < MAX_ARGC)
302 while (*arg_ptr && isspace (*arg_ptr))
303 arg_ptr++;
305 if (!*arg_ptr)
306 break;
307 plugin->argv[plugin->argc++] = arg_ptr;
309 while (*arg_ptr && !isspace (*arg_ptr))
310 arg_ptr++;
312 if (!*arg_ptr)
313 break;
314 *arg_ptr++ = '\0';
317 /* initialize the plugin */
318 if (plugin->plugin_init (plugin, plugin->type, plugin->argc, plugin->argv))
320 pluginlog->info("Plugin initialization failed for %s", plugin->name);
321 plugin_abort();
324 plugin->initialized = 1;
328 plugin_t *plugin_unload(plugin_t *plugin)
330 plugin_t *dead_plug;
332 if (plugin->initialized)
333 plugin->plugin_fini();
335 lt_dlclose(plugin->handle);
336 delete [] plugin->name;
338 dead_plug = plugin;
339 plugin = plugin->next;
340 free(dead_plug);
342 return plugin;
346 void plugin_fini_all (void)
348 plugin_t *plugin;
350 for (plugin = plugins; plugin; plugin = plugin_unload(plugin));
352 return;
355 void plugin_load(char *name, char *args, plugintype_t type)
357 plugin_t *plugin;
359 plugin = (plugin_t *)malloc (sizeof(plugin_t));
360 if (!plugin)
362 BX_PANIC(("malloc plugin_t failed"));
365 plugin->type = type;
366 plugin->name = name;
367 plugin->args = args;
368 plugin->initialized = 0;
370 char plugin_filename[BX_PATHNAME_LEN], buf[BX_PATHNAME_LEN];
371 sprintf(buf, PLUGIN_FILENAME_FORMAT, name);
372 sprintf(plugin_filename, "%s%s", PLUGIN_PATH, buf);
374 // Set context so that any devices that the plugin registers will
375 // be able to see which plugin created them. The registration will
376 // be called from either dlopen (global constructors) or plugin_init.
377 BX_ASSERT (current_plugin_context == NULL);
378 current_plugin_context = plugin;
379 plugin->handle = lt_dlopen (plugin_filename);
380 BX_INFO (("lt_dlhandle is %p", plugin->handle));
381 if (!plugin->handle)
383 current_plugin_context = NULL;
384 BX_PANIC (("dlopen failed for module '%s': %s", name, lt_dlerror ()));
385 free (plugin);
386 return;
389 sprintf(buf, PLUGIN_INIT_FMT_STRING, name);
390 plugin->plugin_init =
391 (int (*)(struct _plugin_t *, enum plugintype_t, int, char *[])) /* monster typecast */
392 lt_dlsym (plugin->handle, buf);
393 if (plugin->plugin_init == NULL) {
394 pluginlog->panic("could not find plugin_init: %s", lt_dlerror ());
395 plugin_abort ();
398 sprintf(buf, PLUGIN_FINI_FMT_STRING, name);
399 plugin->plugin_fini = (void (*)(void)) lt_dlsym (plugin->handle, buf);
400 if (plugin->plugin_init == NULL) {
401 pluginlog->panic("could not find plugin_fini: %s", lt_dlerror ());
402 plugin_abort ();
404 pluginlog->info("loaded plugin %s",plugin_filename);
407 /* Insert plugin at the _end_ of the plugin linked list. */
408 plugin->next = NULL;
410 if (!plugins)
412 /* Empty list, this become the first entry. */
413 plugins = plugin;
415 else
417 /* Non-empty list. Add to end. */
418 plugin_t *temp = plugins;
420 while (temp->next)
421 temp = temp->next;
423 temp->next = plugin;
426 plugin_init_one(plugin);
428 // check that context didn't change. This should only happen if we
429 // need a reentrant plugin_load.
430 BX_ASSERT (current_plugin_context == plugin);
431 current_plugin_context = NULL;
433 return;
436 void plugin_abort(void)
438 pluginlog->panic("plugin load aborted");
441 #endif /* end of #if BX_PLUGINS */
443 /************************************************************************/
444 /* Plugin system: initialisation of plugins entry points */
445 /************************************************************************/
447 void
448 plugin_startup(void)
450 pluginRegisterIRQ = builtinRegisterIRQ;
451 pluginUnregisterIRQ = builtinUnregisterIRQ;
453 pluginSetHRQHackCallback = builtinSetHRQHackCallback;
454 pluginSetHRQ = builtinSetHRQ;
456 pluginRegisterIOReadHandler = builtinRegisterIOReadHandler;
457 pluginRegisterIOWriteHandler = builtinRegisterIOWriteHandler;
459 pluginUnregisterIOReadHandler = builtinUnregisterIOReadHandler;
460 pluginUnregisterIOWriteHandler = builtinUnregisterIOWriteHandler;
462 pluginRegisterIOReadHandlerRange = builtinRegisterIOReadHandlerRange;
463 pluginRegisterIOWriteHandlerRange = builtinRegisterIOWriteHandlerRange;
465 pluginUnregisterIOReadHandlerRange = builtinUnregisterIOReadHandlerRange;
466 pluginUnregisterIOWriteHandlerRange = builtinUnregisterIOWriteHandlerRange;
468 pluginRegisterDefaultIOReadHandler = builtinRegisterDefaultIOReadHandler;
469 pluginRegisterDefaultIOWriteHandler = builtinRegisterDefaultIOWriteHandler;
471 pluginRegisterTimer = builtinRegisterTimer;
472 pluginActivateTimer = builtinActivateTimer;
474 #if BX_PLUGINS
475 pluginlog = new logfunctions();
476 pluginlog->put("PLGIN");
477 pluginlog->settype(PLUGINLOG);
478 int status = lt_dlinit ();
479 if (status != 0) {
480 BX_ERROR (("initialization error in ltdl library (for loading plugins)"));
481 BX_PANIC (("error message was: %s", lt_dlerror ()));
483 #endif
487 /************************************************************************/
488 /* Plugin system: Device registration */
489 /************************************************************************/
491 void pluginRegisterDeviceDevmodel(plugin_t *plugin, plugintype_t type, bx_devmodel_c *devmodel, char *name)
493 device_t *device;
495 device = (device_t *)malloc (sizeof (device_t));
496 if (!device)
498 pluginlog->panic("can't allocate device_t");
501 device->name = name;
502 BX_ASSERT (devmodel != NULL);
503 device->devmodel = devmodel;
504 device->plugin = plugin; // this can be NULL
505 device->next = NULL;
507 // Don't add every kind of device to the list.
508 switch (type) {
509 case PLUGTYPE_CORE:
510 // Core devices are present whether or not we are using plugins, so
511 // they are managed by the same code in iodev/devices.cc whether
512 // plugins are on or off.
513 free(device);
514 return; // Do not add core devices to the devices list.
515 case PLUGTYPE_OPTIONAL:
516 case PLUGTYPE_USER:
517 default:
518 // The plugin system will manage optional and user devices only.
519 break;
522 if (!devices)
524 /* Empty list, this become the first entry. */
525 devices = device;
527 else
529 /* Non-empty list. Add to end. */
530 device_t *temp = devices;
532 while (temp->next)
533 temp = temp->next;
535 temp->next = device;
539 /************************************************************************/
540 /* Plugin system: Check if a plugin is loaded */
541 /************************************************************************/
543 bx_bool pluginDevicePresent(char *name)
545 device_t *device;
547 for (device = devices; device; device = device->next)
549 if (strcmp(device->name,name)==0) return true;
552 return false;
555 #if BX_PLUGINS
556 /************************************************************************/
557 /* Plugin system: Load one plugin */
558 /************************************************************************/
560 int bx_load_plugin(const char *name, plugintype_t type)
562 char *namecopy = new char[1+strlen(name)];
563 strcpy(namecopy, name);
564 plugin_load(namecopy, "", type);
565 return 0;
568 void bx_unload_plugin(const char *name)
570 plugin_t *plugin, *prev = NULL;
572 for (plugin = plugins; plugin; plugin = plugin->next) {
573 if (!strcmp(plugin->name, name)) {
574 plugin = plugin_unload(plugin);
575 if (prev == NULL) {
576 plugins = plugin;
577 } else {
578 prev->next = plugin;
580 break;
581 } else {
582 prev = plugin;
587 #endif /* end of #if BX_PLUGINS */
589 /*************************************************************************/
590 /* Plugin system: Execute init function of all registered plugin-devices */
591 /*************************************************************************/
593 void bx_init_plugins()
595 device_t *device;
597 // two loops
598 for (device = devices; device; device = device->next)
600 pluginlog->info("init_mem of '%s' plugin device by virtual method",device->name);
601 device->devmodel->init_mem(BX_MEM(0));
604 for (device = devices; device; device = device->next)
606 pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name);
607 device->devmodel->init();
611 /**************************************************************************/
612 /* Plugin system: Execute reset function of all registered plugin-devices */
613 /**************************************************************************/
615 void bx_reset_plugins(unsigned signal)
617 device_t *device;
618 for (device = devices; device; device = device->next)
620 pluginlog->info("reset of '%s' plugin device by virtual method",device->name);
621 device->devmodel->reset(signal);
625 /*******************************************************/
626 /* Plugin system: Unload all registered plugin-devices */
627 /*******************************************************/
629 void bx_unload_plugins()
631 device_t *device, *next;
633 device = devices;
634 while (device != NULL) {
635 if (device->plugin != NULL) {
636 #if BX_PLUGINS
637 bx_unload_plugin(device->name);
638 #endif
639 } else {
640 delete device->devmodel;
642 next = device->next;
643 free(device);
644 device = next;
646 devices = NULL;
649 #if BX_SUPPORT_SAVE_RESTORE
650 /**************************************************************************/
651 /* Plugin system: Register device state of all registered plugin-devices */
652 /**************************************************************************/
654 void bx_plugins_register_state()
656 device_t *device;
657 for (device = devices; device; device = device->next)
659 pluginlog->info("register state of '%s' plugin device by virtual method",device->name);
660 device->devmodel->register_state();
664 /***************************************************************************/
665 /* Plugin system: Execute code after restoring state of all plugin devices */
666 /***************************************************************************/
668 void bx_plugins_after_restore_state()
670 device_t *device;
671 for (device = devices; device; device = device->next)
673 device->devmodel->after_restore_state();
676 #endif