]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.c
d3feef8ee45889cd674ce55cd1d7425cb1abfaa4
[mirror_edk2.git] / EdkModulePkg / Universal / Console / GraphicsConsole / Dxe / 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_OUT_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_OUT_PROTOCOL *This,
34 IN CHAR16 *UnicodeWeight,
35 IN UINTN Count
36 );
37
38 STATIC
39 EFI_STATUS
40 EraseCursor (
41 IN EFI_SIMPLE_TEXT_OUT_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 FreePool (Private->LineBuffer);
511 FreePool (Private);
512 }
513 }
514
515 return Status;
516 }
517
518 EFI_STATUS
519 EFIAPI
520 GraphicsConsoleControllerDriverStop (
521 IN EFI_DRIVER_BINDING_PROTOCOL *This,
522 IN EFI_HANDLE Controller,
523 IN UINTN NumberOfChildren,
524 IN EFI_HANDLE *ChildHandleBuffer
525 )
526 {
527 EFI_STATUS Status;
528 EFI_SIMPLE_TEXT_OUT_PROTOCOL *SimpleTextOutput;
529 GRAPHICS_CONSOLE_DEV *Private;
530
531 Status = gBS->OpenProtocol (
532 Controller,
533 &gEfiSimpleTextOutProtocolGuid,
534 (VOID **) &SimpleTextOutput,
535 This->DriverBindingHandle,
536 Controller,
537 EFI_OPEN_PROTOCOL_GET_PROTOCOL
538 );
539 if (EFI_ERROR (Status)) {
540 return EFI_NOT_STARTED;
541 }
542
543 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);
544
545 Status = gBS->UninstallProtocolInterface (
546 Controller,
547 &gEfiSimpleTextOutProtocolGuid,
548 &Private->SimpleTextOutput
549 );
550
551 if (!EFI_ERROR (Status)) {
552 //
553 // Close the GOP or UGA IO Protocol
554 //
555 if (Private->GraphicsOutput != NULL) {
556 gBS->CloseProtocol (
557 Controller,
558 &gEfiGraphicsOutputProtocolGuid,
559 This->DriverBindingHandle,
560 Controller
561 );
562 } else {
563 gBS->CloseProtocol (
564 Controller,
565 &gEfiUgaDrawProtocolGuid,
566 This->DriverBindingHandle,
567 Controller
568 );
569 }
570
571 //
572 // Remove the font pack
573 //
574 mHii->RemovePack (mHii, Private->HiiHandle);
575
576 //
577 // Free our instance data
578 //
579 if (Private != NULL) {
580 FreePool (Private->LineBuffer);
581 FreePool (Private);
582 }
583 }
584
585 return Status;
586 }
587
588 EFI_STATUS
589 EfiLocateHiiProtocol (
590 VOID
591 )
592 /*++
593
594 Routine Description:
595 Find if the HII protocol is available. If yes, locate the HII protocol
596
597 Arguments:
598
599 Returns:
600
601 --*/
602 {
603 EFI_HANDLE Handle;
604 UINTN Size;
605 EFI_STATUS Status;
606
607 //
608 // There should only be one - so buffer size is this
609 //
610 Size = sizeof (EFI_HANDLE);
611
612 Status = gBS->LocateHandle (
613 ByProtocol,
614 &gEfiHiiProtocolGuid,
615 NULL,
616 &Size,
617 &Handle
618 );
619
620 if (EFI_ERROR (Status)) {
621 return Status;
622 }
623
624 Status = gBS->HandleProtocol (
625 Handle,
626 &gEfiHiiProtocolGuid,
627 (VOID **)&mHii
628 );
629
630 return Status;
631 }
632 //
633 // Body of the STO functions
634 //
635 EFI_STATUS
636 EFIAPI
637 GraphicsConsoleConOutReset (
638 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
639 IN BOOLEAN ExtendedVerification
640 )
641 /*++
642 Routine Description:
643
644 Implements SIMPLE_TEXT_OUTPUT.Reset().
645 If ExtendeVerification is TRUE, then perform dependent Graphics Console
646 device reset, and set display mode to mode 0.
647 If ExtendedVerification is FALSE, only set display mode to mode 0.
648
649 Arguments:
650
651 This - Indicates the calling context.
652
653 ExtendedVerification - Indicates that the driver may perform a more exhaustive
654 verification operation of the device during reset.
655
656 Returns:
657
658 EFI_SUCCESS
659 The reset operation succeeds.
660
661 EFI_DEVICE_ERROR
662 The Graphics Console is not functioning correctly
663
664 --*/
665 {
666 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));
667 return This->SetMode (This, 0);
668 }
669
670 EFI_STATUS
671 EFIAPI
672 GraphicsConsoleConOutOutputString (
673 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
674 IN CHAR16 *WString
675 )
676 /*++
677 Routine Description:
678
679 Implements SIMPLE_TEXT_OUTPUT.OutputString().
680 The Unicode string will be converted to Glyphs and will be
681 sent to the Graphics Console.
682
683
684 Arguments:
685
686 This - Indicates the calling context.
687
688 WString - The Null-terminated Unicode string to be displayed on
689 the Graphics Console.
690
691 Returns:
692
693 EFI_SUCCESS
694 The string is output successfully.
695
696 EFI_DEVICE_ERROR
697 The Graphics Console failed to send the string out.
698
699 EFI_WARN_UNKNOWN_GLYPH
700 Indicates that some of the characters in the Unicode string could not
701 be rendered and are skipped.
702
703 --*/
704 {
705 GRAPHICS_CONSOLE_DEV *Private;
706 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
707 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
708 INTN Mode;
709 UINTN MaxColumn;
710 UINTN MaxRow;
711 UINTN Width;
712 UINTN Height;
713 UINTN Delta;
714 EFI_STATUS Status;
715 BOOLEAN Warning;
716 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
717 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
718 UINTN DeltaX;
719 UINTN DeltaY;
720 UINTN Count;
721 UINTN Index;
722 INT32 OriginAttribute;
723 EFI_TPL OldTpl;
724 CHAR16 SpaceStr[] = { NARROW_CHAR, ' ', 0 };
725
726 Status = EFI_SUCCESS;
727
728 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
729 //
730 // Current mode
731 //
732 Mode = This->Mode->Mode;
733 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
734 GraphicsOutput = Private->GraphicsOutput;
735 UgaDraw = Private->UgaDraw;
736
737 MaxColumn = Private->ModeData[Mode].Columns;
738 MaxRow = Private->ModeData[Mode].Rows;
739 DeltaX = Private->ModeData[Mode].DeltaX;
740 DeltaY = Private->ModeData[Mode].DeltaY;
741 Width = MaxColumn * GLYPH_WIDTH;
742 Height = (MaxRow - 1) * GLYPH_HEIGHT;
743 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
744
745 //
746 // The Attributes won't change when during the time OutputString is called
747 //
748 GetTextColors (This, &Foreground, &Background);
749
750 EraseCursor (This);
751
752 Warning = FALSE;
753
754 //
755 // Backup attribute
756 //
757 OriginAttribute = This->Mode->Attribute;
758
759 while (*WString) {
760
761 if (*WString == CHAR_BACKSPACE) {
762 //
763 // If the cursor is at the left edge of the display, then move the cursor
764 // one row up.
765 //
766 if (This->Mode->CursorColumn == 0 && This->Mode->CursorRow > 0) {
767 This->Mode->CursorRow--;
768 This->Mode->CursorColumn = (INT32) (MaxColumn - 1);
769 This->OutputString (This, SpaceStr);
770 EraseCursor (This);
771 This->Mode->CursorRow--;
772 This->Mode->CursorColumn = (INT32) (MaxColumn - 1);
773 } else if (This->Mode->CursorColumn > 0) {
774 //
775 // If the cursor is not at the left edge of the display, then move the cursor
776 // left one column.
777 //
778 This->Mode->CursorColumn--;
779 This->OutputString (This, SpaceStr);
780 EraseCursor (This);
781 This->Mode->CursorColumn--;
782 }
783
784 WString++;
785
786 } else if (*WString == CHAR_LINEFEED) {
787 //
788 // If the cursor is at the bottom of the display, then scroll the display one
789 // row, and do not update the cursor position. Otherwise, move the cursor
790 // down one row.
791 //
792 if (This->Mode->CursorRow == (INT32) (MaxRow - 1)) {
793 if (GraphicsOutput != NULL) {
794 //
795 // Scroll Screen Up One Row
796 //
797 GraphicsOutput->Blt (
798 GraphicsOutput,
799 NULL,
800 EfiBltVideoToVideo,
801 DeltaX,
802 DeltaY + GLYPH_HEIGHT,
803 DeltaX,
804 DeltaY,
805 Width,
806 Height,
807 Delta
808 );
809
810 //
811 // Print Blank Line at last line
812 //
813 GraphicsOutput->Blt (
814 GraphicsOutput,
815 &Background,
816 EfiBltVideoFill,
817 0,
818 0,
819 DeltaX,
820 DeltaY + Height,
821 Width,
822 GLYPH_HEIGHT,
823 Delta
824 );
825 } else {
826 //
827 // Scroll Screen Up One Row
828 //
829 UgaDraw->Blt (
830 UgaDraw,
831 NULL,
832 EfiUgaVideoToVideo,
833 DeltaX,
834 DeltaY + GLYPH_HEIGHT,
835 DeltaX,
836 DeltaY,
837 Width,
838 Height,
839 Delta
840 );
841
842 //
843 // Print Blank Line at last line
844 //
845 UgaDraw->Blt (
846 UgaDraw,
847 (EFI_UGA_PIXEL *) (UINTN) &Background,
848 EfiUgaVideoFill,
849 0,
850 0,
851 DeltaX,
852 DeltaY + Height,
853 Width,
854 GLYPH_HEIGHT,
855 Delta
856 );
857 }
858 } else {
859 This->Mode->CursorRow++;
860 }
861
862 WString++;
863
864 } else if (*WString == CHAR_CARRIAGE_RETURN) {
865 //
866 // Move the cursor to the beginning of the current row.
867 //
868 This->Mode->CursorColumn = 0;
869 WString++;
870
871 } else if (*WString == WIDE_CHAR) {
872
873 This->Mode->Attribute |= EFI_WIDE_ATTRIBUTE;
874 WString++;
875
876 } else if (*WString == NARROW_CHAR) {
877
878 This->Mode->Attribute &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
879 WString++;
880
881 } else {
882 //
883 // Print the character at the current cursor position and move the cursor
884 // right one column. If this moves the cursor past the right edge of the
885 // display, then the line should wrap to the beginning of the next line. This
886 // is equivalent to inserting a CR and an LF. Note that if the cursor is at the
887 // bottom of the display, and the line wraps, then the display will be scrolled
888 // one line.
889 // If wide char is going to be displayed, need to display one character at a time
890 // Or, need to know the display length of a certain string.
891 //
892 // Index is used to determine how many character width units (wide = 2, narrow = 1)
893 // Count is used to determine how many characters are used regardless of their attributes
894 //
895 for (Count = 0, Index = 0; (This->Mode->CursorColumn + Index) < MaxColumn; Count++, Index++) {
896 if (WString[Count] == CHAR_NULL) {
897 break;
898 }
899
900 if (WString[Count] == CHAR_BACKSPACE) {
901 break;
902 }
903
904 if (WString[Count] == CHAR_LINEFEED) {
905 break;
906 }
907
908 if (WString[Count] == CHAR_CARRIAGE_RETURN) {
909 break;
910 }
911
912 if (WString[Count] == WIDE_CHAR) {
913 break;
914 }
915
916 if (WString[Count] == NARROW_CHAR) {
917 break;
918 }
919 //
920 // Is the wide attribute on?
921 //
922 if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) {
923 //
924 // If wide, add one more width unit than normal since we are going to increment at the end of the for loop
925 //
926 Index++;
927 //
928 // This is the end-case where if we are at column 79 and about to print a wide character
929 // We should prevent this from happening because we will wrap inappropriately. We should
930 // not print this character until the next line.
931 //
932 if ((This->Mode->CursorColumn + Index + 1) > MaxColumn) {
933 Index++;
934 break;
935 }
936 }
937 }
938
939 Status = DrawUnicodeWeightAtCursorN (This, WString, Count);
940 if (EFI_ERROR (Status)) {
941 Warning = TRUE;
942 }
943 //
944 // At the end of line, output carriage return and line feed
945 //
946 WString += Count;
947 This->Mode->CursorColumn += (INT32) Index;
948 if (This->Mode->CursorColumn > (INT32) MaxColumn) {
949 This->Mode->CursorColumn -= 2;
950 This->OutputString (This, SpaceStr);
951 }
952
953 if (This->Mode->CursorColumn >= (INT32) MaxColumn) {
954 EraseCursor (This);
955 This->OutputString (This, mCrLfString);
956 EraseCursor (This);
957 }
958 }
959 }
960
961 This->Mode->Attribute = OriginAttribute;
962
963 EraseCursor (This);
964
965 if (Warning) {
966 Status = EFI_WARN_UNKNOWN_GLYPH;
967 }
968
969 gBS->RestoreTPL (OldTpl);
970 return Status;
971
972 }
973
974 EFI_STATUS
975 EFIAPI
976 GraphicsConsoleConOutTestString (
977 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
978 IN CHAR16 *WString
979 )
980 /*++
981 Routine Description:
982
983 Implements SIMPLE_TEXT_OUTPUT.TestString().
984 If one of the characters in the *Wstring is
985 neither valid valid Unicode drawing characters,
986 not ASCII code, then this function will return
987 EFI_UNSUPPORTED.
988
989
990 Arguments:
991
992 This - Indicates the calling context.
993
994 WString - The Null-terminated Unicode string to be tested.
995
996 Returns:
997
998 EFI_SUCCESS
999 The Graphics Console is capable of rendering the output string.
1000
1001 EFI_UNSUPPORTED
1002 Some of the characters in the Unicode string cannot be rendered.
1003
1004 --*/
1005 {
1006 EFI_STATUS Status;
1007 UINT16 GlyphWidth;
1008 UINT32 GlyphStatus;
1009 UINT16 Count;
1010 GLYPH_UNION *Glyph;
1011
1012 GlyphStatus = 0;
1013 Count = 0;
1014
1015 while (WString[Count]) {
1016 Status = mHii->GetGlyph (
1017 mHii,
1018 WString,
1019 &Count,
1020 (UINT8 **) &Glyph,
1021 &GlyphWidth,
1022 &GlyphStatus
1023 );
1024
1025 if (EFI_ERROR (Status)) {
1026 return EFI_UNSUPPORTED;
1027 }
1028 }
1029
1030 return EFI_SUCCESS;
1031 }
1032
1033 EFI_STATUS
1034 EFIAPI
1035 GraphicsConsoleConOutQueryMode (
1036 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
1037 IN UINTN ModeNumber,
1038 OUT UINTN *Columns,
1039 OUT UINTN *Rows
1040 )
1041 /*++
1042 Routine Description:
1043
1044 Implements SIMPLE_TEXT_OUTPUT.QueryMode().
1045 It returnes information for an available text mode
1046 that the Graphics Console supports.
1047 In this driver,we only support text mode 80x25, which is
1048 defined as mode 0.
1049
1050
1051 Arguments:
1052
1053 This - Indicates the calling context.
1054
1055 ModeNumber - The mode number to return information on.
1056
1057 Columns - The returned columns of the requested mode.
1058
1059 Rows - The returned rows of the requested mode.
1060
1061 Returns:
1062
1063 EFI_SUCCESS
1064 The requested mode information is returned.
1065
1066 EFI_UNSUPPORTED
1067 The mode number is not valid.
1068
1069 --*/
1070 {
1071 GRAPHICS_CONSOLE_DEV *Private;
1072 EFI_STATUS Status;
1073 EFI_TPL OldTpl;
1074
1075 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
1076 return EFI_UNSUPPORTED;
1077 }
1078
1079 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
1080 Status = EFI_SUCCESS;
1081
1082 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1083
1084 *Columns = Private->ModeData[ModeNumber].Columns;
1085 *Rows = Private->ModeData[ModeNumber].Rows;
1086
1087 if (*Columns <= 0 && *Rows <= 0) {
1088 Status = EFI_UNSUPPORTED;
1089 goto Done;
1090
1091 }
1092
1093 Done:
1094 gBS->RestoreTPL (OldTpl);
1095 return Status;
1096 }
1097
1098 EFI_STATUS
1099 EFIAPI
1100 GraphicsConsoleConOutSetMode (
1101 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
1102 IN UINTN ModeNumber
1103 )
1104 /*++
1105 Routine Description:
1106
1107 Implements SIMPLE_TEXT_OUTPUT.SetMode().
1108 Set the Graphics Console to a specified mode.
1109 In this driver, we only support mode 0.
1110
1111 Arguments:
1112
1113 This - Indicates the calling context.
1114
1115 ModeNumber - The text mode to set.
1116
1117 Returns:
1118
1119 EFI_SUCCESS
1120 The requested text mode is set.
1121
1122 EFI_DEVICE_ERROR
1123 The requested text mode cannot be set because of Graphics Console device error.
1124
1125 EFI_UNSUPPORTED
1126 The text mode number is not valid.
1127
1128 --*/
1129 {
1130 EFI_STATUS Status;
1131 GRAPHICS_CONSOLE_DEV *Private;
1132 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1133 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewLineBuffer;
1134 UINT32 HorizontalResolution;
1135 UINT32 VerticalResolution;
1136 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1137 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1138 UINT32 ColorDepth;
1139 UINT32 RefreshRate;
1140 EFI_TPL OldTpl;
1141
1142 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
1143
1144 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1145 GraphicsOutput = Private->GraphicsOutput;
1146 UgaDraw = Private->UgaDraw;
1147 ModeData = &(Private->ModeData[ModeNumber]);
1148
1149 if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {
1150 Status = EFI_UNSUPPORTED;
1151 goto Done;
1152 }
1153
1154 //
1155 // Make sure the requested mode number is supported
1156 //
1157 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
1158 Status = EFI_UNSUPPORTED;
1159 goto Done;
1160 }
1161
1162 if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {
1163 Status = EFI_UNSUPPORTED;
1164 goto Done;
1165 }
1166 //
1167 // Attempt to allocate a line buffer for the requested mode number
1168 //
1169 NewLineBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->Columns * GLYPH_WIDTH * GLYPH_HEIGHT);
1170
1171 if (NewLineBuffer == NULL) {
1172 //
1173 // The new line buffer could not be allocated, so return an error.
1174 // No changes to the state of the current console have been made, so the current console is still valid
1175 //
1176 Status = EFI_OUT_OF_RESOURCES;
1177 goto Done;
1178 }
1179 //
1180 // If the mode has been set at least one other time, then LineBuffer will not be NULL
1181 //
1182 if (Private->LineBuffer != NULL) {
1183 //
1184 // Clear the current text window on the current graphics console
1185 //
1186 This->ClearScreen (This);
1187
1188 //
1189 // If the new mode is the same as the old mode, then just return EFI_SUCCESS
1190 //
1191 if ((INT32) ModeNumber == This->Mode->Mode) {
1192 FreePool (NewLineBuffer);
1193 Status = EFI_SUCCESS;
1194 goto Done;
1195 }
1196 //
1197 // Otherwise, the size of the text console and/or the UGA mode will be changed,
1198 // so turn off the cursor, and free the LineBuffer for the current mode
1199 //
1200 This->EnableCursor (This, FALSE);
1201
1202 FreePool (Private->LineBuffer);
1203 }
1204 //
1205 // Assign the current line buffer to the newly allocated line buffer
1206 //
1207 Private->LineBuffer = NewLineBuffer;
1208
1209 if (GraphicsOutput != NULL) {
1210 if (ModeData->GopModeNumber != GraphicsOutput->Mode->Mode) {
1211 //
1212 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1213 //
1214 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeData->GopModeNumber);
1215 if (EFI_ERROR (Status)) {
1216 //
1217 // The mode set operation failed
1218 //
1219 goto Done;
1220 }
1221 } else {
1222 //
1223 // The current graphics mode is correct, so simply clear the entire display
1224 //
1225 Status = GraphicsOutput->Blt (
1226 GraphicsOutput,
1227 &mEfiColors[0],
1228 EfiBltVideoFill,
1229 0,
1230 0,
1231 0,
1232 0,
1233 ModeData->GopWidth,
1234 ModeData->GopHeight,
1235 0
1236 );
1237 }
1238 } else {
1239 //
1240 // Get the current UGA Draw mode information
1241 //
1242 Status = UgaDraw->GetMode (
1243 UgaDraw,
1244 &HorizontalResolution,
1245 &VerticalResolution,
1246 &ColorDepth,
1247 &RefreshRate
1248 );
1249 if (EFI_ERROR (Status) || HorizontalResolution != ModeData->GopWidth || VerticalResolution != ModeData->GopHeight) {
1250 //
1251 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1252 //
1253 Status = UgaDraw->SetMode (
1254 UgaDraw,
1255 ModeData->GopWidth,
1256 ModeData->GopHeight,
1257 32,
1258 60
1259 );
1260 if (EFI_ERROR (Status)) {
1261 //
1262 // The mode set operation failed
1263 //
1264 goto Done;
1265 }
1266 } else {
1267 //
1268 // The current graphics mode is correct, so simply clear the entire display
1269 //
1270 Status = UgaDraw->Blt (
1271 UgaDraw,
1272 (EFI_UGA_PIXEL *) (UINTN) &mEfiColors[0],
1273 EfiUgaVideoFill,
1274 0,
1275 0,
1276 0,
1277 0,
1278 ModeData->GopWidth,
1279 ModeData->GopHeight,
1280 0
1281 );
1282 }
1283 }
1284
1285 //
1286 // The new mode is valid, so commit the mode change
1287 //
1288 This->Mode->Mode = (INT32) ModeNumber;
1289
1290 //
1291 // Move the text cursor to the upper left hand corner of the displat and enable it
1292 //
1293 This->SetCursorPosition (This, 0, 0);
1294 This->EnableCursor (This, TRUE);
1295
1296 Status = EFI_SUCCESS;
1297
1298 Done:
1299 gBS->RestoreTPL (OldTpl);
1300 return Status;
1301 }
1302
1303 EFI_STATUS
1304 EFIAPI
1305 GraphicsConsoleConOutSetAttribute (
1306 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
1307 IN UINTN Attribute
1308 )
1309 /*++
1310 Routine Description:
1311
1312 Implements SIMPLE_TEXT_OUTPUT.SetAttribute().
1313
1314 Arguments:
1315
1316 This - Indicates the calling context.
1317
1318 Attrubute - The attribute to set. Only bit0..6 are valid, all other bits
1319 are undefined and must be zero.
1320
1321 Returns:
1322
1323 EFI_SUCCESS
1324 The requested attribute is set.
1325
1326 EFI_DEVICE_ERROR
1327 The requested attribute cannot be set due to Graphics Console port error.
1328
1329 EFI_UNSUPPORTED
1330 The attribute requested is not defined by EFI spec.
1331
1332 --*/
1333 {
1334 EFI_TPL OldTpl;
1335
1336 if ((Attribute | 0xFF) != 0xFF) {
1337 return EFI_UNSUPPORTED;
1338 }
1339
1340 if ((INT32) Attribute == This->Mode->Attribute) {
1341 return EFI_SUCCESS;
1342 }
1343
1344 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
1345
1346 EraseCursor (This);
1347
1348 This->Mode->Attribute = (INT32) Attribute;
1349
1350 EraseCursor (This);
1351
1352 gBS->RestoreTPL (OldTpl);
1353
1354 return EFI_SUCCESS;
1355 }
1356
1357 EFI_STATUS
1358 EFIAPI
1359 GraphicsConsoleConOutClearScreen (
1360 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This
1361 )
1362 /*++
1363 Routine Description:
1364
1365 Implements SIMPLE_TEXT_OUTPUT.ClearScreen().
1366 It clears the Graphics Console's display to the
1367 currently selected background color.
1368
1369
1370 Arguments:
1371
1372 This - Indicates the calling context.
1373
1374 Returns:
1375
1376 EFI_SUCCESS
1377 The operation completed successfully.
1378
1379 EFI_DEVICE_ERROR
1380 The Graphics Console cannot be cleared due to Graphics Console device error.
1381
1382 EFI_UNSUPPORTED
1383 The Graphics Console is not in a valid text mode.
1384
1385 --*/
1386 {
1387 EFI_STATUS Status;
1388 GRAPHICS_CONSOLE_DEV *Private;
1389 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1390 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1391 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1392 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
1393 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1394 EFI_TPL OldTpl;
1395
1396 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
1397
1398 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1399 GraphicsOutput = Private->GraphicsOutput;
1400 UgaDraw = Private->UgaDraw;
1401 ModeData = &(Private->ModeData[This->Mode->Mode]);
1402
1403 GetTextColors (This, &Foreground, &Background);
1404 if (GraphicsOutput != NULL) {
1405 Status = GraphicsOutput->Blt (
1406 GraphicsOutput,
1407 &Background,
1408 EfiBltVideoFill,
1409 0,
1410 0,
1411 0,
1412 0,
1413 ModeData->GopWidth,
1414 ModeData->GopHeight,
1415 0
1416 );
1417 } else {
1418 Status = UgaDraw->Blt (
1419 UgaDraw,
1420 (EFI_UGA_PIXEL *) (UINTN) &Background,
1421 EfiUgaVideoFill,
1422 0,
1423 0,
1424 0,
1425 0,
1426 ModeData->GopWidth,
1427 ModeData->GopHeight,
1428 0
1429 );
1430 }
1431
1432 This->Mode->CursorColumn = 0;
1433 This->Mode->CursorRow = 0;
1434
1435 EraseCursor (This);
1436
1437 gBS->RestoreTPL (OldTpl);
1438
1439 return Status;
1440 }
1441
1442 EFI_STATUS
1443 EFIAPI
1444 GraphicsConsoleConOutSetCursorPosition (
1445 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
1446 IN UINTN Column,
1447 IN UINTN Row
1448 )
1449 /*++
1450 Routine Description:
1451
1452 Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().
1453
1454 Arguments:
1455
1456 This - Indicates the calling context.
1457
1458 Column - The row to set cursor to.
1459
1460 Row - The column to set cursor to.
1461
1462 Returns:
1463
1464 EFI_SUCCESS
1465 The operation completed successfully.
1466
1467 EFI_DEVICE_ERROR
1468 The request fails due to Graphics Console device error.
1469
1470 EFI_UNSUPPORTED
1471 The Graphics Console is not in a valid text mode, or the cursor position
1472 is invalid for current mode.
1473
1474 --*/
1475 {
1476 GRAPHICS_CONSOLE_DEV *Private;
1477 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1478 EFI_STATUS Status;
1479 EFI_TPL OldTpl;
1480
1481 Status = EFI_SUCCESS;
1482
1483 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
1484
1485 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1486 ModeData = &(Private->ModeData[This->Mode->Mode]);
1487
1488 if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) {
1489 Status = EFI_UNSUPPORTED;
1490 goto Done;
1491 }
1492
1493 if (((INT32) Column == This->Mode->CursorColumn) && ((INT32) Row == This->Mode->CursorRow)) {
1494 Status = EFI_SUCCESS;
1495 goto Done;
1496 }
1497
1498 EraseCursor (This);
1499
1500 This->Mode->CursorColumn = (INT32) Column;
1501 This->Mode->CursorRow = (INT32) Row;
1502
1503 EraseCursor (This);
1504
1505 Done:
1506 gBS->RestoreTPL (OldTpl);
1507
1508 return Status;
1509 }
1510
1511 EFI_STATUS
1512 EFIAPI
1513 GraphicsConsoleConOutEnableCursor (
1514 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
1515 IN BOOLEAN Visible
1516 )
1517 /*++
1518 Routine Description:
1519
1520 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1521 In this driver, the cursor cannot be hidden.
1522
1523 Arguments:
1524
1525 This - Indicates the calling context.
1526
1527 Visible - If TRUE, the cursor is set to be visible,
1528 If FALSE, the cursor is set to be invisible.
1529
1530 Returns:
1531
1532 EFI_SUCCESS
1533 The request is valid.
1534
1535 EFI_UNSUPPORTED
1536 The Graphics Console does not support a hidden cursor.
1537
1538 --*/
1539 {
1540 EFI_TPL OldTpl;
1541
1542 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
1543
1544 EraseCursor (This);
1545
1546 This->Mode->CursorVisible = Visible;
1547
1548 EraseCursor (This);
1549
1550 gBS->RestoreTPL (OldTpl);
1551 return EFI_SUCCESS;
1552 }
1553
1554 STATIC
1555 EFI_STATUS
1556 GetTextColors (
1557 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
1558 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
1559 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background
1560 )
1561 {
1562 INTN Attribute;
1563
1564 Attribute = This->Mode->Attribute & 0x7F;
1565
1566 *Foreground = mEfiColors[Attribute & 0x0f];
1567 *Background = mEfiColors[Attribute >> 4];
1568
1569 return EFI_SUCCESS;
1570 }
1571
1572 STATIC
1573 EFI_STATUS
1574 DrawUnicodeWeightAtCursorN (
1575 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
1576 IN CHAR16 *UnicodeWeight,
1577 IN UINTN Count
1578 )
1579 {
1580 GRAPHICS_CONSOLE_DEV *Private;
1581 EFI_STATUS Status;
1582 EFI_STATUS ReturnStatus;
1583 GLYPH_UNION *Glyph;
1584 GLYPH_UNION GlyphData;
1585 INTN GlyphX;
1586 INTN GlyphY;
1587 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1588 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1589 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
1590 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1591 UINTN Index;
1592 UINTN ArrayIndex;
1593 UINTN Counts;
1594 UINT16 GlyphWidth;
1595 UINT32 GlyphStatus;
1596
1597 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1598
1599 ReturnStatus = EFI_SUCCESS;
1600 GlyphStatus = 0;
1601 GlyphWidth = 0x08;
1602
1603 GetTextColors (This, &Foreground, &Background);
1604
1605 Index = 0;
1606 ArrayIndex = 0;
1607 while (Index < Count) {
1608 if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) {
1609 GlyphStatus = WIDE_CHAR;
1610 } else {
1611 GlyphStatus = NARROW_CHAR;
1612 }
1613
1614 Status = mHii->GetGlyph (
1615 mHii,
1616 UnicodeWeight,
1617 (UINT16 *) &Index,
1618 (UINT8 **) &Glyph,
1619 &GlyphWidth,
1620 &GlyphStatus
1621 );
1622 if (EFI_ERROR (Status)) {
1623 ReturnStatus = Status;
1624 }
1625
1626 Counts = 0;
1627
1628 CopyMem (&GlyphData, Glyph, sizeof (GLYPH_UNION));
1629
1630 do {
1631 //
1632 // We are creating the second half of the wide character's BLT buffer
1633 //
1634 if (GlyphWidth == 0x10 && Counts == 1) {
1635 CopyMem (&GlyphData.NarrowGlyph.GlyphCol1, &Glyph->WideGlyph.GlyphCol2, sizeof (Glyph->WideGlyph.GlyphCol2));
1636 }
1637
1638 Counts++;
1639
1640 if (GlyphWidth == 0x10) {
1641 mHii->GlyphToBlt (
1642 mHii,
1643 (UINT8 *) &GlyphData,
1644 Foreground,
1645 Background,
1646 Count * 2,
1647 GLYPH_WIDTH,
1648 GLYPH_HEIGHT,
1649 &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH]
1650 );
1651 } else {
1652 mHii->GlyphToBlt (
1653 mHii,
1654 (UINT8 *) &GlyphData,
1655 Foreground,
1656 Background,
1657 Count,
1658 GLYPH_WIDTH,
1659 GLYPH_HEIGHT,
1660 &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH]
1661 );
1662 }
1663
1664 ArrayIndex++;
1665
1666 } while (Counts < 2 && GlyphWidth == 0x10);
1667
1668 }
1669 //
1670 // If we are printing Wide characters, treat the BLT as if it is twice as many characters
1671 //
1672 if (GlyphWidth == 0x10) {
1673 Count = Count * 2;
1674 }
1675 //
1676 // Blt a character to the screen
1677 //
1678 GlyphX = This->Mode->CursorColumn * GLYPH_WIDTH;
1679 GlyphY = This->Mode->CursorRow * GLYPH_HEIGHT;
1680 GraphicsOutput = Private->GraphicsOutput;
1681 UgaDraw = Private->UgaDraw;
1682 if (GraphicsOutput != NULL) {
1683 GraphicsOutput->Blt (
1684 GraphicsOutput,
1685 Private->LineBuffer,
1686 EfiBltBufferToVideo,
1687 0,
1688 0,
1689 GlyphX + Private->ModeData[This->Mode->Mode].DeltaX,
1690 GlyphY + Private->ModeData[This->Mode->Mode].DeltaY,
1691 GLYPH_WIDTH * Count,
1692 GLYPH_HEIGHT,
1693 GLYPH_WIDTH * Count * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1694 );
1695 } else {
1696 UgaDraw->Blt (
1697 UgaDraw,
1698 (EFI_UGA_PIXEL *) (UINTN) Private->LineBuffer,
1699 EfiUgaBltBufferToVideo,
1700 0,
1701 0,
1702 GlyphX + Private->ModeData[This->Mode->Mode].DeltaX,
1703 GlyphY + Private->ModeData[This->Mode->Mode].DeltaY,
1704 GLYPH_WIDTH * Count,
1705 GLYPH_HEIGHT,
1706 GLYPH_WIDTH * Count * sizeof (EFI_UGA_PIXEL)
1707 );
1708 }
1709
1710 return ReturnStatus;
1711 }
1712
1713 STATIC
1714 EFI_STATUS
1715 EraseCursor (
1716 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This
1717 )
1718 {
1719 GRAPHICS_CONSOLE_DEV *Private;
1720 EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode;
1721 INTN GlyphX;
1722 INTN GlyphY;
1723 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1724 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1725 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground;
1726 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background;
1727 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[GLYPH_HEIGHT][GLYPH_WIDTH];
1728 UINTN X;
1729 UINTN Y;
1730
1731 CurrentMode = This->Mode;
1732
1733 if (!CurrentMode->CursorVisible) {
1734 return EFI_SUCCESS;
1735 }
1736
1737 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1738 GraphicsOutput = Private->GraphicsOutput;
1739 UgaDraw = Private->UgaDraw;
1740
1741 //
1742 // BUGBUG - we need to think about what to do with wide and narrow character deletions.
1743 //
1744 //
1745 // Blt a character to the screen
1746 //
1747 GlyphX = (CurrentMode->CursorColumn * GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX;
1748 GlyphY = (CurrentMode->CursorRow * GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY;
1749 if (GraphicsOutput != NULL) {
1750 GraphicsOutput->Blt (
1751 GraphicsOutput,
1752 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,
1753 EfiBltVideoToBltBuffer,
1754 GlyphX,
1755 GlyphY,
1756 0,
1757 0,
1758 GLYPH_WIDTH,
1759 GLYPH_HEIGHT,
1760 GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1761 );
1762 } else {
1763 UgaDraw->Blt (
1764 UgaDraw,
1765 (EFI_UGA_PIXEL *) (UINTN) BltChar,
1766 EfiUgaVideoToBltBuffer,
1767 GlyphX,
1768 GlyphY,
1769 0,
1770 0,
1771 GLYPH_WIDTH,
1772 GLYPH_HEIGHT,
1773 GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
1774 );
1775 }
1776
1777 GetTextColors (This, &Foreground.Pixel, &Background.Pixel);
1778
1779 //
1780 // Convert Monochrome bitmap of the Glyph to BltBuffer structure
1781 //
1782 for (Y = 0; Y < GLYPH_HEIGHT; Y++) {
1783 for (X = 0; X < GLYPH_WIDTH; X++) {
1784 if ((mCursorGlyph.GlyphCol1[Y] & (1 << X)) != 0) {
1785 BltChar[Y][GLYPH_WIDTH - X - 1].Raw ^= Foreground.Raw;
1786 }
1787 }
1788 }
1789
1790 if (GraphicsOutput != NULL) {
1791 GraphicsOutput->Blt (
1792 GraphicsOutput,
1793 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,
1794 EfiBltBufferToVideo,
1795 0,
1796 0,
1797 GlyphX,
1798 GlyphY,
1799 GLYPH_WIDTH,
1800 GLYPH_HEIGHT,
1801 GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1802 );
1803 } else {
1804 UgaDraw->Blt (
1805 UgaDraw,
1806 (EFI_UGA_PIXEL *) (UINTN) BltChar,
1807 EfiUgaBltBufferToVideo,
1808 0,
1809 0,
1810 GlyphX,
1811 GlyphY,
1812 GLYPH_WIDTH,
1813 GLYPH_HEIGHT,
1814 GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
1815 );
1816 }
1817
1818 return EFI_SUCCESS;
1819 }