Coverage Report

Created: 2024-10-17 06:29

/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
}