]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
Revert "OvmfPkg/PlatformPei: assign PciSize on both i440fx/q35 branches explicitly"
[mirror_edk2.git] / OvmfPkg / VirtioPciDeviceDxe / VirtioPciDevice.c
1 /** @file
2
3 This driver produces Virtio Device Protocol instances for Virtio PCI devices.
4
5 Copyright (C) 2012, Red Hat, Inc.
6 Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
7 Copyright (C) 2013, ARM Ltd.
8 Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
9
10 SPDX-License-Identifier: BSD-2-Clause-Patent
11
12 **/
13
14 #include <IndustryStandard/Pci.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/UefiLib.h>
20
21 #include "VirtioPciDevice.h"
22
23 STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate = {
24 0, // Revision
25 0, // SubSystemDeviceId
26 VirtioPciGetDeviceFeatures, // GetDeviceFeatures
27 VirtioPciSetGuestFeatures, // SetGuestFeatures
28 VirtioPciSetQueueAddress, // SetQueueAddress
29 VirtioPciSetQueueSel, // SetQueueSel
30 VirtioPciSetQueueNotify, // SetQueueNotify
31 VirtioPciSetQueueAlignment, // SetQueueAlignment
32 VirtioPciSetPageSize, // SetPageSize
33 VirtioPciGetQueueSize, // GetQueueNumMax
34 VirtioPciSetQueueSize, // SetQueueNum
35 VirtioPciGetDeviceStatus, // GetDeviceStatus
36 VirtioPciSetDeviceStatus, // SetDeviceStatus
37 VirtioPciDeviceWrite, // WriteDevice
38 VirtioPciDeviceRead, // ReadDevice
39 VirtioPciAllocateSharedPages, // AllocateSharedPages
40 VirtioPciFreeSharedPages, // FreeSharedPages
41 VirtioPciMapSharedBuffer, // MapSharedBuffer
42 VirtioPciUnmapSharedBuffer, // UnmapSharedBuffer
43 };
44
45 /**
46
47 Read a word from Region 0 of the device specified by PciIo.
48
49 Region 0 must be an iomem region. This is an internal function for the PCI
50 implementation of the protocol.
51
52 @param[in] Dev Virtio PCI device.
53
54 @param[in] FieldOffset Source offset.
55
56 @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.
57
58 @param[in] BufferSize Number of bytes available in the target buffer. Must
59 equal FieldSize.
60
61 @param[out] Buffer Target buffer.
62
63
64 @return Status code returned by PciIo->Io.Read().
65
66 **/
67 EFI_STATUS
68 EFIAPI
69 VirtioPciIoRead (
70 IN VIRTIO_PCI_DEVICE *Dev,
71 IN UINTN FieldOffset,
72 IN UINTN FieldSize,
73 IN UINTN BufferSize,
74 OUT VOID *Buffer
75 )
76 {
77 UINTN Count;
78 EFI_PCI_IO_PROTOCOL_WIDTH Width;
79 EFI_PCI_IO_PROTOCOL *PciIo;
80
81 ASSERT (FieldSize == BufferSize);
82
83 PciIo = Dev->PciIo;
84 Count = 1;
85
86 switch (FieldSize) {
87 case 1:
88 Width = EfiPciIoWidthUint8;
89 break;
90
91 case 2:
92 Width = EfiPciIoWidthUint16;
93 break;
94
95 case 8:
96 //
97 // The 64bit PCI I/O is broken down into two 32bit reads to prevent
98 // any alignment or width issues.
99 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():
100 //
101 // The I/O operations are carried out exactly as requested. The caller
102 // is responsible for any alignment and I/O width issues which the
103 // bus, device, platform, or type of I/O might require. For example on
104 // some platforms, width requests of EfiPciIoWidthUint64 do not work.
105 //
106 Count = 2;
107
108 //
109 // fall through
110 //
111 case 4:
112 Width = EfiPciIoWidthUint32;
113 break;
114
115 default:
116 ASSERT (FALSE);
117 return EFI_INVALID_PARAMETER;
118 }
119
120 return PciIo->Io.Read (
121 PciIo,
122 Width,
123 PCI_BAR_IDX0,
124 FieldOffset,
125 Count,
126 Buffer
127 );
128 }
129
130 /**
131
132 Write a word into Region 0 of the device specified by PciIo.
133
134 Region 0 must be an iomem region. This is an internal function for the PCI
135 implementation of the protocol.
136
137 @param[in] Dev Virtio PCI device.
138
139 @param[in] FieldOffset Destination offset.
140
141 @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
142
143 @param[in] Value Little endian value to write, converted to UINT64.
144 The least significant FieldSize bytes will be used.
145
146
147 @return Status code returned by PciIo->Io.Write().
148
149 **/
150 EFI_STATUS
151 EFIAPI
152 VirtioPciIoWrite (
153 IN VIRTIO_PCI_DEVICE *Dev,
154 IN UINTN FieldOffset,
155 IN UINTN FieldSize,
156 IN UINT64 Value
157 )
158 {
159 UINTN Count;
160 EFI_PCI_IO_PROTOCOL_WIDTH Width;
161 EFI_PCI_IO_PROTOCOL *PciIo;
162
163 PciIo = Dev->PciIo;
164 Count = 1;
165
166 switch (FieldSize) {
167 case 1:
168 Width = EfiPciIoWidthUint8;
169 break;
170
171 case 2:
172 Width = EfiPciIoWidthUint16;
173 break;
174
175 case 8:
176 //
177 // The 64bit PCI I/O is broken down into two 32bit writes to prevent
178 // any alignment or width issues.
179 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():
180 //
181 // The I/O operations are carried out exactly as requested. The caller
182 // is responsible for any alignment and I/O width issues which the
183 // bus, device, platform, or type of I/O might require. For example on
184 // some platforms, width requests of EfiPciIoWidthUint64 do not work
185 //
186 Count = Count * 2;
187
188 //
189 // fall through
190 //
191 case 4:
192 Width = EfiPciIoWidthUint32;
193 break;
194
195 default:
196 ASSERT (FALSE);
197 return EFI_INVALID_PARAMETER;
198 }
199
200 return PciIo->Io.Write (
201 PciIo,
202 Width,
203 PCI_BAR_IDX0,
204 FieldOffset,
205 Count,
206 &Value
207 );
208 }
209
210 /**
211
212 Device probe function for this driver.
213
214 The DXE core calls this function for any given device in order to see if the
215 driver can drive the device.
216
217 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
218 incorporating this driver (independently of
219 any device).
220
221 @param[in] DeviceHandle The device to probe.
222
223 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
224
225
226 @retval EFI_SUCCESS The driver supports the device being probed.
227
228 @retval EFI_UNSUPPORTED Based on virtio-pci discovery, we do not support
229 the device.
230
231 @return Error codes from the OpenProtocol() boot service or
232 the PciIo protocol.
233
234 **/
235 STATIC
236 EFI_STATUS
237 EFIAPI
238 VirtioPciDeviceBindingSupported (
239 IN EFI_DRIVER_BINDING_PROTOCOL *This,
240 IN EFI_HANDLE DeviceHandle,
241 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
242 )
243 {
244 EFI_STATUS Status;
245 EFI_PCI_IO_PROTOCOL *PciIo;
246 PCI_TYPE00 Pci;
247
248 //
249 // Attempt to open the device with the PciIo set of interfaces. On success,
250 // the protocol is "instantiated" for the PCI device. Covers duplicate open
251 // attempts (EFI_ALREADY_STARTED).
252 //
253 Status = gBS->OpenProtocol (
254 DeviceHandle, // candidate device
255 &gEfiPciIoProtocolGuid, // for generic PCI access
256 (VOID **)&PciIo, // handle to instantiate
257 This->DriverBindingHandle, // requestor driver identity
258 DeviceHandle, // ControllerHandle, according to
259 // the UEFI Driver Model
260 EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to
261 // the device; to be released
262 );
263 if (EFI_ERROR (Status)) {
264 return Status;
265 }
266
267 //
268 // Read entire PCI configuration header for more extensive check ahead.
269 //
270 Status = PciIo->Pci.Read (
271 PciIo, // (protocol, device)
272 // handle
273 EfiPciIoWidthUint32, // access width & copy
274 // mode
275 0, // Offset
276 sizeof Pci / sizeof (UINT32), // Count
277 &Pci // target buffer
278 );
279
280 if (Status == EFI_SUCCESS) {
281 //
282 // virtio-0.9.5, 2.1 PCI Discovery
283 //
284 if ((Pci.Hdr.VendorId == VIRTIO_VENDOR_ID) &&
285 (Pci.Hdr.DeviceId >= 0x1000) &&
286 (Pci.Hdr.DeviceId <= 0x103F) &&
287 (Pci.Hdr.RevisionID == 0x00)) {
288 Status = EFI_SUCCESS;
289 } else {
290 Status = EFI_UNSUPPORTED;
291 }
292 }
293
294 //
295 // We needed PCI IO access only transitorily, to see whether we support the
296 // device or not.
297 //
298 gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
299 This->DriverBindingHandle, DeviceHandle);
300
301 return Status;
302 }
303
304 /**
305
306 Initialize the VirtIo PCI Device
307
308 @param[in, out] Dev The driver instance to configure. The caller is
309 responsible for Device->PciIo's validity (ie. working IO
310 access to the underlying virtio-pci device).
311
312 @retval EFI_SUCCESS Setup complete.
313
314 @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
315 provided address offset and read size.
316
317 @return Error codes from PciIo->Pci.Read().
318
319 **/
320 STATIC
321 EFI_STATUS
322 EFIAPI
323 VirtioPciInit (
324 IN OUT VIRTIO_PCI_DEVICE *Device
325 )
326 {
327 EFI_STATUS Status;
328 EFI_PCI_IO_PROTOCOL *PciIo;
329 PCI_TYPE00 Pci;
330
331 ASSERT (Device != NULL);
332 PciIo = Device->PciIo;
333 ASSERT (PciIo != NULL);
334 ASSERT (PciIo->Pci.Read != NULL);
335
336 Status = PciIo->Pci.Read (
337 PciIo, // (protocol, device)
338 // handle
339 EfiPciIoWidthUint32, // access width & copy
340 // mode
341 0, // Offset
342 sizeof (Pci) / sizeof (UINT32), // Count
343 &Pci // target buffer
344 );
345 if (EFI_ERROR (Status)) {
346 return Status;
347 }
348
349 //
350 // Copy protocol template
351 //
352 CopyMem (&Device->VirtioDevice, &mDeviceProtocolTemplate,
353 sizeof (VIRTIO_DEVICE_PROTOCOL));
354
355 //
356 // Initialize the protocol interface attributes
357 //
358 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);
359 Device->VirtioDevice.SubSystemDeviceId = Pci.Device.SubsystemID;
360
361 //
362 // Note: We don't support the MSI-X capability. If we did,
363 // the offset would become 24 after enabling MSI-X.
364 //
365 Device->DeviceSpecificConfigurationOffset =
366 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI;
367
368 return EFI_SUCCESS;
369 }
370
371 /**
372
373 Uninitialize the internals of a virtio-pci device that has been successfully
374 set up with VirtioPciInit().
375
376 @param[in, out] Dev The device to clean up.
377
378 **/
379
380 STATIC
381 VOID
382 EFIAPI
383 VirtioPciUninit (
384 IN OUT VIRTIO_PCI_DEVICE *Device
385 )
386 {
387 // Note: This function mirrors VirtioPciInit() that does not allocate any
388 // resources - there's nothing to free here.
389 }
390
391 /**
392
393 After we've pronounced support for a specific device in
394 DriverBindingSupported(), we start managing said device (passed in by the
395 Driver Execution Environment) with the following service.
396
397 See DriverBindingSupported() for specification references.
398
399 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
400 incorporating this driver (independently of
401 any device).
402
403 @param[in] DeviceHandle The supported device to drive.
404
405 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
406
407
408 @retval EFI_SUCCESS Driver instance has been created and
409 initialized for the virtio-pci device, it
410 is now accessible via VIRTIO_DEVICE_PROTOCOL.
411
412 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
413
414 @return Error codes from the OpenProtocol() boot
415 service, the PciIo protocol, VirtioPciInit(),
416 or the InstallProtocolInterface() boot service.
417
418 **/
419 STATIC
420 EFI_STATUS
421 EFIAPI
422 VirtioPciDeviceBindingStart (
423 IN EFI_DRIVER_BINDING_PROTOCOL *This,
424 IN EFI_HANDLE DeviceHandle,
425 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
426 )
427 {
428 VIRTIO_PCI_DEVICE *Device;
429 EFI_STATUS Status;
430
431 Device = (VIRTIO_PCI_DEVICE *) AllocateZeroPool (sizeof *Device);
432 if (Device == NULL) {
433 return EFI_OUT_OF_RESOURCES;
434 }
435
436 Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
437 (VOID **)&Device->PciIo, This->DriverBindingHandle,
438 DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
439 if (EFI_ERROR (Status)) {
440 goto FreeVirtioPci;
441 }
442
443 //
444 // We must retain and ultimately restore the original PCI attributes of the
445 // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
446 // 18.3.2 Start() and Stop().
447 //
448 // The third parameter ("Attributes", input) is ignored by the Get operation.
449 // The fourth parameter ("Result", output) is ignored by the Enable and Set
450 // operations.
451 //
452 // For virtio-pci we only need IO space access.
453 //
454 Status = Device->PciIo->Attributes (Device->PciIo,
455 EfiPciIoAttributeOperationGet, 0, &Device->OriginalPciAttributes);
456 if (EFI_ERROR (Status)) {
457 goto ClosePciIo;
458 }
459
460 Status = Device->PciIo->Attributes (
461 Device->PciIo,
462 EfiPciIoAttributeOperationEnable,
463 (EFI_PCI_IO_ATTRIBUTE_IO |
464 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
465 NULL
466 );
467 if (EFI_ERROR (Status)) {
468 goto ClosePciIo;
469 }
470
471 //
472 // PCI IO access granted, configure protocol instance
473 //
474
475 Status = VirtioPciInit (Device);
476 if (EFI_ERROR (Status)) {
477 goto RestorePciAttributes;
478 }
479
480 //
481 // Setup complete, attempt to export the driver instance's VirtioDevice
482 // interface.
483 //
484 Device->Signature = VIRTIO_PCI_DEVICE_SIGNATURE;
485 Status = gBS->InstallProtocolInterface (&DeviceHandle,
486 &gVirtioDeviceProtocolGuid, EFI_NATIVE_INTERFACE,
487 &Device->VirtioDevice);
488 if (EFI_ERROR (Status)) {
489 goto UninitDev;
490 }
491
492 return EFI_SUCCESS;
493
494 UninitDev:
495 VirtioPciUninit (Device);
496
497 RestorePciAttributes:
498 Device->PciIo->Attributes (Device->PciIo, EfiPciIoAttributeOperationSet,
499 Device->OriginalPciAttributes, NULL);
500
501 ClosePciIo:
502 gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
503 This->DriverBindingHandle, DeviceHandle);
504
505 FreeVirtioPci:
506 FreePool (Device);
507
508 return Status;
509 }
510
511 /**
512
513 Stop driving the Virtio PCI device
514
515 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
516 incorporating this driver (independently of any
517 device).
518
519 @param[in] DeviceHandle Stop driving this device.
520
521 @param[in] NumberOfChildren Since this function belongs to a device driver
522 only (as opposed to a bus driver), the caller
523 environment sets NumberOfChildren to zero, and
524 we ignore it.
525
526 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
527
528 @retval EFI_SUCCESS Driver instance has been stopped and the PCI
529 configuration attributes have been restored.
530
531 @return Error codes from the OpenProtocol() or
532 CloseProtocol(), UninstallProtocolInterface()
533 boot services.
534
535 **/
536 STATIC
537 EFI_STATUS
538 EFIAPI
539 VirtioPciDeviceBindingStop (
540 IN EFI_DRIVER_BINDING_PROTOCOL *This,
541 IN EFI_HANDLE DeviceHandle,
542 IN UINTN NumberOfChildren,
543 IN EFI_HANDLE *ChildHandleBuffer
544 )
545 {
546 EFI_STATUS Status;
547 VIRTIO_DEVICE_PROTOCOL *VirtioDevice;
548 VIRTIO_PCI_DEVICE *Device;
549
550 Status = gBS->OpenProtocol (
551 DeviceHandle, // candidate device
552 &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface
553 (VOID **)&VirtioDevice, // target pointer
554 This->DriverBindingHandle, // requestor driver identity
555 DeviceHandle, // requesting lookup for dev.
556 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added
557 );
558 if (EFI_ERROR (Status)) {
559 return Status;
560 }
561
562 Device = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);
563
564 //
565 // Handle Stop() requests for in-use driver instances gracefully.
566 //
567 Status = gBS->UninstallProtocolInterface (DeviceHandle,
568 &gVirtioDeviceProtocolGuid, &Device->VirtioDevice);
569 if (EFI_ERROR (Status)) {
570 return Status;
571 }
572
573 VirtioPciUninit (Device);
574
575 Device->PciIo->Attributes (Device->PciIo, EfiPciIoAttributeOperationSet,
576 Device->OriginalPciAttributes, NULL);
577
578 Status = gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
579 This->DriverBindingHandle, DeviceHandle);
580
581 FreePool (Device);
582
583 return Status;
584 }
585
586
587 //
588 // The static object that groups the Supported() (ie. probe), Start() and
589 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
590 // C, 10.1 EFI Driver Binding Protocol.
591 //
592 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
593 &VirtioPciDeviceBindingSupported,
594 &VirtioPciDeviceBindingStart,
595 &VirtioPciDeviceBindingStop,
596 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
597 NULL, // ImageHandle, to be overwritten by
598 // EfiLibInstallDriverBindingComponentName2() in VirtioPciEntryPoint()
599 NULL // DriverBindingHandle, ditto
600 };
601
602
603 //
604 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
605 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
606 // in English, for display on standard console devices. This is recommended for
607 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
608 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
609 //
610 STATIC
611 EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
612 { "eng;en", L"Virtio PCI Driver" },
613 { NULL, NULL }
614 };
615
616 STATIC
617 EFI_COMPONENT_NAME_PROTOCOL gComponentName;
618
619 EFI_STATUS
620 EFIAPI
621 VirtioPciGetDriverName (
622 IN EFI_COMPONENT_NAME_PROTOCOL *This,
623 IN CHAR8 *Language,
624 OUT CHAR16 **DriverName
625 )
626 {
627 return LookupUnicodeString2 (
628 Language,
629 This->SupportedLanguages,
630 mDriverNameTable,
631 DriverName,
632 (BOOLEAN)(This == &gComponentName) // Iso639Language
633 );
634 }
635
636 EFI_STATUS
637 EFIAPI
638 VirtioPciGetDeviceName (
639 IN EFI_COMPONENT_NAME_PROTOCOL *This,
640 IN EFI_HANDLE DeviceHandle,
641 IN EFI_HANDLE ChildHandle,
642 IN CHAR8 *Language,
643 OUT CHAR16 **ControllerName
644 )
645 {
646 return EFI_UNSUPPORTED;
647 }
648
649 STATIC
650 EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
651 &VirtioPciGetDriverName,
652 &VirtioPciGetDeviceName,
653 "eng" // SupportedLanguages, ISO 639-2 language codes
654 };
655
656 STATIC
657 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
658 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &VirtioPciGetDriverName,
659 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioPciGetDeviceName,
660 "en" // SupportedLanguages, RFC 4646 language codes
661 };
662
663
664 //
665 // Entry point of this driver.
666 //
667 EFI_STATUS
668 EFIAPI
669 VirtioPciDeviceEntryPoint (
670 IN EFI_HANDLE ImageHandle,
671 IN EFI_SYSTEM_TABLE *SystemTable
672 )
673 {
674 return EfiLibInstallDriverBindingComponentName2 (
675 ImageHandle,
676 SystemTable,
677 &gDriverBinding,
678 ImageHandle,
679 &gComponentName,
680 &gComponentName2
681 );
682 }