iPXE
Defines | Functions | Variables
rtc_entropy.c File Reference

RTC-based entropy source. More...

#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <biosint.h>
#include <pic8259.h>
#include <rtc.h>
#include <ipxe/entropy.h>

Go to the source code of this file.

Defines

#define RTC_MAX_WAIT_MS   100
 Maximum time to wait for an RTC interrupt, in milliseconds.
#define rtc_flag   __use_text16 ( rtc_flag )

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
void rtc_isr (void)
 RTC interrupt handler.
volatile uint8_t __text16 (rtc_flag)
 Flag set by RTC interrupt handler.
static void rtc_hook_isr (void)
 Hook RTC interrupt handler.
static void rtc_unhook_isr (void)
 Unhook RTC interrupt handler.
static void rtc_enable_int (void)
 Enable RTC interrupts.
static void rtc_disable_int (void)
 Disable RTC interrupts.
static int rtc_entropy_check (void)
 Check that entropy gathering is functional.
static int rtc_entropy_enable (void)
 Enable entropy gathering.
static void rtc_entropy_disable (void)
 Disable entropy gathering.
uint8_t rtc_sample (void)
 Measure a single RTC tick.
 PROVIDE_ENTROPY_INLINE (rtc, min_entropy_per_sample)
 PROVIDE_ENTROPY (rtc, entropy_enable, rtc_entropy_enable)
 PROVIDE_ENTROPY (rtc, entropy_disable, rtc_entropy_disable)
 PROVIDE_ENTROPY_INLINE (rtc, get_noise)

Variables

static struct segoff rtc_old_handler
 Previous RTC interrupt handler.

Detailed Description

RTC-based entropy source.

Definition in file rtc_entropy.c.


Define Documentation

#define RTC_MAX_WAIT_MS   100

Maximum time to wait for an RTC interrupt, in milliseconds.

Definition at line 42 of file rtc_entropy.c.

Referenced by rtc_entropy_check().

#define rtc_flag   __use_text16 ( rtc_flag )

Definition at line 52 of file rtc_entropy.c.

Referenced by rtc_entropy_check().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
void rtc_isr ( void  )

RTC interrupt handler.

Referenced by rtc_hook_isr(), and rtc_unhook_isr().

volatile uint8_t __text16 ( rtc_flag  )

Flag set by RTC interrupt handler.

static void rtc_hook_isr ( void  ) [static]

Hook RTC interrupt handler.

Definition at line 58 of file rtc_entropy.c.

References __asm__(), CMOS_ADDRESS, CMOS_DATA, hook_bios_interrupt(), RTC_INT, rtc_isr(), rtc_old_handler, RTC_STATUS_C, and TEXT16_CODE.

Referenced by rtc_entropy_enable().

                                  {

        /* RTC interrupt handler */
        __asm__ __volatile__ (
                TEXT16_CODE ( "\nrtc_isr:\n\t"
                              /* Preserve registers */
                              "pushw %%ax\n\t"
                              /* Set "interrupt triggered" flag */
                              "movb $0x01, %%cs:rtc_flag\n\t"
                              /* Read RTC status register C to
                               * acknowledge interrupt
                               */
                              "movb %2, %%al\n\t"
                              "outb %%al, %0\n\t"
                              "inb %1\n\t"
                              /* Send EOI */
                              "movb $0x20, %%al\n\t"
                              "outb %%al, $0xa0\n\t"
                              "outb %%al, $0x20\n\t"
                              /* Restore registers and return */
                              "popw %%ax\n\t"
                              "iret\n\t"
                              "\nrtc_flag:\n\t"
                              ".byte 0\n\t" )
                :
                : "i" ( CMOS_ADDRESS ), "i" ( CMOS_DATA ),
                  "i" ( RTC_STATUS_C ) );

        hook_bios_interrupt ( RTC_INT, ( intptr_t ) rtc_isr, &rtc_old_handler );
}
static void rtc_unhook_isr ( void  ) [static]

Unhook RTC interrupt handler.

Definition at line 93 of file rtc_entropy.c.

References assert, rc, RTC_INT, rtc_isr(), rtc_old_handler, and unhook_bios_interrupt().

Referenced by rtc_entropy_disable(), and rtc_entropy_enable().

                                    {
        int rc;

        rc = unhook_bios_interrupt ( RTC_INT, ( intptr_t ) rtc_isr,
                                     &rtc_old_handler );
        assert ( rc == 0 ); /* Should always be able to unhook */
}
static void rtc_enable_int ( void  ) [static]

Enable RTC interrupts.

Definition at line 105 of file rtc_entropy.c.

References CMOS_ADDRESS, CMOS_DATA, CMOS_DEFAULT_ADDRESS, CMOS_DISABLE_NMI, inb(), outb(), RTC_STATUS_B, RTC_STATUS_B_PIE, and RTC_STATUS_C.

