How to set hwclock on a realtime clock

Hey Guys,

We have a add on board with some i2c devices on it like hardware clock and Security Chip.
My question is howto disable the fake hwclock and enable the realtime clock on ubuntucore without to install classic mode, we wouldnt control it via snaps only by the kernel module.

I tried to load the kernel module, but i didnt found the way to disable the fake hwclock and hwclock did not found the i2c device.

Greets Tony

on core we ship an initrd script that checks the last mount time of the disk and if the hwclock is to far off we set the clock to that value to get a mildly reasonable time … to turn this off you need to drop the “fixrtc” keyword from the kernel cmdline in your gadget snap …

regarding the addon rtc, an app snap with a daemon that uses the time-control interface (and if needed the respective i2c interfaces you defined in your gadget to initialize the board) should work to talk to /dev/rtc* and to execute the hwclock command.

I had quite a lot of trouble getting my RTC to work - but did eventually. I’m not sure I have a direct answer to your question but maybe I’ll share my $0.02 - also as a way of verifying with the community that what I did isn’t totally stupid…

Firstly, is your system successfully loading the kernel module for your RTC? If it is, then I assume you’re seeing /dev/rtc0 and /dev/rtc (a symlink to the former) pop up in your dev directory?

At least in my setup, which is a Raspberry Pi 3 with a Strato Pi board that contains a MCP79410 RTC chip, and the latest beta of Ubuntu Core 16, the /dev/rtc0 device only appeared after loading the kernel module.

With the rtc device in place, I was able to successfully run hwclock in order to get or set the time from my on-board RTC. Note that without that device module loaded, hwclock wouldn’t run for me - so I’m not aware of there being a “fake” hwclock as such installed by default - but I may be wrong, and it may depend on your system configuration.

Finally, I manually added a hwclock service to systemd, which would read the system time from the RTC on boot, and save it on shutdown. I believe you can do this via a snap, though I went a slightly more manual way. I created a hwclock.service definition file file manually in /writable/system-data/etc/systemd/system with the following contents:

[Unit]
Description=Hardware clock synchronization
[Service]
Type=oneshot
ExecStart=/sbin/hwclock --hctosys --utc --adjfile=/writable/system-data/etc/adjtime
ExecStop=/sbin/hwclock --systohc --utc --adjfile=/writable/system-data/etc/adjtime
[Install]
WantedBy=multi-user.target

Then I unmasked and enabled the service:

sudo systemctl unmask hwclock
sudo systemctl enable hwclock
1 Like

Something like this might work (totally untested but roughly the same you do above as image hack)

ogra@acheron:~/Devel/hwclock-test$ cat snap/snapcraft.yaml 
name: hwclock-test
version: '2.27.1'
summary: Simple test snap to run teh hwclock cmd
description: |
  A simple snap to test the hwclock functionallity

grade: stable
confinement: strict

apps:
  hwclock:
    daemon: oneshot
    command: sbin/hwclock --hctosys --utc --adjfile=$SNAP_DATA/etc/adjtime
    stop-command: sbin/hwclock --systohc --utc --adjfile=$SNAP_DATA/etc/adjtime
    plugs: [ time-control ]

parts:
  hwclock:
    plugin: nil
    stage-packages:
      - util-linux

(that would obviously need some more code (i.e. an install hook to copy $SNAP/etc/adjtime to $SNAP_DATA/etc/adjtime) but should demonstrate the basics)

Hey @svet , thanks for the answer, but yeah the service is not necessary I had take a look around in the etc folder and found this one:

/writable/system-data/etc/rc0.d/K04hwclock.sh where exactly did what you are do with your service.

I’m follow @ogra’s instruction to set in the cmdline.txt fixrtc at the end and i have enable in the config.txt i add follow line: dtoverlay=i2c-rtc,mcp7940x

I’m also run my own gadget for the Pi3 so it was easy for me to modify and build an image for that.

The hwclock is now working as expected. :wink:

Greets Tony

1 Like

Ah, nice! I hadn’t spotted that SysV init script - I only noticed the masked systemd service. I think that script, as written currently, would throw an error about /etc/adjtime not being writable, but should still work fine. Glad you got it sorted!

I might come back to you with questions about writing an own gadget, as I think I’ll need that in order to get some of the other Strato Pi functionality working :slight_smile:

