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