]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuVideoDxe/Driver.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Driver.c
1 /** @file
2 This driver is a sample implementation of the Graphics Output Protocol for
3 the QEMU (Cirrus Logic 5446) video controller.
4
5 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "Qemu.h"
12 #include <IndustryStandard/Acpi.h>
13
14 EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {
15 QemuVideoControllerDriverSupported,
16 QemuVideoControllerDriverStart,
17 QemuVideoControllerDriverStop,
18 0x10,
19 NULL,
20 NULL
21 };
22
23 QEMU_VIDEO_CARD gQemuVideoCardList[] = {
24 {
25 PCI_CLASS_DISPLAY_VGA,
26 CIRRUS_LOGIC_VENDOR_ID,
27 CIRRUS_LOGIC_5430_DEVICE_ID,
28 QEMU_VIDEO_CIRRUS_5430,
29 L"Cirrus 5430"
30 },{
31 PCI_CLASS_DISPLAY_VGA,
32 CIRRUS_LOGIC_VENDOR_ID,
33 CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID,
34 QEMU_VIDEO_CIRRUS_5430,
35 L"Cirrus 5430"
36 },{
37 PCI_CLASS_DISPLAY_VGA,
38 CIRRUS_LOGIC_VENDOR_ID,
39 CIRRUS_LOGIC_5446_DEVICE_ID,
40 QEMU_VIDEO_CIRRUS_5446,
41 L"Cirrus 5446"
42 },{
43 PCI_CLASS_DISPLAY_VGA,
44 0x1234,
45 0x1111,
46 QEMU_VIDEO_BOCHS_MMIO,
47 L"QEMU Standard VGA"
48 },{
49 PCI_CLASS_DISPLAY_OTHER,
50 0x1234,
51 0x1111,
52 QEMU_VIDEO_BOCHS_MMIO,
53 L"QEMU Standard VGA (secondary)"
54 },{
55 PCI_CLASS_DISPLAY_VGA,
56 0x1b36,
57 0x0100,
58 QEMU_VIDEO_BOCHS,
59 L"QEMU QXL VGA"
60 },{
61 PCI_CLASS_DISPLAY_VGA,
62 0x1af4,
63 0x1050,
64 QEMU_VIDEO_BOCHS_MMIO,
65 L"QEMU VirtIO VGA"
66 },{
67 PCI_CLASS_DISPLAY_VGA,
68 0x15ad,
69 0x0405,
70 QEMU_VIDEO_VMWARE_SVGA,
71 L"QEMU VMWare SVGA"
72 },{
73 0 /* end of list */
74 }
75 };
76
77 static QEMU_VIDEO_CARD *
78 QemuVideoDetect (
79 IN UINT8 SubClass,
80 IN UINT16 VendorId,
81 IN UINT16 DeviceId
82 )
83 {
84 UINTN Index = 0;
85
86 while (gQemuVideoCardList[Index].VendorId != 0) {
87 if ((gQemuVideoCardList[Index].SubClass == SubClass) &&
88 (gQemuVideoCardList[Index].VendorId == VendorId) &&
89 (gQemuVideoCardList[Index].DeviceId == DeviceId))
90 {
91 return gQemuVideoCardList + Index;
92 }
93
94 Index++;
95 }
96
97 return NULL;
98 }
99
100 /**
101 Check if this device is supported.
102
103 @param This The driver binding protocol.
104 @param Controller The controller handle to check.
105 @param RemainingDevicePath The remaining device path.
106
107 @retval EFI_SUCCESS The bus supports this controller.
108 @retval EFI_UNSUPPORTED This device isn't supported.
109
110 **/
111 EFI_STATUS
112 EFIAPI
113 QemuVideoControllerDriverSupported (
114 IN EFI_DRIVER_BINDING_PROTOCOL *This,
115 IN EFI_HANDLE Controller,
116 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
117 )
118 {
119 EFI_STATUS Status;
120 EFI_PCI_IO_PROTOCOL *PciIo;
121 PCI_TYPE00 Pci;
122 QEMU_VIDEO_CARD *Card;
123
124 //
125 // Open the PCI I/O Protocol
126 //
127 Status = gBS->OpenProtocol (
128 Controller,
129 &gEfiPciIoProtocolGuid,
130 (VOID **)&PciIo,
131 This->DriverBindingHandle,
132 Controller,
133 EFI_OPEN_PROTOCOL_BY_DRIVER
134 );
135 if (EFI_ERROR (Status)) {
136 return Status;
137 }
138
139 //
140 // Read the PCI Configuration Header from the PCI Device
141 //
142 Status = PciIo->Pci.Read (
143 PciIo,
144 EfiPciIoWidthUint32,
145 0,
146 sizeof (Pci) / sizeof (UINT32),
147 &Pci
148 );
149 if (EFI_ERROR (Status)) {
150 goto Done;
151 }
152
153 Status = EFI_UNSUPPORTED;
154 if (!IS_PCI_DISPLAY (&Pci)) {
155 goto Done;
156 }
157
158 Card = QemuVideoDetect (Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);
159 if (Card != NULL) {
160 DEBUG ((DEBUG_INFO, "QemuVideo: %s detected\n", Card->Name));
161 Status = EFI_SUCCESS;
162 }
163
164 Done:
165 //
166 // Close the PCI I/O Protocol
167 //
168 gBS->CloseProtocol (
169 Controller,
170 &gEfiPciIoProtocolGuid,
171 This->DriverBindingHandle,
172 Controller
173 );
174
175 return Status;
176 }
177
178 /**
179 Start to process the controller.
180
181 @param This The USB bus driver binding instance.
182 @param Controller The controller to check.
183 @param RemainingDevicePath The remaining device patch.
184
185 @retval EFI_SUCCESS The controller is controlled by the usb bus.
186 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
187 bus.
188 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
189
190 **/
191 EFI_STATUS
192 EFIAPI
193 QemuVideoControllerDriverStart (
194 IN EFI_DRIVER_BINDING_PROTOCOL *This,
195 IN EFI_HANDLE Controller,
196 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
197 )
198 {
199 EFI_TPL OldTpl;
200 EFI_STATUS Status;
201 QEMU_VIDEO_PRIVATE_DATA *Private;
202 BOOLEAN IsQxl;
203 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
204 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
205 PCI_TYPE00 Pci;
206 QEMU_VIDEO_CARD *Card;
207 EFI_PCI_IO_PROTOCOL *ChildPciIo;
208 UINT64 SupportedVgaIo;
209
210 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
211
212 //
213 // Allocate Private context data for GOP interface.
214 //
215 Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA));
216 if (Private == NULL) {
217 Status = EFI_OUT_OF_RESOURCES;
218 goto RestoreTpl;
219 }
220
221 //
222 // Set up context record
223 //
224 Private->Signature = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE;
225
226 //
227 // Open PCI I/O Protocol
228 //
229 Status = gBS->OpenProtocol (
230 Controller,
231 &gEfiPciIoProtocolGuid,
232 (VOID **)&Private->PciIo,
233 This->DriverBindingHandle,
234 Controller,
235 EFI_OPEN_PROTOCOL_BY_DRIVER
236 );
237 if (EFI_ERROR (Status)) {
238 goto FreePrivate;
239 }
240
241 //
242 // Read the PCI Configuration Header from the PCI Device
243 //
244 Status = Private->PciIo->Pci.Read (
245 Private->PciIo,
246 EfiPciIoWidthUint32,
247 0,
248 sizeof (Pci) / sizeof (UINT32),
249 &Pci
250 );
251 if (EFI_ERROR (Status)) {
252 goto ClosePciIo;
253 }
254
255 //
256 // Determine card variant.
257 //
258 Card = QemuVideoDetect (Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);
259 if (Card == NULL) {
260 Status = EFI_DEVICE_ERROR;
261 goto ClosePciIo;
262 }
263
264 Private->Variant = Card->Variant;
265
266 //
267 // IsQxl is based on the detected Card->Variant, which at a later point might
268 // not match Private->Variant.
269 //
270 IsQxl = (BOOLEAN)(Card->Variant == QEMU_VIDEO_BOCHS);
271
272 //
273 // Save original PCI attributes
274 //
275 Status = Private->PciIo->Attributes (
276 Private->PciIo,
277 EfiPciIoAttributeOperationGet,
278 0,
279 &Private->OriginalPciAttributes
280 );
281
282 if (EFI_ERROR (Status)) {
283 goto ClosePciIo;
284 }
285
286 //
287 // Get supported PCI attributes
288 //
289 Status = Private->PciIo->Attributes (
290 Private->PciIo,
291 EfiPciIoAttributeOperationSupported,
292 0,
293 &SupportedVgaIo
294 );
295 if (EFI_ERROR (Status)) {
296 goto ClosePciIo;
297 }
298
299 SupportedVgaIo &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
300 if ((SupportedVgaIo == 0) && IS_PCI_VGA (&Pci)) {
301 Status = EFI_UNSUPPORTED;
302 goto ClosePciIo;
303 }
304
305 //
306 // Set new PCI attributes
307 //
308 Status = Private->PciIo->Attributes (
309 Private->PciIo,
310 EfiPciIoAttributeOperationEnable,
311 EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | SupportedVgaIo,
312 NULL
313 );
314 if (EFI_ERROR (Status)) {
315 goto ClosePciIo;
316 }
317
318 //
319 // Check whenever the qemu stdvga mmio bar is present (qemu 1.3+).
320 //
321 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
322 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;
323
324 Status = Private->PciIo->GetBarAttributes (
325 Private->PciIo,
326 PCI_BAR_IDX2,
327 NULL,
328 (VOID **)&MmioDesc
329 );
330 if (EFI_ERROR (Status) ||
331 (MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM))
332 {
333 DEBUG ((DEBUG_INFO, "QemuVideo: No mmio bar, fallback to port io\n"));
334 Private->Variant = QEMU_VIDEO_BOCHS;
335 } else {
336 DEBUG ((
337 DEBUG_INFO,
338 "QemuVideo: Using mmio bar @ 0x%lx\n",
339 MmioDesc->AddrRangeMin
340 ));
341 }
342
343 if (!EFI_ERROR (Status)) {
344 FreePool (MmioDesc);
345 }
346 }
347
348 //
349 // VMWare SVGA is handled like Bochs (with port IO only).
350 //
351 if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {
352 Private->Variant = QEMU_VIDEO_BOCHS;
353 Private->FrameBufferVramBarIndex = PCI_BAR_IDX1;
354 }
355
356 //
357 // Check if accessing the bochs interface works.
358 //
359 if ((Private->Variant == QEMU_VIDEO_BOCHS_MMIO) ||
360 (Private->Variant == QEMU_VIDEO_BOCHS))
361 {
362 UINT16 BochsId;
363 BochsId = BochsRead (Private, VBE_DISPI_INDEX_ID);
364 if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {
365 DEBUG ((DEBUG_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId));
366 Status = EFI_DEVICE_ERROR;
367 goto RestoreAttributes;
368 }
369 }
370
371 //
372 // Get ParentDevicePath
373 //
374 Status = gBS->HandleProtocol (
375 Controller,
376 &gEfiDevicePathProtocolGuid,
377 (VOID **)&ParentDevicePath
378 );
379 if (EFI_ERROR (Status)) {
380 goto RestoreAttributes;
381 }
382
383 //
384 // Set Gop Device Path
385 //
386 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
387 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
388 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
389 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
390 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
391
392 Private->GopDevicePath = AppendDevicePathNode (
393 ParentDevicePath,
394 (EFI_DEVICE_PATH_PROTOCOL *)&AcpiDeviceNode
395 );
396 if (Private->GopDevicePath == NULL) {
397 Status = EFI_OUT_OF_RESOURCES;
398 goto RestoreAttributes;
399 }
400
401 //
402 // Create new child handle and install the device path protocol on it.
403 //
404 Status = gBS->InstallMultipleProtocolInterfaces (
405 &Private->Handle,
406 &gEfiDevicePathProtocolGuid,
407 Private->GopDevicePath,
408 NULL
409 );
410 if (EFI_ERROR (Status)) {
411 goto FreeGopDevicePath;
412 }
413
414 //
415 // Construct video mode buffer
416 //
417 switch (Private->Variant) {
418 case QEMU_VIDEO_CIRRUS_5430:
419 case QEMU_VIDEO_CIRRUS_5446:
420 Status = QemuVideoCirrusModeSetup (Private);
421 break;
422 case QEMU_VIDEO_BOCHS_MMIO:
423 case QEMU_VIDEO_BOCHS:
424 Status = QemuVideoBochsModeSetup (Private, IsQxl);
425 break;
426 default:
427 ASSERT (FALSE);
428 Status = EFI_DEVICE_ERROR;
429 break;
430 }
431
432 if (EFI_ERROR (Status)) {
433 goto UninstallGopDevicePath;
434 }
435
436 //
437 // Start the GOP software stack.
438 //
439 Status = QemuVideoGraphicsOutputConstructor (Private);
440 if (EFI_ERROR (Status)) {
441 goto FreeModeData;
442 }
443
444 Status = gBS->InstallMultipleProtocolInterfaces (
445 &Private->Handle,
446 &gEfiGraphicsOutputProtocolGuid,
447 &Private->GraphicsOutput,
448 NULL
449 );
450 if (EFI_ERROR (Status)) {
451 goto DestructQemuVideoGraphics;
452 }
453
454 //
455 // Reference parent handle from child handle.
456 //
457 Status = gBS->OpenProtocol (
458 Controller,
459 &gEfiPciIoProtocolGuid,
460 (VOID **)&ChildPciIo,
461 This->DriverBindingHandle,
462 Private->Handle,
463 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
464 );
465 if (EFI_ERROR (Status)) {
466 goto UninstallGop;
467 }
468
469 #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
470 if ((Private->Variant == QEMU_VIDEO_BOCHS_MMIO) ||
471 (Private->Variant == QEMU_VIDEO_BOCHS))
472 {
473 InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
474 }
475
476 #endif
477
478 gBS->RestoreTPL (OldTpl);
479 return EFI_SUCCESS;
480
481 UninstallGop:
482 gBS->UninstallProtocolInterface (
483 Private->Handle,
484 &gEfiGraphicsOutputProtocolGuid,
485 &Private->GraphicsOutput
486 );
487
488 DestructQemuVideoGraphics:
489 QemuVideoGraphicsOutputDestructor (Private);
490
491 FreeModeData:
492 FreePool (Private->ModeData);
493
494 UninstallGopDevicePath:
495 gBS->UninstallProtocolInterface (
496 Private->Handle,
497 &gEfiDevicePathProtocolGuid,
498 Private->GopDevicePath
499 );
500
501 FreeGopDevicePath:
502 FreePool (Private->GopDevicePath);
503
504 RestoreAttributes:
505 Private->PciIo->Attributes (
506 Private->PciIo,
507 EfiPciIoAttributeOperationSet,
508 Private->OriginalPciAttributes,
509 NULL
510 );
511
512 ClosePciIo:
513 gBS->CloseProtocol (
514 Controller,
515 &gEfiPciIoProtocolGuid,
516 This->DriverBindingHandle,
517 Controller
518 );
519
520 FreePrivate:
521 FreePool (Private);
522
523 RestoreTpl:
524 gBS->RestoreTPL (OldTpl);
525
526 return Status;
527 }
528
529 /**
530 Stop this device
531
532 @param This The USB bus driver binding protocol.
533 @param Controller The controller to release.
534 @param NumberOfChildren The number of children of this device that
535 opened the controller BY_CHILD.
536 @param ChildHandleBuffer The array of child handle.
537
538 @retval EFI_SUCCESS The controller or children are stopped.
539 @retval EFI_DEVICE_ERROR Failed to stop the driver.
540
541 **/
542 EFI_STATUS
543 EFIAPI
544 QemuVideoControllerDriverStop (
545 IN EFI_DRIVER_BINDING_PROTOCOL *This,
546 IN EFI_HANDLE Controller,
547 IN UINTN NumberOfChildren,
548 IN EFI_HANDLE *ChildHandleBuffer
549 )
550 {
551 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
552
553 EFI_STATUS Status;
554 QEMU_VIDEO_PRIVATE_DATA *Private;
555
556 if (NumberOfChildren == 0) {
557 //
558 // Close the PCI I/O Protocol
559 //
560 gBS->CloseProtocol (
561 Controller,
562 &gEfiPciIoProtocolGuid,
563 This->DriverBindingHandle,
564 Controller
565 );
566 return EFI_SUCCESS;
567 }
568
569 //
570 // free all resources for whose access we need the child handle, because the
571 // child handle is going away
572 //
573 ASSERT (NumberOfChildren == 1);
574 Status = gBS->OpenProtocol (
575 ChildHandleBuffer[0],
576 &gEfiGraphicsOutputProtocolGuid,
577 (VOID **)&GraphicsOutput,
578 This->DriverBindingHandle,
579 Controller,
580 EFI_OPEN_PROTOCOL_GET_PROTOCOL
581 );
582 if (EFI_ERROR (Status)) {
583 return Status;
584 }
585
586 //
587 // Get our private context information
588 //
589 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
590 ASSERT (Private->Handle == ChildHandleBuffer[0]);
591
592 QemuVideoGraphicsOutputDestructor (Private);
593 //
594 // Remove the GOP protocol interface from the system
595 //
596 Status = gBS->UninstallMultipleProtocolInterfaces (
597 Private->Handle,
598 &gEfiGraphicsOutputProtocolGuid,
599 &Private->GraphicsOutput,
600 NULL
601 );
602
603 if (EFI_ERROR (Status)) {
604 return Status;
605 }
606
607 //
608 // Restore original PCI attributes
609 //
610 Private->PciIo->Attributes (
611 Private->PciIo,
612 EfiPciIoAttributeOperationSet,
613 Private->OriginalPciAttributes,
614 NULL
615 );
616
617 gBS->CloseProtocol (
618 Controller,
619 &gEfiPciIoProtocolGuid,
620 This->DriverBindingHandle,
621 Private->Handle
622 );
623
624 FreePool (Private->ModeData);
625 gBS->UninstallProtocolInterface (
626 Private->Handle,
627 &gEfiDevicePathProtocolGuid,
628 Private->GopDevicePath
629 );
630 FreePool (Private->GopDevicePath);
631
632 //
633 // Free our instance data
634 //
635 gBS->FreePool (Private);
636
637 return EFI_SUCCESS;
638 }
639
640 /**
641 TODO: Add function description
642
643 @param Private TODO: add argument description
644 @param Address TODO: add argument description
645 @param Data TODO: add argument description
646
647 TODO: add return values
648
649 **/
650 VOID
651 outb (
652 QEMU_VIDEO_PRIVATE_DATA *Private,
653 UINTN Address,
654 UINT8 Data
655 )
656 {
657 Private->PciIo->Io.Write (
658 Private->PciIo,
659 EfiPciIoWidthUint8,
660 EFI_PCI_IO_PASS_THROUGH_BAR,
661 Address,
662 1,
663 &Data
664 );
665 }
666
667 /**
668 TODO: Add function description
669
670 @param Private TODO: add argument description
671 @param Address TODO: add argument description
672 @param Data TODO: add argument description
673
674 TODO: add return values
675
676 **/
677 VOID
678 outw (
679 QEMU_VIDEO_PRIVATE_DATA *Private,
680 UINTN Address,
681 UINT16 Data
682 )
683 {
684 Private->PciIo->Io.Write (
685 Private->PciIo,
686 EfiPciIoWidthUint16,
687 EFI_PCI_IO_PASS_THROUGH_BAR,
688 Address,
689 1,
690 &Data
691 );
692 }
693
694 /**
695 TODO: Add function description
696
697 @param Private TODO: add argument description
698 @param Address TODO: add argument description
699
700 TODO: add return values
701
702 **/
703 UINT8
704 inb (
705 QEMU_VIDEO_PRIVATE_DATA *Private,
706 UINTN Address
707 )
708 {
709 UINT8 Data;
710
711 Private->PciIo->Io.Read (
712 Private->PciIo,
713 EfiPciIoWidthUint8,
714 EFI_PCI_IO_PASS_THROUGH_BAR,
715 Address,
716 1,
717 &Data
718 );
719 return Data;
720 }
721
722 /**
723 TODO: Add function description
724
725 @param Private TODO: add argument description
726 @param Address TODO: add argument description
727
728 TODO: add return values
729
730 **/
731 UINT16
732 inw (
733 QEMU_VIDEO_PRIVATE_DATA *Private,
734 UINTN Address
735 )
736 {
737 UINT16 Data;
738
739 Private->PciIo->Io.Read (
740 Private->PciIo,
741 EfiPciIoWidthUint16,
742 EFI_PCI_IO_PASS_THROUGH_BAR,
743 Address,
744 1,
745 &Data
746 );
747 return Data;
748 }
749
750 /**
751 TODO: Add function description
752
753 @param Private TODO: add argument description
754 @param Index TODO: add argument description
755 @param Red TODO: add argument description
756 @param Green TODO: add argument description
757 @param Blue TODO: add argument description
758
759 TODO: add return values
760
761 **/
762 VOID
763 SetPaletteColor (
764 QEMU_VIDEO_PRIVATE_DATA *Private,
765 UINTN Index,
766 UINT8 Red,
767 UINT8 Green,
768 UINT8 Blue
769 )
770 {
771 VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8)Index);
772 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8)(Red >> 2));
773 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8)(Green >> 2));
774 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8)(Blue >> 2));
775 }
776
777 /**
778 TODO: Add function description
779
780 @param Private TODO: add argument description
781
782 TODO: add return values
783
784 **/
785 VOID
786 SetDefaultPalette (
787 QEMU_VIDEO_PRIVATE_DATA *Private
788 )
789 {
790 UINTN Index;
791 UINTN RedIndex;
792 UINTN GreenIndex;
793 UINTN BlueIndex;
794
795 Index = 0;
796 for (RedIndex = 0; RedIndex < 8; RedIndex++) {
797 for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {
798 for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {
799 SetPaletteColor (Private, Index, (UINT8)(RedIndex << 5), (UINT8)(GreenIndex << 5), (UINT8)(BlueIndex << 6));
800 Index++;
801 }
802 }
803 }
804 }
805
806 /**
807 TODO: Add function description
808
809 @param Private TODO: add argument description
810
811 TODO: add return values
812
813 **/
814 VOID
815 ClearScreen (
816 QEMU_VIDEO_PRIVATE_DATA *Private
817 )
818 {
819 UINT32 Color;
820
821 Color = 0;
822 Private->PciIo->Mem.Write (
823 Private->PciIo,
824 EfiPciIoWidthFillUint32,
825 Private->FrameBufferVramBarIndex,
826 0,
827 0x400000 >> 2,
828 &Color
829 );
830 }
831
832 /**
833 TODO: Add function description
834
835 @param Private TODO: add argument description
836
837 TODO: add return values
838
839 **/
840 VOID
841 DrawLogo (
842 QEMU_VIDEO_PRIVATE_DATA *Private,
843 UINTN ScreenWidth,
844 UINTN ScreenHeight
845 )
846 {
847 }
848
849 /**
850 TODO: Add function description
851
852 @param Private TODO: add argument description
853 @param ModeData TODO: add argument description
854
855 TODO: add return values
856
857 **/
858 VOID
859 InitializeCirrusGraphicsMode (
860 QEMU_VIDEO_PRIVATE_DATA *Private,
861 QEMU_VIDEO_CIRRUS_MODES *ModeData
862 )
863 {
864 UINT8 Byte;
865 UINTN Index;
866
867 outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);
868 outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);
869
870 for (Index = 0; Index < 15; Index++) {
871 outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);
872 }
873
874 if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {
875 outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);
876 Byte = (UINT8)((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);
877 outb (Private, SEQ_DATA_REGISTER, Byte);
878 }
879
880 outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);
881 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);
882 outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);
883 outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);
884
885 for (Index = 0; Index < 28; Index++) {
886 outw (Private, CRTC_ADDRESS_REGISTER, (UINT16)((ModeData->CrtcSettings[Index] << 8) | Index));
887 }
888
889 for (Index = 0; Index < 9; Index++) {
890 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16)((GraphicsController[Index] << 8) | Index));
891 }
892
893 inb (Private, INPUT_STATUS_1_REGISTER);
894
895 for (Index = 0; Index < 21; Index++) {
896 outb (Private, ATT_ADDRESS_REGISTER, (UINT8)Index);
897 outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);
898 }
899
900 outb (Private, ATT_ADDRESS_REGISTER, 0x20);
901
902 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);
903 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);
904 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);
905 outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);
906
907 SetDefaultPalette (Private);
908 ClearScreen (Private);
909 }
910
911 VOID
912 BochsWrite (
913 QEMU_VIDEO_PRIVATE_DATA *Private,
914 UINT16 Reg,
915 UINT16 Data
916 )
917 {
918 EFI_STATUS Status;
919
920 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
921 Status = Private->PciIo->Mem.Write (
922 Private->PciIo,
923 EfiPciIoWidthUint16,
924 PCI_BAR_IDX2,
925 0x500 + (Reg << 1),
926 1,
927 &Data
928 );
929 ASSERT_EFI_ERROR (Status);
930 } else {
931 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
932 outw (Private, VBE_DISPI_IOPORT_DATA, Data);
933 }
934 }
935
936 UINT16
937 BochsRead (
938 QEMU_VIDEO_PRIVATE_DATA *Private,
939 UINT16 Reg
940 )
941 {
942 EFI_STATUS Status;
943 UINT16 Data;
944
945 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
946 Status = Private->PciIo->Mem.Read (
947 Private->PciIo,
948 EfiPciIoWidthUint16,
949 PCI_BAR_IDX2,
950 0x500 + (Reg << 1),
951 1,
952 &Data
953 );
954 ASSERT_EFI_ERROR (Status);
955 } else {
956 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
957 Data = inw (Private, VBE_DISPI_IOPORT_DATA);
958 }
959
960 return Data;
961 }
962
963 VOID
964 VgaOutb (
965 QEMU_VIDEO_PRIVATE_DATA *Private,
966 UINTN Reg,
967 UINT8 Data
968 )
969 {
970 EFI_STATUS Status;
971
972 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
973 Status = Private->PciIo->Mem.Write (
974 Private->PciIo,
975 EfiPciIoWidthUint8,
976 PCI_BAR_IDX2,
977 0x400 - 0x3c0 + Reg,
978 1,
979 &Data
980 );
981 ASSERT_EFI_ERROR (Status);
982 } else {
983 outb (Private, Reg, Data);
984 }
985 }
986
987 VOID
988 InitializeBochsGraphicsMode (
989 QEMU_VIDEO_PRIVATE_DATA *Private,
990 QEMU_VIDEO_MODE_DATA *ModeData
991 )
992 {
993 DEBUG ((
994 DEBUG_INFO,
995 "InitializeBochsGraphicsMode: %dx%d @ %d\n",
996 ModeData->HorizontalResolution,
997 ModeData->VerticalResolution,
998 ModeData->ColorDepth
999 ));
1000
1001 /* unblank */
1002 VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);
1003
1004 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0);
1005 BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);
1006 BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0);
1007 BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0);
1008
1009 BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16)ModeData->ColorDepth);
1010 BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16)ModeData->HorizontalResolution);
1011 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16)ModeData->HorizontalResolution);
1012 BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16)ModeData->VerticalResolution);
1013 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16)ModeData->VerticalResolution);
1014
1015 BochsWrite (
1016 Private,
1017 VBE_DISPI_INDEX_ENABLE,
1018 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED
1019 );
1020
1021 SetDefaultPalette (Private);
1022 ClearScreen (Private);
1023 }
1024
1025 EFI_STATUS
1026 EFIAPI
1027 InitializeQemuVideo (
1028 IN EFI_HANDLE ImageHandle,
1029 IN EFI_SYSTEM_TABLE *SystemTable
1030 )
1031 {
1032 EFI_STATUS Status;
1033
1034 Status = EfiLibInstallDriverBindingComponentName2 (
1035 ImageHandle,
1036 SystemTable,
1037 &gQemuVideoDriverBinding,
1038 ImageHandle,
1039 &gQemuVideoComponentName,
1040 &gQemuVideoComponentName2
1041 );
1042 ASSERT_EFI_ERROR (Status);
1043
1044 return Status;
1045 }