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