From 99cb585b6ee1dff088a374a0c3103862af485ef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Mon, 15 Jul 2019 17:32:20 +0200 Subject: [PATCH] libports: system RTC server and test For now in libports because it relies on contrib sources from musl doing the time data conversion. Issue #3450 --- repos/libports/run/system_rtc.run | 99 ++++++ repos/libports/src/server/system_rtc/README | 17 + repos/libports/src/server/system_rtc/main.cc | 291 ++++++++++++++++++ .../libports/src/server/system_rtc/target.mk | 10 + repos/libports/src/test/system_rtc/main.cc | 167 ++++++++++ repos/libports/src/test/system_rtc/target.mk | 3 + 6 files changed, 587 insertions(+) create mode 100644 repos/libports/run/system_rtc.run create mode 100644 repos/libports/src/server/system_rtc/README create mode 100644 repos/libports/src/server/system_rtc/main.cc create mode 100644 repos/libports/src/server/system_rtc/target.mk create mode 100644 repos/libports/src/test/system_rtc/main.cc create mode 100644 repos/libports/src/test/system_rtc/target.mk diff --git a/repos/libports/run/system_rtc.run b/repos/libports/run/system_rtc.run new file mode 100644 index 000000000..fb18a8433 --- /dev/null +++ b/repos/libports/run/system_rtc.run @@ -0,0 +1,99 @@ +# RTC test + +assert_spec x86 + +if {[expr ![have_include power_on/qemu]]} { + puts "Test requires Qemu." + exit 0 +} + +set build_components { + core init timer drivers/rtc server/system_rtc test/system_rtc + server/report_rom +} + +build $build_components + +create_boot_directory + +set config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +set boot_components { + core ld.lib.so init timer rtc_drv test-system_rtc system_rtc + report_rom +} + +build_boot_image $boot_components + +append qemu_args " -nographic " + +run_genode_until ".*--- system RTC test finished ---.*\n" 60 diff --git a/repos/libports/src/server/system_rtc/README b/repos/libports/src/server/system_rtc/README new file mode 100644 index 000000000..58fa79118 --- /dev/null +++ b/repos/libports/src/server/system_rtc/README @@ -0,0 +1,17 @@ +The system RTC component provides access to a synthetic real time clock. While +it can get its initial value from a hardware RTC, it will interpolate the time +by using a Timer session at runtime. + +Like the RTC driver component, if the 'allow_setting_rtc' attribute in the +'config' node is set to 'yes', it will use the content of the 'set_rtc' ROM to +update the RTC value. A valid ROM must contain a top node with the following +attributes: + +* 'year' (e.g. 2019) +* 'month' (1 - 12) +* 'day' (1 - 31) +* 'hour' (0 - 23) +* 'minute' (0 - 59) +* 'second' (0 - 59) + +The component will always report the time as 24h day in UTC. diff --git a/repos/libports/src/server/system_rtc/main.cc b/repos/libports/src/server/system_rtc/main.cc new file mode 100644 index 000000000..22d38a557 --- /dev/null +++ b/repos/libports/src/server/system_rtc/main.cc @@ -0,0 +1,291 @@ +/* + * \brief System RTC server + * \author Josef Soentgen + * \date 2019-07-15 + */ + +/* + * Copyright (C) 2019 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 +#include +#include +#include +#include +#include +#include + +/* local includes */ +namespace Contrib { +#include +}; /* Contrib */ + + +namespace Util { + + Genode::int64_t convert(Rtc::Timestamp const &ts) + { + Contrib::tm tm; + Genode::memset(&tm, 0, sizeof(Contrib::tm)); + tm.tm_sec = ts.second; + tm.tm_min = ts.minute; + tm.tm_hour = ts.hour; + tm.tm_mday = ts.day; + tm.tm_mon = ts.month - 1; + tm.tm_year = ts.year - 1900; + + return Contrib::tm_to_secs(&tm); + } + + Rtc::Timestamp convert(Genode::int64_t t) + { + Contrib::tm tm; + Genode::memset(&tm, 0, sizeof(Contrib::tm)); + + int const err = Contrib::secs_to_tm((long long)t, &tm); + if (err) { Genode::warning("could not convert timestamp"); } + + return Rtc::Timestamp { + .microsecond = 0, + .second = err ? 0 : (unsigned)tm.tm_sec, + .minute = err ? 0 : (unsigned)tm.tm_min, + .hour = err ? 0 : (unsigned)tm.tm_hour, + .day = err ? 1 : (unsigned)tm.tm_mday, + .month = err ? 1 : (unsigned)tm.tm_mon + 1, + .year = err ? 1970 : (unsigned)tm.tm_year + 1900 + }; + } + + struct Point_in_time + { + Genode::int64_t rtc_seconds; + Genode::int64_t curr_seconds; + }; + + Rtc::Timestamp generate(Point_in_time const &p, Genode::uint64_t secs) + { + Genode::int64_t const s = ((Genode::int64_t)secs - p.curr_seconds) + p.rtc_seconds; + return convert(s); + } + +} /* namespace Util */ + + +namespace Rtc { + using namespace Genode; + + struct Time; + struct Session_component; + struct Root; + struct Main; +} /* namespace Rtc */ + + +struct Rtc::Time +{ + Env &_env; + + Signal_context_capability _notify_sigh; + + Timer::Connection _timer { _env }; + Rtc::Connection _rtc { _env }; + + Util::Point_in_time _time_base { }; + + void _update_time(Timestamp const &ts) + { + _time_base.rtc_seconds = Util::convert(ts); + _time_base.curr_seconds = _timer.curr_time().trunc_to_plain_ms().value / 1000; + if (_notify_sigh.valid()) { + Signal_transmitter(_notify_sigh).submit(); + } + } + + void _handle_rtc_set() + { + Timestamp ts = _rtc.current_time(); + log("Set RTC base from RTC driver to ", ts); + _update_time(ts); + } + + Signal_handler