]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
UEFI HII: Merge UEFI HII support changes from branch.
[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 1
622 Status = HiiLibRemovePackagesFromHiiDatabase (Private->HiiHandle);
623 if (!EFI_ERROR (Status)) {
624 mFirstAccessFlag = TRUE;
625 }
626 #else
627 mHii->RemovePack (mHii, Private->HiiHandle);
628 #endif
629
630 //
631 // Free our instance data
632 //
633 if (Private != NULL) {
634 FreePool (Private->LineBuffer);
635 FreePool (Private);
636 }
637 }
638
639 return Status;
640 }
641
642 EFI_STATUS
643 CheckModeSupported (
644 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
645 IN UINT32 HorizontalResolution,
646 IN UINT32 VerticalResolution,
647 OUT UINT32 *CurrentModeNumber
648 )
649 {
650 UINT32 ModeNumber;
651 EFI_STATUS Status;
652 UINTN SizeOfInfo;
653 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
654
655 Status = EFI_SUCCESS;
656
657 for (ModeNumber = 0; ModeNumber < GraphicsOutput->Mode->MaxMode; ModeNumber++) {
658 Status = GraphicsOutput->QueryMode (
659 GraphicsOutput,
660 ModeNumber,
661 &SizeOfInfo,
662 &Info
663 );
664 if (!EFI_ERROR (Status)) {
665 if ((Info->HorizontalResolution == HorizontalResolution) &&
666 (Info->VerticalResolution == VerticalResolution)) {
667 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
668 if (!EFI_ERROR (Status)) {
669 gBS->FreePool (Info);
670 break;
671 }
672 }
673 gBS->FreePool (Info);
674 }
675 }
676
677 if (ModeNumber == GraphicsOutput->Mode->MaxMode) {
678 Status = EFI_UNSUPPORTED;
679 }
680
681 *CurrentModeNumber = ModeNumber;
682 return Status;
683 }
684
685 EFI_STATUS
686 EfiLocateHiiProtocol (
687 VOID
688 )
689 /*++
690
691 Routine Description:
692 Locate HII protocols for future usage.
693
694 Arguments:
695
696 Returns:
697
698 --*/
699 {
700 EFI_HANDLE Handle;
701 UINTN Size;
702 EFI_STATUS Status;
703
704 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
705
706 //
707 // There should only be one - so buffer size is this
708 //
709 Size = sizeof (EFI_HANDLE);
710
711 Status = gBS->LocateHandle (
712 ByProtocol,
713 &gEfiHiiDatabaseProtocolGuid,
714 NULL,
715 &Size,
716 (VOID **) &Handle
717 );
718
719 if (EFI_ERROR (Status)) {
720 return Status;
721 }
722
723 Status = gBS->HandleProtocol (
724 Handle,
725 &gEfiHiiDatabaseProtocolGuid,
726 (VOID **) &mHiiDatabase
727 );
728
729 if (EFI_ERROR (Status)) {
730 return Status;
731 }
732
733 Status = gBS->HandleProtocol (
734 Handle,
735 &gEfiHiiFontProtocolGuid,
736 (VOID **) &mHiiFont
737 );
738 return Status;
739 #else
740
741 //
742 // There should only be one - so buffer size is this
743 //
744 Size = sizeof (EFI_HANDLE);
745
746 Status = gBS->LocateHandle (
747 ByProtocol,
748 &gEfiHiiProtocolGuid,
749 NULL,
750 &Size,
751 &Handle
752 );
753
754 if (EFI_ERROR (Status)) {
755 return Status;
756 }
757
758 Status = gBS->HandleProtocol (
759 Handle,
760 &gEfiHiiProtocolGuid,
761 &mHii
762 );
763
764 return Status;
765 #endif
766 }
767
768 //
769 // Body of the STO functions
770 //
771 EFI_STATUS
772 EFIAPI
773 GraphicsConsoleConOutReset (
774 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
775 IN BOOLEAN ExtendedVerification
776 )
777 /*++
778 Routine Description:
779
780 Implements SIMPLE_TEXT_OUTPUT.Reset().
781 If ExtendeVerification is TRUE, then perform dependent Graphics Console
782 device reset, and set display mode to mode 0.
783 If ExtendedVerification is FALSE, only set display mode to mode 0.
784
785 Arguments:
786
787 This - Indicates the calling context.
788
789 ExtendedVerification - Indicates that the driver may perform a more exhaustive
790 verification operation of the device during reset.
791
792 Returns:
793
794 EFI_SUCCESS
795 The reset operation succeeds.
796
797 EFI_DEVICE_ERROR
798 The Graphics Console is not functioning correctly
799
800 --*/
801 {
802 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));
803 return This->SetMode (This, 0);
804 }
805
806 EFI_STATUS
807 EFIAPI
808 GraphicsConsoleConOutOutputString (
809 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
810 IN CHAR16 *WString
811 )
812 /*++
813 Routine Description:
814
815 Implements SIMPLE_TEXT_OUTPUT.OutputString().
816 The Unicode string will be converted to Glyphs and will be
817 sent to the Graphics Console.
818
819
820 Arguments:
821
822 This - Indicates the calling context.
823
824 WString - The Null-terminated Unicode string to be displayed on
825 the Graphics Console.
826
827 Returns:
828
829 EFI_SUCCESS
830 The string is output successfully.
831
832 EFI_DEVICE_ERROR
833 The Graphics Console failed to send the string out.
834
835 EFI_WARN_UNKNOWN_GLYPH
836 Indicates that some of the characters in the Unicode string could not
837 be rendered and are skipped.
838
839 --*/
840 {
841 GRAPHICS_CONSOLE_DEV *Private;
842 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
843 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
844 INTN Mode;
845 UINTN MaxColumn;
846 UINTN MaxRow;
847 UINTN Width;
848 UINTN Height;
849 UINTN Delta;
850 EFI_STATUS Status;
851 BOOLEAN Warning;
852 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
853 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
854 UINTN DeltaX;
855 UINTN DeltaY;
856 UINTN Count;
857 UINTN Index;
858 INT32 OriginAttribute;
859 EFI_TPL OldTpl;
860 CHAR16 SpaceStr[] = { NARROW_CHAR, ' ', 0 };
861
862 Status = EFI_SUCCESS;
863
864 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
865 //
866 // Current mode
867 //
868 Mode = This->Mode->Mode;
869 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
870 GraphicsOutput = Private->GraphicsOutput;
871 UgaDraw = Private->UgaDraw;
872
873 MaxColumn = Private->ModeData[Mode].Columns;
874 MaxRow = Private->ModeData[Mode].Rows;
875 DeltaX = Private->ModeData[Mode].DeltaX;
876 DeltaY = Private->ModeData[Mode].DeltaY;
877 Width = MaxColumn * GLYPH_WIDTH;
878 Height = (MaxRow - 1) * GLYPH_HEIGHT;
879 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
880
881 //
882 // The Attributes won't change when during the time OutputString is called
883 //
884 GetTextColors (This, &Foreground, &Background);
885
886 EraseCursor (This);
887
888 Warning = FALSE;
889
890 //
891 // Backup attribute
892 //
893 OriginAttribute = This->Mode->Attribute;
894
895 while (*WString) {
896
897 if (*WString == CHAR_BACKSPACE) {
898 //
899 // If the cursor is at the left edge of the display, then move the cursor
900 // one row up.
901 //
902 if (This->Mode->CursorColumn == 0 && This->Mode->CursorRow > 0) {
903 This->Mode->CursorRow--;
904 This->Mode->CursorColumn = (INT32) (MaxColumn - 1);
905 This->OutputString (This, SpaceStr);
906 EraseCursor (This);
907 This->Mode->CursorRow--;
908 This->Mode->CursorColumn = (INT32) (MaxColumn - 1);
909 } else if (This->Mode->CursorColumn > 0) {
910 //
911 // If the cursor is not at the left edge of the display, then move the cursor
912 // left one column.
913 //
914 This->Mode->CursorColumn--;
915 This->OutputString (This, SpaceStr);
916 EraseCursor (This);
917 This->Mode->CursorColumn--;
918 }
919
920 WString++;
921
922 } else if (*WString == CHAR_LINEFEED) {
923 //
924 // If the cursor is at the bottom of the display, then scroll the display one
925 // row, and do not update the cursor position. Otherwise, move the cursor
926 // down one row.
927 //
928 if (This->Mode->CursorRow == (INT32) (MaxRow - 1)) {
929 if (GraphicsOutput != NULL) {
930 //
931 // Scroll Screen Up One Row
932 //
933 GraphicsOutput->Blt (
934 GraphicsOutput,
935 NULL,
936 EfiBltVideoToVideo,
937 DeltaX,
938 DeltaY + GLYPH_HEIGHT,
939 DeltaX,
940 DeltaY,
941 Width,
942 Height,
943 Delta
944 );
945
946 //
947 // Print Blank Line at last line
948 //
949 GraphicsOutput->Blt (
950 GraphicsOutput,
951 &Background,
952 EfiBltVideoFill,
953 0,
954 0,
955 DeltaX,
956 DeltaY + Height,
957 Width,
958 GLYPH_HEIGHT,
959 Delta
960 );
961 } else {
962 //
963 // Scroll Screen Up One Row
964 //
965 UgaDraw->Blt (
966 UgaDraw,
967 NULL,
968 EfiUgaVideoToVideo,
969 DeltaX,
970 DeltaY + GLYPH_HEIGHT,
971 DeltaX,
972 DeltaY,
973 Width,
974 Height,
975 Delta
976 );
977
978 //
979 // Print Blank Line at last line
980 //
981 UgaDraw->Blt (
982 UgaDraw,
983 (EFI_UGA_PIXEL *) (UINTN) &Background,
984 EfiUgaVideoFill,
985 0,
986 0,
987 DeltaX,
988 DeltaY + Height,
989 Width,
990 GLYPH_HEIGHT,
991 Delta
992 );
993 }
994 } else {
995 This->Mode->CursorRow++;
996 }
997
998 WString++;
999
1000 } else if (*WString == CHAR_CARRIAGE_RETURN) {
1001 //
1002 // Move the cursor to the beginning of the current row.
1003 //
1004 This->Mode->CursorColumn = 0;
1005 WString++;
1006
1007 } else if (*WString == WIDE_CHAR) {
1008
1009 This->Mode->Attribute |= EFI_WIDE_ATTRIBUTE;
1010 WString++;
1011
1012 } else if (*WString == NARROW_CHAR) {
1013
1014 This->Mode->Attribute &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
1015 WString++;
1016
1017 } else {
1018 //
1019 // Print the character at the current cursor position and move the cursor
1020 // right one column. If this moves the cursor past the right edge of the
1021 // display, then the line should wrap to the beginning of the next line. This
1022 // is equivalent to inserting a CR and an LF. Note that if the cursor is at the
1023 // bottom of the display, and the line wraps, then the display will be scrolled
1024 // one line.
1025 // If wide char is going to be displayed, need to display one character at a time
1026 // Or, need to know the display length of a certain string.
1027 //
1028 // Index is used to determine how many character width units (wide = 2, narrow = 1)
1029 // Count is used to determine how many characters are used regardless of their attributes
1030 //
1031 for (Count = 0, Index = 0; (This->Mode->CursorColumn + Index) < MaxColumn; Count++, Index++) {
1032 if (WString[Count] == CHAR_NULL) {
1033 break;
1034 }
1035
1036 if (WString[Count] == CHAR_BACKSPACE) {
1037 break;
1038 }
1039
1040 if (WString[Count] == CHAR_LINEFEED) {
1041 break;
1042 }
1043
1044 if (WString[Count] == CHAR_CARRIAGE_RETURN) {
1045 break;
1046 }
1047
1048 if (WString[Count] == WIDE_CHAR) {
1049 break;
1050 }
1051
1052 if (WString[Count] == NARROW_CHAR) {
1053 break;
1054 }
1055 //
1056 // Is the wide attribute on?
1057 //
1058 if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) {
1059 //
1060 // If wide, add one more width unit than normal since we are going to increment at the end of the for loop
1061 //
1062 Index++;
1063 //
1064 // This is the end-case where if we are at column 79 and about to print a wide character
1065 // We should prevent this from happening because we will wrap inappropriately. We should
1066 // not print this character until the next line.
1067 //
1068 if ((This->Mode->CursorColumn + Index + 1) > MaxColumn) {
1069 Index++;
1070 break;
1071 }
1072 }
1073 }
1074
1075 Status = DrawUnicodeWeightAtCursorN (This, WString, Count);
1076 if (EFI_ERROR (Status)) {
1077 Warning = TRUE;
1078 }
1079 //
1080 // At the end of line, output carriage return and line feed
1081 //
1082 WString += Count;
1083 This->Mode->CursorColumn += (INT32) Index;
1084 if (This->Mode->CursorColumn > (INT32) MaxColumn) {
1085 This->Mode->CursorColumn -= 2;
1086 This->OutputString (This, SpaceStr);
1087 }
1088
1089 if (This->Mode->CursorColumn >= (INT32) MaxColumn) {
1090 EraseCursor (This);
1091 This->OutputString (This, mCrLfString);
1092 EraseCursor (This);
1093 }
1094 }
1095 }
1096
1097 This->Mode->Attribute = OriginAttribute;
1098
1099 EraseCursor (This);
1100
1101 if (Warning) {
1102 Status = EFI_WARN_UNKNOWN_GLYPH;
1103 }
1104
1105 gBS->RestoreTPL (OldTpl);
1106 return Status;
1107
1108 }
1109
1110 EFI_STATUS
1111 EFIAPI
1112 GraphicsConsoleConOutTestString (
1113 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1114 IN CHAR16 *WString
1115 )
1116 /*++
1117 Routine Description:
1118
1119 Implements SIMPLE_TEXT_OUTPUT.TestString().
1120 If one of the characters in the *Wstring is
1121 neither valid valid Unicode drawing characters,
1122 not ASCII code, then this function will return
1123 EFI_UNSUPPORTED.
1124
1125
1126 Arguments:
1127
1128 This - Indicates the calling context.
1129
1130 WString - The Null-terminated Unicode string to be tested.
1131
1132 Returns:
1133
1134 EFI_SUCCESS
1135 The Graphics Console is capable of rendering the output string.
1136
1137 EFI_UNSUPPORTED
1138 Some of the characters in the Unicode string cannot be rendered.
1139
1140 --*/
1141 {
1142 EFI_STATUS Status;
1143 UINT16 Count;
1144
1145 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
1146 EFI_IMAGE_OUTPUT *Blt = NULL;
1147 #else
1148 UINT16 GlyphWidth;
1149 UINT32 GlyphStatus = 0;
1150 GLYPH_UNION *Glyph;
1151 #endif
1152
1153 Count = 0;
1154
1155 while (WString[Count] != 0) {
1156 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
1157 Status = mHiiFont->GetGlyph (
1158 mHiiFont,
1159 WString[Count],
1160 NULL,
1161 &Blt,
1162 NULL
1163 );
1164 SafeFreePool (Blt);
1165 Blt = NULL;
1166 Count++;
1167 #else
1168 Status = mHii->GetGlyph (
1169 mHii,
1170 WString,
1171 &Count,
1172 (UINT8 **) &Glyph,
1173 &GlyphWidth,
1174 &GlyphStatus
1175 );
1176 #endif
1177 if (EFI_ERROR (Status)) {
1178 return EFI_UNSUPPORTED;
1179 }
1180 }
1181
1182 return EFI_SUCCESS;
1183 }
1184
1185 EFI_STATUS
1186 EFIAPI
1187 GraphicsConsoleConOutQueryMode (
1188 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1189 IN UINTN ModeNumber,
1190 OUT UINTN *Columns,
1191 OUT UINTN *Rows
1192 )
1193 /*++
1194 Routine Description:
1195
1196 Implements SIMPLE_TEXT_OUTPUT.QueryMode().
1197 It returnes information for an available text mode
1198 that the Graphics Console supports.
1199 In this driver,we only support text mode 80x25, which is
1200 defined as mode 0.
1201
1202
1203 Arguments:
1204
1205 This - Indicates the calling context.
1206
1207 ModeNumber - The mode number to return information on.
1208
1209 Columns - The returned columns of the requested mode.
1210
1211 Rows - The returned rows of the requested mode.
1212
1213 Returns:
1214
1215 EFI_SUCCESS
1216 The requested mode information is returned.
1217
1218 EFI_UNSUPPORTED
1219 The mode number is not valid.
1220
1221 --*/
1222 {
1223 GRAPHICS_CONSOLE_DEV *Private;
1224 EFI_STATUS Status;
1225 EFI_TPL OldTpl;
1226
1227 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
1228 return EFI_UNSUPPORTED;
1229 }
1230
1231 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1232 Status = EFI_SUCCESS;
1233
1234 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1235
1236 *Columns = Private->ModeData[ModeNumber].Columns;
1237 *Rows = Private->ModeData[ModeNumber].Rows;
1238
1239 if (*Columns <= 0 && *Rows <= 0) {
1240 Status = EFI_UNSUPPORTED;
1241 goto Done;
1242
1243 }
1244
1245 Done:
1246 gBS->RestoreTPL (OldTpl);
1247 return Status;
1248 }
1249
1250 EFI_STATUS
1251 EFIAPI
1252 GraphicsConsoleConOutSetMode (
1253 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1254 IN UINTN ModeNumber
1255 )
1256 /*++
1257 Routine Description:
1258
1259 Implements SIMPLE_TEXT_OUTPUT.SetMode().
1260 Set the Graphics Console to a specified mode.
1261 In this driver, we only support mode 0.
1262
1263 Arguments:
1264
1265 This - Indicates the calling context.
1266
1267 ModeNumber - The text mode to set.
1268
1269 Returns:
1270
1271 EFI_SUCCESS
1272 The requested text mode is set.
1273
1274 EFI_DEVICE_ERROR
1275 The requested text mode cannot be set because of Graphics Console device error.
1276
1277 EFI_UNSUPPORTED
1278 The text mode number is not valid.
1279
1280 --*/
1281 {
1282 EFI_STATUS Status;
1283 GRAPHICS_CONSOLE_DEV *Private;
1284 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1285 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewLineBuffer;
1286 UINT32 HorizontalResolution;
1287 UINT32 VerticalResolution;
1288 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1289 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1290 UINT32 ColorDepth;
1291 UINT32 RefreshRate;
1292 EFI_TPL OldTpl;
1293
1294 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1295
1296 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1297 GraphicsOutput = Private->GraphicsOutput;
1298 UgaDraw = Private->UgaDraw;
1299 ModeData = &(Private->ModeData[ModeNumber]);
1300
1301 if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {
1302 Status = EFI_UNSUPPORTED;
1303 goto Done;
1304 }
1305
1306 //
1307 // Make sure the requested mode number is supported
1308 //
1309 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
1310 Status = EFI_UNSUPPORTED;
1311 goto Done;
1312 }
1313
1314 if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {
1315 Status = EFI_UNSUPPORTED;
1316 goto Done;
1317 }
1318 //
1319 // Attempt to allocate a line buffer for the requested mode number
1320 //
1321 NewLineBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->Columns * GLYPH_WIDTH * GLYPH_HEIGHT);
1322
1323 if (NewLineBuffer == NULL) {
1324 //
1325 // The new line buffer could not be allocated, so return an error.
1326 // No changes to the state of the current console have been made, so the current console is still valid
1327 //
1328 Status = EFI_OUT_OF_RESOURCES;
1329 goto Done;
1330 }
1331 //
1332 // If the mode has been set at least one other time, then LineBuffer will not be NULL
1333 //
1334 if (Private->LineBuffer != NULL) {
1335 //
1336 // Clear the current text window on the current graphics console
1337 //
1338 This->ClearScreen (This);
1339
1340 //
1341 // If the new mode is the same as the old mode, then just return EFI_SUCCESS
1342 //
1343 if ((INT32) ModeNumber == This->Mode->Mode) {
1344 FreePool (NewLineBuffer);
1345 Status = EFI_SUCCESS;
1346 goto Done;
1347 }
1348 //
1349 // Otherwise, the size of the text console and/or the GOP/UGA mode will be changed,
1350 // so erase the cursor, and free the LineBuffer for the current mode
1351 //
1352 EraseCursor (This);
1353
1354 FreePool (Private->LineBuffer);
1355 }
1356 //
1357 // Assign the current line buffer to the newly allocated line buffer
1358 //
1359 Private->LineBuffer = NewLineBuffer;
1360
1361 if (GraphicsOutput != NULL) {
1362 if (ModeData->GopModeNumber != GraphicsOutput->Mode->Mode) {
1363 //
1364 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1365 //
1366 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeData->GopModeNumber);
1367 if (EFI_ERROR (Status)) {
1368 //
1369 // The mode set operation failed
1370 //
1371 goto Done;
1372 }
1373 } else {
1374 //
1375 // The current graphics mode is correct, so simply clear the entire display
1376 //
1377 Status = GraphicsOutput->Blt (
1378 GraphicsOutput,
1379 &mEfiColors[0],
1380 EfiBltVideoFill,
1381 0,
1382 0,
1383 0,
1384 0,
1385 ModeData->GopWidth,
1386 ModeData->GopHeight,
1387 0
1388 );
1389 }
1390 } else {
1391 //
1392 // Get the current UGA Draw mode information
1393 //
1394 Status = UgaDraw->GetMode (
1395 UgaDraw,
1396 &HorizontalResolution,
1397 &VerticalResolution,
1398 &ColorDepth,
1399 &RefreshRate
1400 );
1401 if (EFI_ERROR (Status) || HorizontalResolution != ModeData->GopWidth || VerticalResolution != ModeData->GopHeight) {
1402 //
1403 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1404 //
1405 Status = UgaDraw->SetMode (
1406 UgaDraw,
1407 ModeData->GopWidth,
1408 ModeData->GopHeight,
1409 32,
1410 60
1411 );
1412 if (EFI_ERROR (Status)) {
1413 //
1414 // The mode set operation failed
1415 //
1416 goto Done;
1417 }
1418 } else {
1419 //
1420 // The current graphics mode is correct, so simply clear the entire display
1421 //
1422 Status = UgaDraw->Blt (
1423 UgaDraw,
1424 (EFI_UGA_PIXEL *) (UINTN) &mEfiColors[0],
1425 EfiUgaVideoFill,
1426 0,
1427 0,
1428 0,
1429 0,
1430 ModeData->GopWidth,
1431 ModeData->GopHeight,
1432 0
1433 );
1434 }
1435 }
1436
1437 //
1438 // The new mode is valid, so commit the mode change
1439 //
1440 This->Mode->Mode = (INT32) ModeNumber;
1441
1442 //
1443 // Move the text cursor to the upper left hand corner of the displat and enable it
1444 //
1445 This->SetCursorPosition (This, 0, 0);
1446
1447 Status = EFI_SUCCESS;
1448
1449 Done:
1450 gBS->RestoreTPL (OldTpl);
1451 return Status;
1452 }
1453
1454 EFI_STATUS
1455 EFIAPI
1456 GraphicsConsoleConOutSetAttribute (
1457 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1458 IN UINTN Attribute
1459 )
1460 /*++
1461 Routine Description:
1462
1463 Implements SIMPLE_TEXT_OUTPUT.SetAttribute().
1464
1465 Arguments:
1466
1467 This - Indicates the calling context.
1468
1469 Attrubute - The attribute to set. Only bit0..6 are valid, all other bits
1470 are undefined and must be zero.
1471
1472 Returns:
1473
1474 EFI_SUCCESS
1475 The requested attribute is set.
1476
1477 EFI_DEVICE_ERROR
1478 The requested attribute cannot be set due to Graphics Console port error.
1479
1480 EFI_UNSUPPORTED
1481 The attribute requested is not defined by EFI spec.
1482
1483 --*/
1484 {
1485 EFI_TPL OldTpl;
1486
1487 if ((Attribute | 0xFF) != 0xFF) {
1488 return EFI_UNSUPPORTED;
1489 }
1490
1491 if ((INT32) Attribute == This->Mode->Attribute) {
1492 return EFI_SUCCESS;
1493 }
1494
1495 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1496
1497 EraseCursor (This);
1498
1499 This->Mode->Attribute = (INT32) Attribute;
1500
1501 EraseCursor (This);
1502
1503 gBS->RestoreTPL (OldTpl);
1504
1505 return EFI_SUCCESS;
1506 }
1507
1508 EFI_STATUS
1509 EFIAPI
1510 GraphicsConsoleConOutClearScreen (
1511 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
1512 )
1513 /*++
1514 Routine Description:
1515
1516 Implements SIMPLE_TEXT_OUTPUT.ClearScreen().
1517 It clears the Graphics Console's display to the
1518 currently selected background color.
1519
1520
1521 Arguments:
1522
1523 This - Indicates the calling context.
1524
1525 Returns:
1526
1527 EFI_SUCCESS
1528 The operation completed successfully.
1529
1530 EFI_DEVICE_ERROR
1531 The Graphics Console cannot be cleared due to Graphics Console device error.
1532
1533 EFI_UNSUPPORTED
1534 The Graphics Console is not in a valid text mode.
1535
1536 --*/
1537 {
1538 EFI_STATUS Status;
1539 GRAPHICS_CONSOLE_DEV *Private;
1540 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1541 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1542 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1543 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
1544 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1545 EFI_TPL OldTpl;
1546
1547 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1548
1549 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1550 GraphicsOutput = Private->GraphicsOutput;
1551 UgaDraw = Private->UgaDraw;
1552 ModeData = &(Private->ModeData[This->Mode->Mode]);
1553
1554 GetTextColors (This, &Foreground, &Background);
1555 if (GraphicsOutput != NULL) {
1556 Status = GraphicsOutput->Blt (
1557 GraphicsOutput,
1558 &Background,
1559 EfiBltVideoFill,
1560 0,
1561 0,
1562 0,
1563 0,
1564 ModeData->GopWidth,
1565 ModeData->GopHeight,
1566 0
1567 );
1568 } else {
1569 Status = UgaDraw->Blt (
1570 UgaDraw,
1571 (EFI_UGA_PIXEL *) (UINTN) &Background,
1572 EfiUgaVideoFill,
1573 0,
1574 0,
1575 0,
1576 0,
1577 ModeData->GopWidth,
1578 ModeData->GopHeight,
1579 0
1580 );
1581 }
1582
1583 This->Mode->CursorColumn = 0;
1584 This->Mode->CursorRow = 0;
1585
1586 EraseCursor (This);
1587
1588 gBS->RestoreTPL (OldTpl);
1589
1590 return Status;
1591 }
1592
1593 EFI_STATUS
1594 EFIAPI
1595 GraphicsConsoleConOutSetCursorPosition (
1596 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1597 IN UINTN Column,
1598 IN UINTN Row
1599 )
1600 /*++
1601 Routine Description:
1602
1603 Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().
1604
1605 Arguments:
1606
1607 This - Indicates the calling context.
1608
1609 Column - The row to set cursor to.
1610
1611 Row - The column to set cursor to.
1612
1613 Returns:
1614
1615 EFI_SUCCESS
1616 The operation completed successfully.
1617
1618 EFI_DEVICE_ERROR
1619 The request fails due to Graphics Console device error.
1620
1621 EFI_UNSUPPORTED
1622 The Graphics Console is not in a valid text mode, or the cursor position
1623 is invalid for current mode.
1624
1625 --*/
1626 {
1627 GRAPHICS_CONSOLE_DEV *Private;
1628 GRAPHICS_CONSOLE_MODE_DATA *ModeData;
1629 EFI_STATUS Status;
1630 EFI_TPL OldTpl;
1631
1632 Status = EFI_SUCCESS;
1633
1634 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1635
1636 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1637 ModeData = &(Private->ModeData[This->Mode->Mode]);
1638
1639 if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) {
1640 Status = EFI_UNSUPPORTED;
1641 goto Done;
1642 }
1643
1644 if (((INT32) Column == This->Mode->CursorColumn) && ((INT32) Row == This->Mode->CursorRow)) {
1645 Status = EFI_SUCCESS;
1646 goto Done;
1647 }
1648
1649 EraseCursor (This);
1650
1651 This->Mode->CursorColumn = (INT32) Column;
1652 This->Mode->CursorRow = (INT32) Row;
1653
1654 EraseCursor (This);
1655
1656 Done:
1657 gBS->RestoreTPL (OldTpl);
1658
1659 return Status;
1660 }
1661
1662 EFI_STATUS
1663 EFIAPI
1664 GraphicsConsoleConOutEnableCursor (
1665 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1666 IN BOOLEAN Visible
1667 )
1668 /*++
1669 Routine Description:
1670
1671 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1672 In this driver, the cursor cannot be hidden.
1673
1674 Arguments:
1675
1676 This - Indicates the calling context.
1677
1678 Visible - If TRUE, the cursor is set to be visible,
1679 If FALSE, the cursor is set to be invisible.
1680
1681 Returns:
1682
1683 EFI_SUCCESS
1684 The request is valid.
1685
1686 EFI_UNSUPPORTED
1687 The Graphics Console does not support a hidden cursor.
1688
1689 --*/
1690 {
1691 EFI_TPL OldTpl;
1692
1693 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1694
1695 EraseCursor (This);
1696
1697 This->Mode->CursorVisible = Visible;
1698
1699 EraseCursor (This);
1700
1701 gBS->RestoreTPL (OldTpl);
1702 return EFI_SUCCESS;
1703 }
1704
1705 STATIC
1706 EFI_STATUS
1707 GetTextColors (
1708 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1709 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
1710 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background
1711 )
1712 {
1713 INTN Attribute;
1714
1715 Attribute = This->Mode->Attribute & 0x7F;
1716
1717 *Foreground = mEfiColors[Attribute & 0x0f];
1718 *Background = mEfiColors[Attribute >> 4];
1719
1720 return EFI_SUCCESS;
1721 }
1722
1723 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
1724 EFI_STATUS
1725 DrawUnicodeWeightAtCursorN (
1726 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1727 IN CHAR16 *UnicodeWeight,
1728 IN UINTN Count
1729 )
1730 {
1731 EFI_STATUS Status;
1732 GRAPHICS_CONSOLE_DEV *Private;
1733 EFI_IMAGE_OUTPUT *Blt;
1734 EFI_STRING String;
1735 EFI_FONT_DISPLAY_INFO *FontInfo;
1736
1737 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1738 //
1739 // GOP protocol is required in UEFI mode.
1740 //
1741 ASSERT (Private->GraphicsOutput != NULL);
1742
1743 Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
1744 if (Blt == NULL) {
1745 return EFI_OUT_OF_RESOURCES;
1746 }
1747
1748 Blt->Width = (UINT16) (Private->ModeData[This->Mode->Mode].GopWidth);
1749 Blt->Height = (UINT16) (Private->ModeData[This->Mode->Mode].GopHeight);
1750 Blt->Image.Screen = Private->GraphicsOutput;
1751
1752 String = AllocateCopyPool ((Count + 1) * sizeof (CHAR16), UnicodeWeight);
1753 if (String == NULL) {
1754 SafeFreePool (Blt);
1755 return EFI_OUT_OF_RESOURCES;
1756 }
1757 *(String + Count) = 0;
1758
1759 FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));
1760 if (FontInfo == NULL) {
1761 SafeFreePool (Blt);
1762 SafeFreePool (String);
1763 return EFI_OUT_OF_RESOURCES;
1764 }
1765 GetTextColors (This, &FontInfo->ForegroundColor, &FontInfo->BackgroundColor);
1766
1767 Status = mHiiFont->StringToImage (
1768 mHiiFont,
1769 EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,
1770 String,
1771 FontInfo,
1772 &Blt,
1773 This->Mode->CursorColumn * GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
1774 This->Mode->CursorRow * GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1775 NULL,
1776 NULL,
1777 NULL
1778 );
1779
1780 SafeFreePool (Blt);
1781 SafeFreePool (String);
1782 SafeFreePool (FontInfo);
1783 return Status;
1784 }
1785 #else
1786 STATIC
1787 EFI_STATUS
1788 DrawUnicodeWeightAtCursorN (
1789 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1790 IN CHAR16 *UnicodeWeight,
1791 IN UINTN Count
1792 )
1793 {
1794 GRAPHICS_CONSOLE_DEV *Private;
1795 EFI_STATUS Status;
1796 EFI_STATUS ReturnStatus;
1797 GLYPH_UNION *Glyph;
1798 GLYPH_UNION GlyphData;
1799 INTN GlyphX;
1800 INTN GlyphY;
1801 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1802 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1803 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
1804 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1805 UINTN Index;
1806 UINTN ArrayIndex;
1807 UINTN Counts;
1808 UINT16 GlyphWidth;
1809 UINT32 GlyphStatus;
1810
1811 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1812
1813 ReturnStatus = EFI_SUCCESS;
1814 GlyphStatus = 0;
1815 GlyphWidth = 0x08;
1816
1817 GetTextColors (This, &Foreground, &Background);
1818
1819 Index = 0;
1820 ArrayIndex = 0;
1821 while (Index < Count) {
1822 if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) {
1823 GlyphStatus = WIDE_CHAR;
1824 } else {
1825 GlyphStatus = NARROW_CHAR;
1826 }
1827
1828 Status = mHii->GetGlyph (
1829 mHii,
1830 UnicodeWeight,
1831 (UINT16 *) &Index,
1832 (UINT8 **) &Glyph,
1833 &GlyphWidth,
1834 &GlyphStatus
1835 );
1836 if (EFI_ERROR (Status)) {
1837 ReturnStatus = Status;
1838 }
1839
1840 Counts = 0;
1841
1842 CopyMem (&GlyphData, Glyph, sizeof (GLYPH_UNION));
1843
1844 do {
1845 //
1846 // We are creating the second half of the wide character's BLT buffer
1847 //
1848 if (GlyphWidth == 0x10 && Counts == 1) {
1849 CopyMem (&GlyphData.NarrowGlyph.GlyphCol1, &Glyph->WideGlyph.GlyphCol2, sizeof (Glyph->WideGlyph.GlyphCol2));
1850 }
1851
1852 Counts++;
1853
1854 if (GlyphWidth == 0x10) {
1855 mHii->GlyphToBlt (
1856 mHii,
1857 (UINT8 *) &GlyphData,
1858 Foreground,
1859 Background,
1860 Count * 2,
1861 GLYPH_WIDTH,
1862 GLYPH_HEIGHT,
1863 &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH]
1864 );
1865 } else {
1866 mHii->GlyphToBlt (
1867 mHii,
1868 (UINT8 *) &GlyphData,
1869 Foreground,
1870 Background,
1871 Count,
1872 GLYPH_WIDTH,
1873 GLYPH_HEIGHT,
1874 &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH]
1875 );
1876 }
1877
1878 ArrayIndex++;
1879
1880 } while (Counts < 2 && GlyphWidth == 0x10);
1881
1882 }
1883 //
1884 // If we are printing Wide characters, treat the BLT as if it is twice as many characters
1885 //
1886 if (GlyphWidth == 0x10) {
1887 Count = Count * 2;
1888 }
1889 //
1890 // Blt a character to the screen
1891 //
1892 GlyphX = This->Mode->CursorColumn * GLYPH_WIDTH;
1893 GlyphY = This->Mode->CursorRow * GLYPH_HEIGHT;
1894 GraphicsOutput = Private->GraphicsOutput;
1895 UgaDraw = Private->UgaDraw;
1896 if (GraphicsOutput != NULL) {
1897 GraphicsOutput->Blt (
1898 GraphicsOutput,
1899 Private->LineBuffer,
1900 EfiBltBufferToVideo,
1901 0,
1902 0,
1903 GlyphX + Private->ModeData[This->Mode->Mode].DeltaX,
1904 GlyphY + Private->ModeData[This->Mode->Mode].DeltaY,
1905 GLYPH_WIDTH * Count,
1906 GLYPH_HEIGHT,
1907 GLYPH_WIDTH * Count * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1908 );
1909 } else {
1910 UgaDraw->Blt (
1911 UgaDraw,
1912 (EFI_UGA_PIXEL *) (UINTN) Private->LineBuffer,
1913 EfiUgaBltBufferToVideo,
1914 0,
1915 0,
1916 GlyphX + Private->ModeData[This->Mode->Mode].DeltaX,
1917 GlyphY + Private->ModeData[This->Mode->Mode].DeltaY,
1918 GLYPH_WIDTH * Count,
1919 GLYPH_HEIGHT,
1920 GLYPH_WIDTH * Count * sizeof (EFI_UGA_PIXEL)
1921 );
1922 }
1923
1924 return ReturnStatus;
1925 }
1926 #endif
1927
1928 STATIC
1929 EFI_STATUS
1930 EraseCursor (
1931 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
1932 )
1933 {
1934 GRAPHICS_CONSOLE_DEV *Private;
1935 EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode;
1936 INTN GlyphX;
1937 INTN GlyphY;
1938 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1939 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1940 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground;
1941 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background;
1942 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[GLYPH_HEIGHT][GLYPH_WIDTH];
1943 UINTN X;
1944 UINTN Y;
1945
1946 CurrentMode = This->Mode;
1947
1948 if (!CurrentMode->CursorVisible) {
1949 return EFI_SUCCESS;
1950 }
1951
1952 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1953 GraphicsOutput = Private->GraphicsOutput;
1954 UgaDraw = Private->UgaDraw;
1955
1956 //
1957 // BUGBUG - we need to think about what to do with wide and narrow character deletions.
1958 //
1959 //
1960 // Blt a character to the screen
1961 //
1962 GlyphX = (CurrentMode->CursorColumn * GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX;
1963 GlyphY = (CurrentMode->CursorRow * GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY;
1964 if (GraphicsOutput != NULL) {
1965 GraphicsOutput->Blt (
1966 GraphicsOutput,
1967 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,
1968 EfiBltVideoToBltBuffer,
1969 GlyphX,
1970 GlyphY,
1971 0,
1972 0,
1973 GLYPH_WIDTH,
1974 GLYPH_HEIGHT,
1975 GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1976 );
1977 } else {
1978 UgaDraw->Blt (
1979 UgaDraw,
1980 (EFI_UGA_PIXEL *) (UINTN) BltChar,
1981 EfiUgaVideoToBltBuffer,
1982 GlyphX,
1983 GlyphY,
1984 0,
1985 0,
1986 GLYPH_WIDTH,
1987 GLYPH_HEIGHT,
1988 GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
1989 );
1990 }
1991
1992 GetTextColors (This, &Foreground.Pixel, &Background.Pixel);
1993
1994 //
1995 // Convert Monochrome bitmap of the Glyph to BltBuffer structure
1996 //
1997 for (Y = 0; Y < GLYPH_HEIGHT; Y++) {
1998 for (X = 0; X < GLYPH_WIDTH; X++) {
1999 if ((mCursorGlyph.GlyphCol1[Y] & (1 << X)) != 0) {
2000 BltChar[Y][GLYPH_WIDTH - X - 1].Raw ^= Foreground.Raw;
2001 }
2002 }
2003 }
2004
2005 if (GraphicsOutput != NULL) {
2006 GraphicsOutput->Blt (
2007 GraphicsOutput,
2008 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,
2009 EfiBltBufferToVideo,
2010 0,
2011 0,
2012 GlyphX,
2013 GlyphY,
2014 GLYPH_WIDTH,
2015 GLYPH_HEIGHT,
2016 GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
2017 );
2018 } else {
2019 UgaDraw->Blt (
2020 UgaDraw,
2021 (EFI_UGA_PIXEL *) (UINTN) BltChar,
2022 EfiUgaBltBufferToVideo,
2023 0,
2024 0,
2025 GlyphX,
2026 GlyphY,
2027 GLYPH_WIDTH,
2028 GLYPH_HEIGHT,
2029 GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
2030 );
2031 }
2032
2033 return EFI_SUCCESS;
2034 }
2035
2036 /**
2037 The user Entry Point for module GraphicsConsole. The user code starts with this function.
2038
2039 @param[in] ImageHandle The firmware allocated handle for the EFI image.
2040 @param[in] SystemTable A pointer to the EFI System Table.
2041
2042 @retval EFI_SUCCESS The entry point is executed successfully.
2043 @retval other Some error occurs when executing this entry point.
2044
2045 **/
2046 EFI_STATUS
2047 EFIAPI
2048 InitializeGraphicsConsole (
2049 IN EFI_HANDLE ImageHandle,
2050 IN EFI_SYSTEM_TABLE *SystemTable
2051 )
2052 {
2053 EFI_STATUS Status;
2054
2055 //
2056 // Install driver model protocol(s).
2057 //
2058 Status = EfiLibInstallDriverBindingComponentName2 (
2059 ImageHandle,
2060 SystemTable,
2061 &gGraphicsConsoleDriverBinding,
2062 ImageHandle,
2063 &gGraphicsConsoleComponentName,
2064 &gGraphicsConsoleComponentName2
2065 );
2066 ASSERT_EFI_ERROR (Status);
2067
2068
2069 return Status;
2070 }
2071