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