1 /////////////////////////////////////////////////////////////////////////
2 // $Id: plugin.cc 14214 2021-04-03 18:26:03Z vruppert $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //  Copyright (C) 2002-2021  The Bochs Project
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20 //
21 /////////////////////////////////////////////////////////////////////////
22 //
23 // This file defines the plugin and plugin-device registration functions and
24 // the device registration functions.  It handles dynamic loading of modules,
25 // using the LTDL library for cross-platform support.
26 //
27 // This file is based on the plugin.c file from plex86, but with significant
28 // changes to make it work in Bochs.
29 // Plex86 is Copyright (C) 1999-2000  The plex86 developers team
30 //
31 /////////////////////////////////////////////////////////////////////////
32 
33 #include "bochs.h"
34 #include "iodev/iodev.h"
35 #include "plugin.h"
36 
37 #ifndef WIN32
38 #include <dirent.h> /* opendir, readdir */
39 #include <locale.h> /* setlocale */
40 #endif
41 
42 #define LOG_THIS genlog->
43 
44 #define PLUGIN_ENTRY_FMT_STRING       "lib%s_plugin_entry"
45 #define GUI_PLUGIN_ENTRY_FMT_STRING   "lib%s_gui_plugin_entry"
46 #define IMG_PLUGIN_ENTRY_FMT_STRING   "lib%s_img_plugin_entry"
47 #define NET_PLUGIN_ENTRY_FMT_STRING   "libeth_%s_plugin_entry"
48 #define SND_PLUGIN_ENTRY_FMT_STRING   "libsound%s_plugin_entry"
49 
50 #define PLUGIN_PATH                   ""
51 
52 #ifndef WIN32
53 #define PLUGIN_FILENAME_FORMAT       "libbx_%s.so"
54 #define GUI_PLUGIN_FILENAME_FORMAT   "libbx_%s_gui.so"
55 #define IMG_PLUGIN_FILENAME_FORMAT   "libbx_%s_img.so"
56 #define NET_PLUGIN_FILENAME_FORMAT   "libbx_eth_%s.so"
57 #define SND_PLUGIN_FILENAME_FORMAT   "libbx_sound%s.so"
58 #else
59 #define PLUGIN_FILENAME_FORMAT       "bx_%s.dll"
60 #define GUI_PLUGIN_FILENAME_FORMAT   "bx_%s_gui.dll"
61 #define IMG_PLUGIN_FILENAME_FORMAT   "bx_%s_img.dll"
62 #define NET_PLUGIN_FILENAME_FORMAT   "bx_eth_%s.dll"
63 #define SND_PLUGIN_FILENAME_FORMAT "bx_sound%s.dll"
64 #endif
65 
66 logfunctions *pluginlog;
67 
68 extern "C" {
69 
70 void  (*pluginRegisterIRQ)(unsigned irq, const char* name) = 0;
71 void  (*pluginUnregisterIRQ)(unsigned irq, const char* name) = 0;
72 
73 void (*pluginSetHRQ)(unsigned val) = 0;
74 void (*pluginSetHRQHackCallback)(void (*callback)(void)) = 0;
75 
76 int (*pluginRegisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
77                             unsigned base, const char *name, Bit8u mask) = 0;
78 int (*pluginRegisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
79                              unsigned base, const char *name, Bit8u mask) = 0;
80 int (*pluginUnregisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
81                             unsigned base, Bit8u mask) = 0;
82 int (*pluginUnregisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
83                              unsigned base, Bit8u mask) = 0;
84 int (*pluginRegisterIOReadHandlerRange)(void *thisPtr, ioReadHandler_t callback,
85                             unsigned base, unsigned end, const char *name, Bit8u mask) = 0;
86 int (*pluginRegisterIOWriteHandlerRange)(void *thisPtr, ioWriteHandler_t callback,
87                              unsigned base, unsigned end, const char *name, Bit8u mask) = 0;
88 int (*pluginUnregisterIOReadHandlerRange)(void *thisPtr, ioReadHandler_t callback,
89                             unsigned begin, unsigned end, Bit8u mask) = 0;
90 int (*pluginUnregisterIOWriteHandlerRange)(void *thisPtr, ioWriteHandler_t callback,
91                              unsigned begin, unsigned end, Bit8u mask) = 0;
92 int (*pluginRegisterDefaultIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
93                             const char *name, Bit8u mask) = 0;
94 int (*pluginRegisterDefaultIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
95                              const char *name, Bit8u mask) = 0;
96 
97 void (*pluginHRQHackCallback)(void);
98 unsigned pluginHRQ = 0;
99 
100 plugin_t *plugins = NULL;      /* Head of the linked list of plugins  */
101 device_t *devices = NULL;      /* Head of the linked list of registered devices  */
102 device_t *core_devices = NULL; /* Head of the linked list of registered core devices  */
103 
104 plugin_t *current_plugin_context = NULL;
105 
106 /************************************************************************/
107 /* Builtins declarations                                                */
108 /************************************************************************/
109 
110   static void
builtinRegisterIRQ(unsigned irq,const char * name)111 builtinRegisterIRQ(unsigned irq, const char* name)
112 {
113   bx_devices.register_irq(irq, name);
114 }
115 
116   static void
builtinUnregisterIRQ(unsigned irq,const char * name)117 builtinUnregisterIRQ(unsigned irq, const char* name)
118 {
119   bx_devices.unregister_irq(irq, name);
120 }
121 
122   static void
builtinSetHRQ(unsigned val)123 builtinSetHRQ(unsigned val)
124 {
125   pluginHRQ = val;
126 }
127 
128   static void
builtinSetHRQHackCallback(void (* callback)(void))129 builtinSetHRQHackCallback(void (*callback)(void))
130 {
131   pluginHRQHackCallback = callback;
132 }
133 
134   static int
builtinRegisterIOReadHandler(void * thisPtr,ioReadHandler_t callback,unsigned base,const char * name,Bit8u mask)135 builtinRegisterIOReadHandler(void *thisPtr, ioReadHandler_t callback,
136                             unsigned base, const char *name, Bit8u mask)
137 {
138   int ret;
139   BX_ASSERT(mask<8);
140   ret = bx_devices.register_io_read_handler (thisPtr, callback, base, name, mask);
141   pluginlog->ldebug("plugin %s registered I/O read  address at %04x", name, base);
142   return ret;
143 }
144 
145   static int
builtinRegisterIOWriteHandler(void * thisPtr,ioWriteHandler_t callback,unsigned base,const char * name,Bit8u mask)146 builtinRegisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
147                              unsigned base, const char *name, Bit8u mask)
148 {
149   int ret;
150   BX_ASSERT(mask<8);
151   ret = bx_devices.register_io_write_handler (thisPtr, callback, base, name, mask);
152   pluginlog->ldebug("plugin %s registered I/O write address at %04x", name, base);
153   return ret;
154 }
155 
156   static int
builtinUnregisterIOReadHandler(void * thisPtr,ioReadHandler_t callback,unsigned base,Bit8u mask)157 builtinUnregisterIOReadHandler(void *thisPtr, ioReadHandler_t callback,
158                             unsigned base, Bit8u mask)
159 {
160   int ret;
161   BX_ASSERT(mask<8);
162   ret = bx_devices.unregister_io_read_handler (thisPtr, callback, base, mask);
163   pluginlog->ldebug("plugin unregistered I/O read address at %04x", base);
164   return ret;
165 }
166 
167   static int
builtinUnregisterIOWriteHandler(void * thisPtr,ioWriteHandler_t callback,unsigned base,Bit8u mask)168 builtinUnregisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
169                              unsigned base, Bit8u mask)
170 {
171   int ret;
172   BX_ASSERT(mask<8);
173   ret = bx_devices.unregister_io_write_handler (thisPtr, callback, base, mask);
174   pluginlog->ldebug("plugin unregistered I/O write address at %04x", base);
175   return ret;
176 }
177 
178   static int
builtinRegisterIOReadHandlerRange(void * thisPtr,ioReadHandler_t callback,unsigned base,unsigned end,const char * name,Bit8u mask)179 builtinRegisterIOReadHandlerRange(void *thisPtr, ioReadHandler_t callback,
180                             unsigned base, unsigned end, const char *name, Bit8u mask)
181 {
182   int ret;
183   BX_ASSERT(mask<8);
184   ret = bx_devices.register_io_read_handler_range (thisPtr, callback, base, end, name, mask);
185   pluginlog->ldebug("plugin %s registered I/O read addresses %04x to %04x", name, base, end);
186   return ret;
187 }
188 
189   static int
builtinRegisterIOWriteHandlerRange(void * thisPtr,ioWriteHandler_t callback,unsigned base,unsigned end,const char * name,Bit8u mask)190 builtinRegisterIOWriteHandlerRange(void *thisPtr, ioWriteHandler_t callback,
191                              unsigned base, unsigned end, const char *name, Bit8u mask)
192 {
193   int ret;
194   BX_ASSERT(mask<8);
195   ret = bx_devices.register_io_write_handler_range (thisPtr, callback, base, end, name, mask);
196   pluginlog->ldebug("plugin %s registered I/O write addresses %04x to %04x", name, base, end);
197   return ret;
198 }
199 
200   static int
builtinUnregisterIOReadHandlerRange(void * thisPtr,ioReadHandler_t callback,unsigned begin,unsigned end,Bit8u mask)201 builtinUnregisterIOReadHandlerRange(void *thisPtr, ioReadHandler_t callback,
202                             unsigned begin, unsigned end, Bit8u mask)
203 {
204   int ret;
205   BX_ASSERT(mask<8);
206   ret = bx_devices.unregister_io_read_handler_range (thisPtr, callback, begin, end, mask);
207   pluginlog->ldebug("plugin unregistered I/O read addresses %04x to %04x", begin, end);
208   return ret;
209 }
210 
211   static int
builtinUnregisterIOWriteHandlerRange(void * thisPtr,ioWriteHandler_t callback,unsigned begin,unsigned end,Bit8u mask)212 builtinUnregisterIOWriteHandlerRange(void *thisPtr, ioWriteHandler_t callback,
213                              unsigned begin, unsigned end, Bit8u mask)
214 {
215   int ret;
216   BX_ASSERT(mask<8);
217   ret = bx_devices.unregister_io_write_handler_range (thisPtr, callback, begin, end, mask);
218   pluginlog->ldebug("plugin unregistered I/O write addresses %04x to %04x", begin, end);
219   return ret;
220 }
221 
222   static int
builtinRegisterDefaultIOReadHandler(void * thisPtr,ioReadHandler_t callback,const char * name,Bit8u mask)223 builtinRegisterDefaultIOReadHandler(void *thisPtr, ioReadHandler_t callback,
224                             const char *name, Bit8u mask)
225 {
226   BX_ASSERT(mask<8);
227   bx_devices.register_default_io_read_handler (thisPtr, callback, name, mask);
228   pluginlog->ldebug("plugin %s registered default I/O read ", name);
229   return 0;
230 }
231 
232   static int
builtinRegisterDefaultIOWriteHandler(void * thisPtr,ioWriteHandler_t callback,const char * name,Bit8u mask)233 builtinRegisterDefaultIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
234                              const char *name, Bit8u mask)
235 {
236   BX_ASSERT(mask<8);
237   bx_devices.register_default_io_write_handler (thisPtr, callback, name, mask);
238   pluginlog->ldebug("plugin %s registered default I/O write ", name);
239   return 0;
240 }
241 
242 #if BX_PLUGINS
243 /************************************************************************/
244 /* Search for all available plugins                                           */
245 /************************************************************************/
246 
plugin_add_entry(char * pgn_name,Bit16u type,Bit8u flags)247 void plugin_add_entry(char *pgn_name, Bit16u type, Bit8u flags)
248 {
249   plugin_t *plugin, *temp;
250 
251   if ((type & PLUGTYPE_GUI) > 0) {
252     if (!strncmp(pgn_name + strlen(pgn_name) - 4, "_gui", 4)) {
253       pgn_name[strlen(pgn_name) - 4] = 0;
254     }
255   } else if (type == PLUGTYPE_IMG) {
256     if (!strncmp(pgn_name + strlen(pgn_name) - 4, "_img", 4)) {
257       pgn_name[strlen(pgn_name) - 4] = 0;
258     }
259   } else if (type == PLUGTYPE_NET) {
260     if (!strncmp(pgn_name, "eth_", 4)) {
261       memmove(pgn_name, pgn_name + 4, strlen(pgn_name) - 3);
262     }
263   } else if (type == PLUGTYPE_SND) {
264     if (!strncmp(pgn_name, "sound", 5)) {
265       memmove(pgn_name, pgn_name + 5, strlen(pgn_name) - 4);
266     }
267   }
268   plugin = new plugin_t;
269   plugin->type = type;
270   plugin->flags = flags;
271   plugin->name = pgn_name;
272   plugin->loadtype = PLUGTYPE_NULL;
273   plugin->initialized = 0;
274   /* Insert plugin at the _end_ of the plugin linked list. */
275   plugin->next = NULL;
276   if (plugins == NULL) {
277     /* Empty list, this become the first entry. */
278     plugins = plugin;
279   } else {
280     /* Non-empty list.  Add to end. */
281     temp = plugins;
282 
283     while (temp->next)
284       temp = temp->next;
285 
286     temp->next = plugin;
287   }
288 }
289 
plugins_search(void)290 void plugins_search(void)
291 {
292   int nlen, flen1, flen2;
293   char *fmtptr, *ltdl_path_var, *pgn_name, *pgn_path, *ptr;
294   char fmtstr[32];
295 #ifndef WIN32
296   const char *path_sep = ":";
297   DIR *dir;
298   struct dirent *dent;
299   lt_dlhandle handle;
300 #else
301   const char *path_sep = ";";
302   WIN32_FIND_DATA finddata;
303   HANDLE hFind;
304   char filter[MAX_PATH];
305   char path[MAX_PATH];
306   HINSTANCE handle;
307 #endif
308   char tmpname[BX_PATHNAME_LEN];
309   plugin_entry_t plugin_entry;
310   Bit16u type;
311   Bit8u flags;
312 
313 #ifndef WIN32
314   setlocale(LC_ALL, "en_US");
315 #endif
316   ltdl_path_var = getenv("LTDL_LIBRARY_PATH");
317   sprintf(fmtstr, PLUGIN_FILENAME_FORMAT, "*");
318   fmtptr = strchr(fmtstr, '*');
319   flen1 = fmtptr - fmtstr;
320   flen2 = strlen(fmtstr) - flen1 - 1;
321   if (ltdl_path_var != NULL) {
322     pgn_path = new char[strlen(ltdl_path_var) + 1];
323     strcpy(pgn_path, ltdl_path_var);
324   } else {
325     pgn_path = new char[2];
326     strcpy(pgn_path, ".");
327   }
328   ptr = strtok(pgn_path, path_sep);
329   while (ptr != NULL) {
330 #ifndef WIN32
331     dir = opendir(ptr);
332     if (dir != NULL) {
333       while ((dent=readdir(dir)) != NULL) {
334         nlen = strlen(dent->d_name);
335         if ((!strncmp(dent->d_name, fmtstr, flen1)) &&
336             (!strcmp(dent->d_name + nlen - flen2, fmtptr + 1))) {
337           pgn_name = new char[nlen - flen1 - flen2 + 1];
338           strncpy(pgn_name, dent->d_name + flen1, nlen - flen1 - flen2);
339           pgn_name[nlen - flen1 - flen2] = 0;
340           handle = lt_dlopen(dent->d_name);
341           if (handle) {
342             sprintf(tmpname, PLUGIN_ENTRY_FMT_STRING, pgn_name);
343             plugin_entry = (plugin_entry_t) lt_dlsym(handle, tmpname);
344             if (plugin_entry != NULL) {
345               type = (Bit16u) plugin_entry(NULL, PLUGTYPE_NULL, PLUGIN_PROBE);
346               flags = (Bit8u) plugin_entry(NULL, PLUGTYPE_NULL, PLUGIN_FLAGS);
347               plugin_add_entry(pgn_name, type, flags);
348             }
349             lt_dlclose(handle);
350           } else {
351             delete [] pgn_name;
352           }
353         }
354       }
355       closedir(dir);
356     }
357 #else
358     sprintf(filter, "%s\\*.dll", ptr);
359     hFind = FindFirstFile(filter, &finddata);
360     if (hFind != INVALID_HANDLE_VALUE) {
361       do {
362         nlen = lstrlen(finddata.cFileName);
363         if ((!strncmp(finddata.cFileName, fmtstr, flen1)) &&
364             (!strcmp(finddata.cFileName + nlen - flen2, fmtptr + 1))) {
365           pgn_name = new char[nlen - flen1 - flen2 + 1];
366           strncpy(pgn_name, finddata.cFileName + flen1, nlen - flen1 - flen2);
367           pgn_name[nlen - flen1 - flen2] = 0;
368           sprintf(path, "%s\\%s", ptr, finddata.cFileName);
369           handle = LoadLibrary(path);
370           if (handle) {
371             sprintf(tmpname, PLUGIN_ENTRY_FMT_STRING, pgn_name);
372             plugin_entry = (plugin_entry_t) GetProcAddress(handle, tmpname);
373             if (plugin_entry != NULL) {
374               type = (Bit16u) plugin_entry(NULL, PLUGTYPE_NULL, PLUGIN_PROBE);
375               flags = (Bit8u) plugin_entry(NULL, PLUGTYPE_NULL, PLUGIN_FLAGS);
376               plugin_add_entry(pgn_name, type, flags);
377             }
378             FreeLibrary(handle);
379           }
380         }
381       } while (FindNextFile(hFind, &finddata));
382       FindClose(hFind);
383     }
384 #endif
385     ptr = strtok(NULL, ":");
386   }
387   delete [] pgn_path;
388 }
389 
bx_get_plugins_count(Bit16u type)390 Bit8u bx_get_plugins_count(Bit16u type)
391 {
392   plugin_t *temp;
393   Bit8u count = 0;
394 
395   if (plugins != NULL) {
396     temp = plugins;
397 
398     while (temp != NULL) {
399       if ((type & temp->type) != 0)
400         count++;
401       temp = temp->next;
402     }
403   }
404   return count;
405 }
406 
bx_get_plugin_name(Bit16u type,Bit8u index)407 const char* bx_get_plugin_name(Bit16u type, Bit8u index)
408 {
409   plugin_t *temp;
410   int count = 0;
411 
412   if (plugins != NULL) {
413     temp = plugins;
414 
415     while (temp != NULL) {
416       if ((type & temp->type) != 0) {
417         if (count == index)
418           return temp->name;
419         count++;
420       }
421       temp = temp->next;
422     }
423   }
424   return NULL;
425 }
426 
bx_get_plugin_flags(Bit16u type,Bit8u index)427 Bit8u bx_get_plugin_flags(Bit16u type, Bit8u index)
428 {
429   plugin_t *temp;
430   int count = 0;
431 
432   if (plugins != NULL) {
433     temp = plugins;
434 
435     while (temp != NULL) {
436       if ((type & temp->type) != 0) {
437         if (count == index)
438           return temp->flags;
439         count++;
440       }
441       temp = temp->next;
442     }
443   }
444   return 0;
445 }
446 
447 /************************************************************************/
448 /* Plugin initialization / deinitialization                             */
449 /************************************************************************/
450 
plugin_init_one(plugin_t * plugin)451 bool plugin_init_one(plugin_t *plugin)
452 {
453   /* initialize the plugin */
454   if (plugin->plugin_entry(plugin, plugin->loadtype, PLUGIN_INIT))
455   {
456     pluginlog->info("Plugin initialization failed for %s", plugin->name);
457     plugin_abort(plugin);
458     return 0;
459   }
460   plugin->initialized = 1;
461   return 1;
462 }
463 
464 
plugin_unload(plugin_t * plugin)465 bool plugin_unload(plugin_t *plugin)
466 {
467   if (plugin->loadtype != PLUGTYPE_NULL) {
468     if (plugin->initialized)
469       plugin->plugin_entry(plugin, plugin->type, PLUGIN_FINI);
470 #if defined(WIN32)
471     FreeLibrary(plugin->handle);
472 #else
473     lt_dlclose(plugin->handle);
474 #endif
475     plugin->loadtype = PLUGTYPE_NULL;
476     return 1;
477   } else {
478     return 0;
479   }
480 }
481 
plugin_load(const char * name,Bit16u type)482 bool plugin_load(const char *name, Bit16u type)
483 {
484   plugin_t *plugin = NULL, *temp;
485 #if defined(WIN32)
486   char dll_path_list[MAX_PATH];
487 #endif
488 
489   if (plugins != NULL) {
490     temp = plugins;
491 
492     while (temp != NULL) {
493       if (!strcmp(name, temp->name) && ((type & temp->type) != 0)) {
494         if (temp->loadtype != PLUGTYPE_NULL) {
495           BX_PANIC(("plugin '%s' already loaded", name));
496           return 0;
497         } else {
498           plugin = temp;
499           break;
500         }
501       }
502       temp = temp->next;
503     }
504   }
505   if (plugin == NULL) {
506     BX_PANIC(("plugin '%s' not found", name));
507     return 0;
508   }
509 
510   char plugin_filename[BX_PATHNAME_LEN], tmpname[BX_PATHNAME_LEN];
511   if (type == PLUGTYPE_GUI) {
512     sprintf(tmpname, GUI_PLUGIN_FILENAME_FORMAT, name);
513   } else if (type == PLUGTYPE_IMG) {
514     sprintf(tmpname, IMG_PLUGIN_FILENAME_FORMAT, name);
515   } else if (type == PLUGTYPE_NET) {
516     sprintf(tmpname, NET_PLUGIN_FILENAME_FORMAT, name);
517   } else if (type == PLUGTYPE_SND) {
518     sprintf(tmpname, SND_PLUGIN_FILENAME_FORMAT, name);
519   } else {
520     sprintf(tmpname, PLUGIN_FILENAME_FORMAT, name);
521   }
522   sprintf(plugin_filename, "%s%s", PLUGIN_PATH, tmpname);
523 
524   // Set context so that any devices that the plugin registers will
525   // be able to see which plugin created them.  The registration will
526   // be called from either dlopen (global constructors) or plugin_entry.
527   BX_ASSERT(current_plugin_context == NULL);
528   current_plugin_context = plugin;
529 #if defined(WIN32)
530   char *ptr;
531   plugin->handle = LoadLibrary(plugin_filename);
532   if (!plugin->handle) {
533     if (GetEnvironmentVariable("LTDL_LIBRARY_PATH", dll_path_list, MAX_PATH)) {
534       ptr = strtok(dll_path_list, ";");
535       while ((ptr) && !plugin->handle) {
536         sprintf(plugin_filename, "%s\\%s", ptr, tmpname);
537         plugin->handle = LoadLibrary(plugin_filename);
538         ptr = strtok(NULL, ";");
539       }
540     }
541   }
542   BX_INFO(("DLL handle is %p", plugin->handle));
543   if (!plugin->handle) {
544     current_plugin_context = NULL;
545     BX_PANIC(("LoadLibrary failed for module '%s' (%s): error=%d", name,
546               plugin_filename, GetLastError()));
547     return 0;
548   }
549 #else
550   plugin->handle = lt_dlopen(plugin_filename);
551   BX_INFO(("lt_dlhandle is %p", plugin->handle));
552   if (!plugin->handle) {
553     current_plugin_context = NULL;
554     BX_PANIC(("dlopen failed for module '%s' (%s): %s", name, plugin_filename,
555               lt_dlerror()));
556     return 0;
557   }
558 #endif
559   plugin->loadtype = type;
560 
561   if (type == PLUGTYPE_GUI) {
562     sprintf(tmpname, GUI_PLUGIN_ENTRY_FMT_STRING, name);
563   } else if (type == PLUGTYPE_IMG) {
564     sprintf(tmpname, IMG_PLUGIN_ENTRY_FMT_STRING, name);
565   } else if (type == PLUGTYPE_NET) {
566     sprintf(tmpname, NET_PLUGIN_ENTRY_FMT_STRING, name);
567   } else if (type == PLUGTYPE_SND) {
568     sprintf(tmpname, SND_PLUGIN_ENTRY_FMT_STRING, name);
569   } else {
570     sprintf(tmpname, PLUGIN_ENTRY_FMT_STRING, name);
571   }
572 #if defined(WIN32)
573   plugin->plugin_entry = (plugin_entry_t) GetProcAddress(plugin->handle, tmpname);
574   if (plugin->plugin_entry == NULL) {
575     pluginlog->panic("could not find plugin_entry for module '%s' (%s): error=%d",
576                      name, plugin_filename, GetLastError());
577     plugin_abort(plugin);
578     return 0;
579   }
580 #else
581   plugin->plugin_entry = (plugin_entry_t) lt_dlsym(plugin->handle, tmpname);
582   if (plugin->plugin_entry == NULL) {
583     pluginlog->panic("could not find plugin_entry for module '%s' (%s): %s",
584                      name, plugin_filename, lt_dlerror());
585     plugin_abort(plugin);
586     return 0;
587   }
588 #endif
589   pluginlog->info("loaded plugin %s",plugin_filename);
590 
591   if (!plugin_init_one(plugin)) {
592     return 0;
593   }
594 
595   // check that context didn't change.  This should only happen if we
596   // need a reentrant plugin_load.
597   BX_ASSERT(current_plugin_context == plugin);
598   current_plugin_context = NULL;
599   return 1;
600 }
601 
plugin_abort(plugin_t * plugin)602 void plugin_abort(plugin_t *plugin)
603 {
604   plugin_unload(plugin);
605   pluginlog->panic("loading plugin '%s' aborted", plugin->name);
606 }
607 
608 #endif   /* end of #if BX_PLUGINS */
609 
610 /************************************************************************/
611 /* Plugin system: initialisation of plugins entry points                */
612 /************************************************************************/
613 
plugin_startup(void)614 void plugin_startup(void)
615 {
616   pluginRegisterIRQ = builtinRegisterIRQ;
617   pluginUnregisterIRQ = builtinUnregisterIRQ;
618 
619   pluginSetHRQHackCallback = builtinSetHRQHackCallback;
620   pluginSetHRQ = builtinSetHRQ;
621 
622   pluginRegisterIOReadHandler = builtinRegisterIOReadHandler;
623   pluginRegisterIOWriteHandler = builtinRegisterIOWriteHandler;
624 
625   pluginUnregisterIOReadHandler = builtinUnregisterIOReadHandler;
626   pluginUnregisterIOWriteHandler = builtinUnregisterIOWriteHandler;
627 
628   pluginRegisterIOReadHandlerRange = builtinRegisterIOReadHandlerRange;
629   pluginRegisterIOWriteHandlerRange = builtinRegisterIOWriteHandlerRange;
630 
631   pluginUnregisterIOReadHandlerRange = builtinUnregisterIOReadHandlerRange;
632   pluginUnregisterIOWriteHandlerRange = builtinUnregisterIOWriteHandlerRange;
633 
634   pluginRegisterDefaultIOReadHandler = builtinRegisterDefaultIOReadHandler;
635   pluginRegisterDefaultIOWriteHandler = builtinRegisterDefaultIOWriteHandler;
636 
637   pluginlog = new logfunctions();
638   pluginlog->put("PLUGIN");
639 #if BX_PLUGINS
640 #if !defined(WIN32)
641   int status = lt_dlinit();
642   if (status != 0) {
643     BX_ERROR(("initialization error in ltdl library (for loading plugins)"));
644     BX_PANIC(("error message was: %s", lt_dlerror()));
645   }
646 #endif
647   plugins_search();
648 #endif
649 }
650 
plugin_cleanup(void)651 void plugin_cleanup(void)
652 {
653 #if BX_PLUGINS
654   plugin_t *dead_plug;
655 
656   while (plugins != NULL) {
657     if (plugins->loadtype != PLUGTYPE_NULL) {
658       plugin_unload(plugins);
659     }
660     delete [] plugins->name;
661 
662     dead_plug = plugins;
663     plugins = plugins->next;
664     delete dead_plug;
665   }
666 #endif
667 }
668 
669 
670 /************************************************************************/
671 /* Plugin system: Device registration                                   */
672 /************************************************************************/
673 
pluginRegisterDeviceDevmodel(plugin_t * plugin,Bit16u type,bx_devmodel_c * devmodel,const char * name)674 void pluginRegisterDeviceDevmodel(plugin_t *plugin, Bit16u type, bx_devmodel_c *devmodel, const char *name)
675 {
676   device_t **devlist;
677 
678   device_t *device = new device_t;
679 
680   device->name = name;
681   BX_ASSERT(devmodel != NULL);
682   device->devmodel = devmodel;
683   device->plugin = plugin;  // this can be NULL
684   device->next = NULL;
685   device->plugtype = type;
686 
687   switch (type) {
688     case PLUGTYPE_CORE:
689     case PLUGTYPE_VGA:
690       devlist = &core_devices;
691       break;
692     case PLUGTYPE_STANDARD:
693     case PLUGTYPE_OPTIONAL:
694     default:
695       devlist = &devices;
696       break;
697   }
698 
699   if (!*devlist) {
700     /* Empty list, this become the first entry. */
701     *devlist = device;
702   } else {
703     /* Non-empty list.  Add to end. */
704     device_t *temp = *devlist;
705 
706     while (temp->next)
707       temp = temp->next;
708 
709     temp->next = device;
710   }
711 }
712 
713 /************************************************************************/
714 /* Plugin system: Remove registered plugin device                       */
715 /************************************************************************/
716 
pluginUnregisterDeviceDevmodel(const char * name,Bit16u type)717 void pluginUnregisterDeviceDevmodel(const char *name, Bit16u type)
718 {
719   device_t **devlist;
720   device_t *device, *prev = NULL;
721 
722   switch (type) {
723     case PLUGTYPE_CORE:
724     case PLUGTYPE_VGA:
725       devlist = &core_devices;
726       break;
727     case PLUGTYPE_STANDARD:
728     case PLUGTYPE_OPTIONAL:
729     default:
730       devlist = &devices;
731       break;
732   }
733 
734   for (device = *devlist; device; device = device->next) {
735     if (!strcmp(name, device->name)) {
736       if (prev == NULL) {
737         *devlist = device->next;
738       } else {
739         prev->next = device->next;
740       }
741       delete device;
742       break;
743     } else {
744       prev = device;
745     }
746   }
747 }
748 
749 /************************************************************************/
750 /* Plugin system: Check if a plugin is loaded                           */
751 /************************************************************************/
752 
pluginDevicePresent(const char * name)753 bool pluginDevicePresent(const char *name)
754 {
755   device_t *device;
756 
757   for (device = devices; device; device = device->next)
758   {
759     if (!strcmp(name, device->name)) return 1;
760   }
761 
762   return 0;
763 }
764 
765 #if BX_PLUGINS
766 /************************************************************************/
767 /* Plugin system: Load one plugin                                       */
768 /************************************************************************/
769 
bx_load_plugin(const char * name,Bit16u type)770 bool bx_load_plugin(const char *name, Bit16u type)
771 {
772   plugin_t *plugin;
773 
774   if (!strcmp(name, "*")) {
775     for (plugin = plugins; plugin; plugin = plugin->next) {
776       if (((type & plugin->type) != 0) && (plugin->loadtype == PLUGTYPE_NULL)) {
777         plugin_load(plugin->name, type);
778       }
779     }
780     return 1;
781   } else {
782     return plugin_load(name, type);
783   }
784 }
785 
bx_unload_plugin(const char * name,bool devflag)786 bool bx_unload_plugin(const char *name, bool devflag)
787 {
788   plugin_t *plugin;
789   bool ret = 0;
790 
791   for (plugin = plugins; plugin; plugin = plugin->next) {
792     if (!strcmp(plugin->name, name)) {
793       if (devflag) {
794         pluginUnregisterDeviceDevmodel(plugin->name, plugin->type);
795       }
796       ret = plugin_unload(plugin);
797       break;
798     }
799   }
800   return ret;
801 }
802 
bx_unload_plugin_type(const char * name,Bit16u type)803 void bx_unload_plugin_type(const char *name, Bit16u type)
804 {
805   plugin_t *plugin;
806 
807   for (plugin = plugins; plugin; plugin = plugin->next) {
808     if (!strcmp(plugin->name, name) && ((plugin->type & type) != 0)) {
809       plugin_unload(plugin);
810       break;
811     }
812   }
813 }
814 
815 #endif   /* end of #if BX_PLUGINS */
816 
817 /*************************************************************************/
818 /* Plugin system: Execute init function of all registered plugin-devices */
819 /*************************************************************************/
820 
bx_init_plugins()821 void bx_init_plugins()
822 {
823   device_t *device;
824 
825   for (device = core_devices; device; device = device->next) {
826     pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name);
827     device->devmodel->init();
828   }
829   for (device = devices; device; device = device->next) {
830     if (device->plugtype == PLUGTYPE_STANDARD) {
831       pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name);
832       device->devmodel->init();
833     }
834   }
835   for (device = devices; device; device = device->next) {
836     if (device->plugtype == PLUGTYPE_OPTIONAL) {
837       pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name);
838       device->devmodel->init();
839     }
840   }
841 }
842 
843 /**************************************************************************/
844 /* Plugin system: Execute reset function of all registered plugin-devices */
845 /**************************************************************************/
846 
bx_reset_plugins(unsigned signal)847 void bx_reset_plugins(unsigned signal)
848 {
849   device_t *device;
850 
851   for (device = core_devices; device; device = device->next) {
852     pluginlog->info("reset of '%s' plugin device by virtual method",device->name);
853     device->devmodel->reset(signal);
854   }
855   for (device = devices; device; device = device->next) {
856     if (device->plugtype == PLUGTYPE_STANDARD) {
857       pluginlog->info("reset of '%s' plugin device by virtual method",device->name);
858       device->devmodel->reset(signal);
859     }
860   }
861   for (device = devices; device; device = device->next) {
862     if (device->plugtype == PLUGTYPE_OPTIONAL) {
863       pluginlog->info("reset of '%s' plugin device by virtual method",device->name);
864       device->devmodel->reset(signal);
865     }
866   }
867 }
868 
869 /*******************************************************/
870 /* Plugin system: Unload all registered plugin-devices */
871 /*******************************************************/
872 
bx_unload_plugins()873 void bx_unload_plugins()
874 {
875   device_t *device, *next;
876 
877   // unload non-core plugins first
878   device = devices;
879   while (device != NULL) {
880     if (device->plugin != NULL) {
881 #if BX_PLUGINS
882       bx_unload_plugin(device->name, 0);
883 #endif
884     } else {
885 #if !BX_PLUGINS
886       if (!bx_unload_opt_plugin(device->name, 0)) {
887         delete device->devmodel;
888       }
889 #endif
890     }
891     next = device->next;
892     delete device;
893     device = next;
894   }
895   devices = NULL;
896 
897   // now it's safe to unload core plugins
898   device = core_devices;
899   while (device != NULL) {
900     if (device->plugin != NULL) {
901 #if BX_PLUGINS
902       bx_unload_plugin(device->name, 0);
903 #endif
904     } else {
905       delete device->devmodel;
906     }
907     next = device->next;
908     delete device;
909     device = next;
910   }
911   core_devices = NULL;
912 }
913 
914 /**************************************************************************/
915 /* Plugin system: Register device state of all registered plugin-devices  */
916 /**************************************************************************/
917 
bx_plugins_register_state()918 void bx_plugins_register_state()
919 {
920   device_t *device;
921 
922   for (device = core_devices; device; device = device->next) {
923     pluginlog->info("register state of '%s' plugin device by virtual method",device->name);
924     device->devmodel->register_state();
925   }
926   for (device = devices; device; device = device->next) {
927     pluginlog->info("register state of '%s' plugin device by virtual method",device->name);
928     device->devmodel->register_state();
929   }
930 }
931 
932 /***************************************************************************/
933 /* Plugin system: Execute code after restoring state of all plugin devices */
934 /***************************************************************************/
935 
bx_plugins_after_restore_state()936 void bx_plugins_after_restore_state()
937 {
938   device_t *device;
939 
940   for (device = core_devices; device; device = device->next) {
941     device->devmodel->after_restore_state();
942   }
943   for (device = devices; device; device = device->next) {
944     if (device->plugtype == PLUGTYPE_STANDARD) {
945       device->devmodel->after_restore_state();
946     }
947   }
948   for (device = devices; device; device = device->next) {
949     if (device->plugtype == PLUGTYPE_OPTIONAL) {
950       device->devmodel->after_restore_state();
951     }
952   }
953 }
954 
955 #if !BX_PLUGINS
956 
957 // Special code for handling modules when plugin support is turned off.
958 
959 #define BUILTIN_OPT_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_OPTIONAL, 0, lib##mod##_plugin_entry, 0}
960 #define BUILTIN_OPTPCI_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_OPTIONAL, PLUGFLAG_PCI, lib##mod##_plugin_entry, 0}
961 #define BUILTIN_VGA_PLUGIN_ENTRY(mod, t, f) {#mod, PLUGTYPE_VGA | t, f, lib##mod##_plugin_entry, 0}
962 #define BUILTIN_CI_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_CI, 0, lib##mod##_plugin_entry, 0}
963 #define BUILTIN_GUI_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_GUI, 0, lib##mod##_gui_plugin_entry, 0}
964 #define BUILTIN_GUICI_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_GUI | PLUGTYPE_CI, 0, lib##mod##_gui_plugin_entry, 0}
965 #define BUILTIN_IMG_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_IMG, 0, lib##mod##_img_plugin_entry, 0}
966 #define BUILTIN_NET_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_NET, 0, libeth_##mod##_plugin_entry, 0}
967 #define BUILTIN_SND_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_SND, 0, libsound##mod##_plugin_entry, 0}
968 #define BUILTIN_USB_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_USB, 0, lib##mod##_plugin_entry, 0}
969 
970 plugin_t bx_builtin_plugins[] = {
971 #if BX_USE_TEXTCONFIG
972   BUILTIN_CI_PLUGIN_ENTRY(textconfig),
973 #endif
974 #if BX_USE_WIN32CONFIG
975   BUILTIN_CI_PLUGIN_ENTRY(win32config),
976 #endif
977 #if BX_WITH_AMIGAOS
978   BUILTIN_GUI_PLUGIN_ENTRY(amigaos),
979 #endif
980 #if BX_WITH_CARBON
981   BUILTIN_GUI_PLUGIN_ENTRY(carbon),
982 #endif
983 #if BX_WITH_MACOS
984   BUILTIN_GUI_PLUGIN_ENTRY(macos),
985 #endif
986 #if BX_WITH_NOGUI
987   BUILTIN_GUI_PLUGIN_ENTRY(nogui),
988 #endif
989 #if BX_WITH_RFB
990   BUILTIN_GUI_PLUGIN_ENTRY(rfb),
991 #endif
992 #if BX_WITH_SDL
993   BUILTIN_GUI_PLUGIN_ENTRY(sdl),
994 #endif
995 #if BX_WITH_SDL2
996   BUILTIN_GUI_PLUGIN_ENTRY(sdl2),
997 #endif
998 #if BX_WITH_TERM
999   BUILTIN_GUI_PLUGIN_ENTRY(term),
1000 #endif
1001 #if BX_WITH_VNCSRV
1002   BUILTIN_GUI_PLUGIN_ENTRY(vncsrv),
1003 #endif
1004 #if BX_WITH_WIN32
1005   BUILTIN_GUI_PLUGIN_ENTRY(win32),
1006 #endif
1007 #if BX_WITH_WX
1008   BUILTIN_GUICI_PLUGIN_ENTRY(wx),
1009 #endif
1010 #if BX_WITH_X11
1011   BUILTIN_GUI_PLUGIN_ENTRY(x),
1012 #endif
1013   BUILTIN_VGA_PLUGIN_ENTRY(vga, 0, PLUGFLAG_PCI),
1014 #if BX_SUPPORT_CLGD54XX
1015   BUILTIN_VGA_PLUGIN_ENTRY(svga_cirrus, 0, PLUGFLAG_PCI),
1016 #endif
1017 #if BX_SUPPORT_VOODOO
1018   BUILTIN_VGA_PLUGIN_ENTRY(voodoo, PLUGTYPE_OPTIONAL, PLUGFLAG_PCI),
1019 #endif
1020   BUILTIN_OPT_PLUGIN_ENTRY(unmapped),
1021   BUILTIN_OPT_PLUGIN_ENTRY(biosdev),
1022   BUILTIN_OPT_PLUGIN_ENTRY(speaker),
1023   BUILTIN_OPT_PLUGIN_ENTRY(extfpuirq),
1024   BUILTIN_OPT_PLUGIN_ENTRY(parallel),
1025   BUILTIN_OPT_PLUGIN_ENTRY(serial),
1026 #if BX_SUPPORT_BUSMOUSE
1027   BUILTIN_OPT_PLUGIN_ENTRY(busmouse),
1028 #endif
1029 #if BX_SUPPORT_E1000
1030   BUILTIN_OPTPCI_PLUGIN_ENTRY(e1000),
1031 #endif
1032 #if BX_SUPPORT_ES1370
1033   BUILTIN_OPTPCI_PLUGIN_ENTRY(es1370),
1034 #endif
1035 #if BX_SUPPORT_GAMEPORT
1036   BUILTIN_OPT_PLUGIN_ENTRY(gameport),
1037 #endif
1038 #if BX_SUPPORT_IODEBUG
1039   BUILTIN_OPT_PLUGIN_ENTRY(iodebug),
1040 #endif
1041 #if BX_SUPPORT_NE2K
1042   BUILTIN_OPTPCI_PLUGIN_ENTRY(ne2k),
1043 #endif
1044 #if BX_SUPPORT_PCIDEV
1045   BUILTIN_OPTPCI_PLUGIN_ENTRY(pcidev),
1046 #endif
1047 #if BX_SUPPORT_PCIPNIC
1048   BUILTIN_OPTPCI_PLUGIN_ENTRY(pcipnic),
1049 #endif
1050 #if BX_SUPPORT_SB16
1051   BUILTIN_OPT_PLUGIN_ENTRY(sb16),
1052 #endif
1053 #if BX_SUPPORT_USB_UHCI
1054   BUILTIN_OPTPCI_PLUGIN_ENTRY(usb_uhci),
1055 #endif
1056 #if BX_SUPPORT_USB_OHCI
1057   BUILTIN_OPTPCI_PLUGIN_ENTRY(usb_ohci),
1058 #endif
1059 #if BX_SUPPORT_USB_EHCI
1060   BUILTIN_OPTPCI_PLUGIN_ENTRY(usb_ehci),
1061 #endif
1062 #if BX_SUPPORT_USB_XHCI
1063   BUILTIN_OPTPCI_PLUGIN_ENTRY(usb_xhci),
1064 #endif
1065 #if BX_SUPPORT_SOUNDLOW
1066   BUILTIN_SND_PLUGIN_ENTRY(dummy),
1067   BUILTIN_SND_PLUGIN_ENTRY(file),
1068 #if BX_HAVE_SOUND_ALSA
1069   BUILTIN_SND_PLUGIN_ENTRY(alsa),
1070 #endif
1071 #if BX_HAVE_SOUND_OSS
1072   BUILTIN_SND_PLUGIN_ENTRY(oss),
1073 #endif
1074 #if BX_HAVE_SOUND_OSX
1075   BUILTIN_SND_PLUGIN_ENTRY(osx),
1076 #endif
1077 #if BX_HAVE_SOUND_SDL
1078   BUILTIN_SND_PLUGIN_ENTRY(sdl),
1079 #endif
1080 #if BX_HAVE_SOUND_WIN
1081   BUILTIN_SND_PLUGIN_ENTRY(win),
1082 #endif
1083 #endif
1084 #if BX_NETWORKING
1085   BUILTIN_NET_PLUGIN_ENTRY(null),
1086   BUILTIN_NET_PLUGIN_ENTRY(vnet),
1087 #if BX_NETMOD_FBSD
1088   BUILTIN_NET_PLUGIN_ENTRY(fbsd),
1089 #endif
1090 #if BX_NETMOD_LINUX
1091   BUILTIN_NET_PLUGIN_ENTRY(linux),
1092 #endif
1093 #if BX_NETMOD_SLIRP
1094   BUILTIN_NET_PLUGIN_ENTRY(slirp),
1095 #endif
1096 #if BX_NETMOD_SOCKET
1097   BUILTIN_NET_PLUGIN_ENTRY(socket),
1098 #endif
1099 #if BX_NETMOD_TAP
1100   BUILTIN_NET_PLUGIN_ENTRY(tap),
1101 #endif
1102 #if BX_NETMOD_TUNTAP
1103   BUILTIN_NET_PLUGIN_ENTRY(tuntap),
1104 #endif
1105 #if BX_NETMOD_VDE
1106   BUILTIN_NET_PLUGIN_ENTRY(vde),
1107 #endif
1108 #if BX_NETMOD_WIN32
1109   BUILTIN_NET_PLUGIN_ENTRY(win32),
1110 #endif
1111 #endif
1112 #if BX_SUPPORT_PCIUSB
1113   BUILTIN_USB_PLUGIN_ENTRY(usb_floppy),
1114   BUILTIN_USB_PLUGIN_ENTRY(usb_hid),
1115   BUILTIN_USB_PLUGIN_ENTRY(usb_hub),
1116   BUILTIN_USB_PLUGIN_ENTRY(usb_msd),
1117   BUILTIN_USB_PLUGIN_ENTRY(usb_printer),
1118 #endif
1119   BUILTIN_IMG_PLUGIN_ENTRY(vmware3),
1120   BUILTIN_IMG_PLUGIN_ENTRY(vmware4),
1121   BUILTIN_IMG_PLUGIN_ENTRY(vbox),
1122   BUILTIN_IMG_PLUGIN_ENTRY(vpc),
1123   BUILTIN_IMG_PLUGIN_ENTRY(vvfat),
1124   {"NULL", PLUGTYPE_NULL, 0, NULL, 0}
1125 };
1126 
bx_get_plugins_count_np(Bit16u type)1127 Bit8u bx_get_plugins_count_np(Bit16u type)
1128 {
1129   int i = 0;
1130   Bit8u count = 0;
1131 
1132   while (strcmp(bx_builtin_plugins[i].name, "NULL")) {
1133     if ((type & bx_builtin_plugins[i].type) != 0)
1134       count++;
1135     i++;
1136   }
1137   return count;
1138 }
1139 
bx_get_plugin_name_np(Bit16u type,Bit8u index)1140 const char* bx_get_plugin_name_np(Bit16u type, Bit8u index)
1141 {
1142   int i = 0;
1143   Bit8u count = 0;
1144 
1145   while (strcmp(bx_builtin_plugins[i].name, "NULL")) {
1146     if ((type & bx_builtin_plugins[i].type) != 0) {
1147       if (count == index)
1148         return bx_builtin_plugins[i].name;
1149       count++;
1150     }
1151     i++;
1152   }
1153   return NULL;
1154 }
1155 
bx_get_plugin_flags_np(Bit16u type,Bit8u index)1156 Bit8u bx_get_plugin_flags_np(Bit16u type, Bit8u index)
1157 {
1158   int i = 0;
1159   Bit8u count = 0;
1160 
1161   while (strcmp(bx_builtin_plugins[i].name, "NULL")) {
1162     if ((type & bx_builtin_plugins[i].type) != 0) {
1163       if (count == index)
1164         return bx_builtin_plugins[i].flags;
1165       count++;
1166     }
1167     i++;
1168   }
1169   return 0;
1170 }
1171 
bx_load_plugin_np(const char * name,Bit16u type)1172 int bx_load_plugin_np(const char *name, Bit16u type)
1173 {
1174   int i = 0;
1175   while (strcmp(bx_builtin_plugins[i].name, "NULL")) {
1176     if ((!strcmp(name, bx_builtin_plugins[i].name)) &&
1177         ((type & bx_builtin_plugins[i].type) != 0)) {
1178       if (bx_builtin_plugins[i].initialized == 0) {
1179         bx_builtin_plugins[i].loadtype = type;
1180         bx_builtin_plugins[i].plugin_entry(NULL, type, PLUGIN_INIT);
1181         bx_builtin_plugins[i].initialized = 1;
1182       }
1183       return 1;
1184     }
1185     i++;
1186   }
1187   return 0;
1188 }
1189 
bx_unload_opt_plugin(const char * name,bool devflag)1190 int bx_unload_opt_plugin(const char *name, bool devflag)
1191 {
1192   int i = 0;
1193   while (strcmp(bx_builtin_plugins[i].name, "NULL")) {
1194     if ((!strcmp(name, bx_builtin_plugins[i].name)) &&
1195         ((bx_builtin_plugins[i].type == PLUGTYPE_OPTIONAL) ||
1196          (bx_builtin_plugins[i].type == PLUGTYPE_VGA))) {
1197       if (bx_builtin_plugins[i].initialized == 1) {
1198         if (devflag) {
1199           pluginUnregisterDeviceDevmodel(bx_builtin_plugins[i].name,
1200                                          bx_builtin_plugins[i].type);
1201         }
1202         bx_builtin_plugins[i].plugin_entry(NULL, bx_builtin_plugins[i].loadtype, PLUGIN_FINI);
1203         bx_builtin_plugins[i].loadtype = PLUGTYPE_NULL;
1204         bx_builtin_plugins[i].initialized = 0;
1205       }
1206       return 1;
1207     }
1208     i++;
1209   }
1210   return 0;
1211 }
1212 
1213 #endif
1214 
1215 }
1216