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