]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / Library / VirtioMmioDeviceLib / VirtioMmioDeviceFunctions.c
1 /** @file
2
3 This driver produces Virtio Device Protocol instances for Virtio MMIO 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 SPDX-License-Identifier: BSD-2-Clause-Patent
10
11 **/
12
13 #include "VirtioMmioDevice.h"
14
15 EFI_STATUS
16 EFIAPI
17 VirtioMmioGetDeviceFeatures (
18 IN VIRTIO_DEVICE_PROTOCOL *This,
19 OUT UINT64 *DeviceFeatures
20 )
21 {
22 VIRTIO_MMIO_DEVICE *Device;
23
24 if (DeviceFeatures == NULL) {
25 return EFI_INVALID_PARAMETER;
26 }
27
28 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
29
30 *DeviceFeatures = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);
31
32 return EFI_SUCCESS;
33 }
34
35 EFI_STATUS
36 EFIAPI
37 VirtioMmioGetQueueSize (
38 IN VIRTIO_DEVICE_PROTOCOL *This,
39 OUT UINT16 *QueueNumMax
40 )
41 {
42 VIRTIO_MMIO_DEVICE *Device;
43
44 if (QueueNumMax == NULL) {
45 return EFI_INVALID_PARAMETER;
46 }
47
48 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
49
50 *QueueNumMax = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX) & 0xFFFF;
51
52 return EFI_SUCCESS;
53 }
54
55 EFI_STATUS
56 EFIAPI
57 VirtioMmioGetDeviceStatus (
58 IN VIRTIO_DEVICE_PROTOCOL *This,
59 OUT UINT8 *DeviceStatus
60 )
61 {
62 VIRTIO_MMIO_DEVICE *Device;
63
64 if (DeviceStatus == NULL) {
65 return EFI_INVALID_PARAMETER;
66 }
67
68 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
69
70 *DeviceStatus = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_STATUS) & 0xFF;
71
72 return EFI_SUCCESS;
73 }
74
75 EFI_STATUS
76 EFIAPI
77 VirtioMmioSetQueueSize (
78 IN VIRTIO_DEVICE_PROTOCOL *This,
79 IN UINT16 QueueSize
80 )
81 {
82 VIRTIO_MMIO_DEVICE *Device;
83
84 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
85
86 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize);
87
88 return EFI_SUCCESS;
89 }
90
91 EFI_STATUS
92 EFIAPI
93 VirtioMmioSetDeviceStatus (
94 IN VIRTIO_DEVICE_PROTOCOL *This,
95 IN UINT8 DeviceStatus
96 )
97 {
98 VIRTIO_MMIO_DEVICE *Device;
99
100 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
101
102 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, DeviceStatus);
103
104 return EFI_SUCCESS;
105 }
106
107 EFI_STATUS
108 EFIAPI
109 VirtioMmioSetQueueNotify (
110 IN VIRTIO_DEVICE_PROTOCOL *This,
111 IN UINT16 QueueNotify
112 )
113 {
114 VIRTIO_MMIO_DEVICE *Device;
115
116 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
117
118 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY, QueueNotify);
119
120 return EFI_SUCCESS;
121 }
122
123 EFI_STATUS
124 EFIAPI
125 VirtioMmioSetQueueAlignment (
126 IN VIRTIO_DEVICE_PROTOCOL *This,
127 IN UINT32 Alignment
128 )
129 {
130 VIRTIO_MMIO_DEVICE *Device;
131
132 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
133
134 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN, Alignment);
135
136 return EFI_SUCCESS;
137 }
138
139 EFI_STATUS
140 EFIAPI
141 VirtioMmioSetPageSize (
142 IN VIRTIO_DEVICE_PROTOCOL *This,
143 IN UINT32 PageSize
144 )
145 {
146 VIRTIO_MMIO_DEVICE *Device;
147
148 if (PageSize != EFI_PAGE_SIZE) {
149 return EFI_UNSUPPORTED;
150 }
151
152 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
153
154 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE, PageSize);
155
156 return EFI_SUCCESS;
157 }
158
159 EFI_STATUS
160 EFIAPI
161 VirtioMmioSetQueueSel (
162 IN VIRTIO_DEVICE_PROTOCOL *This,
163 IN UINT16 Sel
164 )
165 {
166 VIRTIO_MMIO_DEVICE *Device;
167
168 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
169
170 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_SEL, Sel);
171
172 return EFI_SUCCESS;
173 }
174
175 EFI_STATUS
176 VirtioMmioSetQueueAddress (
177 IN VIRTIO_DEVICE_PROTOCOL *This,
178 IN VRING *Ring,
179 IN UINT64 RingBaseShift
180 )
181 {
182 VIRTIO_MMIO_DEVICE *Device;
183
184 ASSERT (RingBaseShift == 0);
185
186 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
187
188 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN,
189 (UINT32)((UINTN)Ring->Base >> EFI_PAGE_SHIFT));
190
191 return EFI_SUCCESS;
192 }
193
194 EFI_STATUS
195 EFIAPI
196 VirtioMmioSetGuestFeatures (
197 IN VIRTIO_DEVICE_PROTOCOL *This,
198 IN UINT64 Features
199 )
200 {
201 VIRTIO_MMIO_DEVICE *Device;
202
203 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
204
205 if (Features > MAX_UINT32) {
206 return EFI_UNSUPPORTED;
207 }
208 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES,
209 (UINT32)Features);
210
211 return EFI_SUCCESS;
212 }
213
214 EFI_STATUS
215 EFIAPI
216 VirtioMmioDeviceWrite (
217 IN VIRTIO_DEVICE_PROTOCOL *This,
218 IN UINTN FieldOffset,
219 IN UINTN FieldSize,
220 IN UINT64 Value
221 )
222 {
223 UINTN DstBaseAddress;
224 VIRTIO_MMIO_DEVICE *Device;
225
226 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
227
228 //
229 // Double-check fieldsize
230 //
231 if ((FieldSize != 1) && (FieldSize != 2) &&
232 (FieldSize != 4) && (FieldSize != 8)) {
233 return EFI_INVALID_PARAMETER;
234 }
235
236 //
237 // Compute base address
238 //
239 DstBaseAddress = Device->BaseAddress +
240 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;
241
242 //
243 // The device-specific memory area of Virtio-MMIO can only be written in
244 // byte accesses. This is not currently in the Virtio spec.
245 //
246 MmioWriteBuffer8 (DstBaseAddress, FieldSize, (UINT8*)&Value);
247
248 return EFI_SUCCESS;
249 }
250
251 EFI_STATUS
252 EFIAPI
253 VirtioMmioDeviceRead (
254 IN VIRTIO_DEVICE_PROTOCOL *This,
255 IN UINTN FieldOffset,
256 IN UINTN FieldSize,
257 IN UINTN BufferSize,
258 OUT VOID *Buffer
259 )
260 {
261 UINTN SrcBaseAddress;
262 VIRTIO_MMIO_DEVICE *Device;
263
264 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
265
266 //
267 // Parameter validation
268 //
269 ASSERT (FieldSize == BufferSize);
270
271 //
272 // Double-check fieldsize
273 //
274 if ((FieldSize != 1) && (FieldSize != 2) &&
275 (FieldSize != 4) && (FieldSize != 8)) {
276 return EFI_INVALID_PARAMETER;
277 }
278
279 //
280 // Compute base address
281 //
282 SrcBaseAddress = Device->BaseAddress +
283 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;
284
285 //
286 // The device-specific memory area of Virtio-MMIO can only be read in
287 // byte reads. This is not currently in the Virtio spec.
288 //
289 MmioReadBuffer8 (SrcBaseAddress, BufferSize, Buffer);
290
291 return EFI_SUCCESS;
292 }
293
294 EFI_STATUS
295 EFIAPI
296 VirtioMmioAllocateSharedPages (
297 IN VIRTIO_DEVICE_PROTOCOL *This,
298 IN UINTN NumPages,
299 OUT VOID **HostAddress
300 )
301 {
302 VOID *Buffer;
303
304 Buffer = AllocatePages (NumPages);
305 if (Buffer == NULL) {
306 return EFI_OUT_OF_RESOURCES;
307 }
308
309 *HostAddress = Buffer;
310 return EFI_SUCCESS;
311 }
312
313 VOID
314 EFIAPI
315 VirtioMmioFreeSharedPages (
316 IN VIRTIO_DEVICE_PROTOCOL *This,
317 IN UINTN NumPages,
318 IN VOID *HostAddress
319 )
320 {
321 FreePages (HostAddress, NumPages);
322 }
323
324 EFI_STATUS
325 EFIAPI
326 VirtioMmioMapSharedBuffer (
327 IN VIRTIO_DEVICE_PROTOCOL *This,
328 IN VIRTIO_MAP_OPERATION Operation,
329 IN VOID *HostAddress,
330 IN OUT UINTN *NumberOfBytes,
331 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
332 OUT VOID **Mapping
333 )
334 {
335 *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
336 *Mapping = NULL;
337
338 return EFI_SUCCESS;
339 }
340
341 EFI_STATUS
342 EFIAPI
343 VirtioMmioUnmapSharedBuffer (
344 IN VIRTIO_DEVICE_PROTOCOL *This,
345 IN VOID *Mapping
346 )
347 {
348 return EFI_SUCCESS;
349 }