]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
0d0293da193e4b73adcfb6dc605704e16117859e
[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 - 2009 Intel Corporation. <BR>
5 All rights reserved. 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 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
644 if (!EFI_ERROR (Status)) {
645 FreePool (Info);
646 break;
647 }
648 }
649 FreePool (Info);
650 }
651 }
652
653 if (ModeNumber == GraphicsOutput->Mode->MaxMode) {
654 Status = EFI_UNSUPPORTED;
655 }
656
657 *CurrentModeNumber = ModeNumber;
658 return Status;
659 }
660
661
662 /**
663 Locate HII Database protocol and HII Font protocol.
664
665 @retval EFI_SUCCESS HII Database protocol and HII Font protocol
666 are located successfully.
667 @return other Failed to locate HII Database protocol or
668 HII Font protocol.
669
670 **/
671 EFI_STATUS
672 EfiLocateHiiProtocol (
673 VOID
674 )
675 {
676 EFI_HANDLE Handle;
677 UINTN Size;
678 EFI_STATUS Status;
679
680 //
681 // There should only be one - so buffer size is this
682 //
683 Size = sizeof (EFI_HANDLE);
684
685 Status = gBS->LocateHandle (
686 ByProtocol,
687 &gEfiHiiDatabaseProtocolGuid,
688 NULL,
689 &Size,
690 (VOID **) &Handle
691 );
692
693 if (EFI_ERROR (Status)) {
694 return Status;
695 }
696
697 Status = gBS->HandleProtocol (
698 Handle,
699 &gEfiHiiDatabaseProtocolGuid,
700 (VOID **) &mHiiDatabase
701 );
702
703 if (EFI_ERROR (Status)) {
704 return Status;
705 }
706
707 Status = gBS->HandleProtocol (
708 Handle,
709 &gEfiHiiFontProtocolGuid,
710 (VOID **) &mHiiFont
711 );
712 return Status;
713 }
714
715 //
716 // Body of the STO functions
717 //
718
719 /**
720 Reset the text output device hardware and optionally run diagnostics.
721
722 Implements SIMPLE_TEXT_OUTPUT.Reset().
723 If ExtendeVerification is TRUE, then perform dependent Graphics Console
724 device reset, and set display mode to mode 0.
725 If ExtendedVerification is FALSE, only set display mode to mode 0.
726
727 @param This Protocol instance pointer.
728 @param ExtendedVerification Indicates that the driver may perform a more
729 exhaustive verification operation of the device
730 during reset.
731
732 @retval EFI_SUCCESS The text output device was reset.
733 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
734 could not be reset.
735
736 **/
737 EFI_STATUS
738 EFIAPI
739 GraphicsConsoleConOutReset (
740 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
741 IN BOOLEAN ExtendedVerification
742 )
743 {
744 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));
745 return This->SetMode (This, 0);
746 }
747
748
749 /**
750 Write a Unicode string to the output device.
751
752 Implements SIMPLE_TEXT_OUTPUT.OutputString().
753 The Unicode string will be converted to Glyphs and will be
754 sent to the Graphics Console.
755
756 @param This Protocol instance pointer.
757 @param WString The NULL-terminated Unicode string to be displayed
758 on the output device(s). All output devices must
759 also support the Unicode drawing defined in this file.
760
761 @retval EFI_SUCCESS The string was output to the device.
762 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
763 the text.
764 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
765 defined text mode.
766 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
767 characters in the Unicode string could not be
768 rendered and were skipped.
769
770 **/
771 EFI_STATUS
772 EFIAPI
773 GraphicsConsoleConOutOutputString (
774 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
775 IN CHAR16 *WString
776 )
777 {
778 GRAPHICS_CONSOLE_DEV *Private;
779 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
780 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
781 INTN Mode;
782 UINTN MaxColumn;
783 UINTN MaxRow;
784 UINTN Width;
785 UINTN Height;
786 UINTN Delta;
787 EFI_STATUS Status;
788 BOOLEAN Warning;
789 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
790 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
791 UINTN DeltaX;
792 UINTN DeltaY;
793 UINTN Count;
794 UINTN Index;
795 INT32 OriginAttribute;
796 EFI_TPL OldTpl;
797
798 Status = EFI_SUCCESS;
799
800 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
801 //
802 // Current mode
803 //
804 Mode = This->Mode->Mode;
805 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
806 GraphicsOutput = Private->GraphicsOutput;
807 UgaDraw = Private->UgaDraw;
808
809 MaxColumn = Private->ModeData[Mode].Columns;
810 MaxRow = Private->ModeData[Mode].Rows;
811 DeltaX = Private->ModeData[Mode].DeltaX;
812 DeltaY = Private->ModeData[Mode].DeltaY;
813 Width = MaxColumn * EFI_GLYPH_WIDTH;
814 Height = (MaxRow - 1) * EFI_GLYPH_HEIGHT;
815 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
816
817 //
818 // The Attributes won't change when during the time OutputString is called
819 //
820 GetTextColors (This, &Foreground, &Background);
821
822 EraseCursor (This);
823
824 Warning = FALSE;
825
826 //
827 // Backup attribute
828 //
829 OriginAttribute = This->Mode->Attribute;
830
831 while (*WString != L'\0') {
832
833 if (*WString == CHAR_BACKSPACE) {
834 //
835 // If the cursor is at the left edge of the display, then move the cursor
836 // one row up.
837 //
838 if (This->Mode->CursorColumn == 0 && This->Mode->CursorRow > 0) {
839 This->Mode->CursorRow--;
840 This->Mode->CursorColumn = (INT32) (MaxColumn - 1);
841 This->OutputString (This, SpaceStr);
842 EraseCursor (This);
843 This->Mode->CursorRow--;
844 This->Mode->CursorColumn = (INT32) (MaxColumn - 1);
845 } else if (This->Mode->CursorColumn > 0) {
846 //
847 // If the cursor is not at the left edge of the display, then move the cursor
848 // left one column.
849 //
850 This->Mode->CursorColumn--;
851 This->OutputString (This, SpaceStr);
852 EraseCursor (This);
853 This->Mode->CursorColumn--;
854 }
855
856 WString++;
857
858 } else if (*WString == CHAR_LINEFEED) {
859 //
860 // If the cursor is at the bottom of the display, then scroll the display one
861 // row, and do not update the cursor position. Otherwise, move the cursor
862 // down one row.
863 //
864 if (This->Mode->CursorRow == (INT32) (MaxRow - 1)) {
865 if (GraphicsOutput != NULL) {
866 //
867 // Scroll Screen Up One Row
868 //
869 GraphicsOutput->Blt (
870 GraphicsOutput,
871 NULL,
872 EfiBltVideoToVideo,
873 DeltaX,
874 DeltaY + EFI_GLYPH_HEIGHT,
875 DeltaX,
876 DeltaY,
877 Width,
878 Height,
879 Delta
880 );
881
882 //
883 // Print Blank Line at last line
884 //
885 GraphicsOutput->Blt (
886 GraphicsOutput,
887 &Background,
888 EfiBltVideoFill,
889 0,
890 0,
891 DeltaX,
892 DeltaY + Height,
893 Width,
894 EFI_GLYPH_HEIGHT,
895 Delta
896 );
897 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
898 //
899 // Scroll Screen Up One Row
900 //
901 UgaDraw->Blt (
902 UgaDraw,
903 NULL,
904 EfiUgaVideoToVideo,
905 DeltaX,
906 DeltaY + EFI_GLYPH_HEIGHT,
907 DeltaX,
908 DeltaY,
909 Width,
910 Height,
911 Delta
912 );
913
914 //
915 // Print Blank Line at last line
916 //
917 UgaDraw->Blt (
918 UgaDraw,
919 (EFI_UGA_PIXEL *) (UINTN) &Background,
920 EfiUgaVideoFill,
921 0,
922 0,
923 DeltaX,
924 DeltaY + Height,
925 Width,
926 EFI_GLYPH_HEIGHT,
927 Delta
928 );
929 }
930 } else {
931 This->Mode->CursorRow++;
932 }
933
934 WString++;
935
936 } else if (*WString == CHAR_CARRIAGE_RETURN) {
937 //
938 // Move the cursor to the beginning of the current row.
939 //
940 This->Mode->CursorColumn = 0;
941 WString++;
942
943 } else if (*WString == WIDE_CHAR) {
944
945 This->Mode->Attribute |= EFI_WIDE_ATTRIBUTE;
946 WString++;
947
948 } else if (*WString == NARROW_CHAR) {
949
950 This->Mode->Attribute &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
951 WString++;
952
953 } else {
954 //
955 // Print the character at the current cursor position and move the cursor
956 // right one column. If this moves the cursor past the right edge of the
957 // display, then the line should wrap to the beginning of the next line. This
958 // is equivalent to inserting a CR and an LF. Note that if the cursor is at the
959 // bottom of the display, and the line wraps, then the display will be scrolled
960 // one line.
961 // If wide char is going to be displayed, need to display one character at a time
962 // Or, need to know the display length of a certain string.
963 //
964 // Index is used to determine how many character width units (wide = 2, narrow = 1)
965 // Count is used to determine how many characters are used regardless of their attributes
966 //
967 for (Count = 0, Index = 0; (This->Mode->CursorColumn + Index) < MaxColumn; Count++, Index++) {
968 if (WString[Count] == CHAR_NULL ||
969 WString[Count] == CHAR_BACKSPACE ||
970 WString[Count] == CHAR_LINEFEED ||
971 WString[Count] == CHAR_CARRIAGE_RETURN ||
972 WString[Count] == WIDE_CHAR ||
973 WString[Count] == NARROW_CHAR) {
974 break;
975 }
976 //
977 // Is the wide attribute on?
978 //
979 if ((This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) != 0) {
980 //
981 // If wide, add one more width unit than normal since we are going to increment at the end of the for loop
982 //
983 Index++;
984 //
985 // This is the end-case where if we are at column 79 and about to print a wide character
986 // We should prevent this from happening because we will wrap inappropriately. We should
987 // not print this character until the next line.
988 //
989 if ((This->Mode->CursorColumn + Index + 1) > MaxColumn) {
990 Index++;
991 break;
992 }
993 }
994 }
995
996 Status = DrawUnicodeWeightAtCursorN (This, WString, Count);
997 if (EFI_ERROR (Status)) {
998 Warning = TRUE;
999 }
1000 //
1001 // At the end of line, output carriage return and line feed
1002 //
1003 WString += Count;
1004 This->Mode->CursorColumn += (INT32) Index;
1005 if (This->Mode->CursorColumn > (INT32) MaxColumn) {
1006 This->Mode->CursorColumn -= 2;
1007 This->OutputString (This, SpaceStr);
1008 }
1009
1010 if (This->Mode->CursorColumn >= (INT32) MaxColumn) {
1011 EraseCursor (This);
1012 This->OutputString (This, mCrLfString);
1013 EraseCursor (This);
1014 }
1015 }
1016 }
1017
1018 This->Mode->Attribute = OriginAttribute;
1019
1020 EraseCursor (This);
1021
1022 if (Warning) {
1023 Status = EFI_WARN_UNKNOWN_GLYPH;
1024 }
1025
1026 gBS->RestoreTPL (OldTpl);
1027 return Status;
1028
1029 }
1030
1031 /**
1032 Verifies that all characters in a Unicode string can be output to the
1033 target device.
1034
1035 Implements SIMPLE_TEXT_OUTPUT.TestString().
1036 If one of the characters in the *Wstring is neither valid valid Unicode
1037 drawing characters, not ASCII code, then this function will return
1038 EFI_UNSUPPORTED
1039
1040 @param This Protocol instance pointer.
1041 @param WString The NULL-terminated Unicode string to be examined for the output
1042 device(s).
1043
1044 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
1045 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
1046 rendered by one or more of the output devices mapped
1047 by the EFI handle.
1048
1049 **/
1050 EFI_STATUS
1051 EFIAPI
1052 GraphicsConsoleConOutTestString (
1053 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1054 IN CHAR16 *WString
1055 )
1056 {
1057 EFI_STATUS Status;
1058 UINT16 Count;
1059
1060 EFI_IMAGE_OUTPUT *Blt;
1061
1062 Blt = NULL;
1063 Count = 0;
1064
1065 while (WString[Count] != 0) {
1066 Status = mHiiFont->GetGlyph (
1067 mHiiFont,
1068 WString[Count],
1069 NULL,
1070 &Blt,
1071 NULL
1072 );
1073 if (Blt != NULL) {
1074 FreePool (Blt);
1075 Blt = NULL;
1076 }
1077 Count++;
1078
1079 if (EFI_ERROR (Status)) {
1080 return EFI_UNSUPPORTED;
1081 }
1082 }
1083
1084 return EFI_SUCCESS;
1085 }
1086
1087
1088 /**
1089 Returns information for an available text mode that the output device(s)
1090 supports
1091
1092 Implements SIMPLE_TEXT_OUTPUT.QueryMode().
1093 It returnes information for an available text mode that the Graphics Console supports.
1094 In this driver,we only support text mode 80x25, which is defined as mode 0.
1095
1096 @param This Protocol instance pointer.
1097 @param ModeNumber The mode number to return information on.
1098 @param Columns The returned columns of the requested mode.
1099 @param Rows The returned rows of the requested mode.
1100
1101 @retval EFI_SUCCESS The requested mode information is returned.
1102 @retval EFI_UNSUPPORTED The mode number is not valid.
1103
1104 **/
1105 EFI_STATUS
1106 EFIAPI
1107 GraphicsConsoleConOutQueryMode (
1108 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1109 IN UINTN ModeNumber,
1110 OUT UINTN *Columns,
1111 OUT UINTN *Rows
1112 )
1113 {
1114 GRAPHICS_CONSOLE_DEV *Private;
1115 EFI_STATUS Status;
1116 EFI_TPL OldTpl;
1117
1118 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
1119 return EFI_UNSUPPORTED;
1120 }
1121
1122 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1123 Status = EFI_SUCCESS;
1124
1125 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1126
1127 *Columns = Private->ModeData[ModeNumber].Columns;
1128 *Rows = Private->ModeData[ModeNumber].Rows;
1129
1130 if (*Columns <= 0 && *Rows <= 0) {
1131 Status = EFI_UNSUPPORTED;
1132 goto Done;
1133
1134 }
1135
1136 Done:
1137 gBS->RestoreTPL (OldTpl);
1138 return Status;
1139 }
1140
1141
1142 /**
1143 Sets the output device(s) to a specified mode.
1144
1145 Implements SIMPLE_TEXT_OUTPUT.SetMode().
1146 Set the Graphics Console to a specified mode. In this driver, we only support mode 0.
1147
1148 @param This Protocol instance pointer.
1149 @param ModeNumber The text mode to set.
1150
1151 @retval EFI_SUCCESS The requested text mode is set.
1152 @retval EFI_DEVICE_ERROR The requested text mode cannot be set because of
1153 Graphics Console device error.
1154 @retval EFI_UNSUPPORTED The text mode number is not valid.
1155
1156 **/
1157 EFI_STATUS
1158 EFIAPI
1159 GraphicsConsoleConOutSetMode (
1160 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1161 IN UINTN ModeNumber
1162 )
1163 {
1164 EFI_STATUS Status;
1165 GRAPHICS_CONSOLE_DEV *Private;
1166 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1167 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewLineBuffer;
1168 UINT32 HorizontalResolution;
1169 UINT32 VerticalResolution;
1170 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1171 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1172 UINT32 ColorDepth;
1173 UINT32 RefreshRate;
1174 EFI_TPL OldTpl;
1175
1176 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1177
1178 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1179 GraphicsOutput = Private->GraphicsOutput;
1180 UgaDraw = Private->UgaDraw;
1181 ModeData = &(Private->ModeData[ModeNumber]);
1182
1183 if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {
1184 Status = EFI_UNSUPPORTED;
1185 goto Done;
1186 }
1187
1188 //
1189 // Make sure the requested mode number is supported
1190 //
1191 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
1192 Status = EFI_UNSUPPORTED;
1193 goto Done;
1194 }
1195
1196 if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {
1197 Status = EFI_UNSUPPORTED;
1198 goto Done;
1199 }
1200 //
1201 // Attempt to allocate a line buffer for the requested mode number
1202 //
1203 NewLineBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->Columns * EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT);
1204
1205 if (NewLineBuffer == NULL) {
1206 //
1207 // The new line buffer could not be allocated, so return an error.
1208 // No changes to the state of the current console have been made, so the current console is still valid
1209 //
1210 Status = EFI_OUT_OF_RESOURCES;
1211 goto Done;
1212 }
1213 //
1214 // If the mode has been set at least one other time, then LineBuffer will not be NULL
1215 //
1216 if (Private->LineBuffer != NULL) {
1217 //
1218 // Clear the current text window on the current graphics console
1219 //
1220 This->ClearScreen (This);
1221
1222 //
1223 // If the new mode is the same as the old mode, then just return EFI_SUCCESS
1224 //
1225 if ((INT32) ModeNumber == This->Mode->Mode) {
1226 FreePool (NewLineBuffer);
1227 Status = EFI_SUCCESS;
1228 goto Done;
1229 }
1230 //
1231 // Otherwise, the size of the text console and/or the GOP/UGA mode will be changed,
1232 // so erase the cursor, and free the LineBuffer for the current mode
1233 //
1234 EraseCursor (This);
1235
1236 FreePool (Private->LineBuffer);
1237 }
1238 //
1239 // Assign the current line buffer to the newly allocated line buffer
1240 //
1241 Private->LineBuffer = NewLineBuffer;
1242
1243 if (GraphicsOutput != NULL) {
1244 if (ModeData->GopModeNumber != GraphicsOutput->Mode->Mode) {
1245 //
1246 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new graphics mode
1247 //
1248 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeData->GopModeNumber);
1249 if (EFI_ERROR (Status)) {
1250 //
1251 // The mode set operation failed
1252 //
1253 goto Done;
1254 }
1255 } else {
1256 //
1257 // The current graphics mode is correct, so simply clear the entire display
1258 //
1259 Status = GraphicsOutput->Blt (
1260 GraphicsOutput,
1261 &mGraphicsEfiColors[0],
1262 EfiBltVideoFill,
1263 0,
1264 0,
1265 0,
1266 0,
1267 ModeData->GopWidth,
1268 ModeData->GopHeight,
1269 0
1270 );
1271 }
1272 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1273 //
1274 // Get the current UGA Draw mode information
1275 //
1276 Status = UgaDraw->GetMode (
1277 UgaDraw,
1278 &HorizontalResolution,
1279 &VerticalResolution,
1280 &ColorDepth,
1281 &RefreshRate
1282 );
1283 if (EFI_ERROR (Status) || HorizontalResolution != ModeData->GopWidth || VerticalResolution != ModeData->GopHeight) {
1284 //
1285 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new graphics mode
1286 //
1287 Status = UgaDraw->SetMode (
1288 UgaDraw,
1289 ModeData->GopWidth,
1290 ModeData->GopHeight,
1291 32,
1292 60
1293 );
1294 if (EFI_ERROR (Status)) {
1295 //
1296 // The mode set operation failed
1297 //
1298 goto Done;
1299 }
1300 } else {
1301 //
1302 // The current graphics mode is correct, so simply clear the entire display
1303 //
1304 Status = UgaDraw->Blt (
1305 UgaDraw,
1306 (EFI_UGA_PIXEL *) (UINTN) &mGraphicsEfiColors[0],
1307 EfiUgaVideoFill,
1308 0,
1309 0,
1310 0,
1311 0,
1312 ModeData->GopWidth,
1313 ModeData->GopHeight,
1314 0
1315 );
1316 }
1317 }
1318
1319 //
1320 // The new mode is valid, so commit the mode change
1321 //
1322 This->Mode->Mode = (INT32) ModeNumber;
1323
1324 //
1325 // Move the text cursor to the upper left hand corner of the display and enable it
1326 //
1327 This->SetCursorPosition (This, 0, 0);
1328
1329 Status = EFI_SUCCESS;
1330
1331 Done:
1332 gBS->RestoreTPL (OldTpl);
1333 return Status;
1334 }
1335
1336
1337 /**
1338 Sets the background and foreground colors for the OutputString () and
1339 ClearScreen () functions.
1340
1341 Implements SIMPLE_TEXT_OUTPUT.SetAttribute().
1342
1343 @param This Protocol instance pointer.
1344 @param Attribute The attribute to set. Bits 0..3 are the foreground
1345 color, and bits 4..6 are the background color.
1346 All other bits are undefined and must be zero.
1347
1348 @retval EFI_SUCCESS The requested attribute is set.
1349 @retval EFI_DEVICE_ERROR The requested attribute cannot be set due to Graphics Console port error.
1350 @retval EFI_UNSUPPORTED The attribute requested is not defined.
1351
1352 **/
1353 EFI_STATUS
1354 EFIAPI
1355 GraphicsConsoleConOutSetAttribute (
1356 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1357 IN UINTN Attribute
1358 )
1359 {
1360 EFI_TPL OldTpl;
1361
1362 if ((Attribute | 0xFF) != 0xFF) {
1363 return EFI_UNSUPPORTED;
1364 }
1365
1366 if ((INT32) Attribute == This->Mode->Attribute) {
1367 return EFI_SUCCESS;
1368 }
1369
1370 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1371
1372 EraseCursor (This);
1373
1374 This->Mode->Attribute = (INT32) Attribute;
1375
1376 EraseCursor (This);
1377
1378 gBS->RestoreTPL (OldTpl);
1379
1380 return EFI_SUCCESS;
1381 }
1382
1383
1384 /**
1385 Clears the output device(s) display to the currently selected background
1386 color.
1387
1388 Implements SIMPLE_TEXT_OUTPUT.ClearScreen().
1389
1390 @param This Protocol instance pointer.
1391
1392 @retval EFI_SUCCESS The operation completed successfully.
1393 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
1394 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1395
1396 **/
1397 EFI_STATUS
1398 EFIAPI
1399 GraphicsConsoleConOutClearScreen (
1400 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
1401 )
1402 {
1403 EFI_STATUS Status;
1404 GRAPHICS_CONSOLE_DEV *Private;
1405 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1406 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1407 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1408 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
1409 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1410 EFI_TPL OldTpl;
1411
1412 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1413
1414 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1415 GraphicsOutput = Private->GraphicsOutput;
1416 UgaDraw = Private->UgaDraw;
1417 ModeData = &(Private->ModeData[This->Mode->Mode]);
1418
1419 GetTextColors (This, &Foreground, &Background);
1420 if (GraphicsOutput != NULL) {
1421 Status = GraphicsOutput->Blt (
1422 GraphicsOutput,
1423 &Background,
1424 EfiBltVideoFill,
1425 0,
1426 0,
1427 0,
1428 0,
1429 ModeData->GopWidth,
1430 ModeData->GopHeight,
1431 0
1432 );
1433 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1434 Status = UgaDraw->Blt (
1435 UgaDraw,
1436 (EFI_UGA_PIXEL *) (UINTN) &Background,
1437 EfiUgaVideoFill,
1438 0,
1439 0,
1440 0,
1441 0,
1442 ModeData->GopWidth,
1443 ModeData->GopHeight,
1444 0
1445 );
1446 } else {
1447 Status = EFI_UNSUPPORTED;
1448 }
1449
1450 This->Mode->CursorColumn = 0;
1451 This->Mode->CursorRow = 0;
1452
1453 EraseCursor (This);
1454
1455 gBS->RestoreTPL (OldTpl);
1456
1457 return Status;
1458 }
1459
1460
1461 /**
1462 Sets the current coordinates of the cursor position.
1463
1464 Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().
1465
1466 @param This Protocol instance pointer.
1467 @param Column The position to set the cursor to. Must be greater than or
1468 equal to zero and less than the number of columns and rows
1469 by QueryMode ().
1470 @param Row The position to set the cursor to. Must be greater than or
1471 equal to zero and less than the number of columns and rows
1472 by QueryMode ().
1473
1474 @retval EFI_SUCCESS The operation completed successfully.
1475 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
1476 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
1477 cursor position is invalid for the current mode.
1478
1479 **/
1480 EFI_STATUS
1481 EFIAPI
1482 GraphicsConsoleConOutSetCursorPosition (
1483 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1484 IN UINTN Column,
1485 IN UINTN Row
1486 )
1487 {
1488 GRAPHICS_CONSOLE_DEV *Private;
1489 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1490 EFI_STATUS Status;
1491 EFI_TPL OldTpl;
1492
1493 Status = EFI_SUCCESS;
1494
1495 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1496
1497 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1498 ModeData = &(Private->ModeData[This->Mode->Mode]);
1499
1500 if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) {
1501 Status = EFI_UNSUPPORTED;
1502 goto Done;
1503 }
1504
1505 if ((This->Mode->CursorColumn == (INT32) Column) && (This->Mode->CursorRow == (INT32) Row)) {
1506 Status = EFI_SUCCESS;
1507 goto Done;
1508 }
1509
1510 EraseCursor (This);
1511
1512 This->Mode->CursorColumn = (INT32) Column;
1513 This->Mode->CursorRow = (INT32) Row;
1514
1515 EraseCursor (This);
1516
1517 Done:
1518 gBS->RestoreTPL (OldTpl);
1519
1520 return Status;
1521 }
1522
1523
1524 /**
1525 Makes the cursor visible or invisible.
1526
1527 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1528
1529 @param This Protocol instance pointer.
1530 @param Visible If TRUE, the cursor is set to be visible, If FALSE,
1531 the cursor is set to be invisible.
1532
1533 @retval EFI_SUCCESS The operation completed successfully.
1534
1535 **/
1536 EFI_STATUS
1537 EFIAPI
1538 GraphicsConsoleConOutEnableCursor (
1539 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1540 IN BOOLEAN Visible
1541 )
1542 {
1543 EFI_TPL OldTpl;
1544
1545 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1546
1547 EraseCursor (This);
1548
1549 This->Mode->CursorVisible = Visible;
1550
1551 EraseCursor (This);
1552
1553 gBS->RestoreTPL (OldTpl);
1554 return EFI_SUCCESS;
1555 }
1556
1557 /**
1558 Gets Graphics Console devcie's foreground color and background color.
1559
1560 @param This Protocol instance pointer.
1561 @param Foreground Returned text foreground color.
1562 @param Background Returned text background color.
1563
1564 @retval EFI_SUCCESS It returned always.
1565
1566 **/
1567 EFI_STATUS
1568 GetTextColors (
1569 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1570 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
1571 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background
1572 )
1573 {
1574 INTN Attribute;
1575
1576 Attribute = This->Mode->Attribute & 0x7F;
1577
1578 *Foreground = mGraphicsEfiColors[Attribute & 0x0f];
1579 *Background = mGraphicsEfiColors[Attribute >> 4];
1580
1581 return EFI_SUCCESS;
1582 }
1583
1584 /**
1585 Draw Unicode string on the Graphics Console device's screen.
1586
1587 @param This Protocol instance pointer.
1588 @param UnicodeWeight One Unicode string to be displayed.
1589 @param Count The count of Unicode string.
1590
1591 @retval EFI_OUT_OF_RESOURCES If no memory resource to use.
1592 @retval EFI_UNSUPPORTED If no Graphics Output protocol and UGA Draw
1593 protocol exist.
1594 @retval EFI_SUCCESS Drawing Unicode string implemented successfully.
1595
1596 **/
1597 EFI_STATUS
1598 DrawUnicodeWeightAtCursorN (
1599 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1600 IN CHAR16 *UnicodeWeight,
1601 IN UINTN Count
1602 )
1603 {
1604 EFI_STATUS Status;
1605 GRAPHICS_CONSOLE_DEV *Private;
1606 EFI_IMAGE_OUTPUT *Blt;
1607 EFI_STRING String;
1608 EFI_FONT_DISPLAY_INFO *FontInfo;
1609 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1610 EFI_HII_ROW_INFO *RowInfoArray;
1611 UINTN RowInfoArraySize;
1612
1613 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1614 Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
1615 if (Blt == NULL) {
1616 return EFI_OUT_OF_RESOURCES;
1617 }
1618
1619 Blt->Width = (UINT16) (Private->ModeData[This->Mode->Mode].GopWidth);
1620 Blt->Height = (UINT16) (Private->ModeData[This->Mode->Mode].GopHeight);
1621
1622 String = AllocateCopyPool ((Count + 1) * sizeof (CHAR16), UnicodeWeight);
1623 if (String == NULL) {
1624 FreePool (Blt);
1625 return EFI_OUT_OF_RESOURCES;
1626 }
1627 //
1628 // Set the end character
1629 //
1630 *(String + Count) = L'\0';
1631
1632 FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));
1633 if (FontInfo == NULL) {
1634 FreePool (Blt);
1635 FreePool (String);
1636 return EFI_OUT_OF_RESOURCES;
1637 }
1638 //
1639 // Get current foreground and background colors.
1640 //
1641 GetTextColors (This, &FontInfo->ForegroundColor, &FontInfo->BackgroundColor);
1642
1643 if (Private->GraphicsOutput != NULL) {
1644 //
1645 // If Graphics Output protocol exists, using HII Font protocol to draw.
1646 //
1647 Blt->Image.Screen = Private->GraphicsOutput;
1648
1649 Status = mHiiFont->StringToImage (
1650 mHiiFont,
1651 EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN | EFI_HII_IGNORE_LINE_BREAK,
1652 String,
1653 FontInfo,
1654 &Blt,
1655 This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
1656 This->Mode->CursorRow * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1657 NULL,
1658 NULL,
1659 NULL
1660 );
1661
1662 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1663 //
1664 // If Graphics Output protocol cannot be found and PcdUgaConsumeSupport enabled,
1665 // using UGA Draw protocol to draw.
1666 //
1667 ASSERT (Private->UgaDraw!= NULL);
1668
1669 UgaDraw = Private->UgaDraw;
1670
1671 Blt->Image.Bitmap = AllocateZeroPool (Blt->Width * Blt->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1672 if (Blt->Image.Bitmap == NULL) {
1673 FreePool (Blt);
1674 FreePool (String);
1675 return EFI_OUT_OF_RESOURCES;
1676 }
1677
1678 RowInfoArray = NULL;
1679 //
1680 // StringToImage only support blt'ing image to device using GOP protocol. If GOP is not supported in this platform,
1681 // we ask StringToImage to print the string to blt buffer, then blt to device using UgaDraw.
1682 //
1683 Status = mHiiFont->StringToImage (
1684 mHiiFont,
1685 EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK,
1686 String,
1687 FontInfo,
1688 &Blt,
1689 This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
1690 This->Mode->CursorRow * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1691 &RowInfoArray,
1692 &RowInfoArraySize,
1693 NULL
1694 );
1695
1696 if (!EFI_ERROR (Status)) {
1697 //
1698 // Line breaks are handled by caller of DrawUnicodeWeightAtCursorN, so the updated parameter RowInfoArraySize by StringToImage will
1699 // always be 1 or 0 (if there is no valid Unicode Char can be printed). ASSERT here to make sure.
1700 //
1701 ASSERT (RowInfoArraySize <= 1);
1702
1703 Status = UgaDraw->Blt (
1704 UgaDraw,
1705 (EFI_UGA_PIXEL *) Blt->Image.Bitmap,
1706 EfiUgaBltBufferToVideo,
1707 This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
1708 (This->Mode->CursorRow) * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1709 This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
1710 (This->Mode->CursorRow) * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1711 RowInfoArray[0].LineWidth,
1712 RowInfoArray[0].LineHeight,
1713 Blt->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1714 );
1715 }
1716
1717 FreePool (RowInfoArray);
1718 FreePool (Blt->Image.Bitmap);
1719 } else {
1720 Status = EFI_UNSUPPORTED;
1721 }
1722
1723 if (Blt != NULL) {
1724 FreePool (Blt);
1725 }
1726 if (String != NULL) {
1727 FreePool (String);
1728 }
1729 if (FontInfo != NULL) {
1730 FreePool (FontInfo);
1731 }
1732 return Status;
1733 }
1734
1735 /**
1736 Erase the cursor on the screen.
1737
1738 @param This Protocol instance pointer.
1739
1740 @retval EFI_SUCCESS The cursor is erased successfully.
1741
1742 **/
1743 EFI_STATUS
1744 EraseCursor (
1745 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
1746 )
1747 {
1748 GRAPHICS_CONSOLE_DEV *Private;
1749 EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode;
1750 INTN GlyphX;
1751 INTN GlyphY;
1752 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1753 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1754 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground;
1755 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background;
1756 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[EFI_GLYPH_HEIGHT][EFI_GLYPH_WIDTH];
1757 UINTN PosX;
1758 UINTN PosY;
1759
1760 CurrentMode = This->Mode;
1761
1762 if (!CurrentMode->CursorVisible) {
1763 return EFI_SUCCESS;
1764 }
1765
1766 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1767 GraphicsOutput = Private->GraphicsOutput;
1768 UgaDraw = Private->UgaDraw;
1769
1770 //
1771 // In this driver, only narrow character was supported.
1772 //
1773 //
1774 // Blt a character to the screen
1775 //
1776 GlyphX = (CurrentMode->CursorColumn * EFI_GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX;
1777 GlyphY = (CurrentMode->CursorRow * EFI_GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY;
1778 if (GraphicsOutput != NULL) {
1779 GraphicsOutput->Blt (
1780 GraphicsOutput,
1781 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,
1782 EfiBltVideoToBltBuffer,
1783 GlyphX,
1784 GlyphY,
1785 0,
1786 0,
1787 EFI_GLYPH_WIDTH,
1788 EFI_GLYPH_HEIGHT,
1789 EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1790 );
1791 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1792 UgaDraw->Blt (
1793 UgaDraw,
1794 (EFI_UGA_PIXEL *) (UINTN) BltChar,
1795 EfiUgaVideoToBltBuffer,
1796 GlyphX,
1797 GlyphY,
1798 0,
1799 0,
1800 EFI_GLYPH_WIDTH,
1801 EFI_GLYPH_HEIGHT,
1802 EFI_GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
1803 );
1804 }
1805
1806 GetTextColors (This, &Foreground.Pixel, &Background.Pixel);
1807
1808 //
1809 // Convert Monochrome bitmap of the Glyph to BltBuffer structure
1810 //
1811 for (PosY = 0; PosY < EFI_GLYPH_HEIGHT; PosY++) {
1812 for (PosX = 0; PosX < EFI_GLYPH_WIDTH; PosX++) {
1813 if ((mCursorGlyph.GlyphCol1[PosY] & (BIT0 << PosX)) != 0) {
1814 BltChar[PosY][EFI_GLYPH_WIDTH - PosX - 1].Raw ^= Foreground.Raw;
1815 }
1816 }
1817 }
1818
1819 if (GraphicsOutput != NULL) {
1820 GraphicsOutput->Blt (
1821 GraphicsOutput,
1822 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,
1823 EfiBltBufferToVideo,
1824 0,
1825 0,
1826 GlyphX,
1827 GlyphY,
1828 EFI_GLYPH_WIDTH,
1829 EFI_GLYPH_HEIGHT,
1830 EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1831 );
1832 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1833 UgaDraw->Blt (
1834 UgaDraw,
1835 (EFI_UGA_PIXEL *) (UINTN) BltChar,
1836 EfiUgaBltBufferToVideo,
1837 0,
1838 0,
1839 GlyphX,
1840 GlyphY,
1841 EFI_GLYPH_WIDTH,
1842 EFI_GLYPH_HEIGHT,
1843 EFI_GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
1844 );
1845 }
1846
1847 return EFI_SUCCESS;
1848 }
1849
1850 /**
1851 HII Database Protocol notification event handler.
1852
1853 Register font package when HII Database Protocol has been installed.
1854
1855 @param[in] Event Event whose notification function is being invoked.
1856 @param[in] Context Pointer to the notification function's context.
1857 **/
1858 VOID
1859 EFIAPI
1860 RegisterFontPackage (
1861 IN EFI_EVENT Event,
1862 IN VOID *Context
1863 )
1864 {
1865 EFI_STATUS Status;
1866 EFI_HII_SIMPLE_FONT_PACKAGE_HDR *SimplifiedFont;
1867 UINT32 PackageLength;
1868 UINT8 *Package;
1869 UINT8 *Location;
1870 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
1871
1872 //
1873 // Locate HII Database Protocol
1874 //
1875 Status = gBS->LocateProtocol (
1876 &gEfiHiiDatabaseProtocolGuid,
1877 NULL,
1878 (VOID **) &HiiDatabase
1879 );
1880 ASSERT_EFI_ERROR (Status);
1881
1882 //
1883 // Add 4 bytes to the header for entire length for HiiAddPackages use only.
1884 //
1885 // +--------------------------------+ <-- Package
1886 // | |
1887 // | PackageLength(4 bytes) |
1888 // | |
1889 // |--------------------------------| <-- SimplifiedFont
1890 // | |
1891 // |EFI_HII_SIMPLE_FONT_PACKAGE_HDR |
1892 // | |
1893 // |--------------------------------| <-- Location
1894 // | |
1895 // | gUsStdNarrowGlyphData |
1896 // | |
1897 // +--------------------------------+
1898
1899 PackageLength = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR) + mNarrowFontSize + 4;
1900 Package = AllocateZeroPool (PackageLength);
1901 ASSERT (Package != NULL);
1902
1903 WriteUnaligned32((UINT32 *) Package,PackageLength);
1904 SimplifiedFont = (EFI_HII_SIMPLE_FONT_PACKAGE_HDR *) (Package + 4);
1905 SimplifiedFont->Header.Length = (UINT32) (PackageLength - 4);
1906 SimplifiedFont->Header.Type = EFI_HII_PACKAGE_SIMPLE_FONTS;
1907 SimplifiedFont->NumberOfNarrowGlyphs = (UINT16) (mNarrowFontSize / sizeof (EFI_NARROW_GLYPH));
1908
1909 Location = (UINT8 *) (&SimplifiedFont->NumberOfWideGlyphs + 1);
1910 CopyMem (Location, gUsStdNarrowGlyphData, mNarrowFontSize);
1911
1912 //
1913 // Add this simplified font package to a package list then install it.
1914 //
1915 mHiiHandle = HiiAddPackages (
1916 &mFontPackageListGuid,
1917 NULL,
1918 Package,
1919 NULL
1920 );
1921 ASSERT (mHiiHandle != NULL);
1922 FreePool (Package);
1923 }
1924
1925 /**
1926 The user Entry Point for module GraphicsConsole. The user code starts with this function.
1927
1928 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1929 @param[in] SystemTable A pointer to the EFI System Table.
1930
1931 @retval EFI_SUCCESS The entry point is executed successfully.
1932 @return other Some error occurs when executing this entry point.
1933
1934 **/
1935 EFI_STATUS
1936 EFIAPI
1937 InitializeGraphicsConsole (
1938 IN EFI_HANDLE ImageHandle,
1939 IN EFI_SYSTEM_TABLE *SystemTable
1940 )
1941 {
1942 EFI_STATUS Status;
1943
1944 //
1945 // Register notify function on HII Database Protocol to add font package.
1946 //
1947 EfiCreateProtocolNotifyEvent (
1948 &gEfiHiiDatabaseProtocolGuid,
1949 TPL_CALLBACK,
1950 RegisterFontPackage,
1951 NULL,
1952 &mHiiRegistration
1953 );
1954
1955 //
1956 // Install driver model protocol(s).
1957 //
1958 Status = EfiLibInstallDriverBindingComponentName2 (
1959 ImageHandle,
1960 SystemTable,
1961 &gGraphicsConsoleDriverBinding,
1962 ImageHandle,
1963 &gGraphicsConsoleComponentName,
1964 &gGraphicsConsoleComponentName2
1965 );
1966 ASSERT_EFI_ERROR (Status);
1967
1968 return Status;
1969 }
1970
1971