aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2022-03-15 15:04:22 +0000
committerMichael Brown <mcb30@ipxe.org>2022-03-15 16:25:13 +0000
commit253987b1826745417f707be983345b601f99b300 (patch)
treeecd4825ab47e823a6438e8381282ecf337265976
parent46a855283ab14f4c081fbba5118bfa2f476306c3 (diff)
downloadipxe-utf8.zip
ipxe-utf8.tar.gz
ipxe-utf8.tar.bz2
[efi] Support Unicode console output via framebuffer consoleutf8
Extend the glyph cache to include a number of dynamic entries that are populated on demand whenever a non-ASCII character needs to be drawn. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/interface/efi/efi_fbcon.c51
1 files changed, 48 insertions, 3 deletions
diff --git a/src/interface/efi/efi_fbcon.c b/src/interface/efi/efi_fbcon.c
index d9e3e69..d388e03 100644
--- a/src/interface/efi/efi_fbcon.c
+++ b/src/interface/efi/efi_fbcon.c
@@ -65,6 +65,9 @@ struct console_driver efi_console __attribute__ (( weak ));
/** Number of ASCII glyphs in cache */
#define EFIFB_ASCII 128
+/** Number of dynamic non-ASCII glyphs in cache */
+#define EFIFB_DYNAMIC 32
+
/* Forward declaration */
struct console_driver efifb_console __console_driver;
@@ -89,6 +92,10 @@ struct efifb {
struct fbcon_font font;
/** Character glyph cache */
userptr_t glyphs;
+ /** Dynamic characters in cache */
+ unsigned int dynamic[EFIFB_DYNAMIC];
+ /** Next dynamic character cache entry to evict */
+ unsigned int next;
};
/** The EFI frame buffer */
@@ -178,6 +185,41 @@ static int efifb_draw_unknown ( unsigned int index ) {
}
/**
+ * Get dynamic glyph index
+ *
+ * @v character Unicode character
+ * @ret index Glyph cache index
+ */
+static unsigned int efifb_dynamic ( unsigned int character ) {
+ unsigned int dynamic;
+ unsigned int index;
+ unsigned int i;
+ int height;
+
+ /* Search existing cached entries */
+ for ( i = 0 ; i < EFIFB_DYNAMIC ; i++ ) {
+ if ( character == efifb.dynamic[i] )
+ return ( EFIFB_ASCII + i );
+ }
+
+ /* Overwrite the oldest cache entry */
+ dynamic = ( efifb.next++ % EFIFB_DYNAMIC );
+ index = ( EFIFB_ASCII + dynamic );
+ DBGC2 ( &efifb, "EFIFB dynamic %#02x is glyph %#02x\n",
+ dynamic, character );
+
+ /* Draw glyph */
+ height = efifb_draw ( character, index, 0 );
+ if ( height < 0 )
+ efifb_draw_unknown ( index );
+
+ /* Record cached character */
+ efifb.dynamic[dynamic] = character;
+
+ return index;
+}
+
+/**
* Get character glyph
*
* @v character Unicode character
@@ -195,8 +237,8 @@ static void efifb_glyph ( unsigned int character, uint8_t *glyph ) {
} else {
- /* Non-ASCII character: use an "unknown" glyph */
- index = 0;
+ /* Non-ASCII character: use dynamic glyph cache */
+ index = efifb_dynamic ( character );
}
/* Copy cached glyph */
@@ -248,7 +290,7 @@ static int efifb_glyphs ( void ) {
efifb.font.height = max;
/* Allocate glyph data */
- len = ( EFIFB_ASCII * efifb.font.height );
+ len = ( ( EFIFB_ASCII + EFIFB_DYNAMIC ) * efifb.font.height );
efifb.glyphs = umalloc ( len );
if ( ! efifb.glyphs ) {
rc = -ENOMEM;
@@ -273,6 +315,9 @@ static int efifb_glyphs ( void ) {
}
}
+ /* Clear dynamic glyph character cache */
+ memset ( efifb.dynamic, 0, sizeof ( efifb.dynamic ) );
+
efifb.font.glyph = efifb_glyph;
return 0;