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