VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VmwSvga3Dxe/Driver.c

Last change on this file was 100688, checked in by vboxsync, 10 months ago

Device/EFI/Firmware/VmwSvga3Dxe: Implement enough of the VMware SVGA 3 interface to get a screen output during the UEFI phase, bugref:10490

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.4 KB
Line 
1/** @file
2 This driver is a sample implementation of the Graphics Output Protocol for
3 the VMware SVGA 3 video controller.
4
5 Copyright (c) 2023, Oracle and/or its affiliates.<BR>
6 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10**/
11
12#include "VmwSvga3.h"
13#include <IndustryStandard/Acpi.h>
14
15EFI_DRIVER_BINDING_PROTOCOL gVmwSvga3VideoDriverBinding = {
16 VmwSvga3VideoControllerDriverSupported,
17 VmwSvga3VideoControllerDriverStart,
18 VmwSvga3VideoControllerDriverStop,
19 0x10,
20 NULL,
21 NULL
22};
23
24
25/**
26 Check if this device is supported.
27
28 @param This The driver binding protocol.
29 @param Controller The controller handle to check.
30 @param RemainingDevicePath The remaining device path.
31
32 @retval EFI_SUCCESS The bus supports this controller.
33 @retval EFI_UNSUPPORTED This device isn't supported.
34
35**/
36EFI_STATUS
37EFIAPI
38VmwSvga3VideoControllerDriverSupported (
39 IN EFI_DRIVER_BINDING_PROTOCOL *This,
40 IN EFI_HANDLE Controller,
41 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
42 )
43{
44 EFI_STATUS Status;
45 EFI_PCI_IO_PROTOCOL *PciIo;
46 PCI_TYPE00 Pci;
47
48 //
49 // Open the PCI I/O Protocol
50 //
51 Status = gBS->OpenProtocol (
52 Controller,
53 &gEfiPciIoProtocolGuid,
54 (VOID **)&PciIo,
55 This->DriverBindingHandle,
56 Controller,
57 EFI_OPEN_PROTOCOL_BY_DRIVER
58 );
59 if (EFI_ERROR (Status)) {
60 return Status;
61 }
62
63 //
64 // Read the PCI Configuration Header from the PCI Device
65 //
66 Status = PciIo->Pci.Read (
67 PciIo,
68 EfiPciIoWidthUint32,
69 0,
70 sizeof (Pci) / sizeof (UINT32),
71 &Pci
72 );
73 if (EFI_ERROR (Status)) {
74 goto Done;
75 }
76
77 Status = EFI_UNSUPPORTED;
78 if (!IS_PCI_DISPLAY (&Pci)) {
79 goto Done;
80 }
81
82 if ( Pci.Hdr.ClassCode[1] == PCI_CLASS_DISPLAY_VGA
83 && Pci.Hdr.VendorId == PCI_VENDOR_ID_VMWARE
84 && Pci.Hdr.DeviceId == PCI_DEVICE_ID_VMWARE_SVGA3) {
85 DEBUG ((DEBUG_INFO, "VmwSvga3Video: SVGA3 detected\n"));
86 Status = EFI_SUCCESS;
87 }
88
89Done:
90 //
91 // Close the PCI I/O Protocol
92 //
93 gBS->CloseProtocol (
94 Controller,
95 &gEfiPciIoProtocolGuid,
96 This->DriverBindingHandle,
97 Controller
98 );
99
100 return Status;
101}
102
103/**
104 Start to process the controller.
105
106 @param This The USB bus driver binding instance.
107 @param Controller The controller to check.
108 @param RemainingDevicePath The remaining device patch.
109
110 @retval EFI_SUCCESS The controller is controlled by the usb bus.
111 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
112 bus.
113 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
114
115**/
116EFI_STATUS
117EFIAPI
118VmwSvga3VideoControllerDriverStart (
119 IN EFI_DRIVER_BINDING_PROTOCOL *This,
120 IN EFI_HANDLE Controller,
121 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
122 )
123{
124 EFI_TPL OldTpl;
125 EFI_STATUS Status;
126 VMWSVGA3_VIDEO_PRIVATE_DATA *Private;
127 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
128 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
129 PCI_TYPE00 Pci;
130 EFI_PCI_IO_PROTOCOL *ChildPciIo;
131
132 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
133
134 //
135 // Allocate Private context data for GOP interface.
136 //
137 Private = AllocateZeroPool (sizeof (VMWSVGA3_VIDEO_PRIVATE_DATA));
138 if (Private == NULL) {
139 Status = EFI_OUT_OF_RESOURCES;
140 goto RestoreTpl;
141 }
142
143 //
144 // Set up context record
145 //
146 Private->Signature = VMWSVGA3_VIDEO_PRIVATE_DATA_SIGNATURE;
147
148 //
149 // Open PCI I/O Protocol
150 //
151 Status = gBS->OpenProtocol (
152 Controller,
153 &gEfiPciIoProtocolGuid,
154 (VOID **)&Private->PciIo,
155 This->DriverBindingHandle,
156 Controller,
157 EFI_OPEN_PROTOCOL_BY_DRIVER
158 );
159 if (EFI_ERROR (Status)) {
160 goto FreePrivate;
161 }
162
163 //
164 // Read the PCI Configuration Header from the PCI Device
165 //
166 Status = Private->PciIo->Pci.Read (
167 Private->PciIo,
168 EfiPciIoWidthUint32,
169 0,
170 sizeof (Pci) / sizeof (UINT32),
171 &Pci
172 );
173 if (EFI_ERROR (Status)) {
174 goto ClosePciIo;
175 }
176
177 //
178 // Check whether this a supported device
179 //
180 if ( Pci.Hdr.ClassCode[1] != PCI_CLASS_DISPLAY_VGA
181 || Pci.Hdr.VendorId != PCI_VENDOR_ID_VMWARE
182 || Pci.Hdr.DeviceId != PCI_DEVICE_ID_VMWARE_SVGA3) {
183 Status = EFI_DEVICE_ERROR;
184 goto ClosePciIo;
185 }
186
187 //
188 // Save original PCI attributes
189 //
190 Status = Private->PciIo->Attributes (
191 Private->PciIo,
192 EfiPciIoAttributeOperationGet,
193 0,
194 &Private->OriginalPciAttributes
195 );
196
197 if (EFI_ERROR (Status)) {
198 goto ClosePciIo;
199 }
200
201 //
202 // Set new PCI attributes
203 //
204 Status = Private->PciIo->Attributes (
205 Private->PciIo,
206 EfiPciIoAttributeOperationEnable,
207 (EFI_PCI_DEVICE_ENABLE |
208 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
209 NULL
210 );
211 if (EFI_ERROR (Status)) {
212 goto ClosePciIo;
213 }
214
215 //
216 // Initialize the device.
217 //
218 Status = VmwSvga3DeviceInit(Private);
219 if (EFI_ERROR (Status)) {
220 goto RestoreAttributes;
221 }
222
223 //
224 // Get ParentDevicePath
225 //
226 Status = gBS->HandleProtocol (
227 Controller,
228 &gEfiDevicePathProtocolGuid,
229 (VOID **)&ParentDevicePath
230 );
231 if (EFI_ERROR (Status)) {
232 goto RestoreAttributes;
233 }
234
235 //
236 // Set Gop Device Path
237 //
238 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
239 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
240 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
241 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
242 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
243
244 Private->GopDevicePath = AppendDevicePathNode (
245 ParentDevicePath,
246 (EFI_DEVICE_PATH_PROTOCOL *)&AcpiDeviceNode
247 );
248 if (Private->GopDevicePath == NULL) {
249 Status = EFI_OUT_OF_RESOURCES;
250 goto RestoreAttributes;
251 }
252
253 //
254 // Create new child handle and install the device path protocol on it.
255 //
256 Status = gBS->InstallMultipleProtocolInterfaces (
257 &Private->Handle,
258 &gEfiDevicePathProtocolGuid,
259 Private->GopDevicePath,
260 NULL
261 );
262 if (EFI_ERROR (Status)) {
263 goto FreeGopDevicePath;
264 }
265
266 //
267 // Start the GOP software stack.
268 //
269 Status = VmwSvga3VideoGraphicsOutputConstructor (Private);
270 if (EFI_ERROR (Status)) {
271 goto UninstallGopDevicePath;
272 }
273
274 Status = gBS->InstallMultipleProtocolInterfaces (
275 &Private->Handle,
276 &gEfiGraphicsOutputProtocolGuid,
277 &Private->GraphicsOutput,
278 NULL
279 );
280 if (EFI_ERROR (Status)) {
281 goto DestructVmwSvga3VideoGraphics;
282 }
283
284 //
285 // Reference parent handle from child handle.
286 //
287 Status = gBS->OpenProtocol (
288 Controller,
289 &gEfiPciIoProtocolGuid,
290 (VOID **)&ChildPciIo,
291 This->DriverBindingHandle,
292 Private->Handle,
293 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
294 );
295 if (EFI_ERROR (Status)) {
296 goto UninstallGop;
297 }
298
299 gBS->RestoreTPL (OldTpl);
300 return EFI_SUCCESS;
301
302UninstallGop:
303 gBS->UninstallProtocolInterface (
304 Private->Handle,
305 &gEfiGraphicsOutputProtocolGuid,
306 &Private->GraphicsOutput
307 );
308
309DestructVmwSvga3VideoGraphics:
310 VmwSvga3VideoGraphicsOutputDestructor (Private);
311
312UninstallGopDevicePath:
313 gBS->UninstallProtocolInterface (
314 Private->Handle,
315 &gEfiDevicePathProtocolGuid,
316 Private->GopDevicePath
317 );
318
319FreeGopDevicePath:
320 FreePool (Private->GopDevicePath);
321
322RestoreAttributes:
323 Private->PciIo->Attributes (
324 Private->PciIo,
325 EfiPciIoAttributeOperationSet,
326 Private->OriginalPciAttributes,
327 NULL
328 );
329
330ClosePciIo:
331 gBS->CloseProtocol (
332 Controller,
333 &gEfiPciIoProtocolGuid,
334 This->DriverBindingHandle,
335 Controller
336 );
337
338FreePrivate:
339 FreePool (Private);
340
341RestoreTpl:
342 gBS->RestoreTPL (OldTpl);
343
344 return Status;
345}
346
347/**
348 Stop this device
349
350 @param This The USB bus driver binding protocol.
351 @param Controller The controller to release.
352 @param NumberOfChildren The number of children of this device that
353 opened the controller BY_CHILD.
354 @param ChildHandleBuffer The array of child handle.
355
356 @retval EFI_SUCCESS The controller or children are stopped.
357 @retval EFI_DEVICE_ERROR Failed to stop the driver.
358
359**/
360EFI_STATUS
361EFIAPI
362VmwSvga3VideoControllerDriverStop (
363 IN EFI_DRIVER_BINDING_PROTOCOL *This,
364 IN EFI_HANDLE Controller,
365 IN UINTN NumberOfChildren,
366 IN EFI_HANDLE *ChildHandleBuffer
367 )
368{
369 EFI_STATUS Status;
370 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
371 VMWSVGA3_VIDEO_PRIVATE_DATA *Private;
372
373 if (NumberOfChildren == 0) {
374 //
375 // Close the PCI I/O Protocol
376 //
377 gBS->CloseProtocol (
378 Controller,
379 &gEfiPciIoProtocolGuid,
380 This->DriverBindingHandle,
381 Controller
382 );
383 return EFI_SUCCESS;
384 }
385
386 //
387 // free all resources for whose access we need the child handle, because the
388 // child handle is going away
389 //
390 ASSERT (NumberOfChildren == 1);
391 Status = gBS->OpenProtocol (
392 ChildHandleBuffer[0],
393 &gEfiGraphicsOutputProtocolGuid,
394 (VOID **)&GraphicsOutput,
395 This->DriverBindingHandle,
396 Controller,
397 EFI_OPEN_PROTOCOL_GET_PROTOCOL
398 );
399 if (EFI_ERROR (Status)) {
400 return Status;
401 }
402
403 //
404 // Get our private context information
405 //
406 Private = VMWSVGA3_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
407 ASSERT (Private->Handle == ChildHandleBuffer[0]);
408
409 VmwSvga3VideoGraphicsOutputDestructor (Private);
410 //
411 // Remove the GOP protocol interface from the system
412 //
413 Status = gBS->UninstallMultipleProtocolInterfaces (
414 Private->Handle,
415 &gEfiGraphicsOutputProtocolGuid,
416 &Private->GraphicsOutput,
417 NULL
418 );
419
420 if (EFI_ERROR (Status)) {
421 return Status;
422 }
423
424 //
425 // Teardown the device.
426 //
427 Status = VmwSvga3DeviceUninit (Private);
428 if (EFI_ERROR (Status)) {
429 return Status;
430 }
431
432 //
433 // Restore original PCI attributes
434 //
435 Private->PciIo->Attributes (
436 Private->PciIo,
437 EfiPciIoAttributeOperationSet,
438 Private->OriginalPciAttributes,
439 NULL
440 );
441
442 gBS->CloseProtocol (
443 Controller,
444 &gEfiPciIoProtocolGuid,
445 This->DriverBindingHandle,
446 Private->Handle
447 );
448
449 gBS->UninstallProtocolInterface (
450 Private->Handle,
451 &gEfiDevicePathProtocolGuid,
452 Private->GopDevicePath
453 );
454 FreePool (Private->GopDevicePath);
455
456 //
457 // Free our instance data
458 //
459 gBS->FreePool (Private);
460
461 return EFI_SUCCESS;
462}
463
464EFI_STATUS
465EFIAPI
466InitializeVmwSvga3Video (
467 IN EFI_HANDLE ImageHandle,
468 IN EFI_SYSTEM_TABLE *SystemTable
469 )
470{
471 EFI_STATUS Status;
472
473 Status = EfiLibInstallDriverBindingComponentName2 (
474 ImageHandle,
475 SystemTable,
476 &gVmwSvga3VideoDriverBinding,
477 ImageHandle,
478 &gVmwSvga3VideoComponentName,
479 &gVmwSvga3VideoComponentName2
480 );
481 ASSERT_EFI_ERROR (Status);
482
483 return Status;
484}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use