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