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