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