1/** @file
2
3  This driver produces EFI_RNG_PROTOCOL instances for virtio-rng devices.
4
5  The implementation is based on OvmfPkg/VirtioScsiDxe/VirtioScsi.c
6
7  Copyright (C) 2012, Red Hat, Inc.
8  Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>
9
10  This driver:
11
12  Copyright (C) 2016, Linaro Ltd.
13
14  This program and the accompanying materials are licensed and made available
15  under the terms and conditions of the BSD License which accompanies this
16  distribution. The full text of the license may be found at
17  http://opensource.org/licenses/bsd-license.php
18
19  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
20  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21
22**/
23
24#include <Library/BaseMemoryLib.h>
25#include <Library/DebugLib.h>
26#include <Library/MemoryAllocationLib.h>
27#include <Library/UefiBootServicesTableLib.h>
28#include <Library/UefiLib.h>
29#include <Library/VirtioLib.h>
30
31#include "VirtioRng.h"
32
33/**
34  Returns information about the random number generation implementation.
35
36  @param[in]     This                 A pointer to the EFI_RNG_PROTOCOL
37                                      instance.
38  @param[in,out] RNGAlgorithmListSize On input, the size in bytes of
39                                      RNGAlgorithmList.
40                                      On output with a return code of
41                                      EFI_SUCCESS, the size in bytes of the
42                                      data returned in RNGAlgorithmList. On
43                                      output with a return code of
44                                      EFI_BUFFER_TOO_SMALL, the size of
45                                      RNGAlgorithmList required to obtain the
46                                      list.
47  @param[out] RNGAlgorithmList        A caller-allocated memory buffer filled
48                                      by the driver with one EFI_RNG_ALGORITHM
49                                      element for each supported RNG algorithm.
50                                      The list must not change across multiple
51                                      calls to the same driver. The first
52                                      algorithm in the list is the default
53                                      algorithm for the driver.
54
55  @retval EFI_SUCCESS                 The RNG algorithm list was returned
56                                      successfully.
57  @retval EFI_UNSUPPORTED             The services is not supported by this
58                                      driver.
59  @retval EFI_DEVICE_ERROR            The list of algorithms could not be
60                                      retrieved due to a hardware or firmware
61                                      error.
62  @retval EFI_INVALID_PARAMETER       One or more of the parameters are
63                                      incorrect.
64  @retval EFI_BUFFER_TOO_SMALL        The buffer RNGAlgorithmList is too small
65                                      to hold the result.
66
67**/
68STATIC
69EFI_STATUS
70EFIAPI
71VirtioRngGetInfo (
72  IN      EFI_RNG_PROTOCOL        *This,
73  IN OUT  UINTN                   *RNGAlgorithmListSize,
74  OUT     EFI_RNG_ALGORITHM       *RNGAlgorithmList
75  )
76{
77  if (This == NULL || RNGAlgorithmListSize == NULL) {
78    return EFI_INVALID_PARAMETER;
79  }
80
81  if (*RNGAlgorithmListSize < sizeof (EFI_RNG_ALGORITHM)) {
82    *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);
83    return EFI_BUFFER_TOO_SMALL;
84  }
85
86  if (RNGAlgorithmList == NULL) {
87    return EFI_INVALID_PARAMETER;
88  }
89
90  *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);
91  CopyGuid (RNGAlgorithmList, &gEfiRngAlgorithmRaw);
92
93  return EFI_SUCCESS;
94}
95
96/**
97  Produces and returns an RNG value using either the default or specified RNG
98  algorithm.
99
100  @param[in]  This                    A pointer to the EFI_RNG_PROTOCOL
101                                      instance.
102  @param[in]  RNGAlgorithm            A pointer to the EFI_RNG_ALGORITHM that
103                                      identifies the RNG algorithm to use. May
104                                      be NULL in which case the function will
105                                      use its default RNG algorithm.
106  @param[in]  RNGValueLength          The length in bytes of the memory buffer
107                                      pointed to by RNGValue. The driver shall
108                                      return exactly this numbers of bytes.
109  @param[out] RNGValue                A caller-allocated memory buffer filled
110                                      by the driver with the resulting RNG
111                                      value.
112
113  @retval EFI_SUCCESS                 The RNG value was returned successfully.
114  @retval EFI_UNSUPPORTED             The algorithm specified by RNGAlgorithm
115                                      is not supported by this driver.
116  @retval EFI_DEVICE_ERROR            An RNG value could not be retrieved due
117                                      to a hardware or firmware error.
118  @retval EFI_NOT_READY               There is not enough random data available
119                                      to satisfy the length requested by
120                                      RNGValueLength.
121  @retval EFI_INVALID_PARAMETER       RNGValue is NULL or RNGValueLength is
122                                      zero.
123
124**/
125STATIC
126EFI_STATUS
127EFIAPI
128VirtioRngGetRNG (
129  IN EFI_RNG_PROTOCOL            *This,
130  IN EFI_RNG_ALGORITHM           *RNGAlgorithm, OPTIONAL
131  IN UINTN                       RNGValueLength,
132  OUT UINT8                      *RNGValue
133  )
134{
135  VIRTIO_RNG_DEV            *Dev;
136  DESC_INDICES              Indices;
137  volatile UINT8            *Buffer;
138  UINTN                     Index;
139  UINT32                    Len;
140  UINT32                    BufferSize;
141  EFI_STATUS                Status;
142
143  if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {
144    return EFI_INVALID_PARAMETER;
145  }
146
147  //
148  // We only support the raw algorithm, so reject requests for anything else
149  //
150  if (RNGAlgorithm != NULL &&
151      !CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
152    return EFI_UNSUPPORTED;
153  }
154
155  Buffer = (volatile UINT8 *)AllocatePool (RNGValueLength);
156  if (Buffer == NULL) {
157    return EFI_DEVICE_ERROR;
158  }
159
160  Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
161
162  //
163  // The Virtio RNG device may return less data than we asked it to, and can
164  // only return MAX_UINT32 bytes per invocation. So loop as long as needed to
165  // get all the entropy we were asked for.
166  //
167  for (Index = 0; Index < RNGValueLength; Index += Len) {
168    BufferSize = (UINT32)MIN (RNGValueLength - Index, (UINTN)MAX_UINT32);
169
170    VirtioPrepare (&Dev->Ring, &Indices);
171    VirtioAppendDesc (&Dev->Ring,
172      (UINTN)Buffer + Index,
173      BufferSize,
174      VRING_DESC_F_WRITE,
175      &Indices);
176
177    if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=
178        EFI_SUCCESS) {
179      Status = EFI_DEVICE_ERROR;
180      goto FreeBuffer;
181    }
182    ASSERT (Len > 0);
183    ASSERT (Len <= BufferSize);
184  }
185
186  for (Index = 0; Index < RNGValueLength; Index++) {
187    RNGValue[Index] = Buffer[Index];
188  }
189  Status = EFI_SUCCESS;
190
191FreeBuffer:
192  FreePool ((VOID *)Buffer);
193  return Status;
194}
195
196STATIC
197EFI_STATUS
198EFIAPI
199VirtioRngInit (
200  IN OUT VIRTIO_RNG_DEV *Dev
201  )
202{
203  UINT8      NextDevStat;
204  EFI_STATUS Status;
205  UINT16     QueueSize;
206  UINT64     Features;
207
208  //
209  // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
210  //
211  NextDevStat = 0;             // step 1 -- reset device
212  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
213  if (EFI_ERROR (Status)) {
214    goto Failed;
215  }
216
217  NextDevStat |= VSTAT_ACK;    // step 2 -- acknowledge device presence
218  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
219  if (EFI_ERROR (Status)) {
220    goto Failed;
221  }
222
223  NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
224  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
225  if (EFI_ERROR (Status)) {
226    goto Failed;
227  }
228
229  //
230  // Set Page Size - MMIO VirtIo Specific
231  //
232  Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
233  if (EFI_ERROR (Status)) {
234    goto Failed;
235  }
236
237  //
238  // step 4a -- retrieve and validate features
239  //
240  Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
241  if (EFI_ERROR (Status)) {
242    goto Failed;
243  }
244
245  Features &= VIRTIO_F_VERSION_1;
246
247  //
248  // In virtio-1.0, feature negotiation is expected to complete before queue
249  // discovery, and the device can also reject the selected set of features.
250  //
251  if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {
252    Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);
253    if (EFI_ERROR (Status)) {
254      goto Failed;
255    }
256  }
257
258  //
259  // step 4b -- allocate request virtqueue, just use #0
260  //
261  Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0);
262  if (EFI_ERROR (Status)) {
263    goto Failed;
264  }
265  Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
266  if (EFI_ERROR (Status)) {
267    goto Failed;
268  }
269
270  //
271  // VirtioRngGetRNG() uses one descriptor
272  //
273  if (QueueSize < 1) {
274    Status = EFI_UNSUPPORTED;
275    goto Failed;
276  }
277
278  Status = VirtioRingInit (QueueSize, &Dev->Ring);
279  if (EFI_ERROR (Status)) {
280    goto Failed;
281  }
282
283  //
284  // Additional steps for MMIO: align the queue appropriately, and set the
285  // size. If anything fails from here on, we must release the ring resources.
286  //
287  Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
288  if (EFI_ERROR (Status)) {
289    goto ReleaseQueue;
290  }
291
292  Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
293  if (EFI_ERROR (Status)) {
294    goto ReleaseQueue;
295  }
296
297  //
298  // step 4c -- Report GPFN (guest-physical frame number) of queue.
299  //
300  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);
301  if (EFI_ERROR (Status)) {
302    goto ReleaseQueue;
303  }
304
305  //
306  // step 5 -- Report understood features and guest-tuneables.
307  //
308  if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
309    Features &= ~(UINT64)VIRTIO_F_VERSION_1;
310    Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
311    if (EFI_ERROR (Status)) {
312      goto ReleaseQueue;
313    }
314  }
315
316  //
317  // step 6 -- initialization complete
318  //
319  NextDevStat |= VSTAT_DRIVER_OK;
320  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
321  if (EFI_ERROR (Status)) {
322    goto ReleaseQueue;
323  }
324
325  //
326  // populate the exported interface's attributes
327  //
328  Dev->Rng.GetInfo    = VirtioRngGetInfo;
329  Dev->Rng.GetRNG     = VirtioRngGetRNG;
330
331  return EFI_SUCCESS;
332
333ReleaseQueue:
334  VirtioRingUninit (&Dev->Ring);
335
336Failed:
337  //
338  // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
339  // Status. VirtIo access failure here should not mask the original error.
340  //
341  NextDevStat |= VSTAT_FAILED;
342  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
343
344  return Status; // reached only via Failed above
345}
346
347
348STATIC
349VOID
350EFIAPI
351VirtioRngUninit (
352  IN OUT VIRTIO_RNG_DEV *Dev
353  )
354{
355  //
356  // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
357  // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
358  // the old comms area.
359  //
360  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
361  VirtioRingUninit (&Dev->Ring);
362}
363
364//
365// Event notification function enqueued by ExitBootServices().
366//
367
368STATIC
369VOID
370EFIAPI
371VirtioRngExitBoot (
372  IN  EFI_EVENT Event,
373  IN  VOID      *Context
374  )
375{
376  VIRTIO_RNG_DEV *Dev;
377
378  //
379  // Reset the device. This causes the hypervisor to forget about the virtio
380  // ring.
381  //
382  // We allocated said ring in EfiBootServicesData type memory, and code
383  // executing after ExitBootServices() is permitted to overwrite it.
384  //
385  Dev = Context;
386  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
387}
388
389
390//
391// Probe, start and stop functions of this driver, called by the DXE core for
392// specific devices.
393//
394// The following specifications document these interfaces:
395// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
396// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
397//
398// The implementation follows:
399// - Driver Writer's Guide for UEFI 2.3.1 v1.01
400//   - 5.1.3.4 OpenProtocol() and CloseProtocol()
401// - UEFI Spec 2.3.1 + Errata C
402//   -  6.3 Protocol Handler Services
403//
404
405STATIC
406EFI_STATUS
407EFIAPI
408VirtioRngDriverBindingSupported (
409  IN EFI_DRIVER_BINDING_PROTOCOL *This,
410  IN EFI_HANDLE                  DeviceHandle,
411  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
412  )
413{
414  EFI_STATUS             Status;
415  VIRTIO_DEVICE_PROTOCOL *VirtIo;
416
417  //
418  // Attempt to open the device with the VirtIo set of interfaces. On success,
419  // the protocol is "instantiated" for the VirtIo device. Covers duplicate
420  // open attempts (EFI_ALREADY_STARTED).
421  //
422  Status = gBS->OpenProtocol (
423                  DeviceHandle,               // candidate device
424                  &gVirtioDeviceProtocolGuid, // for generic VirtIo access
425                  (VOID **)&VirtIo,           // handle to instantiate
426                  This->DriverBindingHandle,  // requestor driver identity
427                  DeviceHandle,               // ControllerHandle, according to
428                                              // the UEFI Driver Model
429                  EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to
430                                              // the device; to be released
431                  );
432  if (EFI_ERROR (Status)) {
433    return Status;
434  }
435
436  if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_ENTROPY_SOURCE) {
437    Status = EFI_UNSUPPORTED;
438  }
439
440  //
441  // We needed VirtIo access only transitorily, to see whether we support the
442  // device or not.
443  //
444  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
445         This->DriverBindingHandle, DeviceHandle);
446  return Status;
447}
448
449STATIC
450EFI_STATUS
451EFIAPI
452VirtioRngDriverBindingStart (
453  IN EFI_DRIVER_BINDING_PROTOCOL *This,
454  IN EFI_HANDLE                  DeviceHandle,
455  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
456  )
457{
458  VIRTIO_RNG_DEV  *Dev;
459  EFI_STATUS Status;
460
461  Dev = (VIRTIO_RNG_DEV *) AllocateZeroPool (sizeof *Dev);
462  if (Dev == NULL) {
463    return EFI_OUT_OF_RESOURCES;
464  }
465
466  Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
467                  (VOID **)&Dev->VirtIo, This->DriverBindingHandle,
468                  DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
469  if (EFI_ERROR (Status)) {
470    goto FreeVirtioRng;
471  }
472
473  //
474  // VirtIo access granted, configure virtio-rng device.
475  //
476  Status = VirtioRngInit (Dev);
477  if (EFI_ERROR (Status)) {
478    goto CloseVirtIo;
479  }
480
481  Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
482                  &VirtioRngExitBoot, Dev, &Dev->ExitBoot);
483  if (EFI_ERROR (Status)) {
484    goto UninitDev;
485  }
486
487  //
488  // Setup complete, attempt to export the driver instance's EFI_RNG_PROTOCOL
489  // interface.
490  //
491  Dev->Signature = VIRTIO_RNG_SIG;
492  Status = gBS->InstallProtocolInterface (&DeviceHandle,
493                  &gEfiRngProtocolGuid, EFI_NATIVE_INTERFACE,
494                  &Dev->Rng);
495  if (EFI_ERROR (Status)) {
496    goto CloseExitBoot;
497  }
498
499  return EFI_SUCCESS;
500
501CloseExitBoot:
502  gBS->CloseEvent (Dev->ExitBoot);
503
504UninitDev:
505  VirtioRngUninit (Dev);
506
507CloseVirtIo:
508  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
509         This->DriverBindingHandle, DeviceHandle);
510
511FreeVirtioRng:
512  FreePool (Dev);
513
514  return Status;
515}
516
517
518STATIC
519EFI_STATUS
520EFIAPI
521VirtioRngDriverBindingStop (
522  IN EFI_DRIVER_BINDING_PROTOCOL *This,
523  IN EFI_HANDLE                  DeviceHandle,
524  IN UINTN                       NumberOfChildren,
525  IN EFI_HANDLE                  *ChildHandleBuffer
526  )
527{
528  EFI_STATUS                      Status;
529  EFI_RNG_PROTOCOL                *Rng;
530  VIRTIO_RNG_DEV                  *Dev;
531
532  Status = gBS->OpenProtocol (
533                  DeviceHandle,                     // candidate device
534                  &gEfiRngProtocolGuid,             // retrieve the RNG iface
535                  (VOID **)&Rng,                    // target pointer
536                  This->DriverBindingHandle,        // requestor driver ident.
537                  DeviceHandle,                     // lookup req. for dev.
538                  EFI_OPEN_PROTOCOL_GET_PROTOCOL    // lookup only, no new ref.
539                  );
540  if (EFI_ERROR (Status)) {
541    return Status;
542  }
543
544  Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (Rng);
545
546  //
547  // Handle Stop() requests for in-use driver instances gracefully.
548  //
549  Status = gBS->UninstallProtocolInterface (DeviceHandle,
550                  &gEfiRngProtocolGuid, &Dev->Rng);
551  if (EFI_ERROR (Status)) {
552    return Status;
553  }
554
555  gBS->CloseEvent (Dev->ExitBoot);
556
557  VirtioRngUninit (Dev);
558
559  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
560         This->DriverBindingHandle, DeviceHandle);
561
562  FreePool (Dev);
563
564  return EFI_SUCCESS;
565}
566
567
568//
569// The static object that groups the Supported() (ie. probe), Start() and
570// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
571// C, 10.1 EFI Driver Binding Protocol.
572//
573STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
574  &VirtioRngDriverBindingSupported,
575  &VirtioRngDriverBindingStart,
576  &VirtioRngDriverBindingStop,
577  0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
578  NULL, // ImageHandle, to be overwritten by
579        // EfiLibInstallDriverBindingComponentName2() in VirtioRngEntryPoint()
580  NULL  // DriverBindingHandle, ditto
581};
582
583
584//
585// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
586// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
587// in English, for display on standard console devices. This is recommended for
588// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
589// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
590//
591
592STATIC
593EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
594  { "eng;en", L"Virtio Random Number Generator Driver" },
595  { NULL,     NULL                   }
596};
597
598STATIC
599EFI_COMPONENT_NAME_PROTOCOL gComponentName;
600
601STATIC
602EFI_STATUS
603EFIAPI
604VirtioRngGetDriverName (
605  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
606  IN  CHAR8                       *Language,
607  OUT CHAR16                      **DriverName
608  )
609{
610  return LookupUnicodeString2 (
611           Language,
612           This->SupportedLanguages,
613           mDriverNameTable,
614           DriverName,
615           (BOOLEAN)(This == &gComponentName) // Iso639Language
616           );
617}
618
619STATIC
620EFI_STATUS
621EFIAPI
622VirtioRngGetDeviceName (
623  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
624  IN  EFI_HANDLE                  DeviceHandle,
625  IN  EFI_HANDLE                  ChildHandle,
626  IN  CHAR8                       *Language,
627  OUT CHAR16                      **ControllerName
628  )
629{
630  return EFI_UNSUPPORTED;
631}
632
633STATIC
634EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
635  &VirtioRngGetDriverName,
636  &VirtioRngGetDeviceName,
637  "eng" // SupportedLanguages, ISO 639-2 language codes
638};
639
640STATIC
641EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
642  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)     &VirtioRngGetDriverName,
643  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioRngGetDeviceName,
644  "en" // SupportedLanguages, RFC 4646 language codes
645};
646
647
648//
649// Entry point of this driver.
650//
651EFI_STATUS
652EFIAPI
653VirtioRngEntryPoint (
654  IN EFI_HANDLE       ImageHandle,
655  IN EFI_SYSTEM_TABLE *SystemTable
656  )
657{
658  return EfiLibInstallDriverBindingComponentName2 (
659           ImageHandle,
660           SystemTable,
661           &gDriverBinding,
662           ImageHandle,
663           &gComponentName,
664           &gComponentName2
665           );
666}
667