/src/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDeviceStubLib/VirtioPciDeviceStubLib.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** @file |
2 | | |
3 | | Copyright (c) 2018, Intel Corporation. All rights reserved.<BR> |
4 | | SPDX-License-Identifier: BSD-2-Clause-Patent |
5 | | |
6 | | **/ |
7 | | #include <Uefi.h> |
8 | | #include <stdio.h> |
9 | | #include <stdlib.h> |
10 | | #include <unistd.h> |
11 | | #include <Library/BaseLib.h> |
12 | | #include <Library/DebugLib.h> |
13 | | #include <Library/BaseMemoryLib.h> |
14 | | #include <Library/MemoryAllocationLib.h> |
15 | | #include <Protocol/BlockIo.h> |
16 | | #include <Protocol/VirtioDevice.h> |
17 | | #include <Protocol/PciIo.h> |
18 | | #include <Protocol/PciRootBridgeIo.h> |
19 | | #include <Library/VirtioPciDeviceStubLib.h> |
20 | | #include <IndustryStandard/Virtio095.h> |
21 | | |
22 | | PCI_CFG_SPACE *PciCfg; |
23 | | |
24 | | VOID |
25 | | EFIAPI |
26 | 0 | PrintByByte(UINT8* Content, UINT32 Len) { |
27 | 0 | UINT32 i; |
28 | 0 | for (i = 0; i < Len; i++) { |
29 | 0 | if (i % 16 == 0) printf ("\n"); |
30 | 0 | printf ("%02x ", Content[i]); |
31 | 0 | } |
32 | 0 | printf ("\n"); |
33 | 0 | } |
34 | | |
35 | | EFI_STATUS |
36 | | EFIAPI |
37 | | VirtioPciIoRead ( |
38 | | IN VIRTIO_PCI_DEVICE *Dev, |
39 | | IN UINTN FieldOffset, |
40 | | IN UINTN FieldSize, |
41 | | IN UINTN BufferSize, |
42 | | OUT VOID *Buffer |
43 | | ); |
44 | | |
45 | | EFI_STATUS |
46 | | EFIAPI |
47 | | VirtioPciIoWrite ( |
48 | | IN VIRTIO_PCI_DEVICE *Dev, |
49 | | IN UINTN FieldOffset, |
50 | | IN UINTN FieldSize, |
51 | | IN UINT64 Value |
52 | | ); |
53 | | |
54 | | /******************************************** |
55 | | * PCI Functions for VIRTIO_DEVICE_PROTOCOL |
56 | | *******************************************/ |
57 | | EFI_STATUS |
58 | | EFIAPI |
59 | | VirtioPciDeviceRead ( |
60 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
61 | | IN UINTN FieldOffset, |
62 | | IN UINTN FieldSize, |
63 | | IN UINTN BufferSize, |
64 | | OUT VOID *Buffer |
65 | | ); |
66 | | |
67 | | EFI_STATUS |
68 | | EFIAPI |
69 | | VirtioPciDeviceWrite ( |
70 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
71 | | IN UINTN FieldOffset, |
72 | | IN UINTN FieldSize, |
73 | | IN UINT64 Value |
74 | | ); |
75 | | |
76 | | EFI_STATUS |
77 | | EFIAPI |
78 | | VirtioPciGetDeviceFeatures ( |
79 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
80 | | OUT UINT64 *DeviceFeatures |
81 | | ); |
82 | | |
83 | | EFI_STATUS |
84 | | EFIAPI |
85 | | VirtioPciGetQueueSize ( |
86 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
87 | | OUT UINT16 *QueueNumMax |
88 | | ); |
89 | | |
90 | | EFI_STATUS |
91 | | EFIAPI |
92 | | VirtioPciSetQueueAlignment ( |
93 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
94 | | IN UINT32 Alignment |
95 | | ); |
96 | | |
97 | | EFI_STATUS |
98 | | EFIAPI |
99 | | VirtioPciSetPageSize ( |
100 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
101 | | IN UINT32 PageSize |
102 | | ); |
103 | | |
104 | | EFI_STATUS |
105 | | EFIAPI |
106 | | VirtioPciGetDeviceStatus ( |
107 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
108 | | OUT UINT8 *DeviceStatus |
109 | | ); |
110 | | |
111 | | EFI_STATUS |
112 | | EFIAPI |
113 | | VirtioPciSetGuestFeatures ( |
114 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
115 | | IN UINT64 Features |
116 | | ); |
117 | | |
118 | | EFI_STATUS |
119 | | EFIAPI |
120 | | VirtioPciSetQueueAddress ( |
121 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
122 | | IN VRING *Ring, |
123 | | IN UINT64 RingBaseShift |
124 | | ); |
125 | | |
126 | | EFI_STATUS |
127 | | EFIAPI |
128 | | VirtioPciSetQueueSel ( |
129 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
130 | | IN UINT16 Sel |
131 | | ); |
132 | | |
133 | | EFI_STATUS |
134 | | EFIAPI |
135 | | VirtioPciSetQueueNotify ( |
136 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
137 | | IN UINT16 Index |
138 | | ); |
139 | | |
140 | | EFI_STATUS |
141 | | EFIAPI |
142 | | VirtioPciSetQueueSize ( |
143 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
144 | | IN UINT16 Size |
145 | | ); |
146 | | |
147 | | EFI_STATUS |
148 | | EFIAPI |
149 | | VirtioPciSetDeviceStatus ( |
150 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
151 | | IN UINT8 DeviceStatus |
152 | | ); |
153 | | |
154 | | EFI_STATUS |
155 | | EFIAPI |
156 | | VirtioPciAllocateSharedPages ( |
157 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
158 | | IN UINTN NumPages, |
159 | | OUT VOID **HostAddress |
160 | | ); |
161 | | |
162 | | VOID |
163 | | EFIAPI |
164 | | VirtioPciFreeSharedPages ( |
165 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
166 | | IN UINTN NumPages, |
167 | | IN VOID *HostAddress |
168 | | ); |
169 | | |
170 | | EFI_STATUS |
171 | | EFIAPI |
172 | | VirtioPciMapSharedBuffer ( |
173 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
174 | | IN VIRTIO_MAP_OPERATION Operation, |
175 | | IN VOID *HostAddress, |
176 | | IN OUT UINTN *NumberOfBytes, |
177 | | OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, |
178 | | OUT VOID **Mapping |
179 | | ); |
180 | | |
181 | | EFI_STATUS |
182 | | EFIAPI |
183 | | VirtioPciUnmapSharedBuffer ( |
184 | | IN VIRTIO_DEVICE_PROTOCOL *This, |
185 | | IN VOID *Mapping |
186 | | ); |
187 | | |
188 | | EFI_STATUS |
189 | | EFIAPI |
190 | | PciIoRead ( |
191 | | IN EFI_PCI_IO_PROTOCOL *PciIo, |
192 | | IN EFI_PCI_IO_PROTOCOL_WIDTH Width, |
193 | | IN UINT8 BAR_IDX, |
194 | | IN UINT64 Offset, |
195 | | IN UINTN Count, |
196 | | IN OUT VOID *Buffer |
197 | 20.3k | ) { |
198 | 20.3k | UINT16 Len = 0; |
199 | | |
200 | 20.3k | switch (Width) |
201 | 20.3k | { |
202 | 7.37k | case EfiPciIoWidthUint32: |
203 | 7.37k | Len = Count * sizeof(UINT32); |
204 | 7.37k | break; |
205 | 11.1k | case EfiPciIoWidthUint16: |
206 | 11.1k | Len = Count * sizeof(UINT16); |
207 | 11.1k | break; |
208 | 1.84k | case EfiPciIoWidthUint8: |
209 | 1.84k | Len = Count * sizeof(UINT8); |
210 | 1.84k | break; |
211 | 0 | default: |
212 | 0 | break; |
213 | 20.3k | } |
214 | 20.3k | CopyMem (Buffer, (void *) ((UINT64) (PciCfg->PciBasicCfg.Device.Bar[1]) << 32 | PciCfg->PciBasicCfg.Device.Bar[0] + Offset), Len); |
215 | 20.3k | return EFI_SUCCESS; |
216 | 20.3k | } |
217 | | |
218 | | EFI_STATUS |
219 | | EFIAPI |
220 | | PciIoWrite ( |
221 | | IN EFI_PCI_IO_PROTOCOL *PciIo, |
222 | | IN EFI_PCI_IO_PROTOCOL_WIDTH Width, |
223 | | IN UINT8 BAR_IDX, |
224 | | IN UINT64 Offset, |
225 | | IN UINTN Count, |
226 | | IN OUT VOID *Buffer |
227 | 830 | ) { |
228 | 830 | UINT16 Len = 0; |
229 | | |
230 | 830 | switch (Width) |
231 | 830 | { |
232 | 136 | case EfiPciIoWidthUint32: |
233 | 136 | Len = Count * sizeof(UINT32); |
234 | 136 | break; |
235 | 74 | case EfiPciIoWidthUint16: |
236 | 74 | Len = Count * sizeof(UINT16); |
237 | 74 | break; |
238 | 620 | case EfiPciIoWidthUint8: |
239 | 620 | Len = Count * sizeof(UINT8); |
240 | 620 | break; |
241 | 0 | default: |
242 | 0 | break; |
243 | 830 | } |
244 | 830 | CopyMem ((void *) ((UINT64) (PciCfg->PciBasicCfg.Device.Bar[1]) << 32 | PciCfg->PciBasicCfg.Device.Bar[0] + Offset), Buffer, Len); |
245 | 830 | return EFI_SUCCESS; |
246 | 830 | } |
247 | | |
248 | | STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate = { |
249 | | 0, // Revision |
250 | | 0, // SubSystemDeviceId |
251 | | VirtioPciGetDeviceFeatures, // GetDeviceFeatures |
252 | | VirtioPciSetGuestFeatures, // SetGuestFeatures |
253 | | VirtioPciSetQueueAddress, // SetQueueAddress |
254 | | VirtioPciSetQueueSel, // SetQueueSel |
255 | | VirtioPciSetQueueNotify, // SetQueueNotify |
256 | | VirtioPciSetQueueAlignment, // SetQueueAlignment |
257 | | VirtioPciSetPageSize, // SetPageSize |
258 | | VirtioPciGetQueueSize, // GetQueueNumMax |
259 | | VirtioPciSetQueueSize, // SetQueueNum |
260 | | VirtioPciGetDeviceStatus, // GetDeviceStatus |
261 | | VirtioPciSetDeviceStatus, // SetDeviceStatus |
262 | | VirtioPciDeviceWrite, // WriteDevice |
263 | | VirtioPciDeviceRead, // ReadDevice |
264 | | VirtioPciAllocateSharedPages, // AllocateSharedPages |
265 | | VirtioPciFreeSharedPages, // FreeSharedPages |
266 | | VirtioPciMapSharedBuffer, // MapSharedBuffer |
267 | | VirtioPciUnmapSharedBuffer, // UnmapSharedBuffer |
268 | | }; |
269 | | |
270 | | EFI_STATUS |
271 | | EFIAPI |
272 | | InitVirtioPciDev ( |
273 | | IN EFI_PCI_IO_PROTOCOL *PciIo, |
274 | | IN VOID *ConfigRegion, |
275 | | IN OUT VIRTIO_PCI_DEVICE *Device |
276 | 0 | ) { |
277 | | // VOID *ConfigRegion; |
278 | | |
279 | | // ConfigRegion = (VOID *) AllocatePool(sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_HDR) + sizeof (VIRTIO_BLK_CONFIG)); |
280 | 0 | if (ConfigRegion == NULL) { |
281 | 0 | return EFI_OUT_OF_RESOURCES; |
282 | 0 | } |
283 | | |
284 | 0 | Device->Signature = VIRTIO_PCI_DEVICE_SIGNATURE; |
285 | | // |
286 | | // Copy protocol template |
287 | | // |
288 | 0 | CopyMem (&Device->VirtioDevice, &mDeviceProtocolTemplate, sizeof (VIRTIO_DEVICE_PROTOCOL)); |
289 | |
|
290 | 0 | PciCfg = (PCI_CFG_SPACE *) ConfigRegion; |
291 | | |
292 | | //This test expects this binary file to exist in the current execution folder |
293 | 0 | FILE *f = fopen("VirtioBlkFuzzSeed0.9.5.bin", "rb"); |
294 | 0 | if (f==NULL) { |
295 | 0 | fputs ("File error",stderr); |
296 | 0 | goto FreeDevice; |
297 | 0 | } |
298 | | |
299 | 0 | fseek(f, 0, SEEK_END); |
300 | |
|
301 | 0 | long int fsize = ftell(f); |
302 | 0 | rewind(f); |
303 | 0 | if (fsize<0) { |
304 | 0 | fputs ("Error on reading file size",stderr); |
305 | 0 | fclose(f); |
306 | 0 | goto FreeDevice; |
307 | 0 | } |
308 | | |
309 | 0 | size_t bytes_read = fread((void *)ConfigRegion, 1, (size_t)fsize, f); |
310 | 0 | fclose(f); |
311 | 0 | if ((UINTN)bytes_read!=fsize) { |
312 | 0 | fputs ("File error",stderr); |
313 | 0 | goto FreeDevice; |
314 | 0 | } |
315 | | |
316 | 0 | PciCfg->PciBasicCfg.Device.Bar[0] = (UINT32) ((UINT64)PciCfg + sizeof(PCI_CFG_SPACE)); |
317 | 0 | PciCfg->PciBasicCfg.Device.Bar[1] = (UINT32) (((UINT64)PciCfg + sizeof(PCI_CFG_SPACE)) >> 32); |
318 | |
|
319 | 0 | Device->VirtioDevice.SubSystemDeviceId = PciCfg->PciBasicCfg.Device.SubsystemID; |
320 | |
|
321 | 0 | PciIo->Io.Read = &PciIoRead; |
322 | 0 | PciIo->Io.Write = &PciIoWrite; |
323 | 0 | Device->PciIo = PciIo; |
324 | | |
325 | | // |
326 | | // Note: We don't support the MSI-X capability. If we did, |
327 | | // the offset would become 24 after enabling MSI-X. |
328 | | // |
329 | 0 | Device->DeviceSpecificConfigurationOffset = VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI; |
330 | |
|
331 | 0 | return EFI_SUCCESS; |
332 | | |
333 | 0 | FreeDevice: |
334 | | // FreePool (ConfigRegion); |
335 | |
|
336 | 0 | return EFI_OUT_OF_RESOURCES; |
337 | 0 | } |
338 | | |
339 | | EFI_STATUS |
340 | | EFIAPI |
341 | | ParseBufferAndInitVirtioPciDev ( |
342 | | IN UINT8 *TestBuffer, |
343 | | IN UINTN BufferSize, |
344 | | IN EFI_PCI_IO_PROTOCOL *PciIo, |
345 | | IN VOID *ConfigRegion, |
346 | | IN OUT VIRTIO_PCI_DEVICE *Device |
347 | | ) |
348 | 295 | { |
349 | 295 | VIRTIO_HDR *VirtioHdr; |
350 | | |
351 | | |
352 | | // ConfigRegion = (VOID *) AllocatePool(sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_HDR) + sizeof (VIRTIO_BLK_CONFIG)); |
353 | 295 | if (ConfigRegion == NULL) { |
354 | 0 | return EFI_OUT_OF_RESOURCES; |
355 | 0 | } |
356 | | |
357 | 295 | if (BufferSize != sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_HDR) + sizeof (VIRTIO_BLK_CONFIG)) { |
358 | 65 | goto FreeDevice; |
359 | 65 | } |
360 | | |
361 | 230 | Device->Signature = VIRTIO_PCI_DEVICE_SIGNATURE; |
362 | | |
363 | 230 | PciCfg = (PCI_CFG_SPACE *) ConfigRegion; |
364 | | |
365 | | // |
366 | | // Copy protocol template |
367 | | // |
368 | 230 | CopyMem (&Device->VirtioDevice, &mDeviceProtocolTemplate, sizeof (VIRTIO_DEVICE_PROTOCOL)); |
369 | | |
370 | 230 | CopyMem ((void *)PciCfg, (void *) TestBuffer, sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_HDR) + sizeof (VIRTIO_BLK_CONFIG)); |
371 | | |
372 | 230 | Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5); |
373 | 230 | Device->VirtioDevice.SubSystemDeviceId = PciCfg->PciBasicCfg.Device.SubsystemID; |
374 | | |
375 | | // |
376 | | // virtio-0.9.5, 2.1 PCI Discovery |
377 | | // |
378 | 230 | if (!((PciCfg->PciBasicCfg.Hdr.VendorId == VIRTIO_VENDOR_ID) && |
379 | 230 | (PciCfg->PciBasicCfg.Hdr.DeviceId >= 0x1000) && |
380 | 230 | (PciCfg->PciBasicCfg.Hdr.DeviceId <= 0x103F) && |
381 | 230 | (PciCfg->PciBasicCfg.Hdr.RevisionID == 0x00))) { |
382 | 59 | goto FreeDevice; |
383 | 59 | } |
384 | | |
385 | 171 | PciCfg->PciBasicCfg.Device.Bar[0] = (UINT32) ((UINT64)PciCfg + sizeof(PCI_CFG_SPACE)); |
386 | 171 | PciCfg->PciBasicCfg.Device.Bar[1] = (UINT32) (((UINT64)PciCfg + sizeof(PCI_CFG_SPACE)) >> 32); |
387 | | |
388 | 171 | Device->VirtioDevice.SubSystemDeviceId = PciCfg->PciBasicCfg.Device.SubsystemID; |
389 | | |
390 | 171 | PciIo->Io.Read = &PciIoRead; |
391 | 171 | PciIo->Io.Write = &PciIoWrite; |
392 | 171 | Device->PciIo = PciIo; |
393 | | |
394 | | // |
395 | | // Note: We don't support the MSI-X capability. If we did, |
396 | | // the offset would become 24 after enabling MSI-X. |
397 | | // |
398 | 171 | Device->DeviceSpecificConfigurationOffset = VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI; |
399 | | |
400 | 171 | return EFI_SUCCESS; |
401 | | |
402 | 124 | FreeDevice: |
403 | 124 | return EFI_OUT_OF_RESOURCES; |
404 | 230 | } |