]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
MdeModulePkg/GraphicsConsoleDxe: Check status to make sure no error
[mirror_edk2.git] / MdeModulePkg / Universal / Console / GraphicsConsoleDxe / GraphicsConsole.c
1 /** @file
2 This is the main routine for initializing the Graphics Console support routines.
3
4 Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "GraphicsConsole.h"
10
11 //
12 // Graphics Console Device Private Data template
13 //
14 GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate = {
15 GRAPHICS_CONSOLE_DEV_SIGNATURE,
16 (EFI_GRAPHICS_OUTPUT_PROTOCOL *)NULL,
17 (EFI_UGA_DRAW_PROTOCOL *)NULL,
18 {
19 GraphicsConsoleConOutReset,
20 GraphicsConsoleConOutOutputString,
21 GraphicsConsoleConOutTestString,
22 GraphicsConsoleConOutQueryMode,
23 GraphicsConsoleConOutSetMode,
24 GraphicsConsoleConOutSetAttribute,
25 GraphicsConsoleConOutClearScreen,
26 GraphicsConsoleConOutSetCursorPosition,
27 GraphicsConsoleConOutEnableCursor,
28 (EFI_SIMPLE_TEXT_OUTPUT_MODE *)NULL
29 },
30 {
31 0,
32 -1,
33 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK),
34 0,
35 0,
36 FALSE
37 },
38 (GRAPHICS_CONSOLE_MODE_DATA *)NULL,
39 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)NULL
40 };
41
42 GRAPHICS_CONSOLE_MODE_DATA mGraphicsConsoleModeData[] = {
43 { 100, 31 },
44 //
45 // New modes can be added here.
46 // The last entry is specific for full screen mode.
47 //
48 { 0, 0 }
49 };
50
51 EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
52 EFI_HII_FONT_PROTOCOL *mHiiFont;
53 EFI_HII_HANDLE mHiiHandle;
54 VOID *mHiiRegistration;
55
56 EFI_GUID mFontPackageListGuid = {
57 0xf5f219d3, 0x7006, 0x4648, { 0xac, 0x8d, 0xd6, 0x1d, 0xfb, 0x7b, 0xc6, 0xad }
58 };
59
60 CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
61
62 EFI_GRAPHICS_OUTPUT_BLT_PIXEL mGraphicsEfiColors[16] = {
63 //
64 // B G R reserved
65 //
66 { 0x00, 0x00, 0x00, 0x00 }, // BLACK
67 { 0x98, 0x00, 0x00, 0x00 }, // LIGHTBLUE
68 { 0x00, 0x98, 0x00, 0x00 }, // LIGHGREEN
69 { 0x98, 0x98, 0x00, 0x00 }, // LIGHCYAN
70 { 0x00, 0x00, 0x98, 0x00 }, // LIGHRED
71 { 0x98, 0x00, 0x98, 0x00 }, // MAGENTA
72 { 0x00, 0x98, 0x98, 0x00 }, // BROWN
73 { 0x98, 0x98, 0x98, 0x00 }, // LIGHTGRAY
74 { 0x30, 0x30, 0x30, 0x00 }, // DARKGRAY - BRIGHT BLACK
75 { 0xff, 0x00, 0x00, 0x00 }, // BLUE
76 { 0x00, 0xff, 0x00, 0x00 }, // LIME
77 { 0xff, 0xff, 0x00, 0x00 }, // CYAN
78 { 0x00, 0x00, 0xff, 0x00 }, // RED
79 { 0xff, 0x00, 0xff, 0x00 }, // FUCHSIA
80 { 0x00, 0xff, 0xff, 0x00 }, // YELLOW
81 { 0xff, 0xff, 0xff, 0x00 } // WHITE
82 };
83
84 EFI_NARROW_GLYPH mCursorGlyph = {
85 0x0000,
86 0x00,
87 { 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF }
88 };
89
90 CHAR16 SpaceStr[] = { NARROW_CHAR, ' ', 0 };
91
92 EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding = {
93 GraphicsConsoleControllerDriverSupported,
94 GraphicsConsoleControllerDriverStart,
95 GraphicsConsoleControllerDriverStop,
96 0xa,
97 NULL,
98 NULL
99 };
100
101 /**
102 Test to see if Graphics Console could be supported on the Controller.
103
104 Graphics Console could be supported if Graphics Output Protocol or UGA Draw
105 Protocol exists on the Controller. (UGA Draw Protocol could be skipped
106 if PcdUgaConsumeSupport is set to FALSE.)
107
108 @param This Protocol instance pointer.
109 @param Controller Handle of device to test.
110 @param RemainingDevicePath Optional parameter use to pick a specific child
111 device to start.
112
113 @retval EFI_SUCCESS This driver supports this device.
114 @retval other This driver does not support this device.
115
116 **/
117 EFI_STATUS
118 EFIAPI
119 GraphicsConsoleControllerDriverSupported (
120 IN EFI_DRIVER_BINDING_PROTOCOL *This,
121 IN EFI_HANDLE Controller,
122 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
123 )
124 {
125 EFI_STATUS Status;
126 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
127 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
128 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
129
130 GraphicsOutput = NULL;
131 UgaDraw = NULL;
132 //
133 // Open the IO Abstraction(s) needed to perform the supported test
134 //
135 Status = gBS->OpenProtocol (
136 Controller,
137 &gEfiGraphicsOutputProtocolGuid,
138 (VOID **)&GraphicsOutput,
139 This->DriverBindingHandle,
140 Controller,
141 EFI_OPEN_PROTOCOL_BY_DRIVER
142 );
143
144 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
145 //
146 // Open Graphics Output Protocol failed, try to open UGA Draw Protocol
147 //
148 Status = gBS->OpenProtocol (
149 Controller,
150 &gEfiUgaDrawProtocolGuid,
151 (VOID **)&UgaDraw,
152 This->DriverBindingHandle,
153 Controller,
154 EFI_OPEN_PROTOCOL_BY_DRIVER
155 );
156 }
157
158 if (EFI_ERROR (Status)) {
159 return Status;
160 }
161
162 //
163 // We need to ensure that we do not layer on top of a virtual handle.
164 // We need to ensure that the handles produced by the conspliter do not
165 // get used.
166 //
167 Status = gBS->OpenProtocol (
168 Controller,
169 &gEfiDevicePathProtocolGuid,
170 (VOID **)&DevicePath,
171 This->DriverBindingHandle,
172 Controller,
173 EFI_OPEN_PROTOCOL_BY_DRIVER
174 );
175 if (!EFI_ERROR (Status)) {
176 gBS->CloseProtocol (
177 Controller,
178 &gEfiDevicePathProtocolGuid,
179 This->DriverBindingHandle,
180 Controller
181 );
182 } else {
183 goto Error;
184 }
185
186 //
187 // Does Hii Exist? If not, we aren't ready to run
188 //
189 Status = EfiLocateHiiProtocol ();
190
191 //
192 // Close the I/O Abstraction(s) used to perform the supported test
193 //
194 Error:
195 if (GraphicsOutput != NULL) {
196 gBS->CloseProtocol (
197 Controller,
198 &gEfiGraphicsOutputProtocolGuid,
199 This->DriverBindingHandle,
200 Controller
201 );
202 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
203 gBS->CloseProtocol (
204 Controller,
205 &gEfiUgaDrawProtocolGuid,
206 This->DriverBindingHandle,
207 Controller
208 );
209 }
210
211 return Status;
212 }
213
214 /**
215 Initialize all the text modes which the graphics console supports.
216
217 It returns information for available text modes that the graphics can support.
218
219 @param[in] HorizontalResolution The size of video screen in pixels in the X dimension.
220 @param[in] VerticalResolution The size of video screen in pixels in the Y dimension.
221 @param[in] GopModeNumber The graphics mode number which graphics console is based on.
222 @param[out] TextModeCount The total number of text modes that graphics console supports.
223 @param[out] TextModeData The buffer to the text modes column and row information.
224 Caller is responsible to free it when it's non-NULL.
225
226 @retval EFI_SUCCESS The supporting mode information is returned.
227 @retval EFI_INVALID_PARAMETER The parameters are invalid.
228
229 **/
230 EFI_STATUS
231 InitializeGraphicsConsoleTextMode (
232 IN UINT32 HorizontalResolution,
233 IN UINT32 VerticalResolution,
234 IN UINT32 GopModeNumber,
235 OUT UINTN *TextModeCount,
236 OUT GRAPHICS_CONSOLE_MODE_DATA **TextModeData
237 )
238 {
239 UINTN Index;
240 UINTN Count;
241 GRAPHICS_CONSOLE_MODE_DATA *ModeBuffer;
242 GRAPHICS_CONSOLE_MODE_DATA *NewModeBuffer;
243 UINTN ValidCount;
244 UINTN ValidIndex;
245 UINTN MaxColumns;
246 UINTN MaxRows;
247
248 if ((TextModeCount == NULL) || (TextModeData == NULL)) {
249 return EFI_INVALID_PARAMETER;
250 }
251
252 Count = sizeof (mGraphicsConsoleModeData) / sizeof (GRAPHICS_CONSOLE_MODE_DATA);
253
254 //
255 // Compute the maximum number of text Rows and Columns that this current graphics mode can support.
256 // To make graphics console work well, MaxColumns and MaxRows should not be zero.
257 //
258 MaxColumns = HorizontalResolution / EFI_GLYPH_WIDTH;
259 MaxRows = VerticalResolution / EFI_GLYPH_HEIGHT;
260
261 //
262 // According to UEFI spec, all output devices support at least 80x25 text mode.
263 //
264 ASSERT ((MaxColumns >= 80) && (MaxRows >= 25));
265
266 //
267 // Add full screen mode to the last entry.
268 //
269 mGraphicsConsoleModeData[Count - 1].Columns = MaxColumns;
270 mGraphicsConsoleModeData[Count - 1].Rows = MaxRows;
271
272 //
273 // Get defined mode buffer pointer.
274 //
275 ModeBuffer = mGraphicsConsoleModeData;
276
277 //
278 // Here we make sure that the final mode exposed does not include the duplicated modes,
279 // and does not include the invalid modes which exceed the max column and row.
280 // Reserve 2 modes for 80x25, 80x50 of graphics console.
281 //
282 NewModeBuffer = AllocateZeroPool (sizeof (GRAPHICS_CONSOLE_MODE_DATA) * (Count + 2));
283 ASSERT (NewModeBuffer != NULL);
284
285 //
286 // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.
287 //
288 ValidCount = 0;
289
290 NewModeBuffer[ValidCount].Columns = 80;
291 NewModeBuffer[ValidCount].Rows = 25;
292 NewModeBuffer[ValidCount].GopWidth = HorizontalResolution;
293 NewModeBuffer[ValidCount].GopHeight = VerticalResolution;
294 NewModeBuffer[ValidCount].GopModeNumber = GopModeNumber;
295 NewModeBuffer[ValidCount].DeltaX = (HorizontalResolution - (NewModeBuffer[ValidCount].Columns * EFI_GLYPH_WIDTH)) >> 1;
296 NewModeBuffer[ValidCount].DeltaY = (VerticalResolution - (NewModeBuffer[ValidCount].Rows * EFI_GLYPH_HEIGHT)) >> 1;
297 ValidCount++;
298
299 if ((MaxColumns >= 80) && (MaxRows >= 50)) {
300 NewModeBuffer[ValidCount].Columns = 80;
301 NewModeBuffer[ValidCount].Rows = 50;
302 NewModeBuffer[ValidCount].DeltaX = (HorizontalResolution - (80 * EFI_GLYPH_WIDTH)) >> 1;
303 NewModeBuffer[ValidCount].DeltaY = (VerticalResolution - (50 * EFI_GLYPH_HEIGHT)) >> 1;
304 }
305
306 NewModeBuffer[ValidCount].GopWidth = HorizontalResolution;
307 NewModeBuffer[ValidCount].GopHeight = VerticalResolution;
308 NewModeBuffer[ValidCount].GopModeNumber = GopModeNumber;
309 ValidCount++;
310
311 //
312 // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer.
313 //
314 for (Index = 0; Index < Count; Index++) {
315 if ((ModeBuffer[Index].Columns == 0) || (ModeBuffer[Index].Rows == 0) ||
316 (ModeBuffer[Index].Columns > MaxColumns) || (ModeBuffer[Index].Rows > MaxRows))
317 {
318 //
319 // Skip the pre-defined mode which is invalid or exceeds the max column and row.
320 //
321 continue;
322 }
323
324 for (ValidIndex = 0; ValidIndex < ValidCount; ValidIndex++) {
325 if ((ModeBuffer[Index].Columns == NewModeBuffer[ValidIndex].Columns) &&
326 (ModeBuffer[Index].Rows == NewModeBuffer[ValidIndex].Rows))
327 {
328 //
329 // Skip the duplicated mode.
330 //
331 break;
332 }
333 }
334
335 if (ValidIndex == ValidCount) {
336 NewModeBuffer[ValidCount].Columns = ModeBuffer[Index].Columns;
337 NewModeBuffer[ValidCount].Rows = ModeBuffer[Index].Rows;
338 NewModeBuffer[ValidCount].GopWidth = HorizontalResolution;
339 NewModeBuffer[ValidCount].GopHeight = VerticalResolution;
340 NewModeBuffer[ValidCount].GopModeNumber = GopModeNumber;
341 NewModeBuffer[ValidCount].DeltaX = (HorizontalResolution - (NewModeBuffer[ValidCount].Columns * EFI_GLYPH_WIDTH)) >> 1;
342 NewModeBuffer[ValidCount].DeltaY = (VerticalResolution - (NewModeBuffer[ValidCount].Rows * EFI_GLYPH_HEIGHT)) >> 1;
343 ValidCount++;
344 }
345 }
346
347 DEBUG_CODE_BEGIN ();
348 for (Index = 0; Index < ValidCount; Index++) {
349 DEBUG ((
350 DEBUG_INFO,
351 "Graphics - Mode %d, Column = %d, Row = %d\n",
352 Index,
353 NewModeBuffer[Index].Columns,
354 NewModeBuffer[Index].Rows
355 ));
356 }
357
358 DEBUG_CODE_END ();
359
360 //
361 // Return valid mode count and mode information buffer.
362 //
363 *TextModeCount = ValidCount;
364 *TextModeData = NewModeBuffer;
365 return EFI_SUCCESS;
366 }
367
368 /**
369 Start this driver on Controller by opening Graphics Output protocol or
370 UGA Draw protocol, and installing Simple Text Out protocol on Controller.
371 (UGA Draw protocol could be skipped if PcdUgaConsumeSupport is set to FALSE.)
372
373 @param This Protocol instance pointer.
374 @param Controller Handle of device to bind driver to
375 @param RemainingDevicePath Optional parameter use to pick a specific child
376 device to start.
377
378 @retval EFI_SUCCESS This driver is added to Controller.
379 @retval other This driver does not support this device.
380
381 **/
382 EFI_STATUS
383 EFIAPI
384 GraphicsConsoleControllerDriverStart (
385 IN EFI_DRIVER_BINDING_PROTOCOL *This,
386 IN EFI_HANDLE Controller,
387 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
388 )
389 {
390 EFI_STATUS Status;
391 GRAPHICS_CONSOLE_DEV *Private;
392 UINT32 HorizontalResolution;
393 UINT32 VerticalResolution;
394 UINT32 ColorDepth;
395 UINT32 RefreshRate;
396 UINT32 ModeIndex;
397 UINTN MaxMode;
398 UINT32 ModeNumber;
399 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode;
400 UINTN SizeOfInfo;
401 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
402 INT32 PreferMode;
403 INT32 Index;
404 UINTN Column;
405 UINTN Row;
406 UINTN DefaultColumn;
407 UINTN DefaultRow;
408
409 ModeNumber = 0;
410
411 //
412 // Initialize the Graphics Console device instance
413 //
414 Private = AllocateCopyPool (
415 sizeof (GRAPHICS_CONSOLE_DEV),
416 &mGraphicsConsoleDevTemplate
417 );
418 if (Private == NULL) {
419 return EFI_OUT_OF_RESOURCES;
420 }
421
422 Private->SimpleTextOutput.Mode = &(Private->SimpleTextOutputMode);
423
424 Status = gBS->OpenProtocol (
425 Controller,
426 &gEfiGraphicsOutputProtocolGuid,
427 (VOID **)&Private->GraphicsOutput,
428 This->DriverBindingHandle,
429 Controller,
430 EFI_OPEN_PROTOCOL_BY_DRIVER
431 );
432
433 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
434 Status = gBS->OpenProtocol (
435 Controller,
436 &gEfiUgaDrawProtocolGuid,
437 (VOID **)&Private->UgaDraw,
438 This->DriverBindingHandle,
439 Controller,
440 EFI_OPEN_PROTOCOL_BY_DRIVER
441 );
442 }
443
444 if (EFI_ERROR (Status)) {
445 goto Error;
446 }
447
448 HorizontalResolution = PcdGet32 (PcdVideoHorizontalResolution);
449 VerticalResolution = PcdGet32 (PcdVideoVerticalResolution);
450
451 if (Private->GraphicsOutput != NULL) {
452 //
453 // The console is build on top of Graphics Output Protocol, find the mode number
454 // for the user-defined mode; if there are multiple video devices,
455 // graphic console driver will set all the video devices to the same mode.
456 //
457 if ((HorizontalResolution == 0x0) || (VerticalResolution == 0x0)) {
458 //
459 // Find the highest resolution which GOP supports.
460 //
461 MaxMode = Private->GraphicsOutput->Mode->MaxMode;
462
463 for (ModeIndex = 0; ModeIndex < MaxMode; ModeIndex++) {
464 Status = Private->GraphicsOutput->QueryMode (
465 Private->GraphicsOutput,
466 ModeIndex,
467 &SizeOfInfo,
468 &Info
469 );
470 if (!EFI_ERROR (Status)) {
471 if ((Info->HorizontalResolution > HorizontalResolution) ||
472 ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution > VerticalResolution)))
473 {
474 HorizontalResolution = Info->HorizontalResolution;
475 VerticalResolution = Info->VerticalResolution;
476 ModeNumber = ModeIndex;
477 }
478
479 FreePool (Info);
480 }
481 }
482
483 if ((HorizontalResolution == 0x0) || (VerticalResolution == 0x0)) {
484 Status = EFI_UNSUPPORTED;
485 goto Error;
486 }
487 } else {
488 //
489 // Use user-defined resolution
490 //
491 Status = CheckModeSupported (
492 Private->GraphicsOutput,
493 HorizontalResolution,
494 VerticalResolution,
495 &ModeNumber
496 );
497 if (EFI_ERROR (Status)) {
498 //
499 // if not supporting current mode, try 800x600 which is required by UEFI/EFI spec
500 //
501 HorizontalResolution = 800;
502 VerticalResolution = 600;
503 Status = CheckModeSupported (
504 Private->GraphicsOutput,
505 HorizontalResolution,
506 VerticalResolution,
507 &ModeNumber
508 );
509 Mode = Private->GraphicsOutput->Mode;
510 if (EFI_ERROR (Status) && (Mode->MaxMode != 0)) {
511 //
512 // If set default mode failed or device doesn't support default mode, then get the current mode information
513 //
514 HorizontalResolution = Mode->Info->HorizontalResolution;
515 VerticalResolution = Mode->Info->VerticalResolution;
516 ModeNumber = Mode->Mode;
517 }
518 }
519 }
520
521 if (EFI_ERROR (Status) || (ModeNumber != Private->GraphicsOutput->Mode->Mode)) {
522 //
523 // Current graphics mode is not set or is not set to the mode which we have found,
524 // set the new graphic mode.
525 //
526 Status = Private->GraphicsOutput->SetMode (Private->GraphicsOutput, ModeNumber);
527 if (EFI_ERROR (Status)) {
528 //
529 // The mode set operation failed
530 //
531 goto Error;
532 }
533 }
534 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
535 //
536 // At first try to set user-defined resolution
537 //
538 ColorDepth = 32;
539 RefreshRate = 60;
540 Status = Private->UgaDraw->SetMode (
541 Private->UgaDraw,
542 HorizontalResolution,
543 VerticalResolution,
544 ColorDepth,
545 RefreshRate
546 );
547 if (EFI_ERROR (Status)) {
548 //
549 // Try to set 800*600 which is required by UEFI/EFI spec
550 //
551 Status = Private->UgaDraw->SetMode (
552 Private->UgaDraw,
553 800,
554 600,
555 ColorDepth,
556 RefreshRate
557 );
558 if (EFI_ERROR (Status)) {
559 Status = Private->UgaDraw->GetMode (
560 Private->UgaDraw,
561 &HorizontalResolution,
562 &VerticalResolution,
563 &ColorDepth,
564 &RefreshRate
565 );
566 if (EFI_ERROR (Status)) {
567 goto Error;
568 }
569 }
570 }
571 }
572
573 DEBUG ((DEBUG_INFO, "GraphicsConsole video resolution %d x %d\n", HorizontalResolution, VerticalResolution));
574
575 //
576 // Initialize the mode which GraphicsConsole supports.
577 //
578 Status = InitializeGraphicsConsoleTextMode (
579 HorizontalResolution,
580 VerticalResolution,
581 ModeNumber,
582 &MaxMode,
583 &Private->ModeData
584 );
585
586 if (EFI_ERROR (Status)) {
587 goto Error;
588 }
589
590 //
591 // Update the maximum number of modes
592 //
593 Private->SimpleTextOutputMode.MaxMode = (INT32)MaxMode;
594
595 //
596 // Initialize the Mode of graphics console devices
597 //
598 PreferMode = -1;
599 DefaultColumn = PcdGet32 (PcdConOutColumn);
600 DefaultRow = PcdGet32 (PcdConOutRow);
601 Column = 0;
602 Row = 0;
603 for (Index = 0; Index < (INT32)MaxMode; Index++) {
604 if ((DefaultColumn != 0) && (DefaultRow != 0)) {
605 if ((Private->ModeData[Index].Columns == DefaultColumn) &&
606 (Private->ModeData[Index].Rows == DefaultRow))
607 {
608 PreferMode = Index;
609 break;
610 }
611 } else {
612 if ((Private->ModeData[Index].Columns > Column) &&
613 (Private->ModeData[Index].Rows > Row))
614 {
615 Column = Private->ModeData[Index].Columns;
616 Row = Private->ModeData[Index].Rows;
617 PreferMode = Index;
618 }
619 }
620 }
621
622 Private->SimpleTextOutput.Mode->Mode = (INT32)PreferMode;
623 DEBUG ((DEBUG_INFO, "Graphics Console Started, Mode: %d\n", PreferMode));
624
625 //
626 // Install protocol interfaces for the Graphics Console device.
627 //
628 Status = gBS->InstallMultipleProtocolInterfaces (
629 &Controller,
630 &gEfiSimpleTextOutProtocolGuid,
631 &Private->SimpleTextOutput,
632 NULL
633 );
634
635 Error:
636 if (EFI_ERROR (Status)) {
637 //
638 // Close the GOP and UGA Draw Protocol
639 //
640 if (Private->GraphicsOutput != NULL) {
641 gBS->CloseProtocol (
642 Controller,
643 &gEfiGraphicsOutputProtocolGuid,
644 This->DriverBindingHandle,
645 Controller
646 );
647 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
648 gBS->CloseProtocol (
649 Controller,
650 &gEfiUgaDrawProtocolGuid,
651 This->DriverBindingHandle,
652 Controller
653 );
654 }
655
656 if (Private->LineBuffer != NULL) {
657 FreePool (Private->LineBuffer);
658 }
659
660 if (Private->ModeData != NULL) {
661 FreePool (Private->ModeData);
662 }
663
664 //
665 // Free private data
666 //
667 FreePool (Private);
668 }
669
670 return Status;
671 }
672
673 /**
674 Stop this driver on Controller by removing Simple Text Out protocol
675 and closing the Graphics Output Protocol or UGA Draw protocol on Controller.
676 (UGA Draw protocol could be skipped if PcdUgaConsumeSupport is set to FALSE.)
677
678
679 @param This Protocol instance pointer.
680 @param Controller Handle of device to stop driver on
681 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
682 children is zero stop the entire bus driver.
683 @param ChildHandleBuffer List of Child Handles to Stop.
684
685 @retval EFI_SUCCESS This driver is removed Controller.
686 @retval EFI_NOT_STARTED Simple Text Out protocol could not be found the
687 Controller.
688 @retval other This driver was not removed from this device.
689
690 **/
691 EFI_STATUS
692 EFIAPI
693 GraphicsConsoleControllerDriverStop (
694 IN EFI_DRIVER_BINDING_PROTOCOL *This,
695 IN EFI_HANDLE Controller,
696 IN UINTN NumberOfChildren,
697 IN EFI_HANDLE *ChildHandleBuffer
698 )
699 {
700 EFI_STATUS Status;
701 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;
702 GRAPHICS_CONSOLE_DEV *Private;
703
704 Status = gBS->OpenProtocol (
705 Controller,
706 &gEfiSimpleTextOutProtocolGuid,
707 (VOID **)&SimpleTextOutput,
708 This->DriverBindingHandle,
709 Controller,
710 EFI_OPEN_PROTOCOL_GET_PROTOCOL
711 );
712 if (EFI_ERROR (Status)) {
713 return EFI_NOT_STARTED;
714 }
715
716 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);
717
718 Status = gBS->UninstallProtocolInterface (
719 Controller,
720 &gEfiSimpleTextOutProtocolGuid,
721 &Private->SimpleTextOutput
722 );
723
724 if (!EFI_ERROR (Status)) {
725 //
726 // Close the GOP or UGA IO Protocol
727 //
728 if (Private->GraphicsOutput != NULL) {
729 gBS->CloseProtocol (
730 Controller,
731 &gEfiGraphicsOutputProtocolGuid,
732 This->DriverBindingHandle,
733 Controller
734 );
735 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
736 gBS->CloseProtocol (
737 Controller,
738 &gEfiUgaDrawProtocolGuid,
739 This->DriverBindingHandle,
740 Controller
741 );
742 }
743
744 if (Private->LineBuffer != NULL) {
745 FreePool (Private->LineBuffer);
746 }
747
748 if (Private->ModeData != NULL) {
749 FreePool (Private->ModeData);
750 }
751
752 //
753 // Free our instance data
754 //
755 FreePool (Private);
756 }
757
758 return Status;
759 }
760
761 /**
762 Check if the current specific mode supported the user defined resolution
763 for the Graphics Console device based on Graphics Output Protocol.
764
765 If yes, set the graphic device's current mode to this specific mode.
766
767 @param GraphicsOutput Graphics Output Protocol instance pointer.
768 @param HorizontalResolution User defined horizontal resolution
769 @param VerticalResolution User defined vertical resolution.
770 @param CurrentModeNumber Current specific mode to be check.
771
772 @retval EFI_SUCCESS The mode is supported.
773 @retval EFI_UNSUPPORTED The specific mode is out of range of graphics
774 device supported.
775 @retval other The specific mode does not support user defined
776 resolution or failed to set the current mode to the
777 specific mode on graphics device.
778
779 **/
780 EFI_STATUS
781 CheckModeSupported (
782 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
783 IN UINT32 HorizontalResolution,
784 IN UINT32 VerticalResolution,
785 OUT UINT32 *CurrentModeNumber
786 )
787 {
788 UINT32 ModeNumber;
789 EFI_STATUS Status;
790 UINTN SizeOfInfo;
791 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
792 UINT32 MaxMode;
793
794 Status = EFI_SUCCESS;
795 MaxMode = GraphicsOutput->Mode->MaxMode;
796
797 for (ModeNumber = 0; ModeNumber < MaxMode; ModeNumber++) {
798 Status = GraphicsOutput->QueryMode (
799 GraphicsOutput,
800 ModeNumber,
801 &SizeOfInfo,
802 &Info
803 );
804 if (!EFI_ERROR (Status)) {
805 if ((Info->HorizontalResolution == HorizontalResolution) &&
806 (Info->VerticalResolution == VerticalResolution))
807 {
808 if ((GraphicsOutput->Mode->Info->HorizontalResolution == HorizontalResolution) &&
809 (GraphicsOutput->Mode->Info->VerticalResolution == VerticalResolution))
810 {
811 //
812 // If video device has been set to this mode, we do not need to SetMode again
813 //
814 FreePool (Info);
815 break;
816 } else {
817 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
818 if (!EFI_ERROR (Status)) {
819 FreePool (Info);
820 break;
821 }
822 }
823 }
824
825 FreePool (Info);
826 }
827 }
828
829 if (ModeNumber == GraphicsOutput->Mode->MaxMode) {
830 Status = EFI_UNSUPPORTED;
831 }
832
833 *CurrentModeNumber = ModeNumber;
834 return Status;
835 }
836
837 /**
838 Locate HII Database protocol and HII Font protocol.
839
840 @retval EFI_SUCCESS HII Database protocol and HII Font protocol
841 are located successfully.
842 @return other Failed to locate HII Database protocol or
843 HII Font protocol.
844
845 **/
846 EFI_STATUS
847 EfiLocateHiiProtocol (
848 VOID
849 )
850 {
851 EFI_STATUS Status;
852
853 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&mHiiDatabase);
854 if (EFI_ERROR (Status)) {
855 return Status;
856 }
857
858 Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **)&mHiiFont);
859 return Status;
860 }
861
862 //
863 // Body of the STO functions
864 //
865
866 /**
867 Reset the text output device hardware and optionally run diagnostics.
868
869 Implements SIMPLE_TEXT_OUTPUT.Reset().
870 If ExtendedVerification is TRUE, then perform dependent Graphics Console
871 device reset, and set display mode to mode 0.
872 If ExtendedVerification is FALSE, only set display mode to mode 0.
873
874 @param This Protocol instance pointer.
875 @param ExtendedVerification Indicates that the driver may perform a more
876 exhaustive verification operation of the device
877 during reset.
878
879 @retval EFI_SUCCESS The text output device was reset.
880 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
881 could not be reset.
882
883 **/
884 EFI_STATUS
885 EFIAPI
886 GraphicsConsoleConOutReset (
887 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
888 IN BOOLEAN ExtendedVerification
889 )
890 {
891 EFI_STATUS Status;
892
893 Status = This->SetMode (This, 0);
894 if (EFI_ERROR (Status)) {
895 return Status;
896 }
897
898 Status = This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));
899 return Status;
900 }
901
902 /**
903 Write a Unicode string to the output device.
904
905 Implements SIMPLE_TEXT_OUTPUT.OutputString().
906 The Unicode string will be converted to Glyphs and will be
907 sent to the Graphics Console.
908
909 @param This Protocol instance pointer.
910 @param WString The NULL-terminated Unicode string to be displayed
911 on the output device(s). All output devices must
912 also support the Unicode drawing defined in this file.
913
914 @retval EFI_SUCCESS The string was output to the device.
915 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
916 the text.
917 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
918 defined text mode.
919 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
920 characters in the Unicode string could not be
921 rendered and were skipped.
922
923 **/
924 EFI_STATUS
925 EFIAPI
926 GraphicsConsoleConOutOutputString (
927 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
928 IN CHAR16 *WString
929 )
930 {
931 GRAPHICS_CONSOLE_DEV *Private;
932 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
933 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
934 INTN Mode;
935 UINTN MaxColumn;
936 UINTN MaxRow;
937 UINTN Width;
938 UINTN Height;
939 UINTN Delta;
940 EFI_STATUS Status;
941 BOOLEAN Warning;
942 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
943 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
944 UINTN DeltaX;
945 UINTN DeltaY;
946 UINTN Count;
947 UINTN Index;
948 INT32 OriginAttribute;
949 EFI_TPL OldTpl;
950
951 if (This->Mode->Mode == -1) {
952 //
953 // If current mode is not valid, return error.
954 //
955 return EFI_UNSUPPORTED;
956 }
957
958 Status = EFI_SUCCESS;
959
960 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
961 //
962 // Current mode
963 //
964 Mode = This->Mode->Mode;
965 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
966 GraphicsOutput = Private->GraphicsOutput;
967 UgaDraw = Private->UgaDraw;
968
969 MaxColumn = Private->ModeData[Mode].Columns;
970 MaxRow = Private->ModeData[Mode].Rows;
971 DeltaX = (UINTN)Private->ModeData[Mode].DeltaX;
972 DeltaY = (UINTN)Private->ModeData[Mode].DeltaY;
973 Width = MaxColumn * EFI_GLYPH_WIDTH;
974 Height = (MaxRow - 1) * EFI_GLYPH_HEIGHT;
975 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
976
977 //
978 // The Attributes won't change when during the time OutputString is called
979 //
980 GetTextColors (This, &Foreground, &Background);
981
982 FlushCursor (This);
983
984 Warning = FALSE;
985
986 //
987 // Backup attribute
988 //
989 OriginAttribute = This->Mode->Attribute;
990
991 while (*WString != L'\0') {
992 if (*WString == CHAR_BACKSPACE) {
993 //
994 // If the cursor is at the left edge of the display, then move the cursor
995 // one row up.
996 //
997 if ((This->Mode->CursorColumn == 0) && (This->Mode->CursorRow > 0)) {
998 This->Mode->CursorRow--;
999 This->Mode->CursorColumn = (INT32)(MaxColumn - 1);
1000 This->OutputString (This, SpaceStr);
1001 FlushCursor (This);
1002 This->Mode->CursorRow--;
1003 This->Mode->CursorColumn = (INT32)(MaxColumn - 1);
1004 } else if (This->Mode->CursorColumn > 0) {
1005 //
1006 // If the cursor is not at the left edge of the display, then move the cursor
1007 // left one column.
1008 //
1009 This->Mode->CursorColumn--;
1010 This->OutputString (This, SpaceStr);
1011 FlushCursor (This);
1012 This->Mode->CursorColumn--;
1013 }
1014
1015 WString++;
1016 } else if (*WString == CHAR_LINEFEED) {
1017 //
1018 // If the cursor is at the bottom of the display, then scroll the display one
1019 // row, and do not update the cursor position. Otherwise, move the cursor
1020 // down one row.
1021 //
1022 if (This->Mode->CursorRow == (INT32)(MaxRow - 1)) {
1023 if (GraphicsOutput != NULL) {
1024 //
1025 // Scroll Screen Up One Row
1026 //
1027 GraphicsOutput->Blt (
1028 GraphicsOutput,
1029 NULL,
1030 EfiBltVideoToVideo,
1031 DeltaX,
1032 DeltaY + EFI_GLYPH_HEIGHT,
1033 DeltaX,
1034 DeltaY,
1035 Width,
1036 Height,
1037 Delta
1038 );
1039
1040 //
1041 // Print Blank Line at last line
1042 //
1043 GraphicsOutput->Blt (
1044 GraphicsOutput,
1045 &Background,
1046 EfiBltVideoFill,
1047 0,
1048 0,
1049 DeltaX,
1050 DeltaY + Height,
1051 Width,
1052 EFI_GLYPH_HEIGHT,
1053 Delta
1054 );
1055 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1056 //
1057 // Scroll Screen Up One Row
1058 //
1059 UgaDraw->Blt (
1060 UgaDraw,
1061 NULL,
1062 EfiUgaVideoToVideo,
1063 DeltaX,
1064 DeltaY + EFI_GLYPH_HEIGHT,
1065 DeltaX,
1066 DeltaY,
1067 Width,
1068 Height,
1069 Delta
1070 );
1071
1072 //
1073 // Print Blank Line at last line
1074 //
1075 UgaDraw->Blt (
1076 UgaDraw,
1077 (EFI_UGA_PIXEL *)(UINTN)&Background,
1078 EfiUgaVideoFill,
1079 0,
1080 0,
1081 DeltaX,
1082 DeltaY + Height,
1083 Width,
1084 EFI_GLYPH_HEIGHT,
1085 Delta
1086 );
1087 }
1088 } else {
1089 This->Mode->CursorRow++;
1090 }
1091
1092 WString++;
1093 } else if (*WString == CHAR_CARRIAGE_RETURN) {
1094 //
1095 // Move the cursor to the beginning of the current row.
1096 //
1097 This->Mode->CursorColumn = 0;
1098 WString++;
1099 } else if (*WString == WIDE_CHAR) {
1100 This->Mode->Attribute |= EFI_WIDE_ATTRIBUTE;
1101 WString++;
1102 } else if (*WString == NARROW_CHAR) {
1103 This->Mode->Attribute &= (~(UINT32)EFI_WIDE_ATTRIBUTE);
1104 WString++;
1105 } else {
1106 //
1107 // Print the character at the current cursor position and move the cursor
1108 // right one column. If this moves the cursor past the right edge of the
1109 // display, then the line should wrap to the beginning of the next line. This
1110 // is equivalent to inserting a CR and an LF. Note that if the cursor is at the
1111 // bottom of the display, and the line wraps, then the display will be scrolled
1112 // one line.
1113 // If wide char is going to be displayed, need to display one character at a time
1114 // Or, need to know the display length of a certain string.
1115 //
1116 // Index is used to determine how many character width units (wide = 2, narrow = 1)
1117 // Count is used to determine how many characters are used regardless of their attributes
1118 //
1119 for (Count = 0, Index = 0; (This->Mode->CursorColumn + Index) < MaxColumn; Count++, Index++) {
1120 if ((WString[Count] == CHAR_NULL) ||
1121 (WString[Count] == CHAR_BACKSPACE) ||
1122 (WString[Count] == CHAR_LINEFEED) ||
1123 (WString[Count] == CHAR_CARRIAGE_RETURN) ||
1124 (WString[Count] == WIDE_CHAR) ||
1125 (WString[Count] == NARROW_CHAR))
1126 {
1127 break;
1128 }
1129
1130 //
1131 // Is the wide attribute on?
1132 //
1133 if ((This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) != 0) {
1134 //
1135 // If wide, add one more width unit than normal since we are going to increment at the end of the for loop
1136 //
1137 Index++;
1138 //
1139 // This is the end-case where if we are at column 79 and about to print a wide character
1140 // We should prevent this from happening because we will wrap inappropriately. We should
1141 // not print this character until the next line.
1142 //
1143 if ((This->Mode->CursorColumn + Index + 1) > MaxColumn) {
1144 Index++;
1145 break;
1146 }
1147 }
1148 }
1149
1150 Status = DrawUnicodeWeightAtCursorN (This, WString, Count);
1151 if (EFI_ERROR (Status)) {
1152 Warning = TRUE;
1153 }
1154
1155 //
1156 // At the end of line, output carriage return and line feed
1157 //
1158 WString += Count;
1159 This->Mode->CursorColumn += (INT32)Index;
1160 if (This->Mode->CursorColumn > (INT32)MaxColumn) {
1161 This->Mode->CursorColumn -= 2;
1162 This->OutputString (This, SpaceStr);
1163 }
1164
1165 if (This->Mode->CursorColumn >= (INT32)MaxColumn) {
1166 FlushCursor (This);
1167 This->OutputString (This, mCrLfString);
1168 FlushCursor (This);
1169 }
1170 }
1171 }
1172
1173 This->Mode->Attribute = OriginAttribute;
1174
1175 FlushCursor (This);
1176
1177 if (Warning) {
1178 Status = EFI_WARN_UNKNOWN_GLYPH;
1179 }
1180
1181 gBS->RestoreTPL (OldTpl);
1182 return Status;
1183 }
1184
1185 /**
1186 Verifies that all characters in a Unicode string can be output to the
1187 target device.
1188
1189 Implements SIMPLE_TEXT_OUTPUT.TestString().
1190 If one of the characters in the *Wstring is neither valid valid Unicode
1191 drawing characters, not ASCII code, then this function will return
1192 EFI_UNSUPPORTED
1193
1194 @param This Protocol instance pointer.
1195 @param WString The NULL-terminated Unicode string to be examined for the output
1196 device(s).
1197
1198 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
1199 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
1200 rendered by one or more of the output devices mapped
1201 by the EFI handle.
1202
1203 **/
1204 EFI_STATUS
1205 EFIAPI
1206 GraphicsConsoleConOutTestString (
1207 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1208 IN CHAR16 *WString
1209 )
1210 {
1211 EFI_STATUS Status;
1212 UINT16 Count;
1213
1214 EFI_IMAGE_OUTPUT *Blt;
1215
1216 Blt = NULL;
1217 Count = 0;
1218
1219 while (WString[Count] != 0) {
1220 Status = mHiiFont->GetGlyph (
1221 mHiiFont,
1222 WString[Count],
1223 NULL,
1224 &Blt,
1225 NULL
1226 );
1227 if (Blt != NULL) {
1228 FreePool (Blt);
1229 Blt = NULL;
1230 }
1231
1232 Count++;
1233
1234 if (EFI_ERROR (Status)) {
1235 return EFI_UNSUPPORTED;
1236 }
1237 }
1238
1239 return EFI_SUCCESS;
1240 }
1241
1242 /**
1243 Returns information for an available text mode that the output device(s)
1244 supports
1245
1246 Implements SIMPLE_TEXT_OUTPUT.QueryMode().
1247 It returnes information for an available text mode that the Graphics Console supports.
1248 In this driver,we only support text mode 80x25, which is defined as mode 0.
1249
1250 @param This Protocol instance pointer.
1251 @param ModeNumber The mode number to return information on.
1252 @param Columns The returned columns of the requested mode.
1253 @param Rows The returned rows of the requested mode.
1254
1255 @retval EFI_SUCCESS The requested mode information is returned.
1256 @retval EFI_UNSUPPORTED The mode number is not valid.
1257
1258 **/
1259 EFI_STATUS
1260 EFIAPI
1261 GraphicsConsoleConOutQueryMode (
1262 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1263 IN UINTN ModeNumber,
1264 OUT UINTN *Columns,
1265 OUT UINTN *Rows
1266 )
1267 {
1268 GRAPHICS_CONSOLE_DEV *Private;
1269 EFI_STATUS Status;
1270 EFI_TPL OldTpl;
1271
1272 if (ModeNumber >= (UINTN)This->Mode->MaxMode) {
1273 return EFI_UNSUPPORTED;
1274 }
1275
1276 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1277 Status = EFI_SUCCESS;
1278
1279 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1280
1281 *Columns = Private->ModeData[ModeNumber].Columns;
1282 *Rows = Private->ModeData[ModeNumber].Rows;
1283
1284 if ((*Columns <= 0) || (*Rows <= 0)) {
1285 Status = EFI_UNSUPPORTED;
1286 goto Done;
1287 }
1288
1289 Done:
1290 gBS->RestoreTPL (OldTpl);
1291 return Status;
1292 }
1293
1294 /**
1295 Sets the output device(s) to a specified mode.
1296
1297 Implements SIMPLE_TEXT_OUTPUT.SetMode().
1298 Set the Graphics Console to a specified mode. In this driver, we only support mode 0.
1299
1300 @param This Protocol instance pointer.
1301 @param ModeNumber The text mode to set.
1302
1303 @retval EFI_SUCCESS The requested text mode is set.
1304 @retval EFI_DEVICE_ERROR The requested text mode cannot be set because of
1305 Graphics Console device error.
1306 @retval EFI_UNSUPPORTED The text mode number is not valid.
1307
1308 **/
1309 EFI_STATUS
1310 EFIAPI
1311 GraphicsConsoleConOutSetMode (
1312 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1313 IN UINTN ModeNumber
1314 )
1315 {
1316 EFI_STATUS Status;
1317 GRAPHICS_CONSOLE_DEV *Private;
1318 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1319 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewLineBuffer;
1320 UINT32 HorizontalResolution;
1321 UINT32 VerticalResolution;
1322 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1323 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1324 UINT32 ColorDepth;
1325 UINT32 RefreshRate;
1326 EFI_TPL OldTpl;
1327
1328 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1329
1330 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1331 GraphicsOutput = Private->GraphicsOutput;
1332 UgaDraw = Private->UgaDraw;
1333
1334 //
1335 // Make sure the requested mode number is supported
1336 //
1337 if (ModeNumber >= (UINTN)This->Mode->MaxMode) {
1338 Status = EFI_UNSUPPORTED;
1339 goto Done;
1340 }
1341
1342 ModeData = &(Private->ModeData[ModeNumber]);
1343
1344 if ((ModeData->Columns <= 0) && (ModeData->Rows <= 0)) {
1345 Status = EFI_UNSUPPORTED;
1346 goto Done;
1347 }
1348
1349 //
1350 // If the mode has been set at least one other time, then LineBuffer will not be NULL
1351 //
1352 if (Private->LineBuffer != NULL) {
1353 //
1354 // If the new mode is the same as the old mode, then just return EFI_SUCCESS
1355 //
1356 if ((INT32)ModeNumber == This->Mode->Mode) {
1357 //
1358 // Clear the current text window on the current graphics console
1359 //
1360 This->ClearScreen (This);
1361 Status = EFI_SUCCESS;
1362 goto Done;
1363 }
1364
1365 //
1366 // Otherwise, the size of the text console and/or the GOP/UGA mode will be changed,
1367 // so erase the cursor, and free the LineBuffer for the current mode
1368 //
1369 FlushCursor (This);
1370
1371 FreePool (Private->LineBuffer);
1372 }
1373
1374 //
1375 // Attempt to allocate a line buffer for the requested mode number
1376 //
1377 NewLineBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->Columns * EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT);
1378
1379 if (NewLineBuffer == NULL) {
1380 //
1381 // The new line buffer could not be allocated, so return an error.
1382 // No changes to the state of the current console have been made, so the current console is still valid
1383 //
1384 Status = EFI_OUT_OF_RESOURCES;
1385 goto Done;
1386 }
1387
1388 //
1389 // Assign the current line buffer to the newly allocated line buffer
1390 //
1391 Private->LineBuffer = NewLineBuffer;
1392
1393 if (GraphicsOutput != NULL) {
1394 if (ModeData->GopModeNumber != GraphicsOutput->Mode->Mode) {
1395 //
1396 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new graphics mode
1397 //
1398 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeData->GopModeNumber);
1399 if (EFI_ERROR (Status)) {
1400 //
1401 // The mode set operation failed
1402 //
1403 goto Done;
1404 }
1405 } else {
1406 //
1407 // The current graphics mode is correct, so simply clear the entire display
1408 //
1409 Status = GraphicsOutput->Blt (
1410 GraphicsOutput,
1411 &mGraphicsEfiColors[0],
1412 EfiBltVideoFill,
1413 0,
1414 0,
1415 0,
1416 0,
1417 ModeData->GopWidth,
1418 ModeData->GopHeight,
1419 0
1420 );
1421 }
1422 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1423 //
1424 // Get the current UGA Draw mode information
1425 //
1426 Status = UgaDraw->GetMode (
1427 UgaDraw,
1428 &HorizontalResolution,
1429 &VerticalResolution,
1430 &ColorDepth,
1431 &RefreshRate
1432 );
1433 if (EFI_ERROR (Status) || (HorizontalResolution != ModeData->GopWidth) || (VerticalResolution != ModeData->GopHeight)) {
1434 //
1435 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new graphics mode
1436 //
1437 Status = UgaDraw->SetMode (
1438 UgaDraw,
1439 ModeData->GopWidth,
1440 ModeData->GopHeight,
1441 32,
1442 60
1443 );
1444 if (EFI_ERROR (Status)) {
1445 //
1446 // The mode set operation failed
1447 //
1448 goto Done;
1449 }
1450 } else {
1451 //
1452 // The current graphics mode is correct, so simply clear the entire display
1453 //
1454 Status = UgaDraw->Blt (
1455 UgaDraw,
1456 (EFI_UGA_PIXEL *)(UINTN)&mGraphicsEfiColors[0],
1457 EfiUgaVideoFill,
1458 0,
1459 0,
1460 0,
1461 0,
1462 ModeData->GopWidth,
1463 ModeData->GopHeight,
1464 0
1465 );
1466 }
1467 }
1468
1469 //
1470 // The new mode is valid, so commit the mode change
1471 //
1472 This->Mode->Mode = (INT32)ModeNumber;
1473
1474 //
1475 // Move the text cursor to the upper left hand corner of the display and flush it
1476 //
1477 This->Mode->CursorColumn = 0;
1478 This->Mode->CursorRow = 0;
1479
1480 FlushCursor (This);
1481
1482 Status = EFI_SUCCESS;
1483
1484 Done:
1485 gBS->RestoreTPL (OldTpl);
1486 return Status;
1487 }
1488
1489 /**
1490 Sets the background and foreground colors for the OutputString () and
1491 ClearScreen () functions.
1492
1493 Implements SIMPLE_TEXT_OUTPUT.SetAttribute().
1494
1495 @param This Protocol instance pointer.
1496 @param Attribute The attribute to set. Bits 0..3 are the foreground
1497 color, and bits 4..6 are the background color.
1498 All other bits are undefined and must be zero.
1499
1500 @retval EFI_SUCCESS The requested attribute is set.
1501 @retval EFI_DEVICE_ERROR The requested attribute cannot be set due to Graphics Console port error.
1502 @retval EFI_UNSUPPORTED The attribute requested is not defined.
1503
1504 **/
1505 EFI_STATUS
1506 EFIAPI
1507 GraphicsConsoleConOutSetAttribute (
1508 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1509 IN UINTN Attribute
1510 )
1511 {
1512 EFI_TPL OldTpl;
1513
1514 if ((Attribute | 0x7F) != 0x7F) {
1515 return EFI_UNSUPPORTED;
1516 }
1517
1518 if ((INT32)Attribute == This->Mode->Attribute) {
1519 return EFI_SUCCESS;
1520 }
1521
1522 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1523
1524 FlushCursor (This);
1525
1526 This->Mode->Attribute = (INT32)Attribute;
1527
1528 FlushCursor (This);
1529
1530 gBS->RestoreTPL (OldTpl);
1531
1532 return EFI_SUCCESS;
1533 }
1534
1535 /**
1536 Clears the output device(s) display to the currently selected background
1537 color.
1538
1539 Implements SIMPLE_TEXT_OUTPUT.ClearScreen().
1540
1541 @param This Protocol instance pointer.
1542
1543 @retval EFI_SUCCESS The operation completed successfully.
1544 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
1545 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1546
1547 **/
1548 EFI_STATUS
1549 EFIAPI
1550 GraphicsConsoleConOutClearScreen (
1551 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
1552 )
1553 {
1554 EFI_STATUS Status;
1555 GRAPHICS_CONSOLE_DEV *Private;
1556 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1557 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1558 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1559 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
1560 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1561 EFI_TPL OldTpl;
1562
1563 if (This->Mode->Mode == -1) {
1564 //
1565 // If current mode is not valid, return error.
1566 //
1567 return EFI_UNSUPPORTED;
1568 }
1569
1570 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1571
1572 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1573 GraphicsOutput = Private->GraphicsOutput;
1574 UgaDraw = Private->UgaDraw;
1575 ModeData = &(Private->ModeData[This->Mode->Mode]);
1576
1577 GetTextColors (This, &Foreground, &Background);
1578 if (GraphicsOutput != NULL) {
1579 Status = GraphicsOutput->Blt (
1580 GraphicsOutput,
1581 &Background,
1582 EfiBltVideoFill,
1583 0,
1584 0,
1585 0,
1586 0,
1587 ModeData->GopWidth,
1588 ModeData->GopHeight,
1589 0
1590 );
1591 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1592 Status = UgaDraw->Blt (
1593 UgaDraw,
1594 (EFI_UGA_PIXEL *)(UINTN)&Background,
1595 EfiUgaVideoFill,
1596 0,
1597 0,
1598 0,
1599 0,
1600 ModeData->GopWidth,
1601 ModeData->GopHeight,
1602 0
1603 );
1604 } else {
1605 Status = EFI_UNSUPPORTED;
1606 }
1607
1608 This->Mode->CursorColumn = 0;
1609 This->Mode->CursorRow = 0;
1610
1611 FlushCursor (This);
1612
1613 gBS->RestoreTPL (OldTpl);
1614
1615 return Status;
1616 }
1617
1618 /**
1619 Sets the current coordinates of the cursor position.
1620
1621 Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().
1622
1623 @param This Protocol instance pointer.
1624 @param Column The position to set the cursor to. Must be greater than or
1625 equal to zero and less than the number of columns and rows
1626 by QueryMode ().
1627 @param Row The position to set the cursor to. Must be greater than or
1628 equal to zero and less than the number of columns and rows
1629 by QueryMode ().
1630
1631 @retval EFI_SUCCESS The operation completed successfully.
1632 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
1633 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
1634 cursor position is invalid for the current mode.
1635
1636 **/
1637 EFI_STATUS
1638 EFIAPI
1639 GraphicsConsoleConOutSetCursorPosition (
1640 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1641 IN UINTN Column,
1642 IN UINTN Row
1643 )
1644 {
1645 GRAPHICS_CONSOLE_DEV *Private;
1646 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1647 EFI_STATUS Status;
1648 EFI_TPL OldTpl;
1649
1650 if (This->Mode->Mode == -1) {
1651 //
1652 // If current mode is not valid, return error.
1653 //
1654 return EFI_UNSUPPORTED;
1655 }
1656
1657 Status = EFI_SUCCESS;
1658
1659 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1660
1661 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1662 ModeData = &(Private->ModeData[This->Mode->Mode]);
1663
1664 if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) {
1665 Status = EFI_UNSUPPORTED;
1666 goto Done;
1667 }
1668
1669 if ((This->Mode->CursorColumn == (INT32)Column) && (This->Mode->CursorRow == (INT32)Row)) {
1670 Status = EFI_SUCCESS;
1671 goto Done;
1672 }
1673
1674 FlushCursor (This);
1675
1676 This->Mode->CursorColumn = (INT32)Column;
1677 This->Mode->CursorRow = (INT32)Row;
1678
1679 FlushCursor (This);
1680
1681 Done:
1682 gBS->RestoreTPL (OldTpl);
1683
1684 return Status;
1685 }
1686
1687 /**
1688 Makes the cursor visible or invisible.
1689
1690 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1691
1692 @param This Protocol instance pointer.
1693 @param Visible If TRUE, the cursor is set to be visible, If FALSE,
1694 the cursor is set to be invisible.
1695
1696 @retval EFI_SUCCESS The operation completed successfully.
1697 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
1698 defined text mode.
1699
1700 **/
1701 EFI_STATUS
1702 EFIAPI
1703 GraphicsConsoleConOutEnableCursor (
1704 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1705 IN BOOLEAN Visible
1706 )
1707 {
1708 EFI_TPL OldTpl;
1709
1710 if (This->Mode->Mode == -1) {
1711 //
1712 // If current mode is not valid, return error.
1713 //
1714 return EFI_UNSUPPORTED;
1715 }
1716
1717 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1718
1719 FlushCursor (This);
1720
1721 This->Mode->CursorVisible = Visible;
1722
1723 FlushCursor (This);
1724
1725 gBS->RestoreTPL (OldTpl);
1726 return EFI_SUCCESS;
1727 }
1728
1729 /**
1730 Gets Graphics Console device's foreground color and background color.
1731
1732 @param This Protocol instance pointer.
1733 @param Foreground Returned text foreground color.
1734 @param Background Returned text background color.
1735
1736 @retval EFI_SUCCESS It returned always.
1737
1738 **/
1739 EFI_STATUS
1740 GetTextColors (
1741 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1742 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
1743 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background
1744 )
1745 {
1746 INTN Attribute;
1747
1748 Attribute = This->Mode->Attribute & 0x7F;
1749
1750 *Foreground = mGraphicsEfiColors[Attribute & 0x0f];
1751 *Background = mGraphicsEfiColors[Attribute >> 4];
1752
1753 return EFI_SUCCESS;
1754 }
1755
1756 /**
1757 Draw Unicode string on the Graphics Console device's screen.
1758
1759 @param This Protocol instance pointer.
1760 @param UnicodeWeight One Unicode string to be displayed.
1761 @param Count The count of Unicode string.
1762
1763 @retval EFI_OUT_OF_RESOURCES If no memory resource to use.
1764 @retval EFI_UNSUPPORTED If no Graphics Output protocol and UGA Draw
1765 protocol exist.
1766 @retval EFI_SUCCESS Drawing Unicode string implemented successfully.
1767
1768 **/
1769 EFI_STATUS
1770 DrawUnicodeWeightAtCursorN (
1771 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1772 IN CHAR16 *UnicodeWeight,
1773 IN UINTN Count
1774 )
1775 {
1776 EFI_STATUS Status;
1777 GRAPHICS_CONSOLE_DEV *Private;
1778 EFI_IMAGE_OUTPUT *Blt;
1779 EFI_STRING String;
1780 EFI_FONT_DISPLAY_INFO *FontInfo;
1781 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1782 EFI_HII_ROW_INFO *RowInfoArray;
1783 UINTN RowInfoArraySize;
1784
1785 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1786 Blt = (EFI_IMAGE_OUTPUT *)AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
1787 if (Blt == NULL) {
1788 return EFI_OUT_OF_RESOURCES;
1789 }
1790
1791 Blt->Width = (UINT16)(Private->ModeData[This->Mode->Mode].GopWidth);
1792 Blt->Height = (UINT16)(Private->ModeData[This->Mode->Mode].GopHeight);
1793
1794 String = AllocateCopyPool ((Count + 1) * sizeof (CHAR16), UnicodeWeight);
1795 if (String == NULL) {
1796 FreePool (Blt);
1797 return EFI_OUT_OF_RESOURCES;
1798 }
1799
1800 //
1801 // Set the end character
1802 //
1803 *(String + Count) = L'\0';
1804
1805 FontInfo = (EFI_FONT_DISPLAY_INFO *)AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));
1806 if (FontInfo == NULL) {
1807 FreePool (Blt);
1808 FreePool (String);
1809 return EFI_OUT_OF_RESOURCES;
1810 }
1811
1812 //
1813 // Get current foreground and background colors.
1814 //
1815 GetTextColors (This, &FontInfo->ForegroundColor, &FontInfo->BackgroundColor);
1816
1817 if (Private->GraphicsOutput != NULL) {
1818 //
1819 // If Graphics Output protocol exists, using HII Font protocol to draw.
1820 //
1821 Blt->Image.Screen = Private->GraphicsOutput;
1822
1823 Status = mHiiFont->StringToImage (
1824 mHiiFont,
1825 EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN | EFI_HII_IGNORE_LINE_BREAK,
1826 String,
1827 FontInfo,
1828 &Blt,
1829 This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
1830 This->Mode->CursorRow * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1831 NULL,
1832 NULL,
1833 NULL
1834 );
1835 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1836 //
1837 // If Graphics Output protocol cannot be found and PcdUgaConsumeSupport enabled,
1838 // using UGA Draw protocol to draw.
1839 //
1840 ASSERT (Private->UgaDraw != NULL);
1841
1842 UgaDraw = Private->UgaDraw;
1843
1844 Blt->Image.Bitmap = AllocateZeroPool (Blt->Width * Blt->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1845 if (Blt->Image.Bitmap == NULL) {
1846 FreePool (Blt);
1847 FreePool (String);
1848 return EFI_OUT_OF_RESOURCES;
1849 }
1850
1851 RowInfoArray = NULL;
1852 //
1853 // StringToImage only support blt'ing image to device using GOP protocol. If GOP is not supported in this platform,
1854 // we ask StringToImage to print the string to blt buffer, then blt to device using UgaDraw.
1855 //
1856 Status = mHiiFont->StringToImage (
1857 mHiiFont,
1858 EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK,
1859 String,
1860 FontInfo,
1861 &Blt,
1862 This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
1863 This->Mode->CursorRow * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1864 &RowInfoArray,
1865 &RowInfoArraySize,
1866 NULL
1867 );
1868
1869 if (!EFI_ERROR (Status)) {
1870 //
1871 // Line breaks are handled by caller of DrawUnicodeWeightAtCursorN, so the updated parameter RowInfoArraySize by StringToImage will
1872 // always be 1 or 0 (if there is no valid Unicode Char can be printed). ASSERT here to make sure.
1873 //
1874 ASSERT (RowInfoArraySize <= 1);
1875
1876 Status = UgaDraw->Blt (
1877 UgaDraw,
1878 (EFI_UGA_PIXEL *)Blt->Image.Bitmap,
1879 EfiUgaBltBufferToVideo,
1880 This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
1881 (This->Mode->CursorRow) * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1882 This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
1883 (This->Mode->CursorRow) * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1884 RowInfoArray[0].LineWidth,
1885 RowInfoArray[0].LineHeight,
1886 Blt->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1887 );
1888 }
1889
1890 FreePool (RowInfoArray);
1891 FreePool (Blt->Image.Bitmap);
1892 } else {
1893 Status = EFI_UNSUPPORTED;
1894 }
1895
1896 if (Blt != NULL) {
1897 FreePool (Blt);
1898 }
1899
1900 if (String != NULL) {
1901 FreePool (String);
1902 }
1903
1904 if (FontInfo != NULL) {
1905 FreePool (FontInfo);
1906 }
1907
1908 return Status;
1909 }
1910
1911 /**
1912 Flush the cursor on the screen.
1913
1914 If CursorVisible is FALSE, nothing to do and return directly.
1915 If CursorVisible is TRUE,
1916 i) If the cursor shows on screen, it will be erased.
1917 ii) If the cursor does not show on screen, it will be shown.
1918
1919 @param This Protocol instance pointer.
1920
1921 @retval EFI_SUCCESS The cursor is erased successfully.
1922
1923 **/
1924 EFI_STATUS
1925 FlushCursor (
1926 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
1927 )
1928 {
1929 GRAPHICS_CONSOLE_DEV *Private;
1930 EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode;
1931 INTN GlyphX;
1932 INTN GlyphY;
1933 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1934 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1935 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground;
1936 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background;
1937 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[EFI_GLYPH_HEIGHT][EFI_GLYPH_WIDTH];
1938 UINTN PosX;
1939 UINTN PosY;
1940
1941 CurrentMode = This->Mode;
1942
1943 if (!CurrentMode->CursorVisible) {
1944 return EFI_SUCCESS;
1945 }
1946
1947 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1948 GraphicsOutput = Private->GraphicsOutput;
1949 UgaDraw = Private->UgaDraw;
1950
1951 //
1952 // In this driver, only narrow character was supported.
1953 //
1954 //
1955 // Blt a character to the screen
1956 //
1957 GlyphX = (CurrentMode->CursorColumn * EFI_GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX;
1958 GlyphY = (CurrentMode->CursorRow * EFI_GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY;
1959 if (GraphicsOutput != NULL) {
1960 GraphicsOutput->Blt (
1961 GraphicsOutput,
1962 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)BltChar,
1963 EfiBltVideoToBltBuffer,
1964 GlyphX,
1965 GlyphY,
1966 0,
1967 0,
1968 EFI_GLYPH_WIDTH,
1969 EFI_GLYPH_HEIGHT,
1970 EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1971 );
1972 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1973 UgaDraw->Blt (
1974 UgaDraw,
1975 (EFI_UGA_PIXEL *)(UINTN)BltChar,
1976 EfiUgaVideoToBltBuffer,
1977 GlyphX,
1978 GlyphY,
1979 0,
1980 0,
1981 EFI_GLYPH_WIDTH,
1982 EFI_GLYPH_HEIGHT,
1983 EFI_GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
1984 );
1985 }
1986
1987 GetTextColors (This, &Foreground.Pixel, &Background.Pixel);
1988
1989 //
1990 // Convert Monochrome bitmap of the Glyph to BltBuffer structure
1991 //
1992 for (PosY = 0; PosY < EFI_GLYPH_HEIGHT; PosY++) {
1993 for (PosX = 0; PosX < EFI_GLYPH_WIDTH; PosX++) {
1994 if ((mCursorGlyph.GlyphCol1[PosY] & (BIT0 << PosX)) != 0) {
1995 BltChar[PosY][EFI_GLYPH_WIDTH - PosX - 1].Raw ^= Foreground.Raw;
1996 }
1997 }
1998 }
1999
2000 if (GraphicsOutput != NULL) {
2001 GraphicsOutput->Blt (
2002 GraphicsOutput,
2003 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)BltChar,
2004 EfiBltBufferToVideo,
2005 0,
2006 0,
2007 GlyphX,
2008 GlyphY,
2009 EFI_GLYPH_WIDTH,
2010 EFI_GLYPH_HEIGHT,
2011 EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
2012 );
2013 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
2014 UgaDraw->Blt (
2015 UgaDraw,
2016 (EFI_UGA_PIXEL *)(UINTN)BltChar,
2017 EfiUgaBltBufferToVideo,
2018 0,
2019 0,
2020 GlyphX,
2021 GlyphY,
2022 EFI_GLYPH_WIDTH,
2023 EFI_GLYPH_HEIGHT,
2024 EFI_GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
2025 );
2026 }
2027
2028 return EFI_SUCCESS;
2029 }
2030
2031 /**
2032 HII Database Protocol notification event handler.
2033
2034 Register font package when HII Database Protocol has been installed.
2035
2036 @param[in] Event Event whose notification function is being invoked.
2037 @param[in] Context Pointer to the notification function's context.
2038 **/
2039 VOID
2040 EFIAPI
2041 RegisterFontPackage (
2042 IN EFI_EVENT Event,
2043 IN VOID *Context
2044 )
2045 {
2046 EFI_STATUS Status;
2047 EFI_HII_SIMPLE_FONT_PACKAGE_HDR *SimplifiedFont;
2048 UINT32 PackageLength;
2049 UINT8 *Package;
2050 UINT8 *Location;
2051 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
2052
2053 //
2054 // Locate HII Database Protocol
2055 //
2056 Status = gBS->LocateProtocol (
2057 &gEfiHiiDatabaseProtocolGuid,
2058 NULL,
2059 (VOID **)&HiiDatabase
2060 );
2061 if (EFI_ERROR (Status)) {
2062 return;
2063 }
2064
2065 //
2066 // Add 4 bytes to the header for entire length for HiiAddPackages use only.
2067 //
2068 // +--------------------------------+ <-- Package
2069 // | |
2070 // | PackageLength(4 bytes) |
2071 // | |
2072 // |--------------------------------| <-- SimplifiedFont
2073 // | |
2074 // |EFI_HII_SIMPLE_FONT_PACKAGE_HDR |
2075 // | |
2076 // |--------------------------------| <-- Location
2077 // | |
2078 // | gUsStdNarrowGlyphData |
2079 // | |
2080 // +--------------------------------+
2081
2082 PackageLength = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR) + mNarrowFontSize + 4;
2083 Package = AllocateZeroPool (PackageLength);
2084 ASSERT (Package != NULL);
2085
2086 WriteUnaligned32 ((UINT32 *)Package, PackageLength);
2087 SimplifiedFont = (EFI_HII_SIMPLE_FONT_PACKAGE_HDR *)(Package + 4);
2088 SimplifiedFont->Header.Length = (UINT32)(PackageLength - 4);
2089 SimplifiedFont->Header.Type = EFI_HII_PACKAGE_SIMPLE_FONTS;
2090 SimplifiedFont->NumberOfNarrowGlyphs = (UINT16)(mNarrowFontSize / sizeof (EFI_NARROW_GLYPH));
2091
2092 Location = (UINT8 *)(&SimplifiedFont->NumberOfWideGlyphs + 1);
2093 CopyMem (Location, gUsStdNarrowGlyphData, mNarrowFontSize);
2094
2095 //
2096 // Add this simplified font package to a package list then install it.
2097 //
2098 mHiiHandle = HiiAddPackages (
2099 &mFontPackageListGuid,
2100 NULL,
2101 Package,
2102 NULL
2103 );
2104 ASSERT (mHiiHandle != NULL);
2105 FreePool (Package);
2106 }
2107
2108 /**
2109 The user Entry Point for module GraphicsConsole. The user code starts with this function.
2110
2111 @param[in] ImageHandle The firmware allocated handle for the EFI image.
2112 @param[in] SystemTable A pointer to the EFI System Table.
2113
2114 @retval EFI_SUCCESS The entry point is executed successfully.
2115 @return other Some error occurs when executing this entry point.
2116
2117 **/
2118 EFI_STATUS
2119 EFIAPI
2120 InitializeGraphicsConsole (
2121 IN EFI_HANDLE ImageHandle,
2122 IN EFI_SYSTEM_TABLE *SystemTable
2123 )
2124 {
2125 EFI_STATUS Status;
2126
2127 //
2128 // Register notify function on HII Database Protocol to add font package.
2129 //
2130 EfiCreateProtocolNotifyEvent (
2131 &gEfiHiiDatabaseProtocolGuid,
2132 TPL_CALLBACK,
2133 RegisterFontPackage,
2134 NULL,
2135 &mHiiRegistration
2136 );
2137
2138 //
2139 // Install driver model protocol(s).
2140 //
2141 Status = EfiLibInstallDriverBindingComponentName2 (
2142 ImageHandle,
2143 SystemTable,
2144 &gGraphicsConsoleDriverBinding,
2145 ImageHandle,
2146 &gGraphicsConsoleComponentName,
2147 &gGraphicsConsoleComponentName2
2148 );
2149 ASSERT_EFI_ERROR (Status);
2150
2151 return Status;
2152 }