From e6b0103b8c7834f6d6edd18f94d60f9d60f4f244 Mon Sep 17 00:00:00 2001 From: Jakob Hauser Date: Mon, 24 May 2021 07:26:28 +0200 Subject: [PATCH] main/swclock-offset: new package (MR 2191) Some devices have a working but non-writable real-time clock (RTC). This package contains two shell scripts: One writes the offset between 'hwclock' and 'swclock' to a file at shutdown, another one reads the offset from the file at boot and sets the 'swclock'. This way the system time in userspace is kept in present time. [ci:skip-build] already built successfully in CI --- .gitlab-ci/shellcheck.sh | 4 ++- main/swclock-offset/APKBUILD | 31 ++++++++++++++++++ main/swclock-offset/swclock-offset-boot.initd | 23 +++++++++++++ main/swclock-offset/swclock-offset-boot.sh | 32 +++++++++++++++++++ .../swclock-offset-openrc.post-install | 17 ++++++++++ .../swclock-offset-openrc.pre-deinstall | 11 +++++++ .../swclock-offset-shutdown.initd | 29 +++++++++++++++++ .../swclock-offset/swclock-offset-shutdown.sh | 30 +++++++++++++++++ .../swclock-offset.post-deinstall | 13 ++++++++ 9 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 main/swclock-offset/APKBUILD create mode 100644 main/swclock-offset/swclock-offset-boot.initd create mode 100644 main/swclock-offset/swclock-offset-boot.sh create mode 100644 main/swclock-offset/swclock-offset-openrc.post-install create mode 100644 main/swclock-offset/swclock-offset-openrc.pre-deinstall create mode 100644 main/swclock-offset/swclock-offset-shutdown.initd create mode 100644 main/swclock-offset/swclock-offset-shutdown.sh create mode 100644 main/swclock-offset/swclock-offset.post-deinstall diff --git a/.gitlab-ci/shellcheck.sh b/.gitlab-ci/shellcheck.sh index d033393c3..707c21314 100755 --- a/.gitlab-ci/shellcheck.sh +++ b/.gitlab-ci/shellcheck.sh @@ -15,6 +15,7 @@ fi # Shell: shellcheck sh_files=" + ./main/mdss-fb-init-hack/mdss-fb-init-hack.sh ./main/postmarketos-base/rootfs-usr-lib-firmwareload.sh ./main/postmarketos-mkinitfs/init.sh.in ./main/postmarketos-mkinitfs/init_functions.sh @@ -23,7 +24,8 @@ sh_files=" ./main/postmarketos-mkinitfs/mkinitfs_test.sh ./main/postmarketos-mkinitfs-hook-debug-shell/20-debug-shell.sh ./main/postmarketos-update-kernel/update-kernel.sh - ./main/mdss-fb-init-hack/mdss-fb-init-hack.sh + ./main/swclock-offset/swclock-offset-boot.sh + ./main/swclock-offset/swclock-offset-shutdown.sh $(find . -path './main/postmarketos-ui-*/*.sh') $(find . -path './main/postmarketos-ui-*/*.pre-install') diff --git a/main/swclock-offset/APKBUILD b/main/swclock-offset/APKBUILD new file mode 100644 index 000000000..8cbc4f8ad --- /dev/null +++ b/main/swclock-offset/APKBUILD @@ -0,0 +1,31 @@ +# Maintainer: Jakob Hauser +pkgname=swclock-offset +pkgver=0.1 +pkgrel=0 +pkgdesc="Keep system time at an offset to a non-writable RTC" +url="https://gitlab.com/postmarketOS/pmaports" +arch="noarch" +license="GPL-3.0-or-later" +install="$pkgname.post-deinstall" +subpackages="$pkgname-openrc" +source="$pkgname-boot.initd $pkgname-shutdown.initd $pkgname-boot.sh $pkgname-shutdown.sh" +options="!check" # No tests + +package() { + install -Dm755 "$srcdir/$pkgname-boot.initd" "$pkgdir/etc/init.d/$pkgname-boot" + install -Dm755 "$srcdir/$pkgname-shutdown.initd" "$pkgdir/etc/init.d/$pkgname-shutdown" + install -Dm755 "$srcdir/$pkgname-boot.sh" "$pkgdir/sbin/$pkgname-boot" + install -Dm755 "$srcdir/$pkgname-shutdown.sh" "$pkgdir/sbin/$pkgname-shutdown" +} + +openrc() { + install="$subpkgname.post-install $subpkgname.pre-deinstall" + default_openrc +} + +sha512sums=" +777dff161dcae742d1bfb7acbf413a319c9e623292a315ccd8cf5f3f0df9258d54d3e9891bdff741a6146ab285bc5a27c7921bc93902b4a2006104666a835ecd swclock-offset-boot.initd +a834fe9f721a4797f5675361fe07b500f93a2082753ed0a0fd583ccfd49738acfe04fb526e2936f3ce270053d151c7080a6a5356246fb816638e72992c6f77db swclock-offset-shutdown.initd +288373bef5d7e5a64d118396491b424fb9cd38bfb3e7c422762c4c1441894617e59140035cd824846880c159fe3b9f6f8ceaddd552014e53b4e0ab05da7931dc swclock-offset-boot.sh +49f2ac3b4f41904097d1b5e903b810abd3da005972fffc14bd34d3c25aaa9b92d293a10bfa4348e160060670ed19d50e06ac6c9b8ebe663e56bf30e36c28edf9 swclock-offset-shutdown.sh +" diff --git a/main/swclock-offset/swclock-offset-boot.initd b/main/swclock-offset/swclock-offset-boot.initd new file mode 100644 index 000000000..34ec4b2e2 --- /dev/null +++ b/main/swclock-offset/swclock-offset-boot.initd @@ -0,0 +1,23 @@ +#!/sbin/openrc-run + +# To avoid time inconsistency at filesystems check, the system time +# shall be set before "fsck". + +description="Setting the system time according to an offset file." + +depend() +{ + before fsck +} + +start() +{ + ebegin "Setting system time" + /sbin/swclock-offset-boot + eend $? +} + +stop() +{ + return 0 +} diff --git a/main/swclock-offset/swclock-offset-boot.sh b/main/swclock-offset/swclock-offset-boot.sh new file mode 100644 index 000000000..3c349e9d6 --- /dev/null +++ b/main/swclock-offset/swclock-offset-boot.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +# This shell scripts reads the offset from the file and sets the 'swclock'. +# +# To keep the offset calculation simple, the epoch timestamp is used. +# +# The RTC is read from the sysfs node. +# +# To set the system time, command "date" is used. The "@" sign marks an +# epoch time format. As the "date" command offers no quiet option, the +# output is written to the null device. + +rtc_sys_node="/sys/class/rtc/rtc0/since_epoch" +offset_file="/var/cache/swclock-offset/offset-storage" + +# check presence of rtc sys node +if [ ! -f $rtc_sys_node ]; then + exit 1 +fi + +# check presence of offset file +if [ ! -f $offset_file ]; then + exit 2 +fi + +# calculate system time +hwclock_epoch=$(cat $rtc_sys_node) +offset_epoch=$(cat $offset_file) +swclock_epoch=$((hwclock_epoch + offset_epoch)) + +# set system time, dump output +date --utc --set=@$swclock_epoch > /dev/null diff --git a/main/swclock-offset/swclock-offset-openrc.post-install b/main/swclock-offset/swclock-offset-openrc.post-install new file mode 100644 index 000000000..e0275855d --- /dev/null +++ b/main/swclock-offset/swclock-offset-openrc.post-install @@ -0,0 +1,17 @@ +#!/bin/sh + +# The service "osclock" is a dummy service simply providing "clock". +# This avoids other services that need "clock" to call the service +# "hwclock". +# +# The service "swclock-offset-boot" needs to run after the sysfs has +# been mounted. As the sysfs is mounted in runlevel sysinit, assigning +# the service to runlevel boot is enough to keep the order. + +# replace service hwclock by osclock +rc-update -q del hwclock boot +rc-update -q add osclock boot + +# assign swclock-offset services to runlevels +rc-update -q add swclock-offset-boot boot +rc-update -q add swclock-offset-shutdown shutdown diff --git a/main/swclock-offset/swclock-offset-openrc.pre-deinstall b/main/swclock-offset/swclock-offset-openrc.pre-deinstall new file mode 100644 index 000000000..242516cdb --- /dev/null +++ b/main/swclock-offset/swclock-offset-openrc.pre-deinstall @@ -0,0 +1,11 @@ +#!/bin/sh + +# This script restores the original state. + +# remove swclock-offset services +rc-update -q del swclock-offset-boot boot +rc-update -q del swclock-offset-shutdown shutdown + +# replace service osclock by hwclock +rc-update -q del osclock boot +rc-update -q add hwclock boot diff --git a/main/swclock-offset/swclock-offset-shutdown.initd b/main/swclock-offset/swclock-offset-shutdown.initd new file mode 100644 index 000000000..ddd9e3cf6 --- /dev/null +++ b/main/swclock-offset/swclock-offset-shutdown.initd @@ -0,0 +1,29 @@ +#!/sbin/openrc-run + +# A dedicated shutdown service is used to write the offset file instead +# of using the stop function of the swclock-offset service at boot. This +# approach is more fail-safe on different installation/deinstallation +# situations. +# +# Because the shutdown services are performed late within the shutdown +# runlevel, dependencies are needed to execute the script before +# processes are killed and filesystems are remounted read-only. + +description="Writing the offset between system time and RTC to a file." + +depend() +{ + before killprocs mount-ro +} + +start() +{ + ebegin "Saving swclock-offset" + /sbin/swclock-offset-shutdown + eend $? +} + +stop() +{ + return 0 +} diff --git a/main/swclock-offset/swclock-offset-shutdown.sh b/main/swclock-offset/swclock-offset-shutdown.sh new file mode 100644 index 000000000..934f91cc1 --- /dev/null +++ b/main/swclock-offset/swclock-offset-shutdown.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# This shell scripts writes the offset between 'hwclock' and 'swclock' +# to a file. +# +# To keep the offset calculation simple, the epoch timestamp is used. +# +# The system time is read by command "date". The RTC is read from the +# sysfs node. + +rtc_sys_node="/sys/class/rtc/rtc0/since_epoch" +offset_directory="/var/cache/swclock-offset" + +# check presence of rtc sys node +if [ ! -f $rtc_sys_node ]; then + exit 1 +fi + +# check presence of offset directory +if [ ! -d $offset_directory ]; then + mkdir -p $offset_directory +fi + +# calculate offset +swclock_epoch=$(date --utc +%s) +hwclock_epoch=$(cat $rtc_sys_node) +offset_epoch=$((swclock_epoch - hwclock_epoch)) + +# write offset file +echo $offset_epoch > $offset_directory/offset-storage diff --git a/main/swclock-offset/swclock-offset.post-deinstall b/main/swclock-offset/swclock-offset.post-deinstall new file mode 100644 index 000000000..e1317fa9c --- /dev/null +++ b/main/swclock-offset/swclock-offset.post-deinstall @@ -0,0 +1,13 @@ +#!/bin/sh + +# remove offset file and directory +offset_file="/var/cache/swclock-offset/offset-storage" +offset_directory="/var/cache/swclock-offset" + +if [ -f $offset_file ]; then + rm $offset_file +fi + +if [ -d $offset_directory ]; then + rmdir $offset_directory +fi