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