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