]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / VirtioPciDeviceDxe / VirtioPciDevice.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
694673c9 6 Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>\r
3bb56c06 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\r
14#include <IndustryStandard/Pci.h>\r
15#include <Library/BaseMemoryLib.h>\r
16#include <Library/DebugLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
18#include <Library/UefiBootServicesTableLib.h>\r
19#include <Library/UefiLib.h>\r
20\r
21#include "VirtioPciDevice.h"\r
22\r
ac0a286f 23STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate = {\r
3bb56c06
OM
24 0, // Revision\r
25 0, // SubSystemDeviceId\r
26 VirtioPciGetDeviceFeatures, // GetDeviceFeatures\r
27 VirtioPciSetGuestFeatures, // SetGuestFeatures\r
3bb56c06
OM
28 VirtioPciSetQueueAddress, // SetQueueAddress\r
29 VirtioPciSetQueueSel, // SetQueueSel\r
30 VirtioPciSetQueueNotify, // SetQueueNotify\r
31 VirtioPciSetQueueAlignment, // SetQueueAlignment\r
32 VirtioPciSetPageSize, // SetPageSize\r
33 VirtioPciGetQueueSize, // GetQueueNumMax\r
34 VirtioPciSetQueueSize, // SetQueueNum\r
35 VirtioPciGetDeviceStatus, // GetDeviceStatus\r
36 VirtioPciSetDeviceStatus, // SetDeviceStatus\r
37 VirtioPciDeviceWrite, // WriteDevice\r
4157b841
BS
38 VirtioPciDeviceRead, // ReadDevice\r
39 VirtioPciAllocateSharedPages, // AllocateSharedPages\r
40 VirtioPciFreeSharedPages, // FreeSharedPages\r
41 VirtioPciMapSharedBuffer, // MapSharedBuffer\r
42 VirtioPciUnmapSharedBuffer, // UnmapSharedBuffer\r
3bb56c06
OM
43};\r
44\r
45/**\r
46\r
47 Read a word from Region 0 of the device specified by PciIo.\r
48\r
49 Region 0 must be an iomem region. This is an internal function for the PCI\r
50 implementation of the protocol.\r
51\r
52 @param[in] Dev Virtio PCI device.\r
53\r
54 @param[in] FieldOffset Source offset.\r
55\r
56 @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.\r
57\r
58 @param[in] BufferSize Number of bytes available in the target buffer. Must\r
59 equal FieldSize.\r
60\r
61 @param[out] Buffer Target buffer.\r
62\r
63\r
64 @return Status code returned by PciIo->Io.Read().\r
65\r
66**/\r
67EFI_STATUS\r
68EFIAPI\r
69VirtioPciIoRead (\r
ac0a286f
MK
70 IN VIRTIO_PCI_DEVICE *Dev,\r
71 IN UINTN FieldOffset,\r
72 IN UINTN FieldSize,\r
73 IN UINTN BufferSize,\r
74 OUT VOID *Buffer\r
3bb56c06
OM
75 )\r
76{\r
ac0a286f
MK
77 UINTN Count;\r
78 EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
79 EFI_PCI_IO_PROTOCOL *PciIo;\r
3bb56c06
OM
80\r
81 ASSERT (FieldSize == BufferSize);\r
82\r
83 PciIo = Dev->PciIo;\r
84 Count = 1;\r
85\r
86 switch (FieldSize) {\r
87 case 1:\r
88 Width = EfiPciIoWidthUint8;\r
89 break;\r
90\r
91 case 2:\r
92 Width = EfiPciIoWidthUint16;\r
93 break;\r
94\r
95 case 8:\r
96 //\r
97 // The 64bit PCI I/O is broken down into two 32bit reads to prevent\r
98 // any alignment or width issues.\r
99 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():\r
100 //\r
101 // The I/O operations are carried out exactly as requested. The caller\r
102 // is responsible for any alignment and I/O width issues which the\r
103 // bus, device, platform, or type of I/O might require. For example on\r
104 // some platforms, width requests of EfiPciIoWidthUint64 do not work.\r
105 //\r
106 Count = 2;\r
107\r
ac0a286f
MK
108 //\r
109 // fall through\r
110 //\r
3bb56c06
OM
111 case 4:\r
112 Width = EfiPciIoWidthUint32;\r
113 break;\r
114\r
115 default:\r
116 ASSERT (FALSE);\r
117 return EFI_INVALID_PARAMETER;\r
118 }\r
119\r
120 return PciIo->Io.Read (\r
121 PciIo,\r
122 Width,\r
123 PCI_BAR_IDX0,\r
124 FieldOffset,\r
125 Count,\r
126 Buffer\r
127 );\r
128}\r
129\r
130/**\r
131\r
132 Write a word into Region 0 of the device specified by PciIo.\r
133\r
134 Region 0 must be an iomem region. This is an internal function for the PCI\r
135 implementation of the protocol.\r
136\r
137 @param[in] Dev Virtio PCI device.\r
138\r
139 @param[in] FieldOffset Destination offset.\r
140\r
141 @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.\r
142\r
143 @param[in] Value Little endian value to write, converted to UINT64.\r
144 The least significant FieldSize bytes will be used.\r
145\r
146\r
147 @return Status code returned by PciIo->Io.Write().\r
148\r
149**/\r
150EFI_STATUS\r
151EFIAPI\r
152VirtioPciIoWrite (\r
ac0a286f
MK
153 IN VIRTIO_PCI_DEVICE *Dev,\r
154 IN UINTN FieldOffset,\r
155 IN UINTN FieldSize,\r
156 IN UINT64 Value\r
3bb56c06
OM
157 )\r
158{\r
ac0a286f
MK
159 UINTN Count;\r
160 EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
161 EFI_PCI_IO_PROTOCOL *PciIo;\r
3bb56c06
OM
162\r
163 PciIo = Dev->PciIo;\r
164 Count = 1;\r
165\r
166 switch (FieldSize) {\r
167 case 1:\r
168 Width = EfiPciIoWidthUint8;\r
169 break;\r
170\r
171 case 2:\r
172 Width = EfiPciIoWidthUint16;\r
173 break;\r
174\r
175 case 8:\r
176 //\r
177 // The 64bit PCI I/O is broken down into two 32bit writes to prevent\r
178 // any alignment or width issues.\r
179 // The UEFI spec says under EFI_PCI_IO_PROTOCOL.Io.Write():\r
180 //\r
181 // The I/O operations are carried out exactly as requested. The caller\r
182 // is responsible for any alignment and I/O width issues which the\r
183 // bus, device, platform, or type of I/O might require. For example on\r
184 // some platforms, width requests of EfiPciIoWidthUint64 do not work\r
185 //\r
186 Count = Count * 2;\r
187\r
ac0a286f
MK
188 //\r
189 // fall through\r
190 //\r
3bb56c06
OM
191 case 4:\r
192 Width = EfiPciIoWidthUint32;\r
193 break;\r
194\r
195 default:\r
196 ASSERT (FALSE);\r
197 return EFI_INVALID_PARAMETER;\r
198 }\r
199\r
200 return PciIo->Io.Write (\r
201 PciIo,\r
202 Width,\r
203 PCI_BAR_IDX0,\r
204 FieldOffset,\r
205 Count,\r
206 &Value\r
207 );\r
208}\r
209\r
210/**\r
211\r
212 Device probe function for this driver.\r
213\r
214 The DXE core calls this function for any given device in order to see if the\r
215 driver can drive the device.\r
216\r
217 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object\r
218 incorporating this driver (independently of\r
219 any device).\r
220\r
221 @param[in] DeviceHandle The device to probe.\r
222\r
223 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.\r
224\r
225\r
226 @retval EFI_SUCCESS The driver supports the device being probed.\r
227\r
228 @retval EFI_UNSUPPORTED Based on virtio-pci discovery, we do not support\r
229 the device.\r
230\r
231 @return Error codes from the OpenProtocol() boot service or\r
232 the PciIo protocol.\r
233\r
234**/\r
235STATIC\r
236EFI_STATUS\r
237EFIAPI\r
238VirtioPciDeviceBindingSupported (\r
ac0a286f
MK
239 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
240 IN EFI_HANDLE DeviceHandle,\r
241 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
3bb56c06
OM
242 )\r
243{\r
ac0a286f
MK
244 EFI_STATUS Status;\r
245 EFI_PCI_IO_PROTOCOL *PciIo;\r
246 PCI_TYPE00 Pci;\r
3bb56c06
OM
247\r
248 //\r
249 // Attempt to open the device with the PciIo set of interfaces. On success,\r
250 // the protocol is "instantiated" for the PCI device. Covers duplicate open\r
251 // attempts (EFI_ALREADY_STARTED).\r
252 //\r
253 Status = gBS->OpenProtocol (\r
254 DeviceHandle, // candidate device\r
255 &gEfiPciIoProtocolGuid, // for generic PCI access\r
256 (VOID **)&PciIo, // handle to instantiate\r
257 This->DriverBindingHandle, // requestor driver identity\r
258 DeviceHandle, // ControllerHandle, according to\r
259 // the UEFI Driver Model\r
260 EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to\r
261 // the device; to be released\r
262 );\r
263 if (EFI_ERROR (Status)) {\r
264 return Status;\r
265 }\r
266\r
267 //\r
268 // Read entire PCI configuration header for more extensive check ahead.\r
269 //\r
270 Status = PciIo->Pci.Read (\r
271 PciIo, // (protocol, device)\r
272 // handle\r
273 EfiPciIoWidthUint32, // access width & copy\r
274 // mode\r
275 0, // Offset\r
276 sizeof Pci / sizeof (UINT32), // Count\r
277 &Pci // target buffer\r
278 );\r
279\r
280 if (Status == EFI_SUCCESS) {\r
281 //\r
282 // virtio-0.9.5, 2.1 PCI Discovery\r
283 //\r
284 if ((Pci.Hdr.VendorId == VIRTIO_VENDOR_ID) &&\r
285 (Pci.Hdr.DeviceId >= 0x1000) &&\r
286 (Pci.Hdr.DeviceId <= 0x103F) &&\r
ac0a286f
MK
287 (Pci.Hdr.RevisionID == 0x00))\r
288 {\r
3bb56c06
OM
289 Status = EFI_SUCCESS;\r
290 } else {\r
291 Status = EFI_UNSUPPORTED;\r
292 }\r
293 }\r
294\r
295 //\r
296 // We needed PCI IO access only transitorily, to see whether we support the\r
297 // device or not.\r
298 //\r
ac0a286f
MK
299 gBS->CloseProtocol (\r
300 DeviceHandle,\r
301 &gEfiPciIoProtocolGuid,\r
302 This->DriverBindingHandle,\r
303 DeviceHandle\r
304 );\r
3bb56c06
OM
305\r
306 return Status;\r
307}\r
308\r
309/**\r
310\r
311 Initialize the VirtIo PCI Device\r
312\r
313 @param[in, out] Dev The driver instance to configure. The caller is\r
314 responsible for Device->PciIo's validity (ie. working IO\r
315 access to the underlying virtio-pci device).\r
316\r
317 @retval EFI_SUCCESS Setup complete.\r
318\r
319 @retval EFI_UNSUPPORTED The underlying IO device doesn't support the\r
320 provided address offset and read size.\r
321\r
322 @return Error codes from PciIo->Pci.Read().\r
323\r
324**/\r
325STATIC\r
326EFI_STATUS\r
327EFIAPI\r
328VirtioPciInit (\r
ac0a286f 329 IN OUT VIRTIO_PCI_DEVICE *Device\r
3bb56c06
OM
330 )\r
331{\r
ac0a286f
MK
332 EFI_STATUS Status;\r
333 EFI_PCI_IO_PROTOCOL *PciIo;\r
334 PCI_TYPE00 Pci;\r
3bb56c06
OM
335\r
336 ASSERT (Device != NULL);\r
337 PciIo = Device->PciIo;\r
338 ASSERT (PciIo != NULL);\r
339 ASSERT (PciIo->Pci.Read != NULL);\r
340\r
341 Status = PciIo->Pci.Read (\r
ac0a286f
MK
342 PciIo, // (protocol, device)\r
343 // handle\r
344 EfiPciIoWidthUint32, // access width & copy\r
345 // mode\r
346 0, // Offset\r
3bb56c06 347 sizeof (Pci) / sizeof (UINT32), // Count\r
ac0a286f 348 &Pci // target buffer\r
3bb56c06
OM
349 );\r
350 if (EFI_ERROR (Status)) {\r
351 return Status;\r
352 }\r
353\r
354 //\r
355 // Copy protocol template\r
356 //\r
ac0a286f
MK
357 CopyMem (\r
358 &Device->VirtioDevice,\r
359 &mDeviceProtocolTemplate,\r
360 sizeof (VIRTIO_DEVICE_PROTOCOL)\r
361 );\r
3bb56c06
OM
362\r
363 //\r
364 // Initialize the protocol interface attributes\r
365 //\r
ac0a286f 366 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);\r
3bb56c06
OM
367 Device->VirtioDevice.SubSystemDeviceId = Pci.Device.SubsystemID;\r
368\r
369 //\r
370 // Note: We don't support the MSI-X capability. If we did,\r
371 // the offset would become 24 after enabling MSI-X.\r
372 //\r
373 Device->DeviceSpecificConfigurationOffset =\r
ac0a286f 374 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI;\r
3bb56c06
OM
375\r
376 return EFI_SUCCESS;\r
377}\r
378\r
379/**\r
380\r
381 Uninitialize the internals of a virtio-pci device that has been successfully\r
382 set up with VirtioPciInit().\r
383\r
384 @param[in, out] Dev The device to clean up.\r
385\r
386**/\r
3bb56c06
OM
387STATIC\r
388VOID\r
389EFIAPI\r
390VirtioPciUninit (\r
ac0a286f 391 IN OUT VIRTIO_PCI_DEVICE *Device\r
3bb56c06
OM
392 )\r
393{\r
394 // Note: This function mirrors VirtioPciInit() that does not allocate any\r
395 // resources - there's nothing to free here.\r
396}\r
397\r
398/**\r
399\r
400 After we've pronounced support for a specific device in\r
401 DriverBindingSupported(), we start managing said device (passed in by the\r
694673c9 402 Driver Execution Environment) with the following service.\r
3bb56c06
OM
403\r
404 See DriverBindingSupported() for specification references.\r
405\r
406 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object\r
407 incorporating this driver (independently of\r
408 any device).\r
409\r
410 @param[in] DeviceHandle The supported device to drive.\r
411\r
412 @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.\r
413\r
414\r
415 @retval EFI_SUCCESS Driver instance has been created and\r
416 initialized for the virtio-pci device, it\r
417 is now accessible via VIRTIO_DEVICE_PROTOCOL.\r
418\r
419 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
420\r
421 @return Error codes from the OpenProtocol() boot\r
422 service, the PciIo protocol, VirtioPciInit(),\r
423 or the InstallProtocolInterface() boot service.\r
424\r
425**/\r
426STATIC\r
427EFI_STATUS\r
428EFIAPI\r
429VirtioPciDeviceBindingStart (\r
ac0a286f
MK
430 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
431 IN EFI_HANDLE DeviceHandle,\r
432 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
3bb56c06
OM
433 )\r
434{\r
ac0a286f
MK
435 VIRTIO_PCI_DEVICE *Device;\r
436 EFI_STATUS Status;\r
3bb56c06 437\r
ac0a286f 438 Device = (VIRTIO_PCI_DEVICE *)AllocateZeroPool (sizeof *Device);\r
3bb56c06
OM
439 if (Device == NULL) {\r
440 return EFI_OUT_OF_RESOURCES;\r
441 }\r
442\r
ac0a286f
MK
443 Status = gBS->OpenProtocol (\r
444 DeviceHandle,\r
445 &gEfiPciIoProtocolGuid,\r
446 (VOID **)&Device->PciIo,\r
447 This->DriverBindingHandle,\r
448 DeviceHandle,\r
449 EFI_OPEN_PROTOCOL_BY_DRIVER\r
450 );\r
3bb56c06
OM
451 if (EFI_ERROR (Status)) {\r
452 goto FreeVirtioPci;\r
453 }\r
454\r
455 //\r
456 // We must retain and ultimately restore the original PCI attributes of the\r
457 // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /\r
458 // 18.3.2 Start() and Stop().\r
459 //\r
460 // The third parameter ("Attributes", input) is ignored by the Get operation.\r
461 // The fourth parameter ("Result", output) is ignored by the Enable and Set\r
462 // operations.\r
463 //\r
464 // For virtio-pci we only need IO space access.\r
465 //\r
ac0a286f
MK
466 Status = Device->PciIo->Attributes (\r
467 Device->PciIo,\r
468 EfiPciIoAttributeOperationGet,\r
469 0,\r
470 &Device->OriginalPciAttributes\r
471 );\r
3bb56c06
OM
472 if (EFI_ERROR (Status)) {\r
473 goto ClosePciIo;\r
474 }\r
475\r
78ef454b
BS
476 Status = Device->PciIo->Attributes (\r
477 Device->PciIo,\r
478 EfiPciIoAttributeOperationEnable,\r
479 (EFI_PCI_IO_ATTRIBUTE_IO |\r
480 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),\r
481 NULL\r
482 );\r
3bb56c06
OM
483 if (EFI_ERROR (Status)) {\r
484 goto ClosePciIo;\r
485 }\r
486\r
487 //\r
488 // PCI IO access granted, configure protocol instance\r
489 //\r
490\r
491 Status = VirtioPciInit (Device);\r
492 if (EFI_ERROR (Status)) {\r
493 goto RestorePciAttributes;\r
494 }\r
495\r
496 //\r
497 // Setup complete, attempt to export the driver instance's VirtioDevice\r
498 // interface.\r
499 //\r
500 Device->Signature = VIRTIO_PCI_DEVICE_SIGNATURE;\r
ac0a286f
MK
501 Status = gBS->InstallProtocolInterface (\r
502 &DeviceHandle,\r
503 &gVirtioDeviceProtocolGuid,\r
504 EFI_NATIVE_INTERFACE,\r
505 &Device->VirtioDevice\r
506 );\r
3bb56c06
OM
507 if (EFI_ERROR (Status)) {\r
508 goto UninitDev;\r
509 }\r
510\r
511 return EFI_SUCCESS;\r
512\r
513UninitDev:\r
514 VirtioPciUninit (Device);\r
515\r
516RestorePciAttributes:\r
ac0a286f
MK
517 Device->PciIo->Attributes (\r
518 Device->PciIo,\r
519 EfiPciIoAttributeOperationSet,\r
520 Device->OriginalPciAttributes,\r
521 NULL\r
522 );\r
3bb56c06
OM
523\r
524ClosePciIo:\r
ac0a286f
MK
525 gBS->CloseProtocol (\r
526 DeviceHandle,\r
527 &gEfiPciIoProtocolGuid,\r
528 This->DriverBindingHandle,\r
529 DeviceHandle\r
530 );\r
3bb56c06
OM
531\r
532FreeVirtioPci:\r
533 FreePool (Device);\r
534\r
535 return Status;\r
536}\r
537\r
538/**\r
539\r
540 Stop driving the Virtio PCI device\r
541\r
542 @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object\r
543 incorporating this driver (independently of any\r
544 device).\r
545\r
546 @param[in] DeviceHandle Stop driving this device.\r
547\r
548 @param[in] NumberOfChildren Since this function belongs to a device driver\r
549 only (as opposed to a bus driver), the caller\r
550 environment sets NumberOfChildren to zero, and\r
551 we ignore it.\r
552\r
553 @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).\r
554\r
555 @retval EFI_SUCCESS Driver instance has been stopped and the PCI\r
556 configuration attributes have been restored.\r
557\r
558 @return Error codes from the OpenProtocol() or\r
559 CloseProtocol(), UninstallProtocolInterface()\r
560 boot services.\r
561\r
562**/\r
563STATIC\r
564EFI_STATUS\r
565EFIAPI\r
566VirtioPciDeviceBindingStop (\r
ac0a286f
MK
567 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
568 IN EFI_HANDLE DeviceHandle,\r
569 IN UINTN NumberOfChildren,\r
570 IN EFI_HANDLE *ChildHandleBuffer\r
3bb56c06
OM
571 )\r
572{\r
ac0a286f 573 EFI_STATUS Status;\r
3bb56c06
OM
574 VIRTIO_DEVICE_PROTOCOL *VirtioDevice;\r
575 VIRTIO_PCI_DEVICE *Device;\r
576\r
577 Status = gBS->OpenProtocol (\r
578 DeviceHandle, // candidate device\r
579 &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface\r
580 (VOID **)&VirtioDevice, // target pointer\r
581 This->DriverBindingHandle, // requestor driver identity\r
582 DeviceHandle, // requesting lookup for dev.\r
583 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added\r
584 );\r
585 if (EFI_ERROR (Status)) {\r
586 return Status;\r
587 }\r
588\r
589 Device = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);\r
590\r
591 //\r
592 // Handle Stop() requests for in-use driver instances gracefully.\r
593 //\r
ac0a286f
MK
594 Status = gBS->UninstallProtocolInterface (\r
595 DeviceHandle,\r
596 &gVirtioDeviceProtocolGuid,\r
597 &Device->VirtioDevice\r
598 );\r
3bb56c06
OM
599 if (EFI_ERROR (Status)) {\r
600 return Status;\r
601 }\r
602\r
603 VirtioPciUninit (Device);\r
604\r
ac0a286f
MK
605 Device->PciIo->Attributes (\r
606 Device->PciIo,\r
607 EfiPciIoAttributeOperationSet,\r
608 Device->OriginalPciAttributes,\r
609 NULL\r
610 );\r
611\r
612 Status = gBS->CloseProtocol (\r
613 DeviceHandle,\r
614 &gEfiPciIoProtocolGuid,\r
615 This->DriverBindingHandle,\r
616 DeviceHandle\r
617 );\r
3bb56c06
OM
618\r
619 FreePool (Device);\r
620\r
621 return Status;\r
622}\r
623\r
3bb56c06
OM
624//\r
625// The static object that groups the Supported() (ie. probe), Start() and\r
626// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata\r
627// C, 10.1 EFI Driver Binding Protocol.\r
628//\r
ac0a286f 629STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {\r
3bb56c06
OM
630 &VirtioPciDeviceBindingSupported,\r
631 &VirtioPciDeviceBindingStart,\r
632 &VirtioPciDeviceBindingStop,\r
633 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers\r
634 NULL, // ImageHandle, to be overwritten by\r
635 // EfiLibInstallDriverBindingComponentName2() in VirtioPciEntryPoint()\r
636 NULL // DriverBindingHandle, ditto\r
637};\r
638\r
3bb56c06
OM
639//\r
640// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and\r
641// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name\r
642// in English, for display on standard console devices. This is recommended for\r
643// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's\r
644// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.\r
645//\r
646STATIC\r
ac0a286f 647EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
3bb56c06 648 { "eng;en", L"Virtio PCI Driver" },\r
ac0a286f 649 { NULL, NULL }\r
3bb56c06
OM
650};\r
651\r
652STATIC\r
ac0a286f 653EFI_COMPONENT_NAME_PROTOCOL gComponentName;\r
3bb56c06
OM
654\r
655EFI_STATUS\r
656EFIAPI\r
657VirtioPciGetDriverName (\r
ac0a286f
MK
658 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
659 IN CHAR8 *Language,\r
660 OUT CHAR16 **DriverName\r
3bb56c06
OM
661 )\r
662{\r
663 return LookupUnicodeString2 (\r
664 Language,\r
665 This->SupportedLanguages,\r
666 mDriverNameTable,\r
667 DriverName,\r
668 (BOOLEAN)(This == &gComponentName) // Iso639Language\r
669 );\r
670}\r
671\r
672EFI_STATUS\r
673EFIAPI\r
674VirtioPciGetDeviceName (\r
ac0a286f
MK
675 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
676 IN EFI_HANDLE DeviceHandle,\r
677 IN EFI_HANDLE ChildHandle,\r
678 IN CHAR8 *Language,\r
679 OUT CHAR16 **ControllerName\r
3bb56c06
OM
680 )\r
681{\r
682 return EFI_UNSUPPORTED;\r
683}\r
684\r
685STATIC\r
ac0a286f 686EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
3bb56c06
OM
687 &VirtioPciGetDriverName,\r
688 &VirtioPciGetDeviceName,\r
689 "eng" // SupportedLanguages, ISO 639-2 language codes\r
690};\r
691\r
692STATIC\r
ac0a286f
MK
693EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
694 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&VirtioPciGetDriverName,\r
695 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&VirtioPciGetDeviceName,\r
3bb56c06
OM
696 "en" // SupportedLanguages, RFC 4646 language codes\r
697};\r
698\r
3bb56c06
OM
699//\r
700// Entry point of this driver.\r
701//\r
702EFI_STATUS\r
703EFIAPI\r
704VirtioPciDeviceEntryPoint (\r
ac0a286f
MK
705 IN EFI_HANDLE ImageHandle,\r
706 IN EFI_SYSTEM_TABLE *SystemTable\r
3bb56c06
OM
707 )\r
708{\r
709 return EfiLibInstallDriverBindingComponentName2 (\r
710 ImageHandle,\r
711 SystemTable,\r
712 &gDriverBinding,\r
713 ImageHandle,\r
714 &gComponentName,\r
715 &gComponentName2\r
716 );\r
717}\r