]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[rng] Check for several functioning RTC interrupts
authorMichael Brown <mcb30@ipxe.org>
Sat, 11 Feb 2023 15:07:00 +0000 (15:07 +0000)
committerMichael Brown <mcb30@ipxe.org>
Sat, 11 Feb 2023 15:11:51 +0000 (15:11 +0000)
Commit 74222cd ("[rng] Check for functioning RTC interrupt") added a
check that the RTC is capable of generating interrupts via the legacy
PIC, since this mechanism appears to be broken in some Hyper-V virtual
machines.

Experimentation shows that the RTC is sometimes capable of generating
a single interrupt, but will then generate no subsequent interrupts.
This currently causes rtc_entropy_check() to falsely detect that the
entropy gathering mechanism is functional.

Fix by checking for several RTC interrupts before declaring that it is
a functional entropy source.

Reported-by: Andreas Hammarskjöld <junior@2PintSoftware.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/x86/interface/pcbios/rtc_entropy.c

index e0c17568537aebdaf2a301b5c98b9808820d7e0f..c400d8a78b5c4d02191caaf69845e0214a9c7379 100644 (file)
@@ -42,6 +42,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 /** Maximum time to wait for an RTC interrupt, in milliseconds */
 #define RTC_MAX_WAIT_MS 100
 
+/** Number of RTC interrupts to check for */
+#define RTC_CHECK_COUNT 3
+
 /** RTC interrupt handler */
 extern void rtc_isr ( void );
 
@@ -145,6 +148,7 @@ static void rtc_disable_int ( void ) {
  * @ret rc             Return status code
  */
 static int rtc_entropy_check ( void ) {
+       unsigned int count = 0;
        unsigned int i;
 
        /* Check that RTC interrupts are working */
@@ -158,14 +162,18 @@ static int rtc_entropy_check ( void ) {
                                       "cli\n\t" );
 
                /* Check for RTC interrupt flag */
-               if ( rtc_flag )
-                       return 0;
+               if ( rtc_flag ) {
+                       rtc_flag = 0;
+                       if ( ++count >= RTC_CHECK_COUNT )
+                               return 0;
+               }
 
                /* Delay */
                mdelay ( 1 );
        }
 
-       DBGC ( &rtc_flag, "RTC timed out waiting for interrupt\n" );
+       DBGC ( &rtc_flag, "RTC timed out waiting for interrupt %d/%d\n",
+              ( count + 1 ), RTC_CHECK_COUNT );
        return -ETIMEDOUT;
 }