]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / VirtioPciDeviceDxe / VirtioPciFunctions.c
CommitLineData
3bb56c06
OM
1/** @file\r
2\r
3 This driver produces Virtio Device Protocol instances for Virtio PCI devices.\r
4\r
5 Copyright (C) 2012, Red Hat, Inc.\r
6 Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
7 Copyright (C) 2013, ARM Ltd.\r
4157b841 8 Copyright (C) 2017, AMD Inc, All rights reserved.<BR>\r
3bb56c06 9\r
b26f0cf9 10 SPDX-License-Identifier: BSD-2-Clause-Patent\r
3bb56c06
OM
11\r
12**/\r
13#include <Library/BaseMemoryLib.h>\r
14#include <Library/DebugLib.h>\r
15#include <Library/MemoryAllocationLib.h>\r
16#include <Library/UefiBootServicesTableLib.h>\r
17#include <Library/UefiLib.h>\r
18#include "VirtioPciDevice.h"\r
19\r
20/**\r
21\r
22 Read a word from Region 0 of the device specified by VirtIo Device protocol.\r
23\r
24 The function implements the ReadDevice protocol member of\r
25 VIRTIO_DEVICE_PROTOCOL.\r
26\r
27 @param[in] This VirtIo Device protocol.\r
28\r
29 @param[in] FieldOffset Source offset.\r
30\r
31 @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.\r
32\r
33 @param[in] BufferSize Number of bytes available in the target buffer. Must\r
34 equal FieldSize.\r
35\r
36 @param[out] Buffer Target buffer.\r
37\r
38\r
39 @return Status code returned by PciIo->Io.Read().\r
40\r
41**/\r
42EFI_STATUS\r
43EFIAPI\r
44VirtioPciDeviceRead (\r
ac0a286f
MK
45 IN VIRTIO_DEVICE_PROTOCOL *This,\r
46 IN UINTN FieldOffset,\r
47 IN UINTN FieldSize,\r
48 IN UINTN BufferSize,\r
49 OUT VOID *Buffer\r
3bb56c06
OM
50 )\r
51{\r
ac0a286f 52 VIRTIO_PCI_DEVICE *Dev;\r
3bb56c06
OM
53\r
54 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
55\r
ac0a286f
MK
56 return VirtioPciIoRead (\r
57 Dev,\r
58 Dev->DeviceSpecificConfigurationOffset + FieldOffset,\r
59 FieldSize,\r
60 BufferSize,\r
61 Buffer\r
62 );\r
3bb56c06
OM
63}\r
64\r
65/**\r
66\r
67 Write a word into Region 0 of the device specified by VirtIo Device protocol.\r
68\r
69 @param[in] This VirtIo Device protocol.\r
70\r
71 @param[in] FieldOffset Destination offset.\r
72\r
73 @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.\r
74\r
75 @param[in] Value Little endian value to write, converted to UINT64.\r
76 The least significant FieldSize bytes will be used.\r
77\r
78\r
79 @return Status code returned by PciIo->Io.Write().\r
80\r
81**/\r
82EFI_STATUS\r
83EFIAPI\r
84VirtioPciDeviceWrite (\r
ac0a286f
MK
85 IN VIRTIO_DEVICE_PROTOCOL *This,\r
86 IN UINTN FieldOffset,\r
87 IN UINTN FieldSize,\r
88 IN UINT64 Value\r
3bb56c06
OM
89 )\r
90{\r
ac0a286f 91 VIRTIO_PCI_DEVICE *Dev;\r
3bb56c06
OM
92\r
93 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
94\r
ac0a286f
MK
95 return VirtioPciIoWrite (\r
96 Dev,\r
97 Dev->DeviceSpecificConfigurationOffset + FieldOffset,\r
98 FieldSize,\r
99 Value\r
100 );\r
3bb56c06
OM
101}\r
102\r
103EFI_STATUS\r
104EFIAPI\r
105VirtioPciGetDeviceFeatures (\r
ac0a286f
MK
106 IN VIRTIO_DEVICE_PROTOCOL *This,\r
107 OUT UINT64 *DeviceFeatures\r
3bb56c06
OM
108 )\r
109{\r
ac0a286f
MK
110 VIRTIO_PCI_DEVICE *Dev;\r
111 EFI_STATUS Status;\r
112 UINT32 Features32;\r
3bb56c06
OM
113\r
114 if (DeviceFeatures == NULL) {\r
115 return EFI_INVALID_PARAMETER;\r
116 }\r
117\r
118 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
119\r
ac0a286f
MK
120 Status = VirtioPciIoRead (\r
121 Dev,\r
122 VIRTIO_PCI_OFFSET_DEVICE_FEATURES,\r
123 sizeof (UINT32),\r
124 sizeof (UINT32),\r
125 &Features32\r
126 );\r
bc8fde6f
LE
127 if (!EFI_ERROR (Status)) {\r
128 *DeviceFeatures = Features32;\r
129 }\r
ac0a286f 130\r
bc8fde6f 131 return Status;\r
3bb56c06
OM
132}\r
133\r
3bb56c06
OM
134EFI_STATUS\r
135EFIAPI\r
136VirtioPciGetQueueSize (\r
137 IN VIRTIO_DEVICE_PROTOCOL *This,\r
138 OUT UINT16 *QueueNumMax\r
139 )\r
140{\r
ac0a286f 141 VIRTIO_PCI_DEVICE *Dev;\r
3bb56c06
OM
142\r
143 if (QueueNumMax == NULL) {\r
144 return EFI_INVALID_PARAMETER;\r
145 }\r
146\r
147 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
148\r
ac0a286f
MK
149 return VirtioPciIoRead (\r
150 Dev,\r
151 VIRTIO_PCI_OFFSET_QUEUE_SIZE,\r
152 sizeof (UINT16),\r
153 sizeof (UINT16),\r
154 QueueNumMax\r
155 );\r
3bb56c06
OM
156}\r
157\r
158EFI_STATUS\r
159EFIAPI\r
160VirtioPciGetDeviceStatus (\r
161 IN VIRTIO_DEVICE_PROTOCOL *This,\r
162 OUT UINT8 *DeviceStatus\r
163 )\r
164{\r
ac0a286f 165 VIRTIO_PCI_DEVICE *Dev;\r
3bb56c06
OM
166\r
167 if (DeviceStatus == NULL) {\r
168 return EFI_INVALID_PARAMETER;\r
169 }\r
170\r
171 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
172\r
ac0a286f
MK
173 return VirtioPciIoRead (\r
174 Dev,\r
175 VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,\r
176 sizeof (UINT8),\r
177 sizeof (UINT8),\r
178 DeviceStatus\r
179 );\r
3bb56c06
OM
180}\r
181\r
182EFI_STATUS\r
183EFIAPI\r
184VirtioPciSetGuestFeatures (\r
185 IN VIRTIO_DEVICE_PROTOCOL *This,\r
ac0a286f 186 IN UINT64 Features\r
3bb56c06
OM
187 )\r
188{\r
ac0a286f 189 VIRTIO_PCI_DEVICE *Dev;\r
3bb56c06
OM
190\r
191 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
192\r
bc8fde6f
LE
193 if (Features > MAX_UINT32) {\r
194 return EFI_UNSUPPORTED;\r
195 }\r
ac0a286f
MK
196\r
197 return VirtioPciIoWrite (\r
198 Dev,\r
199 VIRTIO_PCI_OFFSET_GUEST_FEATURES,\r
200 sizeof (UINT32),\r
201 Features\r
202 );\r
3bb56c06
OM
203}\r
204\r
205EFI_STATUS\r
206EFIAPI\r
207VirtioPciSetQueueAddress (\r
07af4eee 208 IN VIRTIO_DEVICE_PROTOCOL *This,\r
53a4c604
BS
209 IN VRING *Ring,\r
210 IN UINT64 RingBaseShift\r
3bb56c06
OM
211 )\r
212{\r
ac0a286f 213 VIRTIO_PCI_DEVICE *Dev;\r
3bb56c06 214\r
53a4c604
BS
215 ASSERT (RingBaseShift == 0);\r
216\r
3bb56c06
OM
217 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
218\r
ac0a286f
MK
219 return VirtioPciIoWrite (\r
220 Dev,\r
221 VIRTIO_PCI_OFFSET_QUEUE_ADDRESS,\r
222 sizeof (UINT32),\r
223 (UINT32)((UINTN)Ring->Base >> EFI_PAGE_SHIFT)\r
224 );\r
3bb56c06
OM
225}\r
226\r
227EFI_STATUS\r
228EFIAPI\r
229VirtioPciSetQueueSel (\r
ac0a286f
MK
230 IN VIRTIO_DEVICE_PROTOCOL *This,\r
231 IN UINT16 Sel\r
3bb56c06
OM
232 )\r
233{\r
ac0a286f 234 VIRTIO_PCI_DEVICE *Dev;\r
3bb56c06
OM
235\r
236 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
237\r
ac0a286f
MK
238 return VirtioPciIoWrite (\r
239 Dev,\r
240 VIRTIO_PCI_OFFSET_QUEUE_SELECT,\r
241 sizeof (UINT16),\r
242 Sel\r
243 );\r
3bb56c06
OM
244}\r
245\r
246EFI_STATUS\r
247EFIAPI\r
248VirtioPciSetQueueAlignment (\r
ac0a286f 249 IN VIRTIO_DEVICE_PROTOCOL *This,\r
e5251fec 250 IN UINT32 Alignment\r
3bb56c06
OM
251 )\r
252{\r
253 return EFI_SUCCESS;\r
254}\r
255\r
256EFI_STATUS\r
257EFIAPI\r
258VirtioPciSetPageSize (\r
ac0a286f 259 IN VIRTIO_DEVICE_PROTOCOL *This,\r
e5251fec 260 IN UINT32 PageSize\r
3bb56c06
OM
261 )\r
262{\r
263 return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
264}\r
265\r
266EFI_STATUS\r
267EFIAPI\r
268VirtioPciSetQueueNotify (\r
ac0a286f
MK
269 IN VIRTIO_DEVICE_PROTOCOL *This,\r
270 IN UINT16 Index\r
3bb56c06
OM
271 )\r
272{\r
ac0a286f 273 VIRTIO_PCI_DEVICE *Dev;\r
3bb56c06
OM
274\r
275 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
276\r
ac0a286f
MK
277 return VirtioPciIoWrite (\r
278 Dev,\r
279 VIRTIO_PCI_OFFSET_QUEUE_NOTIFY,\r
280 sizeof (UINT16),\r
281 Index\r
282 );\r
3bb56c06
OM
283}\r
284\r
285EFI_STATUS\r
286EFIAPI\r
287VirtioPciSetQueueSize (\r
ac0a286f
MK
288 IN VIRTIO_DEVICE_PROTOCOL *This,\r
289 IN UINT16 Size\r
3bb56c06
OM
290 )\r
291{\r
292 //\r
293 // This function is only applicable in Virtio-MMIO.\r
294 // (The QueueSize field is read-only in Virtio proper (PCI))\r
295 //\r
296 return EFI_SUCCESS;\r
297}\r
298\r
299EFI_STATUS\r
300EFIAPI\r
301VirtioPciSetDeviceStatus (\r
ac0a286f
MK
302 IN VIRTIO_DEVICE_PROTOCOL *This,\r
303 IN UINT8 DeviceStatus\r
3bb56c06
OM
304 )\r
305{\r
ac0a286f 306 VIRTIO_PCI_DEVICE *Dev;\r
3bb56c06
OM
307\r
308 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
309\r
ac0a286f
MK
310 return VirtioPciIoWrite (\r
311 Dev,\r
312 VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,\r
313 sizeof (UINT8),\r
314 DeviceStatus\r
315 );\r
3bb56c06 316}\r
4157b841
BS
317\r
318EFI_STATUS\r
319EFIAPI\r
320VirtioPciAllocateSharedPages (\r
321 IN VIRTIO_DEVICE_PROTOCOL *This,\r
322 IN UINTN NumPages,\r
323 OUT VOID **HostAddress\r
324 )\r
325{\r
ac0a286f 326 VOID *Buffer;\r
4157b841
BS
327\r
328 Buffer = AllocatePages (NumPages);\r
329 if (Buffer == NULL) {\r
330 return EFI_OUT_OF_RESOURCES;\r
331 }\r
332\r
333 *HostAddress = Buffer;\r
334 return EFI_SUCCESS;\r
335}\r
336\r
337VOID\r
338EFIAPI\r
339VirtioPciFreeSharedPages (\r
340 IN VIRTIO_DEVICE_PROTOCOL *This,\r
341 IN UINTN NumPages,\r
342 IN VOID *HostAddress\r
343 )\r
344{\r
345 FreePages (HostAddress, NumPages);\r
346}\r
347\r
348EFI_STATUS\r
349EFIAPI\r
350VirtioPciMapSharedBuffer (\r
351 IN VIRTIO_DEVICE_PROTOCOL *This,\r
352 IN VIRTIO_MAP_OPERATION Operation,\r
353 IN VOID *HostAddress,\r
354 IN OUT UINTN *NumberOfBytes,\r
355 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
356 OUT VOID **Mapping\r
357 )\r
358{\r
ac0a286f
MK
359 *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;\r
360 *Mapping = NULL;\r
4157b841
BS
361\r
362 return EFI_SUCCESS;\r
363}\r
364\r
365EFI_STATUS\r
366EFIAPI\r
367VirtioPciUnmapSharedBuffer (\r
ac0a286f
MK
368 IN VIRTIO_DEVICE_PROTOCOL *This,\r
369 IN VOID *Mapping\r
4157b841
BS
370 )\r
371{\r
372 return EFI_SUCCESS;\r
373}\r