]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
OvmfPkg/VirtioMmioDeviceLib: implement IOMMU-like member functions
[mirror_edk2.git] / OvmfPkg / Library / VirtioMmioDeviceLib / VirtioMmioDevice.c
1 /** @file
2
3 This driver produces Virtio Device Protocol instances for Virtio Mmio devices.
4
5 Copyright (C) 2013, ARM Ltd.
6 Copyright (C) 2017, AMD Inc. All rights reserved.<BR>
7
8 This program and the accompanying materials are licensed and made available
9 under the terms and conditions of the BSD License which accompanies this
10 distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
14 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/UefiBootServicesTableLib.h>
20
21 #include "VirtioMmioDevice.h"
22
23 static VIRTIO_DEVICE_PROTOCOL mMmioDeviceProtocolTemplate = {
24 0, // Revision
25 0, // SubSystemDeviceId
26 VirtioMmioGetDeviceFeatures, // GetDeviceFeatures
27 VirtioMmioSetGuestFeatures, // SetGuestFeatures
28 VirtioMmioSetQueueAddress, // SetQueueAddress
29 VirtioMmioSetQueueSel, // SetQueueSel
30 VirtioMmioSetQueueNotify, // SetQueueNotify
31 VirtioMmioSetQueueAlignment, // SetQueueAlign
32 VirtioMmioSetPageSize, // SetPageSize
33 VirtioMmioGetQueueSize, // GetQueueNumMax
34 VirtioMmioSetQueueSize, // SetQueueNum
35 VirtioMmioGetDeviceStatus, // GetDeviceStatus
36 VirtioMmioSetDeviceStatus, // SetDeviceStatus
37 VirtioMmioDeviceWrite, // WriteDevice
38 VirtioMmioDeviceRead, // ReadDevice
39 VirtioMmioAllocateSharedPages, // AllocateSharedPages
40 VirtioMmioFreeSharedPages, // FreeSharedPages
41 VirtioMmioMapSharedBuffer, // MapSharedBuffer
42 VirtioMmioUnmapSharedBuffer // UnmapSharedBuffer
43 };
44
45 /**
46
47 Initialize the VirtIo MMIO Device
48
49 @param[in] BaseAddress Base Address of the VirtIo MMIO Device
50
51 @param[in, out] Device The driver instance to configure.
52
53 @retval EFI_SUCCESS Setup complete.
54
55 @retval EFI_UNSUPPORTED The driver is not a VirtIo MMIO device.
56
57 **/
58 STATIC
59 EFI_STATUS
60 EFIAPI
61 VirtioMmioInit (
62 IN PHYSICAL_ADDRESS BaseAddress,
63 IN OUT VIRTIO_MMIO_DEVICE *Device
64 )
65 {
66 UINT32 MagicValue;
67 UINT32 VendorId;
68 UINT32 Version;
69
70 //
71 // Initialize VirtIo Mmio Device
72 //
73 CopyMem (&Device->VirtioDevice, &mMmioDeviceProtocolTemplate,
74 sizeof (VIRTIO_DEVICE_PROTOCOL));
75 Device->BaseAddress = BaseAddress;
76 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);
77 Device->VirtioDevice.SubSystemDeviceId =
78 MmioRead32 (BaseAddress + VIRTIO_MMIO_OFFSET_DEVICE_ID);
79
80 //
81 // Double-check MMIO-specific values
82 //
83 MagicValue = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_MAGIC);
84 if (MagicValue != VIRTIO_MMIO_MAGIC) {
85 return EFI_UNSUPPORTED;
86 }
87
88 Version = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VERSION);
89 if (Version != 1) {
90 return EFI_UNSUPPORTED;
91 }
92
93 //
94 // Double-check MMIO-specific values
95 //
96 VendorId = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VENDOR_ID);
97 if (VendorId != VIRTIO_VENDOR_ID) {
98 //
99 // The ARM Base and Foundation Models do not report a valid VirtIo VendorId.
100 // They return a value of 0x0 for the VendorId.
101 //
102 DEBUG((EFI_D_WARN, "VirtioMmioInit: Warning: The VendorId (0x%X) does not "
103 "match the VirtIo VendorId (0x%X).\n",
104 VendorId, VIRTIO_VENDOR_ID));
105 }
106
107 return EFI_SUCCESS;
108 }
109
110
111 /**
112
113 Uninitialize the internals of a virtio-mmio device that has been successfully
114 set up with VirtioMmioInit().
115
116 @param[in, out] Device The device to clean up.
117
118 **/
119
120 STATIC
121 VOID
122 EFIAPI
123 VirtioMmioUninit (
124 IN VIRTIO_MMIO_DEVICE *Device
125 )
126 {
127 //
128 // Note: This function mirrors VirtioMmioInit() that does not allocate any
129 // resources - there's nothing to free here.
130 //
131 }
132
133 EFI_STATUS
134 VirtioMmioInstallDevice (
135 IN PHYSICAL_ADDRESS BaseAddress,
136 IN EFI_HANDLE Handle
137 )
138 {
139 EFI_STATUS Status;
140 VIRTIO_MMIO_DEVICE *VirtIo;
141
142 if (!BaseAddress) {
143 return EFI_INVALID_PARAMETER;
144 }
145 if (Handle == NULL) {
146 return EFI_INVALID_PARAMETER;
147 }
148
149 //
150 // Allocate VIRTIO_MMIO_DEVICE
151 //
152 VirtIo = AllocateZeroPool (sizeof (VIRTIO_MMIO_DEVICE));
153 if (VirtIo == NULL) {
154 return EFI_OUT_OF_RESOURCES;
155 }
156
157 VirtIo->Signature = VIRTIO_MMIO_DEVICE_SIGNATURE;
158
159 Status = VirtioMmioInit (BaseAddress, VirtIo);
160 if (EFI_ERROR (Status)) {
161 goto FreeVirtioMem;
162 }
163
164 //
165 // Install VIRTIO_DEVICE_PROTOCOL to Handle
166 //
167 Status = gBS->InstallProtocolInterface (&Handle,
168 &gVirtioDeviceProtocolGuid, EFI_NATIVE_INTERFACE,
169 &VirtIo->VirtioDevice);
170 if (EFI_ERROR (Status)) {
171 goto UninitVirtio;
172 }
173
174 return EFI_SUCCESS;
175
176 UninitVirtio:
177 VirtioMmioUninit (VirtIo);
178
179 FreeVirtioMem:
180 FreePool (VirtIo);
181 return Status;
182 }
183
184 EFI_STATUS
185 VirtioMmioUninstallDevice (
186 IN EFI_HANDLE DeviceHandle
187 )
188 {
189 VIRTIO_DEVICE_PROTOCOL *VirtioDevice;
190 VIRTIO_MMIO_DEVICE *MmioDevice;
191 EFI_STATUS Status;
192
193 Status = gBS->OpenProtocol (
194 DeviceHandle, // candidate device
195 &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface
196 (VOID **)&VirtioDevice, // target pointer
197 DeviceHandle, // requestor driver identity
198 DeviceHandle, // requesting lookup for dev.
199 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added
200 );
201 if (EFI_ERROR (Status)) {
202 return Status;
203 }
204
205 //
206 // Get the MMIO device from the VirtIo Device instance
207 //
208 MmioDevice = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);
209
210 //
211 // Uninstall the protocol interface
212 //
213 Status = gBS->UninstallProtocolInterface (DeviceHandle,
214 &gVirtioDeviceProtocolGuid, &MmioDevice->VirtioDevice
215 );
216 if (EFI_ERROR (Status)) {
217 return Status;
218 }
219
220 //
221 // Uninitialize the VirtIo Device
222 //
223 VirtioMmioUninit (MmioDevice);
224 FreePool (MmioDevice);
225
226 return EFI_SUCCESS;
227 }