327 lines
11 KiB
Plaintext
327 lines
11 KiB
Plaintext
----------------------------------------------------------------------
|
|
Patch name: patch.example-user-plugin
|
|
Author: Volker Ruppert
|
|
Updated: 7 Feb 2021
|
|
Status: Demo
|
|
|
|
Detailed description:
|
|
This sample code can be used as a framework for writing own optional
|
|
device plugins (AKA "user plugins). It contains enough code for testing
|
|
the existing plugin device support in Bochs and creates a device that
|
|
installs a 32-bit r/w register at i/o address 0x1000.
|
|
This example also shows how to install and handle user-defined config
|
|
options for bochsrc, command line and the config interface. In this
|
|
demo it is used to specify the reset value.
|
|
For user plugin support Bochs must be configured with plugins enabled.
|
|
Compiling with plugin support is known to work on Linux and Windows
|
|
(Cygwin, MinGW/MSYS and MSVC nmake / gui). This sample plugin can be
|
|
loaded in bochsrc either with "plugin_ctrl" or with it's own name:
|
|
|
|
plugin_ctrl: testdev=1
|
|
|
|
testdev: testval=1
|
|
|
|
Patch was created with:
|
|
diff -u
|
|
Apply patch to what version:
|
|
svn revision 14132 (Feb 7, 2021)
|
|
Instructions:
|
|
To patch, go to main bochs directory.
|
|
Type "patch -p0 < THIS_PATCH_FILE".
|
|
Configure and compile Bochs as usual
|
|
cd user-plugins
|
|
make
|
|
make install
|
|
----------------------------------------------------------------------
|
|
diff -urN ../bochs/user_plugins/Makefile.in ./user_plugins/Makefile.in
|
|
--- ../bochs/user_plugins/Makefile.in 1970-01-01 01:00:00.000000000 +0100
|
|
+++ ./user_plugins/Makefile.in 2021-02-07 19:08:10.591961411 +0100
|
|
@@ -0,0 +1,112 @@
|
|
+# Copyright (C) 2009-2021 Volker Ruppert
|
|
+#
|
|
+# This library is free software; you can redistribute it and/or
|
|
+# modify it under the terms of the GNU Lesser General Public
|
|
+# License as published by the Free Software Foundation; either
|
|
+# version 2 of the License, or (at your option) any later version.
|
|
+#
|
|
+# This library is distributed in the hope that it will be useful,
|
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+# Lesser General Public License for more details.
|
|
+#
|
|
+# You should have received a copy of the GNU Lesser General Public
|
|
+# License along with this library; if not, write to the Free Software
|
|
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+
|
|
+# Makefile for the user plugin example of bochs
|
|
+
|
|
+
|
|
+@SUFFIX_LINE@
|
|
+
|
|
+prefix = @prefix@
|
|
+exec_prefix = @exec_prefix@
|
|
+srcdir = @srcdir@
|
|
+VPATH = @srcdir@
|
|
+bindir = @bindir@
|
|
+libdir = @libdir@
|
|
+plugdir = @libdir@/bochs/plugins
|
|
+datarootdir = @datarootdir@
|
|
+mandir = @mandir@
|
|
+man1dir = $(mandir)/man1
|
|
+man5dir = $(mandir)/man5
|
|
+docdir = $(datarootdir)/doc/bochs
|
|
+sharedir = $(datarootdir)/bochs
|
|
+top_builddir = ..
|
|
+top_srcdir = @top_srcdir@
|
|
+
|
|
+SHELL = @SHELL@
|
|
+
|
|
+@SET_MAKE@
|
|
+
|
|
+CXX = @CXX@
|
|
+CXXFLAGS = $(BX_INCDIRS) @CXXFLAGS@ @GUI_CXXFLAGS@
|
|
+
|
|
+LDFLAGS = @LDFLAGS@
|
|
+LIBS = @LIBS@
|
|
+RANLIB = @RANLIB@
|
|
+PLUGIN_PATH=@libdir@
|
|
+top_builddir = ..
|
|
+LIBTOOL=@LIBTOOL@
|
|
+WIN32_DLL_IMPORT_LIBRARY=../@WIN32_DLL_IMPORT_LIB@
|
|
+
|
|
+BX_INCDIRS = -I.. -I$(srcdir)/.. -I../iodev -I$(srcdir)/../iodev -I../@INSTRUMENT_DIR@ -I$(srcdir)/../@INSTRUMENT_DIR@
|
|
+
|
|
+PLUGIN_OBJS = testdev.o
|
|
+
|
|
+plugins: @PLUGIN_TARGET_2@
|
|
+
|
|
+plugins_gcc: $(PLUGIN_OBJS:@PLUGIN_LIBNAME_TRANSFORMATION@)
|
|
+
|
|
+plugins_msvc: bx_testdev.dll
|
|
+
|
|
+install: @INSTALL_PLUGINS_VAR@
|
|
+
|
|
+install_libtool_plugins::
|
|
+ list=`echo *.la`; for i in $$list; do $(LIBTOOL) --mode=install install $$i $(DESTDIR)$(plugdir); done
|
|
+ $(LIBTOOL) --finish $(DESTDIR)$(plugdir)
|
|
+
|
|
+install_dll_plugins::
|
|
+ list=`echo *.dll`; for i in $$list; do cp $$i $(DESTDIR)$(plugdir); done
|
|
+
|
|
+# standard compile rule for C++ files
|
|
+.@CPP_SUFFIX@.o:
|
|
+ $(CXX) @DASH@c $(CXXFLAGS) $(LOCAL_CXXFLAGS) @CXXFP@$< @OFP@$@
|
|
+
|
|
+##### building plugins with libtool
|
|
+%.lo: %.@CPP_SUFFIX@
|
|
+ $(LIBTOOL) --mode=compile $(CXX) -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $< -o $@
|
|
+
|
|
+libbx_%.la: %.lo
|
|
+ $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH)
|
|
+
|
|
+# special link rules for plugins with Cygwin, MinGW/MSYS and MSVC nmake
|
|
+bx_testdev.dll: testdev.o
|
|
+ @LINK_DLL@ testdev.o $(WIN32_DLL_IMPORT_LIBRARY)
|
|
+
|
|
+clean:
|
|
+ @RMCOMMAND@ -rf .libs *.lo *.o *.la *.a *.dll *.exp *.lib *.dll.manifest
|
|
+
|
|
+dist-clean: clean
|
|
+ @RMCOMMAND@ Makefile
|
|
+
|
|
+###########################################
|
|
+# dependencies generated by
|
|
+# gcc -MM -I.. -I../instrument/stubs *.cc | sed -e 's/\.cc/.@CPP_SUFFIX@/g'
|
|
+# gcc -MM -I.. -I../instrument/stubs *.cc | \
|
|
+# sed -e 's/\.cc/.@CPP_SUFFIX@/g' -e 's/\.o:/.lo:/g'
|
|
+#
|
|
+# This means that every source file is listed twice, once with a .o rule
|
|
+# and then again with an identical .lo rule. The .lo rules are used when
|
|
+# building plugins.
|
|
+###########################################
|
|
+testdev.o: testdev.@CPP_SUFFIX@ ../iodev/iodev.h ../bochs.h ../config.h ../osdep.h \
|
|
+ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \
|
|
+ ../cpudb.h ../gui/paramtree.h ../memory/memory-bochs.h ../pc_system.h \
|
|
+ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \
|
|
+ ../param_names.h testdev.h
|
|
+testdev.lo: testdev.@CPP_SUFFIX@ ../iodev/iodev.h ../bochs.h ../config.h ../osdep.h \
|
|
+ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \
|
|
+ ../cpudb.h ../gui/paramtree.h ../memory/memory-bochs.h ../pc_system.h \
|
|
+ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \
|
|
+ ../param_names.h testdev.h
|
|
diff -urN ../bochs/user_plugins/testdev.cc ./user_plugins/testdev.cc
|
|
--- ../bochs/user_plugins/testdev.cc 1970-01-01 01:00:00.000000000 +0100
|
|
+++ ./user_plugins/testdev.cc 2021-02-07 19:26:36.000020446 +0100
|
|
@@ -0,0 +1,127 @@
|
|
+// Copyright (C) 2009-2021 Volker Ruppert
|
|
+//
|
|
+// This library is free software; you can redistribute it and/or
|
|
+// modify it under the terms of the GNU Lesser General Public
|
|
+// License as published by the Free Software Foundation; either
|
|
+// version 2 of the License, or (at your option) any later version.
|
|
+//
|
|
+// This library is distributed in the hope that it will be useful,
|
|
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+// Lesser General Public License for more details.
|
|
+//
|
|
+// You should have received a copy of the GNU Lesser General Public
|
|
+// License along with this library; if not, write to the Free Software
|
|
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+
|
|
+// User plugin example (see patch description for details)
|
|
+
|
|
+// Define BX_PLUGGABLE in files that can be compiled into plugins. For
|
|
+// platforms that require a special tag on exported symbols, BX_PLUGGABLE
|
|
+// is used to know when we are exporting symbols and when we are importing.
|
|
+#define BX_PLUGGABLE
|
|
+
|
|
+#include "iodev.h"
|
|
+#include "testdev.h"
|
|
+
|
|
+#define LOG_THIS theTestDevice->
|
|
+
|
|
+bx_testdev_c *theTestDevice = NULL;
|
|
+
|
|
+// builtin configuration handling functions
|
|
+
|
|
+void testdev_init_options(void)
|
|
+{
|
|
+ bx_param_c *root_param = SIM->get_param("user");
|
|
+ bx_list_c *menu = new bx_list_c(root_param, "testdev", "Test Device");
|
|
+ menu->set_options(bx_list_c::SHOW_PARENT);
|
|
+ new bx_param_bool_c(menu, "enabled", "Enable Test device", "", 1);
|
|
+ new bx_param_num_c(menu, "testval", "Test Parameter", "", 0, BX_MAX_BIT32U, 0);
|
|
+}
|
|
+
|
|
+Bit32s testdev_options_parser(const char *context, int num_params, char *params[])
|
|
+{
|
|
+ if (!strcmp(params[0], "testdev")) {
|
|
+ bx_list_c *base = (bx_list_c*) SIM->get_param("user.testdev");
|
|
+ for (int i = 1; i < num_params; i++) {
|
|
+ if (SIM->parse_param_from_list(context, params[i], base) < 0) {
|
|
+ BX_ERROR(("%s: unknown parameter for testdev ignored.", context));
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ BX_PANIC(("%s: unknown directive '%s'", context, params[0]));
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+Bit32s testdev_options_save(FILE *fp)
|
|
+{
|
|
+ return SIM->write_param_list(fp, (bx_list_c*) SIM->get_param("user.testdev"), NULL, 0);
|
|
+}
|
|
+
|
|
+// device plugin entry point
|
|
+
|
|
+PLUGIN_ENTRY_FOR_MODULE(testdev)
|
|
+{
|
|
+ if (mode == PLUGIN_INIT) {
|
|
+ theTestDevice = new bx_testdev_c();
|
|
+ BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theTestDevice, "testdev");
|
|
+ // add new configuration parameter for the config interface
|
|
+ testdev_init_options();
|
|
+ // register user-defined option for bochsrc and command line
|
|
+ SIM->register_addon_option("testdev", testdev_options_parser, testdev_options_save);
|
|
+ } else if (mode == PLUGIN_FINI) {
|
|
+ SIM->unregister_addon_option("testdev");
|
|
+ bx_list_c *menu = (bx_list_c*)SIM->get_param("user");
|
|
+ menu->remove("testdev");
|
|
+ delete theTestDevice;
|
|
+ } else {
|
|
+ return (int)PLUGTYPE_OPTIONAL;
|
|
+ }
|
|
+ return(0); // Success
|
|
+}
|
|
+
|
|
+// the device object
|
|
+
|
|
+bx_testdev_c::bx_testdev_c(void)
|
|
+{
|
|
+ put("USER");
|
|
+}
|
|
+
|
|
+bx_testdev_c::~bx_testdev_c(void)
|
|
+{
|
|
+ // nothing here yet
|
|
+}
|
|
+
|
|
+void bx_testdev_c::init(void)
|
|
+{
|
|
+ if (!SIM->get_param_num("user.testdev.enabled")->get())
|
|
+ return;
|
|
+ DEV_register_ioread_handler(this, read_handler, 0x1000, "Test Device", 4);
|
|
+ DEV_register_iowrite_handler(this, write_handler, 0x1000, "Test Device", 4);
|
|
+}
|
|
+
|
|
+void bx_testdev_c::reset(unsigned type)
|
|
+{
|
|
+ BX_USER_THIS s.reg0 = SIM->get_param_num("user.testdev.testval")->get();
|
|
+}
|
|
+
|
|
+void bx_testdev_c::register_state(void)
|
|
+{
|
|
+ bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "testdev", "Test Device");
|
|
+ BXRS_HEX_PARAM_FIELD(list, reg0, BX_USER_THIS s.reg0);
|
|
+}
|
|
+
|
|
+Bit32u bx_testdev_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
|
|
+{
|
|
+ UNUSED(this_ptr);
|
|
+
|
|
+ return BX_USER_THIS s.reg0;
|
|
+}
|
|
+
|
|
+void bx_testdev_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
|
|
+{
|
|
+ UNUSED(this_ptr);
|
|
+
|
|
+ BX_USER_THIS s.reg0 = value;
|
|
+}
|
|
diff -urN ../bochs/user_plugins/testdev.h ./user_plugins/testdev.h
|
|
--- ../bochs/user_plugins/testdev.h 1970-01-01 01:00:00.000000000 +0100
|
|
+++ ./user_plugins/testdev.h 2021-02-07 19:08:10.591961411 +0100
|
|
@@ -0,0 +1,40 @@
|
|
+// Copyright (C) 2009-2021 Volker Ruppert
|
|
+//
|
|
+// This library is free software; you can redistribute it and/or
|
|
+// modify it under the terms of the GNU Lesser General Public
|
|
+// License as published by the Free Software Foundation; either
|
|
+// version 2 of the License, or (at your option) any later version.
|
|
+//
|
|
+// This library is distributed in the hope that it will be useful,
|
|
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+// Lesser General Public License for more details.
|
|
+//
|
|
+// You should have received a copy of the GNU Lesser General Public
|
|
+// License along with this library; if not, write to the Free Software
|
|
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+
|
|
+#ifndef BX_TESTDEV_H
|
|
+#define BX_TESTDEV_H
|
|
+
|
|
+#define BX_USER_THIS theTestDevice->
|
|
+
|
|
+class bx_testdev_c : public bx_devmodel_c {
|
|
+public:
|
|
+ bx_testdev_c();
|
|
+ virtual ~bx_testdev_c();
|
|
+
|
|
+ virtual void init(void);
|
|
+ virtual void reset(unsigned type);
|
|
+ virtual void register_state(void);
|
|
+
|
|
+private:
|
|
+ static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
|
|
+ static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
|
|
+
|
|
+ struct {
|
|
+ Bit32u reg0;
|
|
+ } s;
|
|
+};
|
|
+
|
|
+#endif
|