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