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