]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
0f83803a3793c16213af4ca28dabc1b3f15d2e7d
[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 UGA mode will be changed,
1284 // so turn off the cursor, and free the LineBuffer for the current mode
1285 //
1286 This->EnableCursor (This, FALSE);
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 This->EnableCursor (This, TRUE);
1381
1382 Status = EFI_SUCCESS;
1383
1384 Done:
1385 gBS->RestoreTPL (OldTpl);
1386 return Status;
1387 }
1388
1389 EFI_STATUS
1390 EFIAPI
1391 GraphicsConsoleConOutSetAttribute (
1392 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1393 IN UINTN Attribute
1394 )
1395 /*++
1396 Routine Description:
1397
1398 Implements SIMPLE_TEXT_OUTPUT.SetAttribute().
1399
1400 Arguments:
1401
1402 This - Indicates the calling context.
1403
1404 Attrubute - The attribute to set. Only bit0..6 are valid, all other bits
1405 are undefined and must be zero.
1406
1407 Returns:
1408
1409 EFI_SUCCESS
1410 The requested attribute is set.
1411
1412 EFI_DEVICE_ERROR
1413 The requested attribute cannot be set due to Graphics Console port error.
1414
1415 EFI_UNSUPPORTED
1416 The attribute requested is not defined by EFI spec.
1417
1418 --*/
1419 {
1420 EFI_TPL OldTpl;
1421
1422 if ((Attribute | 0xFF) != 0xFF) {
1423 return EFI_UNSUPPORTED;
1424 }
1425
1426 if ((INT32) Attribute == This->Mode->Attribute) {
1427 return EFI_SUCCESS;
1428 }
1429
1430 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1431
1432 EraseCursor (This);
1433
1434 This->Mode->Attribute = (INT32) Attribute;
1435
1436 EraseCursor (This);
1437
1438 gBS->RestoreTPL (OldTpl);
1439
1440 return EFI_SUCCESS;
1441 }
1442
1443 EFI_STATUS
1444 EFIAPI
1445 GraphicsConsoleConOutClearScreen (
1446 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
1447 )
1448 /*++
1449 Routine Description:
1450
1451 Implements SIMPLE_TEXT_OUTPUT.ClearScreen().
1452 It clears the Graphics Console's display to the
1453 currently selected background color.
1454
1455
1456 Arguments:
1457
1458 This - Indicates the calling context.
1459
1460 Returns:
1461
1462 EFI_SUCCESS
1463 The operation completed successfully.
1464
1465 EFI_DEVICE_ERROR
1466 The Graphics Console cannot be cleared due to Graphics Console device error.
1467
1468 EFI_UNSUPPORTED
1469 The Graphics Console is not in a valid text mode.
1470
1471 --*/
1472 {
1473 EFI_STATUS Status;
1474 GRAPHICS_CONSOLE_DEV *Private;
1475 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1476 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1477 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1478 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
1479 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1480 EFI_TPL OldTpl;
1481
1482 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1483
1484 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1485 GraphicsOutput = Private->GraphicsOutput;
1486 UgaDraw = Private->UgaDraw;
1487 ModeData = &(Private->ModeData[This->Mode->Mode]);
1488
1489 GetTextColors (This, &Foreground, &Background);
1490 if (GraphicsOutput != NULL) {
1491 Status = GraphicsOutput->Blt (
1492 GraphicsOutput,
1493 &Background,
1494 EfiBltVideoFill,
1495 0,
1496 0,
1497 0,
1498 0,
1499 ModeData->GopWidth,
1500 ModeData->GopHeight,
1501 0
1502 );
1503 } else {
1504 Status = UgaDraw->Blt (
1505 UgaDraw,
1506 (EFI_UGA_PIXEL *) (UINTN) &Background,
1507 EfiUgaVideoFill,
1508 0,
1509 0,
1510 0,
1511 0,
1512 ModeData->GopWidth,
1513 ModeData->GopHeight,
1514 0
1515 );
1516 }
1517
1518 This->Mode->CursorColumn = 0;
1519 This->Mode->CursorRow = 0;
1520
1521 EraseCursor (This);
1522
1523 gBS->RestoreTPL (OldTpl);
1524
1525 return Status;
1526 }
1527
1528 EFI_STATUS
1529 EFIAPI
1530 GraphicsConsoleConOutSetCursorPosition (
1531 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1532 IN UINTN Column,
1533 IN UINTN Row
1534 )
1535 /*++
1536 Routine Description:
1537
1538 Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().
1539
1540 Arguments:
1541
1542 This - Indicates the calling context.
1543
1544 Column - The row to set cursor to.
1545
1546 Row - The column to set cursor to.
1547
1548 Returns:
1549
1550 EFI_SUCCESS
1551 The operation completed successfully.
1552
1553 EFI_DEVICE_ERROR
1554 The request fails due to Graphics Console device error.
1555
1556 EFI_UNSUPPORTED
1557 The Graphics Console is not in a valid text mode, or the cursor position
1558 is invalid for current mode.
1559
1560 --*/
1561 {
1562 GRAPHICS_CONSOLE_DEV *Private;
1563 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1564 EFI_STATUS Status;
1565 EFI_TPL OldTpl;
1566
1567 Status = EFI_SUCCESS;
1568
1569 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1570
1571 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1572 ModeData = &(Private->ModeData[This->Mode->Mode]);
1573
1574 if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) {
1575 Status = EFI_UNSUPPORTED;
1576 goto Done;
1577 }
1578
1579 if (((INT32) Column == This->Mode->CursorColumn) && ((INT32) Row == This->Mode->CursorRow)) {
1580 Status = EFI_SUCCESS;
1581 goto Done;
1582 }
1583
1584 EraseCursor (This);
1585
1586 This->Mode->CursorColumn = (INT32) Column;
1587 This->Mode->CursorRow = (INT32) Row;
1588
1589 EraseCursor (This);
1590
1591 Done:
1592 gBS->RestoreTPL (OldTpl);
1593
1594 return Status;
1595 }
1596
1597 EFI_STATUS
1598 EFIAPI
1599 GraphicsConsoleConOutEnableCursor (
1600 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1601 IN BOOLEAN Visible
1602 )
1603 /*++
1604 Routine Description:
1605
1606 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1607 In this driver, the cursor cannot be hidden.
1608
1609 Arguments:
1610
1611 This - Indicates the calling context.
1612
1613 Visible - If TRUE, the cursor is set to be visible,
1614 If FALSE, the cursor is set to be invisible.
1615
1616 Returns:
1617
1618 EFI_SUCCESS
1619 The request is valid.
1620
1621 EFI_UNSUPPORTED
1622 The Graphics Console does not support a hidden cursor.
1623
1624 --*/
1625 {
1626 EFI_TPL OldTpl;
1627
1628 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1629
1630 EraseCursor (This);
1631
1632 This->Mode->CursorVisible = Visible;
1633
1634 EraseCursor (This);
1635
1636 gBS->RestoreTPL (OldTpl);
1637 return EFI_SUCCESS;
1638 }
1639
1640 STATIC
1641 EFI_STATUS
1642 GetTextColors (
1643 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1644 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
1645 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background
1646 )
1647 {
1648 INTN Attribute;
1649
1650 Attribute = This->Mode->Attribute & 0x7F;
1651
1652 *Foreground = mEfiColors[Attribute & 0x0f];
1653 *Background = mEfiColors[Attribute >> 4];
1654
1655 return EFI_SUCCESS;
1656 }
1657
1658 STATIC
1659 EFI_STATUS
1660 DrawUnicodeWeightAtCursorN (
1661 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1662 IN CHAR16 *UnicodeWeight,
1663 IN UINTN Count
1664 )
1665 {
1666 GRAPHICS_CONSOLE_DEV *Private;
1667 EFI_STATUS Status;
1668 EFI_STATUS ReturnStatus;
1669 GLYPH_UNION *Glyph;
1670 GLYPH_UNION GlyphData;
1671 INTN GlyphX;
1672 INTN GlyphY;
1673 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1674 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1675 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
1676 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1677 UINTN Index;
1678 UINTN ArrayIndex;
1679 UINTN Counts;
1680 UINT16 GlyphWidth;
1681 UINT32 GlyphStatus;
1682
1683 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1684
1685 ReturnStatus = EFI_SUCCESS;
1686 GlyphStatus = 0;
1687 GlyphWidth = 0x08;
1688
1689 GetTextColors (This, &Foreground, &Background);
1690
1691 Index = 0;
1692 ArrayIndex = 0;
1693 while (Index < Count) {
1694 if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) {
1695 GlyphStatus = WIDE_CHAR;
1696 } else {
1697 GlyphStatus = NARROW_CHAR;
1698 }
1699
1700 Status = mHii->GetGlyph (
1701 mHii,
1702 UnicodeWeight,
1703 (UINT16 *) &Index,
1704 (UINT8 **) &Glyph,
1705 &GlyphWidth,
1706 &GlyphStatus
1707 );
1708 if (EFI_ERROR (Status)) {
1709 ReturnStatus = Status;
1710 }
1711
1712 Counts = 0;
1713
1714 CopyMem (&GlyphData, Glyph, sizeof (GLYPH_UNION));
1715
1716 do {
1717 //
1718 // We are creating the second half of the wide character's BLT buffer
1719 //
1720 if (GlyphWidth == 0x10 && Counts == 1) {
1721 CopyMem (&GlyphData.NarrowGlyph.GlyphCol1, &Glyph->WideGlyph.GlyphCol2, sizeof (Glyph->WideGlyph.GlyphCol2));
1722 }
1723
1724 Counts++;
1725
1726 if (GlyphWidth == 0x10) {
1727 mHii->GlyphToBlt (
1728 mHii,
1729 (UINT8 *) &GlyphData,
1730 Foreground,
1731 Background,
1732 Count * 2,
1733 GLYPH_WIDTH,
1734 GLYPH_HEIGHT,
1735 &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH]
1736 );
1737 } else {
1738 mHii->GlyphToBlt (
1739 mHii,
1740 (UINT8 *) &GlyphData,
1741 Foreground,
1742 Background,
1743 Count,
1744 GLYPH_WIDTH,
1745 GLYPH_HEIGHT,
1746 &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH]
1747 );
1748 }
1749
1750 ArrayIndex++;
1751
1752 } while (Counts < 2 && GlyphWidth == 0x10);
1753
1754 }
1755 //
1756 // If we are printing Wide characters, treat the BLT as if it is twice as many characters
1757 //
1758 if (GlyphWidth == 0x10) {
1759 Count = Count * 2;
1760 }
1761 //
1762 // Blt a character to the screen
1763 //
1764 GlyphX = This->Mode->CursorColumn * GLYPH_WIDTH;
1765 GlyphY = This->Mode->CursorRow * GLYPH_HEIGHT;
1766 GraphicsOutput = Private->GraphicsOutput;
1767 UgaDraw = Private->UgaDraw;
1768 if (GraphicsOutput != NULL) {
1769 GraphicsOutput->Blt (
1770 GraphicsOutput,
1771 Private->LineBuffer,
1772 EfiBltBufferToVideo,
1773 0,
1774 0,
1775 GlyphX + Private->ModeData[This->Mode->Mode].DeltaX,
1776 GlyphY + Private->ModeData[This->Mode->Mode].DeltaY,
1777 GLYPH_WIDTH * Count,
1778 GLYPH_HEIGHT,
1779 GLYPH_WIDTH * Count * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1780 );
1781 } else {
1782 UgaDraw->Blt (
1783 UgaDraw,
1784 (EFI_UGA_PIXEL *) (UINTN) Private->LineBuffer,
1785 EfiUgaBltBufferToVideo,
1786 0,
1787 0,
1788 GlyphX + Private->ModeData[This->Mode->Mode].DeltaX,
1789 GlyphY + Private->ModeData[This->Mode->Mode].DeltaY,
1790 GLYPH_WIDTH * Count,
1791 GLYPH_HEIGHT,
1792 GLYPH_WIDTH * Count * sizeof (EFI_UGA_PIXEL)
1793 );
1794 }
1795
1796 return ReturnStatus;
1797 }
1798
1799 STATIC
1800 EFI_STATUS
1801 EraseCursor (
1802 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
1803 )
1804 {
1805 GRAPHICS_CONSOLE_DEV *Private;
1806 EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode;
1807 INTN GlyphX;
1808 INTN GlyphY;
1809 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1810 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1811 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground;
1812 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background;
1813 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[GLYPH_HEIGHT][GLYPH_WIDTH];
1814 UINTN X;
1815 UINTN Y;
1816
1817 CurrentMode = This->Mode;
1818
1819 if (!CurrentMode->CursorVisible) {
1820 return EFI_SUCCESS;
1821 }
1822
1823 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1824 GraphicsOutput = Private->GraphicsOutput;
1825 UgaDraw = Private->UgaDraw;
1826
1827 //
1828 // BUGBUG - we need to think about what to do with wide and narrow character deletions.
1829 //
1830 //
1831 // Blt a character to the screen
1832 //
1833 GlyphX = (CurrentMode->CursorColumn * GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX;
1834 GlyphY = (CurrentMode->CursorRow * GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY;
1835 if (GraphicsOutput != NULL) {
1836 GraphicsOutput->Blt (
1837 GraphicsOutput,
1838 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,
1839 EfiBltVideoToBltBuffer,
1840 GlyphX,
1841 GlyphY,
1842 0,
1843 0,
1844 GLYPH_WIDTH,
1845 GLYPH_HEIGHT,
1846 GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1847 );
1848 } else {
1849 UgaDraw->Blt (
1850 UgaDraw,
1851 (EFI_UGA_PIXEL *) (UINTN) BltChar,
1852 EfiUgaVideoToBltBuffer,
1853 GlyphX,
1854 GlyphY,
1855 0,
1856 0,
1857 GLYPH_WIDTH,
1858 GLYPH_HEIGHT,
1859 GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
1860 );
1861 }
1862
1863 GetTextColors (This, &Foreground.Pixel, &Background.Pixel);
1864
1865 //
1866 // Convert Monochrome bitmap of the Glyph to BltBuffer structure
1867 //
1868 for (Y = 0; Y < GLYPH_HEIGHT; Y++) {
1869 for (X = 0; X < GLYPH_WIDTH; X++) {
1870 if ((mCursorGlyph.GlyphCol1[Y] & (1 << X)) != 0) {
1871 BltChar[Y][GLYPH_WIDTH - X - 1].Raw ^= Foreground.Raw;
1872 }
1873 }
1874 }
1875
1876 if (GraphicsOutput != NULL) {
1877 GraphicsOutput->Blt (
1878 GraphicsOutput,
1879 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,
1880 EfiBltBufferToVideo,
1881 0,
1882 0,
1883 GlyphX,
1884 GlyphY,
1885 GLYPH_WIDTH,
1886 GLYPH_HEIGHT,
1887 GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1888 );
1889 } else {
1890 UgaDraw->Blt (
1891 UgaDraw,
1892 (EFI_UGA_PIXEL *) (UINTN) BltChar,
1893 EfiUgaBltBufferToVideo,
1894 0,
1895 0,
1896 GlyphX,
1897 GlyphY,
1898 GLYPH_WIDTH,
1899 GLYPH_HEIGHT,
1900 GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
1901 );
1902 }
1903
1904 return EFI_SUCCESS;
1905 }
1906
1907 /**
1908 The user Entry Point for module GraphicsConsole. The user code starts with this function.
1909
1910 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1911 @param[in] SystemTable A pointer to the EFI System Table.
1912
1913 @retval EFI_SUCCESS The entry point is executed successfully.
1914 @retval other Some error occurs when executing this entry point.
1915
1916 **/
1917 EFI_STATUS
1918 EFIAPI
1919 InitializeGraphicsConsole (
1920 IN EFI_HANDLE ImageHandle,
1921 IN EFI_SYSTEM_TABLE *SystemTable
1922 )
1923 {
1924 EFI_STATUS Status;
1925
1926 //
1927 // Install driver model protocol(s).
1928 //
1929 Status = EfiLibInstallDriverBindingComponentName2 (
1930 ImageHandle,
1931 SystemTable,
1932 &gGraphicsConsoleDriverBinding,
1933 ImageHandle,
1934 &gGraphicsConsoleComponentName,
1935 &gGraphicsConsoleComponentName2
1936 );
1937 ASSERT_EFI_ERROR (Status);
1938
1939
1940 return Status;
1941 }
1942