diff --git a/doc/examples/README.md b/doc/examples/README.md
index b334593edf33499d95a82ecbd84b2363c35b8806..9b68178e50767b5a66b1db1fa610dc95cc1c8a90 100644
--- a/doc/examples/README.md
+++ b/doc/examples/README.md
@@ -22,8 +22,8 @@ The full sequence starting from compilation, assuming that the build system is c
 cd </path/to/cmsgemos/>
 cd gemrpc
 DESTDIR=_install cmake3 --build _build --target install
-rsync -v -a --delete --include='/bin/***' --include='/lib/' --include='/lib/rpcmodules/***' --exclude='*' _build/_install/mnt/persistent/gempro/ gempro@gem-shelf01-amc02:
-ssh gempro@gem-shelf01-amc02 'bash -l -c "/bin/clockinit /mnt/persistent/gemdaq/scripts/clkA_ttc_in_160p32_320p64_out_BW_HIGH.txt 320_160 A0 A1 A1 A0; v7load /mnt/persistent/gemdaq/fw/gem_ctp7.bit; source /mnt/persistent/gemdaq/gemloader/gemloader_configure.sh; killall -9 gemrpc; LD_LIBRARY_PATH=/mnt/persistent/gempro/lib/rpcmodules:/mnt/persistent/gempro/lib GEM_PATH=/mnt/persistent/gemdaq bin/gemrpc"'
+rsync -v -a --delete --include='/bin/***' --include='/lib/' --include='/lib/gem/***' --exclude='*' _build/_install/mnt/persistent/gempro/ gempro@gem-shelf01-amc02:
+ssh gempro@gem-shelf01-amc02 'bash -l -c "killall -9 gemrpc; bin/gemrpc; bin/gem-recover"'
 ```
 
 The GBT configurations examples can be found under `gemrpc/doc/gbt/<gem type>/`, but the files used for the configuration of the chamber are stored on the AMC folder `/mnt/persistent/gempro/etc/gem/gbt`.
diff --git a/extern/rpcsvc/server/interface/ModuleManager.h b/extern/rpcsvc/server/interface/ModuleManager.h
index 11d8cf48eb14bbfdbb7d53f48a6cf86e60fdf450..21f8f8049f33e40b394d5235679207ffa09f57ae 100644
--- a/extern/rpcsvc/server/interface/ModuleManager.h
+++ b/extern/rpcsvc/server/interface/ModuleManager.h
@@ -26,8 +26,7 @@ protected:
 
 public:
     ModuleManager() {};
-    int load_modules_dir(std::string dir);
-    bool load_module(std::string dir, std::string mod_name, std::string version_key);
+    bool load_module(std::string module_name);
     void register_method(std::string service, std::string module, rpc_method_t func);
     void invoke_method(std::string method, RPCMsg* request, RPCMsg* response);
 };
diff --git a/extern/rpcsvc/server/src/ModuleManager.cpp b/extern/rpcsvc/server/src/ModuleManager.cpp
index d4b7108ab712f0e6171c93943a6ea2fc62a1c1a0..0b7aa4c444e03d9b0e889fcb437b27f158d972d1 100644
--- a/extern/rpcsvc/server/src/ModuleManager.cpp
+++ b/extern/rpcsvc/server/src/ModuleManager.cpp
@@ -5,104 +5,34 @@
 
 #include "ModuleManager.h"
 
-int ModuleManager::load_modules_dir(std::string dir)
+bool ModuleManager::load_module(std::string module_name)
 {
-    DIR* dh = opendir(dir.c_str());
-    if (!dh)
-        return -1;
-    errno = 0;
     LogManager::ScopeService scopesvc(LOGGER, "ModuleManager");
-    while (struct dirent* ent = readdir(dh)) {
-        if (std::string(".") == ent->d_name || std::string("..") == ent->d_name)
-            continue;
 
-        LOGGER->log_message(LogManager::DEBUG, stdsprintf("Loading module %s/%s", dir.c_str(), ent->d_name));
-
-        void* mod = dlopen((dir + "/" + ent->d_name).c_str(), RTLD_NOW | RTLD_LOCAL);
-        if (!mod) {
-            LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to dlopen %s/%s: %s", dir.c_str(), ent->d_name, dlerror()));
-            continue;
-        }
-
-        void* initfunc = dlsym(mod, "module_init");
-        if (!initfunc) {
-            LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to locate initialization function in %s/%s: %s", dir.c_str(), ent->d_name, dlerror()));
-            continue;
-        }
-
-        void* module_activity_color = dlsym(mod, "module_activity_color");
-        if (module_activity_color)
-            this->modload_activity_color = *static_cast<int*>(module_activity_color);
-
-        LOGGER->log_message(LogManager::DEBUG, stdsprintf("Initializing loaded module %s/%s", dir.c_str(), ent->d_name));
-        LOGGER->push_active_service(ent->d_name);
-        reinterpret_cast<void (*)(ModuleManager*)>(initfunc)(this);
-        LOGGER->pop_active_service(ent->d_name);
-        this->modulestate[dir + "/" + ent->d_name] = 1;
-        LOGGER->log_message(LogManager::DEBUG, stdsprintf("Completed module initialization for %s/%s", dir.c_str(), ent->d_name));
-
-        this->modload_activity_color = 0;
-        errno = 0; // for next readdir();
-    }
-    if (errno) {
-        closedir(dh);
-        return -1;
-    }
-    closedir(dh);
-    return 0;
-}
-
-bool ModuleManager::load_module(std::string dir, std::string mod_name, std::string version_key)
-{
-    LogManager::ScopeService scopesvc(LOGGER, "ModuleManager");
-
-    if (mod_name.find("/") != std::string::npos) {
-        LOGGER->log_message(LogManager::CRITICAL, stdsprintf("Security violation.  Module name \"%s\" contains a '/'!", mod_name.c_str()));
-        return false;
-    }
-
-    LOGGER->log_message(LogManager::DEBUG, stdsprintf("Loading module %s/%s.so", dir.c_str(), mod_name.c_str()));
-    void* mod = dlopen((dir + "/" + mod_name + ".so").c_str(), RTLD_NOW | RTLD_LOCAL);
+    void* mod = dlopen(module_name.data(), RTLD_NOW | RTLD_LOCAL);
     if (!mod) {
-        LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to dlopen %s/%s.so: %s", dir.c_str(), mod_name.c_str(), dlerror()));
+        LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to dlopen %s: %s", module_name.data(), dlerror()));
         return false;
     }
 
-    void* module_version_key_sym = dlsym(mod, "module_version_key");
-    if (!module_version_key_sym) {
-        LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to locate version key in %s/%s.so: %s", dir.c_str(), mod_name.c_str(), dlerror()));
-        return false;
-    }
-
-    const char* module_version_key = reinterpret_cast<const char*>(*reinterpret_cast<void**>(module_version_key_sym));
-    if (version_key != module_version_key) {
-        LOGGER->log_message(LogManager::WARNING, stdsprintf("Bad version key for %s/%s.so: \"%s\"!=\"%s\"", dir.c_str(), mod_name.c_str(), version_key.c_str(), module_version_key));
-        return false;
-    }
-
-    if (this->modulestate[dir + "/" + mod_name + ".so"] == 1) {
-        LOGGER->log_message(LogManager::INFO, stdsprintf("Module %s/%s.so is already loaded", dir.c_str(), mod_name.c_str()));
+    if (this->modulestate[module_name] == 1) {
+        LOGGER->log_message(LogManager::INFO, stdsprintf("Module %s is already loaded", module_name.data()));
         return true;
     }
 
     void* initfunc = dlsym(mod, "module_init");
     if (!initfunc) {
-        LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to locate initialization function in %s/%s.so: %s", dir.c_str(), mod_name.c_str(), dlerror()));
+        LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to locate initialization function in %s: %s", module_name.data(), dlerror()));
         return false;
     }
 
-    void* module_activity_color = dlsym(mod, "module_activity_color");
-    if (module_activity_color)
-        this->modload_activity_color = *static_cast<int*>(module_activity_color);
-
-    LOGGER->log_message(LogManager::DEBUG, stdsprintf("Initializing loaded module %s/%s.so", dir.c_str(), mod_name.c_str()));
-    LOGGER->push_active_service(mod_name);
+    LOGGER->log_message(LogManager::DEBUG, stdsprintf("Initializing loaded module %s", module_name.data()));
+    LOGGER->push_active_service(module_name);
     reinterpret_cast<void (*)(ModuleManager*)>(initfunc)(this);
-    LOGGER->pop_active_service(mod_name);
-    this->modulestate[dir + "/" + mod_name + ".so"] = 1;
-    LOGGER->log_message(LogManager::DEBUG, stdsprintf("Completed module initialization for %s/%s.so", dir.c_str(), mod_name.c_str()));
+    LOGGER->pop_active_service(module_name);
+    this->modulestate[module_name] = 1;
+    LOGGER->log_message(LogManager::DEBUG, stdsprintf("Completed module initialization for %s", module_name.c_str()));
 
-    this->modload_activity_color = 0;
     return true;
 }
 
diff --git a/extern/rpcsvc/server/src/run_client.cpp b/extern/rpcsvc/server/src/run_client.cpp
index e27175c2b109ad2ed52568d709abcd8af89d90eb..c4e1567e034bbbe82e9d90b7c69d33684dfefa96 100644
--- a/extern/rpcsvc/server/src/run_client.cpp
+++ b/extern/rpcsvc/server/src/run_client.cpp
@@ -1,6 +1,6 @@
 #define PROTOVER 3
 #define MIN_PROTOVER 3
-#define MODULES_DIR "/mnt/persistent/gempro/lib/rpcmodules"
+#define MODULE_NAME "libgemhardwarerpc.so"
 #define LOG_PATH_FORMAT "syslog"
 // #define LOG_PATH_FORMAT "/var/log/rpcsvc/rpcsvc.%s.%u.log"
 #define LOG_OUTPUT_LEVEL LogManager::INFO
@@ -101,10 +101,8 @@ int run_client(int clientfd)
     LOGGER->log_message(LogManager::NOTICE, stdsprintf("Client connected from %s", get_ip4_string(clientfd).c_str()));
 
     ModuleManager modmgr;
-#ifdef LOAD_ALL_MODULES
-    if (modmgr.load_modules_dir(MODULES_DIR) < 0)
-        ERROR_DIE("Unable to load modules");
-#endif
+    if (!modmgr.load_module(MODULE_NAME))
+        ERROR_DIE("Unable to load the RPC module");
 
     uint32_t protover = htonl(PROTOVER);
     if (write(clientfd, &protover, 4) != 4)
@@ -156,13 +154,7 @@ int run_client(int clientfd)
         RPCMsg rpcrsp(rpcreq.get_method());
 
         try {
-            if (rpcreq.get_method() == "module.load") {
-                // This special case will be handled here.
-
-                if (!modmgr.load_module(MODULES_DIR, rpcreq.get_string("module"), rpcreq.get_string("module_version_key")))
-                    rpcrsp.set_string("rpcerror", "Unable to load the requested module.");
-            } else
-                modmgr.invoke_method(rpcreq.get_method(), &rpcreq, &rpcrsp);
+            modmgr.invoke_method(rpcreq.get_method(), &rpcreq, &rpcrsp);
         } catch (RPCMsg::TypeException& e) {
             rpcrsp.set_string("rpcerror", std::string("RPCMsg::TypeException Occurred"));
         } catch (RPCMsg::BadKeyException& e) {
@@ -171,23 +163,6 @@ int run_client(int clientfd)
 
         std::string rsp = rpcrsp.serialize();
         uint32_t rsplen = rsp.size();
-
-#if 0
-		// -------- DEBUG BEGIN --------
-		dprintf("Debug Message Seralize:  [rsplen=%u]\n", rsplen);
-		for (uint32_t i = 0; i < rsplen; i++) {
-			if (rsp.c_str()[i] >= 32 && rsp.c_str()[i] <= 127)
-				dprintf("%3c", rsp.c_str()[i]);
-			else
-				dprintf("   ");
-		}
-		dprintf("\n");
-		for (uint32_t i = 0; i < rsplen; i++)
-			dprintf(" %02x", rsp.c_str()[i]);
-		dprintf("\n");
-		// -------- DEBUG END --------
-#endif
-
         uint32_t rspcrc = crc32(0, reinterpret_cast<const unsigned char*>(rsp.data()), rsplen);
 
         rsplen = htonl(rsplen);
diff --git a/extern/xhal/client/interface/XHALInterface.h b/extern/xhal/client/interface/XHALInterface.h
index 83678469f78ecba6f0d1182067a7e409fd5bd0f2..5856ce29370570bb233b4aea4432a6ca361281c1 100644
--- a/extern/xhal/client/interface/XHALInterface.h
+++ b/extern/xhal/client/interface/XHALInterface.h
@@ -81,9 +81,6 @@ namespace client {
         /// @brief Initialize interface and establish RPC service connection with CTP7
         void disconnect();
 
-        /// @brief load remote module
-        void loadModule(const std::string& module_name, const std::string& module_version);
-
         /// @brief Call a remote RPC method
         ///
         /// The remote method called is defined by the template parameter
diff --git a/extern/xhal/client/src/XHALInterface.cpp b/extern/xhal/client/src/XHALInterface.cpp
index 697eca56736bf52ca902da701b035fbfda687083..92893b9dab39068668d5f214fb03b1ea75303822 100644
--- a/extern/xhal/client/src/XHALInterface.cpp
+++ b/extern/xhal/client/src/XHALInterface.cpp
@@ -88,14 +88,6 @@ void xhal::client::XHALInterface::disconnect()
     }
 }
 
-void xhal::client::XHALInterface::loadModule(const std::string& module_name, const std::string& module_version)
-{
-    try {
-        ASSERT(rpc.load_module(module_name, module_version));
-    }
-    STANDARD_CATCH;
-}
-
 void xhal::client::XHALInterface::setLogLevel(int loglevel)
 {
     switch (loglevel) {
diff --git a/gemhardware/managers/src/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp
index e87149004de34d9add280e1fb1a029fcb075019d..4919af6b36d21154ef5d1d8f17dfd32b942f15de 100644
--- a/gemhardware/managers/src/AMCManager.cpp
+++ b/gemhardware/managers/src/AMCManager.cpp
@@ -91,10 +91,10 @@ void gem::hardware::AMCManager::initializeAction()
     // Establish the communication with the backend board
     const std::string deviceName = toolbox::toString("gem-shelf%02d-amc%02d", m_crate.value_, m_slot.value_);
     m_connection = std::make_shared<xhal::client::XHALInterface>(deviceName);
-    m_connection->loadModule("gem_rpc", "");
 
     // == AMC ==
-    m_connection->call<::amc::recoverAMC>();
+    CMSGEMOS_INFO("AMCManager::initializeAction: reset AMC");
+    m_connection->call<::amc::resetAMC>();
 
     // == OptoHybrids ==
 
diff --git a/gemmonitor/src/AMCMonitor.cpp b/gemmonitor/src/AMCMonitor.cpp
index e921a66ca066cfc8d34daac988598aa8d5b234c3..163eb89156106f03987ce2ddf8d763263b9fd8a1 100644
--- a/gemmonitor/src/AMCMonitor.cpp
+++ b/gemmonitor/src/AMCMonitor.cpp
@@ -40,7 +40,7 @@ void gem::monitor::AMCMonitor::actionPerformed(xdata::Event& event)
         CMSGEMOS_DEBUG("AMCMonitor::actionPerformed() setDefaultValues");
         const std::string deviceName = toolbox::toString("gem-shelf%02d-amc%02d", m_crate.value_, m_slot.value_);
         m_amc = std::make_shared<xhal::client::XHALInterface>(deviceName);
-        m_amc->loadModule("gem_rpc", "");
+
         m_ohMask = m_amc->call<::daqmon::getmonOHMask>();
 
         const std::string class_name = this->getApplicationDescriptor()->getClassName();
diff --git a/gemrpc/CMakeLists.txt b/gemrpc/CMakeLists.txt
index 742851c6d30b64d85a3292e7bc46873640605595..9c1df35603aa2361482ef1356489028a5dc911ae 100644
--- a/gemrpc/CMakeLists.txt
+++ b/gemrpc/CMakeLists.txt
@@ -65,33 +65,16 @@ else()
     include_directories("${CMAKE_CURRENT_BINARY_DIR}/_interface")
 
     #
-    # memhub is a regular library
+    # memhub library
     #
     add_library(memhub SHARED src/memhub.cpp)
     target_link_libraries(memhub PUBLIC memsvc)
-    install(TARGETS memhub LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/rpcmodules")
+    install(TARGETS memhub LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/gem")
 
     #
-    # RPC modules
+    # GEM hardware library
     #
-    function(gemrpc_add_module NAME)
-        cmake_parse_arguments(ARGS "" "" "SOURCES;DEPS" ${ARGN})
-
-        add_library(${NAME} SHARED ${ARGS_SOURCES})
-        target_link_libraries(${NAME} PRIVATE ${ARGS_DEPS})
-        target_link_libraries(${NAME} PRIVATE memhub)
-        target_link_libraries(${NAME} PUBLIC xhal::common)
-        target_link_libraries(${NAME} PRIVATE xhal::server)
-        target_link_libraries(${NAME} PRIVATE log4cplus)
-
-        # Remove the `lib` prefix
-        set_target_properties(${NAME} PROPERTIES PREFIX "")
-
-        install(TARGETS ${NAME} LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/rpcmodules")
-    endfunction()
-
-    gemrpc_add_module(gem_rpc
-        SOURCES
+    add_library(gemhardware SHARED
         src/amc.cpp
         src/amc/blaster_ram.cpp
         src/amc/daq.cpp
@@ -101,13 +84,43 @@ else()
         src/daq_monitor.cpp
         src/expert_tools.cpp
         src/gbt.cpp
-        src/gem_rpc.cpp
+        # src/optical.cpp
         src/optohybrid.cpp
         src/vfat3.cpp
         src/utils.cpp
         src/XHALXMLParser.cpp
-        DEPS
-        lmdb xerces-c reedmuller-c)
-    target_include_directories(gem_rpc PUBLIC extern)
+    )
+
+    target_link_libraries(gemhardware PUBLIC memhub)
+    target_link_libraries(gemhardware PUBLIC xhal::common)
+
+    target_link_libraries(gemhardware PRIVATE lmdb)
+    target_link_libraries(gemhardware PRIVATE log4cplus)
+    target_link_libraries(gemhardware PRIVATE reedmuller-c)
+    target_link_libraries(gemhardware PRIVATE xerces-c)
+
+    target_include_directories(gemhardware PUBLIC extern)
+
+    install(TARGETS gemhardware LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/gem")
+
+    #
+    # RPC module
+    #
+    add_library(gemhardwarerpc SHARED src/gemhardwarerpc.cpp)
+
+    target_link_libraries(gemhardwarerpc PRIVATE gemhardware)
+    target_link_libraries(gemhardwarerpc PRIVATE xhal::server)
+
+    install(TARGETS gemhardwarerpc LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/gem")
+
+    #
+    # Standalone executables
+    #
+    add_executable(gem-recover src/recover.cpp)
+    target_link_libraries(gem-recover PRIVATE gemhardware)
+    install(TARGETS gem-recover RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}")
 
+    add_executable(gem-update-address-table src/update_address_table.cpp)
+    target_link_libraries(gem-update-address-table PRIVATE gemhardware)
+    install(TARGETS gem-update-address-table RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}")
 endif()
diff --git a/gemrpc/interface/amc.h b/gemrpc/interface/amc.h
index 79eb910c3ee2e8a9d040f28987eb7617bba49d31..41a18e1401a3c4f164bfc39f90dafd34c9a151b4 100644
--- a/gemrpc/interface/amc.h
+++ b/gemrpc/interface/amc.h
@@ -93,25 +93,31 @@ struct repeatedRegRead : public xhal::common::Method {
 /// @brief Recovers the AMC
 ///
 /// * Enable the optical TX lasers
-/// * Reset the FPGA registers
-/// * Configure the GTH transceivers
+/// * Reset the external PLL (Si5324)
+/// * Load the Virtex-7 firmware
+/// * Load the OptoHybrid firmware into RAM
 ///
-/// @throws @c std::runtime::error if
-///         * fails to enable the optical TX lasers.
+/// @throws @c std::runtime::error if any of the operation fails.
 struct recoverAMC : public xhal::common::Method {
     void operator()() const;
 };
 
-/// @brief Resets all the AMC clocks
+/// @brief Resets the AMC
+///
+/// * Reset the FPGA registers
+/// * Configure the MGT
+struct resetAMC : public xhal::common::Method {
+    void operator()() const;
+};
+
+/// @brief Resets the AMC clocks
 ///
-/// * Reset the external PLL (Si5324) [currently disabled]
 /// * Reset the internal PLL
 /// * Reset the FPGA logic after clock changes
 /// * Align the clock phase to the TTC backplane clock
-/// * Reset the GTH transceivers
+/// * Reset the MGT
 ///
 /// @throws @c std::runtime::error if
-///         * fails to reset the external PLL;
 ///         * fails to reset the internal PLL.
 struct resetClocks : public xhal::common::Method {
     void operator()() const;
diff --git a/gemrpc/interface/daq_monitor.h b/gemrpc/interface/daq_monitor.h
index 7e408c54101aa9d38f274f2138b12d728897e0a5..8371041ef54987468240c74618c420f978604288 100644
--- a/gemrpc/interface/daq_monitor.h
+++ b/gemrpc/interface/daq_monitor.h
@@ -122,13 +122,13 @@ struct getmonVFATLink : xhal::common::Method {
     std::map<std::string, uint32_t> operator()(const bool& doReset = false) const;
 };
 
-/// @brief Creates a dump of the required registers, specified by a file expected in <blah>/registers.txt
+/// @brief Creates a dump of the required registers, specified in the file passed as argument
 ///
 /// @throws @c std::runtime_error if it is not possible to open @c fname
 ///
 /// @returns @c std::map
 struct getmonCTP7dump : xhal::common::Method {
-    std::map<std::string, uint32_t> operator()(const std::string& fname = "/mnt/persistent/gemdaq/mon_registers.txt") const;
+    std::map<std::string, uint32_t> operator()(const std::string& fname) const;
 };
 
 /// @brief Tests the register "GEM_AMC.SLOW_CONTROL.SCA.STATUS.READY" to derive the OH mask that should be used
diff --git a/gemrpc/interface/utils.h b/gemrpc/interface/utils.h
index 53b55087a006a1269b178771d4e23017d62f5985..bddf943f20be5994c37263e2c58ea5f500106c73 100644
--- a/gemrpc/interface/utils.h
+++ b/gemrpc/interface/utils.h
@@ -39,11 +39,9 @@ struct RegInfo {
     }
 };
 
-/// @brief Updates the LMDB object
-///
-/// @param @c at_xml is the name of the XML address table to use to populate the LMDB
+/// @brief Updates the LMDB address table
 struct update_address_table : public xhal::common::Method {
-    void operator()(const std::string& at_xml) const;
+    void operator()() const;
 };
 
 /// @brief Read register information from LMDB
diff --git a/gemrpc/interface/vfat3.h b/gemrpc/interface/vfat3.h
index 1396ffc3523de85b610687e48d019d2af8cba435..b0f3b1d6f87b4042dcf7e155b41a1b5dbddf9c05 100644
--- a/gemrpc/interface/vfat3.h
+++ b/gemrpc/interface/vfat3.h
@@ -39,7 +39,7 @@ struct configureVFAT3DACMonitor : public xhal::common::Method {
 
 /// @brief Configures VFAT3 chips
 ///
-/// VFAT configurations are stored in files under \c /mnt/persistent/gemdaq/vfat3/config_OHX_VFATY.cfg.
+/// VFAT configurations are stored in files under \c $HOME/etc/gem/vfat/config_OHx_VFATy.cfg.
 /// Each non-empty line contains one register name followed by its value.
 /// The comment character is #.
 ///
diff --git a/gemrpc/src/amc.cpp b/gemrpc/src/amc.cpp
index e3076f73f938b38edf7248963eef768b694772ae..aca70345c08c0bb00101700b952ecd8638d2dcd2 100644
--- a/gemrpc/src/amc.cpp
+++ b/gemrpc/src/amc.cpp
@@ -18,6 +18,7 @@
 #include <gem/rpc/utils.h>
 
 #include <chrono>
+#include <fstream>
 #include <thread>
 #include <time.h>
 
@@ -158,14 +159,49 @@ std::vector<uint32_t> amc::sbitReadOut::operator()(const uint32_t& ohN, const ui
 
 void amc::recoverAMC::operator()() const
 {
-    // Step 1: Enable the optical TX lasers
+    const std::string home_path = std::getenv("HOME");
+
+    // == Enable the optical TX lasers ==
     LOG4CPLUS_INFO(logger, "Enable the optical TX lasers");
     utils::execute_command("/bin/txpower enable");
 
-    // Step 2: Reset the FPGA registers
+    // == Reset the external PLL ==
+    LOG4CPLUS_INFO(logger, "Reset the external PLL");
+    const std::string ctp7_cfg_filename = home_path + "/etc/gem/gem_ctp7.cfg";
+    std::ifstream ctp7_cfg_file { ctp7_cfg_filename };
+    std::string ctp7_cfg;
+    std::getline(ctp7_cfg_file, ctp7_cfg);
+    utils::execute_command(std::string { "/bin/clockinit " } + ctp7_cfg);
+
+    // Wait for the PLL to lock
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+
+    // == Load the Virtex-7 firmware ==
+    LOG4CPLUS_INFO(logger, "Load the Virtex-7 firmware");
+    const std::string ctp7_fw_filename = home_path + "/etc/gem/gem_ctp7.bit";
+    utils::execute_command(std::string { "/bin/v7load " } + ctp7_fw_filename);
+
+    // == Load the OptoHybrid firmware into RAM ==
+    LOG4CPLUS_INFO(logger, "Load the OptoHybrid firmware into RAM");
+
+    const std::string optohybrid_fw_filename = home_path + "/etc/gem/gem_optohybrid.bit";
+    utils::execute_command(std::string { "/bin/gemloader load " } + optohybrid_fw_filename);
+
+    // Write the firmware size (rounded-up to a multiple of 4 bytes)
+    std::ifstream optohybrid_fw(optohybrid_fw_filename, std::ifstream::ate | std::ifstream::binary);
+    const uint32_t optohybrid_fw_size = ((static_cast<uint32_t>(optohybrid_fw.tellg()) + 3) / 4) * 4;
+    utils::writeRawAddress(0x6a000004, optohybrid_fw_size);
+
+    // Enable the GEM loader IP core
+    utils::writeRawAddress(0x6a000000, 1);
+}
+
+void amc::resetAMC::operator()() const
+{
+    // == Reset the FPGA registers ==
     utils::writeReg("GEM_AMC.GEM_SYSTEM.CTRL.IPBUS_RESET", 1);
 
-    // Step 3: Configure the GTH transceivers
+    // == Configure the GTH transceivers ==
     //
     // Regular GTH config/control value:
     // Bit 0: TX_POWERDOWN: Transmitter powered down
@@ -192,14 +228,7 @@ void amc::recoverAMC::operator()() const
 
 void amc::resetClocks::operator()() const
 {
-    // Step 1: Reset the external PLL
-    /* LOG4CPLUS_INFO(logger, "Reset the external PLL"); */
-    /* utils::execute_command("/bin/clockinit $GEM_PATH/scripts/clkA_ttc_in_160p32_320p64_out_BW_HIGH.txt 320_160 A0 A1 A1 A0"); */
-
-    /* // Wait for the PLL to lock */
-    /* std::this_thread::sleep_for(std::chrono::milliseconds(1000)); */
-
-    // Step 2: Reset the internal PLL
+    // == Reset the internal PLL ==
     LOG4CPLUS_INFO(logger, "Reset the internal PLL");
     utils::writeReg("GEM_AMC.TTC.CTRL.MMCM_RESET", 1);
     for (size_t i = 0; i < 10; ++i) {
@@ -212,11 +241,11 @@ void amc::resetClocks::operator()() const
         std::this_thread::sleep_for(std::chrono::milliseconds(100));
     }
 
-    // Step 3: Reset the FPGA logic after clock changes
+    // == Reset the FPGA logic after clock changes ==
     utils::writeReg("GEM_AMC.GEM_SYSTEM.CTRL.GLOBAL_RESET", 1);
     std::this_thread::sleep_for(std::chrono::milliseconds(50));
 
-    // Step 4: Align the clock phase to the TTC backplane clock
+    // == Align the clock phase to the TTC backplane clock ==
     LOG4CPLUS_INFO(logger, "Align the clock phase to the TTC backplane clock");
 
     // Write the target phase
@@ -231,14 +260,14 @@ void amc::resetClocks::operator()() const
     } while ((utils::readReg("GEM_AMC.TTC.STATUS.CLK.PHASE_MONITOR.PHASE") > targetPhase + tollerancePhase) || (utils::readReg("GEM_AMC.TTC.STATUS.CLK.PHASE_MONITOR.PHASE") < targetPhase - tollerancePhase));
     utils::writeReg("GEM_AMC.TTC.CTRL.CNT_RESET", 1);
 
-    // Step 5: Reset the GTH transceivers
-    LOG4CPLUS_INFO(logger, "Reset the GTH transceivers");
+    // == Reset the MGT ==
+    LOG4CPLUS_INFO(logger, "Reset the MGT");
     for (uint32_t i = 0; i < 64; i++) {
         const auto tmp = std::string { "GEM_AMC.OPTICAL_LINKS.MGT_CHANNEL_" } + std::to_string(i) + ".RESET";
         utils::writeReg(tmp, 0x7);
     }
 
-    // Check the GTH status
+    // Check the MGT status
     LOG4CPLUS_INFO(logger, "GTHs status");
     LOG4CPLUS_INFO(logger, " Ch # |  GTH Status  |    GTH Ctrl  ");
     LOG4CPLUS_INFO(logger, "------------------------------------");
diff --git a/gemrpc/src/gbt.cpp b/gemrpc/src/gbt.cpp
index 5eca83e92311c75699aad53f11237403bce66d0c..3830aeec708f81c21c0f72b478fde769a873e730 100644
--- a/gemrpc/src/gbt.cpp
+++ b/gemrpc/src/gbt.cpp
@@ -176,7 +176,8 @@ void gbt::writeGBTReg(const uint32_t ohN, const uint32_t gbtN, const uint16_t ad
 void gbt::configureGBTs::operator()(const uint32_t& ohN) const
 {
     for (unsigned int j = 0; j < GBTS_PER_OH; j++) {
-        const std::string gbtConfigFileName = "/mnt/persistent/gempro/etc/gem/gbt/config_OH" + std::to_string(ohN) + "_GBT" + std::to_string(j) + ".cfg";
+        const std::string home_path = std::getenv("HOME");
+        const std::string gbtConfigFileName = home_path + "/etc/gem/gbt/config_OH" + std::to_string(ohN) + "_GBT" + std::to_string(j) + ".cfg";
         std::ifstream gbtConfigFile;
         gbtConfigFile.exceptions(std::ifstream::badbit);
         gbtConfigFile.open(gbtConfigFileName);
diff --git a/gemrpc/src/gem_rpc.cpp b/gemrpc/src/gemhardwarerpc.cpp
similarity index 98%
rename from gemrpc/src/gem_rpc.cpp
rename to gemrpc/src/gemhardwarerpc.cpp
index 9dfeab383c08540331840fd8ead8c0a51fdbd1ed..fe4a2a8852d2cb0e10fe164b30e8fd2d412c7109 100644
--- a/gemrpc/src/gem_rpc.cpp
+++ b/gemrpc/src/gemhardwarerpc.cpp
@@ -1,4 +1,4 @@
-/// @file gem_rpc.cpp
+/// @file gemhardwarerpc.cpp
 /// @brief the registration of all the RPC methods done inside the module_init function for the different RPC modules are combined into this
 /// @author Monika Mittal <monika.mittal@cern.ch>
 /// @author Laurent Pétré <laurent.petre@cern.ch>
@@ -48,6 +48,7 @@ void module_init(ModuleManager* modmgr)
     xhal::server::registerMethod<amc::getOHVFATMaskMultiLink>(modmgr);
     xhal::server::registerMethod<amc::recoverAMC>(modmgr);
     xhal::server::registerMethod<amc::repeatedRegRead>(modmgr);
+    xhal::server::registerMethod<amc::resetAMC>(modmgr);
     xhal::server::registerMethod<amc::resetClocks>(modmgr);
     xhal::server::registerMethod<amc::sbitReadOut>(modmgr);
 
diff --git a/gemrpc/src/recover.cpp b/gemrpc/src/recover.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aee91ac0a889f670c40fb55909170977f86419ef
--- /dev/null
+++ b/gemrpc/src/recover.cpp
@@ -0,0 +1,12 @@
+#include "utils.h"
+#include <gem/rpc/amc.h>
+
+int main(int argc, const char* argv[])
+{
+    ::utils::init_lmdb();
+    memhub_open(&memsvc);
+
+    ::amc::recoverAMC {}();
+
+    return 0;
+}
diff --git a/gemrpc/src/update_address_table.cpp b/gemrpc/src/update_address_table.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4ea9a6bad64636f5c9698945a529cdf3fdcbcd83
--- /dev/null
+++ b/gemrpc/src/update_address_table.cpp
@@ -0,0 +1,8 @@
+#include <gem/rpc/utils.h>
+
+int main(int argc, const char* argv[])
+{
+    ::utils::update_address_table {}();
+
+    return 0;
+}
diff --git a/gemrpc/src/utils.cpp b/gemrpc/src/utils.cpp
index 1889ecc04e44e696f238f45a07761977a4df2278..b43405cff4c9fa4d8f7792b7f1a712a56c1d829a 100644
--- a/gemrpc/src/utils.cpp
+++ b/gemrpc/src/utils.cpp
@@ -95,19 +95,18 @@ void utils::execute_command(const std::string& command)
     }
 }
 
-void utils::update_address_table::operator()(const std::string& at_xml) const
+void utils::update_address_table::operator()() const
 {
     auto logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("logger"));
     LOG4CPLUS_INFO(logger, "START UPDATE ADDRESS TABLE");
 
-    const char* const gem_path = std::getenv("GEM_PATH");
-    if (gem_path == nullptr)
-        throw std::runtime_error("The GEM_PATH environment variable must be defined.");
-    const auto lmdb_data_file = std::string { gem_path } + "/address_table.mdb/data.mdb";
-    const auto lmdb_lock_file = std::string { gem_path } + "/address_table.mdb/lock.mdb";
-    const auto lmdb_area_file = std::string { gem_path } + "/address_table.mdb";
+    const std::string home_path = std::getenv("HOME");
+    const std::string xml_address_table = home_path + "/etc/gem/gem_ctp7.xml";
+    const std::string lmdb_data_file = home_path + "/var/gem/address_tables.mdb/data.mdb";
+    const std::string lmdb_lock_file = home_path + "/var/gem/address_tables.mdb/lock.mdb";
+    const std::string lmdb_area_file = home_path + "/var/gem/address_tables.mdb";
 
-    auto parser = std::make_unique<xhal::common::utils::XHALXMLParser>(at_xml.data());
+    auto parser = std::make_unique<xhal::common::utils::XHALXMLParser>(xml_address_table.data());
     try {
         parser->setLogLevel(0);
         parser->parseXML();
@@ -180,10 +179,8 @@ void utils::init_lmdb()
     if (lmdb_handles)
         return;
 
-    const char* const gem_path = std::getenv("GEM_PATH");
-    if (gem_path == nullptr)
-        throw std::runtime_error("The GEM_PATH environment variable must be defined.");
-    const auto lmdb_data_file = std::string { gem_path } + "/address_table.mdb";
+    const std::string home_path = std::getenv("HOME");
+    const std::string lmdb_data_file = home_path + "/var/gem/address_tables.mdb";
 
     auto env = lmdb::env::create();
     env.set_mapsize(utils::LMDB_SIZE);
diff --git a/gemrpc/src/vfat3.cpp b/gemrpc/src/vfat3.cpp
index 3c44342517ea3aa4b1032d9ad690321b69168b13..61b448ddea03dd95daf6973f90d6841e836c3c3d 100644
--- a/gemrpc/src/vfat3.cpp
+++ b/gemrpc/src/vfat3.cpp
@@ -175,7 +175,8 @@ void vfat3::configureVFAT3s::operator()(const uint16_t& ohN, const uint32_t& vfa
     LOG4CPLUS_INFO(logger, "Loading configuration settings");
     for (size_t vfatN = 0; vfatN < oh::VFATS_PER_OH; ++vfatN) {
         if ((notmask >> vfatN) & 0x1) {
-            const std::string configFile = "/mnt/persistent/gempro/etc/gem/vfat/config_OH" + std::to_string(ohN) + "_VFAT" + std::to_string(vfatN) + ".cfg";
+            const std::string home_path = std::getenv("HOME");
+            const std::string configFile = home_path + "/etc/gem/vfat/config_OH" + std::to_string(ohN) + "_VFAT" + std::to_string(vfatN) + ".cfg";
             std::ifstream infile(configFile);
             if (!infile.is_open()) {
                 std::stringstream errmsg;