Browse Source

[efi] Add support for EFI_GRAPHICS_OUTPUT_PROTOCOL frame buffer consoles

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 8 years ago
parent
commit
6847232e70

+ 6
- 0
src/config/config_efi.c View File

@@ -39,3 +39,9 @@ PROVIDE_REQUIRING_SYMBOL();
39 39
 #ifdef CONSOLE_EFI
40 40
 REQUIRE_OBJECT ( efi_console );
41 41
 #endif
42
+#ifdef CONSOLE_EFIFB
43
+REQUIRE_OBJECT ( efi_fbcon );
44
+#endif
45
+#ifdef CONSOLE_FRAMEBUFFER
46
+REQUIRE_OBJECT ( efi_fbcon );
47
+#endif

+ 4
- 0
src/image/efi_image.c View File

@@ -34,6 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
34 34
 #include <ipxe/init.h>
35 35
 #include <ipxe/features.h>
36 36
 #include <ipxe/uri.h>
37
+#include <ipxe/console.h>
37 38
 
38 39
 FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 );
39 40
 
@@ -236,6 +237,9 @@ static int efi_image_exec ( struct image *image ) {
236 237
 	/* Wrap calls made by the loaded image (for debugging) */
237 238
 	efi_wrap ( handle );
238 239
 
240
+	/* Reset console since image will probably use it */
241
+	console_reset();
242
+
239 243
 	/* Start the image */
240 244
 	if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) {
241 245
 		rc = -EEFI_START ( efirc );

+ 1
- 0
src/include/ipxe/errfile.h View File

@@ -342,6 +342,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
342 342
 #define ERRFILE_efi_watchdog	      ( ERRFILE_OTHER | 0x00490000 )
343 343
 #define ERRFILE_efi_pxe		      ( ERRFILE_OTHER | 0x004a0000 )
344 344
 #define ERRFILE_efi_usb		      ( ERRFILE_OTHER | 0x004b0000 )
345
+#define ERRFILE_efi_fbcon	      ( ERRFILE_OTHER | 0x004c0000 )
345 346
 
346 347
 /** @} */
347 348
 

+ 551
- 0
src/interface/efi/efi_fbcon.c View File

@@ -0,0 +1,551 @@
1
+/*
2
+ * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ *
19
+ * You can also choose to distribute this program under the terms of
20
+ * the Unmodified Binary Distribution Licence (as given in the file
21
+ * COPYING.UBDL), provided that you have satisfied its requirements.
22
+ */
23
+
24
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
+
26
+/**
27
+ * @file
28
+ *
29
+ * EFI frame buffer console
30
+ *
31
+ */
32
+
33
+#include <string.h>
34
+#include <strings.h>
35
+#include <ctype.h>
36
+#include <errno.h>
37
+#include <assert.h>
38
+#include <limits.h>
39
+#include <ipxe/efi/efi.h>
40
+#include <ipxe/efi/Protocol/GraphicsOutput.h>
41
+#include <ipxe/efi/Protocol/HiiFont.h>
42
+#include <ipxe/ansicol.h>
43
+#include <ipxe/fbcon.h>
44
+#include <ipxe/console.h>
45
+#include <ipxe/umalloc.h>
46
+#include <ipxe/rotate.h>
47
+#include <config/console.h>
48
+
49
+/* Avoid dragging in EFI console if not otherwise used */
50
+extern struct console_driver efi_console;
51
+struct console_driver efi_console __attribute__ (( weak ));
52
+
53
+/* Set default console usage if applicable
54
+ *
55
+ * We accept either CONSOLE_FRAMEBUFFER or CONSOLE_EFIFB.
56
+ */
57
+#if ( defined ( CONSOLE_FRAMEBUFFER ) && ! defined ( CONSOLE_EFIFB ) )
58
+#define CONSOLE_EFIFB CONSOLE_FRAMEBUFFER
59
+#endif
60
+#if ! ( defined ( CONSOLE_EFIFB ) && CONSOLE_EXPLICIT ( CONSOLE_EFIFB ) )
61
+#undef CONSOLE_EFIFB
62
+#define CONSOLE_EFIFB ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
63
+#endif
64
+
65
+/* Forward declaration */
66
+struct console_driver efifb_console __console_driver;
67
+
68
+/** An EFI frame buffer */
69
+struct efifb {
70
+	/** EFI graphics output protocol */
71
+	EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
72
+	/** EFI HII font protocol */
73
+	EFI_HII_FONT_PROTOCOL *hiifont;
74
+	/** Saved mode */
75
+	UINT32 saved_mode;
76
+
77
+	/** Frame buffer console */
78
+	struct fbcon fbcon;
79
+	/** Physical start address */
80
+	physaddr_t start;
81
+	/** Pixel geometry */
82
+	struct fbcon_geometry pixel;
83
+	/** Colour mapping */
84
+	struct fbcon_colour_map map;
85
+	/** Font definition */
86
+	struct fbcon_font font;
87
+	/** Character glyphs */
88
+	userptr_t glyphs;
89
+};
90
+
91
+/** The EFI frame buffer */
92
+static struct efifb efifb;
93
+
94
+/**
95
+ * Get character glyph
96
+ *
97
+ * @v character		Character
98
+ * @v glyph		Character glyph to fill in
99
+ */
100
+static void efifb_glyph ( unsigned int character, uint8_t *glyph ) {
101
+	size_t offset = ( character * efifb.font.height );
102
+
103
+	copy_from_user ( glyph, efifb.glyphs, offset, efifb.font.height );
104
+}
105
+
106
+/**
107
+ * Get character glyphs
108
+ *
109
+ * @ret rc		Return status code
110
+ */
111
+static int efifb_glyphs ( void ) {
112
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
113
+	EFI_FONT_DISPLAY_INFO *info;
114
+	EFI_IMAGE_OUTPUT *blt;
115
+	EFI_GRAPHICS_OUTPUT_BLT_PIXEL *pixel;
116
+	size_t offset;
117
+	size_t len;
118
+	uint8_t bitmask;
119
+	unsigned int character;
120
+	unsigned int x;
121
+	unsigned int y;
122
+	EFI_STATUS efirc;
123
+	int rc;
124
+
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;
132
+	}
133
+	assert ( info != NULL );
134
+	efifb.font.height = info->FontInfo.FontSize;
135
+
136
+	/* Allocate glyph data */
137
+	len = ( 256 * efifb.font.height * sizeof ( bitmask ) );
138
+	efifb.glyphs = umalloc ( len );
139
+	if ( ! efifb.glyphs ) {
140
+		rc = -ENOMEM;
141
+		goto err_alloc;
142
+	}
143
+	memset_user ( efifb.glyphs, 0, 0, len );
144
+
145
+	/* Get font data */
146
+	for ( character = 0 ; character < 256 ; character++ ) {
147
+
148
+		/* Skip non-printable characters */
149
+		if ( ! isprint ( character ) )
150
+			continue;
151
+
152
+		/* Get glyph */
153
+		blt = NULL;
154
+		if ( ( efirc = efifb.hiifont->GetGlyph ( efifb.hiifont,
155
+							 character, info, &blt,
156
+							 NULL ) ) != 0 ) {
157
+			rc = -EEFI ( efirc );
158
+			DBGC ( &efifb, "EFIFB could not get glyph %d: %s\n",
159
+			       character, strerror ( rc ) );
160
+			continue;
161
+		}
162
+		assert ( blt != NULL );
163
+
164
+		/* Sanity check */
165
+		if ( blt->Width > 8 ) {
166
+			DBGC ( &efifb, "EFIFB glyph %d invalid width %d\n",
167
+			       character, blt->Width );
168
+			continue;
169
+		}
170
+		if ( blt->Height > efifb.font.height ) {
171
+			DBGC ( &efifb, "EFIFB glyph %d invalid height %d\n",
172
+			       character, blt->Height );
173
+			continue;
174
+		}
175
+
176
+		/* Convert glyph to bitmap */
177
+		pixel = blt->Image.Bitmap;
178
+		offset = ( character * efifb.font.height );
179
+		for ( y = 0 ; y < blt->Height ; y++ ) {
180
+			bitmask = 0;
181
+			for ( x = 0 ; x < blt->Width ; x++ ) {
182
+				bitmask = rol8 ( bitmask, 1 );
183
+				if ( pixel->Blue || pixel->Green || pixel->Red )
184
+					bitmask |= 0x01;
185
+				pixel++;
186
+			}
187
+			copy_to_user ( efifb.glyphs, offset++, &bitmask,
188
+				       sizeof ( bitmask ) );
189
+		}
190
+		bs->FreePool ( blt );
191
+	}
192
+
193
+	/* Free font information */
194
+	bs->FreePool ( info );
195
+
196
+	efifb.font.glyph = efifb_glyph;
197
+	return 0;
198
+
199
+	ufree ( efifb.glyphs );
200
+ err_alloc:
201
+	bs->FreePool ( info );
202
+ err_info:
203
+	return rc;
204
+}
205
+
206
+/**
207
+ * Generate colour mapping for a single colour component
208
+ *
209
+ * @v mask		Mask value
210
+ * @v scale		Scale value to fill in
211
+ * @v lsb		LSB value to fill in
212
+ * @ret rc		Return status code
213
+ */
214
+static int efifb_colour_map_mask ( uint32_t mask, uint8_t *scale,
215
+				   uint8_t *lsb ) {
216
+	uint32_t check;
217
+
218
+	/* Fill in LSB and scale */
219
+	*lsb = ( mask ? ( ffs ( mask ) - 1 ) : 0 );
220
+	*scale = ( mask ? ( 8 - ( fls ( mask ) - *lsb ) ) : 8 );
221
+
222
+	/* Check that original mask was contiguous */
223
+	check = ( ( 0xff >> *scale ) << *lsb );
224
+	if ( check != mask )
225
+		return -ENOTSUP;
226
+
227
+	return 0;
228
+}
229
+
230
+/**
231
+ * Generate colour mapping
232
+ *
233
+ * @v info		EFI mode information
234
+ * @v map		Colour mapping to fill in
235
+ * @ret bpp		Number of bits per pixel, or negative error
236
+ */
237
+static int efifb_colour_map ( EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info,
238
+			      struct fbcon_colour_map *map ) {
239
+	static EFI_PIXEL_BITMASK rgb_mask = {
240
+		0x000000ffUL, 0x0000ff00UL, 0x00ff0000UL, 0xff000000UL
241
+	};
242
+	static EFI_PIXEL_BITMASK bgr_mask = {
243
+		0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL, 0xff000000UL
244
+	};
245
+	EFI_PIXEL_BITMASK *mask;
246
+	uint8_t reserved_scale;
247
+	uint8_t reserved_lsb;
248
+	int rc;
249
+
250
+	/* Determine applicable mask */
251
+	switch ( info->PixelFormat ) {
252
+	case PixelRedGreenBlueReserved8BitPerColor:
253
+		mask = &rgb_mask;
254
+		break;
255
+	case PixelBlueGreenRedReserved8BitPerColor:
256
+		mask = &bgr_mask;
257
+		break;
258
+	case PixelBitMask:
259
+		mask = &info->PixelInformation;
260
+		break;
261
+	default:
262
+		DBGC ( &efifb, "EFIFB unrecognised pixel format %d\n",
263
+		       info->PixelFormat );
264
+		return -ENOTSUP;
265
+	}
266
+
267
+	/* Map each colour component */
268
+	if ( ( rc = efifb_colour_map_mask ( mask->RedMask, &map->red_scale,
269
+					    &map->red_lsb ) ) != 0 )
270
+		return rc;
271
+	if ( ( rc = efifb_colour_map_mask ( mask->GreenMask, &map->green_scale,
272
+					    &map->green_lsb ) ) != 0 )
273
+		return rc;
274
+	if ( ( rc = efifb_colour_map_mask ( mask->BlueMask, &map->blue_scale,
275
+					    &map->blue_lsb ) ) != 0 )
276
+		return rc;
277
+	if ( ( rc = efifb_colour_map_mask ( mask->ReservedMask, &reserved_scale,
278
+					    &reserved_lsb ) ) != 0 )
279
+		return rc;
280
+
281
+	/* Calculate total number of bits per pixel */
282
+	return ( 32 - ( reserved_scale + map->red_scale + map->green_scale +
283
+			map->blue_scale ) );
284
+}
285
+
286
+/**
287
+ * Select video mode
288
+ *
289
+ * @v min_width		Minimum required width (in pixels)
290
+ * @v min_height	Minimum required height (in pixels)
291
+ * @v min_bpp		Minimum required colour depth (in bits per pixel)
292
+ * @ret mode_number	Mode number, or negative error
293
+ */
294
+static int efifb_select_mode ( unsigned int min_width, unsigned int min_height,
295
+			       unsigned int min_bpp ) {
296
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
297
+	struct fbcon_colour_map map;
298
+	EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
299
+	int best_mode_number = -ENOENT;
300
+	unsigned int best_score = INT_MAX;
301
+	unsigned int score;
302
+	unsigned int mode;
303
+	int bpp;
304
+	UINTN size;
305
+	EFI_STATUS efirc;
306
+	int rc;
307
+
308
+	/* Find the best mode */
309
+	for ( mode = 0 ; mode < efifb.gop->Mode->MaxMode ; mode++ ) {
310
+
311
+		/* Get mode information */
312
+		if ( ( efirc = efifb.gop->QueryMode ( efifb.gop, mode, &size,
313
+						      &info ) ) != 0 ) {
314
+			rc = -EEFI ( efirc );
315
+			DBGC ( &efifb, "EFIFB could not get mode %d "
316
+			       "information: %s\n", mode, strerror ( rc ) );
317
+			goto err_query;
318
+		}
319
+
320
+		/* Skip unusable modes */
321
+		bpp = efifb_colour_map ( info, &map );
322
+		if ( bpp < 0 ) {
323
+			rc = bpp;
324
+			DBGC ( &efifb, "EFIFB could not build colour map for "
325
+			       "mode %d: %s\n", mode, strerror ( rc ) );
326
+			goto err_map;
327
+		}
328
+
329
+		/* Skip modes not meeting the requirements */
330
+		if ( ( info->HorizontalResolution < min_width ) ||
331
+		     ( info->VerticalResolution < min_height ) ||
332
+		     ( ( ( unsigned int ) bpp ) < min_bpp ) ) {
333
+			goto err_requirements;
334
+		}
335
+
336
+		/* Select this mode if it has the best (i.e. lowest)
337
+		 * score.  We choose the scoring system to favour
338
+		 * modes close to the specified width and height;
339
+		 * within modes of the same width and height we prefer
340
+		 * a higher colour depth.
341
+		 */
342
+		score = ( ( info->HorizontalResolution *
343
+			    info->VerticalResolution ) - bpp );
344
+		if ( score < best_score ) {
345
+			best_mode_number = mode;
346
+			best_score = score;
347
+		}
348
+
349
+	err_requirements:
350
+	err_map:
351
+		bs->FreePool ( info );
352
+	err_query:
353
+		continue;
354
+	}
355
+
356
+	if ( best_mode_number < 0 )
357
+		DBGC ( &efifb, "EFIFB found no suitable mode\n" );
358
+	return best_mode_number;
359
+}
360
+
361
+/**
362
+ * Restore video mode
363
+ *
364
+ * @v rc		Return status code
365
+ */
366
+static int efifb_restore ( void ) {
367
+	EFI_STATUS efirc;
368
+	int rc;
369
+
370
+	/* Restore original mode */
371
+	if ( ( efirc = efifb.gop->SetMode ( efifb.gop,
372
+					    efifb.saved_mode ) ) != 0 ) {
373
+		rc = -EEFI ( efirc );
374
+		DBGC ( &efifb, "EFIFB could not restore mode %d: %s\n",
375
+		       efifb.saved_mode, strerror ( rc ) );
376
+		return rc;
377
+	}
378
+
379
+	return 0;
380
+}
381
+
382
+/**
383
+ * Initialise EFI frame buffer
384
+ *
385
+ * @v config		Console configuration, or NULL to reset
386
+ * @ret rc		Return status code
387
+ */
388
+static int efifb_init ( struct console_configuration *config ) {
389
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
390
+	EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
391
+	void *interface;
392
+	int mode;
393
+	int bpp;
394
+	EFI_STATUS efirc;
395
+	int rc;
396
+
397
+	/* Locate graphics output protocol */
398
+	if ( ( efirc = bs->LocateProtocol ( &efi_graphics_output_protocol_guid,
399
+					    NULL, &interface ) ) != 0 ) {
400
+		rc = -EEFI ( efirc );
401
+		DBGC ( &efifb, "EFIFB could not locate graphics output "
402
+		       "protocol: %s\n", strerror ( rc ) );
403
+		goto err_locate_gop;
404
+	}
405
+	efifb.gop = interface;
406
+
407
+	/* Locate HII font protocol */
408
+	if ( ( efirc = bs->LocateProtocol ( &efi_hii_font_protocol_guid,
409
+					    NULL, &interface ) ) != 0 ) {
410
+		rc = -EEFI ( efirc );
411
+		DBGC ( &efifb, "EFIFB could not locate HII font protocol: %s\n",
412
+		       strerror ( rc ) );
413
+		goto err_locate_hiifont;
414
+	}
415
+	efifb.hiifont = interface;
416
+
417
+	/* Locate glyphs */
418
+	if ( ( rc = efifb_glyphs() ) != 0 )
419
+		goto err_glyphs;
420
+
421
+	/* Save original mode */
422
+	efifb.saved_mode = efifb.gop->Mode->Mode;
423
+
424
+	/* Select mode */
425
+	if ( ( mode = efifb_select_mode ( config->width, config->height,
426
+					  config->depth ) ) < 0 ) {
427
+		rc = mode;
428
+		goto err_select_mode;
429
+	}
430
+
431
+	/* Set mode */
432
+	if ( ( efirc = efifb.gop->SetMode ( efifb.gop, mode ) ) != 0 ) {
433
+		rc = -EEFI ( efirc );
434
+		DBGC ( &efifb, "EFIFB could not set mode %d: %s\n",
435
+		       mode, strerror ( rc ) );
436
+		goto err_set_mode;
437
+	}
438
+	info = efifb.gop->Mode->Info;
439
+
440
+	/* Populate colour map */
441
+	bpp = efifb_colour_map ( info, &efifb.map );
442
+	if ( bpp < 0 ) {
443
+		rc = bpp;
444
+		DBGC ( &efifb, "EFIFB could not build colour map for "
445
+		       "mode %d: %s\n", mode, strerror ( rc ) );
446
+		goto err_map;
447
+	}
448
+
449
+	/* Populate pixel geometry */
450
+	efifb.pixel.width = info->HorizontalResolution;
451
+	efifb.pixel.height = info->VerticalResolution;
452
+	efifb.pixel.len = ( ( bpp + 7 ) / 8 );
453
+	efifb.pixel.stride = ( efifb.pixel.len * info->PixelsPerScanLine );
454
+
455
+	/* Populate frame buffer address */
456
+	efifb.start = efifb.gop->Mode->FrameBufferBase;
457
+	DBGC ( &efifb, "EFIFB using mode %d (%dx%d %dbpp at %#08lx)\n",
458
+	       mode, efifb.pixel.width, efifb.pixel.height, bpp, efifb.start );
459
+
460
+	/* Initialise frame buffer console */
461
+	if ( ( rc = fbcon_init ( &efifb.fbcon, phys_to_user ( efifb.start ),
462
+				 &efifb.pixel, &efifb.map, &efifb.font,
463
+				 config ) ) != 0 )
464
+		goto err_fbcon_init;
465
+
466
+	return 0;
467
+
468
+	fbcon_fini ( &efifb.fbcon );
469
+ err_fbcon_init:
470
+ err_map:
471
+	efifb_restore();
472
+ err_set_mode:
473
+ err_select_mode:
474
+	ufree ( efifb.glyphs );
475
+ err_glyphs:
476
+ err_locate_hiifont:
477
+ err_locate_gop:
478
+	return rc;
479
+}
480
+
481
+/**
482
+ * Finalise EFI frame buffer
483
+ *
484
+ */
485
+static void efifb_fini ( void ) {
486
+
487
+	/* Finalise frame buffer console */
488
+	fbcon_fini ( &efifb.fbcon );
489
+
490
+	/* Restore saved mode */
491
+	efifb_restore();
492
+
493
+	/* Free glyphs */
494
+	ufree ( efifb.glyphs );
495
+}
496
+
497
+/**
498
+ * Print a character to current cursor position
499
+ *
500
+ * @v character		Character
501
+ */
502
+static void efifb_putchar ( int character ) {
503
+
504
+	fbcon_putchar ( &efifb.fbcon, character );
505
+}
506
+
507
+/**
508
+ * Configure console
509
+ *
510
+ * @v config		Console configuration, or NULL to reset
511
+ * @ret rc		Return status code
512
+ */
513
+static int efifb_configure ( struct console_configuration *config ) {
514
+	int rc;
515
+
516
+	/* Reset console, if applicable */
517
+	if ( ! efifb_console.disabled ) {
518
+		efifb_fini();
519
+		efi_console.disabled &= ~CONSOLE_DISABLED_OUTPUT;
520
+		ansicol_reset_magic();
521
+	}
522
+	efifb_console.disabled = CONSOLE_DISABLED;
523
+
524
+	/* Do nothing more unless we have a usable configuration */
525
+	if ( ( config == NULL ) ||
526
+	     ( config->width == 0 ) || ( config->height == 0 ) ) {
527
+		return 0;
528
+	}
529
+
530
+	/* Initialise EFI frame buffer */
531
+	if ( ( rc = efifb_init ( config ) ) != 0 )
532
+		return rc;
533
+
534
+	/* Mark console as enabled */
535
+	efifb_console.disabled = 0;
536
+	efi_console.disabled |= CONSOLE_DISABLED_OUTPUT;
537
+
538
+	/* Set magic colour to transparent if we have a background picture */
539
+	if ( config->pixbuf )
540
+		ansicol_set_magic_transparent();
541
+
542
+	return 0;
543
+}
544
+
545
+/** EFI graphics output protocol console driver */
546
+struct console_driver efifb_console __console_driver = {
547
+	.usage = CONSOLE_EFIFB,
548
+	.putchar = efifb_putchar,
549
+	.configure = efifb_configure,
550
+	.disabled = CONSOLE_DISABLED,
551
+};

+ 4
- 0
src/interface/efi/efi_snp.c View File

@@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
28 28
 #include <ipxe/iobuf.h>
29 29
 #include <ipxe/in.h>
30 30
 #include <ipxe/version.h>
31
+#include <ipxe/console.h>
31 32
 #include <ipxe/efi/efi.h>
32 33
 #include <ipxe/efi/efi_driver.h>
33 34
 #include <ipxe/efi/efi_strings.h>
@@ -1495,6 +1496,9 @@ efi_snp_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file,
1495 1496
 	if ( ( rc = ipxe ( netdev ) ) != 0 )
1496 1497
 		goto err_ipxe;
1497 1498
 
1499
+	/* Reset console */
1500
+	console_reset();
1501
+
1498 1502
  err_ipxe:
1499 1503
 	efi_watchdog_stop();
1500 1504
 	efi_snp_release();

Loading…
Cancel
Save