1 /** @file
2 VGA Class Driver that managers VGA devices and produces Simple Text Output Protocol.
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "VgaClass.h"
10
11 //
12 // EFI Driver Binding Protocol for the VGA Class Driver
13 //
14 EFI_DRIVER_BINDING_PROTOCOL gVgaClassDriverBinding = {
15 VgaClassDriverBindingSupported,
16 VgaClassDriverBindingStart,
17 VgaClassDriverBindingStop,
18 0xa,
19 NULL,
20 NULL
21 };
22
23 //
24 // Local variables
25 //
26 CHAR16 CrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
27
28 //
29 // This list is used to define the valid extend chars.
30 // It also provides a mapping from Unicode to PCANSI or
31 // ASCII. The ASCII mapping we just made up.
32 //
33 //
34 UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = {
35 {
36 BOXDRAW_HORIZONTAL,
37 0xc4,
38 L'-'
39 },
40 {
41 BOXDRAW_VERTICAL,
42 0xb3,
43 L'|'
44 },
45 {
46 BOXDRAW_DOWN_RIGHT,
47 0xda,
48 L'/'
49 },
50 {
51 BOXDRAW_DOWN_LEFT,
52 0xbf,
53 L'\\'
54 },
55 {
56 BOXDRAW_UP_RIGHT,
57 0xc0,
58 L'\\'
59 },
60 {
61 BOXDRAW_UP_LEFT,
62 0xd9,
63 L'/'
64 },
65 {
66 BOXDRAW_VERTICAL_RIGHT,
67 0xc3,
68 L'|'
69 },
70 {
71 BOXDRAW_VERTICAL_LEFT,
72 0xb4,
73 L'|'
74 },
75 {
76 BOXDRAW_DOWN_HORIZONTAL,
77 0xc2,
78 L'+'
79 },
80 {
81 BOXDRAW_UP_HORIZONTAL,
82 0xc1,
83 L'+'
84 },
85 {
86 BOXDRAW_VERTICAL_HORIZONTAL,
87 0xc5,
88 L'+'
89 },
90 {
91 BOXDRAW_DOUBLE_HORIZONTAL,
92 0xcd,
93 L'-'
94 },
95 {
96 BOXDRAW_DOUBLE_VERTICAL,
97 0xba,
98 L'|'
99 },
100 {
101 BOXDRAW_DOWN_RIGHT_DOUBLE,
102 0xd5,
103 L'/'
104 },
105 {
106 BOXDRAW_DOWN_DOUBLE_RIGHT,
107 0xd6,
108 L'/'
109 },
110 {
111 BOXDRAW_DOUBLE_DOWN_RIGHT,
112 0xc9,
113 L'/'
114 },
115 {
116 BOXDRAW_DOWN_LEFT_DOUBLE,
117 0xb8,
118 L'\\'
119 },
120 {
121 BOXDRAW_DOWN_DOUBLE_LEFT,
122 0xb7,
123 L'\\'
124 },
125 {
126 BOXDRAW_DOUBLE_DOWN_LEFT,
127 0xbb,
128 L'\\'
129 },
130 {
131 BOXDRAW_UP_RIGHT_DOUBLE,
132 0xd4,
133 L'\\'
134 },
135 {
136 BOXDRAW_UP_DOUBLE_RIGHT,
137 0xd3,
138 L'\\'
139 },
140 {
141 BOXDRAW_DOUBLE_UP_RIGHT,
142 0xc8,
143 L'\\'
144 },
145 {
146 BOXDRAW_UP_LEFT_DOUBLE,
147 0xbe,
148 L'/'
149 },
150 {
151 BOXDRAW_UP_DOUBLE_LEFT,
152 0xbd,
153 L'/'
154 },
155 {
156 BOXDRAW_DOUBLE_UP_LEFT,
157 0xbc,
158 L'/'
159 },
160 {
161 BOXDRAW_VERTICAL_RIGHT_DOUBLE,
162 0xc6,
163 L'|'
164 },
165 {
166 BOXDRAW_VERTICAL_DOUBLE_RIGHT,
167 0xc7,
168 L'|'
169 },
170 {
171 BOXDRAW_DOUBLE_VERTICAL_RIGHT,
172 0xcc,
173 L'|'
174 },
175 {
176 BOXDRAW_VERTICAL_LEFT_DOUBLE,
177 0xb5,
178 L'|'
179 },
180 {
181 BOXDRAW_VERTICAL_DOUBLE_LEFT,
182 0xb6,
183 L'|'
184 },
185 {
186 BOXDRAW_DOUBLE_VERTICAL_LEFT,
187 0xb9,
188 L'|'
189 },
190 {
191 BOXDRAW_DOWN_HORIZONTAL_DOUBLE,
192 0xd1,
193 L'+'
194 },
195 {
196 BOXDRAW_DOWN_DOUBLE_HORIZONTAL,
197 0xd2,
198 L'+'
199 },
200 {
201 BOXDRAW_DOUBLE_DOWN_HORIZONTAL,
202 0xcb,
203 L'+'
204 },
205 {
206 BOXDRAW_UP_HORIZONTAL_DOUBLE,
207 0xcf,
208 L'+'
209 },
210 {
211 BOXDRAW_UP_DOUBLE_HORIZONTAL,
212 0xd0,
213 L'+'
214 },
215 {
216 BOXDRAW_DOUBLE_UP_HORIZONTAL,
217 0xca,
218 L'+'
219 },
220 {
221 BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE,
222 0xd8,
223 L'+'
224 },
225 {
226 BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL,
227 0xd7,
228 L'+'
229 },
230 {
231 BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL,
232 0xce,
233 L'+'
234 },
235
236 {
237 BLOCKELEMENT_FULL_BLOCK,
238 0xdb,
239 L'*'
240 },
241 {
242 BLOCKELEMENT_LIGHT_SHADE,
243 0xb0,
244 L'+'
245 },
246
247 {
248 GEOMETRICSHAPE_UP_TRIANGLE,
249 0x1e,
250 L'^'
251 },
252 {
253 GEOMETRICSHAPE_RIGHT_TRIANGLE,
254 0x10,
255 L'>'
256 },
257 {
258 GEOMETRICSHAPE_DOWN_TRIANGLE,
259 0x1f,
260 L'v'
261 },
262 {
263 GEOMETRICSHAPE_LEFT_TRIANGLE,
264 0x11,
265 L'<'
266 },
267
268 {
269 ARROW_LEFT,
270 0x3c,
271 L'<'
272 },
273
274 {
275 ARROW_UP,
276 0x18,
277 L'^'
278 },
279
280 {
281 ARROW_RIGHT,
282 0x3e,
283 L'>'
284 },
285
286 {
287 ARROW_DOWN,
288 0x19,
289 L'v'
290 },
291
292 {
293 0x0000,
294 0x00,
295 0x00
296 }
297 };
298
299 /**
300 Entrypoint of this VGA Class Driver.
301
302 This function is the entrypoint of this VGA Class Driver. It installs Driver Binding
303 Protocols together with Component Name Protocols.
304
305 @param ImageHandle The firmware allocated handle for the EFI image.
306 @param SystemTable A pointer to the EFI System Table.
307
308 @retval EFI_SUCCESS The entry point is executed successfully.
309
310 **/
311 EFI_STATUS
312 EFIAPI
InitializeVgaClass(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)313 InitializeVgaClass(
314 IN EFI_HANDLE ImageHandle,
315 IN EFI_SYSTEM_TABLE *SystemTable
316 )
317 {
318 EFI_STATUS Status;
319
320 //
321 // Install driver model protocol(s).
322 //
323 Status = EfiLibInstallDriverBindingComponentName2 (
324 ImageHandle,
325 SystemTable,
326 &gVgaClassDriverBinding,
327 ImageHandle,
328 &gVgaClassComponentName,
329 &gVgaClassComponentName2
330 );
331 ASSERT_EFI_ERROR (Status);
332
333 return EFI_SUCCESS;
334 }
335
336 /**
337 Internal worker function to program CRTC register via PCI I/O Protocol.
338
339 @param VgaClassDev device instance object
340 @param Address Address of register to write
341 @param Data Data to write to register.
342
343 **/
344 VOID
WriteCrtc(IN VGA_CLASS_DEV * VgaClassDev,IN UINT16 Address,IN UINT8 Data)345 WriteCrtc (
346 IN VGA_CLASS_DEV *VgaClassDev,
347 IN UINT16 Address,
348 IN UINT8 Data
349 )
350 {
351 VgaClassDev->PciIo->Io.Write (
352 VgaClassDev->PciIo,
353 EfiPciIoWidthUint8,
354 VgaClassDev->VgaMiniPort->CrtcAddressRegisterBar,
355 VgaClassDev->VgaMiniPort->CrtcAddressRegisterOffset,
356 1,
357 &Address
358 );
359
360 VgaClassDev->PciIo->Io.Write (
361 VgaClassDev->PciIo,
362 EfiPciIoWidthUint8,
363 VgaClassDev->VgaMiniPort->CrtcDataRegisterBar,
364 VgaClassDev->VgaMiniPort->CrtcDataRegisterOffset,
365 1,
366 &Data
367 );
368 }
369
370 /**
371 Internal worker function to set cursor's position to VgaClass device
372
373 @param VgaClassDev Private data structure for device instance.
374 @param Column Colomn of position to set cursor to.
375 @param Row Row of position to set cursor to.
376 @param MaxColumn Max value of column.
377
378 **/
379 VOID
SetVideoCursorPosition(IN VGA_CLASS_DEV * VgaClassDev,IN UINTN Column,IN UINTN Row,IN UINTN MaxColumn)380 SetVideoCursorPosition (
381 IN VGA_CLASS_DEV *VgaClassDev,
382 IN UINTN Column,
383 IN UINTN Row,
384 IN UINTN MaxColumn
385 )
386 {
387 Column = Column & 0xff;
388 Row = Row & 0xff;
389 MaxColumn = MaxColumn & 0xff;
390
391 WriteCrtc (
392 VgaClassDev,
393 CRTC_CURSOR_LOCATION_HIGH,
394 (UINT8) ((Row * MaxColumn + Column) >> 8)
395 );
396 WriteCrtc (
397 VgaClassDev,
398 CRTC_CURSOR_LOCATION_LOW,
399 (UINT8) ((Row * MaxColumn + Column) & 0xff)
400 );
401 }
402
403 /**
404 Internal worker function to detect if a Unicode char is for Box Drawing text graphics.
405
406 @param Graphic Unicode char to test.
407 @param PcAnsi Pointer to PCANSI equivalent of Graphic for output.
408 If NULL, then PCANSI value is not returned.
409 @param Ascii Pointer to ASCII equivalent of Graphic for output.
410 If NULL, then ASCII value is not returned.
411
412 @retval TRUE Gpaphic is a supported Unicode Box Drawing character.
413 @retval FALSE Gpaphic is not a supported Unicode Box Drawing character.
414
415 **/
416 BOOLEAN
LibIsValidTextGraphics(IN CHAR16 Graphic,OUT CHAR8 * PcAnsi,OPTIONAL OUT CHAR8 * Ascii OPTIONAL)417 LibIsValidTextGraphics (
418 IN CHAR16 Graphic,
419 OUT CHAR8 *PcAnsi, OPTIONAL
420 OUT CHAR8 *Ascii OPTIONAL
421 )
422 {
423 UNICODE_TO_CHAR *Table;
424
425 //
426 // Unicode drawing code charts are all in the 0x25xx range, arrows are 0x21xx.
427 // So first filter out values not in these 2 ranges.
428 //
429 if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) {
430 return FALSE;
431 }
432
433 //
434 // Search UnicodeToPcAnsiOrAscii table for matching entry.
435 //
436 for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) {
437 if (Graphic == Table->Unicode) {
438 if (PcAnsi != NULL) {
439 *PcAnsi = Table->PcAnsi;
440 }
441
442 if (Ascii != NULL) {
443 *Ascii = Table->Ascii;
444 }
445
446 return TRUE;
447 }
448 }
449
450 //
451 // If value is not found in UnicodeToPcAnsiOrAscii table, then return FALSE.
452 //
453 return FALSE;
454 }
455
456 /**
457 Internal worker function to check whether input value is an ASCII char.
458
459 @param Char Character to check.
460
461 @retval TRUE Input value is an ASCII char.
462 @retval FALSE Input value is not an ASCII char.
463
464 **/
465 BOOLEAN
IsValidAscii(IN CHAR16 Char)466 IsValidAscii (
467 IN CHAR16 Char
468 )
469 {
470 if ((Char >= 0x20) && (Char <= 0x7f)) {
471 return TRUE;
472 }
473
474 return FALSE;
475 }
476
477 /**
478 Internal worker function to check whether input value is a unicode control char.
479
480 @param Char Character to check.
481
482 @retval TRUE Input value is a unicode control char.
483 @retval FALSE Input value is not a unicode control char.
484
485 **/
486 BOOLEAN
IsValidEfiCntlChar(IN CHAR16 Char)487 IsValidEfiCntlChar (
488 IN CHAR16 Char
489 )
490 {
491 if (Char == CHAR_NULL || Char == CHAR_BACKSPACE || Char == CHAR_LINEFEED || Char == CHAR_CARRIAGE_RETURN) {
492 return TRUE;
493 }
494
495 return FALSE;
496 }
497
498 /**
499 Tests to see if this driver supports a given controller.
500
501 This function implments EFI_DRIVER_BINDING_PROTOCOL.Supported().
502 It Checks if this driver supports the controller specified. Any Controller
503 with VgaMiniPort Protocol and Pci I/O protocol can be supported.
504
505 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
506 @param ControllerHandle Handle of device to test
507 @param RemainingDevicePath Optional parameter use to pick a specific child
508 device to start.
509
510 @retval EFI_SUCCESS This driver supports this device.
511 @retval EFI_ALREADY_STARTED This driver is already running on this device.
512 @retval EFI_UNSUPPORTED This driver does not support this device.
513
514 **/
515 EFI_STATUS
516 EFIAPI
VgaClassDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)517 VgaClassDriverBindingSupported (
518 IN EFI_DRIVER_BINDING_PROTOCOL *This,
519 IN EFI_HANDLE Controller,
520 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
521 )
522 {
523 EFI_STATUS Status;
524
525 //
526 // Checks if Abstraction(s) needed to perform the supported test
527 //
528 Status = gBS->OpenProtocol (
529 Controller,
530 &gEfiVgaMiniPortProtocolGuid,
531 NULL,
532 This->DriverBindingHandle,
533 Controller,
534 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
535 );
536 if (EFI_ERROR (Status)) {
537 return Status;
538 }
539 //
540 // Open the IO Abstraction(s) needed to perform the supported test
541 //
542 Status = gBS->OpenProtocol (
543 Controller,
544 &gEfiPciIoProtocolGuid,
545 NULL,
546 This->DriverBindingHandle,
547 Controller,
548 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
549 );
550 if (EFI_ERROR (Status)) {
551 return Status;
552 }
553
554 return Status;
555 }
556
557 /**
558 Starts the device controller.
559
560 This function implments EFI_DRIVER_BINDING_PROTOCOL.Start().
561 It starts the device specified by Controller with the driver based on PCI I/O Protocol
562 and VgaMiniPort Protocol. It creates context for device instance and install EFI_SIMPLE_TEXT_OUT_PROTOCOL.
563
564 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
565 @param ControllerHandle Handle of device to bind driver to
566 @param RemainingDevicePath Optional parameter use to pick a specific child
567 device to start.
568
569 @retval EFI_SUCCESS The device was started.
570 @retval other Fail to start the device.
571
572 **/
573 EFI_STATUS
574 EFIAPI
VgaClassDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)575 VgaClassDriverBindingStart (
576 IN EFI_DRIVER_BINDING_PROTOCOL *This,
577 IN EFI_HANDLE Controller,
578 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
579 )
580 {
581 EFI_STATUS Status;
582 EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort;
583 EFI_PCI_IO_PROTOCOL *PciIo;
584 VGA_CLASS_DEV *VgaClassPrivate;
585 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
586
587 Status = gBS->HandleProtocol (
588 Controller,
589 &gEfiDevicePathProtocolGuid,
590 (VOID **) &DevicePath
591 );
592 if (EFI_ERROR (Status)) {
593 return Status;
594 }
595 //
596 // Report that VGA Class driver is being enabled
597 //
598 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
599 EFI_PROGRESS_CODE,
600 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,
601 DevicePath
602 );
603
604 //
605 // Open the PCI I/O Protocol
606 //
607 Status = gBS->OpenProtocol (
608 Controller,
609 &gEfiPciIoProtocolGuid,
610 (VOID **) &PciIo,
611 This->DriverBindingHandle,
612 Controller,
613 EFI_OPEN_PROTOCOL_GET_PROTOCOL
614 );
615 if (EFI_ERROR (Status)) {
616 return Status;
617 }
618 //
619 // Open the VGA Mini Port Protocol
620 //
621 Status = gBS->OpenProtocol (
622 Controller,
623 &gEfiVgaMiniPortProtocolGuid,
624 (VOID **) &VgaMiniPort,
625 This->DriverBindingHandle,
626 Controller,
627 EFI_OPEN_PROTOCOL_BY_DRIVER
628 );
629 if (EFI_ERROR (Status)) {
630 return Status;
631 }
632 //
633 // Allocate the private device structure
634 //
635 VgaClassPrivate = AllocateZeroPool (sizeof (VGA_CLASS_DEV));
636 ASSERT (VgaClassPrivate != NULL);
637
638 //
639 // Initialize the private device structure
640 //
641 VgaClassPrivate->Signature = VGA_CLASS_DEV_SIGNATURE;
642 VgaClassPrivate->Handle = Controller;
643 VgaClassPrivate->VgaMiniPort = VgaMiniPort;
644 VgaClassPrivate->PciIo = PciIo;
645
646 VgaClassPrivate->SimpleTextOut.Reset = VgaClassReset;
647 VgaClassPrivate->SimpleTextOut.OutputString = VgaClassOutputString;
648 VgaClassPrivate->SimpleTextOut.TestString = VgaClassTestString;
649 VgaClassPrivate->SimpleTextOut.ClearScreen = VgaClassClearScreen;
650 VgaClassPrivate->SimpleTextOut.SetAttribute = VgaClassSetAttribute;
651 VgaClassPrivate->SimpleTextOut.SetCursorPosition = VgaClassSetCursorPosition;
652 VgaClassPrivate->SimpleTextOut.EnableCursor = VgaClassEnableCursor;
653 VgaClassPrivate->SimpleTextOut.QueryMode = VgaClassQueryMode;
654 VgaClassPrivate->SimpleTextOut.SetMode = VgaClassSetMode;
655
656 VgaClassPrivate->SimpleTextOut.Mode = &VgaClassPrivate->SimpleTextOutputMode;
657 VgaClassPrivate->SimpleTextOutputMode.MaxMode = VgaMiniPort->MaxMode;
658 VgaClassPrivate->DevicePath = DevicePath;
659
660 //
661 // Initialize the VGA device.
662 //
663 Status = VgaClassPrivate->SimpleTextOut.SetAttribute (
664 &VgaClassPrivate->SimpleTextOut,
665 EFI_TEXT_ATTR (EFI_WHITE, EFI_BLACK)
666 );
667 if (EFI_ERROR (Status)) {
668 goto ErrorExit;
669 }
670
671 Status = VgaClassPrivate->SimpleTextOut.Reset (
672 &VgaClassPrivate->SimpleTextOut,
673 FALSE
674 );
675 if (EFI_ERROR (Status)) {
676 goto ErrorExit;
677 }
678
679 Status = VgaClassPrivate->SimpleTextOut.EnableCursor (
680 &VgaClassPrivate->SimpleTextOut,
681 TRUE
682 );
683 if (EFI_ERROR (Status)) {
684 goto ErrorExit;
685 }
686
687 Status = gBS->InstallMultipleProtocolInterfaces (
688 &Controller,
689 &gEfiSimpleTextOutProtocolGuid,
690 &VgaClassPrivate->SimpleTextOut,
691 NULL
692 );
693
694 return Status;
695
696 ErrorExit:
697 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
698 EFI_ERROR_CODE | EFI_ERROR_MINOR,
699 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
700 DevicePath
701 );
702
703 return Status;
704
705 }
706
707 /**
708 Starts the device controller.
709
710 This function implments EFI_DRIVER_BINDING_PROTOCOL.Stop().
711 It stops this driver on Controller. Support stopping any child handles
712 created by this driver.
713
714 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
715 @param ControllerHandle A handle to the device being stopped.
716 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
717 @param ChildHandleBuffer An array of child handles to be freed.
718
719 @retval EFI_SUCCESS This driver is removed ControllerHandle
720 @retval other This driver was not removed from this device
721
722 **/
723 EFI_STATUS
724 EFIAPI
VgaClassDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL)725 VgaClassDriverBindingStop (
726 IN EFI_DRIVER_BINDING_PROTOCOL *This,
727 IN EFI_HANDLE Controller,
728 IN UINTN NumberOfChildren,
729 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
730 )
731 {
732 EFI_STATUS Status;
733 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
734 VGA_CLASS_DEV *VgaClassPrivate;
735
736 Status = gBS->OpenProtocol (
737 Controller,
738 &gEfiSimpleTextOutProtocolGuid,
739 (VOID **) &SimpleTextOut,
740 This->DriverBindingHandle,
741 Controller,
742 EFI_OPEN_PROTOCOL_GET_PROTOCOL
743 );
744 if (EFI_ERROR (Status)) {
745 return Status;
746 }
747
748 VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (SimpleTextOut);
749
750 //
751 // Report that VGA Class driver is being disabled
752 //
753 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
754 EFI_PROGRESS_CODE,
755 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,
756 VgaClassPrivate->DevicePath
757 );
758
759 Status = gBS->UninstallProtocolInterface (
760 Controller,
761 &gEfiSimpleTextOutProtocolGuid,
762 &VgaClassPrivate->SimpleTextOut
763 );
764 if (EFI_ERROR (Status)) {
765 return Status;
766 }
767 //
768 // Release PCI I/O and VGA Mini Port Protocols on the controller handle.
769 //
770 gBS->CloseProtocol (
771 Controller,
772 &gEfiPciIoProtocolGuid,
773 This->DriverBindingHandle,
774 Controller
775 );
776
777 gBS->CloseProtocol (
778 Controller,
779 &gEfiVgaMiniPortProtocolGuid,
780 This->DriverBindingHandle,
781 Controller
782 );
783
784 FreePool (VgaClassPrivate);
785
786 return EFI_SUCCESS;
787 }
788
789 /**
790 Resets the text output device hardware.
791
792 This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset().
793 It resets the text output device hardware. The cursor position is set to (0, 0),
794 and the screen is cleared to the default background color for the output device.
795
796 @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
797 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
798 verification operation of the device during reset.
799
800 @retval EFI_SUCCESS The text output device was reset.
801 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and could not be reset.
802
803 **/
804 EFI_STATUS
805 EFIAPI
VgaClassReset(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN BOOLEAN ExtendedVerification)806 VgaClassReset (
807 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
808 IN BOOLEAN ExtendedVerification
809 )
810 {
811 EFI_STATUS Status;
812 VGA_CLASS_DEV *VgaClassPrivate;
813
814 VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (This);
815
816 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
817 EFI_PROGRESS_CODE,
818 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_RESET,
819 VgaClassPrivate->DevicePath
820 );
821
822 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));
823
824 Status = This->SetMode (This, 0);
825 if (EFI_ERROR (Status)) {
826 return Status;
827 }
828
829 return This->ClearScreen (This);
830 }
831
832 /**
833 Writes a Unicode string to the output device.
834
835 This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString().
836 It writes a Unicode string to the output device. This is the most basic output mechanism
837 on an output device.
838
839 @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
840 @param String The Null-terminated Unicode string to be displayed on the output device(s).
841
842 @retval EFI_SUCCESS The string was output to the device.
843 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output the text.
844 @retval EFI_UNSUPPORTED The output device's mode is not currently in a defined text mode.
845 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the characters in
846 the Unicode string could not be rendered and were skipped.
847
848 **/
849 EFI_STATUS
850 EFIAPI
VgaClassOutputString(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN CHAR16 * String)851 VgaClassOutputString (
852 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
853 IN CHAR16 *String
854 )
855 {
856 EFI_STATUS Status;
857 VGA_CLASS_DEV *VgaClassDev;
858 EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
859 UINTN MaxColumn;
860 UINTN MaxRow;
861 UINT32 VideoChar;
862 CHAR8 GraphicChar;
863
864 VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
865 Mode = This->Mode;
866
867 Status = This->QueryMode (
868 This,
869 Mode->Mode,
870 &MaxColumn,
871 &MaxRow
872 );
873 if (EFI_ERROR (Status)) {
874 return Status;
875 }
876
877 //
878 // Parse each character of the string to output
879 //
880 for (; *String != CHAR_NULL; String++) {
881
882 switch (*String) {
883 case CHAR_BACKSPACE:
884 if (Mode->CursorColumn > 0) {
885 Mode->CursorColumn--;
886 }
887 break;
888
889 case CHAR_LINEFEED:
890 if (Mode->CursorRow == (INT32) (MaxRow - 1)) {
891 //
892 // Scroll the screen by copying the contents
893 // of the VGA display up one line
894 //
895 VgaClassDev->PciIo->CopyMem (
896 VgaClassDev->PciIo,
897 EfiPciIoWidthUint32,
898 VgaClassDev->VgaMiniPort->VgaMemoryBar,
899 VgaClassDev->VgaMiniPort->VgaMemoryOffset,
900 VgaClassDev->VgaMiniPort->VgaMemoryBar,
901 VgaClassDev->VgaMiniPort->VgaMemoryOffset + MaxColumn * 2,
902 ((MaxRow - 1) * MaxColumn) >> 1
903 );
904
905 //
906 // Print Blank Line of spaces with the current color attributes
907 //
908 VideoChar = (Mode->Attribute << 8) | ' ';
909 VideoChar = (VideoChar << 16) | VideoChar;
910 VgaClassDev->PciIo->Mem.Write (
911 VgaClassDev->PciIo,
912 EfiPciIoWidthFillUint32,
913 VgaClassDev->VgaMiniPort->VgaMemoryBar,
914 VgaClassDev->VgaMiniPort->VgaMemoryOffset + (MaxRow - 1) * MaxColumn * 2,
915 MaxColumn >> 1,
916 &VideoChar
917 );
918 }
919
920 if (Mode->CursorRow < (INT32) (MaxRow - 1)) {
921 Mode->CursorRow++;
922 }
923 break;
924
925 case CHAR_CARRIAGE_RETURN:
926 Mode->CursorColumn = 0;
927 break;
928
929 default:
930 if (!LibIsValidTextGraphics (*String, &GraphicChar, NULL)) {
931 //
932 // If this character is not ,Box Drawing text graphics, then convert it to ASCII.
933 //
934 GraphicChar = (CHAR8) *String;
935 if (!IsValidAscii (GraphicChar)) {
936 //
937 // If not valid ASCII char, convert it to "?"
938 //
939 GraphicChar = '?';
940 }
941 }
942
943 VideoChar = (Mode->Attribute << 8) | GraphicChar;
944 VgaClassDev->PciIo->Mem.Write (
945 VgaClassDev->PciIo,
946 EfiPciIoWidthUint16,
947 VgaClassDev->VgaMiniPort->VgaMemoryBar,
948 VgaClassDev->VgaMiniPort->VgaMemoryOffset + ((Mode->CursorRow * MaxColumn + Mode->CursorColumn) * 2),
949 1,
950 &VideoChar
951 );
952
953 if (Mode->CursorColumn >= (INT32) (MaxColumn - 1)) {
954 This->OutputString (This, CrLfString);
955 } else {
956 Mode->CursorColumn++;
957 }
958 break;
959 }
960 }
961
962 SetVideoCursorPosition (
963 VgaClassDev,
964 (UINTN) Mode->CursorColumn,
965 (UINTN) Mode->CursorRow,
966 MaxColumn
967 );
968
969 return EFI_SUCCESS;
970 }
971
972 /**
973 Verifies that all characters in a Unicode string can be output to the target device.
974
975 This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString().
976 It verifies that all characters in a Unicode string can be output to the target device.
977
978 @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
979 @param String The Null-terminated Unicode string to be examined for the output device(s).
980
981 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
982 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be rendered by
983 one or more of the output devices mapped by the EFI handle.
984
985 **/
986 EFI_STATUS
987 EFIAPI
VgaClassTestString(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN CHAR16 * String)988 VgaClassTestString (
989 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
990 IN CHAR16 *String
991 )
992 {
993 while (*String != CHAR_NULL) {
994 if (!(IsValidAscii (*String) || IsValidEfiCntlChar (*String) || LibIsValidTextGraphics (*String, NULL, NULL))) {
995 return EFI_UNSUPPORTED;
996 }
997
998 String++;
999 }
1000
1001 return EFI_SUCCESS;
1002 }
1003
1004 /**
1005 Clears the output device(s) display to the currently selected background color.
1006
1007 This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen().
1008 The ClearScreen() function clears the output device(s) display to the currently
1009 selected background color. The cursor position is set to (0, 0).
1010
1011 @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
1012
1013 @retval EFI_SUCESS The operation completed successfully.
1014 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
1015 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1016
1017 **/
1018 EFI_STATUS
1019 EFIAPI
VgaClassClearScreen(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This)1020 VgaClassClearScreen (
1021 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
1022 )
1023 {
1024 EFI_STATUS Status;
1025 VGA_CLASS_DEV *VgaClassDev;
1026 UINTN MaxRow;
1027 UINTN MaxColumn;
1028 UINT32 VideoChar;
1029
1030 VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
1031
1032 Status = This->QueryMode (
1033 This,
1034 This->Mode->Mode,
1035 &MaxColumn,
1036 &MaxRow
1037 );
1038 if (EFI_ERROR (Status)) {
1039 return Status;
1040 }
1041
1042 VideoChar = (This->Mode->Attribute << 8) | ' ';
1043 VideoChar = (VideoChar << 16) | VideoChar;
1044 VgaClassDev->PciIo->Mem.Write (
1045 VgaClassDev->PciIo,
1046 EfiPciIoWidthFillUint32,
1047 VgaClassDev->VgaMiniPort->VgaMemoryBar,
1048 VgaClassDev->VgaMiniPort->VgaMemoryOffset,
1049 (MaxRow * MaxColumn) >> 1,
1050 &VideoChar
1051 );
1052
1053 This->SetCursorPosition (This, 0, 0);
1054
1055 return EFI_SUCCESS;
1056 }
1057
1058 /**
1059 Sets the background and foreground colors for theOutputString() and ClearScreen() functions.
1060
1061 This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute().
1062 It sets the background and foreground colors for the OutputString() and ClearScreen() functions.
1063 The color mask can be set even when the device is in an invalid text mode.
1064 Devices supporting a different number of text colors are required to emulate the above colors
1065 to the best of the device's capabilities.
1066
1067 @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
1068 @param Attribute The attribute to set.
1069 Bits 0..3 are the foreground color,
1070 and bits 4..6 are the background color.
1071
1072 @retval EFI_SUCCESS The requested attributes were set.
1073 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
1074
1075 **/
1076 EFI_STATUS
1077 EFIAPI
VgaClassSetAttribute(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN Attribute)1078 VgaClassSetAttribute (
1079 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1080 IN UINTN Attribute
1081 )
1082 {
1083 if (Attribute <= EFI_MAX_ATTRIBUTE) {
1084 This->Mode->Attribute = (INT32) Attribute;
1085 return EFI_SUCCESS;
1086 }
1087
1088 return EFI_UNSUPPORTED;
1089 }
1090
1091 /**
1092 Sets the current coordinates of the cursor position.
1093
1094 This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition().
1095 It sets the current coordinates of the cursor position.
1096 The upper left corner of the screen is defined as coordinate (0, 0).
1097
1098 @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
1099 @param Column Column of position to set the cursor to.
1100 @param Row Row of position to set the cursor to.
1101
1102 @retval EFI_SUCCESS The operation completed successfully.
1103 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
1104 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the cursor
1105 position is invalid for the current mode.
1106
1107 **/
1108 EFI_STATUS
1109 EFIAPI
VgaClassSetCursorPosition(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN Column,IN UINTN Row)1110 VgaClassSetCursorPosition (
1111 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1112 IN UINTN Column,
1113 IN UINTN Row
1114 )
1115 {
1116 EFI_STATUS Status;
1117 VGA_CLASS_DEV *VgaClassDev;
1118 UINTN MaxColumn;
1119 UINTN MaxRow;
1120
1121 VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
1122
1123 Status = This->QueryMode (
1124 This,
1125 This->Mode->Mode,
1126 &MaxColumn,
1127 &MaxRow
1128 );
1129 if (EFI_ERROR (Status)) {
1130 return Status;
1131 }
1132
1133 if (Column >= MaxColumn || Row >= MaxRow) {
1134 return EFI_UNSUPPORTED;
1135 }
1136
1137 SetVideoCursorPosition (VgaClassDev, Column, Row, MaxColumn);
1138
1139 This->Mode->CursorColumn = (INT32) Column;
1140 This->Mode->CursorRow = (INT32) Row;
1141
1142 return EFI_SUCCESS;
1143 }
1144
1145 /**
1146 Makes the cursor visible or invisible.
1147
1148 This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.EnableCursor().
1149 It makes the cursor visible or invisible.
1150
1151 @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
1152 @param Visible If TRUE, the cursor is set to be visible.
1153 If FALSE, the cursor is set to be invisible.
1154
1155 @retval EFI_SUCESS The operation completed successfully.
1156 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request or the
1157 device does not support changing the cursor mode.
1158 @retval EFI_UNSUPPORTED The output device does not support visibility control of the cursor.
1159
1160 **/
1161 EFI_STATUS
1162 EFIAPI
VgaClassEnableCursor(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN BOOLEAN Visible)1163 VgaClassEnableCursor (
1164 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1165 IN BOOLEAN Visible
1166 )
1167 {
1168 VGA_CLASS_DEV *VgaClassDev;
1169
1170 VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
1171 if (Visible) {
1172 if (This->Mode->Mode == 1) {
1173 //
1174 // 80 * 50
1175 //
1176 WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x06);
1177 WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x07);
1178 } else {
1179 //
1180 // 80 * 25
1181 //
1182 WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x0e);
1183 WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x0f);
1184 }
1185 } else {
1186 WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x20);
1187 }
1188
1189 This->Mode->CursorVisible = Visible;
1190 return EFI_SUCCESS;
1191 }
1192
1193 /**
1194 Returns information for an available text mode that the output device(s) supports.
1195
1196 This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode().
1197 It returns information for an available text mode that the output device(s) supports.
1198 It is required that all output devices support at least 80x25 text mode. This mode is defined to be mode 0.
1199 If the output devices support 80x50, that is defined to be mode 1.
1200
1201 @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
1202 @param ModeNumber The mode number to return information on.
1203 @param Columns Columen in current mode number
1204 @param Rows Row in current mode number.
1205
1206 @retval EFI_SUCCESS The requested mode information was returned.
1207 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
1208 @retval EFI_UNSUPPORTED The mode number was not valid.
1209
1210 **/
1211 EFI_STATUS
1212 EFIAPI
VgaClassQueryMode(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN ModeNumber,OUT UINTN * Columns,OUT UINTN * Rows)1213 VgaClassQueryMode (
1214 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1215 IN UINTN ModeNumber,
1216 OUT UINTN *Columns,
1217 OUT UINTN *Rows
1218 )
1219 {
1220 if ((INT32) ModeNumber >= This->Mode->MaxMode) {
1221 *Columns = 0;
1222 *Rows = 0;
1223 return EFI_UNSUPPORTED;
1224 }
1225
1226 switch (ModeNumber) {
1227 case 0:
1228 *Columns = 80;
1229 *Rows = 25;
1230 break;
1231
1232 case 1:
1233 *Columns = 80;
1234 *Rows = 50;
1235 break;
1236
1237 default:
1238 *Columns = 0;
1239 *Rows = 0;
1240 return EFI_UNSUPPORTED;
1241 }
1242
1243 return EFI_SUCCESS;
1244 }
1245
1246 /**
1247 Sets the output device(s) to a specified mode.
1248
1249 This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode().
1250 It sets the output device(s) to the requested mode.
1251 On success the device is in the geometry for the requested mode,
1252 and the device has been cleared to the current background color with the cursor at (0,0).
1253
1254 @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
1255 @param ModeNumber The text mode to set.
1256
1257 @retval EFI_SUCCESS The requested text mode was set.
1258 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
1259 @retval EFI_UNSUPPORTED The mode number was not valid.
1260
1261 **/
1262 EFI_STATUS
1263 EFIAPI
VgaClassSetMode(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN ModeNumber)1264 VgaClassSetMode (
1265 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
1266 IN UINTN ModeNumber
1267 )
1268 {
1269 VGA_CLASS_DEV *VgaClassDev;
1270
1271 VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
1272
1273 if ((INT32) ModeNumber >= This->Mode->MaxMode) {
1274 return EFI_UNSUPPORTED;
1275 }
1276
1277 This->ClearScreen (This);
1278
1279 This->Mode->Mode = (INT32) ModeNumber;
1280
1281 return VgaClassDev->VgaMiniPort->SetMode (VgaClassDev->VgaMiniPort, ModeNumber);
1282 }
1283