Cheers, Svet

@svet , sure youre welcome, :slight_smile:

I wonder if it would make sense for the time-control interface to auto-load the rtc module since it grants write access to /dev/rtc*. @ogra - can you think of any downsides in doing this?

Typically the kernel loads the module if there is a device (either by default or when loading an overlay devicetree for an addon board).

This works fine on all boards that acutally have an rtc, so i’m not actually sure what you want to load (the Pi simply doesnt have a rtc at all)

Hmm, so there seem to be bugs in the time-control interface…

Using a snapcraft.yaml like:

name: hwclock-test
version: '2.27.1'
summary: Simple test snap to run the hwclock cmd
description: |
  A simple snap to test the hwclock functionality

grade: stable
confinement: strict

apps:
  hwclock:
    daemon: oneshot
    command: sh -c "/sbin/hwclock --hctosys --utc --adjfile=$SNAP_DATA/adjtime || true"
    stop-command: sh -c "/sbin/hwclock --systohc --utc --adjfile=$SNAP_DATA/adjtime || true"
    plugs:
      - time-control

parts:
  hwclock:
    plugin: nil

Should theoretically get me a proper hwclock call when the time-cotrol interface is connected …

ogra@localhost:~$ snap interfaces|grep time-
:time-control              hwclock-test

But i get:

SECCOMP auid=4294967295 uid=0 gid=0 ses=4294967295 pid=4875 comm="hwclock" exe="/sbin/hwclock" sig=31 arch=40000028 syscall=79 compat=0 ip=0x76f20386 code=0x0


ogra@localhost:~$ scmp_sys_resolver 79
settimeofday

@jdstrand, I suppose thats not the desired behaviour and we’ll need some seccomp declarations in interfaces/builtin/time_control.go

Thanks for reporting this. Added it to my list for the next batch of updates.

This is committed to master. We’re working to also get it into 2.31.

Thanks @ogra and @jdstrand for helping to get this work. I finally got around to trying this out as I’m slowly moving to more snap-based images. Unfortunately it didn’t quite work out.

Following @ogra’s latest suggested snapcraft.yaml, I get a plain old

sh: 1: /sbin/hwclock: Permission denied

So I guess the time-control interface doesn’t expose the system’s /sbin/hwclock binary…is the intention that it should?

I also tried the alternative approach of putting util-linux under stage-packages and using the snap’s own hwclock binary. That leads to a mystery error, which I’ve described below. The error occurs during the “starting service” stage of the snap installation, and due to it the snap never actually installs. So I don’t even get a chance to connect the time-control interface.

What I get on the console is the following:

error: cannot perform the following tasks:
- Start snap "hwclock-svc" (17) services ([start snap.hwclock-svc.hwclock.service] failed with exit status 1: Job for snap.hwclock-svc.hwclock.service failed because the control process exited with error code.
See "systemctl status snap.hwclock-svc.hwclock.service" and "journalctl -xe" for details.
)

The systemd journal contains the following:

Aug 13 14:34:59 localhost.localdomain systemd[1]: Starting Service for snap application hwclock-svc.hwclock...
Aug 13 14:34:59 localhost.localdomain hwclock-svc.hwclock[6348]: hwclock: Unable to connect to audit system
Aug 13 14:34:59 localhost.localdomain systemd[1]: snap.hwclock-svc.hwclock.service: Main process exited, code=exited, status=77/n/a
Aug 13 14:34:59 localhost.localdomain systemd[1]: Failed to start Service for snap application hwclock-svc.hwclock.
Aug 13 14:34:59 localhost.localdomain systemd[1]: snap.hwclock-svc.hwclock.service: Unit entered failed state.
Aug 13 14:34:59 localhost.localdomain systemd[1]: snap.hwclock-svc.hwclock.service: Failed with result 'exit-code'.
Aug 13 14:34:59 localhost.localdomain systemd[1]: Stopped Service for snap application hwclock-svc.hwclock.

The key message here appears to be “Unable to connect to audit system”. Googling that doesn’t appear to throw up any relevant results.

The following are the apparmor log entries form dmesg. Not sure what to make of them.

