]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Virtio10Dxe/Virtio10.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / Virtio10Dxe / Virtio10.c
1 /** @file
2 A non-transitional driver for VirtIo 1.0 PCI devices.
3
4 Copyright (C) 2016, Red Hat, Inc.
5 Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8 **/
9
10 #include <IndustryStandard/Pci.h>
11 #include <IndustryStandard/Virtio.h>
12 #include <Protocol/PciIo.h>
13 #include <Protocol/PciRootBridgeIo.h>
14 #include <Protocol/VirtioDevice.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/PciCapLib.h>
19 #include <Library/PciCapPciIoLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/UefiLib.h>
22
23 #include "Virtio10.h"
24
25 //
26 // Utility functions
27 //
28
29 /**
30 Transfer data between the caller and a register in a virtio-1.0 register
31 block.
32
33 @param[in] PciIo The EFI_PCI_IO_PROTOCOL instance that represents
34 the device.
35
36 @param[in] Config The "fat pointer" structure that identifies the
37 register block to access.
38
39 @param[in] Write TRUE if the register should be written, FALSE if
40 the register should be read.
41
42 @param[in] FieldOffset The offset of the register within the register
43 block.
44
45 @param[in] FieldSize The size of the register within the register
46 block. Can be one of 1, 2, 4 and 8. Accesses to
47 8-byte registers are broken up into two 4-byte
48 accesses.
49
50 @param[in,out] Buffer When Write is TRUE, the register is written with
51 data from Buffer. When Write is FALSE, the caller
52 receives the register value into Buffer.
53
54 @retval EFI_SUCCESS Register access successful.
55
56 @retval EFI_INVALID_PARAMETER The register block pointed-to by Config
57 doesn't exist; or FieldOffset and FieldSize
58 would overflow the register block; or
59 FieldSize is invalid.
60
61 @return Error codes from
62 EFI_PCI_IO_PROTOCOL.(Io|Mem).(Read|Write)
63 member functions.
64 **/
65 STATIC
66 EFI_STATUS
67 Virtio10Transfer (
68 IN EFI_PCI_IO_PROTOCOL *PciIo,
69 IN VIRTIO_1_0_CONFIG *Config,
70 IN BOOLEAN Write,
71 IN UINTN FieldOffset,
72 IN UINTN FieldSize,
73 IN OUT VOID *Buffer
74 )
75 {
76 UINTN Count;
77 EFI_PCI_IO_PROTOCOL_WIDTH Width;
78 EFI_PCI_IO_PROTOCOL_ACCESS *BarType;
79 EFI_PCI_IO_PROTOCOL_IO_MEM Access;
80
81 if (!Config->Exists ||
82 (FieldSize > Config->Length) ||
83 (FieldOffset > Config->Length - FieldSize))
84 {
85 return EFI_INVALID_PARAMETER;
86 }
87
88 Count = 1;
89 switch (FieldSize) {
90 case 1:
91 Width = EfiPciIoWidthUint8;
92 break;
93
94 case 2:
95 Width = EfiPciIoWidthUint16;
96 break;
97
98 case 8:
99 Count = 2;
100 //
101 // fall through
102 //
103
104 case 4:
105 Width = EfiPciIoWidthUint32;
106 break;
107
108 default:
109 return EFI_INVALID_PARAMETER;
110 }
111
112 BarType = (Config->BarType == Virtio10BarTypeMem) ? &PciIo->Mem : &PciIo->Io;
113 Access = Write ? BarType->Write : BarType->Read;
114
115 return Access (
116 PciIo,
117 Width,
118 Config->Bar,
119 Config->Offset + FieldOffset,
120 Count,
121 Buffer
122 );
123 }
124
125 /**
126 Determine if a PCI BAR is IO or MMIO.
127
128 @param[in] PciIo The EFI_PCI_IO_PROTOCOL instance that represents the
129 device.
130
131 @param[in] BarIndex The number of the BAR whose type the caller is
132 interested in.
133
134 @param[out] BarType On output, a VIRTIO_1_0_BAR_TYPE value that gives the
135 type of the BAR.
136
137 @retval EFI_SUCCESS The BAR type has been recognized and stored in
138 BarType.
139
140 @retval EFI_UNSUPPORTED The BAR type couldn't be identified.
141
142 @return Error codes from
143 EFI_PCI_IO_PROTOCOL.GetBarAttributes().
144 **/
145 STATIC
146 EFI_STATUS
147 GetBarType (
148 IN EFI_PCI_IO_PROTOCOL *PciIo,
149 IN UINT8 BarIndex,
150 OUT VIRTIO_1_0_BAR_TYPE *BarType
151 )
152 {
153 EFI_STATUS Status;
154 VOID *Resources;
155
156 Status = PciIo->GetBarAttributes (PciIo, BarIndex, NULL, &Resources);
157 if (EFI_ERROR (Status)) {
158 return Status;
159 }
160
161 Status = EFI_UNSUPPORTED;
162
163 if (*(UINT8 *)Resources == ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR) {
164 EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
165
166 Descriptor = Resources;
167 switch (Descriptor->ResType) {
168 case ACPI_ADDRESS_SPACE_TYPE_MEM:
169 *BarType = Virtio10BarTypeMem;
170 Status = EFI_SUCCESS;
171 break;
172
173 case ACPI_ADDRESS_SPACE_TYPE_IO:
174 *BarType = Virtio10BarTypeIo;
175 Status = EFI_SUCCESS;
176 break;
177
178 default:
179 break;
180 }
181 }
182
183 FreePool (Resources);
184 return Status;
185 }
186
187 /*
188 Traverse the PCI capabilities list of a virtio-1.0 device, and capture the
189 locations of the interesting virtio-1.0 register blocks.
190
191 @param[in,out] Device The VIRTIO_1_0_DEV structure that identifies
192 the device. On input, the caller is responsible
193 that the Device->PciIo member be live, and that
194 the CommonConfig, NotifyConfig,
195 NotifyOffsetMultiplier and SpecificConfig
196 members be zeroed. On output, said members
197 will have been updated from the PCI
198 capabilities found.
199
200 @retval EFI_SUCCESS Traversal successful.
201
202 @return Error codes from PciCapPciIoLib, PciCapLib, and the
203 GetBarType() helper function.
204 */
205 STATIC
206 EFI_STATUS
207 ParseCapabilities (
208 IN OUT VIRTIO_1_0_DEV *Device
209 )
210 {
211 EFI_STATUS Status;
212 PCI_CAP_DEV *PciDevice;
213 PCI_CAP_LIST *CapList;
214 UINT16 VendorInstance;
215 PCI_CAP *VendorCap;
216
217 Status = PciCapPciIoDeviceInit (Device->PciIo, &PciDevice);
218 if (EFI_ERROR (Status)) {
219 return Status;
220 }
221
222 Status = PciCapListInit (PciDevice, &CapList);
223 if (EFI_ERROR (Status)) {
224 goto UninitPciDevice;
225 }
226
227 for (VendorInstance = 0;
228 !EFI_ERROR (
229 PciCapListFindCap (
230 CapList,
231 PciCapNormal,
232 EFI_PCI_CAPABILITY_ID_VENDOR,
233 VendorInstance,
234 &VendorCap
235 )
236 );
237 VendorInstance++)
238 {
239 UINT8 CapLen;
240 VIRTIO_PCI_CAP VirtIoCap;
241 VIRTIO_1_0_CONFIG *ParsedConfig;
242
243 //
244 // Big enough to accommodate a VIRTIO_PCI_CAP structure?
245 //
246 Status = PciCapRead (
247 PciDevice,
248 VendorCap,
249 OFFSET_OF (EFI_PCI_CAPABILITY_VENDOR_HDR, Length),
250 &CapLen,
251 sizeof CapLen
252 );
253 if (EFI_ERROR (Status)) {
254 goto UninitCapList;
255 }
256
257 if (CapLen < sizeof VirtIoCap) {
258 //
259 // Too small, move to next.
260 //
261 continue;
262 }
263
264 //
265 // Read interesting part of capability.
266 //
267 Status = PciCapRead (PciDevice, VendorCap, 0, &VirtIoCap, sizeof VirtIoCap);
268 if (EFI_ERROR (Status)) {
269 goto UninitCapList;
270 }
271
272 switch (VirtIoCap.ConfigType) {
273 case VIRTIO_PCI_CAP_COMMON_CFG:
274 ParsedConfig = &Device->CommonConfig;
275 break;
276 case VIRTIO_PCI_CAP_NOTIFY_CFG:
277 ParsedConfig = &Device->NotifyConfig;
278 break;
279 case VIRTIO_PCI_CAP_DEVICE_CFG:
280 ParsedConfig = &Device->SpecificConfig;
281 break;
282 default:
283 //
284 // Capability is not interesting.
285 //
286 continue;
287 }
288
289 //
290 // Save the location of the register block into ParsedConfig.
291 //
292 Status = GetBarType (Device->PciIo, VirtIoCap.Bar, &ParsedConfig->BarType);
293 if (EFI_ERROR (Status)) {
294 goto UninitCapList;
295 }
296
297 ParsedConfig->Bar = VirtIoCap.Bar;
298 ParsedConfig->Offset = VirtIoCap.Offset;
299 ParsedConfig->Length = VirtIoCap.Length;
300
301 if (VirtIoCap.ConfigType == VIRTIO_PCI_CAP_NOTIFY_CFG) {
302 //
303 // This capability has an additional field called NotifyOffsetMultiplier;
304 // parse it too.
305 //
306 if (CapLen < sizeof VirtIoCap + sizeof Device->NotifyOffsetMultiplier) {
307 //
308 // Too small, move to next.
309 //
310 continue;
311 }
312
313 Status = PciCapRead (
314 PciDevice,
315 VendorCap,
316 sizeof VirtIoCap,
317 &Device->NotifyOffsetMultiplier,
318 sizeof Device->NotifyOffsetMultiplier
319 );
320 if (EFI_ERROR (Status)) {
321 goto UninitCapList;
322 }
323 }
324
325 //
326 // Capability parsed successfully.
327 //
328 ParsedConfig->Exists = TRUE;
329 }
330
331 ASSERT_EFI_ERROR (Status);
332
333 UninitCapList:
334 PciCapListUninit (CapList);
335
336 UninitPciDevice:
337 PciCapPciIoDeviceUninit (PciDevice);
338
339 return Status;
340 }
341
342 /**
343 Accumulate the BAR type of a virtio-1.0 register block into a UINT64
344 attribute map, such that the latter is suitable for enabling IO / MMIO
345 decoding with EFI_PCI_IO_PROTOCOL.Attributes().
346
347 @param[in] Config The "fat pointer" structure that identifies the
348 register block. It is allowed for the register
349 block not to exist.
350
351 @param[in,out] Attributes On output, if the register block exists,
352 EFI_PCI_IO_ATTRIBUTE_MEMORY or
353 EFI_PCI_IO_ATTRIBUTE_IO is OR-ed into Attributes,
354 according to the register block's BAR type.
355 **/
356 STATIC
357 VOID
358 UpdateAttributes (
359 IN VIRTIO_1_0_CONFIG *Config,
360 IN OUT UINT64 *Attributes
361 )
362 {
363 if (Config->Exists) {
364 *Attributes |= (Config->BarType == Virtio10BarTypeMem) ?
365 EFI_PCI_IO_ATTRIBUTE_MEMORY :
366 EFI_PCI_IO_ATTRIBUTE_IO;
367 }
368 }
369
370 //
371 // VIRTIO_DEVICE_PROTOCOL member functions
372 //
373
374 STATIC
375 EFI_STATUS
376 EFIAPI
377 Virtio10GetDeviceFeatures (
378 IN VIRTIO_DEVICE_PROTOCOL *This,
379 OUT UINT64 *DeviceFeatures
380 )
381 {
382 VIRTIO_1_0_DEV *Dev;
383 UINT32 Selector;
384 UINT32 Features32[2];
385
386 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
387
388 for (Selector = 0; Selector < 2; ++Selector) {
389 EFI_STATUS Status;
390
391 //
392 // Select the low or high half of the features.
393 //
394 Status = Virtio10Transfer (
395 Dev->PciIo,
396 &Dev->CommonConfig,
397 TRUE,
398 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceFeatureSelect),
399 sizeof Selector,
400 &Selector
401 );
402 if (EFI_ERROR (Status)) {
403 return Status;
404 }
405
406 //
407 // Fetch that half.
408 //
409 Status = Virtio10Transfer (
410 Dev->PciIo,
411 &Dev->CommonConfig,
412 FALSE,
413 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceFeature),
414 sizeof Features32[Selector],
415 &Features32[Selector]
416 );
417 if (EFI_ERROR (Status)) {
418 return Status;
419 }
420 }
421
422 *DeviceFeatures = LShiftU64 (Features32[1], 32) | Features32[0];
423 return EFI_SUCCESS;
424 }
425
426 STATIC
427 EFI_STATUS
428 EFIAPI
429 Virtio10SetGuestFeatures (
430 IN VIRTIO_DEVICE_PROTOCOL *This,
431 IN UINT64 Features
432 )
433 {
434 VIRTIO_1_0_DEV *Dev;
435 UINT32 Selector;
436 UINT32 Features32[2];
437
438 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
439
440 Features32[0] = (UINT32)Features;
441 Features32[1] = (UINT32)RShiftU64 (Features, 32);
442
443 for (Selector = 0; Selector < 2; ++Selector) {
444 EFI_STATUS Status;
445
446 //
447 // Select the low or high half of the features.
448 //
449 Status = Virtio10Transfer (
450 Dev->PciIo,
451 &Dev->CommonConfig,
452 TRUE,
453 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DriverFeatureSelect),
454 sizeof Selector,
455 &Selector
456 );
457 if (EFI_ERROR (Status)) {
458 return Status;
459 }
460
461 //
462 // Write that half.
463 //
464 Status = Virtio10Transfer (
465 Dev->PciIo,
466 &Dev->CommonConfig,
467 TRUE,
468 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DriverFeature),
469 sizeof Features32[Selector],
470 &Features32[Selector]
471 );
472 if (EFI_ERROR (Status)) {
473 return Status;
474 }
475 }
476
477 return EFI_SUCCESS;
478 }
479
480 STATIC
481 EFI_STATUS
482 EFIAPI
483 Virtio10SetQueueAddress (
484 IN VIRTIO_DEVICE_PROTOCOL *This,
485 IN VRING *Ring,
486 IN UINT64 RingBaseShift
487 )
488 {
489 VIRTIO_1_0_DEV *Dev;
490 EFI_STATUS Status;
491 UINT64 Address;
492 UINT16 Enable;
493
494 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
495
496 Address = (UINTN)Ring->Desc;
497 Address += RingBaseShift;
498 Status = Virtio10Transfer (
499 Dev->PciIo,
500 &Dev->CommonConfig,
501 TRUE,
502 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueDesc),
503 sizeof Address,
504 &Address
505 );
506 if (EFI_ERROR (Status)) {
507 return Status;
508 }
509
510 Address = (UINTN)Ring->Avail.Flags;
511 Address += RingBaseShift;
512 Status = Virtio10Transfer (
513 Dev->PciIo,
514 &Dev->CommonConfig,
515 TRUE,
516 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueAvail),
517 sizeof Address,
518 &Address
519 );
520 if (EFI_ERROR (Status)) {
521 return Status;
522 }
523
524 Address = (UINTN)Ring->Used.Flags;
525 Address += RingBaseShift;
526 Status = Virtio10Transfer (
527 Dev->PciIo,
528 &Dev->CommonConfig,
529 TRUE,
530 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueUsed),
531 sizeof Address,
532 &Address
533 );
534 if (EFI_ERROR (Status)) {
535 return Status;
536 }
537
538 Enable = 1;
539 Status = Virtio10Transfer (
540 Dev->PciIo,
541 &Dev->CommonConfig,
542 TRUE,
543 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueEnable),
544 sizeof Enable,
545 &Enable
546 );
547 return Status;
548 }
549
550 STATIC
551 EFI_STATUS
552 EFIAPI
553 Virtio10SetQueueSel (
554 IN VIRTIO_DEVICE_PROTOCOL *This,
555 IN UINT16 Index
556 )
557 {
558 VIRTIO_1_0_DEV *Dev;
559 EFI_STATUS Status;
560
561 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
562
563 Status = Virtio10Transfer (
564 Dev->PciIo,
565 &Dev->CommonConfig,
566 TRUE,
567 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect),
568 sizeof Index,
569 &Index
570 );
571 return Status;
572 }
573
574 STATIC
575 EFI_STATUS
576 EFIAPI
577 Virtio10SetQueueNotify (
578 IN VIRTIO_DEVICE_PROTOCOL *This,
579 IN UINT16 Index
580 )
581 {
582 VIRTIO_1_0_DEV *Dev;
583 EFI_STATUS Status;
584 UINT16 SavedQueueSelect;
585 UINT16 NotifyOffset;
586
587 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
588
589 //
590 // Read NotifyOffset first. NotifyOffset is queue specific, so we have
591 // to stash & restore the current queue selector around it.
592 //
593 // So, start with saving the current queue selector.
594 //
595 Status = Virtio10Transfer (
596 Dev->PciIo,
597 &Dev->CommonConfig,
598 FALSE,
599 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect),
600 sizeof SavedQueueSelect,
601 &SavedQueueSelect
602 );
603 if (EFI_ERROR (Status)) {
604 return Status;
605 }
606
607 //
608 // Select the requested queue.
609 //
610 Status = Virtio10Transfer (
611 Dev->PciIo,
612 &Dev->CommonConfig,
613 TRUE,
614 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect),
615 sizeof Index,
616 &Index
617 );
618 if (EFI_ERROR (Status)) {
619 return Status;
620 }
621
622 //
623 // Read the QueueNotifyOff field.
624 //
625 Status = Virtio10Transfer (
626 Dev->PciIo,
627 &Dev->CommonConfig,
628 FALSE,
629 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueNotifyOff),
630 sizeof NotifyOffset,
631 &NotifyOffset
632 );
633 if (EFI_ERROR (Status)) {
634 return Status;
635 }
636
637 //
638 // Re-select the original queue.
639 //
640 Status = Virtio10Transfer (
641 Dev->PciIo,
642 &Dev->CommonConfig,
643 TRUE,
644 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect),
645 sizeof SavedQueueSelect,
646 &SavedQueueSelect
647 );
648 if (EFI_ERROR (Status)) {
649 return Status;
650 }
651
652 //
653 // We can now kick the queue.
654 //
655 Status = Virtio10Transfer (
656 Dev->PciIo,
657 &Dev->NotifyConfig,
658 TRUE,
659 NotifyOffset * Dev->NotifyOffsetMultiplier,
660 sizeof Index,
661 &Index
662 );
663 return Status;
664 }
665
666 STATIC
667 EFI_STATUS
668 EFIAPI
669 Virtio10SetQueueAlign (
670 IN VIRTIO_DEVICE_PROTOCOL *This,
671 IN UINT32 Alignment
672 )
673 {
674 return (Alignment == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
675 }
676
677 STATIC
678 EFI_STATUS
679 EFIAPI
680 Virtio10SetPageSize (
681 IN VIRTIO_DEVICE_PROTOCOL *This,
682 IN UINT32 PageSize
683 )
684 {
685 return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
686 }
687
688 STATIC
689 EFI_STATUS
690 EFIAPI
691 Virtio10GetQueueNumMax (
692 IN VIRTIO_DEVICE_PROTOCOL *This,
693 OUT UINT16 *QueueNumMax
694 )
695 {
696 VIRTIO_1_0_DEV *Dev;
697 EFI_STATUS Status;
698
699 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
700
701 Status = Virtio10Transfer (
702 Dev->PciIo,
703 &Dev->CommonConfig,
704 FALSE,
705 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSize),
706 sizeof *QueueNumMax,
707 QueueNumMax
708 );
709 return Status;
710 }
711
712 STATIC
713 EFI_STATUS
714 EFIAPI
715 Virtio10SetQueueNum (
716 IN VIRTIO_DEVICE_PROTOCOL *This,
717 IN UINT16 QueueSize
718 )
719 {
720 EFI_STATUS Status;
721 UINT16 CurrentSize;
722
723 //
724 // This member function is required for VirtIo MMIO, and a no-op in
725 // VirtIo PCI 0.9.5. In VirtIo 1.0, drivers can theoretically use this
726 // member to reduce memory consumption, but none of our drivers do. So
727 // just check that they set the size that is already in effect.
728 //
729 Status = Virtio10GetQueueNumMax (This, &CurrentSize);
730 if (EFI_ERROR (Status)) {
731 return Status;
732 }
733
734 return (CurrentSize == QueueSize) ? EFI_SUCCESS : EFI_UNSUPPORTED;
735 }
736
737 STATIC
738 EFI_STATUS
739 EFIAPI
740 Virtio10GetDeviceStatus (
741 IN VIRTIO_DEVICE_PROTOCOL *This,
742 OUT UINT8 *DeviceStatus
743 )
744 {
745 VIRTIO_1_0_DEV *Dev;
746 EFI_STATUS Status;
747
748 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
749
750 Status = Virtio10Transfer (
751 Dev->PciIo,
752 &Dev->CommonConfig,
753 FALSE,
754 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceStatus),
755 sizeof *DeviceStatus,
756 DeviceStatus
757 );
758 return Status;
759 }
760
761 STATIC
762 EFI_STATUS
763 EFIAPI
764 Virtio10SetDeviceStatus (
765 IN VIRTIO_DEVICE_PROTOCOL *This,
766 IN UINT8 DeviceStatus
767 )
768 {
769 VIRTIO_1_0_DEV *Dev;
770 EFI_STATUS Status;
771
772 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
773
774 Status = Virtio10Transfer (
775 Dev->PciIo,
776 &Dev->CommonConfig,
777 TRUE,
778 OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceStatus),
779 sizeof DeviceStatus,
780 &DeviceStatus
781 );
782 return Status;
783 }
784
785 STATIC
786 EFI_STATUS
787 EFIAPI
788 Virtio10WriteDevice (
789 IN VIRTIO_DEVICE_PROTOCOL *This,
790 IN UINTN FieldOffset,
791 IN UINTN FieldSize,
792 IN UINT64 Value
793 )
794 {
795 VIRTIO_1_0_DEV *Dev;
796 EFI_STATUS Status;
797
798 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
799
800 Status = Virtio10Transfer (
801 Dev->PciIo,
802 &Dev->SpecificConfig,
803 TRUE,
804 FieldOffset,
805 FieldSize,
806 &Value
807 );
808 return Status;
809 }
810
811 STATIC
812 EFI_STATUS
813 EFIAPI
814 Virtio10ReadDevice (
815 IN VIRTIO_DEVICE_PROTOCOL *This,
816 IN UINTN FieldOffset,
817 IN UINTN FieldSize,
818 IN UINTN BufferSize,
819 OUT VOID *Buffer
820 )
821 {
822 VIRTIO_1_0_DEV *Dev;
823 EFI_STATUS Status;
824
825 if (FieldSize != BufferSize) {
826 return EFI_INVALID_PARAMETER;
827 }
828
829 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
830
831 Status = Virtio10Transfer (
832 Dev->PciIo,
833 &Dev->SpecificConfig,
834 FALSE,
835 FieldOffset,
836 FieldSize,
837 Buffer
838 );
839 return Status;
840 }
841
842 STATIC
843 EFI_STATUS
844 EFIAPI
845 Virtio10AllocateSharedPages (
846 IN VIRTIO_DEVICE_PROTOCOL *This,
847 IN UINTN Pages,
848 IN OUT VOID **HostAddress
849 )
850 {
851 VIRTIO_1_0_DEV *Dev;
852 EFI_STATUS Status;
853
854 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
855
856 Status = Dev->PciIo->AllocateBuffer (
857 Dev->PciIo,
858 AllocateAnyPages,
859 EfiBootServicesData,
860 Pages,
861 HostAddress,
862 EFI_PCI_ATTRIBUTE_MEMORY_CACHED
863 );
864 return Status;
865 }
866
867 STATIC
868 VOID
869 EFIAPI
870 Virtio10FreeSharedPages (
871 IN VIRTIO_DEVICE_PROTOCOL *This,
872 IN UINTN Pages,
873 IN VOID *HostAddress
874 )
875 {
876 VIRTIO_1_0_DEV *Dev;
877
878 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
879
880 Dev->PciIo->FreeBuffer (
881 Dev->PciIo,
882 Pages,
883 HostAddress
884 );
885 }
886
887 STATIC
888 EFI_STATUS
889 EFIAPI
890 Virtio10MapSharedBuffer (
891 IN VIRTIO_DEVICE_PROTOCOL *This,
892 IN VIRTIO_MAP_OPERATION Operation,
893 IN VOID *HostAddress,
894 IN OUT UINTN *NumberOfBytes,
895 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
896 OUT VOID **Mapping
897 )
898 {
899 EFI_STATUS Status;
900 VIRTIO_1_0_DEV *Dev;
901 EFI_PCI_IO_PROTOCOL_OPERATION PciIoOperation;
902
903 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
904
905 //
906 // Map VIRTIO_MAP_OPERATION to EFI_PCI_IO_PROTOCOL_OPERATION
907 //
908 switch (Operation) {
909 case VirtioOperationBusMasterRead:
910 PciIoOperation = EfiPciIoOperationBusMasterRead;
911 break;
912 case VirtioOperationBusMasterWrite:
913 PciIoOperation = EfiPciIoOperationBusMasterWrite;
914 break;
915 case VirtioOperationBusMasterCommonBuffer:
916 PciIoOperation = EfiPciIoOperationBusMasterCommonBuffer;
917 break;
918 default:
919 return EFI_INVALID_PARAMETER;
920 }
921
922 Status = Dev->PciIo->Map (
923 Dev->PciIo,
924 PciIoOperation,
925 HostAddress,
926 NumberOfBytes,
927 DeviceAddress,
928 Mapping
929 );
930 return Status;
931 }
932
933 STATIC
934 EFI_STATUS
935 EFIAPI
936 Virtio10UnmapSharedBuffer (
937 IN VIRTIO_DEVICE_PROTOCOL *This,
938 IN VOID *Mapping
939 )
940 {
941 EFI_STATUS Status;
942 VIRTIO_1_0_DEV *Dev;
943
944 Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
945
946 Status = Dev->PciIo->Unmap (
947 Dev->PciIo,
948 Mapping
949 );
950
951 return Status;
952 }
953
954 STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = {
955 VIRTIO_SPEC_REVISION (1, 0, 0),
956 0, // SubSystemDeviceId, filled in dynamically
957 Virtio10GetDeviceFeatures,
958 Virtio10SetGuestFeatures,
959 Virtio10SetQueueAddress,
960 Virtio10SetQueueSel,
961 Virtio10SetQueueNotify,
962 Virtio10SetQueueAlign,
963 Virtio10SetPageSize,
964 Virtio10GetQueueNumMax,
965 Virtio10SetQueueNum,
966 Virtio10GetDeviceStatus,
967 Virtio10SetDeviceStatus,
968 Virtio10WriteDevice,
969 Virtio10ReadDevice,
970 Virtio10AllocateSharedPages,
971 Virtio10FreeSharedPages,
972 Virtio10MapSharedBuffer,
973 Virtio10UnmapSharedBuffer
974 };
975
976 //
977 // EFI_DRIVER_BINDING_PROTOCOL member functions
978 //
979
980 STATIC
981 EFI_STATUS
982 EFIAPI
983 Virtio10BindingSupported (
984 IN EFI_DRIVER_BINDING_PROTOCOL *This,
985 IN EFI_HANDLE DeviceHandle,
986 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
987 )
988 {
989 EFI_STATUS Status;
990 EFI_PCI_IO_PROTOCOL *PciIo;
991 PCI_TYPE00 Pci;
992
993 Status = gBS->OpenProtocol (
994 DeviceHandle,
995 &gEfiPciIoProtocolGuid,
996 (VOID **)&PciIo,
997 This->DriverBindingHandle,
998 DeviceHandle,
999 EFI_OPEN_PROTOCOL_BY_DRIVER
1000 );
1001 if (EFI_ERROR (Status)) {
1002 return Status;
1003 }
1004
1005 Status = PciIo->Pci.Read (
1006 PciIo,
1007 EfiPciIoWidthUint32,
1008 0,
1009 sizeof Pci / sizeof (UINT32),
1010 &Pci
1011 );
1012 if (EFI_ERROR (Status)) {
1013 goto CloseProtocol;
1014 }
1015
1016 Status = EFI_UNSUPPORTED;
1017 //
1018 // Recognize non-transitional modern devices. Also, we'll have to parse the
1019 // PCI capability list, so make sure the CapabilityPtr field will be valid.
1020 //
1021 if ((Pci.Hdr.VendorId == VIRTIO_VENDOR_ID) &&
1022 (Pci.Hdr.DeviceId >= 0x1040) &&
1023 (Pci.Hdr.DeviceId <= 0x107F) &&
1024 (Pci.Hdr.RevisionID >= 0x01) &&
1025 (Pci.Device.SubsystemID >= 0x40) &&
1026 ((Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) != 0))
1027 {
1028 //
1029 // The virtio-vga device is special. It can be driven both as a VGA device
1030 // with a linear framebuffer, and through its underlying, modern,
1031 // virtio-gpu-pci device, which has no linear framebuffer itself. For
1032 // compatibility with guest OSes that insist on inheriting a linear
1033 // framebuffer from the firmware, we should leave virtio-vga to
1034 // QemuVideoDxe, and support only virtio-gpu-pci here.
1035 //
1036 // Both virtio-vga and virtio-gpu-pci have DeviceId 0x1050, but only the
1037 // former has device class PCI_CLASS_DISPLAY_VGA.
1038 //
1039 if ((Pci.Hdr.DeviceId != 0x1050) || !IS_PCI_VGA (&Pci)) {
1040 Status = EFI_SUCCESS;
1041 }
1042 }
1043
1044 CloseProtocol:
1045 gBS->CloseProtocol (
1046 DeviceHandle,
1047 &gEfiPciIoProtocolGuid,
1048 This->DriverBindingHandle,
1049 DeviceHandle
1050 );
1051
1052 return Status;
1053 }
1054
1055 STATIC
1056 EFI_STATUS
1057 EFIAPI
1058 Virtio10BindingStart (
1059 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1060 IN EFI_HANDLE DeviceHandle,
1061 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1062 )
1063 {
1064 VIRTIO_1_0_DEV *Device;
1065 EFI_STATUS Status;
1066 PCI_TYPE00 Pci;
1067 UINT64 SetAttributes;
1068
1069 Device = AllocateZeroPool (sizeof *Device);
1070 if (Device == NULL) {
1071 return EFI_OUT_OF_RESOURCES;
1072 }
1073
1074 Device->Signature = VIRTIO_1_0_SIGNATURE;
1075 CopyMem (&Device->VirtIo, &mVirtIoTemplate, sizeof mVirtIoTemplate);
1076
1077 Status = gBS->OpenProtocol (
1078 DeviceHandle,
1079 &gEfiPciIoProtocolGuid,
1080 (VOID **)&Device->PciIo,
1081 This->DriverBindingHandle,
1082 DeviceHandle,
1083 EFI_OPEN_PROTOCOL_BY_DRIVER
1084 );
1085 if (EFI_ERROR (Status)) {
1086 goto FreeDevice;
1087 }
1088
1089 Status = Device->PciIo->Pci.Read (
1090 Device->PciIo,
1091 EfiPciIoWidthUint32,
1092 0,
1093 sizeof Pci / sizeof (UINT32),
1094 &Pci
1095 );
1096 if (EFI_ERROR (Status)) {
1097 goto ClosePciIo;
1098 }
1099
1100 Device->VirtIo.SubSystemDeviceId = Pci.Hdr.DeviceId - 0x1040;
1101
1102 Status = ParseCapabilities (Device);
1103 if (EFI_ERROR (Status)) {
1104 goto ClosePciIo;
1105 }
1106
1107 Status = Device->PciIo->Attributes (
1108 Device->PciIo,
1109 EfiPciIoAttributeOperationGet,
1110 0,
1111 &Device->OriginalPciAttributes
1112 );
1113 if (EFI_ERROR (Status)) {
1114 goto ClosePciIo;
1115 }
1116
1117 SetAttributes = (EFI_PCI_IO_ATTRIBUTE_BUS_MASTER |
1118 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
1119 UpdateAttributes (&Device->CommonConfig, &SetAttributes);
1120 UpdateAttributes (&Device->NotifyConfig, &SetAttributes);
1121 UpdateAttributes (&Device->SpecificConfig, &SetAttributes);
1122 Status = Device->PciIo->Attributes (
1123 Device->PciIo,
1124 EfiPciIoAttributeOperationEnable,
1125 SetAttributes,
1126 NULL
1127 );
1128 if (EFI_ERROR (Status)) {
1129 goto ClosePciIo;
1130 }
1131
1132 Status = gBS->InstallProtocolInterface (
1133 &DeviceHandle,
1134 &gVirtioDeviceProtocolGuid,
1135 EFI_NATIVE_INTERFACE,
1136 &Device->VirtIo
1137 );
1138 if (EFI_ERROR (Status)) {
1139 goto RestorePciAttributes;
1140 }
1141
1142 return EFI_SUCCESS;
1143
1144 RestorePciAttributes:
1145 Device->PciIo->Attributes (
1146 Device->PciIo,
1147 EfiPciIoAttributeOperationSet,
1148 Device->OriginalPciAttributes,
1149 NULL
1150 );
1151
1152 ClosePciIo:
1153 gBS->CloseProtocol (
1154 DeviceHandle,
1155 &gEfiPciIoProtocolGuid,
1156 This->DriverBindingHandle,
1157 DeviceHandle
1158 );
1159
1160 FreeDevice:
1161 FreePool (Device);
1162
1163 return Status;
1164 }
1165
1166 STATIC
1167 EFI_STATUS
1168 EFIAPI
1169 Virtio10BindingStop (
1170 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1171 IN EFI_HANDLE DeviceHandle,
1172 IN UINTN NumberOfChildren,
1173 IN EFI_HANDLE *ChildHandleBuffer
1174 )
1175 {
1176 EFI_STATUS Status;
1177 VIRTIO_DEVICE_PROTOCOL *VirtIo;
1178 VIRTIO_1_0_DEV *Device;
1179
1180 Status = gBS->OpenProtocol (
1181 DeviceHandle,
1182 &gVirtioDeviceProtocolGuid,
1183 (VOID **)&VirtIo,
1184 This->DriverBindingHandle,
1185 DeviceHandle,
1186 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1187 );
1188 if (EFI_ERROR (Status)) {
1189 return Status;
1190 }
1191
1192 Device = VIRTIO_1_0_FROM_VIRTIO_DEVICE (VirtIo);
1193
1194 Status = gBS->UninstallProtocolInterface (
1195 DeviceHandle,
1196 &gVirtioDeviceProtocolGuid,
1197 &Device->VirtIo
1198 );
1199 if (EFI_ERROR (Status)) {
1200 return Status;
1201 }
1202
1203 Device->PciIo->Attributes (
1204 Device->PciIo,
1205 EfiPciIoAttributeOperationSet,
1206 Device->OriginalPciAttributes,
1207 NULL
1208 );
1209 gBS->CloseProtocol (
1210 DeviceHandle,
1211 &gEfiPciIoProtocolGuid,
1212 This->DriverBindingHandle,
1213 DeviceHandle
1214 );
1215 FreePool (Device);
1216
1217 return EFI_SUCCESS;
1218 }
1219
1220 STATIC EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = {
1221 &Virtio10BindingSupported,
1222 &Virtio10BindingStart,
1223 &Virtio10BindingStop,
1224 0x10, // Version
1225 NULL, // ImageHandle, to be overwritten
1226 NULL // DriverBindingHandle, to be overwritten
1227 };
1228
1229 //
1230 // EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PROTOCOL
1231 // implementations
1232 //
1233
1234 STATIC
1235 EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
1236 { "eng;en", L"Virtio 1.0 PCI Driver" },
1237 { NULL, NULL }
1238 };
1239
1240 STATIC
1241 EFI_COMPONENT_NAME_PROTOCOL mComponentName;
1242
1243 STATIC
1244 EFI_STATUS
1245 EFIAPI
1246 Virtio10GetDriverName (
1247 IN EFI_COMPONENT_NAME_PROTOCOL *This,
1248 IN CHAR8 *Language,
1249 OUT CHAR16 **DriverName
1250 )
1251 {
1252 return LookupUnicodeString2 (
1253 Language,
1254 This->SupportedLanguages,
1255 mDriverNameTable,
1256 DriverName,
1257 (BOOLEAN)(This == &mComponentName) // Iso639Language
1258 );
1259 }
1260
1261 STATIC
1262 EFI_STATUS
1263 EFIAPI
1264 Virtio10GetDeviceName (
1265 IN EFI_COMPONENT_NAME_PROTOCOL *This,
1266 IN EFI_HANDLE DeviceHandle,
1267 IN EFI_HANDLE ChildHandle,
1268 IN CHAR8 *Language,
1269 OUT CHAR16 **ControllerName
1270 )
1271 {
1272 return EFI_UNSUPPORTED;
1273 }
1274
1275 STATIC
1276 EFI_COMPONENT_NAME_PROTOCOL mComponentName = {
1277 &Virtio10GetDriverName,
1278 &Virtio10GetDeviceName,
1279 "eng"
1280 };
1281
1282 STATIC
1283 EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {
1284 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&Virtio10GetDriverName,
1285 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&Virtio10GetDeviceName,
1286 "en"
1287 };
1288
1289 //
1290 // Entry point of this driver
1291 //
1292
1293 EFI_STATUS
1294 EFIAPI
1295 Virtio10EntryPoint (
1296 IN EFI_HANDLE ImageHandle,
1297 IN EFI_SYSTEM_TABLE *SystemTable
1298 )
1299 {
1300 return EfiLibInstallDriverBindingComponentName2 (
1301 ImageHandle,
1302 SystemTable,
1303 &mDriverBinding,
1304 ImageHandle,
1305 &mComponentName,
1306 &mComponentName2
1307 );
1308 }