[ipxe-devel] Patch: Introduce revocable_pause()

Earl Chew earl_chew at yahoo.com
Thu Nov 5 15:06:59 UTC 2015


This patch introduces function revocable_pause() that allows for a pause
that can be interrupted if a keystroke is detected. The function will
print the remaining time as the pause counts down.

I don't have an UEFI setup, so the small amount of efi_systab related
code is untested.


commit f6680ded106172f5ffb1c59e032caabb3ab0c54d
Author: Earl Chew <earl_chew at yahoo.com>
Date:   Sun Nov 1 07:32:55 2015 -0800

     [pause] Introduce revocable_pause

     Signed-off-by: Earl Chew <earl_chew at yahoo.com>

diff --git a/src/pause.c b/src/pause.c
index 72c50f0..5f5cec5 100644
--- a/src/pause.c
+++ b/src/pause.c
@@ -25,9 +25,12 @@
   */

  #include <stdio.h>
+#include <string.h>
+#include "bootapp.h"
  #include "wimboot.h"
  #include "cmdline.h"
  #include "pause.h"
+#include "efi.h"

  /**
   * Pause before booting
@@ -44,3 +47,101 @@ void pause ( void ) {
  		printf ( "\n" );
  	}
  }
+
+/**
+ * Pause allowing revocation from the keyboard
+ *
+ */
+#define TICKS_24HRS 0x1800b0
+
+static uint32_t ticks ( uint32_t mark ) {
+	struct bootapp_callback_params params;
+	uint32_t sample;
+
+	memset ( &params, 0, sizeof ( params ) );
+	params.vector.interrupt = 0x1a;
+	params.ah = 0x00;
+	call_interrupt ( &params );
+
+	sample = params.cx << 16 | params.dx;
+	if (sample < mark)
+		sample += TICKS_24HRS;
+	return sample - mark;
+}
+
+static void pause1s ( void ) {
+	if ( efi_systab ) {
+		efi_systab->BootServices->Stall(1000 * 1000);
+	} else {
+		uint32_t mark = ticks(0);
+
+		while (ticks(mark) < TICKS_24HRS / (24 * 60 * 60))
+			continue;
+	}
+}
+
+static uint32_t keystroke ( void ) {
+	uint32_t key;
+
+	if ( efi_systab ) {
+		EFI_INPUT_KEY efikey;
+
+		if ( efi_systab->ConIn->ReadKeyStroke (
+				efi_systab->ConIn, &efikey ) != EFI_SUCCESS )
+			key = 0;
+		else
+			key = 0x10000 | efikey.UnicodeChar;
+	} else {
+		struct bootapp_callback_params params;
+
+		memset ( &params, 0, sizeof ( params ) );
+		params.vector.interrupt = 0x16;
+		params.ah = 0x01;
+		call_interrupt ( &params );
+
+		if (params.eflags & ZF) {
+			params.eax = 0;
+		} else {
+			memset ( &params, 0, sizeof ( params ) );
+			params.vector.interrupt = 0x16;
+			params.ah = 0x00;
+			call_interrupt ( &params );
+			params.eax = 0x10000 | params.ax;
+		}
+
+		key = params.eax;
+	}
+
+	return key;
+}
+
+static void erase ( const char *text ) {
+	unsigned int ix;
+
+	for (ix = 0; text[ix]; ++ix )
+		printf("\b");
+	for (ix = 0; text[ix]; ++ix )
+		printf(" ");
+	for (ix = 0; text[ix]; ++ix )
+		printf("\b");
+}
+
+unsigned int revocable_pause ( unsigned int seconds ) {
+
+	char text[sizeof(" ") + sizeof(seconds) * 3] = { 0 };
+
+	while ( seconds ) {
+
+		snprintf( text, sizeof(text), " %u", seconds );
+		printf( "%s", text );
+		pause1s ();
+		erase( text );
+
+		if ( keystroke() )
+			break;
+
+		--seconds;
+	}
+
+	return seconds;
+}
diff --git a/src/pause.h b/src/pause.h
index 4fe364b..7846589 100644
--- a/src/pause.h
+++ b/src/pause.h
@@ -28,5 +28,6 @@
   */

  extern void pause ( void );
+extern unsigned int revocable_pause ( unsigned int seconds );

  #endif /* _PAUSE_H */




More information about the ipxe-devel mailing list