From 438870e2238d428aa97835eac925b6271b3c4cff Mon Sep 17 00:00:00 2001
From: Stefan Kalkowski <stefan.kalkowski@genode-labs.com>
Date: Wed, 11 May 2022 14:16:41 +0200
Subject: [PATCH] platform_drv: outsource common parts for derivate

Outsource parts of the Main object into a common compound object,
common parts of the Makefile description and depot source package.

Fix genodelabs/genode#4503
---
 repos/os/recipes/src/platform_drv/content.inc | 17 ++++
 repos/os/recipes/src/platform_drv/content.mk  |  7 +-
 repos/os/src/drivers/platform/common.h        | 89 +++++++++++++++++++
 repos/os/src/drivers/platform/main.cc         | 53 ++++-------
 repos/os/src/drivers/platform/target.inc      | 16 ++++
 repos/os/src/drivers/platform/target.mk       | 14 +--
 6 files changed, 141 insertions(+), 55 deletions(-)
 create mode 100644 repos/os/recipes/src/platform_drv/content.inc
 create mode 100644 repos/os/src/drivers/platform/common.h
 create mode 100644 repos/os/src/drivers/platform/target.inc

diff --git a/repos/os/recipes/src/platform_drv/content.inc b/repos/os/recipes/src/platform_drv/content.inc
new file mode 100644
index 0000000000..bce4ea0042
--- /dev/null
+++ b/repos/os/recipes/src/platform_drv/content.inc
@@ -0,0 +1,17 @@
+include $(GENODE_DIR)/repos/base/recipes/src/content.inc
+
+GENERIC_SRC_DIR := $(GENODE_DIR)/repos/os/src/drivers/platform
+GENERIC_INC_DIR := $(GENODE_DIR)/repos/os/include/pci
+
+GENERIC_SRC_FILES := $(filter-out target.mk,$(filter-out main.cc,$(notdir $(wildcard $(GENERIC_SRC_DIR)/*.*))))
+GENERIC_HDR_FILES := $(notdir $(wildcard $(GENERIC_INC_DIR)/*.h))
+
+MIRROR_FROM_OS_DIR := $(addprefix src/drivers/platform/,$(GENERIC_SRC_FILES)) \
+                      $(addprefix include/pci/,$(GENERIC_HDR_FILES))
+
+content: $(MIRROR_FROM_OS_DIR)
+
+$(MIRROR_FROM_OS_DIR):
+	mkdir -p $(dir $@)
+	cp -r $(GENODE_DIR)/repos/os/$@ $@
+
diff --git a/repos/os/recipes/src/platform_drv/content.mk b/repos/os/recipes/src/platform_drv/content.mk
index 9039ef6a2d..e4d3e7b810 100644
--- a/repos/os/recipes/src/platform_drv/content.mk
+++ b/repos/os/recipes/src/platform_drv/content.mk
@@ -1,7 +1,2 @@
 SRC_DIR = src/drivers/platform
-include $(GENODE_DIR)/repos/base/recipes/src/content.inc
-
-content: include/init/child_policy.h
-
-include/init/child_policy.h:
-	$(mirror_from_rep_dir)
+include $(GENODE_DIR)/repos/os/recipes/src/platform_drv/content.inc
diff --git a/repos/os/src/drivers/platform/common.h b/repos/os/src/drivers/platform/common.h
new file mode 100644
index 0000000000..5c2a1672c3
--- /dev/null
+++ b/repos/os/src/drivers/platform/common.h
@@ -0,0 +1,89 @@
+/*
+ * \brief  Platform driver - compound object for all derivate implementations
+ * \author Stefan Kalkowski
+ * \date   2022-05-10
+ */
+
+/*
+ * Copyright (C) 2022 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#include <root.h>
+
+namespace Driver { class Common; };
+
+class Driver::Common
+{
+	private:
+
+		Env                    & _env;
+		Attached_rom_dataspace   _devices_rom  { _env, "devices"          };
+		Reporter                 _cfg_reporter { _env, "config"           };
+		Reporter                 _dev_reporter { _env, "devices"          };
+		Heap                     _heap         { _env.ram(), _env.rm()    };
+		Sliced_heap              _sliced_heap  { _env.ram(), _env.rm()    };
+		Device_model             _devices      { _heap, _dev_reporter     };
+		Signal_handler<Common>   _dev_handler  { _env.ep(), *this,
+		                                         &Common::_handle_devices };
+		Driver::Root             _root;
+
+		void _handle_devices();
+
+	public:
+
+		Heap         & heap()    { return _heap;    }
+		Device_model & devices() { return _devices; }
+
+		void handle_config(Xml_node config);
+		void announce_service();
+
+		Common(Genode::Env            & env,
+		       Attached_rom_dataspace & config_rom);
+};
+
+
+void Driver::Common::_handle_devices()
+{
+	_devices_rom.update();
+	_devices.update(_devices_rom.xml());
+	_root.update_policy();
+}
+
+
+void Driver::Common::handle_config(Xml_node config)
+{
+	config.for_each_sub_node("report", [&] (Xml_node const node) {
+		_dev_reporter.enabled(node.attribute_value("devices", false));
+		_cfg_reporter.enabled(node.attribute_value("config",  false));
+	});
+
+	_root.update_policy();
+
+	if (_cfg_reporter.enabled()) {
+		Reporter::Xml_generator xml(_cfg_reporter, [&] () {
+			config.with_raw_content([&] (char const *src, size_t len) {
+				xml.append(src, len);
+			});
+		});
+	}
+}
+
+
+void Driver::Common::announce_service()
+{
+	_env.parent().announce(_env.ep().manage(_root));
+}
+
+
+Driver::Common::Common(Genode::Env            & env,
+                       Attached_rom_dataspace & config_rom)
+:
+	_env(env),
+	_root(_env, _sliced_heap, config_rom, _devices)
+{
+	_handle_devices();
+	_devices_rom.sigh(_dev_handler);
+}
diff --git a/repos/os/src/drivers/platform/main.cc b/repos/os/src/drivers/platform/main.cc
index 89a3b50ab2..9ae9f2ffdf 100644
--- a/repos/os/src/drivers/platform/main.cc
+++ b/repos/os/src/drivers/platform/main.cc
@@ -12,59 +12,36 @@
  */
 
 #include <base/component.h>
-#include <root.h>
+#include <common.h>
 
 namespace Driver { struct Main; };
 
 struct Driver::Main
 {
-	void update();
+	Env                  & _env;
+	Attached_rom_dataspace _config_rom     { _env, "config"        };
+	Common                 _common         { _env, _config_rom     };
+	Signal_handler<Main>   _config_handler { _env.ep(), *this,
+	                                         &Main::_handle_config };
 
-	Env                  & env;
-	Heap                   heap         { env.ram(), env.rm() };
-	Sliced_heap            sliced_heap  { env.ram(), env.rm() };
-	Attached_rom_dataspace config_rom   { env, "config"       };
-	Attached_rom_dataspace devices_rom  { env, "devices"      };
-	Reporter               cfg_reporter { env, "config"       };
-	Reporter               dev_reporter { env, "devices"      };
-	Device_model           devices      { heap, dev_reporter  };
-	Signal_handler<Main>   handler      { env.ep(), *this,
-	                                      &Main::update       };
-	Driver::Root           root         { env, sliced_heap,
-	                                      config_rom, devices };
+	void _handle_config();
 
 	Main(Genode::Env & e)
-	: env(e)
+	: _env(e)
 	{
-		update();
-		config_rom.sigh(handler);
-		devices_rom.sigh(handler);
-		env.parent().announce(env.ep().manage(root));
+		_handle_config();
+		_config_rom.sigh(_config_handler);
+		_common.announce_service();
 	}
 };
 
 
-void Driver::Main::update()
+void Driver::Main::_handle_config()
 {
-	config_rom.update();
-	devices_rom.update();
-
-	config_rom.xml().for_each_sub_node("report", [&] (Xml_node const node) {
-		dev_reporter.enabled(node.attribute_value("devices", false));
-		cfg_reporter.enabled(node.attribute_value("config",  false));
-	});
-
-	devices.update(devices_rom.xml());
-	root.update_policy();
-
-	if (cfg_reporter.enabled()) {
-		Reporter::Xml_generator xml(cfg_reporter, [&] () {
-			config_rom.xml().with_raw_content([&] (char const *src, size_t len) {
-				xml.append(src, len);
-			});
-		});
-	}
+	_config_rom.update();
+	_common.handle_config(_config_rom.xml());
 }
 
+
 void Component::construct(Genode::Env &env) {
 	static Driver::Main main(env); }
diff --git a/repos/os/src/drivers/platform/target.inc b/repos/os/src/drivers/platform/target.inc
new file mode 100644
index 0000000000..15fa2656b4
--- /dev/null
+++ b/repos/os/src/drivers/platform/target.inc
@@ -0,0 +1,16 @@
+SRC_CC  += device.cc
+SRC_CC  += device_component.cc
+SRC_CC  += device_model_policy.cc
+SRC_CC  += device_pd.cc
+SRC_CC  += main.cc
+SRC_CC  += pci.cc
+SRC_CC  += root.cc
+SRC_CC  += session_component.cc
+
+GENERIC_DIR := $(dir $(call select_from_repositories,src/drivers/platform/target.inc))
+
+INC_DIR += $(PRG_DIR) $(GENERIC_DIR)
+LIBS    += base
+
+vpath %.cc $(PRG_DIR)
+vpath %.cc $(GENERIC_DIR)
diff --git a/repos/os/src/drivers/platform/target.mk b/repos/os/src/drivers/platform/target.mk
index 61b5510e6b..787c060371 100644
--- a/repos/os/src/drivers/platform/target.mk
+++ b/repos/os/src/drivers/platform/target.mk
@@ -1,11 +1,3 @@
-TARGET   = platform_drv
-SRC_CC  += device.cc
-SRC_CC  += device_component.cc
-SRC_CC  += device_model_policy.cc
-SRC_CC  += device_pd.cc
-SRC_CC  += main.cc
-SRC_CC  += pci.cc
-SRC_CC  += root.cc
-SRC_CC  += session_component.cc
-INC_DIR  = $(PRG_DIR)
-LIBS     = base
+TARGET = platform_drv
+
+include $(PRG_DIR)/target.inc