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 SPDX-License-Identifier: BSD-2-Clause-Patent
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/UefiLib.h>
24 #include <Library/VirtioLib.h>
26 #include "VirtioRng.h"
29 Returns information about the random number generation implementation.
31 @param[in] This A pointer to the EFI_RNG_PROTOCOL
33 @param[in,out] RNGAlgorithmListSize On input, the size in bytes of
35 On output with a return code of
36 EFI_SUCCESS, the size in bytes of the
37 data returned in RNGAlgorithmList. On
38 output with a return code of
39 EFI_BUFFER_TOO_SMALL, the size of
40 RNGAlgorithmList required to obtain the
42 @param[out] RNGAlgorithmList A caller-allocated memory buffer filled
43 by the driver with one EFI_RNG_ALGORITHM
44 element for each supported RNG algorithm.
45 The list must not change across multiple
46 calls to the same driver. The first
47 algorithm in the list is the default
48 algorithm for the driver.
50 @retval EFI_SUCCESS The RNG algorithm list was returned
52 @retval EFI_UNSUPPORTED The services is not supported by this
54 @retval EFI_DEVICE_ERROR The list of algorithms could not be
55 retrieved due to a hardware or firmware
57 @retval EFI_INVALID_PARAMETER One or more of the parameters are
59 @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small
67 IN EFI_RNG_PROTOCOL
*This
,
68 IN OUT UINTN
*RNGAlgorithmListSize
,
69 OUT EFI_RNG_ALGORITHM
*RNGAlgorithmList
72 if (This
== NULL
|| RNGAlgorithmListSize
== NULL
) {
73 return EFI_INVALID_PARAMETER
;
76 if (*RNGAlgorithmListSize
< sizeof (EFI_RNG_ALGORITHM
)) {
77 *RNGAlgorithmListSize
= sizeof (EFI_RNG_ALGORITHM
);
78 return EFI_BUFFER_TOO_SMALL
;
81 if (RNGAlgorithmList
== NULL
) {
82 return EFI_INVALID_PARAMETER
;
85 *RNGAlgorithmListSize
= sizeof (EFI_RNG_ALGORITHM
);
86 CopyGuid (RNGAlgorithmList
, &gEfiRngAlgorithmRaw
);
92 Produces and returns an RNG value using either the default or specified RNG
95 @param[in] This A pointer to the EFI_RNG_PROTOCOL
97 @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that
98 identifies the RNG algorithm to use. May
99 be NULL in which case the function will
100 use its default RNG algorithm.
101 @param[in] RNGValueLength The length in bytes of the memory buffer
102 pointed to by RNGValue. The driver shall
103 return exactly this numbers of bytes.
104 @param[out] RNGValue A caller-allocated memory buffer filled
105 by the driver with the resulting RNG
108 @retval EFI_SUCCESS The RNG value was returned successfully.
109 @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm
110 is not supported by this driver.
111 @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due
112 to a hardware or firmware error.
113 @retval EFI_NOT_READY There is not enough random data available
114 to satisfy the length requested by
116 @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is
124 IN EFI_RNG_PROTOCOL
*This
,
125 IN EFI_RNG_ALGORITHM
*RNGAlgorithm
, OPTIONAL
126 IN UINTN RNGValueLength
,
131 DESC_INDICES Indices
;
132 volatile UINT8
*Buffer
;
137 EFI_PHYSICAL_ADDRESS DeviceAddress
;
140 if (This
== NULL
|| RNGValueLength
== 0 || RNGValue
== NULL
) {
141 return EFI_INVALID_PARAMETER
;
145 // We only support the raw algorithm, so reject requests for anything else
147 if (RNGAlgorithm
!= NULL
&&
148 !CompareGuid (RNGAlgorithm
, &gEfiRngAlgorithmRaw
)) {
149 return EFI_UNSUPPORTED
;
152 Buffer
= (volatile UINT8
*)AllocatePool (RNGValueLength
);
153 if (Buffer
== NULL
) {
154 return EFI_DEVICE_ERROR
;
157 Dev
= VIRTIO_ENTROPY_SOURCE_FROM_RNG (This
);
159 // Map Buffer's system phyiscal address to device address
161 Status
= VirtioMapAllBytesInSharedBuffer (
163 VirtioOperationBusMasterWrite
,
169 if (EFI_ERROR (Status
)) {
170 Status
= EFI_DEVICE_ERROR
;
175 // The Virtio RNG device may return less data than we asked it to, and can
176 // only return MAX_UINT32 bytes per invocation. So loop as long as needed to
177 // get all the entropy we were asked for.
179 for (Index
= 0; Index
< RNGValueLength
; Index
+= Len
) {
180 BufferSize
= (UINT32
)MIN (RNGValueLength
- Index
, (UINTN
)MAX_UINT32
);
182 VirtioPrepare (&Dev
->Ring
, &Indices
);
183 VirtioAppendDesc (&Dev
->Ring
,
184 DeviceAddress
+ Index
,
189 if (VirtioFlush (Dev
->VirtIo
, 0, &Dev
->Ring
, &Indices
, &Len
) !=
191 Status
= EFI_DEVICE_ERROR
;
195 ASSERT (Len
<= BufferSize
);
199 // Unmap the device buffer before accessing it.
201 Status
= Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Mapping
);
202 if (EFI_ERROR (Status
)) {
203 Status
= EFI_DEVICE_ERROR
;
207 for (Index
= 0; Index
< RNGValueLength
; Index
++) {
208 RNGValue
[Index
] = Buffer
[Index
];
210 Status
= EFI_SUCCESS
;
214 // If we are reached here due to the error then unmap the buffer otherwise
215 // the buffer is already unmapped after VirtioFlush().
217 if (EFI_ERROR (Status
)) {
218 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Mapping
);
222 FreePool ((VOID
*)Buffer
);
230 IN OUT VIRTIO_RNG_DEV
*Dev
237 UINT64 RingBaseShift
;
240 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
242 NextDevStat
= 0; // step 1 -- reset device
243 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
244 if (EFI_ERROR (Status
)) {
248 NextDevStat
|= VSTAT_ACK
; // step 2 -- acknowledge device presence
249 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
250 if (EFI_ERROR (Status
)) {
254 NextDevStat
|= VSTAT_DRIVER
; // step 3 -- we know how to drive it
255 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
256 if (EFI_ERROR (Status
)) {
261 // Set Page Size - MMIO VirtIo Specific
263 Status
= Dev
->VirtIo
->SetPageSize (Dev
->VirtIo
, EFI_PAGE_SIZE
);
264 if (EFI_ERROR (Status
)) {
269 // step 4a -- retrieve and validate features
271 Status
= Dev
->VirtIo
->GetDeviceFeatures (Dev
->VirtIo
, &Features
);
272 if (EFI_ERROR (Status
)) {
276 Features
&= VIRTIO_F_VERSION_1
| VIRTIO_F_IOMMU_PLATFORM
;
279 // In virtio-1.0, feature negotiation is expected to complete before queue
280 // discovery, and the device can also reject the selected set of features.
282 if (Dev
->VirtIo
->Revision
>= VIRTIO_SPEC_REVISION (1, 0, 0)) {
283 Status
= Virtio10WriteFeatures (Dev
->VirtIo
, Features
, &NextDevStat
);
284 if (EFI_ERROR (Status
)) {
290 // step 4b -- allocate request virtqueue, just use #0
292 Status
= Dev
->VirtIo
->SetQueueSel (Dev
->VirtIo
, 0);
293 if (EFI_ERROR (Status
)) {
296 Status
= Dev
->VirtIo
->GetQueueNumMax (Dev
->VirtIo
, &QueueSize
);
297 if (EFI_ERROR (Status
)) {
302 // VirtioRngGetRNG() uses one descriptor
305 Status
= EFI_UNSUPPORTED
;
309 Status
= VirtioRingInit (Dev
->VirtIo
, QueueSize
, &Dev
->Ring
);
310 if (EFI_ERROR (Status
)) {
315 // If anything fails from here on, we must release the ring resources.
317 Status
= VirtioRingMap (
323 if (EFI_ERROR (Status
)) {
328 // Additional steps for MMIO: align the queue appropriately, and set the
329 // size. If anything fails from here on, we must unmap the ring resources.
331 Status
= Dev
->VirtIo
->SetQueueNum (Dev
->VirtIo
, QueueSize
);
332 if (EFI_ERROR (Status
)) {
336 Status
= Dev
->VirtIo
->SetQueueAlign (Dev
->VirtIo
, EFI_PAGE_SIZE
);
337 if (EFI_ERROR (Status
)) {
342 // step 4c -- Report GPFN (guest-physical frame number) of queue.
344 Status
= Dev
->VirtIo
->SetQueueAddress (
349 if (EFI_ERROR (Status
)) {
354 // step 5 -- Report understood features and guest-tuneables.
356 if (Dev
->VirtIo
->Revision
< VIRTIO_SPEC_REVISION (1, 0, 0)) {
357 Features
&= ~(UINT64
)(VIRTIO_F_VERSION_1
| VIRTIO_F_IOMMU_PLATFORM
);
358 Status
= Dev
->VirtIo
->SetGuestFeatures (Dev
->VirtIo
, Features
);
359 if (EFI_ERROR (Status
)) {
365 // step 6 -- initialization complete
367 NextDevStat
|= VSTAT_DRIVER_OK
;
368 Status
= Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
369 if (EFI_ERROR (Status
)) {
374 // populate the exported interface's attributes
376 Dev
->Rng
.GetInfo
= VirtioRngGetInfo
;
377 Dev
->Rng
.GetRNG
= VirtioRngGetRNG
;
382 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
385 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
389 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
390 // Status. VirtIo access failure here should not mask the original error.
392 NextDevStat
|= VSTAT_FAILED
;
393 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, NextDevStat
);
395 return Status
; // reached only via Failed above
403 IN OUT VIRTIO_RNG_DEV
*Dev
407 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
408 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
409 // the old comms area.
411 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
413 Dev
->VirtIo
->UnmapSharedBuffer (Dev
->VirtIo
, Dev
->RingMap
);
415 VirtioRingUninit (Dev
->VirtIo
, &Dev
->Ring
);
419 // Event notification function enqueued by ExitBootServices().
432 DEBUG ((DEBUG_VERBOSE
, "%a: Context=0x%p\n", __FUNCTION__
, Context
));
434 // Reset the device. This causes the hypervisor to forget about the virtio
437 // We allocated said ring in EfiBootServicesData type memory, and code
438 // executing after ExitBootServices() is permitted to overwrite it.
441 Dev
->VirtIo
->SetDeviceStatus (Dev
->VirtIo
, 0);
446 // Probe, start and stop functions of this driver, called by the DXE core for
449 // The following specifications document these interfaces:
450 // - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
451 // - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
453 // The implementation follows:
454 // - Driver Writer's Guide for UEFI 2.3.1 v1.01
455 // - 5.1.3.4 OpenProtocol() and CloseProtocol()
456 // - UEFI Spec 2.3.1 + Errata C
457 // - 6.3 Protocol Handler Services
463 VirtioRngDriverBindingSupported (
464 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
465 IN EFI_HANDLE DeviceHandle
,
466 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
470 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
473 // Attempt to open the device with the VirtIo set of interfaces. On success,
474 // the protocol is "instantiated" for the VirtIo device. Covers duplicate
475 // open attempts (EFI_ALREADY_STARTED).
477 Status
= gBS
->OpenProtocol (
478 DeviceHandle
, // candidate device
479 &gVirtioDeviceProtocolGuid
, // for generic VirtIo access
480 (VOID
**)&VirtIo
, // handle to instantiate
481 This
->DriverBindingHandle
, // requestor driver identity
482 DeviceHandle
, // ControllerHandle, according to
483 // the UEFI Driver Model
484 EFI_OPEN_PROTOCOL_BY_DRIVER
// get exclusive VirtIo access to
485 // the device; to be released
487 if (EFI_ERROR (Status
)) {
491 if (VirtIo
->SubSystemDeviceId
!= VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) {
492 Status
= EFI_UNSUPPORTED
;
496 // We needed VirtIo access only transitorily, to see whether we support the
499 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
500 This
->DriverBindingHandle
, DeviceHandle
);
507 VirtioRngDriverBindingStart (
508 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
509 IN EFI_HANDLE DeviceHandle
,
510 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
516 Dev
= (VIRTIO_RNG_DEV
*) AllocateZeroPool (sizeof *Dev
);
518 return EFI_OUT_OF_RESOURCES
;
521 Status
= gBS
->OpenProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
522 (VOID
**)&Dev
->VirtIo
, This
->DriverBindingHandle
,
523 DeviceHandle
, EFI_OPEN_PROTOCOL_BY_DRIVER
);
524 if (EFI_ERROR (Status
)) {
529 // VirtIo access granted, configure virtio-rng device.
531 Status
= VirtioRngInit (Dev
);
532 if (EFI_ERROR (Status
)) {
536 Status
= gBS
->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES
, TPL_CALLBACK
,
537 &VirtioRngExitBoot
, Dev
, &Dev
->ExitBoot
);
538 if (EFI_ERROR (Status
)) {
543 // Setup complete, attempt to export the driver instance's EFI_RNG_PROTOCOL
546 Dev
->Signature
= VIRTIO_RNG_SIG
;
547 Status
= gBS
->InstallProtocolInterface (&DeviceHandle
,
548 &gEfiRngProtocolGuid
, EFI_NATIVE_INTERFACE
,
550 if (EFI_ERROR (Status
)) {
557 gBS
->CloseEvent (Dev
->ExitBoot
);
560 VirtioRngUninit (Dev
);
563 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
564 This
->DriverBindingHandle
, DeviceHandle
);
576 VirtioRngDriverBindingStop (
577 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
578 IN EFI_HANDLE DeviceHandle
,
579 IN UINTN NumberOfChildren
,
580 IN EFI_HANDLE
*ChildHandleBuffer
584 EFI_RNG_PROTOCOL
*Rng
;
587 Status
= gBS
->OpenProtocol (
588 DeviceHandle
, // candidate device
589 &gEfiRngProtocolGuid
, // retrieve the RNG iface
590 (VOID
**)&Rng
, // target pointer
591 This
->DriverBindingHandle
, // requestor driver ident.
592 DeviceHandle
, // lookup req. for dev.
593 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// lookup only, no new ref.
595 if (EFI_ERROR (Status
)) {
599 Dev
= VIRTIO_ENTROPY_SOURCE_FROM_RNG (Rng
);
602 // Handle Stop() requests for in-use driver instances gracefully.
604 Status
= gBS
->UninstallProtocolInterface (DeviceHandle
,
605 &gEfiRngProtocolGuid
, &Dev
->Rng
);
606 if (EFI_ERROR (Status
)) {
610 gBS
->CloseEvent (Dev
->ExitBoot
);
612 VirtioRngUninit (Dev
);
614 gBS
->CloseProtocol (DeviceHandle
, &gVirtioDeviceProtocolGuid
,
615 This
->DriverBindingHandle
, DeviceHandle
);
624 // The static object that groups the Supported() (ie. probe), Start() and
625 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
626 // C, 10.1 EFI Driver Binding Protocol.
628 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
629 &VirtioRngDriverBindingSupported
,
630 &VirtioRngDriverBindingStart
,
631 &VirtioRngDriverBindingStop
,
632 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
633 NULL
, // ImageHandle, to be overwritten by
634 // EfiLibInstallDriverBindingComponentName2() in VirtioRngEntryPoint()
635 NULL
// DriverBindingHandle, ditto
640 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
641 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
642 // in English, for display on standard console devices. This is recommended for
643 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
644 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
648 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
649 { "eng;en", L
"Virtio Random Number Generator Driver" },
654 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
659 VirtioRngGetDriverName (
660 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
662 OUT CHAR16
**DriverName
665 return LookupUnicodeString2 (
667 This
->SupportedLanguages
,
670 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
677 VirtioRngGetDeviceName (
678 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
679 IN EFI_HANDLE DeviceHandle
,
680 IN EFI_HANDLE ChildHandle
,
682 OUT CHAR16
**ControllerName
685 return EFI_UNSUPPORTED
;
689 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
690 &VirtioRngGetDriverName
,
691 &VirtioRngGetDeviceName
,
692 "eng" // SupportedLanguages, ISO 639-2 language codes
696 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
697 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &VirtioRngGetDriverName
,
698 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &VirtioRngGetDeviceName
,
699 "en" // SupportedLanguages, RFC 4646 language codes
704 // Entry point of this driver.
708 VirtioRngEntryPoint (
709 IN EFI_HANDLE ImageHandle
,
710 IN EFI_SYSTEM_TABLE
*SystemTable
713 return EfiLibInstallDriverBindingComponentName2 (