iPXE
rtc_time.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26/** @file
27 *
28 * RTC-based time source
29 *
30 */
31
32#include <stdint.h>
33#include <time.h>
34#include <rtc.h>
35#include <ipxe/time.h>
36
37/**
38 * Read RTC register
39 *
40 * @v address Register address
41 * @ret data Data
42 */
43static unsigned int rtc_readb ( int address ) {
45 return inb ( CMOS_DATA );
46}
47
48/**
49 * Check if RTC update is in progress
50 *
51 * @ret is_busy RTC update is in progress
52 */
53static int rtc_is_busy ( void ) {
55}
56
57/**
58 * Read RTC BCD register
59 *
60 * @v address Register address
61 * @ret value Value
62 */
63static unsigned int rtc_readb_bcd ( int address ) {
64 unsigned int bcd;
65
66 bcd = rtc_readb ( address );
67 return ( bcd - ( 6 * ( bcd >> 4 ) ) );
68}
69
70/**
71 * Read RTC time
72 *
73 * @ret time Time, in seconds
74 */
75static time_t rtc_read_time ( void ) {
76 unsigned int status_b;
77 int is_binary;
78 int is_24hour;
79 unsigned int ( * read_component ) ( int address );
80 struct tm tm;
81 int is_pm;
82 unsigned int hour;
83 time_t time;
84
85 /* Wait for any in-progress update to complete */
86 while ( rtc_is_busy() ) {}
87
88 /* Determine RTC mode */
89 status_b = rtc_readb ( RTC_STATUS_B );
90 is_binary = ( status_b & RTC_STATUS_B_BINARY );
91 is_24hour = ( status_b & RTC_STATUS_B_24_HOUR );
92 read_component = ( is_binary ? rtc_readb : rtc_readb_bcd );
93
94 /* Read time values */
95 tm.tm_sec = read_component ( RTC_SEC );
96 tm.tm_min = read_component ( RTC_MIN );
97 hour = read_component ( RTC_HOUR );
98 if ( ! is_24hour ) {
99 is_pm = ( hour >= 80 );
100 hour = ( ( ( ( hour & 0x7f ) % 80 ) % 12 ) +
101 ( is_pm ? 12 : 0 ) );
102 }
103 tm.tm_hour = hour;
104 tm.tm_mday = read_component ( RTC_MDAY );
105 tm.tm_mon = ( read_component ( RTC_MON ) - 1 );
106 tm.tm_year = ( read_component ( RTC_YEAR ) +
107 100 /* Assume we are in the 21st century, since
108 * this code was written in 2012 */ );
109
110 DBGC ( RTC_STATUS_A, "RTCTIME is %04d-%02d-%02d %02d:%02d:%02d "
111 "(%s,%d-hour)\n", ( tm.tm_year + 1900 ), ( tm.tm_mon + 1 ),
113 ( is_binary ? "binary" : "BCD" ), ( is_24hour ? 24 : 12 ) );
114
115 /* Convert to seconds since the Epoch */
116 time = mktime ( &tm );
117
118 return time;
119}
120
121/**
122 * Get current time in seconds
123 *
124 * @ret time Time, in seconds
125 */
126static time_t rtc_now ( void ) {
127 time_t time = 0;
128 time_t last_time;
129
130 /* Read time until we get two matching values in a row, in
131 * case we end up reading a corrupted value in the middle of
132 * an update.
133 */
134 do {
135 last_time = time;
136 time = rtc_read_time();
137 } while ( time != last_time );
138
139 return time;
140}
141
uint64_t address
Base address.
Definition ena.h:13
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define outb(data, io_addr)
Definition io.h:310
#define inb(io_addr)
Definition io.h:283
Time source.
#define PROVIDE_TIME(_subsys, _api_func, _func)
Provide a time API implementation.
Definition time.h:34
time_t time_now(void)
Get current time in seconds (ignoring system clock offset)
int64_t time_t
Seconds since the Epoch.
Definition time.h:19
Date and time.
CMOS Real-Time Clock (RTC)
#define RTC_STATUS_B_BINARY
RTC binary mode bit.
Definition rtc.h:69
#define RTC_YEAR
RTC year.
Definition rtc.h:54
#define RTC_SEC
RTC seconds.
Definition rtc.h:36
#define RTC_MIN
RTC minutes.
Definition rtc.h:39
#define RTC_MON
RTC month.
Definition rtc.h:51
#define CMOS_DATA
CMOS/RTC data register.
Definition rtc.h:33
#define RTC_HOUR
RTC hours.
Definition rtc.h:42
#define RTC_STATUS_B
RTC status register B.
Definition rtc.h:63
#define RTC_STATUS_B_24_HOUR
RTC 24 hour format bit.
Definition rtc.h:66
#define CMOS_ADDRESS
CMOS/RTC address (and NMI) register.
Definition rtc.h:27
#define RTC_MDAY
RTC day of month.
Definition rtc.h:48
#define RTC_STATUS_A
RTC status register A.
Definition rtc.h:57
#define RTC_STATUS_A_UPDATE_IN_PROGRESS
RTC update in progress bit.
Definition rtc.h:60
static unsigned int rtc_readb(int address)
Read RTC register.
Definition rtc_time.c:43
static time_t rtc_now(void)
Get current time in seconds.
Definition rtc_time.c:126
static int rtc_is_busy(void)
Check if RTC update is in progress.
Definition rtc_time.c:53
static unsigned int rtc_readb_bcd(int address)
Read RTC BCD register.
Definition rtc_time.c:63
static time_t rtc_read_time(void)
Read RTC time.
Definition rtc_time.c:75
Broken-down time.
Definition time.h:16
int tm_mon
Month of year [0,11].
Definition time.h:26
int tm_year
Years since 1900.
Definition time.h:28
int tm_hour
Hour [0,23].
Definition time.h:22
int tm_sec
Seconds [0,60].
Definition time.h:18
int tm_mday
Day of month [1,31].
Definition time.h:24
int tm_min
Minutes [0,59].
Definition time.h:20
time_t mktime(struct tm *tm)
Calculate seconds since the Epoch.
Definition time.c:118