mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-20 09:02:09 +00:00
Remove loader and qpluginwidget
The original use cases of the loader have long been covered by the dynamic init. The only substantial client of the loader remained to be the qpluginwidget. However, the qpluginwidget was supported only by the Arora web browser. But the blending of plugins with websites ultimately remained a tech demo, and Arora has been replaced by Falkon. Fixes #5229
This commit is contained in:
parent
179b3eb7e4
commit
f171bc5050
repos
gems/run
libports
include/qpluginwidget
lib
recipes
api/libqpluginwidget
src
run
src
lib/qpluginwidget
test/qt5/qpluginwidget
os
include/loader_session
recipes
api/loader_session
pkg
src
run
src
@ -264,7 +264,6 @@ proc prepare_to_run_genode { } {
|
||||
} [depot_user] {/src/report_rom
|
||||
} [depot_user] {/src/fs_rom
|
||||
} [depot_user] {/src/vfs
|
||||
} [depot_user] {/src/loader
|
||||
} [depot_user] {/src/init
|
||||
} [depot_user] {/src/depot_query
|
||||
}
|
||||
@ -658,7 +657,6 @@ set default_test_pkgs {
|
||||
test-depot_query_index
|
||||
test-ds_ownership
|
||||
test-dynamic_config
|
||||
test-dynamic_config_loader
|
||||
test-entrypoint
|
||||
test-expat
|
||||
test-fault_detection
|
||||
|
@ -1,169 +0,0 @@
|
||||
/*
|
||||
* \brief A Qt Widget that can load a plugin application and show its GUI view
|
||||
* \author Christian Prochaska
|
||||
* \date 2010-08-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2020 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.
|
||||
*/
|
||||
|
||||
#ifndef QPLUGINWIDGET_H
|
||||
#define QPLUGINWIDGET_H
|
||||
|
||||
/* Genode includes */
|
||||
#include <libc/component.h>
|
||||
#include <loader_session/connection.h>
|
||||
|
||||
/* Qt includes */
|
||||
#include <QtGui>
|
||||
#include <QtNetwork>
|
||||
|
||||
#include <qgenodeviewwidget/qgenodeviewwidget.h>
|
||||
|
||||
enum Plugin_loading_state
|
||||
{
|
||||
LOADING,
|
||||
LOADED,
|
||||
NETWORK_ERROR,
|
||||
INFLATE_ERROR,
|
||||
CAP_QUOTA_EXCEEDED_ERROR,
|
||||
RAM_QUOTA_EXCEEDED_ERROR,
|
||||
ROM_CONNECTION_FAILED_EXCEPTION,
|
||||
TIMEOUT_EXCEPTION
|
||||
};
|
||||
|
||||
class QPluginWidget;
|
||||
|
||||
/* separate class, because meta object features are not supported in nested classes */
|
||||
class PluginStarter : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
Libc::Env *_env;
|
||||
QUrl _plugin_url;
|
||||
QByteArray _args;
|
||||
int _max_width;
|
||||
int _max_height;
|
||||
Gui::View_capability _parent_view;
|
||||
|
||||
Loader::Connection *_pc;
|
||||
enum Plugin_loading_state _plugin_loading_state;
|
||||
QString _plugin_loading_error_string;
|
||||
|
||||
QNetworkAccessManager *_qnam;
|
||||
QNetworkReply *_reply;
|
||||
|
||||
void _start_plugin(QString &file_name, QByteArray const &file_buf);
|
||||
|
||||
protected slots:
|
||||
void networkReplyFinished();
|
||||
|
||||
public:
|
||||
PluginStarter(Libc::Env *env,
|
||||
QUrl plugin_url, QString &args,
|
||||
int max_width, int max_height,
|
||||
Gui::View_capability parent_view);
|
||||
|
||||
void run();
|
||||
enum Plugin_loading_state plugin_loading_state() { return _plugin_loading_state; }
|
||||
QString &plugin_loading_error_string() { return _plugin_loading_error_string; }
|
||||
|
||||
/**
|
||||
* Requst size of the Genode GUI view of the loaded subsystem
|
||||
*/
|
||||
Loader::Area view_size();
|
||||
|
||||
/**
|
||||
* Set geometry of the Genode GUI view of the loaded subsystem
|
||||
*/
|
||||
void view_geometry(Loader::Rect rect, Loader::Point offset);
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
};
|
||||
|
||||
|
||||
class QPluginWidget : public QEmbeddedViewWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
static Libc::Env *_env;
|
||||
static QPluginWidget *_last;
|
||||
|
||||
enum Plugin_loading_state _plugin_loading_state;
|
||||
QString _plugin_loading_error_string;
|
||||
|
||||
PluginStarter *_plugin_starter;
|
||||
bool _plugin_starter_started;
|
||||
|
||||
QUrl _plugin_url;
|
||||
QString _plugin_args;
|
||||
|
||||
int _max_width;
|
||||
int _max_height;
|
||||
|
||||
public:
|
||||
|
||||
enum { PRESERVED_CAPS = 150 };
|
||||
enum { PRESERVED_RAM_QUOTA = 5*1024*1024 };
|
||||
|
||||
void cleanup();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *);
|
||||
virtual void showEvent(QShowEvent *);
|
||||
virtual void hideEvent(QHideEvent *);
|
||||
|
||||
protected slots:
|
||||
void pluginStartFinished();
|
||||
|
||||
public:
|
||||
QPluginWidget(QWidget *parent, QUrl plugin_url, QString &args,
|
||||
int max_width = -1, int max_height = -1);
|
||||
~QPluginWidget();
|
||||
|
||||
static void env(Libc::Env &env) { _env = &env; }
|
||||
};
|
||||
|
||||
|
||||
class QPluginWidgetInterface
|
||||
{
|
||||
public:
|
||||
virtual void env(Libc::Env &env) = 0;
|
||||
virtual QWidget *createWidget(QWidget *parent, QUrl plugin_url, QString &args,
|
||||
int max_width = -1, int max_height = -1) = 0;
|
||||
};
|
||||
|
||||
|
||||
Q_DECLARE_INTERFACE(QPluginWidgetInterface, "org.genode.QPluginWidgetInterface")
|
||||
|
||||
|
||||
class QPluginWidgetPlugin : public QObject, public QPluginWidgetInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.genode.QPluginWidgetInterface" FILE "qpluginwidget.json")
|
||||
Q_INTERFACES(QPluginWidgetInterface)
|
||||
|
||||
public:
|
||||
|
||||
explicit QPluginWidgetPlugin(QObject *parent = 0) : QObject(parent) { }
|
||||
|
||||
void env(Libc::Env &env) { QPluginWidget::env(env); }
|
||||
|
||||
QWidget *createWidget(QWidget *parent, QUrl plugin_url, QString &args,
|
||||
int max_width = -1, int max_height = -1)
|
||||
{
|
||||
return new QPluginWidget(parent, plugin_url, args, max_width, max_height);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // QPLUGINWIDGET_H
|
@ -1,22 +0,0 @@
|
||||
QMAKE_PROJECT_FILE = $(REP_DIR)/src/lib/qpluginwidget/qpluginwidget.pro
|
||||
|
||||
QMAKE_TARGET_BINARIES = libqpluginwidget.lib.so
|
||||
|
||||
QT5_PORT_LIBS = libQt5Core libQt5Gui libQt5Network libQt5Widgets libqgenode
|
||||
|
||||
LIBS = libc libm libqgenodeviewwidget mesa qoost stdcxx zlib $(QT5_PORT_LIBS)
|
||||
|
||||
include $(call select_from_repositories,lib/import/import-qt5_qmake.mk)
|
||||
|
||||
QT5_GENODE_LIBS_SHLIB += libqgenodeviewwidget.lib.so libqgenode.lib.so
|
||||
|
||||
qmake_root/include/qpluginwidget: qmake_root/include
|
||||
ln -snf $(call select_from_repositories,include/qpluginwidget) $@
|
||||
|
||||
qmake_prepared.tag: qmake_root/include/qpluginwidget \
|
||||
qmake_root/lib/libqgenodeviewwidget.lib.so \
|
||||
qmake_root/lib/libqgenode.lib.so
|
||||
|
||||
ifeq ($(called_from_lib_mk),yes)
|
||||
all: build_with_qmake
|
||||
endif
|
@ -1,128 +0,0 @@
|
||||
_ZN13PluginStarter11qt_metacallEN11QMetaObject4CallEiPPv T
|
||||
_ZN13PluginStarter11qt_metacastEPKc T
|
||||
_ZN13PluginStarter13_start_pluginER7QStringRK10QByteArray T
|
||||
_ZN13PluginStarter13view_geometryEN6Genode4RectIijEENS0_5PointIiEE T
|
||||
_ZN13PluginStarter16staticMetaObjectE D 48
|
||||
_ZN13PluginStarter20networkReplyFinishedEv T
|
||||
_ZN13PluginStarter3runEv T
|
||||
_ZN13PluginStarter8finishedEv T
|
||||
_ZN13PluginStarter9view_sizeEv T
|
||||
_ZN13PluginStarterC1EPN4Libc3EnvE4QUrlR7QStringiiN6Genode10CapabilityIN3Gui4ViewEEE T
|
||||
_ZN13PluginStarterC2EPN4Libc3EnvE4QUrlR7QStringiiN6Genode10CapabilityIN3Gui4ViewEEE T
|
||||
_ZN13QPluginWidget10paintEventEP11QPaintEvent T
|
||||
_ZN13QPluginWidget11qt_metacallEN11QMetaObject4CallEiPPv T
|
||||
_ZN13QPluginWidget11qt_metacastEPKc T
|
||||
_ZN13QPluginWidget16staticMetaObjectE D 48
|
||||
_ZN13QPluginWidget19pluginStartFinishedEv T
|
||||
_ZN13QPluginWidget4_envE B 8
|
||||
_ZN13QPluginWidget5_lastE B 8
|
||||
_ZN13QPluginWidget7cleanupEv T
|
||||
_ZN13QPluginWidget9hideEventEP10QHideEvent T
|
||||
_ZN13QPluginWidget9showEventEP10QShowEvent T
|
||||
_ZN13QPluginWidgetC1EP7QWidget4QUrlR7QStringii T
|
||||
_ZN13QPluginWidgetC2EP7QWidget4QUrlR7QStringii T
|
||||
_ZN13QPluginWidgetD0Ev T
|
||||
_ZN13QPluginWidgetD1Ev T
|
||||
_ZN13QPluginWidgetD2Ev T
|
||||
_ZN19QPluginWidgetPlugin11qt_metacallEN11QMetaObject4CallEiPPv T
|
||||
_ZN19QPluginWidgetPlugin11qt_metacastEPKc T
|
||||
_ZN19QPluginWidgetPlugin16staticMetaObjectE D 48
|
||||
_ZNK13PluginStarter10metaObjectEv T
|
||||
_ZNK13QPluginWidget10metaObjectEv T
|
||||
_ZNK19QPluginWidgetPlugin10metaObjectEv T
|
||||
_ZTI13PluginStarter D 24
|
||||
_ZTI13QPluginWidget D 24
|
||||
_ZTI18Signal_wait_thread D 24
|
||||
_ZTI19QPluginWidgetPlugin D 56
|
||||
_ZTI22QPluginWidgetInterface D 16
|
||||
_ZTIN6Genode10ConnectionIN6Loader7SessionEEE D 24
|
||||
_ZTIN6Genode10ConnectionINS_11Rom_sessionEEE D 24
|
||||
_ZTIN6Genode10Rpc_clientIN6Loader7SessionEEE D 24
|
||||
_ZTIN6Genode10Rpc_clientINS_11Rom_sessionEEE D 24
|
||||
_ZTIN6Genode10Rpc_clientINS_9DataspaceEEE D 24
|
||||
_ZTIN6Genode11Msgbuf_base13Too_many_capsE D 24
|
||||
_ZTIN6Genode11NoncopyableE D 16
|
||||
_ZTIN6Genode11Rom_sessionE D 24
|
||||
_ZTIN6Genode14Rom_connection21Rom_connection_failedE D 24
|
||||
_ZTIN6Genode14Rom_connectionE D 56
|
||||
_ZTIN6Genode14Service_deniedE D 24
|
||||
_ZTIN6Genode14String_consoleE D 24
|
||||
_ZTIN6Genode15Connection_baseE D 56
|
||||
_ZTIN6Genode16Dataspace_clientE D 24
|
||||
_ZTIN6Genode18Rom_session_clientE D 24
|
||||
_ZTIN6Genode6Parent6ClientE D 24
|
||||
_ZTIN6Genode7SessionE D 16
|
||||
_ZTIN6Genode8Id_spaceINS_6Parent6ClientEE10Out_of_idsE D 40
|
||||
_ZTIN6Genode9DataspaceE D 24
|
||||
_ZTIN6Genode9ExceptionE D 16
|
||||
_ZTIN6Genode9InterfaceE D 16
|
||||
_ZTIN6Genode9Ipc_errorE D 24
|
||||
_ZTIN6Loader10ConnectionE D 56
|
||||
_ZTIN6Loader14Session_clientE D 24
|
||||
_ZTIN6Loader7Session19View_does_not_existE D 24
|
||||
_ZTIN6Loader7Session25Rom_module_does_not_existE D 24
|
||||
_ZTIN6Loader7Session9ExceptionE D 24
|
||||
_ZTIN6Loader7SessionE D 24
|
||||
_ZTS13PluginStarter R 16
|
||||
_ZTS13QPluginWidget R 16
|
||||
_ZTS18Signal_wait_thread D 21
|
||||
_ZTS19QPluginWidgetPlugin R 22
|
||||
_ZTS22QPluginWidgetInterface D 25
|
||||
_ZTSN6Genode10ConnectionIN6Loader7SessionEEE D 41
|
||||
_ZTSN6Genode10ConnectionINS_11Rom_sessionEEE D 41
|
||||
_ZTSN6Genode10Rpc_clientIN6Loader7SessionEEE D 41
|
||||
_ZTSN6Genode10Rpc_clientINS_11Rom_sessionEEE D 41
|
||||
_ZTSN6Genode10Rpc_clientINS_9DataspaceEEE D 38
|
||||
_ZTSN6Genode11Msgbuf_base13Too_many_capsE D 38
|
||||
_ZTSN6Genode11NoncopyableE D 23
|
||||
_ZTSN6Genode11Rom_sessionE D 23
|
||||
_ZTSN6Genode14Rom_connection21Rom_connection_failedE D 49
|
||||
_ZTSN6Genode14Rom_connectionE D 26
|
||||
_ZTSN6Genode14Service_deniedE D 26
|
||||
_ZTSN6Genode14String_consoleE D 26
|
||||
_ZTSN6Genode15Connection_baseE D 27
|
||||
_ZTSN6Genode16Dataspace_clientE D 28
|
||||
_ZTSN6Genode18Rom_session_clientE D 30
|
||||
_ZTSN6Genode6Parent6ClientE D 24
|
||||
_ZTSN6Genode7SessionE D 18
|
||||
_ZTSN6Genode8Id_spaceINS_6Parent6ClientEE10Out_of_idsE D 51
|
||||
_ZTSN6Genode9DataspaceE D 20
|
||||
_ZTSN6Genode9ExceptionE D 20
|
||||
_ZTSN6Genode9InterfaceE D 20
|
||||
_ZTSN6Genode9Ipc_errorE D 20
|
||||
_ZTSN6Loader10ConnectionE D 22
|
||||
_ZTSN6Loader14Session_clientE D 26
|
||||
_ZTSN6Loader7Session19View_does_not_existE D 39
|
||||
_ZTSN6Loader7Session25Rom_module_does_not_existE D 45
|
||||
_ZTSN6Loader7Session9ExceptionE D 28
|
||||
_ZTSN6Loader7SessionE D 18
|
||||
_ZTV13PluginStarter D 128
|
||||
_ZTV13QPluginWidget D 520
|
||||
_ZTV18Signal_wait_thread D 128
|
||||
_ZTV19QPluginWidgetPlugin D 168
|
||||
_ZTV22QPluginWidgetInterface D 32
|
||||
_ZTVN6Genode10ConnectionIN6Loader7SessionEEE D 32
|
||||
_ZTVN6Genode10ConnectionINS_11Rom_sessionEEE D 32
|
||||
_ZTVN6Genode10Rpc_clientIN6Loader7SessionEEE D 120
|
||||
_ZTVN6Genode10Rpc_clientINS_11Rom_sessionEEE D 56
|
||||
_ZTVN6Genode10Rpc_clientINS_9DataspaceEEE D 56
|
||||
_ZTVN6Genode11Rom_sessionE D 56
|
||||
_ZTVN6Genode14Rom_connectionE D 88
|
||||
_ZTVN6Genode14String_consoleE D 48
|
||||
_ZTVN6Genode15Connection_baseE D 32
|
||||
_ZTVN6Genode16Dataspace_clientE D 56
|
||||
_ZTVN6Genode18Rom_session_clientE D 56
|
||||
_ZTVN6Genode6Parent6ClientE D 32
|
||||
_ZTVN6Genode7SessionE D 32
|
||||
_ZTVN6Genode9DataspaceE D 56
|
||||
_ZTVN6Genode9InterfaceE D 32
|
||||
_ZTVN6Loader10ConnectionE D 152
|
||||
_ZTVN6Loader14Session_clientE D 120
|
||||
_ZTVN6Loader7SessionE D 120
|
||||
_ZThn16_N13QPluginWidgetD0Ev T
|
||||
_ZThn16_N13QPluginWidgetD1Ev T
|
||||
_ZThn8_N13QPluginWidgetD0Ev T
|
||||
_ZThn8_N13QPluginWidgetD1Ev T
|
||||
config D 8
|
||||
qt_plugin_instance T
|
||||
qt_plugin_query_metadata T
|
@ -1,10 +0,0 @@
|
||||
MIRROR_FROM_REP_DIR := include/qpluginwidget \
|
||||
lib/symbols/libqpluginwidget
|
||||
|
||||
content: $(MIRROR_FROM_REP_DIR) LICENSE
|
||||
|
||||
$(MIRROR_FROM_REP_DIR):
|
||||
$(mirror_from_rep_dir)
|
||||
|
||||
LICENSE:
|
||||
cp $(GENODE_DIR)/LICENSE $@
|
@ -1 +0,0 @@
|
||||
2020-07-12 a577a19b5fd06a2545f5c7d23ea207ae9f969f7a
|
@ -1 +0,0 @@
|
||||
libqpluginwidget
|
@ -1,10 +0,0 @@
|
||||
MIRROR_FROM_REP_DIR := lib/mk/libqpluginwidget.mk \
|
||||
src/lib/qpluginwidget
|
||||
|
||||
content: $(MIRROR_FROM_REP_DIR) LICENSE
|
||||
|
||||
$(MIRROR_FROM_REP_DIR):
|
||||
$(mirror_from_rep_dir)
|
||||
|
||||
LICENSE:
|
||||
cp $(GENODE_DIR)/LICENSE $@
|
@ -1 +0,0 @@
|
||||
2024-04-18 0e1e1d72700cded78c10738da97b037922615141
|
@ -1,14 +0,0 @@
|
||||
base
|
||||
framebuffer_session
|
||||
gui_session
|
||||
input_session
|
||||
libc
|
||||
libqgenodeviewwidget
|
||||
loader_session
|
||||
mesa
|
||||
os
|
||||
qoost
|
||||
qt5_base
|
||||
stdcxx
|
||||
vfs
|
||||
zlib
|
@ -1,9 +0,0 @@
|
||||
MIRROR_FROM_REP_DIR := src/test/qt5/qpluginwidget
|
||||
|
||||
content: $(MIRROR_FROM_REP_DIR) LICENSE
|
||||
|
||||
$(MIRROR_FROM_REP_DIR):
|
||||
$(mirror_from_rep_dir)
|
||||
|
||||
LICENSE:
|
||||
cp $(GENODE_DIR)/LICENSE $@
|
@ -1 +0,0 @@
|
||||
2024-04-18 17be4478bdcc509cef17276f8e97dacc56bd5c69
|
@ -1,15 +0,0 @@
|
||||
base
|
||||
framebuffer_session
|
||||
input_session
|
||||
libc
|
||||
libqgenodeviewwidget
|
||||
libqpluginwidget
|
||||
loader_session
|
||||
mesa
|
||||
gui_session
|
||||
os
|
||||
qoost
|
||||
qt5_base
|
||||
qt5_component
|
||||
stdcxx
|
||||
vfs
|
@ -1,74 +0,0 @@
|
||||
source ${genode_dir}/repos/libports/run/qt5_common.inc
|
||||
|
||||
import_from_depot [depot_user]/src/qt5_component \
|
||||
[depot_user]/src/libqgenodeviewwidget \
|
||||
[depot_user]/src/libqpluginwidget \
|
||||
[depot_user]/src/test-qpluginwidget \
|
||||
[depot_user]/src/zlib
|
||||
|
||||
build { server/loader server/tar_rom test/nitpicker }
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
} [qt5_parent_provides] {
|
||||
</parent-provides>
|
||||
<default caps="100"/>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
} [qt5_start_nodes] {
|
||||
<start name="loader" caps="100">
|
||||
<resource name="RAM" quantum="8M"/>
|
||||
<provides><service name="Loader"/></provides>
|
||||
<config>
|
||||
<policy label_prefix="test-qpluginwidget">
|
||||
<parent-rom name="ld.lib.so"/>
|
||||
<parent-rom name="init"/>
|
||||
<parent-rom name="tar_rom"/>
|
||||
<parent-rom name="testnit"/>
|
||||
</policy>
|
||||
</config>
|
||||
<route>
|
||||
<service name="Gui"> <child name="wm"/> </service>
|
||||
<any-service> <parent /> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
<start name="test-qpluginwidget" caps="900">
|
||||
<resource name="RAM" quantum="30M"/>
|
||||
<config>
|
||||
<vfs>
|
||||
<dir name="dev">
|
||||
<log/>
|
||||
<inline name="rtc">2018-01-01 00:01</inline>
|
||||
</dir>
|
||||
<dir name="pipe"> <pipe/> </dir>
|
||||
<dir name="qt">
|
||||
<dir name="plugins">
|
||||
<dir name="qpluginwidget">
|
||||
<rom name="libqpluginwidget.lib.so"/>
|
||||
</dir>
|
||||
</dir>
|
||||
</dir>
|
||||
<tar name="qt5_dejavusans.tar"/>
|
||||
<tar name="qt5_libqgenode.tar"/>
|
||||
</vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" pipe="/pipe" rtc="/dev/rtc"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="Gui"> <child name="wm"/> </service>
|
||||
<service name="Report" label="shape">
|
||||
<child name="pointer" label="wm -> test-qpluginwidget -> shape"/>
|
||||
</service>
|
||||
<service name="ROM" label="mesa_gpu_drv.lib.so">
|
||||
<parent label="mesa_gpu-softpipe.lib.so" />
|
||||
</service>
|
||||
<any-service> <parent /> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
build_boot_image [qt5_boot_modules]
|
||||
|
||||
run_genode_until forever
|
@ -1,506 +0,0 @@
|
||||
/*
|
||||
* \brief A Qt Widget that can load a plugin application and show its GUI view
|
||||
* \author Christian Prochaska
|
||||
* \date 2010-08-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2020 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <rom_session/connection.h>
|
||||
#include <util/arg_string.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
/* Qt includes */
|
||||
#include <QtGui>
|
||||
|
||||
#include <qpa_genode/qgenodeplatformwindow.h>
|
||||
|
||||
#include <qpluginwidget/qpluginwidget.h>
|
||||
|
||||
Libc::Env *QPluginWidget::_env = 0;
|
||||
QPluginWidget *QPluginWidget::_last = 0;
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
const char *config = " \
|
||||
<config> \
|
||||
<parent-provides> \
|
||||
<service name=\"CPU\"/> \
|
||||
<service name=\"LOG\"/> \
|
||||
<service name=\"PD\"/> \
|
||||
<service name=\"RM\"/> \
|
||||
<service name=\"ROM\"/> \
|
||||
<service name=\"Timer\"/> \
|
||||
<service name=\"Gui\"/> \
|
||||
</parent-provides> \
|
||||
<default-route> \
|
||||
<any-service> <parent/> <any-child/> </any-service> \
|
||||
</default-route> \
|
||||
<start name=\"tar_rom\" caps=\"100\"> \
|
||||
<resource name=\"RAM\" quantum=\"1M\"/> \
|
||||
<provides> <service name=\"ROM\"/> </provides> \
|
||||
<config> \
|
||||
<archive name=\"plugin.tar\"/> \
|
||||
</config> \
|
||||
</start> \
|
||||
<start name=\"init\" caps=\"2000\"> \
|
||||
<resource name=\"RAM\" quantum=\"2G\"/> \
|
||||
<route> \
|
||||
<service name=\"ROM\" label=\"config\"> \
|
||||
<child name=\"tar_rom\" label=\"config.plugin\"/> \
|
||||
</service> \
|
||||
<any-service> <parent /> </any-service> \
|
||||
</route> \
|
||||
</start> \
|
||||
</config> \
|
||||
";
|
||||
|
||||
|
||||
class Signal_wait_thread : public QThread
|
||||
{
|
||||
private:
|
||||
|
||||
Signal_receiver &_signal_receiver;
|
||||
QMutex &_timeout_mutex;
|
||||
|
||||
protected:
|
||||
|
||||
void run()
|
||||
{
|
||||
_signal_receiver.wait_for_signal();
|
||||
_timeout_mutex.unlock();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Signal_wait_thread(Signal_receiver &signal_receiver, QMutex &timeout_mutex)
|
||||
: _signal_receiver(signal_receiver),
|
||||
_timeout_mutex(timeout_mutex) { }
|
||||
};
|
||||
|
||||
|
||||
PluginStarter::PluginStarter(Libc::Env *env,
|
||||
QUrl plugin_url, QString &args,
|
||||
int max_width, int max_height,
|
||||
Gui::View_capability parent_view)
|
||||
:
|
||||
_env(env),
|
||||
_plugin_url(plugin_url),
|
||||
_args(args.toLatin1()),
|
||||
_max_width(max_width),
|
||||
_max_height(max_height),
|
||||
_parent_view(parent_view),
|
||||
_pc(0),
|
||||
_plugin_loading_state(LOADING),
|
||||
_qnam(0),
|
||||
_reply(0)
|
||||
{ }
|
||||
|
||||
|
||||
void PluginStarter::_start_plugin(QString &file_name, QByteArray const &file_buf)
|
||||
{
|
||||
Genode::size_t caps = Arg_string::find_arg(_args.constData(), "caps").ulong_value(0);
|
||||
|
||||
if ((long)_env->pd().avail_caps().value - (long)caps < QPluginWidget::PRESERVED_CAPS) {
|
||||
Genode::error("Cannot donate ", caps, " capabilities to the plugin (quota exceeded).");
|
||||
_plugin_loading_state = CAP_QUOTA_EXCEEDED_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_name.endsWith(".gz")) {
|
||||
file_name.remove(".gz");
|
||||
|
||||
uint32_t file_size = *(uint32_t*)(file_buf.constData() +
|
||||
file_buf.size() - sizeof(uint32_t));
|
||||
|
||||
Genode::log(__func__, ": file_size_uncompressed=", file_size);
|
||||
|
||||
Genode::size_t ram_quota = Arg_string::find_arg(_args.constData(),
|
||||
"ram_quota").ulong_value(0) +
|
||||
file_size;
|
||||
|
||||
if (((long)_env->pd().avail_ram().value - (long)ram_quota) <
|
||||
QPluginWidget::PRESERVED_RAM_QUOTA) {
|
||||
Genode::error("Cannot donate ", ram_quota, " bytes of RAM to the plugin (quota exceeded).");
|
||||
_plugin_loading_state = RAM_QUOTA_EXCEEDED_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
_pc = new Loader::Connection(*_env,
|
||||
Genode::Ram_quota{ram_quota},
|
||||
Genode::Cap_quota{caps});
|
||||
|
||||
Dataspace_capability ds = _pc->alloc_rom_module(file_name.toUtf8().constData(), file_size);
|
||||
if (ds.valid()) {
|
||||
void *ds_addr = _env->rm().attach(ds);
|
||||
|
||||
z_stream zs;
|
||||
zs.next_in = (Bytef*)(file_buf.data());
|
||||
zs.avail_in = file_buf.size();
|
||||
zs.total_in = 0;
|
||||
zs.next_out = (Bytef*)ds_addr;
|
||||
zs.avail_out = file_size;
|
||||
zs.total_out = 0;
|
||||
zs.zalloc = Z_NULL;
|
||||
zs.zfree = Z_NULL;
|
||||
|
||||
/* enable gzip format detection */
|
||||
if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK) {
|
||||
Genode::error("inflateInit2() failed");
|
||||
_plugin_loading_state = INFLATE_ERROR;
|
||||
|
||||
inflateEnd(&zs);
|
||||
_env->rm().detach(ds_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* uncompress */
|
||||
if (inflate(&zs, Z_SYNC_FLUSH) != Z_STREAM_END) {
|
||||
Genode::error("inflate() failed");
|
||||
_plugin_loading_state = INFLATE_ERROR;
|
||||
|
||||
inflateEnd(&zs);
|
||||
_env->rm().detach(ds_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
inflateEnd(&zs);
|
||||
|
||||
_env->rm().detach(ds_addr);
|
||||
_pc->commit_rom_module(file_name.toUtf8().constData());
|
||||
}
|
||||
} else {
|
||||
Genode::size_t ram_quota = Arg_string::find_arg(_args.constData(), "ram_quota").ulong_value(0);
|
||||
|
||||
if (((long)_env->pd().avail_ram().value - (long)ram_quota) <
|
||||
QPluginWidget::PRESERVED_RAM_QUOTA) {
|
||||
_plugin_loading_state = RAM_QUOTA_EXCEEDED_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
_pc = new Loader::Connection(*_env,
|
||||
Genode::Ram_quota{ram_quota},
|
||||
Genode::Cap_quota{caps});
|
||||
|
||||
Dataspace_capability plugin_ds = _pc->alloc_rom_module("plugin.tar", file_buf.size());
|
||||
if (plugin_ds.valid()) {
|
||||
void *plugin_ds_addr = _env->rm().attach(plugin_ds);
|
||||
::memcpy(plugin_ds_addr, file_buf.constData(), file_buf.size());
|
||||
_env->rm().detach(plugin_ds_addr);
|
||||
_pc->commit_rom_module("plugin.tar");
|
||||
}
|
||||
}
|
||||
|
||||
Dataspace_capability config_ds = _pc->alloc_rom_module("config", ::strlen(config) + 1);
|
||||
if (config_ds.valid()) {
|
||||
void *config_ds_addr = _env->rm().attach(config_ds);
|
||||
::memcpy(config_ds_addr, config, ::strlen(config) + 1);
|
||||
_env->rm().detach(config_ds_addr);
|
||||
_pc->commit_rom_module("config");
|
||||
}
|
||||
|
||||
Signal_context sig_ctx;
|
||||
Signal_receiver sig_rec;
|
||||
|
||||
_pc->view_ready_sigh(sig_rec.manage(&sig_ctx));
|
||||
_pc->constrain_geometry(Loader::Area(_max_width, _max_height));
|
||||
_pc->parent_view(_parent_view);
|
||||
_pc->start("init", "init");
|
||||
|
||||
QMutex view_ready_mutex;
|
||||
Signal_wait_thread signal_wait_thread(sig_rec, view_ready_mutex);
|
||||
signal_wait_thread.start();
|
||||
if (view_ready_mutex.tryLock(10000)) {
|
||||
_plugin_loading_state = LOADED;
|
||||
} else {
|
||||
_plugin_loading_state = TIMEOUT_EXCEPTION;
|
||||
signal_wait_thread.terminate();
|
||||
}
|
||||
signal_wait_thread.wait();
|
||||
}
|
||||
|
||||
|
||||
void PluginStarter::run()
|
||||
{
|
||||
if (_plugin_url.scheme() == "rom") {
|
||||
|
||||
QString file_name = _plugin_url.path().remove("/");
|
||||
|
||||
try {
|
||||
Rom_connection rc(*_env, file_name.toLatin1().constData());
|
||||
|
||||
Dataspace_capability rom_ds = rc.dataspace();
|
||||
|
||||
char const *rom_ds_addr = (char const *)_env->rm().attach(rom_ds);
|
||||
|
||||
QByteArray file_buf = QByteArray::fromRawData(rom_ds_addr, Dataspace_client(rom_ds).size());
|
||||
|
||||
_start_plugin(file_name, file_buf);
|
||||
|
||||
_env->rm().detach(rom_ds_addr);
|
||||
|
||||
} catch (Rom_connection::Rom_connection_failed) {
|
||||
_plugin_loading_state = ROM_CONNECTION_FAILED_EXCEPTION;
|
||||
}
|
||||
|
||||
emit finished();
|
||||
|
||||
} else if (_plugin_url.scheme() == "http") {
|
||||
|
||||
_qnam = new QNetworkAccessManager();
|
||||
_reply = _qnam->get(QNetworkRequest(_plugin_url));
|
||||
|
||||
connect(_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished()));
|
||||
}
|
||||
|
||||
exec();
|
||||
|
||||
delete _pc;
|
||||
|
||||
moveToThread(QApplication::instance()->thread());
|
||||
}
|
||||
|
||||
|
||||
void PluginStarter::networkReplyFinished()
|
||||
{
|
||||
if (_reply->error() != QNetworkReply::NoError) {
|
||||
_plugin_loading_state = NETWORK_ERROR;
|
||||
_plugin_loading_error_string = _reply->errorString();
|
||||
_reply->deleteLater();
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "download finished, size = " << _reply->size();
|
||||
|
||||
QString file_name = _plugin_url.path().remove("/");;
|
||||
QByteArray file_buf = _reply->readAll();
|
||||
|
||||
_start_plugin(file_name, file_buf);
|
||||
|
||||
_reply->deleteLater();
|
||||
_qnam->deleteLater();
|
||||
|
||||
emit finished();
|
||||
}
|
||||
|
||||
|
||||
Loader::Area PluginStarter::view_size()
|
||||
{
|
||||
return _pc ? _pc->view_size() : Loader::Area();
|
||||
}
|
||||
|
||||
|
||||
void PluginStarter::view_geometry(Loader::Rect rect, Loader::Point offset)
|
||||
{
|
||||
if (_pc)
|
||||
_pc->view_geometry(rect, offset);
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
** QPluginWidget **
|
||||
*******************/
|
||||
|
||||
QPluginWidget::QPluginWidget(QWidget *parent, QUrl plugin_url, QString &args,
|
||||
int max_width, int max_height)
|
||||
:
|
||||
QEmbeddedViewWidget(parent),
|
||||
_plugin_loading_state(LOADING),
|
||||
_plugin_starter(0),
|
||||
_plugin_starter_started(false),
|
||||
_plugin_url(plugin_url),
|
||||
_plugin_args(args),
|
||||
_max_width(max_width),
|
||||
_max_height(max_height)
|
||||
{
|
||||
qDebug() << "plugin_url = " << plugin_url;
|
||||
qDebug() << "plugin_url.scheme() = " << plugin_url.scheme();
|
||||
qDebug() << "plugin_url.path() = " << plugin_url.path();
|
||||
qDebug() << "plugin_url.toLocalFile() = " << plugin_url.toLocalFile();
|
||||
qDebug() << "args =" << args;
|
||||
|
||||
if (_last) {
|
||||
_last->cleanup();
|
||||
_last = this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QPluginWidget::~QPluginWidget()
|
||||
{
|
||||
cleanup();
|
||||
|
||||
if (_last == this)
|
||||
_last = 0;
|
||||
}
|
||||
|
||||
|
||||
void QPluginWidget::cleanup()
|
||||
{
|
||||
if (_plugin_starter) {
|
||||
/* make the thread leave the event loop */
|
||||
_plugin_starter->exit();
|
||||
/* wait until the thread has left the run() function */
|
||||
_plugin_starter->wait();
|
||||
/* delete the QThread object */
|
||||
delete _plugin_starter;
|
||||
_plugin_starter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QPluginWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QWidget::paintEvent(event);
|
||||
|
||||
if (_plugin_loading_state == LOADED) {
|
||||
|
||||
QEmbeddedViewWidget::View_geometry const view_geometry =
|
||||
QEmbeddedViewWidget::_calc_view_geometry();
|
||||
|
||||
if (mask().isEmpty()) {
|
||||
|
||||
Loader::Rect const geometry(Loader::Point(view_geometry.x,
|
||||
view_geometry.y),
|
||||
Loader::Area(view_geometry.w,
|
||||
view_geometry.h));
|
||||
|
||||
Loader::Point const offset(view_geometry.buf_x,
|
||||
view_geometry.buf_y);
|
||||
|
||||
_plugin_starter->view_geometry(geometry, offset);
|
||||
|
||||
} else {
|
||||
|
||||
Loader::Rect const
|
||||
geometry(Loader::Point(mapToGlobal(mask().boundingRect().topLeft()).x(),
|
||||
mapToGlobal(mask().boundingRect().topLeft()).y()),
|
||||
Loader::Area(mask().boundingRect().width(),
|
||||
mask().boundingRect().height()));
|
||||
|
||||
Loader::Point const offset(view_geometry.buf_x, view_geometry.buf_y);
|
||||
|
||||
_plugin_starter->view_geometry(geometry, offset);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
QPainter painter(this);
|
||||
painter.drawRect(0, 0, width() - 1, height() - 1);
|
||||
switch (_plugin_loading_state) {
|
||||
case LOADING:
|
||||
painter.drawText(rect(), Qt::AlignCenter, tr("Loading plugin..."));
|
||||
break;
|
||||
case NETWORK_ERROR:
|
||||
painter.drawText(rect(), Qt::AlignCenter, tr("Could not load plugin: ") +
|
||||
_plugin_loading_error_string);
|
||||
break;
|
||||
case INFLATE_ERROR:
|
||||
painter.drawText(rect(), Qt::AlignCenter,
|
||||
tr("Could not load plugin: error decompressing gzipped file."));
|
||||
break;
|
||||
case CAP_QUOTA_EXCEEDED_ERROR:
|
||||
painter.drawText(rect(), Qt::AlignCenter,
|
||||
tr("Could not load plugin: not enough capabilities."));
|
||||
break;
|
||||
case RAM_QUOTA_EXCEEDED_ERROR:
|
||||
painter.drawText(rect(), Qt::AlignCenter,
|
||||
tr("Could not load plugin: not enough memory."));
|
||||
break;
|
||||
case TIMEOUT_EXCEPTION:
|
||||
painter.drawText(rect(), Qt::AlignCenter, tr("Could not load plugin: timeout."));
|
||||
break;
|
||||
case ROM_CONNECTION_FAILED_EXCEPTION:
|
||||
painter.drawText(rect(), Qt::AlignCenter, tr("Could not load plugin: file not found."));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QPluginWidget::showEvent(QShowEvent *event)
|
||||
{
|
||||
/* only now do we know the parent widget for sure */
|
||||
|
||||
if (!_plugin_starter_started) {
|
||||
|
||||
QGenodePlatformWindow *platform_window =
|
||||
dynamic_cast<QGenodePlatformWindow*>(window()->windowHandle()->handle());
|
||||
|
||||
assert(_env != nullptr);
|
||||
|
||||
_plugin_starter = new PluginStarter(_env,
|
||||
_plugin_url, _plugin_args,
|
||||
_max_width, _max_height,
|
||||
platform_window->view_cap());
|
||||
_plugin_starter->moveToThread(_plugin_starter);
|
||||
connect(_plugin_starter, SIGNAL(finished()), this, SLOT(pluginStartFinished()));
|
||||
_plugin_starter->start();
|
||||
|
||||
_plugin_starter_started = true;
|
||||
}
|
||||
|
||||
QEmbeddedViewWidget::showEvent(event);
|
||||
}
|
||||
|
||||
|
||||
void QPluginWidget::pluginStartFinished()
|
||||
{
|
||||
_plugin_loading_state = _plugin_starter->plugin_loading_state();
|
||||
|
||||
if (_plugin_loading_state == LOADED) {
|
||||
|
||||
Loader::Area const size = _plugin_starter->view_size();
|
||||
|
||||
QEmbeddedViewWidget::_orig_geometry(size.w(), size.h(), 0, 0);
|
||||
|
||||
int w = (_max_width > -1) ? qMin(size.w(), (unsigned)_max_width) : size.w();
|
||||
int h = (_max_height > -1) ? qMin(size.h(), (unsigned)_max_height) : size.h();
|
||||
|
||||
setFixedSize(w, h);
|
||||
|
||||
} else {
|
||||
_plugin_loading_error_string = _plugin_starter->plugin_loading_error_string();
|
||||
setFixedSize((_max_width > -1) ? _max_width : 100,
|
||||
(_max_height > -1) ? _max_height : 100);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void QPluginWidget::hideEvent(QHideEvent *event)
|
||||
{
|
||||
QWidget::hideEvent(event);
|
||||
|
||||
if (_plugin_loading_state == LOADED) {
|
||||
|
||||
QEmbeddedViewWidget::View_geometry const view_geometry =
|
||||
QEmbeddedViewWidget::_calc_view_geometry();
|
||||
|
||||
Loader::Rect geometry(Loader::Point(mapToGlobal(pos()).x(),
|
||||
mapToGlobal(pos()).y()),
|
||||
Loader::Area(0, 0));
|
||||
|
||||
Loader::Point offset(view_geometry.buf_x, view_geometry.buf_y);
|
||||
|
||||
_plugin_starter->view_geometry(geometry, offset);
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"Keys": [ "qpluginwidget" ]
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
TEMPLATE = lib
|
||||
CONFIG += plugin
|
||||
QT = core gui gui_private network widgets
|
||||
HEADERS = qmake_root/include/qpluginwidget/qpluginwidget.h
|
||||
SOURCES = qpluginwidget.cpp
|
||||
OTHER_FILES = qpluginwidget.json
|
@ -1,17 +0,0 @@
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="ROM"/>
|
||||
<service name="Timer"/>
|
||||
<service name="Gui"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="testnit" caps="100">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
</start>
|
||||
</config>
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* \brief QPluginWidget test
|
||||
* \author Christian Prochaska
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2020 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.
|
||||
*/
|
||||
|
||||
/* Qt includes */
|
||||
#include <QtGui>
|
||||
#include <QApplication>
|
||||
|
||||
/* Qoost includes */
|
||||
#include <qoost/compound_widget.h>
|
||||
|
||||
/* qpluginwidget includes */
|
||||
#include <qpluginwidget/qpluginwidget.h>
|
||||
|
||||
/* qt5_component includes */
|
||||
#include <qt5_component/qpa_init.h>
|
||||
|
||||
void Libc::Component::construct(Libc::Env &env)
|
||||
{
|
||||
Libc::with_libc([&] {
|
||||
|
||||
qpa_init(env);
|
||||
|
||||
int argc = 1;
|
||||
char const *argv[] = { "test-qpluginwidget", 0 };
|
||||
|
||||
QApplication app(argc, (char**)argv);
|
||||
|
||||
Compound_widget<QWidget, QHBoxLayout> w;
|
||||
|
||||
QPluginLoader plugin_loader("/qt/plugins/qpluginwidget/libqpluginwidget.lib.so");
|
||||
|
||||
QObject *plugin = plugin_loader.instance();
|
||||
|
||||
if (!plugin)
|
||||
qFatal("Error: Could not load QPluginWidget Qt plugin");
|
||||
|
||||
QPluginWidgetInterface *plugin_widget_interface = qobject_cast<QPluginWidgetInterface*>(plugin);
|
||||
|
||||
plugin_widget_interface->env(env);
|
||||
|
||||
QString plugin_args("ram_quota=6M, caps=500");
|
||||
|
||||
QPluginWidget *plugin_widget = static_cast<QPluginWidget*>(
|
||||
plugin_widget_interface->createWidget(&w,
|
||||
QUrl("rom:///test-plugin.tar"),
|
||||
plugin_args, 100, 100)
|
||||
);
|
||||
|
||||
w.layout()->addWidget(plugin_widget);
|
||||
|
||||
w.resize(150, 150);
|
||||
|
||||
w.show();
|
||||
|
||||
return app.exec();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* dummy will not be called */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
qFatal("Error: '", __func__, "' should not be called.");
|
||||
return -1;
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
TEMPLATE = app
|
||||
TARGET = test-qpluginwidget
|
||||
QT = core gui network widgets
|
||||
SOURCES = main.cpp
|
@ -1,23 +0,0 @@
|
||||
QMAKE_PROJECT_FILE = $(PRG_DIR)/qpluginwidget.pro
|
||||
|
||||
QMAKE_TARGET_BINARIES = test-qpluginwidget
|
||||
|
||||
QT5_PORT_LIBS = libQt5Core libQt5Gui libQt5Network libQt5Widgets
|
||||
|
||||
LIBS = libc libm mesa qt5_component stdcxx libqgenodeviewwidget libqpluginwidget qoost $(QT5_PORT_LIBS)
|
||||
|
||||
include $(call select_from_repositories,lib/import/import-qt5_qmake.mk)
|
||||
|
||||
#
|
||||
# create tar archive for test plugin
|
||||
#
|
||||
|
||||
TEST_PLUGIN_TAR = $(BUILD_BASE_DIR)/bin/test-plugin.tar
|
||||
|
||||
$(TARGET): $(TEST_PLUGIN_TAR)
|
||||
|
||||
$(TEST_PLUGIN_TAR): config.plugin
|
||||
$(VERBOSE)tar cf $@ -C $(PRG_DIR) config.plugin
|
||||
|
||||
clean:
|
||||
$(VERBOSE)rm $(TEST_PLUGIN_TAR)
|
@ -1,22 +0,0 @@
|
||||
/*
|
||||
* \brief Loader-session capability type
|
||||
* \author Christian Prochaska
|
||||
* \date 2009-10-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__LOADER_SESSION__CAPABILITY_H_
|
||||
#define _INCLUDE__LOADER_SESSION__CAPABILITY_H_
|
||||
|
||||
#include <base/capability.h>
|
||||
#include <loader_session/loader_session.h>
|
||||
|
||||
namespace Loader { typedef Genode::Capability<Session> Session_capability; }
|
||||
|
||||
#endif /* _INCLUDE__LOADER_SESSION__CAPABILITY_H_ */
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* \brief Client-side loader-session interface
|
||||
* \author Christian Prochaska
|
||||
* \date 2009-10-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__LOADER_SESSION__CLIENT_H_
|
||||
#define _INCLUDE__LOADER_SESSION__CLIENT_H_
|
||||
|
||||
#include <loader_session/loader_session.h>
|
||||
#include <loader_session/capability.h>
|
||||
#include <base/rpc_client.h>
|
||||
|
||||
|
||||
namespace Loader { struct Session_client; }
|
||||
|
||||
|
||||
struct Loader::Session_client : Genode::Rpc_client<Session>
|
||||
{
|
||||
explicit Session_client(Loader::Session_capability session)
|
||||
: Rpc_client<Session>(session) { }
|
||||
|
||||
Dataspace_capability alloc_rom_module(Name const &name,
|
||||
size_t size) override {
|
||||
return call<Rpc_alloc_rom_module>(name, size); }
|
||||
|
||||
void commit_rom_module(Name const &name) override {
|
||||
call<Rpc_commit_rom_module>(name); }
|
||||
|
||||
void cap_quota(Cap_quota limit) override {
|
||||
call<Rpc_cap_quota>(limit); }
|
||||
|
||||
void ram_quota(Ram_quota quantum) override {
|
||||
call<Rpc_ram_quota>(quantum); }
|
||||
|
||||
void constrain_geometry(Area size) override {
|
||||
call<Rpc_constrain_geometry>(size); }
|
||||
|
||||
void parent_view(Gui::View_capability view) override {
|
||||
call<Rpc_parent_view>(view); }
|
||||
|
||||
void view_ready_sigh(Signal_context_capability sigh) override {
|
||||
call<Rpc_view_ready_sigh>(sigh); }
|
||||
|
||||
void fault_sigh(Signal_context_capability sigh) override {
|
||||
call<Rpc_fault_sigh>(sigh); }
|
||||
|
||||
void start(Name const &binary, Name const &label = "") override {
|
||||
call<Rpc_start>(binary, label); }
|
||||
|
||||
void view_geometry(Rect rect, Point offset) override {
|
||||
call<Rpc_view_geometry>(rect, offset); }
|
||||
|
||||
Area view_size() const override {
|
||||
return call<Rpc_view_size>(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__PLUGIN_SESSION__CLIENT_H_ */
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* \brief Connection to Loader service
|
||||
* \author Christian Prochaska
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__LOADER_SESSION__CONNECTION_H_
|
||||
#define _INCLUDE__LOADER_SESSION__CONNECTION_H_
|
||||
|
||||
#include <loader_session/client.h>
|
||||
#include <base/connection.h>
|
||||
|
||||
namespace Loader { struct Connection; }
|
||||
|
||||
|
||||
struct Loader::Connection : Genode::Connection<Session>, Session_client
|
||||
{
|
||||
Connection(Genode::Env &env, Ram_quota ram_quota, Cap_quota cap_quota)
|
||||
:
|
||||
Genode::Connection<Session>(env, Label(), ram_quota, Args()),
|
||||
Session_client(cap())
|
||||
{
|
||||
upgrade_caps(cap_quota.value);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__LOADER_SESSION__CONNECTION_H_ */
|
@ -1,201 +0,0 @@
|
||||
/*
|
||||
* \brief Loader session interface
|
||||
* \author Christian Prochaska
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__LOADER_SESSION__LOADER_SESSION_H_
|
||||
#define _INCLUDE__LOADER_SESSION__LOADER_SESSION_H_
|
||||
|
||||
#include <base/rpc.h>
|
||||
#include <base/rpc_args.h>
|
||||
#include <dataspace/capability.h>
|
||||
#include <gui_session/client.h>
|
||||
#include <pd_session/pd_session.h>
|
||||
#include <base/signal.h>
|
||||
#include <session/session.h>
|
||||
#include <util/geometry.h>
|
||||
|
||||
namespace Loader {
|
||||
|
||||
typedef Genode::Point<> Point;
|
||||
typedef Genode::Area<> Area;
|
||||
typedef Genode::Rect<> Rect;
|
||||
|
||||
using Genode::Dataspace_capability;
|
||||
using Genode::Signal_context_capability;
|
||||
using Genode::Ram_quota;
|
||||
using Genode::Cap_quota;
|
||||
|
||||
struct Session;
|
||||
}
|
||||
|
||||
|
||||
struct Loader::Session : Genode::Session
|
||||
{
|
||||
/*
|
||||
* Resolve ambiguity of 'size_t' type when using 'loader_session.h'
|
||||
* together with libc headers.
|
||||
*/
|
||||
typedef Genode::size_t size_t;
|
||||
|
||||
/*
|
||||
* Exception types
|
||||
*/
|
||||
struct Exception : Genode::Exception { };
|
||||
struct View_does_not_exist : Exception { };
|
||||
struct Rom_module_does_not_exist : Exception { };
|
||||
|
||||
typedef Genode::Rpc_in_buffer<64> Name;
|
||||
typedef Genode::Rpc_in_buffer<128> Path;
|
||||
|
||||
/**
|
||||
* \noapi
|
||||
*/
|
||||
static const char *service_name() { return "Loader"; }
|
||||
|
||||
static constexpr unsigned CAP_QUOTA = 2;
|
||||
|
||||
virtual ~Session() { }
|
||||
|
||||
/**
|
||||
* Allocate dataspace to be used as ROM module by the loaded subsystem
|
||||
*
|
||||
* \param name designated name of the ROM module
|
||||
* \param size size of ROM module
|
||||
*
|
||||
* \return Dataspace_capability dataspace that contains the backing
|
||||
* store of the ROM module
|
||||
*
|
||||
* The content of the dataspace is made visible to the loaded subsystem
|
||||
* not before 'commit_rom_module' has been called. This two-step
|
||||
* procedure enables the client to update the content of the ROM module
|
||||
* during the lifetime of the session by subsequently calling dataspace
|
||||
* with the same name as argument. Each time, a new dataspace is
|
||||
* allocated but not yet presented to the loaded subsystem. When
|
||||
* calling 'commit_rom_module', the most recently allocated dataspace
|
||||
* becomes visible. The server frees intermediate dataspaces that are
|
||||
* no longer used.
|
||||
*/
|
||||
virtual Dataspace_capability alloc_rom_module(Name const &name, size_t size) = 0;
|
||||
|
||||
/**
|
||||
* Expose ROM module to loaded subsystem
|
||||
*
|
||||
* \throw Rom_module_does_not_exist if the ROM module name wasn't
|
||||
* allocated beforehand
|
||||
*/
|
||||
virtual void commit_rom_module(Name const &name) = 0;
|
||||
|
||||
/**
|
||||
* Define capability quota assigned to the subsystem
|
||||
*/
|
||||
virtual void cap_quota(Cap_quota) = 0;
|
||||
|
||||
/**
|
||||
* Define RAM quota assigned to the subsystem
|
||||
*
|
||||
* The quantum specified must be in the bounds of the quota attached
|
||||
* the session. Note that RAM resources used for ROM modules are
|
||||
* accounted, too. If ROM modules are modified at runtime by subsequent
|
||||
* calls of 'alloc_rom_module', the resources needed for the respective
|
||||
* ROM modules are doubled.
|
||||
*
|
||||
* If 'ram_quota' is not called prior calling 'start', all available
|
||||
* session resources will be assigned to the subsystem.
|
||||
*/
|
||||
virtual void ram_quota(Ram_quota quantum) = 0;
|
||||
|
||||
/**
|
||||
* Constrain size of the nitpicker buffer used by the subsystem
|
||||
*
|
||||
* Calling this method prior 'start()' enables the virtualization
|
||||
* of the nitpicker session interface.
|
||||
*/
|
||||
virtual void constrain_geometry(Area size) = 0;
|
||||
|
||||
/**
|
||||
* Set the parent view of the subsystem's view.
|
||||
*
|
||||
* If 'parent_view' is not called prior calling 'start', the
|
||||
* subsystem's view will not have a parent view.
|
||||
*/
|
||||
virtual void parent_view(Gui::View_capability view) = 0;
|
||||
|
||||
/**
|
||||
* Register signal handler notified at creation time of the first view
|
||||
*/
|
||||
virtual void view_ready_sigh(Signal_context_capability sigh) = 0;
|
||||
|
||||
/**
|
||||
* Register signal handler notified when a failure occurs in the
|
||||
* loaded subsystem.
|
||||
*
|
||||
* This signal is delivered if any child process of the subsystem
|
||||
* produces an unresolvable page fault, exists, or triggers a CPU
|
||||
* exception. (e.g., division by zero) For more information about
|
||||
* the possible types of faults, please refer to the documentation of
|
||||
* 'Rm_session::fault_handler' and 'Cpu_session::exception_handler'.
|
||||
*
|
||||
* This method should not be called after the 'start' method.
|
||||
*/
|
||||
virtual void fault_sigh(Signal_context_capability sigh) = 0;
|
||||
|
||||
/**
|
||||
* Start subsystem
|
||||
*
|
||||
* \throw Rom_module_does_not_exist if the specified binary could
|
||||
* not obtained as ROM module
|
||||
*/
|
||||
virtual void start(Name const &binary, Name const &label = "") = 0;
|
||||
|
||||
/**
|
||||
* Set view geometry and buffer offset
|
||||
*/
|
||||
virtual void view_geometry(Rect rect, Point offset) = 0;
|
||||
|
||||
/**
|
||||
* Return view size as initialized by the loaded subsystem
|
||||
*/
|
||||
virtual Area view_size() const = 0;
|
||||
|
||||
|
||||
/*******************
|
||||
** RPC interface **
|
||||
*******************/
|
||||
|
||||
GENODE_RPC(Rpc_alloc_rom_module, Dataspace_capability, alloc_rom_module,
|
||||
Name const &, size_t);
|
||||
GENODE_RPC_THROW(Rpc_commit_rom_module, void, commit_rom_module,
|
||||
GENODE_TYPE_LIST(Rom_module_does_not_exist),
|
||||
Name const &);
|
||||
GENODE_RPC(Rpc_cap_quota, void, cap_quota, Cap_quota);
|
||||
GENODE_RPC(Rpc_ram_quota, void, ram_quota, Ram_quota);
|
||||
GENODE_RPC(Rpc_constrain_geometry, void, constrain_geometry, Area);
|
||||
GENODE_RPC(Rpc_parent_view, void, parent_view, Gui::View_capability);
|
||||
GENODE_RPC(Rpc_view_ready_sigh, void, view_ready_sigh, Signal_context_capability);
|
||||
GENODE_RPC(Rpc_fault_sigh, void, fault_sigh, Signal_context_capability);
|
||||
GENODE_RPC_THROW(Rpc_start, void, start,
|
||||
GENODE_TYPE_LIST(Rom_module_does_not_exist),
|
||||
Name const &, Name const &);
|
||||
GENODE_RPC_THROW(Rpc_view_geometry, void, view_geometry,
|
||||
GENODE_TYPE_LIST(View_does_not_exist),
|
||||
Rect, Point);
|
||||
GENODE_RPC_THROW(Rpc_view_size, Area, view_size,
|
||||
GENODE_TYPE_LIST(View_does_not_exist));
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_alloc_rom_module, Rpc_commit_rom_module,
|
||||
Rpc_cap_quota, Rpc_ram_quota, Rpc_constrain_geometry,
|
||||
Rpc_parent_view, Rpc_view_ready_sigh, Rpc_fault_sigh,
|
||||
Rpc_start, Rpc_view_geometry, Rpc_view_size);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__LOADER_SESSION__LOADER_SESSION_H_ */
|
@ -1,2 +0,0 @@
|
||||
MIRRORED_FROM_REP_DIR := include/loader_session
|
||||
include $(REP_DIR)/recipes/api/session.inc
|
@ -1 +0,0 @@
|
||||
2023-05-26 96b84925b69e7133e72c8e9c1d160c5ba49e36b7
|
@ -1 +0,0 @@
|
||||
Test for changing the configuration of a loader plugin at runtime.
|
@ -1,3 +0,0 @@
|
||||
_/src/init
|
||||
_/src/test-dynamic_config
|
||||
_/src/loader
|
@ -1 +0,0 @@
|
||||
2024-04-11 730c3ed6f7b932dac3f5f3dcbba9e5ddce5a5c2b
|
@ -1,46 +0,0 @@
|
||||
<runtime ram="32M" caps="1000" binary="init">
|
||||
|
||||
<requires> <timer/> </requires>
|
||||
|
||||
<fail after_seconds="20"/>
|
||||
<succeed>
|
||||
[init -> loader -> test-dynamic_config_loader -> -> test-label] obtained counter value 11 from config
|
||||
</succeed>
|
||||
|
||||
<content>
|
||||
<rom label="ld.lib.so"/>
|
||||
<rom label="test-dynamic_config"/>
|
||||
<rom label="test-dynamic_config_loader"/>
|
||||
<rom label="loader"/>
|
||||
</content>
|
||||
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="RM"/>
|
||||
<service name="PD"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="LOG"/>
|
||||
<service name="Timer"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<default caps="200"/>
|
||||
<start name="loader">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides><service name="Loader"/></provides>
|
||||
<config>
|
||||
<policy label_prefix="test-dynamic_config_loader">
|
||||
<parent-rom name="test-dynamic_config"/>
|
||||
<parent-rom name="ld.lib.so"/>
|
||||
</policy>
|
||||
</config>
|
||||
</start>
|
||||
<start name="test-dynamic_config_loader">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
</start>
|
||||
</config>
|
||||
</runtime>
|
@ -1,4 +1,2 @@
|
||||
_/src/init
|
||||
_/src/loader
|
||||
_/src/test-segfault
|
||||
_/src/test-fault_detection
|
||||
|
@ -1,39 +1,14 @@
|
||||
<runtime ram="32M" caps="1000" binary="init">
|
||||
<runtime ram="10M" caps="500" binary="test-fault_detection">
|
||||
|
||||
<fail after_seconds="60"/>
|
||||
<succeed>--- finished fault_detection test ---</succeed>
|
||||
|
||||
<config/>
|
||||
|
||||
<content>
|
||||
<rom label="ld.lib.so"/>
|
||||
<rom label="loader"/>
|
||||
<rom label="test-segfault"/>
|
||||
<rom label="test-fault_detection"/>
|
||||
</content>
|
||||
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="LOG"/>
|
||||
<service name="CPU"/>
|
||||
<service name="RM"/>
|
||||
<service name="PD"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="loader" caps="100">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<provides> <service name="Loader"/> </provides>
|
||||
<config>
|
||||
<policy label_prefix="test-fault_detection">
|
||||
<parent-rom name="test-segfault"/>
|
||||
<parent-rom name="ld.lib.so"/>
|
||||
<parent-rom name="init"/>
|
||||
</policy>
|
||||
</config>
|
||||
</start>
|
||||
<start name="test-fault_detection" caps="500">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
</start>
|
||||
</config>
|
||||
</runtime>
|
||||
|
@ -1,2 +0,0 @@
|
||||
SRC_DIR := src/server/loader include/init
|
||||
include $(GENODE_DIR)/repos/base/recipes/src/content.inc
|
@ -1 +0,0 @@
|
||||
2024-04-11 2e67e65d674e6c3ae78d9d7335ec47ae25b9c6a2
|
@ -1,6 +0,0 @@
|
||||
base
|
||||
os
|
||||
framebuffer_session
|
||||
input_session
|
||||
loader_session
|
||||
gui_session
|
@ -3,5 +3,4 @@ os
|
||||
input_session
|
||||
framebuffer_session
|
||||
gui_session
|
||||
loader_session
|
||||
timer_session
|
||||
|
@ -1,6 +1,5 @@
|
||||
base
|
||||
os
|
||||
loader_session
|
||||
gui_session
|
||||
framebuffer_session
|
||||
input_session
|
||||
|
@ -1,73 +0,0 @@
|
||||
create_boot_directory
|
||||
import_from_depot [depot_user]/src/[base_src] \
|
||||
[depot_user]/pkg/[drivers_interactive_pkg] \
|
||||
[depot_user]/src/init \
|
||||
[depot_user]/src/nitpicker
|
||||
build {
|
||||
server/loader
|
||||
test/loader
|
||||
test/nitpicker
|
||||
}
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<default caps="100"/>
|
||||
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
|
||||
<start name="drivers" caps="1500" managing_system="yes">
|
||||
<resource name="RAM" quantum="64M"/>
|
||||
<binary name="init"/>
|
||||
<route>
|
||||
<service name="ROM" label="config"> <parent label="drivers.config"/> </service>
|
||||
<service name="Timer"> <child name="timer"/> </service>
|
||||
<service name="Capture"> <child name="nitpicker"/> </service>
|
||||
<service name="Event"> <child name="nitpicker"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="nitpicker">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides>
|
||||
<service name="Gui"/> <service name="Capture"/> <service name="Event"/>
|
||||
</provides>
|
||||
<config>
|
||||
<capture/> <event/>
|
||||
<domain name="" layer="2" /> <default-policy domain=""/>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="loader">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Loader"/></provides>
|
||||
<config>
|
||||
<policy label_prefix="test-loader">
|
||||
<parent-rom name="testnit"/>
|
||||
<parent-rom name="ld.lib.so"/>
|
||||
</policy>
|
||||
</config>
|
||||
</start>
|
||||
<start name="test-loader" caps="200">
|
||||
<resource name="RAM" quantum="1G"/>
|
||||
</start>
|
||||
</config>}
|
||||
|
||||
build_boot_image [build_artifacts]
|
||||
run_genode_until forever
|
@ -1,12 +0,0 @@
|
||||
This directory contains a loader service, which allows for the instantiation of
|
||||
subsystems via a session interface. The resources for the new subsystem are
|
||||
provided by the client when opening the session. The client has no control over
|
||||
the functioning of the subsystem except for the controlling the lifetime of the
|
||||
subsystem.
|
||||
|
||||
By default, the loaded subsystem can access only those ROM modules that were
|
||||
loaded into the loader session by the loader client. However, it is possible
|
||||
to define a whitelist of ROM modules to be obtained from the loader's parent.
|
||||
For an example, refer to the example 'run/loader.run' script.
|
||||
|
||||
|
@ -1,138 +0,0 @@
|
||||
/*
|
||||
* \brief Loader child interface
|
||||
* \author Christian Prochaska
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _CHILD_H_
|
||||
#define _CHILD_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/child.h>
|
||||
#include <util/arg_string.h>
|
||||
#include <init/child_policy.h>
|
||||
#include <cpu_session/connection.h>
|
||||
#include <pd_session/connection.h>
|
||||
#include <region_map/client.h>
|
||||
|
||||
namespace Loader {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
typedef Registered<Parent_service> Parent_service;
|
||||
typedef Registry<Parent_service> Parent_services;
|
||||
|
||||
class Child;
|
||||
}
|
||||
|
||||
|
||||
class Loader::Child : public Child_policy
|
||||
{
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
Allocator &_alloc;
|
||||
|
||||
Session_label const _label;
|
||||
Name const _binary_name;
|
||||
|
||||
Cap_quota const _cap_quota;
|
||||
Ram_quota const _ram_quota;
|
||||
|
||||
Parent_services &_parent_services;
|
||||
|
||||
Service &_local_gui_service;
|
||||
Service &_local_rom_service;
|
||||
Service &_local_cpu_service;
|
||||
Service &_local_pd_service;
|
||||
|
||||
Genode::Child _child;
|
||||
|
||||
Service &_matching_service(Service::Name const &name)
|
||||
{
|
||||
if (name == "Gui") return _local_gui_service;
|
||||
if (name == "ROM") return _local_rom_service;
|
||||
if (name == "CPU") return _local_cpu_service;
|
||||
if (name == "PD") return _local_pd_service;
|
||||
|
||||
/* populate session-local parent service registry on demand */
|
||||
Service *service = nullptr;
|
||||
_parent_services.for_each([&] (Parent_service &s) {
|
||||
if (s.name() == name)
|
||||
service = &s; });
|
||||
|
||||
if (service)
|
||||
return *service;
|
||||
|
||||
return *new (_alloc) Parent_service(_parent_services, _env, name);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Child(Env &env,
|
||||
Allocator &alloc,
|
||||
Name const &binary_name,
|
||||
Session_label const &label,
|
||||
Cap_quota cap_quota,
|
||||
Ram_quota ram_quota,
|
||||
Parent_services &parent_services,
|
||||
Service &local_rom_service,
|
||||
Service &local_cpu_service,
|
||||
Service &local_pd_service,
|
||||
Service &local_gui_service,
|
||||
Signal_context_capability /* fault_sigh */)
|
||||
:
|
||||
_env(env),
|
||||
_alloc(alloc),
|
||||
_label(label),
|
||||
_binary_name(binary_name),
|
||||
_cap_quota(Genode::Child::effective_quota(cap_quota)),
|
||||
_ram_quota(Genode::Child::effective_quota(ram_quota)),
|
||||
_parent_services(parent_services),
|
||||
_local_gui_service(local_gui_service),
|
||||
_local_rom_service(local_rom_service),
|
||||
_local_cpu_service(local_cpu_service),
|
||||
_local_pd_service(local_pd_service),
|
||||
_child(_env.rm(), _env.ep().rpc_ep(), *this)
|
||||
{ }
|
||||
|
||||
~Child() { }
|
||||
|
||||
|
||||
/****************************
|
||||
** Child-policy interface **
|
||||
****************************/
|
||||
|
||||
Name name() const override { return _label; }
|
||||
|
||||
Binary_name binary_name() const override { return _binary_name; }
|
||||
|
||||
Pd_session &ref_pd() override { return _env.pd(); }
|
||||
Pd_session_capability ref_pd_cap() const override { return _env.pd_session_cap(); }
|
||||
|
||||
void init(Pd_session &pd, Pd_session_capability pd_cap) override
|
||||
{
|
||||
pd.ref_account(ref_pd_cap());
|
||||
ref_pd().transfer_quota(pd_cap, _cap_quota);
|
||||
ref_pd().transfer_quota(pd_cap, _ram_quota);
|
||||
}
|
||||
|
||||
Route resolve_session_request(Service::Name const &name,
|
||||
Session_label const &label,
|
||||
Session::Diag const diag) override
|
||||
{
|
||||
return Route { .service = _matching_service(name),
|
||||
.label = label,
|
||||
.diag = diag };
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _CHILD_H_ */
|
@ -1,288 +0,0 @@
|
||||
/*
|
||||
* \brief Virtualized GUI session interface exposed to the subsystem
|
||||
* \author Christian Prochaska
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _GUI_H_
|
||||
#define _GUI_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/arg_string.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <base/component.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <gui_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include <input.h>
|
||||
|
||||
namespace Gui {
|
||||
using namespace Genode;
|
||||
class Session_component;
|
||||
}
|
||||
|
||||
|
||||
class Gui::Session_component : public Rpc_object<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Signal handler to be notified once the geometry of the view is
|
||||
* known.
|
||||
*/
|
||||
Signal_context_capability _view_ready_sigh;
|
||||
|
||||
Entrypoint &_ep;
|
||||
|
||||
Area _max_size;
|
||||
|
||||
Gui::Connection _gui;
|
||||
|
||||
View_handle _parent_view_handle;
|
||||
|
||||
/*
|
||||
* Physical view
|
||||
*/
|
||||
View_handle _view_handle;
|
||||
Rect _view_geometry { };
|
||||
Point _view_offset { };
|
||||
|
||||
/*
|
||||
* Geometry of virtual view presented to the loaded subsystem
|
||||
*/
|
||||
Rect _virt_view_geometry { };
|
||||
Point _virt_view_offset { };
|
||||
bool _virt_view_geometry_defined = false;
|
||||
|
||||
Input::Motion_delta _motion_delta { };
|
||||
|
||||
Input::Session_component _proxy_input;
|
||||
|
||||
static long _session_arg(const char *arg, const char *key) {
|
||||
return Arg_string::find_arg(arg, key).long_value(0); }
|
||||
|
||||
/*
|
||||
* Command buffer
|
||||
*/
|
||||
typedef Gui::Session::Command_buffer Command_buffer;
|
||||
Attached_ram_dataspace _command_ds;
|
||||
Command_buffer &_command_buffer = *_command_ds.local_addr<Command_buffer>();
|
||||
|
||||
void _propagate_view_offset()
|
||||
{
|
||||
_gui.enqueue<Command::Offset>(_view_handle,
|
||||
_view_offset + _virt_view_offset);
|
||||
}
|
||||
|
||||
void _update_motion_delta()
|
||||
{
|
||||
_motion_delta = _virt_view_geometry.p1() - _view_geometry.p1();
|
||||
}
|
||||
|
||||
void _execute_command(Command const &command)
|
||||
{
|
||||
switch (command.opcode) {
|
||||
|
||||
case Command::OP_GEOMETRY:
|
||||
{
|
||||
_virt_view_geometry = command.geometry.rect;
|
||||
|
||||
if (!_virt_view_geometry_defined)
|
||||
Signal_transmitter(_view_ready_sigh).submit();
|
||||
|
||||
_virt_view_geometry_defined = true;
|
||||
|
||||
_update_motion_delta();
|
||||
return;
|
||||
}
|
||||
|
||||
case Command::OP_OFFSET:
|
||||
{
|
||||
_virt_view_offset = command.offset.offset;
|
||||
_propagate_view_offset();
|
||||
_gui.execute();
|
||||
return;
|
||||
}
|
||||
|
||||
case Command::OP_TO_FRONT:
|
||||
{
|
||||
_gui.enqueue<Command::To_front>(_view_handle, _parent_view_handle);
|
||||
_gui.execute();
|
||||
return;
|
||||
}
|
||||
|
||||
case Command::OP_TO_BACK:
|
||||
{
|
||||
warning("OP_TO_BACK not implemented");
|
||||
return;
|
||||
}
|
||||
|
||||
case Command::OP_BACKGROUND:
|
||||
{
|
||||
warning("OP_BACKGROUND not implemented");
|
||||
return;
|
||||
}
|
||||
|
||||
case Command::OP_TITLE:
|
||||
{
|
||||
_gui.enqueue(command);
|
||||
_gui.execute();
|
||||
return;
|
||||
}
|
||||
|
||||
case Command::OP_NOP:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(Entrypoint &ep,
|
||||
Env &env,
|
||||
Region_map &rm,
|
||||
Ram_allocator &ram,
|
||||
Area max_size,
|
||||
Gui::View_capability parent_view,
|
||||
Signal_context_capability view_ready_sigh,
|
||||
char const * /* args */)
|
||||
:
|
||||
_view_ready_sigh(view_ready_sigh),
|
||||
_ep(ep),
|
||||
_max_size(max_size),
|
||||
_gui(env),
|
||||
|
||||
/* import parent view */
|
||||
_parent_view_handle(_gui.view_handle(parent_view)),
|
||||
|
||||
/* create GUI view */
|
||||
_view_handle(_gui.create_view(_parent_view_handle)),
|
||||
|
||||
_proxy_input(rm, _gui.input_session(), _motion_delta),
|
||||
|
||||
_command_ds(ram, env.rm(), sizeof(Command_buffer))
|
||||
{
|
||||
_ep.manage(_proxy_input);
|
||||
_ep.manage(*this);
|
||||
}
|
||||
|
||||
~Session_component()
|
||||
{
|
||||
_ep.dissolve(_proxy_input);
|
||||
_ep.dissolve(*this);
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
** GUI session interface **
|
||||
***************************/
|
||||
|
||||
Framebuffer::Session_capability framebuffer_session() override
|
||||
{
|
||||
return _gui.framebuffer_session();
|
||||
}
|
||||
|
||||
Input::Session_capability input_session() override
|
||||
{
|
||||
return _proxy_input.cap();
|
||||
}
|
||||
|
||||
View_handle create_view(View_handle) override
|
||||
{
|
||||
return View_handle(1);
|
||||
}
|
||||
|
||||
void destroy_view(View_handle) override { }
|
||||
|
||||
View_handle view_handle(View_capability, View_handle) override
|
||||
{
|
||||
return View_handle();
|
||||
}
|
||||
|
||||
View_capability view_capability(View_handle) override
|
||||
{
|
||||
return View_capability();
|
||||
}
|
||||
|
||||
void release_view_handle(View_handle) override { }
|
||||
|
||||
Dataspace_capability command_dataspace() override
|
||||
{
|
||||
return _command_ds.cap();
|
||||
}
|
||||
|
||||
void execute() override
|
||||
{
|
||||
for (unsigned i = 0; i < _command_buffer.num(); i++)
|
||||
_execute_command(_command_buffer.get(i));
|
||||
}
|
||||
|
||||
Framebuffer::Mode mode() override
|
||||
{
|
||||
unsigned const mode_width = _max_size.valid() ?
|
||||
_max_size.w() :
|
||||
_gui.mode().area.w();
|
||||
|
||||
unsigned const mode_height = _max_size.valid() ?
|
||||
_max_size.h() :
|
||||
_gui.mode().area.h();
|
||||
|
||||
return Framebuffer::Mode { .area = { mode_width, mode_height } };
|
||||
}
|
||||
|
||||
void mode_sigh(Signal_context_capability) override { }
|
||||
|
||||
void buffer(Framebuffer::Mode mode, bool use_alpha) override
|
||||
{
|
||||
_gui.buffer(mode, use_alpha);
|
||||
}
|
||||
|
||||
void focus(Capability<Session>) override { }
|
||||
|
||||
/**
|
||||
* Return geometry of loader view
|
||||
*/
|
||||
Area loader_view_size() const
|
||||
{
|
||||
int const width = _max_size.valid()
|
||||
? min(_virt_view_geometry.w(), _max_size.w())
|
||||
: _virt_view_geometry.w();
|
||||
|
||||
int const height = _max_size.valid()
|
||||
? min(_virt_view_geometry.h(), _max_size.h())
|
||||
: _virt_view_geometry.h();
|
||||
|
||||
return Area(width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define geometry of loader view
|
||||
*/
|
||||
void loader_view_geometry(Rect rect, Point offset)
|
||||
{
|
||||
typedef Gui::Session::Command Command;
|
||||
|
||||
_view_geometry = rect;
|
||||
_view_offset = offset;
|
||||
|
||||
_propagate_view_offset();
|
||||
_gui.enqueue<Command::Geometry>(_view_handle, _view_geometry);
|
||||
_gui.enqueue<Command::To_front>(_view_handle, _parent_view_handle);
|
||||
_gui.execute();
|
||||
|
||||
_update_motion_delta();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _GUI_H_ */
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* \brief Virtualized input session
|
||||
* \author Christian Prochaska
|
||||
* \author Norman Feske
|
||||
* \date 2010-09-02
|
||||
*
|
||||
* This input service implementation is used by the virtualized GUI
|
||||
* service to translate the input coordinate system from the coordinates
|
||||
* seen by the user of the virtualized session and the physical coordinates
|
||||
* dictated by the loader-session client.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _INPUT_H_
|
||||
#define _INPUT_H_
|
||||
|
||||
#include <base/rpc_server.h>
|
||||
#include <input/event.h>
|
||||
#include <input/keycodes.h>
|
||||
#include <input_session/client.h>
|
||||
|
||||
namespace Input {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
typedef Genode::Point<> Motion_delta;
|
||||
|
||||
class Session_component;
|
||||
}
|
||||
|
||||
|
||||
class Input::Session_component : public Rpc_object<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Session_component(Session_component const &);
|
||||
Session_component &operator = (Session_component const &);
|
||||
|
||||
Session_client _real_input;
|
||||
Motion_delta &_motion_delta;
|
||||
Attached_dataspace _ev_ds;
|
||||
Event * const _ev_buf;
|
||||
|
||||
Genode::Signal_context_capability _sigh { };
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(Region_map &rm,
|
||||
Session_capability real_input,
|
||||
Motion_delta &motion_delta)
|
||||
:
|
||||
_real_input(rm, real_input), _motion_delta(motion_delta),
|
||||
_ev_ds(rm, _real_input.dataspace()),
|
||||
_ev_buf(_ev_ds.local_addr<Event>())
|
||||
{ }
|
||||
|
||||
|
||||
/*****************************
|
||||
** Input session interface **
|
||||
*****************************/
|
||||
|
||||
Dataspace_capability dataspace() override { return _real_input.dataspace(); }
|
||||
|
||||
bool pending() const override { return _real_input.pending(); }
|
||||
|
||||
int flush() override
|
||||
{
|
||||
/* translate mouse position to child's coordinate system */
|
||||
Motion_delta const delta = _motion_delta;
|
||||
|
||||
int const num_ev = _real_input.flush();
|
||||
for (int i = 0; i < num_ev; i++) {
|
||||
|
||||
Input::Event &ev = _ev_buf[i];
|
||||
|
||||
ev.handle_absolute_motion([&] (int x, int y) {
|
||||
Point<> p = Point<>(x, y) + delta;
|
||||
ev = Input::Absolute_motion{p.x(), p.y()};
|
||||
});
|
||||
}
|
||||
|
||||
return num_ev;
|
||||
}
|
||||
|
||||
void sigh(Signal_context_capability sigh) override
|
||||
{
|
||||
/*
|
||||
* Maintain local copy of signal-context capability to keep
|
||||
* NOVA from flushing transitive delegations of the capability.
|
||||
*/
|
||||
_sigh = sigh;
|
||||
|
||||
_real_input.sigh(sigh);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INPUT_H_ */
|
@ -1,438 +0,0 @@
|
||||
/*
|
||||
* \brief Loader service
|
||||
* \author Norman Feske
|
||||
* \date 2012-04-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2017 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/session_object.h>
|
||||
#include <loader_session/loader_session.h>
|
||||
#include <root/component.h>
|
||||
#include <os/session_policy.h>
|
||||
|
||||
/* local includes */
|
||||
#include <child.h>
|
||||
#include <gui.h>
|
||||
#include <rom.h>
|
||||
|
||||
|
||||
namespace Loader {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
class Session_component;
|
||||
class Root;
|
||||
}
|
||||
|
||||
|
||||
class Loader::Session_component : public Session_object<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
struct Local_rom_factory : Local_service<Rom_session_component>::Factory
|
||||
{
|
||||
Entrypoint &_ep;
|
||||
Allocator &_md_alloc;
|
||||
Rom_module_registry &_rom_modules;
|
||||
Mutex _mutex { };
|
||||
List<Rom_session_component> _rom_sessions { };
|
||||
|
||||
void _close(Rom_session_component &rom)
|
||||
{
|
||||
_rom_sessions.remove(&rom);
|
||||
Genode::destroy(_md_alloc, &rom);
|
||||
}
|
||||
|
||||
Local_rom_factory(Entrypoint &ep,
|
||||
Allocator &md_alloc,
|
||||
Rom_module_registry &rom_modules)
|
||||
:
|
||||
_ep(ep), _md_alloc(md_alloc), _rom_modules(rom_modules)
|
||||
{ }
|
||||
|
||||
~Local_rom_factory()
|
||||
{
|
||||
Mutex::Guard guard(_mutex);
|
||||
|
||||
while (_rom_sessions.first())
|
||||
_close(*_rom_sessions.first());
|
||||
}
|
||||
|
||||
Rom_session_component &create(Args const &args, Affinity) override
|
||||
{
|
||||
/* try to find ROM module at local ROM service */
|
||||
try {
|
||||
Mutex::Guard guard(_mutex);
|
||||
|
||||
Session_label const label = label_from_args(args.string());
|
||||
Session_label const name = label.last_element();
|
||||
|
||||
Rom_module &module = _rom_modules.lookup_and_lock(name.string());
|
||||
|
||||
Rom_session_component *rom = new (_md_alloc)
|
||||
Rom_session_component(_ep, module);
|
||||
|
||||
_rom_sessions.insert(rom);
|
||||
|
||||
return *rom;
|
||||
|
||||
} catch (...) { }
|
||||
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
void upgrade(Rom_session_component &, Args const &) override { }
|
||||
|
||||
void destroy(Rom_session_component &session) override
|
||||
{
|
||||
Mutex::Guard guard(_mutex);
|
||||
|
||||
_close(session);
|
||||
}
|
||||
};
|
||||
|
||||
typedef Local_service<Rom_session_component> Local_rom_service;
|
||||
|
||||
/**
|
||||
* Common base class of 'Local_cpu_service' and 'Local_pd_service'
|
||||
*/
|
||||
struct Intercepted_parent_service : Genode::Parent_service
|
||||
{
|
||||
Signal_context_capability fault_sigh { };
|
||||
|
||||
Intercepted_parent_service(Env &env, Service::Name const &name)
|
||||
: Parent_service(env, name) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Intercept CPU session requests to install default exception
|
||||
* handler
|
||||
*/
|
||||
struct Local_cpu_service : Intercepted_parent_service
|
||||
{
|
||||
Local_cpu_service(Env &env) : Intercepted_parent_service(env, "CPU") { }
|
||||
|
||||
void initiate_request(Session_state &session) override
|
||||
{
|
||||
Intercepted_parent_service::initiate_request(session);
|
||||
|
||||
if (session.phase != Session_state::AVAILABLE)
|
||||
return;
|
||||
|
||||
Cpu_session_client cpu(reinterpret_cap_cast<Cpu_session>(session.cap));
|
||||
cpu.exception_sigh(fault_sigh);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Intercept PD session requests to install default fault handler
|
||||
*/
|
||||
struct Local_pd_service : Intercepted_parent_service
|
||||
{
|
||||
Local_pd_service(Env &env) : Intercepted_parent_service(env, "PD") { }
|
||||
|
||||
void initiate_request(Session_state &session) override
|
||||
{
|
||||
Intercepted_parent_service::initiate_request(session);
|
||||
|
||||
if (session.phase != Session_state::AVAILABLE)
|
||||
return;
|
||||
|
||||
Pd_session_client pd(reinterpret_cap_cast<Pd_session>(session.cap));
|
||||
|
||||
Region_map_client(pd.address_space()).fault_handler(fault_sigh);
|
||||
Region_map_client(pd.stack_area()) .fault_handler(fault_sigh);
|
||||
Region_map_client(pd.linker_area()) .fault_handler(fault_sigh);
|
||||
}
|
||||
};
|
||||
|
||||
struct Local_gui_factory : Local_service<Gui::Session_component>::Factory
|
||||
{
|
||||
Entrypoint &_ep;
|
||||
Env &_env;
|
||||
Region_map &_rm;
|
||||
Ram_allocator &_ram;
|
||||
|
||||
Area _max_size { };
|
||||
Gui::View_capability _parent_view { };
|
||||
|
||||
Signal_context_capability view_ready_sigh { };
|
||||
|
||||
Constructible<Gui::Session_component> session { };
|
||||
|
||||
Local_gui_factory(Entrypoint &ep, Env &env,
|
||||
Region_map &rm, Ram_allocator &ram)
|
||||
: _ep(ep), _env(env), _rm(rm), _ram(ram) { }
|
||||
|
||||
void constrain_geometry(Area size) { _max_size = size; }
|
||||
|
||||
void parent_view(Gui::View_capability view)
|
||||
{
|
||||
_parent_view = view;
|
||||
}
|
||||
|
||||
Gui::Session_component &create(Args const &args, Affinity) override
|
||||
{
|
||||
if (session.constructed()) {
|
||||
Genode::warning("attempt to open more than one GUI session");
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
session.construct(_ep, _env, _rm, _ram, _max_size,
|
||||
_parent_view, view_ready_sigh, args.string());
|
||||
return *session;
|
||||
}
|
||||
|
||||
void upgrade(Gui::Session_component &, Args const &) override { }
|
||||
void destroy(Gui::Session_component &) override { }
|
||||
};
|
||||
|
||||
typedef Local_service<Gui::Session_component> Local_gui_service;
|
||||
|
||||
enum { STACK_SIZE = 2*4096 };
|
||||
|
||||
Env &_env;
|
||||
Xml_node const _config;
|
||||
Constrained_ram_allocator _local_ram { _env.ram(), _ram_quota_guard(),
|
||||
_cap_quota_guard() };
|
||||
Heap _md_alloc { _local_ram, _env.rm() };
|
||||
size_t _subsystem_cap_quota_limit = 0;
|
||||
size_t _subsystem_ram_quota_limit = 0;
|
||||
Parent_services _parent_services { };
|
||||
Rom_module_registry _rom_modules { _env, _config, _local_ram, _md_alloc };
|
||||
Local_rom_factory _rom_factory { _env.ep(), _md_alloc, _rom_modules };
|
||||
Local_rom_service _rom_service { _rom_factory };
|
||||
Local_cpu_service _cpu_service { _env };
|
||||
Local_pd_service _pd_service { _env };
|
||||
Local_gui_factory _gui_factory { _env.ep(), _env, _env.rm(), _local_ram };
|
||||
Local_gui_service _gui_service { _gui_factory };
|
||||
Signal_context_capability _fault_sigh { };
|
||||
Constructible<Child> _child { };
|
||||
|
||||
/**
|
||||
* Return virtual GUI session component
|
||||
*/
|
||||
Gui::Session_component &_virtual_gui_session()
|
||||
{
|
||||
if (!_gui_factory.session.constructed())
|
||||
throw View_does_not_exist();
|
||||
|
||||
return *_gui_factory.session;
|
||||
}
|
||||
|
||||
Gui::Session_component const &_virtual_gui_session() const
|
||||
{
|
||||
if (!_gui_factory.session.constructed())
|
||||
throw View_does_not_exist();
|
||||
|
||||
return *_gui_factory.session;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(Env &env, Session_label const &label, Xml_node config,
|
||||
Resources const &resources)
|
||||
:
|
||||
Session_object(env.ep(), resources, label, Diag { }),
|
||||
_env(env), _config(config)
|
||||
{
|
||||
/* fetch all parent-provided ROMs according to the config */
|
||||
config.for_each_sub_node("parent-rom", [&] (Xml_node rom)
|
||||
{
|
||||
typedef Rom_module::Name Name;
|
||||
Name name = rom.attribute_value("name", Name());
|
||||
_rom_modules.fetch_parent_rom_module(name);
|
||||
});
|
||||
}
|
||||
|
||||
~Session_component()
|
||||
{
|
||||
_child.destruct();
|
||||
|
||||
/*
|
||||
* The parent-service registry is populated by the 'Child'
|
||||
* on demand. Revert those allocations.
|
||||
*/
|
||||
_parent_services.for_each([&] (Parent_service &service) {
|
||||
destroy(_md_alloc, &service); });
|
||||
}
|
||||
|
||||
|
||||
/******************************
|
||||
** Loader session interface **
|
||||
******************************/
|
||||
|
||||
Dataspace_capability alloc_rom_module(Name const &name, size_t size) override
|
||||
{
|
||||
return _rom_modules.alloc_rom_module(name.string(), size);
|
||||
}
|
||||
|
||||
void commit_rom_module(Name const &name) override
|
||||
{
|
||||
try {
|
||||
_rom_modules.commit_rom_module(name.string()); }
|
||||
catch (Rom_module_registry::Lookup_failed) {
|
||||
throw Rom_module_does_not_exist(); }
|
||||
}
|
||||
|
||||
void cap_quota(Cap_quota caps) override
|
||||
{
|
||||
_subsystem_cap_quota_limit = caps.value;
|
||||
}
|
||||
|
||||
void ram_quota(Ram_quota quantum) override
|
||||
{
|
||||
_subsystem_ram_quota_limit = quantum.value;
|
||||
}
|
||||
|
||||
void constrain_geometry(Area size) override
|
||||
{
|
||||
_gui_factory.constrain_geometry(size);
|
||||
}
|
||||
|
||||
void parent_view(Gui::View_capability view) override
|
||||
{
|
||||
_gui_factory.parent_view(view);
|
||||
}
|
||||
|
||||
void view_ready_sigh(Signal_context_capability sigh) override
|
||||
{
|
||||
_gui_factory.view_ready_sigh = sigh;
|
||||
}
|
||||
|
||||
void fault_sigh(Signal_context_capability sigh) override
|
||||
{
|
||||
/*
|
||||
* CPU exception handler for CPU sessions originating from the
|
||||
* subsystem.
|
||||
*/
|
||||
_cpu_service.fault_sigh = sigh;
|
||||
|
||||
/*
|
||||
* Region-map fault handler for PD sessions originating from the
|
||||
* subsystem.
|
||||
*/
|
||||
_pd_service.fault_sigh = sigh;
|
||||
|
||||
/*
|
||||
* CPU exception and RM fault handler for the immediate child.
|
||||
*/
|
||||
_fault_sigh = sigh;
|
||||
}
|
||||
|
||||
void start(Name const &binary_name, Name const &label) override
|
||||
{
|
||||
if (_child.constructed()) {
|
||||
warning("cannot start subsystem twice");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t const avail_cap_quota = _cap_quota_guard().avail().value;
|
||||
|
||||
size_t const cap_quota = (_subsystem_cap_quota_limit > 0)
|
||||
? min(_subsystem_cap_quota_limit, avail_cap_quota)
|
||||
: avail_cap_quota;
|
||||
|
||||
size_t const avail_ram_quota = _ram_quota_guard().avail().value;
|
||||
|
||||
size_t const ram_quota = (_subsystem_ram_quota_limit > 0)
|
||||
? min(_subsystem_ram_quota_limit, avail_ram_quota)
|
||||
: avail_ram_quota;
|
||||
|
||||
try {
|
||||
_child.construct(_env, _md_alloc, binary_name.string(),
|
||||
prefixed_label(_label, Session_label(label.string())),
|
||||
Cap_quota{cap_quota}, Ram_quota{ram_quota},
|
||||
_parent_services, _rom_service,
|
||||
_cpu_service, _pd_service, _gui_service,
|
||||
_fault_sigh);
|
||||
}
|
||||
catch (Genode::Service_denied) {
|
||||
throw Rom_module_does_not_exist(); }
|
||||
}
|
||||
|
||||
void view_geometry(Rect rect, Point offset) override
|
||||
{
|
||||
_virtual_gui_session().loader_view_geometry(rect, offset);
|
||||
}
|
||||
|
||||
Area view_size() const override
|
||||
{
|
||||
return _virtual_gui_session().loader_view_size();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Loader::Root : public Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
Xml_node const _config;
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args) override
|
||||
{
|
||||
Xml_node session_config("<policy/>");
|
||||
|
||||
Session_label const label = label_from_args(args);
|
||||
|
||||
try { session_config = Session_policy(label, _config); }
|
||||
catch (...) { }
|
||||
|
||||
return new (md_alloc())
|
||||
Session_component(_env, label, session_config,
|
||||
session_resources_from_args(args));
|
||||
}
|
||||
|
||||
void _upgrade_session(Session_component *s, const char *args) override
|
||||
{
|
||||
s->upgrade(ram_quota_from_args(args));
|
||||
s->upgrade(cap_quota_from_args(args));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root(Env &env, Xml_node config, Allocator &md_alloc)
|
||||
:
|
||||
Root_component<Session_component>(&env.ep().rpc_ep(), &md_alloc),
|
||||
_env(env), _config(config)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
namespace Loader { struct Main; }
|
||||
|
||||
|
||||
struct Loader::Main
|
||||
{
|
||||
Env &_env;
|
||||
|
||||
Heap _heap { _env.ram(), _env.rm() };
|
||||
|
||||
Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
Root _root { _env, _config.xml(), _heap };
|
||||
|
||||
Main(Env &env) : _env(env)
|
||||
{
|
||||
_env.parent().announce(_env.ep().manage(_root));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Loader::Main main(env); }
|
@ -1,301 +0,0 @@
|
||||
/*
|
||||
* \brief ROM service exposed to the loaded subsystem
|
||||
* \author Norman Feske
|
||||
* \date 2012-04-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _ROM_H_
|
||||
#define _ROM_H_
|
||||
|
||||
#include <rom_session/rom_session.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Rom_module : public List<Rom_module>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
typedef String<128> Name;
|
||||
|
||||
private:
|
||||
|
||||
Name const _name;
|
||||
|
||||
Ram_allocator &_ram;
|
||||
Attached_ram_dataspace _fg;
|
||||
Attached_ram_dataspace _bg;
|
||||
|
||||
Constructible<Attached_rom_dataspace> _parent_rom { };
|
||||
|
||||
bool _bg_has_pending_data = false;
|
||||
|
||||
Signal_context_capability _sigh { };
|
||||
|
||||
Blockade _blockade { };
|
||||
|
||||
public:
|
||||
|
||||
enum Origin { PARENT_PROVIDED, SESSION_LOCAL };
|
||||
|
||||
Rom_module(Env &env, Xml_node /* config */, Name const &name,
|
||||
Ram_allocator &ram_allocator, Origin origin)
|
||||
:
|
||||
_name(name), _ram(ram_allocator),
|
||||
_fg(_ram, env.rm(), 0), _bg(_ram, env.rm(), 0)
|
||||
{
|
||||
if (origin == SESSION_LOCAL)
|
||||
return;
|
||||
|
||||
try {
|
||||
_parent_rom.construct(env, name.string()); }
|
||||
catch (...) {
|
||||
warning("ROM ", name, " unavailable from parent, "
|
||||
"try to use session-local ROM");
|
||||
}
|
||||
}
|
||||
|
||||
bool has_name(Name const &name) const { return _name == name; }
|
||||
|
||||
void lock() { _blockade.block(); }
|
||||
void unlock() { _blockade.wakeup(); }
|
||||
|
||||
/**
|
||||
* Return dataspace as handed out to loader session
|
||||
*
|
||||
* The loader session submits the data into the ROM module into
|
||||
* the background dataspace. Once it is ready, the 'commit_bg()'
|
||||
* function is called.
|
||||
*/
|
||||
Dataspace_capability bg_dataspace(size_t size)
|
||||
{
|
||||
/* let background buffer grow if needed */
|
||||
if (_bg.size() < size)
|
||||
_bg.realloc(&_ram, size);
|
||||
|
||||
return _bg.cap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return dataspace as handed out to ROM session client
|
||||
*/
|
||||
Rom_dataspace_capability fg_dataspace()
|
||||
{
|
||||
if (_parent_rom.constructed())
|
||||
return static_cap_cast<Rom_dataspace>(_parent_rom->cap());
|
||||
|
||||
if (!_fg.size() && !_bg_has_pending_data) {
|
||||
Genode::error("no data loaded");
|
||||
return Rom_dataspace_capability();
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep foreground if no background exists. Otherwise, use
|
||||
* old background as new foreground.
|
||||
*/
|
||||
if (_bg_has_pending_data) {
|
||||
_fg.swap(_bg);
|
||||
_bg_has_pending_data = false;
|
||||
}
|
||||
|
||||
Dataspace_capability ds_cap = _fg.cap();
|
||||
return static_cap_cast<Rom_dataspace>(ds_cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set signal handler to inform about ROM module updates
|
||||
*
|
||||
* This function is indirectly called by the ROM session client.
|
||||
*/
|
||||
void sigh(Signal_context_capability sigh)
|
||||
{
|
||||
if (_parent_rom.constructed())
|
||||
_parent_rom->sigh(sigh);
|
||||
|
||||
_sigh = sigh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit data contained in background dataspace
|
||||
*
|
||||
* This function is indirectly called by the loader session.
|
||||
*/
|
||||
void commit_bg()
|
||||
{
|
||||
_bg_has_pending_data = true;
|
||||
|
||||
if (_sigh.valid())
|
||||
Signal_transmitter(_sigh).submit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Rom_module_lock_guard
|
||||
{
|
||||
Rom_module &rom;
|
||||
|
||||
Rom_module_lock_guard(Rom_module &rom) : rom(rom) { }
|
||||
|
||||
~Rom_module_lock_guard() { rom.unlock(); }
|
||||
};
|
||||
|
||||
|
||||
class Rom_module_registry
|
||||
{
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
Xml_node const _config;
|
||||
Mutex _mutex { };
|
||||
Ram_allocator &_ram_allocator;
|
||||
Allocator &_md_alloc;
|
||||
List<Rom_module> _list { };
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Exception type
|
||||
*/
|
||||
class Lookup_failed { };
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param ram_allocator RAM allocator used as backing store for
|
||||
* module data
|
||||
* \param md_alloc backing store for ROM module meta data
|
||||
*/
|
||||
Rom_module_registry(Env &env, Xml_node config,
|
||||
Ram_allocator &ram_allocator,
|
||||
Allocator &md_alloc)
|
||||
:
|
||||
_env(env), _config(config), _ram_allocator(ram_allocator),
|
||||
_md_alloc(md_alloc)
|
||||
{ }
|
||||
|
||||
~Rom_module_registry()
|
||||
{
|
||||
Mutex::Guard guard(_mutex);
|
||||
|
||||
while (_list.first()) {
|
||||
Rom_module *rom = _list.first();
|
||||
rom->lock();
|
||||
_list.remove(rom);
|
||||
destroy(&_md_alloc, rom);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup ROM module by name
|
||||
*
|
||||
* \throw Lookup_failed
|
||||
*/
|
||||
Rom_module &lookup_and_lock(Rom_module::Name const &name)
|
||||
{
|
||||
Mutex::Guard guard(_mutex);
|
||||
|
||||
Rom_module *curr = _list.first();
|
||||
for (; curr; curr = curr->next()) {
|
||||
if (curr->has_name(name)) {
|
||||
curr->lock();
|
||||
return *curr;
|
||||
}
|
||||
}
|
||||
throw Lookup_failed();
|
||||
}
|
||||
|
||||
Dataspace_capability alloc_rom_module(Rom_module::Name const &name, size_t size)
|
||||
{
|
||||
try {
|
||||
Rom_module &module = lookup_and_lock(name);
|
||||
Rom_module_lock_guard guard(module);
|
||||
return module.bg_dataspace(size);
|
||||
}
|
||||
catch (Lookup_failed) {
|
||||
|
||||
Mutex::Guard guard(_mutex);
|
||||
|
||||
Rom_module *module = new (&_md_alloc)
|
||||
Rom_module(_env, _config, name, _ram_allocator,
|
||||
Rom_module::SESSION_LOCAL);
|
||||
|
||||
Rom_module_lock_guard module_guard(*module);
|
||||
|
||||
_list.insert(module);
|
||||
|
||||
return module->bg_dataspace(size);
|
||||
}
|
||||
}
|
||||
|
||||
void fetch_parent_rom_module(Rom_module::Name const &name)
|
||||
{
|
||||
try {
|
||||
lookup_and_lock(name);
|
||||
}
|
||||
catch (Lookup_failed) {
|
||||
|
||||
Mutex::Guard guard(_mutex);
|
||||
|
||||
Rom_module *module = new (&_md_alloc)
|
||||
Rom_module(_env, _config, name, _ram_allocator,
|
||||
Rom_module::PARENT_PROVIDED);
|
||||
|
||||
Rom_module_lock_guard module_guard(*module);
|
||||
|
||||
_list.insert(module);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \throw Lookup_failed
|
||||
*/
|
||||
void commit_rom_module(char const *name)
|
||||
{
|
||||
Rom_module &rom_module = lookup_and_lock(name);
|
||||
rom_module.commit_bg();
|
||||
rom_module.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Rom_session_component : public Rpc_object<Rom_session>,
|
||||
private List<Rom_session_component>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
friend class List<Rom_session_component>;
|
||||
|
||||
Entrypoint &_ep;
|
||||
Rom_module &_rom_module;
|
||||
|
||||
public:
|
||||
|
||||
Rom_session_component(Entrypoint &ep, Rom_module &rom_module)
|
||||
: _ep(ep), _rom_module(rom_module) { _ep.manage(*this); }
|
||||
|
||||
~Rom_session_component() { _ep.dissolve(*this); }
|
||||
|
||||
Rom_dataspace_capability dataspace() override
|
||||
{
|
||||
Rom_module_lock_guard guard(_rom_module);
|
||||
return _rom_module.fg_dataspace();
|
||||
}
|
||||
|
||||
void sigh(Signal_context_capability sigh) override
|
||||
{
|
||||
Rom_module_lock_guard guard(_rom_module);
|
||||
_rom_module.sigh(sigh);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _ROM_H_ */
|
@ -1,4 +0,0 @@
|
||||
TARGET = loader
|
||||
LIBS = base
|
||||
SRC_CC = main.cc
|
||||
INC_DIR += $(PRG_DIR)
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* \brief Test for changing the configuration of a loader plugin at runtime
|
||||
* \author Christian Prochaska
|
||||
* \date 2012-04-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <timer_session/connection.h>
|
||||
#include <loader_session/connection.h>
|
||||
#include <base/component.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
struct Main
|
||||
{
|
||||
enum { CONFIG_SIZE = 100 };
|
||||
|
||||
Env &env;
|
||||
int counter { -1 };
|
||||
Loader::Connection loader { env, Ram_quota{8*1024*1024}, Cap_quota{100} };
|
||||
Timer::Connection timer { env };
|
||||
Signal_handler<Main> timer_handler { env.ep(), *this, &Main::handle_timer };
|
||||
|
||||
void handle_timer()
|
||||
{
|
||||
char *config_ds_addr =
|
||||
env.rm().attach(loader.alloc_rom_module("config", CONFIG_SIZE));
|
||||
|
||||
String<100> config("<config><counter>", counter++, "</counter></config>");
|
||||
copy_cstring(config_ds_addr, config.string(), CONFIG_SIZE);
|
||||
env.rm().detach(config_ds_addr);
|
||||
loader.commit_rom_module("config");
|
||||
timer.trigger_once(250 * 1000);
|
||||
}
|
||||
|
||||
Main(Env &env) : env(env)
|
||||
{
|
||||
timer.sigh(timer_handler);
|
||||
handle_timer();
|
||||
loader.start("test-dynamic_config", "test-label");
|
||||
}
|
||||
};
|
||||
|
||||
void Component::construct(Env &env) { static Main main(env); }
|
@ -1,3 +0,0 @@
|
||||
TARGET = test-dynamic_config_loader
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
@ -16,7 +16,6 @@
|
||||
#include <base/child.h>
|
||||
#include <rom_session/connection.h>
|
||||
#include <log_session/log_session.h>
|
||||
#include <loader_session/connection.h>
|
||||
#include <region_map/client.h>
|
||||
|
||||
using namespace Genode;
|
||||
@ -151,120 +150,25 @@ struct Faulting_child_test
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************
|
||||
** Test for detecting failures in a child started by the loader **
|
||||
******************************************************************/
|
||||
|
||||
struct Faulting_loader_child_test
|
||||
{
|
||||
static char const *name() { return "failure detection in loaded child"; }
|
||||
|
||||
Constructible<Loader::Connection> loader;
|
||||
|
||||
void start_iteration(Env &env, Signal_context_capability fault_sigh)
|
||||
{
|
||||
loader.construct(env, Ram_quota{1024*1024}, Cap_quota{100});
|
||||
|
||||
/* register fault handler at loader session */
|
||||
loader->fault_sigh(fault_sigh);
|
||||
|
||||
/* start subsystem */
|
||||
loader->start("test-segfault");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
** Test for detecting failures in a grandchild started by the loader **
|
||||
***********************************************************************/
|
||||
|
||||
struct Faulting_loader_grand_child_test
|
||||
{
|
||||
static char const *name() { return "failure detection of loaded grand child"; }
|
||||
|
||||
static char const *config()
|
||||
{
|
||||
return
|
||||
"<config>\n"
|
||||
" <parent-provides>\n"
|
||||
" <service name=\"ROM\"/>\n"
|
||||
" <service name=\"CPU\"/>\n"
|
||||
" <service name=\"PD\"/>\n"
|
||||
" <service name=\"LOG\"/>\n"
|
||||
" </parent-provides>\n"
|
||||
" <default-route>\n"
|
||||
" <any-service> <parent/> <any-child/> </any-service>\n"
|
||||
" </default-route>\n"
|
||||
" <start name=\"test-segfault\" caps=\"50\">\n"
|
||||
" <resource name=\"RAM\" quantum=\"2M\"/>\n"
|
||||
" </start>\n"
|
||||
"</config>";
|
||||
}
|
||||
|
||||
static size_t config_size() { return strlen(config()); }
|
||||
|
||||
Constructible<Loader::Connection> loader;
|
||||
|
||||
void start_iteration(Env &env, Signal_context_capability fault_sigh)
|
||||
{
|
||||
loader.construct(env, Ram_quota{4*1024*1024}, Cap_quota{130});
|
||||
|
||||
/* import config into loader session */
|
||||
{
|
||||
Attached_dataspace ds(env.rm(),
|
||||
loader->alloc_rom_module("config", config_size()));
|
||||
memcpy(ds.local_addr<char>(), config(), config_size());
|
||||
loader->commit_rom_module("config");
|
||||
}
|
||||
|
||||
/* register fault handler at loader session */
|
||||
loader->fault_sigh(fault_sigh);
|
||||
|
||||
/* start subsystem */
|
||||
loader->start("init", "init");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Main
|
||||
{
|
||||
Env &_env;
|
||||
|
||||
Constructible<Iterative_test<Faulting_child_test> > _test_1 { };
|
||||
Constructible<Iterative_test<Faulting_loader_child_test> > _test_2 { };
|
||||
Constructible<Iterative_test<Faulting_loader_grand_child_test> > _test_3 { };
|
||||
Constructible<Iterative_test<Faulting_child_test> > _test { };
|
||||
|
||||
Signal_handler<Main> _test_1_finished_handler {
|
||||
_env.ep(), *this, &Main::_handle_test_1_finished };
|
||||
Signal_handler<Main> _test_finished_handler {
|
||||
_env.ep(), *this, &Main::_handle_test_finished };
|
||||
|
||||
Signal_handler<Main> _test_2_finished_handler {
|
||||
_env.ep(), *this, &Main::_handle_test_2_finished };
|
||||
|
||||
Signal_handler<Main> _test_3_finished_handler {
|
||||
_env.ep(), *this, &Main::_handle_test_3_finished };
|
||||
|
||||
void _handle_test_1_finished()
|
||||
void _handle_test_finished()
|
||||
{
|
||||
_test_1.destruct();
|
||||
_test_2.construct(_env, _test_2_finished_handler);
|
||||
}
|
||||
|
||||
void _handle_test_2_finished()
|
||||
{
|
||||
_test_2.destruct();
|
||||
_test_3.construct(_env, _test_3_finished_handler);
|
||||
}
|
||||
|
||||
void _handle_test_3_finished()
|
||||
{
|
||||
_test_3.destruct();
|
||||
_test.destruct();
|
||||
log("--- finished fault_detection test ---");
|
||||
_env.parent().exit(0);
|
||||
}
|
||||
|
||||
Main(Env &env) : _env(env)
|
||||
{
|
||||
_test_1.construct(_env, _test_1_finished_handler);
|
||||
_test.construct(_env, _test_finished_handler);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* \brief Loader test program
|
||||
* \author Christian Prochaska
|
||||
* \date 2011-07-07
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2017 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 <base/component.h>
|
||||
#include <loader_session/connection.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
namespace Test {
|
||||
using namespace Genode;
|
||||
struct Main;
|
||||
}
|
||||
|
||||
|
||||
struct Test::Main
|
||||
{
|
||||
Env &_env;
|
||||
|
||||
Loader::Connection _loader { _env, Ram_quota{8*1024*1024}, Cap_quota{100} };
|
||||
Timer::Connection _timer { _env };
|
||||
|
||||
Loader::Area _size { };
|
||||
Loader::Point _pos { };
|
||||
|
||||
void _handle_view_ready()
|
||||
{
|
||||
_size = _loader.view_size();
|
||||
_timer.trigger_periodic(250*1000);
|
||||
}
|
||||
|
||||
Signal_handler<Main> _view_ready_handler {
|
||||
_env.ep(), *this, &Main::_handle_view_ready };
|
||||
|
||||
void _handle_timer()
|
||||
{
|
||||
_loader.view_geometry(Loader::Rect(_pos, _size), Loader::Point(0, 0));
|
||||
_pos = Loader::Point((_pos.x() + 50) % 500, (_pos.y() + 30) % 300);
|
||||
}
|
||||
|
||||
Signal_handler<Main> _timer_handler {
|
||||
_env.ep(), *this, &Main::_handle_timer };
|
||||
|
||||
Main(Env &env) : _env(env)
|
||||
{
|
||||
_loader.view_ready_sigh(_view_ready_handler);
|
||||
_timer.sigh(_timer_handler);
|
||||
|
||||
_loader.start("testnit", "test-label");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Test::Main main(env); }
|
@ -1,3 +0,0 @@
|
||||
TARGET = test-loader
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
Loading…
x
Reference in New Issue
Block a user