]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
OvmfPkg: Apply uncrustify changes
[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 {
289 Status = EFI_SUCCESS;
290 } else {
291 Status = EFI_UNSUPPORTED;
292 }
293 }
294
295 //
296 // We needed PCI IO access only transitorily, to see whether we support the
297 // device or not.
298 //
299 gBS->CloseProtocol (
300 DeviceHandle,
301 &gEfiPciIoProtocolGuid,
302 This->DriverBindingHandle,
303 DeviceHandle
304 );
305
306 return Status;
307 }
308
309 /**
310
311 Initialize the VirtIo PCI Device
312
313 @param[in, out] Dev The driver instance to configure. The caller is
314 responsible for Device->PciIo's validity (ie. working IO
315 access to the underlying virtio-pci device).
316
317 @retval EFI_SUCCESS Setup complete.
318
319 @retval EFI_UNSUPPORTED The underlying IO device doesn't support the
320 provided address offset and read size.
321
322 @return Error codes from PciIo->Pci.Read().
323
324 **/
325 STATIC
326 EFI_STATUS
327 EFIAPI
328 VirtioPciInit (
329 IN OUT VIRTIO_PCI_DEVICE *Device
330 )
331 {
332 EFI_STATUS Status;
333 EFI_PCI_IO_PROTOCOL *PciIo;
334 PCI_TYPE00 Pci;
335
336 ASSERT (Device != NULL);
337 PciIo = Device->PciIo;
338 ASSERT (PciIo != NULL);
339 ASSERT (PciIo->Pci.Read != NULL);
340
341 Status = PciIo->Pci.Read (
342 PciIo, // (protocol, device)
343 // handle
344 EfiPciIoWidthUint32, // access width & copy
345 // mode
346 0, // Offset
347 sizeof (Pci) / sizeof (UINT32), // Count
348 &Pci // target buffer
349 );
350 if (EFI_ERROR (Status)) {
351 return Status;
352 }
353
354 //
355 // Copy protocol template
356 //
357 CopyMem (
358 &Device->VirtioDevice,
359 &mDeviceProtocolTemplate,
360 sizeof (VIRTIO_DEVICE_PROTOCOL)
361 );
362
363 //
364 // Initialize the protocol interface attributes
365 //
366 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);
367 Device->VirtioDevice.SubSystemDeviceId = Pci.Device.SubsystemID;
368
369 //
370 // Note: We don't support the MSI-X capability. If we did,
371 // the offset would become 24 after enabling MSI-X.
372 //
373 Device->DeviceSpecificConfigurationOffset =
374 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI;
375
376 return EFI_SUCCESS;
377 }
378
379 /**
380
381 Uninitialize the internals of a virtio-pci device that has been successfully
382 set up with VirtioPciInit().
383
384 @param[in, out] Dev The device to clean up.
385
386 **/
387 STATIC
388 VOID
389 EFIAPI
390 VirtioPciUninit (
391 IN OUT VIRTIO_PCI_DEVICE *Device
392 )
393 {
394 // Note: This function mirrors VirtioPciInit() that does not allocate any
395 // resources - there's nothing to free here.
396 }
397
398 /**
399
400 After we've pronounced support for a specific device in
401 DriverBindingSupported(), we start managing said device (passed in by the
402 Driver Execution Environment) with the following service.
403
404 See DriverBindingSupported() for specification references.
405
406 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
407 incorporating this driver (independently of
408 any device).
409
410 @param[in] DeviceHandle The supported device to drive.
411
412 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
413
414
415 @retval EFI_SUCCESS Driver instance has been created and
416 initialized for the virtio-pci device, it
417 is now accessible via VIRTIO_DEVICE_PROTOCOL.
418
419 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
420
421 @return Error codes from the OpenProtocol() boot
422 service, the PciIo protocol, VirtioPciInit(),
423 or the InstallProtocolInterface() boot service.
424
425 **/
426 STATIC
427 EFI_STATUS
428 EFIAPI
429 VirtioPciDeviceBindingStart (
430 IN EFI_DRIVER_BINDING_PROTOCOL *This,
431 IN EFI_HANDLE DeviceHandle,
432 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
433 )
434 {
435 VIRTIO_PCI_DEVICE *Device;
436 EFI_STATUS Status;
437
438 Device = (VIRTIO_PCI_DEVICE *)AllocateZeroPool (sizeof *Device);
439 if (Device == NULL) {
440 return EFI_OUT_OF_RESOURCES;
441 }
442
443 Status = gBS->OpenProtocol (
444 DeviceHandle,
445 &gEfiPciIoProtocolGuid,
446 (VOID **)&Device->PciIo,
447 This->DriverBindingHandle,
448 DeviceHandle,
449 EFI_OPEN_PROTOCOL_BY_DRIVER
450 );
451 if (EFI_ERROR (Status)) {
452 goto FreeVirtioPci;
453 }
454
455 //
456 // We must retain and ultimately restore the original PCI attributes of the
457 // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
458 // 18.3.2 Start() and Stop().
459 //
460 // The third parameter ("Attributes", input) is ignored by the Get operation.
461 // The fourth parameter ("Result", output) is ignored by the Enable and Set
462 // operations.
463 //
464 // For virtio-pci we only need IO space access.
465 //
466 Status = Device->PciIo->Attributes (
467 Device->PciIo,
468 EfiPciIoAttributeOperationGet,
469 0,
470 &Device->OriginalPciAttributes
471 );
472 if (EFI_ERROR (Status)) {
473 goto ClosePciIo;
474 }
475
476 Status = Device->PciIo->Attributes (
477 Device->PciIo,
478 EfiPciIoAttributeOperationEnable,
479 (EFI_PCI_IO_ATTRIBUTE_IO |
480 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
481 NULL
482 );
483 if (EFI_ERROR (Status)) {
484 goto ClosePciIo;
485 }
486
487 //
488 // PCI IO access granted, configure protocol instance
489 //
490
491 Status = VirtioPciInit (Device);
492 if (EFI_ERROR (Status)) {
493 goto RestorePciAttributes;
494 }
495
496 //
497 // Setup complete, attempt to export the driver instance's VirtioDevice
498 // interface.
499 //
500 Device->Signature = VIRTIO_PCI_DEVICE_SIGNATURE;
501 Status = gBS->InstallProtocolInterface (
502 &DeviceHandle,
503 &gVirtioDeviceProtocolGuid,
504 EFI_NATIVE_INTERFACE,
505 &Device->VirtioDevice
506 );
507 if (EFI_ERROR (Status)) {
508 goto UninitDev;
509 }
510
511 return EFI_SUCCESS;
512
513 UninitDev:
514 VirtioPciUninit (Device);
515
516 RestorePciAttributes:
517 Device->PciIo->Attributes (
518 Device->PciIo,
519 EfiPciIoAttributeOperationSet,
520 Device->OriginalPciAttributes,
521 NULL
522 );
523
524 ClosePciIo:
525 gBS->CloseProtocol (
526 DeviceHandle,
527 &gEfiPciIoProtocolGuid,
528 This->DriverBindingHandle,
529 DeviceHandle
530 );
531
532 FreeVirtioPci:
533 FreePool (Device);
534
535 return Status;
536 }
537
538 /**
539
540 Stop driving the Virtio PCI device
541
542 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
543 incorporating this driver (independently of any
544 device).
545
546 @param[in] DeviceHandle Stop driving this device.
547
548 @param[in] NumberOfChildren Since this function belongs to a device driver
549 only (as opposed to a bus driver), the caller
550 environment sets NumberOfChildren to zero, and
551 we ignore it.
552
553 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
554
555 @retval EFI_SUCCESS Driver instance has been stopped and the PCI
556 configuration attributes have been restored.
557
558 @return Error codes from the OpenProtocol() or
559 CloseProtocol(), UninstallProtocolInterface()
560 boot services.
561
562 **/
563 STATIC
564 EFI_STATUS
565 EFIAPI
566 VirtioPciDeviceBindingStop (
567 IN EFI_DRIVER_BINDING_PROTOCOL *This,
568 IN EFI_HANDLE DeviceHandle,
569 IN UINTN NumberOfChildren,
570 IN EFI_HANDLE *ChildHandleBuffer
571 )
572 {
573 EFI_STATUS Status;
574 VIRTIO_DEVICE_PROTOCOL *VirtioDevice;
575 VIRTIO_PCI_DEVICE *Device;
576
577 Status = gBS->OpenProtocol (
578 DeviceHandle, // candidate device
579 &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface
580 (VOID **)&VirtioDevice, // target pointer
581 This->DriverBindingHandle, // requestor driver identity
582 DeviceHandle, // requesting lookup for dev.
583 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added
584 );
585 if (EFI_ERROR (Status)) {
586 return Status;
587 }
588
589 Device = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);
590
591 //
592 // Handle Stop() requests for in-use driver instances gracefully.
593 //
594 Status = gBS->UninstallProtocolInterface (
595 DeviceHandle,
596 &gVirtioDeviceProtocolGuid,
597 &Device->VirtioDevice
598 );
599 if (EFI_ERROR (Status)) {
600 return Status;
601 }
602
603 VirtioPciUninit (Device);
604
605 Device->PciIo->Attributes (
606 Device->PciIo,
607 EfiPciIoAttributeOperationSet,
608 Device->OriginalPciAttributes,
609 NULL
610 );
611
612 Status = gBS->CloseProtocol (
613 DeviceHandle,
614 &gEfiPciIoProtocolGuid,
615 This->DriverBindingHandle,
616 DeviceHandle
617 );
618
619 FreePool (Device);
620
621 return Status;
622 }
623
624 //
625 // The static object that groups the Supported() (ie. probe), Start() and
626 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
627 // C, 10.1 EFI Driver Binding Protocol.
628 //
629 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
630 &VirtioPciDeviceBindingSupported,
631 &VirtioPciDeviceBindingStart,
632 &VirtioPciDeviceBindingStop,
633 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
634 NULL, // ImageHandle, to be overwritten by
635 // EfiLibInstallDriverBindingComponentName2() in VirtioPciEntryPoint()
636 NULL // DriverBindingHandle, ditto
637 };
638
639 //
640 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
641 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
642 // in English, for display on standard console devices. This is recommended for
643 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
644 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
645 //
646 STATIC
647 EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
648 { "eng;en", L"Virtio PCI Driver" },
649 { NULL, NULL }
650 };
651
652 STATIC
653 EFI_COMPONENT_NAME_PROTOCOL gComponentName;
654
655 EFI_STATUS
656 EFIAPI
657 VirtioPciGetDriverName (
658 IN EFI_COMPONENT_NAME_PROTOCOL *This,
659 IN CHAR8 *Language,
660 OUT CHAR16 **DriverName
661 )
662 {
663 return LookupUnicodeString2 (
664 Language,
665 This->SupportedLanguages,
666 mDriverNameTable,
667 DriverName,
668 (BOOLEAN)(This == &gComponentName) // Iso639Language
669 );
670 }
671
672 EFI_STATUS
673 EFIAPI
674 VirtioPciGetDeviceName (
675 IN EFI_COMPONENT_NAME_PROTOCOL *This,
676 IN EFI_HANDLE DeviceHandle,
677 IN EFI_HANDLE ChildHandle,
678 IN CHAR8 *Language,
679 OUT CHAR16 **ControllerName
680 )
681 {
682 return EFI_UNSUPPORTED;
683 }
684
685 STATIC
686 EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
687 &VirtioPciGetDriverName,
688 &VirtioPciGetDeviceName,
689 "eng" // SupportedLanguages, ISO 639-2 language codes
690 };
691
692 STATIC
693 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
694 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&VirtioPciGetDriverName,
695 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&VirtioPciGetDeviceName,
696 "en" // SupportedLanguages, RFC 4646 language codes
697 };
698
699 //
700 // Entry point of this driver.
701 //
702 EFI_STATUS
703 EFIAPI
704 VirtioPciDeviceEntryPoint (
705 IN EFI_HANDLE ImageHandle,
706 IN EFI_SYSTEM_TABLE *SystemTable
707 )
708 {
709 return EfiLibInstallDriverBindingComponentName2 (
710 ImageHandle,
711 SystemTable,
712 &gDriverBinding,
713 ImageHandle,
714 &gComponentName,
715 &gComponentName2
716 );
717 }