Referenced by rtc_entropy_enable().

                                    {
        uint8_t status_b;

        /* Clear any stale pending interrupts via status register C */
        outb ( ( RTC_STATUS_C | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
        inb ( CMOS_DATA );

        /* Set Periodic Interrupt Enable bit in status register B */
        outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
        status_b = inb ( CMOS_DATA );
        outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
        outb ( ( status_b | RTC_STATUS_B_PIE ), CMOS_DATA );

        /* Re-enable NMI and reset to default address */
        outb ( CMOS_DEFAULT_ADDRESS, CMOS_ADDRESS );
        inb ( CMOS_DATA ); /* Discard; may be needed on some platforms */
}
static void rtc_disable_int ( void  ) [static]

Disable RTC interrupts.

Definition at line 127 of file rtc_entropy.c.

References CMOS_ADDRESS, CMOS_DATA, CMOS_DEFAULT_ADDRESS, CMOS_DISABLE_NMI, inb(), outb(), RTC_STATUS_B, and RTC_STATUS_B_PIE.

Referenced by rtc_entropy_disable(), and rtc_entropy_enable().

                                     {
        uint8_t status_b;

        /* Clear Periodic Interrupt Enable bit in status register B */
        outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
        status_b = inb ( CMOS_DATA );
        outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
        outb ( ( status_b & ~RTC_STATUS_B_PIE ), CMOS_DATA );

        /* Re-enable NMI and reset to default address */
        outb ( CMOS_DEFAULT_ADDRESS, CMOS_ADDRESS );
        inb ( CMOS_DATA ); /* Discard; may be needed on some platforms */
}
static int rtc_entropy_check ( void  ) [static]

Check that entropy gathering is functional.

Return values:
rcReturn status code

Definition at line 146 of file rtc_entropy.c.

References __asm__(), DBGC, ETIMEDOUT, mdelay(), rtc_flag, and RTC_MAX_WAIT_MS.

Referenced by rtc_entropy_enable().

                                      {
        unsigned int i;

        /* Check that RTC interrupts are working */
        rtc_flag = 0;
        for ( i = 0 ; i < RTC_MAX_WAIT_MS ; i++ ) {

                /* Allow interrupts to occur */
                __asm__ __volatile__ ( "sti\n\t"
                                       "nop\n\t"
                                       "nop\n\t"
                                       "cli\n\t" );

                /* Check for RTC interrupt flag */
                if ( rtc_flag )
                        return 0;

                /* Delay */
                mdelay ( 1 );
        }

        DBGC ( &rtc_flag, "RTC timed out waiting for interrupt\n" );
        return -ETIMEDOUT;
}
static int rtc_entropy_enable ( void  ) [static]

Enable entropy gathering.

Return values:
rcReturn status code

Definition at line 176 of file rtc_entropy.c.

References rc, rtc_disable_int(), rtc_enable_int(), rtc_entropy_check(), rtc_hook_isr(), RTC_IRQ, and rtc_unhook_isr().

                                       {
        int rc;

        /* Hook ISR and enable RTC interrupts */
        rtc_hook_isr();
        enable_irq ( RTC_IRQ );
        rtc_enable_int();

        /* Check that RTC interrupts are working */
        if ( ( rc = rtc_entropy_check() ) != 0 )
                goto err_check;

        return 0;

 err_check:
        rtc_disable_int();
        disable_irq ( RTC_IRQ );
        rtc_unhook_isr();
        return rc;
}
static void rtc_entropy_disable ( void  ) [static]

Disable entropy gathering.

Definition at line 201 of file rtc_entropy.c.

References rtc_disable_int(), RTC_IRQ, and rtc_unhook_isr().

                                         {

        /* Disable RTC interrupts and unhook ISR */
        rtc_disable_int();
        disable_irq ( RTC_IRQ );
        rtc_unhook_isr();
}
uint8_t rtc_sample ( void  )

Measure a single RTC tick.

Return values:
deltaLength of RTC tick (in TSC units)

Definition at line 214 of file rtc_entropy.c.

References __asm__(), and REAL_CODE.

Referenced by ENTROPY_INLINE().

                            {
        uint32_t before;
        uint32_t after;
        uint32_t temp;

        __asm__ __volatile__ (
                REAL_CODE ( /* Enable interrupts */
                            "sti\n\t"
                            /* Wait for RTC interrupt */
                            "movb %b2, %%cs:rtc_flag\n\t"
                            "\n1:\n\t"
                            "xchgb %b2, %%cs:rtc_flag\n\t" /* Serialize */
                            "testb %b2, %b2\n\t"
                            "jz 1b\n\t"
                            /* Read "before" TSC */
                            "rdtsc\n\t"
                            /* Store "before" TSC on stack */
                            "pushl %0\n\t"
                            /* Wait for another RTC interrupt */
                            "xorb %b2, %b2\n\t"
                            "movb %b2, %%cs:rtc_flag\n\t"
                            "\n1:\n\t"
                            "xchgb %b2, %%cs:rtc_flag\n\t" /* Serialize */
                            "testb %b2, %b2\n\t"
                            "jz 1b\n\t"
                            /* Read "after" TSC */
                            "rdtsc\n\t"
                            /* Retrieve "before" TSC on stack */
                            "popl %1\n\t"
                            /* Disable interrupts */
                            "cli\n\t"
                            )
                : "=a" ( after ), "=d" ( before ), "=Q" ( temp )
                : "2" ( 0 ) );

        return ( after - before );
}

Variable Documentation

struct segoff rtc_old_handler [static]

Previous RTC interrupt handler.

Definition at line 48 of file rtc_entropy.c.

Referenced by rtc_hook_isr(), and rtc_unhook_isr().