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