3 This driver produces EFI_RNG_PROTOCOL instances for virtio-rng devices.
5 The implementation is based on OvmfPkg/VirtioScsiDxe/VirtioScsi.c
7 Copyright (C) 2012, Red Hat, Inc.
8 Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>
9 Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
13 Copyright (C) 2016, Linaro Ltd.
15 This program and the accompanying materials are licensed and made available
16 under the terms and conditions of the BSD License which accompanies this
17 distribution. The full text of the license may be found at
18 http://opensource.org/licenses/bsd-license.php
20 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
21 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 #include <Library/BaseMemoryLib.h>
26 #include <Library/DebugLib.h>
27 #include <Library/MemoryAllocationLib.h>
28 #include <Library/UefiBootServicesTableLib.h>
29 #include <Library/UefiLib.h>
30 #include <Library/VirtioLib.h>
32 #include "VirtioRng.h"
35 Returns information about the random number generation implementation.
37 @param[in] This A pointer to the EFI_RNG_PROTOCOL
39 @param[in,out] RNGAlgorithmListSize On input, the size in bytes of
41 On output with a return code of
42 EFI_SUCCESS, the size in bytes of the
43 data returned in RNGAlgorithmList. On
44 output with a return code of
45 EFI_BUFFER_TOO_SMALL, the size of
46 RNGAlgorithmList required to obtain the
48 @param[out] RNGAlgorithmList A caller-allocated memory buffer filled
49 by the driver with one EFI_RNG_ALGORITHM
50 element for each supported RNG algorithm.
51 The list must not change across multiple
52 calls to the same driver. The first
53 algorithm in the list is the default
54 algorithm for the driver.
56 @retval EFI_SUCCESS The RNG algorithm list was returned
58 @retval EFI_UNSUPPORTED The services is not supported by this
60 @retval EFI_DEVICE_ERROR The list of algorithms could not be
61 retrieved due to a hardware or firmware
63 @retval EFI_INVALID_PARAMETER One or more of the parameters are
65 @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small
73 IN EFI_RNG_PROTOCOL
*This
,
74 IN OUT UINTN
*RNGAlgorithmListSize
,
75 OUT EFI_RNG_ALGORITHM
*RNGAlgorithmList
78 if (This
== NULL
|| RNGAlgorithmListSize
== NULL
) {
79 return EFI_INVALID_PARAMETER
;
82 if (*RNGAlgorithmListSize
< sizeof (EFI_RNG_ALGORITHM
)) {
83 *RNGAlgorithmListSize
= sizeof (EFI_RNG_ALGORITHM
);
84 return EFI_BUFFER_TOO_SMALL
;
87 if (RNGAlgorithmList
== NULL
) {
88 return EFI_INVALID_PARAMETER
;
91 *RNGAlgorithmListSize
= sizeof (EFI_RNG_ALGORITHM
);
92 CopyGuid (RNGAlgorithmList
, &gEfiRngAlgorithmRaw
);
98 Produces and returns an RNG value using either the default or specified RNG
101 @param[in] This A pointer to the EFI_RNG_PROTOCOL
103 @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that
104 identifies the RNG algorithm to use. May
105 be NULL in which case the function will
106 use its default RNG algorithm.
107 @param[in] RNGValueLength The length in bytes of the memory buffer
108 pointed to by RNGValue. The driver shall
109 return exactly this numbers of bytes.
110 @param[out] RNGValue A caller-allocated memory buffer filled
111 by the driver with the resulting RNG
114 @retval EFI_SUCCESS The RNG value was returned successfully.
115 @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm
116 is not supported by this driver.
117 @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due
118 to a hardware or firmware error.
119 @retval EFI_NOT_READY There is not enough random data available
120 to satisfy the length requested by
122 @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is
130 IN EFI_RNG_PROTOCOL
*This
,
131 IN EFI_RNG_ALGORITHM
*RNGAlgorithm
, OPTIONAL
132 IN UINTN RNGValueLength
,
137 DESC_INDICES Indices
;
138 volatile UINT8
*Buffer
;
143 EFI_PHYSICAL_ADDRESS DeviceAddress
;
146 if (This
== NULL
|| RNGValueLength
== 0 || RNGValue
== NULL
) {
147 return EFI_INVALID_PARAMETER
;
151 // We only support the raw algorithm, so reject requests for anything else
153 if (RNGAlgorithm
!= NULL
&&
154 !CompareGuid (RNGAlgorithm
, &gEfiRngAlgorithmRaw
)) {
155 return EFI_UNSUPPORTED
;
158 Buffer
= (volatile UINT8
*)AllocatePool (RNGValueLength
);
159 if (Buffer
== NULL
) {
160 return EFI_DEVICE_ERROR
;
163 Dev
= VIRTIO_ENTROPY_SOURCE_FROM_RNG (This
);
165 // Map Buffer's system phyiscal address to device address
167 Status
= VirtioMapAllBytesInSharedBuffer (
169 VirtioOperationBusMasterWrite
,
175 if (EFI_ERROR (Status
)) {
176 Status
= EFI_DEVICE_ERROR
;
181 // The Virtio RNG device may return less data than we asked it to, and can
182 // only return MAX_UINT32 bytes per invocation. So loop as long as needed to
183 // get all the entropy we were asked for.
185 for (Index
= 0; Index
< RNGValueLength
; Index
+= Len
) {
186 BufferSize
= (UINT32
)MIN (RNGValueLength
- Index
, (UINTN
)MAX_UINT32
);
188 VirtioPrepare (&Dev
->Ring
, &Indices
);
189 VirtioAppendDesc (&Dev
->Ring
,
190 DeviceAddress
+ Index
,
195 if (VirtioFlush (Dev
->VirtIo
, 0, &Dev
->Ring
, &Indices
, &Len
) !=
197 Status
= EFI_DEVICE_ERROR
;
201 ASSERT (Len
<= BufferSize
);
205 // Unmap the device buffer before accessing it.
207 Status
= Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Mapping
);
208 if (EFI_ERROR (Status
)) {
209 Status
= EFI_DEVICE_ERROR
;
213 for (Index
= 0; Index
< RNGValueLength
; Index
++) {
214 RNGValue
[Index
] = Buffer
[Index
];
216 Status
= EFI_SUCCESS
;
220 // If we are reached here due to the error then unmap the buffer otherwise
221 // the buffer is already unmapped after VirtioFlush().
223 if (EFI_ERROR (Status
)) {
224 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Mapping
);
228 FreePool ((VOID
*)Buffer
);
236 IN OUT VIRTIO_RNG_DEV
*Dev
243 UINT64 RingBaseShift
;
246 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
248 NextDevStat
= 0; // step 1 -- reset device
249 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
250 if (EFI_ERROR (Status
)) {
254 NextDevStat
|= VSTAT_ACK
; // step 2 -- acknowledge device presence
255 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
256 if (EFI_ERROR (Status
)) {
260 NextDevStat
|= VSTAT_DRIVER
; // step 3 -- we know how to drive it
261 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
262 if (EFI_ERROR (Status
)) {
267 // Set Page Size - MMIO VirtIo Specific
269 Status
= Dev
->VirtIo
->SetPageSize (Dev
->VirtIo
, EFI_PAGE_SIZE
);
270 if (EFI_ERROR (Status
)) {
275 // step 4a -- retrieve and validate features
277 Status
= Dev
->VirtIo
->GetDeviceFeatures (Dev
->VirtIo
, &Features
);
278 if (EFI_ERROR (Status
)) {
282 Features
&= VIRTIO_F_VERSION_1
| VIRTIO_F_IOMMU_PLATFORM
;
285 // In virtio-1.0, feature negotiation is expected to complete before queue
286 // discovery, and the device can also reject the selected set of features.
288 if (Dev
->VirtIo
->Revision
>= VIRTIO_SPEC_REVISION (1, 0, 0)) {
289 Status
= Virtio10WriteFeatures (Dev
->VirtIo
, Features
, &NextDevStat
);
290 if (EFI_ERROR (Status
)) {
296 // step 4b -- allocate request virtqueue, just use #0
298 Status
= Dev
->VirtIo
->SetQueueSel (Dev
->VirtIo
, 0);
299 if (EFI_ERROR (Status
)) {
302 Status
= Dev
->VirtIo
->GetQueueNumMax (Dev
->VirtIo
, &QueueSize
);
303 if (EFI_ERROR (Status
)) {
308 // VirtioRngGetRNG() uses one descriptor
311 Status
= EFI_UNSUPPORTED
;
315 Status
= VirtioRingInit (Dev
->VirtIo
, QueueSize
, &Dev
->Ring
);
316 if (EFI_ERROR (Status
)) {
321 // If anything fails from here on, we must release the ring resources.
323 Status
= VirtioRingMap (
329 if (EFI_ERROR (Status
)) {
334 // Additional steps for MMIO: align the queue appropriately, and set the
335 // size. If anything fails from here on, we must unmap the ring resources.
337 Status
= Dev
->VirtIo
->SetQueueNum (Dev
->VirtIo
, QueueSize
);
338 if (EFI_ERROR (Status
)) {
342 Status
= Dev
->VirtIo
->SetQueueAlign (Dev
->VirtIo
, EFI_PAGE_SIZE
);
343 if (EFI_ERROR (Status
)) {
348 // step 4c -- Report GPFN (guest-physical frame number) of queue.
350 Status
= Dev
->VirtIo
->SetQueueAddress (
355 if (EFI_ERROR (Status
)) {
360 // step 5 -- Report understood features and guest-tuneables.
362 if (Dev
->VirtIo
->Revision
< VIRTIO_SPEC_REVISION (1, 0, 0)) {
363 Features
&= ~(UINT64
)(VIRTIO_F_VERSION_1
| VIRTIO_F_IOMMU_PLATFORM
);
364 Status
= Dev
->VirtIo
->SetGuestFeatures (Dev
->VirtIo
, Features
);
365 if (EFI_ERROR (Status
)) {
371 // step 6 -- initialization complete
373 NextDevStat
|= VSTAT_DRIVER_OK
;
374 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
375 if (EFI_ERROR (Status
)) {
380 // populate the exported interface's attributes
382 Dev
->Rng
.GetInfo
= VirtioRngGetInfo
;
383 Dev
->Rng
.GetRNG
= VirtioRngGetRNG
;
388 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
391 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
395 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
396 // Status. VirtIo access failure here should not mask the original error.
398 NextDevStat
|= VSTAT_FAILED
;
399 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
401 return Status
; // reached only via Failed above
409 IN OUT VIRTIO_RNG_DEV
*Dev
413 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
414 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
415 // the old comms area.
417 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
419 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
421 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
425 // Event notification function enqueued by ExitBootServices().
438 DEBUG ((DEBUG_VERBOSE
, "%a: Context=0x%p\n", __FUNCTION__
, Context
));
440 // Reset the device. This causes the hypervisor to forget about the virtio
443 // We allocated said ring in EfiBootServicesData type memory, and code
444 // executing after ExitBootServices() is permitted to overwrite it.
447 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
452 // Probe, start and stop functions of this driver, called by the DXE core for
455 // The following specifications document these interfaces:
456 // - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
457 // - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
459 // The implementation follows:
460 // - Driver Writer's Guide for UEFI 2.3.1 v1.01
461 // - 5.1.3.4 OpenProtocol() and CloseProtocol()
462 // - UEFI Spec 2.3.1 + Errata C
463 // - 6.3 Protocol Handler Services
469 VirtioRngDriverBindingSupported (
470 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
471 IN EFI_HANDLE DeviceHandle
,
472 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
476 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
479 // Attempt to open the device with the VirtIo set of interfaces. On success,
480 // the protocol is "instantiated" for the VirtIo device. Covers duplicate
481 // open attempts (EFI_ALREADY_STARTED).
483 Status
= gBS
->OpenProtocol (
484 DeviceHandle
, // candidate device
485 &gVirtioDeviceProtocolGuid
, // for generic VirtIo access
486 (VOID
**)&VirtIo
, // handle to instantiate
487 This
->DriverBindingHandle
, // requestor driver identity
488 DeviceHandle
, // ControllerHandle, according to
489 // the UEFI Driver Model
490 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive VirtIo access to
491 // the device; to be released
493 if (EFI_ERROR (Status
)) {
497 if (VirtIo
->SubSystemDeviceId
!= VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) {
498 Status
= EFI_UNSUPPORTED
;
502 // We needed VirtIo access only transitorily, to see whether we support the
505 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
506 This
->DriverBindingHandle
, DeviceHandle
);
513 VirtioRngDriverBindingStart (
514 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
515 IN EFI_HANDLE DeviceHandle
,
516 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
522 Dev
= (VIRTIO_RNG_DEV
*) AllocateZeroPool (sizeof *Dev
);
524 return EFI_OUT_OF_RESOURCES
;
527 Status
= gBS
->OpenProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
528 (VOID
**)&Dev
->VirtIo
, This
->DriverBindingHandle
,
529 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
530 if (EFI_ERROR (Status
)) {
535 // VirtIo access granted, configure virtio-rng device.
537 Status
= VirtioRngInit (Dev
);
538 if (EFI_ERROR (Status
)) {
542 Status
= gBS
->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES
, TPL_CALLBACK
,
543 &VirtioRngExitBoot
, Dev
, &Dev
->ExitBoot
);
544 if (EFI_ERROR (Status
)) {
549 // Setup complete, attempt to export the driver instance's EFI_RNG_PROTOCOL
552 Dev
->Signature
= VIRTIO_RNG_SIG
;
553 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
554 &gEfiRngProtocolGuid
, EFI_NATIVE_INTERFACE
,
556 if (EFI_ERROR (Status
)) {
563 gBS
->CloseEvent (Dev
->ExitBoot
);
566 VirtioRngUninit (Dev
);
569 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
570 This
->DriverBindingHandle
, DeviceHandle
);
582 VirtioRngDriverBindingStop (
583 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
584 IN EFI_HANDLE DeviceHandle
,
585 IN UINTN NumberOfChildren
,
586 IN EFI_HANDLE
*ChildHandleBuffer
590 EFI_RNG_PROTOCOL
*Rng
;
593 Status
= gBS
->OpenProtocol (
594 DeviceHandle
, // candidate device
595 &gEfiRngProtocolGuid
, // retrieve the RNG iface
596 (VOID
**)&Rng
, // target pointer
597 This
->DriverBindingHandle
, // requestor driver ident.
598 DeviceHandle
, // lookup req. for dev.
599 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no new ref.
601 if (EFI_ERROR (Status
)) {
605 Dev
= VIRTIO_ENTROPY_SOURCE_FROM_RNG (Rng
);
608 // Handle Stop() requests for in-use driver instances gracefully.
610 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
611 &gEfiRngProtocolGuid
, &Dev
->Rng
);
612 if (EFI_ERROR (Status
)) {
616 gBS
->CloseEvent (Dev
->ExitBoot
);
618 VirtioRngUninit (Dev
);
620 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
621 This
->DriverBindingHandle
, DeviceHandle
);
630 // The static object that groups the Supported() (ie. probe), Start() and
631 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
632 // C, 10.1 EFI Driver Binding Protocol.
634 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
635 &VirtioRngDriverBindingSupported
,
636 &VirtioRngDriverBindingStart
,
637 &VirtioRngDriverBindingStop
,
638 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
639 NULL
, // ImageHandle, to be overwritten by
640 // EfiLibInstallDriverBindingComponentName2() in VirtioRngEntryPoint()
641 NULL
// DriverBindingHandle, ditto
646 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
647 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
648 // in English, for display on standard console devices. This is recommended for
649 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
650 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
654 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
655 { "eng;en", L
"Virtio Random Number Generator Driver" },
660 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
665 VirtioRngGetDriverName (
666 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
668 OUT CHAR16
**DriverName
671 return LookupUnicodeString2 (
673 This
->SupportedLanguages
,
676 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
683 VirtioRngGetDeviceName (
684 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
685 IN EFI_HANDLE DeviceHandle
,
686 IN EFI_HANDLE ChildHandle
,
688 OUT CHAR16
**ControllerName
691 return EFI_UNSUPPORTED
;
695 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
696 &VirtioRngGetDriverName
,
697 &VirtioRngGetDeviceName
,
698 "eng" // SupportedLanguages, ISO 639-2 language codes
702 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
703 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioRngGetDriverName
,
704 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioRngGetDeviceName
,
705 "en" // SupportedLanguages, RFC 4646 language codes
710 // Entry point of this driver.
714 VirtioRngEntryPoint (
715 IN EFI_HANDLE ImageHandle
,
716 IN EFI_SYSTEM_TABLE
*SystemTable
719 return EfiLibInstallDriverBindingComponentName2 (