iPXE
Functions
rtc_time.c File Reference

RTC-based time source. More...

#include <stdint.h>
#include <time.h>
#include <rtc.h>
#include <ipxe/time.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static unsigned int rtc_readb (int address)
 Read RTC register.
static int rtc_is_busy (void)
 Check if RTC update is in progress.
static unsigned int rtc_readb_bcd (int address)
 Read RTC BCD register.
static time_t rtc_read_time (void)
 Read RTC time.
static time_t rtc_now (void)
 Get current time in seconds.
 PROVIDE_TIME (rtc, time_now, rtc_now)

Detailed Description

RTC-based time source.

Definition in file rtc_time.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static unsigned int rtc_readb ( int  address) [static]

Read RTC register.

Parameters:
addressRegister address
Return values:
dataData

Definition at line 43 of file rtc_time.c.

References CMOS_ADDRESS, CMOS_DATA, inb(), and outb().

Referenced by rtc_is_busy(), rtc_read_time(), and rtc_readb_bcd().

                                              {
        outb ( address, CMOS_ADDRESS );
        return inb ( CMOS_DATA );
}
static int rtc_is_busy ( void  ) [static]

Check if RTC update is in progress.

Return values:
is_busyRTC update is in progress

Definition at line 53 of file rtc_time.c.

References rtc_readb(), RTC_STATUS_A, and RTC_STATUS_A_UPDATE_IN_PROGRESS.

Referenced by rtc_read_time().

static unsigned int rtc_readb_bcd ( int  address) [static]

Read RTC BCD register.

Parameters:
addressRegister address
Return values:
valueValue

Definition at line 63 of file rtc_time.c.

References rtc_readb().

Referenced by rtc_read_time().

                                                  {
        unsigned int bcd;

        bcd = rtc_readb ( address );
        return ( bcd - ( 6 * ( bcd >> 4 ) ) );
}
static time_t rtc_read_time ( void  ) [static]

Read RTC time.

Return values:
timeTime, in seconds

Definition at line 75 of file rtc_time.c.

References address, DBGC, mktime(), RTC_HOUR, rtc_is_busy(), RTC_MDAY, RTC_MIN, RTC_MON, rtc_readb(), rtc_readb_bcd(), RTC_SEC, RTC_STATUS_A, RTC_STATUS_B, RTC_STATUS_B_24_HOUR, RTC_STATUS_B_BINARY, RTC_YEAR, time, tm::tm_hour, tm::tm_mday, tm::tm_min, tm::tm_mon, tm::tm_sec, and tm::tm_year.

Referenced by rtc_now().

                                     {
        unsigned int status_b;
        int is_binary;
        int is_24hour;
        unsigned int ( * read_component ) ( int address );
        struct tm tm;
        int is_pm;
        unsigned int hour;
        time_t time;

        /* Wait for any in-progress update to complete */
        while ( rtc_is_busy() ) {}

        /* Determine RTC mode */
        status_b = rtc_readb ( RTC_STATUS_B );
        is_binary = ( status_b & RTC_STATUS_B_BINARY );
        is_24hour = ( status_b & RTC_STATUS_B_24_HOUR );
        read_component = ( is_binary ? rtc_readb : rtc_readb_bcd );

        /* Read time values */
        tm.tm_sec = read_component ( RTC_SEC );
        tm.tm_min = read_component ( RTC_MIN );
        hour = read_component ( RTC_HOUR );
        if ( ! is_24hour ) {
                is_pm = ( hour >= 80 );
                hour = ( ( ( ( hour & 0x7f ) % 80 ) % 12 ) +
                         ( is_pm ? 12 : 0 ) );
        }
        tm.tm_hour = hour;
        tm.tm_mday = read_component ( RTC_MDAY );
        tm.tm_mon = ( read_component ( RTC_MON ) - 1 );
        tm.tm_year = ( read_component ( RTC_YEAR ) +
                       100 /* Assume we are in the 21st century, since
                            * this code was written in 2012 */ );

        DBGC ( RTC_STATUS_A, "RTCTIME is %04d-%02d-%02d %02d:%02d:%02d "
               "(%s,%d-hour)\n", ( tm.tm_year + 1900 ), ( tm.tm_mon + 1 ),
               tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
               ( is_binary ? "binary" : "BCD" ), ( is_24hour ? 24 : 12 ) );

        /* Convert to seconds since the Epoch */
        time = mktime ( &tm );

        return time;
}
static time_t rtc_now ( void  ) [static]

Get current time in seconds.

Return values:
timeTime, in seconds

Definition at line 126 of file rtc_time.c.

References rtc_read_time(), and time.

                               {
        time_t time = 0;
        time_t last_time;

        /* Read time until we get two matching values in a row, in
         * case we end up reading a corrupted value in the middle of
         * an update.
         */
        do {
                last_time = time;
                time = rtc_read_time();
        } while ( time != last_time );

        return time;
}
PROVIDE_TIME ( rtc  ,
time_now  ,
rtc_now   
)