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