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