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