[ 4922.159637] audit: type=1400 audit(1534170895.720:103): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap-update-ns.hwclock-svc" pid=6294 comm="apparmor_parser"
[ 4922.757714] audit: type=1400 audit(1534170896.320:104): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.hwclock-svc.hwclock" pid=6296 comm="apparmor_parser"
[ 4925.702444] audit: type=1326 audit(1534170899.264:105): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=6348 comm="hwclock" exe="/snap/hwclock-svc/20/sbin/hwclock" sig=0 arch=40000028 syscall=281 compat=0 ip=0x76e8bb48 code=0x50000

The behavior is identical on two different systems: a Raspberry Pi (with RTC) on Ubuntu Core, and a desktop on Ubuntu 18.04. So the issue doesn’t appear to be system-dependent.

By the way I’ve made this a public snap; it’s at https://snapcraft.io/hwclock-svc and the latest source is at https://github.com/svet-b/hwclock-snap/blob/master/snap/snapcraft.yaml.

Thanks in advance for any tips!

$ scmp_sys_resolver 281
socket

looks like you want the network-bind interface in your app entry …

regarding the fact that it also fails on the desktop side, this sounds like additionally you are missing some kernel feature, did you enable the right devicetree overlay for the RTC addon board ?

Thanks for helping work out what’s going on!

I added network-bind and network slots (for good measure) but that didn’t lead to any tangible changes.

Console output and journal are the same as before. dmesg is similar: (also including the messages from the installation process)

[ 2215.536010] audit: type=1400 audit(1534175120.483:44): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap-update-ns.hwclock-svc" pid=2209 comm="apparmor_parser"
[ 2216.165727] audit: type=1400 audit(1534175121.111:45): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.hwclock-svc.hwclock" pid=2211 comm="apparmor_parser"
[ 2218.398554] audit: type=1400 audit(1534175123.347:46): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap-update-ns.core" pid=2263 comm="apparmor_parser"
[ 2218.425470] audit: type=1400 audit(1534175123.371:47): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.core.hook.configure" pid=2265 comm="apparmor_parser"
[ 2219.456010] audit: type=1400 audit(1534175124.403:48): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.hwclock-svc.hwclock" pid=2272 comm="apparmor_parser"
[ 2219.469112] audit: type=1400 audit(1534175124.415:49): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap-update-ns.hwclock-svc" pid=2274 comm="apparmor_parser"
[ 2219.829434] audit: type=1400 audit(1534175124.775:50): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap-update-ns.core" pid=2286 comm="apparmor_parser"
[ 2219.861632] audit: type=1400 audit(1534175124.807:51): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.core.hook.configure" pid=2288 comm="apparmor_parser"
[ 2220.961029] audit: type=1400 audit(1534175125.907:52): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.hwclock-svc.hwclock" pid=2296 comm="apparmor_parser"
[ 2220.974489] audit: type=1400 audit(1534175125.923:53): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap-update-ns.hwclock-svc" pid=2298 comm="apparmor_parser"
[ 2222.327761] audit: type=1326 audit(1534175127.276:54): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=2310 comm="hwclock" exe="/snap/hwclock-svc/28/sbin/hwclock" sig=0 arch=40000028 syscall=281 compat=0 ip=0x76eedb48 code=0x50000
[ 2226.002712] audit: type=1400 audit(1534175130.952:55): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap-update-ns.core" pid=2374 comm="apparmor_parser"
[ 2226.017361] audit: type=1400 audit(1534175130.964:56): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.core.hook.configure" pid=2376 comm="apparmor_parser"

I don’t think it’s an RTC or kernel issue - I say that primarily because installing the snap with --devmode succeeds and works just fine (as does running hwclock more generally).

It does:

$ grep hwclock ./interfaces/builtin/time_control.go
...
/sbin/hwclock ixr,

As for the audit subsystem, you will need to plugs the ‘network-audit’ interface, which allows reads and writes to the audit subsystem’s netlink socket.

Thanks @jdstrand, looks like you nailed it. The reason I was getting the permission denied on /sbin/hwclock was that I hadn’t actually connected the interface :man_facepalming:. But yes, apart from that, netlink-audit also needs to be set up and connected in order to stop getting the audit system error.

I’ve updated my snapcraft.yaml to a working configuration.

Next step is to make sure that the service actually runs during early boot, rather than only after network-online.target, which appears to be the default.