2 This driver is a sample implementation of the Graphics Output Protocol for
3 the QEMU (Cirrus Logic 5446) video controller.
5 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <IndustryStandard/Acpi.h>
20 EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding
= {
21 QemuVideoControllerDriverSupported
,
22 QemuVideoControllerDriverStart
,
23 QemuVideoControllerDriverStop
,
29 QEMU_VIDEO_CARD gQemuVideoCardList
[] = {
31 CIRRUS_LOGIC_VENDOR_ID
,
32 CIRRUS_LOGIC_5430_DEVICE_ID
,
33 QEMU_VIDEO_CIRRUS_5430
,
36 CIRRUS_LOGIC_VENDOR_ID
,
37 CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID
,
38 QEMU_VIDEO_CIRRUS_5430
,
41 CIRRUS_LOGIC_VENDOR_ID
,
42 CIRRUS_LOGIC_5446_DEVICE_ID
,
43 QEMU_VIDEO_CIRRUS_5446
,
48 QEMU_VIDEO_BOCHS_MMIO
,
58 QEMU_VIDEO_BOCHS_MMIO
,
65 static QEMU_VIDEO_CARD
*
73 while (gQemuVideoCardList
[Index
].VendorId
!= 0) {
74 if (gQemuVideoCardList
[Index
].VendorId
== VendorId
&&
75 gQemuVideoCardList
[Index
].DeviceId
== DeviceId
) {
76 return gQemuVideoCardList
+ Index
;
84 Check if this device is supported.
86 @param This The driver binding protocol.
87 @param Controller The controller handle to check.
88 @param RemainingDevicePath The remaining device path.
90 @retval EFI_SUCCESS The bus supports this controller.
91 @retval EFI_UNSUPPORTED This device isn't supported.
96 QemuVideoControllerDriverSupported (
97 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
98 IN EFI_HANDLE Controller
,
99 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
103 EFI_PCI_IO_PROTOCOL
*PciIo
;
105 QEMU_VIDEO_CARD
*Card
;
108 // Open the PCI I/O Protocol
110 Status
= gBS
->OpenProtocol (
112 &gEfiPciIoProtocolGuid
,
114 This
->DriverBindingHandle
,
116 EFI_OPEN_PROTOCOL_BY_DRIVER
118 if (EFI_ERROR (Status
)) {
123 // Read the PCI Configuration Header from the PCI Device
125 Status
= PciIo
->Pci
.Read (
129 sizeof (Pci
) / sizeof (UINT32
),
132 if (EFI_ERROR (Status
)) {
136 Status
= EFI_UNSUPPORTED
;
137 if (!IS_PCI_VGA (&Pci
)) {
140 Card
= QemuVideoDetect(Pci
.Hdr
.VendorId
, Pci
.Hdr
.DeviceId
);
142 DEBUG ((EFI_D_INFO
, "QemuVideo: %s detected\n", Card
->Name
));
143 Status
= EFI_SUCCESS
;
148 // Close the PCI I/O Protocol
152 &gEfiPciIoProtocolGuid
,
153 This
->DriverBindingHandle
,
161 Start to process the controller.
163 @param This The USB bus driver binding instance.
164 @param Controller The controller to check.
165 @param RemainingDevicePath The remaining device patch.
167 @retval EFI_SUCCESS The controller is controlled by the usb bus.
168 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
170 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
175 QemuVideoControllerDriverStart (
176 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
177 IN EFI_HANDLE Controller
,
178 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
183 QEMU_VIDEO_PRIVATE_DATA
*Private
;
185 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
186 ACPI_ADR_DEVICE_PATH AcpiDeviceNode
;
188 QEMU_VIDEO_CARD
*Card
;
189 EFI_PCI_IO_PROTOCOL
*ChildPciIo
;
191 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
194 // Allocate Private context data for GOP inteface.
196 Private
= AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA
));
197 if (Private
== NULL
) {
198 Status
= EFI_OUT_OF_RESOURCES
;
203 // Set up context record
205 Private
->Signature
= QEMU_VIDEO_PRIVATE_DATA_SIGNATURE
;
208 // Open PCI I/O Protocol
210 Status
= gBS
->OpenProtocol (
212 &gEfiPciIoProtocolGuid
,
213 (VOID
**) &Private
->PciIo
,
214 This
->DriverBindingHandle
,
216 EFI_OPEN_PROTOCOL_BY_DRIVER
218 if (EFI_ERROR (Status
)) {
223 // Read the PCI Configuration Header from the PCI Device
225 Status
= Private
->PciIo
->Pci
.Read (
229 sizeof (Pci
) / sizeof (UINT32
),
232 if (EFI_ERROR (Status
)) {
237 // Determine card variant.
239 Card
= QemuVideoDetect(Pci
.Hdr
.VendorId
, Pci
.Hdr
.DeviceId
);
241 Status
= EFI_DEVICE_ERROR
;
244 Private
->Variant
= Card
->Variant
;
247 // IsQxl is based on the detected Card->Variant, which at a later point might
248 // not match Private->Variant.
250 IsQxl
= (BOOLEAN
)(Card
->Variant
== QEMU_VIDEO_BOCHS
);
253 // Save original PCI attributes
255 Status
= Private
->PciIo
->Attributes (
257 EfiPciIoAttributeOperationGet
,
259 &Private
->OriginalPciAttributes
262 if (EFI_ERROR (Status
)) {
267 // Set new PCI attributes
269 Status
= Private
->PciIo
->Attributes (
271 EfiPciIoAttributeOperationEnable
,
272 EFI_PCI_DEVICE_ENABLE
| EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
| EFI_PCI_IO_ATTRIBUTE_VGA_IO
,
275 if (EFI_ERROR (Status
)) {
280 // Check whenever the qemu stdvga mmio bar is present (qemu 1.3+).
282 if (Private
->Variant
== QEMU_VIDEO_BOCHS_MMIO
) {
283 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*MmioDesc
;
285 Status
= Private
->PciIo
->GetBarAttributes (
291 if (EFI_ERROR (Status
) ||
292 MmioDesc
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_MEM
) {
293 DEBUG ((EFI_D_INFO
, "QemuVideo: No mmio bar, fallback to port io\n"));
294 Private
->Variant
= QEMU_VIDEO_BOCHS
;
296 DEBUG ((EFI_D_INFO
, "QemuVideo: Using mmio bar @ 0x%lx\n",
297 MmioDesc
->AddrRangeMin
));
300 if (!EFI_ERROR (Status
)) {
306 // Check if accessing the bochs interface works.
308 if (Private
->Variant
== QEMU_VIDEO_BOCHS_MMIO
||
309 Private
->Variant
== QEMU_VIDEO_BOCHS
) {
311 BochsId
= BochsRead(Private
, VBE_DISPI_INDEX_ID
);
312 if ((BochsId
& 0xFFF0) != VBE_DISPI_ID0
) {
313 DEBUG ((EFI_D_INFO
, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId
));
314 Status
= EFI_DEVICE_ERROR
;
315 goto RestoreAttributes
;
320 // Get ParentDevicePath
322 Status
= gBS
->HandleProtocol (
324 &gEfiDevicePathProtocolGuid
,
325 (VOID
**) &ParentDevicePath
327 if (EFI_ERROR (Status
)) {
328 goto RestoreAttributes
;
332 // Set Gop Device Path
334 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
335 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
336 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
337 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
338 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
340 Private
->GopDevicePath
= AppendDevicePathNode (
342 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
344 if (Private
->GopDevicePath
== NULL
) {
345 Status
= EFI_OUT_OF_RESOURCES
;
346 goto RestoreAttributes
;
350 // Create new child handle and install the device path protocol on it.
352 Status
= gBS
->InstallMultipleProtocolInterfaces (
354 &gEfiDevicePathProtocolGuid
,
355 Private
->GopDevicePath
,
358 if (EFI_ERROR (Status
)) {
359 goto FreeGopDevicePath
;
363 // Construct video mode buffer
365 switch (Private
->Variant
) {
366 case QEMU_VIDEO_CIRRUS_5430
:
367 case QEMU_VIDEO_CIRRUS_5446
:
368 Status
= QemuVideoCirrusModeSetup (Private
);
370 case QEMU_VIDEO_BOCHS_MMIO
:
371 case QEMU_VIDEO_BOCHS
:
372 Status
= QemuVideoBochsModeSetup (Private
, IsQxl
);
376 Status
= EFI_DEVICE_ERROR
;
379 if (EFI_ERROR (Status
)) {
380 goto UninstallGopDevicePath
;
384 // Start the GOP software stack.
386 Status
= QemuVideoGraphicsOutputConstructor (Private
);
387 if (EFI_ERROR (Status
)) {
391 Status
= gBS
->InstallMultipleProtocolInterfaces (
393 &gEfiGraphicsOutputProtocolGuid
,
394 &Private
->GraphicsOutput
,
397 if (EFI_ERROR (Status
)) {
398 goto DestructQemuVideoGraphics
;
402 // Reference parent handle from child handle.
404 Status
= gBS
->OpenProtocol (
406 &gEfiPciIoProtocolGuid
,
407 (VOID
**) &ChildPciIo
,
408 This
->DriverBindingHandle
,
410 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
412 if (EFI_ERROR (Status
)) {
416 #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
417 if (Private
->Variant
== QEMU_VIDEO_BOCHS_MMIO
||
418 Private
->Variant
== QEMU_VIDEO_BOCHS
) {
419 InstallVbeShim (Card
->Name
, Private
->GraphicsOutput
.Mode
->FrameBufferBase
);
423 gBS
->RestoreTPL (OldTpl
);
427 gBS
->UninstallProtocolInterface (Private
->Handle
,
428 &gEfiGraphicsOutputProtocolGuid
, &Private
->GraphicsOutput
);
430 DestructQemuVideoGraphics
:
431 QemuVideoGraphicsOutputDestructor (Private
);
434 FreePool (Private
->ModeData
);
436 UninstallGopDevicePath
:
437 gBS
->UninstallProtocolInterface (Private
->Handle
,
438 &gEfiDevicePathProtocolGuid
, Private
->GopDevicePath
);
441 FreePool (Private
->GopDevicePath
);
444 Private
->PciIo
->Attributes (Private
->PciIo
, EfiPciIoAttributeOperationSet
,
445 Private
->OriginalPciAttributes
, NULL
);
448 gBS
->CloseProtocol (Controller
, &gEfiPciIoProtocolGuid
,
449 This
->DriverBindingHandle
, Controller
);
455 gBS
->RestoreTPL (OldTpl
);
463 @param This The USB bus driver binding protocol.
464 @param Controller The controller to release.
465 @param NumberOfChildren The number of children of this device that
466 opened the controller BY_CHILD.
467 @param ChildHandleBuffer The array of child handle.
469 @retval EFI_SUCCESS The controller or children are stopped.
470 @retval EFI_DEVICE_ERROR Failed to stop the driver.
475 QemuVideoControllerDriverStop (
476 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
477 IN EFI_HANDLE Controller
,
478 IN UINTN NumberOfChildren
,
479 IN EFI_HANDLE
*ChildHandleBuffer
482 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
485 QEMU_VIDEO_PRIVATE_DATA
*Private
;
487 if (NumberOfChildren
== 0) {
489 // Close the PCI I/O Protocol
493 &gEfiPciIoProtocolGuid
,
494 This
->DriverBindingHandle
,
501 // free all resources for whose access we need the child handle, because the
502 // child handle is going away
504 ASSERT (NumberOfChildren
== 1);
505 Status
= gBS
->OpenProtocol (
506 ChildHandleBuffer
[0],
507 &gEfiGraphicsOutputProtocolGuid
,
508 (VOID
**) &GraphicsOutput
,
509 This
->DriverBindingHandle
,
511 EFI_OPEN_PROTOCOL_GET_PROTOCOL
513 if (EFI_ERROR (Status
)) {
518 // Get our private context information
520 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
521 ASSERT (Private
->Handle
== ChildHandleBuffer
[0]);
523 QemuVideoGraphicsOutputDestructor (Private
);
525 // Remove the GOP protocol interface from the system
527 Status
= gBS
->UninstallMultipleProtocolInterfaces (
529 &gEfiGraphicsOutputProtocolGuid
,
530 &Private
->GraphicsOutput
,
534 if (EFI_ERROR (Status
)) {
539 // Restore original PCI attributes
541 Private
->PciIo
->Attributes (
543 EfiPciIoAttributeOperationSet
,
544 Private
->OriginalPciAttributes
,
550 &gEfiPciIoProtocolGuid
,
551 This
->DriverBindingHandle
,
555 FreePool (Private
->ModeData
);
556 gBS
->UninstallProtocolInterface (Private
->Handle
,
557 &gEfiDevicePathProtocolGuid
, Private
->GopDevicePath
);
558 FreePool (Private
->GopDevicePath
);
561 // Free our instance data
563 gBS
->FreePool (Private
);
569 TODO: Add function description
571 @param Private TODO: add argument description
572 @param Address TODO: add argument description
573 @param Data TODO: add argument description
575 TODO: add return values
580 QEMU_VIDEO_PRIVATE_DATA
*Private
,
585 Private
->PciIo
->Io
.Write (
588 EFI_PCI_IO_PASS_THROUGH_BAR
,
596 TODO: Add function description
598 @param Private TODO: add argument description
599 @param Address TODO: add argument description
600 @param Data TODO: add argument description
602 TODO: add return values
607 QEMU_VIDEO_PRIVATE_DATA
*Private
,
612 Private
->PciIo
->Io
.Write (
615 EFI_PCI_IO_PASS_THROUGH_BAR
,
623 TODO: Add function description
625 @param Private TODO: add argument description
626 @param Address TODO: add argument description
628 TODO: add return values
633 QEMU_VIDEO_PRIVATE_DATA
*Private
,
639 Private
->PciIo
->Io
.Read (
642 EFI_PCI_IO_PASS_THROUGH_BAR
,
651 TODO: Add function description
653 @param Private TODO: add argument description
654 @param Address TODO: add argument description
656 TODO: add return values
661 QEMU_VIDEO_PRIVATE_DATA
*Private
,
667 Private
->PciIo
->Io
.Read (
670 EFI_PCI_IO_PASS_THROUGH_BAR
,
679 TODO: Add function description
681 @param Private TODO: add argument description
682 @param Index TODO: add argument description
683 @param Red TODO: add argument description
684 @param Green TODO: add argument description
685 @param Blue TODO: add argument description
687 TODO: add return values
692 QEMU_VIDEO_PRIVATE_DATA
*Private
,
699 VgaOutb (Private
, PALETTE_INDEX_REGISTER
, (UINT8
) Index
);
700 VgaOutb (Private
, PALETTE_DATA_REGISTER
, (UINT8
) (Red
>> 2));
701 VgaOutb (Private
, PALETTE_DATA_REGISTER
, (UINT8
) (Green
>> 2));
702 VgaOutb (Private
, PALETTE_DATA_REGISTER
, (UINT8
) (Blue
>> 2));
706 TODO: Add function description
708 @param Private TODO: add argument description
710 TODO: add return values
715 QEMU_VIDEO_PRIVATE_DATA
*Private
724 for (RedIndex
= 0; RedIndex
< 8; RedIndex
++) {
725 for (GreenIndex
= 0; GreenIndex
< 8; GreenIndex
++) {
726 for (BlueIndex
= 0; BlueIndex
< 4; BlueIndex
++) {
727 SetPaletteColor (Private
, Index
, (UINT8
) (RedIndex
<< 5), (UINT8
) (GreenIndex
<< 5), (UINT8
) (BlueIndex
<< 6));
735 TODO: Add function description
737 @param Private TODO: add argument description
739 TODO: add return values
744 QEMU_VIDEO_PRIVATE_DATA
*Private
750 Private
->PciIo
->Mem
.Write (
752 EfiPciIoWidthFillUint32
,
761 TODO: Add function description
763 @param Private TODO: add argument description
765 TODO: add return values
770 QEMU_VIDEO_PRIVATE_DATA
*Private
,
778 TODO: Add function description
780 @param Private TODO: add argument description
781 @param ModeData TODO: add argument description
783 TODO: add return values
787 InitializeCirrusGraphicsMode (
788 QEMU_VIDEO_PRIVATE_DATA
*Private
,
789 QEMU_VIDEO_CIRRUS_MODES
*ModeData
795 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x1206);
796 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x0012);
798 for (Index
= 0; Index
< 15; Index
++) {
799 outw (Private
, SEQ_ADDRESS_REGISTER
, ModeData
->SeqSettings
[Index
]);
802 if (Private
->Variant
== QEMU_VIDEO_CIRRUS_5430
) {
803 outb (Private
, SEQ_ADDRESS_REGISTER
, 0x0f);
804 Byte
= (UINT8
) ((inb (Private
, SEQ_DATA_REGISTER
) & 0xc7) ^ 0x30);
805 outb (Private
, SEQ_DATA_REGISTER
, Byte
);
808 outb (Private
, MISC_OUTPUT_REGISTER
, ModeData
->MiscSetting
);
809 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0506);
810 outw (Private
, SEQ_ADDRESS_REGISTER
, 0x0300);
811 outw (Private
, CRTC_ADDRESS_REGISTER
, 0x2011);
813 for (Index
= 0; Index
< 28; Index
++) {
814 outw (Private
, CRTC_ADDRESS_REGISTER
, (UINT16
) ((ModeData
->CrtcSettings
[Index
] << 8) | Index
));
817 for (Index
= 0; Index
< 9; Index
++) {
818 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((GraphicsController
[Index
] << 8) | Index
));
821 inb (Private
, INPUT_STATUS_1_REGISTER
);
823 for (Index
= 0; Index
< 21; Index
++) {
824 outb (Private
, ATT_ADDRESS_REGISTER
, (UINT8
) Index
);
825 outb (Private
, ATT_ADDRESS_REGISTER
, AttributeController
[Index
]);
828 outb (Private
, ATT_ADDRESS_REGISTER
, 0x20);
830 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0009);
831 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x000a);
832 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x000b);
833 outb (Private
, DAC_PIXEL_MASK_REGISTER
, 0xff);
835 SetDefaultPalette (Private
);
836 ClearScreen (Private
);
841 QEMU_VIDEO_PRIVATE_DATA
*Private
,
848 if (Private
->Variant
== QEMU_VIDEO_BOCHS_MMIO
) {
849 Status
= Private
->PciIo
->Mem
.Write (
857 ASSERT_EFI_ERROR (Status
);
859 outw (Private
, VBE_DISPI_IOPORT_INDEX
, Reg
);
860 outw (Private
, VBE_DISPI_IOPORT_DATA
, Data
);
866 QEMU_VIDEO_PRIVATE_DATA
*Private
,
873 if (Private
->Variant
== QEMU_VIDEO_BOCHS_MMIO
) {
874 Status
= Private
->PciIo
->Mem
.Read (
882 ASSERT_EFI_ERROR (Status
);
884 outw (Private
, VBE_DISPI_IOPORT_INDEX
, Reg
);
885 Data
= inw (Private
, VBE_DISPI_IOPORT_DATA
);
892 QEMU_VIDEO_PRIVATE_DATA
*Private
,
899 if (Private
->Variant
== QEMU_VIDEO_BOCHS_MMIO
) {
900 Status
= Private
->PciIo
->Mem
.Write (
908 ASSERT_EFI_ERROR (Status
);
910 outb (Private
, Reg
, Data
);
915 InitializeBochsGraphicsMode (
916 QEMU_VIDEO_PRIVATE_DATA
*Private
,
917 QEMU_VIDEO_BOCHS_MODES
*ModeData
920 DEBUG ((EFI_D_INFO
, "InitializeBochsGraphicsMode: %dx%d @ %d\n",
921 ModeData
->Width
, ModeData
->Height
, ModeData
->ColorDepth
));
924 VgaOutb (Private
, ATT_ADDRESS_REGISTER
, 0x20);
926 BochsWrite (Private
, VBE_DISPI_INDEX_ENABLE
, 0);
927 BochsWrite (Private
, VBE_DISPI_INDEX_BANK
, 0);
928 BochsWrite (Private
, VBE_DISPI_INDEX_X_OFFSET
, 0);
929 BochsWrite (Private
, VBE_DISPI_INDEX_Y_OFFSET
, 0);
931 BochsWrite (Private
, VBE_DISPI_INDEX_BPP
, (UINT16
) ModeData
->ColorDepth
);
932 BochsWrite (Private
, VBE_DISPI_INDEX_XRES
, (UINT16
) ModeData
->Width
);
933 BochsWrite (Private
, VBE_DISPI_INDEX_VIRT_WIDTH
, (UINT16
) ModeData
->Width
);
934 BochsWrite (Private
, VBE_DISPI_INDEX_YRES
, (UINT16
) ModeData
->Height
);
935 BochsWrite (Private
, VBE_DISPI_INDEX_VIRT_HEIGHT
, (UINT16
) ModeData
->Height
);
937 BochsWrite (Private
, VBE_DISPI_INDEX_ENABLE
,
938 VBE_DISPI_ENABLED
| VBE_DISPI_LFB_ENABLED
);
940 SetDefaultPalette (Private
);
941 ClearScreen (Private
);
946 InitializeQemuVideo (
947 IN EFI_HANDLE ImageHandle
,
948 IN EFI_SYSTEM_TABLE
*SystemTable
953 Status
= EfiLibInstallDriverBindingComponentName2 (
956 &gQemuVideoDriverBinding
,
958 &gQemuVideoComponentName
,
959 &gQemuVideoComponentName2
961 ASSERT_EFI_ERROR (Status
);
964 // Install EFI Driver Supported EFI Version Protocol required for
965 // EFI drivers that are on PCI and other plug in cards.
967 gQemuVideoDriverSupportedEfiVersion
.FirmwareVersion
= PcdGet32 (PcdDriverSupportedEfiVersion
);
968 Status
= gBS
->InstallMultipleProtocolInterfaces (
970 &gEfiDriverSupportedEfiVersionProtocolGuid
,
971 &gQemuVideoDriverSupportedEfiVersion
,
974 ASSERT_EFI_ERROR (Status
);