site  contact  subhomenews

Setting system time in initrd fixed

February 18, 2020 — BarryK

When the Linux kernel boots, the default date is January 1, 1970, which is not so good in the initrd as there are various file operations performed. If for example, a file is created or edited, after the switch_root to the main filesystem, where the date and time are set correctly, those files will have that old modify date, which could cause trouble. Also, the initrd may modify the working-partition size, or do a filesystem check, and it will have that very old date.

It is much better if the correct date and time is known in the initrd. Which means that the system time has to be set from the hardware clock.

I made an interesting discovery. The /dev nodes in the intrd are static, there is no devtmpfs mounted on /dev, which is a very "old school" way to do things. There is /dev/rtc (major, minor=10,135), and what I have discovered is that it is no longer valid. It is for old kernels prior to 2.6. What we need now is /dev/rtc0 (major,minor=253,0), with /dev/rtc a symlink to it.

Also, I have compiled the 5.4.20 kernel with all of the "rtc*.ko" drivers builtin, so the appropriate one will be working in the initrd. I did check that none of them need firmware. Though, it may be that modern PCs do not load any rtc*.ko driver, as the RTC functionality is builtin to the SoC -- that is the case with my Apollo Lake SoC in my laptop.

Now, the 'init' script in the initrd in EasyOS has been modified:

###set date and time###
#could read .session/etc/clock and run hwclock, but for now this probably good enough (refer: rc.shutdown)...
#200218 fixed /dev/rtc0 and symlink /dev/rtc for modern kernels, replacing old /dev/rtc
# also have rtc drivers builtin to kernel >=5.4.20. can now use hwclock...
CLKflg=1
if [ -e /sys/class/rtc/rtc0 ];then
if [ -s /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/clock ];then
. /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/clock #has HWCLOCKTIME=localtime or utc
case "$HWCLOCKTIME" in
localtime) hwclock -s --localtime -f /dev/rtc0; CLKflg=$? ;;
utc) hwclock -s -u -f /dev/rtc0; CLKflg=$? ;;
esac
else #first bootup, assume hw clock is locatime...
hwclock -s --localtime -f /dev/rtc0
fi
fi
if [ $CLKflg -ne 0 ];then

if [ -s /mnt/${WKG_DEV}/${WKG_DIR}.session/root/.var/local/shutdown_date_saved ];then
date -s "`cat /mnt/${WKG_DEV}/${WKG_DIR}.session/root/.var/local/shutdown_date_saved`" > /dev/null
fi
fi

...dark-red is the new code.

EasyOS was not too bad anyway, before doing this, as /etc/rc.d/rc.shutdown saves the date in /var/local/shutdown_date_saved, so the system clock would have got set to the date that last shutdown the computer. Now we are being a bit more accurate. 

Of course, at the very first bootup, say from a USB-stick, /var/local/shutdown_date_saved will not exist, so the date will be January 7, 1970 if hwclock is not working. Various operations, such as resizing the working-partition to fill the drive and file /etc/rc.d/PUPSTATE, will have that old date. 

Tags: easy