--- /dev/null
+/** @file\r
+\r
+ This driver produces EFI_RNG_PROTOCOL instances for virtio-rng devices.\r
+\r
+ The implementation is based on OvmfPkg/VirtioScsiDxe/VirtioScsi.c\r
+\r
+ Copyright (C) 2012, Red Hat, Inc.\r
+ Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>\r
+\r
+ This driver:\r
+\r
+ Copyright (C) 2016, Linaro Ltd.\r
+\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/VirtioLib.h>\r
+\r
+#include "VirtioRng.h"\r
+\r
+/**\r
+ Returns information about the random number generation implementation.\r
+\r
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL\r
+ instance.\r
+ @param[in,out] RNGAlgorithmListSize On input, the size in bytes of\r
+ RNGAlgorithmList.\r
+ On output with a return code of\r
+ EFI_SUCCESS, the size in bytes of the\r
+ data returned in RNGAlgorithmList. On\r
+ output with a return code of\r
+ EFI_BUFFER_TOO_SMALL, the size of\r
+ RNGAlgorithmList required to obtain the\r
+ list.\r
+ @param[out] RNGAlgorithmList A caller-allocated memory buffer filled\r
+ by the driver with one EFI_RNG_ALGORITHM\r
+ element for each supported RNG algorithm.\r
+ The list must not change across multiple\r
+ calls to the same driver. The first\r
+ algorithm in the list is the default\r
+ algorithm for the driver.\r
+\r
+ @retval EFI_SUCCESS The RNG algorithm list was returned\r
+ successfully.\r
+ @retval EFI_UNSUPPORTED The services is not supported by this\r
+ driver.\r
+ @retval EFI_DEVICE_ERROR The list of algorithms could not be\r
+ retrieved due to a hardware or firmware\r
+ error.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are\r
+ incorrect.\r
+ @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small\r
+ to hold the result.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioRngGetInfo (\r
+ IN EFI_RNG_PROTOCOL *This,\r
+ IN OUT UINTN *RNGAlgorithmListSize,\r
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList\r
+ )\r
+{\r
+ if (This == NULL || RNGAlgorithmListSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (*RNGAlgorithmListSize < sizeof (EFI_RNG_ALGORITHM)) {\r
+ *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ if (RNGAlgorithmList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);\r
+ CopyGuid (RNGAlgorithmList, &gEfiRngAlgorithmRaw);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Produces and returns an RNG value using either the default or specified RNG\r
+ algorithm.\r
+\r
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL\r
+ instance.\r
+ @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that\r
+ identifies the RNG algorithm to use. May\r
+ be NULL in which case the function will\r
+ use its default RNG algorithm.\r
+ @param[in] RNGValueLength The length in bytes of the memory buffer\r
+ pointed to by RNGValue. The driver shall\r
+ return exactly this numbers of bytes.\r
+ @param[out] RNGValue A caller-allocated memory buffer filled\r
+ by the driver with the resulting RNG\r
+ value.\r
+\r
+ @retval EFI_SUCCESS The RNG value was returned successfully.\r
+ @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm\r
+ is not supported by this driver.\r
+ @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due\r
+ to a hardware or firmware error.\r
+ @retval EFI_NOT_READY There is not enough random data available\r
+ to satisfy the length requested by\r
+ RNGValueLength.\r
+ @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is\r
+ zero.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioRngGetRNG (\r
+ IN EFI_RNG_PROTOCOL *This,\r
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL\r
+ IN UINTN RNGValueLength,\r
+ OUT UINT8 *RNGValue\r
+ )\r
+{\r
+ VIRTIO_RNG_DEV *Dev;\r
+ DESC_INDICES Indices;\r
+ volatile UINT8 *Buffer;\r
+ UINTN Index;\r
+ UINT32 Len;\r
+ UINT32 BufferSize;\r
+ EFI_STATUS Status;\r
+\r
+ if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // We only support the raw algorithm, so reject requests for anything else\r
+ //\r
+ if (RNGAlgorithm != NULL &&\r
+ !CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Buffer = (volatile UINT8 *)AllocatePool (RNGValueLength);\r
+ if (Buffer == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);\r
+\r
+ //\r
+ // The Virtio RNG device may return less data than we asked it to, and can\r
+ // only return MAX_UINT32 bytes per invocation. So loop as long as needed to\r
+ // get all the entropy we were asked for.\r
+ //\r
+ for (Index = 0; Index < RNGValueLength; Index += Len) {\r
+ BufferSize = (UINT32)MIN (RNGValueLength - Index, (UINTN)MAX_UINT32);\r
+\r
+ VirtioPrepare (&Dev->Ring, &Indices);\r
+ VirtioAppendDesc (&Dev->Ring,\r
+ (UINTN)Buffer + Index,\r
+ BufferSize,\r
+ VRING_DESC_F_WRITE,\r
+ &Indices);\r
+\r
+ if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=\r
+ EFI_SUCCESS) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto FreeBuffer;\r
+ }\r
+ ASSERT (Len > 0);\r
+ ASSERT (Len <= BufferSize);\r
+ }\r
+\r
+ for (Index = 0; Index < RNGValueLength; Index++) {\r
+ RNGValue[Index] = Buffer[Index];\r
+ }\r
+ Status = EFI_SUCCESS;\r
+\r
+FreeBuffer:\r
+ FreePool ((VOID *)Buffer);\r
+ return Status;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioRngInit (\r
+ IN OUT VIRTIO_RNG_DEV *Dev\r
+ )\r
+{\r
+ UINT8 NextDevStat;\r
+ EFI_STATUS Status;\r
+ UINT16 QueueSize;\r
+ UINT32 Features;\r
+\r
+ //\r
+ // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.\r
+ //\r
+ NextDevStat = 0; // step 1 -- reset device\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Failed;\r
+ }\r
+\r
+ NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Failed;\r
+ }\r
+\r
+ NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Failed;\r
+ }\r
+\r
+ //\r
+ // Set Page Size - MMIO VirtIo Specific\r
+ //\r
+ Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Failed;\r
+ }\r
+\r
+ //\r
+ // step 4a -- retrieve and validate features\r
+ //\r
+ Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Failed;\r
+ }\r
+\r
+ //\r
+ // step 4b -- allocate request virtqueue, just use #0\r
+ //\r
+ Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Failed;\r
+ }\r
+ Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Failed;\r
+ }\r
+\r
+ //\r
+ // VirtioRngGetRNG() uses one descriptor\r
+ //\r
+ if (QueueSize < 1) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Failed;\r
+ }\r
+\r
+ Status = VirtioRingInit (QueueSize, &Dev->Ring);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Failed;\r
+ }\r
+\r
+ //\r
+ // Additional steps for MMIO: align the queue appropriately, and set the\r
+ // size. If anything fails from here on, we must release the ring resources.\r
+ //\r
+ Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
+ Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
+ //\r
+ // step 4c -- Report GPFN (guest-physical frame number) of queue.\r
+ //\r
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,\r
+ (UINT32) ((UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT));\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
+ //\r
+ // step 5 -- Report understood features and guest-tuneables. None are\r
+ // currently defined for VirtioRng, and no generic features are needed by\r
+ // this driver.\r
+ //\r
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
+ //\r
+ // step 6 -- initialization complete\r
+ //\r
+ NextDevStat |= VSTAT_DRIVER_OK;\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
+ //\r
+ // populate the exported interface's attributes\r
+ //\r
+ Dev->Rng.GetInfo = VirtioRngGetInfo;\r
+ Dev->Rng.GetRNG = VirtioRngGetRNG;\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ReleaseQueue:\r
+ VirtioRingUninit (&Dev->Ring);\r
+\r
+Failed:\r
+ //\r
+ // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device\r
+ // Status. VirtIo access failure here should not mask the original error.\r
+ //\r
+ NextDevStat |= VSTAT_FAILED;\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+\r
+ return Status; // reached only via Failed above\r
+}\r
+\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+VirtioRngUninit (\r
+ IN OUT VIRTIO_RNG_DEV *Dev\r
+ )\r
+{\r
+ //\r
+ // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When\r
+ // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from\r
+ // the old comms area.\r
+ //\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
+ VirtioRingUninit (&Dev->Ring);\r
+}\r
+\r
+//\r
+// Event notification function enqueued by ExitBootServices().\r
+//\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+VirtioRngExitBoot (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ VIRTIO_RNG_DEV *Dev;\r
+\r
+ //\r
+ // Reset the device. This causes the hypervisor to forget about the virtio\r
+ // ring.\r
+ //\r
+ // We allocated said ring in EfiBootServicesData type memory, and code\r
+ // executing after ExitBootServices() is permitted to overwrite it.\r
+ //\r
+ Dev = Context;\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
+}\r
+\r
+\r
+//\r
+// Probe, start and stop functions of this driver, called by the DXE core for\r
+// specific devices.\r
+//\r
+// The following specifications document these interfaces:\r
+// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol\r
+// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol\r
+//\r
+// The implementation follows:\r
+// - Driver Writer's Guide for UEFI 2.3.1 v1.01\r
+// - 5.1.3.4 OpenProtocol() and CloseProtocol()\r
+// - UEFI Spec 2.3.1 + Errata C\r
+// - 6.3 Protocol Handler Services\r
+//\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioRngDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE DeviceHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VIRTIO_DEVICE_PROTOCOL *VirtIo;\r
+\r
+ //\r
+ // Attempt to open the device with the VirtIo set of interfaces. On success,\r
+ // the protocol is "instantiated" for the VirtIo device. Covers duplicate\r
+ // open attempts (EFI_ALREADY_STARTED).\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ DeviceHandle, // candidate device\r
+ &gVirtioDeviceProtocolGuid, // for generic VirtIo access\r
+ (VOID **)&VirtIo, // handle to instantiate\r
+ This->DriverBindingHandle, // requestor driver identity\r
+ DeviceHandle, // ControllerHandle, according to\r
+ // the UEFI Driver Model\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to\r
+ // the device; to be released\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_ENTROPY_SOURCE) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // We needed VirtIo access only transitorily, to see whether we support the\r
+ // device or not.\r
+ //\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+ This->DriverBindingHandle, DeviceHandle);\r
+ return Status;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioRngDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE DeviceHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ VIRTIO_RNG_DEV *Dev;\r
+ EFI_STATUS Status;\r
+\r
+ Dev = (VIRTIO_RNG_DEV *) AllocateZeroPool (sizeof *Dev);\r
+ if (Dev == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+ (VOID **)&Dev->VirtIo, This->DriverBindingHandle,\r
+ DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeVirtioRng;\r
+ }\r
+\r
+ //\r
+ // VirtIo access granted, configure virtio-rng device.\r
+ //\r
+ Status = VirtioRngInit (Dev);\r
+ if (EFI_ERROR (Status)) {\r
+ goto CloseVirtIo;\r
+ }\r
+\r
+ Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,\r
+ &VirtioRngExitBoot, Dev, &Dev->ExitBoot);\r
+ if (EFI_ERROR (Status)) {\r
+ goto UninitDev;\r
+ }\r
+\r
+ //\r
+ // Setup complete, attempt to export the driver instance's EFI_RNG_PROTOCOL\r
+ // interface.\r
+ //\r
+ Dev->Signature = VIRTIO_RNG_SIG;\r
+ Status = gBS->InstallProtocolInterface (&DeviceHandle,\r
+ &gEfiRngProtocolGuid, EFI_NATIVE_INTERFACE,\r
+ &Dev->Rng);\r
+ if (EFI_ERROR (Status)) {\r
+ goto CloseExitBoot;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+CloseExitBoot:\r
+ gBS->CloseEvent (Dev->ExitBoot);\r
+\r
+UninitDev:\r
+ VirtioRngUninit (Dev);\r
+\r
+CloseVirtIo:\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+ This->DriverBindingHandle, DeviceHandle);\r
+\r
+FreeVirtioRng:\r
+ FreePool (Dev);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioRngDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE DeviceHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_RNG_PROTOCOL *Rng;\r
+ VIRTIO_RNG_DEV *Dev;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ DeviceHandle, // candidate device\r
+ &gEfiRngProtocolGuid, // retrieve the RNG iface\r
+ (VOID **)&Rng, // target pointer\r
+ This->DriverBindingHandle, // requestor driver ident.\r
+ DeviceHandle, // lookup req. for dev.\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no new ref.\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (Rng);\r
+\r
+ //\r
+ // Handle Stop() requests for in-use driver instances gracefully.\r
+ //\r
+ Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
+ &gEfiRngProtocolGuid, &Dev->Rng);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ gBS->CloseEvent (Dev->ExitBoot);\r
+\r
+ VirtioRngUninit (Dev);\r
+\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+ This->DriverBindingHandle, DeviceHandle);\r
+\r
+ FreePool (Dev);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+//\r
+// The static object that groups the Supported() (ie. probe), Start() and\r
+// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata\r
+// C, 10.1 EFI Driver Binding Protocol.\r
+//\r
+STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {\r
+ &VirtioRngDriverBindingSupported,\r
+ &VirtioRngDriverBindingStart,\r
+ &VirtioRngDriverBindingStop,\r
+ 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers\r
+ NULL, // ImageHandle, to be overwritten by\r
+ // EfiLibInstallDriverBindingComponentName2() in VirtioRngEntryPoint()\r
+ NULL // DriverBindingHandle, ditto\r
+};\r
+\r
+\r
+//\r
+// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and\r
+// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name\r
+// in English, for display on standard console devices. This is recommended for\r
+// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's\r
+// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.\r
+//\r
+\r
+STATIC\r
+EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
+ { "eng;en", L"Virtio Random Number Generator Driver" },\r
+ { NULL, NULL }\r
+};\r
+\r
+STATIC\r
+EFI_COMPONENT_NAME_PROTOCOL gComponentName;\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioRngGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+{\r
+ return LookupUnicodeString2 (\r
+ Language,\r
+ This->SupportedLanguages,\r
+ mDriverNameTable,\r
+ DriverName,\r
+ (BOOLEAN)(This == &gComponentName) // Iso639Language\r
+ );\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioRngGetDeviceName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE DeviceHandle,\r
+ IN EFI_HANDLE ChildHandle,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+STATIC\r
+EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
+ &VirtioRngGetDriverName,\r
+ &VirtioRngGetDeviceName,\r
+ "eng" // SupportedLanguages, ISO 639-2 language codes\r
+};\r
+\r
+STATIC\r
+EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &VirtioRngGetDriverName,\r
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioRngGetDeviceName,\r
+ "en" // SupportedLanguages, RFC 4646 language codes\r
+};\r
+\r
+\r
+//\r
+// Entry point of this driver.\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioRngEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ return EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gDriverBinding,\r
+ ImageHandle,\r
+ &gComponentName,\r
+ &gComponentName2\r
+ );\r
+}\r