소스 검색

[efi] Work around broken GetFontInfo() implementations

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>
tags/v1.20.1
Michael Brown 8 년 전
부모
커밋
e303a6b387
1개의 변경된 파일38개의 추가작업 그리고 16개의 파일을 삭제
  1. 38
    16
      src/interface/efi/efi_fbcon.c

+ 38
- 16
src/interface/efi/efi_fbcon.c 파일 보기

@@ -110,7 +110,6 @@ static void efifb_glyph ( unsigned int character, uint8_t *glyph ) {
110 110
  */
111 111
 static int efifb_glyphs ( void ) {
112 112
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
113
-	EFI_FONT_DISPLAY_INFO *info;
114 113
 	EFI_IMAGE_OUTPUT *blt;
115 114
 	EFI_GRAPHICS_OUTPUT_BLT_PIXEL *pixel;
116 115
 	size_t offset;
@@ -122,16 +121,42 @@ static int efifb_glyphs ( void ) {
122 121
 	EFI_STATUS efirc;
123 122
 	int rc;
124 123
 
125
-	/* Get font height */
126
-	if ( ( efirc = efifb.hiifont->GetFontInfo ( efifb.hiifont, NULL, NULL,
127
-						    &info, NULL ) ) != 0 ) {
128
-		rc = -EEFI ( efirc );
129
-		DBGC ( &efifb, "EFIFB could not get font information: %s\n",
130
-		       strerror ( rc ) );
131
-		goto err_info;
124
+	/* Get font height.  The GetFontInfo() call nominally returns
125
+	 * this information in an EFI_FONT_DISPLAY_INFO structure, but
126
+	 * is known to fail on many UEFI implementations.  Instead, we
127
+	 * iterate over all printable characters to find the maximum
128
+	 * height.
129
+	 */
130
+	efifb.font.height = 0;
131
+	for ( character = 0 ; character < 256 ; character++ ) {
132
+
133
+		/* Skip non-printable characters */
134
+		if ( ! isprint ( character ) )
135
+			continue;
136
+
137
+		/* Get glyph */
138
+		blt = NULL;
139
+		if ( ( efirc = efifb.hiifont->GetGlyph ( efifb.hiifont,
140
+							 character, NULL, &blt,
141
+							 NULL ) ) != 0 ) {
142
+			rc = -EEFI ( efirc );
143
+			DBGC ( &efifb, "EFIFB could not get glyph %d: %s\n",
144
+			       character, strerror ( rc ) );
145
+			continue;
146
+		}
147
+		assert ( blt != NULL );
148
+
149
+		/* Calculate maximum height */
150
+		if ( efifb.font.height < blt->Height )
151
+			efifb.font.height = blt->Height;
152
+
153
+		/* Free glyph */
154
+		bs->FreePool ( blt );
155
+	}
156
+	if ( ! efifb.font.height ) {
157
+		DBGC ( &efifb, "EFIFB could not get font height\n" );
158
+		return -ENOENT;
132 159
 	}
133
-	assert ( info != NULL );
134
-	efifb.font.height = info->FontInfo.FontSize;
135 160
 
136 161
 	/* Allocate glyph data */
137 162
 	len = ( 256 * efifb.font.height * sizeof ( bitmask ) );
@@ -152,7 +177,7 @@ static int efifb_glyphs ( void ) {
152 177
 		/* Get glyph */
153 178
 		blt = NULL;
154 179
 		if ( ( efirc = efifb.hiifont->GetGlyph ( efifb.hiifont,
155
-							 character, info, &blt,
180
+							 character, NULL, &blt,
156 181
 							 NULL ) ) != 0 ) {
157 182
 			rc = -EEFI ( efirc );
158 183
 			DBGC ( &efifb, "EFIFB could not get glyph %d: %s\n",
@@ -187,19 +212,16 @@ static int efifb_glyphs ( void ) {
187 212
 			copy_to_user ( efifb.glyphs, offset++, &bitmask,
188 213
 				       sizeof ( bitmask ) );
189 214
 		}
215
+
216
+		/* Free glyph */
190 217
 		bs->FreePool ( blt );
191 218
 	}
192 219
 
193
-	/* Free font information */
194
-	bs->FreePool ( info );
195
-
196 220
 	efifb.font.glyph = efifb_glyph;
197 221
 	return 0;
198 222
 
199 223
 	ufree ( efifb.glyphs );
200 224
  err_alloc:
201
-	bs->FreePool ( info );
202
- err_info:
203 225
 	return rc;
204 226
 }
205 227
 

Loading…
취소
저장