]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Work around broken GetFontInfo() implementations
authorMichael Brown <mcb30@ipxe.org>
Thu, 10 Mar 2016 18:06:26 +0000 (18:06 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 10 Mar 2016 18:09:59 +0000 (18:09 +0000)
Several UEFI platforms are known to return EFI_NOT_FOUND when asked to
retrieve the system default font information via GetFontInfo().  Work
around these broken platforms by iterating over the glyphs to find the
maximum height used by a printable character.

Originally-fixed-by: Jonathan Dieter <jdieter@lesbg.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/interface/efi/efi_fbcon.c

index 01b691b65227d769acd4ab4f96b3f5c18f6ac779..abc5a93908a62a08fab4f292ac2509d0b296f735 100644 (file)
@@ -110,7 +110,6 @@ static void efifb_glyph ( unsigned int character, uint8_t *glyph ) {
  */
 static int efifb_glyphs ( void ) {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
-       EFI_FONT_DISPLAY_INFO *info;
        EFI_IMAGE_OUTPUT *blt;
        EFI_GRAPHICS_OUTPUT_BLT_PIXEL *pixel;
        size_t offset;
@@ -122,16 +121,42 @@ static int efifb_glyphs ( void ) {
        EFI_STATUS efirc;
        int rc;
 
-       /* Get font height */
-       if ( ( efirc = efifb.hiifont->GetFontInfo ( efifb.hiifont, NULL, NULL,
-                                                   &info, NULL ) ) != 0 ) {
-               rc = -EEFI ( efirc );
-               DBGC ( &efifb, "EFIFB could not get font information: %s\n",
-                      strerror ( rc ) );
-               goto err_info;
+       /* Get font height.  The GetFontInfo() call nominally returns
+        * this information in an EFI_FONT_DISPLAY_INFO structure, but
+        * is known to fail on many UEFI implementations.  Instead, we
+        * iterate over all printable characters to find the maximum
+        * height.
+        */
+       efifb.font.height = 0;
+       for ( character = 0 ; character < 256 ; character++ ) {
+
+               /* Skip non-printable characters */
+               if ( ! isprint ( character ) )
+                       continue;
+
+               /* Get glyph */
+               blt = NULL;
+               if ( ( efirc = efifb.hiifont->GetGlyph ( efifb.hiifont,
+                                                        character, NULL, &blt,
+                                                        NULL ) ) != 0 ) {
+                       rc = -EEFI ( efirc );
+                       DBGC ( &efifb, "EFIFB could not get glyph %d: %s\n",
+                              character, strerror ( rc ) );
+                       continue;
+               }
+               assert ( blt != NULL );
+
+               /* Calculate maximum height */
+               if ( efifb.font.height < blt->Height )
+                       efifb.font.height = blt->Height;
+
+               /* Free glyph */
+               bs->FreePool ( blt );
+       }
+       if ( ! efifb.font.height ) {
+               DBGC ( &efifb, "EFIFB could not get font height\n" );
+               return -ENOENT;
        }
-       assert ( info != NULL );
-       efifb.font.height = info->FontInfo.FontSize;
 
        /* Allocate glyph data */
        len = ( 256 * efifb.font.height * sizeof ( bitmask ) );
@@ -152,7 +177,7 @@ static int efifb_glyphs ( void ) {
                /* Get glyph */
                blt = NULL;
                if ( ( efirc = efifb.hiifont->GetGlyph ( efifb.hiifont,
-                                                        character, info, &blt,
+                                                        character, NULL, &blt,
                                                         NULL ) ) != 0 ) {
                        rc = -EEFI ( efirc );
                        DBGC ( &efifb, "EFIFB could not get glyph %d: %s\n",
@@ -187,19 +212,16 @@ static int efifb_glyphs ( void ) {
                        copy_to_user ( efifb.glyphs, offset++, &bitmask,
                                       sizeof ( bitmask ) );
                }
+
+               /* Free glyph */
                bs->FreePool ( blt );
        }
 
-       /* Free font information */
-       bs->FreePool ( info );
-
        efifb.font.glyph = efifb_glyph;
        return 0;
 
        ufree ( efifb.glyphs );
  err_alloc:
-       bs->FreePool ( info );
- err_info:
        return rc;
 }