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