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