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